1 7 package org.jboss.security.auth.spi; 8 9 import java.security.Principal ; 10 import java.util.Map ; 11 import java.util.HashMap ; 12 13 import javax.security.auth.Subject ; 14 import javax.security.auth.callback.Callback ; 15 import javax.security.auth.callback.CallbackHandler ; 16 import javax.security.auth.callback.NameCallback ; 17 import javax.security.auth.callback.PasswordCallback ; 18 import javax.security.auth.callback.UnsupportedCallbackException ; 19 import javax.security.auth.login.FailedLoginException ; 20 import javax.security.auth.login.LoginException ; 21 22 import org.jboss.security.Util; 23 import org.jboss.crypto.digest.DigestCallback; 24 25 26 42 public abstract class UsernamePasswordLoginModule extends AbstractServerLoginModule 43 { 44 45 private Principal identity; 46 47 private char[] credential; 48 50 private String hashAlgorithm = null; 51 54 private String hashCharset = null; 55 56 private String hashEncoding = null; 57 58 private boolean ignorePasswordCase; 59 60 74 public void initialize(Subject subject, CallbackHandler callbackHandler, 75 Map sharedState, Map options) 76 { 77 super.initialize(subject, callbackHandler, sharedState, options); 78 79 hashAlgorithm = (String ) options.get("hashAlgorithm"); 82 if( hashAlgorithm != null ) 83 { 84 hashEncoding = (String ) options.get("hashEncoding"); 85 if( hashEncoding == null ) 86 hashEncoding = Util.BASE64_ENCODING; 87 hashCharset = (String ) options.get("hashCharset"); 88 if( log.isTraceEnabled() ) 89 { 90 log.trace("Password hashing activated: algorithm = " + hashAlgorithm 91 + ", encoding = " + hashEncoding 92 + ", charset = " + (hashCharset == null ? "{default}" : hashCharset) 93 + ", callback = " + options.get("digestCallback") 94 ); 95 } 96 } 97 String flag = (String ) options.get("ignorePasswordCase"); 98 ignorePasswordCase = Boolean.valueOf(flag).booleanValue(); 99 } 100 101 103 public boolean login() throws LoginException 104 { 105 if( super.login() == true ) 107 { 108 Object username = sharedState.get("javax.security.auth.login.name"); 110 if( username instanceof Principal ) 111 identity = (Principal ) username; 112 else 113 { 114 String name = username.toString(); 115 try 116 { 117 identity = createIdentity(name); 118 } 119 catch(Exception e) 120 { 121 log.debug("Failed to create principal", e); 122 throw new LoginException ("Failed to create principal: "+ e.getMessage()); 123 } 124 } 125 Object password = sharedState.get("javax.security.auth.login.password"); 126 if( password instanceof char[] ) 127 credential = (char[]) password; 128 else if( password != null ) 129 { 130 String tmp = password.toString(); 131 credential = tmp.toCharArray(); 132 } 133 return true; 134 } 135 136 super.loginOk = false; 137 String [] info = getUsernameAndPassword(); 138 String username = info[0]; 139 String password = info[1]; 140 if( username == null && password == null ) 141 { 142 identity = unauthenticatedIdentity; 143 super.log.trace("Authenticating as unauthenticatedIdentity="+identity); 144 } 145 146 if( identity == null ) 147 { 148 try 149 { 150 identity = createIdentity(username); 151 } 152 catch(Exception e) 153 { 154 log.debug("Failed to create principal", e); 155 throw new LoginException ("Failed to create principal: "+ e.getMessage()); 156 } 157 158 if( hashAlgorithm != null ) 160 password = createPasswordHash(username, password); 161 String expectedPassword = getUsersPassword(); 163 if( validatePassword(password, expectedPassword) == false ) 164 { 165 super.log.debug("Bad password for username="+username); 166 throw new FailedLoginException ("Password Incorrect/Password Required"); 167 } 168 } 169 170 if( getUseFirstPass() == true ) 171 { sharedState.put("javax.security.auth.login.name", username); 173 sharedState.put("javax.security.auth.login.password", credential); 174 } 175 super.loginOk = true; 176 super.log.trace("User '" + identity + "' authenticated, loginOk="+loginOk); 177 return true; 178 } 179 180 protected Principal getIdentity() 181 { 182 return identity; 183 } 184 protected Principal getUnauthenticatedIdentity() 185 { 186 return unauthenticatedIdentity; 187 } 188 189 protected Object getCredentials() 190 { 191 return credential; 192 } 193 protected String getUsername() 194 { 195 String username = null; 196 if( getIdentity() != null ) 197 username = getIdentity().getName(); 198 return username; 199 } 200 201 206 protected String [] getUsernameAndPassword() throws LoginException 207 { 208 String [] info = {null, null}; 209 if( callbackHandler == null ) 211 { 212 throw new LoginException ("Error: no CallbackHandler available " + 213 "to collect authentication information"); 214 } 215 NameCallback nc = new NameCallback ("User name: ", "guest"); 216 PasswordCallback pc = new PasswordCallback ("Password: ", false); 217 Callback [] callbacks = {nc, pc}; 218 String username = null; 219 String password = null; 220 try 221 { 222 callbackHandler.handle(callbacks); 223 username = nc.getName(); 224 char[] tmpPassword = pc.getPassword(); 225 if( tmpPassword != null ) 226 { 227 credential = new char[tmpPassword.length]; 228 System.arraycopy(tmpPassword, 0, credential, 0, tmpPassword.length); 229 pc.clearPassword(); 230 password = new String (credential); 231 } 232 } 233 catch(java.io.IOException ioe) 234 { 235 throw new LoginException (ioe.toString()); 236 } 237 catch(UnsupportedCallbackException uce) 238 { 239 throw new LoginException ("CallbackHandler does not support: " + uce.getCallback()); 240 } 241 info[0] = username; 242 info[1] = password; 243 return info; 244 } 245 246 271 protected String createPasswordHash(String username, String password) 272 { 273 DigestCallback callback = null; 274 String callbackClassName = (String ) options.get("digestCallback"); 275 if( callbackClassName != null ) 276 { 277 try 278 { 279 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 280 Class callbackClass = loader.loadClass(callbackClassName); 281 callback = (DigestCallback) callbackClass.newInstance(); 282 if( log.isTraceEnabled() ) 283 log.trace("Created DigestCallback: "+callback); 284 } 285 catch (Exception e) 286 { 287 if( log.isTraceEnabled() ) 288 log.trace("Failed to load DigestCallback", e); 289 SecurityException ex = new SecurityException ("Failed to load DigestCallback"); 290 ex.initCause(e); 291 throw ex; 292 } 293 HashMap tmp = new HashMap (options); 294 tmp.put("javax.security.auth.login.name", username); 295 tmp.put("javax.security.auth.login.password", password); 296 callback.init(tmp); 297 } 298 String passwordHash = Util.createPasswordHash(hashAlgorithm, hashEncoding, 299 hashCharset, username, password, callback); 300 return passwordHash; 301 } 302 303 309 protected boolean validatePassword(String inputPassword, String expectedPassword) 310 { 311 if( inputPassword == null || expectedPassword == null ) 312 return false; 313 boolean valid = false; 314 if( ignorePasswordCase == true ) 315 valid = inputPassword.equalsIgnoreCase(expectedPassword); 316 else 317 valid = inputPassword.equals(expectedPassword); 318 return valid; 319 } 320 321 322 328 abstract protected String getUsersPassword() throws LoginException ; 329 330 } 331 | Popular Tags |