|
||
|
|
Chapter 5 Front-End API Functions
The Netscape 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
![]()
- Adding Notes to Access Log Entries
![]()
- Sending Data to the Client
![]()
- Determining if an Operation Was Abandoned
![]()
- Working with Entries, Attributes, and Values
![]()
- Working with DNs and RDNs
![]()
- Working with Search Filters
![]()
- Checking Passwords
![]()
The front-end functions are declared in the
slapi-plugin.hheader file.
To write an error message to the error log, call the
slapi_new_condvar()function. For example, the followingslapi_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.Adding Notes to Access Log Entries
When the back-end database processes a search operation, it attempts to use indexes to narrow down the list of candidates matching the search criteria. If the back-end is unable to use indexes, it appends the following string to the access log entry for the search:
This note indicates that an unindexed search was performed.
If you are writing your own back-end database search function, you can append this note to access log entries by setting the
SLAPI_OPERATION_NOTESparameter to the flagSLAPI_OP_NOTE_UNINDEXED. This parameter identifies any notes that need to be appended to access log entries. Currently,SLAPI_OP_NOTE_UNINDEXEDis 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.
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_SUCCESSstatus 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_Entrydatatype 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
Convert an entry to an LDIF string representation and vice versa
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 datatypeSlapi_Entry. Once you create a new entry, you should call other front-end routines to set the DN and attributes of the entry.
- By copying an existing entry
![]()
- To make a copy of an existing entry, call the
slapi_entry_dup()routine. This function returns a pointer to a new entry of the datatypeSlapi_Entrythat 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, o=ex
ample.comRefer to the Netscape 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_Entryto its LDIF string representation, call theslapi_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 theslapi_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 you are interested in.To retrieve the subsequent attributes in the entry, call
slapi_entry_next_attr(), passing to it the pointer to the current attribute in thecookieparameter of the function. Likeslapi_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 return 0 if the entry contains the attribute, -1 if it does not.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.![]()
In certain situations, the front-end passes DNs to the back-end through the parameter block. For example, when calling the add function, the parameter block includes a parameter that specifies the DN of the new entry to be added.
If you need to manipulate DNs within parameter blocks, you can call the following front-end routines:
Table 5-2 Front-End Functions for Manipulating DNs
Determines if a DN is the root DN (the DN of the privileged superuser)
Determines if a DN is a suffix served by one of the server's back-ends
Determining if a DN is the Root DN
To determine if a DN is the root DN, call
slapi_dn_isroot(). This function returns1if the specified DN is the root DN of the local database. It returns0if the DN is not the root DN.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, o=Example Corporation, c=US
In this case, one of the suffixes is:
This suffix indicates that the
Babs Jensenentry is located in theExample Corporationsubtree 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 back-end, call theslapi_dn_isbesuffix()function.The
suffixdirective in the server configuration file specifies which DNs are served by a particular back-end. For example, suppose the suffix directive is configured to the following:suffix "o=Example Corporation, c=US"
Here, all entries within the "o=Example Corporation, c=US" subtree are served by this back-end.
To get a copy of the parent DN for a DN, call the
slapi_dn_parent()function or theslapi_dn_beparent()function.These functions return the parent DN of
dn. Ifdnis a suffix served by the back-end,slapi_dn_beparent()will returnNULL.When you are done working with the parent DN, you should free it from memory by calling
free().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.
When a client requests an LDAP search operation, the front-end passes the search filter to the back-end as part of the parameter block. (The filter is passed through the
SLAPI_SEARCH_FILTERparameter. A string representation of the filter is also available in theSLAPI_SEARCH_STRFILTERparameter.)To manipulate search filters, call the following front-end routines:
Table 5-3 Front-End Functions for Manipulating Filters
Determining if an Entry Matches a Filter
After retrieving a filter from the
SLAPI_SEARCH_FILTERparameter of the parameter block, you can call theslapi_filter_test()function to determine if entries in your database match the filterTo 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:
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, orLDAP_FILTER_APPROX, you can get the attribute and value used in the filter by callingslapi_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 theslapi_filter_get_type()function.![]()
- If the filter type is
LDAP_FILTER_SUBSTRINGS, you can get the attribute type that the filter searches for by callingslapi_filter_get_subfilt().![]()
- To get the components of a complex filter of the type
LDAP_FILTER_AND,LDAP_FILTER_OR, orLDAP_FILTER_NOT, call theslapi_filter_list_first()andslapi_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:
- If
slapi_list_first()returns a NULL, the complex filter is not of the typeLDAP_FILTER_AND,LDAP_FILTER_OR, orLDAP_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(), andslapi_filter_get_subfilt()functions.
Converting a String to a Filter
A search filter can be represented by either the datatype
Slapi_Filteror as a string. In a parameter block for a search operation,SLAPI_SEARCH_FILTERis a filter of the datatypeSlapi_FilterandSLAPI_SEARCH_STRFILTERis 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 typeSlapi_Filter.To convert the string representation of a filter into a filter of the datatype
Slapi_Filter, call theslapi_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 callingslapi_filter_free().Filters of the type
LDAP_FILTER_NOTcan have only one component. If the filter type (ftype) isLDAP_FILTER_NOT, you must pass a NULL value for the second filter when callingslapi_filter_join().
When Directory Server 4.x stores the password for an entry in the
userpasswordattribute, it encodes the password using the scheme specified in thepasswdhashdirective of the configuration file. The scheme can becryptorshaor"" (for cleartext).By default, Directory Server 6.x uses the
userpasswordattribute to store the credentials for an entry. The server encodes the password using the scheme specified in thensslapd-rootpwstorageschemeorpasswordStorageSchemeattributes of thecn=configentry contained in thedse.ldiffile. The scheme can be any of the following:
CLEAR(means no encryption and can be defined using theclear-password-storage-schemeplug-in)![]()
CRYPT(means Unix crypt algorithm and can be defined using thecrypt-password-storage-schemeplug-in)![]()
SHA(means Secure Hashing Algorithm and can be defined using the sha-password-storage-schemeplug-in)![]()
SSHA(means Salted Secure Hashing Algorithm and can be defined using thessha-password-storage-schemeplug-in)![]()
To determine if a given password is one of the values of the
userpasswordattribute, callslapi_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 theuserpasswordattribute.
© 2001 Sun Microsystems, Inc. Portions copyright 1999, 2002-2003 Netscape Communications Corporation. All rights reserved.
Read the Full Copyright and Thrid-Party Acknowledgments.
Last Updated October 30, 2003