00001
00027 package org.objectweb.jonas.security.auth.spi;
00028
00029 import java.io.File;
00030 import java.io.FileInputStream;
00031 import java.security.cert.CertStore;
00032 import java.security.cert.CertStoreParameters;
00033 import java.security.cert.CertificateFactory;
00034 import java.security.cert.CollectionCertStoreParameters;
00035 import java.security.cert.LDAPCertStoreParameters;
00036 import java.security.cert.X509CRL;
00037 import java.security.cert.X509CRLSelector;
00038 import java.security.cert.X509Certificate;
00039 import java.util.ArrayList;
00040 import java.util.Iterator;
00041 import java.util.Map;
00042
00043 import javax.security.auth.Subject;
00044 import javax.security.auth.callback.Callback;
00045 import javax.security.auth.callback.CallbackHandler;
00046 import javax.security.auth.callback.NameCallback;
00047 import javax.security.auth.login.LoginException;
00048 import javax.security.auth.spi.LoginModule;
00049
00050 import org.objectweb.jonas.security.auth.JPrincipal;
00051 import org.objectweb.jonas.security.auth.callback.CertificateCallback;
00052
00058 public class CRLLoginModule implements LoginModule {
00059
00063 private Subject subject = null;
00064
00068 private CallbackHandler callbackHandler = null;
00069
00073 private Map sharedState = null;
00074
00078 private Map options = null;
00079
00083 private String principalName = null;
00084
00088 private String password = null;
00089
00093 private ArrayList principalRoles = null;
00094
00098 private X509Certificate cert = null;
00099
00113 public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
00114 this.subject = subject;
00115 this.callbackHandler = callbackHandler;
00116 this.sharedState = sharedState;
00117 this.options = options;
00118 }
00119
00130 public boolean login() throws LoginException {
00131
00132
00133 if (callbackHandler == null) {
00134 throw new LoginException("No handler has been defined.");
00135 }
00136 String crlsResourceName = (String) options.get("CRLsResourceName");
00137 String certStoreAccessName = null;
00138 NameCallback nameCallback = null;
00139 CertificateCallback certificateCallback = null;
00140 try {
00141
00142
00143 nameCallback = new NameCallback("User :");
00144 certificateCallback = new CertificateCallback();
00145 Callback[] callbacks = new Callback[] {nameCallback, certificateCallback};
00146 callbackHandler.handle(callbacks);
00147 } catch (Exception e) {
00148 throw new LoginException("Problem while getting informations in the callbackhandler: " + e.getMessage());
00149 }
00150
00151 try {
00152 this.cert = (X509Certificate) certificateCallback.getUserCertificate();
00153 if (nameCallback.getName().startsWith("##DN##")) {
00154 if ((this.cert == null)) {
00155 throw new LoginException("Client certificate not present, it can be verified with CRL");
00156 }
00157 } else {
00158
00159
00160 return true;
00161 }
00162
00163
00164 CertStoreParameters certStoreParameters = null;
00165
00166
00167 if (crlsResourceName.equalsIgnoreCase("Directory")) {
00168 certStoreAccessName = "Collection";
00169
00170 String crlsDirectoryName = (String) options.get("CRLsDirectoryName");
00171
00172 if (crlsDirectoryName == null) {
00173 throw new LoginException(
00174 "You have to give an argument to this login module. The \"CRLsDirectoryName\" parameter is required.");
00175 }
00176 File crlsDirectory = new File(crlsDirectoryName);
00177 if (!crlsDirectory.isDirectory()) {
00178 throw new LoginException(crlsDirectoryName + " is not a directory");
00179 }
00180
00181 CertificateFactory cf = CertificateFactory.getInstance("X.509");
00182 FileInputStream fis = null;
00183
00184 String[] crlFileName = crlsDirectory.list();
00185
00186 ArrayList crls = new ArrayList(crlFileName.length);
00187 X509CRL crl = null;
00188
00189 for (int i = 0; i < crlFileName.length; i++) {
00190
00191 if (crlFileName[i].matches(".+\\.crl")) {
00192 fis = new FileInputStream(crlsDirectory.getAbsolutePath() + File.separatorChar + crlFileName[i]);
00193 crl = (X509CRL) cf.generateCRL(fis);
00194 crls.add(crl);
00195 fis.close();
00196 fis = null;
00197 crl = null;
00198 }
00199 }
00200
00201 certStoreParameters = new CollectionCertStoreParameters(crls);
00202 } else if (crlsResourceName.equalsIgnoreCase("LDAP")) {
00203
00204 certStoreAccessName = "LDAP";
00205
00206 String address = (String) options.get("address");
00207 int port = Integer.parseInt((String) options.get("port"));
00208 if (address == null) {
00209 throw new LoginException(
00210 "You have to give an argument to this login module. The \"address\" and \"port\" parameter are required.");
00211 }
00212
00213 certStoreParameters = new LDAPCertStoreParameters(address, port);
00214 } else {
00215 throw new LoginException(
00216 "You have to give an argument to this login module. The \"CRLsResourceName\" is not valid. Must be set to \"Directory\" or \"LDAP\"");
00217 }
00218
00219
00220 CertStore crlsStore = CertStore.getInstance(certStoreAccessName, certStoreParameters);
00221 X509CRLSelector x509CRLSelector = new X509CRLSelector();
00222
00223
00224
00225 x509CRLSelector.addIssuerName(this.cert.getIssuerX500Principal().getEncoded());
00226 Iterator crlIterator = crlsStore.getCRLs(x509CRLSelector).iterator();
00227 while (crlIterator.hasNext()) {
00228 if (((X509CRL) crlIterator.next()).isRevoked(this.cert)) {
00229 throw new LoginException("Client certificate has been revoked");
00230 }
00231 }
00232 } catch (Exception e) {
00233 throw new LoginException("Error during the login phase : " + e.getMessage());
00234 }
00235
00236 return true;
00237 }
00238
00253 public boolean commit() throws LoginException {
00254 return true;
00255 }
00256
00268 public boolean abort() throws LoginException {
00269
00270
00271 principalName = null;
00272 principalRoles = null;
00273
00274 return true;
00275 }
00276
00284 public boolean logout() throws LoginException {
00285
00286
00287 subject.getPrincipals().remove(new JPrincipal(principalName));
00288
00289 return true;
00290 }
00291
00292 }