Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
  * JBoss, Home of Professional Open Source
  * Copyright 2005, JBoss Inc., and individual contributors as indicated
  * by the @authors tag. See the copyright.txt in the distribution for a
  * full listing of individual contributors.
  *
  * This is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as
  * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
 package org.jboss.security.auth.spi;
 
 import java.net.URL;
 
 
Common login module utility methods

Author(s):
Scott.Stark@jboss.org
Version:
$Revision: 73918 $
 
 public class Util
 {
    private static Logger log = Logger.getLogger(Util.class);  
 
    public static final String BASE64_ENCODING = "BASE64";
    public static final String BASE16_ENCODING = "HEX";
    public static final String RFC2617_ENCODING = "RFC2617";
   
The ASCII printable characters the MD5 digest maps to for RFC2617
 
    private static char[] MD5_HEX = "0123456789abcdef".toCharArray();

   
   
   
Create the set of roles the user belongs to by parsing the roles.properties data for username=role1,role2,... and username.XXX=role1,role2,... patterns.

Parameters:
targetUser - the username to obtain roles for
roles - the Properties containing the user=roles mappings
roleGroupSeperator - the character that seperates a username from a group name, e.g., targetUser[.GroupName]=roles
aslm - the login module to use for Principal creation
Returns:
Group[] containing the sets of roles
  
    static Group[] getRoleSets(String targetUserProperties roles,
       char roleGroupSeperatorAbstractServerLoginModule aslm)
    {
       Logger log = aslm.log;      
       boolean trace = log.isTraceEnabled();
       Enumeration<?> users = roles.propertyNames();
       SimpleGroup rolesGroup = new SimpleGroup("Roles");
       ArrayList<Groupgroups = new ArrayList<Group>();
       groups.add(rolesGroup);
       while (users.hasMoreElements() && targetUser != null)
       {
          String user = (Stringusers.nextElement();
          String value = roles.getProperty(user);
          iftrace )
             log.trace("Checking user: "+user+", roles string: "+value);
          // See if this entry is of the form targetUser[.GroupName]=roles
          //JBAS-3742 - skip potential '.' in targetUser
          int index = user.indexOf(roleGroupSeperatortargetUser.length());
          boolean isRoleGroup = false;
          boolean userMatch = false;
          if (index > 0 && targetUser.regionMatches(0, user, 0, index) == true)
             isRoleGroup = true;
          else
            userMatch = targetUser.equals(user);
         // Check for username.RoleGroup pattern
         if (isRoleGroup == true)
         {
            String groupName = user.substring(index + 1);
            if (groupName.equals("Roles"))
            {
               iftrace )
                  log.trace("Adding to Roles: "+value);
               parseGroupMembers(rolesGroupvalueaslm);
            }
            else
            {
               iftrace )
                  log.trace("Adding to "+groupName+": "+value);
               SimpleGroup group = new SimpleGroup(groupName);
               parseGroupMembers(groupvalueaslm);
               groups.add(group);
            }
         }
         else if (userMatch == true)
         {
            iftrace )
               log.trace("Adding to Roles: "+value);
            // Place these roles into the Default "Roles" group
            parseGroupMembers(rolesGroupvalueaslm);
         }
      }
      Group[] roleSets = new Group[groups.size()];
      groups.toArray(roleSets);
      return roleSets;
   }

   
Execute the rolesQuery against the dsJndiName to obtain the roles for the authenticated user.

Returns:
Group[] containing the sets of roles
   static Group[] getRoleSets(String usernameString dsJndiName,
      String rolesQueryAbstractServerLoginModule aslm)
      throws LoginException
   {
      return getRoleSets(usernamedsJndiNamerolesQueryaslmfalse);
   }

   
Execute the rolesQuery against the dsJndiName to obtain the roles for the authenticated user.

Returns:
Group[] containing the sets of roles
   static Group[] getRoleSets(String usernameString dsJndiName,
      String rolesQueryAbstractServerLoginModule aslmboolean suspendResume)
      throws LoginException
   {
      return DbUtil.getRoleSets(usernamedsJndiNamerolesQueryaslmsuspendResume); 
   }

   
Utility method which loads the given properties file and returns a Properties object containing the key,value pairs in that file. The properties files should be in the class path as this method looks to the thread context class loader (TCL) to locate the resource. If the TCL is a URLClassLoader the findResource(String) method is first tried. If this fails or the TCL is not a URLClassLoader getResource(String) is tried.

