Netscape Communications Corporation ("Netscape") and its licensors retain all ownership rig hts to the software prog rams offered by Netscape (referred
to herein as "Software") and related documentation. Use of the Software and related documentation is governed by the license agreement for the
Software and applicable copyright law.
Your right to copy this documentation is limited by copyright law. Making unauthorized copies, adaptations or compilation works is prohibited and
constitutes a punishable violation of the law. Netscape may revise this documentation from time to time without notice.
THIS DOCUMENTATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN NO EVENT SHALL NETSCAPE BE LIABLE FOR
INDIRECT, SPECIAL, INCIDENTAL , OR CON SEQ UENTIAL DAMAGES OF ANY KIND ARISING FRO M ANY ERRO R IN THI S
DOCUMENTATION, INCLUDING WITHOUT LIMITATION ANY LOSS OR INTERRUPTION OF BUSINESS, PROFITS, USE, OR DATA.
The downloading, exporting, or reexporting of Netscape software or any underlying information or technology must be in full compliance with all
United States and other applicable laws and regulations. Any provision of Netscape sof tware or documentatio n to the U.S. government is with restricted
rights as described in the license agreement for that Software.
Netscape and the Netscape N logo are registered trademarks of Netscape Communications Corporation in the United States and other countries. Other
Netscape logos, product names, and service names are also trademarks of Netscape Communications Corporation, which may be registe red in some
countries. Other product and brand names are the exclusive property of their respective owners.
This product incorporates International Components for Unicode (ICU) libraries, ICU is an open source development project sponsored, s uppor ted, and
used by IBM.
This product incorporates compression code by the Info-ZIP group. There are no extra charges or costs due to the use of this code, and the original
compression sources are freely available from http://www.infozip.com/ on the Internet.
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software must display the following acknowledgment: This product includes software
developed by the University of California, Berkeley and its contributors.
4. Neither the name of the University nor the names of its contributors may be used to endorse or pro mote pro ducts derived fro m this soft ware without
specific prior written permission.
THIS SOFTWARE IS PR OVID ED BY THE RE GENTS A ND CON TRIBU TORS "A S IS" AND A NY EXPRE SS OR IMPL IED WA RRANTIES , I NCLUDIN G,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONS EQ UENT IAL D AMA GES ( INC LUD ING, BUT NOT LIMI TED TO, PROC UREMEN T OF S UBSTI TUTE GO ODS OR S ERVI CES;
LOSS OF USE, DATA, OR PROFIT S; OR BU SINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Portions of the Software copyright (C) 1987, 1988 Student Information Processing Board of the Massachusetts Institute of Technology.
Permission to use, copy, modify, and distribute such M.I.T. software and its documentation f or any purpose and without fee is hereby granted, provided
that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation,
and that the names of M.I.T. and the M.I.T. S.I.P.B. not be used in advertising or publicity pertaining to distribution of the software without specific,
written prior permission. M.I.T. and the M.I.T. S.I.P.B. make no representations about the suitability of this software for any purpose. It is provided "as
is" without express or implied warranty.
10Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 11
Preface
This book describes how to write server plug-ins in order to customize and extend
the capabilities of the Netscape Directory Server (D irectory S e rver).
•What You Should Already Know
•Using Directory Server Plug-In APIs
•Document Conventions
•Where to Find Directory Server Information
What You Should Already Know
This book assumes you have this basic backgrou nd:
•A general understanding of the Internet and the World Wide Web (WWW).
•A general understanding of the Lightweight Directory Access Protocol (LDAP)
and the Directory Server. This book does not duplicate basic information on
server administration or LDAP concepts. For such information, refer to the
documents listed in “Where to Find Directory Server Information,” on page 14.
•Programming experience in C or C++.
Using Directory Server Plug-In APIs
Note the following:
•When you install Directory S erver, the plug-in related files are placed in this
directory:
•The location and syntax for the plug-in directives have changed. In t he
Directory Server 4.x release, the
of the
your
<server_root>/slapd-<instance_id>/config directory. For guidelines,
refer to the Readme file located here:
<server_root>/plugins/slapd/slapi/examples/
•Database plug-ins are not supported in this version of Directory Server. Be sure
to use the pre-operation, post-operation, and/or extended operation API to
register plug-in functions. Note that some code examples in this book are yet to
be updated to reflect this change.
•To comply with Internet Protocol version 6, Directory Server plug-ins can now
use the
to allow plug-ins to recognize the IP address of the LDAP client and server.
These new parameters use the Netscape Portable Runtime (NSPR)
structure for storing the IP addresses. Because of this, the NSPR files are
shipped with Directory Server.
plugin directives were in the database section
slapd.ldbm.conf file. In this release of Directory Server, you must add
plugin directives to the dse.ldif file, which is located in the
SLAPI_CONN_CLIENTEDADDR and SLAPI_CONNSERVERADDR parameters
PRNetADDr
The NSPR API allows compliant applications to use system facilities such as
threads, thread synchronization, I/O, interval timing, atom ic operations, and
several other low-level services in a platform-i ndependent manner.
•Several functions have been deprecated in this release of the Directory Server
Plug-in API. The deprecated functions are still supported for backward
compatibility. They are, however, not documented in this release. The table
below lists the deprecated functions and the func tions you should use in their
place. If you need additional information on functions that have been
deprecated, check this file:
Table 0-1Deprecated Functions and Their Suggested Replacements
Deprecated FunctionSuggested Replacement Function
The following functions th at deal with bervals ar e deprecated and their use is not recommended. For each
deprecated functi on, you will fin d in slapi-plugin.h a correspo nding fun ction with a _sv extens ion that
uses Slapi_Values instead of bervals. The new functions are more efficient than the old ones.
12Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 13
Document Conventions
Table 0-1Deprecated Functions and Their Suggested Replacements (Continued)
Deprecated FunctionSuggested Replacement Function
slapi_entry_attr_replace()slapi_entry_attr_replace_sv()
slapi_attr_get_values()slapi_attr_value_find()
slapi_attr_get_oid()slapi_attr_get_oid_copy()
slapi_pw_find()slapi_pw_find_sv()
slapi_call_syntax_values2keys()slapi_call_syntax_values2keys_sv()
slapi_call_syntax_assertion2keys_ava()slapi_call_syntax_assertion2keys_ava_sv()
slapi_call_syntax_assertion2keys_sub()slapi_call_syntax_assertion2keys_sub_sv()
slapi_entry_attr_hasvalue()slapi_entry_attr_has_syntax_value()
The following inter nal-operat ion ca lls ar e deprec ated. The new in te rnal o peration function s tha t are defined
in slapi-plugin.h take a Slapi_PBlock for extensibility and support the new plug-in configuration
capabilities.
slapi_search_internal_callback()slapi_search_internal_callback_pb()
slapi_search_internal()slapi_search_internal_pb()
slapi_modify_internal()slapi_modify_internal_pb()
slapi_add_internal()slapi_add_internal_pb()
slapi_delete_internal()slapi_delete_internal_pb()
slapi_modrdn_internal()slapi_modrdn_internal_pb()
The following three functions are not multi-thread safe; they return a pointer to unprotected data. Use the
new functions in slapi-plugin.h that end in _copy() instead.
slapi_get_supported_controls()slapi_get_supported_controls_copy()
slapi_get_supported_extended_ops()slapi_get_supported_extended_ops_copy()
slapi_get_supported_saslmechanism()slapi_get_supported_saslmechanisms_copy()
Document Conventions
The Directory Server runs on Windows NT and a number of different UNIX
platforms; the information here applies to all versions. File and directory paths are
given in Unix format (with forward slashes separating directory names). For
Windows versions, the directory paths are the same, except that you use
backslashes instead of s lashes to separate directorie s.
This book uses Uniform Resource Locators (URLs) of the form
Preface13
Page 14
Where to Find Directory Server Information
http://<server>.<domain>/<path>/<file>.html
In these URLs, <server> represents the name of the server on which you run your
application (such as
name (such as
server, and
<file>.html represents an individual filename.
research1 or www), <domain> represents your Internet domain
example.com), <path> represents the directory structure on the
If your server has Secure Sockets Layer (SSL) enabled, you would use
instead of
http in the URL.
This book uses the following font conventions:
The monospace font is used for sample code and code listings, API and
•
language eleme nts (such as function names and class names), filenames,
pathnames, directory names, HTML tags, and any text that must be typed on
the screen.
•Italic type is used for book titles, emphasis, and placeholders, and words used
in the literal sense.
•Variables are enclosed in angle brackets.
•Boldface type is used for glossary terms.
Where to Find Directory Server Information
This book explains how to write your own server plug-ins to customize the
Directory Server. You can write plug-ins that validate data before the data is stored
in the directory, that notify users when data has changed, or that replace the
standard database in the Directory Server with your own database.
https
The document set for Directory Server also contains the following guides:
•Netscape Directory Server Inst a llation Guide. Contains procedures for installing
your Directory Server as well as procedures for migrating from a previous
installation of Directory Server.
•Netscape Directo ry Ser ver Deplo yme nt Guid e. Contains procedures for the
day-to-day maintenance of your directory service. Includes information on
configuring server-side plug-ins.
•Netscape Dire ctory Server Administrator’s Guide. Contains procedures for the
day-to-day maintenance of your directory service. Includes information on
configuring server-side plug-ins.
14Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 15
Where to Find Directory Server Information
•Netscape Directory Server Configuration, Command, and File Reference. Contains
information about using the command-line scripts shipped with Directory
Server.
•Netscape Directory Server Schema Reference. Contains information about the
Directory Se rver schema.
For a list of documentation installed with Directory Server, open the
<server_root>/manual/en/slapd/index.htm file, where <server_root> is th e
directory in which you installed Directory Server.
For the latest information about Directory Server, including current release notes,
complete product documentation, technical notes, and deployment information,
check this site:
http://enterprise.netscape.com/docs
For a list of LDAP standards-related documen ts, check this site:
http://www.mozilla.org/directory/standards.html
Preface15
Page 16
Where to Find Directory Server Information
16Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 17
Introduction to Directory Server
Chapter 1, “An Overview of Directory Server Plug-Ins”
Chapter 2, “Writing and Compiling Plug-Ins”
Part1
Plug-Ins
Chapter 3, “Configuring Plug-Ins”
Chapter 4, “A Quick Example”
17
Page 18
18Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 19
Chapter1
An Overview of Directory Server
Plug-Ins
This chapter introduces you to Netscape Directory Server (Directory Server)
plug-ins and discusses the different types of plug-ins that you can write. The
chapter covers the following topics:
•What Are Directory Server Plug-Ins?
•How Directory Server Plug-Ins Work
•Types of Directory Server Plug-Ins
If you have already written a plug-in for Directory Server, refer to the section
“Using Directory Server Plug-In APIs” on page 11 for information on migrating
your plug-in to the latest version of the Directory Server.
What Are Directory Server Plug-Ins?
If you want to extend the capabilities of the Directory Server, you can write your
own Directory Server plug-in. A server plug-in is a shared object or library (or on the
Windows NT platform, a dynamic link library) that contains custom functions that
you write.
By writing your own plug-in functions, you can extend the functionality of the
Directory Server. For example, here are some of the things you can do with
Directory Se rver plug-ins:
•You can design an action that the Directory Server performs before the server
processes an LDAP action. For example, you can write a custom function to
validate data before the server performs an LDAP operation on the data.
19
Page 20
How Directory Server Plug-Ins Work
•You can design an action that the Directory Server performs after the server
successfully completes an LDAP operation. For example, you can send mail to
a client after an LDAP operation is successfully completed.
•You can define extended operations, as defined in the the LDAP v3 protocol.
•You can provide alternate matching rules when comparing certain attribute
values.
How Directory Server Plug-Ins Work
When properly configured, the Directory Server will load your plug-in on startup.
Once loaded, the Directory Server will resolve calls made to your plug-in functions
as it processes the LDAP requests cont ained in your applications.
Internally, the Directory Server has hook s that allow you to register your own
functions to be called when specific events occur. For example, the Directory Server
has hooks to call a registered plug-in in the following situa tions:
•Before preforming an LDAP operation (for example, before an entry is added
to the directory)
•When adding, modifying, remo ving, renaming, or searching for entries in the
database
•After performing an LDAP operation (for example, after an entry is added to
the directory)
•Before writing an entry to the database
•After reading an entry from the database
•When processing an extended operation
•When indexing an attribute
•When filtering search result candidates ba sed on an attribute
When you register your plug-in functions, you specify the function type and the
plug-in type. Together, these specifications indicate when the function is called. For
more information on this topic, refer to the section “Types of Directory Server
Plug-Ins” on page 24.
20Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 21
How Directory Server Plug-Ins Work
Calling Directory Server Plug-In Functions
At specific LDAP events, the Directory Server calls all plug-in functions that are
registered for that event. For example, before performing an LDAP add operation
(an add event), the server calls all plug-in functions registered as pre-operation add
functions. When the add operation is completed, the server will call all registered
post-operation add functions.
In most plug-in function calls, the server passes a parameter block to the function.
The parameter block contains data relevant to the operation. In most Director y
Server plug-in functions you write, you access a nd mo dify the data in the
param eter block.
For example, when the Directory Server receives an LDAP add request, the server
does the following:
1.Parses the request and retrieves the new DN and the entry to be added.
2.Places pointers to the DN and the entry in the parameter block.
3.Calls any registered pre-o p eration add functions, passing the parameter block
to these functions.
4.Calls the registered database add function (which is responsible for adding the
entry to the directory database), and passes to it the parameter block.
5.Calls any registered post-operation add functions, passing the parameter block
to these functions.
If you are writing a function that is invoked before an LDAP operation is
performed, you can prevent the operation from being performed. For exam ple, you
can write a function that validates data before a new entry is added to the
directory. If the data is not valid, you can prevent the LDAP add operation from
occurring and return an error message to the LDAP client.
In some situations, you can also set the data that is used by the server to perform an
operation. For example, in a pre-operation add function, you can change an entry
before it is added to the directory.
The Directory Server Architecture
Internally, the Directory Server consists of two ma jor subsections: The front-end
and the back -end.
Chapter 1An Overview of Directory Server Plug-Ins21
Page 22
How Directory Server Plug-Ins Work
The front-end receives LDAP requests from clients and processes those requests.
When processing requests, the front-end calls functions in the back-end to read and
write data. The front-end then sends the results back to the client.
The back-end reads and writes data to the database containing the directory entries.
The back-end abstracts the database from the front-end. The data stored in a
back-end is identified by the suffixes that the back-end supports. For example, a
back-end that supports the “o=example.com” suff ix contains directory entries that
end with that suffix.
Figure 1-1 illustrates the Directory Server architecture.
22Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 23
Figure 1-1Directory Server Architecture
How Directory Server Plug-Ins Work
Chapter 1An Overview of Directory Server Plug-Ins23
Page 24
Types of Directory Server Plug-Ins
Types of Directory Server Plug-Ins
You can write the following types of plug-ins for the Directory Server:
•Pre-operation/data validatio n. The server calls a pre-operation/data
validation plug -in function before p erforming an LD AP operation.
The main purpose of this type of plug-in is to validat e data befo re the data is
added to the directory or before it is used in an operat ion.
•Post-operation/data notificati on. The server calls a post-operation/data
notification plug-in function after performing an LDAP operati on.
The main purpose of this type of plug-in is to invoke a function after a
particular operation is executed. For example, you can write a plug-in that
sends email to users if their entries are modified.
•Entry storage and entry f etch. The server calls an entry storage plug-in functi on
right before writing data to the database back-end. The server calls entry fetch
plug-in functions after retrieving an entry from the database back-end.
For example, you can create an entry storage plug-in that encrypts an entry
before it is saved to the database and an entry fetch plug-in that decrypts an
entry after it is read from the database.
•Extended operation. The server calls an extended operation plug-in function
when the client requests an operation by OID. Extended operations are defined
in LDAP v3 and are described in more detail in Chapter 10 , “Writing Extended
Operation Plug- I ns.”
•Syntax. The server calls a syntax plug-in function when getting a list of
possible candidates for a search. The server also calls these functions when
adding or deleting values from certain attribute indexes.
Syntax plug-in functions can d efine the comparison operations used in
searches. For example, you could use a syntax plug-in function to define how
the “equals” comparison works for case-insensitive strings.
•Matching rule. The server calls matching rule plug-in functions when the
client sends a search request with an extensible matching search filter. You can
also write matching rule plug-in functions that the server calls when indexing
attributes for the back-end database.
Figure 1-2 illustrates how some of these different plug-in types fit into the
Directory Server architecture.
24Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 25
Types of Directory Server Plug-Ins
Figure 1-2Architecture of the Directory Server and Server Plug-Ins
Chapter 1An Overview of Directory Server Plug-Ins25
Page 26
Types of Directory Server Plug-Ins
26Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 27
Chapter2
Writing and Compiling Plug-Ins
This chapter provides an introduction on how to write and compile Netscape
Directory Server (Directory Server) plug-ins. Chapter 3, “Configuring Plug-Ins,”
describes how to load your plug-in int o the Directory Server configuration once it
is successfully compiled. This chapter covers the following topics:
•Writing a Plug-In Function
•Writing Plug-in Init ialization Functions
•Compiling a Directory Server Pl ug-In
If you have already written a plug-in for the Directory Server, refer to the
section “Using Directory Server Plug-In APIs” on page 11 for information on
migrating your plug-in to the latest versi on of the Directory Server.
Writing a Plug-In Function
To write a Directory Server plug-in, you must do the follo wing in your plug-in
code:
•Include the API header file
•Set the function parameters using the parameter block
•Call the front-end
•Specify the function return value
For additional information o n writing specific plug-in types, refer to the follow ing
chapters:
•Chapter 6, “Writing Pre/Post-Operation Plug-Ins”
•Chapter 9, “Writing Entry Store/Fetch Plug-Ins ”
27
Page 28
Writing a Plug-In Function
•Chapter 10, “Writing Extended Operation Plu g-Ins”
Including the API Header File
The interface to the Directory Server plug-in API is located in the slapi-plugin.h
header file. You must include this header file in the plug-ins you write. The
following line of code shows an example of including this header file:
#include "slapi-plugin.h"
When you install the Directory Server, slapi-plugin.h g et s installed into the
following directory:
<server_root>/plugins/slapd/slapi/include
Passing Data with Parameter Blocks
Often, plug-in functions make use of a parameter block, Slapi_PBlock, for passing
information to and from the Directory Server. The following plug-in function types
pass a parameter block as a fu nction argume nt:
•Pre-operation plug-in functions
•Post-operat ion plug-in functions
•Matching rule functions for indexing
•Factory functions for matching rule index functions
•Factory functions for matching rule filter functions
When invoking these types of plug-in functions, you pass to the Directory Server a
single argument of type
values needed to complete the function request. Your plug-in function should have
a prototype similar to the following:
int myFunction( Slapi_PBlock pb );
In this prototype, pb is the parameter block that contains the parameters
pertaining to the operation or function.
For example, the parameter block for an add operatio n will contain the target DN
and the entry to be added; the parameter block for a bind operation will contain the
DN of the user, the authentication method, and the user’s credentials.
Slapi_PBlock. This argument contains the parameter
28Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 29
Writing a Plug-In Function
Working with Parameter Blocks
In the functions you write, you set values in the parameter block that pertain to the
operation you are p e rforming. You can a lso get data from the parameter block
which you can use within your functions. This process is described in the next
section, “Getting Data from the Parameter Block , ” on page 29.
You can also set values in the parameter block during the processing of your
plug-in functions. The Directory Se rver ca n then use the new data values to
complete an operation which it might be processin g. For d e tails on this, see
“Setting Data in the Parameter Block,” on pag e 30.
Some of the data that you can retrieve from the parameter block includes entries,
attributes, search filters, and distinguished names (DNs). Once you retrieve a piece
of data, you can manipulate it using the front-end API functions. For example, you
can use front-end API functions to verify that an entry complies with the schema or
you can split up a search filter into it s ind ividual components. For details, see the
section “Calling Front-End Functions,” on page 31.
Getting Data from the Parameter Block
When the Directory Server calls your plug-in function, it passes any relevant data
to your function in a parameter block. The parameter block is defined as a
Slapi_PBlock data type. To access the data in a parameter block, call the
slapi_pblock_get() function.
NOTEOften,
When you call your own functions to modify the value retrieved by
slapi_pblock_get(), you are modifying the actual data in the
parameter block, not a copy of the data.
In the following example, the
the base DN for the LDAP search operation. It then normalizes the DN, converts all
characters to lowercase, and writes the converted DN to the error log. Note that the
actual DN (not a copy of it) is normalized and converted to lowercase.
Code Example 2-1Getting Data From the Parameter Block
#include <slapi-plugin.h>
...
int
searchdn_preop_search( Slapi_PBlock *pb )
{
char *dn;
slapi_pblock_get() returns a pointer to the actual data.
searchdn_preop_search() function gets the DN of
Chapter 2Writing and Compiling Plug-Ins29
Page 30
Writing a Plug-In Function
Code Example 2-1Gett ing Data From the Pa rameter Block (Continued)
/* Indicate the point when the plug-in starts executing */
slapi_log_error( SLAPI_LOG_PLUGIN, "searchdn_preop_search",
"*** PREOPERATION SEARCH PLUGIN ***\n");
/* Get the base DN of the search from the parameter block. */
slapi_pblock_get( pb, SLAPI_SEARCH_TARGET, &dn );
/* Normalize the DN (the actual DN, not a copy of it)
and convert it to lowercase */
slapi_dn_normalize_case( dn );
/* Log the normalized DN */
In this code example, SLAPI_SEARCH_TARGET identifies the parameter in the
parameter block that contains the base DN of the search. For a complete listing of
the parameter block IDs, see Chapter 16, “Parameter Block Reference.”
Setting Data in the Parameter Block
To modify the value of a parameter in the parameter block, call the function
slapi_pblock_set(). For example, you call can slapi_pblock_set() to change
the value of the
plug-in.
In the following example, the
SLAPI_PRIVATE
Code Example 2-2Setting Values in the Parameter Block
#include <slapi-plugin.h>
...
int
ldif_back_init( Slapi_PBlock *pb )
{
LDIF *db; /* context of the database */
...
/* Allocate space for the database context, which contains
information about the database and a pointer to the list
of entries. */
if ( slapi_pblock_set( pb, SLAPI_PRIVATE, (void *) db ) == -1 )
SLAPI_PRIVATE parameter, which stores private data for the
ldif_back_init() function sets the value of the
parameter to the context of the database.
30Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 31
Code Example 2-2Setting Values in the Parameter Block (Continued)
"Unable to store database information\n" );
}
...
}
Notice that this example uses the function slapi_new_condvar() to notify the user
if an error occurred.
Writing a Plug-In Function
In this code example,
SLAPI_PRIVATE identifies the parameter in the parameter
block that contains private data for use in the database functions. For a complete
listing of the parameter block IDs, see Chapter 16, “Parameter Block Reference.”
Calling Front-End Functions
The types of data that you can get from a parameter block i nclude entries,
attributes, distinguished names, and search filters. If you want to manipulate these
data items, you can call the associated front-end API functions provided with the
Directory Server. For example, using the the front-end API functions, you can:
•Write messages to the error log
•Get the attributes of an entry
•Get or set the DN of an entry
•Add or delete the values of an attribute
•Determine the OID of an attribute
•Determine the type of a search filter
For more information on the front-end A PI, see Chapter 5, “Front-End API
Functions” and Chapter 15, “Function Reference.”
Plug-in Return Values
If your plug-in function is successful, it should return 0 to the front-end. If it is not
successful, it should return a non-zero value and you should call the front-end
API function
problem (“Logging Messages ” on page 58 details this process).
slapi_new_condvar() to log an error message to describe the
Chapter 2Writing and Compiling Plug-Ins31
Page 32
Writing Plug-in Initialization Functions
In some cases, you may need to send an LDAP result back to the client. For
example, if you are writing a pre-operation bind function and an error occurs
during the processing of the function, the function should return a non-zero value,
log an error message, and send the appropriate LDAP result code back to the client.
For information on the appropriate result code to return to the client, refer to the
chapter that documents the type of plug-in you ar e writing.
Writing Plug-in Initialization Functions
Before the Directory Server can call your plug-in function, the function be must
properly initialized. To do this, you m ust write an initialization function for your
server plug-in. The initialization function should do the following:
1.Specify the plug-in compatibility version.
2.Register each of your plug-in functions.
3.Return a valu e to the Directory Server.
Your initialization function should have a prototype simi lar to the following:
int my_init_function( Slapi_PBlock pb );
Notice that in the initialization function, the Directory Server passes a single
argument of t y pe
Slapi_PBlock.
Initialization Functions for Windows Platforms
If you are writing an initialization function for a plug-in that runs on Windows NT
or Windows 2000, make sure to export the initialization function. For example:
__declspec(dllexport) int my_init_function(Slapi_PBlock pb);
On top of exporting the initializa tion function, you must also specify the name of
the initialization funct ion in a
In addition to the initialization function, you might need to export other functions
contained in your plug-in. In particular, you will need to export a ny functions that
are not specifically registered by your initialization functions, such as the entry
store and entry fetch plug-in functions that are described in Chapter 9. Registering
plug-in functions is described in det ail in the next section, “Registering Your
Plug-In Functions.”
.def file.
32Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 33
Writing Plug-in Initialization Functions
NOTEYou do not need to export all plug-in functions. Specifically, you do
not need to export any plug-in function that is specified in the
parameter block.
Specifying Directory Server Compatibility
You need to specify the compatibility version of your plug-in so that the Directory
Server can determine whether or not it supports the plug-in.
To specify the plug-in compatibility version, call the
functio n an d set the
SLAPI_PLUGIN_VERSION parameter to the version number
slapi_pblock_set()
associated with the plug-in. For example:
slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, \
SLAPI_PLUGIN_VERSION_03);
•Plug-in version 1 (SLAPI_PLUGIN_VERSION_01) is compatible with versions 3.x
and 4.x of the Directory Server.
•Plug-in version 2 (
SLAPI_PLUGIN_VERSION_02) is compatible with version 4.x
of the Directory Server.
•Plug-in version 3 (
SLAPI_PLUGIN_VERSION_03) is compat ible with ve rsio ns 6.1
and later of the Directory Server.
Specifying Information About the Plug-In
You specify information about your plug-in, such as a description of the
plug-in, with the
see “Slapi_PluginDesc,” on page 207.
It is advised that you include a plug-in description since the Netscape Console
displays this information as part of the server configuration information.
Slapi_PluginDesc structure. For details on this data structure,
To specify plug-in information, call the
SLAPI_PLUGIN_DESCRIPTION parameter to this structure. For example:
Code Example 2-3Specifying Plug-In Info rm at ion
/* Specify information about the plug-in */
Slapi_PluginDesc mypdesc = { "test-plugin", "example.com",
"0.5", "sample pre-operation plugin" };
...
slapi_pblock_set() function and set the
Chapter 2Writing and Compiling Plug-Ins33
Page 34
Writing Plug-in Initialization Functions
Code Example 2-3Specifying Plug-In Information (Continued)
/* Set this information in the parameter block */
slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
(void *)&mypdesc );
In this example code specifies the following plug-in information:
•The unique identifier for the server plug-in is
•The vendor of the server plug-in is
•The version of the server plug-in is
example.com.
0.5.
test-plugin.
Note that this version is intended to be used for your tracking purposes only; it
is not the same as the server compatibility version number specified by the
SLAPI_PLUGIN_VERSION parameter (see “Specifying Directory Server
Compatibility” on page 33 for details on this parameter). As you make changes
to your plug-in code, you can track the version distributed using the number
contained in the
Slapi_PluginDesc structure.
•The description of the server plug-in is contained in the data structure value
sample pre-operation plug-in.
Registering Your Plug-In Functi ons
Whether you register your plug-in through the initialization function depends
upon the type of function you are registering.
For some plug-in types, you do not need to register the plu g-in function from
within the initialization function. For example, you register entry store and entry
fetch plug-ins by specifying the function names in the
dse.ldif file.
plugin directive in the
For other plug-in types, such as pre-operation plug-ins and post-operation
plug-ins, the Directory Server gets the pointer to your function from a
parameter in the initializatio n function parameter block. In these cases, you use
the
slapi_pblock_set() function to specify the name of your plug-in function.
The full list parameters that you can use to register your plug-in functions are
listed in “Parameters for Registering Plug-In Functions” on page 556.
34Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 35
Writing Plug-in Initialization Functions
For example, if you want to register searchdn_preop_search() as a pre-operation
search function, include the follo wing code in your initialization f unction:
NOTEIf you do not register your plug-in functions, the Directory Server
will not call your plug-in functions. Make sure to register your
plug-in functions.
You can register more than one plug-in function in your initialization function; you
do not need to write an initialization function for each plug-in func tion that you
need to register. You should, however, define a different initialization function for
each type of plug-in that you are registering.
Returning a Value to the Directory Server
If the initialization function is successful, it should return 0. If an error occurs, it
should return
exit.
-1. If the initialization funct ion returns -1, the Directory Server will
Example of an Initialization Function
The following is an example of an initialization function that registers the
pre-operation plug-in function
function returns, the server will call
search operation is executed.
Code Example 2-4An Example Initialization Function
/* If the plug-in was successfully registered, log a
message and return 0. */
slapi_log_error( SLAPI_LOG_PLUGIN, "searchdn_preop_init",
"Plug-in successfully registered.\n" );
return( 0 );
}
Compiling a Directory Server Plug-In
Keep in mind the following tips when com piling your server plug-in:
•You need to compile and link your code as a shared object or library on UNIX
or as a dynamic link library (DLL) on Windows pl atforms. For e xample, on
Solaris, specify
command.
Some compilers require that you provide special flags when compiling code to
be used in a shared object or DLL. For example, on Solaris, you must specify
the
-Kpic or -KPIC flag, which specifies that you want to generate
position-independent code. Consult the documentation for your platform
compiler and linker for details.
•Make sure that the
is in your include path. Use
for Windows NT and Windows 2000 plug-ins.
•On Windows platforms, link to the
located in this directory:
36Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 37
Compiling a Directory Server Plug-In
•If you want, you can compile all plug-in functions in a single library. Although
you can include different types of plug-in functions in the same library, you
need to write separate initialization functions for each type of plug-in function.
Refer to the chapter “Configuring Plug-Ins” on page 39 for details on how to
specify each initialization functi on in a directive for a specific type of plug-in.
The following code shows a sample Makefile for Solaris. The example assumes that
the source files are located in the following directory:
<server_root>/plugins/slapd/slapi/examples
The server plug-in API header files are located in the relative path ../include.
Code Example 2-5Example Solaris Makefile
# SOLARIS Makefile for Directory Server plug-in examples
#
CC = cc
LD = ld
INCLUDE_FLAGS = -I../include
CFLAGS = $(INCLUDE_FLAGS) -D_REENTRANT -KPIC
LDFLAGS = -G
OBJS = testsaslbind.o testextendedop.o testpreop.o testpostop.o
38Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 39
Chapter3
Configuring Plug-Ins
After you compile your server plug-in, you need to configure the Netscape
Directory Server (Directory Server) so that it properl y loa d s your plug-in. The
following sections in this chapter show how this is done:
•Creating a Plug-In Configuration File
•Loading the Plug-In Configurati on File
•Passing Extra Argume nts to Plug-Ins
•Setting the Log Level of the Server
Creating a Plug-In Config u ra tio n File
To add your plug-in to the Directory Server configuration, you need to create an
LDIF representation of your plug-in entry, add the plug-in entry to the Directory
Server configuration, and reload the server configuration. Thi s section illustrates
how to create your plug-in entry. The section “Loading the Plug-In Configuration
File,” on page 44 explains how to add the plug-in entry to the Directory Server
configuration and reload the server configuration.
The plug-in configuration file must be an LDIF file written in ASCII format. Code
Example 3-1 shows the contents of an example plug-in configuration file. Note that
line numbers have been added for ease of reference; do not number the lines in
your own LDIF file.
Code Example 3-1An Example Plug-In Configuration File
1. dn: cn=Example Plug-in,cn=plugins,cn=config
2. objectclass: top
3. objectclass: nsSlapdPlugin
4. objectclass: extensibleObject
39
Page 40
Creating a Plug-In Configuration File
Code Example 3-1An Example Plug-In Configuration File (Continued)
10. nsslapd-pluginid: Example Pre-operation Plug-in
11. nsslapd-pluginversion: 1.0
12. nsslapd-pluginvendor: Example Corporation
13. nsslapd-plugindescription: This plug-in does ...
This example plug-in configuration file defines an example plug-in as follows:
•Line 1 sets the DN of the plug-in, which identi fi es the plug-in:
dn: cn=Example Plug-in,cn=plugins,cn=config
Here, the common name of the plug-in is set to Example Plug-in. The rest of
the DN entry (
that contains the configuration settings for plug-ins.
cn=plugins,cn=config) places the entry in the database tree
•Lines 2-4 declare the object classes of the plug-in.
•Line 5 sets the common name of the plug-in to
Example Plug-in.
•Line 6 defines the absolute path to the library that implements the plug-in:
nsslapd-pluginpath: C:/ds60/lib/test-plugin.dll
In this example, the plug-in is a Windows NT DLL, located in the directory
C:/ds60/lib.
•Line 7 identifies the initialization function that the server calls to register the
plug-in. In this example, the initialization is set to
searchdn_preop_init. For
information on implementing initialization functions, see “Writing Plug-in
Initialization Fun c tions,” on page 32.
•Line 8 sets the type of plug-in. In this case, it is a pre-operation plug-in. For a
complete list of the types of plug-in you can declare, refer to the “Summary of
Plug-In Directives” on page 42.
•Line 9 specifies whether or not the plug-in is active by default. The
nsslapd-pluginenabled attribute can have a value of either on or off. The
following line specifies that the plug- in is active by default:
nsslapd-pluginenabled: on
40Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 41
Creating a Plug-In Configuration File
You can also use the Directory Server Console to activate or deactivate the
plug-in once the plug-in is loaded.
•Line 10 uses the
nsslapd-pluginid attribute to set the name of the plug-in.
The name that you specify here will show up in the Directory Server Console.
In this example, the plug-in identification is set to
Plug-in
.
Example Pre-operation
•Line 11 sets the version number of the plug-in. This version number will also
show up in the Directory Server Console, and is used to track the vers ion of the
distributed plug-in; it does not indicate the Directory Server compatibility, as is
defined by the plug-in version number described in “Specifying Directory
Server Compatibility,” on page 33.
•Line 12 identifies the vendor/author of the plug-in. In the following line, the
vendor is set to “Example Corporation”:
nsslapd-pluginvendor: Example Corporation
•Finally, Line 13 sets the description of the plug-in. The description you set will
be the plug-in description that is visible through the Directory Server Console.
Plug-In Dependencies
You can specify that your plug-in is dependent on one or more different plug-ins. If
you do specify any plug-in dependencies, thos e pl ug- ins that you specify must
properly start before your associ ated plu g -i n wil l start.
There are two attributes that you can use in the plug-in configuration file to specify
the dependencies of your plug-in:
•nsslapd-plugin-depends-on-name
•nsslapd-plugin-depends-on-type
Each of these attributes can take multiple values, meaning that your plug-in
depends on one or more other plug-ins.
Specific Plug-in Dependencies
If you specify the nsslapd-plugin-depends-on-name attribute in your plug-in
configuration file, set its value to the names of one or more plug-ins. For example,
in your plug-in configurati on file, you could specify the following:
In this example, the plug-in depends on two specifically named plug-ins:
my_pluginA and vendor_plugin. This configuration line indicates that before your
plug-in can be loaded, the two specifically named plug-ins must be loaded. If either
of these two plug-ins fail to load, the Directory Server will exit with a
Plug-In Type Dependencies
If you specify the nsslapd-plugin-depends-on-type attribute in your plug-in
configuration file, set its value to one or more plug-in types. For example, in your
plug-in configuration file, you could specify the following:
nsslapd-plugin-depends-on-type: syntax
This configuration line indicates that your plug-in depends on any plug-in of type
syntax. If there is a configured plug-in of type syntax, it must be successfully
loaded before your plug-in can be loaded, otherwise the Directory Server will exit
with a
Note that if you specify a plug-in type dependency, the Directory Server will
search for any and all plug-ins of the type( s) specif ied. If none are found,
processing will continue without errors. However, the Directory Server must load
all plug-ins of the type(s) specified before it can load your plug-in. For a complete
list of the supported plug-in types, refer to the “Summ ary of Plug-In Directives,”
on page 42.
-1 error code.
-1 error code.
Specifying the Order of Plug-In Directives
You cannot in general rely on plug-ins being called in a certain order. For example,
you cannot rely on a particular pre-operation plug-in to be called before another.
You should ensure that your plug-in is written in such a way as to make it
independent of the order in which it will be called.
If you must use ordering, you can make use of alphabetical order. The server loads
the plug-ins in alphabetical order—that is, the loading order is determined by
standard ASCII ordering o f the
cn
=plugins,cn=config in the dse.ldif file. Because this feature may be
deprecated in a future version of the product, it is recommended that yo u write
your plug-in to not rely on any specific loading order.
cn value of the plug-in entry, which appears under
Summary of Plug-In Directives
The following table summarizes the different types of plug-ins that you can specify
in the plug-in configuration file.
42Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 43
Creating a Plug-In Configuration File
Table 3-1Directives for Specifying Different Plug-In Types
DirectiveDescription
entryfetchDeclares an entry fetch plug-in, which is called by the server after retrieving an
entry from the default back-end database.
Example of use: If you encrypt data with an entry store plug-in function before
saving the data to the database, you can define an entry fetch function that
decrypts data after reading it from the database.
entrystoreDeclares an entry store plug-in, which is called by the server before saving an
entry to the default back-end database. (If you are writing your own database
plug-in, you do not need to use this plug-in.)
Example of use: You can define an entry store function to encrypt data before
saving the data to th e data base.
extendedopDeclares an extended operation plug-in, which is called by the server when
receiving a request for an extended operation from a client.
matchingRuleDeclares a matching rule plug-in, which is called by the server when receives a
search request with an extensible matching search filter from a client.
This type of plug-in is also called by th e se rver when indexing attribut es for t he
back-end database.
postoperationDeclares a post-operation/data notification plug-in, which is called by the
server after performing an LDAP operation.
Example of use: You can define a data notificatio n function to send notificati on
to the adminis trator if certa in data has changed.
preoperationDeclares a pre-operation/data validation plug-in, which is called by the server
before perfo rming an LDAP op eration.
Example of use: You can define a data validati on function to check new entri es
before they are added to the directory.
syntaxDeclares a syntax plug-in, which is called by the server when getting a list of
possible candidates for a search, when determining how to compare values in
searches, and when adding or deleting values from certain attribute indexes.
Example of use: You can define a function that specifies how the “equals”
comparison works for case-insensitive strings.
Chapter 3Configuring Plug-Ins43
Page 44
Loading the Plug-In Configuration File
Table 3-1Directives for Specifying Different Plug-In Types (Continued)
DirectiveDescription
objectDeclares an object plug-in. Object plug-ins can install
SLAPI_PLUGIN_START_FN, SLAPI_PLUGIN_CLOSE_FN, and
SLAPI_PLUGIN_POSTSTART_FN functions. They can also use the
slapi_register_plugin() call to register any kind of plug-in they like.
Object plug-ins are typically used to simplify configuration of a group of related
plug-ins (one entry under cn=config instead of many).
Example of use: You can use this type when your plug-in doesn’t fit in any of
the other types listed in this table. For example, if your plug-in does more than
one thing, then you should use this directive. This type of plug-in will typically
register the types of operations it wants to handle using the internal API.
pwdstorageschemeThis directive will be supported in the future .
Loading the Plug-In Co nfig u ra tio n File
After you have written the plug-in config uration file, you must load it into the
dse.ldif file, which is located in the
<server_root>/slapd-<instance_id>/config directory. You can do this either
by using an LDAP utility, such as
ldapmodify, or by editing the file directly. If you
choose to edit the file directly, be sure to shut down the Directory Server first.
The following line shows an example of an LDAP command that loads the plug-in
Once the plug-in configuration is loaded, you must shut down the Directory Server
and then restart it before you can make calls to your plug-in. There are various
ways to shut down and restart the Directory Server; for example, you can:
•Use the Directory Server Console
•Use the UNIX scripts
stop-slapd and start-slapd
•Use the Windows NT Services applet, wh ic h c an be found in the Contr ol Panel
44Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 45
Passing Extra Arguments to Plug-Ins
In the Directory Server 4.x version, you could specify addition al arguments at the
end of the
This method allows for more descriptive configuration, which is easier to maintain.
To find the plug-in entry DN, retrieve
SLAPI_TARGET_DN from the pblock passed
to your start function. Once the DN is known, the normal plug-in API functions for
entry retrieval and manipulation can be used for configuration retrieval.
For additional information, check the code sa mples provided here:
<server_root>/plugins/slapd/slapi/examples
Setting the Log Leve l of the Serv er
If your functions call the slapi_new_condvar() function to write messag es to the
error log, you need to make sure that the Directory Server is configured to log
messages with the severity level you’ve specified. The available severity levels are
fully documented in the Reference section on page534.
For example, suppose you call this function in your plug-in:
You need to make sure that the Directory Server is configured to log messages with
the severity level
SLAPI_LOG_PLUGIN. In the Directory Server 4.x, this corresponds
to the log level of “plugin”.
46Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 47
Chapter4
A Quick Example
This chapter provides an example of a pre-operation Netscape Directory Server
(Directory Server) server plug-in that you can compile and run. Along with the
source code to the example, the chapter provides a Solaris Makefile that you can
use to build the plug-in.
You may not understand some of the func tionality contained in the example
program; however, all the concepts contained in the example code are explained in
detail in chapters that follow.
An Example Pre-Operation Plug-In
The example shows how to create a pre-operation plug-in for the LDAP search
operation. In other words, the Directory Server will proc ess the registered plug-in
functions before it processes each LDAP search operation. The example contains
two primary functions:
•The
•The
These functions illustrate the data in the parameter block tha t is available to your
function. You can get and manipulate the parameter block data by calling various
front-end API functions .
test_preop_search() function logs information about the search,
including the base DN of the search, the search scope, and the type of filter
used.
test_preop_init() function is the initialization function that registers
test_preop_search() as a SLAPI_PLUGIN_PRE_SEARCH_FN pre-operation
plug-in functi on for LDAP search op erations.
47
Page 48
An Example Pre-Operation Plug-In
Writing the Plug-In Example
The following example code includes the sample pre-operation search function and
the sample initializat ion function.
Code Example 4-1Sample Pre-Operation Search and Initialization Functions
/* function prototypes */
int test_preop_init( Slapi_PBlock *pb );
int test_preop_search( Slapi_PBlock *pb );
/* Description of the plug-in */
Slapi_PluginDesc srchpdesc = { "test-search", "example.com", "0.5",
"sample pre-operation search plugin" };
/* Initialization function
This function registers your plug-in function as a
pre-operation search function in the Directory Server.
You need to specify this initialization function in the
server configuration file so that the server calls
this initialization function on startup. */
#ifdef _WIN32
__declspec(dllexport)
#endif
int
test_preop_init( Slapi_PBlock *pb )
{
/* Specify the version of the plug-in ("01" in this release ) */
if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION,
SLAPI_PLUGIN_VERSION_01 ) != 0 ||
/* Specify the description of the plug-in */
slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
(void *)&srchpdesc ) != 0 ||
/* Set test_preop_search() as the function to call before
executing LDAP search operations. */
slapi_pblock_set( pb, SLAPI_PLUGIN_PRE_SEARCH_FN,
(void *) test_preop_search ) !=0 ) {
/* Log an error message and return -1 if a problem occurred */
slapi_log_error( SLAPI_LOG_PLUGIN, "test_preop_init",
"Error registering the plug-in.\n" );
return( -1 );
}
/* If successful, log a message and return 0 */
slapi_log_error( SLAPI_LOG_PLUGIN, "test_preop_init",
"Plug-in successfully registered.\n" );
return( 0 );
}
/* Pre-operation plug-in function for LDAP search operations
This function is called by the server before processing an LDAP
search operation. The function gets data about the search request
48Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 49
An Example Pre-Operation Plug-In
Code Example 4-1Sample Pre-Operation Search and Initialization Functions (Continued)
from the parameter block and prints the data to the error log. */
int
test_preop_search( Slapi_PBlock *pb )
{
char *base, *filter_str, *attr_type, *substr_init, *substr_final;
char **substr_any;
int scope, deref, filter_type, i;
Slapi_Filter *filter;
struct berval *bval;
/* Log a message to indicate when the plug-in function starts */
slapi_log_error( SLAPI_LOG_PLUGIN, "test_preop_search",
"*** PREOPERATION SEARCH PLUGIN ***\n");
/* Get and log the base DN of the search criteria */
if ( slapi_pblock_get( pb, SLAPI_SEARCH_TARGET, &base ) == 0 )
"LDAP_FILTER_PRESENT\n" );
/* For presence filters, get and log the attribute type */
slapi_filter_get_type( filter, &attr_type );
if ( attr_type != NULL )
slapi_log_error( SLAPI_LOG_PLUGIN, "\tSearch for presence of attr",
On Solaris, you can use the following Makefile to compile the example. (This
sample Makefile assume s that the source code is stored in
you are compiling a plug-in named
srchxmpl.c and that
srchxmpl.so.)
Chapter 4A Quick Example51
Page 52
An Example Pre-Operation Plug-In
Code Example 4-2Example Solaris Makefile
# SOLARIS Makefile for Directory Server plug-in examples
#
CC = cc
LD = ld
INCLUDE_FLAGS = -I../include
CFLAGS = $(INCLUDE_FLAGS) -D_REENTRANT -KPIC
LDFLAGS = -G
OBJS = srchxmpl.o
all: srchxmpl.so
srchxmpl.so: $(OBJS)
$(LD) $(LDFLAGS) -o $@ $(OBJS)
.c.o:
$(CC) $(CFLAGS) -c $<
clean:
-rm -f $(OBJS) srchxmpl.so
On Windows platforms, make sure to link to the libslapd.lib import library
(located under the
<server_root>\plugins\slapd\slapi\lib directory).
Registering the Plug-In Example
To register this example plug-in, you should d o th e following:
1.Create an LDIF confi gura tion file in an ASCII text editor; see “Creating a
Plug-In Configuration File,” on page 39.
2.Load the plug -i n configuration file; see “Loading the Plug-In Configuration
File,” on page 44.
3.Shut down the Directory Server.
4.Restart the Directo ry Server.
When you restart the Directory Server, it will read the entries in the
file, which contain the entry for you new plug- in. If all is done correctly, your
plug-in will now be loaded. (You may want to check the plug-ins list in the
Directory Server Console.)
dse.ldif
52Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 53
An Example Pre-Operation Plug-In
Running the Plug-In Example
After compiling the plug-in and registering it with the Directory Server, you’re
ready to make calls that are processed by the plug-in functions.
The first step is to restart the Directory Server and check the error log to see that the
plug-in is properly registered. You should see the follo wing line in the error log:
Error log messsage here!
Verify that the Plugins log level is selected. (The sample source code logs messages
to the error log with the Plugins severity level.)
If the plug-in is properly registered, you can then perform a few searches against
the directory. The pre-operation search plug-in function should write data about
each search to the error log.
Chapter 4A Quick Example53
Page 54
An Example Pre-Operation Plug-In
54Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 55
Basic Plug-In Programming
Chapter 5, “Front-End API Functions
Chapter 6, “Writing Pre/Post-Operation Plug-Ins”
Part2
Techniques
Chapter 7, “Defining Functions for LDAP Operations”
Chapter 8, “Defining Functions for Authentication”
55
Page 56
56Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 57
Chapter5
Front-End API Functions
The Netscape Directory Server (Directory Server) provides some general-purpose,
front-end API functions that allow you to work wit h the en tries in the Directory
Server. This chapter explains how to use the front-end API functions to accomplish
various tasks; you can call these functions in your plug-in to interact with the client
(for example, send results or result codes), log messages, and work with entries,
attributes, and filters. While all of the functions described here must be used in
conjunction with other API functions, understanding how these functions work
will help you under stand how to program other plug-in API fu nc tions.
This chapter contains the following sections:
•Logging Messages
•Adding Notes to Access Log Entries
•Sending Data to the Client
•Determining if an Operation Was Abandoned
•Working with Entries, Attributes, and Values
•Working with DNs and RDNs
•Working with Search Filters
•Checking Passwords
The front-end functions are declared in the
slapi-plugin.h header file.
57
Page 58
Logging Messages
Logging Messages
To write an error message to the error log, call th e slapi_new_condvar() function.
For example, the following
the error log:
Make sure that the Directory Server is configured to log messages that have the
severity that you specify (for example,
see “Setting the Log Level of the Server” on page 46.
slapi_log_error() function call writes a message in
SLAPI_LOG_PLUGIN). For more information,
Adding Notes to Access Log Entries
When the back-end database processes a search operation, it attempts to use
indexes to narrow down the list of candidates matching the search criteria. If the
back-end is unable to use indexes, it appends the following string to the access log
entry for the search:
notes="U"
This note indicates that an unindexed search was performed.
If you are writing your own back-end database search function, you ca n append
this note to access log entries by setting the
the flag
to be appended to access log entries. Currently,
only value that you can set for this parameter. In future releases, additional flags
will be defined. You will be able to use bitwise OR combinations of flags to specify
different combinations of notes.
The server appends these notes and writes out the access log entries whenever
sending a result or search entry back to the client.
SLAPI_OP_NOTE_UNINDEXED. This parameter identifies any notes that need
SLAPI_OPERATION_NOTES parameter to
SLAPI_OP_NOTE_UNINDEXED is the
58Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 59
Sending Data to the Client
Sometimes you might need to communicate various information directly back to
the client. For example, you might want to do this in the following situations:
•If you need to send a result code back to the client (for example, to report an
error or a successful result to an LDAP operation), call the
slapi_send_ldap_result() function.
•If you are fulfilling a search request and need to send matching entries back to
the client, call the
•If you need to refer the LDAP request to a different LDAP server, call the
slapi_str2filter() function.
slapi_send_ldap_search_entry() function for each entry.
Sending Data to the Client
For example, the following statement sends an
LDAP_SUCCESS status code back to
the client.
slapi_send_ldap_result( pb, LDAP_SUCCESS, NULL, \
"The operation was processed successfully.\n", 0, NULL );
NOTE
It is important that you send only one result per operation back to the
client.
Determining if an Operation Was Abandoned
At any point in time, the client can choose to abandon an LDAP operation. When
writing database functions, keep in mind that you should periodically check to see
if the operation has been abandoned.
To determine if an operation has been abandoned, call
For example:
if ( slapi_op_abandoned( pb ) ) {
slapi_log_error( SLAPI_LOG_PLUGIN, "my_function",
"The operation was abandoned.\n" );
return 1;
}
slapi_op_abandoned().
Chapter 5Front-End API Functions59
Page 60
Working with Entries, Attributes, and Values
Working with Entries, Attributes, and Values
This section discusses how to create new entries in the di re ctory and how to
convert them to LDIF and back.
In certain situations, you will need to pass directory entries between the front-end
and the client. For example, it you create a custom add function, the front-end
passes to your function an entry in the parameter block. When you perform a
search operation, you return each matching search entry to the client.
When working with entries, you use the
Slapi_Entry datatype to get attribute
value pairs. The front-end routines listed in Table 5-1 are designed to help you
manipulate entries passed in parameter blocks. These functions are described in
more detail in the sections that follow the table.
Table 5-1Front-End Functions for Manipulating Entries and Attributes
Front-end functionDescription
slapi_entry_alloc()Allocate memory for a new entry
slapi_entry_dup()Copy an entry
slapi_entry_free()Free an unused entry from memory
slapi_filter_free()
slapi_str2entry()
slapi_entry_get_dn()
slapi_entry_set_dn()
slapi_entry_schema_check()Verify that an entry complies with the schema
slapi_entry_first_attr()
slapi_entry_next_attr()
slapi_entry_attr_find()Find the values for a specified attribute
Convert an entry to an LDIF str ing
representation and vice versa
Get or set the DN for an entry
Get the attributes of an entry
slapi_entry_attr_merge_sv()Merge an attribute and its values into an
slapi_entry_add_values_sv() Add values to an attribute in an entry
slapi_entry_delete_values_sv()Delete values from an attribute in an entry
60Netscape Directory Server Plug-In Programmer’s Guide • December 2003
entry
Page 61
Working with Entries, Attributes, and Values
Creating a New Entry
In some situations, you might need to create a new entry. There are two basic ways
to do this:
•By allocating memory for a new entry
To allocate memory for a new entry, call the
This function returns a pointer to a new entry of the opaque datatype
Slapi_Entry
. Once you create a new entry, you should call other front-end
slapi_entry_alloc() function.
routines to set the DN and attributes of the entry.
•By copying an existing entry
To make a copy of an existing entry, call the
function returns a pointer to a new entry of the datat ype
slapi_entry_dup() routine. This
Slapi_Entry that
contains the copied data.
When you are finished using the entry, you should free it from memory by calling
slapi_entry_free() function.
the
Converting Between Entries and Strings
Entries can be stored in LDIF files. When stored in the se files, entr ies are converted
into a string representation. The following format is the LDIF string representation
for a directory entry:
If you want to continue the specificat ion of a value on additional lines (in other
words, if the value wraps around to another line), use a single space (the ASCII 32
character) at the beginning of subsequent lines. For example:
dn: cn=Jane Doe
inski, ou=Accoun
ting, o=ex
ample.com
Refer to the Netscape Directory Server Administrator’s Guide for details on DN syntax.
Chapter 5Front-End API Functions61
Page 62
Working with Entries, Attributes, and Values
If a double-colon is used after a data type, it signifies that the value after the
double-colon is encoded as a base-64 string. Data is sometimes encoded as a
base-64 string. For example, it might be encoded this way if the value contains a
non-printing character or newli ne.
To get the LDIF string representation of an entry (and vice versa), call the following
functions:
•To convert an entry from the datatype
representation, call the
slapi_filter_free() function.
Slapi_Entry to its LDIF string
This function returns the LDIF string representation of the entry or NULL if an
error occurs. When you no longer need to use the string, you should free it
from memory by calling the
slapi_ch_free() function.
•To convert an LDIF string representation back to an entry of the da tatype
Slapi_Entry
This function returns an entry of the datatype
, call the slapi_str2entry() function.
Slapi_Entry. If an error
occurred during the conversion process, the function returns NULL instead.
When you are done working with the entry, y ou should call the
slapi_entry_free() function.
NOTECalling
slapi_str2entry() modifies the value of the string
argument passed into the function (not a copy). If you s till want to
use the string representation of the entry, make a copy of the string
before calling this function.
Getting and Setting the DN of an Entry
You can call the following two front-end routines to get and set the DN for an
entry:
•To get the DN for an entry, call the
•To set the DN for an entry, call the
Verifying Compliance with the Schema
Before you add or modify an entry in the database, you may want to verify that the
new or changed entry still complies with the database schema.
62Netscape Directory Server Plug-In Programmer’s Guide • December 2003
slapi_entry_get_dn() function.
slapi_entry_set_dn() function.
Page 63
Working with Entries, Attributes, and Values
To see if an entry complies with the schema, call the
slapi_entry_schema_check() function.
Getting the Attribut es and Values of an Entry
There are two basic ways to obtain the attributes and values of an entry:
•You can iterate through the attributes of the entry, testing each one to see if it is
the needed attribute.
•You can use the
specific attribute.
Once you find the attribute you are looking for, use
return the value of that attribute.
slapi_entry_attr_find() function to see if an entry has a
slapi_attr_value_find() to
Iterating Through the Attributes in an Entry
To iterate through the attributes associated with an entry, call the
slapi_entry_first_attr() function to get the first attribute of the entry. This
function returns a pointer to the first attribute in the entry. With a pointer to the
attribute, you can test to see if it is the attribute you are interested in.
To retrieve the subsequent attributes in the entry, call
passing to it the pointer to the current attribute in the
function. Like
pointer to the current attribute.
Once you find the attribute you need, you can retrieve its value using
slapi_attr_value_find().
slapi_entry_first_attr(), slapi_entry_next_attr() returns a
slapi_entry_next_attr(),
cookie parameter of the
Finding a Specific Attr i bu te in an Entr y
To see if an entry contains a specific attribute, call slapi_entry_attr_find().
This function return 0 if the entry contains the attribute, -1 if it does not .
Adding and Removing Values
You can also call front-end routines to add or remove attributes and values in an
entry. The front-end provides the following functionality:
•To add new values to an entry, call the
function .
slapi_entry_add_values_sv()
Chapter 5Front-End API Functions63
Page 64
Working with DNs and RDNs
•To remove values from an entry, call slapi_entry_delete_values_sv().
•In certain situations, you may want to add an attribute and its values to an
entry while not replacing any attribute values that already exist. To do this, call
slapi_entry_attr_merge_sv() function.
the
Working with DNs and RDNs
In certain situations, the front-end passes DNs to the back-end through the
parameter block. For example, when calling the add function, the parameter block
includes a parameter that specifies the DN of the new entry to be added.
If you need to manipulate DNs within parameter blocks, you can call the following
front-end routines:
Table 5-2Front-End Functions for Manipulating DNs
FunctionDescription
slapi_dn_isroot()Determines if a DN is the root DN (the DN of the
privileged superuser)
slapi_dn_parent()
slapi_dn_beparent()
slapi_dn_issuffix()Determines if a DN is the child of another DN
slapi_dn_isbesuffix()Determines if a DN is a suffix served by one of
slapi_dn_normalize()Normalizes a DN
slapi_dn_ignore_case()Converts all ch aracters in a DN to lowercase
slapi_dn_normalize_case()Normalizes a DN and converts all characters to
Gets a copy of the parent DN
the server’s back-ends
lowercase
Determining if a DN is the Root DN
To determine if a DN is the root DN, call slapi_dn_isroot(). This function
returns
DN is not the root DN.
1 if the specified DN is the root DN of the local database. It returns 0 if the
64Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 65
Working with DNs and RDNs
Working with DN Suffixes
A suffix of a DN identifies a subtree in the directory tree where the DN is located.
For example, consider the following DN:
This suffix indicates that the Babs Jensen entry is located in the Example
Corporation
subtree in the directory tree.
To determine if a value is a suffix for a DN, call
determine if a DN is one of the suffixes served by the back-end, call the
slapi_dn_isbesuffix() function.
slapi_dn_issuffix(). To
Server Suffixes
The suffix directive in the server configuration file specifies which DNs are
served by a particular back-end. For example, suppose the suf f ix d irective is
configured to the following:
suffix “o=Example Corporation, c=US”
Here, all entries within the “o=Example Corporation, c=US” subtree are served by
this back-end.
Getting the Parent DN of a DN
To get a copy of the parent DN for a DN, call the slapi_dn_parent() function or
the
slapi_dn_beparent() function.
These functions return the parent DN of
slapi_dn_beparent() will return NULL.
dn. If dn is a suffix served by the back-end,
When you are done working with the parent DN, you should free it from memory
by calling
Normalizing a DN
If you need to compare DNs (for example, if you are searching your database for a
particular DN), you should normalize the DNs that you are comparing to ensure
that they are properly compared.
free().
Chapter 5Front-End API Functions65
Page 66
Working with Search Filters
You can use the following front-end function to normalize and convert the case of a
DN:
•Use
•Use
•Use
slapi_dn_normalize() normalize a DN.
slapi_dn_ignore_case() to convert all characters in a DN to lowercase.
slapi_dn_normalize_case() to both normalize the DN and convert all
characters in the DN to lowercase.
NOTEThese functions operate on the actual DN specified in the
argument, not a copy of the DN. If you want to modify a copy of the
DN, call
slapi_ch_strdup() to make a copy of the DN.
Working with Search Filters
When a client requests an LDAP search operation, the front-end passes the search
filter to the back-end as part of the parameter block. (The filter is passed through
the
SLAPI_SEARCH_FILTER parameter. A string representation of the filter is also
available in the
To manipulate search filters, call the following f ront-end routines:
SLAPI_SEARCH_STRFILTER parameter.)
Table 5-3Front-End Functions for Manipulating Filters
FunctionDescription
slapi_filter_test() Determine if an entry matches a filter’s criteria
slapi_filter_get_choice() Get the filter type
slapi_filter_get_ava() Get the attribute type and value used for
comparison in an attribute-value assertion
filter (only applicable to the followin g searches:
LDAP_FILTER_EQUALITY,
LDAP_FILTER_GE, LDAP_FILTER_LE, and
LDAP_FILTER_APPROX)
slapi_filter_get_type() Get the type of attribute that the fil ter is
searching for (only applicable to
LDAP_FILTER_PRESENT searches)
slapi_filter_get_subfilt()Get the substring pattern used for the filter
(applicable only to
LDAP_FILTER_SUBSTRING searches)
66Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 67
Working with Search Filters
Table 5-3Front-End Functions for Manipulating Filters (Continued)
FunctionDescription
slapi_str2filter()Convert a string representation of a filter to a
filter of the datatype Slapi_Filter
slapi_filter_join() Construct a ne w LDAP_FILTER_AND,
Get the components of a filter (only applicable
to LDAP_FILTER_AND, LDAP_FILTER_OR,
and LDAP_FILTER_NOT searches)
Determining if an Entry Matches a Filter
After retrieving a filter from the SLAPI_SEARCH_FILTER parameter of the
param eter block, you can call the
slapi_filter_test() function to determine if
entries in your database match the filter.
Getting the Filter Typ e
To determine the type of filter you are using, call slapi_filter_get_choice().
This function returns the filter type, which can be any one of the following values:
Table 5-4Types of Filters
Filter TypeDescription
LDAP_FILTER_ANDThe search should find entries matching all filters that
LDAP_FILTER_ORThe search should find entries matching any filter
LDAP_FILTER_NOTThe search should find entries not matching the
LDAP_FILTER_EQUALITYThe search should find entries that contain a value
LDAP_FILTER_SUBSTRINGSThe search should find entries that contain a value
are specified in this complex filter.
specified in this complex filter.
specified filter.
equal to the specified attribute value.
matching the specified substrings.
Chapter 5Front-End API Functions67
Page 68
Working with Search Filters
Table 5-4Types of Filters (Continued)
Filter TypeDescription
LDAP_FILTER_GEThe search should find entries that contain a value
LDAP_FILTER_LEThe search should find entries that contain a value less
LDAP_FILTER_PRESENTThe search should find entries that contain the
LDAP_FILTER_APPROXThe search should find entries that contain a value
Getting the Search Criteria
To get the search criteria specified by a search filter, call one of the following
functions:
greater than or equal to the specified attribute value.
than or equal to the specified attribute value.
specified attribute.
approximately matching the specified attribute value.
•If the filter type is
LDAP_FILTER_LE
value used in the filter by calling
•If the filter type is
the filter is searching for by calling the
•If the filter type is
that the filter searches for by calling
•To get the components of a complex filter of th e type
LDAP_FILTER_OR
and
slapi_filter_list_next() functions.
LDAP_FILTER_EQUALITY, LDAP_FILTER_GE,
, or LDAP_FILTER_APPROX, you can get the attribute and
slapi_filter_get_ava().
LDAP_FILTER_PRESENT, you can get the attribute type that
slapi_filter_get_type() function.
LDAP_FILTER_SUBSTRINGS, you can get the attribute type
slapi_filter_get_subfilt().
LDAP_FILTER_AND,
, or LDAP_FILTER_NOT, call the slapi_filter_list_first()
Both of these functions will return either a filter compo nen t of the complex
filter or a NULL value, according to the following:
❍If slapi_list_first() returns a NULL, the complex filter is not of the
type
LDAP_FILTER_AND, LDAP_FILTER_OR, or LDAP_FILTER_NOT.
❍If slapi_list_next() returns a NULL, the component returned by the
call is the last component in the complex filter.
NOTEYou do not need to free the values returned by the
slapi_filter_get_ava(), slapi_filter_get_type(), and
slapi_filter_get_subfilt() functions.
68Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 69
Checking Passwords
Converting a String to a Filter
A search filter can be represented by either the datatype Slapi_Filter or as a
string. In a parameter block for a search operation,
of the datatype
Slapi_Filter and SLAPI_SEARCH_STRFILTER is the string
representation of that filter. In general, it is easier to specify a filter as a string than
it is to construct a filter from the type
Slapi_Filter.
SLAPI_SEARCH_FILTER is a filter
To convert the string representation of a filter into a filter of the datatype
Slapi_Filter
, call the slapi_str2filter() function.
When you are done working with the filter, yo u should free it by calling the
slapi_filter_free() function.
Creating Complex Filters by Combining Filters
You can use AND, OR and NOT to combine different filters to create a complex
filter. To do this, call the
The
slapi_filter_join() function returns the complex filter you’ve created.
When you are done using the complex filter, you should free it by calling
slapi_filter_free().
Filters of the type
(
ftype) is LDAP_FILTER_NOT, you must pass a NULL value for the second filter
when calling
LDAP_FILTER_NOT can have only one component. If the filter type
slapi_filter_join().
Checking Passwords
slapi_filter_join() function.
When Directory Server 4.x stores the password for an entry in the userpassword
attribute, it encodes the password using the scheme sp ecifie d i n the
directive of the configuration file. The scheme can be
cleartext).
By default, Directory Server 6.x uses the
credentials for an entry. The server encodes the password using the scheme
specified in the
attributes of the
be any of the following:
•
CLEAR (means no encryp tion and can be defi ned using the
clear-password-storage-scheme plug-in)
passwdhash
crypt or sha or““ (for
userpassword attribute to store the
nsslapd-rootpwstoragescheme or passwordStorageScheme
cn=config entry contained in the dse.ldif file. The scheme can
Chapter 5Front-End API Functions69
Page 70
Checking Passwords
•CRYPT (means Unix crypt algorithm and ca n be d efine d using the
crypt-password-storage-scheme plug-in)
SHA (means Secure Hashing Algorithm and can be defined using the
•
sha
-password-storage-scheme plug-in)
•
SSHA (means Salted Secure Hashing Algorith m and can be defined using the
ssha-password-storage-scheme plug-in)
To determine if a given password is one of the values of the
attribute, call
slapi_pw_find_sv(). This function determines which password
userpassword
scheme was used to store the password and uses the appropriate comparison
function to compare a given value against the encrypted values of the
userpassword attribute.
70Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 71
Chapter6
Writing Pre/Post-Operation Plug-Ins
This chapter explains how to write functions that the Netscape Directory S e rver
(Directory Server) calls before and after executing an LDAP operation. These
functions are called pre-operation and post-operation plug-in functions.
•How Pre/Post-Operation Plug-Ins Wo rk
•Types Pre-Operation and Post-Operation Functions
•Registering Pre/Post-Operation Functions
How Pre/Post-Operation Plug-Ins Work
The Directory Server can perform the following LDAP operations: Bind, Unbind,
Search, Modify, Add, Delete, Modify RDN, Compare, and Abandon.
NOTEThe Directory Server can also perform extended operations as
defined in the LDAP v3 protocol. For information on implementing
plug-in functions to execute extended operations, see Chapter 10,
“Writing Extended Operation Plu g -I ns ”.
You can configure the Directory Server to call your custom plug-in functions before
and after executing any of these LDAP operations.
For example, you can write a pre-operation function that validates an entry before
the server performs an LDAP add operation. An example of a post-operation
plug-in function would be one that sends a notification to a user after their entry
has been modified by an LDAP modify operation.
71
Page 72
How Pre/Post-Operation Plug-Ins Work
You can also set up the Directory Server to call your own plug-in functions before
and after:
•Sending an LDAP entry back to the client
•Sending an LDAP result code back to the client
•Sending an LDAP referral back to the client
Figure 6-1 illustrates how the Directory Server front-end calls pre-operation and
post-operation functions before and after executing an LDAP operation.
When processing a request, the Directory Server will call all registered
pre-operation functions before it calls the back-end to service the request. All
pre-operation functions must return before the front-end calls the associated
back-end function.
Figure 6-1Calling Pre-Operation and Post-Operation Plug-In Functions
72Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 73
Types Pre-Operation and Post-Operation Functions
Types Pre-Operation and Post-Op eration
Functions
As is the case with other server plug-in functions, pre-operation func tions and
post-operation functions are specified in a parameter block that you can set on
server startup. Each function corresponds to an ID in the parameter block. In your
initialization function, you can call the
the name of your function that correspond s to the pre-operation or post-operation
function. For more information on the parameter block, see “Getting Data from the
Parameter Block” on page 29.
Types of Pre-Operation Functions
Table 6-1 lists the Directory Server pre-operation functions and the purpose of each
function.
slapi_pblock_set() function to specify
Table 6-1Functions Called Before the Directory Server Executes an Operation
ID in Parameter BlockDescription
SLAPI_PLUGIN_PRE_BIND_FNSpecifies the function called before the Directory Server
executes an LDAP bind operation. For information on writing
this type of function, see “Processing an LDAP Bind
Operation” on page 78.
SLAPI_PLUGIN_PRE_UNBIND_FNSpecifies the function called before the Directory Server
executes an LDAP unbind operation. For information on
writing this type of function, see “Processing an LDAP
Unbind Operation” on page 79.
SLAPI_PLUGIN_PRE_SEARCH_FNSpecifies the function called before the Directory Server
executes an LDAP search operation. For information on
writing this type of function, see “Processing an LDAP Search
Operation” on page 80.
SLAPI_PLUGIN_PRE_COMPARE_FNSpecifies the function called before the Directory Server
executes an LDAP compare operation. For information on
writing this type of function, see “Processing an LDAP
Compare Operation” on page 84.
SLAPI_PLUGIN_PRE_ADD_FNSpecifies the function called before the Directory Server
executes an LDAP add operation. For information on writing
this type of function, see “Processing an LDAP Add
Operation” on page 84.
Chapter 6Writing Pre/Post-Operation Plug-Ins73
Page 74
Types Pre-Operation and Post-Operation Functions
Table 6-1Functions Called Before the Directory Server Executes an Operation (Continued)
ID in Parameter BlockDescription
SLAPI_PLUGIN_PRE_MODIFY_FNSpecifies the function called before the Directory Server
executes an LDAP modify operation. For information on
writing this type of func tion, see “P rocessing an LDAP Modify
Operation” on page 86.
SLAPI_PLUGIN_PRE_MODRDN_FNSpecifies the function called before the Directory Server
executes an LDAP modify RDN oper ation. Fo r inform ation o n
writing this type of func tion, see “P rocessing an LDAP Modify
RDN Operation” on page 87.
SLAPI_PLUGIN_PRE_DELETE_FNSpecifies the function called before the Directory Server
executes an LDAP delete operation. For information on
writing this type of function, see “Processing an LDAP Delete
Operation” on page 89.
SLAPI_PLUGIN_PRE_ABANDON_FNSpecifies the function called before the Directory Server
executes an LDAP abandon operation. For information on
writing this type of function, see “Processing an LDAP
Abandon Operation” on page 89.
SLAPI_PLUGIN_PRE_ENTRY_FNSpecifies the function called before the Directory Server sends
an entry back to the client (for example, when you call
slapi_send_ldap_search_entry(), the pre-operation
entry function is called before the entry is sent back to the
client).
SLAPI_PLUGIN_PRE_REFERRAL_FNSpecifies the function called before the Directory Server
sends a referral back to the client (for example, when you
call slapi_str2filter(), the pre-operation referral
function is called before the referral is sent back to the client).
SLAPI_PLUGIN_PRE_RESULT_FNSpecifies the function called before the Directory Server
sends a result code back to the client (for example, when
you call slapi_send_ldap_result(), the pre-operation
result function is called before the result code is sent back to
the client).
Types of Post-Operation Functions
Table 6-2 lists the Directory Server post-operation functions and the purpose of
each function.
74Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 75
Types Pre-Operation and Post-Operation Functions
Table 6-2Functions Called After the Directory Server Executes an Operation
ID in Parameter BlockDescription
SLAPI_PLUGIN_POST_BIND_FNSpecifies the function called after the Directory Server
executes an LDAP bind operation. For information on
writing this type of function, see “Processing an LDAP Bind
Operation” on page 78.
SLAPI_PLUGIN_POST_UNBIND_FNSpecifies the function called after the Directory Server
executes an LDAP unbind operation. For information on
writing this type of function, see “Processing an LDAP
Unbind Operation” on page 79.
SLAPI_PLUGIN_POST_SEARCH_FNSpecifies the function called after the Directory Server
executes an LDAP search operation. For information on
writing this type of function, see “Processing an LDAP
Search Operati on ” on page 80.
SLAPI_PLUGIN_POST_COMPARE_FNSpecifies the function called after the Directory Server
executes an LDAP compare operation. For information on
writing this type of function, see “Processing an LDAP
Compare Operation” on page 84.
SLAPI_PLUGIN_POST_ADD_FNSpecifies the function called after the Directory Server
executes an LDAP add o peration. For in formation on writing
this type of function, see “Processing an LDAP Add
Operation” on page 84.
SLAPI_PLUGIN_POST_MODIFY_FNSpecifies the function called after the Directory Server
executes an LDAP modify operation. For information on
writing this type of function, see “Processing an LDAP
Modify Operation” on page 86.
SLAPI_PLUGIN_POST_MODRDN_FNSpecifies the function called after the Directory Server
executes an LDAP modify RDN operation. For information
on writing this type of function, see “Processing an LDAP
Modify RDN Operation” on page 87.
SLAPI_PLUGIN_POST_DELETE_FNSpecifies the function called after the Directory Server
executes an LDAP delete operation. For information on
writing this type of function, see “Processing an LDAP
Delete Operation” on page 89.
SLAPI_PLUGIN_POST_ABANDON_FNSpecifies the function called after the Directory Server
executes an LDAP abandon operation. For information on
writing this type of function, see “Processing an LDAP
Abandon Operation” on page 89.
Chapter 6Writing Pre/Post-Operation Plug-Ins75
Page 76
Registering Pre/Post-Operation Functions
Table 6-2Functions Called After the Directory Server Executes an Operation (Continued)
ID in Parameter BlockDescription
SLAPI_PLUGIN_POST_ENTRY_FNSpecifies the function called after the Directory Server
sends an entry back to the client (for example, when you
call slapi_send_ldap_search_entry(), the
post-operati on entry functi on is called after the entry is sent
back to the client).
SLAPI_PLUGIN_POST_REFERRAL_FNSpecifies the function called after the Directory Server
sends a referral back to the client (for example, when you
call slapi_str2filter(), the pre-operation referral
function is called after the referral is sent back to the client).
SLAPI_PLUGIN_POST_RESULT_FNSpecifies the function called after the Directory Server
sends a result code back to the client (for example, when
you call slapi_send_ldap_result(), the pre-operation
result function is called after the result code is sent back to
the client).
Registering Pre/Post-Operation Functions
To register your pre-operation and post-operation plug-in functions, you need to
write an initialization func tion and then configure the server to load your plug-in.
For details, follow the procedures outlined in “Writing Plug-i n Initialization
Functions” on page 32 and “Configuring Plug-Ins” on page 39.
76Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 77
Chapter7
Defining Functions for LDAP
Operations
This chapter explains how to write pre-operation and po st- operation functions for
specific LDAP operations. In general, the functions outlined here use a parameter
block to pass information between the plug-in and the Netscape Directory Server
(Directory Server). Because of this, these plug-in functions will pass a single
argument, a parameter block defined by the data type
information on this, see “Passing Data with Parameter Blocks” on page 28.
Slapi_PBlock. For more
This chapter outlines how to define plug-in functions to do the following:
•Specifying Start and Close Functions
•Processing an LDAP Bind Operation
•Processing an LDAP Unbind Opera tion
•Processing an LDAP Search Operation
•Processing an LDAP Compare Operation
•Processing an LDAP Add Operation
•Processing an LDAP Modify Operation
•Processing an LDAP Modify RDN Operation
•Processing an LDAP Dele te Operation
•Processing an LDAP Abandon Operation
77
Page 78
Specifying Start and Close Functions
Specifying Start and Close Functions
For each pre-operation and post-operation plug-in, you can specify the name of a
function to be called after the server starts and before the server is shut down.
Use the following parameters to specify these functions:
SLAPI_PLUGIN_START_FNSpecifies the function called after the Directory Server
starts up.
SLAPI_PLUGIN_CLOSE_FNSpecifies the function called before the Directory Server
shuts down.
If you register multiple plug-ins with different start and close functions, the
functions are called in the order that the plug-ins are registered (in other words, in
the order that the
plugin directives appear in the server configuration file).
Processing an LDAP Bind Operation
When the Directory Server receives an LDAP bind request from a client, the
front-end determines the DN that the client is attempting to bind as and the
authentication method being used. The front-end also gets the credentials used for
authentication, an d (if SASL is used for authe nticat ion), t he SASL mechan ism used.
Defining Functions for the Bind Operation
In the parameter block, the following parameters specify plug-in functions that are
called in the process of executing a bind operation:
•The
•The
You register your plug-in function s by calling
parameters in your initializa tion function. (For details, see “Registering Your
Plug-In Functions” on page 34.)
SLAPI_PLUGIN_PRE_BIND_FN parameter specifies the pre-operation bind
function.
SLAPI_PLUGIN_POST_BIND_FN parameter specifies the post-operation bind
function.
slapi_pblock_set() to set these
78Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 79
Processing an LDAP Unbind Operation
Your pre-operation and post-operation bind functions should return 0 if successful.
If the pre-operation function returns a non-zero value, the post-operation bind
function is never cal led.
For information on defining a func tion that handles authentication, see Chapter 8,
“Defining Functions for Authentication.”
Getting and Setting Parameters for the Bind
Operation
The front-end makes this inform ation available to pre-operation and
post-operation plug-in functions in the form of parameters in a parameter block.
Parameter IDData TypeDescription
SLAPI_BIND_TARGETchar *DN of the entry to bin d as.
SLAPI_BIND_METHODintAuthentication method used, for example,
LDAP_AUTH_SIMPLE or LDAP_AUTH_SASL.
SLAPI_BIND_CREDENTIALSstruct
berval *
SLAPI_BIND_RET_SASLCREDSstruct
berval *
SLAPI_BIND_SASLMECHANISMchar *SASL mechanism used, for example,
Note that i f the
SLAPI_BIND_SASLMECHANISM parameter is empty, simple
Credentials from the bind request.
Credentials that you want sent back to the client.
Set this before calling
slapi_send_ldap_result().
LDAP_SASL_EXTERNAL.
authentication was used and simple credentials were provided.
Processing an LDAP Unbind Oper ation
When the Directory Server receives an LDAP unbind request from a client, the
front-end calls the unbind function for each back-end. No operation-specific
parameters are placed in the parameter block that is passed to the unbind function.
In the parameter block, the following parameters specify plug-in functions that are
called in the process of executing an unbind operation:
Chapter 7Defining Functions for LDAP Operations79
Page 80
Processing an LDAP Search Operation
•The SLAPI_PLUGIN_PRE_UNBIND_FN parameter specifies the pre-operation
unbind function.
•The
SLAPI_PLUGIN_POST_UNBIND_FN parameter specifies the post-operation
unbind function.
You set these parameters to the names of your functio ns by calling
slapi_pblock_set().
Your plug-in functions should return 0 if successful. If the pre-operation function
returns a non-zero value, the post-operation unbind function is never called.
Processing an LDAP Search Operation
The server processes an LDAP search operation in two stages:
•First, the server gets a list of candidate entries, using an index (if applicable).
For example, for a search filter that finds entries where “
checks the index for the “
start with “
a”, and generates a list of matching entries.
mail” attribute (if the index exists), finds the keys that
If no applicable index exists, all entries are considered to be candid a tes.
To get the list of candidates, the server calls the backend search function. For
details, see “Getting the List of Candidates” on page 81.
mail=a*”, the server
•Next, the server iterates through each candidate in the list and determines if
the candidate matches the search criteria.
If an entry matches the criteria, the server sends the entry to the client.
To check each candidate, the server calls the backend “next candidate”
function for each candidate in the list. For details, see “Iterating Through
Candidates” on page 82.
The rest of this section explains these stages in more detail.
80Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 81
Processing an LDAP Search Operation
Getting the List of Candidates
When the Directory Server receives an LDAP search request, the front-end gets
information about the search (such as the scope and base DN). The front-end
normalizes the base DN (by calling the
determines if the base DN identifies a DSA-specific entry (DSE). If so, the front-end
handles the search request directly and does not pass it to the backend search
function.
If the base DN is not a DSE, the front-end finds the back-end that services the suffix
specified in the base DN. The front-end then pas ses the search criteria to the search
function for that back-end.
The front-end makes this inform ation available to pre-operation and
post-operation plug-in functions in the form of parameters in a parameter block.
Parameter IDData TypeDescription
SLAPI_SEARCH_TARGETchar *DN of the base entry in the search
slapi_dn_normalize() function) and
operation (the starting point of
the search).
SLAPI_SEARCH_SCOPEintThe scope of the search. The
scope can be one of the following
values:
•LDAP_SCOPE_BASE
•LDAP_SCOPE_ONELEVEL
•LDAP_SCOPE_SUBTREE
SLAPI_SEARCH_DEREFintMethod for handling aliases in a
search. This method can be one of
the following values:
•LDAP_DEREF_NEVER
•LDAP_DEREF_SEARCHING
•LDAP_DEREF_FINDING
•LDAP_DEREF_ALWAYS
SLAPI_SEARCH_SIZELIMITintMaximum number of entries to
return in the search resul ts.
SLAPI_SEARCH_TIMELIMITintMaximum amount of time (in
SLAPI_SEARCH_STRFILTERchar *String representation of the filter
SLAPI_SEARCH_ATTRSchar **Array of attribute types to be
SLAPI_SEARCH_ATTRSONLYintSpecifies whether the search
opaque data structure)
representing the filter to be used
in the search.
to be used in the search.
returned in the search results.
results return attribute types only
or attribute types and values. ( 0
means return both at tr ib u tes an d
values; 1 means return attribute
types only)
Your search function should return 0 if successful. Call the slapi_pblock_set()
function to assign the set of search results to the
SLAPI_SEARCH_RESULT_SET
parameter in the parameter block.
The front-end then uses this function in conjunction with the “next entry” function
(see “Iterating Through Candidates” on page 82) to iterate through the result set.
The front-end sends each re sult back to the client and continues updates the
SLAPI_NENTRIES parameter with the current number of entries sent back to the
client.
If a result is actually a referral, the front-end sends the referral back to the client
and updates the
SLAPI_SEARCH_REFERRALS parameter with the list of referral
URLs.
Finally, after sending the last entry to the client, the front-end sends an LDAP
result message specifying the number of entries found.
Iterating Through Cand idates
In addition to the parameters specified in “Processing an LDAP Search Operation”
on page 80, the “nex t entry” funct ion has access to the f ollow ing par ameter s (whic h
are set by the front-end and the back-end during the course of executing a search
operation):
82Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 83
Processing an LDAP Search Operation
Parameter IDData TypeDescription
SLAPI_SEARCH_RESULT_SETvoid *Set of search results.
SLAPI_SEARCH_RESULT_ENTRYvoid *Entry returned from iterating
through the results set. This
“next entry” function actua lly
sets this paramet er.
SLAPI_SEARCH_RESULT_ENTRY_EXTvoid *(Netscape Directory Server 4.x)
Reserved for future use.
The context identifying the last
result sent in the results set.
This “next entry” function
actually sets this parameter.
SLAPI_NENTRIESintNumber of search results found
SLAPI_SEARCH_REFERRALSstruct
berval **
Array of the URLs to other
LDAP servers that the current
server is referring the client to
The “next entry” function should get the next result specified in the set of results in
the parameter
as the value of the
SLAPI_SEARCH_RESULT_SET. The function should set this next entry
SLAPI_SEARCH_RESULT_ENTRY parameter in the parameter
block, and the “next entry” function should return 0 if successful.
The “next entry” function should set the
SLAPI_SEARCH_RESULT_ENTRY parameter
to NULL and return -1 if one of the following situations occurs :
•The operation is abandoned (you can check this by calling the
slapi_op_abandoned() function)
•The time limit has been exceeded
•The maximum number of entries has been exceeded
If no more entries exist in the set of results, the “next entry” function should set the
SLAPI_SEARCH_RESULT_ENTRY parameter to NULL and return 0.
Chapter 7Defining Functions for LDAP Operations83
Page 84
Processing an LDAP Compare Operation
Processing an LDAP Compare Operation
When the Directory Server receives an LDAP compare request from a client, the
front-end gets the DN of the entry being compared and the attribute and value
being used in the comparison.
The front-end makes this information available to pre-operation and
post-operation plug-in functions in the form of parameters in a parameter block.
Parameter IDData TypeDescription
SLAPI_COMPARE_TARGETchar *DN of the entry to be compared.
SLAPI_COMPARE_TYPEchar *Attribute type to use in the comparison.
SLAPI_COMPARE_VALUEstruct
berval *
The compare function should call
LDAP_COMPARE_TRUE if the specified value is equal to the value of the entry’s
attribute or
LDAP_COMPARE_FALSE if the values are not equal.
slapi_send_ldap_result() to send
Attribute value to use in the comparison
If successful, the compare function should return 0. If an erro r occurs (f or exam ple,
if the specified attribute doesn’t exist), the compare fun ct ion should call
slapi_send_ldap_result() to send an LDAP error code and should return 1.
Processing an LDAP Add Operation
When the Directory Server receives an LDAP add request from a client, the
front-end normalizes the DN of the new entry. The front-end makes this
information available to pre-operation and post-operation plug-in functions in the
form of parameters in a parameter block.
Parameter IDData TypeDescription
SLAPI_ADD_TARGETchar *DN of the entry to be added.
SLAPI_ADD_ENTRYSlapi_Entry *The entry to be added (specified as the
84Netscape Directory Server Plug-In Programmer’s Guide • December 2003
opaque Slapi_Entry datatype).
Page 85
Processing an LDAP Add Operation
The add function should check the following:
•If the operation has been abandoned, the function should return -1. (You do
not need to call
slapi_send_ldap_result() to send an LDAP error code to
the client. According to the LDAP protocol, the client does not expect a server
response after an operation is abandoned.)
•If the entry already exists in the database, the function should call
slapi_send_ldap_result() to send an LDAP error code
LDAP_ALREADY_EXISTS and should return -1.
•If the parent entry (or the closest matching entry) is a referral entry (an entry
with the object class “ref”) and no manageDSAIT control is included with the
request, the function should call
slapi_str2filter() to send a referral and
return -1.
To determine if a manageDSAIT control is present, call
to get the value of the
SLAPI_MANAGEDSAIT parameter. If the value is 1, the
slapi_pblock_get()
control is included in the request. If 0, the control is not included in the request.
•If the parent entry does not exist, the function should call
slapi_send_ldap_result() to send an LDAP error code
LDAP_NO_SUCH_OBJECT and return -1.
•If the entry is not schema-compliant (call
determine this), the function should call
the LDAP error code
LDAP_OBJECT_CLASS_VIOLATION and should return -1.
slapi_entry_schema_check() to
slapi_send_ldap_result() to send
•If the requestor does not have permission to add the entry (call
slapi_access_allowed() to determine this), the function should call
slapi_send_ldap_result() to send the LDAP error code
LDAP_INSUFFICIENT_ACCESS and should return -1.
You should also verify that the ACI syntax for the entry is correct (call
slapi_acl_check_mods() to determine this).
If the add function is successful, the function should call
slapi_send_ldap_result() to send an LDAP_SUCCESS code back to the client
and should return 0.
Chapter 7Defining Functions for LDAP Operations85
Page 86
Processing an LDAP Modify Operation
Processing an LDAP Modify Operation
When the Directory Server receives an LDAP modify request from a client, the
front-end gets the DN of the entry to be modified and the modifications to be
made. The front-end makes this information available to pre-operation and
post-operation plug-in functions in the form of parameters in a parameter block.
Parameter IDData TypeDescription
SLAPI_MODIFY_TARGETchar *DN of the entry to be modified.
SLAPI_MODIFY_MODSLDAPMod **A NULL-terminated array of LDAPMod
structures, which represent the
modifications to be performed on the entry.
The modify function should check the following:
•If the operation has been abandoned, the function should return -1. (You do
not need to call slapi_send_ldap_result() to send an LDAP error code to
the client. According to the LDAP protocol, the client does not expect a server
response after an operation is abandoned.)
•If the entry is a referral entry (an entry with the object class “ref”) and no
manageDSAIT control is included with the request, the function should call
slapi_str2filter() to send a referral and return -1.
To determine if a manageDSAIT control is present, call
to get the value of the
SLAPI_MANAGEDSAIT parameter. If the value is 1, the
slapi_pblock_get()
control is included in the request. If 0, the control is not included in the request.
•If the entry does not exist, check the following:
❍If the closest matching entry is a referral entry and if no manageDSAIT
control is included in the request, the function should call
slapi_send_ldap_referral() to send a referral and return -1.
❍Oth e rwise, the function should call slapi_send_ldap_result() to send
an LDAP error code
•If the entry is not schema-compliant (call
determine this), the function should call
the LDAP error code
LDAP_NO_SUCH_OBJECT and return -1.
slapi_entry_schema_check() to
slapi_send_ldap_result() to send
LDAP_OBJECT_CLASS_VIOLATION and should return -1.
86Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 87
Processing an LDAP Modify RDN Operation
•If the RDN of the entry contains attribute values th at are not part of th e entry
(for example, if the RDN is “uid=bje nsen” but the entry has no uid value or has
a different uid value), the function should call
send the LDAP error code
LDAP_NOT_ALLOWED_ON_RDN and should return
slapi_send_ldap_result() to
-1.
•If the requestor does not have permission to modify the entry (call
slapi_access_allowed() to determine this), the function should call
slapi_send_ldap_result() to send the LDAP error code
LDAP_INSUFFICIENT_ACCESS and should return -1.
You should also verify that the ACI syntax for the entry is correct (call
slapi_acl_check_mods() to determine this).
If the modify function is successful, the function should call
slapi_send_ldap_result() to send an LDAP_SUCCESS code back to the client
and should return 0.
Processing an LDAP Modify RDN Operation
When the Directory Server receives an LDAP modify RDN request from a client,
the front-end gets the original DN of the entry, the new RDN, and (if the entry is
moving to a different location in the directory tree) the DN of the new parent of the
entry.
The front-end makes this inform ation available to pre-operation and
post-operation plug-in functions in the form of parameters in a parameter block.
Parameter IDData TypeDescription
SLAPI_MODRDN_TARGETchar *DN of the entry that you want to
rename.
SLAPI_MODRDN_NEWRDNchar *New RDN to assign to the en try.
SLAPI_MODRDN_DELOLDRDNintSpecifies whether or not you want to
delete the old RDN. (0 means don’t
delete the old RDN; 1 means delete
the old RDN)
SLAPI_MODRDN_NEWSUPERIORchar *DN of the new parent of the entry, if
the entry is being moved to a new
location in the directory tree.
Chapter 7Defining Functions for LDAP Operations87
Page 88
Processing an LDAP Modify RDN Operation
The modify RDN function should check the following:
•If the operation has been abandoned, the function should return -1. (You do
not need to call
the client. According to the LDAP protocol, the client does not expect a server
response after an operation is abandoned.)
•If the entry is a referral entry (an entry with the object class “ref”) and no
manageDSAIT control is included with the request, the function should call
slapi_str2filter() to send a referral and return -1.
slapi_send_ldap_result() to send an LDAP error code to
To determine if a manageDSAIT control is present, call
to get the value of the
SLAPI_MANAGEDSAIT parameter. If the value is 1, the
slapi_pblock_get()
control is included in the request. If 0, the control is not included in the request.
•If the entry does not exist, check the following:
❍If the closest matching entry is a referral entry and if no manageDSAIT
control is included in the request, the function should call
slapi_send_ldap_referral() to send a referral and return -1.
❍Oth e rwise, the function should call slapi_send_ldap_result() to send
an LDAP error code
•If the entry is not schema-compliant (call
determine this), the function should call
the LDAP error code
LDAP_NO_SUCH_OBJECT and return -1.
slapi_entry_schema_check() to
slapi_send_ldap_result() to send
LDAP_OBJECT_CLASS_VIOLATION and should return -1.
•If the RDN of the entry contains attribute values that are not part of the entry
(for example, if the RDN is “uid=bje nsen” but the entry has no uid value or has
a different uid value), the function should call
send the LDAP error code
LDAP_NOT_ALLOWED_ON_RDN and should return
slapi_send_ldap_result() to
-1.
•If the requestor does not have permission to modify the entry (call
slapi_access_allowed() to determine this), the function should call
slapi_send_ldap_result() to send the LDAP error code
LDAP_INSUFFICIENT_ACCESS and should return -1.
You should also verify that the ACI syntax for the entry is correct (call
slapi_acl_check_mods() to determine this).
If the modify RDN function is succes sf ul, the function should call
slapi_send_ldap_result() to send an LDAP_SUCCESS code back to the client
and should return 0.
88Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 89
Processing an LDAP Delete Operation
Processing an LDAP Delete Operation
When the Directory Server receives an LDAP delete request from a client, the
front-end gets the DN of the entry to be removed from the directory. The front-end
makes this information ava ilable to pre-operation and post-operation plug-in
functions in the form of parameters in a parameter block .
Parameter IDData TypeDescription
SLAPI_DELETE_TARGETchar *DN of the entry to delete.
If the delete function is successful, it should return 0.
Processing an LDAP Abandon Operation
When the Directory Server receives an LDAP abandon request from a client, the
front-end gets the message ID of the operation that should be abandoned. The
front-end makes this information available to pre-operation and post-operation
plug-in functions in the form of parameters in a parameter block.
Parameter IDData TypeDescription
SLAPI_ABANDON_MSGIDunsigned longMessage ID of the operation to
abandon.
Chapter 7Defining Functions for LDAP Operations89
Page 90
Processing an LDAP Abandon Operation
90Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 91
Chapter8
Defining Functions for Authentication
This chapter explains how to write a plug-in function to bypass or replace the
standard function for authentication with your own f unction.
Information on authentication with the Netscape Directory Server (Directory
Server) is organized in the following sections:
•Understanding Authentication Me thods
•How the Directory Server Identifies Clients
•How the Authentication Process Works
•Writing Your Own Authentication Plug-in
•Writing a Pre-Operation Bind Plug-in
•Using SASL with an LDAP Client
Understanding Authentication Methods
Authentication methods for LDAP is described in RFC 2829, which you can find at
this location:
Two methods that you can use to authenticate clients are simple authentication and
SASL authentication:
•Simple authentication is de scribed in RFC 2251, which you can find at this
location:
Simple authentication provides minimal facilities for authentication. In the
simple authentication method, clients send a DN and password to the server
for authentication. The server compares the password sent by the client against
the password stored in the client’s directory entry.
http://www.ietf.org/rfc/rfc2829.txt
http://www.ietf.org/rfc/rfc2251.txt
91
Page 92
How the Directory Server Identifies Clients
•Simple Authentication and Security Layer (SASL) is described in RFC 2222,
which you can find a t this location:
http://www.ietf.org/rfc/rfc2222.txt
SASL provides the means to use mechanisms other than simple authentication
and SSL to authenticate to the Directory Server.
How the Directory Server Identifies Clients
The server keeps track of the identity of the LDAP client through the
SLAPI_CONN_DN and SLAPI_CONN_AUTHTYPE parameters.
During an LDAP bind operation, the server authenticates the user and puts the DN
and authenticated method in the
parameters.
When an authenticated client requests the server to perform an LDAP operation,
the server checks the DN in the
client has the appropriate access rights.
SLAPI_CONN_DN and SLAPI_CONN_AUTHTYPE
SLAPI_CONN_DN parameter to determine if the
How the Authentication Process Works
When the Directory Server receives an LDAP bind request from a client, it
processes the request in the following steps:
1.The server parses the LDAP bind request and retrieves the following
information:
❍The D N that the client is attempting to authenticate as
❍The met ho d of authentication used
❍Any credentials (such as a password) included in the request
If the method of authentication is
server also retrieves the name of the SASL mechanism used from the LDAP
bind request.
2.The server normalizes the DN retrieved from the request. (See the
slapi_dn_normalize() function for more information on normalized DNs.)
3.The server retrieves any LDAP v3 controls included with the LDAP bind
request.
LDAP_AUTH_SASL (SASL authentication), the
92Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 93
How the Authentication Process Works
4.If the method of auth entica tion is LDAP_AUTH_SASL (SASL authentication), the
server determines whether or not the SASL mechanism (specified in the
request) is supported.
If the SASL mechanism is not supported by the server, the server sends an
LDAP_AUTH_METHOD_NOT_SUPPORTED
result code back to the cli ent and ends the
processing of the bind request.
5.If the method of auth entica tion is LDAP_AUTH_SIMPLE (simple authentication),
the server checks if the DN is an empty string or if there are no credentials.
If the DN is an empty string, if the DN is not specified, or if no credentials are
specified, the server assumes that the client is binding anonymously and sends
an
LDAP_SUCCESS result code back to the client.
The DN and authentication method for the connection (which are used to
determine access rights for all operations performed through the connection)
are left as NULL and
6.If the DN specified in the request is not served by this Directory Server (for
example, if the DN is
root of the server is
SLAPD_AUTH_NONE, respectively.
“uid=moxcross, o=netscape.com” and the directory
“o=example.com”), the server sends one of the following
two results back to the client and ends the processing of the bind request:
❍If the server is configured with a default referral (an LDAP URL
identifying an LDAP server that handles referrals), the server sends an
LDAP_REFERRAL
result code back to the client (LDAP_PARTIAL_RESULTS if
the client only supports the LDAP v2 protocol).
❍If the server is not configured with a default referral, the server sends an
LDAP_NO_SUCH_OBJECT
result code back to the client.
7.The server puts the information from the bind request into the parameter
block:
❍SLAPI_BIND_TARGET is set to the DN that the client is authenticating as.
❍SLAPI_BIND_METHOD is set to the auth entica tion method (for example,
LDAP_AUTH_SIMPLE or LDAP_AUTH_SASL).
❍SLAPI_BIND_CREDENTIALS is set to the credentials (for example, the
password) included in the request.
❍SLAPI_BIND_SASLMECHANISM (if the authentication m ethod is
LDAP_AUTH_SASL
) is set to the name of the SASL mechanism that the client
is using for authentication.
8.If the DN is the root DN or the update DN (the DN of the master entity
responsible for replicating the directory), the server authenticates the client.
Chapter 8Defining Functions for Authentication93
Page 94
How the Authentication Process Works
❍If the credentials are correct, the server sets the SLAPI_CONN_DN
parameter to the DN and the SLAPI_CONN_AUTHTYPE parameter to
LDAP_AUTH_SIMPLE
to the client and ends the processing of the bind request.
❍If the credentials are incorrect, the server sends an
LDAP_INVALID_CREDENTIALS
processing of the bind request.
9.The server calls any pre-operation bind plug-in functions. If the function
returns a non-zero value, the server ends the processing of the bind request.
If you are writing your own plug-in fun c tion to handle authentication, you
should return a non-zero value so that the server does not attempt to co ntinue
processing the bind request.
10. The server calls the backend bind function. The bind function returns one of
the following values:
❍If the function returns a non-zero value (SLAPI_BIND_FAIL_OR_ANONYMOUS
in Netscape Directory Server 4.x), the server ends the processing of the
bind request. The bind function is responsible for sending the appropriate
result code back to the client before returning a non-zero value.
. The server sends an LDAP_SUCCESS result code back
result code back to the client and ends the
❍If the function returns 0 (SLAPI_BIND_SUCCESS in Netscape Directory
Server 4.x), the server continues processing the bind request. The server
sends the
LDAP_SUCCESS result code back to the client. (The bind function
does not do this.)
11. If the backend bind function succeeds, the server sets the SLAPI_CONN_DN
parameter to the DN and the SLAPI_CONN_AUTHTYPE parameter to the
authentication method.
12. The server sends an LDAP_SUCCESS result code back to the client and ends the
processing of the bind request.
If the client’s password is going to expire, the server includes a “password
expiring” control (with the OID 2.16.840.1.113730.3.4.5) with the result sent to
the client. If the client is logging in for the first time and needs to change the
password, the server includes a “password expired” control (with the OID
2.16.840.1.113730.3.4.4) with the result sent to the client.
94Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 95
Writing Your Own Authentication Plug-in
Writing Your Own Authenti cation Plug-in
A situation may arise in which you may want to write and implement your own
function for authentication; that is, replace the standard m e an s of authentication
with your own function. You can write a pre-operation bind plug-in function (a
function that the server calls before processing an LDAP bind request) that
performs the authentication and bypasses the default bind function al ity. For
details, see the next section, “Writing a Pre-Operation Bind Plug-in” on page 95.
Writing a Pre-Operation Bind Plug-in
You can define your own pre-operation bind plug-in fu nc tion to authentica te
LDAP clients. The server will call your function during the authentication process
(in Step 9). Your function should return a non-zero value to bypass the default
backend bind function and the post-operation bind functions.
Note that this means that Step 10 through Step 12 are skipped. Your pre-operation
plug-in function is responsible for sending the result code to the client and for
setting the DN and authentication method for the conn ection.
Figure 8-1 summarizes the process of using a pre-operation bind plug-in function
to authenticate LDAP clients to the Directory Server.
Chapter 8Defining Functions for Authentication95
Page 96
Writing a Pre-Operation Bind Plug-in
Figure 8-1Using a Pre-Operation Bind Plug-In Function to Handle Authentication
Figure 8-2 illustrates the steps that your pre-operation bind plug-in function must
take to authenticate LDAP clients to the Directory Server.
96Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 97
Writing a Pre-Operation Bind Plug-in
Figure 8-2How Your Pre-Operation Bind Plug-In Function Can Authenticate LDAP
Clients
Defining Your Authentication Function
The following sections cover guidelin es that you can follow when defining your
authentication function:
•Getting and Checking the Bind Parameters
•Getting the Entry and Checking the Credentials
•What to Do If Authentication Fail s
•What to Do If Authentication Succeeds
NOTEBe sure to check this source file for an example of a pre-operation
Call the slapi_pblock_get() function to get the values of the following
parameters:
SLAPI_BIND_TARGET (a string value specifying the DN that the client is
•
attempting to authenticate as)
•
SLAPI_BIND_METHOD (an integer value specifying the authentication method,
such as
LDAP_AUTH_SIMPLE or LDAP_AUTH_SASL)
Chapter 8Defining Functions for Authentication97
Page 98
Writing a Pre-Operation Bind Plug-in
•SLAPI_BIND_CREDENTIALS (a berval structure containing the credentials sent
by the client)
If you plan to support authentication th rough SASL mechanisms, you should also
get the value of the
specifying the name of the SASL mechanism to use for authentication).
Make sure to check the following:
•Determine if the client is requesting to bind as an anonymous user.
If the
SLAPI_BIND_CREDENTIALS parameter is empty or NULL, the client is
attempting to bind anonymously.
Call
back to the client.
SLAPI_BIND_SASLMECHANISM parameter (a string value
SLAPI_BIND_METHOD parameter is LDAP_AUTH_SIMPLE and the
slapi_send_ldap_result() to send the LDAP result code LDAP_SUCCESS
•If the
SLAPI_BIND_METHOD parameter specifies a method that you do not
recognize or support, call
LDAP_STRONG_AUTH_NOT_SUPPORTED result code back to the client.
slapi_send_ldap_result() to send an
In both cases, return a non-zero value to prevent the server from calling the default
backend function for authentication.
Getting the Entry and Checking the Credentials
Get the entry for the DN specified by the SLAPI_BIND_TARGET parameter and
compare the credentials in the
known credentials for that entry.
By default, Directory Server 4.x uses the
credentials for an entry. The server encodes the password using the scheme
specified in the
scheme can be
passwdhash directive of the slapd.conf configuration file. The
crypt or sha or“ “ (for cleartext).
By default, Directory Server 6.x uses the
credentials for an entry. The server encodes the password using the scheme
specified in the
attributes of the
nsslapd-rootpwstoragescheme or passwordStorageScheme
cn=config entry contained in the dse.ldif file. The scheme can
be any of the following:
SLAPI_BIND_CREDENTIALS parameter against the
userpassword attribute to store the
userpassword attribute to store the
CLEAR (means no encryp tion and can be defi ned using the
•
clear-password-storage-scheme plug-in)
•
CRYPT (means Unix crypt algorithm and can be define d using the
crypt-password-storage-scheme plug-in)
98Netscape Directory Server Plug-In Programmer’s Guide • December 2003
Page 99
Writing a Pre-Operation Bind Plug-in
•SHA (means Secure Hashing Algorithm and can be defined using the
sha
-password-storage-scheme plug-in)
SSHA (means Salted Secure Hashing Algorith m and can be defined using the
•
ssha-password-storage-scheme plug-in)
If you need to compare the client’s credentials against the value of the
userpassword attribute, you can call the slapi_pw_find_sv() function. This
function determines whi c h password scheme was used to store the password and
uses the appropriate comparison function to compare a given value against the
encrypted value of the
userpassword attribute.
What to Do If Authentication Fails
If authentication fails, send one of the following result codes back to the client:
•If no entry matches the DN specified by the client, send an
LDAP_NO_SUCH_OBJECT result code back to the client.
When calling the
back to the client, specify the closest matching DN as th e
slapi_send_ldap_result() function to send the result code
matched argument.
•If the client fails to provide the necessary cre dentials or if cred entials cannot be
found in the entry, send an
LDAP_INAPPROPRIATE_AUTH result code back to the
client.
•If the credentials specified by the client do not match the credentials found in
the entry, send an
•If a general error occurs, send an
LDAP_INVALID_CREDENTIALS result code back to the client.
LDAP_OPERATIONS_ERROR result code back to
the client.
Your function should also return a non-zero value
(
SLAPI_BIND_FAIL_OR_ANONYMOUS in Netscape Directory Server 4.x).
You do not need to set any values for the
SLAPI_CONN_AUTHTYPE
and
LDAP_AUTH_NONE, which indicate that the client has bound anonymously.
parameter. By default, these parameters are set to NULL
SLAPI_CONN_DN parameter and the
What to Do If Authentication Succeeds
If the authentication is successful, your authentica tion function should do the
following:
•Call
and the
method.
slapi_pblock_set() to set the values of the SLAPI_CONN_DN parameter
SLAPI_CONN_AUTHTYPE parameter to the DN and authentication
Chapter 8Defining Functions for Authentication99
Page 100
Writing a Pre-Operation Bind Plug-in
This sets the DN and authentication method for the connection to the clien t.
(The server uses this DN and method in subsequent operations when checking
access rights.)
You can set
❍SLAPD_AUTH_NONE represents no authentication. (The client is binding
SLAPI_CONN_AUTHTYPE to one of the following values:
anonymously.)
❍SLAPD_AUTH_SIMPLE represents the simple authentication method.
❍SLAPD_AUTH_SSL represents authentication through SSL.
❍SLAPD_AUTH_SASL represents SASL authentication.
Note that these values differ from the values in the
parameter. The values listed above are string values defined in the
slapi-plugin.h
parameter (such as
values defined in the
header file, whereas the values of the SLAPI_BIND_METHOD
LDAP_AUTH_SIMPLE and LDAP_AUTH_SASL) are integer
ldap.h header file.
SLAPI_BIND_METHOD
•If you want to, specify the credentials that you want sent back to the client.
If the value of the
you want to return a set of credentials to the client, call
to set the
SLAPI_BIND_RET_SASLCREDS parameter to the credentials.
SLAPI_BIND_METHOD parameter is LDAP_AUTH_SASL and
slapi_pblock_set()
•Send the result of the authentication process back to the client.
slapi_send_ldap_result() to send an LDAP_SUCCESS return code to
Call
the client.
Make sure that your function returns a non-zero value to bypass the default
backend bind function and any post-operation plug-in functions.
Registering the SASL Mechanism
If you are using SASL as the authentication method, you need to register the SASL
mechanisms t hat you plan to use.
In your initialization function (see “Writing Plug-in Initialization Functions” on
page 32), call the
of the SASL mechanism. For example: