FileDocCategorySizeDatePackage
WebPermissionUtil.javaAPI DocGlassfish v2 API29791Fri May 04 22:36:20 BST 2007com.sun.web.security

WebPermissionUtil

public class WebPermissionUtil extends Object
This class is used for generating Web permissions based on the deployment descriptor.
author
Harpreet Singh
author
Jean-Francois Arcand
author
Ron Monzillo

Fields Summary
private static Logger
logger
private static final int
PT_DEFAULT
private static final int
PT_EXTENSION
private static final int
PT_PREFIX
private static final int
PT_EXACT
private static ArrayList
skippableList
Exclude list when processing resource to url mapping.
Constructors Summary
public WebPermissionUtil()

    
      
    
Methods Summary
public static voidcreateWebRoleRefPermission(WebBundleDescriptor wbd, javax.security.jacc.PolicyConfiguration pc)

	if(logger.isLoggable(Level.FINE)){
	    logger.entering("WebPermissionUtil", "createWebRoleRefPermission");
	    logger.log(Level.FINE,"JACC: role-reference translation: Processing WebRoleRefPermission : CODEBASE = "+ pc.getContextID());
	}
	List role = new ArrayList();
	Set roleset = wbd.getRoles();
	for(Enumeration e = wbd.getWebComponentDescriptors(); e.hasMoreElements();){
	    WebComponentDescriptor comp = (WebComponentDescriptor) e.nextElement();

	    String name = comp.getCanonicalName();
	    Enumeration  esrr = comp.getSecurityRoleReferences();

	    for (; esrr.hasMoreElements();){
		SecurityRoleReference srr = (SecurityRoleReference)esrr.nextElement();
		if(srr != null){
		    String action = srr.getRolename();
		    WebRoleRefPermission wrrp = new WebRoleRefPermission(name, action);
		    role.add(new Role(action));
		    pc.addToRole(srr.getSecurityRoleLink().getName(),wrrp);
		    if(logger.isLoggable(Level.FINE)){
			logger.log(Level.FINE,"JACC: role-reference translation: RoleRefPermission created with name(servlet-name)  = "+ name  + 
				   " and action(Role-name tag) = " + action + " added to role(role-link tag) = "+ srr.getSecurityRoleLink().getName());
		    }

		}
	    }
	    if(logger.isLoggable(Level.FINE)){
		logger.log(Level.FINE,"JACC: role-reference translation: Going through the list of roles not present in RoleRef elements and creating WebRoleRefPermissions ");
	    }
	    for(Iterator it = roleset.iterator(); it.hasNext();){
		Role r = (Role)it.next();
		if(logger.isLoggable(Level.FINE)){
		    logger.log(Level.FINE,"JACC: role-reference translation: Looking at Role =  "+r.getName());
		}
		if(!role.contains(r)){
		    String action = r.getName();
		    WebRoleRefPermission wrrp = new WebRoleRefPermission(name, action);
		    pc.addToRole(action ,wrrp);
		    if(logger.isLoggable(Level.FINE)){
			logger.log(Level.FINE,"JACC: role-reference translation: RoleRef  = "+ action + 
				   " is added for servlet-resource = " + name);
			logger.log(Level.FINE, "JACC: role-reference translation: Permission added for above role-ref =" 
				   + wrrp.getName() +" "+ wrrp.getActions());
		    }
		}
	    }
	}
	if(logger.isLoggable(Level.FINE)){
	    logger.exiting("WebPermissionUtil", "createWebRoleRefPermission");
	}
        
        // START S1AS8PE 4966609
        /**
         * For every security role in the web application add a
         * WebRoleRefPermission to the corresponding role. The name of all such
         * permissions shall be the empty string, and the actions of each 
         * permission shall be the corresponding role name. When checking a 
         * WebRoleRefPermission from a JSP not mapped to a servlet, use a 
         * permission with the empty string as its name
         * and with the argument to isUserInRole as its actions
         */
        for(Iterator it = roleset.iterator(); it.hasNext();){
            Role r = (Role)it.next();
            if(logger.isLoggable(Level.FINE)){
                logger.log(Level.FINE,
                    "JACC: role-reference translation: Looking at Role =  "
                        + r.getName());
            }
            String action = r.getName();
            WebRoleRefPermission wrrp = new WebRoleRefPermission("", action);
            pc.addToRole(action ,wrrp);
            if(logger.isLoggable(Level.FINE)){
                logger.log(Level.FINE,
                    "JACC: role-reference translation: RoleRef  = "
                    + action 
                    + " is added for jsp's that can't be mapped to servlets");
                logger.log(Level.FINE, 
                    "JACC: role-reference translation: Permission added for above role-ref =" 
                     + wrrp.getName() +" "+ wrrp.getActions());
            }
        }
        // END S1AS8PE 4966609
        
        
    
