Sun Java logo     Previous      Contents      Index      Next     

Sun logo
Sun Java(TM) System Directory Server 5 2004Q2 Plug-In Developer's Guide 

Chapter 8
Writing Entry Store and Entry Fetch Plug-Ins

This chapter covers how to write plug-ins that modify how Directory Server operates when writing entries to and reading entries from the directory database.

This chapter includes the following sections:


Calling Entry Store and Entry Fetch Plug-Ins

This section describes when entry store and entry fetch plug-ins are called and how entries are expected to be handled by the plug-in.

The server calls entry store plug-in functions before writing data to a directory database. It calls entry fetch plug-in functions after reading data from the directory database. Entry store and entry fetch plug-ins may therefore typically be used to encrypt and decrypt directory entries, or to perform auditing work.

An LDIF String, Not a Parameter Block

Unlike other types of plug-ins, entry store and entry fetch plug-in functions do not take a parameter block as an argument. Instead, they take two parameters, the LDIF string representation of an entry and the length of the string. Directory Server uses the modified LDIF string after the plug-in returns successfully. An example prototype for an entry store plug-in function:

int my_entrystore_fn(char ** entry, unsigned int * length);

Plug-in functions may manipulate the string as necessary. Entry store and entry fetch plug-ins return 0 on success. When the function returns, Directory Server expects entry and length to contain the modified versions of the parameters.


Writing a Plug-In to Encrypt Entries

This section demonstrates how to write a plug-in that scrambles directory entries written to the directory database and de-scrambles directory entries read from the directory database.


Caution

The example does not constitute a secure entry storage scheme.


Code Example 8-1 demonstrates how entry store and entry fetch plug-ins are registered with Directory Server.

