Save This Page
Home » JBoss-5.1.0 » org » jboss » web » tomcat » security » [javadoc | source]
    1   /*
    2    * JBoss, Home of Professional Open Source.
    3    * Copyright 2008, Red Hat Middleware LLC, and individual contributors
    4    * as indicated by the @author tags. See the copyright.txt file in the
    5    * distribution for a full listing of individual contributors.
    6    *
    7    * This is free software; you can redistribute it and/or modify it
    8    * under the terms of the GNU Lesser General Public License as
    9    * published by the Free Software Foundation; either version 2.1 of
   10    * the License, or (at your option) any later version.
   11    *
   12    * This software is distributed in the hope that it will be useful,
   13    * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   15    * Lesser General Public License for more details.
   16    *
   17    * You should have received a copy of the GNU Lesser General Public
   18    * License along with this software; if not, write to the Free
   19    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
   20    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
   21    */
   22   package org.jboss.web.tomcat.security;
   23   
   24   import java.io.IOException;
   25   import java.security.Principal;
   26   
   27   import javax.naming.InitialContext;
   28   import javax.naming.NamingException;
   29   import javax.security.auth.Subject;
   30   import javax.servlet.ServletException;
   31   import javax.servlet.http.HttpSession;
   32   
   33   import org.apache.catalina.Manager;
   34   import org.apache.catalina.Session;
   35   import org.apache.catalina.Wrapper;
   36   import org.apache.catalina.connector.Request;
   37   import org.apache.catalina.connector.Response;
   38   import org.apache.catalina.valves.ValveBase;
   39   import org.jboss.logging.Logger;
   40   import org.jboss.metadata.javaee.jboss.RunAsIdentityMetaData;
   41   import org.jboss.metadata.web.jboss.JBossWebMetaData;
   42   import org.jboss.security.AuthenticationManager;
   43   import org.jboss.security.RunAsIdentity;
   44   import org.jboss.security.plugins.JaasSecurityManagerServiceMBean;
   45   import org.jboss.servlet.http.HttpEvent;
   46   
   47   /**
   48    * A Valve that sets/clears the SecurityAssociation information associated with
   49    * the request thread for identity propagation.
   50    *
   51    * @author Scott.Stark@jboss.org
   52    * @author Thomas.Diesler@jboss.org
   53    * @author Anil.Saldhana@jboss.org
   54    * @version $Revision: 81037 $
   55    */
   56   public class SecurityAssociationValve extends ValveBase
   57   {
   58      private static Logger log = Logger.getLogger(SecurityAssociationValve.class);
   59      public static ThreadLocal<Principal> userPrincipal = new ThreadLocal<Principal>();
   60      /** Maintain the active WebMetaData for request security checks */
   61      public static ThreadLocal<JBossWebMetaData> activeWebMetaData = new ThreadLocal<JBossWebMetaData>();
   62      /** Maintain the Catalina Request for programmatic web login */
   63      public static ThreadLocal<Request> activeRequest = new ThreadLocal<Request>();
   64      /** Maintain the Catalina Response for programmatic web login */
   65      public static ThreadLocal<Response> activeResponse = new ThreadLocal<Response>();
   66      
   67      /** The web app metadata */
   68      private JBossWebMetaData metaData;
   69      /** The name in the session under which the Subject is stored */
   70      private String subjectAttributeName = null;
   71      /** The service used to flush authentication cache on session invalidation. */
   72      private JaasSecurityManagerServiceMBean secMgrService;
   73      private boolean trace;  
   74   
   75      public SecurityAssociationValve(JBossWebMetaData metaData,
   76         JaasSecurityManagerServiceMBean secMgrService)
   77      {
   78         this.metaData = metaData;
   79         this.secMgrService = secMgrService;
   80         this.trace = log.isTraceEnabled();
   81      }
   82   
   83      /**
   84       * The name of the request attribute under with the authenticated JAAS
   85       * Subject is stored on successful authentication. If null or empty then
   86       * the Subject will not be stored.
   87       */
   88      public void setSubjectAttributeName(String subjectAttributeName)
   89      {
   90         this.subjectAttributeName = subjectAttributeName;
   91         if (subjectAttributeName != null && subjectAttributeName.length() == 0)
   92            this.subjectAttributeName = null;
   93      }
   94   
   95      public void invoke(Request request, Response response)
   96              throws IOException, ServletException
   97      {
   98         Session session = null;
   99         // Get the request caller which could be set due to SSO 
  100         Principal caller = request.getPrincipal();
  101         // The cached web container principal
  102         JBossGenericPrincipal principal = null;
  103         HttpSession hsession = request.getSession(false);
  104   
  105         if( trace )
  106            log.trace("Begin invoke, caller="+caller);
  107         // Set the active meta data
  108         activeWebMetaData.set(metaData); 
  109         //Set the active request and response objects
  110         activeRequest.set(request);
  111         activeResponse.set(response);
  112         
  113         try
  114         {
  115            Wrapper servlet = null;
  116            try
  117            {
  118               servlet = request.getWrapper();
  119               if (servlet != null)
  120               {
  121                  String name = servlet.getName();
  122                  RunAsIdentityMetaData identity = metaData.getRunAsIdentity(name);
  123                  RunAsIdentity runAsIdentity = null;
  124                  if(identity != null)
  125                  {
  126                     if (trace)
  127                        log.trace(name + ", runAs: " + identity);
  128                     runAsIdentity = new RunAsIdentity(identity.getRoleName(),
  129                           identity.getPrincipalName(), identity.getRunAsRoles());
  130                  }
  131                  SecurityAssociationActions.pushRunAsIdentity(runAsIdentity); 
  132               }
  133               userPrincipal.set(caller);
  134   
  135               // If there is a session, get the tomcat session for the principal
  136               Manager manager = container.getManager();
  137               if (manager != null && hsession != null)
  138               {
  139                  try
  140                  {
  141                     session = manager.findSession(hsession.getId());
  142                  }
  143                  catch (IOException ignore)
  144                  {
  145                  }
  146               }
  147   
  148               if (caller == null || (caller instanceof JBossGenericPrincipal) == false)
  149               {
  150                  // Look to the session for the active caller security context
  151                  if (session != null)
  152                  {
  153                     principal =
  154                        (JBossGenericPrincipal) session.getPrincipal();
  155                  }
  156               }
  157               else
  158               {
  159                  // Use the request principal as the caller identity
  160                  principal = (JBossGenericPrincipal) caller;
  161               }
  162   
  163               // If there is a caller use this as the identity to propagate
  164               if (principal != null)
  165               {
  166                  if (trace)
  167                     log.trace("Restoring principal info from cache");
  168                  SecurityAssociationActions.setPrincipalInfo(principal.getAuthPrincipal(),
  169                     principal.getCredentials(), principal.getSubject());  
  170               }
  171               // Put the authenticated subject in the session if requested
  172               if (subjectAttributeName != null)
  173               {
  174                  javax.naming.Context securityNamingCtx = getSecurityNamingContext();
  175                  if (securityNamingCtx != null)
  176                  {
  177                     // Get the JBoss security manager from the ENC context
  178                     AuthenticationManager securityMgr = (AuthenticationManager) securityNamingCtx.lookup("securityMgr");
  179                     Subject subject = securityMgr.getActiveSubject();
  180                     request.getRequest().setAttribute(subjectAttributeName, subject);
  181                  }
  182               }
  183            }
  184            catch (Throwable e)
  185            {
  186               log.debug("Failed to determine servlet", e);
  187            }
  188            
  189            // Perform the request
  190            getNext().invoke(request, response);
  191            if(servlet != null)
  192            { 
  193               SecurityAssociationActions.popRunAsIdentity();
  194            }
  195   
  196            /* If the security domain cache is to be kept in synch with the
  197            session then flush the cache if the session has been invalidated.
  198            */
  199            if( secMgrService != null &&
  200               session != null && session.isValid() == false &&
  201               metaData.isFlushOnSessionInvalidation() == true )
  202            {
  203               if( principal != null )
  204               {
  205                  String securityDomain = metaData.getSecurityDomain();
  206                  if (trace)
  207                  {
  208                     log.trace("Session is invalid, security domain: "+securityDomain
  209                        +", user="+principal);
  210                  }
  211                  try
  212                  {
  213                     Principal authPrincipal = principal.getAuthPrincipal();
  214                     secMgrService.flushAuthenticationCache(securityDomain, authPrincipal);
  215                  }
  216                  catch(Exception e)
  217                  {
  218                     log.debug("Failed to flush auth cache", e);
  219                  }
  220               }
  221            } 
  222         }
  223         finally
  224         {
  225            if( trace )
  226               log.trace("End invoke, caller="+caller);
  227            activeWebMetaData.set(null);
  228            userPrincipal.set(null);
  229            activeRequest.set(null);
  230            activeResponse.set(null);
  231         }
  232      }
  233   
  234      private javax.naming.Context getSecurityNamingContext()
  235      {
  236         javax.naming.Context securityCtx = null;
  237         // Get the JBoss security manager from the ENC context
  238         try
  239         {
  240            InitialContext iniCtx = new InitialContext();
  241            securityCtx = (javax.naming.Context) iniCtx.lookup("java:comp/env/security");
  242         }
  243         catch (NamingException e)
  244         {
  245            // Apparently there is no security context?
  246         }
  247         return securityCtx;
  248      }
  249   
  250      public void event(Request request, Response response, HttpEvent event)
  251         throws IOException, ServletException
  252      {
  253         Session session = null;
  254         // Get the request caller which could be set due to SSO 
  255         Principal caller = request.getPrincipal();
  256         // The cached web container principal
  257         JBossGenericPrincipal principal = null;
  258         HttpSession hsession = request.getSession(false);
  259         
  260         if( trace )
  261            log.trace("Begin invoke, caller="+caller);
  262         // Set the active meta data
  263         activeWebMetaData.set(metaData); 
  264         //Set the active request and response objects
  265         activeRequest.set(request);
  266         activeResponse.set(response);
  267         
  268         try
  269         {
  270            Wrapper servlet = null;
  271            try
  272            {
  273               servlet = request.getWrapper();
  274               if (servlet != null)
  275               {
  276                  String name = servlet.getName();
  277                  RunAsIdentityMetaData identity = metaData.getRunAsIdentity(name);
  278                  RunAsIdentity runAsIdentity = null;
  279                  if(identity != null)
  280                  {
  281                     if (trace)
  282                        log.trace(name + ", runAs: " + identity);
  283                     runAsIdentity = new RunAsIdentity(identity.getRoleName(),
  284                           identity.getPrincipalName(), identity.getRunAsRoles());
  285                  }
  286                  SecurityAssociationActions.pushRunAsIdentity(runAsIdentity); 
  287               }
  288               userPrincipal.set(caller);
  289               
  290               // If there is a session, get the tomcat session for the principal
  291               Manager manager = container.getManager();
  292               if (manager != null && hsession != null)
  293               {
  294                  try
  295                  {
  296                     session = manager.findSession(hsession.getId());
  297                  }
  298                  catch (IOException ignore)
  299                  {
  300                  }
  301               }
  302               
  303               if (caller == null || (caller instanceof JBossGenericPrincipal) == false)
  304               {
  305                  // Look to the session for the active caller security context
  306                  if (session != null)
  307                  {
  308                     principal =
  309                        (JBossGenericPrincipal) session.getPrincipal();
  310                  }
  311               }
  312               else
  313               {
  314                  // Use the request principal as the caller identity
  315                  principal = (JBossGenericPrincipal) caller;
  316               }
  317               
  318               // If there is a caller use this as the identity to propagate
  319               if (principal != null)
  320               {
  321                  if (trace)
  322                     log.trace("Restoring principal info from cache");
  323                  SecurityAssociationActions.setPrincipalInfo(principal.getAuthPrincipal(),
  324                        principal.getCredentials(), principal.getSubject());  
  325               }
  326               // Put the authenticated subject in the session if requested
  327               if (subjectAttributeName != null)
  328               {
  329                  javax.naming.Context securityNamingCtx = getSecurityNamingContext();
  330                  if (securityNamingCtx != null)
  331                  {
  332                     // Get the JBoss security manager from the ENC context
  333                     AuthenticationManager securityMgr = (AuthenticationManager) securityNamingCtx.lookup("securityMgr");
  334                     Subject subject = securityMgr.getActiveSubject();
  335                     request.getRequest().setAttribute(subjectAttributeName, subject);
  336                  }
  337               }
  338            }
  339            catch (Throwable e)
  340            {
  341               log.debug("Failed to determine servlet", e);
  342            }
  343            
  344            // Perform the request
  345            getNext().event(request, response, event);
  346            if(servlet != null)
  347            { 
  348               SecurityAssociationActions.popRunAsIdentity();
  349            }
  350            
  351            /* If the security domain cache is to be kept in synch with the
  352       session then flush the cache if the session has been invalidated.
  353             */
  354            if( secMgrService != null &&
  355                  session != null && session.isValid() == false &&
  356                  metaData.isFlushOnSessionInvalidation() == true )
  357            {
  358               if( principal != null )
  359               {
  360                  String securityDomain = metaData.getSecurityDomain();
  361                  if (trace)
  362                  {
  363                     log.trace("Session is invalid, security domain: "+securityDomain
  364                           +", user="+principal);
  365                  }
  366                  try
  367                  {
  368                     Principal authPrincipal = principal.getAuthPrincipal();
  369                     secMgrService.flushAuthenticationCache(securityDomain, authPrincipal);
  370                  }
  371                  catch(Exception e)
  372                  {
  373                     log.debug("Failed to flush auth cache", e);
  374                  }
  375               }
  376            } 
  377         }
  378         finally
  379         {
  380            if( trace )
  381               log.trace("End invoke, caller="+caller);
  382            activeWebMetaData.set(null);
  383            userPrincipal.set(null);
  384            activeRequest.set(null);
  385            activeResponse.set(null);
  386         }
  387      }
  388         
  389   }

Save This Page
Home » JBoss-5.1.0 » org » jboss » web » tomcat » security » [javadoc | source]