Plug-in Programmerís Guide
Red Hat Directory Server                                                            


Chapter 5

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:

The front-end functions are declared in the slapi-plugin.h header file.

Logging Messages

To write an error message to the error log, call the slapi_new_condvar() function. For example, the following slapi_log_error() function call writes a message in the error log:

slapi_log_error( SLAPI_LOG_PLUGIN, "searchdn_preop_search",

This call will create the following message in the error log:

[01/Oct/1997:02:24:18 -0700] searchdn_preop_search \

Make sure that the Directory Server is configured to log messages that have the severity that you specify (for example, SLAPI_LOG_PLUGIN). For more information, see "Setting the Log Level of the Server," on page 54.

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:


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 SLAPI_OPERATION_NOTES parameter to the flag SLAPI_OP_NOTE_UNINDEXED. This parameter identifies any notes that need to be appended to access log entries. Currently, 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.

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:

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 );

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 slapi_op_abandoned(). For example:

if ( slapi_op_abandoned( pb ) ) {
  slapi_log_error( SLAPI_LOG_PLUGIN, "my_function",
    "The operation was abandoned.\n" );
  return 1;

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 datatype to get attribute value pairs. The front-end routines listed in Table 5-1 are designed to help you manipulate entries passed in parameter blocks. These functions are described in more detail in the sections that follow the table.

Table 5-1 Front-End Functions for Manipulating Entries and Attributes  
Front-end function
Allocate memory for a new entry.
Copy an entry.
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.
Verify that an entry complies with the schema.
Get the attributes of an entry.
Find the values for a specified attribute.
Merge an attribute and its values into an entry.
Add values to an attribute in an entry.
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:

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. Once you create a new entry, you should call other front-end routines to set the DN and attributes of the entry.
To make a copy of an existing entry, call the slapi_entry_dup() routine. This function returns a pointer to a new entry of the datatype Slapi_Entry 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:

dn:[:] dn \n
attr :[:] value \n]
attr :[:] value \n]
space    continuedvalue \n]*

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

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:

This function returns the LDIF string representation of the entry or NULL if an error occurs. When you no longer need to use the string, you should free it from memory by calling the slapi_ch_free() function.
This function returns an entry of the datatype 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() function.

Calling slapi_str2entry() 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.

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:

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:

Once you find the attribute you are looking for, use slapi_attr_value_find() to return the value of that attribute.

Iterating through the Attributes in an Entry

To iterate through the attributes associated with an entry, call the slapi_entry_first_attr() function to get the first attribute of the entry. This function returns a pointer to the first attribute in the entry. With a pointer to the attribute, you can test to see if it is the attribute in which you are interested.

To retrieve the subsequent attributes in the entry, call slapi_entry_next_attr(), passing to it the pointer to the current attribute in the cookie parameter of the function. Like slapi_entry_first_attr(), slapi_entry_next_attr() returns a pointer to the current attribute.

Once you find the attribute you need, you can retrieve its value using slapi_attr_value_find().

Finding a Specific Attribute in an Entry

To see if an entry contains a specific attribute, call slapi_entry_attr_find(). 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:

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.

If you need to manipulate DNs within parameter blocks, you can call the following front-end routines:

Table 5-2 Front-End Functions for Manipulating DNs  
Determines if a DN is the root DN (the DN of the privileged superuser).
Gets a copy of the parent DN.
Determines if a DN is the child of another DN.
Determines if a DN is a suffix served by one of the server's back-ends.
Normalizes a DN.
Converts all characters in a DN to lowercase.
Normalizes a DN and converts all characters to lowercase.

Determining If a DN Is the Root DN

To determine if a DN is the root DN, call slapi_dn_isroot(). This function returns 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:

cn=Babs Jensen,ou=Product Development,l=US, dc=example,dc=com

In this case, one of the suffixes is:

l=US, dc=example,dc=com

This suffix indicates that the Babs Jensen entry is located in the Example Corporation subtree in the directory tree.

To determine if a value is a suffix for a DN, call slapi_dn_issuffix(). To determine if a DN is one of the suffixes served by the backend, call the slapi_dn_isbesuffix() function.

Server Suffixes

The suffix directive in the server configuration file specifies which DNs are served by a particular backend. For example, suppose the suffix directive is configured to the following:

suffix "l=US, dc=example,dc=com"

Here, all entries within the l=US, dc=example,dc=com subtree are served by this backend.

Getting the Parent DN of a DN

