1 22 package org.jboss.security.srp.jaas; 23 24 import java.security.Principal ; 25 import java.util.Arrays ; 26 import java.util.Map ; 27 import java.util.Set ; 28 import javax.crypto.spec.SecretKeySpec; 29 import javax.naming.InitialContext ; 30 import javax.naming.NamingException ; 31 import javax.security.auth.Subject ; 32 import javax.security.auth.callback.CallbackHandler ; 33 import javax.security.auth.callback.Callback ; 34 import javax.security.auth.callback.UnsupportedCallbackException ; 35 import javax.security.auth.login.LoginException ; 36 import javax.security.auth.spi.LoginModule ; 37 38 import org.jboss.logging.Logger; 39 import org.jboss.security.auth.callback.SecurityAssociationCallback; 40 import org.jboss.security.srp.SRPParameters; 41 import org.jboss.security.srp.SRPServerSession; 42 import org.jboss.security.srp.SRPSessionKey; 43 import org.jboss.util.CachePolicy; 44 45 59 public class SRPCacheLoginModule implements LoginModule 60 { 61 private static Logger log = Logger.getLogger(SRPCacheLoginModule.class); 62 private Subject subject; 63 private CallbackHandler handler; 64 private Map sharedState; 65 private String domainName; 66 private String cacheJndiName; 67 private byte[] clientChallenge; 68 private SRPServerSession session; 69 private Principal userPrincipal; 70 private boolean loginFailed; 71 72 public SRPCacheLoginModule() 73 { 74 } 75 76 87 public void initialize(Subject subject, CallbackHandler handler, Map sharedState, Map options) 88 { 89 this.subject = subject; 90 this.handler = handler; 91 this.sharedState = sharedState; 92 cacheJndiName = (String ) options.get("cacheJndiName"); 93 log.trace("cacheJndiName="+cacheJndiName); 94 domainName = (String ) options.get("domainName"); 95 } 96 97 107 public boolean login() throws LoginException 108 { 109 loginFailed = true; 110 getUserInfo(); 111 112 String username = userPrincipal.getName(); 113 try 115 { 116 if( cacheJndiName == null ) 117 throw new LoginException ("Required cacheJndiName option not set"); 118 InitialContext iniCtx = new InitialContext (); 119 CachePolicy cache = (CachePolicy) iniCtx.lookup(cacheJndiName); 120 SRPSessionKey key; 121 if( userPrincipal instanceof SRPPrincipal ) 122 { 123 SRPPrincipal srpPrincpal = (SRPPrincipal) userPrincipal; 124 key = new SRPSessionKey(username, srpPrincpal.getSessionID()); 125 } 126 else 127 { 128 key = new SRPSessionKey(username); 129 } 130 Object cacheCredential = cache.get(key); 131 if( cacheCredential == null ) 132 { 133 throw new LoginException ("No SRP session found for: "+key); 134 } 135 log.trace("Found SRP cache credential: "+cacheCredential); 136 139 if( cacheCredential instanceof SRPServerSession ) 140 { 141 session = (SRPServerSession) cacheCredential; 142 if( validateCache(session) == false ) 143 throw new LoginException ("Failed to validate SRP session key for: "+key); 144 } 145 else 146 { 147 throw new LoginException ("Unknown type of cache credential: "+cacheCredential.getClass()); 148 } 149 } 150 catch(NamingException e) 151 { 152 log.error("Failed to load SRP auth cache", e); 153 throw new LoginException ("Failed to load SRP auth cache: "+e.toString(true)); 154 } 155 156 log.trace("Login succeeded"); 157 sharedState.put("javax.security.auth.login.name", username); 159 sharedState.put("javax.security.auth.login.password", clientChallenge); 160 loginFailed = false; 161 return true; 162 } 163 164 171 public boolean commit() throws LoginException 172 { 173 if( loginFailed == true ) 174 return false; 175 Set principals = subject.getPrincipals(); 176 principals.add(userPrincipal); 177 subject.getPublicCredentials().add(clientChallenge); 178 byte[] sessionKey = session.getSessionKey(); 179 SRPParameters params = session.getParameters(); 180 Set privateCredentials = subject.getPrivateCredentials(); 181 privateCredentials.add(params); 182 if( params.cipherAlgorithm != null ) 183 { 184 SecretKeySpec secretKey = new SecretKeySpec(sessionKey, params.cipherAlgorithm); 185 privateCredentials.add(secretKey); 186 } 187 else 188 { 189 privateCredentials.add(sessionKey); 190 } 191 192 return true; 193 } 194 195 public boolean abort() throws LoginException 196 { 197 userPrincipal = null; 198 clientChallenge = null; 199 return true; 200 } 201 202 208 public boolean logout() throws LoginException 209 { 210 try 211 { 212 if( subject.isReadOnly() == false ) 213 { Set s = subject.getPrincipals(userPrincipal.getClass()); 215 s.remove(userPrincipal); 216 subject.getPublicCredentials().remove(clientChallenge); 217 byte[] sessionKey = session.getSessionKey(); 218 SRPParameters params = session.getParameters(); 219 Set privateCredentials = subject.getPrivateCredentials(); 220 if( params.cipherAlgorithm != null ) 221 { 222 SecretKeySpec secretKey = new SecretKeySpec(sessionKey, params.cipherAlgorithm); 223 privateCredentials.remove(secretKey); 224 } 225 else 226 { 227 privateCredentials.remove(sessionKey); 228 } 229 privateCredentials.remove(params); 230 } 231 } 232 catch(Exception e) 233 { 234 throw new LoginException ("Failed to remove commit information, "+e.getMessage()); 235 } 236 return true; 237 } 238 239 241 243 private void getUserInfo() throws LoginException 244 { 245 if( handler == null ) 247 throw new LoginException ("No CallbackHandler provied"); 248 249 SecurityAssociationCallback sac = new SecurityAssociationCallback(); 250 Callback [] callbacks = { sac }; 251 try 252 { 253 handler.handle(callbacks); 254 userPrincipal = sac.getPrincipal(); 255 clientChallenge = (byte[]) sac.getCredential(); 256 sac.clearCredential(); 257 } 258 catch(java.io.IOException e) 259 { 260 throw new LoginException (e.toString()); 261 } 262 catch(UnsupportedCallbackException uce) 263 { 264 throw new LoginException ("UnsupportedCallback: " + uce.getCallback().toString()); 265 } 266 catch(ClassCastException e) 267 { 268 throw new LoginException ("Credential info is not of type byte[], "+ e.getMessage()); 269 } 270 } 271 272 275 private boolean validateCache(SRPServerSession session) 276 { 277 byte[] challenge = session.getClientResponse(); 278 boolean isValid = Arrays.equals(challenge, clientChallenge); 279 return isValid; 280 } 281 282 } 283 | Popular Tags |