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 static org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicyErrorEnum.ACCOUNT_LOCKED;
24 import static org.apache.directory.api.ldap.extras.controls.ppolicy.PasswordPolicyErrorEnum.PASSWORD_EXPIRED;
25 import static org.apache.directory.api.ldap.model.constants.PasswordPolicySchemaConstants.PWD_ACCOUNT_LOCKED_TIME_AT;
26 import static org.apache.directory.api.ldap.model.constants.PasswordPolicySchemaConstants.PWD_CHANGED_TIME_AT;
27 import static org.apache.directory.api.ldap.model.constants.PasswordPolicySchemaConstants.PWD_END_TIME_AT;
28 import static org.apache.directory.api.ldap.model.constants.PasswordPolicySchemaConstants.PWD_GRACE_USE_TIME_AT;
29 import static org.apache.directory.api.ldap.model.constants.PasswordPolicySchemaConstants.PWD_LAST_SUCCESS_AT;
30 import static org.apache.directory.api.ldap.model.constants.PasswordPolicySchemaConstants.PWD_START_TIME_AT;
31
32 import java.io.IOException;
33 import java.util.Collections;
34 import java.util.Date;
35
36 import org.apache.directory.api.ldap.model.constants.AuthenticationLevel;
37 import org.apache.directory.api.ldap.model.entry.Attribute;
38 import org.apache.directory.api.ldap.model.entry.DefaultModification;
39 import org.apache.directory.api.ldap.model.entry.Entry;
40 import org.apache.directory.api.ldap.model.entry.Modification;
41 import org.apache.directory.api.ldap.model.entry.ModificationOperation;
42 import org.apache.directory.api.ldap.model.exception.LdapException;
43 import org.apache.directory.api.ldap.model.exception.LdapOtherException;
44 import org.apache.directory.api.ldap.model.name.Dn;
45 import org.apache.directory.api.ldap.model.password.PasswordUtil;
46 import org.apache.directory.api.util.DateUtils;
47 import org.apache.directory.server.core.api.DirectoryService;
48 import org.apache.directory.server.core.api.InterceptorEnum;
49 import org.apache.directory.server.core.api.authn.ppolicy.PasswordPolicyConfiguration;
50 import org.apache.directory.server.core.api.authn.ppolicy.PasswordPolicyException;
51 import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
52 import org.apache.directory.server.core.api.partition.Partition;
53 import org.apache.directory.server.core.api.partition.PartitionTxn;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
56
57
58
59
60
61
62
63 public abstract class AbstractAuthenticator implements Authenticator
64 {
65
66 protected static final Logger LOG = LoggerFactory.getLogger( AbstractAuthenticator.class );
67
68
69 private DirectoryService directoryService;
70
71
72 private final AuthenticationLevel authenticatorType;
73
74
75 private Dn baseDn;
76
77
78
79
80
81
82
83 protected AbstractAuthenticator( AuthenticationLevel type )
84 {
85 this.authenticatorType = type;
86 this.baseDn = Dn.ROOT_DSE;
87 }
88
89
90
91
92
93
94
95
96 protected AbstractAuthenticator( AuthenticationLevel type, Dn baseDn )
97 {
98 this.authenticatorType = type;
99 this.baseDn = baseDn;
100 }
101
102
103
104
105
106
107 public DirectoryService getDirectoryService()
108 {
109 return directoryService;
110 }
111
112
113
114
115
116 @Override
117 public AuthenticationLevel getAuthenticatorType()
118 {
119 return authenticatorType;
120 }
121
122
123
124
125
126
127
128
129 @Override
130 public final void init( DirectoryService directoryService ) throws LdapException
131 {
132 this.directoryService = directoryService;
133 doInit();
134 }
135
136
137
138
139
140 protected void doInit()
141 {
142 }
143
144
145
146
147
148
149
150 @Override
151 public final void destroy()
152 {
153 try
154 {
155 doDestroy();
156 }
157 finally
158 {
159 this.directoryService = null;
160 }
161 }
162
163
164
165
166
167 protected void doDestroy()
168 {
169 }
170
171
172
173
174
175 @Override
176 public void invalidateCache( Dn bindDn )
177 {
178 }
179
180
181
182
183
184 @Override
185 public boolean isValid( Dn bindDn )
186 {
187
188 return ( baseDn == null ) || ( baseDn.isAncestorOf( bindDn ) );
189 }
190
191
192
193
194
195 @Override
196 public Dn getBaseDn()
197 {
198 return baseDn;
199 }
200
201
202
203
204
205 @Override
206 public void setBaseDn( Dn baseDn )
207 {
208 this.baseDn = baseDn;
209 }
210
211
212 private void internalModify( ModifyOperationContext modContext ) throws LdapException
213 {
214 Partition partition = directoryService.getPartitionNexus().getPartition( modContext.getDn() );
215 modContext.setPartition( partition );
216 PartitionTxn partitionTxn = null;
217
218 try
219 {
220 partitionTxn = partition.beginWriteTransaction();
221 modContext.setTransaction( partitionTxn );
222
223 directoryService.getPartitionNexus().modify( modContext );
224
225 partitionTxn.commit();
226 }
227 catch ( LdapException le )
228 {
229 try
230 {
231 if ( partitionTxn != null )
232 {
233 partitionTxn.abort();
234 }
235
236 throw le;
237 }
238 catch ( IOException ioe )
239 {
240 throw new LdapOtherException( ioe.getMessage(), ioe );
241 }
242 }
243 catch ( IOException ioe )
244 {
245 try
246 {
247 partitionTxn.abort();
248
249 throw new LdapOtherException( ioe.getMessage(), ioe );
250 }
251 catch ( IOException ioe2 )
252 {
253 throw new LdapOtherException( ioe2.getMessage(), ioe2 );
254 }
255 }
256 }
257
258
259
260
261
262 @Override
263 public void checkPwdPolicy( Entry userEntry ) throws LdapException
264 {
265 if ( !directoryService.isPwdPolicyEnabled() )
266 {
267 return;
268 }
269
270 AuthenticationInterceptorserver/core/authn/AuthenticationInterceptor.html#AuthenticationInterceptor">AuthenticationInterceptor authenticationInterceptor = ( AuthenticationInterceptor ) directoryService
271 .getInterceptor(
272 InterceptorEnum.AUTHENTICATION_INTERCEPTOR.getName() );
273 PasswordPolicyConfiguration pPolicyConfig = authenticationInterceptor.getPwdPolicy( userEntry );
274
275
276 if ( pPolicyConfig.isPwdLockout() )
277 {
278 LOG.debug( "checking if account with the Dn {} is locked", userEntry.getDn() );
279
280 Attribute accountLockAttr = userEntry.get( PWD_ACCOUNT_LOCKED_TIME_AT );
281
282 if ( accountLockAttr != null )
283 {
284 String lockedTime = accountLockAttr.getString();
285
286 if ( "000001010000Z".equals( lockedTime ) )
287 {
288 throw new PasswordPolicyException( "account was permanently locked", ACCOUNT_LOCKED.getValue() );
289 }
290 else
291 {
292 Date lockedDate = DateUtils.getDate( lockedTime );
293 long unlockTime = pPolicyConfig.getPwdLockoutDuration() * 1000L;
294 unlockTime += lockedDate.getTime();
295
296 Date unlockDate = new Date( unlockTime );
297 Date now = new Date( directoryService.getTimeProvider().currentIimeMillis() );
298
299 if ( unlockDate.after( now ) )
300 {
301 throw new PasswordPolicyException( "account will remain locked till " + unlockDate,
302 ACCOUNT_LOCKED.getValue() );
303 }
304 else
305 {
306
307 Modification pwdAccountLockMod = new DefaultModification(
308 ModificationOperation.REMOVE_ATTRIBUTE, accountLockAttr );
309 ModifyOperationContextceptor/context/ModifyOperationContext.html#ModifyOperationContext">ModifyOperationContext modContext = new ModifyOperationContext(
310 directoryService.getAdminSession() );
311 modContext.setDn( userEntry.getDn() );
312 modContext.setModItems( Collections.singletonList( pwdAccountLockMod ) );
313
314 internalModify( modContext );
315 }
316 }
317 }
318 }
319
320 Attribute pwdStartTimeAttr = userEntry.get( PWD_START_TIME_AT );
321
322 if ( pwdStartTimeAttr != null )
323 {
324 Date pwdStartTime = DateUtils.getDate( pwdStartTimeAttr.getString() );
325
326 if ( System.currentTimeMillis() < pwdStartTime.getTime() )
327 {
328 throw new PasswordPolicyException( "account is locked, will be activated after " + pwdStartTime,
329 ACCOUNT_LOCKED.getValue() );
330 }
331 }
332
333 Attribute pwdEndTimeAttr = userEntry.get( PWD_END_TIME_AT );
334
335 if ( pwdEndTimeAttr != null )
336 {
337 Date pwdEndTime = DateUtils.getDate( pwdEndTimeAttr.getString() );
338
339 if ( System.currentTimeMillis() >= pwdEndTime.getTime() )
340 {
341 throw new PasswordPolicyException(
342 "password end time reached, will be locked till administrator activates it",
343 ACCOUNT_LOCKED.getValue() );
344 }
345 }
346
347 if ( pPolicyConfig.getPwdMaxIdle() > 0 )
348 {
349 Attribute pwdLastSuccessTimeAttr = userEntry.get( PWD_LAST_SUCCESS_AT );
350
351
352 if ( pwdLastSuccessTimeAttr != null )
353 {
354 long time = pPolicyConfig.getPwdMaxIdle() * 1000L;
355 time += DateUtils.getDate( pwdLastSuccessTimeAttr.getString() ).getTime();
356
357 if ( directoryService.getTimeProvider().currentIimeMillis() >= time )
358 {
359 throw new PasswordPolicyException(
360 "account locked due to the max idle time of the password was exceeded",
361 ACCOUNT_LOCKED.getValue() );
362 }
363 }
364 }
365
366
367 if ( pPolicyConfig.getPwdMaxAge() > 0 )
368 {
369
370 if ( pPolicyConfig.getPwdGraceAuthNLimit() > 0 )
371 {
372 Attribute pwdGraceUseAttr = userEntry.get( PWD_GRACE_USE_TIME_AT );
373
374
375 if ( ( pwdGraceUseAttr != null ) && ( pwdGraceUseAttr.size() >= pPolicyConfig.getPwdGraceAuthNLimit() ) )
376 {
377 throw new PasswordPolicyException( "password expired and max grace logins were used",
378 PASSWORD_EXPIRED.getValue() );
379 }
380 }
381 else
382 {
383
384 Attribute pwdChangeTimeAttr = userEntry.get( PWD_CHANGED_TIME_AT );
385
386
387 if ( pwdChangeTimeAttr != null )
388 {
389 boolean expired = PasswordUtil.isPwdExpired( pwdChangeTimeAttr.getString(),
390 pPolicyConfig.getPwdMaxAge(), directoryService.getTimeProvider() );
391
392 if ( expired )
393 {
394 throw new PasswordPolicyException( "password expired", PASSWORD_EXPIRED.getValue() );
395 }
396 }
397 }
398 }
399 }
400 }