1 17 18 package org.apache.geronimo.security.realm.providers; 19 20 import org.apache.commons.logging.Log; 21 import org.apache.commons.logging.LogFactory; 22 import org.apache.geronimo.common.GeronimoSecurityException; 23 import org.apache.geronimo.security.jaas.JaasLoginModuleUse; 24 import org.apache.geronimo.system.serverinfo.ServerInfo; 25 import org.apache.geronimo.util.encoders.HexTranslator; 26 27 import javax.security.auth.Subject ; 28 import javax.security.auth.callback.Callback ; 29 import javax.security.auth.callback.CallbackHandler ; 30 import javax.security.auth.callback.NameCallback ; 31 import javax.security.auth.callback.PasswordCallback ; 32 import javax.security.auth.callback.UnsupportedCallbackException ; 33 import javax.security.auth.login.FailedLoginException ; 34 import javax.security.auth.login.LoginException ; 35 import javax.security.auth.spi.LoginModule ; 36 import java.io.IOException ; 37 import java.io.InputStream ; 38 import java.net.URI ; 39 import java.security.MessageDigest ; 40 import java.security.NoSuchAlgorithmException ; 41 import java.util.Enumeration ; 42 import java.util.HashMap ; 43 import java.util.HashSet ; 44 import java.util.Iterator ; 45 import java.util.Map ; 46 import java.util.Properties ; 47 import java.util.Set ; 48 49 50 57 public class PropertiesFileLoginModule implements LoginModule { 58 public final static String USERS_URI = "usersURI"; 59 public final static String GROUPS_URI = "groupsURI"; 60 public final static String DIGEST = "digest"; 61 private static Log log = LogFactory.getLog(PropertiesFileLoginModule.class); 62 final Properties users = new Properties (); 63 final Map groups = new HashMap (); 64 private String digest; 65 66 Subject subject; 67 CallbackHandler handler; 68 String username; 69 String password; 70 71 public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { 72 this.subject = subject; 73 this.handler = callbackHandler; 74 try { 75 ServerInfo serverInfo = (ServerInfo) options.get(JaasLoginModuleUse.SERVERINFO_LM_OPTION); 76 final String users = (String )options.get(USERS_URI); 77 final String groups = (String )options.get(GROUPS_URI); 78 digest = (String ) options.get(DIGEST); 79 if(digest != null && !digest.equals("")) { 80 try { 82 MessageDigest.getInstance(digest); 83 } catch(NoSuchAlgorithmException e) { 84 log.error("Initialization failed. Digest algorithm "+digest+" is not available.", e); 85 throw new IllegalArgumentException ("Unable to configure properties file login module: "+e.getMessage()); 86 } 87 } 88 if(users == null || groups == null) { 89 throw new IllegalArgumentException ("Both "+USERS_URI+" and "+GROUPS_URI+" must be provided!"); 90 } 91 URI usersURI = new URI (users); 92 URI groupsURI = new URI (groups); 93 loadProperties(serverInfo, usersURI, groupsURI); 94 } catch (Exception e) { 95 log.error("Initialization failed", e); 96 throw new IllegalArgumentException ("Unable to configure properties file login module: "+e.getMessage()); 97 } 98 } 99 100 public void loadProperties(ServerInfo serverInfo, URI userURI, URI groupURI) throws GeronimoSecurityException { 101 try { 102 URI userFile = serverInfo.resolveServer(userURI); 103 URI groupFile = serverInfo.resolveServer(groupURI); 104 InputStream stream = userFile.toURL().openStream(); 105 users.load(stream); 106 stream.close(); 107 108 Properties temp = new Properties (); 109 stream = groupFile.toURL().openStream(); 110 temp.load(stream); 111 stream.close(); 112 113 Enumeration e = temp.keys(); 114 while (e.hasMoreElements()) { 115 String groupName = (String ) e.nextElement(); 116 String [] userList = ((String ) temp.get(groupName)).split(","); 117 118 Set userset = (Set ) groups.get(groupName); 119 if (userset == null) { 120 userset = new HashSet (); 121 groups.put(groupName, userset); 122 } 123 124 for (int i = 0; i < userList.length; i++) { 125 userset.add(userList[i]); 126 } 127 } 128 129 } catch (Exception e) { 130 log.error("Properties File Login Module - data load failed", e); 131 throw new GeronimoSecurityException(e); 132 } 133 } 134 135 136 public boolean login() throws LoginException { 137 Callback [] callbacks = new Callback [2]; 138 139 callbacks[0] = new NameCallback ("User name"); 140 callbacks[1] = new PasswordCallback ("Password", false); 141 try { 142 handler.handle(callbacks); 143 } catch (IOException ioe) { 144 throw (LoginException ) new LoginException ().initCause(ioe); 145 } catch (UnsupportedCallbackException uce) { 146 throw (LoginException ) new LoginException ().initCause(uce); 147 } 148 assert callbacks.length == 2; 149 username = ((NameCallback ) callbacks[0]).getName(); 150 if(username == null || username.equals("")) { 151 return false; 152 } 153 String realPassword = users.getProperty(username); 154 char[] entered = ((PasswordCallback ) callbacks[1]).getPassword(); 155 password = entered == null ? null : new String (entered); 156 boolean result = (realPassword == null && password == null) || 157 (realPassword != null && password != null && checkPassword(realPassword, password)); 158 if(!result) { 159 throw new FailedLoginException (); 160 } 161 return true; 162 } 163 164 public boolean commit() throws LoginException { 165 Set principals = subject.getPrincipals(); 166 167 principals.add(new GeronimoUserPrincipal(username)); 168 169 Iterator e = groups.keySet().iterator(); 170 while (e.hasNext()) { 171 String groupName = (String ) e.next(); 172 Set users = (Set ) groups.get(groupName); 173 Iterator iter = users.iterator(); 174 while (iter.hasNext()) { 175 String user = (String ) iter.next(); 176 if (username.equals(user)) { 177 principals.add(new GeronimoGroupPrincipal(groupName)); 178 break; 179 } 180 } 181 } 182 183 return true; 184 } 185 186 public boolean abort() throws LoginException { 187 username = null; 188 password = null; 189 190 return true; 191 } 192 193 public boolean logout() throws LoginException { 194 username = null; 195 password = null; 196 return true; 198 } 199 200 204 public String [] getPrincipalClassNames() { 205 return new String []{GeronimoUserPrincipal.class.getName(), GeronimoGroupPrincipal.class.getName()}; 206 } 207 208 212 public String [] getPrincipalsOfClass(String className) { 213 Set s; 214 if(className.equals(GeronimoGroupPrincipal.class.getName())) { 215 s = groups.keySet(); 216 } else if(className.equals(GeronimoUserPrincipal.class.getName())) { 217 s = users.keySet(); 218 } else { 219 throw new IllegalArgumentException ("No such principal class "+className); 220 } 221 return (String []) s.toArray(new String [s.size()]); 222 } 223 224 230 private boolean checkPassword(String real, String provided){ 231 if(digest == null || digest.equals("")) { 232 return real.equals(provided); 234 } 235 try { 236 MessageDigest md = MessageDigest.getInstance(digest); 238 byte[] data = md.digest(provided.getBytes()); 239 byte[] hexData = new byte[data.length * 2]; 241 HexTranslator ht = new HexTranslator(); 242 ht.encode(data, 0, data.length, hexData, 0); 243 return real.equalsIgnoreCase(new String (hexData)); 245 } catch (NoSuchAlgorithmException e) { 246 log.error("Should not occur. Availability of algorithm has been checked at initialization.", e); 248 } 249 return false; 250 } 251 } 252 | Popular Tags |