blob: 4aab05fd48d058c878149a2fe57c16eb40b4a5bf [file] [log] [blame]
Title: 4.3. Password Policy
NavPrev: 4.2-authorization.html
NavPrevText: 4.2 - Authorization
NavUp: 4-authentication-and-authorization.html
NavUpText: 4 - Authentication & Authorization
NavNext: 5-administration.html
NavNextText: 5 - Administration
Notice: Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
.
http://www.apache.org/licenses/LICENSE-2.0
.
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
# 4.3. Password Policy
The **Password Policy for LDAP Directories** is a **[RFC](http://tools.ietf.org/html/draft-behera-ldap-password-policy-10)** draft that has been designed for the very first version in 1999, and the latest version is from 2009. Although it's still a draft, and it's currently noted as inactive, it has been implemented by many existing **LDAP** servers.
**ApacheDS** implements most of the draft.
<DIV class="warning" markdown="1">
Enforcing a strict password policy is extremely punitive to users. It may leads users to workaround the policy by storing their password in a post-it, a workaround that will defeat any password policy...
Always try to think about better alternatives than force users to always define a password with 10 or more characters, including numbers, upper and lower case, special chars, and to change it every month...
A long sentence (4 or 5 words), like "The horse has won the race three time" is most certainly a better password than any other combination, and is easy to remember...
</DIV>
## What is a password policy ?
As explained on [wikipedia](http://en.wikipedia.org/wiki/Password_policy):
:::Text
A password policy is a set of rules designed to enhance computer security by encouraging users to employ strong passwords
and use them properly.
Basically, the system, once activated, will enforce some rules and check the password strength. We will list the various options in this chapter.
There are different aspects to consider:
* The password check when it's added or modified
* The password management when the user bind, in other words, it's life cycle
* The password protection against attacks
Those aspects are exposed in the following paragraphs.
## How do we configure it ?
The _Password Policy_ can be configured in two ways.
First of all, it's important to know that it's activated by default. Let's see the default configuration first.
There is an entry containing all the default configuration values for the _Password Policy_, under the DN **"ou=passwordPolicies, ads-interceptorId=authenticationInterceptor, ou=interceptors, ads-directoryServiceId=&lt;default&gt;, ou=config"**, which corresponds to the following hierarchy:
* ou=config
* ads-directoryServiceId=<default>
* ou=interceptors
* ads-interceptorId=authenticationInterceptor
* ou=passwordPolicies
This entry contains the following values:
| Attribute | Default value | Comment |
|---|---|---|
| ads-pwdAllowUserChange | TRUE | Tells if the user can change its password |
| ads-pwdCheckQuality | 1 | The kind of quality we want for the password (0, 1, or 2) |
| ads-pwdExpireWarning | 600 | |
| ads-pwdFailureCountInterval | 30 | The duration of failure logs we keep in the entry |
| ads-pwdGraceAuthnLimit | 5 | |
| ads-pwdGraceExpire | 0 | |
| ads-pwdInHistory | 5 | The number of passwords we keep in the password history |
| ads-pwdLockout | TRUE | Tells if the password should be locked or not on failures |
| ads-pwdLockoutDuration | 0 | The delay in seconds we wait before allowing a new attempt when the password hs been locked |
| ads-pwdMaxAge | 0 | |
| ads-pwdMaxDelay | 0 | The maximum we wait before sending the BindResponse |
| ads-pwdMaxFailure | 5 | The maximum number of failure we accept before locking the password |
| ads-pwdMaxIdle | 0 | |
| ads-pwdMaxLength | 0 | |
| ads-pwdMinAge | 0 | The delay between two password changes |
| ads-pwdMinDelay | 0 | The minimum we wait before sending the BindResponse |
| ads-pwdMinLength | 5 | |
| ads-pwdMustChange | FALSE | |
| ads-pwdSafeModify | FALSE | |
Here is the entry in LDIF format:
:::Text
dn: ads-pwdId=default,ou=passwordPolicies,ads-interceptorId=authenticationIn
terceptor,ou=interceptors,ads-directoryServiceId=default,ou=config
objectclass: top
objectclass: ads-base
objectclass: ads-passwordPolicy
ads-pwdAttribute: userPassword
ads-pwdId: default
ads-enabled: TRUE
ads-pwdAllowUserChange: TRUE
ads-pwdCheckQuality: 1
ads-pwdExpireWarning: 600
ads-pwdFailureCountInterval: 30
ads-pwdGraceAuthnLimit: 5
ads-pwdGraceExpire: 0
ads-pwdInHistory: 5
ads-pwdLockout: TRUE
ads-pwdLockoutDuration: 0
ads-pwdMaxAge: 0
ads-pwdMaxDelay: 0
ads-pwdMaxFailure: 5
ads-pwdMaxIdle: 0
ads-pwdMaxLength: 0
ads-pwdMinAge: 0
ads-pwdMinDelay: 0
ads-pwdMinLength: 5
ads-pwdMustChange: FALSE
ads-pwdSafeModify: FALSE
<DIV class="warning" markdown="1">
All the configured delays are stored in seconds. As a rule of thumb, a day is 86400 seconds, a week is 604800 seconds and a month can be 2419200 seconds or 2505600 seconds (february normal and leap years), 2592000 seconds (april, june, september, november) and 2678400 (january, march, may, july, august, october and december)
</DIV>
In the draft, it is said that the passwordPolicy can apply to one user or to many. It's also suggested that some _Administrative Area_ could be used for that purpose : the users present in such an area will be constrained but the associated _PasswordPolicy_. At the moment, **ApacheDS** does not implement such a mechanism, and will rely on either the global configuration, stored in the _ou=config_ partition, or we can define a specific _Password Policy_ for a user. In this case, we will store in each user the reference to the _Password Policy_ to use into the _pwdPolicySubentry_ attribute (it contains a reference -a **DN** - to an entry storing the specific configuration).
This specific configuration is stored into an entry having the _pwdPolicy_ Auxiliary ObjectClass, which description is :
:::Text
( 1.3.6.1.4.1.42.2.27.8.2.1
NAME 'pwdPolicy'
SUP top
AUXILIARY
MUST ( pwdAttribute )
MAY ( pwdMinAge $ pwdMaxAge $ pwdInHistory $ pwdCheckQuality $
pwdMinLength $ pwdMaxLength $ pwdExpireWarning $
pwdGraceAuthNLimit $ pwdGraceExpiry $ pwdLockout $
pwdLockoutDuration $ pwdMaxFailure $ pwdFailureCountInterval $
pwdMustChange $ pwdAllowUserChange $ pwdSafeModify $
pwdMinDelay $ pwdMaxDelay $ pwdMaxIdle ) )
<DIV class="warning" markdown="1">
Note that the specification allows the administrator to apply the password policy on any attribute, with a default value of _userPassword_ ApacheDS does not yet allow the use of another Attribute.
</DIV>
#### Enabling/Disabling the PasswordPolicy
The _PasswordPolicy_ is enabled by default. It's possible to disable it by setting the _ads-enabled_ value to FALSE, with a server restart.
## Password protection
This part is exposing the various techniques the system uses to protect your password from an attack.
### Password guessing limit
The idea is to protect the password against multiple guess attempts. The following rules are applied:
* a counter tracks the failed attempts, and blocks when it's reached
* an incremental delay is added after a failure before a new attempt can be done
* a global delay for all the failed attempt is used, when reached, the account is locked
When the account is locked, it can remain locked, or be unlocked after a grace period.
#### Attempts counter
<DIV class="info" markdown="1">
Impacted Attributes: ads-pwdLockout, ads-pwdMaxFailure, ads-pwdLockoutDuration
</DIV>
Each failed attempt will be logged in the entry, in the _ads-pwdFailureTime_ Attribute (it will contain the date and time of the attempt). When the attribute contains more values than the maximum number of failed attempts, the entry will be locked (the _ads-pwdAccountLockedTime_ Attribute will contain the date and time the entry has been locked).
<DIV class="warning" markdown="1">
In order to activate this control the ads-pwdLockout parameter must be set to TRUE.
</DIV>
The following table expose the various possible cases, with three failed attempts:
| _ads-pwdmaxfailure_ | _ads-pwdLockout_ | _ads-pwdFailureTime_ | _ads-pwdAccountLockedTime_ | Locked | Comment |
|---|---|---|---|---|---|
| 3 | true | date1 | - | No | Failure 1 |
| | | date1, date2 | - | No | Failure 2 |
| | | date1, date2, date3 | date3 | Yes | Failure 3: account locked |
| 3 | false | date1 | - | No | Failure 1 |
| | | date1, date2 | - | No | Failure 2 |
| | | date1, date2, date3 | - | No | Failure 3 |
As we can see, the account is locked only when we reach the number of failure, and the _ads-pwdLockout_ flag is TRUE. If the _ads-pwdLockoutDuration_ flag is set, then the password will remain locked for the delay stored in this attribute.
#### Delayed login
<DIV class="info" markdown="1">
Impacted Attributes: ads-pwdLockout, ads-pwdMaxFailure, ads-pwdLockoutDuration
</DIV>
When we have reached a number of failed attempt, the account will be locked. We can set another attribute to tell the server that the locked out account can be unlocked after a delay: the _ads-pwdLockoutDuration_ Attribute stores this delay.
When the account is locked, no further attempt will succeed, even if the correct password is sent. After the delay, the user will be unlocked.
#### Purging failures
<DIV class="info" markdown="1">
Impacted Attributes: ads-pwdFailureCountInterval
</DIV>
As we store all the failures within the entry, at some point we may want to purge those failures. This is done either because we have successfully logged, or because the _ads-pwdFailureCountInterval_ value has expired. In this last case, all the failures older than the current time minus the set interval will be removed.
### Password checks and strength enforcement
Those rules are used to enforce some constraints on the password, so that weak passwords can't be used.
#### Quality Check policy
<DIV class="info" markdown="1">
Impacted Attributes: ads-pwdQualityCheck<br>
Default value: 1
</DIV>
The system can be enabled or disabled, and when enabled, two different level of checks can be done: relaxed or strict.
We use a parameter to specify the kind of check we do on the password: _ads-pwdCheckQuality_, which can take three values:
* 0: The password is not checked
* 1: We check the password when we can, i.e. when it's not hashed. When the password is hashed, or in a form that does not allow us to apply the checks, then we ignore the errors
* 2: The password is checked, and if it's hashed or in a form that does not allow the checks to be done, then the changes are rejected.
#### Password History
<DIV class="info" markdown="1">
Impacted Attributes: ads-pwdInHistory
</DIV>
The server can keep a backlog of passwords, so that a user can't keep a password for ever. When requested to do so the user will have to change his/her password, and the old password will be stored in the user's entry password history.
We can specify the number of passwords we keep in the password history by configuring the _ads-pwdInHistory_ attribute.
#### Minimum delay between modifications
<DIV class="info" markdown="1">
Impacted Attributes: ads-pwdMinAge
</DIV>
When the password history is activated, some users may change their passwords many times to get their old password out of the history, and add it as their password again. Setting a delay between two password changes may protect the password against such action.
The _ads-pwdMinAge_ attribute is used for this purpose, and it keeps a value in seconds.
#### Password length constraint
<DIV class="info" markdown="1">
Impacted Attributes: ads-pwdMinLength and ads-pwdMaxLength
</DIV>
You can control the minimum and maximum length for a password by setting the _ads-pwdMinLength_ and _ads-pwdMaxLength_ attributes.
<DIV class="warning" markdown="1">
Setting a password max length is most certainly a waste of time. It's very likely that this parameter has been added to the specification for the sake of symetry...
</DIV>
### Password lifecycle management
We now have to expose the rules that apply to the password during it's life.
#### Password max age
<DIV class="info" markdown="1">
Impacted Attribute: ads-pwdMaxAge
</DIV>
A password may have a limited life expectation, and when this age is reached, the password will be invalidated. This is configured through the _ads-pwdMaxAge_ parameter, which contains the number of second a password will last.
This password invalidation can be overruled by the two next parameters.
<DIV class="warning" markdown="1">
This parameter works hands in hands with some other parameter, like the ads-pwdGraceAuthNLimit and ads-GraceExpire. If those parameters are set too, you may get some different delay for your password expiration.
</DIV>
#### Password grace auth N limit
<DIV class="info" markdown="1">
Impacted Attribute: ads-pwdGraceAuthNLimit
</DIV>
When the password has expired, this parameter (_ads-pwdGraceAuthNLimit_) tells how many times a user will still be allowed to bind before the password is definitively locked. Each attempt will decrement the associated counter.
#### Password grace Expire
<DIV class="info" markdown="1">
Impacted Attribute: ads-pwdGraceExpire
</DIV>
Another option when the password has expired is to give the user the possibility to log in during a certain period of time. This is mainly useful when the _ads-pwdGraceAuthNLimit_ is set: not only there is a limited number of attempts, but those attempts must be done in a limited period of time, ortherwise the password will be locked.
If the configuration of the _ads-pwdGraceAuthNLimit_ is 0, the _ads-pwdGraceExpire_ value is simply added to the _ads-pwdMaxAge_ value.
#### Idle Password
<DIV class="info" markdown="1">
Impacted Attribute: ads-pwdMaxIdle
</DIV>
You can set a maximum inactivity delay for a password, before this password expires. This is set using the _ads-pwdMaxIdle_ parameter
#### Expiration warning
<DIV class="info" markdown="1">
Impacted Attribute: ads-pwdExpireWarning
</DIV>
The _ads-pwdExpireWarning_ parameter will be used to send back a warning if the password if the password is going to expire in a given delay. This is convenient as soon as the client sends the _PasswordPolicy_ control to the server, and as soon as the client reads the response's control.
#### Allow user changes
<DIV class="info" markdown="1">
Impacted Attribute: ads-pwdAllowUserChange
</DIV>
The _ads-pwdAllowUserChange_ parameter can be used to allow - or forbid - a user to change his/her own password. When this parameter is set to _TRUE_, the user can't change his/her password.
### Not supported parameters
A few parameters are described in the specification, but aren't supported. Here is the list :
* ads-pwdMinDelay : The minimal delay the server waits before sending back a response.
* ads-pwdMaxDelay : The maximal delay the server waits before sending back a response.