To get a copy of the parent DN for a DN, call the slapi_dn_parent() function or the slapi_dn_beparent() function.

These functions return the parent DN of dn. If dn is a suffix served by the backend, slapi_dn_beparent() will return NULL.

When you are done working with the parent DN, you should free it from memory by calling free().

Normalizing a DN

If you need to compare DNs (for example, if you are searching your database for a particular DN), you should normalize the DNs that you are comparing to ensure that they are properly compared.

You can use the following front-end function to normalize and convert the case of a DN:


These functions operate on the actual DN specified in the argument, not a copy of the DN. If you want to modify a copy of the DN, call slapi_ch_strdup() to make a copy of the DN.

Working with Search Filters

When a client requests an LDAP search operation, the front-end passes the search filter to the backend as part of the parameter block. (The filter is passed through the SLAPI_SEARCH_FILTER parameter. A string representation of the filter is also available in the SLAPI_SEARCH_STRFILTER parameter.)

To manipulate search filters, call the following front-end routines:

Table 5-3 Front-End Functions for Manipulating Filters  
Determine if an entry matches a filter's criteria.
Get the filter type.
Get the attribute type and value used for 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).
Get the type of attribute that the filter is searching for (only applicable to LDAP_FILTER_PRESENT searches).
Get the substring pattern used for the filter (applicable only to LDAP_FILTER_SUBSTRING searches).
Convert a string representation of a filter to a filter of the datatype Slapi_Filter.
Construct a new LDAP_FILTER_AND, LDAP_FILTER_OR, or LDAP_FILTER_NOT filter from other filters.
Get the components of a filter (only applicable to LDAP_FILTER_AND, LDAP_FILTER_OR, and LDAP_FILTER_NOT searches).
Free a filter from memory.

Determining If an Entry Matches a Filter

After retrieving a filter from the SLAPI_SEARCH_FILTER parameter of the parameter block, you can call the slapi_filter_test() function to determine if entries in your database match the filter.

Getting the Filter Type

To determine the type of filter you are using, call slapi_filter_get_choice(). This function returns the filter type, which can be any one of the following values:

Table 5-4 Types of Filters  
Filter Type
The search should find entries matching all filters that are specified in this complex filter.
The search should find entries matching any filter specified in this complex filter.
The search should find entries not matching the specified filter.
The search should find entries that contain a value equal to the specified attribute value.
The search should find entries that contain a value matching the specified substrings.
The search should find entries that contain a value greater than or equal to the specified attribute value.
The search should find entries that contain a value less than or equal to the specified attribute value.
The search should find entries that contain the specified attribute.
The search should find entries that contain a value approximately matching the specified attribute value.

Getting the Search Criteria

To get the search criteria specified by a search filter, call one of the following functions:

Both of these functions will return either a filter component of the complex filter or a NULL value, according to the following:
  • If slapi_list_first() returns a NULL, the complex filter is not of the type LDAP_FILTER_AND, LDAP_FILTER_OR, or LDAP_FILTER_NOT.
  • If slapi_list_next() returns a NULL, the component returned by the call is the last component in the complex filter.

You do not need to free the values returned by the slapi_filter_get_ava(), slapi_filter_get_type(), and slapi_filter_get_subfilt() functions.

Converting a String to a Filter

A search filter can be represented by either the datatype Slapi_Filter or as a string. In a parameter block for a search operation, SLAPI_SEARCH_FILTER is a filter of the datatype Slapi_Filter and SLAPI_SEARCH_STRFILTER is the string representation of that filter. In general, it is easier to specify a filter as a string than it is to construct a filter from the type Slapi_Filter.

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 slapi_filter_join() function.

The slapi_filter_join() function returns the complex filter you've created. When you are done using the complex filter, you should free it by calling slapi_filter_free().

Filters of the type LDAP_FILTER_NOT can have only one component. If the filter type (ftype) is LDAP_FILTER_NOT, you must pass a NULL value for the second filter when calling slapi_filter_join().

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 nsslapd-rootpwstoragescheme or passwordStorageScheme attributes of the cn=config entry contained in the dse.ldif file. The scheme can be any of the following:

To determine if a given password is one of the values of the userPassword attribute, call slapi_pw_find_sv(). This function determines which password 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.


© 2001 Sun Microsystems, Inc. Used by permission. © 2005 Red Hat, Inc. All rights reserved.
Read the Full Copyright and Third-Party Acknowledgments.

last updated May 26, 2005