FileDocCategorySizeDatePackage
RealmBase.javaAPI DocGlassfish v2 API60301Fri May 04 22:32:18 BST 2007org.apache.catalina.realm

RealmBase

public abstract class RealmBase extends Object implements org.apache.catalina.Lifecycle, org.apache.catalina.Realm, MBeanRegistration
Simple implementation of Realm that reads an XML file to configure the valid users, passwords, and roles. The file format (and default file location) are identical to those currently supported by Tomcat 3.X.
author
Craig R. McClanahan
version
$Revision: 1.15 $ $Date: 2007/05/05 05:32:17 $

Fields Summary
private static com.sun.org.apache.commons.logging.Log
log
private static final String
DATE_ONE
"Expires" header always set to Date(1), so generate once only
protected int
debug
The debugging detail level for this component.
protected org.apache.catalina.Container
container
The Container with which this Realm is associated.
protected boolean
checkIfRequestIsSecure
Flag indicating whether a check to see if the request is secure is required before adding Pragma and Cache-Control headers when proxy caching has been disabled
protected String
digest
Digest algorithm used in storing passwords in a non-plaintext format. Valid values are those accepted for the algorithm name by the MessageDigest class, or null if no digesting should be performed.
protected String
digestEncoding
The encoding charset for the digest.
protected static final String
info
Descriptive information about this Realm implementation.
protected org.apache.catalina.util.LifecycleSupport
lifecycle
The lifecycle event support for this component.
protected MessageDigest
md
The MessageDigest object for digesting user credentials (passwords).
protected static final org.apache.catalina.util.MD5Encoder
md5Encoder
The MD5 helper object for this class.
protected static MessageDigest
md5Helper
MD5 message digest provider.
protected static final org.apache.catalina.util.StringManager
sm
The string manager for this package.
protected boolean
started
Has this component been started?
protected PropertyChangeSupport
support
The property change support for this component.
protected boolean
validate
Should we validate client certificate chains when they are presented?
protected String
type
protected String
domain
protected String
host
protected String
path
protected ObjectName
oname
protected ObjectName
controller
protected MBeanServer
mserver
protected boolean
initialized
Constructors Summary
Methods Summary
public static final java.lang.StringDigest(java.lang.String credentials, java.lang.String algorithm, java.lang.String encoding)
Digest password using the algorithm especificied and convert the result to a corresponding hex string. If exception, the plain credentials string is returned

param
credentials Password or other credentials to use in authenticating this username
param
algorithm Algorithm used to do the digest
param
encoding Character encoding of the string to digest


        try {
            // Obtain a new message digest with "digest" encryption
            MessageDigest md =
                (MessageDigest) MessageDigest.getInstance(algorithm).clone();

            // encode the credentials
            // Should use the digestEncoding, but that's not a static field
            if (encoding == null) {
                md.update(credentials.getBytes());
            } else {
                md.update(credentials.getBytes(encoding));                
            }

            // Digest the credentials and return as hexadecimal
            return (HexUtils.convert(md.digest()));
        } catch(Exception ex) {
            ex.printStackTrace();
            return credentials;
        }

    
public voidaddLifecycleListener(org.apache.catalina.LifecycleListener listener)
Add a lifecycle event listener to this component.

param
listener The listener to add


        lifecycle.addLifecycleListener(listener);

    
public voidaddPropertyChangeListener(java.beans.PropertyChangeListener listener)
Add a property change listener to this component.

param
listener The listener to add


        support.addPropertyChangeListener(listener);

    
public java.security.Principalauthenticate(java.lang.String username, java.lang.String credentials)
Return the Principal associated with the specified username and credentials, if there is one; otherwise return null.

param
username Username of the Principal to look up
param
credentials Password or other credentials to use in authenticating this username


        String serverCredentials = getPassword(username);

        boolean validated ;
        if ( serverCredentials == null ) {
            validated = false;
        } else if(hasMessageDigest()) {
            validated = serverCredentials.equalsIgnoreCase(digest(credentials));
        } else {
            validated = serverCredentials.equals(credentials);
        }
        if(! validated ) {
            return null;
        }
        return getPrincipal(username);
    
public java.security.Principalauthenticate(java.lang.String username, byte[] credentials)
Return the Principal associated with the specified username and credentials, if there is one; otherwise return null.

param
username Username of the Principal to look up
param
credentials Password or other credentials to use in authenticating this username


        return (authenticate(username, credentials.toString()));

    
public java.security.Principalauthenticate(java.lang.String username, java.lang.String clientDigest, java.lang.String nOnce, java.lang.String nc, java.lang.String cnonce, java.lang.String qop, java.lang.String realm, java.lang.String md5a2)
Return the Principal associated with the specified username, which matches the digest calculated using the given parameters using the method described in RFC 2069; otherwise return null.