Code Example 8-1  Registering Entry Store and Entry Fetch Plug-Ins (testentry.c

#include "slapi-plugin.h"

Slapi_PluginDesc entrypdesc = {

    "test-entry",                      /* plug-in identifier      */

    "Sun Microsystems, Inc.",          /* vendor name             */

    "5.2",                             /* plug-in revision number */

    "Sample entry store/fetch plug-in" /* plug-in description     */

};

int

testentry_init(Slapi_PBlock *pb)

{

    int rc = 0;                        /* 0 means success         */

    rc |= slapi_pblock_set(            /* Plug-in API version     */

        pb,

        SLAPI_PLUGIN_VERSION,

        SLAPI_PLUGIN_CURRENT_VERSION

    );

    rc |= slapi_pblock_set(            /* Plug-in description     */

        pb,

        SLAPI_PLUGIN_DESCRIPTION,

        (void *) &entrypdesc

    );

    rc |= slapi_pblock_set(            /* Entry store function    */

        pb,

        SLAPI_PLUGIN_ENTRY_STORE_FUNC,  

        (void *) testentry_scramble

    );

    rc |= slapi_pblock_set(            /* Entry fetch function    */

        pb,

        SLAPI_PLUGIN_ENTRY_FETCH_FUNC,  

        (void *) testentry_unscramble

    );

    return rc;

}

Finding the Examples

This chapter refers to the plug-in function examples in ServerRoot/plugins/slapd/slapi/examples/testentry.c.

Code Example 8-2 shows the entry store scrambling function used in this chapter, and called by Directory Server before writing an entry to the database.

Code Example 8-2  Entry Fetch Scrambler (testentry.c

#include "slapi-plugin.h"

#ifdef _WIN32

typedef unsigned int uint;

#endif

#ifdef _WIN32

__declspec(dllexport)

#endif

int

testentry_scramble(char ** entry, uint * len)

{

    uint i;

    /* Scramble using bitwise exclusive-or on each character.     */

    for (i = 0; i < *len - 1; i++) { (*entry)[i] ^= 0xaa; }

    

    slapi_log_info_ex(

        SLAPI_LOG_INFO_AREA_PLUGIN,

        SLAPI_LOG_INFO_LEVEL_DEFAULT,

        SLAPI_LOG_NO_MSGID,

        SLAPI_LOG_NO_CONNID,

        SLAPI_LOG_NO_OPID,

        "testentry_scramble in test-entry plug-in",

        "Entry data scrambled.\n"

    );

    return 0;

}

Code Example 8-3 shows the entry fetch de-scrambling function used in this chapter, and called by the server after reading an entry from the database.

Code Example 8-3  Entry Fetch De-Scrambler (testentry.c

#include "slapi-plugin.h"

#ifdef _WIN32

typedef unsigned int uint;

#endif

#ifdef _WIN32

__declspec(dllexport)

#endif

int

testentry_unscramble(char ** entry, uint * len)

{

    uint i;

    /* Return now if the entry is not scrambled.                  */

    if (!strncmp(*entry, "dn:", 3)) { return 0; }

    

    /* Unscramble using bitwise exclusive-or on each character.   */

    for (i = 0; i < *len - 1; i++) { (*entry)[i] ^= 0xaa; }

    

    slapi_log_info_ex(

        SLAPI_LOG_INFO_AREA_PLUGIN,

        SLAPI_LOG_INFO_LEVEL_DEFAULT,

        SLAPI_LOG_NO_MSGID,

        SLAPI_LOG_NO_CONNID,

        SLAPI_LOG_NO_OPID,

        "testentry_unscramble in test-entry plug-in",

        "Entry data unscrambled.\n"

    );

    return 0;

}

Notice the symmetry between the two functions. The scrambling mask, 0xaa or 10101010 in binary, makes the transformation simple to understand but not secure. A secure encryption mechanism may be significantly more complicated.

Trying It Out

We demonstrate the plug-in by showing the difference between scrambled and unscrambled data in the database itself. We therefore do not enable the plug-in immediately, but instead add an entry to a new directory suffix before scrambling and observe the results in the database on disk. Then we remove the entry, enable the scrambling plug-in, add the same entry again, and finally observe the results after the entry has been scrambled.

Setting Up an Example Suffix

If you have not done so already, prepare some data by creating a directory suffix, dc=example,dc=com, whose users we load from an LDIF file, ServerRoot/slapd-serverID/ldif/Example-Plugin.ldif. Refer to Setting Up an Example Suffix for instructions.

Looking for Strings in the Database Before Scrambling

Here, we add an entry for Quentin Cubbins to our example suffix before registering the entry store-fetch plug-in with Directory Server. We see that Quentin’s mail address is visible in the database holding mail address attribute values. Quentin’s entry, quentin.ldif, appears as shown in Code Example 8-4.

Code Example 8-4  LDIF Representation of Quentin’s Entry 

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: qcubbins@example.com

userPassword: qcubbins

secretary: uid=bcubbins,ou=People,dc=example,dc=com

Add Quentin’s entry to the directory. For example, if the entry is in quentin.ldif:

$ ldapmodify -a -p port -h host -D "cn=Directory Manager" -w password -f quentin.ldif

Now look for strings in the directory database file for the mail attribute values.

Code Example 8-5  Attribute Values in a Database File Before Scrambling 

$ cd ServerRoot/slapd-serverID/db/example/

$ strings example_mail.db3 | grep example.com

=qcubbins@example.com

=agodiva@example.com

=hfuddnud@example.com

=pblinn@example.com

=scooper@example.com

=bcubbins@example.com

=yyorgens@example.com

Notice that Quentin’s mail address is clearly visible to a user who manages to gain access to the database files. If this were not a mail address, but instead a credit card number, we could have a possible security issue.

Looking for Strings in the Database After Scrambling

Here, we add an entry for Quentin Cubbins to our example suffix after registering the entry store-fetch plug-in with Directory Server. We see that Quentin’s mail address is no longer visible in the database holding mail address attribute values.

Before loading the plug-in, delete Quentin’s entry. For example:

$ ldapdelete -p port -h host -D "cn=Directory Manager" -w password \
"uid=qcubbins,ou=People,dc=example,dc=com"

Next, load the plug-in configuration entry into the directory, and then restart the server. To load the configuration entry, first save it to a file, testentry.ldif. Code Example 8-6 shows the configuration entry.

Code Example 8-6  Configuration Entry (testentry.c

dn: cn=Test entry,cn=plugins,cn=config

objectClass: top

objectClass: nsSlapdPlugin

objectClass: extensibleObject

cn: Test entry

nsslapd-pluginPath: ServerRoot/plugins/slapd/slapi/examples/LibName

nsslapd-pluginInitfunc: testentry_init

nsslapd-pluginType: ldbmentryfetchstore

nsslapd-pluginEnabled: on

nsslapd-plugin-depends-on-type: database

nsslapd-pluginId: test-entry

nsslapd-pluginVersion: 5.2

nsslapd-pluginVendor: Sun Microsystems, Inc.

nsslapd-pluginDescription: Sample entry store/fetch plug-in

After editing ServerRoot to correspond to your system and saving testentry.ldif, modify the directory configuration to include the entry:

$ ldapmodify -a -p port -h host -D "cn=Directory Manager" -w password \
-f testentry.ldif

Restart Directory Server for the modification to take effect. For example:

$ ServerRoot/slapd-serverID/start-slapd

With the entry store-fetch plug-in active, add Quentin’s entry back into the directory:

$ ldapmodify -a -p port -h host -D "cn=Directory Manager" -w password \
-f quentin.ldif

Now search again for strings in the directory database file for the mail attribute values.

Code Example 8-7  Attribute Values in a Database File After Scrambling 

$ cd ServerRoot/slapd-serverID/db/example/

$ strings example_mail.db3 | grep example.com

=agodiva@example.com

=hfuddnud@example.com

=pblinn@example.com

=scooper@example.com

=bcubbins@example.com

=yyorgens@example.com

Notice that Quentin’s mail address value is now not visible in the directory database. Directory users having appropriate access rights (anonymous in this simple example case) can still view the attribute during a search. The attribute and its value are emphasized in Code Example 8-8.

Code Example 8-8  De-Scrambled Search Results 

$ ldapsearch -L -p port -h host -b "dc=example,dc=com" "(uid=qcubbins)"

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: qcubbins@example.com

secretary: uid=bcubbins,ou=People,dc=example,dc=com

In this way, we see that entry fetch-store plug-ins affect only the way entries are stored, and not the directory frontend.



Previous      Contents      Index      Next     


Copyright 2004 Sun Microsystems, Inc. All rights reserved.