remm 2003/11/24 08:46:56 Modified: catalina/src/share/org/apache/catalina/authenticator AuthenticatorBase.java BasicAuthenticator.java DigestAuthenticator.java FormAuthenticator.java NonLoginAuthenticator.java SSLAuthenticator.java SingleSignOn.java mbeans-descriptors.xml Added: catalina/src/share/org/apache/catalina/authenticator SingleSignOnEntry.java Log: - Bug 23881: SSO in embedded Tomcat. - Patch submitted by Brian Stansberry. Thanks :) Revision Changes Path 1.14 +86 -20 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/AuthenticatorBase.java Index: AuthenticatorBase.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/AuthenticatorBase.java,v retrieving revision 1.13 retrieving revision 1.14 diff -u -r1.13 -r1.14 --- AuthenticatorBase.java 23 Oct 2003 17:33:10 -0000 1.13 +++ AuthenticatorBase.java 24 Nov 2003 16:46:56 -0000 1.14 @@ -625,7 +625,7 @@ * * @param request Request we are processing * @param response Response we are creating - * @param login Login configuration describing how authentication + * @param config Login configuration describing how authentication * should be performed * * @exception IOException if an input/output error occurs @@ -643,7 +643,6 @@ protected synchronized String generateSessionId() { // Generate a byte array containing a session identifier - Random random = getRandom(); byte bytes[] = new byte[SESSION_ID_BYTES]; getRandom().nextBytes(bytes); bytes = getDigest().digest(bytes); @@ -801,6 +800,53 @@ /** + * Attempts reauthentication to the <code>Realm</code> using + * the credentials included in argument <code>entry</code>. + * + * @param ssoId identifier of SingleSignOn session with which the + * caller is associated + * @param request the request that needs to be authenticated + */ + protected boolean reauthenticateFromSSO(String ssoId, HttpRequest request) { + + if (sso == null || ssoId == null) + return false; + + boolean reauthenticated = false; + + SingleSignOnEntry entry = sso.lookup(ssoId); + if (entry != null && entry.getCanReauthenticate()) { + Principal reauthPrincipal = null; + Container parent = getContainer(); + if (parent != null) { + Realm realm = getContainer().getRealm(); + String username = entry.getUsername(); + if (realm != null && username != null) { + reauthPrincipal = + realm.authenticate(username, entry.getPassword()); + } + } + + if (reauthPrincipal != null) { + associate(ssoId, getSession(request, true)); + request.setAuthType(entry.getAuthType()); + request.setUserPrincipal(reauthPrincipal); + + reauthenticated = true; + if (log.isDebugEnabled()) { + log.debug(" Reauthenticated cached principal '" + + entry.getPrincipal().getName() + + "' with auth type '" + + entry.getAuthType() + "'"); + } + } + } + + return reauthenticated; + } + + + /** * Register an authenticated Principal and authentication type in our * request, in the current session (if there is one), and with our * SingleSignOn valve, if there is one. Set the appropriate cookie @@ -825,9 +871,9 @@ request.setAuthType(authType); request.setUserPrincipal(principal); + Session session = getSession(request, false); // Cache the authentication information in our session, if any if (cache) { - Session session = getSession(request, false); if (session != null) { session.setAuthType(authType); session.setPrincipal(principal); @@ -845,19 +891,39 @@ // Construct a cookie to be returned to the client if (sso == null) return; - HttpServletRequest hreq = - (HttpServletRequest) request.getRequest(); - HttpServletResponse hres = - (HttpServletResponse) response.getResponse(); - String value = generateSessionId(); - Cookie cookie = new Cookie(Constants.SINGLE_SIGN_ON_COOKIE, value); - cookie.setMaxAge(-1); - cookie.setPath("/"); - hres.addCookie(cookie); - - // Register this principal with our SSO valve - sso.register(value, principal, authType, username, password); - request.setNote(Constants.REQ_SSOID_NOTE, value); + + // Only create a new SSO entry if the SSO did not already set a note + // for an existing entry (as it would do with subsequent requests + // for DIGEST and SSL authenticated contexts) + String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE); + if (ssoId == null) { + // Construct a cookie to be returned to the client + HttpServletResponse hres = + (HttpServletResponse) response.getResponse(); + ssoId = generateSessionId(); + Cookie cookie = new Cookie(Constants.SINGLE_SIGN_ON_COOKIE, ssoId); + cookie.setMaxAge(-1); + cookie.setPath("/"); + hres.addCookie(cookie); + + // Register this principal with our SSO valve + sso.register(ssoId, principal, authType, username, password); + request.setNote(Constants.REQ_SSOID_NOTE, ssoId); + + } else { + // Update the SSO session with the latest authentication data + sso.update(ssoId, principal, authType, username, password); + } + + // Fix for Bug 10040 + // Always associate a session with a new SSO reqistration. + // SSO entries are only removed from the SSO registry map when + // associated sessions are destroyed; if a new SSO entry is created + // above for this request and the user never revisits the context, the + // SSO entry will never be cleared if we don't associate the session + if (session == null) + session = getSession(request, true); + sso.associate(ssoId, session); } 1.3 +26 -7 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/BasicAuthenticator.java Index: BasicAuthenticator.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/BasicAuthenticator.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- BasicAuthenticator.java 12 Mar 2003 06:00:23 -0000 1.2 +++ BasicAuthenticator.java 24 Nov 2003 16:46:56 -0000 1.3 @@ -133,7 +133,7 @@ * * @param request Request we are processing * @param response Response we are creating - * @param login Login configuration describing how authentication + * @param config Login configuration describing how authentication * should be performed * * @exception IOException if an input/output error occurs @@ -146,12 +146,31 @@ // Have we already authenticated someone? Principal principal = ((HttpServletRequest) request.getRequest()).getUserPrincipal(); + String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE); if (principal != null) { if (log.isDebugEnabled()) log.debug("Already authenticated '" + principal.getName() + "'"); + // Associate the session with any existing SSO session + if (ssoId != null) + associate(ssoId, getSession(request, true)); return (true); } + // Is there an SSO session against which we can try to reauthenticate? + if (ssoId != null) { + if (log.isDebugEnabled()) + log.debug("SSO Id " + ssoId + " set; attempting " + + "reauthentication"); + /* Try to reauthenticate using data cached by SSO. If this fails, + either the original SSO logon was of DIGEST or SSL (which + we can't reauthenticate ourselves because there is no + cached username and password), or the realm denied + the user's reauthentication for some reason. + In either case we have to prompt the user for a logon */ + if (reauthenticateFromSSO(ssoId, request)) + return true; + } + // Validate any credentials already included with this request HttpServletRequest hreq = (HttpServletRequest) request.getRequest(); @@ -171,8 +190,8 @@ String realmName = config.getRealmName(); if (realmName == null) realmName = hreq.getServerName() + ":" + hreq.getServerPort(); - // if (debug >= 1) - // log("Challenging for realm '" + realmName + "'"); + // if (log.isDebugEnabled()) + // log.debug("Challenging for realm '" + realmName + "'"); hres.setHeader("WWW-Authenticate", "Basic realm=\"" + realmName + "\""); hres.setStatus(HttpServletResponse.SC_UNAUTHORIZED); 1.3 +46 -11 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/DigestAuthenticator.java Index: DigestAuthenticator.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/DigestAuthenticator.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- DigestAuthenticator.java 2 Sep 2003 21:22:04 -0000 1.2 +++ DigestAuthenticator.java 24 Nov 2003 16:46:56 -0000 1.3 @@ -75,6 +75,9 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.apache.catalina.HttpRequest; import org.apache.catalina.HttpResponse; import org.apache.catalina.Realm; @@ -94,6 +97,7 @@ public class DigestAuthenticator extends AuthenticatorBase { + private static Log log = LogFactory.getLog(DigestAuthenticator.class); // -------------------------------------------------------------- Constants @@ -206,7 +210,7 @@ * * @param request Request we are processing * @param response Response we are creating - * @param login Login configuration describing how authentication + * @param config Login configuration describing how authentication * should be performed * * @exception IOException if an input/output error occurs @@ -219,8 +223,42 @@ // Have we already authenticated someone? Principal principal = ((HttpServletRequest) request.getRequest()).getUserPrincipal(); - if (principal != null) + //String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE); + if (principal != null) { + if (log.isDebugEnabled()) + log.debug("Already authenticated '" + principal.getName() + "'"); + // Associate the session with any existing SSO session in order + // to get coordinated session invalidation at logout + String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE); + if (ssoId != null) + associate(ssoId, getSession(request, true)); return (true); + } + + // NOTE: We don't try to reauthenticate using any existing SSO session, + // because that will only work if the original authentication was + // BASIC or FORM, which are less secure than the DIGEST auth-type + // specified for this webapp + // + // Uncomment below to allow previous FORM or BASIC authentications + // to authenticate users for this webapp + // TODO make this a configurable attribute (in SingleSignOn??) + /* + // Is there an SSO session against which we can try to reauthenticate? + if (ssoId != null) { + if (log.isDebugEnabled()) + log.debug("SSO Id " + ssoId + " set; attempting " + + "reauthentication"); + // Try to reauthenticate using data cached by SSO. If this fails, + // either the original SSO logon was of DIGEST or SSL (which + // we can't reauthenticate ourselves because there is no + // cached username and password), or the realm denied + // the user's reauthentication for some reason. + // In either case we have to prompt the user for a logon + if (reauthenticateFromSSO(ssoId, request)) + return true; + } + */ // Validate any credentials already included with this request HttpServletRequest hreq = @@ -264,8 +302,6 @@ * * @param request HTTP servlet request * @param authorization Authorization credentials from this request - * @param login Login configuration describing how authentication - * should be performed * @param realm Realm used to authenticate Principals */ protected static Principal findPrincipal(HttpServletRequest request, @@ -292,7 +328,6 @@ String qop = null; String uri = null; String response = null; - String opaque = null; String method = request.getMethod(); while (commaTokenizer.hasMoreTokens()) { @@ -434,8 +469,8 @@ * </pre> * * @param request HTTP Servlet request - * @param resonse HTTP Servlet response - * @param login Login configuration describing how authentication + * @param response HTTP Servlet response + * @param config Login configuration describing how authentication * should be performed * @param nOnce nonce token */ 1.5 +23 -10 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/FormAuthenticator.java Index: FormAuthenticator.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/FormAuthenticator.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- FormAuthenticator.java 2 Sep 2003 21:22:04 -0000 1.4 +++ FormAuthenticator.java 24 Nov 2003 16:46:56 -0000 1.5 @@ -138,7 +138,7 @@ * * @param request Request we are processing * @param response Response we are creating - * @param login Login configuration describing how authentication + * @param config Login configuration describing how authentication * should be performed * * @exception IOException if an input/output error occurs @@ -157,16 +157,32 @@ // Have we already authenticated someone? Principal principal = hreq.getUserPrincipal(); + String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE); if (principal != null) { if (log.isDebugEnabled()) log.debug("Already authenticated '" + principal.getName() + "'"); - String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE); + // Associate the session with any existing SSO session if (ssoId != null) associate(ssoId, getSession(request, true)); return (true); } + // Is there an SSO session against which we can try to reauthenticate? + if (ssoId != null) { + if (log.isDebugEnabled()) + log.debug("SSO Id " + ssoId + " set; attempting " + + "reauthentication"); + // Try to reauthenticate using data cached by SSO. If this fails, + // either the original SSO logon was of DIGEST or SSL (which + // we can't reauthenticate ourselves because there is no + // cached username and password), or the realm denied + // the user's reauthentication for some reason. + // In either case we have to prompt the user for a logon */ + if (reauthenticateFromSSO(ssoId, request)) + return true; + } + // Have we authenticated this user before but have caching disabled? if (!cache) { session = getSession(request, true); @@ -205,9 +221,6 @@ register(request, response, principal, Constants.FORM_METHOD, (String) session.getNote(Constants.SESS_USERNAME_NOTE), (String) session.getNote(Constants.SESS_PASSWORD_NOTE)); - String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE); - if (ssoId != null) - associate(ssoId, session); if (restoreRequest(request, session)) { if (log.isDebugEnabled()) log.debug("Proceed to restored request"); @@ -380,7 +393,7 @@ while (paramNames.hasNext()) { String paramName = (String) paramNames.next(); String paramValues[] = - (String[]) saved.getParameterValues(paramName); + saved.getParameterValues(paramName); request.addParameter(paramName, paramValues); } } 1.3 +14 -5 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/NonLoginAuthenticator.java Index: NonLoginAuthenticator.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/NonLoginAuthenticator.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- NonLoginAuthenticator.java 2 Sep 2003 21:22:04 -0000 1.2 +++ NonLoginAuthenticator.java 24 Nov 2003 16:46:56 -0000 1.3 @@ -119,7 +119,7 @@ * * @param request Request we are processing * @param response Response we are creating - * @param login Login configuration describing how authentication + * @param config Login configuration describing how authentication * should be performed * * @exception IOException if an input/output error occurs @@ -129,6 +129,15 @@ LoginConfig config) throws IOException { + /* Associating this request's session with an SSO would allow + coordinated session invalidation, but should the session for + a webapp that the user didn't log into be invalidated when + another session is logged out? + String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE); + if (ssoId != null) + associate(ssoId, getSession(request, true)); + */ + if (debug >= 1) log("User authentication is not required"); return (true); 1.10 +36 -5 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/SSLAuthenticator.java Index: SSLAuthenticator.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/SSLAuthenticator.java,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- SSLAuthenticator.java 17 Oct 2003 18:47:43 -0000 1.9 +++ SSLAuthenticator.java 24 Nov 2003 16:46:56 -0000 1.10 @@ -122,7 +122,7 @@ * * @param request Request we are processing * @param response Response we are creating - * @param login Login configuration describing how authentication + * @param config Login configuration describing how authentication * should be performed * * @exception IOException if an input/output error occurs @@ -135,11 +135,42 @@ // Have we already authenticated someone? Principal principal = ((HttpServletRequest) request.getRequest()).getUserPrincipal(); + //String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE); if (principal != null) { if (debug >= 1) log("Already authenticated '" + principal.getName() + "'"); + // Associate the session with any existing SSO session in order + // to get coordinated session invalidation at logout + String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE); + if (ssoId != null) + associate(ssoId, getSession(request, true)); return (true); } + + // NOTE: We don't try to reauthenticate using any existing SSO session, + // because that will only work if the original authentication was + // BASIC or FORM, which are less secure than the CLIENT-CERT auth-type + // specified for this webapp + // + // Uncomment below to allow previous FORM or BASIC authentications + // to authenticate users for this webapp + // TODO make this a configurable attribute (in SingleSignOn??) + /* + // Is there an SSO session against which we can try to reauthenticate? + if (ssoId != null) { + if (log.isDebugEnabled()) + log.debug("SSO Id " + ssoId + " set; attempting " + + "reauthentication"); + // Try to reauthenticate using data cached by SSO. If this fails, + // either the original SSO logon was of DIGEST or SSL (which + // we can't reauthenticate ourselves because there is no + // cached username and password), or the realm denied + // the user's reauthentication for some reason. + // In either case we have to prompt the user for a logon + if (reauthenticateFromSSO(ssoId, request)) + return true; + } + */ // Retrieve the certificate chain for this client HttpServletResponse hres = 1.8 +121 -66 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/SingleSignOn.java Index: SingleSignOn.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/SingleSignOn.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- SingleSignOn.java 15 Nov 2003 09:42:26 -0000 1.7 +++ SingleSignOn.java 24 Nov 2003 16:46:56 -0000 1.8 @@ -145,6 +145,12 @@ */ protected LifecycleSupport lifecycle = new LifecycleSupport(this); + /** + * Indicates whether this valve should require a downstream Authenticator to + * reauthenticate each request, or if it itself can bind a UserPrincipal + * and AuthType object to the request. + */ + private boolean requireReauthentication = false; /** * The cache of single sign on identifiers, keyed by the Session that is @@ -191,6 +197,75 @@ } + /** + * Gets whether each request needs to be reauthenticated (by an + * Authenticator downstream in the pipeline) to the security + * <code>Realm</code>, or if this Valve can itself bind security info + * to the request based on the presence of a valid SSO entry without + * rechecking with the <code>Realm</code.. + * + * @return <code>true</code> if it is required that a downstream + * Authenticator reauthenticate each request before calls to + * <code>HttpServletRequest.setUserPrincipal()</code> + * and <code>HttpServletRequest.setAuthType()</code> are made; + * <code>false</code> if the <code>Valve</code> can itself make + * those calls relying on the presence of a valid SingleSignOn + * entry associated with the request. + * + * @see #setRequireReauthentication + */ + public boolean getRequireReauthentication() + { + return requireReauthentication; + } + + + /** + * Sets whether each request needs to be reauthenticated (by an + * Authenticator downstream in the pipeline) to the security + * <code>Realm</code>, or if this Valve can itself bind security info + * to the request, based on the presence of a valid SSO entry, without + * rechecking with the <code>Realm</code. + * <p> + * If this property is <code>false</code> (the default), this + * <code>Valve</code> will bind a UserPrincipal and AuthType to the request + * if a valid SSO entry is associated with the request. It will not notify + * the security <code>Realm</code> of the incoming request. + * <p> + * This property should be set to <code>true</code> if the overall server + * configuration requires that the <code>Realm</code> reauthenticate each + * request thread. An example of such a configuration would be one where + * the <code>Realm</code> implementation provides security for both a + * web tier and an associated EJB tier, and needs to set security + * credentials on each request thread in order to support EJB access. + * <p> + * If this property is set to <code>true</code>, this Valve will set flags + * on the request notifying the downstream Authenticator that the request + * is associated with an SSO session. The Authenticator will then call its + * [EMAIL PROTECTED] AuthenticatorBase#reauthenticateFromSSO reauthenticateFromSSO} + * method to attempt to reauthenticate the request to the + * <code>Realm</code>, using any credentials that were cached with this + * Valve. + * <p> + * The default value of this property is <code>false</code>, in order + * to maintain backward compatibility with previous versions of Tomcat. + * + * @param required <code>true</code> if it is required that a downstream + * Authenticator reauthenticate each request before calls + * to <code>HttpServletRequest.setUserPrincipal()</code> + * and <code>HttpServletRequest.setAuthType()</code> are + * made; <code>false</code> if the <code>Valve</code> can + * itself make those calls relying on the presence of a + * valid SingleSignOn entry associated with the request. + * + * @see AuthenticatorBase#reauthenticateFromSSO + */ + public void setRequireReauthentication(boolean required) + { + this.requireReauthentication = required; + } + + // ------------------------------------------------------ Lifecycle Methods @@ -301,10 +376,6 @@ if (ssoId == null) return; - deregister(ssoId); - // FIXME: There's no way right now to specify per application or - // global logout - /* if ( event.getData() != null && "logout".equals( event.getData().toString() )) { // logout of all applications @@ -313,7 +384,6 @@ // invalidate just one session deregister(ssoId, session); } - */ } @@ -396,11 +466,14 @@ if (entry != null) { if (debug >= 1) log(" Found cached principal '" + - entry.principal.getName() + "' with auth type '" + - entry.authType + "'"); + entry.getPrincipal().getName() + "' with auth type '" + + entry.getAuthType() + "'"); request.setNote(Constants.REQ_SSOID_NOTE, cookie.getValue()); - ((HttpRequest) request).setAuthType(entry.authType); - ((HttpRequest) request).setUserPrincipal(entry.principal); + // Only set security elements if reauthentication is not required + if (!getRequireReauthentication()) { + ((HttpRequest) request).setAuthType(entry.getAuthType()); + ((HttpRequest) request).setUserPrincipal(entry.getPrincipal()); + } } else { if (debug >= 1) log(" No cached principal found, erasing SSO cookie"); @@ -433,7 +506,7 @@ } - // -------------------------------------------------------- Package Methods + // ------------------------------------------------------ Protected Methods /** @@ -553,9 +626,6 @@ } - // ------------------------------------------------------ Protected Methods - - /** * Log a message on the Logger associated with our Container (if any). * @@ -605,61 +675,46 @@ } + //---------------------------------------------- Package-Protected Methods -} - - -// ------------------------------------------------------------ Private Classes - - -/** - * A private class representing entries in the cache of authenticated users. - */ -class SingleSignOnEntry { - - public String authType = null; - - public String password = null; - - public Principal principal = null; - - public Session sessions[] = new Session[0]; - - public String username = null; + /** + * Updates any <code>SingleSignOnEntry</code> found under key + * <code>ssoId</code> with the given authentication data. + * <p> + * The purpose of this method is to allow an SSO entry that was + * established without a username/password combination (i.e. established + * following DIGEST or CLIENT-CERT authentication) to be updated with + * a username and password if one becomes available through a subsequent + * BASIC or FORM authentication. The SSO entry will then be usable for + * reauthentication. + * <p> + * <b>NOTE:</b> Only updates the SSO entry if a call to + * <code>SingleSignOnEntry.getCanReauthenticate()</code> returns + * <code>false</code>; otherwise, it is assumed that the SSO entry already + * has sufficient information to allow reauthentication and that no update + * is needed. + * + * @param ssoId identifier of Single sign to be updated + * @param principal the <code>Principal</code> returned by the latest + * call to <code>Realm.authenticate</code>. + * @param authType the type of authenticator used (BASIC, CLIENT-CERT, + * DIGEST or FORM) + * @param username the username (if any) used for the authentication + * @param password the password (if any) used for the authentication + */ + void update(String ssoId, Principal principal, String authType, + String username, String password) { - public SingleSignOnEntry(Principal principal, String authType, - String username, String password) { - super(); - this.principal = principal; - this.authType = authType; - this.username = username; - this.password = password; - } + SingleSignOnEntry sso = lookup(ssoId); + if (sso != null && !sso.getCanReauthenticate()) { + if (debug >= 1) + log("Update sso id " + ssoId + " to auth type " + authType); - public synchronized void addSession(SingleSignOn sso, Session session) { - for (int i = 0; i < sessions.length; i++) { - if (session == sessions[i]) - return; - } - Session results[] = new Session[sessions.length + 1]; - System.arraycopy(sessions, 0, results, 0, sessions.length); - results[sessions.length] = session; - sessions = results; - session.addSessionListener(sso); - } + synchronized(sso) { + sso.updateCredentials(principal, authType, username, password); + } - public synchronized void removeSession(Session session) { - Session[] nsessions = new Session[sessions.length - 1]; - for (int i = 0, j = 0; i < sessions.length; i++) { - if (session == sessions[i]) - continue; - nsessions[j++] = sessions[i]; } - sessions = nsessions; - } - - public synchronized Session[] findSessions() { - return (this.sessions); } } 1.2 +4 -0 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/mbeans-descriptors.xml Index: mbeans-descriptors.xml =================================================================== RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/mbeans-descriptors.xml,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- mbeans-descriptors.xml 19 Mar 2003 07:29:20 -0000 1.1 +++ mbeans-descriptors.xml 24 Nov 2003 16:46:56 -0000 1.2 @@ -129,6 +129,10 @@ <attribute name="debug" description="The debugging detail level for this component" type="int"/> + + <attribute name="requireReauthentication" + description="Should we attempt to reauthenticate each request against the security Realm?" + type="boolean"/> </mbean> 1.1 jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/SingleSignOnEntry.java Index: SingleSignOnEntry.java =================================================================== /* * $Header: /home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/authenticator/SingleSignOnEntry.java,v 1.1 2003/11/24 16:46:56 remm Exp $ * $Revision: 1.1 $ * $Date: 2003/11/24 16:46:56 $ * * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999-2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.catalina.authenticator; import java.security.Principal; import org.apache.catalina.Session; import org.apache.catalina.authenticator.Constants; /** * A class that represents entries in the cache of authenticated users. * This is necessary to make it available to * <code>AuthenticatorBase</code> subclasses that need it in order to perform * reauthentications when SingleSignOn is in use. * * @author B Stansberry, based on work by Craig R. McClanahan * @version $Revision: 1.1 $ * * @see SingleSignOn * @see AuthenticatorBase#reauthenticateFromSSO */ class SingleSignOnEntry { // ------------------------------------------------------ Instance Fields private String authType = null; private String password = null; private Principal principal = null; private Session sessions[] = new Session[0]; private String username = null; private boolean canReauthenticate = false; // --------------------------------------------------------- Constructors /** * Creates a new SingleSignOnEntry * * @param principal the <code>Principal</code> returned by the latest * call to <code>Realm.authenticate</code>. * @param authType the type of authenticator used (BASIC, CLIENT-CERT, * DIGEST or FORM) * @param username the username (if any) used for the authentication * @param password the password (if any) used for the authentication */ SingleSignOnEntry(Principal principal, String authType, String username, String password) { super(); updateCredentials(principal, authType, username, password); } // ------------------------------------------------------- Package Methods /** * Adds a <code>Session</code> to the list of those associated with * this SSO. * * @param sso The <code>SingleSignOn</code> valve that is managing * the SSO session. * @param session The <code>Session</code> being associated with the SSO. */ synchronized void addSession(SingleSignOn sso, Session session) { for (int i = 0; i < sessions.length; i++) { if (session == sessions[i]) return; } Session results[] = new Session[sessions.length + 1]; System.arraycopy(sessions, 0, results, 0, sessions.length); results[sessions.length] = session; sessions = results; session.addSessionListener(sso); } /** * Removes the given <code>Session</code> from the list of those * associated with this SSO. * * @param session the <code>Session</code> to remove. */ synchronized void removeSession(Session session) { Session[] nsessions = new Session[sessions.length - 1]; for (int i = 0, j = 0; i < sessions.length; i++) { if (session == sessions[i]) continue; nsessions[j++] = sessions[i]; } sessions = nsessions; } /** * Returns the <code>Session</code>s associated with this SSO. */ synchronized Session[] findSessions() { return (this.sessions); } /** * Gets the name of the authentication type originally used to authenticate * the user associated with the SSO. * * @return "BASIC", "CLIENT-CERT", "DIGEST", "FORM" or "NONE" */ String getAuthType() { return (this.authType); } /** * Gets whether the authentication type associated with the original * authentication supports reauthentication. * * @return <code>true</code> if <code>getAuthType</code> returns * "BASIC" or "FORM", <code>false</code> otherwise. */ boolean getCanReauthenticate() { return (this.canReauthenticate); } /** * Gets the password credential (if any) associated with the SSO. * * @return the password credential associated with the SSO, or * <code>null</code> if the original authentication type * does not involve a password. */ String getPassword() { return (this.password); } /** * Gets the <code>Principal</code> that has been authenticated by * the SSO. */ Principal getPrincipal() { return (this.principal); } /** * Gets the username provided by the user as part of the authentication * process. */ String getUsername() { return (this.username); } /** * Updates the SingleSignOnEntry to reflect the latest security * information associated with the caller. * * @param principal the <code>Principal</code> returned by the latest * call to <code>Realm.authenticate</code>. * @param authType the type of authenticator used (BASIC, CLIENT-CERT, * DIGEST or FORM) * @param username the username (if any) used for the authentication * @param password the password (if any) used for the authentication */ void updateCredentials(Principal principal, String authType, String username, String password) { this.principal = principal; this.authType = authType; this.username = username; this.password = password; this.canReauthenticate = (Constants.BASIC_METHOD.equals(authType) || Constants.FORM_METHOD.equals(authType)); } }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]