param
username Username of the Principal to look up
param
clientDigest Digest which has been submitted by the client
param
nOnce Unique (or supposedly unique) token which has been used for this request
param
realm Realm name
param
md5a2 Second MD5 digest used to calculate the digest : MD5(Method + ":" + uri)


        String md5a1 = getDigest(username, realm);
        if (md5a1 == null)
            return null;
        String serverDigestValue = md5a1 + ":" + nOnce + ":" + nc + ":"
            + cnonce + ":" + qop + ":" + md5a2;

        byte[] valueBytes = null;
        if(getDigestEncoding() == null) {
            valueBytes = serverDigestValue.getBytes();
        } else {
            try {
                valueBytes = serverDigestValue.getBytes(getDigestEncoding());
            } catch (UnsupportedEncodingException uee) {
                log.error("Illegal digestEncoding: " + getDigestEncoding(), uee);
                throw new IllegalArgumentException(uee.getMessage());
            }
        }

        String serverDigest = null;
        // Bugzilla 32137
        synchronized(md5Helper) {
            serverDigest = md5Encoder.encode(md5Helper.digest(valueBytes));
        }

        if (log.isDebugEnabled()) {
            log.debug("Digest : " + clientDigest + " Username:" + username 
                    + " ClientSigest:" + clientDigest + " nOnce:" + nOnce 
                    + " nc:" + nc + " cnonce:" + cnonce + " qop:" + qop 
                    + " realm:" + realm + "md5a2:" + md5a2 
                    + " Server digest:" + serverDigest);
        }
        
        if (serverDigest.equals(clientDigest))
            return getPrincipal(username);
        else
            return null;
    
public java.security.Principalauthenticate(java.security.cert.X509Certificate[] certs)
Return the Principal associated with the specified chain of X509 client certificates. If there is none, return null.

param
certs Array of client certificates, with the first one in the array being the certificate of the client itself.


        if ((certs == null) || (certs.length < 1))
            return (null);

        // Check the validity of each certificate in the chain
        if (log.isDebugEnabled())
            log.debug("Authenticating client certificate chain");
        if (validate) {
            for (int i = 0; i < certs.length; i++) {
                if (log.isDebugEnabled())
                    log.debug(" Checking validity for '" +
                        certs[i].getSubjectDN().getName() + "'");
                try {
                    certs[i].checkValidity();
                } catch (Exception e) {
                    if (log.isDebugEnabled())
                        log.debug("  Validity exception", e);
                    return (null);
                }
            }
        }

        // Check the existence of the client Principal in our database
        return (getPrincipal(certs[0].getSubjectDN().getName()));

    
public voidbackgroundProcess()
Execute a periodic task, such as reloading, etc. This method will be invoked inside the classloading context of this container. Unexpected throwables will be caught and logged.

    
public voiddestroy()

    
        // unregister this realm
        if ( oname!=null ) {   
            try {   
                Registry.getRegistry(null, null).unregisterComponent(oname); 
                log.debug( "unregistering realm " + oname );   
            } catch( Exception ex ) {   
                log.error( "Can't unregister realm " + oname, ex);   
            }      
        }
          
    
protected java.lang.Stringdigest(java.lang.String credentials)
Digest the password using the specified algorithm and convert the result to a corresponding hexadecimal string. If exception, the plain credentials string is returned.

param
credentials Password or other credentials to use in authenticating this username


        // If no MessageDigest instance is specified, return unchanged
        if (hasMessageDigest() == false)
            return (credentials);

        // Digest the user credentials and return as hexadecimal
        synchronized (this) {
            try {
                md.reset();
    
                byte[] bytes = null;
                if(getDigestEncoding() == null) {
                    bytes = credentials.getBytes();
                } else {
                    try {
                        bytes = credentials.getBytes(getDigestEncoding());
                    } catch (UnsupportedEncodingException uee) {
                        log.error("Illegal digestEncoding: " + getDigestEncoding(), uee);
                        throw new IllegalArgumentException(uee.getMessage());
                    }
                }
                md.update(bytes);

                return (HexUtils.convert(md.digest()));
            } catch (Exception e) {
                log.error(sm.getString("realmBase.digest"), e);
                return (credentials);
            }
        }

    
protected voiddisableProxyCaching(org.apache.catalina.HttpRequest request, org.apache.catalina.HttpResponse response, boolean disableProxyCaching, boolean securePagesWithPragma)

        HttpServletRequest hsrequest = (HttpServletRequest) request.getRequest();
        // Make sure that constrained resources are not cached by web proxies
        // or browsers as caching can provide a security hole
        if (disableProxyCaching
                && !"POST".equalsIgnoreCase(hsrequest.getMethod())
                && (!checkIfRequestIsSecure || !hsrequest.isSecure())) {
            HttpServletResponse sresponse =
                    (HttpServletResponse) response.getResponse();
            if (securePagesWithPragma) {
                // FIXME: These cause problems with downloading office docs
                // from IE under SSL and may not be needed for newer Mozilla
                // clients.
                sresponse.setHeader("Pragma", "No-cache");
                sresponse.setHeader("Cache-Control", "no-cache");
            } else {
                sresponse.setHeader("Cache-Control", "private");
            }
            sresponse.setHeader("Expires", DATE_ONE);
        }
    
public org.apache.catalina.LifecycleListener[]findLifecycleListeners()
Get the lifecycle listeners associated with this lifecycle. If this Lifecycle has no listeners registered, a zero-length array is returned.


        return lifecycle.findLifecycleListeners();

    
public org.apache.catalina.deploy.SecurityConstraint[]findSecurityConstraints(org.apache.catalina.HttpRequest request, org.apache.catalina.Context context)
Return the SecurityConstraints configured to guard the request URI for this request, or null if there is no such constraint.

