1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.server.core.authn;
21
22
23 import java.net.SocketAddress;
24
25 import javax.naming.Context;
26
27 import org.apache.commons.collections4.map.LRUMap;
28 import org.apache.directory.api.ldap.model.constants.AuthenticationLevel;
29 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
30 import org.apache.directory.api.ldap.model.entry.Attribute;
31 import org.apache.directory.api.ldap.model.entry.Entry;
32 import org.apache.directory.api.ldap.model.entry.Value;
33 import org.apache.directory.api.ldap.model.exception.LdapAuthenticationException;
34 import org.apache.directory.api.ldap.model.exception.LdapException;
35 import org.apache.directory.api.ldap.model.name.Dn;
36 import org.apache.directory.api.ldap.model.password.PasswordUtil;
37 import org.apache.directory.server.core.api.DirectoryService;
38 import org.apache.directory.server.core.api.InterceptorEnum;
39 import org.apache.directory.server.core.api.LdapPrincipal;
40 import org.apache.directory.server.core.api.authn.ppolicy.PasswordPolicyConfiguration;
41 import org.apache.directory.server.core.api.authn.ppolicy.PasswordPolicyException;
42 import org.apache.directory.server.core.api.entry.ClonedServerEntry;
43 import org.apache.directory.server.core.api.interceptor.context.BindOperationContext;
44 import org.apache.directory.server.core.api.interceptor.context.LookupOperationContext;
45 import org.apache.directory.server.i18n.I18n;
46 import org.apache.mina.core.session.IoSession;
47
48
49
50
51
52
53
54
55
56
57
58
59 public class SimpleAuthenticator extends AbstractAuthenticator
60 {
61
62 private static final boolean IS_DEBUG = LOG.isDebugEnabled();
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80 private final LRUMap credentialCache;
81
82
83 private static final int DEFAULT_CACHE_SIZE = 100;
84
85
86
87
88
89 public SimpleAuthenticator()
90 {
91 super( AuthenticationLevel.SIMPLE );
92 credentialCache = new LRUMap( DEFAULT_CACHE_SIZE );
93 }
94
95
96
97
98
99
100
101
102 public SimpleAuthenticator( Dn baseDn )
103 {
104 super( AuthenticationLevel.SIMPLE, baseDn );
105 credentialCache = new LRUMap( DEFAULT_CACHE_SIZE );
106 }
107
108
109
110
111
112
113 public SimpleAuthenticator( int cacheSize )
114 {
115 super( AuthenticationLevel.SIMPLE, Dn.ROOT_DSE );
116
117 credentialCache = new LRUMap( cacheSize > 0 ? cacheSize : DEFAULT_CACHE_SIZE );
118 }
119
120
121
122
123
124
125
126
127 public SimpleAuthenticator( int cacheSize, Dn baseDn )
128 {
129 super( AuthenticationLevel.SIMPLE, baseDn );
130
131 credentialCache = new LRUMap( cacheSize > 0 ? cacheSize : DEFAULT_CACHE_SIZE );
132 }
133
134
135
136
137
138
139
140
141 private LdapPrincipal getStoredPassword( BindOperationContext bindContext ) throws LdapException
142 {
143 LdapPrincipal principal = null;
144
145
146 if ( !getDirectoryService().isPwdPolicyEnabled() )
147 {
148 synchronized ( credentialCache )
149 {
150 principal = ( LdapPrincipal ) credentialCache.get( bindContext.getDn() );
151 }
152 }
153
154 byte[][] storedPasswords;
155
156 if ( principal == null )
157 {
158
159
160 storedPasswords = lookupUserPassword( bindContext );
161
162
163
164
165
166 if ( storedPasswords == null )
167 {
168 storedPasswords = new byte[][]
169 {};
170 }
171
172
173 principal = new LdapPrincipal( getDirectoryService().getSchemaManager(), bindContext.getDn(),
174 AuthenticationLevel.SIMPLE );
175 principal.setUserPassword( storedPasswords );
176
177
178 if ( !getDirectoryService().isPwdPolicyEnabled() )
179 {
180 synchronized ( credentialCache )
181 {
182 credentialCache.put( bindContext.getDn().getNormName(), principal );
183 }
184 }
185 }
186
187 return principal;
188 }
189
190
191
192
193
194
195
196
197
198 @Override
199 public LdapPrincipal authenticate( BindOperationContext bindContext ) throws LdapException
200 {
201 if ( IS_DEBUG )
202 {
203 LOG.debug( "Authenticating {}", bindContext.getDn() );
204 }
205
206
207 byte[] credentials = bindContext.getCredentials();
208
209 LdapPrincipal principal = getStoredPassword( bindContext );
210
211 IoSession session = bindContext.getIoSession();
212
213 if ( session != null )
214 {
215 SocketAddress clientAddress = session.getRemoteAddress();
216 principal.setClientAddress( clientAddress );
217 SocketAddress serverAddress = session.getServiceAddress();
218 principal.setServerAddress( serverAddress );
219 }
220
221
222 byte[][] storedPasswords = principal.getUserPasswords();
223
224 PasswordPolicyException ppe = null;
225 try
226 {
227 checkPwdPolicy( bindContext.getEntry() );
228 }
229 catch ( PasswordPolicyException e )
230 {
231 ppe = e;
232 }
233
234
235 for ( byte[] storedPassword : storedPasswords )
236 {
237 if ( PasswordUtil.compareCredentials( credentials, storedPassword ) )
238 {
239 if ( ppe != null )
240 {
241 LOG.debug( "{} Authentication failed: {}", bindContext.getDn(), ppe.getMessage() );
242 throw ppe;
243 }
244
245 if ( IS_DEBUG )
246 {
247 LOG.debug( "{} Authenticated", bindContext.getDn() );
248 }
249
250 return principal;
251 }
252 }
253
254
255 String message = I18n.err( I18n.ERR_230, bindContext.getDn().getName() );
256 LOG.info( message );
257 throw new LdapAuthenticationException( message );
258 }
259
260
261
262
263
264
265
266
267 private byte[][] lookupUserPassword( BindOperationContext bindContext ) throws LdapException
268 {
269
270 Entry userEntry;
271
272 try
273 {
274
275
276
277
278
279
280
281
282 userEntry = bindContext.getPrincipal();
283
284 if ( userEntry == null )
285 {
286 LookupOperationContexttor/context/LookupOperationContext.html#LookupOperationContext">LookupOperationContext lookupContext = new LookupOperationContext( getDirectoryService().getAdminSession(),
287 bindContext.getDn(), SchemaConstants.ALL_USER_ATTRIBUTES, SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES );
288
289 lookupContext.setPartition( bindContext.getPartition() );
290 lookupContext.setTransaction( bindContext.getTransaction() );
291
292 userEntry = getDirectoryService().getPartitionNexus().lookup( lookupContext );
293 }
294
295 if ( userEntry == null )
296 {
297 Dn dn = bindContext.getDn();
298 String upDn = dn == null ? "" : dn.getName();
299
300 throw new LdapAuthenticationException( I18n.err( I18n.ERR_231, upDn ) );
301 }
302 }
303 catch ( Exception cause )
304 {
305 LOG.error( I18n.err( I18n.ERR_6, cause.getLocalizedMessage() ) );
306 LdapAuthenticationException e = new LdapAuthenticationException( cause.getLocalizedMessage() );
307 e.initCause( cause );
308 throw e;
309 }
310
311 DirectoryService directoryService = getDirectoryService();
312 String userPasswordAttribute = SchemaConstants.USER_PASSWORD_AT;
313
314 if ( directoryService.isPwdPolicyEnabled() )
315 {
316 AuthenticationInterceptorserver/core/authn/AuthenticationInterceptor.html#AuthenticationInterceptor">AuthenticationInterceptor authenticationInterceptor = ( AuthenticationInterceptor ) directoryService
317 .getInterceptor(
318 InterceptorEnum.AUTHENTICATION_INTERCEPTOR.getName() );
319 PasswordPolicyConfiguration pPolicyConfig = authenticationInterceptor.getPwdPolicy( userEntry );
320 userPasswordAttribute = pPolicyConfig.getPwdAttribute();
321
322 }
323
324 Attribute userPasswordAttr = userEntry.get( userPasswordAttribute );
325
326 bindContext.setEntry( new ClonedServerEntry( userEntry ) );
327
328
329 if ( userPasswordAttr == null )
330 {
331 return new byte[][]
332 {};
333 }
334 else
335 {
336 byte[][] userPasswords = new byte[userPasswordAttr.size()][];
337 int pos = 0;
338
339 for ( Value userPassword : userPasswordAttr )
340 {
341 userPasswords[pos] = userPassword.getBytes();
342 pos++;
343 }
344
345 return userPasswords;
346 }
347 }
348
349
350
351
352
353
354 @Override
355 public void invalidateCache( Dn bindDn )
356 {
357 synchronized ( credentialCache )
358 {
359 credentialCache.remove( bindDn.getNormName() );
360 }
361 }
362 }