Plug-in Programmer’s Guide Red Hat Directory Server |
Previous |
Contents |
Index |
Next |
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:
- 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 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",
"*** PREOPERATION SEARCH PLUGIN ***\n");This call will create the following message in the error log:
[01/Oct/1997:02:24:18 -0700] searchdn_preop_search \
- *** PREOPERATION SEARCH PLUGIN ***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:
- If you need to send a result code back to the client (for example, to report an error or a successful result to an LDAP operation), call the slapi_send_ldap_result() function.
- If you are fulfilling a search request and need to send matching entries back to the client, call the slapi_send_ldap_search_entry() function for each entry.
- If you need to refer the LDAP request to a different LDAP server, call the slapi_str2filter() 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 );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.
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
ample
dc=comRefer 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 Slapi_Entry to its LDIF string representation, call the slapi_filter_free() function.
- This function returns the LDIF string representation of the entry or NULL if an error occurs. When you no longer need to use the string, you should free it from memory by calling the slapi_ch_free() function.
- To convert an LDIF string representation back to an entry of the datatype Slapi_Entry, call the slapi_str2entry() 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.
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 slapi_entry_get_dn() function.
- To set the DN for an entry, call the slapi_entry_set_dn() 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 slapi_entry_attr_find() function to see if an entry has a specific attribute.
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:
- To add new values to an entry, call the slapi_entry_add_values_sv() function .
- To remove values from an entry, call slapi_entry_delete_values_sv().
- In certain situations, you may want to add an attribute and its values to an entry while not replacing any attribute values that already exist. To do this, call the slapi_entry_attr_merge_sv() function.
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:
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=comIn this case, one of the suffixes is:
l=US, dc=example,dc=comThis 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:
- Use slapi_dn_normalize() normalize a DN.
- Use slapi_dn_ignore_case() to convert all characters in a DN to lowercase.
- Use slapi_dn_normalize_case() to both normalize the DN and convert all characters in the DN to lowercase.
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:
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:
Getting the Search Criteria
To get the search criteria specified by a search filter, call one of the following functions:
- If the filter type is LDAP_FILTER_EQUALITY, LDAP_FILTER_GE, LDAP_FILTER_LE, or LDAP_FILTER_APPROX, you can get the attribute and value used in the filter by calling slapi_filter_get_ava().
- If the filter type is LDAP_FILTER_PRESENT, you can get the attribute type that the filter is searching for by calling the slapi_filter_get_type() function.
- If the filter type is LDAP_FILTER_SUBSTRINGS, you can get the attribute type that the filter searches for by calling slapi_filter_get_subfilt().
- To get the components of a complex filter of the type LDAP_FILTER_AND, LDAP_FILTER_OR, or LDAP_FILTER_NOT, call the slapi_filter_list_first() and slapi_filter_list_next() functions.
- Both of these functions will return either a filter component of the complex filter or a NULL value, according to the following:
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:
- CLEAR - Means no encryption and can be defined using the clear-password-storage-scheme plug-in.
- CRYPT - Means Unix crypt algorithm and can be defined using the crypt-password-storage-scheme plug-in.
- SHA - Means Secure Hashing Algorithm and can be defined using the sha-password-storage-scheme plug-in.
- SSHA - Means Salted Secure Hashing Algorithm and can be defined using the ssha-password-storage-scheme plug-in.
To determine if a given password is one of the values of the 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.
Previous |
Contents |
Index |
Next |