1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.ldap.server.authn;
18
19
20 import org.apache.ldap.common.exception.LdapAuthenticationException;
21 import org.apache.ldap.common.exception.LdapAuthenticationNotSupportedException;
22 import org.apache.ldap.common.message.ResultCodeEnum;
23 import org.apache.ldap.common.util.StringTools;
24 import org.apache.ldap.server.interceptor.Interceptor;
25 import org.apache.ldap.server.interceptor.InterceptorContext;
26 import org.apache.ldap.server.interceptor.NextInterceptor;
27 import org.apache.ldap.server.invocation.Invocation;
28 import org.apache.ldap.server.jndi.EnvKeys;
29 import org.apache.ldap.server.jndi.ServerContext;
30 import org.apache.ldap.server.jndi.ServerLdapContext;
31
32 import javax.naming.Context;
33 import javax.naming.NamingException;
34 import java.lang.reflect.Constructor;
35 import java.util.*;
36
37
38 /***
39 * An {@link Interceptor} that authenticates users.
40 *
41 * @author Apache Directory Project (dev@directory.apache.org)
42 * @author Alex Karasulu (akarasulu@apache.org)
43 * @author Trustin Lee (trustin@apache.org)
44 * @version $Rev: 159259 $, $Date: 2005-03-28 12:00:29 -0500 (Mon, 28 Mar 2005) $
45 */
46 public class AuthenticationService implements Interceptor
47 {
48 /*** short for Context.SECURITY_AUTHENTICATION */
49 private static final String AUTH_TYPE = Context.SECURITY_AUTHENTICATION;
50
51 /*** short for Context.SECURITY_CREDENTIALS */
52 private static final String CREDS = Context.SECURITY_CREDENTIALS;
53
54 /*** authenticators **/
55 public Map authenticators = new LinkedHashMap();
56
57
58 /***
59 * Creates an authentication service interceptor.
60 */
61 public AuthenticationService()
62 {
63 }
64
65 public void init( InterceptorContext ctx ) throws NamingException
66 {
67
68
69
70
71 boolean allowAnonymous = !ctx.getEnvironment().containsKey( EnvKeys.DISABLE_ANONYMOUS );
72
73
74
75 GenericAuthenticatorContext authenticatorContext = new GenericAuthenticatorContext();
76
77 authenticatorContext.setPartitionNexus( ctx.getRootNexus() );
78
79 authenticatorContext.setAllowAnonymous( allowAnonymous );
80
81 try
82 {
83
84
85 GenericAuthenticatorConfig authenticatorConfig = new GenericAuthenticatorConfig();
86
87 authenticatorConfig.setAuthenticatorName( "none" );
88
89 authenticatorConfig.setAuthenticatorContext( authenticatorContext );
90
91 org.apache.ldap.server.authn.Authenticator authenticator = new AnonymousAuthenticator();
92
93 authenticator.init( authenticatorConfig );
94
95 this.register( authenticator );
96
97
98 authenticatorConfig = new GenericAuthenticatorConfig();
99
100 authenticatorConfig.setAuthenticatorName( "simple" );
101
102 authenticatorConfig.setAuthenticatorContext( authenticatorContext );
103
104 authenticator = new SimpleAuthenticator();
105
106 authenticator.init( authenticatorConfig );
107
108 this.register( authenticator );
109 }
110 catch ( Exception e )
111 {
112 throw new NamingException( e.getMessage() );
113 }
114
115 GenericAuthenticatorConfig[] configs = null;
116
117 configs = AuthenticatorConfigBuilder.getAuthenticatorConfigs( new Hashtable( ctx.getEnvironment() ) );
118
119 for ( int ii = 0; ii < configs.length; ii++ )
120 {
121 try
122 {
123 configs[ii].setAuthenticatorContext( authenticatorContext );
124
125 String authenticatorClass = configs[ii].getAuthenticatorClass();
126
127 Class clazz = Class.forName( authenticatorClass );
128
129 Constructor constructor = clazz.getConstructor( new Class[] { } );
130
131 AbstractAuthenticator authenticator = ( AbstractAuthenticator ) constructor.newInstance( new Object[] { } );
132
133 authenticator.init( configs[ii] );
134
135 this.register( authenticator );
136 }
137 catch ( Exception e )
138 {
139 e.printStackTrace();
140 }
141 }
142
143 }
144
145 public void destroy()
146 {
147 authenticators.clear();
148 }
149
150 /***
151 * Registers an AuthenticationService with the AuthenticationService. Called by each
152 * AuthenticationService implementation after it has started to register for
153 * authentication operation calls.
154 *
155 * @param authenticator AuthenticationService component to register with this
156 * AuthenticatorService.
157 */
158 public void register( org.apache.ldap.server.authn.Authenticator authenticator )
159 {
160 Collection authenticatorList = getAuthenticators( authenticator.getAuthenticatorType() );
161
162 if ( authenticatorList == null )
163 {
164 authenticatorList = new ArrayList();
165
166 authenticators.put( authenticator.getAuthenticatorType(), authenticatorList );
167 }
168
169 authenticatorList.add( authenticator );
170 }
171
172 /***
173 * Unregisters an AuthenticationService with the AuthenticationService. Called for each
174 * registered AuthenticationService right before it is to be stopped. This prevents
175 * protocol server calls from reaching the Backend and effectively puts
176 * the ContextPartition's naming context offline.
177 *
178 * @param authenticator AuthenticationService component to unregister with this
179 * AuthenticationService.
180 */
181 public void unregister( org.apache.ldap.server.authn.Authenticator authenticator )
182 {
183 Collection authenticatorList = getAuthenticators( authenticator.getAuthenticatorType() );
184
185 if ( authenticatorList == null )
186 {
187 return;
188 }
189
190 authenticatorList.remove( authenticator );
191 }
192
193 /***
194 * Gets the authenticators with a specific type.
195 *
196 * @param type the authentication type
197 * @return the authenticators with the specified type
198 */
199 public Collection getAuthenticators( String type )
200 {
201 return ( Collection ) authenticators.get( type );
202 }
203
204 public void process( NextInterceptor nextProcessor, Invocation call ) throws NamingException
205 {
206
207
208 ServerContext ctx = ( ServerLdapContext ) call.getContextStack().peek();
209
210 if ( ctx.getPrincipal() != null )
211 {
212 if ( ctx.getEnvironment().containsKey( CREDS ) )
213 {
214 ctx.removeFromEnvironment( CREDS );
215 }
216
217 nextProcessor.process(call);
218
219 return;
220 }
221
222 String authList = ( String ) ctx.getEnvironment().get( AUTH_TYPE );
223
224 if ( authList == null )
225 {
226 if ( ctx.getEnvironment().containsKey( CREDS ) )
227 {
228
229
230 authList = "simple";
231 }
232 else
233 {
234
235
236 authList = "none";
237 }
238
239 }
240
241 authList = StringTools.deepTrim( authList );
242
243 String[] auth = authList.split( " " );
244
245 Collection authenticators = null;
246
247
248
249 for ( int i=0; i<auth.length; i++)
250 {
251 authenticators = getAuthenticators( auth[i] );
252
253 if ( authenticators != null )
254 {
255 break;
256 }
257 }
258
259 if ( authenticators == null )
260 {
261 ctx.getEnvironment();
262
263 ResultCodeEnum rc = ResultCodeEnum.AUTHMETHODNOTSUPPORTED;
264
265 throw new LdapAuthenticationNotSupportedException( rc );
266 }
267
268
269 for ( Iterator i = authenticators.iterator(); i.hasNext(); )
270 {
271 try
272 {
273 Authenticator authenticator = ( Authenticator ) i.next();
274
275
276
277 LdapPrincipal authorizationId = authenticator.authenticate( ctx );
278
279
280
281 ctx.setPrincipal( new TrustedPrincipalWrapper( authorizationId ) );
282
283
284
285 ctx.removeFromEnvironment( CREDS );
286
287 nextProcessor.process(call);
288
289 return;
290 }
291 catch ( LdapAuthenticationException e )
292 {
293
294 }
295 }
296
297 throw new LdapAuthenticationException();
298 }
299
300
301 /***
302 * Created this wrapper to pass to ctx.setPrincipal() which is public for added
303 * security. This adds more security because an instance of this class is not
304 * easily accessible whereas LdapPrincipals can be accessed easily from a context
305 * althought they cannot be instantiated outside of the authn package. Malicious
306 * code may not be able to set the principal to what they would like but they
307 * could switch existing principals using the now public ServerContext.setPrincipal()
308 * method. To avoid this we make sure that this metho takes a TrustedPrincipalWrapper
309 * as opposed to the LdapPrincipal. Only this service can create and call setPrincipal
310 * with a TrustedPrincipalWrapper.
311 */
312 public final class TrustedPrincipalWrapper
313 {
314 /*** the wrapped ldap principal */
315 private final LdapPrincipal principal;
316
317
318 /***
319 * Creates a TrustedPrincipalWrapper around an LdapPrincipal.
320 *
321 * @param principal the LdapPrincipal to wrap
322 */
323 private TrustedPrincipalWrapper( LdapPrincipal principal )
324 {
325 this.principal = principal;
326 }
327
328
329 /***
330 * Gets the LdapPrincipal this TrustedPrincipalWrapper wraps.
331 *
332 * @return the wrapped LdapPrincipal
333 */
334 public LdapPrincipal getPrincipal()
335 {
336 return principal;
337 }
338 }
339 }