Skip Navigation Links | |
Exit Print View | |
Oracle Directory Server Enterprise Edition Developer's Guide 11 g Release 1 (11.1.1.5.0) |
Part I Directory Server Plug-In API Guide
1. Before You Start Writing Plug-Ins
2. Changes to the Plug-In API Since Directory Server 5.2
3. Getting Started With Directory Server Plug-Ins
4. Working With Entries Using Plug-Ins
5. Extending Client Request Handling Using Plug-Ins
6. Handling Authentication Using Plug-Ins
7. Performing Internal Operations With Plug-Ins
8. Writing Entry Store and Entry Fetch Plug-Ins
9. Writing Extended Operation Plug-Ins
10. Writing Matching Rule Plug-Ins
11. Writing Password Storage Scheme Plug-Ins
Calling Password Storage Scheme Plug-Ins
Types of Password Storage Scheme Plug-Ins
Effect on Password Attribute Values
Invocation for Add and Modify Requests
Writing a Password Storage Scheme Plug-In
Registering the Password Storage Scheme Plug-In
Setting Up the Password Storage Scheme Plug-In
12. Writing Password Quality Check Plug-Ins
13. Writing Computed Attribute Plug-Ins
Part II Directory Server Plug-In API Reference
14. Data Type and Structure Reference
15. Function Reference, Part I
16. Function Reference, Part II
This section demonstrates how to write a plug-in that encodes passwords. The plug-in also allows Directory Server to compare stored passwords with passwords provided by a client application.
Caution - The examples in this chapter do not constitute a secure password storage scheme. |
The source for the example plug-in referenced in this chapter is install-path/examples/testpwdstore.c. For encoding and comparing, the plug-in performs an exclusive or with 42 on each character of the password.
When Directory Server calls a password storage scheme plug-in encode function, it passes that function an input password char * and expects an encoded password char * in return. The prototype for the example encode function, xorenc(), is as follows:
static char * xorenc(char * pwd);
Allocate space for the encoded password with slapi_ch_malloc() rather than regular malloc(). Directory Server can then terminate with an “out of memory” message if allocation fails memory with slapi_ch_free().
By convention, you prefix the encoded password with the name of the password storage scheme, enclosed in braces, { and }. In other words, the example plug-in is called XOR.
The name is declared in the example:
static char * name = "XOR"; /* Storage scheme name */
You return encoded strings prefixed with {XOR}. You also register the name with Directory Server.
Example 11-1 Encoding a userPassword Value (testpwdstore.c)
#include "slapi-plugin.h" static char * name ="XOR"; /* Storage scheme name */ #define PREFIX_START '{' #define PREFIX_END '}' static char * xorenc(char * pwd) { char * tmp = NULL; /* Used for encoding */ char * head = NULL; /* Encoded password */ char * cipher = NULL; /* Prefix, then pwd */ int i, len; /* Allocate space to build the encoded password */ len = strlen(pwd); tmp = slapi_ch_malloc(len + 1); if (tmp == NULL) return NULL; memset(tmp, '\0', len + 1); head = tmp; /* Encode. This example is not secure by any means. */ for (i = 0; i < len; i++, pwd++, tmp++) *tmp = *pwd ^ 42; /* Add the prefix to the cipher */ if (tmp != NULL) { cipher = slapi_ch_malloc(3 + strlen(name) + strlen(head)); if (cipher != NULL) { sprintf(cipher,"%c%s%c%s",PREFIX_START,name,PREFIX_END,head); } } slapi_ch_free((void **) &head); return (cipher); /* Server frees cipher */ }
Notice that you free only memory allocated for temporary use. Directory Server frees memory for the char * returned, not the plug-in. For details on slapi_ch_malloc() and slapi_ch_free(), see Chapter 15, Function Reference, Part I.
When Directory Server calls a password storage scheme plug-in compare function, it passes that function an input password char * and a stored, encoded password char * from the directory. The compare function returns zero, 0, if the input password matches the password from the directory. The function returns 1 otherwise. The prototype for the example compare function, xorcmp(), is therefore as follows:
static int xorcmp(char * userpwd, char * dbpwd);
Here, userpwd is the input password. dbpwd is the password from the directory. The compare function must encode the input password to compare the result to the password from the directory.
Example 11-2 Comparing a userPassword Value (testpwdstore.c)
#include "slapi-plugin.h" static int xorcmp(char * userpwd, char * dbpwd) { /* Check the correspondence of the two char by char */ int i, len = strlen(userpwd); for (i = 0; i < len; i++) { if ((userpwd[i] ^ 42) != dbpwd[i]) return 1; /* Different passwords */ } return 0; /* Identical passwords */ }
Notice that Directory Server strips the prefix from the password before passing the value to the compare function. In other words, you need not account for {XOR} in this case.
Not all encoding algorithms have such a trivial compare function.
You must register four password storage scheme specific items with Directory Server:
The storage scheme name that is used for the prefix
The encode function
The compare function
The decode function
Notice that you provide no decoding function. In this case, Directory Server does not decode user passwords after they are stored.
Example 11-3 Registering a Password Storage Scheme Plug-In (testpwdstore.c)
#include "slapi-plugin.h" static char * name ="XOR"; /* Storage scheme name */ static Slapi_PluginDesc desc = { "xor-password-storage-scheme", /* Plug-in identifier */ "Oracle Corporation (test)", /* Vendor name */ "11.1.1.3.0", /* Revision number */ "Exclusive-or example (XOR)" /* Plug-in description */ }; #ifdef _WIN32 __declspec(dllexport) #endif int xor_init(Slapi_PBlock * pb) { int rc = 0; /* 0 means success */ rc |= slapi_pblock_set( /* Plug-in API version */ pb, SLAPI_PLUGIN_VERSION, (void *) SLAPI_PLUGIN_CURRENT_VERSION ); rc |= slapi_pblock_set( /* Plug-in description */ pb, SLAPI_PLUGIN_DESCRIPTION, (void *) &desc ); rc |= slapi_pblock_set( /* Storage scheme name */ pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_NAME, (void *) name ); rc |= slapi_pblock_set( /* Encode password */ pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_ENC_FN, (void *) xorenc ); rc |= slapi_pblock_set( /* Compare password */ pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_CMP_FN, (void *) xorcmp ); rc |= slapi_pblock_set( /* Never decode pwd */ pb, SLAPI_PLUGIN_PWD_STORAGE_SCHEME_DEC_FN, NULL ); return rc; }
Set up a directory instance ad build the plug-in if you have not done so already.
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.
Hint Use install-path/examples/Makefile or install-path/examples/Makefile64.
$ 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.
$ dsadm restart instance-path
This section demonstrates the example plug-in for this chapter.
Plug the XOR password storage scheme into Directory Server if you have not done so already.
Before you do anything else, quickly check that Directory Server calls the plug-in encode function as expected. To perform this quick test, use the pwdhash tool. The pwdhash tool has Directory Server encode a password, then display the result.
Example 11-4 Testing the Password Storage Scheme
$ pwdhash -D /local/ds -s XOR password {XOR}ZKYY]EXN
Do not be concerned with the exact value of the resulting encoded password. The output should, however, start with {XOR}.
As Directory Server calls the encode function dynamically, you can fix the plug-in library. Then try pwdhash without doing anything to Directory Server. If this quick test does not work, fix the example.
Here, you use the XOR scheme to encode a new password for Barbara Jensen.
$ dsconf set-server-prop -h localhost -p 1389 pwd-storage-scheme:XOR
$ ldapsearch -h localhost -p 1389 -b dc=example,dc=com uid=bjensen version: 1 dn: uid=bjensen, ou=People, dc=example,dc=com cn: Barbara Jensen cn: Babs Jensen sn: Jensen givenName: Barbara objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson ou: Product Development ou: People l: Cupertino uid: bjensen mail: bjensen@example.com telephoneNumber: +1 408 555 1862 facsimileTelephoneNumber: +1 408 555 1992 roomNumber: 0209 userPassword: {XOR}ZKYY]EXN
Notice that Barbara’s password is XOR-encoded.
Barbara has the right to search other entries under dc=example,dc=com. Here, you search for Kirsten Vaughan's entry as bjensen.
Example 11-5 Binding With the New Password
$ ldapsearch -h localhost -p 1389 -b dc=example,dc=com -D uid=bjensen,ou=People,dc=example,dc=com -w password uid=kvaughan version: 1 dn: uid=kvaughan, ou=People, dc=example,dc=com cn: Kirsten Vaughan sn: Vaughan givenName: Kirsten objectClass: top objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson ou: Human Resources ou: People l: Sunnyvale uid: kvaughan mail: kvaughan@example.com telephoneNumber: +1 408 555 5625 facsimileTelephoneNumber: +1 408 555 3372 roomNumber: 2871
You know that Directory Server uses a plug-in to check Barbara’s password during the bind. Thus, Directory Server must have used the XOR plug-in because you saw that Barbara’s password was XOR-encoded. If the whole process appears to work, you can conclude that the compare function works, too.