param
request Request we are processing
param
context Context the Request is mapped to


        ArrayList results = null;
        // Are there any defined security constraints?
        SecurityConstraint constraints[] = context.findConstraints();
        if ((constraints == null) || (constraints.length == 0)) {
            if (log.isDebugEnabled())
                log.debug("  No applicable constraints defined");
            return (null);
        }

        HttpServletRequest hreq = (HttpServletRequest) request.getRequest();
        // Check each defined security constraint
        String uri = request.getRequestPathMB().toString();
        
        // START SJSWS 6324431
        String origUri = uri;
        boolean caseSensitiveMapping = 
            ((StandardContext)context).isCaseSensitiveMapping();
        if (uri != null && !caseSensitiveMapping) {
            uri = uri.toLowerCase();
        }
        // END SJSWS 6324431

        String method = hreq.getMethod();
        int i;
        boolean found = false;
        for (i = 0; i < constraints.length; i++) {
            SecurityCollection [] collection = constraints[i].findCollections();
                     
            // If collection is null, continue to avoid an NPE
            // See Bugzilla 30624
            if ( collection == null) {
                continue;
            }

            if (log.isTraceEnabled()) {
                /* SJSWS 6324431
                log.trace("  Checking constraint '" + constraints[i] +
                    "' against " + method + " " + uri + " --> " +
                    constraints[i].included(uri, method));
                */
                // START SJSWS 6324431
                log.trace("  Checking constraint '" + constraints[i] +
                          "' against " + method + " " + origUri + " --> " +
                          constraints[i].included(uri, method, 
                                                  caseSensitiveMapping));
                // END SJSWS 6324431
            }
            /* SJSWS 6324431
            if (log.isDebugEnabled() && constraints[i].included(uri, method)) {
                log.debug("  Matched constraint '" + constraints[i] +
                    "' against " + method + " " + uri);
            }
            */
            // START SJSWS 6324431
            if (log.isDebugEnabled()
                    && constraints[i].included(uri, method,
                                               caseSensitiveMapping)) {
                log.debug("  Matched constraint '" + constraints[i] +
                    "' against " + method + " " + origUri);
            }
            // END SJSWS 6324431

            for(int j=0; j < collection.length; j++){
                String [] patterns = collection[j].findPatterns();
 
                // If patterns is null, continue to avoid an NPE
                // See Bugzilla 30624
                if ( patterns == null) {
                    continue;
                }

                for(int k=0; k < patterns.length; k++) {
                    /* SJSWS 6324431
                    if(uri.equals(patterns[k])) {
                    */
                    // START SJSWS 6324431
                    String pattern = caseSensitiveMapping ? patterns[k] :
                        patterns[k].toLowerCase();
                    if (uri != null && uri.equals(pattern)) {
                    // END SJSWS 6324431
                        found = true;
                        if(collection[j].findMethod(method)) {
                            if(results == null) {
                                results = new ArrayList();
                            }
                            results.add(constraints[i]);
                        }
                    }
                }
            }
        }

        if(found) {
            return resultsToArray(results);
        }

        int longest = -1;

        for (i = 0; i < constraints.length; i++) {
            SecurityCollection [] collection = constraints[i].findCollections();
            
            // If collection is null, continue to avoid an NPE
            // See Bugzilla 30624
            if ( collection == null) {
                continue;
            }

            if (log.isTraceEnabled()) {
                /* SJSWS 6324431
                log.trace("  Checking constraint '" + constraints[i] +
                    "' against " + method + " " + uri + " --> " +
                    constraints[i].included(uri, method));
                */
                // START SJSWS 6324431
                log.trace("  Checking constraint '" + constraints[i] +
                          "' against " + method + " " + origUri + " --> " +
                          constraints[i].included(uri, method,
                                                  caseSensitiveMapping));
                // END SJSWS 6324431
            }
            /* SJSWS 6324431
            if (log.isDebugEnabled() && constraints[i].included(uri, method)) {
                log.debug("  Matched constraint '" + constraints[i] +
                    "' against " + method + " " + uri);
            }
            */
            // START SJSWS 6324431
            if (log.isDebugEnabled()
                    && constraints[i].included(uri, method,
                                               caseSensitiveMapping)) {
                log.debug("  Matched constraint '" + constraints[i] +
                    "' against " + method + " " + origUri);
            }
            // END SJSWS 6324431

            for(int j=0; j < collection.length; j++){
                String [] patterns = collection[j].findPatterns();

                // If patterns is null, continue to avoid an NPE
                // See Bugzilla 30624
                if ( patterns == null) {
                    continue;
                }

                boolean matched = false;
                int length = -1;
                for(int k=0; k < patterns.length; k++) {
                    /* SJSWS 6324431
                    String pattern = patterns[k];
                    */
                    // START SJSWS 6324431
                    String pattern = caseSensitiveMapping ?
                        patterns[k]:patterns[k].toLowerCase();
                    // END SJSWS 6324431
                    if(pattern.startsWith("/") && pattern.endsWith("/*") && 
                       pattern.length() >= longest) {
                            
                        if(pattern.length() == 2) {
                            matched = true;
                            length = pattern.length();
                        } else if (uri != null
                                && (pattern.regionMatches(
                                        0,uri,0,pattern.length()-1)
                                    || (pattern.length()-2 == uri.length()
                                        && pattern.regionMatches(
                                            0,uri,0,pattern.length()-2)))) {
                            matched = true;
                            length = pattern.length();
                        }
                    }
                }
                if(matched) {
                    found = true;
                    if(length > longest) {
                        if(results != null) {
                            results.clear();
                        }
                        longest = length;
                    }
                    if(collection[j].findMethod(method)) {
                        if(results == null) {
                            results = new ArrayList();
                        }
                        results.add(constraints[i]);
                    }
                }
            }
        }

        if(found) {
            return  resultsToArray(results);
        }

        for (i = 0; i < constraints.length; i++) {
            SecurityCollection [] collection = constraints[i].findCollections();

            // If collection is null, continue to avoid an NPE
            // See Bugzilla 30624
            if ( collection == null) {
                continue;
            }
            
            if (log.isTraceEnabled()) {
                /* SJSWS 6324431
                log.trace("  Checking constraint '" + constraints[i] +
                    "' against " + method + " " + uri + " --> " +
                    constraints[i].included(uri, method));
                */
                // START SJSWS 6324431
                log.trace("  Checking constraint '" + constraints[i] +
                          "' against " + method + " " + origUri + " --> " +
                          constraints[i].included(uri, method, 
                                                  caseSensitiveMapping));
                // END SJSWS 6324431
            }
            /* SJSWS 6324431
            if (log.isDebugEnabled() && constraints[i].included(uri, method)) {
                log.debug("  Matched constraint '" + constraints[i] +
                    "' against " + method + " " + uri);
            }
            */
            // START SJSWS 6324431
            if (log.isDebugEnabled()
                    && constraints[i].included(uri, method,
                                               caseSensitiveMapping)) {
                log.debug("  Matched constraint '" + constraints[i] +
                    "' against " + method + " " + origUri);
            }
            // END SJSWS 6324431

            boolean matched = false;
            int pos = -1;
            for(int j=0; j < collection.length; j++){
                String [] patterns = collection[j].findPatterns();

                // If patterns is null, continue to avoid an NPE
                // See Bugzilla 30624
                if ( patterns == null) {
                    continue;
                }

                for(int k=0; k < patterns.length && !matched; k++) {
                    /* SJSWS 6324431
                    String pattern = patterns[k];
                    */
                    // START SJSWS 6324431
                    String pattern = caseSensitiveMapping ? 
                        patterns[k]:patterns[k].toLowerCase();
                    // END SJSWS 6324431
                    if (uri != null && pattern.startsWith("*.")){
                        int slash = uri.lastIndexOf("/");
                        int dot = uri.lastIndexOf(".");
                        if(slash >= 0 && dot > slash &&
                           dot != uri.length()-1 &&
                           uri.length()-dot == pattern.length()-1) {
                            if(pattern.regionMatches(1,uri,dot,uri.length()-dot)) {
                                matched = true;
                                pos = j;
                            }
                        }
                    }
                }
            }
            if(matched) {
                found = true;
                if(collection[pos].findMethod(method)) {
                    if(results == null) {
                        results = new ArrayList();
                    }
                    results.add(constraints[i]);
                }
            }
        }

        if(found) {
            return resultsToArray(results);
        }

        for (i = 0; i < constraints.length; i++) {
            SecurityCollection [] collection = constraints[i].findCollections();
            
            // If collection is null, continue to avoid an NPE
            // See Bugzilla 30624
            if ( collection == null) {
                continue;
            }

            if (log.isTraceEnabled()) {
                /* SJSWS 6324431
                log.trace("  Checking constraint '" + constraints[i] +
                    "' against " + method + " " + uri + " --> " +
                    constraints[i].included(uri, method));
                */
                // START SJSWS 6324431
                log.trace("  Checking constraint '" + constraints[i] +
                          "' against " + method + " " + origUri + " --> " +
                          constraints[i].included(uri, method,
                                                  caseSensitiveMapping));
                // END SJSWS 6324431
            }
            /* SJSWS 6324431
            if (log.isDebugEnabled() && constraints[i].included(uri, method)) {
                log.debug("  Matched constraint '" + constraints[i] +
                    "' against " + method + " " + uri);
            }
            */
            // START SJSWS 6324431
            if (log.isDebugEnabled()
                    && constraints[i].included(uri, method,
                                               caseSensitiveMapping)) {
                log.debug("  Matched constraint '" + constraints[i] +
                    "' against " + method + " " + origUri);
            }
            // END SJSWS 6324431

            for(int j=0; j < collection.length; j++){
                String [] patterns = collection[j].findPatterns();

                // If patterns is null, continue to avoid an NPE
                // See Bugzilla 30624
                if ( patterns == null) {
                    continue;
                }

                boolean matched = false;
                for(int k=0; k < patterns.length && !matched; k++) {
                    /* SJSWS 6324431
                    String pattern = patterns[k];
                    */
                    // START SJSWS 6324431
                    String pattern = caseSensitiveMapping ? 
                        patterns[k]:patterns[k].toLowerCase();
                    // END SJSWS 6324431
                    if(pattern.equals("/")){
                        matched = true;
                    }
                }
                if(matched) {
                    if(results == null) {
                        results = new ArrayList();
                    }                    
                    results.add(constraints[i]);
                }
            }
        }

        if(results == null) {
            // No applicable security constraint was found
            if (log.isDebugEnabled())
                log.debug("  No applicable constraint located");
        }
        return resultsToArray(results);
    
