JResourceLoginModule.java

00001 
00026 package org.objectweb.jonas.security.auth.spi;
00027 
00028 import java.util.ArrayList;
00029 import java.util.Map;
00030 
00031 import javax.naming.InitialContext;
00032 import javax.security.auth.Subject;
00033 import javax.security.auth.callback.Callback;
00034 import javax.security.auth.callback.CallbackHandler;
00035 import javax.security.auth.callback.NameCallback;
00036 import javax.security.auth.callback.PasswordCallback;
00037 import javax.security.auth.login.LoginException;
00038 import javax.security.auth.spi.LoginModule;
00039 
00040 import org.objectweb.jonas.security.auth.JGroup;
00041 import org.objectweb.jonas.security.auth.JPrincipal;
00042 import org.objectweb.jonas.security.auth.JRole;
00043 import org.objectweb.jonas.security.auth.callback.CertificateCallback;
00044 import org.objectweb.jonas.security.realm.factory.JResource;
00045 import org.objectweb.jonas.security.realm.factory.JResourceException;
00046 import org.objectweb.jonas.security.realm.principals.User;
00047 
00055 public class JResourceLoginModule implements LoginModule {
00056 
00060     private Subject subject = null;
00061 
00065     private CallbackHandler callbackHandler = null;
00066 
00070     private Map options = null;
00071 
00075     private String principalName = null;
00076 
00080     private String password = null;
00081 
00085     private ArrayList principalRoles = null;
00086 
00090     private boolean loginWasDoneWithSuccess = false;;
00091 
00105     public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
00106         this.subject = subject;
00107         this.callbackHandler = callbackHandler;
00108         this.options = options;
00109     }
00110 
00121     public boolean login() throws LoginException {
00122 
00123         // No handler
00124         if (callbackHandler == null) {
00125             throw new LoginException("No handler has been defined.");
00126         }
00127 
00128         // Resource to be used (jndi name)
00129         String resourceName = (String) options.get("resourceName");
00130 
00131         // Use certificate callback
00132         String certCallback = (String) options.get("certCallback");
00133 
00134         // No resource is specified -> fail
00135         if (resourceName == null) {
00136             throw new LoginException(
00137                     "You have to give an argument to this login module. The 'resourceName' parameter is required.");
00138         }
00139 
00140         // Get the resource and perform authentication
00141         try {
00142             InitialContext ictx = new InitialContext();
00143             JResource jResource = null;
00144             try {
00145                 jResource = (JResource) ictx.lookup(resourceName);
00146             } catch (Exception e) {
00147                 throw createChainedLoginException("Cannot retrieve the resource '" + resourceName
00148                         + "'. Check that this resource is bound in the registry", e);
00149             }
00150 
00151             // Handle callbacks
00152             NameCallback nameCallback = new NameCallback("User :");
00153             // False to hide password when it is entered
00154             PasswordCallback passwordCallback = new PasswordCallback("Password :", false);
00155             CertificateCallback certificateCallback = new CertificateCallback();
00156             Callback[] callbacks = null;
00157 
00158             if ((certCallback != null) && (Boolean.valueOf(certCallback).booleanValue())) {
00159                 callbacks = new Callback[] {nameCallback, passwordCallback, certificateCallback};
00160             } else {
00161                 callbacks = new Callback[] {nameCallback, passwordCallback};
00162             }
00163             callbackHandler.handle(callbacks);
00164 
00165             // Get values
00166             principalName = nameCallback.getName();
00167             if (principalName == null) {
00168                 throw new LoginException("A null username is not a valid username");
00169             }
00170             if (principalName.startsWith("##DN##") && (certificateCallback.getUserCertificate() == null)) {
00171                 throw new LoginException("Name must have a certificate to access this certificate based access login");
00172             }
00173             char[] arrayPass = passwordCallback.getPassword();
00174             if (arrayPass == null) {
00175                 throw new LoginException("A null password is not a valid password");
00176             }
00177 
00178             // Authentication - step 1 (user)
00179             User user = null;
00180             try {
00181                 user = jResource.findUser(principalName);
00182             } catch (Exception jre) {
00183                 // could not retrieve user
00184                 throw createChainedLoginException("Can not find the user", jre);
00185             }
00186             // User was not found
00187             if (user == null) {
00188                 throw new LoginException("User '" + principalName + "' not found.");
00189             }
00190 
00191             // Authentication - step 2 (password)
00192             boolean validated = jResource.isValidUser(user, new String(arrayPass));
00193             if (!validated) {
00194                 throw new LoginException("The password for the user '" + principalName + "' is not valid");
00195             }
00196             this.password = user.getPassword();
00197             // Authentication - step 3 (roles)
00198             try {
00199                 principalRoles = jResource.getArrayListCombinedRoles(user);
00200             } catch (JResourceException jre) {
00201                 throw createChainedLoginException(jre.getMessage(), jre);
00202             }
00203 
00204         } catch (Exception e) {
00205             throw createChainedLoginException("Error during the login phase : " + e.getMessage(), e);
00206         }
00207         loginWasDoneWithSuccess = true;
00208         return true;
00209     }
00210 
00217     private static LoginException createChainedLoginException(String msg, Exception e) {
00218         LoginException le = new LoginException(msg);
00219         le.initCause(e);
00220         return le;
00221     }
00222 
00237     public boolean commit() throws LoginException {
00238 
00239             //overall authentication succeeded
00240         if (loginWasDoneWithSuccess) {
00241             // Add principal to the current subject
00242             subject.getPrincipals().add(new JPrincipal(principalName));
00243             subject.getPrivateCredentials().add(password);
00244             JGroup group = new JGroup("Roles");
00245 
00246             // Convert list into array
00247             String[] roles = new String[principalRoles.size()];
00248             roles = (String[]) principalRoles.toArray(roles);
00249             int size = principalRoles.size();
00250             for (int i = 0; i < size; i++) {
00251                 group.addMember(new JRole(roles[i]));
00252             }
00253 
00254             // Add group
00255             subject.getPrincipals().add(group);
00256         }
00257         return loginWasDoneWithSuccess;
00258     }
00259 
00271     public boolean abort() throws LoginException {
00272         //overall authentication succeeded
00273         if (loginWasDoneWithSuccess) {
00274             // Reset temp values
00275             principalName = null;
00276             principalRoles = null;
00277         }
00278         return loginWasDoneWithSuccess;
00279     }
00280 
00288     public boolean logout() throws LoginException {
00289 
00290         //overall authentication succeeded
00291         if (loginWasDoneWithSuccess) {
00292             // Remove principal name
00293             subject.getPrincipals().remove(new JPrincipal(principalName));
00294         }
00295 
00296         return loginWasDoneWithSuccess;
00297     }
00298 
00299 }

Generated on Tue Feb 15 15:05:21 2005 for JOnAS by  doxygen 1.3.9.1