Oracle® Fusion Middleware Developer's Guide for Oracle Directory Server Enterprise Edition 11g Release 1 (11.1.1.7.0) Part Number E28970-01 |
|
|
PDF · Mobi · ePub |
Directory Server is delivered with a configurable password quality check plug-in. The plug-in allows you to guard against users who change their password to a value that is susceptible to typical English-language dictionary attacks. You might decide however to extend password quality checking further. This chapter shows how to write custom plug-ins that check password quality when the password is modified.
This chapter covers the following topics:
This section explains how Directory Server password policy configurations affect password quality checks. This section also explains what Directory Server expects your password quality check plug-in to do.
One aspect of password policy involves refusing passwords that do not meet your quality criteria. When a user submits a password value, that value is to be stored on her entry in the userPassword attribute. You might want the server to ensure the password value is not easy to guess or to discover. You might also want the server to log a warning when a weak password is accepted, or even to refuse weak passwords. Determining what you want is part of setting up a password policy.
The password policy entry attribute that governs to what extent the server checks password quality is pwdCheckQuality. When this attribute is set to cause the server to check password quality, the server can call plug-ins to do so. This chapter shows how to write a plug-in that checks password quality.
For a more extensive explanation of password policy configuration, see Chapter 7, Directory Server Password Policy, in Administrator's Guide for Oracle Directory Server Enterprise Edition.
If you can achieve your password policy requirements by using the strong password check plug-in provided with Directory Server, do not write your own plug-in.
The strong password check plug-in provided with Directory Server can be configured for your deployment, checking the password quality aspects that you consider essential. You can configure the following:
The number of lowercase, uppercase, numeric, and special characters required in a password value
A special configuration setting also allows you to enforce a mix of characters.
The absence of prohibited strings, read from a dictionary file
You can use the default English-language file that is provided. Alternatively, you can add or substitute your own file.
These configuration settings are in addition to other checks. Such checks govern password length, whether the password matches common attributes on the entry, and so forth.
In many cases, you can avoid writing your own password check plug-in.
If you decide to implement your own password check plug-in, it must be of type passwordcheck
. Your plug-in must implement at least the password checking function, SLAPI_PLUGIN_PASSWDCHECK_FN
. This function verifies that all passwords supplied in the parameter block array, SLAPI_PASSWDCHECK_VALS
, satisfy the quality check. The SLAPI_PASSWDCHECK_VALS
may contain more than one password value.
The function must return the following values, depending on the password values to check.
-1
Return this value when you must send a failure result to the client application for a reason other than quality check failure. You might return this value for example when the server is busy loading a large dictionary file. The server then would not be ready to check password quality.
When you return this value, the server aborts the add or modify operation in progress.
0
Return this value when all passwords in SLAPI_PASSWDCHECK_VALS
satisfy the password quality check.
>0
Return a positive integer when at least one of the passwords in SLAPI_PASSWDCHECK_VALS
fails the password quality check.
When you return a positive integer, pass an error message back through SLAPI_RESULT_TEXT
in the parameter block with slapi_pblock_set ()
. Allocate space for the message using slapi_ch_malloc()
. The server takes responsibility to free the memory allocated for the message.
The message string must start with invalid password syntax:
, exactly as it is given here.
The server sends the client application a result of LDAP_CONSTRAINT_VIOLATION
, 19. If, however, passwordRootdnMayBypassModsChecks is set to allow password administrators, including the directory root DN user, to modify passwords irrespective of password policy checks, the server nevertheless accepts modifications by that user.
In the simple case used in this chapter, the work is minimal. For real—world cases, the work might however be significant, particularly if you choose to implement your own dictionary check. If you implement your own dictionary check, the plug-in might cache the dictionary content from a large file. In this case, load the dictionary as part of a plug-in start function rather than part of plug-in initialization. You thus avoid blocking startup of the server while the cache is constructed.
This section demonstrates how to write a plug-in that performs a simple password quality check.
Only code excerpts are shown in this chapter. The complete code example can be found where you installed Directory Server, install-path
/examples/pwdcheck.c
.
When Directory Server receives a request to add or modify a userPassword
value, the server calls the registered passwordcheck
plug-in. The server passes one or more values as a set of Slapi_Value
structures in the parameter block. You can retrieve these values with slapi_pblock_get ()
.
#include "slapi-plugin.h" static int check_pwd(Slapi_PBlock * pb) { Slapi_Value ** pwdvals = NULL; slapi_pblock_get(pb, SLAPI_PASSWDCHECK_VALS, &pwdvals;); }
Your code must then return zero, 0
, when password values are acceptable. Your code must return nonzero when password values are unacceptable. In the simple case where bad password values are only those equal to secret12
, the code is a quick strcmp
.
#include "slapi-plugin.h" /* Reject password values equal to secret12. */ static int check_pwd(Slapi_PBlock * pb) { Slapi_Value ** pwdvals = NULL; … /* Do not check values if none exist. */ if (pwdvals == NULL) return 0; for (i=0 ; pwdvals[i] != NULL; i++) { const char * password = slapi_value_get_string(pwdvals[i]); if (strcmp("secret12", password) == 0) { slapi_pblock_set(pb, SLAPI_RESULT_TEXT, slapi_ch_strdup("invalid password syntax: Bad password!")); return 1; } } return 0; }
Here, the code has Directory Server reject a password only when its value is secret12
.
Password check plug-ins register a password checking function, SLAPI_PLUGIN_PASSWDCHECK_FN
, during initialization with the server.
#include "slapi-plugin.h" int pwdcheck_init(Slapi_PBlock * pb) { int rc = 0; rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_CURRENT_VERSION ); rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *) &pwd_desc; /* See the code for pwd_desc. */ ); rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_PASSWDCHECK_FN, (void *) check_pwd ); return rc; }
You can implement your own dictionary check that caches the dictionary content from a large file. In this case, load the dictionary as part of a plug-in start function rather than part of plug-in initialization. Thus, you avoid blocking startup of the server while the cache is constructed.
You test the plug-in using sample data delivered with Directory Server You use command-line tools to setup and register the plug-in.
If you have not done so already, set up a directory instance with a suffix, dc=example,dc=com
, containing data loaded from a sample LDIF file, install-path
/resources/ldif/Example.ldif
.
Create a new Directory Server instance.
For example:
$ dsadm create -h localhost -p 1389 /local/ds Choose the Directory Manager password: Confirm the Directory Manager password: $
Start the new Directory Server instance.
For example:
$ dsadm start /local/ds Server started: pid=4705 $
Create a suffix called dc=example,dc=com
.
For example, with long lines folded for the printed page:
$ dsconf create-suffix -h localhost -p 1389 dc=example,dc=com Enter "cn=directory manager" password: Certificate "CN=defaultCert, CN=hostname:1636" presented by the server is not trusted. Type "Y" to accept, "y" to accept just once, "n" to refuse, "d" for more details: Y $
Load the sample LDIF.
For example, with long lines folded for the printed page:
$ dsconf import -h localhost -p 1389 \ install-path/resources/ldif/Example.ldif dc=example,dc=com Enter "cn=directory manager" password: New data will override existing data of the suffix "dc=example,dc=com". Initialization will have to be performed on replicated suffixes. Do you want to continue [y/n] ? y ## Index buffering enabled with bucket size 16 ## Beginning import job... ## Processing file "install-path/resources/ldif/Example.ldif" ## Finished scanning file "install-path/resources/ldif/Example.ldif" (160 entries) ## Workers finished; cleaning up... ## Workers cleaned up. ## Cleaning up producer thread... ## Indexing complete. ## Starting numsubordinates attribute generation. This may take a while, please wait for further activity reports. ## Numsubordinates attribute generation complete. Flushing caches... ## Closing files... ## Import complete. Processed 160 entries in 5 seconds. (32.00 entries/sec) Task completed (slapd exit code: 0). $
See Also
You can use Directory Service Control Center to perform this task.
If you have not already done so, build the example plug-in library and activate both plug-in informational logging and the example plug-in.
Build the plug-in.
Hint Use install-path
/examples/Makefile
or install-path
/examples/Makefile64
.
Configure Directory Server to log plug-in informational messages and load the plug-in.
$ dsconf create-plugin -F custom-plugin-init-function -G custom-plugin-argument -H lib-path \
-Y custom-plugin-type "Custom Plugin"
$ dsconf enable-plugin "Custom Plugin"
Hint For more information, use the commands specified in the plug-in source file.
Restart Directory Server.
$ dsadm restart instance-path
Before You Begin
Populate the suffix dc=example,dc=com
with sample data. Also, register the plug-in with Directory Server.
Enforce password quality checking so Directory Server calls your password check plug-in.
$ dsconf set-server-prop -h localhost -p 1389 \ pwd-check-enabled:on pwd-strong-check-enabled:off
Enable logging of informational messages.
$ dsconf set-log-prop -h localhost -p 1389 error level:err-plugins
Prepare an entry that tests your password quality check.
$ cat quentin.ldif
dn: uid=qcubbins,ou=People,dc=example,dc=com
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
uid: qcubbins
givenName: Quentin
sn: Cubbins
cn: Quentin Cubbins
mail: quentin.cubbins@example.com
userPassword: secret12
Add the entry to the directory.
$ ldapmodify -a -D uid=kvaughan,ou=people,dc=example,dc=com \ -w bribery -h localhost -p 1389 -f quentin.ldif adding new entry uid=qcubbins,ou=People,dc=example,dc=com ldap_add_s: Constraint violation
Check the errors
log for further information.
$ grep secret12 /local/ds/logs/errors [16/Feb/2006:18:13:06 +0100] - INFORMATION - Sample password check plug-in - conn=0 op=1 msgId=2 - Invalid password: secret12
The example log message as shown has been wrapped for readability in the printed version of this document.