public java.lang.StringgetAlternateAuthType(org.apache.catalina.HttpRequest req)
Return an alternate auth type from the request if available. Tomcat realms do not implement this so always return null as default.

param
req The request object.
return
Alternate auth type or null.

        return null;
    
public java.security.PrincipalgetAlternatePrincipal(org.apache.catalina.HttpRequest req)
Return an alternate principal from the request if available. Tomcat realms do not implement this so always return null as default.

param
req The request object.
return
Alternate principal or null.

        return null;
    
public org.apache.catalina.ContainergetContainer()
Return the Container with which this Realm has been associated.



    // ------------------------------------------------------------- Properties


                   
       

        return (container);

    
public javax.management.ObjectNamegetController()

        return controller;
    
public intgetDebug()
Return the debugging detail level for this component.


        return (this.debug);

    
protected java.lang.StringgetDigest(java.lang.String username, java.lang.String realmName)
Return the digest associated with given principal's user name.

        if (md5Helper == null) {
            try {
                md5Helper = MessageDigest.getInstance("MD5");
            } catch (NoSuchAlgorithmException e) {
                log.error("Couldn't get MD5 digest: ", e);
                throw new IllegalStateException(e.getMessage());
            }
        }

    	if (hasMessageDigest()) {
    		// Use pre-generated digest
    		return getPassword(username);
    	}
    	
        String digestValue = username + ":" + realmName + ":"
            + getPassword(username);

        byte[] valueBytes = null;
        if(getDigestEncoding() == null) {
            valueBytes = digestValue.getBytes();
        } else {
            try {
                valueBytes = digestValue.getBytes(getDigestEncoding());
            } catch (UnsupportedEncodingException uee) {
                log.error("Illegal digestEncoding: " + getDigestEncoding(), uee);
                throw new IllegalArgumentException(uee.getMessage());
            }
        }

        byte[] digest = null;
        // Bugzilla 32137
        synchronized(md5Helper) {
            digest = md5Helper.digest(valueBytes);
        }

        return md5Encoder.encode(digest);
    
