Sun Java System Directory Server Enterprise Edition 6.1 Developer's Guide

Writing a Custom Password Quality Check Plug-In

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/ds6/examples/pwdcheck.c.

Checking Password Values

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.

Initializing the Password Check Plug-In

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.

Testing the Password Check Plug-In

You test the plug-in using sample data delivered with Directory Server You use command-line tools to setup and register the plug-in.

ProcedureTo Set Up an Example Suffix

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/ds6/ldif/Example.ldif.

  1. Create a new Directory Server instance.

    For example:


    $ dsadm create /local/ds
    Choose the Directory Manager password:
    Confirm the Directory Manager password:
    $ 
  2. Start the new Directory Server instance.

    For example:


    $ dsadm start /local/ds
    Server started: pid=4705
    $ 
  3. 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
    $ 
  4. Load the sample LDIF.

    For example, with long lines folded for the printed page:


    $ dsconf import -h localhost -p 1389 \
     /opt/SUNWdsee/ds6/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 "/opt/SUNWdsee/ds6/ldif/Example.ldif"
    ## Finished scanning file "/opt/SUNWdsee/ds6/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. For more information, see the Directory Service Control Center online help.

ProcedureTo Register the Plug-In

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.

  1. Build the plug-in.

    Hint Use install-path/examples/Makefile or install-path/examples/Makefile64.

  2. Configure Directory Server to log plug-in informational messages and load the plug-in.

    Hint Use the commands specified in the comments at the outset of the plug-in source file.

  3. Restart Directory Server.


    $ dsadm restart instance-path
    

ProcedureTo Use the Password Check Plug-In

Before You Begin

Populate the suffix dc=example,dc=com with sample data. Also, register the plug-in with Directory Server.

  1. 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
  2. Enable logging of informational messages.


    $ dsconf set-log-prop -h localhost -p 1389 error level:err-plugins
  3. 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
    
  4. 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
  5. 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.