View Javadoc

1   /*
2    jGuard is a security framework based on top of jaas (java authentication and authorization security).
3    it is written for web applications, to resolve simply, access control problems.
4    version $Name$
5    http://sourceforge.net/projects/jguard/
6   
7    Copyright (C) 2004  Charles GAY
8   
9    This library is free software; you can redistribute it and/or
10   modify it under the terms of the GNU Lesser General Public
11   License as published by the Free Software Foundation; either
12   version 2.1 of the License, or (at your option) any later version.
13  
14   This library is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17   Lesser General Public License for more details.
18  
19   You should have received a copy of the GNU Lesser General Public
20   License along with this library; if not, write to the Free Software
21   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  
23  
24   jGuard project home page:
25   http://sourceforge.net/projects/jguard/
26  
27   */
28  package net.sf.jguard.ext.authentication.loginmodules;
29  
30  import java.io.IOException;
31  import java.lang.reflect.Array;
32  import java.security.cert.CertificateParsingException;
33  import java.security.cert.X509Certificate;
34  import java.util.Arrays;
35  import java.util.Collection;
36  import java.util.Iterator;
37  import java.util.List;
38  import java.util.Set;
39  
40  import java.util.logging.Level;
41  import javax.security.auth.Subject;
42  import javax.security.auth.callback.Callback;
43  import javax.security.auth.callback.CallbackHandler;
44  import javax.security.auth.callback.UnsupportedCallbackException;
45  import javax.security.auth.login.LoginException;
46  import javax.security.auth.spi.LoginModule;
47  
48  import net.sf.jguard.core.authentication.credentials.JGuardCredential;
49  import net.sf.jguard.ext.SecurityConstants;
50  import net.sf.jguard.ext.authentication.callbacks.CertificatesCallback;
51  import org.slf4j.Logger;
52  import org.slf4j.LoggerFactory;
53  
54  /**
55   * Base class for LoginModules related to certificate. 
56   * @author <a href="mailto:diabolo512@users.sourceforge.net">Charles Gay</a>
57   * @see CRLLoginModule
58   * @see OCSPLoginModule
59   * @since 1.0.0
60   */
61  public abstract class CertificateLoginModule implements LoginModule {
62  
63  	
64  	private static final Logger logger = LoggerFactory.getLogger(CertificateLoginModule.class.getName());
65  	protected Subject subject;
66  	protected boolean loginOK = true;
67  	protected X509Certificate[] certChainToCheck;
68  	protected CallbackHandler callbackHandler;
69  	/**
70  	 *
71  	 * @see javax.security.auth.spi.LoginModule#abort()
72  	 */
73  	public boolean abort() throws LoginException {
74  		if(subject!= null){
75  	          subject.getPrincipals().clear();
76  	          subject.getPrivateCredentials().clear();
77  	          subject.getPublicCredentials().clear();
78  	    }
79  	    return true;
80  	}
81  	public boolean commit() throws LoginException {
82  		if(loginOK){
83  			return certificateCommit();
84  		}else{
85  			return false;
86  		}
87  	}
88  
89  	
90  
91  	/**
92  	 *
93  	 * @see javax.security.auth.spi.LoginModule#logout()
94  	 */
95  	public boolean logout() throws LoginException {
96  		subject.getPrincipals().clear();
97  		subject.getPublicCredentials().clear();
98  		subject.getPrivateCredentials().clear();
99  		return true;
100 	}
101 
102 
103 	
104 	protected boolean certificateCommit() throws LoginException {
105 		Set publicCredentials = this.subject.getPublicCredentials();
106 		List certs = Arrays.asList(this.certChainToCheck);
107 		//we only use the first certificate which is the one assigned to user
108 		X509Certificate cert = (X509Certificate)certs.get(0);
109         subject.getPrincipals().add(cert.getSubjectX500Principal());
110         
111 		
112 		if(cert.getSubjectUniqueID()!=null){
113 			JGuardCredential credential1 = new JGuardCredential();
114 			credential1.setName(SecurityConstants.UNIQUE_ID);
115 			credential1.setValue(cert.getSubjectUniqueID());
116 			publicCredentials.add(credential1);
117 		}
118 		
119 		Collection altNames=null;
120 		try {
121 			altNames = cert.getSubjectAlternativeNames();
122 		} catch (CertificateParsingException e) {
123 			logger.error(" certificate cannot be parsed ");
124 			//alternativeNames must be valid unless they don't exist
125 			throw new LoginException(e.getMessage());
126 		}
127 		if(altNames==null){
128 			return true;
129 		}
130 		int count = 0;
131 		//populate alternativeNames
132 		Iterator itAltNames  = altNames.iterator();
133 		while(itAltNames.hasNext()){
134 			List extensionEntry = (List)itAltNames.next();
135 			Integer nameType = (Integer) extensionEntry.get(0);
136 			Object name = extensionEntry.get(1);
137 			byte[] nameAsBytes = null;
138 			JGuardCredential credential = new JGuardCredential();
139 			credential.setName(SecurityConstants.ALTERNATIVE_NAME+"#"+count);
140 			if(name instanceof Array){
141 				nameAsBytes = (byte[]) name;
142 			}
143 			if(nameAsBytes!= null){
144 				credential.setValue(nameType+"#"+new String(nameAsBytes));
145 			}else{
146 				credential.setValue(nameType+"#"+(String)name);
147 			}
148 			publicCredentials.add(credential);
149 			count++;
150 		}
151 
152 		return true;
153 	}
154 	
155 	
156 	public boolean login()throws LoginException{
157 		if (callbackHandler == null) {
158 			loginOK = false;
159 			throw new LoginException("there is no CallbackHandler to authenticate the user");
160 		}
161 		Callback[] callbacks = new Callback[1];
162 		callbacks[0] = new CertificatesCallback();
163 		try {
164 			callbackHandler.handle(callbacks);
165 		} catch (IOException e1) {
166 			logger.error( " IOException when we handle callbacks with callback " + callbackHandler.getClass().getName(), e1);
167 		} catch (UnsupportedCallbackException e1) {
168 			logger.error( " one callback type is not supported ", e1);
169 		}
170 		certChainToCheck = ((CertificatesCallback) callbacks[0]).getCertificates();
171 		if (certChainToCheck == null ||certChainToCheck.length==0) {
172 			loginOK = false;
173 			//no certificates can be checked so we inactivate this loginmodule
174 			return false;
175 		}
176 		return true;
177 	}
178 }