Parameters:
defaultsName - the name of the default properties file resource that will be used as the default Properties to the ctor of the propertiesName Properties instance.
propertiesName - the name of the properties file resource
log - the logger used for trace level messages
Returns:
the loaded properties file if found
Throws:
java.io.IOException thrown if the properties file cannot be found or loaded
   static Properties loadProperties(String defaultsNameString propertiesNameLogger log)
      throws IOException
   {
      Properties bundle = null;
      ClassLoader loader = SecurityActions.getContextClassLoader();
      URL defaultUrl = null;
      URL url = null;
      // First check for local visibility via a URLClassLoader.findResource
      ifloader instanceof URLClassLoader )
      {
         URLClassLoader ucl = (URLClassLoaderloader;
         defaultUrl = SecurityActions.findResource(ucl,defaultsName);
         url = SecurityActions.findResource(ucl,propertiesName);
         log.trace("findResource: "+url);
      }
      // Do a general resource search
      ifdefaultUrl == null )
         defaultUrl = loader.getResource(defaultsName);
      ifurl == null )
         url = loader.getResource(propertiesName);
      ifurl == null && defaultUrl == null )
      {
         String msg = "No properties file: " + propertiesName
            + " or defaults: " +defaultsName" found";
         throw new IOException(msg);
      }
      log.trace("Properties file=" + url+", defaults="+defaultUrl);
      Properties defaults = new Properties();
      ifdefaultUrl != null )
      {
         try
         {
            InputStream is = defaultUrl.openStream();
            defaults.load(is);
            is.close();
            log.debug("Loaded defaults, users="+defaults.keySet());
         }
         catch(Throwable e)
         {
            log.debug("Failed to load defaults"e);
         }
      }
      bundle = new Properties(defaults);
      ifurl != null )
      {
         InputStream is = null;
         try
         {
            is = SecurityActions.openStream(url);
         }
         catch (PrivilegedActionException e)
         {
            log.trace("Open stream error"e);
            throw new IOException(e.getLocalizedMessage());
         }
         if (is != null)
         {
            bundle.load(is);
            is.close();
         }
         else
         {
            throw new IOException("Properties file " + propertiesName + " not avilable");
         }
         log.debug("Loaded properties, users="+bundle.keySet());
      }
      return bundle;
   }

   
Utility method which loads the given properties file and returns a Properties object containing the key,value pairs in that file. The properties files should be in the class path as this method looks to the thread context class loader (TCL) to locate the resource. If the TCL is a URLClassLoader the findResource(String) method is first tried. If this fails or the TCL is not a URLClassLoader getResource(String) is tried. If not, an absolute path is tried.

Parameters:
propertiesName - the name of the properties file resource
log - the logger used for trace level messages
Returns:
the loaded properties file if found
Throws:
java.io.IOException thrown if the properties file cannot be found or loaded
   static Properties loadProperties(String propertiesNameLogger log)
      throws IOException
   { 
      ClassLoader loader = SecurityActions.getContextClassLoader(); 
      URL url = null;
      // First check for local visibility via a URLClassLoader.findResource
      ifloader instanceof URLClassLoader )
      {
         URLClassLoader ucl = (URLClassLoaderloader
         url = SecurityActions.findResource(ucl,propertiesName);
         log.trace("findResource: "+url);
      } 
      ifurl == null )
         url = loader.getResource(propertiesName);
      ifurl == null)
      {
         url = new URL(propertiesName); 
      }
      log.trace("Properties file=" + url ); 
      Properties bundle = new Properties();
      ifurl != null )
      {
         InputStream is = null;
         try
         {
            is = SecurityActions.openStream(url);
         }
         catch (PrivilegedActionException e)
         {
            log.trace("open stream error:"e);
            throw new IOException(e.getLocalizedMessage());
         }
         if (is != null)
         {
            bundle.load(is);
            is.close();
         }
         else
         {
            throw new IOException("Properties file " + propertiesName + " not available");
         }
         log.debug("Loaded properties, users="+bundle.keySet());
      }
      return bundle;
   }


   
Parse the comma delimited roles names given by value and add them to group. The type of Principal created for each name is determined by the createIdentity method.

Parameters:
group - the Group to add the roles to.
roles - the comma delimited role names.
See also:
AbstractServerLoginModule.createIdentity(java.lang.String)
 
   static void parseGroupMembers(Group groupString roles,
      AbstractServerLoginModule aslm)
   {
      StringTokenizer tokenizer = new StringTokenizer(roles",");
      while (tokenizer.hasMoreTokens())
      {
         String token = tokenizer.nextToken();
         try
         {
            Principal p = aslm.createIdentity(token);
            group.addMember(p);
         }
         catch (Exception e)
         {
            aslm.log.warn("Failed to create principal for: "+tokene);
         }
      }
   }
   
   
Calculate a password hash using a MessageDigest.

Parameters:
hashAlgorithm - the MessageDigest algorithm name
hashEncoding - either base64 or hex to specify the type of encoding the MessageDigest as a string.
hashCharset - the charset used to create the byte[] passed to the MessageDigestfrom the password String. If null the platform default is used.
username - ignored in default version
password - the password string to be hashed
Returns:
the hashed string if successful, null if there is a digest exception
    public static String createPasswordHash(String hashAlgorithmString hashEncoding,
       String hashCharsetString usernameString password)
   {
      return createPasswordHash(hashAlgorithmhashEncoding,
       hashCharsetusernamepasswordnull);
   }
    
