FileDocCategorySizeDatePackage
Audit.javaAPI DocGlassfish v2 API28331Fri May 04 22:35:22 BST 2007com.sun.enterprise.security

Audit.java

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 * 
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License. You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [year]
 * [name of copyright owner]"
 * 
 * Contributor(s):
 * 
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package com.sun.enterprise.security;

import java.util.*;
import java.lang.reflect.*;

import java.util.logging.Logger;
import java.util.logging.Level;
import java.security.Principal;

import com.sun.enterprise.config.serverbeans.Server;
import com.sun.enterprise.config.serverbeans.SecurityService;
import com.sun.enterprise.config.serverbeans.ServerBeansFactory;
import com.sun.enterprise.config.ConfigContext;
import com.sun.enterprise.server.ApplicationServer;

import com.sun.logging.LogDomains;
import org.apache.catalina.HttpRequest;

import com.sun.enterprise.deployment.Application;
import com.sun.enterprise.deployment.EjbBundleDescriptor;
import com.sun.enterprise.deployment.EjbDescriptor;
import com.sun.enterprise.deployment.MethodPermission;
import com.sun.enterprise.deployment.MethodDescriptor;
import com.sun.enterprise.deployment.RunAsIdentityDescriptor;
import com.sun.enterprise.deployment.EjbIORConfigurationDescriptor;
import com.sun.enterprise.deployment.WebBundleDescriptor;
import com.sun.enterprise.deployment.SecurityConstraintImpl;
import com.sun.enterprise.deployment.AuthorizationConstraintImpl;
import com.sun.enterprise.deployment.WebResourceCollectionImpl;
import com.sun.enterprise.deployment.web.LoginConfiguration;
import com.sun.enterprise.deployment.web.UserDataConstraint;
import com.sun.enterprise.deployment.web.SecurityRole;
import com.sun.enterprise.deployment.WebComponentDescriptor;
import com.sun.ejb.containers.EJBLocalRemoteObject;
import com.sun.enterprise.security.SecurityContext;

import com.sun.enterprise.deployment.Role;
import com.sun.enterprise.deployment.interfaces.SecurityRoleMapper;
import javax.servlet.http.HttpServletRequest;

import com.sun.appserv.security.AuditModule;

/**
 * Audit support class.
 *
 * <P>This class provides convenience methods for producing audit output.
 * Audit output is logged using the standard iAS logger SECURITYLOGGER.
 * However, audit output is only produced if auditing is active. Auditing
 * is configured in server.xml in the security-service element.
 *
 * <P>Audit output if logged with Level.WARNING.
 *
 * <P>Some diagnostic methods are also provided for debugging.
 *
 */
public class Audit extends AuditModule
{
    private static final String AUDIT_ON = "auditOn";
    private static boolean auditFlag = false;
    private static Logger logger =
        LogDomains.getLogger(LogDomains.SECURITY_LOGGER);
    /*
    private static String strPrivateAudit = null;
    private static String strDenied = null;
    private static String strOK = null;
    private static String strMethodName = null;
    private static String strSession = null;
    */
    
    /**
     * Check auditing state.
     *
     * @returns True if auditing is active currently.
     *
     */
    public static boolean isActive()
    {
        return auditFlag;
    }

    public void init(Properties props) {
        super.init(props);
        String audit = props.getProperty(AUDIT_ON);
        auditFlag = (audit == null)?false: Boolean.valueOf(audit).booleanValue();
    }
    
    /**
     * Invoked post authentication request for a user in a given realm
     * @param user username for whom the authentication request was made
     * @param realm the realm name under which the user is authenticated.
     * @param success the status of the authentication
     */
    public void authentication(String user, String realm, boolean success) {
        if (auditFlag) {
            StringBuffer sbuf = new StringBuffer("Audit: Authentication for user = (");
            sbuf.append(user); 
            sbuf.append(") under realm = (");
            sbuf.append(realm).append(") returned = ").append(success);
            logger.log(Level.INFO, sbuf.toString());
        }
    }
    