public java.lang.StringgetDigest()
Return the digest algorithm used for storing credentials.


        return digest;

    
public java.lang.StringgetDigestEncoding()
Returns the digest encoding charset.

return
The charset (may be null) for platform default

        return digestEncoding;
    
public java.lang.StringgetDomain()

        return domain;
    
public java.lang.StringgetInfo()
Return descriptive information about this Realm implementation and the corresponding version number, in the format <description>/<version>.


        return info;

    
protected abstract java.lang.StringgetName()
Return a short name for this Realm implementation, for use in log messages.

public javax.management.ObjectNamegetObjectName()

        return oname;
    
protected abstract java.lang.StringgetPassword(java.lang.String username)
Return the password associated with the given principal's user name.

protected abstract java.security.PrincipalgetPrincipal(java.lang.String username)
Return the Principal associated with the given user name.

public java.lang.StringgetRealmName()
Returns the name of the associated realm.

return
realm name or null if not set.

        // DO NOTHING. PRIVATE EXTENSION
        return null;
    
public java.lang.StringgetType()

        return type;
    
public booleangetValidate()
Return the "validate certificate chains" flag.


        return (this.validate);

    
protected booleanhasMessageDigest()

        return !(md == null);
    
public booleanhasResourcePermission(org.apache.catalina.HttpRequest request, org.apache.catalina.HttpResponse response, org.apache.catalina.deploy.SecurityConstraint[] constraints, org.apache.catalina.Context context)
Perform access control based on the specified authorization constraint. Return true if this constraint is satisfied and processing should continue, or false otherwise.