Calculate a password hash using a MessageDigest.

Parameters:
hashAlgorithm - the MessageDigest algorithm name
hashEncoding - either base64 or hex to specify the type of encoding the MessageDigest as a string.
hashCharset - the charset used to create the byte[] passed to the MessageDigestfrom the password String. If null the platform default is used.
username - ignored in default version
password - the password string to be hashed
callback - the callback used to allow customization of the hash to occur. The preDigest method is called before the password is added and the postDigest method is called after the password has been added.
Returns:
the hashed string if successful, null if there is a digest exception
 
    public static String createPasswordHash(String hashAlgorithmString hashEncoding,
       String hashCharsetString usernameString passwordDigestCallback callback)
    {
       byte[] passBytes;
       String passwordHash = null;
       // convert password to byte data
       try
       {
          if(hashCharset == null)
             passBytes = password.getBytes();
          else
             passBytes = password.getBytes(hashCharset);
       }
       catch(UnsupportedEncodingException uee)
       {
          .error("charset " + hashCharset + " not found. Using platform default."uee);
          passBytes = password.getBytes();
       }
       // calculate the hash and apply the encoding.
       try
       {
          MessageDigest md = MessageDigest.getInstance(hashAlgorithm);
          ifcallback != null )
             callback.preDigest(md);
          md.update(passBytes);
          ifcallback != null )
             callback.postDigest(md);
          byte[] hash = md.digest();
          if(hashEncoding.equalsIgnoreCase())
          {
             passwordHash = Util.encodeBase64(hash);
          }
          else if(hashEncoding.equalsIgnoreCase())
          {
             passwordHash = Util.encodeBase16(hash);
          }
          else if(hashEncoding.equalsIgnoreCase())
          {
             passwordHash = Util.encodeRFC2617(hash);
          }
          else
          {
             .error("Unsupported hash encoding format " + hashEncoding);
          }
       }
       catch(Exception e)
       {
          .error("Password hash calculation failed "e);
       }
       return passwordHash;
    }
    
    
3.1.3 Representation of digest values An optional header allows the server to specify the algorithm used to create the checksum or digest. By default the MD5 algorithm is used and that is the only algorithm described in this document. For the purposes of this document, an MD5 digest of 128 bits is represented as 32 ASCII printable characters. The bits in the 128 bit digest are converted from most significant to least significant bit, four bits at a time to their ASCII presentation as follows. Each four bits is represented by its familiar hexadecimal notation from the characters 0123456789abcdef. That is, binary 0000 getInfos represented by the character '0', 0001, by '1', and so on up to the representation of 1111 as 'f'.

Parameters:
data - the raw MD5 hash data
Returns:
the encoded MD5 representation
   public static String encodeRFC2617(byte[] data)
   {
      char[] hash = new char[32];
      for (int i = 0; i < 16; i++)
      {
         int j = (data[i] >> 4) & 0xf;
         hash[i * 2] = [j];
         j = data[i] & 0xf;
         hash[i * 2 + 1] = [j];
      }
      return new String(hash);
   } 
   
    
Hex encoding of hashes, as used by Catalina. Each byte is converted to the corresponding two hex characters.
    public static String encodeBase16(byte[] bytes)
    {
       StringBuffer sb = new StringBuffer(bytes.length * 2);
       for (int i = 0; i < bytes.lengthi++)
       {
          byte b = bytes[i];
          // top 4 bits
          char c = (char)((b >> 4) & 0xf);
          if(c > 9)
             c = (char)((c - 10) + 'a');
          else
             c = (char)(c + '0');
          sb.append(c);
          // bottom 4 bits
          c = (char)(b & 0xf);
          if (c > 9)
             c = (char)((c - 10) + 'a');
          else
             c = (char)(c + '0');
          sb.append(c);
       }
       return sb.toString();
    }

    
BASE64 encoder implementation. Provides encoding methods, using the BASE64 encoding rules, as defined in the MIME specification, rfc1521.
    public static String encodeBase64(byte[] bytes)
    {
       String base64 = null;
       try
       {
          base64 = Base64Encoder.encode(bytes);
       }
       catch(Exception e)
       {
       }
       return base64;
    }
    
    // These functions assume that the byte array has MSB at 0, LSB at end.
    // Reverse the byte array (not the String) if this is not the case.
    // All base64 strings are in natural order, least significant digit last.
    public static String tob64(byte[] buffer)
    {
       return Base64Utils.tob64(buffer);  
    }
    public static byte[] fromb64(String strthrows NumberFormatException
    {
       return Base64Utils.fromb64(str); 
    } 
New to GrepCode? Check out our FAQ X