    /**
     * Invoked post web authorization request. 
     * @param user the username for whom the authorization was performed
     * @param req the HttpRequest object for the web request
     * @param type either hasResourcePermission, hasUserDataPermission or 
     * hasRoleRefPermission
     * @param success the status of the web authorization request
     */
    public void webInvocation(String user, HttpServletRequest req,
            String type, boolean success) 
    {
        if (auditFlag){
            StringBuilder sbuf = new StringBuilder("Audit: [Web] Authorization for user = (");
            sbuf.append(user).append(") and permission type = (").append(type).append(") for request ");
            sbuf.append(req.getMethod()).append(" ").append(req.getRequestURI()).append(" returned =").append(success);
            logger.log(Level.INFO, sbuf.toString());
        }
    }
    /**
     * Invoked post ejb authorization request.
     * @param user the username for whom the authorization was performed
     * @param ejb the ejb name for which this authorization was performed
     * @param method the method name for which this authorization was performed
     * @param success the status of the ejb authorization request
     */
    public void ejbInvocation(String user, String ejb, String method, boolean success) {
        if(auditFlag){
            // Modified from StringBuffer to StringBuilder
            StringBuilder sbuf = new StringBuilder("Audit: [EJB] Authorization for user =");
            sbuf.append(user).append(" for ejb = (");
            sbuf.append(ejb).append(") method = (").append(method).append(") returned =").append(success);
            logger.log(Level.INFO, sbuf.toString());
        }
    }

    /**
     * Invoked post ejb authorization request.
     * @param user the username for whom the authorization was performed
     * @param ejb the ejb name for which this authorization was performed
     * @param method the method name for which this authorization was performed
     * @param success the status of the ejb authorization request
     */

    /**
     * Invoked during validation of the web service request
     * @param uri The URL representation of the web service endpoint
     * @param endpoint The name of the endpoint representation
     * @param success the status of the web service request validation
     */
    public void webServiceInvocation(String uri, String endpoint, boolean success) {

        if(auditFlag){
            StringBuilder sbuf = new StringBuilder("Audit: [WebService] ");
            sbuf.append("uri: ").append(uri);
            sbuf.append("endpoint: ").append(endpoint);
            sbuf.append(", valid request =").append(success);
            logger.log(Level.INFO, sbuf.toString());
        }
    }


    /**
     * Invoked during validation of the web service request
     * @param endpoint The URL representation of the web service endpoint
     * @param success the status of the web service request validation
     */
    public void ejbAsWebServiceInvocation(String endpoint, boolean success) {

        if(auditFlag){
            StringBuilder sbuf = new StringBuilder("Audit: [EjbAsWebService] ");
            sbuf.append("endpoint : ").append(endpoint).append(", valid request =").append(success);
            logger.log(Level.INFO, sbuf.toString());
        }
    }


    /**
     * Invoked upon completion of the server startup
     */
    public void serverStarted() {
        if(auditFlag){
            logger.log(Level.INFO, "Audit: Application server startup complete");
        }
    }

    /**
     * Invoked upon completion of the server shutdown
     */
    public void serverShutdown() {
        if(auditFlag){
            logger.log(Level.INFO, "Audit: Application server shutdown complete");
        }
    }