static booleanimplies(java.lang.String pattern, java.lang.String path)

        skippableList = new ArrayList();
        skippableList.add("meta-inf");
        skippableList.add("web-inf");
        skippableList.add("tld");
        skippableList.add(".com.sun.deployment.backend.lock");
    

        // Check for exact match
        if (pattern.equals(path))
            return (true);

        // Check for path prefix matching
        if (pattern.startsWith("/") && pattern.endsWith("/*")) {
            pattern = pattern.substring(0, pattern.length() - 2);

	    int length = pattern.length();

            if (length == 0) return (true);  // "/*" is the same as "/"

	    return (path.startsWith(pattern) && 
		    (path.length() == length || 
		     path.substring(length).startsWith("/")));
        }

        // Check for suffix matching
        if (pattern.startsWith("*.")) {
            int slash = path.lastIndexOf('/");
            int period = path.lastIndexOf('.");
            if ((slash >= 0) && (period > slash) &&
                path.endsWith(pattern.substring(1))) {
                return (true);
            }
            return (false);
        }

        // Check for universal mapping
        if (pattern.equals("/"))
            return (true);

        return (false);
    
public static java.util.HashMapparseConstraints(WebBundleDescriptor wbd)

	
      if(logger.isLoggable(Level.FINE)){
	  logger.entering("WebPermissionUtil", "parseConstraints");
      }

      HashMap qpMap = new HashMap();

      // bootstrap the map with the default pattern;
      qpMap.put("/", new MapValue("/"));

      //Enumerate over security constraints
      Enumeration esc = wbd.getSecurityConstraints(); 
      while (esc.hasMoreElements()) {
	  
	  if(logger.isLoggable(Level.FINE)){
	      logger.log(Level.FINE,"JACC: constraint translation: begin parsing security constraint");
	  }

	  SecurityConstraint sc = (SecurityConstraint) esc.nextElement();
	  AuthorizationConstraint ac = sc.getAuthorizationConstraint();
	  UserDataConstraint udc = sc.getUserDataConstraint();

	  // Enumerate over collections of URLPatterns within constraint
	  Enumeration ewrc = sc.getWebResourceCollections();
	  while (ewrc.hasMoreElements()) {

	      if(logger.isLoggable(Level.FINE)){
		  logger.log(Level.FINE,"JACC: constraint translation: begin parsing web resource collection");
	      }

	      WebResourceCollection wrc = 
		  (WebResourceCollection)ewrc.nextElement();

	      // Enumerate over URLPatterns within collection
	      Enumeration eurl = wrc.getUrlPatterns();
	      while (eurl.hasMoreElements()) {

		  String url = (String) eurl.nextElement();

		  if(logger.isLoggable(Level.FINE)){
		      logger.log(Level.FINE,"JACC: constraint translation: process url: "+url);
		  }

		  // determine if pattern is already in map
		  MapValue mValue = (MapValue) qpMap.get(url);

		  // apply new patterns to map
		  if (mValue == null) {
		      mValue = new MapValue(url);

		      //Iterate over patterns in map
		      Iterator it = qpMap.keySet().iterator(); 
		      while (it.hasNext()) {

			  String otherUrl = (String) it.next();

			  int otherUrlType = patternType(otherUrl);
			  switch(patternType(url)) {

			      // if the new url/pattern is a path-prefix 
			      // pattern, it must be qualified by every 
			      // different (from it) path-prefix pattern 
			      // (in the map) that is implied by the new 
			      // pattern, and every exact pattern (in the map)
			      // that is implied by the new url.
			      // Also, the new pattern  must be added as a 
			      // qualifier of the default pattern, and every 
			      // extension pattern (existing in the map), and 
			      // of every different path-prefix pattern that 
			      // implies the new pattern.
			      // Note that we know that the new pattern does
			      // not exist in the map, thus we know that the
			      // new pattern is different from any existing
			      // path prefix pattern.
	     
			      case PT_PREFIX:
				  if ((otherUrlType == PT_PREFIX || 
				      otherUrlType == PT_EXACT) &&
				      implies(url,otherUrl))
				      mValue.addQualifier(otherUrl);
			  
				  else if (otherUrlType == PT_PREFIX &&
					   implies(otherUrl,url))
				      ((MapValue) qpMap.get(otherUrl)).
					  addQualifier(url);
				  
				  else if (otherUrlType == PT_EXTENSION ||
				       otherUrlType == PT_DEFAULT)
				      ((MapValue) qpMap.get(otherUrl)).
					  addQualifier(url);
				  break;

			      // if the new pattern is an extension pattern,
			      // it must be qualified by every path-prefix
			      // pattern (in the map), and every exact
			      // pattern (in the map) that is implied by
			      // the new pattern.
			      // Also, it must be added as a qualifier of
			      // the defualt pattern, if it exists in the
			      // map.
			      case PT_EXTENSION:
				  if (otherUrlType == PT_PREFIX || 
				       (otherUrlType == PT_EXACT &&
					implies(url,otherUrl)))
				      mValue.addQualifier(otherUrl);

				  else if (otherUrlType == PT_DEFAULT)
				      ((MapValue) qpMap.get(otherUrl)).
					  addQualifier(url); 
				  break;

			      // if the new pattern is the default pattern
			      // it must be qualified by every other pattern
			      // in the map.
			      case PT_DEFAULT:
				  if (otherUrlType != PT_DEFAULT) 
				      mValue.addQualifier(otherUrl);
				  break;

			      // if the new pattern is an exact pattern, it
			      // is not be qualified, but it must be added as 
			      // as a qualifier to the default pattern, and to
			      // every path-prefix or extension pattern (in 
			      // the map) that implies the new pattern.
			      case PT_EXACT:
				  if ((otherUrlType == PT_PREFIX || 
				       otherUrlType == PT_EXTENSION) &&
				      implies(otherUrl,url))
				      ((MapValue) qpMap.get(otherUrl)).
					  addQualifier(url); 
				  else if (otherUrlType == PT_DEFAULT)
				      ((MapValue) qpMap.get(otherUrl)).
					  addQualifier(url);
				  break;
			  }
		      }

		      // add the new pattern and its pattern spec to the map
		      qpMap.put(url, mValue);

		  }

		  BitSet methods = 
		      MapValue.methodArrayToSet(wrc.getHttpMethodsAsArray());

		  if(logger.isLoggable(Level.FINE)){
		      logger.log(Level.FINE,"JACC: constraint translation: methods of collection: "+ MapValue.getActions(methods));
		  }

		  if (ac == null) {
		      if(logger.isLoggable(Level.FINE)){
			  logger.log(Level.FINE,"JACC: constraint translation: collection is unchecked for authorization at methods: "+ MapValue.getActions(methods));
		      }
		      mValue.setPredefinedOutcomeOnMethods(methods,true);
		  }
		  else {
		      Enumeration eroles = ac.getSecurityRoles();
		      if (!eroles.hasMoreElements()) {
			  if(logger.isLoggable(Level.FINE)){
			      logger.log(Level.FINE,"JACC: constraint translation: collection is exclude at methods: "+ MapValue.getActions(methods));
			  }
			  mValue.setPredefinedOutcomeOnMethods(methods,false);
		      }
		      else while (eroles.hasMoreElements()) {
			  SecurityRoleDescriptor srd = 
			      (SecurityRoleDescriptor)eroles.nextElement();
			  mValue.setRoleOnMethods(srd.getName(),methods,wbd);
			  if(logger.isLoggable(Level.FINE)){
			      logger.log(Level.FINE,"JACC: constraint translation: collection is athorized to: "+ srd.getName() + " at methods: "+ MapValue.getActions(methods));
			  }
		      }
		  }

		  if (udc == null) {
		      if(logger.isLoggable(Level.FINE)){
			  logger.log(Level.FINE,"JACC: constraint translation: collection requires no transport guarantee at methods: "+ MapValue.getActions(methods));
		      }
		      mValue.setConnectOnMethods(null,methods);
		  }
		  else {
		      if(logger.isLoggable(Level.FINE)){
			  logger.log(Level.FINE,"JACC: constraint translation: collection requires transport guarantee: "+ udc.getTransportGuarantee()+ " at methods: "+ MapValue.getActions(methods));
		      }
		      mValue.setConnectOnMethods(udc.getTransportGuarantee(),
						 methods);
		  }
   
		  if(logger.isLoggable(Level.FINE)){
		      logger.log(Level.FINE,"JACC: constraint translation: end processing url: "+url);
		  }
	      }

	      if(logger.isLoggable(Level.FINE)){
		  logger.log(Level.FINE,"JACC: constraint translation: end parsing web resource collection");
	      }
	  }

	  if(logger.isLoggable(Level.FINE)){
	      logger.log(Level.FINE,"JACC: constraint translation: end parsing security constraint");
	  }
      }

      if(logger.isLoggable(Level.FINE)){
	  logger.exiting("WebPermissionUtil","parseConstraints");
      }

      return qpMap;
    
static intpatternType(java.lang.Object urlPattern)

      
        
	String pattern = urlPattern.toString();
	if (pattern.startsWith("*.")) return PT_EXTENSION;
	else if (pattern.startsWith("/") && pattern.endsWith("/*")) 
	    return PT_PREFIX;
	else if (pattern.equals("/")) return PT_DEFAULT;
	else return PT_EXACT;
    
public static voidprocessConstraints(WebBundleDescriptor wbd, javax.security.jacc.PolicyConfiguration pc)

	if(logger.isLoggable(Level.FINE)){
	    logger.entering("WebPermissionUtil", "processConstraints");
	    logger.log(Level.FINE,"JACC: constraint translation: CODEBASE = "+
		       pc.getContextID());
	}

	HashMap qpMap = parseConstraints(wbd);
	HashMap roleMap = new HashMap();

	Permissions excluded = new Permissions();
	Permissions unchecked = new Permissions();

	// for each urlPatternSpec in the map
	if(logger.isLoggable(Level.FINE)){
	    logger.log(Level.FINE,"JACC: constraint capture: begin processing qualified url patterns");
	}

	Iterator it = qpMap.values().iterator();
	while (it.hasNext()) {
	    MapValue m = (MapValue) it.next();
	    if (!m.irrelevantByQualifier) {

		String name = m.urlPatternSpec.toString();

		if(logger.isLoggable(Level.FINE)){
		    logger.log(Level.FINE,"JACC: constraint capture: urlPattern: "+ name);
		}

		// handle excluded method
		BitSet methods = m.getExcludedMethods();
		if (!methods.isEmpty()) {

		    if(logger.isLoggable(Level.FINE)){
			logger.log(Level.FINE,"JACC: constraint capture: adding excluded methods: "+ MapValue.getActions(methods));

		    }

		    String[] actions = MapValue.getMethodArray(methods);
		    excluded.add(new WebResourcePermission(name,actions));
		    excluded.add(new WebUserDataPermission(name,actions,null));
		}

		// handle methods requring  role
		HashMap rMap = m.getRoleMap();
		Iterator rit = rMap.keySet().iterator();
		while (rit.hasNext()) {

		    String role = (String) rit.next();
		    methods = (BitSet) rMap.get(role);

		    if (!methods.isEmpty()) {

			Permissions p = (Permissions) roleMap.get(role);
			if (p == null) {
			    p = new Permissions();
			    roleMap.put(role,p);
			}

			if(logger.isLoggable(Level.FINE)){
			    logger.log(Level.FINE,"JACC: constraint capture: adding methods that may be called by role: "+ role+" methods: "+ MapValue.getActions(methods));
			}

			String[] actions = MapValue.getMethodArray(methods);
			p.add(new WebResourcePermission(name,actions));
		    }
		}

		// handle transport constrained methods (skip unprotected
		// that is, connectKey index == 0)
		for (int i=1; i<MethodValue.connectKeys.length; i++) {
		    methods = m.getConnectMap(1<<i);
		    if (!methods.isEmpty()) {
			
			if(logger.isLoggable(Level.FINE)){

			    logger.log(Level.FINE,"JACC: constraint capture: adding methods that accept connections with protection: "+ MethodValue.connectKeys[i]+" methods: "+ MapValue.getActions(methods));
			}

			String[] actions = MapValue.getMethodArray(methods);
			unchecked.add(new WebUserDataPermission
			    (name, actions,
			     (String) MethodValue.connectKeys[i]));
		    }
		}

		// handle methods that are not auth constrained
		methods = m.getAuthConstrainedMethods();
		if (!methods.get(MethodValue.AllMethodsIdx)) {
		    String actions;
		    if (methods.isEmpty()) {
			actions = null;
		    } else {
			actions = "!" + MapValue.getActions(methods);
		    }
		    if(logger.isLoggable(Level.FINE)){
			logger.log(Level.FINE,"JACC: constraint capture: adding unchecked (for authorization) methods: "+ actions);
		    }
		    unchecked.add(new WebResourcePermission(name,actions));
		} 

		// handle methods that are not transport constrained
		methods = m.getTransportConstrainedMethods();
		if (!methods.get(MethodValue.AllMethodsIdx)) {
		    String actions;
		    if (methods.isEmpty()) {
			actions = null;
		    } else {
			actions = "!" + MapValue.getActions(methods);
		    }
		    if(logger.isLoggable(Level.FINE)){
			logger.log(Level.FINE,"JACC: constraint capture: adding methods that accept unprotected connections: "+ actions);
		    }
		    unchecked.add(new WebUserDataPermission(name,actions));
		}
	    }
	}

	if(logger.isLoggable(Level.FINE)){
	    logger.log(Level.FINE,"JACC: constraint capture: end processing qualified url patterns");

	    Enumeration e = excluded.elements();
	    while (e.hasMoreElements()) {
		Permission p = (Permission) e.nextElement();
		String ptype = (p instanceof WebResourcePermission) ? "WRP  " : "WUDP ";
		logger.log(Level.FINE,"JACC: permission(excluded) type: "+ ptype + " name: "+ p.getName() + " actions: "+ p.getActions());
	    }

	    e = unchecked.elements();
	    while (e.hasMoreElements()) {
		Permission p = (Permission) e.nextElement();
		String ptype = (p instanceof WebResourcePermission) ? "WRP  " : "WUDP ";
		logger.log(Level.FINE,"JACC: permission(unchecked) type: "+ ptype + " name: "+ p.getName() + " actions: "+ p.getActions());
	    }
	}
	
	pc.addToExcludedPolicy(excluded);

	pc.addToUncheckedPolicy(unchecked);

	it = roleMap.keySet().iterator();
	while (it.hasNext()) {
	    String role = (String) it.next();
	    Permissions pCollection = (Permissions) roleMap.get(role);
	    pc.addToRole(role,pCollection);

	    if(logger.isLoggable(Level.FINE)){
		Enumeration e = pCollection.elements();
		while (e.hasMoreElements()) {
		    Permission p = (Permission) e.nextElement();
		    String ptype = (p instanceof WebResourcePermission) ? "WRP  " : "WUDP ";
		    logger.log(Level.FINE,"JACC: permission("+ role + ") type: "+ ptype + " name: "+ p.getName() + " actions: "+ p.getActions());
		}

	    }
	}

	if(logger.isLoggable(Level.FINE)){
	    logger.exiting("WebPermissionUtil", "processConstraints");
	}