terms and conditions set forth in the Open Publication License, V1.0 or later (the latest version is presently available at
http://www.opencontent.org/openpub/).
Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder.
Distribution of the work or derivative of the work in any standard (paper) book form for commercial purposes is prohibited unless prior permission is
obtained from the copyright holder.
Red Hat and the Red Hat "Shadow Man" logo are registered trademarks of Red Hat, Inc. in the United States and other countries.
All other trademarks referenced herein are the property of their respective owners.
The GPG fingerprint of the security@redhat.com key is:
CA 20 86 86 2B D6 9D FC 65 F6 EC C4 21 91 80 CD DB 42 A6 0E
20Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 21
Preface
This book describes how to write server plug-ins in order to customize and extend
the capabilities of the Red Hat Directory Server (Directory Server).
•What You Should Already Know (page 21)
•Using Directory Server Plug-in APIs (page 21)
•Document Conventions (page 23)
•Where to Find Directory Server Information (page 24)
What You Should Already Know
This book assumes you have this basic background:
•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 24.
•Programming experience in C or C++.
Using Directory Server Plug-in APIs
Note the following:
•When you install Directory Server, the plug-in related files are placed in this
directory:
21
Page 22
Using Directory Server Plug-in APIs
•The main header file is located here:
•The location and syntax for you to add the plug-in directives are in the
dse.ldif
/opt/redhat-ds/slapd-instance_id/config
the
•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. 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 use
the
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.
The NSPR API allows compliant applications to use system facilities such as
threads, thread synchronization, I/O, interval timing, atomic operations, and
several other low-level services in a platform-independent 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 functions 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 that deal with bervals are deprecated and their use is not recommended. For each
deprecated function, you will find in slapi-plugin.h a corresponding function with an _sv extension
that uses Slapi_Values instead of bervals. The new functions are more efficient than the old ones.
The following internal-operation calls are deprecated. The new internal operation functions that are defined
in slapi-plugin.h take a Slapi_PBlock for extensibility and support the new plug-in configuration
capabilities.
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.
The Directory Server runs on a number of different UNIX platforms; the
information here applies to all versions.
This book uses Uniform Resource Locators (URLs) of this form:
Preface23
Page 24
Where to Find Directory Server Information
http://server.domain/path/file.html
In these URLs,
application (such as
name (such as
and
file.html
server
represents the name of the server on which you run your
research1
example.com
or
www
),
domain
),
path
represents the directory structure on the server,
represents an individual filename.
represents your Internet domain
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 elements (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, placeholders, glossary terms,
variables, and words used in the literal sense.
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:
•Red Hat Directory Server Deployment Guide. Contains procedures for the
day-to-day maintenance of your directory service. Includes information on
configuring server-side plug-ins.
•Red Hat Directory Server Installation Guide. Contains procedures for installing
your Directory Server as well as procedures for migrating from a previous
installation of Directory Server.
•Red Hat Directory Server Administrator’s Guide. Contains procedures for the
day-to-day maintenance of your directory service. Includes information on
configuring server-side plug-ins.
•Red Hat Directory Server Configuration, Command, and File Reference. Contains
information about using the command-line scripts shipped with Directory
Server.
24Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 25
Where to Find Directory Server Information
•Red Hat Directory Server Schema Reference. Contains information about the
Directory Server schema.
•Red Hat Directory Server Gateway Customization Guide. Introduces Directory
Server Gateway and explains how to implement a gateway instance with basic
directory look-up functionality. Also contains information useful for
implementing a more powerful gateway instance with directory authentication
and administration capability.
•Red Hat Directory Server Org Chart. Introduces the Red Hat Directory Server
Org Chart application and explains how to integrate it with an instance of
Directory Server.
•Red Hat Directory Server DSML Gateway Guide. Introduces the Red Hat
Directory Server DSML Gateway function and explains how to customize it for
use as an independent gateway.
For a list of documentation installed with Directory Server, open the
/opt/redhat-ds/manual/en/slapd/index.htm
file.
For the latest information about Directory Server, including current release notes,
complete product documentation, technical notes, and deployment information,
check this site:
http://www.redhat.com/docs/manuals/dir-server/
For a list of LDAP standards-related documents, check this site:
http://www.mozilla.org/directory/standards.html
Preface25
Page 26
Where to Find Directory Server Information
26Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 27
Introduction to Directory Server Plug-ins
Chapter 1, “An Overview of Directory Server Plug-ins”
Chapter 2, “Writing and Compiling Plug-ins”
Chapter 3, “Configuring Plug-ins”
Part1
Chapter 4, “A Quick Example”
27
Page 28
28Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 29
Chapter1
An Overview of Directory Server
Plug-ins
This chapter introduces you to Red Hat 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? (page 29 )
•How Directory Server Plug-ins Work (page 30)
•Types of Directory Server Plug-ins (page 34)
If you have already written a plug-in for Directory Server, refer to “Using Directory
Server Plug-in APIs,” on page 21, 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 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 Server 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.
29
Page 30
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 contained in your applications.
Internally, the Directory Server has hooks 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 situations:
•Before preforming an LDAP operation (for example, before an entry is added
to the directory).
•When adding, modifying, removing, 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 based 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 34.
30Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 31
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 Directory
Server plug-in functions you write, you access and modify the data in the
parameter 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-operation 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 example, you
can write a function that validates data before a new entry is added to the
directory. If the data are 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 are 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 major subsections, the front-end
and the backend.
Chapter 1An Overview of Directory Server Plug-ins31
Page 32
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 backend to read
and write data. The front-end then sends the results back to the client.
The backend reads and writes data to the database containing the directory entries.
The backend abstracts the database from the front-end. The data stored in a
backend is identified by the suffixes that the backend supports. For example, a
backend that supports the
that end with that suffix.
Figure 1-1 illustrates the Directory Server architecture.
dc=example,dc=com
suffix contains directory entries
32Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 33
Figure 1-1Directory Server Architecture
How Directory Server Plug-ins Work
Chapter 1An Overview of Directory Server Plug-ins33
Page 34
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 validation. The server calls a pre-operation/data
validation plug-in function before performing an LDAP operation.
The main purpose of this type of plug-in is to validate data before the data is
added to the directory or before it is used in an operation.
•Post-operation/data notification. The server calls a post-operation/data
notification plug-in function after performing an LDAP operation.
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 fetch. The server calls an entry storage plug-in
function right before writing data to the database backend. The server calls
entry fetch plug-in functions after retrieving an entry from the database
backend.
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-ins.”
•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 define 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 backend database.
Figure 1-2 illustrates how some of these different plug-in types fit into the
Directory Server architecture.
34Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 35
Types of Directory Server Plug-ins
Figure 1-2Architecture of the Directory Server and Server Plug-ins
Chapter 1An Overview of Directory Server Plug-ins35
Page 36
Types of Directory Server Plug-ins
36Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 37
Chapter2
Writing and Compiling Plug-ins
This chapter provides an introduction on how to write and compile Red Hat
Directory Server (Directory Server) plug-ins. chapter 3, “Configuring Plug-ins,”
describes how to load your plug-in into the Directory Server configuration once it
is successfully compiled. This chapter covers the following topics:
If you have already written a plug-in for the Directory Server, refer to the section
“Using Directory Server Plug-in APIs,” on page 21, for information on migrating
your plug-in to the latest version of the Directory Server.
Writing a Plug-in Function
To write a Directory Server plug-in, you must do the following 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 on writing specific plug-in types, refer to the following
chapters:
The interface to the Directory Server plug-in API is located in the
slapi-plugin.h
write. The following line of code shows an example of including this header file:
#include "slapi-plugin.h"
header file. You must include this header file in the plug-ins you
When you install the Directory Server,
plugins/
folder within the server’s root directory. For example:
/opt/redhat-ds/plugins/slapd/slapi/include
slapi-plugin.h
gets installed into the
Passing Data with Parameter Blocks
Often, plug-in functions make use of a parameter block,
passing information to and from the Directory Server. The following plug-in
function types pass a parameter block as a function argument:
•Pre-operation plug-in functions.
•Post-operation 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
Slapi_PBlock
. This argument contains the parameter
values needed to complete the function request. Your plug-in function should
have a prototype similar to the following:
Slapi_PBlock
, for
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 operation 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.
38 Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 39
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 performing. You can also 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 39.
You can also set values in the parameter block during the processing of your
plug-in functions. The Directory Server can then use the new data values to
complete an operation which it might be processing. For details on this, see
“Setting Data in the Parameter Block,” on page 40.
Some of the data that you can retrieve from the parameter block include 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 its individual components. For details, see
“Calling Front-End Functions,” on page 41.
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
slapi_pblock_get()
NOTEOften,
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. 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;
data type. To access the data in a parameter block, call the
function.
slapi_pblock_get()
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.
searchdn_preop_search()
returns a pointer to the actual data.
function gets the DN of
Chapter 2Writing and Compiling Plug-ins39
Page 40
Writing a Plug-in Function
Code Example 2-1Getting Data from the Parameter 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 */
slapi_log_error( SLAPI_LOG_PLUGIN, "searchdn_preop_search",
"Normalized DN: %s\n", dn );
return( 0 );
}
In this code example,
SLAPI_SEARCH_TARGET
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()
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 */
...
parameter to the context of the database.
. For example, you call can
SLAPI_PRIVATE
parameter, which stores private data for the
ldif_back_init()
identifies the parameter in the
slapi_pblock_set()
to change
function sets the value of the
/* 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 )
40 Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 41
Code Example 2-2Setting Values in the Parameter Block (Continued)
"Unable to store database information\n" );
}
...
}
Writing a Plug-in Function
This example uses the function
slapi_log_error()
to notify the user if an error
occurred.
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 include 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 API, 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
(“Logging Messages,” on page 65, details this process).
slapi_log_error()
to log an error message to describe the problem
Chapter 2Writing and Compiling Plug-ins41
Page 42
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 are writing.
Writing Plug-in Initialization Functions
Before the Directory Server can call your plug-in function, the function must be
properly initialized. To do this, you must 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 value to the Directory Server.
NOTE
The initialization function should not do anything more than these three
steps. If you need to perform additional configuration or initialization, use
a start function. This function is specified by using slapi_pblock_set()
with the SLAPI_PLUGIN_START_FN parameter in the initialization
function.
Your initialization function should have a prototype similar to the following:
int my_init_function( Slapi_PBlock pb );
In the initialization function, the Directory Server passes a single argument of
type
Slapi_PBlock
.
Specifying Directory Server Compatibility
You need to specify the compatibility version of your plug-in so that the Directory
Server can determine whether it supports the plug-in.
To specify the plug-in compatibility version, call the
function, and set the
SLAPI_PLUGIN_VERSION
parameter to the version number
associated with the plug-in. For example:
slapi_pblock_set()
42 Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 43
slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, \
SLAPI_PLUGIN_VERSION_03);
Writing Plug-in Initialization Functions
•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 compatible with versions 6.x
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
“Slapi_PluginDesc,” on page 215.
It is advised that you include a plug-in description since the Red Hat Console
displays this information as part of the server configuration information.
To specify plug-in information, call the
SLAPI_PLUGIN_DESCRIPTION
Code Example 2-3Specifying Plug-in Information
Slapi_PluginDesc
structure. For details on this data structure, see
slapi_pblock_set()
function, and set the
parameter to this structure. For example:
/* Specify information about the plug-in */
Slapi_PluginDesc mypdesc = { "test-plugin", "example.com",
"0.5", "sample pre-operation plugin" };
...
/* Set this information in the parameter block */
slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION,
(void *)&mypdesc );
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
.
.
Chapter 2Writing and Compiling Plug-ins43
Page 44
Writing Plug-in Initialization Functions
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
Compatibility,” on page 42, 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
•The description of the server plug-in is contained in the data structure value
sample pre-operation plug-in
Registering Your Plug-in Functions
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 plug-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.
parameter (see “Specifying Directory Server
Slapi_PluginDesc
structure.
.
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 initialization 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 570.
For example, if you want to register
searchdn_preop_search()
as a
pre-operation search function, include the following code in your initialization
function:
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.
44 Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 45
Writing Plug-in Initialization 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 function 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 -1. If the initialization function returns -1, the Directory Server will
exit.
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.
searchdn_preop_search()
searchdn_preop_search()
. After the initialization
before each LDAP
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" );
Chapter 2Writing and Compiling Plug-ins45
Page 46
Compiling a Directory Server Plug-in
Code Example 2-4An Example Initialization Function (Continued)
return( 0 );
}
Compiling a Directory Server Plug-in
Keep in mind the following tips when compiling your server plug-in:
•You need to compile and link your code as a shared object or library. For
example, 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
position-independent code. Consult the documentation for your platform
compiler and linker for details.
ld -G objects -o shared_object
flag, which specifies that you want to generate
as your link
•Make sure that the
/opt/redhat-ds/plugins/slapd/slapi/include
directory is in your include path.
•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 chapter 3, “Configuring Plug-ins,” for details on
how to specify each initialization function 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:
/opt/redhat-ds/plugins/slapd/slapi/examples
The server plug-in API header files are located in the relative path
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
../include
.
46 Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 47
Compiling a Directory Server Plug-in
Code Example 2-5Example Solaris Makefile (Continued)
48 Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 49
Chapter3
Configuring Plug-ins
After you compile your server plug-in, you need to configure the Red Hat
Directory Server (Directory Server) so that it properly loads your plug-in. The
following sections in this chapter show how this is done:
•Creating a Plug-in Configuration File (page 47)
•Loading the Plug-in Configuration File (page 52)
•Passing Extra Arguments to Plug-ins (page 52)
•Setting the Log Level of the Server (page 54)
Creating a Plug-in Configuration 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. This section illustrates
how to create your plug-in entry. The section “Loading the Plug-in Configuration
File,” on page 52, 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. 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
47
Page 50
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 identifies the plug-in:
dn: cn=Example Plug-in,cn=plugins,cn=config
Here, the common name of the plug-in is set to
the DN entry (
cn=plugins,cn=config
) places the entry in the database tree
Example Plug-in
. The rest of
that contains the configuration settings for plug-ins.
•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: /servers/lib/test-plugin.so
•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 Functions,” on page 42.
•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 51.
•Line 9 specifies whether 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
You can also use the Directory Server Console to activate or deactivate the
plug-in once the plug-in is loaded.
48Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 51
Creating a Plug-in Configuration File
•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 version 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 42.
•Line 12 identifies the vendor/author of the plug-in. In the following line, the
vendor is set to
nsslapd-pluginvendor: Example Corporation
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, those plug-ins that you specify must
properly start before your associated plug-in will 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-named
•
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
configuration file, set its value to the names of one or more plug-ins. For example,
in your plug-in configuration file, you could specify the following:
In this example, the plug-in depends on two specifically named plug-ins:
my_pluginA
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 -1
error code.
Plug-in Type Dependencies
and
vendor_plugin
. This configuration line indicates that before
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 the
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 -1 error code.
If you specify a plug-in type dependency, the Directory Server will search for any
and all plug-ins of the type(s) specified. 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 “Summary of Plug-in Directives,” on
page 51.
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 of the cn value of the plug-in entry, which appears
under
cn=plugins,cn=config
deprecated in a future version of the product, it is recommended that you write
your plug-in not to rely on any specific loading order.
50Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
in the
dse.ldif
file. Because this feature may be
Page 53
Creating a Plug-in Configuration File
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.
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 backend 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 backend 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 the database.
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 receiving a
search request with an extensible matching search filter from a client.
This type of plug-in is also called by the server when indexing attributes for the
backend 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 notification function to send notification
to the administrator if certain data have changed.
preoperationDeclares a pre-operation/data validation plug-in, which is called by the server
before performing an LDAP operation.
Example of use: You can define a data validation function to check new entries
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-ins51
Page 54
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 Configuration File
After you have written the plug-in configuration file, you must load it into the
dse.ldif
file, which is located in the
/opt/redhat-ds/slapd-instance_id/config
directory. You can do this either by using an LDAP utility, such as
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
defined in the configuration file
ldapmodify -h my_host -p 389 -a -D "cn= Directory Manager"
-w adminadmin -f example-plugin.ldif
example-plugin.ldif
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; you can either use the
Directory Server Console or use the
stop-slapd
and
Passing Extra Arguments to Plug-ins
The standard method for configuring plug-ins is to provide configuration
parameters as attributes and values in the plug-in entry in the
plug-ins use the
added to that object class in the schema. A better alternative is to define a custom
auxiliary object class which contains the custom plug-in configuration attributes.
extensibleObject
object class, so any custom attribute can be
:
start-slapd
dse.ldif
ldapmodify
scripts.
file. All
, or
52Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 55
Passing Extra Arguments to Plug-ins
Use the plug-in start function (registered in the initialization function with
slapi_pblock_set()
using
SLAPI_PLUGIN_START_FN
) to use the custom
configuration. One of the pblock parameters passed to the start function is the
plug-in entry, as the
SLAPI_ADD_TARGET
parameter. The
slapi_entry_attr_*
family of functions can be used to get and use these values.
Plug-ins can be dynamically configured at run-time by registering DSE callbacks
for the plug-in entry with
slapi_config_register_callback()
.
Example 1:
dn: cn=Test ExtendedOp,cn=plugins,cn=config
objectClass: top
objectClass: nsSlapdPlugin
objectClass: extensibleObject
cn: Test ExtendedOp
nsslapd-pluginPath: /opt/redhat-ds/servers/plugins/slapd/slapi/
This method allows for a much more descriptive configuration, which is easier to
maintain. The attributes beginning with
pam
are specific to the plug-in and used
for its configuration. The plug-in entry is provided to the plug-in start function as
a
Slapi_Entry *
slapi_entry_attr_*
in the
SLAPI_ADD_TARGET
pblock parameter. Use the
family of functions to get the configuration values from
that entry.
For additional information, check the code samples provided here:
/opt/redhat-ds/plugins/slapd/slapi/examples
Setting the Log Level of the Server
If your functions call the
slapi_log_error()
function to write messages 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 page 550.
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
nsslapd-errorlog-level
SLAPI_LOG_PLUGIN
attribute in
cn=config
. Error logging is controlled with the
.
54Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 57
Chapter4
A Quick Example
This chapter provides an example of a pre-operation Red Hat 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 functionality 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 process 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 that is available to your
function. You can get and manipulate the parameter block data by calling various
front-end API functions.
test_preop_search()
including the base DN of the search, the search scope, and the type of filter
used.
test_preop_init()
test_preop_search()
plug-in function for LDAP search operations.
function logs information about the search,
function is the initialization function that registers
as a
SLAPI_PLUGIN_PRE_SEARCH_FN
pre-operation
55
Page 58
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 initialization 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
56 Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 59
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 assumes that the source code is stored in
you are compiling a plug-in named
srchxmpl.so
srchxmpl.c
and that
.)
Chapter 4A Quick Example59
Page 62
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
Registering the Plug-in Example
To register this example plug-in, you should do the following:
1.
Create an LDIF configuration file in an ASCII text editor; see “Creating a
Plug-in Configuration File,” on page 47.
2.
Load the plug-in configuration file; see “Loading the Plug-in Configuration
File,” on page 52.
3.
Shut down the Directory Server.
4.
Restart the Directory Server.
When you restart the Directory Server, it will read the entries in the
dse.ldif
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.)
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 following line in the error
log:
60 Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 63
An Example Pre-Operation Plug-in
Error log messsage here!
Verify that the plug-ins log level is selected. Error logging is controlled with the
nsslapd-errorlog-level
this value to
65536
or set an OR the current value to
attribute in
cn=config
. For the plug-ins log level, set
65536
. (The sample source code
logs messages to the error log with the plug-ins log 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 Example61
Page 64
An Example Pre-Operation Plug-in
62 Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 65
Basic Plug-in Programming Techniques
Chapter 5, “Front-End API Functions
Chapter 6, “Writing Pre/Post-Operation Plug-ins”
Chapter 7, “Defining Functions for LDAP Operations”
Part2
Chapter 8, “Defining Functions for Authentication”
63
Page 66
64Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 67
Chapter5
Front-End API Functions
The Red Hat Directory Server (Directory Server) provides some general-purpose,
front-end API functions that allow you to work with the entries 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 understand how to program other plug-in API functions.
This chapter contains the following sections:
•Logging Messages (page 65)
•Adding Notes to Access Log Entries (page 66)
•Sending Data to the Client (page 66)
•Determining If an Operation Was Abandoned (page 67)
•Working with Entries, Attributes, and Values (page 67)
•Working with DNs and RDNs (page 71)
•Working with Search Filters (page 74)
•Checking Passwords (page 77)
The front-end functions are declared in the
Logging Messages
To write an error message to the error log, call the
For example, the following function call writes a message in the error log:
Make sure that the Directory Server is configured to log messages that have the
severity that you specify (for example,
SLAPI_LOG_PLUGIN
information, see “Setting the Log Level of the Server,” on page 54. The
slapi_log_error()
output, similar to the standard
function allows you to add parameters to and format the
printf()
function. This allows you to add your
own parameters and data to the log output.
Adding Notes to Access Log Entries
When the backend database processes a search operation, it attempts to use
indexes to narrow down the list of candidates matching the search criteria. If the
backend is unable to use indexes, it appends the following string to the access log
entry for the search:
). For more
notes="U"
This note indicates that an unindexed search was performed.
If you are writing your own backend database search function, you can append
this note to access log entries by setting the
to the flag
SLAPI_OP_NOTE_UNINDEXED
need to be appended to access log entries. Currently,
SLAPI_OPERATION_NOTES
parameter
. This parameter identifies any notes that
SLAPI_OP_NOTE_UNINDEXED
is the 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.
66Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 69
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()
•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_send_ldap_referral()
slapi_send_ldap_search_entry()
Sending Data to the Client
function.
function for each entry.
function.
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 Functions67
Page 70
Working with Entries, Attributes, and Values
Working with Entries, Attributes, and Values
This section discusses how to create new entries in the directory 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
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_init()Initialize the entry created with
slapi_entry_alloc().
This must be done before any other operation
can occur on the entry. Otherwise, severe
memory errors may occur.
slapi_entry_dup()Copy an entry.
slapi_entry_free()Free an unused entry from memory.
Convert an entry to an LDIF string
representation and vice versa.
Get or set the DN for an entry.
datatype to get attribute
slapi_entry_schema_check()Verify that an entry complies with the
slapi_entry_first_attr()
slapi_entry_next_attr()
slapi_entry_attr_find()Find the values for a specified attribute.
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.
68Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
schema.
Get the attributes of an entry.
entry.
Page 71
Working with Entries, Attributes, and Values
Table 5-1Front-End Functions for Manipulating Entries and Attributes (Continued)
Front-end functionDescription
slapi_entry_delete_values_sv()Delete values from an attribute in an entry.
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
slapi_entry_alloc()
function.
This function returns a pointer to a new entry of the opaque datatype
Slapi_Entry
. Then, call the
slapi_entry_init()
function to initialize the
entry for use with the other slapi functions. Once you create and initialize a
new entry, you should call other front-end routines to set the DN and
attributes of the entry.
NOTEFailing to call
slapi_entry_init()
after
slapi_entry_alloc()
may cause severe memory problems.
•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 datatype
slapi_entry_dup()
Slapi_Entry
routine. This
that
contains the copied data.
When you are finished using the entry, you should free it from memory by calling
the
slapi_entry_free()
function.
Converting between Entries and Strings
Entries can be stored in LDIF files. When stored in these files, entries are converted
into a string representation. The following format is the LDIF string representation
for a directory entry:
If you want to continue the specification 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, dc=ex
ample
dc=com
Refer to the Red Hat Directory Server Administrator’s Guide for details on DN
syntax.
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 newline.
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_entry2str_with_options()
slapi_entry2str()
Slapi_Entry
and
functions.
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_string()
function.
•To convert an LDIF string representation back to an entry of the datatype
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, you should call the
slapi_entry_free()
NOTECalling
slapi_str2entry()
function.
modifies the value of the string
argument passed into the function (not a copy). If you still want to
use the string representation of the entry, make a copy of the string
before calling this function.
70Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 73
Working with Entries, Attributes, and Values
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
slapi_entry_get_dn()
slapi_entry_set_dn()
function.
function.
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.
To see if an entry complies with the schema, call the
slapi_entry_schema_check()
function.
Getting the Attributes 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.
slapi_entry_attr_find()
function to see if an entry has a
Once you find the attribute you are looking for, use
return the value of that attribute.
slapi_attr_value_find()
Iterating through the Attributes in an Entry
To iterate through the attributes associated with an entry, call the
slapi_entry_first_attr()
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 in which you are interested.
To retrieve the subsequent attributes in the entry, call
slapi_entry_next_attr()
the
cookie
slapi_entry_next_attr()
Once you find the attribute you need, you can retrieve its value using
slapi_attr_value_find()
parameter of the function. Like
function to get the first attribute of the entry. This
, passing to it the pointer to the current attribute in
slapi_entry_first_attr()
returns a pointer to the current attribute.
.
Chapter 5Front-End API Functions71
,
to
Page 74
Working with DNs and RDNs
Finding a Specific Attribute in an Entry
To see if an entry contains a specific attribute, call
This function returns 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 .
•To remove values from an entry, call
•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 the
slapi_entry_attr_merge_sv()
Working with DNs and RDNs
In certain situations, the front-end passes DNs to the backend 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.
slapi_entry_attr_find()
slapi_entry_add_values_sv()
slapi_entry_delete_values_sv()
function.
.
.
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 characters in a DN to lowercase.
72Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Gets a copy of the parent DN.
the server’s back-ends.
Page 75
Table 5-2Front-End Functions for Manipulating DNs (Continued)
FunctionDescription
slapi_dn_normalize_case()Normalizes a DN and converts all characters to
lowercase.
Determining If a DN Is the Root DN
Working with DNs and RDNs
To determine if a DN is the root DN, call
slapi_dn_isroot()
. This function
returns 1 if the specified DN is the root DN of the local database. It returns 0 if the
DN is not the root DN.
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:
To determine if a value is a suffix for a DN, call
determine if a DN is one of the suffixes served by the backend, call the
slapi_dn_isbesuffix()
For more information on suffixes and backend configuration, see the Red Hat
Directory Server Administrator’s Guide.
Babs Jensen
function.
entry is located in the
slapi_dn_issuffix()
Example
. To
Getting the Parent DN of a DN
To get a copy of the parent DN for a DN, call the
the
slapi_dn_beparent()
These functions return the parent DN of dn. If dn is a suffix served by the backend,
slapi_dn_beparent()
When you are done working with the parent DN, you should free it from memory
by calling
function.
will return
slapi_ch_free_string()
NULL
slapi_dn_parent()
function or
.
.
Chapter 5Front-End API Functions73
Page 76
Working with Search Filters
Normalizing a DN
You can use the following front-end function to normalize and convert the case of
a DN:
•Use
•Use
•Use
slapi_dn_normalize()
slapi_dn_ignore_case()
slapi_dn_normalize_case()
to normalize a DN.
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 compare DNs (for example, to search the database for a particular DN), use
the
slapi_sdn_compare()
function instead of normalizing and comparing the
DNs using string functions.
Working with Search Filters
When a client requests an LDAP search operation, the front-end passes the search
filter to the backend as part of the parameter block. (The filter is passed through
the
SLAPI_SEARCH_FILTER
available in the
SLAPI_SEARCH_STRFILTER
parameter. A string representation of the filter is also
to convert all characters in a DN to lowercase.
to both normalize the DN and convert all
to make a copy of the DN.
parameter.)
To manipulate search filters, call the following front-end routines:
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
74Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
comparison in an attribute-value assertion
filter (only applicable to the following searches:
LDAP_FILTER_EQUALITY,
LDAP_FILTER_GE, LDAP_FILTER_LE, and
LDAP_FILTER_APPROX).
Page 77
Table 5-3Front-End Functions for Manipulating Filters (Continued)
FunctionDescription
slapi_filter_get_type()Get the type of attribute that the filter 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).
slapi_str2filter()Convert a string representation of a filter to a
filter of the datatype Slapi_Filter.
slapi_filter_join() Construct a new LDAP_FILTER_AND,
A search filter can be represented by either the datatype
string. In a parameter block for a search operation,
of the datatype
Slapi_Filter
and
SLAPI_SEARCH_STRFILTER
SLAPI_SEARCH_FILTER
Slapi_Filter
is the string
or as a
is a filter
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
.
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, you 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()
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
when calling
LDAP_FILTER_NOT
slapi_filter_join()
slapi_filter_join()
function.
function returns the complex filter you’ve created.
.
can have only one component. If the filter type
, you must pass a NULL value for the second filter
.
Chapter 5Front-End API Functions77
Page 80
Checking Passwords
Checking Passwords
By default, Directory Server uses the
userPassword
attribute to store the
credentials for an entry. The server encodes the password using the scheme
specified in the
attributes of the
nsslapd-rootpwstoragescheme
cn=config
entry contained in the
or
passwordStorageScheme
dse.ldif
file. The scheme can
be any of the following:
•
CLEAR
clear-password-storage-scheme
•
CRYPT
crypt-password-storage-scheme
•
SHA
sha
•
SSHA
the
To determine if a given password is one of the values of the
attribute, call
— Means no encryption and can be defined using the
plug-in.
— Means Unix crypt algorithm and can be defined using the
plug-in.
— Means Secure Hashing Algorithm and can be defined using the
-password-storage-scheme
plug-in.
— Means Salted Secure Hashing Algorithm and can be defined using
ssha-password-storage-scheme
slapi_pw_find_sv()
. This function determines which password
plug-in.
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.
78Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 81
Chapter6
Writing Pre/Post-Operation Plug-ins
This chapter explains how to write functions that the Red Hat Directory Server
(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 Work (page 79)
•Types of Pre-Operation and Post-Operation Functions (page 81)
The Directory Server can perform the following LDAP operations: bind, unbind,
search, modify, add, delete, modifyRDN, compare, and abandon.
NOTEThe Directory Server can also perform extended operations as
defined in the LDAPv3 protocol. For information on implementing
plug-in functions to execute extended operations, see chapter 10,
“Writing Extended Operation Plug-ins.”
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.
79
Page 82
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 backend to service the request. All
pre-operation functions must return before the front-end calls the associated
backend function.
Figure 6-1Calling Pre-Operation and Post-Operation Plug-in Functions
80Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 83
Types of Pre-Operation and Post-Operation Functions
Types of Pre-Operation and Post-Operation Functions
As is the case with other server plug-in functions, pre-operation functions 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 corresponds to the pre-operation or post-operation
function. For more information on the parameter block, see “Getting Data from the
Parameter Block,” on page 39.
Types of Pre-Operation Functions
Table 6-1 lists the Directory Server pre-operation functions and the purpose of each
function.
Table 6-1Functions Called before the Directory Server Executes an Operation
ID in Parameter BlockDescription
slapi_pblock_set()
function to specify
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 86.
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 87.
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 88.
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 91.
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 92.
Chapter 6Writing Pre/Post-Operation Plug-ins81
Page 84
Types of 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 function, see “Processing an LDAP Modify
Operation,” on page 93.
SLAPI_PLUGIN_PRE_MODRDN_FNSpecifies the function called before the Directory Server
executes an LDAP modifyRDN operation. For information on
writing this type of function, see “Processing an LDAP Modify
RDN Operation,” on page 95.
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.
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 97.
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_send_ldap_referral(), 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.
82Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 85
Types of 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 86.
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 87.
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 Operation,” on page 88.
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 91.
SLAPI_PLUGIN_POST_ADD_FNSpecifies the function called after the Directory Server
executes an LDAP add operation. For information on writing
this type of function, see “Processing an LDAP Add
Operation,” on page 92.
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 93.
SLAPI_PLUGIN_POST_MODRDN_FNSpecifies the function called after the Directory Server
executes an LDAP modifyRDN operation. For information
on writing this type of function, see “Processing an LDAP
Modify RDN Operation,” on page 95.
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 96.
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 97.
Chapter 6Writing Pre/Post-Operation Plug-ins83
Page 86
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-operation
entry function 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_send_ldap_referral(), the post-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 post-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 function and then configure the server to load your plug-in.
For details, follow the procedures outlined in “Writing Plug-in Initialization
Functions,” on page 42, and “Configuring Plug-ins,” on page 47.
84Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 87
Chapter7
Defining Functions for LDAP Operations
This chapter explains how to write pre-operation and post-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 Red Hat 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 38.
Slapi_PBlock
. For more
This chapter outlines how to define plug-in functions to do the following:
•Specifying Start and Close Functions (page 85)
•Processing an LDAP Bind Operation (page 86)
•Processing an LDAP Unbind Operation (page 87)
•Processing an LDAP Search Operation (page 88)
•Processing an LDAP Compare Operation (page 91)
•Processing an LDAP Add Operation (page 92)
•Processing an LDAP Modify Operation (page 93)
•Processing an LDAP Modify RDN Operation (page 95)
•Processing an LDAP Delete Operation (page 96)
•Processing an LDAP Abandon Operation (page 97)
Specifying Start and Close Functions
For each pre-operation and post-operation plug-in, you can specify a function to be
called after the server starts and before the server is shut down.
85
Page 88
Processing an LDAP Bind Operation
In the plug-in init function, use the following parameters with
slapi_pblock_set()
SLAPI_PLUGIN_START_FNSpecifies the function called after the Directory Server
SLAPI_PLUGIN_CLOSE_FNSpecifies the function called before the Directory Server
to specify these functions:
starts up.
shuts down.
Processing an LDAP Bind Operation
When the Directory Server receives an LDAP bind request from a client, the
front-end determines the DN as which the client is attempting to bind and the
authentication method being used. The front-end also gets the credentials used
for authentication and, if SASL is used for authentication, the SASL mechanism
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 functions by calling
parameters in your initialization function. (For details, see “Registering Your
Plug-in Functions,” on page 44.)
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 called.
For information on defining a function that handles authentication, see chapter 8,
“Defining Functions for Authentication.”
SLAPI_PLUGIN_PRE_BIND_FN
function.
SLAPI_PLUGIN_POST_BIND_FN
bind function.
parameter specifies the pre-operation bind
parameter specifies the post-operation
slapi_pblock_set()
to set these
86Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 89
Processing an LDAP Unbind Operation
Getting and Setting Parameters for the Bind
Operation
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_BIND_TARGETchar *DN of the entry as which to bind.
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,
If the
SLAPI_BIND_SASLMECHANISM
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.
parameter is empty, simple authentication was
used, and simple credentials were provided.
Processing an LDAP Unbind Operation
When the Directory Server receives an LDAP
front-end calls the
unbind
function for each backend. No operation-specific
parameters are placed in the parameter block that is passed to the
In the parameter block, the following parameters specify plug-in functions that are
called in the process of executing an
unbind
unbind
operation:
request from a client, the
unbind
function.
•The
•The
SLAPI_PLUGIN_PRE_UNBIND_FN
unbind
SLAPI_PLUGIN_POST_UNBIND_FN
unbind
You set these parameters to the names of your functions by calling
slapi_pblock_set()
parameter specifies the pre-operation
function.
parameter specifies the post-operation
function.
.
Chapter 7Defining Functions for LDAP Operations87
Page 90
Processing an LDAP Search Operation
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.
If no applicable index exists, all entries are considered to be candidates.
To get the list of candidates, the server calls the backend search function. For
details, see “Getting the List of Candidates,” on page 88.
•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
function for each candidate in the list. For details, see “Iterating through
Candidates,” on page 90.
The rest of this section explains these stages in more detail.
mail
attribute (if the index exists), finds the keys that
mail=a*
next candidate
, the server
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.
slapi_dn_normalize()
function and
If the base DN is not a DSE, the front-end finds the backend that services the
suffix specified in the base DN. The front-end then passes the search criteria to the
search
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.
88Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
function for that backend.
Page 91
Processing an LDAP Search Operation
Parameter IDData TypeDescription
SLAPI_SEARCH_TARGETchar *DN of the base entry in the search
operation (the starting point of
the search).
SLAPI_ORIGINAL_TARGET_DNchar *The original DN sent by the client
(this DN is normalized by
SLAPI_SEARCH_TARGET);
read-only parameter.
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 results.
SLAPI_SEARCH_TIMELIMITintMaximum amount of time (in
opaque data structure)
representing the filter to be used
in the search.
SLAPI_SEARCH_STRFILTERchar *String representation of the filter
to be used in the search.
SLAPI_SEARCH_ATTRSchar **Array of attribute types to be
returned in the search results.
Chapter 7Defining Functions for LDAP Operations89
Page 92
Processing an LDAP Search Operation
Parameter IDData TypeDescription
SLAPI_SEARCH_ATTRSONLYintSpecifies whether the search
results return attribute types only
or attribute types and values. (0
means return both attributes and
values; 1 means return attribute
types only).
Your search function should return 0 if successful. Call the
function to assign the set of search results to the
SLAPI_SEARCH_RESULT_SET
slapi_pblock_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 90) to iterate through the
result set. The front-end sends each result 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 Candidates
In addition to the parameters specified in “Processing an LDAP Search
Operation,” on page 88, the
parameters (which are set by the front-end and the backend during the course of
executing a search operation):
next entry
function has access to the following
Parameter IDData TypeDescription
SLAPI_SEARCH_RESULT_SETvoid *Set of search results.
SLAPI_SEARCH_RESULT_ENTRYvoid *Entry returned from iterating
90Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
through the results set. This
“next entry” function actually
sets this parameter.
Page 93
Processing an LDAP Compare Operation
Parameter IDData TypeDescription
SLAPI_SEARCH_RESULT_ENTRY_EXTvoid *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 **
The
next entry
the parameter
as the value of the
function should get the next result specified in the set of results in
SLAPI_SEARCH_RESULT_SET
SLAPI_SEARCH_RESULT_ENTRY
. The function should set this next entry
Array of the URLs to other
LDAP servers to which the
current server is referring the
client.
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
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
SLAPI_SEARCH_RESULT_ENTRY
parameter to NULL and return 0.
next entry
function should set the
parameter
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.
Chapter 7Defining Functions for LDAP Operations91
Page 94
Processing an LDAP Add Operation
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
attribute or
LDAP_COMPARE_FALSE
if the specified value is equal to the value of the entry’s
slapi_send_ldap_result()
if the values are not equal.
Attribute value to use in the comparison
If successful, the compare function should return 0. If an error occurs (for
example, if the specified attribute doesn’t exist), the compare function 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.
to send
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
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()
the client. According to the LDAP protocol, the client does not expect a server
response after an operation is abandoned.)
92Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
opaque Slapi_Entry datatype).
to send an LDAP error code to
Page 95
Processing an LDAP Modify Operation
•If the entry already exists in the database, the function should call
slapi_send_ldap_result()
LDAP_ALREADY_EXISTS
and should return -1.
to send an LDAP error code
•If the parent entry (or the closest matching entry) is a referral entry (an entry
with the object class
request, the function should call
ref
) and no
manageDSAIT
slapi_send_ldap_referral()
control is included with the
to send a
referral and return -1.
To determine if a
get the value of the
manageDSAIT
SLAPI_MANAGEDSAIT
control is present, call
slapi_pblock_get()
parameter. If the value is 1, the
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()
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
to send an LDAP error code
slapi_entry_schema_check()
slapi_send_ldap_result()
and should return -1.
•If the requestor does not have permission to add the entry (call
You should also verify that the ACI syntax for the entry is correct; call
slapi_acl_check_mods()
If the
add
function is successful, the function should call
slapi_send_ldap_result()
to determine this.
to send an
LDAP_SUCCESS
code back to the client
and should return 0.
to
to
to send
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.
Chapter 7Defining Functions for LDAP Operations93
Page 96
Processing an LDAP Modify Operation
Parameter IDData TypeDescription
SLAPI_MODIFY_MODSLDAPMod **A NULL-terminated array of LDAPMod
The
modify
•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.)
structures, which represent the
modifications to be performed on the entry.
function should check the following:
slapi_send_ldap_result()
to send an LDAP error code to
•If the entry is a referral entry (an entry with the object class
manageDSAIT
slapi_send_ldap_referral()
To determine if a
to get the value of the
control is included with the request, the function should call
to send a referral and return -1.
manageDSAIT
SLAPI_MANAGEDSAIT
control is present, call
parameter. If the value is 1, the
ref
) and no
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()
❍
Otherwise, the function should call
an LDAP error code
LDAP_NO_SUCH_OBJECT
•If the entry is not schema-compliant (call
determine this), the function should call
the LDAP error code
LDAP_OBJECT_CLASS_VIOLATION
to send a referral and return -1.
slapi_send_ldap_result()
and return -1.
slapi_entry_schema_check()
slapi_send_ldap_result()
and should return -1.
to send
to
to send
•If the RDN of the entry contains attribute values that are not part of the entry
(for example, if the RDN is
has a different
slapi_send_ldap_result()
LDAP_NOT_ALLOWED_ON_RDN
uid
value), the function should call
uid=bjensen
, but the entry has no
to send the LDAP error code
and should return -1.
uid
value or
•If the requestor does not have permission to modify the entry (call
94Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
to determine this), the function should call
to send the LDAP error code
and should return -1.
Page 97
Processing an LDAP Modify RDN Operation
You should also verify that the ACI syntax for the entry is correct; call
slapi_acl_check_mods()
If the
modify
slapi_send_ldap_result()
function is successful, the function should call
to determine this.
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
modifyRDN
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 information 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 entry.
SLAPI_MODRDN_DELOLDRDNintSpecifies whether 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.
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
manageDSAIT
slapi_send_ldap_referral()
slapi_send_ldap_result()
to send an LDAP error code to
ref
) and no
control is included with the request, the function should call
to send a referral and return -1.
Chapter 7Defining Functions for LDAP Operations95
Page 98
Processing an LDAP Delete Operation
To determine if a
to get the value of the
manageDSAIT
SLAPI_MANAGEDSAIT
control is present, call
slapi_pblock_get()
parameter. If the value is 1, the
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()
❍
Otherwise, the function should call
an LDAP error code
LDAP_NO_SUCH_OBJECT
•If the entry is not schema-compliant (call
determine this), the function should call
the LDAP error code
LDAP_OBJECT_CLASS_VIOLATION
to send a referral and return -1.
slapi_send_ldap_result()
and return -1.
slapi_entry_schema_check()
slapi_send_ldap_result()
and should return -1.
to send
to
to send
•If the RDN of the entry contains attribute values that are not part of the entry
(for example, if the RDN is
has a different
slapi_send_ldap_result()
LDAP_NOT_ALLOWED_ON_RDN
uid
value), the function should call
uid=bjensen
, but the entry has no
to send the LDAP error code
and should return -1.
uid
value or
•If the requestor does not have permission to modify the entry (call
You should also verify that the ACI syntax for the entry is correct; call
slapi_acl_check_mods()
If the
modifyRDN
slapi_send_ldap_result()
function is successful, the function should call
to determine this.
to send an
LDAP_SUCCESS
and should return 0.
Processing an LDAP Delete Operation
When the Directory Server receives an LDAP
front-end gets the DN of the entry to be removed from the directory. 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.
delete
code back to the client
request from a client, the
96Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Page 99
Processing an LDAP Abandon Operation
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 Operations97
Page 100
Processing an LDAP Abandon Operation
98Red Hat Directory Server Plug-in Programmer’s Guide • May 2005
Loading...
+ hidden pages
You need points to download manuals.
1 point = 1 manual.
You can buy points or you can get point for every manual you upload.