    /**
     * Initialize auditing.  This reads the server.xml configuration to
     * determine whether audit is turned on or off.
     *
     */
    /*
    public static void init()
    {
        try {
            ConfigContext configContext =
                ApplicationServer.getServerContext().getConfigContext();
            assert(configContext != null);

            Server configBean =
                ServerBeansFactory.getServerBean(configContext);
            assert(configBean != null);

            SecurityService securityBean =
                ServerBeansFactory.getSecurityServiceBean(configContext);
            assert(securityBean != null);

            auditFlag = securityBean.isAuditEnabled();
            
        } catch (Exception e) {
            logger.log(Level.WARNING, "audit.badinit", e);
        }

        if (auditFlag) {
            logger.info("audit.enabled");
        }

                                // load i18n message bits for audit entries
        ResourceBundle resBundle = logger.getResourceBundle();
        strPrivateAudit = resBundle.getString("audit.string_private_audit");
        strDenied = " " + resBundle.getString("audit.denied");
        strOK = " " + resBundle.getString("audit.ok");
        strMethodName = " " + resBundle.getString("audit.methodname");
        strSession = " " + resBundle.getString("audit.session");
    }

*/
    /**
     * Log an EJB method invocation.
     *
     * @param user Effective user for the invocation.
     * @param ejb EJB name.
     * @param method Method name.
     * @param success True if the invocation was allowed, false if denied.
     *
     */
/*
    public static void ejbMethodInvocation(SecurityContext secCtx,
                                           EJBLocalRemoteObject ejbObj,
                                           Method method,
                                           boolean success)
    {
        if (!logger.isLoggable(Level.INFO)) {
            return;
        }
        
        String user = "(null)";
        if (secCtx != null) {
            Principal p = secCtx.getCallerPrincipal();
            if (p!=null) {
                user = p.getName();
            }
        }

        String ejb = "(N/A)";
        if (ejbObj != null) {
            ejb = ejbObj.toString();
        }

        String meth = "(N/A)";
        if (method != null) {
            meth = method.toString();
        }
        
        StringBuffer sb = new StringBuffer();
        sb.append(strPrivateAudit); // "Audit: principal="
        
        if(user != null) {
            sb.append(user);
        } else {
            sb.append("(null)");
        }

        sb.append(" ejb=");
        sb.append(ejb);
        sb.append(strMethodName); // " method="
        sb.append(method);
        if (success) {
            sb.append(strOK);   // " OK"
        } else {
            sb.append(strDenied); // " DENIED"
        }

        logger.info(sb.toString());
    }

*/
    /**
     * Log a servlet invocation.
     *
     * @param req The HttpRequest.
     * @param success True if the invocation was allowed, false if denied.
     *
     */
  /*
    public static void webInvocation(HttpRequest req, boolean success)
    {
        /// DO NOTHING FOR NOW.
        //if (!logger.isLoggable(Level.INFO) || !auditFlag) {
        //    return;
        //}
                
        //if (req == null) {
        //    logger.fine("Audit: No HttpRequest available.");
        //    return;
        //}
        
        //if (!(req instanceof HttpRequestBase)) {
        //    logger.fine("Audit internal error, class: " + req.getClass());
        //    return;
        //}

        //HttpRequestBase reqs = (HttpRequestBase)req;
        
        //StringBuffer sb = new StringBuffer();
        //sb.append(strPrivateAudit); // "Audit: principal="
        
        //String user = reqs.getRemoteUser();
        //if (user != null) {
        //    sb.append(user);
        //} else {
        //    sb.append("(null)");
        //}

        //sb.append(" ");
        //sb.append(reqs.getMethod());
        //sb.append(" ");
        //sb.append(reqs.getRequestURI());
        //sb.append(strSession); //  " session="
        //sb.append(reqs.getRequestedSessionId());
        //if (success) {
        //    sb.append(strOK);   //  " OK"
        //} else {
        //    sb.append(strDenied); // " DENIED"
        //}

        //logger.info(sb.toString());
    }

    */
    /**
     * Diagnostic method. Read roles and ACLs from the given Application
     * and dump a somewhat organized summary of what has been set.
     * This can be used to diagnose deployment or runtime deployment errors
     * as well as to help in configuring application descriptors.
     *
     * <P>Implementation is not particularly efficient but this is only
     * called for debugging purposes at startup. All errors are ignored.
     *
     * @param app Application object to analyze.
     *
     */
    public static void showACL(Application app)
    {
        if (!isActive() || !logger.isLoggable(Level.FINEST)) {
            return;
        }

        try {
            dumpDiagnostics(app);

        } catch (Throwable e) {
            logger.fine("Error while showing ACL diagnostics: " +
                        e.toString());
        }
    }

    
    /**
     * Do the work for showACL().
     *
     */
    private static void dumpDiagnostics(Application app)
    {
        logger.finest("====[ Role and ACL Summary ]==========");
        if (!app.isVirtual()) {
            logger.finest("Summary for application: "+
                          app.getRegistrationName());
        } else {
            logger.finest("Standalone module.");
        }
        logger.finest("EJB components: "+
                           app.getEjbComponentCount());
        logger.finest("Web components: " +
                           app.getWebComponentCount());

        Iterator i;
        StringBuffer sb;
        
        // show all roles with associated group & user mappings
        Set allRoles = app.getRoles();
        if (allRoles == null) {
            logger.finest("- No roles present.");
            return;
        }
        SecurityRoleMapper rmap = app.getRoleMapper();
        if (rmap == null) {
            logger.finest("- No role mappings present.");
            return;
        }
        
        i = allRoles.iterator();
        logger.finest("--[ Configured roles and mappings ]--");
        HashMap allRoleMap = new HashMap();
        
        while (i.hasNext()) {
            Role r = (Role)i.next();
            logger.finest(" [" + r.getName() + "]");
            allRoleMap.put(r.getName(), new HashSet());
            
            sb = new StringBuffer();
            sb.append("  is mapped to groups: ");
            Enumeration grps = rmap.getGroupsAssignedTo(r);
            while (grps.hasMoreElements()) {
                sb.append(grps.nextElement());
                sb.append(" ");
            }
            logger.finest(sb.toString());

            sb = new StringBuffer();
            sb.append("  is mapped to principals: ");
            Enumeration users = rmap.getUsersAssignedTo(r);
            while (users.hasMoreElements()) {
                sb.append(users.nextElement());
                sb.append(" ");
            }
            logger.finest(sb.toString());
        }

        // Process all EJB modules

        Set ejbDescriptorSet = app.getEjbBundleDescriptors() ;

        i = ejbDescriptorSet.iterator();
        while (i.hasNext()) {

            EjbBundleDescriptor bundle = (EjbBundleDescriptor)i.next();

            logger.finest("--[ EJB module: " + bundle.getName() + " ]--");
            Set ejbs = bundle.getEjbs();
            Iterator it = ejbs.iterator();
            while (it.hasNext()) {

                EjbDescriptor ejb = (EjbDescriptor)it.next();
                logger.finest("EJB: "+ejb.getEjbClassName());

                // check and show run-as if present
                if (!ejb.getUsesCallerIdentity()) {
                     RunAsIdentityDescriptor runas = ejb.getRunAsIdentity();
                     if (runas == null) {
                         logger.finest(" (ejb does not use caller "+
                                            "identity)");
                     } else {
                         String role = runas.getRoleName();
                         String user = runas.getPrincipal();
                         logger.finest(" Will run-as: Role: " + role +
                                            "  Principal: " + user);
                         if (role==null || "".equals(role) ||
                             user==null || "".equals(user)) {
                                 if(logger.isLoggable(Level.FINEST)){
                                    logger.finest("*** Configuration error!");
                                 }
                         }
                     }
                }

                // iterate through available methods
                logger.finest(" Method to Role restriction list:");
                Set methods = ejb.getMethodDescriptors();
                Iterator si = methods.iterator();
                
                while (si.hasNext()) {
                    
                    MethodDescriptor md = (MethodDescriptor)si.next();
                    logger.finest("   "+md.getFormattedString());

                    Set perms = ejb.getMethodPermissionsFor(md);
                    StringBuffer rbuf = new StringBuffer();
                    rbuf.append("     can only be invoked by: ");
                    Iterator sip = perms.iterator();
                    boolean unchecked=false,excluded=false,roleBased=false;
                    
                    while (sip.hasNext()) {
                        MethodPermission p = (MethodPermission)sip.next();
                        if (p.isExcluded()) {
                            excluded=true;
                            logger.finest("     excluded - can not "+
                                               "be invoked");
                        } else if (p.isUnchecked()) {
                            unchecked=true;
                            logger.finest("     unchecked - can be "+
                                               "invoked by all");
                        } else if (p.isRoleBased()) {
                            roleBased = true;
                            Role r = p.getRole();
                            rbuf.append(r.getName());
                            rbuf.append(" ");
                                // add to role's accessible list
                            HashSet ram = (HashSet)allRoleMap.get(r.getName());
                            ram.add(bundle.getName() + ":" +
                                    ejb.getEjbClassName() + "." +
                                    md.getFormattedString());
                        }
                    }

                    if (roleBased) {
                        logger.finest(rbuf.toString());
                        if (excluded || unchecked) {
                            logger.finest("*** Configuration error!");
                        }
                    } else if (unchecked) {
                        if (excluded) {
                            logger.finest("*** Configuration error!");
                        }
                        Set rks = allRoleMap.keySet();
                        Iterator rksi = rks.iterator();
                        while (rksi.hasNext()) {
                            HashSet ram = (HashSet)allRoleMap.get(rksi.next());
                            ram.add(bundle.getName() + ":" +
                                    ejb.getEjbClassName() + "." +
                                    md.getFormattedString());
                        }
                    } else if (!excluded) {
                        logger.finest("*** Configuration error!");
                    }
                }

                // IOR config for this ejb
                logger.finest(" IOR configuration:");
                Set iors = ejb.getIORConfigurationDescriptors();
                if (iors != null) {
                    Iterator iorsi = iors.iterator();
                    while (iorsi.hasNext()) {
                        EjbIORConfigurationDescriptor ior =
                            (EjbIORConfigurationDescriptor)iorsi.next();
                        StringBuffer iorsb = new StringBuffer();
                        iorsb.append("realm=");
                        iorsb.append(ior.getRealmName());
                        iorsb.append(", integrity=");
                        iorsb.append(ior.getIntegrity());
                        iorsb.append(", trust-in-target=");
                        iorsb.append(ior.getEstablishTrustInTarget());
                        iorsb.append(", trust-in-client=");
                        iorsb.append(ior.getEstablishTrustInClient());
                        iorsb.append(", propagation=");
                        iorsb.append(ior.getCallerPropagation());
                        iorsb.append(", auth-method=");
                        iorsb.append(ior.getAuthenticationMethod());
                        logger.finest(iorsb.toString());
                    }
                }
            }
        }

        // show role->accessible methods list
        logger.finest("--[ EJB methods accessible by role ]--");

        Set rks = allRoleMap.keySet();
        Iterator rksi = rks.iterator();
        while (rksi.hasNext()) {
            String roleName = (String)rksi.next();
            logger.finest(" [" + roleName + "]");
            HashSet ram = (HashSet)allRoleMap.get(roleName);
            Iterator rami = ram.iterator();
            while (rami.hasNext()) {
                String meth = (String)rami.next();
                logger.finest("   "+meth);
            }
        }

        

        // Process all Web modules

        Set webDescriptorSet = app.getWebBundleDescriptors() ;

        i = webDescriptorSet.iterator();
        while (i.hasNext()) {
            WebBundleDescriptor wbd = (WebBundleDescriptor)i.next();
            logger.finest("--[ Web module: " + wbd.getContextRoot() + " ]--");

            // login config
            LoginConfiguration lconf = wbd.getLoginConfiguration();
            if (lconf != null) {
                logger.finest("  Login config: realm="+
                              lconf.getRealmName() + ", method="+
                              lconf.getAuthenticationMethod() + ", form="+
                              lconf.getFormLoginPage() + ", error="+
                              lconf.getFormErrorPage());
            }

            // get WebComponentDescriptorsSet()  info
            logger.finest("  Contains components:");
            Set webComps = wbd.getWebComponentDescriptorsSet();
            Iterator webCompsIt = webComps.iterator();
            while (webCompsIt.hasNext()) {
                WebComponentDescriptor wcd =
                    (WebComponentDescriptor)webCompsIt.next();
                StringBuffer name = new StringBuffer();
                name.append("   - "+wcd.getCanonicalName());
                name.append(" [ ");
                Enumeration urlPs = wcd.getUrlPatterns();
                while (urlPs.hasMoreElements()) {
                    name.append(urlPs.nextElement().toString());
                    name.append(" ");
                }
                name.append("]");
                logger.finest(name.toString());
                
                RunAsIdentityDescriptor runas =
                    (RunAsIdentityDescriptor)wcd.getRunAsIdentity();
                if (runas!=null) {
                    String role = runas.getRoleName();
                    String user = runas.getPrincipal();
                    logger.finest("      Will run-as: Role: " + role +
                                  "  Principal: " + user);
                    if (role==null || "".equals(role) ||
                        user==null || "".equals(user)) {
                        logger.finest("*** Configuration error!");
                    }
                }
                
            }
            
            // security constraints
            logger.finest("  Security constraints:");
            Enumeration scEnum = wbd.getSecurityConstraints();
            while (scEnum.hasMoreElements()) {

                SecurityConstraintImpl sc =
                    (SecurityConstraintImpl)scEnum.nextElement();

                Set wrcSet = sc.getWebResourceCollectionSet();
                Iterator wrcIt = wrcSet.iterator();
                while (wrcIt.hasNext()) {
                    WebResourceCollectionImpl wrc =
                        (WebResourceCollectionImpl)wrcIt.next();

                    // show list of methods for this collection
                    Enumeration methEnum = wrc.getHttpMethods();
                    StringBuffer sbm = new StringBuffer();
                    while (methEnum.hasMoreElements()) {
                        sbm.append(methEnum.nextElement());
                        sbm.append(" ");
                    }
                    logger.finest("     Using method: "+sbm.toString());

                    // and then list of url patterns
                    Enumeration urlEnum = wrc.getUrlPatterns();
                    while (urlEnum.hasMoreElements()) {
                        logger.finest("       "+
                                      urlEnum.nextElement().toString());
                    }
                } // end res.collection iterator

                // show roles which apply to above set of collections
                AuthorizationConstraintImpl authCons =
                 (AuthorizationConstraintImpl)sc.getAuthorizationConstraint();
                Enumeration rolesEnum = authCons.getSecurityRoles();
                StringBuffer rsb = new StringBuffer();
                rsb.append("     Accessible by roles: ");
                while (rolesEnum.hasMoreElements()) {
                    SecurityRole sr = (SecurityRole)rolesEnum.nextElement();
                    rsb.append(sr.getName());
                    rsb.append(" ");
                }
                logger.finest(rsb.toString());

                // show transport guarantee
                UserDataConstraint udc =sc.getUserDataConstraint();
                if (udc != null) {
                    logger.finest("     Transport guarantee: "+
                                  udc.getTransportGuarantee());
                }
                
            } // end sec.constraint
            
        } // end webDescriptorSet.iterator
        

        logger.finest("======================================");
    }
    

}