param
request Request we are processing
param
response Response we are creating
param
constraints Security constraint we are enforcing
param
context The Context to which client of this class is attached.
exception
IOException if an input/output error occurs


        if (constraints == null || constraints.length == 0)
            return (true);

        // Specifically allow access to the form login and form error pages
        // and the "j_security_check" action
        LoginConfig config = context.getLoginConfig();
        if ((config != null) &&
            (Constants.FORM_METHOD.equals(config.getAuthMethod()))) {
            String requestURI = request.getRequestPathMB().toString();
            String loginPage = config.getLoginPage();
            if (loginPage.equals(requestURI)) {
                if (log.isDebugEnabled())
                    log.debug(" Allow access to login page " + loginPage);
                return (true);
            }
            String errorPage = config.getErrorPage();
            if (errorPage.equals(requestURI)) {
                if (log.isDebugEnabled())
                    log.debug(" Allow access to error page " + errorPage);
                return (true);
            }
            if (requestURI.endsWith(Constants.FORM_ACTION)) {
                if (log.isDebugEnabled())
                    log.debug(" Allow access to username/password submission");
                return (true);
            }
        }

        // Which user principal have we already authenticated?
        Principal principal = ((HttpServletRequest)request.getRequest())
                                                            .getUserPrincipal();
        for(int i=0; i < constraints.length; i++) {
            SecurityConstraint constraint = constraints[i];
            String roles[] = constraint.findAuthRoles();
            if (roles == null)
                roles = new String[0];

            if (constraint.getAllRoles())
                return (true);

            if (log.isDebugEnabled())
                log.debug("  Checking roles " + principal);

            if (roles.length == 0) {
                if(constraint.getAuthConstraint()) {

                    /* S1AS 4878272
                    ((HttpServletResponse) response.getResponse()).sendError
                        (HttpServletResponse.SC_FORBIDDEN,
                         sm.getString("realmBase.forbidden"));
                    */
                    // BEGIN S1AS 4878272
                    ((HttpServletResponse) response.getResponse()).sendError
                        (HttpServletResponse.SC_FORBIDDEN);
                    response.setDetailMessage(sm.getString("realmBase.forbidden"));
                    // END S1AS 4878272

                    if( log.isDebugEnabled() ) log.debug("No roles ");
                    return (false); // No listed roles means no access at all
                } else {
                    log.debug("Passing all access");
                    return (true);
                }
            } else if (principal == null) {
                if (log.isDebugEnabled())
                    log.debug("  No user authenticated, cannot grant access");

                /* S1AS 4878272
                ((HttpServletResponse) response.getResponse()).sendError
                    (HttpServletResponse.SC_FORBIDDEN,
                     sm.getString("realmBase.notAuthenticated"));
                */
                // BEGIN S1AS 4878272
                ((HttpServletResponse) response.getResponse()).sendError
                    (HttpServletResponse.SC_FORBIDDEN);
                response.setDetailMessage(sm.getString("realmBase.notAuthenticated"));
                // END S1AS 4878272
                return (false);
            }


            for (int j = 0; j < roles.length; j++) {
                if (hasRole(principal, roles[j]))
                    return (true);
                if( log.isDebugEnabled() )
                    log.debug( "No role found:  " + roles[j]);
            }
        }
        // Return a "Forbidden" message denying access to this resource
        /* S1AS 4878272
        ((HttpServletResponse) response.getResponse()).sendError
        */
        // BEGIN S1AS 4878272
        ((HttpServletResponse) response.getResponse()).sendError
            (HttpServletResponse.SC_FORBIDDEN);
        response.setDetailMessage(sm.getString("realmBase.forbidden"));
        // END S1AS 4878272
        return (false);

    
public booleanhasRole(org.apache.catalina.HttpRequest request, org.apache.catalina.HttpResponse response, java.security.Principal principal, java.lang.String role)
Return true if the specified Principal has the specified security role, within the context of this Realm; otherwise return false. This method can be overridden by Realm implementations. The default implementation is to forward to hasRole(Principal principal, String role).

param
request Request we are processing
param
response Response we are creating
param
principal Principal for whom the role is to be checked
param
role Security role to be checked

        return hasRole(principal, role);
    
public booleanhasRole(java.security.Principal principal, java.lang.String role)
Return true if the specified Principal has the specified security role, within the context of this Realm; otherwise return false. This method can be overridden by Realm implementations, but the default is adequate when an instance of GenericPrincipal is used to represent authenticated Principals from this Realm.

param
principal Principal for whom the role is to be checked
param
role Security role to be checked


        // Should be overriten in JAASRealm - to avoid pretty inefficient conversions
        if ((principal == null) || (role == null) ||
            !(principal instanceof GenericPrincipal))
            return (false);

        GenericPrincipal gp = (GenericPrincipal) principal;
        if (!(gp.getRealm() == this)) {
            log.debug("Different realm " + this + " " + gp.getRealm());//    return (false);
        }
        boolean result = gp.hasRole(role);
        if (log.isDebugEnabled()) {
            String name = principal.getName();
            if (result)
                log.debug(sm.getString("realmBase.hasRoleSuccess", name, role));
            else
                log.debug(sm.getString("realmBase.hasRoleFailure", name, role));
        }
        return (result);

    
public booleanhasUserDataPermission(org.apache.catalina.HttpRequest request, org.apache.catalina.HttpResponse response, org.apache.catalina.deploy.SecurityConstraint[] constraints)
Enforce any user data constraint required by the security constraint guarding this request URI. Return true if this constraint was not violated and processing should continue, or false if we have created a response already.

param
request Request we are processing
param
response Response we are creating
param
constraints Security constraint being checked
exception
IOException if an input/output error occurs


        // Is there a relevant user data constraint?
        if (constraints == null || constraints.length == 0) {
            if (log.isDebugEnabled())
                log.debug("  No applicable security constraint defined");
            return (true);
        }
        for(int i=0; i < constraints.length; i++) {
            SecurityConstraint constraint = constraints[i];
            String userConstraint = constraint.getUserConstraint();
            if (userConstraint == null) {
                if (log.isDebugEnabled())
                    log.debug("  No applicable user data constraint defined");
                return (true);
            }
            if (userConstraint.equals(Constants.NONE_TRANSPORT)) {
                if (log.isDebugEnabled())
                    log.debug("  User data constraint has no restrictions");
                return (true);
            }

        }
        // Validate the request against the user data constraint
        if (request.getRequest().isSecure()) {
            if (log.isDebugEnabled())
                log.debug("  User data constraint already satisfied");
            return (true);
        }
        // Initialize variables we need to determine the appropriate action
        HttpServletRequest hrequest = (HttpServletRequest) request.getRequest();
        HttpServletResponse hresponse = (HttpServletResponse) 
                                                         response.getResponse();
        int redirectPort = request.getConnector().getRedirectPort();

        // Is redirecting disabled?
        if (redirectPort <= 0) {
            if (log.isDebugEnabled())
                log.debug("  SSL redirect is disabled");
            /* S1AS 4878272
            hresponse.sendError
            response.sendError
                (HttpServletResponse.SC_FORBIDDEN,
                 hrequest.getRequestURI());
            */
            // BEGIN S1AS 4878272
            hresponse.sendError(HttpServletResponse.SC_FORBIDDEN);
            response.setDetailMessage(hrequest.getRequestURI());
            // END S1AS 4878272
            return (false);
        }

        // Redirect to the corresponding SSL port
        StringBuffer file = new StringBuffer();
        String protocol = "https";
        String host = hrequest.getServerName();
        // Protocol
        file.append(protocol).append("://").append(host);
        // Host with port
        if(redirectPort != 443) {
            file.append(":").append(redirectPort);
        }
        // URI
        file.append(hrequest.getRequestURI());
        String requestedSessionId = hrequest.getRequestedSessionId();
        if ((requestedSessionId != null) &&
            hrequest.isRequestedSessionIdFromURL()) {
            file.append(";jsessionid=");
            file.append(requestedSessionId);
        }
        String queryString = hrequest.getQueryString();
        if (queryString != null) {
            file.append('?");
            file.append(queryString);
        }
        if (log.isDebugEnabled())
            log.debug("  Redirecting to " + file.toString());
        hresponse.sendRedirect(file.toString());
        return (false);

    
public voidinit()

    
       
        if( initialized && container != null ) return;
        
        initialized=true;
        if( container== null ) {
            ObjectName parent=null;
            // Register with the parent
            try {
                if( host == null ) {
                    // global
                    parent=new ObjectName(domain +":type=Engine");
                } else if( path==null ) {
                    parent=new ObjectName(domain +
                            ":type=Host,host=" + host);
                } else {
                    parent=new ObjectName(domain +":j2eeType=WebModule,name=//" +
                            host + path);
                }
                if( mserver.isRegistered(parent ))  {
                    log.debug("Register with " + parent);
                    mserver.setAttribute(parent, new Attribute("realm", this));
                }
            } catch (Exception e) {
                log.info("Parent not available yet: " + parent);  
            }
        }
        
        if( oname==null ) {
            // register
            try {
                ContainerBase cb=(ContainerBase)container;
                oname=new ObjectName(cb.getDomain()+":type=Realm" + cb.getContainerSuffix());
                Registry.getRegistry(null, null).registerComponent(this, oname, null );
                log.debug("Register Realm "+oname);
            } catch (Throwable e) {
                log.error( "Can't register " + oname, e);
            }
        }

    
public booleaninvokeAuthenticateDelegate(org.apache.catalina.HttpRequest request, org.apache.catalina.HttpResponse response, org.apache.catalina.Context context, org.apache.catalina.Authenticator authenticator)
Authenticates the user making this request, based on the specified login configuration. Return true if any specified requirements have been satisfied, or false if we have created a response challenge already.

param
request Request we are processing
param
response Response we are creating
param
context The Context to which client of this class is attached.
param
authentication the current authenticator.
exception
IOException if an input/output error occurs

        LoginConfig config = context.getLoginConfig();
        return ((AuthenticatorBase) authenticator).authenticate(
                        request, response, config);
    
public booleaninvokePostAuthenticateDelegate(org.apache.catalina.HttpRequest request, org.apache.catalina.HttpResponse response, org.apache.catalina.Context context)
Post authentication for given request and response.

param
request Request we are processing
param
response Response we are creating
param
context The Context to which client of this class is attached.
exception
IOException if an input/output error occurs

         return true;
    
protected voidlog(java.lang.String message)
Log a message on the Logger associated with our Container (if any)

param
message Message to be logged


        Logger logger = null;
        String name = null;
        if (container != null) {
            logger = container.getLogger();
            name = container.getName();
        }

        if (logger != null) {
            logger.log(getName()+"[" + name + "]: " + message);
        } else {
            System.out.println(getName()+"[" + name + "]: " + message);
        }

    
protected voidlog(java.lang.String message, java.lang.Throwable throwable)
Log a message on the Logger associated with our Container (if any)

param
message Message to be logged
param
throwable Associated exception


        Logger logger = null;
        String name = null;
        if (container != null) {
            logger = container.getLogger();
            name = container.getName();
        }

        if (logger != null) {
            logger.log(getName()+"[" + name + "]: " + message, throwable);
        } else {
            System.out.println(getName()+"[" + name + "]: " + message);
            throwable.printStackTrace(System.out);
        }
    
public static voidmain(java.lang.String[] args)
Digest password using the algorithm especificied and convert the result to a corresponding hex string. If exception, the plain credentials string is returned


        String encoding = null;
        int firstCredentialArg = 2;
        
        if (args.length > 4 && args[2].equalsIgnoreCase("-e")) {
            encoding = args[3];
            firstCredentialArg = 4;
        }
        
        if(args.length > firstCredentialArg && args[0].equalsIgnoreCase("-a")) {
            for(int i=firstCredentialArg; i < args.length ; i++){
                System.out.print(args[i]+":");
                System.out.println(Digest(args[i], args[1], encoding));
            }
        } else {
            System.out.println
                ("Usage: RealmBase -a <algorithm> [-e <encoding>] <credentials>");
        }

    
public voidpostDeregister()

    
public voidpostRegister(java.lang.Boolean registrationDone)

    
public intpreAuthenticateCheck(org.apache.catalina.HttpRequest request, org.apache.catalina.HttpResponse response, org.apache.catalina.deploy.SecurityConstraint[] constraints, boolean disableProxyCaching, boolean securePagesWithPragma, boolean ssoEnabled)
Checks whether or not authentication is needed. Returns an int, one of AUTHENTICATE_NOT_NEEDED, AUTHENTICATE_NEEDED, or AUTHENTICATED_NOT_AUTHORIZED.

param
request Request we are processing
param
response Response we are creating
param
constraints Security constraint we are enforcing
param
disableProxyCaching whether or not to disable proxy caching for protected resources.
param
securePagesWithPragma true if we add headers which are incompatible with downloading office documents in IE under SSL but which fix a caching problem in Mozilla.
param
ssoEnabled true if sso is enabled
exception
IOException if an input/output error occurs

        for(int i=0; i < constraints.length; i++) {
            if (constraints[i].getAuthConstraint()) {
                disableProxyCaching(request, response, disableProxyCaching, securePagesWithPragma);
                return Realm.AUTHENTICATE_NEEDED;
            }
        }
        return Realm.AUTHENTICATE_NOT_NEEDED;
    
public voidpreDeregister()

    
public javax.management.ObjectNamepreRegister(javax.management.MBeanServer server, javax.management.ObjectName name)

        oname=name;
        mserver=server;
        domain=name.getDomain();

        type=name.getKeyProperty("type");
        host=name.getKeyProperty("host");
        path=name.getKeyProperty("path");

        return name;
    
public voidremoveLifecycleListener(org.apache.catalina.LifecycleListener listener)
Remove a lifecycle event listener from this component.

param
listener The listener to remove


        lifecycle.removeLifecycleListener(listener);

    
public voidremovePropertyChangeListener(java.beans.PropertyChangeListener listener)
Remove a property change listener from this component.

param
listener The listener to remove


        support.removePropertyChangeListener(listener);

    
private org.apache.catalina.deploy.SecurityConstraint[]resultsToArray(java.util.ArrayList results)
Convert an ArrayList to a SecurityContraint [].

        if(results == null) {
            return null;
        }
        SecurityConstraint [] array = new SecurityConstraint[results.size()];
        results.toArray(array);
        return array;
    
public voidsetContainer(org.apache.catalina.Container container)
Set the Container with which this Realm has been associated.

param
container The associated Container


        Container oldContainer = this.container;
        this.container = container;
        this.checkIfRequestIsSecure = container.isCheckIfRequestIsSecure();
        support.firePropertyChange("container", oldContainer, this.container);

    
public voidsetController(javax.management.ObjectName controller)

        this.controller = controller;
    
public voidsetDebug(int debug)
Set the debugging detail level for this component.

param
debug The new debugging detail level


        this.debug = debug;

    
public voidsetDigest(java.lang.String digest)
Set the digest algorithm used for storing credentials.

param
digest The new digest algorithm


        this.digest = digest;

    
public voidsetDigestEncoding(java.lang.String charset)
Sets the digest encoding charset.

param
charset The charset (null for platform default)

        digestEncoding = charset;
    
public voidsetRealmName(java.lang.String name, java.lang.String authMethod)
Set the name of the associated realm.

param
name the name of the realm.

        // DO NOTHING. PRIVATE EXTENSION
    
public voidsetValidate(boolean validate)
Set the "validate certificate chains" flag.

param
validate The new validate certificate chains flag


        this.validate = validate;

    
public voidstart()
Prepare for the beginning of active use of the public methods of this component. This method should be called before any of the public methods of this component are utilized. It should also send a LifecycleEvent of type START_EVENT to any registered listeners.

exception
LifecycleException if this component detects a fatal error that prevents this component from being used


        // Validate and update our current component state
        if (started) {
            log.info(sm.getString("realmBase.alreadyStarted"));
            return;
        }
        if( !initialized ) {
            init();
        }
        lifecycle.fireLifecycleEvent(START_EVENT, null);
        started = true;

        // Create a MessageDigest instance for credentials, if desired
        if (digest != null) {
            try {
                md = MessageDigest.getInstance(digest);
            } catch (NoSuchAlgorithmException e) {
                throw new LifecycleException
                    (sm.getString("realmBase.algorithm", digest), e);
            }
        }

    
public voidstop()
Gracefully terminate the active use of the public methods of this component. This method should be the last one called on a given instance of this component. It should also send a LifecycleEvent of type STOP_EVENT to any registered listeners.

exception
LifecycleException if this component detects a fatal error that needs to be reported


        // Validate and update our current component state
        if (!started) {
            log.info(sm.getString("realmBase.notStarted"));
            return;
        }
        lifecycle.fireLifecycleEvent(STOP_EVENT, null);
        started = false;

        // Clean up allocated resources
        md = null;
        
        destroy();