From dd758b072fb1a4f58b62866e00ab4e09c8ac2698 Mon Sep 17 00:00:00 2001 From: "richm%stanfordalumni.org" Date: Wed, 20 Jun 2007 14:26:52 +0000 Subject: [PATCH] initial import of docbook contribution from Sun git-svn-id: svn://10.0.0.236/trunk@228382 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/directory/docs/Readme.txt | 24 + .../docs/ldapcsdk/00-Programmers-Guide.book | 114 + mozilla/directory/docs/ldapcsdk/abstract.sgm | 20 + .../docs/ldapcsdk/best-practices.sgm | 378 + .../directory/docs/ldapcsdk/choose-api.sgm | 98 + mozilla/directory/docs/ldapcsdk/csdk-api.sgm | 1465 ++ .../directory/docs/ldapcsdk/csdk-client.sgm | 768 + .../directory/docs/ldapcsdk/csdk-compare.sgm | 438 + .../directory/docs/ldapcsdk/csdk-controls.sgm | 2028 ++ .../docs/ldapcsdk/csdk-datatypes.sgm | 3580 +++ .../directory/docs/ldapcsdk/csdk-extendop.sgm | 389 + .../docs/ldapcsdk/csdk-filter-conf.sgm | 375 + .../docs/ldapcsdk/csdk-functions.sgm | 20727 ++++++++++++++++ .../docs/ldapcsdk/csdk-ldap-urls.sgm | 312 + .../docs/ldapcsdk/csdk-multithread.sgm | 807 + .../docs/ldapcsdk/csdk-quickstart.sgm | 171 + .../docs/ldapcsdk/csdk-resultcodes.sgm | 1480 ++ mozilla/directory/docs/ldapcsdk/csdk-sasl.sgm | 222 + .../directory/docs/ldapcsdk/csdk-search.sgm | 1738 ++ .../docs/ldapcsdk/csdk-server-info.sgm | 374 + mozilla/directory/docs/ldapcsdk/csdk-ssl.sgm | 382 + .../docs/ldapcsdk/csdk-understanding.sgm | 970 + .../directory/docs/ldapcsdk/csdk-whatsnew.sgm | 178 + .../directory/docs/ldapcsdk/csdk-write.sgm | 2118 ++ .../docs/ldapcsdk/figures/hierovrw.eps | Bin 0 -> 378039 bytes mozilla/directory/docs/ldapcsdk/legal.sgm | 113 + mozilla/directory/docs/ldapcsdk/license.txt | 226 + mozilla/directory/docs/ldapcsdk/preface.sgm | 375 + .../docs/ldapcsdk/understanding-ldap.sgm | 274 + .../docs/ldapjdk/00-Programmers-Guide.book | 108 + mozilla/directory/docs/ldapjdk/abstract.sgm | 20 + .../directory/docs/ldapjdk/best-practices.sgm | 378 + mozilla/directory/docs/ldapjdk/choose-api.sgm | 98 + .../docs/ldapjdk/figures/entries.eps | Bin 0 -> 425571 bytes .../docs/ldapjdk/figures/hier1lvl.eps | Bin 0 -> 364963 bytes .../docs/ldapjdk/figures/hierbase.eps | Bin 0 -> 345079 bytes .../docs/ldapjdk/figures/hierovrw.eps | Bin 0 -> 378039 bytes .../docs/ldapjdk/figures/hiersrch.eps | Bin 0 -> 344019 bytes mozilla/directory/docs/ldapjdk/jdk-adding.sgm | 677 + .../docs/ldapjdk/jdk-asynchronous.sgm | 277 + .../docs/ldapjdk/jdk-common-classes.sgm | 617 + .../directory/docs/ldapjdk/jdk-comparing.sgm | 123 + .../directory/docs/ldapjdk/jdk-controls.sgm | 940 + .../docs/ldapjdk/jdk-extended-ops.sgm | 156 + .../docs/ldapjdk/jdk-filter-conf.sgm | 545 + .../directory/docs/ldapjdk/jdk-ldap-urls.sgm | 202 + .../directory/docs/ldapjdk/jdk-quickstart.sgm | 212 + mozilla/directory/docs/ldapjdk/jdk-sasl.sgm | 338 + .../directory/docs/ldapjdk/jdk-searching.sgm | 970 + .../docs/ldapjdk/jdk-server-info.sgm | 575 + mozilla/directory/docs/ldapjdk/jdk-ssl.sgm | 209 + .../docs/ldapjdk/jdk-understanding.sgm | 412 + .../docs/ldapjdk/jdk-writing-client.sgm | 361 + mozilla/directory/docs/ldapjdk/legal.sgm | 113 + mozilla/directory/docs/ldapjdk/license.txt | 226 + mozilla/directory/docs/ldapjdk/preface.sgm | 349 + .../docs/ldapjdk/understanding-ldap.sgm | 274 + 57 files changed, 48324 insertions(+) create mode 100644 mozilla/directory/docs/Readme.txt create mode 100644 mozilla/directory/docs/ldapcsdk/00-Programmers-Guide.book create mode 100644 mozilla/directory/docs/ldapcsdk/abstract.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/best-practices.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/choose-api.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/csdk-api.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/csdk-client.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/csdk-compare.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/csdk-controls.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/csdk-datatypes.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/csdk-extendop.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/csdk-filter-conf.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/csdk-functions.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/csdk-ldap-urls.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/csdk-multithread.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/csdk-quickstart.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/csdk-resultcodes.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/csdk-sasl.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/csdk-search.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/csdk-server-info.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/csdk-ssl.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/csdk-understanding.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/csdk-whatsnew.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/csdk-write.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/figures/hierovrw.eps create mode 100644 mozilla/directory/docs/ldapcsdk/legal.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/license.txt create mode 100644 mozilla/directory/docs/ldapcsdk/preface.sgm create mode 100644 mozilla/directory/docs/ldapcsdk/understanding-ldap.sgm create mode 100644 mozilla/directory/docs/ldapjdk/00-Programmers-Guide.book create mode 100644 mozilla/directory/docs/ldapjdk/abstract.sgm create mode 100644 mozilla/directory/docs/ldapjdk/best-practices.sgm create mode 100644 mozilla/directory/docs/ldapjdk/choose-api.sgm create mode 100644 mozilla/directory/docs/ldapjdk/figures/entries.eps create mode 100644 mozilla/directory/docs/ldapjdk/figures/hier1lvl.eps create mode 100644 mozilla/directory/docs/ldapjdk/figures/hierbase.eps create mode 100644 mozilla/directory/docs/ldapjdk/figures/hierovrw.eps create mode 100644 mozilla/directory/docs/ldapjdk/figures/hiersrch.eps create mode 100644 mozilla/directory/docs/ldapjdk/jdk-adding.sgm create mode 100644 mozilla/directory/docs/ldapjdk/jdk-asynchronous.sgm create mode 100644 mozilla/directory/docs/ldapjdk/jdk-common-classes.sgm create mode 100644 mozilla/directory/docs/ldapjdk/jdk-comparing.sgm create mode 100644 mozilla/directory/docs/ldapjdk/jdk-controls.sgm create mode 100644 mozilla/directory/docs/ldapjdk/jdk-extended-ops.sgm create mode 100644 mozilla/directory/docs/ldapjdk/jdk-filter-conf.sgm create mode 100644 mozilla/directory/docs/ldapjdk/jdk-ldap-urls.sgm create mode 100644 mozilla/directory/docs/ldapjdk/jdk-quickstart.sgm create mode 100644 mozilla/directory/docs/ldapjdk/jdk-sasl.sgm create mode 100644 mozilla/directory/docs/ldapjdk/jdk-searching.sgm create mode 100644 mozilla/directory/docs/ldapjdk/jdk-server-info.sgm create mode 100644 mozilla/directory/docs/ldapjdk/jdk-ssl.sgm create mode 100644 mozilla/directory/docs/ldapjdk/jdk-understanding.sgm create mode 100644 mozilla/directory/docs/ldapjdk/jdk-writing-client.sgm create mode 100644 mozilla/directory/docs/ldapjdk/legal.sgm create mode 100644 mozilla/directory/docs/ldapjdk/license.txt create mode 100644 mozilla/directory/docs/ldapjdk/preface.sgm create mode 100644 mozilla/directory/docs/ldapjdk/understanding-ldap.sgm diff --git a/mozilla/directory/docs/Readme.txt b/mozilla/directory/docs/Readme.txt new file mode 100644 index 00000000000..de942b20735 --- /dev/null +++ b/mozilla/directory/docs/Readme.txt @@ -0,0 +1,24 @@ +The split here is Directory SDK for C versus Directory SDK for Java. + +The content is the very latest I have... but I have been tardy in reading +the developer Wiki, so perhaps some of what I've done is out of sync. I mean +Anton has reviewed the C SDK content and I've updated that to account for +his review comments. Also, I added what was necessary to cover the new +sample code I wrote (and I think Anton checked in). But it might not do +blindly to overwrite anything on the Wiki with what I have here. And it +might require a little post-update Wiki gardening to remove weeds. + +The Directory SDK for C guide includes reference material. The Directory SDK +for Java guide does not, since there should be Javadoc somewhere. If this +assumption is wrong, let me know. I had a script to do that in my home dir +at work. + +This version has the proper license as per +https://bugzilla.mozilla.org/show_bug.cgi?id=369156 + +The top files for each book are named 00-Programmers-Guide.book, so all +the other files are then pulled in through SYSTEM entities. In other words +run validation on the .books. + +Hope it helps, +mark.craig@gmail.com, June 19, 2007 diff --git a/mozilla/directory/docs/ldapcsdk/00-Programmers-Guide.book b/mozilla/directory/docs/ldapcsdk/00-Programmers-Guide.book new file mode 100644 index 00000000000..377b7e0270b --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/00-Programmers-Guide.book @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]> + +LDAP C SDK Programmer's Guide + +MarkCraig + +June 2007 + +Sun Microsystems, Inc. +
+4150 Network Circle +Santa ClaraCA95054 +U.S.A. +
+2000-2007Sun Microsystems, Inc. All Rights Reserved. +License - +The contents of this document are subject to the terms of +the Creative Commons Attribution-ShareAlike 2.5 license or any later version (the +"License"). You may not use this document except in compliance with +the License. +See the License for the specific language governing +permissions and limitations under the License. The full text of the +License is provided at the end of this +document.&legal; + +&abstract; + +
&preface; +&understanding-ldap; +&choose-api; +&best-practices; +&csdk-understanding; +&csdk-quickstart; +&csdk-whatsnew; +&csdk-client; +&csdk-api; +&csdk-search; +&csdk-filter-conf; +&csdk-write; +&csdk-compare; +&csdk-ldap-urls; +&csdk-server-info; +&csdk-ssl; +&csdk-controls; +&csdk-sasl; +&csdk-extendop; +&csdk-multithread; +&csdk-datatypes; +&csdk-functions; +&csdk-resultcodes; + +Creative Commons Attribution-ShareAlike 2.5 +The contents of this document are subject to the terms of the +Creative Commons Attribution-ShareAlike 2.5 license (the +"License"). You may not use this document except in compliance with +the License. +See the License for the specific language governing permissions +and limitations under the License. The full text of the License is as +follows. +&license; + +Index + +
diff --git a/mozilla/directory/docs/ldapcsdk/abstract.sgm b/mozilla/directory/docs/ldapcsdk/abstract.sgm new file mode 100644 index 00000000000..273b411e7ae --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/abstract.sgm @@ -0,0 +1,20 @@ + +This &BookTitle; shows you how to +create LDAP client applications in the C language to connect to LDAP servers. +This guide also shows you how to perform standard LDAP operations. diff --git a/mozilla/directory/docs/ldapcsdk/best-practices.sgm b/mozilla/directory/docs/ldapcsdk/best-practices.sgm new file mode 100644 index 00000000000..8f96271f1d6 --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/best-practices.sgm @@ -0,0 +1,378 @@ + +Best Practices for +Writing Client Applications + + +This chapter includes best practices for developing client applications +and cover the following topics: +Creating Your Application + +Troubleshooting Problems + + + +Creating Your Application + +This section identifies practices to observe when creating directory +client applications. +Specify LDAP v3 + +Authenticate Correctly + +Limit Connection Overhead + +Handle Potential +Inactivity Timeouts +Retrieve Entries Intelligently + +Write Simple, Conforming LDAP +Filters +Performing Specific Modifications + +Trust Result Codes + +Limit Dealings With Groups +and Roles +Read the DSE + +Use Resource-Intensive Features Sparingly +Avoid Hard Coding Certain Information + +Define Schemas Only When Necessary + +Handle Referrals + +Treat a Directory as a Directory + + +Specify LDAP v3 + +Many client libraries default to LDAP v2, but you can elect to use LDAP +v3. To benefit from LDAP v3 features, you can set up the connection, and then +authenticate explicitly using LDAP v3. +With JNDI, you could use LDAP v3 as shown here. +import java.util.Hashtable; +import javax.naming.ldap.InitialLdapContext; + +Hashtable env = new Hashtable(); +env.put("java.naming.ldap.version", "3"); +InitialLdapContext ctx = new InitialLdapContext(env, null); + +With &DirectorySDKForC;, you could use LDAP v3 as shown +here. +#include "ldap.h" + +int version = LDAP_VERSION3; +ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, &version ); +&DirectorySDKForC; uses LDAP v3 by default. +With &DirectorySDKForJava;, you could use LDAP v3 as shown +here. +import netscape.ldap.LDAPConnection; + +LDAPConnection ld = new LDAPConnection(); +ld.setOption(LDAPv3.PROTOCOL_VERSION, new Integer(3)); + + + + + +Authenticate Correctly +Your SDK uses terminology that is slightly different from LDAP v3. In +LDAP v3, you connect, then you bind and perform LDAP operations, then you +unbind and disconnect. The bind is the authentication operation in LDAP. Your +application can hold onto a connection but change the authentication credentials +by using the bind operation again. +Some directories do not allow anonymous access, even for reads. When +you build your application, keep the option that allows users to authenticate +to the directory. Furthermore, the information sent across the network can +be sensitive. You can protect sensitive data by allowing the application to +secure the connection by using Secure Sockets Layer (SSL) or Start Transport +Layer Security (TLS). +If your application needs to authenticate, obtain a regular account +to authenticate with the directory, rather than using the directory superuser +account such as cn=Directory Manager. When you authenticate +as directory superuser, you often bypass normal access control mechanisms. +Bypassing normal access control renders auditing directory access more difficult. + +When authenticating, have your application use SSL or SASL DIGEST MD5 +to avoid sending passwords over the network in clear text. Furthermore, when +using password-based authentication, have your application check password +policy controls, especially to determine when a password must be renewed. + +Limit Connection Overhead +A new connection requires system resources. The LDAP model allows you +to reuse connections by binding again with a different identity on the same +connection. Thus, you can avoid the costs of new connections, particularly +negotiated connections such as connections that use SSL, by reusing connections. +Your application can use a pool of connections, rebinding when necessary. +Your application can alternatively use the proxy authorization control to +remain authenticated as the application but perform operations on behalf of +a particular user. +When establishing a connection, your application can provide alternate +server host names and port numbers to facilitate failover that is transparent +to the application. You can also set time limits for LDAP operations to avoid +getting blocked. +When finished with a connection, your application should perform an +unbind. +Handle Potential Inactivity Timeouts +Most network equipment can use timeouts to drop stale connections, ensuring +the equipment keeps a maximum number of connections that are available. +If your application pools connections or opens connections for persistent +search, than guard against timeouts that drop those connections. Use the connections +occasionally to reset inactivity timers present in the network. +Alternatively, if you have control over the connection, consider disabling +inactivity time outs for your applications that need to keep persistent connections +open. Load balancers and proxy software often use inactivity timeouts. + +Retrieve Entries Intelligently +&cnDirectoryServer; typically responds quickly to requests for entries. +Yet, &cnDirectoryServer; can respond most quickly when your application asks +it to do only necessary work. If you need to read only a few attributes in +an entry, request each attribute explicitly. Avoid reading the entire entry, +then parsing the entire entry to obtain the required data. +Furthermore, when you do request attributes in an entry, retrieve all +the required attributes at once. Each new request involves a new operation +on the server. +If any of the attributes that you require are operational attributes, +you must request those attributes specifically. Such attributes are identifiable +in directory schema by their USAGE, which is directoryOperation + or dsaOperation. +When retrieving entries and attributes, recognize that you might not +have access to all the attributes that exist. +Write Simple, Conforming LDAP Filters + +LDAP filters +writing + +The best filters use attributes that are indexed according to the way +the attributes are indexed. For example, if employeeNumber is +indexed for equality, your filter should be an equality filter such as (employeeNumber=123456) +. Do not use a substring filter instead. +Avoid deeply nested complex filters when you can. When you must use +complex filters, place the most specific filters first to narrow the list +of candidate entries the directory must check. For best results, use not +, !, only with and, & +, for example (&(cn=Barbara)(!(sn=Jensen))). +When you use not with or in a filter, +the directory must construct a candidate list of everything except what your +filter specifies. +Performing Specific Modifications +Modifications are atomic on the entry to which the modifications apply. +When modifying multivalued attributes, delete and replace specific values. +Do not replace an entire list of multiple values to change only a few values. +Replacing specific values is particularly good practice when the changes must +be replicated across a set of servers. +Moreover, when you have large values to store in an attribute, store +a reference to the data instead of storing the data object. +Trust Result Codes + +result codes +trust + +&cnDirectoryServer; trades tight consistency across replica servers +for very high performance, availability, and scalability. By allowing +loose consistency of data across sets of replica servers, &cnDirectoryServer; instances +can respond very quickly to your application. Yet, data replication is not +instantaneous. A short but detectable delay can ensue after a server returns +success for a write operation, but before the effects are seen on other replicas. + +Therefore, when your application receives a result code from &cnDirectoryServer; to +indicate that an operation was successful, your application should trust the +result code. When application requests are balanced across replicas, reading +from another replica might result in errors due to a slight delay in replication. + +Limit Dealings With Groups and Roles + +groups +working with + +When you want to know whether an account belongs to a group or a role, +read only the necessary attribute values. Do not read the entire list of group +members. + +For dynamic groups, do the following: +Read the URL from the group definition. +Examine the host, DN, and scope of the URL. +Apply the filter part of the URL to the entry for the account. + + + +roles +working with +For roles, compare the DN of the role to the +nsRole attribute of the entry for the account, such as (nsrole=cn=management,ou=people,dc=example,dc=com) +. You can then retrieve all the values of the nsRole attribute +for the account. +Read the DSE + +DSE, root +reading + +The root DSE is the entry that is retrieved by ldapsearch -b +"" -s base "(objectclass=*)". The root DSE describes server capabilities. +The root DSE contains information about supported LDAP protocol versions, +naming contexts (suffixes), LDAP v3 controls, LDAP v3 extensions, and authentication +mechanisms. The root DSE can contain information about the server version. +Some directory administrators protect access to the root DSE. Yet, applications +might read the root DSE to confirm that the server in fact supports functionality +required by applications. +Use Resource-Intensive Features Sparingly +Directories offer powerful features that can nevertheless place a heavy +load on the server. Two such features are persistent search, and server-side +sorting. +Persistent search lets you start a search that does not stop when complete, +but instead allows you to receive updates when entries are modified. To provide +this feature, the server must handle your search when anything happens to +an entry in its scope. +Server-side sorting requires that the server sort the entries that are +returned during a search. Instead of returning entries as quickly as possible, +the server must therefore get the list to return, and sort the list. + +Avoid Hard Coding Certain Information +The container entry for a subtree might be not be identical on different +directories. Rather than hard code the container entry throughout your application, +locate the container entry. Then navigate beneath the container entry in the +tree. +Object classes and attribute types for the same information can also +differ from directory to directory. Use configuration files, properties files, +or other easily modifiable variables rather than hard coding object class +and attribute type identifiers into your application. +Be aware as well that object class and attribute type identifiers are +not case-sensitive in LDAP. Your application should therefore recognize +that inetOrgPerson and inetorgperson are +equivalent, as are isMemberOf and ismemberof. + +Define Schemas Only When Necessary + +schema +defining + +Schemas define the object classes and attribute types that are recognized +by the directory. If your application can use a standard schema, use the standard +schema. &cnDirectoryServer; contains schemas that define numerous standard +object classes, and attribute types. + +When you must define your own schema objects, follow these guidelines: +Extend existing object classes by using AUXILIARY classes. + +Create new attributes rather than redefining existing attributes. +Other applications might depend on existing attributes to keep +their existing semantics. +Obtain new object identifiers for the schema elements you +define, rather than reusing existing object identifiers. +Obtain new names for the schema elements you define, rather +than reusing existing names. +Update &cnDirectoryServer; schema over LDAP if you can. + + + +Handle Referrals + +referrals +following + +LDAP v3 allows directories that are unable to handle your request to +refer your application to other directories. Your application should follow +those referrals. +When following referrals, realize that authentication procedures might +not be exactly the same on different directories. Also, directories that refer +to each other could potentially cause a referral loop. With &DirectorySDKForC; and &DirectorySDKForJava;, +you can limit referral hops to prevent your application from being referred +endlessly from one directory to another directory. The JNDI interface enables +you to follow referrals automatically. +Treat a Directory as a Directory +A directory is typically a repository for identity data, and for information +that you expect to keep for awhile and read often. You might typically find +relational databases better adapted to hold transient data such as session +keys and presence information, or voluminous accumulated data such as application +logs. + +Troubleshooting Problems +This section covers basic troubleshooting approaches and techniques +to use when developing directory client applications. You can check result +codes, check server log files, and inspect network packets. +Check Result Codes + +troubleshooting +result codes + +When an LDAP request from your application fails on the server, the +server sends back a result code, and possibly an explanatory message. Your +application should check the result codes, and for explanatory messages. Common +failure result codes include the following, which are expressed as decimal +values. Others result codes are defined as well. + +1 +LDAP operations error. The server encountered an error while +processing your request. + + +32 +No such object. The entry is not present on the server. Also, +no referral is defined for the entry. + + +49 +Invalid credentials. Your application failed to authenticate +properly. + + +53 +LDAP unwilling to perform. The directory does not support +the request. Alternatively, the directory is not currently in a state in which +to complete your request. For example, the directory might be in read-only +mode when your application requests a modification. + + +65 +Object class violation. Your write request would cause an +entry to no longer conform to the schema defined for the directory. + + +68 +Already exists. Your application is requesting to add an entry +that has the same DN as an entry already present in the directory. + + + +RFC 4511 defines +LDAP error codes, as does Chapter 22, Directory +SDK for C Result Codes. +Check Server Log Files + +troubleshooting +log files + +&cnDirectoryServer; logs messages related to server operation in its +logs/errors file. If you have access to this file, you might find +useful troubleshooting information there. +When debugging your application against &cnDirectoryServer;, you can +adjust the log level, as well. See the server documentation for instructions. + +Inspect Network Packets + +troubleshooting +decoding packets + +Although LDAP is not a textual protocol, tools such as +snoop1M, +ethereal, and tcpdump can decode the packets, +sometimes providing you with important debugging information. + + diff --git a/mozilla/directory/docs/ldapcsdk/choose-api.sgm b/mozilla/directory/docs/ldapcsdk/choose-api.sgm new file mode 100644 index 00000000000..9db9908e1ee --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/choose-api.sgm @@ -0,0 +1,98 @@ + +Choosing a Client +SDK + +This chapter discusses software development kits to help you select +the appropriate directory SDK for your particular situation. + +This chapter covers the following topics: +Java Naming and Directory Interface + +Directory SDK for Java + +Directory SDK for C + +Operating System libldap Library +Support for Other Programming +Languages + + +Java Naming and Directory Interface + +Java Naming and Directory Interface + +JNDI +Java Naming and Directory Interface +Java Naming and Directory Interface (JNDI) technology supports directory +access through LDAP and DSML v2 from Java applications, +and is part of the Java platform. With JNDI, you can build powerful, portable, +directory-enabled applications that do not depend on classes outside the Java +platform. +JNDI provides an abstract model that lets you access not only directories, +but also naming services in general, including DNS, RMI, COS, and file systems. +For information about JNDI, see . The JNDI +Tutorial contains descriptions and examples of how to use JNDI. +The tutorial is at . +&DirectorySDKForC; +&DirectorySDKForC; lets you access LDAP directories from C and C++ +applications. &DirectorySDKForC; applications depend on &DirectorySDKForC; libraries, +which are available on a wide range of platforms. +&DirectorySDKForC; was the subject of Internet-Draft work but never +became a standard API. &DirectorySDKForC; closely follows LDAP v3, providing +support for core LDAP operations and for LDAP v3 extensions and widely used +controls. &DirectorySDKForC; offers a rich API to the C and C++ developer +familiar with the LDAP model. &cnDirectoryServer; relies on &DirectorySDKForC;. + +This document demonstrates how to use &DirectorySDKForC;. &DirectorySDKForC; code +is published in open source form as part of the Mozilla Directory SDK project. + +&DirectorySDKForJava; +&DirectorySDKForJava; lets you access LDAP directories from Java +applications, but it is not part of the Java platform. +Although not a standard API, &DirectorySDKForJava; closely follows +LDAP v3 idioms. &DirectorySDKForJava; provides a rich set of interfaces +to the Java developer familiar with the LDAP model. +This document demonstrates how to use &DirectorySDKForJava;. &DirectorySDKForJava; code +is published in open source form as part of the Mozilla Directory SDK project. + +Operating System <filename>libldap</filename> Library + + +libraries +libldap + +libldap + +The native LDAP library on Solaris systems provides +essentially the same API as &DirectorySDKForC;. Many &DirectorySDKForC; need +only be recompiled to work with libldap. +The LDAP library is sometimes not compatible with libldap on +many GNU/Linux distributions. Many GNU/Linux distributions provide OpenLDAP +support by default. +Support for Other Programming Languages +Support for directory access is available in a number of contexts where +you do not choose to use the C or Java languages. +For example, Perl has the PerLDAP module and the Net::LDAP collection +of modules. Python has the python-ldap package. PHP can +be compiled with LDAP support. Ruby has the Ruby/LDAP extension module. In +many cases, you can choose the language that fits the task and find that LDAP +support is available. + diff --git a/mozilla/directory/docs/ldapcsdk/csdk-api.sgm b/mozilla/directory/docs/ldapcsdk/csdk-api.sgm new file mode 100644 index 00000000000..ee927171e6e --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/csdk-api.sgm @@ -0,0 +1,1465 @@ + +Using the LDAP C API + +This chapter covers features of the LDAP C API to use when writing +an LDAP client application with &DirectorySDKForC;. + +This chapter covers the following topics: +Synchronous and Asynchronous Functions + +Retrieving SDK Information + +Managing Memory + +Reporting Errors + +Handling Referrals With Directory +SDK for C +Creating an In-Memory Cache + +Handling Failover + + + +APIsCC API +Synchronous and Asynchronous Functions +You can perform most operations with synchronous or +with asynchronous functions. For example, to search +the directory, you can call either the synchronous ldap_search_ext_s function +or the asynchronous ldap_search_ext function. In general, +all synchronous functions have names that end with _s. +The difference between the synchronous and asynchronous functions is +the calling convention. The LDAP exchanges are identical. +Calling Synchronous Functions + +C SDK +synchronous functions + +When you call a synchronous function, your client +waits for the operation to complete before executing any subsequent lines +of code. Synchronous functions return LDAP_SUCCESS when +they are successful. Synchronous functions return an LDAP error code when +they are not successful. The following example deletes the entry in the directory. + +Calling Synchronous <function>ldap_delete_ext_s +</function> to Delete an Entry +#include <stdio.h> +#include "ldap.h" +... +LDAP *ld; +char *matched_msg = NULL, *error_msg = NULL; +int rc; +... +/* Perform an LDAP delete operation. */ +rc = ldap_delete_ext_s( ld, DELETE_DN, NULL, NULL ); +if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_delete_ext_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + + /* If the server cannot find an entry with the specified DN, + it may send back the portion of the DN that matches an + existing entry.*/ + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } +} else { + printf( "%s deleted successfully.\n", DELETE_DN ); +} +... + +To see other sample programs that call synchronous functions, view the +source files in the examples/ directory. +Calling Asynchronous Functions + +C SDK +asynchronous functions + +When you call an asynchronous function, your client +does not need to wait for the operation to complete. The client can continue +performing other tasks, such as initiating other LDAP operations, while the +asynchronous operation is executing. An asynchronous function passes back +a unique message ID to identify the operation being performed. You can pass +this message ID to the ldap_result function to check +the status of the operation. The following sections explain how to call an +asynchronous function and how to check the results of the operation. To see +other sample programs that call asynchronous functions, view the source files +in the examples/ directory. +Verifying that an LDAP Request Was Sent +Asynchronous functions return an LDAP result code indicating whether +or not the LDAP request was successfully sent to the server. If the function +returns LDAP_SUCCESS, the function has successfully +sent the request to the server. The following example sends an LDAP delete +request to the server and checks if the result was sent successfully. The +example uses the asynchronous ldap_delete_ext function. +Calling Asynchronous <function>ldap_delete_ext +</function> and Sending a Verification +#include <stdio.h> +#include "ldap.h" +... +/* Change these as needed. */ +#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com" +... +LDAP *ld; +int rc, msgid; +... +/* Send an LDAP delete request to the server. */ +rc = ldap_delete_ext( ld, DELETE_DN, NULL, NULL, &msgid ); +if ( rc != LDAP_SUCCESS ) { + /* If the request was not sent successfully, + print an error message and return. */ + fprintf( stderr, "ldap_delete_ext: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); +} +... + + +Retrieving the Server Response +If the request was sent successfully, the function passes the message +ID of the LDAP operation back to the client. Use the message ID to determine +if the server has sent back results for this operation. Call ldap_result +, passing the message ID as a parameter. + +The function then returns one of the following values: +-1 indicates that an error occurred. + +0 indicates that the time—out period +has been exceeded and that the server has not yet sent a response back to +your client. +Any other value indicates that the server has sent a response +for the requested operation back to your client. The ldap_result parameter +passes back a pointer to an LDAPMessage structure. + +This structure contains the server’s response, which can include +the following information: +An LDAP result code that specifies the result of the operation +you requestedSee Reporting Errors for +details. +An additional error message sent back from the server +This information is optional. +If the server cannot find the entry specified by a DN, the +portion that identifies an existing entry.See Receiving the Matching Portion of a DN for details. + +A set of referrals, if the server’s directory does not +contain the requested entriesThe server must be configured to +return referralsSee Handling Referrals +With Directory SDK for C for details. +A set of server response controls that apply to the operation +you requestedSee Chapter 16, +LDAP Controls With Directory SDK for C for information about controls. + + + + +You can specify a timeout period to wait for results from the server. +Polling Loop +You can set up a loop to poll for results while doing other work. The +following example defines a function that does other work while waiting for +the server to send a response back to your client +Polling for Results +int global_counter = 0; +void do_other_work() +{ + global_counter++; +} + + +<literal>while</literal> Loop +This example sets up a while loop to call your function +when you are not checking for the server’s response. +Using a <literal>while</literal> Loop +to Handle Results +#include <stdio.h> +#include "ldap.h" +... +LDAP *ld; +LDAPMessage *res; +LDAPControl **serverctrls; +char *matched_msg = NULL, *error_msg = NULL; +char **referrals; +int rc, parse_rc, msgid, finished = 0; +struct timeval zerotime; + +zerotime.tv_sec = zerotime.tv_usec = 0L; +... +/* Send an LDAP delete request to the server. */ +rc = ldap_delete_ext( ld, DELETE_DN, NULL, NULL, &msgid ); +... +/* Poll the server for the results of the LDAP operation. */ +while ( !finished ) { + rc = ldap_result( ld, msgid, 0, &zerotime, &res ); + + /* Check to see if a result was received. */ + switch ( rc ) { + case -1: + .../* An error occurred. */... + case 0: + /* The timeout period specified by zerotime was exceeded, meaning + the server has still not yet sent the results of the delete + operation back to the client. Break out of this switch statement, + and continue calling ldap_result() to poll for results. */ + default: + finished = 1; + .../* Your client received a response from the server. */... + } + + /* Do other work while waiting. This is called if ldap_result() + returns 0 (before you continue to top of the loop and call + ldap_result() again). */ + if ( !finished ) { + do_other_work(); + } + ... +} +... + + + +Getting Information From a Server Response +To get information from the server response, call ldap_parse_result + as shown here. +The <function>ldap_parse_result</function> Function + +LDAP_API(int) LDAP_CALL +ldap_parse_result( LDAP *ld, LDAPMessage *res, int *errcodep, + char **matcheddnp, char **errmsgp, char ***referralsp, + LDAPControl ***serverctrlsp, int freeit ); + + +You can get the following information from parameters of the ldap_parse_result +: +errcodep holds the LDAP result code of +the operation that the server finished processing.See Reporting Errors for details. +errmsgp is an additional error message +that the server can send to your client. +matcheddnp is the portion of the DN that +matches an existing entry. The portion of the DN is used when the server is +not able to find an entry for the DN that you specified.See Receiving the Matching Portion of a DN for details. + +referralsp is a set of referrals sent back +to your client. The set of referrals is sent if you requested an entry that +is not part of the DIT managed by the server. The server must be configured +to refer clients to other LDAP servers.See +Handling Referrals With Directory SDK for C for details. + +serverctrlsp is a set of server response +controls that apply to the operation.See Chapter 16, LDAP Controls With Directory SDK +for C for details. + +When processing LDAP search operations, the server can send back individual +entries, individual search references, chains of entries, and chains of search +references. +The following example retrieves error information from an LDAPMessage + structure returned by ldap_result. +Retrieving Error Information +From an <structname>LDAPMessage</structname> Structure +#include <stdio.h> +#include "ldap.h" +... +LDAP *ld; +LDAPMessage *res; +LDAPControl **serverctrls; +char *matched_msg = NULL, *error_msg = NULL; +char **referrals; +int rc, parse_rc, msgid, finished = 0; +struct timeval zerotime; + +zerotime.tv_sec = zerotime.tv_usec = 0L; +... +rc = ldap_result( ld, msgid, 0, &zerotime, &res ); + +/* Check to see if a result was received. */ +switch ( rc ) { +case -1: + ... +case 0: + ... +default: + ... + /* Call ldap_parse_result() to get information from the results + received from the server. */ + parse_rc = ldap_parse_result( ld, res, &rc, &matched_msg, + &error_msg, &referrals, &serverctrls, 1 ); + + /* Make sure the results were parsed successfully. */ + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_parse_result: %s\n", + ldap_err2string( parse_rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + + /* Check the results of the LDAP operation. */ + if ( rc != LDAP_SUCCESS ) { + fprintf(stderr, "Error: %s\n", ldap_err2string(rc)); + if ( error_msg != NULL & *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + /* If the server returned the portion of the DN + that identifies an existing entry, print it out. */ + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + } else { + printf( "Operation completed successfully" ); + } +} +... + + +Freeing an <structname>LDAPMessage</structname> Structure + +When you are done, call ldap_msgfree to free the +LDAPMessage structure unless the structure is part of a chain +of results. The result code returned by this function is not the same as the +result code of the operation, errcodep. This operation +returns a result code that indicates the type of operation to which the freed +LDAPMessage structure is a response. +If you pass a non-zero value for the freeit parameter +of ldap_result, the structure is automatically freed +after the information is retrieved. +Canceling an Operation in Progress +If you need to cancel an LDAP operation, call ldap_abandon_ext. +The function returns LDAP_SUCCESS if successful, or an +LDAP result code if an error occurs. After you cancel an operation, you cannot +retrieve the results of that operation. Thus, calling ldap_result does +not return any results. +Sample Code to Call an Asynchronous Function + +example programs +asynchronous deletion of an entry + +The following example calls ldap_delete_ext to +delete an entry in the directory, and ldap_result within +a loop to poll the results of the delete. +Performing Asynchronous Deletion +of an Entry +#include <stdio.h> +#include "ldap.h" +... +void do_other_work(); +int global_counter = 0; +... +/* Change these as needed. */ +#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com" +... +LDAP *ld; +LDAPMessage *res; +LDAPControl **serverctrls; +char *matched_msg = NULL, *error_msg = NULL; +char **referrals; +int rc, parse_rc, msgid, finished = 0; +struct timeval zerotime; + +zerotime.tv_sec = zerotime.tv_usec = 0L; +... +/* Send an LDAP delete request to the server. */ +rc = ldap_delete_ext( ld, DELETE_DN, NULL, NULL, &msgid ); +if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_delete_ext: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); +} + +/* Poll the server for the results of the delete operation. */ +while ( !finished ) { + /* Call ldap_result() to get the results of the delete operation. + ldap_result() blocks for the time specified by the timeout argument + (set to zerotime here) while waiting for the result from the server. */ + rc = ldap_result( ld, msgid, 0, &zerotime, &res ); + + /* Check to see if a result was received. */ + switch ( rc ) { + case -1: + /* If ldap_result() returned -1, an error occurred. */ + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + + case 0: + /* The timeout period specified by zerotime was exceeded, meaning + the server has still not yet sent the results of the delete + operation back to the client. Break out of this switch statement, + and continue calling ldap_result() to poll for results. */ + break; + + default: + /* ldap_result() got the results of the delete operation + from the server. No need to keep polling. */ + finished = 1; + + /* Call ldap_parse_result() to get information from the results + received from the server. Note the last argument is a non-zero + value. This means after the function retrieves information from + the LDAPMessage structure, the structure is freed. + (You do not need to call ldap_msgfree() to free the structure.)*/ + parse_rc = ldap_parse_result( ld, res, &rc, &matched_msg, + &error_msg, &referrals, &serverctrls, 1 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_parse_result: %s\n", + ldap_err2string( parse_rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + + /* Check the results of the LDAP delete operation. */ + if ( rc != LDAP_SUCCESS ) { + fprintf(stderr, "ldap_delete_ext: %s\n", ldap_err2string(rc)); + if ( error_msg != NULL & *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + /* Print the portion of a specified DN that matches an + existing entry, if returned by the server. */ + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + } else { + printf( "%s deleted successfully.\n" + "Counted to %d while waiting for the delete operation.\n", + DELETE_DN, global_counter ); + } + } + + /* Do other work while waiting for the results of the + delete operation. */ + if ( !finished ) { + do_other_work(); + } +} +ldap_unbind( ld ); +return 0; +... + +/* Perform other work while polling for results. */ +void +do_other_work() +{ + global_counter++; +} +... + + + + +Retrieving SDK Information + +C SDK +retrieving SDK information + +You can get information about the particular version of &DirectorySDKForC; +that you are using by calling the ldap_get_option function: +ldap_get_option(..., LDAP_OPT_API_INFO, ...); +The retrieved information can include the version of the SDK or the +highest version of the LDAP that the SDK supports. This example shows how +to use this function to retrieve version information. +Retrieving the SDK Version Using <function> +ldap_get_option</function> + +example programs +retrieving SDK version + +#include <stdio.h> +#include "ldap.h" + +main() +{ + +LDAPAPIInfo ldapi; +LDAPAPIFeatureInfo fi; +int i; +int rc; +LDAP *ld; + +memset( &ldapi, 0, sizeof(ldapi)); +ldapi.ldapai_info_version = LDAP_API_INFO_VERSION; + +if ((rc = ldap_get_option( ld, LDAP_OPT_API_INFO, &ldapi)) != 0) { + printf("Error: ldap_get_option (rc: %d)\n", rc); + exit(0); +} + +printf("LDAP Library Information -\n" + " Highest supported protocol version: %d\n" + " LDAP API revision: %d\n" + " API vendor name: %s\n" + " Vendor-specific version: %.2f\n", + ldapi.ldapai_protocol_version, ldapi.ldapai_api_version, + ldapi.ldapai_vendor_name, + (float)ldapi.ldapai_vendor_version / 100.0 ); + +if ( ldapi.ldapai_extensions != NULL ) { + printf(" LDAP API Extensions:\n"); + + for ( i = 0; ldapi.ldapai_extensions[i] != NULL; i++ ) { + printf(" %s", ldapi.ldapai_extensions[i] ); + fi.ldapaif_info_version = LDAP_FEATURE_INFO_VERSION; + fi.ldapaif_name = ldapi.ldapai_extensions[i]; + fi.ldapaif_version = 0; + + if ( ldap_get_option( NULL, LDAP_OPT_API_FEATURE_INFO, &fi ) + != 0 ) { + printf("Error: ldap_get_option( NULL," + " LDAP_OPT_API_FEATURE_INFO, ... ) for %s failed" + " (Feature Info version: %d)\n", + fi.ldapaif_name, fi.ldapaif_info_version ); + } else { + printf(" (revision %d)\n", fi.ldapaif_version); + } + } + } + printf("\n"); +} + + +Managing Memory + +C SDK +managing memory + +memory management + +Several of the SDK functions allocate memory when called. When you have +finished working with data allocated by these functions, you should free the +memory. The following shows some of the functions that allocate memory and +the corresponding functions you use to free the memory when done. +SDK Functions to Allocate +and Free Memory + + + + +Function to Free Memory + +Type of Memory Freed + + + + + +ldap_unbind, ldap_unbind_s + + +Frees LDAP structures allocated by ldap_init + or prldap_init. + + + +ldap_msgfree + +Frees LDAPMessage structures allocated by +ldap_result or ldap_search_ext_s. + + + +ldap_ber_free + +Frees BerElement structures allocated by +ldap_first_attribute. + + + +ldap_value_free + +Frees char ** arrays and structures allocated by +ldap_get_values. + + + +ldap_value_free_len + +Frees arrays of berval structures allocated +by ldap_get_values_len. + + + +ber_bvfree + +Frees berval structures allocated by ldap_extended_operation_s +, ldap_parse_extended_result, ldap_parse_sasl_bind_result +, and ldap_sasl_bind_s. + + + +ldap_free_friendlymap + +Frees FriendlyMap structures allocated by +ldap_friendly_name. + + + +ldap_free_urldesc + +Frees LDAPURLDesc structures allocated by +ldap_url_parse. + + + +ldap_getfilter_free + +Frees LDAPFiltDesc structures allocated by +ldap_init_getfilter or ldap_init_getfilter_buf. + + + + +ldap_mods_free + +Frees LDAPMod** arrays and +structures allocated by functions that you call when you add or modify entries. + + + + +ldap_free_sort_keylist + +Frees LDAPsortkey** arrays +that you allocate by calling ldap_create_sort_keylist. + + + + +ldap_control_free + +Frees LDAPControl structures that you allocate +by calling ldap_create_sort_control or ldap_create_persistentsearch_control +. + + + +ldap_controls_free + +Frees LDAPControl** arrays +and structures that you allocate by calling ldap_get_entry_controls, +ldap_parse_result, or ldap_parse_reference. + + + + +ldap_memfree + +Frees any other types of memory that you allocate. This function is +a general function for freeing memory. + + + +
+
+Reporting Errors + +C SDK +reporting errors + +errors +reporting + +In LDAP, the success or failure of an operation is specified by a +result code sent back to the client. A result code of zero ( +0) normally indicates that the operation was successful, whereas +a nonzero result code usually indicates that an error occurred. For a detailed +list of result codes, see Chapter 22, Directory +SDK for C Result Codes. +Setting Error Codes + +C SDK +setting error codes + +error codes +setting + +When an LDAP operation is performed, the error information from the +operation is specified in the LDAP structure. If +you want to set error codes and error information in the LDAP structure, +call the ldap_set_lderrno function. This example sets +the LDAP_PARAM_ERROR error code in an LDAP structure. + +Setting an Error Code +#include "ldap.h" +... +LDAP *ld; +char *errmsg = "Invalid parameter"; +... +if ( ldap_my_function() != LDAP_SUCCESS ) { + ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, errmsg ); + return( 1 ); +} +... + + +Getting Information About an Error + +C SDK +retrieving error information + +When an error occurs in an LDAP operation, the server sends an LDAP +result code for the error back to the client. The server also sends a message +with any additional information about the error. + +You can get this information back from the server in two ways: +If you are calling asynchronous functions, you can get the +information from the LDAPMessage structure that represents +the result the server returns.For details, see Getting Information From an LDAPMessage Structure. + +Sometimes, you do not have an LDAPMessage structure. +For example, you might be calling functions that do not interact with the +server. When you do not have a message ID, get error information from the +LDAP connection handle.For details, see Getting Information From an LDAP Structure. + + +Getting Information From an <structname>LDAPMessage</structname> Structure + +If you have requested the operation through an asynchronous function, +get the result by calling the ldap_result function. This +function passes the result as an LDAPMessage structure. +You can get information from this structure by calling the ldap_parse_result + function whose prototype is shown here +The <function>ldap_parse_result +</function> Function +LDAP_API(int) LDAP_CALL ldap_parse_result( LDAP *ld, + LDAPMessage *res, int *errcodep, char **matcheddnp, + char **errmsgp, char ***referralsp, + LDAPControl ***serverctrlsp, int freeit ); + + +Different types of information are returned in the parameters of this +function. +The LDAP result code is the errcodep argument. + +Additional information from the server is passed back as the +errmsgp argument. +When the server cannot find an entry from a DN, the portion +of the DN that identifies an entry is passed as the matcheddnp argument. +See Receiving the Matching Portion of +a DN for details. + +You can also get the error message that describes the LDAP result code +by using the ldap_err2string function. See Getting the Error Message From an Error Code for +details. +The following example gets and prints information about an error returned +from the server. +Getting and Printing Error +Information From an <structname>LDAPMessage</structname> Structure + +example programs +printing error information + +#include <stdio.h> +#include "ldap.h" +... +LDAP *ld; +LDAPMessage *res; +int msgid = 0, rc = 0, parse_rc = 0, finished = 0; +char *matched_msg = NULL, *error_msg = NULL; +char **referrals; +LDAPControl **serverctrls; +struct timeval zerotime; +... +while ( !finished ) { + /* Check to see if the server returned a result. */ + rc = ldap_result( ld, msgid, 0, &zerotime, &res ); + switch ( rc ) { + ... + default: + /* The client has received the result of the LDAP operation. */ + finished = 1; + + /* Parse this result to determine if the operation was successful. */ + parse_rc = ldap_parse_result( ld, res, &rc, &matched_msg, + &error_msg, &referrals, &serverctrls, 1 ); + + /* Verify that the result was parsed correctly. */ + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_parse_result error: %s\n", + ldap_err2string( parse_rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + + /* Check the results of the operation. */ + if ( rc != LDAP_SUCCESS ) { + + /* Print the error message corresponding to the result code. */ + fprintf( stderr, "Error: %s\n", + ldap_err2string( rc ) ); + + /* If the server sent an additional message, print it out. */ + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + + /* If the server cannot find an entry with the specified DN, + it may send back the portion of the DN that matches + an existing entry. */ + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + + /* Disconnect and return. */ + ldap_unbind( ld ); + return( 1 ); + } +... + + +Getting Information From an <structname>LDAP</structname> Structure + +Sometimes, you do not get an LDAPMessage structure. +For example, when you call functions that do not interact with the server, +get error information from the connection handle. You can get information +about the last error that has occurred by calling the ldap_get_lerrno function +whose prototype is shown here. +The <function>ldap_get_lderrno</function> Function + +LDAP_API(int) LDAP_CALL ldap_get_lderrno(LDAP *ld, +char **m, char **s); + + +The different types of information to retrieve are returned in the following +ways: +The LDAP result code is returned by this function. + +Additional information from the server is passed back as the +s argument. +When the server cannot find an entry from a DN, the portion +of the DN that identifies an entry is passed as the m argument. +See Receiving the Matching Portion of +a DN for details. + +If you do not need to use the parameters returned by the ldap_get_lerrno + function, set the parameters to NULL: +ldap_get_lderrno( ld, NULL, NULL ); +The following example gets and prints information about an error from +an LDAP structure. +Getting and Printing an Error +Message From an <structname>LDAP</structname> Structure +#include <stdio.h> +#include "ldap.h" +... +LDAP *ld; +char* *error_msg = NULL, *matched_msg = NULL; +int rc; +... +rc = ldap_get_lderrno( ld, &matched_msg, &error_msg ); +fprintf( stderr, "ldap_result error: %s\n", ldap_err2string( rc ) ); +if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); +} + +/* If the server cannot find an entry with the specified DN, + it may send back the portion of the DN that matches + an existing entry. */ +if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); +} +... + + +Getting the Error Message From an Error Code +If you have an error code, you can retrieve its corresponding error +message using the ldap_err2string function. The function +returns a pointer to the error message. The pointer returned by this function +is a pointer to static data. Do not free this string. +Retrieving an Error +Message From an Error Code +#include <stdio.h> +#include "ldap.h" +... +int rc; +... +if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "Error: %s\n", ldap_err2string( rc ) ); +} +... + + + +Receiving the Matching Portion of a DN + +distinguished names (DNs) +return portion of + +If the server cannot find an entry specified by a DN, the server can +return the portion of the DN that identifies an existing entry. According +to LDAP v3, if a server returns an LDAP_NO_SUCH_OBJECT, +LDAP_ALIAS_PROBLEM, LDAP_INVALID_DN_SYNTAX, +or LDAP_ALIAS_DEREF_PROBLEM result code, the LDAP server +should also send back the portion of the DN that matches an entry that is +closest to the requested entry. +For example, suppose that the LDAP server processes a request to modify +the entry with the DN uid=bjensen,ou=Contractors,dc=example,dc=com but +that entry does not exist in the directory. If ou=Contractors,dc=example,dc=com + does exist, the server sends this portion of the DN with the result +code LDAP_NO_SUCH_OBJECT. If ou=Contractors,dc=example,dc=com + does not exist, but dc=example,dc=com does, +the server sends dc=example,dc=com back to the client. +The server also returns the result code LDAP_NO_SUCH_OBJECT. +Basically, the server removes one DN component at a time, until the server +can find a DN that identifies an existing entry. +Printing Error Messages + +error messages +printing + +To print the error message that describes the last error that occurred, +call the ldap_get_lerrno function. The following prints +a message if a function fails to delete an entry in the server. +Printing Error Messages +From Error Codes +#include "ldap.h" +... +int lderr; +char * errmsg; +LDAP *ld; +char *dn = "uid=bjensen,ou=People,dc=example,dc=com"; +... +if ( ldap_delete_s( ld, dn ) != LDAP_SUCCESS ) { + lderr = ldap_get_lderrno (ld, NULL, &errmsg); + if ( errmsg, != NULL ) { + fprintf(stderr, "ldap_delete_s: %s\n", errmsg ); + ldap_memfree( errmsg ); + } + return( 1 ); +} +... + +The client also prints the following message if the client does not +have access permissions to delete the entry: +ldap_delete_s: Insufficient access + + +Handling Referrals With Directory SDK for C + +C SDK +handling referrals + +referrals +handling with C SDK + +When a server receives a request for a DN, that DN might not be in its +directory tree. The server can refer clients to another server that might +contain the DN. The reference that the client receives is called a referral +. +Consider an LDAP server that has a directory that starts under dc=example,dc=com +. + +Your client sends the server a request to modify the entry with the +DN uid=bjensen,ou=People,dc=exampleWest,dc=com, that is, +the entry is not under dc=example,dc=com. One of the following +can occur: +If the server is not configured to send a referral, the server +sends back an LDAP_NO_SUCH_OBJECT result code. + +If the server is configured to refer you to another LDAP server, +the server sends a referral back to your client. The referral consists of +the result code, LDAP_PARTIAL_RESULTS for LDAP v2 clients, +or LDAP_REFERRAL for LDAP v3 clients, and one or more +LDAP URLs. For LDAP v2 clients, the URLs are included in the error message +that the server sends to the client. For LDAP v3 clients, the URLs are included +in a separate section of the result. + + +Depending on how your LDAP client is configured, one of the following +can occur: +If your client handles referrals automatically, the client +connects to the LDAP server specified in the referral. The client then requests +the operation from that server. The client binds anonymously to that server. + +If your client does not handle referrals automatically, your +client returns the result code sent from the server, LDAP_PARTIAL_RESULTS + or LDAP_REFERRAL. You can get the LDAP +URLs from the result by calling the ldap_parse_result function. + + +By default, clients built with &DirectorySDKForC; follow referrals +automatically. +Searching References and Referrals + +C SDK +search references + +A concept that is similar to a referral is a search reference. A +search reference is an entry with the object class referral. +The ref attribute of this object class contains an LDAP +URL that identifies another LDAP server. When your client searches a subtree +of a directory that contains search references, the server returns a mix of +matching entries and search references. + +As your client retrieves search references from the server, one of the +following occurs: +If your client handles referrals automatically, &DirectorySDKForC; +retrieves each search reference, binds to the server identified in the reference, +and then retrieves the entry. +If your client does not handle referrals automatically, &DirectorySDKForC; +adds the search reference to the chain of search results. The search reference +is a message of the type LDAP_RES_SEARCH_REFERENCE. You +can get the search references from a chain of results by calling the ldap_first_reference + and ldap_next_reference functions. You can +also call the ldap_first_message and ldap_next_message + functions to get each message in the search results, and then +call the ldap_msgtype function to determine if the message +is of the type LDAP_RES_SEARCH_REFERENCE. + +See ldap_ssl.h Header File for information +about specifying a DN and password for binding to a server for a referral. + +Enabling or Disabling Referral Handling With &DirectorySDKForC; + + +referrals +handling with C SDK + +By default, clients built with &DirectorySDKForC; automatically follow +referrals to other servers. To change the way referrals are handled, call +the ldap_set_option function and pass LDAP_OPT_REFERRALS + as the value of the option parameter. + +To prevent the client from automatically following referrals, +set the optdata parameter to LDAP_OPT_OFF. + +If you want the client to automatically follow referrals again, +set the optdata parameter to LDAP_OPT_ON. +Both LDAP_OPT_OFF and LDAP_OPT_ON are +cast to (void *). You can pass these parameters directly +to the function as shown in the following example. The parameter prevents +the client from automatically following referrals to other LDAP servers. + + +Disabling Referrals +#include <stdio.h> +#include "ldap.h" +... +LDAP *ld; +int rc; +char *host = "localhost"; +... +/* Initialize a session with the LDAP server ldap.example.com:389. */ +/* Use prldap_init() for IPv6 support. */ +if ( ( ld = ldap_init( host, LDAP_PORT ) ) == NULL ) { + perror( "ldap_init" ); + return( 1 ); +} + +/* Never follow referrals. */ +if ( ldap_set_option( ld, + LDAP_OPT_REFERRALS, + LDAP_OPT_OFF) != + LDAP_SUCCESS ) { + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_set_option: %s\n", + ldap_err2string( rc ); + return( 1 ); +} +... + + +Limiting Referral Hops With &DirectorySDKForC; + +C SDK +referral hop limit + +You can specify the maximum number of referral hops that should be followed +in a sequence of referrals. The maximum setting is called the referral +hop limit. You can specify the limit as a preference for the connection. +You can also specify the limit as a search constraint for a specific search +operation. For example, LDAP server 1 refers your client to server 2, server +2 to server 3, and then server 3 to server 4. Your client is being referred +three times. With a limit of two referral hops, your client would not follow +the referral to server 4, as the third referral exceeds the limit. If the +referral hop limit is exceeded, the client returns the result code LDAP_REFERRAL_LIMIT_EXCEEDED +. +To set the referral hop limit, pass LDAP_OPT_REFERRAL_HOP_LIMIT as +the value of the option parameter. Also, pass the maximum +number of hops as the value of the optdata parameter. By +default, the maximum number of hops is 5. +Binding for Referrals + +C SDK +binding for referrals + +referrals +binding for + +If the session setup specifies that the client always follows referrals, +the LDAP server that the client connects to can refer the client to another +server. By default, the client binds anonymously when following referrals. +No user name or password is specified. The following sections explain how +to set up your client to authenticate with a DN and with corresponding credentials. + +How Referral Binding Works +To authenticate to the referred LDAP server, define a rebind function +of the type LDAP_REBINDPROC_CALLBACK. The rebind +function gets the DN and password to be used for authentication. Then, you +specify that your function should be used if binding to other servers when +following referrals. + +Referral handling proceeds as follows: +The LDAP server sends a referral back to the client. +The referral contains an LDAP URL that identifies another LDAP server. + +The client calls the rebind function, specified by the LDAP_OPT_REBIND_FN + option, passing 0 as the freeit argument. + +The rebind function sets the dnp, +passwdp, and authmethodp arguments. + +The dnp argument points to the DN used +to authenticate to the new LDAP server. +The passwdp argument points to the +credentials for this DN. +The authmethodp argument points to +the method of authentication that is used, such as LDAP_AUTH_SIMPLE. + + + +If successful, the rebind function returns LDAP_SUCCESS +, and referral processing continues.If any other +value is returned, referral processing stops, and that value is returned as +the result code for the original LDAP request. +The client gets the DN, the credentials, and the authentication +method from the arguments of the rebind function. The client uses this information +to authenticate to the new LDAP server. +The client calls the rebind function again, passing 1 as +the freeit argument. +The rebind function frees any memory that was allocated earlier +to specify the DN and credentials. + + +Defining the Rebind Function + +You need to define a rebind function that does the following: + If freeit is 0, +do the following: + +Set dnp to point to the DN to be used +for authentication. +Set passwdp to point to the credentials +to be used for authentication. +Set authmethodp to point to the method +of authentication to be used, such as LDAP_AUTH_SIMPLE. + +Alternatively, you can also make use of the arg argument, +a pointer to the argument specified in the ldap_set_rebind_proc function. +If successful, the function returns LDAP_SUCCESS. Otherwise, +the function returns the appropriate LDAP error code. + + +If freeit is 1, +free any memory that you allocated to create the DN and credentials. +The following code defines the rebind function. The table defines the +parameters of the rebind function. LDAP_CALL and +LDAP_CALLBACK set up calling conventions. The structures are +defined in the lber.h header file. + +Rebind Function Definition +int LDAP_CALL LDAP_CALLBACK rebindproc( LDAP *ld, char **dnp, + char **passwdp, int *authmethodp, int freeit, void *arg ); + +<structname> +LDAP_CALL</structname> and <structname>LDAP_CALLBACK</structname> Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to the connection handle to the LDAP server. + + + +dnp + +Pointer to the DN of the user or entity who wants to perform the LDAP +operations. Your function needs to set this value. + + + +passwdp + +Pointer to the user password. Your function needs to set this value. + + + + +authmethodp + +Pointer to the method of authentication. Your function needs to set +this value. + + + +freeit + +Specifies whether or not to free the memory allocated by the previous +rebindproc function call in the event that this function is called +more than once. If freeit is set to a nonzero value, +your function should free the memory allocated by the previous call. + + + + +arg + +Pointer to data that can be passed to your function. + + + +
+
+Registering the Rebind Function + +After you define a rebind function, you must register the function. +You can register the function in one of the following ways: +Call ldap_set_rebind_proc, specifying +your function and any data that you want passed as an argument. + +Call ldap_set_option to set the LDAP_OPT_REBIND_FN + option to your function. Use the LDAP_OPT_REBIND_ARG option +to specify any arguments to pass to your rebind function. + + +
+
+Creating an In-Memory Cache + +C SDK +setting up in-memory cache + +cache +setting up + +&DirectorySDKForC; includes functions that allow you to create an +in-memory cache of search results for your client. Then, when sending a search +request and receiving results, the results would be cached. The next time +your client issues the same search request, the results are read from the +cache. To set up a cache for your connection, complete the following procedure. +To Set Up an In-Memory Cache + +Call the ldap_memcache_init function to create +a new LDAPMemCache structure.The structure +is the cache. Pass the pointer to this structure for subsequent operations. + +Call the ldap_memcache_set function to associate +the cache with an LDAP structure, which is a connection +handle.When a search request is cached, the search criteria are +used as the key to the item in the cache. If you run the same search again, +the results are read from the cache. If you alter the criteria, your client +gets the results from the server rather than the cache. For example, you can +specify to return all attributes instead of just the uid attribute, +The cache periodically checks for expired items. The cache mechanism +removes expired items from the cache. +When you write a multithreaded application, set up a separate +thread to keep the cache up to date. To keep the cache updated, +call the ldap_memcache_update function. +If you want to remove items from the cache or flush the cache, +call the ldap_memcache_flush function. +When you are done working with the cache, call the ldap_memcache_destroy + function. + + +Setting Up an In-Memory Cache +#include "ldap.h" +... +#define HOSTNAME "localhost" +#define PORTNUMBER LDAP_PORT +... +LDAP *ld; +LDAPMemCache *dircache; +char *matched_msg = NULL, *error_msg = NULL; +int rc; +... +/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ +if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); +} +... +/* Create an in-memory cache. */ +rc = ldap_memcache_init( 0, 0, NULL, NULL, &dircache ); +if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_memcache_init: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); +} + +/* Associate the cache with the connection. */ +rc = ldap_memcache_set( ld, dircache ); +if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_memcache_set: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); +} +... + + + +Handling Failover + +C SDK +handling failover + +failover handling +C SDK + +While performing an LDAP operation, if the LDAP client loses the connection +with the server, the SDK returns an LDAP_SERVER_DOWN or +LDAP_CONNECT_ERROR result code. + +To reconnect to the server, you can do one of the following: +Free the current connection handle. Then create a new connection +handle.See Creating a New Connection +Handle for details. +Use the reconnect option, LDAP_OPT_RECONNECT +, to connect to the server again with the same connection handle. +See Using the Reconnect Option for +details.You can use this option if you do not want to free the +connection handle, for example, if multiple threads are sharing the same connection +handle. + +Creating a New Connection Handle +Call the ldap_unbind or ldap_unbind_s function +to free the existing connection handle, which is an LDAP structure. +Then call ldap_init or prldap_init to +initialize a new connection as shown in the following example. +The disadvantage of this approach is the need to free the connection +handle, which can make sharing connection handles between threads difficult. +Initializing a New Connection Handle +#include "ldap.h" +... +LDAP *ld; +int tries = 0, rc = 0; +... +do { + /* Call a function that performs an LDAP operation + (my_ldap_request_function() can be any of these functions, + such as ldap_search_ext_s()) */ + rc = my_ldap_request_function( ld ); + + /* Check to see if the connection was lost. */ + if ( rc != LDAP_SERVER_DOWN && rc != LDAP_CONNECT_ERROR ) { + return( rc ); /* Return result code. */ + } + + /* If the connection was lost, free the handle. */ + ldap_unbind( ld ); + + /* Create a new connection handle and attempt to bind again. */ + /* Use prldap_init() for IPv6 support. */ + if (( ld = ldap_init( hostlist, port )) != NULL ) { + ldap_simple_bind_s(); + + /* Perform any other initialization + work on the connection handle. */ + } +} while ( ld != NULL && ++tries < 2 ); +... + + +Using the Reconnect Option +To reconnect to the server without freeing the connection handle, for +example, if multiple threads need to share the same connection handle, call +the ldap_set_option function to set the LDAP_OPT_RECONNECT + option to LDAP_OPT_ON. Call this function immediately +after calling ldap_init or prldap_init as +shown in the following example: +Reconnecting to an Existing +Connection Handle +#include "ldap.h" +... +#define HOSTNAME "localhost" +#define PORTNUMBER LDAP_PORT +... +LDAP *ld; +... +/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ +if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); +} + +/* Set the reconnect option. */ +if ( ldap_set_option( ld, LDAP_OPT_RECONNECT, LDAP_OPT_ON ) == 0 ) { + /* success */ + } else { + /* failure */ +} +... + +If after setting this option, the connection to the server has been +lost, the SDK returns an LDAP_CONNECT_ERROR or +LDAP_SERVER_DOWN result code to your client. When you receive +this result code, call the ldap_simple_bind_s function. +This function reestablishes a connection to one of the hosts specified in +the ldap_init or prldap_init function +call. If your client is able to reconnect with the server, ldap_simple_bind_s + issues a bind request to the server and returns the result. The +following example attempts to reconnect to the server if the client is disconnected. + +Reconnecting to a Server +After Disconnect +#include "ldap.h" +... +LDAP *ld; +int tries = 0, rc = 0; +... +do { + /* Call a function that performs an LDAP operation + (my_ldap_request_function() can be any of these functions, + such as ldap_search_ext_s()) */ + rc = my_ldap_request_function( ld ); + + /* Check to see if the connection was lost. */ + if ( rc != LDAP_SERVER_DOWN && rc != LDAP_CONNECT_ERROR ) { + return( rc ); /* Return the result code. */ + } + + /* If the connection was lost, call + ldap_simple_bind_s() to reconnect. */ + if ( ldap_simple_bind_s( ld, dn, passwd ) != LDAP_SUCCESS ) { + /* failure -- could not reconnect */ + /* remember that ld as bad */ + return( rc ); + } +} while ( ++tries < 2 ); + + + +
diff --git a/mozilla/directory/docs/ldapcsdk/csdk-client.sgm b/mozilla/directory/docs/ldapcsdk/csdk-client.sgm new file mode 100644 index 00000000000..4b9985d4c79 --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/csdk-client.sgm @@ -0,0 +1,768 @@ + +Writing an LDAP Client With &DirectorySDKForC; + +With &DirectorySDKForC;, you can write a new application. You can +also enable an existing application to interact with a Lightweight Directory +Access Protocol (LDAP) server. This chapter explains how to connect to an +LDAP server, authenticate, request operations, and disconnect from the server. + +This chapter covers the following topics: +Designing an LDAP Client With Directory +SDK for C +Initializing an LDAP Session With +Directory SDK for C +Binding and Authenticating to an +LDAP Server With Directory SDK for C +Performing LDAP Operations With Directory +SDK for C +Closing the Connection to an LDAP +Server With Directory SDK for C + + +Designing an LDAP Client With &DirectorySDKForC; + +C SDK +designing LDAP client + +LDAP clients +designing with C SDK + +The following procedure outlines a typical process for communicating +with an LDAP server. +To Communicate With an LDAP Server + +Initialize an LDAP session.See +Initializing an LDAP Session With Directory SDK for C for details. + +Bind to the LDAP server, if necessary.See Binding and Authenticating to an LDAP Server With Directory +SDK for C for details. +Perform LDAP operations, such as searching the directory or modifying +entries in the directory.See Performing +LDAP Operations With Directory SDK for C for details. +Close the connection to the LDAP server when finished.See Closing the Connection to an LDAP Server With Directory +SDK for C for details. + + +Performing an LDAP Search + +example programs +LDAP search + +This sample source code shows a client that requests an LDAP search +operation from a server. The LDAP server runs on the local system on port +389. The client searches the directory for entries with the last +name Jensen (sn=Jensen), and prints +the distinguished name (DN) of any matching entry. +#include <stdio.h> +#include "ldap.h" + +/* Specify the search criteria here. */ +#define HOSTNAME "localhost" +#define PORTNUMBER 389 +#define BASEDN "dc=example,dc=com" +#define SCOPE LDAP_SCOPE_SUBTREE +#define FILTER "(sn=Jensen)" + +int +main( int argc, char **argv ) +{ + LDAP *ld; + LDAPMessage *result, *e; + char *dn; + int version, rc; + /* Print out an informational message. */ + printf( "Connecting to host %s at port %d...\n\n", HOSTNAME, + PORTNUMBER ); + + /* STEP 1: Get a handle to an LDAP connection and + set any session preferences. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } + + /* Use the LDAP_OPT_PROTOCOL_VERSION session preference to specify + that the client is an LDAPv3 client. */ + version = LDAP_VERSION3; + ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); + + /* STEP 2: Bind to the server. + In this example, the client binds anonymously to the server + (no DN or credentials are specified). */ + rc = ldap_simple_bind_s( ld, NULL, NULL ); + if ( rc != LDAP_SUCCESS ) { + fprintf(stderr, "ldap_simple_bind_s: %s\n", ldap_err2string(rc)); + return( 1 ); + } + + /* Print out an informational message. */ + printf( "Searching the directory for entries\n" + " starting from the base DN %s\n" + " within the scope %d\n" + " matching the search filter %s...\n\n", + BASEDN, SCOPE, FILTER ); + + /* STEP 3: Perform the LDAP operations. + In this example, a simple search operation is performed. + The client iterates through each of the entries returned and + prints out the DN of each entry. */ + rc = ldap_search_ext_s( ld, BASEDN, SCOPE, FILTER, NULL, 0, + NULL, NULL, NULL, 0, &result ); + if ( rc != LDAP_SUCCESS ) { + fprintf(stderr, "ldap_search_ext_s: %s\n", ldap_err2string(rc)); + return( 1 ); + } + for ( e = ldap_first_entry( ld, result ); e != NULL; + e = ldap_next_entry( ld, e ) ) { + if ( (dn = ldap_get_dn( ld, e )) != NULL ) { + printf( "dn: %s\n", dn ); + ldap_memfree( dn ); + } + } + ldap_msgfree( result ); + + /* STEP 4: Disconnect from the server. */ + ldap_unbind( ld ); + return( 0 ); +} +... + + + +Initializing an LDAP Session With &DirectorySDKForC; + +C SDK +initializing an LDAP session + +LDAP session +initializing + +Before connecting to an LDAP server, you must initialize a session. +As part of this process, you create an LDAP structure +that contains information about the LDAP server and session. You then pass +this LDAP structure, usually as a pointer, to all +subsequent functions in order to identify the LDAP server with which you are +working. Sample code for initializing an LDAP session is provided in Example Session Initialization. +If you plan to connect to the LDAP server over the Secure Sockets +Layer (SSL) protocol, the procedure for initializing an LDAP session is different. +For details, see Chapter 15, SSL Connections +With Directory SDK for C. +Specifying a Single LDAP Server +To initialize an LDAP session, call ldap_init, +or prldap_init for IPv6 support, with the host name and +port number of the LDAP server. If the server is using the default port +389 for the LDAP server, pass LDAP_PORT as the +value for the defport parameter as shown here. +Passing an LDAP Server With the Default +LDAP Port +... +LDAP *ld +... +ld = ldap_init( "directory.example.com", LDAP_PORT ); + +If successful, ldap_init, or prldap_init, +returns a connection handle to the LDAP server. A connection handle is +a pointer to the LDAP structure that contains information +about the connection. You must pass this pointer to the API for connecting, +authenticating, and performing LDAP operations on a server. For example, when +you search the directory, you pass the connection handle as a parameter to +provide a context for the connection. +The initialization function does not open a connection to the +LDAP server. The actual opening of a connection occurs when the first operation +is attempted. + +Specifying a List of LDAP Servers +When initializing the LDAP session, you can also specify a list of LDAP +servers for which you want to attempt connections. If the first LDAP server +in the list does not respond, the client attempts to connect to the next server +in the list. To specify a list of LDAP servers, pass a space-delimited list +of the host names as the first argument to the ldap_init or +prldap_init function. In the following example, the LDAP client +attempts to connect to the LDAP server on ld1.example.com, +port 389. If that server does not respond, the client attempts +to connect to the LDAP server on ld2.example2.com, port +389. If that server does not respond, the client uses the server +on ld3.example.com, port 389. +Passing Multiple LDAP Servers +With the Default LDAP Port +... +LDAP *ld +... +ld = ldap_init( "ld1.example.com ld2.example2.com + ld3.example.com", LDAP_PORT ); + +If any servers do not use the default LDAP port, use the host +:port format to specify the server name +and port number. In the following example, that means ld1.example.com, +port 389. If that server does not respond, the client attempts +to connect to the LDAP server on ld2.example.com, port +1389. +Passing Non-Default LDAP Ports +... +LDAP *ld +... +ld = ldap_init( "ld1.example.com ld2.example.com:1389", + LDAP_PORT ); + + +Example Session Initialization + +example programs +initializing an LDAP session + +The following example initializes a session with an LDAP server, specifying +a list of LDAP servers to try: ldap.example.com:389 and +directory.example.com:1389. The example also sets a session preference +that identifies the client as an LDAP v3 client. This session initialization +code uses the prldap_init function, which works on IPv6 +networks. Notice that prldap_init does not connect to +the LDAP server right away. +After you initialize a session with an LDAP server, you can set session +preferences. For information, seeSetting Session +Preferences With Directory SDK for C. +Initializing an LDAP Session +#include <stdio.h> +#include "ldappr.h" +#include "ldap.h" +... +LDAP *ld; +int ldap_default_port, version; + +/* Specify list of LDAP servers that you want to try connecting to. */ +char *ldap_host = "ldap.example.com directory.example.com:1389"; + +/* If the LDAP server is running on the standard LDAP port (port 389), + * you can use LDAP_PORT to identify the port number. */ +ldap_default_port = LDAP_PORT; +... +/* Initialize the session with the LDAP servers. */ +if ( ( ld = prldap_init( ldap_host, ldap_default_port, NULL ) ) == NULL ) { + perror( "prldap_init" ); + return( 1 ); +} + +/* Specify the LDAP version supported by the client. */ +version = LDAP_VERSION3; +ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); + +... +/* Subsequent calls pass ld as argument to identify the LDAP server. */ + +... + + +Setting Session Preferences With &DirectorySDKForC; + +C SDK +setting LDAP session preferences + +With &DirectorySDKForC;, you can set preferences for your client +that you want applied to all LDAP sessions. To get or set the value of a preference, +call the ldap_get_option or ldap_set_option functions +respectively. + +Both functions pass two parameters in addition to the ld parameter, +which represents the connection to the server: +The option parameter identifies the +option that you want to get or set. +The value parameter is either a pointer +to a place to put the value to get, or a pointer to the value to set. + + +You can set a preference for all connections by passing NULL as +the first argument, not an LDAP structure that specifies +the connection. +Reconnecting Automatically +If communication with the LDAP server is interrupted, the server returns +LDAP_SERVER_DOWN. If you want your client to continue to attempt +communication with the server, you can set the LDAP_OPT_RECONNECT preference +for the session. Once set, if your connection is lost, the client attempts +another bind with the same authentication to reestablish the connection. +The following example shows that to set the reconnect preference, call +the ldap_set_option function and pass LDAP_OPT_RECONNECT + as the value of the option parameter. To +resume LDAP I/O operations automatically, set the optdata parameter +to LDAP_OPT_ON. This setting specifies the same connection +handle that can be used to reconnect to the server. +Passing Restart Preferences +ldap_set_option( ld, LDAP_OPT_RECONNECT, LDAP_OPT_ON ); + +To avoid resuming I/O operations, you would set the optdata parameter +to LDAP_OPT_OFF. This setting specifies that you want to +create a new connection handle to connect to the server. By default, the +optdata parameter is set to LDAP_OPT_OFF. Both +LDAP_OPT_OFF and LDAP_OPT_ON are cast to (void +*). +Specifying the LDAP Version of Your Client +If you plan to call functions that use LDAP v3 features such as controls +or extended operations, set the protocol version to LDAP v3. By default, clients +built with &DirectorySDKForC; identify themselves to LDAP servers as LDAP +v3 clients, but that was not the case with previous versions. +To specify the LDAP version supported by your client, call the ldap_set_option + function and set the LDAP_OPT_PROTOCOL_VERSION option +to the value 3. +Passing the LDAP Protocol Version Number +... +version = LDAP_VERSION3; +ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); +... + +After setting this option, as part of the authentication process, your +client sends the supported LDAP version number to the server. By setting the +version, you allow the server to determine whether or not to enable LDAP v3 +features. +LDAP v3 allows you to perform LDAP operations without first binding +to the server. An LDAP v3 server assumes that the client is LDAP v3 compliant +if the client issues non-bind operations before the client issues a bind. + +Setting Connection Timeout +Clients that use &DirectorySDKForC; can control the TCP/IP level +timeout. When the TCP/IP timeout option is not set, an attempt to connect +to a server blocks until the connection completes or the system times out. +By using the LDAP_X_OPT_CONNECT_TIMEOUT option, you can +adjust how long to wait for a connection. +You specify the timeout as an int number of milliseconds, +then call the ldap_set_option function, passing the +LDAP_X_OPT_CONNECT_TIMEOUT option. +Passing Connection Timeout Preferences +The following example sets the connection timeout to one second. +int timeout = 1000; /* 1000 milliseconds == 1 second */ +ldap_set_option( ld, LDAP_X_OPT_CONNECT_TIMEOUT, &timeout ); + + +The LDAP_X_OPT_CONNECT_TIMEOUT option can be set +using the following values as well: +LDAP_X_IO_TIMEOUT_NO_WAITReturn +immediately if the server cannot be reached. +LDAP_X_IO_TIMEOUT_NO_TIMEOUTWait +indefinitely for the server to connect. + +By passing NULL as the first parameter to the +ldap_set_option function, you can set the default timeout for all +connections used by your application. + + +Binding and Authenticating to an LDAP Server With &DirectorySDKForC; + +C SDK +binding and authenticating + +binding +with C SDK + +When connecting to the LDAP server, your client might need to send a +bind request. + +A bind request should be sent if either of the following are true. +You want to authenticate to the server to add or modify entries +in a directory that requires authentication as a user with certain access +privileges. +You are connecting to an LDAP v2 server. LDAP v2 servers typically +require clients to bind before any operations can be performed. + + + +The bind request should contain the following information: + LDAP version of the client + Method of authentication to use + DN that the client is attempting to authenticate as + + Credentials to be used for authentication + +LDAP clients can also bind anonymously to the LDAP server if, for example, +the server is configured not to require authentication for a simple directory +search. +Using Simple Authentication With &DirectorySDKForC; + +C SDK +methods of authentication +simple authentication + +authentication +C SDK +simple + + +If you plan to use simple authentication, call one of the following +functions: +ldap_simple_bind_s is a synchronous function +for use if you want to wait for the bind operation to complete before the +function returns.See Performing a Synchronous +Authentication Operation +ldap_simple_bind is an asynchronous function +for use if you do not want to wait for the bind operation to complete. With +this function, you can perform other work while periodically checking for +the results of the bind operation.See Performing +an Asynchronous Authentication Operation + +For more information about the differences between the types of functions, +see Synchronous and Asynchronous Functions. +Performing a Synchronous Authentication Operation +If you want to wait for the bind operation to complete before continuing, +call ldap_simple_bind_s. This function returns LDAP_SUCCESS + if the operation completed successfully, or an LDAP result code +if a problem occurred. See ldap_simple_bind_s in ldap_simple_bind_s for a list of result codes returned. + +If you specify a DN but no password, your client binds to the server +anonymously. If you want a NULL password to be rejected +as incorrect, you must write code to perform the check before you call +ldap_simple_bind_s. +The following example uses the synchronous ldap_simple_bind_s function +to authenticate user Barbara Jensen to the LDAP server. +Performing Synchronous Authentication + +#include <stdio.h> +#include "ldap.h" + +/* Change these as needed. */ +#define HOSTNAME "localhost" +#define PORTNUMBER LDAP_PORT +#define BIND_DN "uid=bjensen,ou=People,dc=example,dc=com" +#define BIND_PW "hifalutin" + +LDAP *ld; +int rc; +/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ +if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); +} + +/* Print out an informational message. */ +printf( "Binding to server %s:%d\n", HOSTNAME, PORTNUMBER ); +printf( "as the DN %s ...\n", BIND_DN ); + +/* Bind to the LDAP server. */ +rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW ); +if ( rc != LDAP_SUCCESS ) { + fprintf(stderr, "ldap_simple_bind_s: %s\n\n", ldap_err2string(rc)); + return( 1 ); +} else { + printf( "Bind operation successful.\n" ); +} + +... +/* If you want, you can perform LDAP operations here. */ +... + +/* Disconnect from the server when done. */ +ldap_unbind( ld ); +return( 0 ); +... + + +Performing an Asynchronous Authentication Operation +If you want to perform other work in parallel while waiting for the +bind operation to complete, call ldap_simple_bind. This +function sends an LDAP bind request to the server and returns a message ID +identifying the bind operation. To see if your client has received the results +of the bind operation, call the ldap_result function +with the message ID. If your client has received the results, ldap_result + passes back the information in an LDAPMessage structure. +To retrieve error information from LDAPMessage, you +can pass the message ID to the ldap_parse_result function. +ldap_parse_result gets the LDAP result code of the operation and +any error messages sent back from the server. This function also retrieves +any controls sent back. +If you specify a DN but no password, your client binds to the server +anonymously. If you want a NULL password to be rejected +as incorrect, you need to write code to perform the check before you call +ldap_simple_bind. +The following example uses the asynchronous ldap_simple_bind function +to authenticate user Barbara Jensen to the LDAP server. +Performing Asynchronous Authentication + + +example programs +asynchronous authentication + +#include <stdio.h> +#include "ldap.h" + +void do_other_work(); +int global_counter = 0; +... + +#define HOSTNAME "localhost" +#define PORTNUMBER LDAP_PORT +#define BIND_DN "uid=bjensen,ou=People,dc=example,dc=com" +#define BIND_PW "hifalutin" + +... +LDAP *ld; +LDAPMessage *res; +int msgid = 0, rc = 0, parse_rc = 0, finished = 0; +char *matched_msg = NULL, *error_msg = NULL; +char **referrals; +LDAPControl **serverctrls; +struct timeval zerotime; + +/* Specify the timeout period for ldap_result(), + which specifies how long the function should block when waiting + for results from the server. */ +zerotime.tv_sec = zerotime.tv_usec = 0L; + +/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ +if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); +} + +/* Print out an informational message. */ +printf( "Binding to server %s:%d\n", HOSTNAME, PORTNUMBER ); +printf( "as the DN %s ...\n", BIND_DN ); + +/* Send an LDAP bind request to the server. */ +msgid = ldap_simple_bind( ld, BIND_DN, BIND_PW ); + +/* If the returned message ID is less than zero, an error occurred. */ +if ( msgid < 0 ) { + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf(stderr, "ldap_simple_bind : %s\n", ldap_err2string(rc)); + ldap_unbind( ld ); + return( 1 ); +} + +/* Check to see if the bind operation completed. */ +while ( !finished ) { + rc = ldap_result( ld, msgid, 0, &zerotime, &res ); + switch ( rc ) { + /* If ldap_result() returns -1, error occurred. */ + case -1: + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return ( 1 ); + + /* If ldap_result() returns 0, the timeout (specified by the + timeout argument) has been exceeded before the client received + the results from the server. Continue calling ldap_result() + to poll for results from the server. */ + case 0: + break; + + default: + /* The client has received the result of the bind operation. */ + finished = 1; + + /* Parse this result to determine if the operation was successful. + Note that a non-zero value is passed as the last parameter, + which indicates that the LDAPMessage structure res should be + freed when done. (No need to call ldap_msgfree().) */ + parse_rc = ldap_parse_result( ld, res, &rc, &matched_msg, + &error_msg, &referrals, &serverctrls, 1 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_parse_result: %s\n", + ldap_err2string( parse_rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + /* Check the results of the operation. */ + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_simple_bind: %s\n", + ldap_err2string( rc ) ); + + /* If the server sent an additional error message, + print it out. */ + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + + /* If an entry specified by a DN could not be found, + the server may also return the portion of the DN + that identifies an existing entry. */ + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + ldap_unbind( ld ); + return( 1 ); + } else { + printf( "Bind operation successful.\n" ); + printf( "Counted to %d while waiting for bind op.\n", + global_counter ); + } + break; + } + /* Do other work here while waiting for results from the server. */ + if ( !finished ) { + do_other_work(); + } +} + +... +/* If you want, you can perform LDAP operations here. */ +... + +/* Disconnect from the server when done. */ +ldap_unbind( ld ); +return( 0 ); +... +/* Function that does work while waiting for results from the server. */ +void do_other_work() { + global_counter++; +} +... + + + +Binding Anonymously With &DirectorySDKForC; + +C SDK +methods of authentication +anonymous authentication + +authentication +C SDK +anonymous + +In some cases, you do not need to authenticate to the LDAP server. For +example, if users are performing a search that has no special access permissions, +you need not authenticate before performing the search. To bind as an anonymous +user, call ldap_simple_bind or ldap_simple_bind_s, +and pass NULL values for the who and +passwd parameters. +rc = ldap_simple_bind_s( ld, NULL, NULL ); + + +With LDAP v2, the client is required to send a bind request, even when +binding anonymously. That is, bind without specifying a name or password. +With LDAP v3, the client is no longer required to bind to the server if the +client does not need to authenticate. + +Performing LDAP Operations With &DirectorySDKForC; + +C SDK +LDAP operations + +LDAP operations +with C SDK + +After initializing a session with a server and completing the authentication +process, you can perform LDAP operations. The LDAP operations include searching +the directory, adding new entries, updating existing entries, and removing +entries. The following lists LDAP operations and the functions that you can +call to perform the operations. +Functions for Performing +LDAP Operations + + + + +To Perform This Operation + +Call This API Function + + + + + +Search for entries + +ldap_search_ext +ldap_search_ext_s + + + +Determine an attribute’s value + +ldap_compare_ext +ldap_compare_ext_s + + + +Add entries + +ldap_add_ext +ldap_add_ext_s + + + +Modify entries + +ldap_modify_ext +ldap_modify_ext_s + + + +Delete entries + +ldap_delete_ext +ldap_delete_ext_s + + + +Change DN of entries + +ldap_rename_ext +ldap_rename_ext_s + + + +
+Most LDAP operations can be performed synchronously or asynchronously. +The functions with names that end in _s are synchronous. +The remaining ones are asynchronous. For more information about the distinction +between the functions, see Synchronous and Asynchronous +Operations.
+Closing the Connection to an LDAP Server With &DirectorySDKForC; + +C SDK +closing an LDAP server connection + +When you have finished performing all necessary LDAP operations, you +need to close the connection to the LDAP server. After you close the connection, +you can no longer use the LDAP structure because +the structure is freed from memory. + +To close a connection to an LDAP server, call one of the following functions: + +ldap_unbind +ldap_unbind_s +ldap_unbind_ext + +Both ldap_unbind and ldap_unbind_s are +identical synchronous functions. These functions use different names so that +each function has a corresponding authentication function, ldap_simple_bind + and ldap_simple_bind_s, to close the server +connection. +The ldap_unbind_ext function allows you to include +explicitly both server and client controls in your unbind request. However, +as the server does not respond to an unbind request, you cannot receive a +response from a server control attached to your unbind request. +The following example closes the current connection with the LDAP server. +Closing an LDAP Server Connection +#include <stdio.h> +#include "ldap.h" +... +LDAP *ld; +int rc; +... +/* After completing your LDAP operations with the server, close + the connection. */ +rc = ldap_unbind( ld ); +if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_unbind: %s\n", ldap_err2string( rc ) ); +} +... + + +
diff --git a/mozilla/directory/docs/ldapcsdk/csdk-compare.sgm b/mozilla/directory/docs/ldapcsdk/csdk-compare.sgm new file mode 100644 index 00000000000..c60374fba7d --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/csdk-compare.sgm @@ -0,0 +1,438 @@ + +Comparing Attribute Values +With &DirectorySDKForC; + +C SDK +comparing attribute values + +This chapter describes how to compare the value of an attribute in an +entry against a specified value. + +This chapter covers the following topics: +Functions for Comparing Attribute +Values With Directory SDK for C +Performing Synchronous Comparison +Operations With Directory SDK for C +Performing Asynchronous Comparison +Operations With Directory SDK for C + + +Functions for Comparing Attribute Values With Directory +SDK for C +&DirectorySDKForC; has functions to determine if an attribute contains +a certain string or binary value. + +To determine if an attribute contains a certain string value, +call either of the following functions: +The synchronous ldap_compare_s function + +The asynchronous ldap_compare function + + + +To determine if an attribute contains a certain binary value, +call either of the following functions: +The synchronous ldap_compare_ext_s function + +The asynchronous ldap_compare_ext function + + + +Performing Synchronous Comparison Operations With +Directory SDK for C + +synchronous functions +comparison operation + +You can wait for the results of the compare operation to complete before +continuing. Call the synchronous ldap_compare_ext_s function +to compare values in berval structures or the synchronous +ldap_compare_s function to compare string values. These functions +send a compare request to the server and block work until the server sends +the results of the operation back to your client. + +Both functions return one of the following values after the compare +operation completes: +LDAP_COMPARE_TRUE indicates that the +attribute contains the specified value. +LDAP_COMPARE_FALSE indicates that the +attribute does not contain the specified value. + +An error code indicates that a problem has occurred during the operation. +The following example calls the synchronous ldap_compare_s function +to determine if an entry has the value bjensen@example.com in +the mail attribute. +Performing a Synchronous Compare +Operation +#include <stdio.h> +#include "ldap.h" +... +#define COMPARE_DN "uid=bjensen,ou=People,dc=example,dc=com" +#define COMPARE_ATTR "mail" +#define COMPARE_VALUE "bjensen@example.com" +... +LDAP *ld; +char *matched_msg = NULL, *error_msg = NULL; +int rc; +... +/* Perform the compare operation. */ +rc = ldap_compare_s( ld, COMPARE_DN, COMPARE_ATTR, COMPARE_VALUE ); +switch( rc ) { +case LDAP_COMPARE_TRUE: + printf( "%s has the value %s in the %s attribute.\n", COMPARE_DN, + COMPARE_VALUE, COMPARE_ATTR ); + break; +case LDAP_COMPARE_FALSE: + printf( "%s does not have the value %s in the %s attribute.\n", + COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR ); + break; +default: + fprintf( stderr, "ldap_compare_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + break; +} +ldap_unbind_s( ld ); +... + +The following sample program calls the synchronous ldap_compare_s + function. The sample program uses this function to determine if +a user entry has the value bjensen@example.com in the +mail attribute. +Sample Synchronous Compare +Program +#include <stdio.h> +#include "ldap.h" + +/* Change these as needed. */ +#define HOSTNAME "localhost" +#define PORTNUMBER LDAP_PORT +#define COMPARE_DN "uid=bjensen,ou=People,dc=example,dc=com" +#define COMPARE_ATTR "mail" +#define COMPARE_VALUE "bjensen@example.com" +int +main( int argc, char **argv ) +{ + LDAP *ld; + char *matched_msg = NULL, *error_msg = NULL; + int rc; +/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } +/* Bind anonymously to the server. */ + rc = ldap_simple_bind_s( ld, NULL, NULL ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + ldap_unbind_s( ld ); + return( 1 ); + } +/* Perform the compare operation. */ + rc = ldap_compare_s( ld, COMPARE_DN, COMPARE_ATTR, COMPARE_VALUE ); + switch( rc ) { + case LDAP_COMPARE_TRUE: + printf( "%s has the value %s in the %s attribute.\n", + COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR ); + break; + case LDAP_COMPARE_FALSE: + printf( "%s does not have the value %s in the %s attribute.\n", + COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR ); + break; + default: + fprintf( stderr, "ldap_compare_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + break; + } + ldap_unbind_s( ld ); + return 0; +} + + +Performing Asynchronous Comparison Operations With +Directory SDK for C + +asynchronous functions +comparison operation + +You can perform other work in parallel while waiting for the comparison +to complete. Call the asynchronous ldap_compare_ext function +to compare values in berval structures or the asynchronous +ldap_compare function to compare string values. These functions +send a compare request to the server and return an LDAP_SUCCESS result +code if the request was successfully sent, or an LDAP result code if an error +occurred. +Both functions pass back a message ID identifying the compare operation. +To determine whether the server sent a response for this operation to your +client, call the ldap_result function and pass in the +message ID. The ldap_result function uses the message +ID to determine if the server sent the results of the compare operation. The +ldap_result function passes back the results in an LDAPMessage + structure. You can call the ldap_parse_result function +to parse the LDAPMessage structure to determine if +the operation was successful. + +The result code should be one of the following: +LDAP_COMPARE_TRUE indicates that the +attribute contains the specified value. +LDAP_COMPARE_FALSE indicates that the +attribute does not contain the specified value. + +An error code indicates that a problem occurred during the operation. +The following example calls the asynchronous ldap_compare function +to determine if an entry has the value bjensen@example.com in +the mail attribute. +Performing an Asynchronous Compare +Operation +#include <stdio.h> +#include "ldap.h" +... +#define COMPARE_DN "uid=bjensen,ou=People,dc=example,dc=com" +#define COMPARE_ATTR "mail" +#define COMPARE_VALUE "bjensen@example.com" +... +LDAP *ld; +LDAPMessage *res; +LDAPControl **serverctrls; +char *matched_msg = NULL, *error_msg = NULL; +char **referrals; +int rc, parse_rc, msgid, finished = 0; +struct timeval zerotime; +zerotime.tv_sec = zerotime.tv_usec = 0L; +... +/* Send the LDAP compare request. */ +msgid = ldap_compare( ld, COMPARE_DN, COMPARE_ATTR, COMPARE_VALUE ); +if ( msgid < 0 ) { + fprintf( stderr, "ldap_compare: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); +} +/* Poll the server for the results of the LDAP compare operation. */ +while ( !finished ) { + rc = ldap_result( ld, msgid, 0, &zerotime, &res ); + switch ( rc ) { + + case -1: + /* An error occurred. */ + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + + case 0: + /* The timeout period specified by zerotime was exceeded, so + call ldap_result() again and continue to poll for the + results. */ + break; + + default: + /* The client has received the results of the + LDAP compare operation from the server. */ + finished = 1; + + /* Parse the results received from the server.*/ + parse_rc = ldap_parse_result( ld, res, &rc, &matched_msg, + &error_msg, &referrals, &serverctrls, 1 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_parse_result: %s\n", + ldap_err2string( parse_rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + + /* Check the results of the LDAP compare operation. */ + switch ( rc ) { + case LDAP_COMPARE_TRUE: + printf( "%s has the value %s in the %s attribute.\n", + COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR ); + break; + case LDAP_COMPARE_FALSE: + printf( "%s does not have the value %s in the %s attribute.\n", + COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR ); + break; + default: + fprintf( stderr, "ldap_compare: %s\n", ldap_err2string( rc ) ); + if ( error_msg != NULL & *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + break; + } + } +} +... + +The following sample program calls the asynchronous ldap_compare function. +The sample program uses this function to determine if a user entry has the +value bjensen@example.com in the mail attribute. + +Sample Asynchronous Compare +Program +#include <stdio.h> +#include "ldap.h" +void do_other_work(); +int global_counter = 0; +/* Change these as needed. */ +#define HOSTNAME "localhost" +#define PORTNUMBER LDAP_PORT +#define COMPARE_DN "uid=bjensen,ou=People,dc=example,dc=com" +#define COMPARE_ATTR "mail" +#define COMPARE_VALUE "bjensen@example.com" +int +main( int argc, char **argv ) +{ + LDAP *ld; + LDAPMessage *res; + LDAPControl **serverctrls; + char *matched_msg = NULL, *error_msg = NULL; + char **referrals; + int rc, parse_rc, msgid, finished = 0; + struct timeval zerotime; + zerotime.tv_sec = zerotime.tv_usec = 0L; +/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } +/* Bind anonymously to the server. */ + rc = ldap_simple_bind_s( ld, NULL, NULL ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, NULL, &error_msg ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + ldap_unbind_s( ld ); + return( 1 ); + } + /* Send the LDAP compare request. */ + msgid = ldap_compare( ld, COMPARE_DN, COMPARE_ATTR, COMPARE_VALUE ); + if ( msgid < 0 ) { + fprintf( stderr, "ldap_compare: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + } +/* Poll the server for the results of the LDAP compare operation. */ + while ( !finished ) { + rc = ldap_result( ld, msgid, 0, &zerotime, &res ); + switch ( rc ) { + case -1: + /* An error occurred. */ + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + case 0: + /* The timeout period specified by zerotime was exceeded. + This means that your client has not yet received the + results of the LDAP compare operation. + Break out of this switch statement, and continue calling + ldap_result() to poll for the results. */ + break; + default: + /* The client has received the results of the + LDAP compare operation from the server. */ + finished = 1; + /* Parse the results received from the server. Note the last + argument is a non-zero value, which indicates that the + LDAPMessage structure will be freed when done. (No need + to call ldap_msgfree().) */ + parse_rc = ldap_parse_result( ld, res, &rc, &matched_msg, + &error_msg, &referrals, &serverctrls, 1 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, + "ldap_parse_result: %s\n", + ldap_err2string( parse_rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + /* Check the results of the LDAP compare operation. */ + switch ( rc ) { + case LDAP_COMPARE_TRUE: + printf( "%s has the value %s in the %s attribute.\n" + "Counted to %d while waiting for the compare operation.\n", + COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR, global_counter ); + break; + case LDAP_COMPARE_FALSE: + printf( "%s does not have the value %s in the %s attribute.\n" + "Counted to %d while waiting for the compare operation.\n", + COMPARE_DN, COMPARE_VALUE, COMPARE_ATTR, global_counter ); + break; + default: + fprintf( stderr, "ldap_compare: %s\n", ldap_err2string( rc ) ); + if ( error_msg != NULL & *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + break; + } + } + /* Do other work while waiting for the results of the + compare operation. */ + if ( !finished ) { + do_other_work(); + } + } + ldap_unbind( ld ); + return 0; +} +/* + * Perform other work while polling for results. This + * doesn't do anything useful, but it could. + */ +void +do_other_work() +{ + global_counter++; +} + + + diff --git a/mozilla/directory/docs/ldapcsdk/csdk-controls.sgm b/mozilla/directory/docs/ldapcsdk/csdk-controls.sgm new file mode 100644 index 00000000000..dc704af333d --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/csdk-controls.sgm @@ -0,0 +1,2028 @@ + +LDAP Controls With &DirectorySDKForC; + +C SDK +LDAP controls + +This chapter explains how LDAP controls work and how to use them. + +This chapter covers the following topics: +How LDAP Controls Work With Directory +SDK for C +Using Controls in the LDAP API + +Determining the Controls Supported +by the Server With Directory SDK for C +Using the Server-Side Sorting Control +With Directory SDK for C +Using the Persistent Search Control +With Directory SDK for C +Using the Entry Change Notification +Control With Directory SDK for C +Using the Virtual List View Control +With Directory SDK for C +Using the Manage DSA IT Control With +Directory SDK for C +Using Password Policy Controls With +Directory SDK for C +Using the Proxied Authorization Control +With Directory SDK for C +Using the Authorization +Identity Bind Request Control With Directory SDK for C +Using the +Get Effective Rights Request Control With Directory SDK for C + +Using the Real +Attributes Only Request Control With Directory SDK for C + +Using the Virtual +Attributes Only Request Control With Directory SDK for C + + + +How LDAP Controls Work With Directory SDK for C +LDAP v3, as documented in RFC 4511, allows clients and servers to use controls +as a mechanism for extending an LDAP operation. A control is +a way to specify additional information as part of a request and a response. +For example, a client can send a control to a server as part of a search request. +The control indicates that the server should sort the search results before +sending the results back to the client. +Servers can also send controls back to clients. For example, &cnDirectoryServer; can +send a control back to a client to indicate that the client password has expired, +or that the password is going to expire. + +A control specifies the following information: +A unique object identifier (OID) as defined by the creator +of the controlThe OID identifies the control. Table 16–1 names common OIDs. + +An indication of whether or not the control is critical to +the operation +Optional data related to the controlFor example, +the server-side sort control needs the attributes that would be used for sorting +search results. + + +When your client includes a control in a request for an LDAP operation, +the server can respond in one of the following ways: +If the server supports the control, and if the control is +appropriate, the server should make use of the control when performing the +operation. + + +If the server does not support the control type, and the control is +not appropriate, the server should do one of the following: +If the control is marked as critical to the operation, the +server should not perform the operation. Instead, the server should return +the result code LDAP_UNAVAILABLE_CRITICAL_EXTENSION. + +If the control is not marked as critical to the operation, +the server should ignore the control and perform the operation. + + + + +If you plan to use a control, make sure that the server supports the +control. See Determining the Controls Supported by +the Server With Directory SDK for C for details. +Using Controls in the LDAP API + +&DirectorySDKForC; supports two types of controls: +Server controls can be included in requests sent by clients +and in responses sent by servers. +Client controls affect the behavior of the SDK only and are +never sent to the server. + +In the SDK, a control is represented by an LDAPControl structure. + + +The fields in this structure represent the data in a control. +ldctl_oid specifies the OID of the control. + +ldctl_value contains a berval structure +that contains data that is associated with the control. +ldctl_iscritical specifies whether or not +the control is critical to the operation. LDAP_OPT_ON indicates +that the control is critical. LDAP_OPT_OFF indicates that +the control is not critical. + +The following shows the LDAPControl structure +definition. +<structname>LDAPControl</structname> Structure + +typedef struct ldapcontrol { + char *ldctl_oid; + struct berval ldctl_value; + char ldctl_iscritical; +} LDAPControl; + +You can allocate space for the control, then create the control yourself. +You can also call a function to create the control. For example, you can call +the ldap_create_sort_control function to create a server-side +sorting control. To include a control in a request, call one of the LDAP v3 +API functions, which are functions with names that end with _ext and +_ext_s. These functions allow you to pass in an array of server +controls and an array of client controls. +You can also include controls in a request by specifying the array of +controls in the LDAP_OPT_SERVER_CONTROLS option. However, +these controls are sent to the server with every request. If the control is +specific to a certain type of operation, you should use functions with names +that end with _ext and _ext_s instead. +To retrieve any controls included in a server’s response, call +the ldap_parse_result function. You can then retrieve +data from the returned controls yourself by checking the fields of the +LDAPControl structure or by calling additional functions such +as ldap_parse_sort_control. +After working with a control, or with an array of controls, free the +controls from memory. Call ldap_control_free or ldap_controls_free + function. +Determining the Controls Supported by the Server +With &DirectorySDKForC; +According to LDAP v3, servers should list any controls that the server +supports in the supportedControl attribute in the root +DSE, which is described in Chapter 14, +Getting Server Information With Directory SDK for C. +The following table shows OIDs for server controls that might be referenced +in the supportedControl attribute. +LDAP v3 Server +Controls for Directory SDK for C + + + + +OID + +Name in ldap.h + +Instructions + + + + + +1.2.840.113556.1.4.473, 1.2.840.113556.1.4.474 + + +LDAP_CONTROL_SORTREQUEST, LDAP_CONTROL_SORTRESPONSE + + +Using the Server-Side Sorting Control With +Directory SDK for C + + + +1.3.6.1.4.1.42.2.27.8.5.1 + +LDAP_CONTROL_PASSWD_POLICY + +Using Password Policy Controls With Directory +SDK for C + + + +1.3.6.1.4.1.42.2.27.9.5.2 + +LDAP_CONTROL_GETEFFECTIVERIGHTS_REQUEST + +Using the Get Effective +Rights Request Control With Directory SDK for C + + + +1.3.6.1.4.1.42.2.27.9.5.8 + +LDAP_CONTROL_ACCOUNT_USABLE + +Using Password Policy Controls With Directory +SDK for C + + + +2.16.840.1.113730.3.4.2 + +LDAP_CONTROL_MANAGEDSAIT + +Using the Manage DSA IT Control With Directory +SDK for C + + + + +2.16.840.1.113730.3.4.3 + +LDAP_CONTROL_PERSISTENTSEARCH + +Using the Persistent Search Control With Directory +SDK for C + + + +2.16.840.1.113730.3.4.7 + +LDAP_CONTROL_ENTRYCHANGE + +Using the Entry Change Notification Control +With Directory SDK for C + + + +2.16.840.1.113730.3.4.4 + +LDAP_CONTROL_PWEXPIRED + +Using Password Policy Controls With Directory +SDK for C + + + +2.16.840.1.113730.3.4.5 + +LDAP_CONTROL_PWEXPIRING + +Using Password Policy Controls With Directory +SDK for C + + + +2.16.840.1.113730.3.4.9, 2.16.840.1.113730.3.4.10 + + +LDAP_CONTROL_VLVREQUEST, +LDAP_CONTROL_VLVRESPONSE + +Using the Virtual List View Control With Directory +SDK for C + + + +2.16.840.1.113730.3.4.12, 2.16.840.1.113730.3.4.18 + + +LDAP_CONTROL_PROXYAUTH, +LDAP_CONTROL_PROXIEDAUTH + +Using the Proxied Authorization Control With +Directory SDK for C + + + +2.16.840.1.113730.3.4.15, 2.16.840.1.113730.3.4.16 + + +LDAP_CONTROL_AUTHZID_RES, LDAP_CONTROL_AUTHZID_REQ + +Also known as LDAP_CONTROL_AUTH_RESPONSE, LDAP_CONTROL_AUTH_REQUEST + + +Using the Authorization Identity +Bind Request Control With Directory SDK for C + + + +2.16.840.1.113730.3.4.17 + +LDAP_CONTROL_REAL_ATTRS_ONLY + +Using the Real Attributes +Only Request Control With Directory SDK for C + + + +2.16.840.1.113730.3.4.19 + +LDAP_CONTROL_VIRTUAL_ATTRS_ONLY + +Using the Virtual Attributes +Only Request Control With Directory SDK for C + + + +
+The following sample command-line program searches for the root DSE. +The program then prints the values of the supportedControl attribute. + +Searching for Supported +Controls +#include "ldap.h" +static char *usage = "Usage: listctrl -h hostname -p portnumber\n"; + +/* Associate OIDs of known controls with descriptions. */ +struct oid2desc { + char *oid; + char *desc; +}; +static struct oid2desc oidmap[] = { + {LDAP_CONTROL_ACCOUNT_USABLE, "Account availability control"} + {LDAP_CONTROL_AUTH_REQUEST, "Authorization bind identity request"} + {LDAP_CONTROL_AUTH_RESPONSE, "Authorization bind identity response"} + {LDAP_CONTROL_ENTRYCHANGE, "Entry change notification control"} + {LDAP_CONTROL_GETEFFECTIVERIGHTS_REQUEST, "Get effective rights control"} + {LDAP_CONTROL_MANAGEDSAIT, "Manage DSA IT control"} + {LDAP_CONTROL_PASSWD_POLICY, "Password policy control"} + {LDAP_CONTROL_PERSISTENTSEARCH, "Persistent search control"} + {LDAP_CONTROL_PROXIEDAUTH, "Proxied authorization (version 2) control"} + {LDAP_CONTROL_PROXYAUTH, "Proxied authorization (version 1) control"} + {LDAP_CONTROL_PWEXPIRED, "Password expired control"} + {LDAP_CONTROL_PWEXPIRING, "Password expiring control"} + {LDAP_CONTROL_REAL_ATTRS_ONLY, "Real attributes only control"} + {LDAP_CONTROL_SORTREQUEST, "Server-side sort request control"} + {LDAP_CONTROL_SORTRESPONSE, "Server-side sort response control"} + {LDAP_CONTROL_VIRTUAL_ATTRS_ONLY, "Virtual attributes only control"} + {LDAP_CONTROL_VLVREQUEST, "Virtual list view request control"} + {LDAP_CONTROL_VLVRESPONSE, "Virtual list view response control"} + {NULL, NULL} +}; + +int +main( int argc, char **argv ) +{ + LDAP *ld; + LDAPMessage *result, *e; + char *hostname = NULL; + char **vals; + char *attrs[2]; + int i, j, c, portnumber = LDAP_PORT, rc; + LDAPControl **serverctrls = NULL, **clntctrls = NULL; + /* Parse the command line arguments. */ + while ( ( c = getopt( argc, argv, "h:p:" ) ) != -1 ) { + switch ( c ) { + case 'h': + hostname = strdup( optarg ); + break; + case 'p': + portnumber = atoi( optarg ); + break; + default: + printf( "Unsupported option: %c\n", c ); + printf( usage ); + exit( 1 ); + } + } + /* By default, connect to localhost at port 389. */ + if ( hostname == NULL || hostname[0] == NULL ) { + hostname = "localhost"; + } + /* Initialize the connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( hostname, portnumber )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } + /* Set automatic referral processing off. */ + if ( ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_set_option" ); + return( 1 ); + } + /* Search for the root DSE and retrieve only the + supportedControl attribute. */ + attrs[ 0 ] = "supportedControl"; + attrs[ 1 ] = NULL; + rc = ldap_search_ext_s( ld, "", LDAP_SCOPE_BASE, "(objectclass=*)", + attrs, 0, serverctrls, clntctrls, NULL, NULL, &result ); + /* Check the search results. */ + switch( rc ) { + /* If successful, the root DSE was found. */ + case LDAP_SUCCESS: + break; + /* If the root DSE was not found, the server does not comply + with the LDAPv3 protocol. */ + case LDAP_PARTIAL_RESULTS: + case LDAP_NO_SUCH_OBJECT: + case LDAP_OPERATIONS_ERROR: + case LDAP_PROTOCOL_ERROR: + printf( "LDAP server %s:%d returned result code %d (%s).\n" + "This server does not support the LDAPv3 protocol.\n", + hostname, portnumber, rc, ldap_err2string( rc ) ); + return( 1 ); + break; + /* If any other value is returned, an error must have occurred. */ + default: + ldap_perror( ld, "ldap_search_ext_s" ); + return( 1 ); + break; + } + /* Get the root DSE from the results. + Since there is only one root DSE, there + should be only one entry in the results. */ + e = ldap_first_entry( ld, result ); + /* Get and print the values of the supportedControl attribute. */ + if (e != NULL && + (vals = ldap_get_values(ld, e, "supportedControl")) != NULL ) { + printf( "\nControls Supported by %s:%d\n", hostname, portnumber ); + printf( "==================================================\n" ); + for ( i = 0; vals[i] != NULL; i++ ) { + printf( "%s\n", vals[i] ); + for ( j = 0; oidmap[j].oid != NULL; j++ ) { + if ( !strcmp( vals[i], oidmap[j].oid )) { + printf( "\t%s\n", oidmap[j].desc ); + } + } + } + /* Free the values allocated by ldap_get_values(). */ + ldap_value_free( vals ); + printf( "\n" ); + } + /* Free memory allocated by ldap_search_ext_s(). */ + ldap_msgfree( result ); + ldap_unbind( ld ); + return( 0 ); +} + +
+Using the Server-Side Sorting Control With &DirectorySDKForC; + +C SDK +LDAP controls +server-side sorting + +The control with OID 1.2.840.113556.1.4.473, or +LDAP_CONTROL_SORTREQUEST as defined in the ldap.h header +file, is a server-side sorting control. When you send a search request with +this control to the server, the server should sort the results before sending +the results back to you. +The server-side sorting control is described in RFC 2891. +Specifying the Sort Order With &DirectorySDKForC; +To specify the sort order of the results, call the ldap_create_sort_keylist + function to create a sort key list from a string in the following +format: +[-]attr-name[:matching-rule-oid +] … + +attr-name is the name of the attribute +to sort by.You can specify a space-delimited list of attribute +names. +matching-rule-oid is the optional +OID of a matching rule that you want to use for sorting. +sn -givenname + +The minus sign indicates that the results should be sorted +in reverse order for that attribute. For example, the following string specifies +that results should be sorted by last name, sn, first in +ascending order. If multiple entries have the same last name, these entries +are sorted by first name, givenname, in descending order: + + +Pass this string to ldap_create_sort_keylist to +create a sort key list, which is an array of LDAPsortkey structures. +You can use this technique to create the server-side sorting control. + +Creating the Server-Side Sorting Control With &DirectorySDKForC; +Next, to create the server-side sorting control, you pass the sort key +list, the array of LDAPsortkey structures, to the +ldap_create_sort_control function. The function passes back a newly +created sort control, an LDAPControlstructure that +you can include in a search request. +You can specify whether or not the control is critical to the search +operation. If the control is marked as critical, but the server cannot sort +the results, the server should not send back any entries. See Interpreting the Results of Sorting With Directory SDK for +C for more information about the ramifications of marking the control +as critical. +After you call the ldap_create_sort_control function +and create the control, free the array of LDAPsortkey structures +by calling ldap_free_sort_keylist. When you are done +receiving sorted results from the server, free the LDAPControl structure +by calling ldap_control_free. +Performing a Search With &DirectorySDKForC; +For the server to sort the results, add the newly created server-side +sorting control to a NULL terminated array of LDAPControl + structures. Pass this array to the ldap_search_ext function +or the ldap_search_ext_s function. The server returns +a result for the search operation. The server also returns a response control. +The response control indicates the success or failure +of the sort. To determine if sort was successful, use the following procedure. +To Search With a Sort Request for Directory SDK for C + +Call ldap_parse_result to parse the result +of the search operation. The function retrieves any response +controls sent back from the server.Response controls are passed +back in a NULL terminated array of LDAPControl structures. + +Pass this array of structures as an argument to ldap_parse_sort_control + to retrieve the LDAP result code for the sorting operation. +If the sorting operation fails, the server can also return the name +of the attribute that caused the failure. The ldap_parse_sort_control function +also retrieves this name, if available. +Free the array by calling the ldap_controls_free function +when you are done parsing the array of response controls.The +server can return the following result codes. + +LDAP_SUCCESS +The results were sorted successfully. + + +LDAP_OPERATION_ERROR +An internal server error occurred. + + +LDAP_TIMELIMIT_EXCEEDED +The maximum time allowed for a search was exceeded before +the server finished sorting the results. + + +LDAP_STRONG_AUTH_REQUIRED +The server refused to send back the sorted search results +because the server requires you to use a stronger authentication method. + + +LDAP_ADMINLIMIT_EXCEEDED +The server retrieved too many entries to sort. + + +LDAP_NO_SUCH_ATTRIBUTE +The sort key list specifies an attribute that does not exist. + + +LDAP_INAPPROPRIATE_MATCHING +The sort key list specifies a matching rule that is not recognized +or appropriate. + + +LDAP_INSUFFICIENT_ACCESS +The server did not send the sorted results because the client +has insufficient access rights. + + +LDAP_BUSY +The server is too busy to sort the results. + + +LDAP_UNWILLING_TO_PERFORM +The server is unable to sort the results. + + +LDAP_OTHER +This general result code indicates that the server failed +to sort the results for a reason other than the ones listed previously. + + + + + + + +Interpreting the Results of Sorting With &DirectorySDKForC; +The following table shows the kinds of results to expect from the LDAP +server under different situations. +Server +Responses to Sorting Controls + + + + +Does the server support the sort control? + +Is the sort control marked as critical? + +Other Conditions + +Results From LDAP Server + + + + + +Server does not support the sort control. + +Control is marked as critical. + +Not applicable + +The server does not send back any entries. + + + + +Control is not marked as critical. + + +The server ignores the sorting control. Instead, the server returns +the entries unsorted. + + + +Server does support the sort control. + +Control is marked as critical. + +The server cannot sort the results by using the specified sort key list. + + +The server does not send back any entries. The server sends back the +sorting response control. The response control specifies the result code of +the sort attempt and optionally the attribute type that caused the error. + + + + + +Control is not marked as critical. + + +The server returns the entries unsorted. The server sends back the sorting +response control. The response control specifies the result code of the sort +attempt and optionally the attribute type that caused the error. + + + + +Not applicable, might or might not be marked as critical. + +The server successfully sorted the entries. + +The server sends back the sorted entries. The server sends back the +sorting response control. The response control specifies the result code of +the sort attempt, LDAP_SUCCESS. + + + + + +The search failed for any reason. + +The server sends back a result code for the search operation. The server +does not send back the sorting response control. + + + +
+
+Server-Side Sorting Control Sample Program for Directory +SDK for C +The following sample program uses the server-side sorting control to +get a list of all users in the directory. The list is sorted in ascending +order by last name, then in descending order by first name. +Applying Server—Side +Sorting Control for Direcory SDK for C +#include <stdio.h> +#include "ldap.h" +/* Change these as needed. */ +#define HOSTNAME "localhost" +#define PORTNUMBER 389 +int +main( int argc, char **argv ) +{ + LDAP *ld; + LDAPMessage *result, *e; + char *attrfail, *matched = NULL, *errmsg = NULL; + char **vals, **referrals; + int rc, parse_rc, version; + unsigned long rcode; + LDAPControl *sortctrl = NULL; + LDAPControl *requestctrls[ 2 ]; + LDAPControl **resultctrls = NULL; + LDAPsortkey **sortkeylist; + /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( HOSTNAME, PORTNUMBER ) ) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } + version = LDAP_VERSION3; + ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); + /* Create a sort key list that specifies the sort order of the results. + Sort the results by last name first, then by first name. */ + ldap_create_sort_keylist( &sortkeylist, "sn -givenname" ); + /* Create the sort control. */ + rc = ldap_create_sort_control( ld, sortkeylist, 1, &sortctrl ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, + "ldap_create_sort_control: %s\n", + ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + requestctrls[ 0 ] = sortctrl; + requestctrls[ 1 ] = NULL; + /* Search for all entries in Sunnyvale */ + rc = ldap_search_ext_s( ld, "dc=example,dc=com", LDAP_SCOPE_SUBTREE, + "(mail=*example.com*)", NULL, 0, requestctrls, + NULL, NULL, 0, &result ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_search_ext_s: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + parse_rc = ldap_parse_result( ld, result, &rc, &matched, + &errmsg, &referrals, &resultctrls, 0 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, + "ldap_parse_result: %s\n", + ldap_err2string( parse_rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_search_ext_s: %s\n", ldap_err2string( rc ) ); + if ( errmsg != NULL && *errmsg != '\0' ) { + fprintf( stderr, "%s\n", errmsg ); + } + ldap_unbind( ld ); + return( 1 ); + } + parse_rc = + ldap_parse_sort_control( ld, resultctrls, &rcode, &attrfail ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, + "ldap_parse_sort_control: %s\n", + ldap_err2string( parse_rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + + if ( rcode != LDAP_SUCCESS ) { + fprintf( stderr, "Sort error: %s\n", ldap_err2string( rcode ) ); + if ( attrfail != NULL && *attrfail != '\0' ) { + fprintf( stderr, "Bad attribute: %s\n", attrfail ); + } + ldap_unbind( ld ); + return( 1 ); + } + /* for each entry print out name + all attrs and values */ + for ( e = ldap_first_entry( ld, result ); e != NULL; + e = ldap_next_entry( ld, e ) ) { + if ((vals = ldap_get_values( ld, e, "sn")) != NULL ) { + if ( vals[0] != NULL ) { + printf( "%s", vals[0] ); + } + ldap_value_free( vals ); + } + if ((vals = ldap_get_values( ld, e, "givenname")) != NULL ) { + if ( vals[0] != NULL ) { + printf( "\t%s", vals[0] ); + } + ldap_value_free( vals ); + } + printf( "\n" ); + } + ldap_msgfree( result ); + ldap_free_sort_keylist( sortkeylist ); + ldap_control_free( sortctrl ); + ldap_controls_free( resultctrls ); + ldap_unbind( ld ); + return( 0 ); +} + + +
+Using the Persistent Search Control With &DirectorySDKForC; + +C SDK +LDAP controls +persistent search + +The control OID 2.16.840.1.113730.3.4.3, LDAP_CONTROL_PERSISTENTSEARCH + as defined in the ldap.h header file, is the +persistent search control. A persistent search is an +ongoing search operation that allows your LDAP client to get notification +of changes to the directory. +The persistent search control is described in the Internet Draft +Persistent Search: A Simple LDAP Change Notification Mechanism. +To use persistent searching for change notification, you create a persistent +search control that specifies the types of changes that you want to track. +You include the control in a search request. When an entry in the directory +changes, the server determines if the entry matches the search criteria in +your request. The server also determines if the change is the type of change +that you are tracking. If both of these conditions are true, the server sends +the entry to your client. +To create a persistent search control, call ldap_create_persistentsearch_control + as shown here. +<function>ldap_create_persistentsearch_control +</function> Prototype for Directory SDK for C +int ldap_create_persistentsearch_control( LDAP *ld, + int changetypes, int changesonly, int return_echg_ctls, + char ctl_iscritical, LDAPControl **ctrlp ); + + +You can specify the following information: +changetypes specifies the type of change +you want to track. + +You can specify any of the following or any combination of the following +using a bitwise or operator, |. +LDAP_CHANGETYPE_ADD indicates that you +want to track added entries. +LDAP_CHANGETYPE_DELETE indicates that you +want to track deleted entries. +LDAP_CHANGETYPE_MODIFY indicates that you +want to track modified entries. +LDAP_CHANGETYPE_MODDN indicates that you +want to track renamed entries. +LDAP_CHANGETYPE_ANY indicates that you +want to track all changes to entries. + + +changesonly indicates whether or not you +want the server to return all entries that initially matched the search criteria. +Use 0 to return all entries, or non zero to return only +the entries that change. +return_echg_ctls indicates whether or not +you want entry change notification controls included with every modified entry +returned by the server. Use a non zero value to return entry change notification +controls. + +You can use this control in conjunction with an entry change notification +control. See Using the Entry Change Notification +Control With Directory SDK for C for details. +The ldap_create_persistentsearch_control function +passes back an LDAPControl structure that represents +the control in the ctrlp parameter. You can add the newly +created control to a NULL terminated array of LDAPControl + structures. Pass this array to the ldap_search_ext function. + +To end the persistent search, call the ldap_abandon_ext function. +Alternatively, call the ldap_unbind function to disconnect +from the server. +The example provided in examples/psearch.c shows +how to perform a persistent search. +Using the Entry Change Notification Control With &DirectorySDKForC; + +C SDK +LDAP controls +entry change notification + +The control with OID 2.16.840.1.113730.3.4.7, LDAP_CONTROL_ENTRYCHANGE + as defined in the ldap.h header file, is the +entry change notification control. This control contains additional information +about the change to the entry. The information includes the type of change, +and the change number, which corresponds to an item in the server’s +change log. If the entry was renamed, the control also contains the old DN +of the entry in the change log. +You use this control in conjunction with a persistent search control. +You can specify the preference for returning entry change notification controls. +The server then includes an entry change notification control with each entry +found by the search. To retrieve and parse an entry change notification control +included with an entry, follow this procedure. +To Use Entry Change Notification With Directory SDK for C + +Pass the LDAPMessage structure that represents +an entry to the ldap_get_entry_controls function. + +Pass the entry change notification control to the ldap_parse_entrychange_control + function.For more information, see Using the Persistent Search Control With Directory SDK for +C. + + + +Using the Virtual List View Control With &DirectorySDKForC; + +C SDK +LDAP controls +virtual list view + +The control with OID 2.16.840.1.113730.3.4.9, LDAP_CONTROL_VLVREQUEST + as defined in the ldap.h header file, is a virtual +list view control. When you send a search request with this control and a +server-side sorting control, the server should sort the results. The server +should then return the specified subset of entries back to your client. +The virtual list view control is described in the Internet Draft, +LDAP Extensions for Scrolling View Browsing of Search Results. + +Using the Manage DSA IT Control With &DirectorySDKForC; + +C SDK +LDAP controls +manage DSA IT + +The control with OID 2.16.840.1.113730.3.4.2, LDAP_CONTROL_MANAGEDSAIT + as defined in the ldap.h header file, is the +manage DSA IT control. You can use this control to manage search references +in the directory. To create this control, create an LDAPControl structure +and set the ldctl_oid field to 2.16.840.1.113730.3.4.2 +. +When you add this control to the array of LDAPControl structures +for ldap_search_ext or ldap_modify_ext, +the server treats search references as ordinary entries. Rather than returning +a reference to you, the server returns the entry that contains the reference. +This mechanism allows your client application to manage search references +in the directory. +The manage DSA IT control is described in RFC 2891. + +Using Password Policy Controls With &DirectorySDKForC; +&cnDirectoryServer; offers three password policy response controls sent +back to a client that performs a bind operation. The server also offers an +account availability control that does not require a bind to return status +about a client account. +Using Password Policy Expiration Controls With +Directory SDK for C + +&cnDirectoryServer; uses two server response controls to send information +back to a client after an LDAP bind operation. +The control with OID 2.16.840.1.113730.3.4.4, +LDAP_CONTROL_PWEXPIRED, is the expired password control.This +control serves when the server requires users to change passwords when first +logging in, and after password reset. After the first login, and after password +reset, the server sends this control to indicate that the client needs to +change the password immediately. At this point, the only operation that the +client can perform is to change the user’s password. If the client requests +any other operation, the server sends back an LDAP_UNWILLING_TO_PERFORM + result code with an expired password control. +The control with OID 2.16.840.1.113730.3.4.5, +LDAP_CONTROL_PWEXPIRING, is the password expiration warning control. +This control is used if the server is configured to expire user passwords +after a certain amount of time. The server sends this control back to the +client if the client binds with a password that is to expire soon . The +ldctl_value field of the LDAPControl structure +specifies the number of seconds before the password expires. + +To Use Password Policy Expiration Controls With Directory SDK +for C + +C SDK +LDAP controls +password policy + + +Call ldap_simple_bind to send a request for +an asynchronous bind operation. +Call ldap_result to get the results of the +operation. +Call ldap_parse_result to parse the result. +The function retrieves the server response controls from the result +as an array of LDAPControl structures. +Check the ldctl_oid field to determine +the OID of the control and the ldctl_value field +for any data that is included in the control. + + + +Using the Account Availability Control +With Directory SDK for C +&cnDirectoryServer; offers an account availability control that does +not require a bind to return status about a client account. The account availability +control is assigned OID 1.3.6.1.4.1.42.2.27.9.5.8, LDAP_CONTROL_ACCOUNT_USABLE +. This control allows the client to read information about an account +without having to bind as the user having that account. +To Use the Account Availability Control +With Directory SDK for C + +C SDK +LDAP controls +account status + + +Allocate an LDAPuserstatus structure +to hold the values for the account status. +Create an account status control with ldap_create_userstatus_control +. +Read the entry for which you want account status, passing in the +control as part of the search. +Get the controls on the entry that the search returns. +Pass the LDAPuserstatus structure to +ldap_parse_userstatus_control to fill the structure. +Read account status information from the LDAPuserstatus structure. + + + +Checking Account Status With Directory SDK for C +This example displays status for Barbara Jensen's account. +/* + * Get account status using the account status control. + */ + +#include "examples.h" + +int +main( int argc, char **argv ) +{ + LDAPuserstatus *status; + int version; + LDAP *ld; + int rc; + LDAPControl *status_ctrl = NULL; + LDAPControl *requestctrls[ 2 ]; + LDAPMessage *result; + char *matched = NULL; + char *errmsg = NULL; + char **referrals; + LDAPControl **resultctrls = NULL; + LDAPMessage *msg; + LDAPControl **ectrls = NULL; + + /* Allocate the LDAPuserstatus structure. */ + if ( !( status = (LDAPuserstatus*)malloc(sizeof(LDAPuserstatus)) ) ) { + perror("malloc"); + return ( 1 ); + } + + /* Use LDAPv3. */ + version = LDAP_VERSION3; + if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, &version ) + != 0 ) { + fprintf( stderr, + "ldap_set_option protocol version to %d failed\n", + version ); + return ( 1 ); + } + + /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } + + /* Create an account status control. */ + rc = ldap_create_userstatus_control( ld, 1, &status_ctrl ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_create_userstatus_control: %s\n", + ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + requestctrls[ 0 ] = status_ctrl; + requestctrls[ 1 ] = NULL; + + /* Authenticate to the directory as a user. */ + if ( ldap_simple_bind_s( ld, USER_DN, USER_PW ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_simple_bind_s" ); + return( 1 ); + } + + /* Read the account entry using the control. */ + rc = ldap_search_ext_s( ld, ENTRYDN, LDAP_SCOPE_BASE, + "(objectclass=*)", NULL, 0, requestctrls, NULL, NULL, 0, &result ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_search_ext_s: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + + /* Show the account status. */ + rc = ldap_parse_result( ld, result, &rc, &matched, &errmsg, + &referrals, &resultctrls, 0 ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_parse_result: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + + for ( msg = ldap_first_message( ld, result ); + msg != NULL; + msg = ldap_next_message ( ld, msg) ) { + if ( ldap_msgtype( msg ) != LDAP_RES_SEARCH_ENTRY ) continue; + if ( ldap_get_entry_controls( ld, msg, &ectrls ) != LDAP_SUCCESS ) { + ldap_perror ( ld, "ldap_get_entry_controls" ); + } else { + rc = ldap_parse_userstatus_control( ld, ectrls, status ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, + "ldap_parse_userstatus_control: %s\n", + ldap_err2string( rc ) ); + } else { + printf( "DN: %s\n", ENTRYDN ); + if ( LDAP_US_ACCOUNT_USABLE == status->us_available ) { + printf( " Account is usable:\tY\n" ); + } else { + printf( " Account is usable:\tN\n" ); + } + printf( " Password expires in:\t%ld s\n", + status->us_expire ); + if ( LDAP_US_ACCOUNT_INACTIVE == status->us_inactive ) { + printf( " Account is locked:\tY\n" ); + } else { + printf( " Account is locked:\tN\n" ); + } + if ( LDAP_US_ACCOUNT_RESET == status->us_reset ) { + printf( " Password was reset:\tY\n" ); + } else { + printf( " Password was reset:\tN\n" ); + } + if ( LDAP_US_ACCOUNT_EXPIRED == status->us_expired ) { + printf( " Password has expired:\tY\n" ); + } else { + printf( " Password has expired:\tN\n" ); + } + printf( " Grace logins left:\t%d\n", + status->us_remaining ); + printf( " Account unlocks in:\t%d s\n", + status->us_seconds ); + } + } + } + + ldap_msgfree( result ); + ldap_control_free( status_ctrl ); + ldap_controls_free( resultctrls ); + ldap_unbind( ld ); + return( 0 ); +} + + + +Using the Password Policy Control With +Directory SDK for C +&cnDirectoryServer; offers a password policy control to retrieve information +about the password policy that applies to the account used to bind to the +server. The password policy control is assigned OID 1.3.6.1.4.1.42.2.27.8.5.1 +, LDAP_CONTROL_PASSWD_POLICY. +To Use the Password Policy Control +With Directory SDK for C + +C SDK +LDAP controls +password policy + + +Allocate an LDAPpwdpolicy structure to +hold the values for the account status. +Create a password policy control with ldap_create_pwdpolicy_control +. +Bind sending the password policy control. +Perform a bind, a modify, an add, a compare, or an extended operation, +getting the result controls. +Pass the LDAPpwdpolicy structure to +ldap_parse_pwdpolicy_control to fill the structure. +Read password policy information from the LDAPpwdpolicy structure. + + + +Checking Password Policy for Directory SDK for C +This example displays the password policy that governs Barbara Jensen's +account retrieved during the bind operation. +/* + * Get password policy information using the password policy control. + */ + +#include "examples.h" + +int +main( int argc, char **argv ) +{ + LDAPpwdpolicy *policy; + int version; + LDAP *ld; + int rc; + LDAPControl *pwpctrl = NULL; + LDAPControl *requestctrls[ 2 ]; + int msgid; + LDAPMessage *result; + int parse_rc; + char *matched = NULL; + char *errmsg = NULL; + char **referrals; + LDAPControl **resultctrls = NULL; + + /* Allocate the LDAPpwdpolicy structure. */ + if ( !( policy = (LDAPpwdpolicy*)malloc(sizeof(LDAPpwdpolicy) ) ) ) { + perror("malloc"); + return ( 1 ); + } + + /* Use LDAPv3. */ + version = LDAP_VERSION3; + if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, &version ) + != 0 ) { + fprintf( stderr, + "ldap_set_option protocol version to %d failed\n", + version ); + return ( 1 ); + } + + /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } + + /* Create a password policy control. */ + rc = ldap_create_pwdpolicy_control( ld, 1, &pwpctrl); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_create_pwdpolicy_control: %s\n", + ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + requestctrls[ 0 ] = pwpctrl; + requestctrls[ 1 ] = NULL; + + /* Use the password policy control for the bind. */ + rc = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, &pwpctrl ); + if ( rc != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_set_option" ); + return ( 1 ); + } + + /* Authenticate to the directory, checking for result controls. */ + msgid = ldap_simple_bind( ld, ENTRYDN, ENTRYPW ); + if ( msgid < 0 ) { + fprintf( stderr, "ldap_simple_bind: %s\n", ldap_err2string( rc ) ); + if ( errmsg != NULL && errmsg != '\0' ) { + fprintf( stderr, "%s\n", errmsg ); + } + ldap_unbind( ld ); + return ( 1 ); + } + + rc = ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &result ); + if ( rc < 0 ) { + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return ( 1 ); + } + + parse_rc = ldap_parse_result( ld, result, &rc, &matched, &errmsg, + &referrals, &resultctrls, 0 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_parse_result: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return ( 1 ); + } + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_simple_bind: %s\n", ldap_err2string( rc ) ); + if ( errmsg != NULL && errmsg != '\0' ) { + fprintf( stderr, "%s\n", errmsg ); + } + } + if ( resultctrls == NULL ) { + fprintf( stderr, "No pwp result control from server.\n" ); + ldap_unbind( ld ); + return ( 1 ); + } + + /* Show the password policy information. */ + parse_rc = ldap_parse_pwdpolicy_control( ld, resultctrls, policy ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_parse_pwdpolicy_control: %s\n", + ldap_err2string( rc ) ); + ldap_unbind( ld ); + return ( 1 ); + } + + printf( "DN: %s\n", ENTRYDN ); + switch ( policy->pp_warning ) { + case LDAP_PP_WARNING_NONE: + printf( " No warnings\n" ); + break; + case LDAP_PP_WARNING_EXP: + printf( " Password expires in: %d s\n", policy->pp_warning_info ); + break; + case LDAP_PP_WARNING_GRACE: + printf( " Grace logins left: %d", policy->pp_warning_info ); + break; + default: printf( " Unrecognized password policy warning\n" ); break; + } + switch ( policy->pp_error ) { + case LDAP_PP_ERROR_NONE: + printf( " No errors\n" ); + break; + case LDAP_PP_ERROR_EXPIRED: + printf( " Password has expired, and must be reset.\n" ); + break; + case LDAP_PP_ERROR_LOCKED: + printf( " Account is locked.\n" ); + break; + case LDAP_PP_ERROR_MUSTCHANGE: + printf( " Password has been reset, and must be changed.\n" ); + break; + case LDAP_PP_ERROR_NOTMOD: + printf( " This user may not change the password.\n" ); + break; + case LDAP_PP_ERROR_OLDPASSWD: + printf( " Old password must be supplied for this operation.\n" ); + break; + case LDAP_PP_ERROR_NOQUALITY: + printf( " Password does not pass quality check.\n" ); + break; + case LDAP_PP_ERROR_TOOSHORT: + printf( " Password is too short.\n" ); + break; + case LDAP_PP_ERROR_MINAGE: + printf( " Password is too new to be modified already.\n" ); + break; + case LDAP_PP_ERROR_INHISTORY: + printf( " Password has already been used.\n" ); + break; + default: printf( " Unrecognized password policy error\n" ); break; + } + + ldap_msgfree( result ); + ldap_control_free( pwpctrl ); + ldap_controls_free( resultctrls ); + ldap_unbind( ld ); + return( 0 ); +} + + + + +Using the Proxied Authorization Control With &DirectorySDKForC; + +C SDK +LDAP controls +proxied authorization control + +Proxied authorization is an extension to LDAP v3 that allows a bound +client to assume the identity of another directory entity without rebinding. +The rebind allows the client to perform operations as if it were bound as +the proxied directory entity. All directory access, including read, write, +search, compare, delete, and add operations, is supported by proxied authorization. +For example, suppose a client is bound as uid=bjensen,ou=Engineering,dc=example,dc=com +. The user bjensen does not have the right to +search the ou=Marketing,dc=example,dc=com tree. However, +uid=lboyd,ou=Marketing,dc=example,dc=com does have rights to search +the Marketing tree, and lboyd grants proxy rights to +bjensen. In this case, bjensen can bind as herself, +assume the identity of lboyd, and then search the Marketing +tree. +This feature is intended as a performance and administrative benefit +for certain types of directory usage. Specifically, applications that allow +many clients to access directory data without rebinding as another directory +entity might use this feature. +Proxy Right for Directory SDK for C +Proxied authorization adds an additional access right: proxy. +If an entry grants the proxy right, then the entity to which that right is +granted can assume the identity of the granting entity. For example, to allow +uid=bjensen the right to proxy as uid=lboyd, +add the Proxy Right access control instruction (ACI) as shown in the following +example. This ACI allows bjensen to assume the identity +of lboyd for all directory operations. The ACI gives +bjensen permission to do to the directory whatever lboyd has +permission to do. +Proxy Right ACI +aci: (target = "ldap:///uid=lboyd,ou=Marketing,dc=example,dc=com") + (targetattr=*) + (version 3.0; aci "grant bjensen the right to proxy as lboyd"; + allow(proxy) + userdn="ldap:///uid=bjensen,ou=Engineering,dc=example,dc=com";) + + +Proxy Authorization Control With Directory SDK for +C +To support proxy authorization, an extension to LDAP v3, the proxy authorization +control has been added to &DirectorySDKForC; in the form of the ldap_create_proxyauth_control + function. You use this function to create the control that allows +a bound entity to assume the identity of another directory entry. +Proxy authorization is an optional LDAP server feature. Proxy authorization +might not be supported on all LDAP servers. You should call the proxy authorization +control function only when interacting with LDAP servers that support this +LDAP v3 extension. You can check on the support of this control by looking +at the root DSE supportedControl attribute. For example, +the following command uses the ldapsearch utility to display +the root DSE: +$ ldapsearch -h localhost -p 389 -b "" -s base "(objectclass=*)" +For the control to work, the server to connect to must support the server +control for Proxy Authorization, OID 2.16.840.1.113730.3.4.12. +This control is LDAP_CONTROL_PROXYAUTH as defined in the +ldap.h header file. +Proxy Authorization Sample Program for Directory +SDK for C +The following sample program creates an LDAP connection, sets the Proxy +Authorization control, binds to the directory, and then performs a search +operation using the Proxy Authorization control. +Program to use Proxy Authorization +Control With Directory SDK for C +#include "ldap.h" + +int version; +LDAP *ld; +LDAPControl *requestctrls[ 2 ]; +LDAPControl *pactrl = NULL; + +/* Customize the following host and bind information for your site. */ +int port=389; +char *host="directory.example.com"; +char *baseDN="dc=example,dc=com"; + +/* Proxied auth specific information. + proxyDN is the entity that will be proxied. + bindDN and bindpw is for the bind entity that will use the proxyDN. */ +char *proxyDN = "uid=lboyd,ou=marketing,dc=example,dc=com"; +char *bindDN = "uid=bjensen,ou=engineering,dc=example,dc=com"; +char *bindpw = "password"; + +/* Do general LDAP init stuff */ +/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ +if ( (ld = ldap_init( host, port ) ) == NULL ) { + printf("ldap_init did not return a conn handle.\n"); + return; + } +/* set version to ldap version 3 */ +version = LDAP_VERSION3; +ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); + +/* authenticate to the directory */ +if ( ldap_simple_bind_s( ld, bindDN, bindpw ) != LDAP_SUCCESS ) { + printf("ldap_simple_bind_s failed"); + return (-1); +} + +/* create the Proxy Authorization control */ +if ( ldap_create_proxyauth_control( ld, proxyDN, 1, &pactrl ) ) { + printf("ldap_create_proxyauth_control failed.\n"); + if ( ldap_unbind( ld ) != LDAP_SUCCESS ) { + printf("ldap_unbind failed\n"); + } + return(-1); +} + +requestctrls[ 0 ] = pactrl; +requestctrls[ 1 ] = NULL; + +/* Perform the search using the control */ +printf("Searching for %s with the proxy auth control.\n", proxyDN); +if ( ldap_search_ext_s( ld, proxyDN, LDAP_SCOPE_SUBTREE, "(objectclass=*)", + NULL, 0, requestctrls, NULL, NULL, LDAP_NO_LIMIT, &results ) != + LDAP_SUCCESS ) { + printf("ldap_search_ext failed.\n"); + printf("Something is wrong with proxied auth.\n"); +} else { + print_search_results(ld, results); +} + + + +Using the Authorization Identity Bind +Request Control With &DirectorySDKForC; + +C SDK +LDAP controls +authorization identity + +The control with OID 2.16.840.1.113730.3.4.16, +LDAP_CONTROL_AUTHZID_REQ, is the authorization identity bind request +control. This control lets you request the authorization ID when binding to +the server. +To Retrieve the Authorization ID + +&cnDirectoryServer; supports the authorization identity bind request +and response controls defined in RFC 3829. The server also allows you to retrieve the authorization +identity value as a string. + +Create an authorization identity request control using the +ldap_create_authzid_control function. +Bind sending the authorization identity request control. + +Read the authorization identity from the response control using +the ldap_parse_authzid_control function. + + +Retrieving the Authorization ID +This example gets the authorization ID for Barbara Jensen +/* + * Get the authorization ID for an operation. + */ + +#include "examples.h" + +int +main( int argc, char **argv ) +{ + int version; + LDAP *ld; + int rc; + LDAPControl *authzidctrl = NULL; + LDAPControl *requestctrls[ 2 ]; + int msgid; + LDAPMessage *result; + int parse_rc; + char *matched = NULL; + char *errmsg = NULL; + char **referrals; + LDAPControl **resultctrls = NULL; + char *authzid; + + /* Use LDAPv3. */ + version = LDAP_VERSION3; + if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, &version ) + != 0 ) { + fprintf( stderr, + "ldap_set_option protocol version to %d failed\n", + version ); + return ( 1 ); + } + + /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } + + /* Create a authorization ID control. */ + rc = ldap_create_authzid_control( ld, 1, &authzidctrl ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_create_authzid_control: %s\n", + ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + requestctrls[ 0 ] = authzidctrl; + requestctrls[ 1 ] = NULL; + + /* Use the authorization ID control for the bind. */ + rc = ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, &authzidctrl ); + if ( rc != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_set_option" ); + return ( 1 ); + } + + /* Authenticate to the directory, checking for result controls. */ + msgid = ldap_simple_bind( ld, ENTRYDN, ENTRYPW ); + if ( msgid < 0 ) { + fprintf( stderr, "ldap_simple_bind: %s\n", ldap_err2string( rc ) ); + if ( errmsg != NULL && errmsg != '\0' ) { + fprintf( stderr, "%s\n", errmsg ); + } + ldap_unbind( ld ); + return ( 1 ); + } + + rc = ldap_result( ld, msgid, LDAP_MSG_ALL, NULL, &result ); + if ( rc < 0 ) { + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return ( 1 ); + } + + parse_rc = ldap_parse_result( ld, result, &rc, &matched, &errmsg, + &referrals, &resultctrls, 0 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_parse_result: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return ( 1 ); + } + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_simple_bind: %s\n", ldap_err2string( rc ) ); + if ( errmsg != NULL && errmsg != '\0' ) { + fprintf( stderr, "%s\n", errmsg ); + } + } + if ( resultctrls == NULL ) { + fprintf( stderr, "No result control from server.\n" ); + ldap_unbind( ld ); + return ( 1 ); + } + + /* Show the authorization ID. */ + parse_rc = ldap_parse_authzid_control( ld, resultctrls, &authzid ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_parse_authzid_control: %s\n", + ldap_err2string( rc ) ); + ldap_unbind( ld ); + return ( 1 ); + } + + printf( "DN: %s\n", ENTRYDN ); + printf( "Authz ID: %s\n", authzid ); + + ldap_msgfree( result ); + ldap_control_free( authzidctrl ); + ldap_controls_free( resultctrls ); + ldap_unbind( ld ); + return( 0 ); +} + + + +Using the Get Effective Rights +Request Control With &DirectorySDKForC; + +C SDK +LDAP controls +get effective rights + +The control with OID 1.3.6.1.4.1.42.2.27.9.5.2, +LDAP_CONTROL_GETEFFECTIVERIGHTS_REQUEST, is the get effective rights +request control. This control lets you request information about the effective +access rights a user has, by performing a search for the aclRights and +aclRightsInfo attributes. +To Get Effective Rights + +Create a get effective rights request control using the ldap_create_geteffectiveRights_control + function. +Perform a search with the control, requesting the aclRights and +aclRightsInfo attributes. +Read the values of the attributes for the effective rights information. + + + +Getting Effective Rights +This example gets effective rights for Kirsten Vaughan. +/* + * Get effective rights for another user. + */ + +#include "examples.h" + +int +main( int argc, char **argv ) +{ + int version; + LDAP *ld; + int rc; + LDAPControl *gerctrl = NULL; + LDAPControl *requestctrls[ 2 ]; + char *authzid; + char **attrlist; + LDAPMessage *result; + LDAPMessage *entry; + char *attr; + BerElement *ber; + char **vals; + int i; + + /* Use LDAPv3. */ + version = LDAP_VERSION3; + if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, &version ) + != 0 ) { + fprintf( stderr, + "ldap_set_option protocol version to %d failed\n", + version ); + return ( 1 ); + } + + /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } + + /* Authenticate to the directory as a user. */ + if ( ldap_simple_bind_s( ld, USER_DN, USER_PW ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_simple_bind_s" ); + return( 1 ); + } + + /* Create a get effective rights control. */ + authzid = "dn: uid=kvaughan,ou=people,dc=example,dc=com"; + if ( !( attrlist = (char**)malloc(sizeof(char * [ 2 ]) ) ) ) { + perror( "malloc" ); + ldap_unbind( ld ); + return ( 1 ); + } + attrlist[ 0 ] = "aclRights"; + attrlist[ 1 ] = NULL; + rc = ldap_create_geteffectiveRights_control( ld, authzid, + (const char **)&attrlist, 1, &gerctrl ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_create_geteffectiveRights_control: %s\n", + ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + requestctrls[ 0 ] = gerctrl; + requestctrls[ 1 ] = NULL; + + /* Read an entry using the control. */ + rc = ldap_search_ext_s( ld, ENTRYDN, LDAP_SCOPE_BASE, + "(objectclass=*)", attrlist, 0, requestctrls, + NULL, NULL, 0, &result ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_search_ext_s: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + + /* Examine the entry for effective rights. */ + printf( "Bind DN: %s\n", ENTRYDN ); + printf( "Authz ID: %s\n", authzid ); + printf( "***Rights***\n" ); + for ( entry = ldap_first_entry( ld, result ); + entry != NULL; + entry = ldap_next_entry( ld, entry ) ) { + for ( attr = ldap_first_attribute( ld, entry, &ber ); + attr != NULL; + attr = ldap_next_attribute ( ld, entry, ber) ) { + if ( (vals = ldap_get_values( ld, entry, attr ) ) != NULL) { + for ( i = 0; vals[i] != NULL; ++i ) { + printf( "%s: %s\n", attr, vals[i] ); + } + ldap_value_free( vals ); + } + ldap_memfree( attr ); + } + if ( ber != NULL ) { + ber_free( ber, 0 ); + } + } + printf( "\n" ); + + ldap_msgfree( result ); + ldap_control_free( gerctrl ); + ldap_unbind( ld ); + return( 0 ); +} + + +When you compile and run this sample program against &cnDirectoryServer; with +a suffix that contains data from Example.ldif, the server +produces output similar to the following. Lines are wrapped for readability. +Bind DN: uid=bjensen, ou=People, dc=example,dc=com +Authz ID: dn: uid=kvaughan,ou=people,dc=example,dc=com +***Rights*** +aclRights;entryLevel: add:1,delete:1,read:1,write:1,proxy:0 +aclRights;attributeLevel;: search:1,read:1,compare:1,write:1, + selfwrite_add:1,selfwrite_delete:1,proxy:0 +aclRights;attributeLevel;dn: uid=kvaughan,ou=people,dc=example,dc=com: + search:1,read:1,compare:1,write:1,selfwrite_add:1,selfwrite_delete:1, + proxy:0 +aclRights;attributeLevel;@c : search:1,read:1,compare:1,write:1, + selfwrite_add:1,selfwrite_delete:1,proxy:0 +See your server documentation for information about aclRights + and aclRightsInfo values. + + +Using the Real Attributes Only +Request Control With &DirectorySDKForC; + +C SDK +LDAP controls +real attributes only + +The control with OID 2.16.840.1.113730.3.4.17, +LDAP_CONTROL_REAL_ATTRS_ONLY, is the real attributes only request +control. This control lets you convey to the server to return only real attributes, +attributes that are stored by the directory, during a search. +To retrieve only virtual attributes, see Using the Virtual Attributes Only +Request Control With Directory SDK for C. +To Retrieve Only Real Attributes + +Create an LDAPControl structure with +the OID defined using LDAP_CONTROL_REAL_ATTRS_ONLY. + +Pass the control in to the server with the search request. + +Free the control when finished. + + +Retrieving Only Real Attributes +This example relies on sample data from Example-roles.ldif. + +/* + * Use the control to get only real attributes. + * First load suffix data from Example-roles.ldif. + */ + +#include "examples.h" + +int +main( int argc, char **argv ) +{ + LDAPControl *ctrl = NULL; + LDAPControl *requestctrls[ 2 ]; + char **attrlist; + int version; + LDAP *ld; + char *target; + int rc; + LDAPMessage *result; + LDAPMessage *entry; + char *dn; + char *attr; + BerElement *ber; + char **vals; + int i; + + /* Prepare a real attributes only request control. */ + if ( !(ctrl = (LDAPControl *)malloc(sizeof(LDAPControl))) ) { + perror( "malloc" ); + return( 1 ); + } + ctrl->ldctl_oid = strdup( LDAP_CONTROL_REAL_ATTRS_ONLY ); + ctrl->ldctl_iscritical = 1; + requestctrls[ 0 ] = ctrl; + requestctrls[ 1 ] = NULL; + + /* Create a list of attributes to retrieve. */ + if ( !( attrlist = (char**)malloc(sizeof(char * [ 3 ]) ) ) ) { + perror( "malloc" ); + return ( 1 ); + } + attrlist[ 0 ] = "cn"; /* Real attribute */ + attrlist[ 1 ] = "nsrole"; /* Virtual attribute */ + attrlist[ 2 ] = NULL; + + /* Use LDAPv3. */ + version = LDAP_VERSION3; + if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, &version ) + != 0 ) { + fprintf( stderr, + "ldap_set_option protocol version to %d failed\n", + version ); + return ( 1 ); + } + + /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } + + /* Authenticate to the directory to read an entry. */ + if ( ldap_simple_bind_s( ld, USER_DN, USER_PW ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_simple_bind_s" ); + return( 1 ); + } + + /* Read an entry using the control. */ + target = "uid=kvaughan,ou=people,dc=example,dc=com"; + rc = ldap_search_ext_s( ld, target, LDAP_SCOPE_BASE, "(objectclass=*)", + attrlist, 0, requestctrls, NULL, NULL, 0, &result ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_search_ext_s: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + + /* Examine the results. */ + for ( entry = ldap_first_entry( ld, result ); + entry != NULL; + entry = ldap_next_entry( ld, entry ) ) { + if ( (dn = ldap_get_dn( ld, entry )) != NULL ) { + printf( "dn: %s\n", dn ); + ldap_memfree( dn ); + } + for ( attr = ldap_first_attribute( ld, entry, &ber ); + attr != NULL; + attr = ldap_next_attribute ( ld, entry, ber) ) { + if ( (vals = ldap_get_values( ld, entry, attr ) ) != NULL) { + for ( i = 0; vals[i] != NULL; ++i ) { + printf( "%s: %s\n", attr, vals[i] ); + } + ldap_value_free( vals ); + } + ldap_memfree( attr ); + } + if ( ber != NULL ) { + ber_free( ber, 0 ); + } + } + printf( "\n" ); + + ldap_msgfree( result ); + ldap_control_free( ctrl ); + ldap_unbind( ld ); + return( 0 ); +} +When you compile and run this sample program against &cnDirectoryServer; with +a suffix that contains data from Example-roles.ldif, +the server produces output similar to this: +dn: uid=kvaughan, ou=People, dc=example,dc=com +cn: Kirsten Vaughan + + + +Using the Virtual Attributes +Only Request Control With &DirectorySDKForC; + +C SDK +LDAP controls +virtual attributes only + +The control with OID 2.16.840.1.113730.3.4.19, +LDAP_CONTROL_VIRTUAL_ATTRS_ONLY, is the virtual attributes only +request control. This control lets you convey to the server to return only +virtual attributes during a search. Virtual attribute values are not stored +by the directory, but instead are generated on request. +To retrieve only real attributes, see Using the Real Attributes Only Request +Control With Directory SDK for C. +To Retrieve Only Virtual Attributes + +Create an LDAPControl structure with +the OID defined using LDAP_CONTROL_VIRTUAL_ATTRS_ONLY. + +Pass the control in to the server with the search request. + +Free the control when finished. + + +Retrieving Only Virtual Attributes +This example relies on sample data from Example-roles.ldif. + +/* + * Use the control to get only virtual attributes. + * First load suffix data from Example-roles.ldif. + */ + +#include "examples.h" + +int +main( int argc, char **argv ) +{ + LDAPControl *ctrl = NULL; + LDAPControl *requestctrls[ 2 ]; + char **attrlist; + int version; + LDAP *ld; + char *target; + int rc; + LDAPMessage *result; + LDAPMessage *entry; + char *dn; + char *attr; + BerElement *ber; + char **vals; + int i; + + /* Prepare a virtual attributes only request control. */ + if ( !(ctrl = (LDAPControl *)malloc(sizeof(LDAPControl))) ) { + perror( "malloc" ); + return( 1 ); + } + ctrl->ldctl_oid = strdup( LDAP_CONTROL_VIRTUAL_ATTRS_ONLY ); + ctrl->ldctl_iscritical = 1; + requestctrls[ 0 ] = ctrl; + requestctrls[ 1 ] = NULL; + + /* Create a list of attributes to retrieve. */ + if ( !( attrlist = (char**)malloc(sizeof(char * [ 3 ]) ) ) ) { + perror( "malloc" ); + return ( 1 ); + } + attrlist[ 0 ] = "cn"; /* Real attribute */ + attrlist[ 1 ] = "nsrole"; /* Virtual attribute */ + attrlist[ 2 ] = NULL; + + /* Use LDAPv3. */ + version = LDAP_VERSION3; + if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, &version ) + != 0 ) { + fprintf( stderr, + "ldap_set_option protocol version to %d failed\n", + version ); + return ( 1 ); + } + + /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } + + /* Authenticate to the directory to read an entry. */ + if ( ldap_simple_bind_s( ld, USER_DN, USER_PW ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_simple_bind_s" ); + return( 1 ); + } + + /* Read an entry using the control. */ + target = "uid=kvaughan,ou=people,dc=example,dc=com"; + rc = ldap_search_ext_s( ld, target, LDAP_SCOPE_BASE, "(objectclass=*)", + attrlist, 0, requestctrls, NULL, NULL, 0, &result ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_search_ext_s: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + + /* Examine the results. */ + for ( entry = ldap_first_entry( ld, result ); + entry != NULL; + entry = ldap_next_entry( ld, entry ) ) { + if ( (dn = ldap_get_dn( ld, entry )) != NULL ) { + printf( "dn: %s\n", dn ); + ldap_memfree( dn ); + } + for ( attr = ldap_first_attribute( ld, entry, &ber ); + attr != NULL; + attr = ldap_next_attribute ( ld, entry, ber) ) { + if ( (vals = ldap_get_values( ld, entry, attr ) ) != NULL) { + for ( i = 0; vals[i] != NULL; ++i ) { + printf( "%s: %s\n", attr, vals[i] ); + } + ldap_value_free( vals ); + } + ldap_memfree( attr ); + } + if ( ber != NULL ) { + ber_free( ber, 0 ); + } + } + printf( "\n" ); + + ldap_msgfree( result ); + ldap_control_free( ctrl ); + ldap_unbind( ld ); + return( 0 ); +} +When you compile and run this sample program against &cnDirectoryServer; with +a suffix that contains data from Example-roles.ldif, +the server produces output similar to this: +dn: uid=kvaughan, ou=People, dc=example,dc=com +nsrole: cn=directory administrators,dc=example,dc=com +nsrole: cn=hr managers,dc=example,dc=com + + + +
diff --git a/mozilla/directory/docs/ldapcsdk/csdk-datatypes.sgm b/mozilla/directory/docs/ldapcsdk/csdk-datatypes.sgm new file mode 100644 index 00000000000..5f4e44efb46 --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/csdk-datatypes.sgm @@ -0,0 +1,3580 @@ + +&DirectorySDKForC; Data Type Reference + +C SDK data types + +data types +C SDK data types +This chapter contains reference material for the public data types and +structures of &DirectorySDKForC;. The first sections detail the data types +of the grouped into task categories. The last section is an alphabetical listing +of the same information. The chapter contains the following sections: + +Conventions +Structure Summary by Task + +Structures Alphabetically + + + +Conventions +The following sections detail certain conventions and concepts used +in &DirectorySDKForC;. +Typographical Conventions + +C SDK data types +typographical conventions + +Table 20–1 lists +the typographical conventions used in the names of data types and structures. +Typographical Conventions +in Data Types and Structures + + + + +Convention + +Description of Use + + + + + +LeadingCaps + +Data structures needed to pass values to and from functions of &DirectorySDKForC;. +For consistency, use this typedef name for these structures, +not their literal struct name. + + + +ALL_CAPS + +Names of callback function prototypes which you can implement for extended +functionality in your client application. + + + +fns suffix + +Structures which hold the function pointers for callback functions, +grouped by task. + + + +
+
+Deprecated Structures + +C SDK data types +deprecated + +A deprecated API is one you should no longer use for new development, +and should begin to phase out for applications you maintain. Deprecated interfaces +may disappear in the major version following their deprecation. +
+Structure Summary by Task + +C SDK data types +summary by task + +In the following sections the structures defined by &DirectorySDKForC; +are grouped into task categories. +BER Structures +The structures listed in Table 20–2 + represent data encoded using the Basic Encoding Rules (BER). The +lber.h header file contains many other type definitions; the ones +listed here are those likely to be handled directly. All others are used internally +by the various functions of &DirectorySDKForC;. +BER Structures + + + + +Structure + +Description + + + + + +berval + +berval represents binary data encoded +using BER. + + + +BerElement + +BerElement indicates the current position +during a traversal of an attribute list. + + + +
+
+Structures for the Core API + +C SDK data types +summary by task + +The structures listed in Table +20–3 are used by the core functions of &DirectorySDKForC;. +These structures are used directly as argument or return types by functions +that provide the core functionality. +Core API Structures + + + + +Structure + +Description + + + + + +LDAP + +LDAP represents a connection handle +to the LDAP server. + + + +LDAPMessage + +LDAPMessage represents the results +of an LDAP operation, a chain of search results, an entry in the search results, +or a search reference in the search results. + + + +LDAPMod + +LDAPMod specifies changes to an attribute +in an directory entry. + + + +LDAPControl + +LDAPControl represents a client or +server control associated with an LDAP operation. + + + +LDAPAPIInfo + +LDAPAPIInfo represents information +about the version of &DirectorySDKForC; being implemented + + + +LDAPAPIFeatureInfo + +LDAPAPIFeatureInfo represents information +about the extended features. + + + +
+
+Structures for API Extensions +The structures listed in Table +20–4 are needed for extensions to the standard API within &DirectorySDKForC;. +These structures are used directly as arguments or return types by the functions +that provide the extended functionality. +API Extension Structures + + + + + +Structure + +Description + + + + + +LDAPsortkey + +LDAPsortkey represents a server control +used to specify that the server should sort the search results before sending +them back to the client. + + + +LDAPVirtualList + +LDAPVirtualList specifies the information +that can be used to create a virtual list view control. + + + +LDAPURLDesc + +LDAPURLDesc represents the components +of an LDAP URL. + + + +LDAPFiltInfo + +LDAPFiltInfo represents information +about a filter in a filter configuration file. + + + +LDAPFiltDesc + +LDAPFiltDesc is a type of structure +returned when you call ldap_init_getfilter to +load a filter configuration file. + + + +FriendlyMap + +FriendlyMap represents the mapping +between a list of standard attribute names and their user friendly counterparts. + + + + +LDAPMemCache + +LDAPMemCache represents an in-memory, +client-side cache. + + + +LDAPpwdpolicy + +LDAPpwdpolicy represents password +policy information concerning an entry. + + + +LDAPuserstatus + +LDAPuserstatus represents +account availability information. + + + +
+Many other types, especially prototypes for callback functions, +are associated with controls. These are listed separately in the subsequent +sections of this chapter. +
+Referral Binding Callback +This prototype for a callback function retrieves authentication information +when automatically following referrals to other servers. +Referral Binding Data Type + + + + +Data Type + +Description + + + + + +LDAP_REBINDPROC_CALLBACK + +Retrieves authentication information when following referrals to other +servers. + + + +
+
+Client-Side Sorting Callbacks +The prototype structures listed in Table 20–6 are extensions +to &DirectorySDKForC; that implement client side sorting of entries. +Client-side Sorting +Structures + + + + +Data Type + +Description + + + + + +LDAP_KEYGEN_CALLBACK + +Function prototype that generates the sorting key for each entry to +be sorted, usually by extracting a value out of an entry. + + + +LDAP_KEYCMP_CALLBACK + +Function prototype to compare 2 keys (for ordering). + + + + +LDAP_KEYFREE_CALLBACK + +Function prototype that frees the memory allocated during the KEYGEN + callback. + + + +LDAP_CMP_CALLBACK + +Function prototype to sort a specified set of entries. + + + +LDAP_VALCMP_CALLBACK + +Function prototype to sort a specified set of values. + + + +
+
+Extended I/O Control +Table 20–7 lists +the prototypes and structures used in the extended I/O control, an extension +to the standard API. +Structures and Prototypes +for Extended I/O Functionality + + + + +Data Type + +Description + + + + + +ldap_x_ext_io_fns + +This structure holds extended I/O function pointers. + + + +LDAP_X_PollFD + +An LDAP file descriptor similar to that of poll. + + + + +LDAP_X_EXTIOF_CONNECT_CALLBACK + + +Function prototype for a callback that opens a socket connection. + + + + +LDAP_X_EXTIOF_CLOSE_CALLBACK + + +Function prototype for a callback that closes a socket connection. + + + + +LDAP_X_EXTIOF_POLL_CALLBACK + + +Function prototype for a callback that surveys a server about a particular +event. + + + +LDAP_X_EXTIOF_NEWHANDLE_CALLBACK + + +Function prototype for a callback that defines a new session handle. + + + + +LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK + + +Function prototype for a callback that disposes of a session handle. + + + + +ldap_x_hostlist_status + +This structure holds utility functions for parsing space-separated host +lists. + + + +
+
+Memory Management Control +The prototypes and structures listed in Table 20–8 are used in +memory management control, an extension to the standard API. They allow developers +to specify their own memory allocation mechanisms and functions. +Memory Management +Data Types + + + + +Data Type + +Description + + + + + +ldap_memalloc_fns + +This structure holds the memory allocation callback functions. + + + + +LDAP_MALLOC_CALLBACK LDAP_CALLOC_CALLBACKLDAP_REALLOC_CALLBACK +LDAP_FREE_CALLBACK + +These callbacks allow developers to specify their own memory allocation +mechanisms. + + + +
+
+Thread Signaling Controls +The prototypes and structures listed in Table 20–9 are used +in the thread signaling control, an extension to the standard API. +Thread Signaling +Control Data Types + + + + +Data Type + +Description + + + + + +ldap_thread_fns + +Structure that contains a set of pointers to functions you want to use +when writing a multithreaded client. + + + +LDAP_TF_MUTEX_ALLOC_CALLBACK + + +Function prototype for allocating a mutex. + + + +LDAP_TF_MUTEX_FREE_CALLBACK + + +Function prototype freeing a mutex. + + + +LDAP_TF_MUTEX_LOCK_CALLBACK + + +Function prototype for locking critical sections of code. + + + +LDAP_TF_MUTEX_UNLOCK_CALLBACK + + +Function prototype for unlocking critical sections of code. + + + +LDAP_TF_GET_ERRNO_CALLBACK + +Function prototype for getting the value of the errno variable. + + + + +LDAP_TF_SET_ERRNO_CALLBACK + +Function prototype for setting the value of the errno variable. + + + + +LDAP_TF_GET_LDERRNO_CALLBACK + + +Function prototype for getting error values from calls to functions +in the libldap library. + + + +LDAP_TF_SET_LDERRNO_CALLBACK + + +Function prototype for setting error values from calls to functions +in the libldap library. + + + +ldap_extra_thread_fns + +Structure that contains a set of pointers to additional functions you +want to use when writing a multithreaded client. + + + +LDAP_TF_MUTEX_TRYLOCK_CALLBACK + + +Function prototype for attempting to lock a mutex. + + + +LDAP_TF_SEMA_ALLOC_CALLBACK + + +Function prototype for allocating a semaphore. + + + +LDAP_TF_SEMA_FREE_CALLBACK + +Function prototype for freeing a semaphore. + + + +LDAP_TF_SEMA_WAIT_CALLBACK + +Function prototype for waiting for the value of a semaphore to be greater +than 0. + + + +LDAP_TF_SEMA_POST_CALLBACK + +Function prototype for incrementing the value of a semaphore. + + + + +LDAP_TF_THREADID_CALLBACK + +Function prototype to return an identifier that is unique to the calling +thread. + + + +
+
+Deprecated and Outdated Types +Deprecated types are those being dropped from the standard or from the +extensions to &DirectorySDKForC;. They are not guaranteed to be defined +in future versions of the API. However, all of these types are still defined +in this version for backwards compatibility. Table 20–10 lists the deprecated +prototypes. +Deprecated Data Types +and Their Replacements + + + + +Data Type + +Replacement + + + + + +LDAP_CANCELPROC_CALLBACK + +Provides a way to be cancel a process, for example, by a user or because +some other condition occurs. + + + +ldap_cache_fnsLDAP_CF_BIND_CALLBACK + LDAP_CF_UNBIND_CALLBACK LDAP_CF_SEARCH_CALLBACKLDAP_CF_COMPARE_CALLBACK +LDAP_CF_ADD_CALLBACKLDAP_CF_DELETE_CALLBACK LDAP_CF_MODIFY_CALLBACK + LDAP_CF_MODRDN_CALLBACKLDAP_CF_RESULT_CALLBACKLDAP_CF_FLUSH_CALLBACK + + +ldap_cache_fns is a deprecated structure +and the typedef declarations associated with it have also +been deprecated. + + + +LDAPVersion + +Replaced by the LDAPAPIInfo type which +is returned by the ldap_get_option function +using the LDAP_OPT_API_INFO option. + + + +
+While not officially deprecated, other data types are outdated because +they have superseded by new types. Outdated types may become deprecated in +future releases of &DirectorySDKForC;. Table +20–11 lists the outdated types and the newer types which implement +the same functionality. +Outdated Types and Their +New Equivalents + + + + +Old Data Type + +New, Equivalent Data Type + + + + + +LDAPHostEnt LDAP_DNSFN_GETHOSTBYNAME LDAP_DNSFN_GETHOSTBYADDR ldap_dns_fns + +The DNS resolver callbacks are an outdated extension to the API. The +new way of specifying host information is through the LDAP_X_EXTIOF_CONNECT_CALLBACK + prototype. + + + +LDAP_IOF_CLOSE_CALLBACK LDAP_IOF_CONNECT_CALLBACK LDAP_IOF_IOCTL_CALLBACK + LDAP_IOF_READ_CALLBACK LDAP_IOF_SELECT_CALLBACK LDAP_IOF_SOCKET_CALLBACK + LDAP_IOF_SSL_ENABLE_CALLBACK LDAP_IOF_WRITE_CALLBACK ldap_io_fns + +Replaced by the types for extended I/O functionality detailed in Table 20–7. + + + +
+
+
+Structures Alphabetically + +C SDK data types +alphabetically + +The following sections detail the structures and controls of &DirectorySDKForC; +in alphabetical order. +<structname>berval</structname> + +C SDK data types +berval + +berval + +berval is a structure that represents binary data +encoded using simplified Basic Encoding Rules (BER). +Description +Use a berval structure when working with attributes +that contain binary data (such as a graphic or audio file). The data and the +size of the data are both included in a berval structure. +<structname>berval</structname> Definition +typedef struct berval { + unsigned long bv_len; + char *bv_val; +}; + +<structname>berval</structname> Field +Descriptions + + + + +Field + +What It Contains + + + + + +bv_len + +The length of the data in bytes. + + + +bv_val + +A pointer to the binary data itself. + + + +
+
+
+<structname>BerElement</structname> + +C SDK data types +BerElement + +BerElement + +The BerElement structure represents data encoded +using the Basic Encoding Rules (BER). +Description +You use this opaque data type to keep track of the current attribute +during the traversal of an attribute list. Calling the ldap_first_attribute + function allocates memory for a BerElement structure +and initializes it to select the values of the first attribute in the entry. +Subsequently, ldap_next_attribute is called +to obtain the name of each remaining attribute and set BerElement to +select their values. Once BerElement has been set to select +an attribute's values, ldap_get_values can +be used to obtain all of them from the buffer. When you are done reading the +attributes, you need to free the BerElement structure +from memory by calling the ldap_ber_free function. +(A BerElement structure can also be allocated by calling +the ber_alloc_t or the +ber_init function. In these cases, free the memory allocated to the +BerElement structure by using the ber_free function.) + +The BerElement definition is not completely +exposed in lber.h because the fields within the structure +are not intended to be accessible to clients. + + +<structname>FriendlyMap</structname> +FriendlyMap represents the mapping between a list +of standard attribute names and their user-friendly counterparts. For example, +you can represent the list of two-letter state codes (CA, IA) with their corresponding +state names (California, Iowa), or map Country ISO codes to the full country +names, in a FriendlyMap structure. +FriendlyMap is not completely defined in +ldap-extension.h because the fields within the structure are not +intended to be accessible to clients. +Related Functions + +ldap_friendly_name allocates +a FriendlyMap structure and reads a list of standard attribute +names and their user friendly counterparts from a file. +ldap_free_friendlymap frees +the memory allocated for a FriendlyMap structure. + + + + +<structname>LDAP</structname> + +C SDK data types +LDAP + +LDAP data type + +LDAP is an opaque data type representing a connection +with the LDAP server. It is initialized through a call to either the ldap_init or ldapssl_init function. + LDAP maintains the state of an LDAP session for the duration +of the connection. When you call functions that perform LDAP operations on +an LDAP server (for example, ldap_search_ext to +search the directory or ldap_modify_ext to +update an entry), you need to pass a pointer to this connection handle. With +the LDAP structure, you can also: + +Call the ldap_get_option and ldap_set_option functions to view or modify the +properties of the connection. +Call the ldap_unbind or ldap_unbind_s function to close the connection and +free the LDAP structure. + +LDAP is not completely defined in ldap-standard.h + because the fields within the structure are not intended to be +accessible to clients. + +<structname>LDAPAPIFeatureInfo</structname> + +C SDK data types +LDAPAPIFeatureInfo + +LDAPAPIFeatureInfo + +LDAPAPIFeatureInfo is a structure that represents +information about the extended features of &DirectorySDKForC;. +<structname>LDAPAPIFeatureInfo</structname> Definition + +#define LDAP_FEATURE_INFO_VERSION +typedef struct ldap_apifeature_info { + int ldapaif_info_version; /* version of this struct (1) */ + char *ldapaif_name; /* name of supported feature */ + int ldapaif_version; /* revision of supported feature */ +} LDAPAPIFeatureInfo; + +The LDAPAPIFeatureInfo structure can be retrieved +by using a sequence like the one displayed in Example 20–3. +Sequence to Retrieve <structname>LDAPAPIFeatureInfo +</structname> +LDAPAPIFeatureInfo ldfi; + ldfi.ldapaif_info_version = LDAP_FEATURE_INFO_VERSION; + ldfi.ldapaif_name = "VIRTUAL_LIST_VIEW"; + if ( ldap_get_option( NULL, LDAP_OPT_API_FEATURE_INFO, &ldfi ) == 0 ) + +Parameters +<structname>LDAPAPIFeatureInfo</structname> Structure +Parameters + + + + +Parameter + +Description + + + + + +ldapaif_info_version + +Specifies the version number of the LDAPAPIFeatureInfo structure. +This must be set to LDAP_FEATURE_INFO_VERSION before call +to ldap_get_option is performed. + + + +ldapaif_name + +Pointer to NULL terminated string that specifies +the name of the supported feature. + + + +ldapaif_version + +Specifies the version number of the supported feature. + + + +
+
+
+<structname>LDAPAPIInfo</structname> + +C SDK data types +LDAPAPIInfo + +LDAPAPIInfo + +LDAPAPIInfo is a structure that represents information +about the API and supported extensions. +<structname>LDAPAPIInfo</structname> Definition +#define LDAP_API_INFO_VERSION +typedef struct ldapapiinfo { + int ldapai_info_version; /* version of LDAPAPIInfo (1) */ + int ldapai_api_version; /* revision of API supported */ + int ldapai_protocol_version; /* highest LDAP version supported */ + char **ldapai_extensions; /* names of API extensions */ + char *ldapi_vendor_name; /* name of supplier */ + int ldapai_vendor_version; /* supplier-specific version x 100 */ + } LDAPAPIInfo; + +The LDAPAPIInfo structure can be retrieved by using +a sequence like the one displayed in Example +20–5. +Sequence to Retrieve <structname>LDAPAPIInfo +</structname> +LDAPAPIInfo ldai; + ldai.ldapai_info_version = LDAP_API_INFO_VERSION; + if ( ldap_get_option( NULL, LDAP_OPT_API_INFO, &ldia ) == 0 ) ... + +Parameters +<structname>LDAPAPIInfo</structname> Structure +Parameters + + + + +Parameter + +Description + + + + + +ldapai_info_version + +Specifies the version number of the LDAPAPIInfo structure. +This must be set to LDAP_API_INFO_VERSION before a call +to ldap_get_option is performed. + + + +ldapai_api_version + +Specifies the version number of the API that is supported. + + + +ldapai_protocol_version + +Specifies the latest LDAP version supported by the LDAP library. + + + + +ldapai_extensions + +Points to a NULL terminated array of character strings +that names the supported LDAP extensions. If none are supported, this field +is set to NULL. The application is responsible for freeing +this memory by calling the ldap_value_free function. + + + + +ldapai_vendor_name + +Pointer to a NULL-terminated string that contains the vendor's name. +Call the ldap_memfree function to free the +memory. + + + +ldapai_vendor_version + +Specifies the vendor’s version of the LDAP libraries. + + + +
+
+
+<structname>ldap_cache_fns</structname> + +C SDK data types +ldap_cache_fns + +ldap_cache_fns + +ldap_cache_fns is a deprecated structure. The following +are also deprecated: + +LDAP_CF_ADD_CALLBACK + +LDAP_CF_BIND_CALLBACK + +LDAP_CF_COMPARE_CALLBACK + +LDAP_CF_DELETE_CALLBACK + +LDAP_CF_FLUSH_CALLBACK + +LDAP_CF_MODIFY_CALLBACK + +LDAP_CF_MODRDN_CALLBACK + +LDAP_CF_RESULT_CALLBACK + +LDAP_CF_SEARCH_CALLBACK + +LDAP_CF_UNBIND_CALLBACK + + +See Also +Please see the ldap_memcache_* functions for current +usage. + +<structname>LDAP_CALLOC_CALLBACK</structname> + +C SDK data types +LDAP_CALLOC_CALLBACK + +LDAP_CALLOC_CALLBACK + +This callback function prototype of ldap_memalloc_fns + represents memory allocation. +See Also +ldap_memalloc_fns + +<structname>LDAP_CANCELPROC_CALLBACK</structname> + +C SDK data types +LDAP_CANCELPROC_CALLBACK + +LDAP_CANCELPROC_CALLBACK + +This callback function prototype is deprecated. +See Also +ldap_ufn_search_c, ldap_ufn_search_ct + +<structname>LDAP_CF_ADD_CALLBACK</structname> + +C SDK data types +LDAP_CF_ADD_CALLBACK + +LDAP_CF_ADD_CALLBACK + +This callback function prototype of ldap_cache_fns + is deprecated. +<structname>LDAP_CF_BIND_CALLBACK</structname> + +C SDK data types +LDAP_CF_BIND_CALLBACK + +LDAP_CF_BIND_CALLBACK + +This callback function prototype of ldap_cache_fns + is deprecated. +<structname>LDAP_CF_COMPARE_CALLBACK</structname> + +C SDK data types +LDAP_CF_COMPARE_CALLBACK + +LDAP_CF_COMPARE_CALLBACK + +This callback function prototype of ldap_cache_fns + is deprecated. +<structname>LDAP_CF_DELETE_CALLBACK</structname> + +C SDK data types +LDAP_CF_DELETE_CALLBACK + +LDAP_CF_DELETE_CALLBACK + +This callback function prototype of ldap_cache_fns + is deprecated. +<structname>LDAP_CF_FLUSH_CALLBACK</structname> + +C SDK data types +LDAP_CF_FLUSH_CALLBACK + +LDAP_CF_FLUSH_CALLBACK + +This callback function prototype of ldap_cache_fns + is deprecated. +<structname>LDAP_CF_MODIFY_CALLBACK</structname> + +C SDK data types +LDAP_CF_MODIFY_CALLBACK + +LDAP_CF_MODIFY_CALLBACK + +This callback function prototype of ldap_cache_fns + is deprecated. +<structname>LDAP_CF_MODRDN_CALLBACK</structname> + +C SDK data types +LDAP_CF_MODRDN_CALLBACK + +LDAP_CF_MODRDN_CALLBACK + +This callback function prototype of ldap_cache_fns + is deprecated. +<structname>LDAP_CF_RESULT_CALLBACK</structname> + +C SDK data types +LDAP_CF_RESULT_CALLBACK + +LDAP_CF_RESULT_CALLBACK + +This callback function prototype of ldap_cache_fns + is deprecated. +<structname>LDAP_CF_SEARCH_CALLBACK</structname> + +C SDK data types +LDAP_CF_SEARCH_CALLBACK + +LDAP_CF_SEARCH_CALLBACK + +This callback function prototype of ldap_cache_fns + is deprecated. +<structname>LDAP_CF_UNBIND_CALLBACK</structname> + +C SDK data types +LDAP_CF_UNBIND_CALLBACK + +LDAP_CF_UNBIND_CALLBACK + +This callback function prototype of ldap_cache_fns + is deprecated. +<structname>LDAP_CMP_CALLBACK</structname> + +C SDK data types +LDAP_CMP_CALLBACK + +LDAP_CMP_CALLBACK + +LDAP_CMP_CALLBACK specifies the prototype for a comparison +callback function used when sorting values. If you define a function with +this prototype and specify it when calling ldap_sort_entries + or ldap_multisort_entries, it will +be called by your LDAP client to sort a specified set of entries. +<structname>LDAP_CMP_CALLBACK</structname> Prototype +typedef int (LDAP_C LDAP_CALLBACK + LDAP_CMP_CALLBACK)(const char*, const char*); + +See Also +ldap_sort_entries, ldap_multisort_entries. + +<structname>LDAPControl</structname> + +C SDK data types +LDAPControl + +LDAPControl + +LDAPControl represents a client or server control +associated with an LDAP operation. If set as a server control, it is sent +to the server along with operation requests; if set as a client control, it +is interpreted locally by the client. +Controls are part of the LDAP v3. You can use a control to extend the +functionality of an LDAP operation. There are two basic types of controls +described in the LDAP v3: + +Server controls are controls that are +sent from the client to the server along with an LDAP request. (In some cases, +a server can include a control in the response it sends back to the client.) +For example, you can include a server control in a search request to specify +that you want the server to sort the search results before sending them back. + +Client controls are controls that can +extend the client but are never sent to the server. As a general example, +you might be able to pass a client control to an LDAP API function, which +might parse the control and use the data that you’ve specified in the +control.&DirectorySDKForC; does not currently support any +client controls. + +Definition of <structname>LDAPControl</structname> +typedef struct ldapcontrol { + char *ldctl_oid; + struct berval ldctl_value; + char ldctl_iscritical; +} LDAPControl; + +<structname>LDAPControl</structname> Field +Descriptions + + + + +Field + +What It Contains + + + + + +ldctl_oid + +Object identifier (OID) of the control. + + + +ldctl_value + +berval structure containing data associated +with the control. If you want to specify a zero-length value, set ldctl_value.bv_len + to 0 and ldctl_value.bv_val to +a zero-length string. To indicate that no data is associated with the control, +set ldctl_value.bv_val to NULL. + + + + +ldctl_iscritical + +Specifies whether or not the control is critical to the operation. This +field can have one of the following values: + +A non-zero value specifies that the control is critical to +the operation. +0 specifies that the control is not critical +to the operation. + + + + + +
+
+<structname>LDAP_DNSFN_GETHOSTBYADDR</structname> + +C SDK data types +LDAP_DNSFN_GETHOSTBYADDR + +LDAP_DNSFN_GETHOSTBYADDR + +LDAP_DNSFN_GETHOSTBYADDR specifies the prototype +for a callback function equivalent to the gethostbyaddr_r() function +available on some UNIX platforms. +While not officially deprecated, the functionality of this callback +prototype is superseded by the extended I/O functions. The new way of specifying +host information is through the LDAP_X_EXTIOF_CONNECT_CALLBACK + prototype. +Description +If you define a function with this prototype and set it in the ldap_dns_fns structure, your function will be called +by the SDK on behalf of your LDAP client if it needs to get the host name +of the LDAP server to which it is connected. +In this version of &DirectorySDKForC;, the functions of the +API never call this function, and your implementation will never be executed. +Therefore, its implementation is optional. +<structname>LDAP_DNSFN_GETHOSTBYADDR</structname> Prototype + +typedef LDAPHostEnt * (LDAP_C LDAP_CALLBACK +LDAP_DNSFN_GETHOSTBYADDR)( const char *addr, int length, int type, + LDAPHostEnt *result, char *buffer, int buflen, int *statusp, + void *extradata ); + + + +<structname>LDAP_DNSFN_GETHOSTBYNAME</structname> + +C SDK data types +LDAP_DNSFN_GETHOSTBYNAME + +LDAP_DNSFN_GETHOSTBYNAME + +LDAP_DNSFN_GETHOSTBYNAME specifies the prototype +for a callback function equivalent to the gethostbyname_r() function +available on some UNIX platforms. +While not officially deprecated, the functionality of this callback +prototype is superseded by the extended I/O functions. The new way of specifying +host information is through the LDAP_X_EXTIOF_CONNECT_CALLBACK + prototype. +Description +If you define a function with this prototype and set it in the ldap_dns_fns + structure, your function will be called by &DirectorySDKForC; +on behalf of your LDAP client to get the host entry for the LDAP server when +connecting to the server. +<structname>LDAP_DNSFN_GETHOSTBYNAME</structname> Prototype + +typedef LDAPHostEnt * (LDAP_C LDAP_CALLBACK +LDAP_DNSFN_GETHOSTBYADDR)( const char *addr, int length, int type, + LDAPHostEnt *result, char *buffer, int buflen, int *statusp, + void *extradata ); + + + +<structname>ldap_dns_fns</structname> + +C SDK data types +ldap_dns_fns + +ldap_dns_fns + +ldap_dns_fns contains a set of pointers to DNS functions +and is equivalent to the gethostbyname_r() and gethostbyaddr_r() + functions available on some UNIX platforms. +While not officially deprecated, the functionality of this structure +is superseded by the extended I/O functions. The new way of specifying host +information is through the LDAP_X_EXTIOF_CONNECT_CALLBACK + prototype. +Description +You can use this structure if you want &DirectorySDKForC; to call +these functions when looking up the host name or IP address for the LDAP server. +For example, you could use this to call versions of the DNS functions that +are safe for use in a multithreaded application. The function must have the +prototype specified by LDAP_DNSFN_GETHOSTBYADDR. +If NULL, the standard built-in OS routine is used. +After you set the fields in this structure, you can register the functions +for use by calling the ldap_set_option function +and setting the LDAP_OPT_DNS_FN_PTRS option to this structure. + +<structname>ldap_dns_fns</structname> Definition +struct ldap_dns_fns { + void *lddnsfn_extradata; + int lddnsfn_bufsize; + LDAP_DNSFN_GETHOSTBYNAME *lddnsfn_gethostbyname; + LDAP_DNSFN_GETHOSTBYADDR *lddnsfn_gethostbyaddr; +}; + +<structname>ldap_dns_fns</structname> Field +Descriptions + + + + +Field + +What It Contains + + + + + +lddnsfn_extradata + +Value passed in the extradata argument of the LDAP_DNSFN_GETHOSTBYADDR and LDAP_DNSFN_GETHOSTBYNAME + function calls. + + + +lddnsfn_bufsize + +Specifies the size of the buffer that you want passed to your DNS callback +function. Your LDAP client passes this value as the buflen argument +of the LDAP_DNSFN_GETHOSTBYADDR and LDAP_DNSFN_GETHOSTBYNAME function calls. + + + + +lddnsfn_gethostbyname + +Function pointer for getting the host entry for the LDAP server. This +function is called by the client when connecting to the server if the function +pointer is not NULL. The function must have the prototype +specified by LDAP_DNSFN_GETHOSTBYNAME. If +NULL, the standard built-in OS routine is used. + + + +lddnsfn_gethostbyaddr + +Function pointer for getting the host name of the LDAP server. This +function is called by the client when needed if the function pointer is not +NULL. + + + +
+
+
+<structname>ldap_extra_thread_fns</structname> + +C SDK data types +ldap_extra_thread_fns + +ldap_extra_thread_fns + +The ldap_extra_thread_fns structure contains a set +of pointers to additional functions that you can use when writing a multithreaded +client. Your client calls these functions when getting results from the LDAP structure. +&DirectorySDKForC; ignores all the elements in this structure +except for the ltf_threadid_fn function. Calling ltf_threadid_fn + will, in some cases, enhance the performance of a multithreaded +program. +After you set the fields in this structure, you can register the functions +for use by calling the ldap_set_option function +and setting the LDAP_OPT_EXTRA_THREAD_FN_PTRS option to +this structure. +<structname>ldap_extra_thread_fns</structname> Definition + +struct ldap_extra_thread_fns { + LDAP_TF_MUTEX_TRYLOCK_CALLBACK *ltf_mutex_trylock; + LDAP_TF_SEMA_ALLOC_CALLBACK *ltf_sema_alloc; + LDAP_TF_SEMA_FREE_CALLBACK *ltf_sema_free; + LDAP_TF_SEMA_WAIT_CALLBACK *ltf_sema_wait; + LDAP_TF_SEMA_POST_CALLBACK *ltf_sema_post; + LDAP_TF_THREADID_CALLBACK *ltf_threadid_fn; +}; + +<structname>ldap_extra_thread_fns</structname> Field +Descriptions + + + + +Field + +What It Contains + + + + + +ltf_mutex_trylock + +Function pointer for attempting to lock a mutex. This function is called +by the client when needed if the function pointer is not NULL. +The function must have the prototype specified by LDAP_TF_MUTEX_TRYLOCK_CALLBACK + . + + + +ltf_sema_alloc + +Function pointer for allocating a semaphore. This finction is called +by the client if needed when the function pointer is not NULL. +The function must have the prototype specified by LDAP_TF_SEMA_ALLOC_CALLBACK + . + + + +ltf_sema_free + +Function pointer for freeing a semaphore. This function is called by +the client when needed if the function pointer is not NULL. +The function must have the prototype specified by LDAP_TF_SEMA_FREE_CALLBACK + . + + + +ltf_sema_wait + +Function pointer for waiting for the value of a semaphore to be greater +than 0. This function is called by the client when needed if the function +pointer is not NULL. The function must have the prototype +specified by LDAP_TF_SEMA_WAIT_CALLBACK. + + + + +ltf_sema_post + +Function pointer for incrementing the value of a semaphore. This function +is called by the client when needed if the function pointer is not NULL. +The function must have the prototype specified by LDAP_TF_SEMA_POST_CALLBACK + . + + + +ltf_threadid_fn + +Function pointer that is called to retrieve the unique identifier for +the calling thread. If this is NULL, it is not used. An +example of a similar function in the POSIX threads standard is pthread_self() +. The function must have the prototype specified by LDAP_TF_THREADID_CALLBACK . + + + +
+
+<structname>LDAPFiltDesc</structname> + +C SDK data types +LDAPFiltDesc + +LDAPFiltDesc + +LDAPFiltDesc is a structure that is returned when +you call ldap_init_getfilter to load a filter +configuration file. +The LDAPFiltDesc definition is not completely +exposed in ldap-extension.h because the fields within the +structure are not intended to be accessible to clients. +Description +After calling the ldap_init_getfilter function, +use the pointer to the returned LDAPFiltDesc structure +in subsequent calls to get information about filters in the filter configuration +file. + +<structname>LDAPFiltInfo</structname> + +C SDK data types +LDAPFiltInfo + +LDAPFiltInfo + +LDAPFiltInfo represents information about a filter +in the filter configuration file. +Description +When you call the ldap_getfirstfilter or ldap_getnextfilter functions to get a filter from +the filter configuration file, they return a pointer to an LDAPFiltInfo structure +containing the information about the filter. +<structname>LDAPFiltInfo</structname> Definition +typedef struct ldap_filt_info { + char *lfi_filter; + char *lfi_desc; + int lfi_scope; + int lfi_isexact; + struct ldap_filt_info *lfi_next; +} LDAPFiltInfo; + +<structname>LDAPFilterInfo</structname> Field +Descriptions + + + + +Field + +What It Contains + + + + + +lfi_filter + +The filter, for example (cn=d*). + + + +lfi_desc + +Description of the filter, also the fifth field in the filter configuration +file. + + + +lfi_scope + +The scope of the filter, also the sixth field in the filter configuration +file, which can be one of the following values: + +LDAP_SCOPE_BASE specifies that the search +will be restricted to the current DN. +LDAP_SCOPE_ONELEVEL specifies that the +search will be restricted to the entries at the level beneath the current +DN. +LDAP_SCOPE_SUBTREE specifies that the search +will encompass entries at all levels beneath the current DN.If +the scope of the filter is not specified in the filter configuration file, +the scope is LDAP_SCOPE_SUBTREE by default. + + + + + + +lfi_isexact + +Specifies whether or not the filter is an exact filter, where an exact +filter contains no wildcard characters and does not match words that sound +alike: + +0 specifies that the filter is not an exact +filter. +1 specifies that the filter is an exact +filter. + + + + + +lfi_next + +Pointer to the LDAPFiltInfo structure representing +the next filter in the filter list. + + + +
+Example 20–13 prints +out information about a filter. +Sample <structname>LDAPFiltInfo</structname> Code + +LDAPFiltInfo *lfip; +/* Print out the filter */ +printf( "Filter:\t%s\n", lfdp->lfd_filter ); +printf( "Description:\t%s\n", lfdp->lfd_desc ); + +For example, in the filter configuration file, if the first filter that +applies to the value @ is: +"@" " " "(mail=%v)" "email address is" "onelevel" +The code prints out: +Filter: (mail=@) +Description: email address is +
+
+<structname>LDAP_FREE_CALLBACK</structname> + +C SDK data types +LDAP_FREE_CALLBACK + +LDAP_FREE_CALLBACK + +This callback function prototype of ldap_memalloc_fns + is used to free allocated memory. +See Also +ldap_memalloc_fns + +<structname>LDAPHostEnt</structname> + +C SDK data types +LDAPHostEnt + +LDAPHostEnt + +The LDAPHostEnt structure represents an entry for +a host found by a domain name server. +While not officially deprecated, the functionality of this callback +prototype is superseded by the extended I/O functions. The new way of specifying +host information is through the LDAP_X_EXTIOF_CONNECT_CALLBACK + prototype. +Description +This type is similar to the hostent structure returned +by functions such as gethostbyname_r() on UNIX systems. +If you are writing your own DNS functions for use by the client, they should +return the host entry in this type of structure. +The fields in this structure should point to addresses within the buffer +that is passed to the DNS callback (referenced in the LDAP callback function). +This buffer contains the host data. The pointers in the hostent structure +returned by the function point to the data in this buffer. +<structname>LDAPHostEnt</structname> Definition +typedef struct LDAPHostEnt { + char *ldaphe_name; + char **ldaphe_aliases; + int ldaphe_addrtype; + int ldaphe_length; + char **ldaphe_addr_list; +} LDAPHostEnt; + +<structname>LDAPHostEnt</structname> Field +Descriptions + + + + +Field + +What It Contains + + + + + +ldaphe_name + +Canonical name of the host + + + +ldaphe_aliases + +List of aliases for this host + + + +ldaphe_addrtype + +Address type of the host + + + +ldaphe_length + +Length of the address + + + +ldaphe_addr_list + +List of addresses for this host as returned by the name server + + + + +
+
+See Also +LDAP_DNSFN_GETHOSTBYADDR, LDAP_DNSFN_GETHOSTBYNAME +
+<structname>LDAP_IOF_CLOSE_CALLBACK</structname> + +C SDK data types +LDAP_IOF_CLOSE_CALLBACK + +LDAP_IOF_CLOSE_CALLBACK + +LDAP_IOF_CLOSE_CONNECT_CALLBACK specifies the prototype +for a callback function equivalent to the standard close system +call. +Description +If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called +by your LDAP client. +<structname>LDAP_IOF_CLOSE_CONNECT_CALLBACK</structname> Prototype + +typedef int (LDAP_C LDAP_CALLBACK + LDAP_IOF_CLOSE_CALLBACK )( LBER_SOCKET ); + + + +<structname>LDAP_IOF_CONNECT_CALLBACK</structname> + +C SDK data types +LDAP_IOF_CONNECT_CALLBACK + +LDAP_IOF_CONNECT_CALLBACK + +LDAP_IOF_CONNECT_CALLBACK specifies the prototype +for a callback function equivalent to the standard connect network +I/O function. +Description +If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called +by your LDAP client. +<structname>LDAP_IOF_CONNECT_CALLBACK</structname> Prototype + +typedef int (LDAP_C LDAP_CALLBACK + LDAP_IOF_CONNECT_CALLBACK )( LBER_SOCKET, + struct sockaddr *, int ); + + + +<structname>LDAP_IOF_IOCTL_CALLBACK</structname> + +C SDK data types +LDAP_IOF_IOCTL_CALLBACK + +LDAP_IOF_IOCTL_CALLBACK + +LDAP_IOF_IOCTL_CALLBACK specifies the prototype for +a callback function equivalent to the standard ioctl system +call. +Description +If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called +by your LDAP client. +<structname>LDAP_IOF_IOCTL_CALLBACK</structname> Prototype + +typedef int (LDAP_C LDAP_CALLBACK + LDAP_IOF_IOCTL_CALLBACK)( LBER_SOCKET, int, ... ); + + + +<structname>LDAP_IOF_READ_CALLBACK</structname> + +C SDK data types +LDAP_IOF_READ_CALLBACK + +LDAP_IOF_READ_CALLBACK + +LDAP_IOF_READ_CALLBACK specifies the prototype for +a callback function equivalent to the standard read I/O +function. +Description +If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called +by your LDAP client. +<structname>LDAP_IOF_READ_CALLBACK</structname> Prototype + +typedef int (LDAP_C LDAP_CALLBACK + LDAP_IOF_READ_CALLBACK)( LBER_SOCKET, void *, int ); + + + +<structname>LDAP_IOF_SELECT_CALLBACK</structname> + +C SDK data types +LDAP_IOF_SELECT_CALLBACK + +LDAP_IOF_SELECT_CALLBACK + +LDAP_IOF_SELECT_CALLBACK specifies the prototype +for a callback function equivalent to the standard select I/O +function. +Description +If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called +by your LDAP client. +<structname>LDAP_IOF_SELECT_CALLBACK</structname> Prototype + +typedef int (LDAP_C LDAP_CALLBACK +LDAP_IOF_SELECT_CALLBACK)( int, fd_set *, fd_set *, + fd_set *, struct timeval * ); + + + +<structname>LDAP_IOF_SOCKET_CALLBACK</structname> + +C SDK data types +LDAP_IOF_SOCKET_CALLBACK + +LDAP_IOF_SOCKET_CALLBACK + +LDAP_IOF_SOCKET_CALLBACK specifies the prototype +for a callback function equivalent to the standard socket network +I/O function. +Description +If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called +by your LDAP client. +<structname>LDAP_IOF_SOCKET_CALLBACK</structname> Prototype + +typedef LBER_SOCKET (LDAP_C LDAP_CALLBACK + LDAP_IOF_SOCKET_CALLBACK)( int, int, int ); + + + +<structname>LDAP_IOF_SSL_ENABLE_CALLBACK</structname> + +C SDK data types +LDAP_IOF_SSL_ENABLE_CALLBACK + +LDAP_IOF_SSL_ENABLE_CALLBACK + +LDAP_IOF_SSL_ENABLE_CALLBACK specifies the prototype +for a callback function equivalent to the ssl_enable function. + +Description +If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called +by your LDAP client. +<structname>LDAP_IOF_SSL_ENABLE_CALLBACK</structname> Prototype + +typedef int (LDAP_C LDAP_CALLBACK + LDAP_IOF_SSL_ENABLE_CALLBACK )( LBER_SOCKET ); + + + +<structname>LDAP_IOF_WRITE_CALLBACK</structname> + +C SDK data types +LDAP_IOF_WRITE_CALLBACK + +LDAP_IOF_WRITE_CALLBACK + +LDAP_IOF_WRITE_CALLBACK specifies the prototype for +a callback function equivalent to the standard write I/O +function. +Description +If you define a function with this prototype and set it in the ldap_io_fns structure, the function will be called +by your LDAP client. +<structname>LDAP_IOF_WRITE_CALLBACK</structname> Prototype + +typedef int (LDAP_C LDAP_CALLBACK LDAP_IOF_WRITE_CALLBACK) + ( LBER_SOCKET, const void *, int ); + + + +<structname>ldap_io_fns</structname> + +C SDK data types +ldap_io_fns + +ldap_io_fns + +The ldap_io_fns structure contains a set of pointers +to input/output functions that you want used with SDK. You need to set up +this structure if you want to connect to the LDAP server using a Secure Sockets +Layer (SSL). +<structname>ldap_io_fns</structname> Structure +struct ldap_io_fns { + LDAP_IOF_READ_CALLBACK *liof_read; + LDAP_IOF_WRITE_CALLBACK *liof_write; + LDAP_IOF_SELECT_CALLBACK *liof_select; + LDAP_IOF_SOCKET_CALLBACK *liof_socket; + LDAP_IOF_IOCTL_CALLBACK *liof_ioctl; + LDAP_IOF_CONNECT_CALLBACK *liof_connect; + LDAP_IOF_CLOSE_CALLBACK *liof_close; + LDAP_IOF_SSL_ENABLE_CALLBACK *liof_ssl_enable; +}; + +<structname>ldap_io_fns</structname> Field +Descriptions + + + + +Field + +What It Contains + + + + + +liof_read + +Function pointer to the equivalent of the standard read() I/O +function. The function must have the prototype specified by LDAP_IOF_READ_CALLBACK. + + + +liof_write + +Function pointer to the equivalent of the standard write() I/O +function. The function must have the prototype specified by LDAP_IOF_WRITE_CALLBACK. + + + +liof_select + +Function pointer to the equivalent of the standard select() I/O +function. The function must have the prototype specified by LDAP_IOF_SELECT_CALLBACK. + + + +liof_socket + +Function pointer to the equivalent of the standard socket() network +I/O function. The function must have the prototype specified by LDAP_IOF_SOCKET_CALLBACK. + + + +liof_ioctl + +Function pointer to the equivalent of the standard ioctl() system +call. The function must have the prototype specified by +LDAP_IOF_IOCTL_CALLBACK. + + + +liof_connect + +Function pointer to the equivalent of the standard connect() network +I/O function. The function must have the prototype specified by LDAP_IOF_CONNECT_CALLBACK. + + + +liof_close + +Function pointer to the equivalent of the standard close() system +call. The function must have the prototype specified by +LDAP_IOF_CLOSE_CALLBACK. + + + +liof_ssl_enable + +Function pointer to the equivalent of the ssl_enable() function. +The function must have the prototype specified by LDAP_IOF_SSL_ENABLE_CALLBACK + . + + + +
+<structname>LDAP_KEYCMP_CALLBACK</structname> + +C SDK data types +LDAP_KEYCMP_CALLBACK + +LDAP_KEYCMP__CALLBACK + +LDAP_KEYCMP_CALLBACK specifies the prototype for +a callback function to sort a specified set of entries. +Definition +If you define a function with this prototype and specify it when calling ldap_keysort_entries, the function will be called +by your LDAP client to sort a specified set of entries. +See Also +ldap_keysort_entries +
+<structname>LDAP_KEYFREE_CALLBACK</structname> + +C SDK data types +LDAP_KEYFREE_CALLBACK + +LDAP_KEYFREE__CALLBACK + +LDAP_KEYFREE_CALLBACK specifies the prototype for +a callback function that frees a sorting key. +Description +ldap_keysort_entries requires a function +pointer that matches the signature defined by this type. + +<structname>LDAP_KEYGEN_CALLBACK</structname> + +C SDK data types +LDAP_KEYGEN_CALLBACK + +LDAP_KEYGEN__CALLBACK + +LDAP_KEYGEN_CALLBACK specifies the prototype for +a callback function that generates a key for sorting. +Description +ldap_keysort_entries requires a function +pointer that matches the signature defined by this type. + +<structname>LDAP_MALLOC_CALLBACK</structname> + +C SDK data types +LDAP_MALLOC_CALLBACK + +LDAP_MALLOC__CALLBACK + +This callback function prototype of ldap_memalloc_fns + represents memory allocation. +See Also +ldap_memalloc_fns + +<structname>ldap_memalloc_fns</structname> + +C SDK data types +ldap_memalloc_fns + +ldap_memalloc_fns + +ldap_memalloc_fns is a structure representing callback +functions for memory allocation. These are global and can not be set on a +per-LDAP session handle basis. Install your own functions by making a call +similar to the one detailed in Example +20–24. +Installing <structname>ldap_memalloc_fns +</structname> +ldap_set_option(NULL, LDAP_OPT_MEMALLOC_FN_PTRS, &memalloc_fns); + + +See Also + +LDAP_MALLOC_CALLBACK + +LDAP_CALLOC_CALLBACK + +LDAP_REALLOC_CALLBACK + +LDAP_FREE_CALLBACK + + + + +<structname>LDAPMemCache</structname> + +C SDK data types +LDAPMemCache + +LDAPMemCache + +LDAPMemCache is a type of structure representing +an in-memory, client-side cache. You can create a cache and specify the following +information: + +The maximum size of the cache. +The maximum amount of time to keep an item in the cache. + +A set of base DNs for the search requests that you want to +cache (optional). +A set of functions to ensure the thread-safety of the cache. +To use a cache, you need to associate it with a connection handle (and LDAP structure). Before a search request is sent +to the server, the cache is checked to determine if the same request was made +before. If an earlier request was cached, the search results are retrieved +from the cache. + +The cache uses the search criteria as the key to cached items. +Search requests with different criteria are cached as separate items. For +example, suppose you send a search request specifying that you just want to +retrieve the uid attribute. Your client caches the result +of that search. If you send a similar search request specifying that you want +to retrieve all attributes instead of just the uid, the +result cached from the previous search are not used. +The cache uses a combination of the following information as the key +to a cached item: + +The host name and port number of the LDAP server that you +are searching. +The DN to which you are currently authenticated.From +the search criteria, the base DN, scope, filter, attributes to be returned, +and an indication of whether to return attribute types only or attribute types +and values. + +Related Functions +Table 20–21 lists +functions related to the LDAPMemCache structure. +Functions for <structname> +LDAPMemCache</structname> Structure + + + + +Function + +Description + + + + + +ldap_memcache_init + +Creates an LDAPMemCache structure and initialize +the caching mechanism. + + + +ldap_memcache_set + +Associates an LDAPMemCache structure with a connection +handle (an LDAP structure). + + + +ldap_memcache_get + +Returns the LDAPMemCache structure that is associated +with a connection handle (an LDAP structure). + + + +ldap_memcache_update + +Forces the cache to remove expired items. + + + +ldap_memcache_flush + +Removes entries from the cache. + + + +ldap_memcache_destroy + +Frees the memory used by the cache and frees the LDAPMemCache structure. + + + + +
+
+<structname>LDAPMessage</structname> + +C SDK data types +LDAPMessage + +LDAPMessage + +LDAPMessage is a structure representing the results +of an LDAP operation such as a chain of search results, an entry in the search +results, or a search reference in the search results. +LDAPMessage is not completely defined in +ldap.h because the fields within the structure are not intended +to be directly accessible to clients. + +Description +Calling the ldap_search_ext_s or ldap_search_ext followed by the ldap_result function creates an LDAPMessage structure +to represent the chain of results from the search. Calling the ldap_first_entry or ldap_next_entry + function creates an LDAPMessage structure to +represent an entry in the search results. Calling ldap_first_reference + or ldap_next_reference creates an +LDAPMessage structure to represent a search reference in the search +results. To free the LDAPMessage structure, call the ldap_msgfree routine. +
+<structname>LDAPMod</structname> + +C SDK data types +LDAPMod + +LDAPMod + +LDAPMod is a structure that you use to specify changes +to an attribute in a directory entry. +Description +Before you call the ldap_add_ext, ldap_add_ext_s, ldap_modify_ext + , or ldap_modify_ext_s functions +to add or modify an entry in the directory, you need to fill LDAPMod structures +with the attribute values that you intend to add or change. +<structname>LDAPMod</structname> Definition +typedef struct ldapmod { + int mod_op; + char *mod_type; + union { + char **modv_strvals; + struct berval **modv_bvals; + } mod_vals; +#define mod_values mod_vals.modv_strvals +#define mod_bvalues mod_vals.modv_bvals +} LDAPMod; + +<structname>LDAPMod</structname> Field +Descriptions + + + + +Field + +What It Contains + + + + + +mod_op + +The operation to be performed on the attribute and the type of data +specified as the attribute values. This field can have one of the following +values: + +LDAP_MOD_ADD adds a value to the attribute. + +LDAP_MOD_DELETE removes the value from +the attribute. +LDAP_MOD_REPLACE replaces all existing +values of the attribute.In addition, if you are specifying binary +values in the mod_bvalues field, you should use the bitwise +OR operator ( | ) to combine LDAP_MOD_BVALUES + with the operation type. For example:mod->mod_op += LDAP_MOD_ADD | LDAP_MOD_BVALUESNote the following +caveats when defining : +If you specify LDAP_MOD_DELETE and remove +all values in an attribute, the attribute is removed from the entry. + +If you specify LDAP_MOD_DELETE and NULL + in the mod_values field, the attribute is removed +from the entry. +If you specify LDAP_MOD_REPLACE and NULL + in the mod_values field, the attribute is removed +from the entry. +If you specify LDAP_MOD_REPLACE and the +attribute does not exist in the entry, the attribute is added to the entry. + +If you specify LDAP_MOD_ADD and the attribute +does not exist in the entry, the attribute is added to the entry.Also, +if you are using the structure to add a new entry, you can specify 0 for +the mod_op field, unless you are adding binary values and +need to specify LDAP_MOD_BVALUES. + + + + + +mod_type + +The attribute type that you want to add, delete, or replace the values +of such as sn or telephoneNumber. + + + + +mod_values + +A pointer to a NULL terminated array of string values +for the attribute. + + + +mod_bvalues + +A pointer to a NULL terminated array of berval structures for the attribute. + + + +
+If you’ve allocated memory for the structures yourself, you should +free them when finished by calling the ldap_mods_free function. +
+Example +Example 20–26 sets up +an LDAPMod structure to change the email address of a user’s +entry to bjensen@example.com. +Setting Up an <structname>LDAPMod</structname> Structure + +LDAP *ld; +LDAPMod attribute1; +LDAPMod *list_of_attrs[2]; +char *mail_values[] = { "bjensen@example.com", NULL }; +char *dn; +... +/* Identify the entry that you want changed */ +char *dn = "uid=bjensen,ou=People,dc=example,dc=com"; + +/* Specify that you want to replace the value of an attribute */ +attribute1.mod_op = LDAP_MOD_REPLACE; + +/* Specify that you want to change the value of the mail attribute */ +attribute1.mod_type = "mail"; + +/* Specify the new value of the mail attribute */ +attribute1.mod_values = mail_values; + +/* Add the change to the list of attributes that you want changed */ +list_of_attrs[0] = &attribute_change; +list_of_attrs[1] = NULL; + +/* Update the entry with the change */ +if ( ldap_modify_s( ld, dn, list_of_attrs ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_modify_s" ); + return( 1 ); +} +... + + +
+<structname>LDAPpwdpolicy</structname> + +C SDK data types +LDAPpwdpolicy + +LDAPpwdpolicy + +An LDAPpwdpolicy structure holds values concerning +the password policy governing a user account. +You fill this structure by passing it to the ldap_parse_pwdpolicy_control function. + +<structname>LDAPpwdpolicy</structname> Description +An LDAPpwdpolicy structure has the following +definition: +typedef struct LDAPpwdpolicy { /* password policy */ + unsigned int pp_warning; /* warning status */ +#define LDAP_PP_WARNING_NONE 0x00 +#define LDAP_PP_WARNING_EXP 0x01 +#define LDAP_PP_WARNING_GRACE 0x02 + int pp_warning_info; /* warning information */ + int pp_error; /* error information */ +#define LDAP_PP_ERROR_NONE -1 /* no error */ +#define LDAP_PP_ERROR_EXPIRED 0 /* password expired */ +#define LDAP_PP_ERROR_LOCKED 1 /* account locked */ +#define LDAP_PP_ERROR_MUSTCHANGE 2 /* paasword has to be changed */ +#define LDAP_PP_ERROR_NOTMOD 3 /* modification not allowed */ +#define LDAP_PP_ERROR_OLDPASSWD 4 /* must provide old password */ +#define LDAP_PP_ERROR_NOQUALITY 5 /* insufficient password quality */ +#define LDAP_PP_ERROR_TOOSHORT 6 /* password too short */ +#define LDAP_PP_ERROR_MINAGE 7 /* min age still in effect */ +#define LDAP_PP_ERROR_INHISTORY 8 /* password in history */ +} LDAPpwdpolicy; +<structname>LDAPpwdpolicy</structname> Field +Descriptions + + + + +Field + +What It Contains + + + + + +pp_warning + +Warning code + + + +pp_warning_info + +If pp_warning is LDAP_PP_WARNING_EXP, +this holds the number of seconds before the password expires. +If pp_warning is LDAP_PP_WARNING_GRACE, +this holds the number of grace logins remaining. + + + +pp_error + +One of the following error codes: + +LDAP_PP_ERROR_NONE, meaning no errors + +LDAP_PP_ERROR_EXPIRED, meaning the password +has expired, and must be reset +LDAP_PP_ERROR_LOCKED, meaning the account +is locked +LDAP_PP_ERROR_MUSTCHANGE, meaning the password +has been reset, and must be changed +LDAP_PP_ERROR_NOTMOD, meaning the user +may not change the password +LDAP_PP_ERROR_OLDPASSWD, meaning the old +password must be supplied for this operation +LDAP_PP_ERROR_NOQUALITY, meaning the password +does not pass the server's password quality check +LDAP_PP_ERROR_TOOSHORT, meaning the password +is too short +LDAP_PP_ERROR_MINAGE, meaning the password +is too new to be modified, yet +LDAP_PP_ERROR_INHISTORY, meaning the password +matches a password stored in the password history, and thus cannot be reused + + + + + + +
+
+Memory Concerns +You allocate and free space for the LDAPpwdpolicy structure. + +
+<structname>LDAP_REALLOC_CALLBACK</structname> + +C SDK data types +LDAP_REALLOC_CALLBACK + +LDAP_REALLOC_CALLBACK + +This callback function prototype of ldap_memalloc_fns + represents memory allocation. +See Also +ldap_memalloc_fns + +<structname>LDAP_REBINDPROC_CALLBACK</structname> + +C SDK data types +LDAP_REBINDPROC_CALLBACK + +LDAP_REBINDPROC_CALLBACK + +LDAP_REBINDPROC_CALLBACK specifies the prototype +for a callback function that retrieves authentication information when automatically +following referrals to other servers. +Description +If you define a function with this prototype and specify it when calling +the ldap_set_rebind_proc function, the function +will be called by your LDAP client. +<structname>LDAP_REBINDPROC_CALLBACK</structname> Prototype + +typedef int (LDAP_CALL LDAP_CALLBACK + LDAP_REBINDPROC_CALLBACK)( LDAP *ld, char **dnp, char **passwdp, + int *authmethodp, int freeit, void *arg); + + +See Also +ldap_set_rebind_proc + +<structname>LDAPsortkey</structname> + +C SDK data types +LDAPsortkey + +LDAPsortkey + +LDAPsortkey represents the criteria to be used by +a server control to sort search results before sending the results back to +the client. +Controls are part of the LDAP v3 and are used to extend the functionality +of an LDAP operation. The two types of controls described in the LDAP v3 are: + +Server controls are controls that are +sent from the client to the server along with an LDAP request. (In some cases, +a server can include a control in the response it sends back to the client.) +For example, you can include a server control in a search request to specify +that you want the server to sort the search results before sending them back. + +Client controls are controls that can +extend the client but that are never sent to the server. As a general example, +you might be able to pass a client control to an LDAP API function, which +might parse the control and use the data that you’ve specified in the +control. &DirectorySDKForC; does not currently support any client controls. + + + +Description +<structname>LDAPsortkey</structname> Definition +typedef struct LDAPsortkey { + char *sk_attrtype; + char *sk_matchruleoid; + int sk_reverseorder; +} LDAPsortkey; + +<structname>LDAPsortkey</structname> Field +Descriptions + + + + +Field + +What It Contains + + + + + +sk_attrtype + +Pointer to a NULL terminated string that specifies +the name of the attribute that you want to use for sorting. + + + +sk_matchruleoid + +Pointer to a NULL terminated string that specifies +the object identifier (OID) of the matching rule that you want to use for +sorting. + + + +sk_reverseorder + +Specifies whether or not the results are sorted in reverse order. This +field can have one of the following values: + +A non-zero value specifies that the results should be sorted +in reverse order. +0 specifies that the results should be +sorted in normal (forward) order. + + + + + +
+As an example, you can use LDAPsortkey to specify +that you want the server to sort search results by the roomNumber attribute. +To create an array of LDAPsortkey structures, you can call +the ldap_create_sort_keylist function. To +free an array of LDAPsortkey structures, you can call +the ldap_free_sort_keylist function. +
+
+<structname>LDAP_TF_GET_ERRNO_CALLBACK</structname> + +C SDK data types +LDAP_TF_GET_ERRNO_CALLBACK + +LDAP_TF_GET_ERRNO_CALLBACK + +LDAP_TF_GET_ERRNO_CALLBACK specifies the prototype +for a callback function to get the value of the errno variable +for a thread. +For more details on the errno variable, see ldap_thread_fns. +Description +<structname>LDAP_TF_GET_ERRNO_CALLBACK</structname> Prototype + +typedef int (LDAP_C LDAP_CALLBACK + LDAP_TF_GET_ERRNO_CALLBACK) ( void ); + + + +<structname>LDAP_TF_GET_LDERRNO_CALLBACK</structname> + +C SDK data types +LDAP_TF_GET_LDERRNO_CALLBACK + +LDAP_TF_GET_LDERRNO_CALLBACK + +LDAP_TF_GET_LDERRNO_CALLBACK specifies the prototype +for a callback function to retrieve the LDAP result code for an operation. +Description +If you define a function with this prototype and set it in the ldap_thread_fns structure, your callback function +is called when the ldap_get_lderrno function +is called. The arguments of ldap_get_lderrno are +passed to your function, and the value returned by your function is returned +by ldap_get_lderrno . +For more details on the arguments and return values that your +function must use, see ldap_get_lderrno. + +<structname>LDAP_TF_GET_LDERRNO_CALLBACK</structname> Prototype + +typedef int (LDAP_C LDAP_CALLBACK + LDAP_TF_GET_LDERRNO_CALLBACK)( char **, char **, void * ); + + + +<structname>LDAP_TF_SET_ERRNO_CALLBACK</structname> + +C SDK data types +LDAP_TF_SET_ERRNO_CALLBACK + +LDAP_TF_SET_ERRNO_CALLBACK + +LDAP_TF_SET_ERRNO_CALLBACK specifies the prototype +for a callback function to set the value of the errno variable +for a thread. +For more details on the errno variable, see ldap_thread_fns. +Description +<structname>LDAP_TF_SET_ERRNO_CALLBACK</structname> Prototype + +typedef void (LDAP_C LDAP_CALLBACK + LDAP_TF_SET_ERRNO_CALLBACK)( int ); + + + +<structname>LDAP_TF_SET_LDERRNO_CALLBACK</structname> + +C SDK data types +LDAP_TF_SET_LDERRNO_CALLBACK + +LDAP_TF_SET_LDERRNO_CALLBACK + +LDAP_TF_SET_LDERRNO_CALLBACK specifies the prototype +for a callback function to set the LDAP result code for an operation. +For more details on the arguments that your function must use, +see ldap_set_lderrno. +Description +If you define a function with this prototype and set it in the ldap_thread_fns structure, your callback function +is called when the ldap_set_lderrno function +is called. The arguments of ldap_set_lderrno are +passed to your function. +<structname>LDAP_TF_SET_LDERRNO_CALLBACK</structname> Prototype + +typedef void (LDAP_C LDAP_CALLBACK + LDAP_TF_SET_LDERRNO_CALLBACK)( int, char *, char *, void * ); + + + +<structname>LDAP_TF_MUTEX_ALLOC_CALLBACK</structname> + +C SDK data types +LDAP_TF_MUTEX_ALLOC_CALLBACK + +LDAP_TF_MUTEX_ALLOC_CALLBACK + +LDAP_TF_MUTEX_ALLOC_CALLBACK specifies the prototype +for a callback function to allocate a mutex. +Description +<structname>LDAP_TF_MUTEX_ALLOC_CALLBACK</structname> Prototype + +typedef void *(LDAP_C LDAP_CALLBACK + LDAP_TF_MUTEX_ALLOC_CALLBACK)( void ); + + +See Also +ldap_thread_fns + +<structname>LDAP_TF_MUTEX_FREE_CALLBACK</structname> + +C SDK data types +LDAP_TF_MUTEX_FREE_CALLBACK + +LDAP_TF_MUTEX_FREE_CALLBACK + +LDAP_TF_MUTEX_FREE_CALLBACK specifies the prototype +for a callback function to free a mutex. +Description +<structname>LDAP_TF_MUTEX_FREE_CALLBACK</structname> Prototype + +typedef void (LDAP_C LDAP_CALLBACK + LDAP_TF_MUTEX_FREE_CALLBACK)( void * ); + + +See Also +ldap_thread_fns + +<structname>LDAP_TF_MUTEX_LOCK_CALLBACK</structname> + +C SDK data types +LDAP_TF_MUTEX_LOCK_CALLBACK + +LDAP_TF_MUTEX_LOCK_CALLBACK + +LDAP_TF_MUTEX_LOCK_CALLBACK specifies the prototype +for a callback function to lock a mutex. +Description +<structname>LDAP_TF_MUTEX_LOCK_CALLBACK</structname> Prototype + +typedef int (LDAP_C LDAP_CALLBACK + LDAP_TF_MUTEX_LOCK_CALLBACK)( void * ); + + +See Also +ldap_thread_fns + +<structname>LDAP_TF_MUTEX_TRYLOCK_CALLBACK</structname> + +C SDK data types +LDAP_TF_MUTEX_TRYLOCK_CALLBACK + +LDAP_TF_MUTEX_TRYLOCK_CALLBACK + +This function prototype is not supported in this release of &DirectorySDKForC;. + +<structname>LDAP_TF_MUTEX_UNLOCK_CALLBACK</structname> + +C SDK data types +LDAP_TF_MUTEX_UNLOCK_CALLBACK + +LDAP_TF_MUTEX_UNLOCK_CALLBACK + +LDAP_TF_MUTEX_UNLOCK_CALLBACK specifies the prototype +for a callback function to unlock a mutex. +Description +<structname>LDAP_TF_MUTEX_UNLOCK_CALLBACK</structname> Prototype + +typedef int (LDAP_C LDAP_CALLBACK + LDAP_TF_MUTEX_UNLOCK_CALLBACK)( void * ); + + +See Also +ldap_thread_fns + +<structname>LDAP_TF_SEMA_ALLOC_CALLBACK</structname> + +C SDK data types +LDAP_TF_SEMA_ALLOC_CALLBACK + +LDAP_TF_SEMA_ALLOC_CALLBACK + +This function prototype is not supported in this release of &DirectorySDKForC;. + +<structname>LDAP_TF_SEMA_FREE_CALLBACK</structname> + +C SDK data types +LDAP_TF_SEMA_FREE_CALLBACK + +LDAP_TF_SEMA_FREE_CALLBACK + +This function prototype is not supported in this release of &DirectorySDKForC;. + + +<structname>LDAP_TF_SEMA_POST_CALLBACK</structname> + +C SDK data types +LDAP_TF_SEMA_POST_CALLBACK + +LDAP_TF_SEMA_POST_CALLBACK + +This function prototype is not supported in this release of &DirectorySDKForC;. + +<structname>LDAP_TF_SEMA_WAIT_CALLBACK</structname> + +C SDK data types +LDAP_TF_SEMA_WAIT_CALLBACK + +LDAP_TF_SEMA_WAIT_CALLBACK + +This function prototype is not supported in this release of &DirectorySDKForC;. + + +<structname>LDAP_TF_THREADID_CALLBACK</structname> + +C SDK data types +LDAP_TF_THREADID_CALLBACK + +LDAP_TF_THREADID_CALLBACK + +LDAP_TF_THREADID_CALLBACK specifies the prototype +for a callback function to return an identifier that is unique to the calling +thread, much like the POSIX pthread_self function does. +Description +<structname>LDAP_TF_THREADID_CALLBACK</structname> Prototype + +typedef void *(LDAP_C LDAP_CALLBACK + LDAP_TF_THREADID_CALLBACK)( void ); + + +See Also +ldap_thread_fns + +<structname>ldap_thread_fns</structname> + +C SDK data types +ldap_thread_fns + +ldap_thread_fns + +The ldap_thread_fns structure contains a set of pointers +to functions that you want to use when write a multithreaded client. +Description +<structname>ldap_thread_fns</structname> Structure +Definition +struct ldap_thread_fns { + LDAP_TF_MUTEX_ALLOC_CALLBACK *ltf_mutex_alloc; + LDAP_TF_MUTEX_FREE_CALLBACK *ltf_mutex_free; + LDAP_TF_MUTEX_LOCK_CALLBACK *ltf_mutex_lock; + LDAP_TF_MUTEX_UNLOCK_CALLBACK *ltf_mutex_unlock; + LDAP_TF_GET_ERRNO_CALLBACK *ltf_get_errno; + LDAP_TF_SET_ERRNO_CALLBACK *ltf_set_errno; + LDAP_TF_GET_LDERRNO_CALLBACK *ltf_get_lderrno; + LDAP_TF_SET_LDERRNO_CALLBACK *ltf_set_lderrno; + void *ltf_lderrno_arg; +}; + +<structname>ldap_thread_fns</structname> Field +Descriptions + + + + +Field + +What It Contains + + + + + +ltf_mutex_alloc + +Function pointer for allocating a mutex. This function is called by +the client when needed if the function pointer is not NULL. +The function must have the prototype specified by LDAP_TF_MUTEX_ALLOC_CALLBACK + . + + + +ltf_mutex_free + +Function pointer for freeing a mutex. This function is called by the +client when needed if the function pointer is not NULL. +The function must have the prototype specified by LDAP_TF_MUTEX_FREE_CALLBACK + . + + + +ltf_mutex_lock + +Function pointer for locking critical sections of code. This function +is called by the client when needed if the function pointer is not NULL. +The function must have the prototype specified by LDAP_TF_MUTEX_LOCK_CALLBACK + . + + + +ltf_mutex_unlock + +Function pointer for unlocking critical sections of code. This function +is called by the client when needed if the function pointer is not NULL. +The function must have the prototype specified by LDAP_TF_MUTEX_UNLOCK_CALLBACK + . + + + +ltf_get_errno + +Function pointer for getting the value of the errno variable. +This function is called by the client when needed if the function pointer +is not NULL. +In a threaded environment, errno is typically redefined +at compile time so that it has a value for each thread, rather than a global +value for the entire process. Because the libldap library +does not know what method your code and threading environment will use to +get the value of errno for each thread, it calls this function +to obtain the value. The function must have the prototype specified by LDAP_TF_GET_ERRNO_CALLBACK. + + + +ltf_set_errno + +Function pointer for setting the value of the errno variable. +This function is called by the client when needed if the function pointer +is not NULL. +In a threaded environment, errno is typically redefined +at compile time so that it has a value for each thread, rather than a global +value for the entire process. Because the libldap library +does not know what method your code and threading environment will use to +get the value of errno for each thread, it calls this function +to obtain the value. The function must have the prototype specified by LDAP_TF_SET_ERRNO_CALLBACK. + + + +ltf_get_lderrno + +Function pointer for getting error values from calls to functions in +the libldap library. This function is called by the client +as needed if the function pointer isn’t NULL. If +this function pointer is not set, the libldap library records +these errors in fields in the LDAP structure. +The function must have the prototype specified by LDAP_TF_GET_LDERRNO_CALLBACK + . + + + +ltf_set_lderrno + +Function pointer for setting error values from calls to functions in +the libldap library. This function is called by the client +as needed if the function pointer is not NULL. If this +function pointer is not set, the libldap library records +these errors in fields in the LDAP structure. +The function must have the prototype specified by LDAP_TF_SET_LDERRNO_CALLBACK + . + + + +ltf_lderrno_arg + +Additional parameter passed to the functions for getting and setting +error values from calls to functions in the libldap library. +(*ltf_get_lderrno) and (*ltf_set_lderrno) identify +these functions. + + + +
+
+
+<structname>LDAPURLDesc</structname> + +C SDK data types +LDAPURLDesc + +LDAPURLDesc + +LDAPURLDesc is a structure that represents the components +of an LDAP URL. +Description +LDAP URLs have the following syntax: +ldap://host:port/ +dn?attributes? +scope?( +filter) +Where, for example: +ldap://ldap.example.com/c=US?o,description?one?(o=Sales) +Calling the ldap_url_parse function +creates an LDAPURLDesc structure with the components of +the URL. +<structname>LDAPURLDesc</structname> Definition +typedef struct ldap_url_desc { + char *lud_host; + int lud_port; + char *lud_dn; + char **lud_attrs; + int lud_scope; + char *lud_filter; + unsigned long lud_options; +} LDAPURLDesc + +<structname>LDAPURLDesc</structname> Field +Descriptions + + + + +Field + +What It Contains + + + + + +lud_host + +Name of the host in the URL. + + + +lud_port + +Number of the port in the URL. + + + +lud_dn + +Distinguished name in the URL. This base entry DN +identifies the starting point of the search. + + + +lud_attrs + +Pointer to a NULL terminated list of the attributes +specified in the URL. + + + +lud_scope + +Integer representing the scope of the search specified in the URL: + +LDAP_SCOPE_BASE specifies a search of the +base entry. +LDAP_SCOPE_ONELEVEL specifies a search +of all entries one level under the base entry (not including the base entry). + +LDAP_SCOPE_SUBTREE specified a search of +all entries at all levels under the base entry (including the base entry). + + + + + + +lud_filter + +Search filter included in the URL. + + + +lud_options + +Options; if LDAP_URL_OPT_SECURE, indicates that the +protocol is ldaps:// instead of ldap://. + + + + +
+For example, suppose you pass the following URL to the ldap_url_parse function: +ldap://ldap.example.com:5000/dc=example,dc=com?cn,mail, \ + telephoneNumber?sub?(sn=Jensen) +The resulting LDAPURLDesc structure-ludpp, +in this example-will contain the values in Table 20–27. +<structname>LDAPURLDesc +</structname> Parsed URL Values + + + + +Component + +Value + + + + + +ludpp->lud_host + +ldap.example.com + + + +ludpp->lud_port + +5000 + + + +ludpp->lud_dn + +dc=example,dc=com + + + +ludpp->lud_attrs[0] + +cn + + + +ludpp->lud_attrs[1] + +mail + + + +ludpp->lud_attrs[2] + +telephoneNumber + + + +ludpp->lud_attrs[3] + +NULL + + + +ludpp->lud_scope + +LDAP_SCOPE_SUBTREE + + + +ludpp->lud_filter + +(sn=Jensen) + + + +
+To free the LDAPURLDesc structure, call the ldap_free_urldesc routine.
+
+<structname>LDAPuserstatus</structname> + +C SDK data types +LDAPuserstatus + +LDAPuserstatus + +An LDAPuserstatus structure holds the values +concerning the status of a user account. +You fill this structure by passing it to the ldap_parse_userstatus_control function. + +<structname>LDAPuserstatus</structname> Description +An LDAPuserstatus structure has the following +definition: +typedef struct LDAPuserstatus { /* user account availability */ + unsigned int us_available; /* availability status */ +#define LDAP_US_ACCOUNT_USABLE 0 +#define LDAP_US_ACCOUNT_NOT_USABLE 1 + int us_expire; /* will expire in seconds */ + int us_inactive; /* boolean inactivation status */ +#define LDAP_US_ACCOUNT_ACTIVE 0 +#define LDAP_US_ACCOUNT_INACTIVE 1 + int us_reset; /* boolean password reset */ +#define LDAP_US_ACCOUNT_NOT_RESET 0 +#define LDAP_US_ACCOUNT_RESET 1 + int us_expired; /* boolean password expired */ +#define LDAP_US_ACCOUNT_NOT_EXPIRED 0 +#define LDAP_US_ACCOUNT_EXPIRED 1 + int us_remaining; /* remaining logins */ + int us_seconds; /* will unlock in seconds */ +} LDAPuserstatus; +<structname>LDAPuserstatus</structname> Field +Descriptions + + + + +Field + +What It Contains + + + + + +us_available + +Whether the account is currently usable + + + +us_expire + +Number of seconds before the password expires +-1 means the password is not set to expire at all. + + + + +us_inactive + +Whether the account is locked + + + +us_reset + +Whether the password has been reset + + + +us_expired + +Whether the password has expired + + + +us_remaining + +Number of remaining grace logins + + + +us_seconds + +Number of seconds before the server unlocks the account + + + +
+
+Memory Concerns +You allocate and free space for the LDAPuserstatus structure. + +
+<structname>LDAP_VALCMP_CALLBACK</structname> + +C SDK data types +LDAP_VALCMP_CALLBACK + +LDAP_VALCMP_CALLBACK + +LDAP_VALCMP_CALLBACK specifies the prototype for +a callback function to sort a specified set of values. +Description +If you define a function with this prototype and specify it when calling +the ldap_sort_strcasecmp function, the function +will be called by your LDAP client. +<structname>LDAP_VALCMP_CALLBACK</structname> Prototype + +typedef int (LDAP_C LDAP_CALLBACK + LDAP_VALCMP_CALLBACK)(const char**, const char**); + +ldap_sort_values requires a function +pointer that matches the signature defined by this type. +ldap_sort_strcasecmp is a value comparison function defined using +this type which can therefore be passed to ldap_sort_values +. +See Also +ldap_sort_values, ldap_sort_strcasecmp + +<structname>LDAPVersion</structname> + +C SDK data types +LDAPVersion + +LDAPVersion + +The LDAPVersion structure contains version information +about &DirectorySDKForC;. +The LDAPVersion type is deprecated; it is documented +here only for backward compatibility. Instead, use the ldap_get_option + function with the LDAP_OPT_API_INFO option and +retrieve an LDAPAPIInfo structure. + +Description +Call the ldap_version function to return +a pointer to an LDAPVersion structure containing version +information. +<structname>LDAPVersion</structname> Definition +typedef struct _LDAPVersion { + int sdk_version; + int protocol_version; + int SSL_version; + int security_level; +} LDAPVersion; + +<structname>LDAPVersion</structname> Field +Definitions + + + + +Field + +What It Contains + + + + + +sdk_version + +Version number of &DirectorySDKForC; multiplied by 100. For example, +the value 600 in this field represents version 6.0. + + + +protocol_version + +Highest supported LDAP protocol version multiplied by 100. For example, +the value 300 in this field represents LDAP v3. + + + +SSL_version + +Supported SSL version multiplied by 100. For example, the value 300 +in this field represents SSL 3.0). + + + +security_level + +Level of encryption supported in bits. For example, 128 for US domestic +or 40 for export. +If SSL is not enabled, the value of this field is LDAP_SECURITY_NONE + . + + + +
+
+
+<structname>LDAPVirtualList</structname> + +C SDK data types +LDAPVirtualList + +LDAPVirtualList + +LDAPVirtualList specifies the information that can +be used to create a virtual list view control. +Description +A virtual list view control is a LDAP v3 control +designed to allow the client to retrieve subsets of search results to display +in a virtual list box. A virtual list box is +typically a graphical user interface that displays a long list of entries +with a few entries visible. To display the list, the client usually does not +retrieve the entire list of entries from the server. Instead, the client just +retrieves the subset of entries to be displayed. +After you create an LDAPVirtualList structure and +specify values for its fields, you can create the virtual list view control +by calling the function ldap_create_virtuallist_control. +You can pass this control and a server-side sorting control-created by calling +the ldap_create_sort_keylist function and +the ldap_create_sort_control function-to +the ldap_search_ext or +ldap_search_ext_s function. To get the virtual list view response +control sent back from the server, call the ldap_parse_result + function to get the list of controls returned by the server, then +call the ldap_parse_virtuallist_control +function to retrieve information from the control. End users can display different +sections of the list by scrolling up or down. +The object identifier (OID) for this control is OID 2.16.840.1.113730.3.4.9 + , or LDAP_CONTROL_VLVREQUEST as defined in +ldap.h. It is supported by &cnDirectoryServer;. +The virtual list view control provides the means for your client to +request and retrieve certain subsets of a long, sorted list of entries. The +control specifies the following information: + +The entry in the list that is currently selected. + +The number of entries to be displayed in the list before the +selected item. +The number of entries to be displayed in the list after the +selected entry.The currently selected entry can be identified +in one of the following ways: +By the index of the entry in the entire list in which case, +the control specifies both the offset of the entry and the total number of +entries in the list. +By the value of the entry in which case, the control specifies +that value.For example, a virtual list view control might specify +that you want to retrieve entries 15 through 24 in a list of 100 results with +entry 20 being the selected entry. The control uses the following information +to specify this: +The selected entry is the 20th entry from the top—in +other words, the index or offset of the entry is 20—of a list of 100. + +Get 5 entries before the selected entry in the list (entries +15 - 19). +Get 4 entries after the selected entry in the list (entries +21 - 24).As another example, a virtual list view control might +specify that you want to retrieve a subset of entries that start with the +letter c or a later letter in the alphabet. The control +might specify the following information: +The selected entry is the first entry that starts with the +letter c. The size of the list is not relevant in determining +the selected entry in this case. +Get 5 entries before the selected entry in the list. + +Get 4 entries after the selected entry in the list. + + +<structname>LDAPVirtualList</structname> Definition +typedef struct ldapvirtuallist { + unsigned long ldvlist_before_count; + unsigned long ldvlist_after_count; + char *ldvlist_attrvalue; + unsigned long ldvlist_index; + unsigned long ldvlist_size; + void *ldvlist_extradata; +} LDAPVirtualList; + +<structname>LDAPVirtualList</structname> Field +Descriptions + + + + +Field + +What It Contains + + + + + +ldvlist_before_count + +Number of entries before the selected entry that you want to retrieve. + + + + +ldvlist_after_count + +Number of entries after the selected entry that you want to retrieve. + + + + +ldvlist_attrvalue + +Specifies the value that you want to find in the list. The selected +entry in the list is the first entry that is greater than or equal to this +value. If this field is NULL, the ldvlist_index and +ldvlist_size fields are used to determine the selected entry instead. + + + + +ldvlist_index + +If the ldvlist_attrvalue field is NULL, +specifies the offset or index of the selected entry in the list. This field +is used in conjunction with the ldvlist_size field to identify +the selected entry. + + + +ldvlist_size + +If the ldvlist_attrvalue field is NULL, +specifies the total number items in the list. This field is used in conjunction +with the ldvlist_index field to identify the selected entry. + + + + +ldvlist_extradata + +Reserved for application-specific use. This data is not used in the +virtual list view control. + + + +
+
+
+<structname>LDAP_X_EXTIOF_CLOSE_CALLBACK</structname> +This specifies the prototype for an extended I/O callback function to +close a socket connection. +Description +<structname>LDAP_X_EXTIOF_CLOSE_CALLBACK</structname> Prototype + +typedef int (LDAP_C LDAP_CALLBACK LDAP_X_EXTIOF_CLOSE_CALLBACK )( + int s, void *arg ); + + +See Also +ldap_x_ext_io_fns + +<structname>LDAP_X_EXTIOF_CONNECT_CALLBACK</structname> +This specifies the prototype for an extended I/O callback function to +open a socket connection. +Description +LDAP_X_EXTIOF_CONNECT_CALLBACK takes a timeout parameter +whose value in milliseconds can be set by calling ldap_set_option + . +<structname>LDAP_X_EXTIOF_CONNECT_CALLBACK</structname> Prototype + +typedef int (LDAP_C LDAP_CALLBACK LDAP_X_EXTIOF_CONNECT_CALLBACK )( + int s, LDAP_X_SockAddr *saddr, int saddr_len, + int timeout /* milliseconds */, void *arg ); + + +See Also +ldap_x_ext_io_fns + +<structname>LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK</structname> +This specifies the prototype for an extended I/O callback function to +dispose of a session handle. +Description +LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK is called right +before the LDAP session handle and its contents are destroyed during ldap_unbind. The value of the arg parameter +passed to the callback is always the default one. +<structname>LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK</structname> Prototype + +typedef void (LDAP_C LDAP_CALLBACK LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK)( + LDAP *ld, void *arg ); + + +See Also +ldap_x_ext_io_fns + +<structname>LDAP_X_EXTIOF_NEWHANDLE_CALLBACK</structname> +This specifies the prototype for an extended I/O callback function to +define a new session handle. +Description +LDAP_X_EXTIOF_NEWHANDLE_CALLBACK is called right +after the LDAP session handle is created during ldap_init +. The value of the arg parameter passed to the +callback is always the default one. If the callback returns anything other +than LDAP_SUCCESS, the session handle allocation fails. +<structname>LDAP_X_EXTIOF_NEWHANDLE_CALLBACK</structname> Prototype + +typedef int (LDAP_C LDAP_CALLBACK LDAP_X_EXTIOF_NEWHANDLE_CALLBACK)( + LDAP *ld, void *arg ); + + +See Also +ldap_x_ext_io_fns + +<structname>ldap_x_ext_io_fns</structname> +This is a structure to hold extended I/O function pointers. +<structname>ldap_x_ext_io_fns</structname> Definition +struct ldap_x_ext_io_fns { + /* lextiof_size should always be set to LDAP_X_EXTIO_FNS_SIZE */ + int lextiof_size; + LDAP_X_EXTIOF_CONNECT_CALLBACK *lextiof_connect; + LDAP_X_EXTIOF_CLOSE_CALLBACK *lextiof_close; + LDAP_X_EXTIOF_READ_CALLBACK *lextiof_read; + LDAP_X_EXTIOF_WRITE_CALLBACK *lextiof_write; + LDAP_X_EXTIOF_POLL_CALLBACK *lextiof_poll; + LDAP_X_EXTIOF_NEWHANDLE_CALLBACK *lextiof_newhandle; + LDAP_X_EXTIOF_DISPOSEHANDLE_CALLBACK *lextiof_disposehandle; + void *lextiof_session_arg; + LDAP_X_EXTIOF_WRITEV_CALLBACK *lextiof_writev; +}; +#define LDAP_X_EXTIO_FNS_SIZE sizeof(struct ldap_x_ext_io_fns) + + +<structname>LDAP_X_EXTIOF_POLL_CALLBACK</structname> +This specifies the prototype for an extended I/O callback function to +close a socket connection. +Description +The LDAP_X_EXTIOF_POLL_CALLBACK interface is provided +instead of a standard select interface. The time out +is in milliseconds. The value of the arg parameter +passed to the callback is always the default one. +<structname>LDAP_X_EXTIOF_POLL_CALLBACK</structname> Prototype + +typedef int (LDAP_C LDAP_CALLBACK LDAP_X_EXTIOF_POLL_CALLBACK)( + LDAP_X_PollFD fds[], int nfds, int timeout /* milliseconds */, + void *arg ); + + +See Also +ldap_x_ext_io_fns, LDAP_X_PollFD + +<structname>ldap_x_hostlist_status</structname> +This structure contains utility functions for parsing space-separated +host lists. +Description +<structname>ldap_x_hostlist_status</structname> Definition + +struct ldap_x_hostlist_status; +LDAP_API(int) LDAP_CALL ldap_x_hostlist_first( const char *hostlist, + int defport, char **hostp, int *portp /* host byte order */, + struct ldap_x_hostlist_status **statusp ); +LDAP_API(int) LDAP_CALL ldap_x_hostlist_next( char **hostp, + int *portp /* host byte order */, + struct ldap_x_hostlist_status *status +); +LDAP_API(void) LDAP_CALL ldap_x_hostlist_statusfree( + struct ldap_x_hostlist_status *status ); + + + +<structname>LDAP_X_PollFD</structname> +This is a structure to hold the set of file descriptors +that will be surveyed for I/O by the LDAP_X_EXTIOF_POLL_CALLBACK +. +Description +<structname>LDAP_X_PollFD</structname> Structure +Definition +typedef struct ldap_x_pollfd { /* used by LDAP_X_EXTIOF_POLL_CALLBACK */ + int lpoll_fd; /* integer file descriptor / socket */ + void *lpoll_arg; /* pointer socket and for use by application */ + short lpoll_events; /* requested event */ + short lpoll_revents; /* returned event */ +} LDAP_X_PollFD; + + + +
+
diff --git a/mozilla/directory/docs/ldapcsdk/csdk-extendop.sgm b/mozilla/directory/docs/ldapcsdk/csdk-extendop.sgm new file mode 100644 index 00000000000..ce540227aee --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/csdk-extendop.sgm @@ -0,0 +1,389 @@ + +Extended Operations With &DirectorySDKForC; + +C SDK +extended operations + +This chapter explains LDAP v3 extended operations. It also explains +how to use the extended operations supported by your LDAP server. + +This chapter covers the following topics: +How Extended Operations Work With +Directory SDK for C +Determining the Extended Operations +Supported With Directory SDK for C +Performing an Extended Operation +With Directory SDK for C +Performing an LDAP Password +Modify Extended Operation With Directory SDK for C +Using Start TLS With +Directory SDK for C +Performing a Who Am I? +Extended Operation With Directory SDK for C + + +How Extended Operations Work With Directory SDK for +C +Extended operations are part of LDAP v3. Each extended operation is +identified by an object identifier (OID). LDAP clients can request the operation +by sending an extended operation request. + +Within the request, the client specifies the following: +The OID of the extended operation that should be performed + +Data specific to the extended operation + +The server receives the request, then performs the extended operation. +The server sends back a response to the client that contains an OID, and any +additional data. +To use extended operations, both the server and the client must understand +the specific extended operation to be performed. From the LDAP server perspective, &cnDirectoryServer; supports +a server plug-in interface that you can use to add support for extended operations. + +Determining the Extended Operations Supported With &DirectorySDKForC; +To determine the extended operations supported by the server, get the +root DSE of the server, and check the supportedExtension attribute. +The values of this attribute are the OIDs of the extended operations supported +by this server. If the root DSE does not have a supportedExtension attribute, +the server does not support any extended operations. See +To Get the Root DSE for instructions on reading that entry. + +Performing an Extended Operation With &DirectorySDKForC; + +To perform an extended operation, for which no specialized API exists, +call one of the following functions: +The synchronous ldap_extended_operation_s function + +The asynchronous ldap_extended_operation function + + +Both of these functions allow you to specify the OID of the extended +operation and the data that you want applied to the operation. +Before calling the function to perform an LDAP extended operation, make +sure to specify that your client is using version 3 of LDAP. If you do not, +an LDAP_NOT_SUPPORTED result code is returned. For +details, see Specifying the LDAP Version of Your +Client. +Synchronous Extended Operation +If you want to wait for the results of an LDAP extended operation to +complete before continuing, call the synchronous ldap_extended_operation_s + function. This function sends a SASL bind request to the server. +The server blocks other work until the server sends the results of the operation +back to your client. +ldap_extended_operation_s returns LDAP_SUCCESS + if the operation completed successfully, or an error code if +a problem occurred. See the documentation for the ldap_extended_operation_s + function for a list of the possible result codes. +Asynchronous Extended Operation +If you want to perform other work in parallel while waiting for an LDAP +extended operation to complete, perform the following procedure. +To Perform an Asynchronous Extended Operation + +Call the asynchronous ldap_extended_operation function +to send an LDAP extended operation request.This function returns +an LDAP_SUCCESS result code if the request was successfully +sent, or an LDAP result code if an error occurred while sending the request. +The function also sets the msgidp argument to point to +a message ID identifying the extended operation. To determine whether the +server sent a response to your client for this operation, call the ldap_result + function and pass in this message ID. The function passes back +the response in an LDAPMessage structure. +Call the ldap_parse_extended_result function +to parse the LDAPMessage structure and retrieve information +from the server’s response.If the server sent an OID of +an extended operation to your client, the OID is passed back as the retoidp + argument. If the server sent data to your client, the data is specified +in the berval structure passed back as the retdatap + argument. +Call the ldap_get_lderrno function to get +the LDAP result code for the operation.The function returns an +LDAP_SUCCESS result code if the extended operation was performed +successfully, or an LDAP error code if a problem occurred. See the documentation +for the ldap_extended_operation function +for a list of result codes that the server can return for this operation. + + + +Perform an Asynchronous Extended Operation +This example client requests an asynchronous extended operation from +the server with OID 1.2.3.4. +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include "ldap.h" + +/* Name and port of the LDAP server you want to connect to. */ +#define MY_HOST "localhost" +#define MY_PORT 389 +/* DN of user (and password of user) who you want to authenticate as */ +#define MGR_DN "cn=Directory Manager" +#define MGR_PW "23skidoo" +int +main( int argc, char **argv ) +{ + /* OID of the extended operation that you are requesting */ + const char *oidrequest = "1.2.3.4"; + char *oidresult; + struct berval valrequest; + struct berval *valresult; + LDAP *ld; + int rc, version; + /* Set up the value that you want to pass to the server */ + printf( "Setting up value to pass to server...\n" ); + valrequest.bv_val = "My Value"; + valrequest.bv_len = strlen( "My Value" ); + /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + printf( "Getting the handle to the LDAP connection...\n" ); + if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) { + perror( "ldap_init" ); + ldap_unbind( ld ); + return( 1 ); + } + /* Set the LDAP protocol version supported by the client + to 3. (By default, this is set to 2. Extended operations + are part of version 3 of the LDAP protocol.) */ + ldap_get_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); + printf( "Resetting version %d to 3.0...\n", version ); + version = LDAP_VERSION3; + ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); + /* Authenticate to the directory as the Directory Manager */ + printf( "Binding to the directory...\n" ); + if ( ldap_simple_bind_s( ld, MGR_DN, MGR_PW ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_simple_bind_s" ); + ldap_unbind( ld ); + return( 1 ); + } + /* Initiate the extended operation */ + printf( "Initiating the extended operation...\n" ); + if ( ( rc = ldap_extended_operation_s( ld, oidrequest, &valrequest, + NULL, NULL, &oidresult, &valresult ) ) != + LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_extended_operation failed: " ); + ldap_unbind( ld ); + return( 1 ); + } + /* Get the OID and the value from the result returned by the server. */ + printf( "Operation successful.\n" ); + printf( "\tReturned OID: %s\n", oidresult ); + printf( "\tReturned value: %s\n", valresult->bv_val ); + /* Disconnect from the server. */ + ldap_unbind( ld ); + return 0; +} + + + + +Performing an LDAP Password Modify Extended +Operation With &DirectorySDKForC; + +C SDK +extended operations +password modify + +RFC +3062, LDAP Password Modify Extended Operation, +describes the extended operation, which is particularly useful for changing +expired passwords. +To Perform an LDAP Password Modify Extended Operation + +Get a connection to the directory that uses LDAP version 3. + +Authenticate to the directory. + +As an administrator, to be able to reset an expired user password +if you do not have the old password +Anonymously to reset an expired password if you have the old password + +As the user herself to change the password that has not yet expired + + +Modify the password with the synchronous function ldap_passwd_s + or the asynchronous function ldap_passwd and +use ldap_parse_passwd or ldap_parse_passwd_result to +examine the results. + + +Performing an LDAP Password Modify Extended Operation +This example changes a password using ldap_passwd_s. +/* + * Use the password modify extended operation to change a password. + */ + +#include "examples.h" + +int +main( int argc, char **argv ) +{ + int version; + LDAP *ld; + char *target; + int rc; + struct berval userid; + struct berval oldpasswd; + struct berval newpasswd; + struct berval genpasswd; + + /* Use LDAPv3. */ + version = LDAP_VERSION3; + if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, &version ) + != 0 ) { + fprintf( stderr, + "ldap_set_option protocol version to %d failed\n", + version ); + return ( 1 ); + } + + /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } + + /* Authenticate to the directory. */ + if ( ldap_simple_bind_s( ld, ENTRYDN, ENTRYPW ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_simple_bind_s" ); + return( 1 ); + } + + /* Change the password using the extended operation. */ + userid.bv_val = ENTRYDN; + userid.bv_len = strlen(userid.bv_val); + + oldpasswd.bv_val = ENTRYPW; + oldpasswd.bv_len = strlen(oldpasswd.bv_val); + + newpasswd.bv_val = "ChangeMe!"; + newpasswd.bv_len = strlen(newpasswd.bv_val); + + rc = ldap_passwd_s( + ld, &userid, &oldpasswd, &newpasswd, &genpasswd, NULL, NULL ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_passwd_s: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + } else { + printf( "Successfully changed password for %s\n", userid.bv_val ); + } + + ldap_unbind( ld ); + return( 0 ); +When you compile and run this sample program against &cnDirectoryServer; with +a suffix that contains data from Example.ldif, the server +produces output similar to this: +Successfully changed password for uid=bjensen, ou=People, dc=example,dc=com + + + + +Using Start TLS With &DirectorySDKForC; + +C SDK +extended operations +start TLS + +RFC +4513, Lightweight Directory Access Protocol (LDAP): Authentication +Methods and Security Mechanisms, describes the extended operation. +Start TLS allows you to connect on a non secure port, and then request transport +layer security. +See Starting Transport Layer Security +With Directory SDK for C for an example of how to use Start TLS. + +Performing a Who Am I? Extended Operation +With &DirectorySDKForC; + +C SDK +extended operations +Who Am I? + +The “Who am I?” extended operation allows you to retrieve +the authorization identity that is associated with a connection. +This method can involve less code than the standard authorization identity +controls that are described in Using the +Authorization Identity Bind Request Control With Directory SDK for C. +To Perform a Who Am I? Extended Operation + +Get a connection to the directory that uses LDAP version 3. + +Use ldap_whoami and ldap_parse_whoami_result +, or use ldap_whoami_s, to retrieve the authorization +identity. + + +Getting Authorization Identity +This example retrieves authorization identity by using ldap_whoami_s +. +/* + * Use the Who Am I? extended operation. + */ + +#include "examples.h" + +int +main( int argc, char **argv ) +{ + int version; + LDAP *ld; + int rc; + char *authzid; + + /* Use LDAPv3. */ + version = LDAP_VERSION3; + if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, &version ) + != 0 ) { + fprintf( stderr, + "ldap_set_option protocol version to %d failed\n", + version ); + return ( 1 ); + } + + /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } + + /* Authenticate to the directory. */ + if ( ldap_simple_bind_s( ld, ENTRYDN, ENTRYPW ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_simple_bind_s" ); + return( 1 ); + } + + /* Examine my authorization ID. */ + rc = ldap_whoami_s( ld, NULL, NULL, &authzid ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_whoami_s: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + printf( "Authorization ID: %s\n", authzid ); + + ldap_unbind( ld ); + return( 0 ); +} +When you compile and run this sample program against &cnDirectoryServer; with a suffix that contains data from Example.ldif, +the server produces output similar to this: +Authorization ID: dn:uid=bjensen,ou=people,dc=example,dc=com + + + + diff --git a/mozilla/directory/docs/ldapcsdk/csdk-filter-conf.sgm b/mozilla/directory/docs/ldapcsdk/csdk-filter-conf.sgm new file mode 100644 index 00000000000..a2d20ff8b79 --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/csdk-filter-conf.sgm @@ -0,0 +1,375 @@ + +Using Filter Configuration Files With &DirectorySDKForC; + +C SDK +filter configuration files + +This chapter explains how to use LDAP C API functions to work with filter +configuration files. + +This chapter covers the following topics: +Understanding Filter Configuration Files for Directory SDK for C +Loading Filter Configuration Files With Directory SDK for C + +Filter Prefixes and Suffixes for Directory SDK for C + +Freeing Filters From Memory With Directory SDK for C + +Creating Filters Programmatically With Directory SDK for C + + + +Understanding Filter Configuration Files for Directory +SDK for C +Filter configuration files can help simplify the process of selecting +the appropriate filter for a search request. A filter configuration +file contains a list of filters that you can load and use in your +searches. You might be writing a client that allows users to search the directory. +Use different search filters tailored for specific types of search criteria. +For example, if the user wants to search for the email address bjensen@example.com +, you might want to use this search filter: +(mail=bjensen@example.com) +Similarly, suppose the search term entered by the user contains numbers, +as in 555-1212. In this case, you might want to use this +search filter: +(telephoneNumber=555-1212) +Rather than write code to find and select the appropriate filter, you +can include the filters in a filter configuration file. For example, the following +section of a filter configuration file specifies one filter for telephone +numbers and two filters for email addresses. The telephone number filter is +used if the search criteria contain one or more numbers. The email filters +are used if the search criteria contain an at sign, @. +Section of Filter Configuration File +"people" + "^[0-9][0-9-]*$" " " + "(telephoneNumber=*%v))" "phone number ends with" + "@" " " "(mail=%v)" "email address is" + "(mail=%v*)" "email address starts with" + +You should specify the filters in the order that you want the filters +to be used. For example, if you want to apply the (mail=%v) filter +before the (mail=%v*) filter, make sure that the filters +appear in that order. +Syntax for Filter Configuration Files + +filter configuration files +syntax + +A filter configuration file has the following format. The variables +are discussed in the following sections. +Syntax for a Filter Configuration +File +tag + pattern1 delimiters +filter1-1 desc1-1 [scope] + filter1-2 desc1-2 [ +scope] + pattern2 delimiters +filter2-1 desc2-1 [scope] +… + +Tag for Filter Groups +A tag identifies a group of filters. You +can use different tags to distinguish filters for different types of objects. +For example, you can use one tag to represent filters for person entries, +another tag to represent filters for organization entries, and so on. +"people" + … (filters for searching "person" entries) … +"organization" + … (filters for "organization" entries) … + +When you call functions like ldap_getfirstfilter to +retrieve a filter, you can specify a tag, or part of a tag, as a parameter. +The tag narrows the list of filters that the function can retrieve. + +Patterns to Select Filters +pattern1 and pattern2 are +regular expressions used to determine which filter is selected, based on the +search criteria. For example, if you specify "^[0-9]" as +the pattern for a filter, the filter is selected for all search criteria that +begin with a number. +"people" + "^[0-9]" … + +Delimiters for Fields +Delimiters specifies the delimiters used +to distinguish one field from another field within the search criteria. For +example, if the search criteria consist of a city name and a state abbreviation +separated by a comma, specify a comma as the delimiter. +Filter Lists +filter1-1, filter1-2, +and filter2-1 are filters. Use %v to +represent the search criteria. For example, to search email addresses, use +the filter (mail=%v). During runtime, if the search criteria +bjensen@example.com is entered, the filter becomes (mail=bjensen@example.com) +. +The search criteria might consist of a number of delimited fields. For +example, the criteria might have a last name, first name format such as +Jensen, Barbara. Use %v1, %v2, …, %vn to +represent the different fields within the search criteria as shown here: +"people" + "^[A-Z]*," "," (&(sn=%v1)(givenName=%v2)) +In this example, the delimiter is a comma. The word before the delimiter +replaces %v1 in the filter. The word after the delimiter +replaces %v2 in the filter. If the user searches for +Jensen, Barbara , the resulting filter is as follows: +(&(sn=Jensen)(givenName=Barbara)) +You can also specify ranges of fields. For example, to specify the values +in the first three fields, use %v1-3. To specify values +from the third field to the last field, use %v3-. To specify +the value in the last field, use %v$. +Descriptions of Filters +desc1-1, desc1-2, +and desc2-1 are phrases that briefly describe the +filters. + +Filter Parameters + +search filters +parameters + +Filter specifications in the configuration file support the following +parameters: + +%v +Insert the search criterion as is in place of %v. + +For example, if the filter specification is (mail=%v), +entering bjensen results in the filter (mail=bjensen) +. + + +%v$ +Insert the last word of the search criterion as is in place +of %v. +For example, if the filter specification is (sn=%v$), +entering Barbara Jensen results in the filter (sn=Jensen) +. + + +%vN +Insert the Nth word of the criteria +in place of %v, where N is a +single digit between 1 and 9. +For example, if the filter specification is (sn=%v2), +entering Barbara Jensen results in the filter (sn=Jensen) +. + + +%vM- +N +Insert the sequence of the Mth +through Nth words of the criteria in place of +%v. Here, M and N are +single digits between 1 and 9. +For example, if the filter specification is (cn=%v1-2), +entering Barbara Jensen results in the filter (cn=Barbara +Jensen). + + +%vN- +Insert the sequence of the Nth +through last words of the criteria in place of %v. Here, +N is a single digit between 1 and 9. +For example, if the filter specification is (cn=%v2-), +entering Ms. Barbara Jensen results in the filter (cn=Barbara +Jensen). + + + + + +Loading Filter Configuration Files With Directory +SDK for C + +filter configuration files +loading + +loading filter configuration files + +To load a filter configuration file, call the ldap_init_getfilter + function. You can also read the filter configuration file from +a buffer in memory by calling the ldap_init_getfilter_buf function. +Both functions return a pointer to an LDAPFiltDesc structure, +which contains information about the filter. If an error occurs, both functions +return NULL. +Retrieving Filters + +filter configuration file +retrieving + +After loading a filter configuration file into memory, you can retrieve +filters based on the search criteria. For example, the search criteria might +be an email address, (bjensen@example.com). Have your client +automatically search for this value in the mail attribute +of person entries. +To retrieve the first filter that matches the search criteria, call +the ldap_getfirstfilter function. To get the next filter +that matches the search criteria, call the ldap_getnextfilter function. +Both functions return a pointer to an LDAPFiltInfo structure, +which contains information about the filter, as shown here. +Retrieving Configuration +Filters +#include <stdio.h> +#include "ldap.h" +… +LDAP *ld; +LDAPMessage *result, *e; +BerElement *ber; +char *a, *dn; +char **vals; +int i; +LDAPFiltDesc *ldfp; +LDAPFiltInfo *ldfi; +char buf[ 80 ]; /* contains the search criteria */ +int found; +… +/* Load the filter configuration file into an LDAPFiltDesc structure. */ +if ( ( ldfp = ldap_init_getfilter( "myfilters.conf" ) ) == NULL ) { + perror( "Cannot open filter configuration file" ); +} + +/* Select a filter to use when searching for the value in buf. +Use filters under the "people" tag in the filter configuration file. */ +found = 0; +for ( ldfi = ldap_getfirstfilter( ldfp, "people", buf ); ldfi != NULL; + ldfi = ldap_getnextfilter( ldfp ) ) { + + /* Use the selected filter to search the directory. */ + if ( ldap_search_s( ld, "dc=example,dc=com", ldfi->lfi_scope, + ldfi->lfi_filter, NULL, 0, &result ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search_s" ); + return( 1 ); + } else { + + /* Once a filter gets results back, stop iterating through + the different filters. */ + if ( ( found = ldap_count_entries( ld, result ) > 0 ) ) { + break; + } else { + ldap_msgfree( result ); + } + } +} + +if ( found == 0 ) { + printf( "No matching entries found.\n" ); +} else { + printf( "Found %d match%s where %s \"%s\"\n\n", found, + found == 1 ? "" : "es", ldfi->lfi_desc, buf ); +} + +ldap_msgfree( result ); +ldap_getfilter_free( ldfp ); +… + +Suppose that the search criteria is bjensen@example.com and +that the client application finds a single matching entry. Then the application +prints the following output: +Found 1 match where email address is bjensen@example.com + + +Filter Prefixes and Suffixes for Directory SDK for +C + +search filters +prefixes + +search filters +suffixes + +If you need to apply a filter to all searches, add a filter prefix and +suffix to all filters. Do not add the criteria to all filters. The prefix +is automatically added to any filter retrieved through the ldap_getfirstfilter + and ldap_getnextfilter functions. The required +suffix ) needed to balance the number of parentheses is +also added. For example, suppose you use this filter in a filter configuration +file: +(cn=Babs Jensen) +You can retrieve this filter by using ldap_getfirstfilter or +ldap_getnextfilter. These functions get a filter that constrains +your client searches to person entries for the defined filter: +(&(objectClass=person)(cn=Babs Jensen)) +To add a prefix and suffix automatically to all filters retrieved from +the filter configuration file, call the ldap_set_filter_additions function. +The following example adds the prefix (&(objectClass=person) and +the suffix ) to each filter retrieved. +Adding Prefixes and Suffixes +to Filters +#include "ldap.h" +… +LDAPFiltDesc *lfdp; +char *filter_file = "myfilters.conf"; +char *prefix = "(&(objectClass=person)"; +char *suffix = ")"; +… +lfdp = ldap_init_getfilter( filter_file ); +ldap_setfilteraffixes( lfdp, prefix, suffix ); +… + + +Freeing Filters From Memory With Directory SDK for +C + +search filters +freeing from memory + +memory +freeing search filters from + +When you complete your search, free the LDAPFiltDesc structure +from memory. To free LDAPFiltDesc, call the ldap_getfilter_free + function as shown here. +Freeing Filters From Memory +#include "ldap.h" +… +LDAPFiltDesc *lfdp; +char *filter_file = "myfilters.conf"; +… +/* Read the filter configuration file into an LDAPFiltDesc structure. */ +lfdp = ldap_init_getfilter( filter_file ); +… +/* Retrieve filters and perform searches. */ +… +/* Free the configuration file (the LDAPFiltDesc structure). */ +ldap_getfilter_free( lfdp ); +… + + +Creating Filters Programmatically With Directory +SDK for C + +search filters +creating programmatically + +You can build your own filters by calling the ldap_create_filter function. +The following example builds the filter (mail=bjensen@example.com). + +Creating Filters +char buf[LDAP_FILT_MAXSIZ]; +char *pattern = "(%a=%v); +char *attr = "mail"; +char *value = "bjensen@example.com"; +… +ldap_create_filter( buf, LDAP_FILT_MAXSIZ, pattern, NULL, NULL, attr, + value, NULL ); +… + + + diff --git a/mozilla/directory/docs/ldapcsdk/csdk-functions.sgm b/mozilla/directory/docs/ldapcsdk/csdk-functions.sgm new file mode 100644 index 00000000000..27f90604018 --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/csdk-functions.sgm @@ -0,0 +1,20727 @@ + +&DirectorySDKForC; Function Reference + +functions +C SDK functions +C SDK functions + +This chapter contains detailed reference material for each public function +of &DirectorySDKForC;. Each reference gives a description of the function, +and its usage syntax, parameters and return values. In many cases, an example +program is also included. The chapter contains the following sections: + +Typographic Conventions + +Function Summary by Task + +Functions Alphabetically + + + +Typographic Conventions +The general purpose of a function is usually given by its name. Table 21–1 lists the +naming conventions used when adding suffixes to function names. +Function Naming +Conventions + + + + +Suffix + +Description + + + + + +_ext + +Identifies extended functions introduced for LDAP v3. These functions +are augmented through additional parameters, as compared to the functions +they replace. As LDAP v3 has become widely adopted, it is recommended you +use extended functions whenever possible in your new applications. + + + + +_s + +Identifies the synchronous form of functions. A synchronous function +will not return until it receives a response from the server, thereby blocking +the caller. Similar function names without this suffix are asynchronous, allowing +the caller to perform other operations while waiting for a result. +The synchronous and asynchronous forms exist only for functions which +involve possible delays due to communication with the LDAP server. Functions +which do not involve communication do not use this suffix. + + + +
+
+Function Summary by Task + +C SDK +functions +summary of + +functions +C SDK + +In the following sections the functions of &DirectorySDKForC; are +grouped into task categories. +Working with Basic Encoding Rules + +C SDK +functions +for BER + +The functions listed in Table +21–2 may be used to encode and decode with Basic Encoding Rules +(BER). They are often used inside of control and extension values. +Functions to Encode +and Decode BER + + + + +Function + +Description + + + + + +ber_alloc, ber_alloc_t +, ber_sockbuf_alloc, ber_special_alloc + +Allocate new BER elements. + + + +ber_bvecfree, ber_bvfree +, ber_free, ber_sockbuf_free +, ber_sockbuf_free_data + +Free allocated memory. + + + +ber_bvdup, ber_dup + + +Duplicate BER structures. + + + +ber_init, ber_init_w_nullchar + + +Construct new structures. + + + +ber_get_boolean, +ber_get_int, ber_get_next, ber_get_next_buffer, ber_get_next_buffer_ext +, ber_get_null, +ber_get_option, ber_get_stringa, ber_get_stringal, ber_get_stringb + + +Retrieve miscellaneous information. + + + +ber_put_bitstring, ber_put_boolean, ber_put_enum, ber_put_int, ber_put_null, ber_put_ostring, ber_put_seq, ber_put_set, ber_put_string + + +Write miscellaneous information. + + + +ber_first_element, ber_next_element, ber_peek_tag +, ber_skip_tag + +Target specific elements and tags. + + + +ber_set_option, ber_set_string_translators + + +Set session parameters. + + + +ber_flatten, ber_printf +, ber_read, ber_reset +, ber_scanf, ber_sockbuf_get_option +, ber_sockbuf_set_option, ber_start_seq, ber_start_seq, ber_start_set, ber_svecfree, ber_write + +Miscellaneous functions. + + + +
+
+Managing LDAP Sessions + +C SDK +functions +for LDAP sessions + +The functions listed in Table +21–3 manage the different phases of an LDAP session: initialization, +configuration, authentication (binding) and termination (unbinding). +Functions to Manage +an LDAP Session + + + + +Function + +Description + + + + + +ldap_init, prldap_init + (IPv6) + +Initializes an LDAP session. + + + +ldapssl_init + +Initializes an LDAP session over SSL. + + + +ldapssl_pkcs_init + +Initializes a thread-safe session over SSL. + + + +ldap_get_option, +ldap_set_option + +Read and writes the current preference settings for a session. + + + + +ldap_memcache_init, ldap_memcache_set, ldap_memcache_get +, ldap_memcache_update, ldap_memcache_flush, ldap_memcache_destroy + + +Creates a memory cache and uses it for search results from this session. +Manages the data in the cache and frees the memory when the cache is no longer +needed. The in-memory cache for search results is an extension to the API. + + + + +ldap_unbind_ext + +Ends an LDAP session and frees the associated data structures. + + + + +
+
+Performing LDAP Operations + +C SDK +functions +for LDAP operations + +The functions listed in Table 21–4 + perform LDAP operations on a server and retrieve the results. +Functions to Perform Operations +on LDAP Server + + + + +Function + +Description + + + + + +ldap_add_ext or ldap_add_ext_s + + +Adds a new entry to the directory. + + + +ldap_modify_ext or ldap_modify_ext_s + +Modifies an entry in the directory + + + +ldap_delete_ext or ldap_delete_ext_s + +Deletes an entry from the directory. + + + +ldap_rename orldap_rename_s + + +Renames or moves one or more entries. + + + +ldap_search_ext or ldap_search_ext_s + +Searches the directory. + + + +ldap_compare_ext or ldap_compare_ext_s + +Compares a value with the values of an entry's attribute. + + + +ldap_result + +Checks the results of an asynchronous operation. + + + +ldap_abandon_ext + +Cancels an asynchronous operation. + + + +ldap_extended_operation or ldap_extended_operation_s + +Performs an LDAP v3 extended operation. + + + +ldap_parse_extended_result + +Parses the results of an LDAP v3 extended operation. + + + +ldap_msgfree + +Frees the memory used by the data structure for the results. + + + + +ldap_simple_bind or ldap_simple_bind_s + +Authenticates to an LDAP server using a password. + + + +ldap_sasl_bind and ldap_parse_sasl_bind_result or +ldap_sasl_bind_s + +Authenticates to an LDAP server using a SASL mechanism. + + + +ldap_set_rebind_proc + +Specifies the function used to get authentication information when following +referrals. + + + +
+
+Processing Search Results + +C SDK +functions +for search results processing + +Search results are given as a chain of LDAPMessage + structures which can contain both entry messages and search reference +messages. The functions listed in Table +21–5 retrieve the results of a search operation and process +the data structures which are returned. +Functions to Process Search +Results + + + + +Function + +Description + + + + + +ldap_first_message + +Gets the first message (an entry or search reference) in a chain of +search results. + + + +ldap_next_message + +Gets the next message (an entry or search reference) in a chain of search +results. + + + +ldap_count_messages + +Counts the number of messages (entries and search references) in a chain +of search results. + + + +ldap_msgid + +Gets the ID number of a message structure containing part of a result. + + + + +ldap_msgtype + +Determines whether a message structure contains an entry or a search +reference. + + + +ldap_msgfree + +Frees the memory allocated for search results or other LDAP operation +results. + + + +ldap_first_entry + +Gets the first entry in a chain of search results. + + + +ldap_next_entry + +Gets the next entry in a chain of search results. + + + +ldap_count_entries + +Counts the number of entries in a chain of search results. + + + +ldap_first_reference + +Gets the first search reference in a chain of search results. + + + + +ldap_next_reference + +Gets the next search reference in a chain of search results. + + + + +ldap_count_references + +Counts the number of search references in a chain of search results. + + + + +ldap_parse_reference + +Extracts the referral strings from a search reference. + + + +
+
+Reading the Contents of an Entry + +C SDK +functions +for reading entry contents + +The functions listed in Table 21–6 + are used to access the contents of an entry returned as a search +result. +Functions to Access Contents +of an Entry + + + + +Function + +Description + + + + + +ldap_get_dn + +Get the DN for an entry. + + + +ldap_explode_dn ldap_explode_rdn + + +Split a DN or relative DN into its components. + + + +ldap_explode_dns + +Takes a DNS-style DN and breaks it up into its components. + + + +ldap_is_dns_dn + +Determines the style of the DN. + + + +ldap_dn2ufn + +Removes cryptic type names to make a DN easier to read. + + + +ldap_first_attribute + +Get the name of the first attribute in an entry. + + + +ldap_next_attribute + +Get the name of the next attribute in an entry. + + + +ldap_get_values + +Get the string values of an attribute. + + + +ldap_get_values_len + +Get the binary values of an attribute. + + + +ldap_count_values + +Count the string values of an attribute. + + + +ldap_count_values_len + +Count the binary values of an attribute. + + + +ldap_value_free + +Free the memory allocated for the string values of an attribute. + + + + +ldap_value_free_len + +Free the memory allocated for the binary values of an attribute. + + + + +
+
+Sorting Search Results + +C SDK +functions +for sorting search results + +With the functions listed in Table +21–7, your LDAP client can sort the data structures returned +as search results. +Client-side Sorting +Functions + + + + +Function + +Description + + + + + +ldap_sort_entries + +Sorts search results by DN or by a single attribute. + + + +ldap_multisort_entries + +Sorts search results by multiple attributes + + + +ldap_keysort_entries + +Sorts search results using key(s). + + + +ldap_sort_values + +Sorts the values of an attribute. + + + +ldap_sort_strcasecmp + +A case-insensitive comparison function that you can pass to ldap_sort_values. + + + +
+&cnDirectoryServer; and others also provide server-side sorting through +LDAP v3 controls. +Server-Side Sorting +Functions + + + + +Function + +Description + + + + + +ldap_create_sort_keylist + +Define the criteria for sorting entries by attribute values. + + + + +ldap_free_sort_keylist + +Free the memory for the sort criteria data structure. + + + +ldap_create_sort_control + +Create the sort control structure needed for server-side sorting. + + + + +ldap_control_free + +Free the memory for the sort control data structure. + + + +ldap_parse_sort_control + +Analyze the server’s response to the sort control. + + + +ldap_controls_free + +Free the memory for the sort control response data structure. + + + + +
+
+Working with Search Filters + +C SDK +functions +for search filters + +The functions listed in Table 21–9 + retrieve and build filters using a filter configuration file. Use +this mechanism to create complex filters to pass to the search functions. +Functions to Initialize, +Retrieve, and Build Filters + + + + +Function + +Description + + + + + +ldap_init_getfilter + +Read a filter configuration file into memory. + + + +ldap_init_getfilter_buf + +Read a filter configuration string from a buffer. + + + +ldap_getfilter_free + +Free the filter configuration data structure from memory. + + + +ldap_set_filter_additions + +Specify the prefix and suffix to be added to all filters retrieved from +the filter configuration. + + + +ldap_getfirstfilter + +Retrieve the first matching filter from the filter configuration. + + + + +ldap_getnextfilter + +Retrieve the next matching filter from the filter configuration. + + + + +ldap_create_filter + +Build a filter without using the filter configuration file mechanism. + + + + +
+
+Using LDAP v3 Controls + +C SDK +functions +for LDAP v3 controls + +&cnDirectoryServer; and others also provide additional functionality +through LDAP v3 controls. The functions listed in Table 21–10 configure LDAP v3 +control structures which ask the server to perform advanced operations. +Functions to Manage LDAP +v3 Controls + + + + +Function + +Description + + + + + +ldap_create_authzid_control, ldap_parse_authzid_control + + +Examine the authorization ID used for the operation. + + + +ldap_create_persistentsearch_control, ldap_get_entry_controls, ldap_parse_entrychange_control + + +Track changes to an entry or a set of entries by setting the persistent +search control and analyzing the entry change control sent by the server. + + + + +ldap_create_proxiedauth_control + + +Define a proxy authorization control to perform an operation under a +different bind DN + + + +ldap_create_pwdpolicy_control +, ldap_parse_pwdpolicy_control + + +Examine password policy information for an entry. + + + +ldap_create_sort_keylist, ldap_free_sort_keylist, ldap_create_sort_control +, ldap_parse_sort_control + + +Define and send criteria for server-side sorting of search results and +check the server’s response + + + +ldap_create_userstatus_control +, ldap_parse_userstatus_control + + +Examine account availability information for an entry. + + + +ldap_create_virtuallist_control, ldap_parse_virtuallist_control + +Use in conjunction with server-side sorting to limit and handle the +number of results returned to the client. + + + +ldap_parse_result + +Parse an LDAP response from the server to extract the result and the +response to the control. + + + +
+
+Using Extensions + +C SDK +functions +for parsing host lists + +The functions listed in Table +21–11 are utility functions for parsing space-separated host +lists. This is useful for implementing an extended I/O CONNECT callback function. + +Extensions Provided + + + + +Function + +Description + + + + + +ldap_x_hostlist_first, ldap_x_hostlist_next, ldap_x_hostlist_status + + +Utility functions for parsing space-separated host lists. + + + +
+
+Working with LDAP URLs + +C SDK +functions +for LDAP URLs + +The functions listed in Table 21–12 + interpret LDAP URLs, universal resource locators of the form ldap://... +. +Functions to Interpret +LDAP URLs + + + + +Function + +Description + + + + + +ldap_is_ldap_url + +Determine if a URL is an LDAP URL. + + + +ldap_url_parse + +Split up an LDAP URL into its components. + + + +ldap_url_search, +ldap_url_search_s, ldap_url_search_st + + +Perform the search specified by an LDAP URL. + + + +ldap_free_urldesc + +Free the memory allocated for a parsed URL. + + + +
+
+Working with UTF-8 Encoding + +C SDK +functions +for UTF-8 encoding + +The functions listed in Table 21–13 + work with strings and characters that use UTF-8 encoding. +Functions to Handle UTF-8 +Encoding + + + + +Function + +Description + + + + + +ldap_utf8len + +Function to determine byte length. + + + +ldap_utf8next + +Function to get next character. + + + +ldap_utf8prev + +Function to get previous character. + + + +ldap_utf8copy + +Function to copy a character to a destination. + + + +ldap_utf8characters + +Function to return the number of characters. + + + +ldap_utf8getcc + +Function moves the pointer to the next character following a UCS-4 character. + + + + +ldap_utf8strtok_r + +Function moves the pointer to the next character following a UCS-4 character. + + + + +ldap_utf8isalnum, +ldap_utf8isalpha, ldap_utf8isdigit, ldap_utf8len, ldap_utf8isspace + + +Functions to determine characteristics of the character. + + + +
+
+Handling Errors + +C SDK +functions +for error handling + +The functions listed in Table 21–14 + handle errors returned by the functions. Chapter 22, +Directory SDK for C Result Codes lists all of the error and status +codes used in the &DirectorySDKForC;. You can also find details about possible +errors in the reference section for each function. +Functions for Error Handling + + + + +Function + +Description + + + + + +ldap_parse_result + +Get the error code resulting from an asynchronous LDAP operation. + + + + +ldap_get_lderrno + +Get information about the last error that occurred. + + + +ldap_set_lderrno + +Set information about an error. + + + +ldap_err2string + +Get the error message for a specific error code. + + + +ldapssl_err2string + +Get the error message for a specific SSL error code. + + + +
+
+Managing Memory + +C SDK +functions +for memory management + +The functions listed in Table 21–15 + free memory allocated by the &DirectorySDKForC; functions. +Functions to Free Memory + + + + +Function + +Description + + + + + +ber_bvfree + +Free the memory allocated for a berval structure. + + + + +ber_free + +Free the memory of a BerElement structure. + + + + +ldap_control_free + +Free the memory of an LDAPControl structure. + + + + +ldap_controls_free + +Free an array of LDAPControl structures. + + + + +ldap_free_friendlymap + +Free the memory of a FriendlyMap structure + + + + +ldap_free_sort_keylist + +Free an array of LDAPsortkey structures + + + + +ldap_free_urldesc + +Free the memory of an LDAPURLDesc structure + + + + +ldap_getfilter_free + +Free the memory of an LDAPFiltDesc structure. + + + + +ldap_memfree + +General function for freeing memory of any other data structure + + + + +ldap_mods_free + +Free an array of LDAPMod structure. + + + + +ldap_msgfree + +Free the memory of an LDAPMessage structure. + + + + +ldap_value_free + +Free the memory allocated for the string values of an attribute. + + + + +ldap_value_free_len + +Free the memory allocated for the binary values of an attribute (an +array of berval structures) + + + +
+You may also manage memory directly with the functions in Table 21–16. +Functions to Directly +Manage Memory + + + + +Function + +Description + + + + + +ldap_x_malloc + +Allocates memory. + + + +ldap_x_calloc + +Allocates memory for an array of elements. + + + +ldap_x_realloc + +Changes the size of a memory block. + + + +ldap_x_free + +Frees a block of memory. + + + +
+
+Working with <acronym>NSPR</acronym> + +C SDK +functions +for NSPR + +The functions listed in Table 21–17 + tie libldap into Netscape Portable Runtime, +NSPR. +Functions to Work with <acronym> +NSPR</acronym> + + + + +Function + +Description + + + + + +prldap_get_default_socket_info + + +Gets default socket information. + + + +prldap_get_session_info + +Gets application-specific data. + + + +prldap_get_session_option + +Gets a session option specific to the prldap layer. + + + + +prldap_get_socket_info + +Gets socket information. + + + +prldap_init + +Creates a new NSPR session handle. + + + +prldap_install_routines + +Installs NSPR functions for use with LDAP handle. + + + + +prldap_set_default_socket_info + + +Sets default socket information. + + + +prldap_set_session_info + +Sets application-specific data. + + + +prldap_set_session_option + +Sets a session option specific to the prldap layer. + + + + +prldap_set_socket_info + +Sets socket information. + + + +
+
+Deprecated and Outdated Functions + +C SDK +functions +deprecated + +The functions listed in first column of Table 21–18 should no longer +be used; they have been superseded by the newer functions listed in the second +column. Deprecated functions are those being dropped from the standard or +from extensions to &DirectorySDKForC;. Outdated functions are those which +are not officially deprecated but which have newer, extended functions for +performing the same operation. +Deprecated functions are not guaranteed to be implemented in future +versions of the API. However, all of these functions are still implemented +in this version for backwards compatibility. For maintenance reasons, they +have often been implemented to call the newer function which performs the +same task. +Deprecated Functions +and Their Replacements + + + + +Deprecated Function + +Replacement + + + + + +ldap_ber_free + +Replaced by ber_free. + + + +ldap_bind, ldap_bind_s + + +Replaced by ldap_simple_bind and ldap_simple_bind_s respectively. + + + +ldap_build_filter + +Replaced by ldap_create_filter. + + + + +ldap_cache_flush + +Replaced by ldap_memcache_* functions. + + + +ldap_charray_add, +ldap_charray_dup, ldap_charray_free, ldap_charray_inlist, ldap_charray_merge +, ldap_charray_position, ldap_str2charray + +None documented to replace these character array functions. + + + +ldap_create_proxyauth_control + + +Replaced by ldap_create_geteffectiveRights_control +. + + + +ldap_get_lang_values, ldap_get_lang_values_len + +Rarely used, no replacement. + + + +ldap_modrdn + +Replaced by ldap_modrdn2, itself outdated +by ldap_rename. + + + +ldap_modrdn_s + +Replaced by ldap_modrdn2_s, itself +outdated by ldap_rename_s. + + + +ldap_open + +Replaced by ldap_init and one of the +bind functions. + + + +ldap_result2error + +Replaced by ldap_parse_result. + + + + +ldap_setfilteraffixes + +Replaced by ldap_set_filter_additions. + + + + +ldap_ufn_search_c, ldap_ufn_search_ct, ldap_ufn_search_s +, ldap_ufn_setfilter, ldap_ufn_setprefix, ldap_ufn_timeout + + +None documented to replace these user-friendly search functions. + + + + +ldap_version + +Replaced by ldap_get_option. + + + + +
+
+Outdated Standard Functions and Equivalents + +C SDK +functions +outdated + +Many LDAP v2 functions are outdated now that LDAP v3 has been widely +adopted. Table 21–19 lists +both the outdated function and its new equivalent. Although LDAP v2 functions +remain in the standard specification, you should use the LDAP v3 functions +in any new client applications. Again, for maintenance reasons, the outdated +functions have often been implemented to call the newer function. +Outdated LDAP v2 Functions +and New Equivalents + + + + +LDAP v2 Functions + +LDAP v3 Equivalent + + + + + +ldap_abandon + +ldap_abandon_ext + + + +ldap_add, ldap_add_s + + +ldap_add_ext, ldap_add_ext_s + + + + +ldap_compare, ldap_compare_s + + +ldap_compare_ext, +ldap_compare_ext_s + + + +ldap_delete, ldap_delete_s + + +ldap_delete_ext, +ldap_delete_ext_s + + + +ldap_modify, ldap_modify_s + + +ldap_modify_ext, +ldap_modify_ext_s + + + +ldap_modrdn2, ldap_modrdn2_s + + +ldap_rename, ldap_rename_s + + + + +ldap_search, ldap_search_s +, ldap_search_st + +ldap_search_ext, +ldap_search_ext_s, ldap_search_ext_s - +use timeout argument + + + +ldap_unbind, ldap_unbind_s + + +ldap_unbind_ext replaces both forms +which are identical besides the suffix. + + + +
+
+
+Functions Alphabetically + +C SDK +functions +alphabetically + +functions +C SDK +C SDK, functions +<function>ber_alloc</function> +The ber_alloc function is used to allocate a new +Basic Encoding Rules (BER) BerElement structure. + +Syntax +#include <lber.h> +BerElement* ber_alloc( void ); + +Parameters +This function has no parameters. +Returns + +If successful, a pointer to the newly allocated BerElement structure. +If unsuccessful, a NULL pointer. + + + +Description +ber_alloc is used to allocate a new BerElement structure for encoding data with the +BER. +See Also +ber_printf, BerElement + + +<function>ber_alloc_t</function> +The ber_alloc_t function constructs and returns +a BerElement structure. +Syntax +#include <lber.h> +BerElement* ber_alloc_t( int options ); + +Parameters +<function>ber_alloc_t</function> Function +Parameter + + + + +Parameter + +Description + + + + + +options + +Contains bitwise OR of options to be used when generating the encoding +of the BerElement. One option is defined +and must always be supplied: +#define LBER_USE_DER 0x01 +When this option is present, lengths will always be encoded in the minimum +number of octets. This option does not cause values of sets and sequences +to be rearranged in tag and byte order, so these functions are not suitable +for generating DER output as defined in X.509 and X.680. + + + +
+
+Returns + +If successful, a pointer to the newly allocated BerElement structure. +If unsuccessful, a NULL pointer. + + + +Description +This function is the same as ber_alloc except +it has an option. +See Also +ber_printf, BerElement + +
+<function>ber_bvecfree</function> +The ber_bvecfree function frees an array of berval structures. +Syntax +#include <lber.h> +void ber_bvecfree( struct berval **bv ); + +Parameters +<function>ber_bvecfree</function> Function +Parameter + + + + +Parameter + +Description + + + + + +bv + +Pointer to the array that you want to free from memory. + + + +
+
+Description +Each berval in the array is freed using ber_bvfree, and then the array itself is freed. + +See Also +ber_bvfree +
+<function>ber_bvdup</function> +The ber_bvdup function returns a copy of a berval structure. +Syntax +#include <lber.h> +berval* ber_bvdup( const struct berval *bv ); + +Parameters +<function>ber_bvdup</function> Function +Parameter + + + + +Parameter + +Description + + + + + +bv + +Pointer to the berval structure to +be duplicated. + + + +
+
+Returns + +If successful, a pointer to the newly allocated berval structure. +If unsuccessful, a NULL pointer. + + + +Description +The ber_bvdup function returns a copy of a berval structure. The data referenced in the structure +is also duplicated. The bv_val field in the returned berval points to a different area of memory than +the bv_val field in the argument berval +. +
+<function>ber_bvfree</function> +The ber_bvfree function frees a berval structure. +Syntax +#include <lber.h> + void ber_bvfree( struct berval *bv ); + +Parameters +<function>ber_bvfree</function> Function +Parameter + + + + +Parameter + +Description + + + + + +bv + +Pointer to the berval structure that +you want to free from memory. + + + +
+
+Description +The ber_bvfree function frees a berval structure from memory. Call this function +to free a berval passed back from the ldap_extended_operation_s , ldap_parse_extended_result +, ldap_sasl_bind_s, or ldap_parse_sasl_bind_result functions. +See Also +ldap_extended_operation_s, ldap_parse_extended_result, ldap_sasl_bind_s + , ldap_parse_sasl_bind_result + +
+<function>ber_dup</function> +The ber_dup function returns a copy of a BerElement structure. +Syntax +#include <lber.h> +BerElement* ber_dup( BerElement *ber ); + +Parameters +<function>ber_dup</function> Function +Parameter + + + + +Parameter + +Description + + + + + +ber + +Pointer to the BerElement to be duplicated. + + + + +
+
+Returns + +If successful, a pointer to the newly allocated BerElement structure. +If unsuccessful, a NULL pointer. + + + +Description +The ber_dup function returns a copy of a BerElement structure. +
+<function>ber_first_element</function> +The ber_first_element function is used to return +the tag and length of the first element in a set or sequence. +Syntax +#include <lber.h> +unsigned long ber_first_element( BerElement *ber, unsigned long *len, + char **last ); + +Parameters +<function>ber_first_element</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ber + +Pointer to a BerElement. + + + +len + +Pointer to the address of the unsigned long which returns the length +of the first element. + + + +last + +Address of the pointer to return the address of the last byte of the +element. + + + +
+
+Returns +NULL pointer is returned on error. +Description +The ber_first_element function is used to return +the tag and length of the first element in a set or sequence. It also returns +a magic cookie parameter that should be passed to subsequent calls to ber_next_element . +See Also +ber_next_element +
+<function>ber_flatten</function> +The ber_flatten function allocates a berval structure whose contents are taken from a +source BerElement structure. +Syntax +#include <lber.h> +int ber_flatten( BerElement *ber, struct berval **bvPtr ); + +Parameters +<function>ber_flatten</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ber + +Pointer to the source BerElement. + + + + +bvPtr + +Pointer to the newly allocated berval structure +which must be freed using ber_bvfree. + + + + +
+
+Returns +Returns 0 on success and -1 on +error. +Description +This function is usually used when encoding LDAP v3 controls or extended +operations values. +See Also +ber_bvfree +
+<function>ber_free</function> +The ber_free function frees a BerElement structure previously allocated with ber_alloc , ber_alloc_t, + ber_init, or the ldap_first_attribute + and ldap_next_attribute search +functions. +Syntax +#include <ldap.h> +void ber_free( BerElement *ber, int freebuf ); + +Parameters +<function>ber_free</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ber + +Pointer to the BerElement structure +that you want to free. + + + +freebuf + +Specifies whether or not to free the buffer in the BerElement structure. + + + +
+
+Description +This function frees a BerElement structure, +which is used to keep track of the current attribute. When you are done working +with the attributes, you should free this structure from memory, if it still +exists. +To retrieve attributes from a search result entry, you need to +call either the ldap_first_attribute or ldap_next_attribute function. When freeing structures +allocated by these functions, you should specify 0 for +the freebuf argument. Otherwise, it should always be set +to 1. + +Example +Example 21–1 frees +the BerElement structure allocated by the ldap_first_attribute function. +Using <function>ber_free</function> +LDAP *ld; +LDAPMessage *a, *e; +BerElement *ber; +... +for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL; + a =ldap_next_attribute( ld, e, ber ) { + ... + /* Retrieve the value of each attribute */ + ... +} + +/* Free the BerElement when done */ +if ( ber != NULL ) { + ber_free( ber, 0 ); +} +... + + +See Also +ber_alloc, ber_alloc_t + , ber_init, ldap_first_attribute +, ldap_next_attribute +
+<function>ber_get_boolean</function> +The ber_get_boolean function is used to read a +boolean value. +Syntax +#include <lber.h> +unsigned long ber_get_boolean( BerElement *ber, + int *boolval ); + +Parameters +<function>ber_get_boolean</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ber + +Pointer to the BerElement structure +that contains the boolean. + + + +boolval + +Specifies the boolean to read. + + + +
+
+Returns +The value is returned on success and LBER_ERROR ( +-1) on failure. +
+<function>ber_get_int</function> +The ber_get_int function tries to interpret the +next element as an integer, returning the result in num. +Syntax +#include <lber.h> +unsigned long ber_get_int( BerElement *ber, int *num ); + +Parameters +<function>ber_get_int</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ber + +Pointer to the BerElement structure +that contains the boolean. + + + +num + +Pointer to the result. + + + +
+
+Returns +The tag of whatever it finds is returned on success and LBER_ERROR + (-1) on failure. +
+<function>ber_get_next</function> +The ber_get_next function reads the next BER element. +Syntax +#include <lber.h> +unsigned long ber_get_next( Sockbuf *sb, unsigned long *len, + BerElement *ber ); + +Parameters +<function>ber_get_next</function> Function +Parameters + + + + +Parameter + +Description + + + + + +sb + +Descriptor (socket or file descriptor) from which to read. + + + +len + +The length of the entire element. + + + +ber + +Pointer to the BerElement structure. + + + + +
+
+Description +ber_get_next strips off and returns the leading +tag, strips off and returns the length of the entire element, and sets up +a pointer to ber for subsequent calls to decode the element. + +
+<function>ber_get_next_buffer</function> +The ber_get_next_buffer function reads the next +BER element from a byte buffer. +This is an older function included in the SDK for backward-compatibility. +If you are writing a new LDAP client, use ber_get_next_buffer_ext + instead. +<function>ber_get_next_buffer_ext</function> +The ber_get_next_buffer_ext function reads the +next BER element from a byte buffer. +ber_get_next_buffer_ext is a +new version of the ber_get_next_buffer function. +If you are writing a new LDAP client, use ber_get_next_buffer_ext + . + +Syntax +#include <lber.h> +unsigned long ber_get_next_buffer_ext( void *buffer, + size_t buffer_size, unsigned long *len, BerElement *ber, + unsigned long *Bytes_Scanned, Sockbuf *sb ); + +Parameters +<function>ber_get_next_buffer_ext</function> Function +Parameters + + + + +Parameter + +Description + + + + + +buffer + +Pointer to the buffer. + + + +buffer_size + +The size of the buffer. + + + +len + +The length of the entire element. + + + +ber + +Pointer to a BerElement. + + + +Bytes_Scanned + +Returns the number of bytes actually searched through. + + + +sb + +Descriptor (socket or file descriptor) from which to read. + + + +
+
+
+<function>ber_get_null</function> +The ber_get_null function is used to read a NULL + element. +Syntax +#include <lber.h> +unsigned long ber_get_null( BerElement *ber ); + +Parameters +<function>ber_get_null</function> Function +Parameter + + + + +Parameter + +Description + + + + + +ber + +Pointer to a BerElement. + + + +
+
+Returns +Returns the tag of the element it skips over. +
+<function>ber_get_option</function> +The ber_get_option function is used to retrieve +information about the API and about the specific implementation being used. +Syntax +#include <lber.h> +int ber_get_option( BerElement *ber, int option, void *value ); + + +<function>ber_get_stringa</function> +The ber_get_stringa function is used to allocate + memory space into which an octet string is read. +Syntax +#include <lber.h> +unsigned long ber_get_stringa( BerElement *ber, char **buf ); + + +<function>ber_get_stringal</function> +The ber_get_stringal function is used to allocate +memory space into which an octet string and its length are read. +Syntax +#include <lber.h> +unsigned long ber_get_stringal( BerElement *ber, struct berval **bv ); + +Description +It takes a berval structure, and returns +the result in this parameter. + +<function>ber_get_stringb</function> +The ber_get_stringb function is used to read an +octet string into a preallocated buffer. +Syntax +#include <lber.h> +unsigned long ber_get_stringb( BerElement *ber, char *buf, + unsigned long *len ); + +Description +The len parameter should be initialized to the size +of the buffer, and will contain the length of the octet string read upon return. +The buffer should be big enough to take the octet string value plus a terminating +NULL byte. + +<function>ber_init</function> +The ber_init function constructs a new BerElement. +Syntax +#include <lber.h> +BerElement * ber_init( const struct berval *bv ); + +Parameters +<function>ber_init</function> Function +Parameter + + + + +Parameter + +Description + + + + + +bv + +Pointer to a berval. + + + +
+
+Returns + +If successful, returns a new BerElement containing +a copy of the data in the bv argument. +If not, returns a NULL pointer. + + + +
+<function>ber_init_w_nullchar</function> +The ber_init_w_nullchar function constructs a new BerElement with a NULL character. +Syntax +#include <lber.h> +void ber_init_w_nullchar( BerElement *ber, int options ); + + +<function>ber_next_element</function> +The ber_next_element function is used to return +the tag and length of the next element in a set or sequence. +Syntax +#include <lber.h> +unsigned long ber_next_element( BerElement *ber, unsigned long *len, + char *last ); + +Parameters +<function>ber_next_element</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ber + +Pointer to a BerElement. + + + +len + +Pointer to the address of the unsigned long which returns the length +of the next element. + + + +last + +Address of the pointer to return the address of the last byte of the +element. + + + +
+
+Returns +NULL pointer is returned on error. +Description +The ber_next_element function is used to return +the tag and length of the first element in a set or sequence. +See Also +ber_first_element +
+<function>ber_peek_tag</function> +The ber_peek_tag function returns the tag of the +next element to be parsed in the supplied BerElement structure. + +Syntax +#include <lber.h> +unsigned long ber_peek_tag( BerElement *ber, unsigned long *len ); + +Parameters +<function>ber_peek_tag</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ber + +Pointer to a BerElement. + + + +len + +Pointer to the address of the unsigned long which returns the length +of the next element. + + + +
+
+Returns +Returns the tag of the next element to be read in the BerElement structure. LBER_DEFAULT is +returned if there is no further data to be read. +
+<function>ber_printf</function> +The ber_printf function encodes a BER element. +Syntax +#include <lber.h> +ber_printf( BerElement *ber, const char *fmt, ... ); + +Parameters +<function>ber_printf</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ber + +Pointer to a BerElement returned by ber_alloc or ber_alloc_t. + + + + +fmt + +Defines the encoding format string. The format string can contain the +following characters: + +-b Boolean. An integer parameter should +be supplied. A boolean element is output. +-i Integer. An integer parameter should +be supplied. An integer element is output. +-B Bitstring. A char * pointer +to the start of the bitstring is supplied, followed by the number of bits +in the bitstring. A bitstring element is output. +-n Null. No parameter is required. A +NULL element is output. +-o Octet string. A char * is +supplied, followed by the length of the string pointed to. An octet string +element is output. +-s Octet string. A NULL terminated +string is supplied. An octet string element is output, not including the trailing + NULL octet. +-t Tag. An int specifying +the tag to give the next element is provided. This works across calls. + +-v Several octet strings. A NULL terminated +array of char *s is supplied. Note that a construct like '{v}' is required +to get an actual sequence of octet strings. +-{ Begin sequence. No parameter is required. + +-} End sequence. No parameter is required. + +-[ Begin set. No parameter is required. + +-] End set. No parameter is required. + + + + + + +... + +Values to be encoded. + + + +
+
+Description +State information is kept with the ber parameter +so multiple calls can be made to ber_printf to append +things to the end of the BerElement. ber_printf + interprets and formats its arguments according to the format string +fmt. Each character in fmt refers to an argument +to ber_printf . +Returns +-1 if there is an error during encoding. +
+<function>ber_put_bitstring</function> +The ber_put_bitstring function writes a bitstring +value to the given BerElement. +Syntax +#include <lber.h> +int ber_put_bitstring( BerElement *ber, char *str, + unsigned long bitlen, unsigned long tag ); + +Description +The ber_put_bitstring function writes bitlen bits +starting at str as a bitstring value to the given BerElement. + +<function>ber_put_boolean</function> +The ber_put_boolean function writes a boolean value +to a BerElement. +Syntax +#include <lber.h> +int ber_put_boolean( BerElement *ber, int boolval, unsigned long tag ); + +Description +The boolean value is given by boolval to the BerElement. + +<function>ber_put_enum</function> +The ber_put_enum function writes an enumerated +value to a BerElement. +Syntax +#include <lber.h> +int ber_put_enum( BerElement *ber, long num, unsigned long tag ); + + +<function>ber_put_int</function> +The ber_put_int function writes an integer to a BerElement. +Syntax +#include <lber.h> +int ber_put_int( BerElement *ber, long num, unsigned long tag ); + + +<function>ber_put_null</function> +The ber_put_null function writes a writes a NULL + element to a BerElement. +Syntax +#include <lber.h> +int ber_put_null( BerElement *ber, unsigned long tag ); + + +<function>ber_put_ostring</function> +The ber_put_ostring function writes bytes to a + BerElement as an octet string. +Syntax +#include <lber.h> +int ber_put_ostring( BerElement *ber, char *str, + unsigned long len, unsigned long tag ); + + +<function>ber_put_seq</function> +The ber_put_seq function puts a sequence to a BerElement. +Syntax +#include <lber.h> +int ber_put_seq( BerElement *ber ); + +Parameters +<function>ber_put_seq</function> Function +Parameter + + + + +Parameter + +Description + + + + + +ber + +Pointer to a BerElement. + + + +
+
+Description +The ber_start_seq function is used +to start a sequence in the BerElement. The +end of the sequence is marked by the nearest matching call to ber_put_seq +. +
+<function>ber_put_set</function> +The ber_put_set function puts a set to a BerElement. +Syntax +#include <lber.h> +int ber_put_set( BerElement *ber ); + +Parameters +<function>ber_put_set</function> Function +Parameter + + + + +Parameter + +Description + + + + + +ber + +Pointer to a BerElement. + + + +
+
+Description +The ber_start_set function is used +to start a set in the BerElement. The end +of the set is marked by the nearest matching call to ber_put_set. + +
+<function>ber_put_string</function> +The ber_put_string function writes a NULL terminated +string (minus the terminating 0) to a BerElement as an octet string. +Syntax +#include <lber.h> +int ber_put_string( BerElement *ber, char *str, unsigned long tag ); + + +<function>ber_read</function> +Syntax +#include <lber.h> +long ber_read( BerElement *ber, char *buf, unsigned long len ); + + +<function>ber_reset</function> +Syntax +#include <lber.h> +void ber_reset( BerElement *ber, int was_writing ); + + +<function>ber_scanf</function> +The ber_scanf function decodes a BerElement. +Syntax +#include <lber.h> +unsigned long ber_scanf( BerElement *ber, const char *fmt, ... ); + +Parameters +<function>ber_scanf</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ber + +Pointer to a BerElement as returned +by ber_get_next. + + + +fmt + +Defines the encoding format string. The format string can contain the +following characters: + +-a Octet string. A char ** should +be supplied. Memory is allocated, filled with the contents of the octet string, + NULL terminated, and returned in the parameter. + +-s Octet string. A char * +buffer should be supplied, followed by a pointer to an integer initialized +to the size of the buffer. Upon return, the NULL terminated +octet string is put into the buffer, and the integer is set to the actual +size of the octet string. +-O Octet string. A struct ber_val +** should be supplied, which upon return points to a memory allocated +struct berval containing the octet string and its length. Call + ber_bvfree to free allocated memory. + +-b Boolean. A pointer to an integer should +be supplied. +-i Integer. A pointer to an integer should +be supplied. +-B Bitstring. A char ** should +be supplied which will point to the memory allocated bits, followed by an + unsigned long *, which will point to the length (in bits) +of the bitstring returned. +-n Null. No parameter is required. The +element is simply skipped if it is recognized. +-v Sequence of octet strings. A char +*** should be supplied, which upon return points to a memory allocated + NULL terminated array of char *s containing +the octet strings. NULL is returned if the sequence is +empty. + + + + + +fmt (continued) + + +-V Sequence of octet strings with lengths. +A struct berval *** should be supplied, which upon +return points to a memory allocated, NULL terminated array +of struct berval *s containing the octet strings and their +lengths. NULL is returned if the sequence is empty. ber_bvecfree can be called to free the allocated +memory. +-x Skip element. The next element is skipped. + +-{ Begin sequence. No parameter is required. +The initial sequence tag and length are skipped. +-} End sequence. No parameter is required +and no action is taken. +-[ Begin set. No parameter is required. +The initial set tag and length are skipped. +-] End set. No parameter is required and +no action is taken. + + + + + +... + +Values to be encoded. + + + +
+
+Description +ber_scanf reads from ber, interprets +the bytes according to the format string fmt, and stores +the results in its additional arguments. The format string contains conversion +specifications which are used to direct the interpretation of the BER element. + +See Also +ber_printf +
+<function>ber_set_option</function> +Syntax +#include <lber.h> +int ber_set_option( BerElement *ber, int option, void *value ); + + +<function>ber_set_string_translators</function> +Syntax +#include <lber.h> +unsigned long ber_skip_tag( BerElement *ber, unsigned long *len ); + + +<function>ber_skip_tag</function> +The ber_skip_tag function advances the pointer +to a BerElement past the first tag and length +to the next tag. +Syntax +#include <lber.h> +unsigned long ber_skip_tag( BerElement *ber, unsigned long *len ); + +Parameters +<function>ber_skip_tag</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ber + +Pointer to a BerElement. + + + +len + +Pointer to the length of the value to be skipped. + + + +
+
+Description +ber_skip_tag should only be used with constructed +types and situations when a BER encoding is used as the value of an octet +string. +See Also +ber_peek_tag +
+<function>ber_sockbuf_alloc</function> +Syntax +#include <lber.h> +Sockbuf* ber_sockbuf_alloc( void ); + + +<function>ber_sockbuf_free</function> +Syntax +#include <lber.h> +void ber_sockbuf_free( Sockbuf* p ); + + +<function>ber_sockbuf_free_data</function> +Syntax +#include <lber.h> +void ber_sockbuf_free_data(Sockbuf *p); + + +<function>ber_sockbuf_get_option</function> +Syntax +#include <lber.h> +int ber_sockbuf_get_option( Sockbuf *sb, int option, void *value ); + + +<function>ber_sockbuf_set_option</function> +Syntax +#include <lber.h> +int ber_sockbuf_set_option( Sockbuf *sb, int option, void *value ); + + +<function>ber_special_alloc</function> +The ber_special_alloc function allocates a BerElement structure plus some extra memory. +Syntax +#include <lber.h> +void* ber_special_alloc( size_t size, BerElement **ppBer ); + +Returns +Returns a pointer to the BerElement and +a pointer to the extra memory. +Description +ber_special_alloc allocates a ber data buffer within +the same block, thus saving a call to calloc later when we read data. + + +<function>ber_special_free</function> +The ber_special_free function frees an allocated BerElement structure. +Syntax +#include <lber.h> +void ber_special_free( void* buf, BerElement *ber ); + +See Also +ber_special_alloc + +<function>ber_stack_init</function> +Syntax +#include <lber.h> +int) LDAP_CALL ber_stack_init(BerElement *ber, int options, + char * buf, size_t size); + + +<function>ber_start_seq</function> +The ber_start_seq function is used to start a sequence +in a BerElement. +Syntax +#include <lber.h> +int ber_start_seq( BerElement *ber, unsigned long tag ); + +See Also +ber_put_seq + +<function>ber_start_set</function> +The ber_start_seq function is used to start a set +in a BerElement. +Syntax +#include <lber.h> +int ber_start_set( BerElement *ber, unsigned long tag ); + +See Also +ber_put_set + +<function>ber_svecfree</function> +Syntax +#include <lber.h> +void ber_svecfree( char **vals ); + + +<function>ber_write</function> +Syntax +#include <lber.h> +long ber_write( BerElement *ber, char *buf, + unsigned long len, int nosos ); + + +<function>ldap_abandon</function> +The ldap_abandon function cancels an asynchronous +LDAP operation that is in progress. +This is an older function included in the SDK for backward-compatibility. +If you are writing a new LDAP client, use ldap_abandon_ext + instead. +Syntax +#include <ldap.h> +int ldap_abandon( LDAP *ld, int msgid ); + +Parameters +<function>ldap_abandon</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +msgid + +Message ID of an LDAP operation. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +-1 if unsuccessful. + +The appropriate LDAP error code is also set in the LDAP structure. You can retrieve the error code +by calling ldap_get_lderrno. Some possible +codes are: + +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the request. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_NO_MEMORY if memory cannot be +allocated. + + + +Description +Please use the newer version of this function, ldap_abandon_ext +. +Example +Example 21–2 cancels +an ldap_url_search operation, abandoning +the results of the operation. +Cancelling an <function>ldap_url_search</function> Operation + +LDAP *ld; +char *url = "ldap://ldap.example.com/c=US?o,description?one?o=sales"; +int msgid; +... +/* Initiate a search operation */ +msgid = ldap_url_search( ld, url, 0 ); +... +/* Abandon the search operation */ +if ( ldap_abandon( ld, msgid ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_abandon" ); + return( 1 ); +} +... + + +See Also +ldap_abandon_ext +
+<function>ldap_abandon_ext</function> +The ldap_abandon_ext function cancels an asynchronous +LDAP operation that is in progress. +ldap_abandon_ext is a new version +of the ldap_abandon function. If you are +writing a new LDAP client, use ldap_abandon_ext. + +Syntax +#include <ldap.h> + int ldap_abandon_ext( LDAP *ld, int msgid, + LDAPControl **serverctrls, LDAPControl **clientctrls ); + +Parameters +<function>ldap_abandon_ext</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +msgid + +Message ID of an LDAP operation to identify the operation to be cancelled. +When you call an asynchronous function such as ldap_search_ext +, the msgidp argument returns a pointer to a message +ID that uniquely identifies the operation. Thus, when you call ldap_abandon_ext, your LDAP client is able to send +a request specifying the message ID of the operation to be cancelled. + + + + +serverctrls + +Pointer to an array of LDAPControl structures +representing LDAP server controls that apply to this operation. If you do +not want to pass any server controls, specify NULL for +this argument. + + + +clientctrls + +Pointer to an array of LDAPControl structures +representing LDAP client controls that apply to this operation. If you do +not want to pass any client controls, specify NULL for +this argument. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the request. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_NO_MEMORY if memory cannot be +allocated. + + +Description +The ldap_abandon_ext function cancels an asynchronous +LDAP operation that is in progress. For example, if you called ldap_search_ext to initiate an LDAP search operation +on the server, you can call ldap_abandon_ext to cancel +it. When you call ldap_abandon_ext, the function checks +to see if the results of the operation have already been returned. If so, +ldap_abandon_ext deletes the message ID from the queue of pending +messages. If the results have not been returned, ldap_abandon_ext sends +a request to abandon the operation. Once cancelled, the results of the operation +will not be returned, even if you subsequently call ldap_result + to retrieve them. To identify the operation to be cancelled, specify +the message ID of the operation in the msgid argument of +the ldap_abandon_ext function. +Example +Example 21–3 cancels +an ldap_url_search operation, abandoning +the results of the operation. +Using <function>ldap_abandon_ext</function> +LDAP *ld; +char *url = "ldap://ldap.example.com/c=US?o,description?one?o=sales"; +int msgid; +LDAPControl **srvrctrls, **clntctrls; +... +/* Initiate a search operation */ +msgid = ldap_url_search( ld, url, 0 ); +... +/* Abandon the search operation */ +if ( ldap_abandon_ext( ld, msgid, srvrctrls, clntctrls ) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_abandon" ); + return( 1 ); +} +... + + +See Also +ldap_add_ext, ldap_compare_ext + , ldap_delete_ext, ldap_extended_operation, ldap_modify_ext +, ldap_rename, +ldap_sasl_bind , ldap_search_ext, + ldap_simple_bind, ldap_url_search + +
+<function>ldap_add</function> +The ldap_add function adds a new entry to the directory +asynchronously. +This is an older function that is included in the SDK for backward-compatibility. +If you are writing a new LDAP client, use ldap_add_ext +instead. +Syntax +#include <ldap.h> + int ldap_add( LDAP *ld, const char *dn, LDAPMod **attrs ); + +Parameters +<function>ldap_add</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the entry to add. With the exception of the leftmost component, +all components of the DN (for example, o=organization or +c=country) must already exist. + + + +attrs + +Pointer to a NULL terminated array of pointers to LDAPMod structures representing the attributes of +the new entry. + + + +
+
+Returns +The message ID of the ldap_add operation. +To check the result of this operation, call +ldap_result and ldap_result2error. +See ldap_add_ext_s for a list of possible +result codes for the LDAP add operation. + +Description +Please use the newer version of this function, ldap_add_ext + . +Example +Example 21–4 adds +a new entry to the directory. +Using <function>ldap_add</function> +#include <ldap.h> +... +LDAP *ld; +LDAPMod *list_of_attrs[4]; +LDAPMod attribute1, attribute2, attribute3; +LDAPMessage *result; +int msgid, rc; +struct timeval tv; + +/* Distinguished name of the new entry. Note that "dc=example,dc=com" and + "ou=People,dc=example,dc=com" must already exist in the directory. */ +char *dn = "uid=bjensen,ou=People,dc=example,dc=com"; + +/* To add a "person" entry, you must specify values for the sn, cn, + and objectClass attributes. (These are required attributes.) */ +char *sn_values[] = { "Jensen", NULL }; + +/* To specify multiple values for an attribute, add the different values + to the array. */ +char *cn_values[] = { "Barbara Jensen", "Babs Jensen", NULL }; + +/* The object class for a "person" entry is "inetOrgPerson", which is a + subclass of "top", "person", and "organizationalPerson". You should add + all of these classes as values of the objectClass attribute. */ +char *objectClass_values[] = { "top", "person", "organizationalPerson", + "inetOrgPerson", NULL }; +... +/* Specify the value and type of each attribute in separate LDAPMod + structures */ +attribute1.mod_type = "sn"; +attribute1.mod_values = sn_values; +attribute2.mod_type = "cn"; +attribute2.mod_values = cn_values; +attribute3.mod_type = "objectClass"; +attribute3.mod_values = objectClass_values; + +/* Add the pointers to these LDAPMod structures to an array */ +list_of_attrs[0] = &attribute1; +list_of_attrs[1] = &attribute2; +list_of_attrs[2] = &attribute3; +list_of_attrs[3] = NULL; +... +/* Set up the timeout period for adding the new entry */ +tv.tv_sec = tv.tv_usec = 0; + +/* Add the user "Barbara Jensen" */ +if ( ( msgid = ldap_add( ld, dn, list_of_attrs ) ) == -1 ) { + ldap_perror( ld, "ldap_add" ); + return( 1 ); +} + +/* Check to see if the operation has completed */ +while ( ( rc = ldap_result( ld, msgid, 0, &tv, &result ) ) == 0 ) { + ... + /* do other work while waiting for the operation to complete */ + ... +} + +/* Check the result to see if any errors occurred */ +if (( rc = ldap_result2error( ld, result, 1 )) != LDAP_SUCCESS ) { + printf( "Error while adding entry: %s\n", ldap_err2string( rc )); +} +... + + +See Also +ldap_add_ext +
+<function>ldap_add_ext</function> +The ldap_add_ext function adds a new entry to the +directory asynchronously. +ldap_add_ext is a new version +of the ldap_add function. If you are writing +a new LDAP client, use ldap_add_ext. + +Syntax +#include <ldap.h> + int ldap_add_ext( LDAP *ld, const char *dn, LDAPMod **attrs, + LDAPControl **serverctrls, LDAPControl **clientctrls, + int *msgidp ); + +Parameters +<function>ldap_add_ext</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the entry to add. With the exception of the leftmost component, +all components of the DN (for example, o=organization or +c=country) must already exist. + + + +attrs + +Pointer to a NULL terminated array of pointers to LDAPMod structures representing the attributes of +the new entry. + + + +serverctrls + +Pointer to an array of LDAPControl structures +representing LDAP server controls that apply to this operation. If you do +not want to pass any server controls, specify NULL for +this argument. + + + +clientctrls + +Pointer to an array of LDAPControl structures +representing LDAP client controls that apply to this operation. If you do +not want to pass any client controls, specify NULL for +this argument. + + + +msgidp + +Pointer to an integer that will be set to the message ID of the LDAP +operation. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the request. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_NOT_SUPPORTED if controls are +included in your request (for example, as a session preference) and your LDAP +client does not specify that it is using the LDAP v3. Make sure that you set +the version of your LDAP client to version 3 before calling this function. + + + +Description +The ldap_add_ext adds a new entry to the directory. +To add a new entry to the directory, you need to specify: + +A unique DN identifying the new entry.Use the + dn argument to specify the DN of the new entry. The parents +of the entry should already exist. For example, if you are adding the entry +uid=bjensen,ou=People,dc=example,dc=com , the entries ou=People + and dc=example,dc=com must already exist in +the directory. +A set of attributes for the new entry.Create +an LDAPMod structure for each attribute. +Set the mod_op field to 0 if the attribute +values are string values. To specify values that consist of binary data (such +as a sound file or a JPEG file), set the mod_op field to +LDAP_MOD_BVALUES. Create an array of these LDAPMod + structures and pass the array as the attrs argument. +ldap_add_ext is an asynchronous function; it does +not directly return results. In order to get the results of the asynchronous +operation, you need to call the ldap_result and ldap_parse_result functions. If you want the results +to be returned directly by the function, call the synchronous function ldap_add_ext_s. For a list of possible result codes +for an LDAP add operation, see the ldap_add_ext_s +function. + + +See Also +ldap_add_ext_s, +ldap_result, ldap_parse_result, LDAPMod +
+<function>ldap_add_ext_s</function> +The ldap_add_ext_s function adds a new entry to +the directory synchronously. +ldap_add_ext_s is a new version +of the ldap_add_s function. If you are writing +a new LDAP client, use ldap_add_ext_s. + +Syntax +#include <ldap.h> + int ldap_add_ext_s( LDAP *ld, const char *dn, LDAPMod **attrs, + LDAPControl **serverctrls, LDAPControl **clientctrls ); + +Parameters +<function>ldap_add_ext_s</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the entry to add. With the exception of the leftmost component, +all components of the DN (for example, o=organization or +c=country) must already exist. + + + +attrs + +Pointer to a NULL terminated array of pointers to LDAPMod structures representing the attributes of +the new entry. + + + +serverctrls + +Pointer to an array of LDAPControl structures +representing LDAP server controls that apply to this operation. If you do +not want to pass any server controls, specify NULL for +this argument. + + + +clientctrls + +Pointer to an array of LDAPControl structures +representing LDAP client controls that apply to this operation. If you do +not want to pass any client controls, specify NULL for +this argument. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the request. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_LOCAL_ERROR if an error occurred +when receiving the results from the server. +LDAP_DECODING_ERROR if an error occurred +when decoding the BER-encoded results from the server. +LDAP_NOT_SUPPORTED if controls are +included in your request (for example, as a session preference) and your LDAP +client does not specify that it is using the LDAP v3. Make sure that you set +the version of your LDAP client to version 3 before calling this function. + + +&cnDirectoryServer; and other LDAP server products may send result +codes in addition to those described. For example, the server may have loaded +a plug-in that returns custom result codes. Check your LDAP server documentation +for other result codes. + +Description +The ldap_add_ext_s function adds a new entry to +the directory. To add a new entry to the directory, you need to specify: + +A unique DN identifying the new entry.Use the + dn argument to specify the DN of the new entry. The parents +of the entry should already exist. For example, if you are adding the entry +uid=bjensen,ou=People,dc=example,dc=com , the entries ou=People + and dc=example,dc=com must already exist in +the directory. +A set of attributes for the new entry.Create +an LDAPMod structure for each attribute. +Set the mod_op field to 0 if the attribute +values are string values. To specify values that consist of binary data (such +as a sound file or a JPEG file), set the mod_op field to +LDAP_MOD_BVALUES. Create an array of these LDAPMod + structures and pass the array as the attrs argument. +ldap_add_ext_s is a synchronous function; it directly +returns the results of the operation. If you want to perform other operations +while waiting for the results of this operation, call the asynchronous function ldap_add_ext. + + +See Also +ldap_add_ext, LDAPMod + +
+<function>ldap_add_s</function> +The ldap_add_s function adds a new entry to the +directory synchronously. +This is an older function that is included in the SDK for backward-compatibility. +If you are writing a new LDAP client, use ldap_add_ext_s + instead. +Syntax +#include <ldap.h> +int ldap_add_s( LDAP *ld, const char *dn, LDAPMod **attrs ); + +Parameters +<function>ldap_add_s</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the entry to add. With the exception of the leftmost component, +all components of the DN (for example, o=organization or +c=country) must already exist. + + + +attrs + +Pointer to a NULL terminated array of pointers to LDAPMod structures representing the attributes of +the new entry. + + + +
+
+Returns +See ldap_add_ext_s for a list of possible +return codes. +Description +Please use the newer version of this function, ldap_add_ext_s + . +Example +Example 21–5 adds +a new entry to the directory. +Using <function>ldap_add_s</function> +#include <ldap.h> +... +LDAP *ld; +LDAPMod *list_of_attrs[4]; +LDAPMod attribute1, attribute2, attribute3; + +/* Distinguished name of the new entry. Note that "dc=example,dc=com" and + "ou=People,dc=example,dc=com" must already exist in the directory. */ +char *dn = "uid=bjensen,ou=People,dc=example, dc=com"; + +/* To add a "person" entry, you must specify values for the sn, cn, + and objectClass attributes. (These are required attributes.) */ +char *sn_values[] = { "Jensen", NULL }; + +/* To specify multiple values for an attribute, add the different values + to the array. */ +char *cn_values[] = { "Barbara Jensen", "Babs Jensen", NULL }; + +/* The object class for a "person" entry is "inetOrgPerson", which is a + * subclass of "top", "person", and "organizationalPerson". You should add + * all of these classes as values of the objectClass attribute. */ +char *objectClass_values[] = { "top", "person", "organizationalPerson", + "inetOrgPerson", NULL }; +... +/* Specify the value and type of each attribute in separate LDAPMod + structures */ +attribute1.mod_type = "sn"; +attribute1.mod_values = sn_values; +attribute2.mod_type = "cn"; +attribute2.mod_values = cn_values; +attribute3.mod_type = "objectClass"; +attribute3.mod_values = objectClass_values; + +/* Add the pointers to these LDAPMod structures to an array */ +list_of_attrs[0] = &attribute1; +list_of_attrs[1] = &attribute2; +list_of_attrs[2] = &attribute3; +list_of_attrs[3] = NULL; +... +/* Add the user "Barbara Jensen" */ +if ( ldap_add_s( ld, dn, list_of_attrs ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_add_s" ); + return( 1 ); +} +... + + +See Also +ldap_add_ext_s +
+<function>ldap_ber_free</function> +The ldap_ber_free function frees a BerElement structure from memory. +This is an older function that is included in the SDK for backward-compatibility. +If you are writing a new LDAP client, use ber_free instead. +Except in name, the two functions are identical. +Syntax +#include <ldap.h> + void ldap_ber_free( BerElement *ber, int freebuf ); + +Parameters +<function>ldap_ber_free</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ber + +Pointer to the BerElement structure +that you want to free. + + + +freebuf + +Specifies whether or not to free the buffer in the BerElement structure. + + + +
+
+Description +Please use the newer version of this function, ber_free + . +See Also +ber_free +
+<function>ldap_bind</function> +This function is deprecated and should not be used. It is included +in ldap-deprecated.h for backward-compatibility. Use ldap_simple_bind instead. +ldap_bind can be used when the authentication method +being used needs to be selected at runtime. +Syntax +#include <ldap-deprecated.h> + ldap_bind( LDAP *ld, const char *who, const char *passwd, int method ); + +Parameters +<function>ldap_bind</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +who + +DN of the user who wants to authenticate. For anonymous authentication, +set this or the passwd argument to NULL. + + + + +passwd + +Password of the user who wants to authenticate. For anonymous authentication, +set this or the who argument to NULL. + + + +method + +Defines the authentication method to be used. It should be set to +LDAP_AUTH_SIMPLE to select simple authentication. + + + +
+
+Returns +ldap_bind returns the message ID of the request +it initiates. +Description +This is an asynchronous function that authenticates a specified entry +to the directory. After a connection is made to an LDAP server using ldap_open, a bind operation must be performed before +other operations can be attempted over the connection. +See Also +ldap_open, ldap_init +, prldap_init (IPv6), ldap_bind_s +
+<function>ldap_bind_s</function> +This function is deprecated and should not be used. It is included +in ldap-deprecated.h for backward-compatibility. Use ldap_simple_bind_s instead. +ldap_bind_s can be used when the authentication +method needs to be selected at runtime. +Syntax +#include <ldap-deprecated.h> + ldap_bind_s( LDAP *ld, const char *who, const char *cred, int method ); + +Parameters +<function>ldap_bind_s</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +who + +DN of the user who wants to authenticate. For anonymous authentication, +set this or the passwd argument to NULL. + + + + +cred + +Password of the user who wants to authenticate. For anonymous authentication, +set this or the who argument to NULL. + + + +method + +Defines the authentication method to be used. It should be set to +LDAP_AUTH_SIMPLE to select simple authentication. + + + +
+
+Returns +ldap_bind_s returns an LDAP error indication. + +Description +This is a synchronous function that authenticates a specified entry +to the directory. After a connection is made to an LDAP server using ldap_open , a bind operation must be performed +before other operations can be attempted over the connection. +See Also +ldap_open, ldap_init +, prldap_init (IPv6), ldap_bind +
+<function>ldap_build_filter</function> +This function is deprecated and should not be used. It is included +in ldap-deprecated.h for backward-compatibility. Use ldap_create_filter instead. +See Also +ldap_create_filter + +<function>ldap_cache_flush</function> +This function is deprecated and should not be used. It is included +in ldap-deprecated.h for backward-compatibility. Use the + ldap_memcache_* functions instead. +For more specific information, see the header file ldap-deprecated.h + . +See Also +ldap_memcache_init, ldap_memcache_set, ldap_memcache_get +, ldap_memcache_update, ldap_memcache_flush , ldap_memcache_destroy + + +<function>ldap_charray_add</function> +This function is deprecated and should not be used. It is included +in ldap-to-be-deprecated.h for backward-compatibility. + +For more specific information, see the header file ldap-to-be-deprecated.h + . +<function>ldap_charray_dup</function> +This function is deprecated and should not be used. It is included +in ldap-to-be-deprecated.h for backward-compatibility. + +For more specific information, see the header file ldap-to-be-deprecated.h + . + +<function>ldap_charray_free</function> +This function is deprecated and should not be used. It is included +in ldap-to-be-deprecated.h for backward-compatibility. + +For more specific information, see the header file ldap-to-be-deprecated.h + . +<function>ldap_charray_inlist</function> +This function is deprecated and should not be used. It is included +in ldap-to-be-deprecated.h for backward-compatibility. + +For more specific information, see the header file ldap-to-be-deprecated.h + . + +<function>ldap_charray_merge</function> +This function is deprecated and should not be used. It is included +in ldap-to-be-deprecated.h for backward-compatibility. + +For more specific information, see the header file ldap-to-be-deprecated.h + . +<function>ldap_charray_position</function> +This function is deprecated and should not be used. It is included +in ldap-to-be-deprecated.h for backward-compatibility. + +For more specific information, see the header file ldap-to-be-deprecated.h + . + +<function>ldap_compare</function> +The ldap_compare function asynchronously determines +if an attribute of an entry contains a specified value. +This is an older function that is included in the SDK for backward-compatibility. +If you are writing a new LDAP client, use ldap_compare_ext + instead. +Syntax +#include <ldap.h> + int ldap_compare( LDAP *ld, const char *dn, const char *attr, + const char *value ); + +Parameters +<function>ldap_compare</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the entry used in the comparison. + + + +attr + +Attribute type that you want to check the value against. + + + +value + +Value that you want to compare against the attribute values. + + + + +
+
+Returns +Returns the message ID of the ldap_compare operation. +To check the result of this operation, call +ldap_result and ldap_result2error. +See ldap_compare_ext_s function for a list +of possible result codes for the LDAP compare operation. + +Description +Please use the newer version of this function, ldap_compare_ext + . +Example +Example 21–6 checks +to see if Barbara Jensen has the email address bjensen@example.com. + +Using <function>ldap_compare</function> +#include <stdio.h> +#include <ldap.h> +... +LDAP *ld; +char *dn = "uid=bjensen,ou=People,dc=example, dc=com"; +int msgid; +... +msg_id = ldap_compare( ld, dn, "mail", "bjensen@example.com" ); +... + + +See Also +ldap_compare_ext +
+<function>ldap_compare_ext</function> +The ldap_compare_ext function asynchronously determines +if an attribute of an entry contains a specified value. +ldap_compare_ext is a new version +of the ldap_compare function. If you are +writing a new LDAP client, use ldap_compare_ext. + +Syntax +#include <ldap.h> +int ldap_compare_ext( LDAP *ld, const char *dn, const char *attr, + struct berval *bvalue, LDAPControl **serverctrls, + LDAPControl **clientctrls, int *msgidp ); + +Parameters +<function>ldap_compare_ext</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the entry used in the comparison. + + + +attr + +Attribute type that you want to check the value against. + + + +value + +Value that you want to compare against the attribute values. + + + + +serverctrls + +Pointer to an array of LDAPControl structures +representing LDAP server controls that apply to this operation. If you do +not want to pass any server controls, specify NULL for +this argument. + + + +clientctrls + +Pointer to an array of LDAPControl structures +representing LDAP client controls that apply to this operation. If you do +not want to pass any client controls, specify NULL for +this argument. + + + +msgidp + +Pointer to an integer that will be set to the message ID of the LDAP +operation. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the request. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_NOT_SUPPORTED if controls are +included in your request (for example, as a session preference) and your LDAP +client does not specify that it is using the LDAP v3. Make sure that you set +the version of your LDAP client to version 3 before calling this function. + + +To check the result of this operation, call +ldap_result and ldap_parse_result. + + +Returns +For a list of the possible result codes for an LDAP compare operation, +see ldap_compare_ext_s. +Description +The ldap_compare_ext function compares the value +of an attribute in an entry against a specified value. Because ldap_compare_ext + is an asynchronous function, it does not directly return results. +If you want the results to be returned directly by the function, call the +synchronous function ldap_compare_ext_s. + +See Also +ldap_compare_ext_s, ldap_result, ldap_parse_result + +
+<function>ldap_compare_ext_s</function> +The ldap_compare_ext_s function synchronously determines +if an attribute of an entry contains a specified value. +Syntax +#include <ldap.h> + int ldap_compare_ext_s( LDAP *ld, const char *dn, + const char *attr, struct berval *bvalue, + LDAPControl **serverctrls, LDAPControl **clientctrls ); + +Parameters +<function>ldap_compare_ext_s</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the entry used in the comparison. + + + +attr + +Attribute type that you want to check the value against. + + + +value + +Value that you want to compare against the attribute values. + + + + +serverctrls + +Pointer to an array of LDAPControl structures +representing LDAP server controls that apply to this operation. If you do +not want to pass any server controls, specify NULL for +this argument. + + + +clientctrls + +Pointer to an array of LDAPControl structures +representing LDAP client controls that apply to this operation. If you do +not want to pass any client controls, specify NULL for +this argument. + + + +
+
+Returns +One of the following values: + +LDAP_COMPARE_TRUE if the entry contains +the attribute value. +LDAP_COMPARE_FALSE if the entry does +not contain the attribute value. +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the request. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_LOCAL_ERROR if an error occurred +when receiving the results from the server. +LDAP_DECODING_ERROR if an error occurred +when decoding the BER-encoded results from the server. +LDAP_NOT_SUPPORTED if controls are +included in your request (for example, as a session preference) and your LDAP +client does not specify that it is using the LDAP v3. Make sure that you set +the version of your LDAP client to version 3 before calling this function. + + +&cnDirectoryServer; and other LDAP server products may send result +codes in addition to those described. For example, the server may have loaded +a plug-in that returns custom result codes. Check your LDAP server documentation +for other result codes. + +Description +The ldap_compare_ext_s function compares the value +of an attribute in an entry against a specified value. ldap_compare_ext_s + is a synchronous function, which directly returns the results +of the operation. If you want to perform other operations while waiting for +the results of this operation, call the asynchronous function ldap_compare_ext. +See Also +ldap_compare_ext +
+<function>ldap_compare_s</function> +The ldap_compare_s function synchronously determines +if an attribute of an entry contains a specified value. +This is an older function that is included in the SDK for backward-compatibility. +If you are writing a new LDAP client, use ldap_compare_ext_s + instead. +Syntax +#include <ldap.h> + int ldap_compare_s( LDAP *ld, const char *dn, + const char *attr, const char *value ); + +Parameters +<function>ldap_compare_s</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the entry used in the comparison. + + + +attr + +Attribute type that you want to check the value against. + + + +value + +Value that you want to compare against the attribute values. + + + + +
+
+Returns +For a list of the possible result codes for an LDAP compare operation, +see ldap_compare_ext_s. +Description +Please use the newer version of this function, ldap_compare_ext_s + . +Example +Example 21–7 checks +to see if Barbara Jensen has the email address bjensen@example.com. + +Using <function>ldap_compare_s</function> +#include <stdio.h> +#include <ldap.h> +LDAP *ld; +char *dn = "uid=bjensen,ou=People,dc=example, dc=com"; +int has_value; +... +has_value = ldap_compare_s( ld, dn, "mail", "bjensen@example.com" ); +switch ( has_value ) { + case LDAP_COMPARE_TRUE: + printf( "The mail attribute contains bjensen@example.com.\n"); + break; + case LDAP_COMPARE_FALSE: + printf( "The mail attribute does not contain bjensen@example.com.\n"); + break; + default: + ldap_perror( ld, "ldap_compare_s" ); + return( 1 ); +} +... + + +See Also +ldap_compare_ext_s +
+<function>ldap_control_free</function> +The ldap_control_free function frees an LDAPControl structure from memory. +Syntax +#include <ldap.h> +void ldap_control_free( LDAPControl *ctrl ); + +Parameters +<function>ldap_control_free</function> Function +Parameter + + + + +Parameter + +Description + + + + + +ctrl + +Pointer to an LDAPControl structure +that you want to free from memory. + + + +
+
+Description +The ldap_control_free function frees an LDAPControl structure from memory. You should call +this function to free controls that you create; for example, if you call the ldap_create_sort_control function. +See Also +ldap_controls_free +
+<function>ldap_controls_free</function> +The ldap_controls_free function frees an array +of LDAPControl structures from memory. +Syntax +#include <ldap.h> +void ldap_controls_free( LDAPControl **ctrls ); + +Parameters +<function>ldap_controls_free</function> Function +Parameter + + + + +Parameter + +Description + + + + + +ctrls + +Pointer to an array of LDAPControl structures +that you want to free from memory. + + + +
+
+Description +The ldap_controls_free function frees an array +of LDAPControl structures from memory. You +should call this function to free arrays of controls that you create or any +arrays returned by ldap_parse_result. + +See Also +ldap_control_free, ldap_parse_result +
+<function>ldap_count_entries</function> +The ldap_count_entries function returns the number +of LDAPMessage structures representing directory +entries in a chain of search results. +Syntax +#include <ldap.h> + int ldap_count_entries( LDAP *ld, LDAPMessage *result ); + +Parameters +<function>ldap_count_entries</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +result + +Chain of search results, represented by pointer to an LDAPMessage structure. + + + +
+
+Returns +One of the following values: + +If successful, the number of LDAPMessage + structures of the type LDAP_RES_SEARCH_ENTRY in +a chain of search results. If there are no structures of this type, returns +0. +-1 if ld is not a valid +connection handle. + + +Description +The ldap_count_entries function returns the number +of LDAPMessage structures representing directory +entries in a chain of search results. These messages have the type LDAP_RES_SEARCH_ENTRY + . +If you pass in a pointer to an LDAPMessage structure +in the middle of the chain of results, the function counts only the entries +between that structure and the last structure in the chain. In this type of +situation, the function does not return the count of all entries in the chain. + + +Example +See the examples under ldap_search_ext and ldap_search_ext_s. +See Also +ldap_result, ldap_search_ext + , ldap_search_ext_s, ldap_first_entry, ldap_next_entry +, ldap_first_entry, ldap_next_message +
+<function>ldap_count_messages</function> +The ldap_count_messages function returns the number +of LDAPMessage structures in a chain of search +results. +Syntax +#include <ldap.h> + int ldap_count_messages( LDAP *ld, LDAPMessage *res ); + +Parameters +<function>ldap_count_messages</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +result + +Chain of search results, represented by pointer to an LDAPMessage structure. + + + +
+
+Returns +One of the following values: + +The number of LDAPMessage structures +in a chain of search results, if successful. If there are no structures, returns + 0. +-1 if ld is not a valid +connection handle. + + +Description +The ldap_count_messages function returns the number +of LDAPMessage structures in a chain of search +results. The count is the number of search entries plus the number of search +references. +If you pass in a pointer to an LDAPMessage structure +in the middle of the chain of results, the function counts only between that +structure and the last structure in the chain. In this type of situation, +the function does not return the count of all structures in the chain. + + +Example +See the examples under ldap_search_ext and ldap_search_ext_s. +See Also +ldap_result, ldap_search_ext + , ldap_search_ext_s, ldap_first_message, ldap_next_message +, ldap_first_entry, ldap_next_entry , ldap_first_reference +, ldap_next_reference +
+<function>ldap_count_references</function> +The ldap_count_references function returns the +number of LDAPMessage structures representing +search references in a chain of search results. +Syntax +#include <ldap.h> + int ldap_count_references( LDAP *ld, LDAPMessage *res ); + +Parameters +<function>ldap_count_references</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +result + +Chain of search results, represented by pointer to an LDAPMessage structure. + + + +
+
+Returns +One of the following values: + +The number of LDAPMessage structures +of the type LDAP_RES_SEARCH_REFERENCE in a chain of search +results, if successful. (If there are no structures of this type, returns +0.) +-1 if ld is not a valid +connection handle. + + +Description +The ldap_count_references function returns the +number of LDAPMessage structures representing +search references in a chain of search results. These messages have the type +LDAP_RES_SEARCH_REFERENCE, continuation references as specified +in LDAPv3 that are stored as referral entries. Like a referral, each continuation +reference itself may contain a number of URLs assumed to be equivalent, and +the client should use one of those URLs. +If you pass in a pointer to an LDAPMessage structure +in the middle of the chain of results, the function counts only the references +between that structure and the last structure in the chain. In this type of +situation, the function does not return the count of all references in the +chain. + +Example +See the examples under ldap_search_ext and ldap_search_ext_s. +See Also +ldap_result, ldap_search_ext + , ldap_search_ext_s, ldap_first_reference, ldap_next_reference + +
+<function>ldap_count_values</function> +The ldap_count_values function returns the number +of values in an array of strings. +Use the ldap_count_values_len function +if the array contains berval structures. + +Syntax +#include <ldap.h> +int ldap_count_values( char **values ); + +Parameters +<function>ldap_count_values</function> Function +Parameter + + + + +Parameter + +Description + + + + + +values + +Array of values. + + + +
+
+Returns +One of the following values: + +The number of values in the array, if successful. + +-1 if unsuccessful. + + +Example +Example 21–8 counts +the number of values assigned to an attribute. +Using <function>ldap_count_values</function> +#include <ldap.h> +... +LDAP *ld; +LDAPMessage *e; +char *a="cn"; +char **vals; +int count; +... + +/* Get the values of the cn attribute */ +vals = ldap_get_values( ld, e, a ); + +/* Count the values of the attribute */ +count = ldap_count_values( vals ); +... + + +See Also +ldap_count_values_len, ldap_get_values +
+<function>ldap_count_values_len</function> +The ldap_count_values_len function returns the +number of values in an array of berval structures. + +Use the ldap_count_values function +if the array contains strings. +Syntax +#include <ldap.h> +int ldap_count_values_len( struct berval **vals ); + +Parameters +<function>ldap_count_values_len</function> Function +Parameter + + + + +Parameter + +Description + + + + + +values + +Array of berval structures. + + + + +
+
+Returns +One of the following values: + +The number of values in the array, if successful. + +-1 if unsuccessful. + + +Example +Example 21–9 +counts the number of values assigned to an attribute. +Using <function>ldap_count_values_len +</function> +#include <ldap.h> +LDAP *ld; +LDAPMessage *e; +char *a="jpegPhoto"; +struct berval **bvals; +int count; +... +/* Get the values of the jpegPhoto attribute */ +bvals = ldap_get_values_len( ld, e, a ); + +/* Count the values of the attribute */ +count = ldap_count_values_len( vals ); +... + + +See Also +ldap_count_values, ldap_get_values_len +
+<function>ldap_create_authzid_control +</function> +The ldap_create_authzid_control function creates +a control that requests the authorization ID for a bind operation. This is +defined in RFC 3829. +In order for the control to work, the LDAP server that you are +connecting to must support the server controls for authorization bind identity +(OID 2.16.840.1.113730.3.4.16 or LDAP_CONTROL_AUTHZID_REQ +, and OID 2.16.840.1.113730.3.4.15 or LDAP_CONTROL_AUTHZID_RES +). +Calling ldap_create_authzid_control creates an +LDAP control that you can pass to the ldap_simple_bind function +to retrieve the authorization ID in the response. You call ldap_parse_authzid_control function +on the controls returned with an entry to retrieve a char * containing +the authorization ID. +When you are done with the search, you should free the control by calling +the ldap_control_free function. +Syntax +#include <ldap.h> +LDAP_API(int) LDAP_CALL ldap_create_authzid_control( LDAP *ld, + const char ctl_iscritical, LDAPControl **ctrlp ); + +Parameters +<function>ldap_create_authzid_control</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +ctl_iscritical + +Specifies whether the control is critical to the operation. + +If non-zero, the control is critical to the operation. If +the server does not support it, the server returns an LDAP_UNAVAILABLE_CRITICAL_EXTENSION + error. +If 0, the control is not critical to the +operation. Even if the server does not support the control, the operation +is still attempted and the control is ignored. + + + + + +ctrlp + +Pointer to an LDAPControl structure +created by this function. When you are done using this control, you should +free it by calling ldap_control_free. + + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the control. + + +See Also +ldap_parse_authzid_control + +
+<function>ldap_create_filter</function> +The ldap_create_filter routine constructs an LDAP +search filter. +Syntax +#include <ldap.h> +int ldap_create_filter( char *buf, unsigned long buflen, + char *pattern, char *prefix, char *suffix, char *attr, + char *value, char **valwords ); + +Parameters +<function>ldap_create_filter</function> Function +Parameters + + + + +Parameter + +Description + + + + + +buf + +Buffer to contain the constructed filter. + + + +buflen + +Size of the buffer. + + + +pattern + +Pattern for the filter. + + + +prefix + +Prefix to prepend to the filter. (NULL if not used.) + + + + +suffix + +Suffix to append to the filter. (NULL if not used.) + + + + +attr + +Replaces %a in the pattern. + + + +value + +Replaces %v in the pattern. + + + +valwords + +Replaces %vM through %vN in the +pattern. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_SIZELIMIT_EXCEEDED if the created +filter exceeds the size of the buffer. +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. + + +Example +Example 21–10 builds +the filter (mail=bjensen@example.com). +Creating a Filter with <function> +ldap_create_filter</function> +char buf[LDAP_FILT_MAXSIZ]; +char *pattern = "(%a=%v)"; +char *attr = "mail"; +char *value = "bjensen@example.com"; +... +ldap_create_filter( buf, LDAP_FILT_MAXSIZ, pattern, NULL, + NULL, attr, value, NULL ); +... + + +See Also +ldap_init_getfilter, ldap_init_getfilter_buf, ldap_getfirstfilter + , ldap_getnextfilter, ldap_set_filter_additions +
+<function>ldap_create_geteffectiveRights_control</function> +The ldap_create_geteffectiveRights_control function +allows a user having correct privileges to query about the access rights another +identity has on one or more entries in the directory. +Syntax +#include <ldap.h> +LDAP_API(int) LDAP_CALL ldap_create_geteffectiveRights_control( LDAP *ld, + const char *authzid, const char **attrlist, const char ctl_iscritical, + LDAPControl **ctrlp ); + +Parameters +<function>ldap_create_geteffectiveRights_control +</function> Function Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +authzid + +The DN of the identity for which you are checking access rights. + + + + +attrlist + +List of attributes to return, such as aclRights and +aclRightsInfo. + + + +ctl_iscritical + +Specifies whether the control is critical to the operation. + +If non-zero, the control is critical to the operation. If +the server does not support it, the server will return an LDAP_UNAVAILABLE_CRITICAL_EXTENSION + error. +If 0, the control is not critical to the +operation. Even if the server does not support the control, the operation +is still attempted and the control is ignored. + + + + + +ctrlp + +Pointer to an LDAPControl structure +created by this function. When you are done using this control, you should +free it by calling ldap_control_free. + + + + +
+
+
+<function>ldap_create_persistentsearch_control</function> +The ldap_create_persistentsearch_control function +creates a control that allows your client to perform a search of an LDAP v3 +server that continues without termination until your client abandons it. +Persistent search is an optional feature; it may not be supported +on all LDAP servers. In order for the control to work, the server that you +are connecting to must support the server control for persistent searches +(OID 2.16.840.1.113730.3.4.3, or LDAP_CONTROL_PERSISTENTSEARCH, +as defined in the ldap.h header file). +Syntax +#include <ldap.h> + int ldap_create_persistentsearch_control( LDAP *ld, + int changetypes, int changesonly, int return_echg_ctls, + char ctl_iscritical, LDAPControl **ctrlp ); + +Parameters +<function>ldap_create_persistentsearch_control +</function> Function Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +changetypes + +Specifies the types of changes that you want to keep track of. This +field can have one or more of the following values: + +LDAP_CHANGETYPE_ADD specifies that you +want to keep track of entries added to the directory. +LDAP_CHANGETYPE_DELETE specifies that you +want to keep track of entries deleted from the directory. +LDAP_CHANGETYPE_MODIFY specifies that you +want to keep track of entries that are modified. +LDAP_CHANGETYPE_MODDN specifies that you +want to keep track of entries that are renamed. +LDAP_CHANGETYPE_ANY specifies that you +want to keep track of all of the above changes to the directory.You +can OR the values together to specify multiple types. + + + + + + +changesonly + +Specifies whether or not you want skip the initial search and only get +the latest changes as they occur: + +If non-zero, the initial search is skipped and only entries +that have changed after the initial search are returned. +If 0, the results of the initial search +are returned first. + + + + + +return_echg_ctls + +Specifies whether or not entry controls are included with each entry +returned to your client: + +If non-zero, a control is included with each entry. + +If 0, controls are not included with the +entries returned from the server. + + + + + +ctl_iscritical + +Specifies whether the control is critical to the operation. + +If non-zero, the control is critical to the operation. If +the server does not support it, the server will return an LDAP_UNAVAILABLE_CRITICAL_EXTENSION + error. +If 0, the control is not critical to the +operation. Even if the server does not support the control, the operation +is still attempted and the control is ignored. + + + + + +ctrlp + +Pointer to an LDAPControl structure +created by this function. When you are done using this control, you should +free it by calling ldap_control_free. + + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the control. + + +Description +The ldap_create_persistentsearch_control function +allows you to perform persistent searches. A persistent search provides +the means to track changes to a set of entries that match the search criteria. +After the initial search is performed, the server keeps track of the search +criteria and sends back information when any entry that matches the criteria +is added, deleted, modified, or renamed. Calling ldap_create_persistentsearch_control + creates an LDAP server control that you can pass to the ldap_search_ext function. +As stated, after you create the control, you can pass it to the LDAP +server during a search operation. If you specify that you want “entry +change notification” controls sent back (that is, if you specify a non-zero +value for the return_echg_ctls parameter), the server +includes controls with each changed entry it sends back. To retrieve the controls +from each entry, call the ldap_get_entry_controls function. +To get data about the changes made to the entry from the control, call the ldap_parse_entrychange_control function. +When you are done with the search, you can cancel the persistent search +by calling the ldap_abandon_ext function. +You should also free the control from memory by calling the ldap_control_free function. +See Also +ldap_search_ext, +ldap_abandon_ext, ldap_get_entry_controls, ldap_parse_entrychange_control, ldap_control_free +
+<function>ldap_create_pwdpolicy_control +</function> +The ldap_create_pwdpolicy_control function creates +a control that requests information about the status of a user account. +ldap_create_pwdpolicy_control implements +an extension to the LDAP v3 supported by &cnDirectoryServer;.In +order for the control to work, the LDAP server that you are connecting to +must support the server control for password policy (OID 1.3.6.1.4.1.42.2.27.8.5.1 +, or LDAP_CONTROL_ACCOUNT_USABLE). +Calling ldap_create_pwdpolicy_control creates an +LDAP control that you can pass to the ldap_simple_bind functions +to retrieve password policy information from bind, modify, add, compare, and +potentially extended operation responses including password policy response +controls. You call ldap_parse_pwdpolicy_control + function on the controls returned with an entry to retrieve a LDAPpwdpolicy structure containing information +about the status of the account. +When you are done with the search, you should free the control by calling +the ldap_control_free function. +Syntax +#include <ldap.h> +LDAP_API(int) LDAP_CALL ldap_create_pwdpolicy_control( LDAP *ld, + const char ctl_iscritical, LDAPControl **ctrlp ); + +Parameters +<function>ldap_create_pwdpolicy_control</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +ctl_iscritical + +Specifies whether the control is critical to the operation. + +If non-zero, the control is critical to the operation. If +the server does not support it, the server returns an LDAP_UNAVAILABLE_CRITICAL_EXTENSION + error. +If 0, the control is not critical to the +operation. Even if the server does not support the control, the operation +is still attempted and the control is ignored. + + + + + +ctrlp + +Pointer to an LDAPControl structure +created by this function. When you are done using this control, you should +free it by calling ldap_control_free. + + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the control. + + +See Also +ldap_parse_pwdpolicy_control +, LDAPpwdpolicy +
+<function>ldap_create_proxiedauth_control</function> +The ldap_create_proxiedauth_control function creates +an LDAP v3 control that allows a bound entity to assume the identity of another +directory entry. +ldap_create_proxiedauth_control is +a new version of the ldap_create_proxyauth_control function. +If you are writing a new LDAP client, use ldap_create_proxiedauth_control + . +Syntax +#include <ldap.h> +int ldap_create_proxiedauth_control( LDAP *ld, char *authzid, + LDAPControl **ctrlp); + +Parameters +<function>ldap_create_proxiedauth_control +</function> Function Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +authzid + +The string representing the identity to assume for the access rights, +defined in the format specified by the following Augmented Backus-Naur Form +(ABNF) from RFC 4513: +; Specific predefined authorization (authz) +; id schemes are defined below -- +; new schemes may be defined in the future. + +authzId = dnAuthzId / uAuthzId + +; distinguished-name-based authz id. +dnAuthzId = "dn:" dn +dn = utf8string ; syntax from RFC 4514 + +; unspecified userid, UTF-8 encoded. +uAuthzId = "u:" userid +userid = utf8string ; syntax unspecified + + + + +ctrlp + +Pointer to an LDAPControl structure +created by this function. When you are done using this control, you should +free it by calling ldap_control_free. + + + + +
+
+Description +More information on proxy authorization can be found in the LDAP +Proxied Authorization Control Internet Draft (). +Proxy authorization is an optional feature; it may not be supported +on all LDAP servers. In order for the control to work, the server that you +are connecting to must support the server control for proxy authorization +(OID 2.16.840.1.113730.3.4.18, or LDAP_CONTROL_PROXIEDAUTH, +as defined in the ldap-extension.h header file). + + +
+<function>ldap_create_proxyauth_control</function> +The ldap_create_proxyauth_control function creates +an LDAP v3 control that allows a bound entity to assume the identity of another +directory entry. +This is an older function that is included in the SDK for backward-compatibility. +If you are writing a new LDAP client, use ldap_create_proxiedauth_control + . +Syntax +#include <ldap.h> + int ldap_create_proxyauth_control( LDAP *ld, char *DN, + char ctl_iscritical, LDAPControl **ctrlp); + +Parameters +<function>ldap_create_proxyauth_control</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +DN + +String representing the DN of the entry who's identity the client will +be assuming. + + + +ctl_iscritical + +Specifies whether the control is critical to the operation. + +If non-zero, the control is critical to the operation. If +the server does not support it, the server will return an LDAP_UNAVAILABLE_CRITICAL_EXTENSION + error. +If 0, the control is not critical to the +operation. Even if the server does not support the control, the operation +is still attempted and the control is ignored. + + + + + +ctrlp + +Pointer to an LDAPControl structure +created by this function. When you are done using this control, you should +free it by calling ldap_control_free. + + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the control. +LDAP_UNAVAILABLE_CRITICAL_EXTENSION if +the server does not support proxy authorization and ctl_iscritical is +set to a non-zero value. + + +See Also +ldap_control_free +
+<function>ldap_create_sort_control</function> +The ldap_create_sort_control function creates a +control that specifies the order in which you want search results returned. +This function implements an extension to the LDAP v3. Server-side +sorting is an optional feature; it may not be supported on all LDAP servers. +Call this function when interacting with LDAP servers that support this LDAP +v3 extension. +Syntax +#include <ldap.h> + int ldap_create_sort_control( LDAP *ld, + LDAPsortkey **sortKeyList, const char ctl_iscritical, + LDAPControl **ctrlp ); + +Parameters +<function>ldap_create_sort_control</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +sortKeyList + +Pointer to an array of LDAPsortkey structures +that specify the attribute types or matching rules used for sorting and the +order (ascending or descending) in which to sort the results. + + + +ctl_iscritical + +Specifies whether the control is critical to the operation. + +If non-zero, the control is critical to the operation. If +the server does not support it, the server will return an LDAP_UNAVAILABLE_CRITICAL_EXTENSION + error. +If 0, the control is not critical to the +operation. Even if the server does not support the control, the operation +is still attempted and the control is ignored. + + + + + +ctrlp + +Pointer to an LDAPControl structure +created by this function. When you are done using this control, you should +free it by calling ldap_control_free. + + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the control. + + +Description +The ldap_create_sort_control function allows you +to specify the order in which you want to receive data from the server. Calling +this function creates an LDAP control that you can pass to the ldap_search_ext and ldap_search_ext_s + functions. +In order for the control to work, the LDAP server that you are +connecting to must support the server control for sorting search results (OID +1.2.840.113556.1.4.473, or LDAP_CONTROL_SORTREQUEST, as +defined in the ldap.h header file). +To specify the attributes to use for sorting the results, you can call ldap_create_sort_keylist to create an array of LDAPsortkey structures and pass the array as the + sortKeyList argument. When you are done with the search, +you should free the control and the array of LDAPsortkey + structures by calling the ldap_control_free and + ldap_free_sort_keylist functions. + +See Also +ldap_create_sort_keylist, ldap_search_ext, ldap_search_ext_s +, ldap_control_free +
+<function>ldap_create_sort_keylist</function> +The ldap_create_sort_keylist function creates an +array of LDAPsortkey structures from a string +representation of a set of sort keys. +Syntax +#include <ldap.h> + int ldap_create_sort_keylist(LDAPsortkey ***sortKeyList, + const char *string_rep); + +Parameters +<function>ldap_create_sort_keylist</function> Function +Parameters + + + + +Parameter + +Description + + + + + +sortKeyList + +Pointer to an array of LDAPsortkey structures +that specify the attribute types or matching rules used for sorting and the +order (ascending or descending) in which to sort the results. + + + +string_rep + +String representation of a set of sort keys. The value should specify +the name of the attribute that you want to sort by. To sort in reverse order, +precede the attribute name with a hyphen, -. To use a matching +rule for sorting, append a colon to the attribute name and specify the object +identifier (OID) of a matching rule after the colon. For example: + +cn (sorts by the cn attribute) + +-cn (sorts by the cn attribute +in reverse order) +-cn:1.2.3.4 (sorts by the cn attribute +in reverse order using the matching rule identified by the OID 1.2.3.4) + + + + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_NO_MEMORY if memory cannot be +allocated. +-1 if an error occurred. + + +Description +Calling the ldap_create_sort_keylist function allows +you to create an array of LDAPsortkey structures +from a string representation of a set of sort keys. You can then pass the +array to the ldap_create_sort_control function. +The string representation specified by the string_rep argument +should specify the name of the attribute that you want to sort by and how +the sort will work. When you are done sorting the results, you should free +the array of LDAPsortkey structures by calling +the ldap_free_sort_keylist function. + +See Also +ldap_create_sort_control, ldap_free_sort_keylist +
+<function>ldap_create_userstatus_control +</function> +The ldap_create_userstatus_control function creates +a control that requests information about the status of a user account. +ldap_create_userstatus_control implements +an extension to the LDAP v3 supported by &cnDirectoryServer;.In +order for the control to work, the LDAP server that you are connecting to +must support the server control for account availability (OID 1.3.6.1.4.1.42.2.27.9.5.8 +, or LDAP_CONTROL_ACCOUNT_USABLE). +Calling ldap_create_userstatus_control creates +an LDAP control that you can pass to the ldap_search_ext + and ldap_search_ext_s functions. +You call ldap_parse_userstatus_control + function on the controls returned with an entry to retrieve a LDAPuserstatus structure containing information +about the status of the account. +When you are done with the search, you should free the control by calling +the ldap_control_free function. +Syntax +#include <ldap.h> +LDAP_API(int) LDAP_CALL ldap_create_userstatus_control( LDAP *ld, + const char ctl_iscritical, LDAPControl **ctrlp ); + +Parameters +<function>ldap_create_userstatus_control</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +ctl_iscritical + +Specifies whether the control is critical to the operation. + +If non-zero, the control is critical to the operation. If +the server does not support it, the server returns an LDAP_UNAVAILABLE_CRITICAL_EXTENSION + error. +If 0, the control is not critical to the +operation. Even if the server does not support the control, the operation +is still attempted and the control is ignored. + + + + + +ctrlp + +Pointer to an LDAPControl structure +created by this function. When you are done using this control, you should +free it by calling ldap_control_free. + + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the control. + + +See Also +ldap_parse_userstatus_control +, LDAPuserstatus + +
+<function>ldap_create_virtuallist_control</function> +The ldap_create_virtuallist_control function creates +a control that requests a subset of search results for use in a virtual list +box. +ldap_create_virtuallist_control implements +an extension to the LDAP v3 supported by &cnDirectoryServer;. +Syntax +#include <ldap.h> +int ldap_create_virtuallist_control( LDAP *ld, + LDAPVirtualList *ldvlistp, LDAPControl **ctrlp ); + +Parameters +<function>ldap_create_virtuallist_control +</function> Function Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +ldvlistp + +Pointer to an LDAPVirtualList structure +that specifies the subset of entries that you want retrieved from the server +and the selected entry. + + + +ctrlp + +Pointer to an LDAPControl structure +created by this function. When you are done using this control, you should +free it by calling ldap_control_free. + + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the control. + + +Description +The ldap_create_virtuallist_control function allows +you to retrieve a subset of entries from the server for use in a virtual list +box. To specify the subset of entries that you want to retrieve, create an + LDAPVirtualList structure and pass in a +pointer to this structure as the ldvlistp argument. +In order for the control to work, the LDAP server that you are +connecting to must support the server control for sorting search results (OID +2.16.840.1.113730.3.4.9, or LDAP_CONTROL_VLVREQUEST, as +defined in the ldap.h header file). +Calling ldap_create_virtuallist_control creates +an LDAP control that you can pass to the ldap_search_ext + and ldap_search_ext_s functions. +You also need to pass a server-side sorting control to the search functions. +You can call ldap_create_sort_keylist and ldap_create_sort_control to create a server-side +sorting control. When you are done with the search, you should free the control +by calling the ldap_control_free function. + +See Also +LDAPVirtualList, +ldap_parse_virtuallist_control, ldap_search_ext , ldap_search_ext_s, ldap_control_free + +
+<function>ldap_delete</function> +The ldap_delete function removes an entry from +the directory asynchronously. +This is an older function that is included in the SDK for backward-compatibility. +If you are writing a new LDAP client, use ldap_delete_ext + instead. +Syntax +#include <ldap.h> +int ldap_delete( LDAP *ld, const char *dn ); + +Parameters +<function>ldap_delete</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the entry to remove. + + + +
+
+Returns +Returns the message ID of the ldap_delete operation. +To check the result of this operation, call +ldap_result and ldap_result2error. +See ldap_delete_ext_s for a list of possible +result codes for the LDAP delete operation. + +Description +Please use the newer version of this function, ldap_delete_ext + . +Example +Example 21–11 uses +the asynchronous ldap_delete function to remove the entry +for Barbara Jensen from the directory. +Using <function>ldap_delete</function> +#include <ldap.h> +... +LDAP *ld; +LDAPMessage *result; +int msgid, rc; +struct timeval tv; + +/* Distinguished name of the entry that you want to delete. */ +char *dn = "uid=bjensen,ou=People,dc=example, dc=com"; +... +/* Set up the timeout period to wait for the "modify" operation */ +tv.tv_sec = tv.tv_usec = 0; + +/* Delete the entry */ +if ( ( msgid = ldap_delete( ld, dn ) ) == -1 ) { + ldap_perror( ld, "ldap_delete" ); + return( 1 ); +} +/* Check to see if the operation has completed */ +while ( ( rc = ldap_result( ld, msgid, 0, &tv, &result ) ) == 0 ) { + ... + /* do other work while waiting for the operation to complete */ + ... +} +/* Check the result to see if any errors occurred */ +ldap_result2error( ld, result, 1 ); +ldap_perror( ld, "ldap_delete" ); +... + + +See Also +ldap_delete_ext +
+<function>ldap_delete_ext</function> +The ldap_delete_ext function deletes an entry from +the directory asynchronously. +ldap_delete_ext is a new version of the ldap_delete function. If you are writing a new LDAP +client, you should call ldap_delete_ext. + +Syntax +#include <ldap.h> +int ldap_delete_ext( LDAP *ld, const char *dn, + LDAPControl **serverctrls, LDAPControl **clientctrls, int *msgidp ); + +Parameters +<function>ldap_delete_ext</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the entry to remove. + + + +serverctrls + +Pointer to an array of LDAPControl structures +representing LDAP server controls that apply to this operation. If you do +not want to pass any server controls, specify NULL for +this argument. + + + +clientctrls + +Pointer to an array of LDAPControl structures +representing LDAP client controls that apply to this operation. If you do +not want to pass any client controls, specify NULL for +this argument. + + + +msgidp + +Pointer to an integer that will be set to the message ID of the LDAP +operation. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the control. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_NOT_SUPPORTED if controls are +included in your request (for example, as a session preference) and your LDAP +client does not specify that it is using the LDAP v3. Make sure that you set +the version of your LDAP client to version 3 before calling this function. + + +To check the result of this operation, call +ldap_result and ldap_result2error. +See ldap_delete_ext_s for a list of possible +result codes for the LDAP delete operation. + +Description +The ldap_delete_ext function deletes an entry from +the directory, using the dn argument to specify the entry +that you want to delete. ldap_delete_ext is an asynchronous +function; it does not directly return results. If you want the results to +be returned directly by the function, call the synchronous function ldap_delete_ext_s . +See Also +ldap_delete_ext_s, ldap_result, ldap_parse_result + +
+<function>ldap_delete_ext_s</function> +The ldap_delete_ext_s function deletes an entry +from the directory synchronously. +ldap_delete_ext_s is a new version of the ldap_delete_s function. If you are writing a new +LDAP client, you should call ldap_delete_ext_s. + +Syntax +#include <ldap.h> +int ldap_delete_ext_s( LDAP *ld, const char *dn, + LDAPControl **serverctrls, LDAPControl **clientctrls ); + +Parameters +<function>ldap_delete_ext_s</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the entry to remove. + + + +serverctrls + +Pointer to an array of LDAPControl structures +representing LDAP server controls that apply to this operation. If you do +not want to pass any server controls, specify NULL for +this argument. + + + +clientctrls + +Pointer to an array of LDAPControl structures +representing LDAP client controls that apply to this operation. If you do +not want to pass any client controls, specify NULL for +this argument. + + + +
+
+Returns +One of the following values: +Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the control. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_NOT_SUPPORTED if controls are +included in your request (for example, as a session preference) and your LDAP +client does not specify that it is using the LDAP v3. Make sure that you set +the version of your LDAP client to version 3 before calling this function. + +LDAP_LOCAL_ERROR if an error occurred +when receiving the results from the server. +LDAP_DECODING_ERROR if an error occurred +when decoding the BER-encoded results from the server. + +&cnDirectoryServer; and other LDAP server products may send result +codes in addition to those described. For example, the server may have loaded +a plug-in that returns custom result codes. Check your LDAP server documentation +for other result codes. + +Description +The ldap_delete_ext_s function deletes an entry +from the directory, using the dn argument to specify the +entry that you want to delete. ldap_delete_ext_s is a +synchronous function, which directly returns the results of the operation. +If you want to perform other operations while waiting for the results of this +operation, call the asynchronous function ldap_delete_ext + instead. +See Also +ldap_delete_ext +
+<function>ldap_delete_s</function> +The ldap_delete_s deletes an entry from the directory +synchronously. +This is an older function that is included in the SDK for backward-compatibility. +If you are writing a new LDAP client, use ldap_delete_ext_s + instead. +Syntax +#include <ldap.h> + int ldap_delete_s(LDAP *ld, const char *dn); + +Parameters +<function>ldap_delete_s</function> Function +Parameters + + + + +Parameters + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the entry to remove. + + + +
+
+Returns +For a list of possible result codes for an LDAP delete operation, see +the ldap_delete_ext_s function. +Description +Please use the newer version of this function, ldap_delete_ext_s + . +Example +Example 21–12 uses +the synchronous ldap_delete_s function to delete the +entry for Barbara Jensen from the directory. +Using <function>ldap_delete_s</function> +#include <ldap.h> +LDAP *ld; + +/* Distinguished name of the entry that you want to delete. */ +char *dn = "uid=bjensen,ou=People,dc=example, dc=com"; +... +/* Delete the entry */ +if ( ldap_delete_s( ld, dn ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_delete_s" ); + return( 1 ); +} +... + + +See Also +ldap_delete_ext_s +
+<function>ldap_dn2ufn</function> +The ldap_dn2ufn function converts a DN into a more +user-friendly form by stripping off the cryptic type names. +Syntax +#include <ldap.h> + char * ldap_dn2ufn( const char *dn ); + +Parameters +<function>ldap_dn2ufn</function> Function +Parameter + + + + +Parameter + +Description + + + + + +dn + +The DN that you want converted. + + + +
+
+Returns +One of the following values: + +If successful, returns the DN in its friendlier form. + +If unsuccessful, returns NULL. + + + +Description +For more information on user friendly naming (UFN), see RFC 1781, + Using the OSI Directory to Achieve User Friendly Naming (). + +
+<function>ldap_entry2html</function> +The ldap_entry2html function writes the HTML representation +of an LDAP entry. +Syntax +#include <disptmpl.h> + int ldap_entry2html( LDAP *ld, char *buf, LDAPMessage *entry, + struct ldap_disptmpl *tmpl, char **defattrs, char ***defvals, + writeptype writeproc, void *writeparm, char *eol, int rdncount, + unsigned long opts, char *urlprefix, char *base ); + +Parameters +<function>ldap_entry2html</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +buf + +A pointer to a buffer of size LDAP_DTMPL_BUFSIZ or +larger. If NULL, a buffer is allocated and freed internally. + + + + +entry + +Specifies the attribute values to be represented. + + + +tmpl + +Pointer to the display template to be used, usually obtained by calling ldap_oc2template. + + + +defattrs + +A NULL terminated array of LDAP attribute names for +which you wish to provide default values. It is only used if the entry contains +no values for the attribute. + + + +defvals + +An array of NULL terminated arrays of default values +corresponding to the attributes. + + + +writeproc + +Your writeproc function should be declared as: +int writeproc( writeparm, p, len ) +void *writeparm; +char *p; +int len; +where p is a pointer to text to be written and +len is the length of the text. p is guaranteed +to be zero terminated. + + + +writeparm + +A pointer to a structure that will be passed as the first parameter +of the writeproc procedure. Typically, this is used to +pass the file descriptor of the file to write to. + + + +eol + +Lines of text are terminated with this string. + + + +rdncount + +Limits the number of components that are displayed for DN attributes. + + + + +opts + +Specifies output options. The allowed values are: + +zero (default output) +LDAP_DISP_OPT_AUTOLABELWIDTH which causes +the width for labels to be determined based on the longest label in tmpl +. +LDAP_DISP_OPT_HTMLBODYONLY which instructs +the library not to include <HTML>, <HEAD>, + <TITLE>, and <BODY> tags. In +other words, an HTML fragment is generated, and the caller is responsible +for prepending and appending the appropriate HTML tags to construct a correct +HTML document. + + + + + +urlprefix + +Starting text to use when constructing an LDAP URL. The default is +the string ldap://. + + + +base + +The base with which to begin when executing search actions. If NULL + , search action template items are ignored. + + + +
+
+Returns + +LDAP_SUCCESS if successful. + +An LDAP error code on error. + + +Description +ldap_entry2html produces an HTML representation +of an entry. It behaves exactly like ldap_entry2text except +for the output and the addition of two parameters. +See Also +ldap_entry2text, +ldap_oc2template +
+<function>ldap_entry2html_search</function> +The ldap_entry2html_search function determines +the appropriate display template to use by calling ldap_oc2template +. +Syntax +#include <disptmpl.h> + int ldap_entry2html_search( LDAP *ld, char *dn, char *base, + LDAPMessage *entry, struct ldap_disptmpl *tmpllist, char **defattrs, + char ***defvals, writeptype writeproc, void *writeparm, char *eol, + int rdncount, unsigned long opts, char *urlprefix ); + +Parameters +<function>ldap_entry2html_search</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the entry to write as HTML. + + + +base + +The base with which to begin when executing search actions. If NULL + , search action template items are ignored. + + + +entry + +Specifies the attribute values to be represented. + + + +tmpllist + +Pointer to the entire list of templates available, usually obtained +by calling ldap_init_templates or ldap_init_templates_buf. If NULL, +will attempt to read a load templates from the default template configuration +file. + + + +defattrs + +A NULL terminated array of LDAP attribute names for +which you wish to provide default values. It is only used if the entry contains +no values for the attribute. + + + +defvals + +An array of NULL terminated arrays of default values +corresponding to the attributes. + + + +writeproc + +writeproc function should be declared as: +int writeproc( writeparm, p, len ) +void *writeparm; +char *p; +int len; +where p is a pointer to text to be written and +len is the length of the text. p is guaranteed +to be zero terminated. + + + +writeparm + +A pointer to a structure that will be passed as the first parameter +of the writeproc procedure. Typically, this is used to +pass the file descriptor of the file to write to. + + + +eol + +Lines of text are terminated with this string. + + + +rdncount + +Limits the number of components that are displayed for DN attributes. + + + + +opts + +Specifies output options. The allowed values are: + +zero (default output) +LDAP_DISP_OPT_AUTOLABELWIDTH which causes +the width for labels to be determined based on the longest label in tmpl +. +LDAP_DISP_OPT_HTMLBODYONLY which instructs +the library not to include <HTML>, <HEAD>, + <TITLE>, and <BODY> tags. In +other words, an HTML fragment is generated, and the caller is responsible +for prepending and appending the appropriate HTML tags to construct a correct +HTML document. + + + + + +urlprefix + +Starting text to use when constructing an LDAP URL. The default +is the string ldap:// + + + +
+
+Returns + +LDAP_SUCCESS if successful. + +An LDAP error code on error. + + +Description +ldap_entry2html_search will call ldap_search_s to retrieve any attribute values to +be displayed. It behaves exactly like ldap_entry2text_search +, except the urlprefix parameter is required and +HTML is the output. +See Also +ldap_search_s, ldap_entry2text_search +, ldap_init_templates, ldap_init_templates_buf, ldap_entry2text + +
+<function>ldap_entry2text</function> +The ldap_entry2text function writes the text representation +of an LDAP entry. +Syntax +#include <disptmpl.h> + int ldap_entry2text( LDAP *ld, char *buf, LDAPMessage *entry, + struct ldap_disptmpl *tmpl, char **defattrs, char ***defvals, + writeptype writeproc, void *writeparm, char *eol, int rdncount, + unsigned long opts ); + +Parameters +<function>ldap_entry2text</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +buf + +A pointer to a buffer of size LDAP_DTMPL_BUFSIZ or +larger. If NULL, a buffer is allocated and freed internally. + + + + +entry + +Specifies the attribute values to be represented. + + + +tmpl + +Pointer to the display template to be used, usually obtained by calling ldap_oc2template. + + + +defattrs + +A NULL terminated array of LDAP attribute names for +which you wish to provide default values. It is only used if the entry contains +no values for the attribute. + + + +defvals + +An array of NULL terminated arrays of default values +corresponding to the attributes. + + + +writeproc + +writeproc function should be declared as: +int writeproc( writeparm, p, len ) +void *writeparm; +char *p; +int len; +where p is a pointer to text to be written and +len is the length of the text. p is guaranteed +to be zero terminated. + + + +writeparm + +A pointer to a structure that will be passed as the first parameter +of the writeproc procedure. Typically, this is used to +pass the file descriptor of the file to write to. + + + +eol + +Lines of text are terminated with this string. + + + +rdncount + +Limits the number of components that are displayed for DN attributes. + + + + +opts + +Specifies output options. The allowed values are: + +zero (default output) +LDAP_DISP_OPT_AUTOLABELWIDTH which causes +the width for labels to be determined based on the longest label in tmpl +. +LDAP_DISP_OPT_HTMLBODYONLY which instructs +the library not to include <HTML>, <HEAD>, + <TITLE>, and <BODY> tags. In +other words, an HTML fragment is generated, and the caller is responsible +for prepending and appending the appropriate HTML tags to construct a correct +HTML document. + + + + + +
+
+Returns + +LDAP_SUCCESS if successful. + +An LDAP error code on error. + + +Description +ldap_entry2text produces a text representation +of an entry and writes the text by calling the writeproc function. +All of the attribute values to be displayed must be present in entry as no +interaction with the LDAP server will be performed. +See Also +ldap_entry2html, +ldap_oc2template +
+<function>ldap_entry2text_search</function> +The ldap_entry2text_search function determines +the appropriate display template to use by calling ldap_oc2template +. +Syntax +#include <disptmpl.h> + int ldap_entry2text_search( LDAP *ld, char *dn, char *base, + LDAPMessage *entry, struct ldap_disptmpl *tmpllist, char **defattrs, + char ***defvals, writeptype writeproc, void *writeparm, + char *eol, int rdncount, unsigned long opts ); + +Parameters +<function>ldap_entry2text_search</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the entry to write. + + + +base + +If NULL, the search action template items are ignored. +If not NULL, it is the search base to use when executing +search actions. + + + +entry + +If entry is not NULL, it should contain the objectClass + attribute values for the entry to be displayed. If NULL, +dn can not be NULL, and ldap_entry2text_search + will retrieve the objectClass values itself by +calling ldap_search_s. + + + +tmpllist + +Pointer to the entire list of templates available, usually obtained +by calling ldap_init_templates or ldap_init_templates_buf. If NULL, +will attempt to read a load templates from the default template configuration +file. + + + +defattrs + +A NULL terminated array of LDAP attribute names for +which you wish to provide default values. It is only used if the entry contains +no values for the attribute. + + + +defvals + +An array of NULL terminated arrays of default values +corresponding to the attributes. + + + +writeproc + +writeproc function should be declared as: +int writeproc( writeparm, p, len ) +void *writeparm; +char *p; +int len; +where p is a pointer to text to be written and +len is the length of the text. p is guaranteed +to be zero terminated. + + + +writeparm + +A pointer to a structure that will be passed as the first parameter +of the writeproc procedure. Typically, this is used to +pass the file descriptor of the file to write to. + + + +eol + +Lines of text are terminated with this string. + + + +rdncount + +Limits the number of components that are displayed for DN attributes. + + + + +opts + +Specifies output options. The allowed values are: + +zero (default output) +LDAP_DISP_OPT_AUTOLABELWIDTH which causes +the width for labels to be determined based on the longest label in tmpl +. +LDAP_DISP_OPT_HTMLBODYONLY which instructs +the library not to include <HTML>, <HEAD>, + <TITLE>, and <BODY> tags. In +other words, an HTML fragment is generated, and the caller is responsible +for prepending and appending the appropriate HTML tags to construct a correct +HTML document. + + + + + +
+
+Returns + +LDAP_SUCCESS if successful. + +An LDAP error code on error. + + +Description +ldap_entry2text_search will call ldap_search_s to retrieve any attribute values to +be displayed. +See Also +ldap_entry2html_search, ldap_oc2template, ldap_search_s +, ldap_init_templates, ldap_init_templates_buf +
+<function>ldap_err2string</function> +The ldap_err2string function returns the corresponding +error message for an error code. +Syntax +#include <ldap.h> + char * ldap_err2string( int err ); + +Parameters +<function>ldap_err2string</function> Function +Parameter + + + + +Parameter + +Description + + + + + +err + +Error code that you want interpreted into an error message. + + + +
+
+Returns +One of the following values: + +If successful, returns the corresponding error message for +the error code. +If unsuccessful (for example, if the error code is not a valid +LDAP API error code), returns Unknown error. + + + +Example +Example 21–13 sets +the variable err_msg to the error message corresponding +to the error code returned by the ldap_simple_bind_s function. + +Using <function>ldap_err2string</function> +#include <ldap.h> +... +LDAP *ld; +char *dn = "uid=bjensen,ou=People,dc=example, dc=com"; +char *pw = "hifalutin"; +char *err_msg; +... +err_msg = ldap_err2string( ldap_simple_bind_s( ld, dn, pw ) ); +... + + +See Also +ldap_get_lderrno, ldap_perror, ldap_result2error +, ldap_set_lderrno, ldapssl_err2string +
+<function>ldap_explode_dn</function> +The ldap_explode_dn function converts a DN into +its component parts. +Syntax +#include <ldap.h> + char ** ldap_explode_dn( const char *dn, int notypes ); + +Parameters +<function>ldap_explode_dn</function> Function +Parameters + + + + +Parameter + +Description + + + + + +dn + +DN that you want separated into components. + + + +notypes + +Specifies whether or not type names in the DN are returned. This parameter +can have the following possible values: + +0 specifies that type names are returned. + +A non-zero value specifies that type names are not returned. + + + + + + +
+
+Returns +One of the following values: + +If successful, returns a NULL terminated +array containing the components of the DN. +If unsuccessful, returns NULL. + + + +Example +The following function call: +ldap_explode_dn( "uid=bjensen,ou=People,dc=example,dc=com", 0 ); +returns this array: +{ "uid=bjensen", "ou=People", "dc=example,dc=com", NULL } +If you change the notypes parameter from 0 to + 1: +ldap_explode_dn( "uid=bjensen,ou=People,dc=example,dc=com", 1 ); +The component names are not returned in the array: +{ "bjensen", "People", "example.com", NULL } + +See Also +ldap_explode_rdn, ldap_get_dn +
+<function>ldap_explode_dns</function> +This function is to be deprecated and should not be used. It is +included in ldap-to-be-deprecated.h for backward-compatibility. + +The ldap_explode_dns function takes a DNS-style +DN, breaks it up into its component parts, and returns a NULL terminated +array. For example, the DN ldap.example.com will return +{ "ldap", "example", "com", NULL }. The result can be freed by calling + ldap_value_free. +Syntax +#include <ldap-to-be-deprecated.h> + char ** ldap_explode_dns( const char *dn ); + +Parameters +<function>ldap_explode_dns</function> Function +Parameter + + + + +Parameter + +Description + + + + + +dn + +DN that you want separated into components. + + + +
+
+Returns +One of the following values: + +If successful, returns a NULL terminated +array containing the components of the DN. +If unsuccessful, returns NULL. + + + +
+<function>ldap_explode_rdn</function> +The ldap_explode_rdn function converts a relative +distinguished name (RDN) into its component parts. +Syntax +#include <ldap.h> +char ** ldap_explode_rdn( const char *dn, int notypes ); + +Parameters +<function>ldap_explode_rdn</function> Function +Parameters + + + + +Parameter + +Description + + + + + +dn + +RDN that you want separated into components. + + + +notypes + +Specifies whether or not type names in the RDN are returned. This parameter +can have the following possible values: + +0 specifies that type names are returned. + +A non-zero value specifies that type names are not returned. + + + + + + +
+
+Returns +One of the following values: + +If successful, returns a NULL terminated +array containing the components of the RDN. +If unsuccessful, returns NULL. + + + +Example +The following function call: +ldap_explode_rdn( "ou=Sales + cn=Barbara Jensen", 0 ); +returns this array: +{ "ou=Sales", "cn=Barbara Jensen", NULL } + +See Also +ldap_explode_dn, +ldap_get_dn +
+<function>ldap_extended_operation</function> +The ldap_extended_operation function sends a request +to the server to perform an extended operation asynchronously. +Syntax +#include <ldap.h> +int ldap_extended_operation( LDAP *ld, const char *requestoid, + struct berval *requestdata, LDAPControl **serverctrls, + LDAPControl **clientctrls, int *msgidp ); + +Parameters +<function>ldap_extended_operation</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +requestoid + +Object identifier (OID) of the extended operation that you want the +server to perform. After processing an LDAP v3 extended operation, an LDAP +server can return an OID and data in the result. To parse the OID and data +from the result, call the ldap_parse_extended_result function. + + + + +requestdata + +Pointer to a berval structure containing +the data that you want passed to the server to perform the extended operation. +The data in the berval is a buffer of the +BER encoded data type, usually obtained using the ber_flatten + function. + + + +serverctrls + +Pointer to an array of LDAPControl structures +representing LDAP server controls that apply to this operation. If you do +not want to pass any server controls, specify NULL for +this argument. + + + +clientctrls + +Pointer to an array of LDAPControl structures +representing LDAP client controls that apply to this operation. If you do +not want to pass any client controls, specify NULL for +this argument. + + + +msgidp + +Pointer to an integer that will be set to the message ID of the LDAP +operation. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the control. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_NOT_SUPPORTED if controls are +included in your request (for example, as a session preference) and your LDAP +client does not specify that it is using the LDAP v3. Make sure that you set +the version of your LDAP client to version 3 before calling this function. + + +To check the result of this operation, call +ldap_result, ldap_parse_extended_result, +and ldap_get_lderrno. + +Description +The ldap_extended_operation function sends a request +to the server to perform an LDAP v3 extended operation. ldap_extended_operation + is an asynchronous function; it does not directly return results. +If you want the results to be returned directly by the function, call the +synchronous function ldap_extended_operation_s. + +See Also +ldap_extended_operation_s, ldap_result, ldap_parse_extended_result +, ldap_get_lderrno, ber_flatten +
+<function>ldap_extended_operation_s</function> +The ldap_extended_operation_s function sends a +request to the server to perform an extended operation synchronously. +Syntax +#include <ldap.h> + int ldap_extended_operation_s( LDAP *ld, const char *requestoid, + struct berval *requestdata, LDAPControl **serverctrls, + LDAPControl **clientctrls, char **retoidp, struct berval **retdatap ); + +Parameters +<function>ldap_extended_operation_s</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +requestoid + +Object identifier (OID) of the extended operation that you want the +server to perform. + + + +requestdata + +Pointer to a berval structure containing +the data that you want passed to the server to perform the extended operation. +The data in the berval is a buffer of the +BER encoded data type, usually obtained using the ber_flatten + function. + + + +serverctrls + +Pointer to an array of LDAPControl structures +representing LDAP server controls that apply to this operation. If you do +not want to pass any server controls, specify NULL for +this argument. + + + +clientctrls + +Pointer to an array of LDAPControl structures +representing LDAP client controls that apply to this operation. If you do +not want to pass any client controls, specify NULL for +this argument. + + + +retoidp + +Pointer to the OID returned by the server after performing the extended +operation. When done, you can free this by calling the ldap_memfree + function. + + + +retdatap + +Pointer to the pointer for a berval structure +containing the data returned by the server after performing the extended operation. +When done, you can free this by calling the ber_bvfree +function. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the control. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_LOCAL_ERROR if an error occurred +when receiving the results from the server. +LDAP_DECODING_ERROR if an error occurred +when decoding the BER-encoded results from the server. +LDAP_NOT_SUPPORTED if controls are +included in your request (for example, as a session preference) and your LDAP +client does not specify that it is using the LDAP v3. Make sure that you set +the version of your LDAP client to version 3 before calling this function. + + +&cnDirectoryServer; and other LDAP server products may send result +codes in addition to those described. For example, the server may have loaded +a plug-in that returns custom result codes. Check your LDAP server documentation +for other result codes. + +Description +The ldap_extended_operation_s function sends a +request to the server to perform an LDAP v3 extended operation. +The LDAP server must support the extended operation. &cnDirectoryServer; supports +a server plug-in interface that you can use to add support for extended operations. + +ldap_extended_operation_s is a synchronous function, +which directly returns the results of the operation. If you want to perform +other operations while waiting for the results of this operation, call the +asynchronous function ldap_extended_operation. +After processing an LDAP v3 extended operation, an LDAP server can return +an object identifier and data in the results. The retoidp and +retdatap arguments point to these values. +See Also +ldap_extended_operation, ber_flatten +
+<function>ldap_first_attribute</function> +The ldap_first_attribute function returns the name +of the first attribute in an entry returned by the ldap_first_entry + , the ldap_next_entry, or the ldap_result functions. +Syntax +#include <ldap.h> + char * ldap_first_attribute( LDAP *ld, LDAPMessage *entry, + BerElement **ber ); + +Parameters +<function>ldap_first_attribute</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +entry + +Pointer to the LDAPMessage structure +representing the entry returned by the ldap_first_entry or ldap_next_entry function. + + + +ber + +Pointer to a BerElement allocated to +keep track of its current position. Pass this pointer to subsequent calls +to ldap_next_attribute to step through the +entry's attributes. + + + +
+
+Returns +One of the following values: + +If successful, returns the pointer to the name of the first +attribute in an entry. When you are done using this data, you should free +the memory by calling the ldap_memfree function. + +If unsuccessful, returns a NULL and sets +the appropriate error code in the LDAP structure. +To get the error code, call the ldap_get_lderrno function. + + + +Example +Example 21–14 +retrieves each attribute for an entry. +Using <function>ldap_first_attribute +</function> +#include <stdio.h> +#include <ldap.h> +... +LDAP *ld; +LDAPMessage *result, *e; +BerElement *ber; +char *a; +char *my_searchbase = "dc=example,dc=com"; +char *my_filter = "(sn=Jensen)" +... +/* Search the directory */ +if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, + my_filter, NULL, 0, &result ) != + LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search_s" ); + return( 1 ); +} + +/* Get the first matching entry.*/ +e = ldap_first_entry( ld, result ); + +/* Retrieve the attributes the entry */ + for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL; + a = ldap_next_attribute( ld, e, ber ) ) { + ... + /* Code to get and manipulate attribute values */ + ... + } + ldap_memfree( a ); + } + /* Free the BerElement from memory when done */ + if ( ber != NULL ) { + ldap_ber_free( ber, 0 ); + } +... + + +See Also +ldap_first_entry, ldap_next_entry, ldap_next_attribute +, BerElement +
+<function>ldap_first_disptmpl</function> +The ldap_first_disptmpl function returns the first +template in a list. +Syntax +#include <disptmpl.h> + ldap_first_disptmpl( struct ldap_disptmpl *tmpllist ); + +Parameters +<function>ldap_first_disptmpl</function> Function +Parameter + + + + +Parameter + +Description + + + + + +tmpllistp + +Pointer to a list of template data structures. + + + +
+
+Description +ldap_first_disptmpl returns the first template +in the list of templates pointed to by the parameter tmpllistp. +tmpllistp is typically obtained by calling ldap_init_templates + . +See Also +ldap_next_disptmpl, ldap_init_templates, ldap_init_templates_buf + +
+<function>ldap_first_entry</function> +The ldap_first_entry function returns a pointer +to the LDAPMessage structure representing +the first directory entry in a chain of search results. +Syntax +#include <ldap.h> + LDAPMessage * ldap_first_entry( LDAP *ld, LDAPMessage *result ); + +Parameters +<function>ldap_first_entry</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +result + +Chain of search results, which are represented by a pointer to the LDAPMessage structure. + + + +
+
+Returns +One of the following values: + +If successful, returns the pointer to the first LDAPMessage structure of the type LDAP_RES_SEARCH_ENTRY + in the chain of search results. +If no LDAPMessage structures +of the type LDAP_RES_SEARCH_ENTRY are in the chain of the +search results or if the function is unsuccessful, returns a NULLMSG. + + + +Description +The ldap_first_entry function returns a pointer +to the LDAPMessage structure representing +the first directory entry in a chain of search results. Search result entries +are in messages of the type LDAP_RES_SEARCH_ENTRY. You +can use this function in conjunction with the ldap_next_entry + function to iterate through the directory entries in a chain of search +results. These functions skip over any messages in the chain that do not have +the type LDAP_RES_SEARCH_ENTRY. +Do not free the LDAPMessage structure +returned by this function. Because this is a structure within a chain of search +results, freeing this structure will free part of the chain of search results. +When you are done working with the search results, you can free the chain +itself, rather than individual structures within the chain. +See Also +ldap_result, ldap_search_ext + , ldap_search_ext_s, ldap_next_entry +
+<function>ldap_first_message</function> +The ldap_first_message function returns a pointer +to the first LDAPMessage structure in a chain +of search results. +Syntax +#include <ldap.h> + LDAPMessage * ldap_first_message( LDAP *ld, LDAPMessage *res ); + +Parameters +<function>ldap_first_message</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +res + +Chain of search results, represented by a pointer to the LDAPMessage structure. + + + +
+
+Returns +One of the following values: + +If successful, returns the pointer to the first LDAPMessage structure in the chain of search results. + +If no LDAPMessage structures +are in the chain or if the function is unsuccessful, returns a NULLMSG. + + + +Description +The ldap_first_message function returns a pointer +to the first LDAPMessage structure in a chain +of search results. You can use this function in conjunction with the ldap_next_message function to iterate through the +chain of search results. You can also call the ldap_msgtype + function to determine if each message contains a matching entry, +a message of the type LDAP_RES_SEARCH_ENTRY, or a search +reference, a message of the type LDAP_RES_SEARCH_REFERENCE. +Do not free the LDAPMessage structure +returned by this function. Because this is a structure within a chain of search +results, freeing this structure will free part of the chain of search results. +When you are done working with the search results, you can free the chain +itself, rather than individual structures within the chain. +See Also +ldap_result, ldap_search_ext + , ldap_search_ext_s, ldap_next_message, ldap_first_entry +, ldap_first_reference +
+<function>ldap_first_reference</function> +The ldap_first_reference function returns a pointer +to the LDAPMessage structure representing +the first search reference in a chain of search results. +Syntax +#include <ldap.h> + LDAPMessage * ldap_first_reference(LDAP *ld, LDAPMessage *res ); + +Parameters +<function>ldap_first_reference</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +res + +Chain of search results, which are represented by a pointer to the LDAPMessage structure. + + + +
+
+Returns +One of the following values: + +If successful, returns the pointer to the first LDAPMessage structure of the type LDAP_RES_SEARCH_REFERENCE + in the chain of search results. +If no LDAPMessage structures +of the type LDAP_RES_SEARCH_REFERENCE are in the chain +of the search results or if the function is unsuccessful, returns a NULLMSG +. + + +Description +The ldap_first_reference function returns a pointer +to the LDAPMessage structure representing +the first search reference in a chain of search results. Search references +are in messages of the type LDAP_RES_SEARCH_REFERENCE, +continuation references as specified in LDAPv3 that are stored as referral +entries. Like a referral, each continuation reference itself may contain a +number of URLs assumed to be equivalent, and the client should use one of +those URLs. +You can use this function in conjunction with the +ldap_next_reference function to iterate through the search references +in a chain of search results. These functions skip over any messages in the +chain that do not have the type LDAP_RES_SEARCH_REFERENCE. +Do not free the LDAPMessage structure +returned by this function. Because this is a structure within a chain of search +results, freeing this structure will free part of the chain of search results. +When you are done working with the search results, you can free the chain +itself, rather than individual structures within the chain. +See Also +ldap_result, ldap_search_ext + , ldap_search_ext_s, ldap_next_reference, ldap_first_message + +
+<function>ldap_first_searchobj</function> +The ldap_first_searchobj function returns the first +search preference configuration from a data structure defined in the list +solist . +Syntax +#include <ldap.h> + ldap_searchobj * ldap_first_searchobj( struct ldap_searchobj *solist ); + +Parameters +<function>ldap_first_searchobj</function> Function +Parameter + + + + +Parameter + +Description + + + + + +solist + +Pointer to the search preference data structures, typically obtained +by calling ldap_init_searchprefs. + + + + +
+
+Description +ldap_first_searchobj provides access to LDAP search +preference configuration data. LDAP search preference configurations are typically +used by LDAP client programs to specify which attributes a user may search +by, the labels for the attributes, and the LDAP filters and scopes associated +with those searches. +See Also +ldap_init_searchprefs, ldap_init_searchprefs_buf +
+<function>ldap_first_tmplcol</function> +The ldap_first_tmplcol function returns a pointer +to the first item within a template. +Syntax +#include <disptmpl.h> + struct ldap_tmplitem * ldap_first_tmplcol( struct ldap_disptmpl *tmpl, + struct ldap_tmplitem *row ); + +Parameters +<function>ldap_first_tmplcol</function> Function +Parameters + + + + +Parameter + +Description + + + + + +tmpl + +The name of the template to be retrieved. + + + +row + +The row in which the item is to be retrieved from. + + + +
+
+Returns + +If successful, a pointer to an ldap_tmplitem structure. + +A NULL pointer on error. + + +Description +ldap_first_tmplcol returns a pointer to the first +item (in the first column) of the row, defined by row, +within the template defined by tmpl. +See Also +ldap_first_tmplrow, ldap_next_tmplcol +
+<function>ldap_first_tmplrow</function> +The ldap_first_tmplrow function returns a pointer +to the first row of items in a template. +Syntax +#include <disptmpl.h> + struct ldap_tmplitem * ldap_first_tmplrow( struct ldap_disptmpl *tmpl ); + +Parameters +<function>ldap_first_tmplrow</function> Function +Parameter + + + + +Parameter + +Description + + + + + +tmpl + +The name of the template to be retrieved. + + + +
+
+Returns + +If successful, a pointer to an ldap_tmplitem structure. + +A NULL pointer on error. + + +See Also +ldap_next_tmplrow, ldap_first_tmplcol +
+<function>ldap_free_friendlymap</function> +The ldap_free_friendlymap function frees the FriendlyMap structures allocated by the ldap_friendly_name function when no more calls +to it are to be made. +Syntax +#include <ldap.h> + void ldap_free_friendlymap( FriendlyMap *map ); + +Parameters +<function>ldap_free_friendlymap</function> Function +Parameter + + + + +Parameter + +Description + + + + + +map + +Pointer to the FriendlyMap mapping +structure in memory. + + + +
+
+Example +Example 21–15 +frees memory allocated by the ldap_friendly_name +function. +Using <function>ldap_free_friendlymap +</function> +#include <ldap.h> +#include <stdio.h> +... +FriendlyMap map = NULL; +char *map_file = "/u/mozilla/ldapsdk/examples/ldapfriendly"; +char *unfriendly_name = "IS"; +char *friendly_name; +... +/* Read the ldapfriendly file into the map in memory */ +friendly_name = ldap_friendly_name( map_file, unfriendly_name, &map ); +printf( "Friendly Name for %s: %s\n", unfriendly_name, friendly_name ); + +/* Since file is in memory, no need to reference it in subsequent calls */ +friendly_name = ldap_friendly_name( NULL, "VI", &map ); +printf( "Friendly Name for VI: %s\n", friendly_name ); +... +ldap_free_friendlymap( map ); +... + + +See Also +ldap_friendly_name, FriendlyMap +
+<function>ldap_free_searchprefs</function> +The ldap_free_searchprefs function disposes of +the data structures allocated by ldap_init_searchprefs. + +Syntax +#include <ldap.h> + void ldap_free_searchprefs( struct ldap_searchobj *solist ); + +Parameters +<function>ldap_free_searchprefs</function> Function +Parameter + + + + +Parameter + +Description + + + + + +solist + +Pointer to the data structures, typically obtained by calling ldap_init_searchprefs. + + + +
+
+See Also +ldap_init_searchprefs, ldap_init_searchprefs_buf +
+<function>ldap_free_sort_keylist</function> +The ldap_free_sort_keylist function frees the structures +allocated by the ldap_create_sort_keylist function. + +Syntax +#include <ldap.h> + void ldap_free_sort_keylist (LDAPsortkey **sortKeyList); + +Parameters +<function>ldap_free_sort_keylist</function> Function +Parameter + + + + +Parameter + +Description + + + + + +sortKeyList + +Array of LDAPsortkey structures that +you want to free from memory. + + + +
+
+Description +The ldap_free_sort_keylist function frees the array +of LDAPsortkey structures allocated by the + ldap_create_sort_keylist function. When +done sorting results, call this function to free the memory that you have +allocated. This function must be called after the ldap_create_sort_control + function has completed. +See Also +ldap_create_sort_keylist, ldap_create_sort_control +
+<function>ldap_free_templates</function> +The ldap_free_templates function disposes of the +templates allocated by ldap_init_templates. +Syntax +#include <disptmpl.h> + void ldap_free_templates( struct ldap_disptmpl *tmpllist ); + +Parameters +<function>ldap_free_templates</function> Function +Parameter + + + + +Parameter + +Description + + + + + +tmpllistp + +Pointer to a list of template data structures. + + + +
+
+Description +ldap_free_templates releases the templates allocated +by ldap_init_templates. Each template defined +in the file is an ldap_disptmpl structure. +
+<function>ldap_free_urldesc</function> +The ldap_free_urldesc function frees memory allocated +by the ldap_url_parse function. +Syntax +#include <ldap.h> + void ldap_free_urldesc( LDAPURLDesc *ludp ); + +Parameters +<function>ldap_free_urldesc</function> Function +Parameter + + + + +Parameter + +Description + + + + + +ludp + +Pointer to a LDAPURLDesc structure. + + + + +
+
+Example +Example 21–16 parses +an LDAP URL and then frees the LDAPURLDesc structure +from memory after verifying that the LDAP URL is valid. +Using <function>ldap_free_urldesc</function> +#include <stdio.h> +#include <ldap.h> +... +char *my_url = + "ldap://ldap.example.com:1389/dc=example,dc=com?cn,mail,telephoneNumber? + sub?(sn=Jensen)"; +LDAPURLDesc *ludpp; +int res, i; +... +if ( ( res = ldap_url_parse( my_url, &ludpp ) ) != 0 ) { + switch( res ){ + case LDAP_URL_ERR_NOTLDAP: + printf( "URL does not begin with \"ldap://\"\n" ); + break; + case LDAP_URL_ERR_NODN: + printf( "URL does not contain a distinguished name\n" ); + break; + case LDAP_URL_ERR_BADSCOPE: + printf( "URL contains an invalid scope\n" ); + break; + case LDAP_URL_ERR_MEM: + printf( "Not enough memory\n" ); + break; + default: + printf( "Unknown error\n" ); + } + return( 1 ); +} +printf( "URL is a valid LDAP URL\n" ); +ldap_free_urldesc( ludpp ); +... + + +See Also +ldap_url_parse +
+<function>ldap_friendly_name</function> +The ldap_friendly_name function maps a set of standard +identifiers to their user-friendly counterparts. For example, you can represent +the list of two-letter state codes (CA, IA) with their corresponding state +names (California, Iowa), or map country ISO codes to the full country names. +ldapfriendly, located in lib/ldapcsdk/etc +, is a sample file that maps two letter country codes to their full +names. It can be used in context with ldap_friendly_name +. +Syntax +#include <ldap.h> + char * ldap_friendly_name( char *filename, char *uname, + FriendlyMap *map ); + +Parameters +<function>ldap_friendly_name</function> function +parameters + + + + +Parameter + +Description + + + + + +filename + +Name of the file mapping the standard identifiers to the user-friendly +names. + + + +uname + +Standard identifier name for which you want to find the user-friendly +name. + + + +map + +Pointer to the FriendlyMap mapping +in memory. Initialize this pointer to NULL on the first +call, then use it during subsequent calls so that the mapping file does not +need to be read again. + + + +
+
+Returns +One of the following values: + +If successful, returns the user-friendly name for the specified +identifier. +If unsuccessful—for example, if the file cannot be read, +if the file is in a bad format, or if the map parameter is set to NULL—returns +the original identifier (the value passed as the uname parameter). + + + +Description +This function relies on the existence of a text file mapping standard +identifiers to user-friendly names. The names in the file are tab-delimited. +Unfriendly to Friendly Name Mapping File +<unfriendly_name> <friendly_name> +AD Andorra +AE United Arab Emirates +AF Afghanistan +AG Antigua and Barbuda +AI Anguilla + + +Example +Example 21–18 +reads in a map of user-friendly names and prints the name corresponding to +the standard identifier IS. +Using <function>ldap_friendly_name +</function> +#include <ldap.h> +#include <stdio.h> +... +FriendlyMap map = NULL; +char *map_file = "/u/mozilla/ldapsdk/examples/ldapfriendly"; +char *unfriendly_name = "IS"; +char *friendly_name; +... +/* Read the ldapfriendly file into the map in memory */ +friendly_name = ldap_friendly_name( map_file, unfriendly_name, &map ); +printf( "Friendly Name for %s: %s\n", unfriendly_name, friendly_name ); + +/* Since file is in memory, no need to reference it in subsequent calls */ +friendly_name = ldap_friendly_name( NULL, "VI", &map ); +printf( "Friendly Name for VI: %s\n", friendly_name ); +... + + +See Also +ldap_free_friendlymap, FriendlyMap +
+<function>ldap_get_dn</function> +The ldap_get_dn routine returns the DN for an entry +in a chain of search results. +Syntax +#include <ldap.h> + char * ldap_get_dn( LDAP *ld, LDAPMessage *entry ); + +Parameters +<function>ldap_get_dn</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +entry + +Pointer to an entry in a chain of search results, as returned by the ldap_first_entry and ldap_next_entry + functions. + + + +
+
+Returns +One of the following values: + +If successful, returns the DN for the specified entry. + +If unsuccessful, returns a NULL and sets +the appropriate error code in the LDAP structure. To get the error code, call +the ldap_get_lderrno function. + + + +Description +You can get an entry from a chain of search results by calling the ldap_first_entry and ldap_next_entry + functions. +Example +Example 21–19 prints +the DN for each entry found in a search. +Using <function>ldap_get_dn</function> +#include <stdio.h> +#include <ldap.h> +... +LDAP *ld; +LDAPMessage *result, *e; +char *dn; +char *my_searchbase = "dc=example,dc=com"; +char *my_filter = "(sn=Jensen)"; +... +/* Search the directory */ +if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter, + NULL, 0, &result ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search_s" ); + return( 1 ); +} + +/* For each matching entry found, print out the name of the entry.*/ +for ( e = ldap_first_entry( ld, result ); e != NULL; + e = ldap_next_entry( ld, e ) ) { + if ( ( dn = ldap_get_dn( ld, e ) ) != NULL ) { + printf( "dn: %s\n", dn ); + /* Free the memory used for the DN when done */ + ldap_memfree( dn ); + } +} +/* Free the result from memory when done. */ +ldap_msgfree( result ); +... + + +See Also +ldap_first_entry, ldap_next_entry, ldap_get_lderrno + +
+<function>ldap_get_entry_controls</function> +The ldap_get_entry_controls function gets the LDAP +controls included with a directory entry in a set of search results. +Syntax +#include <ldap.h> + int ldap_get_entry_controls( LDAP *ld, LDAPMessage *entry, + LDAPControl ***serverctrlsp ); + +Parameters +<function>ldap_get_entry_controls</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +entry + +Pointer to an LDAPMessage structure +representing an entry in a chain of search results. + + + +serverctrlsp + +Pointer to an array of LDAPControl structures, +which represent the LDAP v3 server controls returned by the server. + + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_DECODING_ERROR if an error occurred +when decoding the BER-encoded results from the server. +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_NO_MEMORY if memory cannot be +allocated. + + +Description +The ldap_get_entry_controls function retrieves +the LDAP v3 controls included in a directory entry in a chain of search results. +The LDAP controls are specified in an array of LDAPControl + structures with each structure representing one LDAP control. Other +controls are returned with results sent from the server. You can call ldap_parse_result to retrieve those controls. + +
+<function>ldap_getfilter_free</function> +The ldap_getfilter_free function frees the memory +used by a filter set. +Syntax +#include <ldap.h> + void ldap_getfilter_free( LDAPFiltDesc *lfdp ); + +Parameters +<function>ldap_getfilter_free</function> Function +Parameter + + + + +Parameter + +Description + + + + + +lfdp + +Pointer to a LDAPFiltDesc structure. + + + + +
+
+Description +Once you call ldap_getfilter_free, the LDAPFiltDesc structure is no longer valid and cannot +be used again. +Example +Example 21–20 frees +the LDAPFiltDesc structure from memory after +all searches are completed. +Using <function>ldap_getfilter_free +</function> +#include <ldap.h> +... +LDAPFiltDesc *lfdp; +char *filter_file = "myfilters.conf"; +... +/* Read the filter configuration file into an LDAPFiltDesc structure */ +lfdp = ldap_init_getfilter( filter_file ); +... +/* Retrieve filters and perform searches */ +... +/* Free the configuration file (the LDAPFiltDesc structure) */ +ldap_getfilter_free( lfdp ); +... + + +See Also +ldap_init_getfilter, ldap_init_getfilter_buf +
+<function>ldap_getfirstfilter</function> +The ldap_getfirstfilter function retrieves the +first filter that is appropriate for a given value. +Syntax +#include <ldap.h> + LDAPFiltInfo * ldap_getfirstfilter( LDAPFiltDesc *lfdp, + char *tagpat, char *value ); + +Parameters +<function>ldap_getfirstfilter</function> Function +Parameters + + + + +Parameter + +Description + + + + + +lfdp + +Pointer to an LDAPFiltDesc structure. + + + + +tagpat + +Regular expression for a tag in the filter configuration. + + + +value + +Value for which to find the first appropriate filter. + + + +
+
+Returns +One of the following values: + +If successful, returns a pointer to an LDAPFiltInfo + structure. +If no more filters can be returned, returns a NULL. + +If unsuccessful, returns a NULL. + + + +Example +Example 21–21 +is based on the getfilt command-line program example provided +with the &DirectorySDKForC;. The program prompts the user to enter search +criteria and, based on the criteria entered, it retrieves filters that match +the criteria. +Using <function>ldap_getfirstfilter +</function> +#include <stdio.h> +#include <ldap.h> +... +LDAP *ld; +LDAPMessage *result, *e; +BerElement *ber; +char *a, *dn; +char **vals; +int i; +LDAPFiltDesc *ldfp; +LDAPFiltInfo *ldfi; +char buf[ 80 ]; /* Contains the search criteria */ +int found; +... +/* Load the filter configuration file into an LDAPFiltDesc structure */ +if ( ( ldfp = ldap_init_getfilter( "myfilters.conf" ) ) == NULL ) { + perror( "Cannot open filter configuration file" ); + return( 1 ); +} + +/* Read a string to search for */ +printf( "Enter a string to search for: " ); +gets( buf ); +if ( strlen( buf ) == 0 ) { + fprintf( stderr, "usage: %s search-string\n", argv[ 0 ]); + return( 1 ); +} + +/* Select a filter to use when searching for the value in buf */ +found = 0; +for ( ldfi = ldap_getfirstfilter( ldfp, "people", buf ); + ldfi != NULL; + ldfi = ldap_getnextfilter( ldfp ) ) { + + /* Use the selected filter to search the directory */ + if ( ldap_search_s( ld, "dc=example,dc=com, ldfi->lfi_scope, + ldfi->lfi_filter, NULL, 0, &result ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search_s" ); + return( 1 ); + } else { + + /* Once a filter gets results back, stop iterating through + the different filters */ + if ( ( found = ldap_count_entries( ld, result ) > 0 ) ) { + break; + } else { + ldap_msgfree( result ); + } + } +} + +if ( found == 0 ) { + printf( "No matching entries found.\n" ); +} else { + printf( "Found %d %s match%s for \"%s\"\n\n", found, + ldfi->lfi_desc, found == 1 ? "" : "es", buf ); +} + +ldap_msgfree( result ); +ldap_getfilter_free( ldfp ); +... + + +See Also +ldap_init_getfilter, ldap_init_getfilter_buf, ldap_getnextfilter + +
+<function>ldap_get_lang_values</function> +This function is deprecated and should not be used. It is included +in ldap-deprecated.h for backward-compatibility. Please +use ldap_get_values. +The ldap_get_lang_values function returns a NULL + terminated array of an attribute’s string values that match +a specified language subtype. +Syntax +#include <ldap.h> +char ** ldap_get_lang_values( LDAP *ld, LDAPMessage *entry, + const char *target, char **type ); + +Parameters +<function>ldap_get_lang_values</function> Function +Parameters + + + + +Parameters + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +entry + +Entry retrieved from the directory. + + + +target + +Attribute type (including an optional language subtype) that you want +to retrieve the values of. + + + +type + +Pointer to a buffer that returns the attribute type retrieved by this +function. + + + +
+
+Returns +One of the following values: + +If successful, returns a NULL terminated +array of the attribute’s values. +If unsuccessful or if no such attribute exists in the entry, +returns a NULL and sets the appropriate error code in the + LDAP structure. To get the error code, call +the ldap_get_lderrno function. + + + +Description +Unlike the ldap_get_values function, +if a language subtype is specified, this function first attempts to find and +return values that match that subtype—for example, cn;lang-en. +If you want to retrieve binary data from an attribute, call the ldap_get_lang_values_len function. +See Also +ldap_first_entry, ldap_first_attribute, ldap_get_lang_values_len + , ldap_get_values, ldap_next_entry, ldap_next_attribute + +
+<function>ldap_get_lang_values_len</function> +This function is deprecated and should not be used. It is included +in ldap-deprecated.h for backward-compatibility. Please +use ldap_get_values_len. +The ldap_get_lang_values_len function returns a + NULL terminated array of pointers to +berval structures, each containing the length and pointer to a binary +value of an attribute for a given entry. +Syntax +#include <ldap-deprecated.h> +struct berval ** ldap_get_lang_values_len( LDAP *ld, + LDAPMessage *entry, const char *target, char **type ); + +Parameters +<function>ldap_get_lang_values_len</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +entry + +Result returned by the ldap_result or ldap_search_s function. + + + +target + +Attribute returned by ldap_first_attribute or ldap_next_attribute, or the attribute as a literal +string, such as jpegPhoto or audio. + + + + +type + +Pointer to a buffer that returns the attribute type retrieved by this +function. + + + +
+
+Returns +One of the following values: + +If successful, returns a NULL terminated +array of pointers to berval structures, which, +in turn, contain pointers to the attribute’s binary values. + +If unsuccessful or if no such attribute exists in the entry, +returns a NULL and sets the appropriate error code in the + LDAP structure. To get the error code, call +the ldap_get_lderrno function. + + + +Description +Use the ldap_get_lang_values routine +if the attribute values are string values. +See Also +ldap_first_attribute, ldap_first_entry, ldap_get_lang_values +, ldap_next_entry, ldap_next_attribute +
+<function>ldap_get_lderrno</function> +The ldap_get_lderrno function gets information +about the last error that occurred for an LDAP operation. +Syntax +#include <ldap.h> +int ldap_get_lderrno( LDAP *ld, char **m, char **s ); + +Parameters +<function>ldap_get_lderrno</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +m + +In the event of an LDAP_NO_SUCH_OBJECT error +return, this parameter contains the portion of the DN that identifies an existing +entry. + + + +s + +The text of the error message. + + + +
+
+Returns +The LDAP error code for the last operation. +Description +ldap_get_lderrno gets information about the last +error that occurred for an LDAP operation. You can also call this function +to get error codes for functions that do not return errors, such as ldap_next_attribute. +Example +Example 21–22 attempts +to add a new user to the directory. If the entry identified by a DN does not +exist, the server returns the portion of the DN that matches an existing entry; +this is the variable matched. +Using <function>ldap_get_lderrno</function> +#include <ldap.h> +LDAP *ld; +char *dn = "uid=bjensen,ou=People,dc=example,dc=com"; +LDAPMod **list_of_attrs; +char *matched; +int rc; +... +if ( ldap_add_s( ld, dn, list_of_attrs ) != LDAP_SUCCESS ) { + rc = ldap_get_lderrno( ld, &matched, NULL ); + return( rc ); +} +... + +In Example 21–22, +if no organizational unit named People exists, the matched +variable is set to dc=example,dc=com . +See Also +ldap_err2string, +ldap_perror, ldap_result2error, ldap_set_lderrno +
+<function>ldap_getnextfilter</function> +The ldap_getnextfilter function retrieves the next +filter that is appropriate for a given value. +Syntax +#include <ldap.h> + LDAPFiltInfo * ldap_getnextfilter( LDAPFiltDesc *lfdp ); + +Parameters +<function>ldap_getnextfilter</function> Function +Parameter + + + + +Parameter + +Description + + + + + +lfdp + +Pointer to an LDAPFiltDesc structure. + + + + +
+
+Returns +One of the following values: + +If successful, returns a pointer to an LDAPFiltInfo + structure. +If no more filters can be returned, returns a NULL. + +If unsuccessful, returns a NULL. + + + +Description +Call this function to get subsequent filters after calling ldap_getfirstfilter. +Example +See Example 21–21. + +See Also +ldap_getfirstfilter +
+<function>ldap_get_option</function> +The function ldap_get_option retrieves session +preferences from an LDAP structure. +Syntax +#include <ldap.h> + int ldap_get_option( LDAP *ld, int option, void *optdata ); + +Parameters +<function>ldap_get_option</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +option + +Option that you want to retrieve. This parameter must be set to one +of the option values. + + + +optdata + +Pointer to the buffer in which the value of the option will be put. + + + + +
+Table 21–110 describes +the options that you can retrieve with ldap_get_option. +Options for the <function> +ldap_get_options</function> Function + + + + +Option + +Description + + + + + +LDAP_OPT_API_FEATURE_INFO + +Retrieves information about the revision of a supported LDAP feature. +This option is READ-ONLY and cannot be set. +The data type for the optdata parameter is (LDAPAPIFeatureInfo +*). + + + +LDAP_OPT_API_INFO + +Retrieves information about the API implementation at execution time +(API version, protocol version, the names of supported API extensions with +their vendor name version, etc.). For details on the structure returned, refer +to the ldap.h header file. This option is READ-ONLY and +cannot be set. +The data type for the optdata parameter is (LDAPAPIInfo +*). + + + +LDAP_OPT_CLIENT_CONTROLS + +Pointer to an array of LDAPControl structures +representing the LDAP v3 client controls you want sent with every request +by default. +The data type for the optdata parameter is (LDAPControl +***). + + + +LDAP_OPT_DESC + +Socket descriptor underlying the main LDAP connection. The LBER_SOCKET + data type depends on the platform that you are using: + +int in UNIX. +SOCKET in Windows.The data +type for the optdata parameter is (LBER_SOCKET +*). + + + + + +LDAP_OPT_DEREF + +Determines how aliases work during a search. optdata can +be one of the following values: + +LDAP_DEREF_NEVER specifies that aliases +are never dereferenced. +LDAP_DEREF_SEARCHING specifies that aliases +are dereferenced when searching under the base object (but not when finding +the base object). +LDAP_DEREF_FINDING specifies that aliases +are dereferenced when finding the base object (but not when searching under +the base object). +LDAP_DEREF_ALWAYS specifies that aliases +are always dereferenced when finding and searching under the base object. +The data type for the optdata parameter is (int +*). + + + + + +LDAP_OPT_DNS_FN_PTRS + +DEPRECATED OPTION: Lets you use alternate +DNS functions for getting the host entry of the LDAP server. +The data type for the optdata parameter is (struct +ldap_dns_fns *). + + + +LDAP_OPT_ERROR_NUMBER + +Retrieves the result code for the most recent LDAP error that occurred +in this session. +The data type for the optdata parameter is (int +*). + + + +LDAP_OPT_ERROR_STRING + +Retrieves the error message returned with the result code for the most +recent LDAP error that occurred in this session. +The data type for the optdata parameter is (char +**). + + + +LDAP_OPT_EXTRA_THREAD_FN_PTRS + +Lets you specify the locking and semaphore functions that you want called +when getting results from the server. +The data type for the optdata parameter is (struct +ldap_extra_thread_fns *). + + + +LDAP_OPT_HOST_NAME + +Sets the host name (or list of hosts) for the primary LDAP server. +The data type for the optdata parameter is (char +**). + + + +LDAP_OPT_IO_FN_PTRS + +DEPRECATED OPTION: Lets you use alternate +communication stacks. +The data type for the optdata parameter is (struct +ldap_io_fns *). + + + +LDAP_OPT_MATCHED_DN + +Gets the matched DN value returned with the most recent LDAP error that +occurred for this session. +The data type for the optdata parameter is (char +**) + + + +LDAP_OPT_MEMALLOC_FN_PTRS + +Gets a pointer to the callback structure which you previously set. +The data type for the optdata parameter is (struct +ldap_memalloc_fnsldap_io_fns *). + + + +LDAP_OPT_PROTOCOL_VERSION + +Version of the protocol supported by your client. You can specify either +LDAP_VERSION2 or LDAP_VERSION3. If no version +is set, the default is LDAP_VERSION2. In order to use LDAP +v3 features, you need to set the protocol version to LDAP_VERSION3. + +The data type for the optdata parameter is (int +*). + + + +LDAP_OPT_REBIND_ARG + +Lets you set the last argument passed to the routine specified by +LDAP_OPT_REBIND_FN. You can also set this option by calling the ldap_set_rebind_proc function. +The data type for the optdata parameter is (void +*). + + + +LDAP_OPT_REBIND_FN + +Lets you set the routine to be called when you need to authenticate +a connection with another LDAP server (for example, during the course of following +a referral). You can also set this option by calling the +ldap_set_rebind_proc function. +The data type for the optdata parameter is (LDAP_REBINDPROC_CALLBACK +*). + + + +LDAP_OPT_RECONNECT + +If the connection to the server is lost, determines whether or not the +same connection handle should be used to reconnect to the server. By default, +this option is off. You handle failover with the following values: + +LDAP_OPT_ON specifies that the same connection +handle can be used to reconnect to the server. +LDAP_OPT_OFF specifies that you want to +create a new connection handle to connect to the server.The data +type for the optdata parameter is (int *). + + + + + + +LDAP_OPT_REFERRALS + +Determines whether or not the client should follow referrals. By default, +the client follows referrals. optdata can be one of the +following values: + +LDAP_OPT_ON specifies that the server should +follow referrals. +LDAP_OPT_OFF specifies that the server +should not follow referrals.The data type for the optdata parameter +is (int *). + + + + + +LDAP_OPT_REFERRAL_HOP_LIMIT + +Maximum number of referrals the client should follow in a sequence. +In other words, the client can only be referred this number of times before +it gives up. By default, the maximum number of referrals that the client can +follow in a sequence is 5 for the initial connection. This limit does not +apply to individual requests that generate multiple referrals in parallel. +The data type for the optdata parameter is (int +*). + + + +LDAP_OPT_RESTART + +Determines whether or not LDAP I/O operations should be restarted automatically +if they are prematurely aborted. optdata can be one of +the following values: + +LDAP_OPT_ON specifies that I/O operations +should be restarted automatically. +LDAP_OPT_OFF specifies that I/O operations +should not be restarted automatically.The data type for the +optdata parameter is (int *). + + + + + +LDAP_OPT_SERVER_CONTROLS + +Pointer to an array of LDAPControl structures +representing the LDAP v3 server controls you want sent with every request +by default. Typically, since controls are specific to the type of request, +you may want to pass the controls using operation-specific functions, such +as ldap_add_ext, instead. +The data type for the optdata parameter is (LDAPControl +***). + + + +LDAP_OPT_SIZELIMIT + +Maximum number of entries that should be returned by the server in search +results. The LDAP server may impose a smaller size limit than the limit you +specify as the server administrator also has the ability to set this limit. +The data type for the optdata parameter is (int +*). + + + +LDAP_OPT_SSL + +Determines whether or not SSL is enabled. optdata can +be one of the following values: + +LDAP_OPT_ON specifies that SSL is enabled. + +LDAP_OPT_OFF specifies that SSL is disabled. +The data type for the optdata parameter is (int +*). + + + + + +LDAP_OPT_THREAD_FN_PTRS + +Lets you specify the thread function pointers. +The data type for the optdata parameter is (struct +ldap_thread_fns *). + + + +LDAP_OPT_TIMELIMIT + +Maximum number of seconds that should be spent by the server when answering +a search request. The LDAP server may impose a shorter time limit than the +limit you specify as the server administrator also has the ability to set +this limit. +The data type for the optdata parameter is (int +*). + + + +LDAP_X_OPT_EXTIO_FN_PTRS + +Extended I/O function callback option. + + + +LDAP_X_OPT_CONNECT_TIMEOUT + +Value of a time out (expressed in milliseconds) for non-blocking connect +call. +The data type for the optdata parameter is (int +*). + + + +LDAP_X_OPT_SOCKBUF + +Socket buffer structure associated to the LDAP connection. + + + +
+See also ldap_get_option +3LDAP for details on LDAP_OPT_X_SASL* + parameters.
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +-1 if unsuccessful. + + +Examples +Example 21–23 gets +the session preference for the maximum number of entries to be returned from +search operations. +Using <function>ldap_get_option</function> +#include <ldap.h> +... +LDAP *ld; +int max_ret; +... +/* Get the maximum number of entries returned */ +if (ldap_get_option, LDAP_OPT_SIZELIMIT, &max_ret) != LDAP_SUCCESS) { + ldap_perror( ld, "ldap_get_option" ); + return( 1 ); +} + +Example 21–23 could +also include the following two small sections of code that show how to use +the LDAP_OPT_API_FEATURE_INFO and the LDAP_OPT_API_INFO + options, respectively. +Using <structname>LDAP_OPT_API_FEATURE_INFO</structname> and <structname> +LDAP_OPT_API_INFO</structname> +LDAPIIFeatureInfo ldfi; +ldfi.ldapaif_info_version = LDAP_FEATURE_INFO_VERSION; +ldfi.ldapaif_name = "VIRTUAL_LIST_VIEW"; +if (ldap_get_option(NULL, LDAP_OPT_API_FEATURE_INFO, &ldfi)==0) { +/* use the info here */ } + +LDAPIInfo ldai; +ldai.ldapiai_info_version = LDAP_API_INFO_VERSION; +if (ldap_get_option( NULL, LDAP_OPT_API_INFO, &ldia ) == 0) { +/* use the ldai info here */ +} + + +See Also +ldap_init, prldap_init + (IPv6), ldap_set_option +
+<function>ldap_get_values</function> +The ldap_get_values function returns a NULL terminated +array of an attribute’s string values for a given entry. +Syntax +#include <ldap.h> + char ** ldap_get_values( LDAP *ld, LDAPMessage *entry, + const char *target ); + +Parameters +<function>ldap_get_values</function> Function +Parameters + + + + +Parameters + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +entry + +Result returned by the ldap_result or ldap_search_s function. + + + +target + +Attribute returned by ldap_first_attribute or ldap_next_attribute, or the attribute as a literal +string, such as jpegPhoto or audio. + + + + +
+
+Returns +One of the following values: + +If successful, returns a NULL terminated +array of the attribute’s values. +If unsuccessful or if no such attribute exists in the entry, +returns a NULL and sets the appropriate error code in the + LDAP structure. To get the error code, call +the ldap_get_lderrno function. + + + +Description +Use the ldap_get_values_len function +if the attribute values are binary. +Example +Example 21–25 gets +and prints the values of an attribute in an entry. This example assumes that +all attributes have string values. +Using <function>ldap_get_values</function> +#include <stdio.h> +#include <ldap.h> +... +LDAP *ld; +LDAPMessage *result, *e; +BerElement *ber; +char *a; +char **vals; +char *my_searchbase = "dc=example,dc=com"; +char *my_filter = "(sn=Jensen)"; +int i; +... +/* Search the directory */ +if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter, + NULL, 0, &result ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search_s" ); + return( 1 ); +} + +/* Get the first matching entry.*/ +e = ldap_first_entry( ld, result ); + +/* Get the first matching attribute */ +a = ldap_first_attribute( ld, e, &ber ); + +/* Get the values of the attribute */ +if ( ( vals = ldap_get_values( ld, e, a ) ) != NULL ) { + for ( i = 0; vals[i] != NULL; i++ ) { + /* Print the name of the attribute and each value */ + printf( "%s: %s\n", a, vals[i] ); + } + /* Free the attribute values from memory when done. */ + ldap_value_free( vals ); +} +... + + +See Also +ldap_first_entry, ldap_first_attribute, ldap_get_values_len +, ldap_next_entry, ldap_next_attribute +
+<function>ldap_get_values_len</function> +The ldap_get_values_len function returns a NULL + terminated array of pointers to berval structures, +each containing the length and pointer to a binary value of an attribute for +a given entry. +Syntax +#include <ldap.h> + struct berval ** ldap_get_values_len( LDAP *ld, + LDAPMessage *entry, const char *target ); + +Parameters +<function>ldap_get_values_len</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +entry + +Result returned by the ldap_result or ldap_search_s function. + + + +target + +Attribute returned by ldap_first_attribute or ldap_next_attribute, or the attribute as a literal +string, such as jpegPhoto or audio. + + + + +
+
+Returns +One of the following values: + +If successful, returns a NULL terminated +array of pointers to berval structures, which in +turn contains pointers to the attribute’s binary values. +If unsuccessful or if no such attribute exists in the entry, +returns NULL and sets the appropriate error code in the + LDAP structure. To get the error code, call +the ldap_get_lderrno function. + + + +Description +Use the ldap_get_values routine if +the attribute values are string values. +Example +Example 21–26 +gets the first value of the jpegPhoto attribute and saves +the JPEG data to a file. +<function>ldap_get_values_len</function> +#include <stdio.h> +#include <ldap.h> +... +LDAP *ld; +LDAPMessage *result, *e; +BerElement *ber; +struct berval photo_data; +struct berval **list_of_photos; +FILE *out; +char *my_searchbase = "dc=example,dc=com"; +char *my_filter = "(sn=Jensen)"; +... +/* Search the directory */ +if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter, NULL, + 0, &result ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search_s" ); + return( 1 ); +} + +/* Get the first matching entry.*/ +e = ldap_first_entry( ld, result ); + +/* Get the value of the jpegPhoto attribute */ +if ( ( list_of_photos = ldap_get_values_len( ld, e, "jpegPhoto" ) ) != + NULL ) { + /* Prepare to write the JPEG data to a file */ + if ( ( out = fopen( "photo.jpg", "wb" ) ) == NULL ) { + perror( "fopen" ); + return( 1 ); + } + /* Get the first JPEG */ + photo_data = *list_of_photos[0]; + /* Write the JPEG data to a file */ + fwrite( photo_data.bv_val, photo_data.bv_len, 1, out ); + fclose( out ); + /* Free the attribute values from memory when done. */ + ldap_value_free_len( list_of_photos ); +} +... + + +See Also +ldap_first_entry, ldap_first_attribute, ldap_get_values +, ldap_next_entry, ldap_next_attribute +
+<function>ldap_init</function> +The ldap_init function initializes a session with +an LDAP server and returns an LDAP structure +that represents the context of the connection to that server. +Syntax +#include <ldap.h> +LDAP * ldap_init( const char *defhost, int defport ); + +Parameters +<function>ldap_init</function> Function +Parameters + + + + +Parameter + +Description + + + + + +defhost + +Space-delimited list of one or more host names (or IP address in dotted +notation, such as "141.211.83.36") of the LDAP servers that you want the LDAP +client to connect to. The names can be in hostname: +portnumber format (in which case, portnumber overrides +the port number specified by the defport argument. + + + + +defport + +Default port number of the LDAP server. To specify the standard LDAP +port (port 389), use LDAP_PORT as the value for this parameter. + + + + +
+
+Returns +One of the following values: + +If successful, returns a pointer to an LDAP + structure. +If unsuccessful, returns a NULL. + + + +Description +The ldap_init function initializes a session with +an LDAP server by allocating an LDAP structure +containing information about the session including the host name and port +of the LDAP server, preferences for the session (such as the maximum number +of entries to return in a search), and the error code of the last LDAP operation +performed. The LDAP structure defaults to +LDAP v2. It is highly recommended to set it to LDAP v3 using the ldap_set_option. +ldap_init does not open a connection +to the LDAP server. The actual connection opening will occur when the first +operation is attempted. Certain fields in the LDAP structure +can be set using ldap_set_option. +You can specify a list of LDAP servers to which you want to attempt +to connect by passing a space-delimited list of the host names as the defhost + argument. Your client will attempt to connect to the first LDAP +server in the list. If the attempt fails, your client will attempt to connect +to the next LDAP server in the list. In Example +21–27 ld1.example.com, port 389. +If that server does not respond, the client will attempt to connect to the +LDAP server on ld2.example.com, port 389. +If that server does not respond, the client will use the server on ld3.example.com + , port 389. +Space-Delimited List for <function>ldap_init +</function> +... +LDAP *ld +... +ld = ldap_init( "ld1.example.com ld2.example.com ld3.example.com", + LDAP_PORT ); + +If any of the servers do not use the default port specified by the +defport argument, use the hostname: +portnumber format to specify the server name. In Example 21–27 ld1.example.com +, port 389. If that server does not respond, +the client will attempt to connect to the LDAP server on ld2.example.com +, port 1389. +<function>ldap_init</function> Example +Using Variable Argument +... +LDAP *ld +... +ld = ldap_init( "ld1.example.com ld2.example.com:1389", LDAP_PORT ); + +If you are connecting to a secure LDAP server over SSL, you should +be calling the ldapssl_init function. + + +Example +Example 21–29 initializes +a session with the LDAP server at ldap.example.com:389, +and sets a session preference that identifies the client as an LDAP v3 client. +Using <function>ldap_init</function> +#include <ldap.h> +... +LDAP *ld; + +/* Specify the host name of the LDAP server. */ +char *ldap_host = "ldap.example.com"; + +/* Because the LDAP server is running on the standard LDAP port (port 389), + * you can use LDAP_PORT to identify the port number. */ +int ldap_port = LDAP_PORT; +... +/* Initialize the session with ldap.example.com:389 */ +/* Use prldap_init() for IPv6 support. */ +if ( ( ld = ldap_init( ldap_host, ldap_port ) ) == NULL ) { + perror( "ldap_init" ); + return( 1 ); +} + +/* Specify the LDAP version supported by the client. */ +version = LDAP_VERSION3; +ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); + +... +/* Subsequent calls that authenticate to the LDAP server. */ +... + + +See Also +prldap_init (IPv6), ldap_unbind, ldap_unbind_s , ldap_simple_bind, ldap_simple_bind_s + +
+<function>ldap_init_getfilter</function> +The ldap_init_getfilter function reads a valid +LDAP filter configuration file (such as ldapfilter.conf) +and returns a pointer to an LDAPFiltDesc structure. + +ldapfilter.conf, the sample LDAP filter configuration +file located in lib/ldapcsdk/etc directory, can be used +in context with ldap_init_getfilter . + +Syntax +#include <ldap.h> +LDAPFiltDesc * ldap_init_getfilter( char *fname ); + +Parameters +<function>ldap_init_getfilter</function> Function +Parameter + + + + +Parameter + +Description + + + + + +fname + +Name of the LDAP filter configuration file to use. + + + +
+
+Returns +One of the following values: + +If successful, returns a pointer to an LDAPFiltDesc + structure. +If unsuccessful (for example, if there is an error reading +the file), returns a NULL. + + +Example +Example 21–30 +loads a filter configuration file named myfilters.conf into +memory. +Loading a Filter Configuration File +#include <ldap.h> +... +LDAPFiltDesc *lfdp; +char *filter_file = "myfilters.conf"; +... +lfdp = ldap_init_getfilter( filter_file ); +... + + +See Also +ldap_init_getfilter_buf, ldap_getfilter_free +
+<function>ldap_init_getfilter_buf</function> +The ldap_init_getfilter_buf function reads LDAP +filter configuration information from a buffer and returns a pointer to an + LDAPFiltDesc structure. +Syntax +#include <ldap.h> + LDAPFiltDesc * ldap_init_getfilter_buf(char *buf, long buflen ); + +Parameters +<function>ldap_init_getfilter_buf</function> Function +Parameters + + + + +Parameter + +Description + + + + + +buf + +Buffer containing LDAP filter configuration information. + + + +buflen + +Size of the buffer + + + +
+
+Returns +One of the following values: + +If successful, returns a pointer to an LDAPFiltDesc + structure. +If unsuccessful—for example, if there is an error reading +the file—returns a NULL. + + +Example +Example 21–31 +copies the following filter configuration to a buffer in memory and uses this +buffer to fill an LDAPFiltDesc structure. +"ldap-example" + "@" " " "(mail=%v)" "email address" + "(mail=%v*)" "start of email address" +Using <function>ldap_init_getfilter +</function> +#include <string.h> +#include <ldap.h> +... +LDAPFiltDesc *lfdp; +char filtbuf[ 1024 ]; +... +/* Create the filter config buffer */ +strcpy( filtbuf, "\"ldap-example\"\n" ); +strcat( filtbuf, " \"@\"\t\" \"\t\"(mail=%v)\"\t\"email address\"\n" ); +strcat( filtbuf, " \t\t\"(mail=%v*)\"\t\"start of email address\"\n" ); +lfdp = ldap_init_getfilter( filtbuf, strlen( filtbuf ) ); +... + + +See Also +ldap_init_getfilter, ldap_getfilter_free +
+<function>ldap_init_searchprefs</function> +The ldap_init_searchprefs function reads a sequence +of search preference configurations from a valid LDAP searchpref configuration +file. +Syntax +#include <ldap.h> +int ldap_init_searchprefs( char *file, struct ldap_searchobj **solistp ); + +Parameters +<function>ldap_init_searchprefs</function> Function +Parameters + + + + +Parameter + +Description + + + + + +file + +Pointer to a valid LDAP searchpref configuration +file. + + + +solistp + +Pointer to a list of search preference data structures. + + + +
+
+Returns +One of the following values: + +LDAP_SEARCHPREF_ERR_VERSION. + +LDAP_SEARCHPREF_ERR_MEM if there is a memory +allocation problem. +Upon success, 0 is returned and solistp + is set to point to a list of search preference data structures. + + + +Description +ldap_init_searchprefs provides a standard way to +access LDAP search preference configuration data. +LDAP search preference configurations are typically used by LDAP +client programs to specify which attributes a user may search by, labels for +the attributes, and LDAP filters and scopes associated with those searches. +Client software presents these choices to a user, who can then specify the +type of search to be performed. + +See Also +ldap_free_searchprefs, ldap_init_searchprefs_buf +
+<function>ldap_init_searchprefs_buf</function> +The ldap_init_searchprefs_buf function reads a +sequence of search preference configurations from the parameter, buf. + +Syntax +#include <ldap.h> +int ldap_init_searchprefs_buf( char *buf, long buflen, + struct ldap_searchobj **solistp ); + +Parameters +<function>ldap_init_searchprefs_buf</function> Function +Parameters + + + + +Parameter + +Description + + + + + +buf + +Pointer to data in the format defined for an LDAP search preference +configuration file. + + + +buflen + +The size of buf. + + + +solistp + +Pointer to a list of search preference data structures. + + + +
+
+Returns +One of the following values: + +LDAP_SEARCHPREF_ERR_VERSION if buf points +to data that is newer than can be handled. +LDAP_SEARCHPREF_ERR_MEM if there is a memory +allocation problem. +Upon success, 0 is returned and solistp + is set to point to a list of search preference data structures. + + + +Description +ldap_init_searchprefs_buf reads a sequence of search +preference configurations from buf. +LDAP search preference configurations are typically used by LDAP +client programs to specify which attributes a user may search by, labels for +the attributes, and LDAP filters and scopes associated with those searches. +Client software presents these choices to a user, who can then specify the +type of search to be performed. + +See Also +ldap_init_searchprefs, ldap_free_searchprefs +
+<function>ldap_init_templates</function> +The ldap_init_templates function reads a sequence +of templates from a valid LDAP template configuration file. +Syntax +#include <disptmpl.h> +int ldap_init_templates( char *file, struct ldap_disptmpl **tmpllistp ); + +Parameters +<function>ldap_init_templates</function> Function +Parameters + + + + +Parameter + +Description + + + + + +file + +Pointer to a valid LDAP template configuration file. + + + +tmpllistp + +Pointer to a list of template data structures. + + + +
+
+Returns + +If successful, 0 is returned and tmpllistp + is configured. +Upon error: + +LDAP_TMPL_ERR_VERSION if buf points +to data that is newer than can be handled. +LDAP_TMPL_ERR_MEM if there is a memory +allocation problem. +LDAP_TMPL_ERR_SYNTAX if there is a problem +with the format of the templates buffer or file. +LDAP_TMPL_ERR_FILE if the file cannot be +read. + + + + +Description +ldap_init_templates reads a sequence of templates +from a valid LDAP template configuration file. Each template defined in the +file is an ldap_disptmpl structure. +See Also +ldap_init_templates_buf, ldap_free_templates +
+<function>ldap_init_templates_buf</function> +The ldap_init_templates_buf function reads a sequence +of templates from a buffer. +Syntax +#include <disptmpl.h> +int ldap_init_templates_buf( char *buf, long buflen, + struct ldap_disptmpl **tmpllistp ); + +Parameters +<function>ldap_init_templates_buf</function> Function +Parameters + + + + +Parameter + +Description + + + + + +buf + +Pointer to data in the format defined for a valid LDAP template configuration +file. + + + +buflen + +The size of buf. + + + +tmpllistp + +Pointer to a list of template data structures. + + + +
+
+Returns + +If successful, 0 is returned and tmpllistp + is configured. +Upon error: + +LDAP_TMPL_ERR_VERSION if buf points +to data that is newer than can be handled. +LDAP_TMPL_ERR_MEM if there is a memory +allocation problem. +LDAP_TMPL_ERR_SYNTAX if there is a problem +with the format of the templates buffer or file. +LDAP_TMPL_ERR_FILE if the file cannot be +read. + + + + +Description +The ldap_init_templates_buf function reads a sequence +of templates from a buffer. +See Also +ldap_init_templates, ldap_free_templates +
+<function>ldap_is_dns_dn</function> +This function is deprecated and should not be used. It is included +in ldap-to-be-deprecated.h for backward-compatibility. + +The ldap_is_dns_dn function determines whether +a DN string is of the experimental DNS-style DN (generally in the form of +an RFC 822 email address) or the RFC 1779 formatted DN. +Description +This function is specific to LDAP v2 and should not be used when dealing +with LDAP v3 servers or data. +More information can be found in RFC 1779 - A String +Representation of Distinguished Names () and +RFC 822 - Standard for the Format of ARPA Internet Text Messages (). + + + +<function>ldap_is_ldap_url</function> +The ldap_is_ldap_url function determines whether +or not a URL is an LDAP URL. +Syntax +#include <ldap.h> + int ldap_is_ldap_url( const char *url ); + +Parameters +<function>ldap_is_ldap_url</function> Function +Parameter + + + + +Parameter + +Description + + + + + +url + +The URL that you want to check. + + + +
+
+Returns +One of the following values: + +1 if the URL is an LDAP URL. + +0 if the URL is not an LDAP URL. + + + +Description +The ldap_is_ldap_url function determines whether +or not a URL is an LDAP URL. An LDAP URL is a URL with the protocol set to +ldap:// (or ldaps://, if the server is communicating +over a SSL connection). +Example +Example 21–32 determines +if a URL is a LDAP URL. +Using <function>ldap_is_ldap_url</function> +#include <stdio.h> +#include <ldap.h> +... +char *my_url = "ldap://ldap.sun.com/dc=example,dc=com"; +... +if ( ldap_is_ldap_url( my_url ) != 0 ) { + printf( "%s is an LDAP URL.\n", my_url ); +} else { + printf( "%s is not an LDAP URL.\n", my_url ); +} +... + + +See Also +ldap_url_parse +
+<function>ldap_keysort_entries</function> +The ldap_keysort_entries function is used for sorting +entries. +Syntax +#include <ldap-extension.h> + int ldap_keysort_entries( LDAP *ld, LDAPMessage **chain, + void *arg, LDAP_KEYGEN_CALLBACK *gen, LDAP_KEYCMP_CALLBACK *cmp, + LDAP_KEYFREE_CALLBACK *fre ); + +Parameters +<function>ldap_keysort_entries</function> Function +Parameter + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +chain + +Chain of entries returned by the ldap_result or ldap_search_s function. + + + +arg + +Pointer to an additional argument that you want to pass. + + + +gen + +Callback used to generate the key(s) for sorting once the compare function +has been applied. + + + +cmp + +Comparison function used when sorting the values. + + + +fre + +Callback used to free the key once the compare function has been applied. + + + + +
+
+See Also +LDAP_KEYGEN_CALLBACK, LDAP_KEYCMP_CALLBACK, LDAP_KEYFREE_CALLBACK + +
+<function>ldap_memcache_destroy</function> +The ldap_memcache_destroy function frees an LDAPMemCache structure from memory. +Syntax +#include <ldap.h> + void ldap_memcache_destroy( LDAPMemCache *cache ); + +Parameters +<function>ldap_memcache_destroy</function> Function +Parameter + + + + +Parameter + +Description + + + + + +cache + +Pointer to the LDAPMemCache structure +that you want freed from memory. + + + +
+
+Description +The ldap_memcache_destroy function frees the specified LDAPMemCache structure from memory. Call this function +after you are done working with a cache. +See Also +ldap_memcache_init +
+<function>ldap_memcache_flush</function> +The ldap_memcache_flush function flushes items +from the specified cache. +Syntax +#include <ldap.h> + void ldap_memcache_flush( LDAPMemCache *cache, char *dn, + int scope ); + +Parameters +<function>ldap_memcache_flush</function> Function +Parameters + + + + +Parameter + +Description + + + + + +cache + +Pointer to the LDAPMemCache structure +that you want to flush entries from. + + + +dn + +Base DN identifying the search requests that you want flushed from the +cache. If the base DN of a search request is within the scope specified by +this DN and the scope argument, the search request is flushed from the cache. +If this argument is NULL, the entire cache is flushed. + + + +scope + +Scope that (together with the dn argument) identifies +the search requests that you want flushed from the cache. If the base DN of +the request is within the scope specified by this argument and the dn argument, +the request is flushed from the cache. This argument can have one of the following +values: + +LDAP_SCOPE_BASE +LDAP_SCOPE_ONELEVEL +LDAP_SCOPE_SUBTREE + + + + + +
+
+Description +The ldap_memcache_flush function flushes search +requests from the cache. If the base DN of a search request is within the +scope specified by the dn and scope arguments, the search +request is flushed from the cache. If no DN is specified, the entire cache +is flushed. +
+<function>ldap_memcache_get</function> +The ldap_memcache_get function gets the in-memory +cache associated with an LDAP connection handle. +Syntax +#include <ldap.h> +int ldap_memcache_get( LDAP *ld, LDAPMemCache **cachep ); + +Parameters +<function>ldap_memcache_get</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +cachep + +When you call ldap_memcache_get, it sets this parameter +to the pointer to the LDAPMemCache structure +associated with the connection handle. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if the cache for the specified +connection handle was retrieved successfully. +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. + + +Description +The ldap_memcache_get function gets the cache associated +with the specified connection handle (LDAP structure). +This cache is used by all search requests made through that connection. You +can call this function if you want to associate a cache with multiple LDAP +connection handles. For example, you can call this function to get the cache +associated with one connection, then you can call the ldap_memcache_set + function to associate the cache with another connection. +See Also +ldap_memcache_set +
+<function>ldap_memcache_init</function> +The ldap_memcache_init function creates an in-memory +cache for your LDAP client that you can associate with an LDAP connection. +Syntax +#include <ldap.h> + int ldap_memcache_init( unsigned long ttl, unsigned long size, + char **baseDNs, struct ldap_thread_fns *thread_fns, + LDAPMemCache **cachep ); + +Parameters +<function>ldap_memcache_init</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ttl + +The maximum amount of time (in seconds) that an item can be cached. +If 0, there is no limit to the amount of time that an +item can be cached. + + + +size + +Maximum amount of memory (in bytes) that the cache will consume. If + 0, the cache has no size limit. + + + +baseDNs + +An array of the base DN strings representing the base DNs of the search +requests you want cached. If not NULL, only the search +requests with the specified base DNs will be cached. If NULL, +all search requests are cached. + + + +thread_fns + +An ldap_thread_fns structure specifying +the functions that you want used to ensure that the cache is thread-safe. +You should specify this if you have multiple threads that are using the same +connection handle and cache. If you are not using multiple threads, pass +NULL for this parameter. + + + +cachep + +When you call this function, it sets this parameter to the pointer to +the newly created LDAPMemCache structure. + + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if the cache for the specified +connection handle was retrieved successfully. +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_SIZELIMIT_EXCEEDED if the initial +size of the cache (specified by the size argument) is too small. + + + +Description +The ldap_memcache_init function creates an in-memory, +client-side cache that you can use to cache search requests. The function +passes back a pointer to an LDAPMemCache structure, +which represents the cache. You should call the ldap_memcache_set + function to associate this cache with an LDAP connection handle (an + LDAP structure). +The cache uses search criteria as the key to cached items. When you +send a search request, the cache checks the search criteria to determine if +that request has been cached previously. If the request was cached, the search +results are read from the cache. To flush the cache, call the ldap_memcache_flush function. When you are done +with the cache, you can free it from memory by calling the ldap_memcache_destroy function. +On Windows systems, if the ldap_memcache_init + function returns an LDAP_PARAM_ERROR result +code, verify that your client is using the version of the nsldap32v30.dll + file provided with the &DirectorySDKForC;. + +See Also +LDAPMemCache, ldap_memcache_set + , ldap_memcache_flush, ldap_memcache_destroy, ldap_memcache_update + +
+<function>ldap_memcache_set</function> +The ldap_memcache_set function associates an in-memory +cache with an LDAP connection handle. +Syntax +#include <ldap.h> + int ldap_memcache_set( LDAP *ld, LDAPMemCache *cache ); + +Parameters +<function>ldap_memcache_set</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +cache + +Pointer to an LDAPMemCache structure, +which represents the cache that you want used for this connection. + + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if the cache for the specified +connection handle was retrieved successfully. +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_SIZELIMIT_EXCEEDED if the initial +size of the cache (specified by the size argument) is too small. + + + +Description +The ldap_memcache_set function associates a cache +(created by calling ldap_memcache_init) with +an LDAP connection handle. You can call this function if you want to associate +a cache with multiple LDAP connection handles. For example, you can call the ldap_memcache_get function to get the cache associated +with one connection, then you can call ldap_memcache_set to +associate the cache with another connection. +After you call this function, search requests made over the specified +LDAP connection will use this cache. Calling the ldap_unbind + function will disassociate the cache from the LDAP connection handle. + +See Also +ldap_memcache_init, ldap_memcache_get +
+<function>ldap_memcache_update</function> +The ldap_memcache_update function checks the cache +for items that have expired and removes them. +Syntax +#include <ldap.h> +void ldap_memcache_update( LDAPMemCache *cache ); + +Parameters +<function>ldap_memcache_update</function> Function +Parameter + + + + +Parameter + +Description + + + + + +cache + +Pointer to an LDAPMemCache structure, +which represents the cache that you want to updated. + + + +
+
+Description +The ldap_memcache_update function checks the cache +for items that have expired and removes them. This check is typically done +as part of the way the cache normally works. You do not need to call this +function unless you want to update the cache at this point in time. +This function is only useful in a multithreaded application, since +it will not return until the cache is destroyed. + +See Also +ldap_memcache_flush +
+<function>ldap_memfree</function> +The ldap_memfree function frees memory allocated +by an LDAP API function call. +Syntax +#include <ldap.h> + void ldap_memfree( void *p ); + +Parameters +<function>ldap_memfree</function> Function +Parameter + + + + +Parameter + +Description + + + + + +p + +Pointer to memory used by the LDAP library. + + + +
+
+Example +Example 21–33 frees +the memory allocated by the ldap_get_dn function. + +Using <function>ldap_memfree</function> +#include <ldap.h> +... +LDAP *ld; +char *dn; +LDAPMessage *entry; +... +/* Get the distinguished name (DN) for an entry */ +dn = ldap_get_dn( ld, entry ); +... +/* When you are finished working with the DN, free the memory allocated. */ +ldap_memfree( dn ); +... + + +See Also +ldap_free_friendlymap, ldap_free_urldesc, ldap_msgfree +, ldap_value_free, ldap_value_free_len +
+<function>ldap_modify</function> +The ldap_modify function modifies an existing entry +in the directory asynchronously. +This is an older function included in the SDK for backward-compatibility. +If you are writing a new LDAP client, use ldap_modify_ext + instead. +Syntax +#include <ldap.h> +int ldap_modify( LDAP *ld, const char *dn, LDAPMod **mods ); + +Parameters +<function>ldap_modify</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the entry to modify. + + + +mods + +Pointer to a NULL terminated array of pointers to LDAPMod structures representing the attributes that +you want to modify. + + + +
+
+Returns +Returns the message ID of the ldap_modify operation. +To check the result of this operation, call ldap_result and ldap_result2error. For a list of possible result +codes for an LDAP modify operation, see ldap_modify_ext_s +. +Description +Please use the newer version of this function, ldap_modify_ext + . +Example +Example 21–34 uses +the asynchronous ldap_modify function to modify the entry +for Barbara Jensen in the directory. It makes the following +changes to the entry: + +Adds the homePhone attribute. + +Changes the telephoneNumber attribute. + +Removes the facsimileTelephoneNumber attribute. + + +Using <function>ldap_modify</function> +#include <ldap.h> +... +LDAP *ld; +LDAPMod *list_of_attrs[4]; +LDAPMod attribute1, attribute2, attribute3; +LDAPMessage *result; +int msgid, rc; +struct timeval tv; + +/* Distinguished name of the entry that you want to modify. */ +char *dn = "uid=bjensen,ou=People,dc=example,dc=com"; + +/* Values to add or change */ +char *homePhone_values[] = { "555-1212", NULL }; +char *telephoneNumber_values[] = { "869-5309", NULL }; + +... +/* Specify each change in separate LDAPMod structures */ +attribute1.mod_type = "homePhone"; +attribute1.mod_op = LDAP_MOD_ADD; +attribute1.mod_values = homePhone_values; +attribute2.mod_type = "telephoneNumber"; +attribute2.mod_op = LDAP_MOD_REPLACE; +attribute2.mod_values = telephoneNumber_values; +attribute3.mod_type = "facsimileTelephoneNumber"; +attribute3.mod_op = LDAP_MOD_DELETE; +attribute3.mod_values = NULL; +/* NOTE: When removing entire attributes, you need to specify a NULL value + * for the mod_values field. */ + +/* Add the pointers to these LDAPMod structures to an array */ +list_of_attrs[0] = &attribute1; +list_of_attrs[1] = &attribute2; +list_of_attrs[2] = &attribute3; +list_of_attrs[3] = NULL; +... +/* Set up the timeout period to wait for the "modify" operation */ +tv.tv_sec = tv.tv_usec = 0; + +/* Change the entry */ +if ( ( msgid = ldap_modify( ld, dn, list_of_attrs ) ) == -1 ) { + ldap_perror( ld, "ldap_modify" ); + return( 1 ); +} + +/* Check to see if the operation has completed */ +while ( ( rc = ldap_result( ld, msgid, 0, &tv, &result ) ) == 0 ) { + ... + /* do other work while waiting for the operation to complete */ + ... +} + +/* Check the result to see if any errors occurred */ +ldap_result2error( ld, result, 1 ); +ldap_perror( ld, "ldap_modify" ); +... + + +See Also +ldap_modify_ext +
+<function>ldap_modify_ext</function> +The ldap_modify_ext function modifies an existing +entry in the directory asynchronously. +ldap_modify_ext is a new version +of the ldap_modify function. If you are writing +a new LDAP client, use ldap_modify_ext. + +Syntax +#include <ldap.h> +int ldap_modify_ext( LDAP *ld, const char *dn, LDAPMod **mods, + LDAPControl **serverctrls, LDAPControl **clientctrls, + int *msgidp ); + +Parameters +<function>ldap_modify_ext</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the entry to modify. + + + +mods + +Pointer to a NULL terminated array of pointers to LDAPMod structures representing the attributes that +you want to modify. + + + +serverctrls + +Pointer to an array of LDAPControl structures +representing LDAP server controls that apply to this operation. If you do +not want to pass any server controls, specify NULL for +this argument. + + + +clientctrls + +Pointer to an array of LDAPControl structures +representing LDAP client controls that apply to this operation. If you do +not want to pass any client controls, specify NULL for +this argument. + + + +msgidp + +Pointer to an integer that will be set to the message ID of the LDAP +operation. To check the result of this operation, call ldap_result + and ldap_parse_result. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the control. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_NOT_SUPPORTED if controls are +included in your request (for example, as a session preference) and your LDAP +client does not specify that it is using the LDAP v3. Make sure that you set +the version of your LDAP client to version 3 before calling this function. + + + +Description +The ldap_modify_ext modifies an entry in the directory +asynchronous; it does not directly return results. If you want the results +to be returned directly by the function, call the synchronous function ldap_modify_ext_s instead. In order to get the results +of this LDAP modify operation, you need to call the ldap_result + and the ldap_parse_result functions. +To make changes to an entry to the directory, you need to specify the following +information: + +A unique DN identifying the new entryUse the + dn argument to specify the DN of the entry you want to +modify. +A set of attributes for the new entryCreate an LDAPMod structure for changes that you want to make +to an attribute. Create an array of these LDAPMod structures +and pass the array as the mods argument. + + +See Also +ldap_modify_ext_s, ldap_result, ldap_parse_result +, LDAPMod +
+<function>ldap_modify_ext_s</function> +The ldap_modify_ext_s modifies an existing entry +in the directory synchronously. +ldap_modify_ext_s is a new version +of the ldap_modify_s function. If you are +writing a new LDAP client, use ldap_modify_ext_s. + +Syntax +#include <ldap.h> + int ldap_modify_ext_s( LDAP *ld, const char *dn, LDAPMod **mods, + LDAPControl **serverctrls, LDAPControl **clientctrls ); + +Parameters +<function>ldap_modify_ext_s</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the entry to modify. + + + +mods + +Pointer to a NULL terminated array of pointers to LDAPMod structures representing the attributes that +you want to modify. + + + +serverctrls + +Pointer to an array of LDAPControl structures +representing LDAP server controls that apply to this operation. If you do +not want to pass any server controls, specify NULL for +this argument. + + + +clientctrls + +Pointer to an array of LDAPControl structures +representing LDAP client controls that apply to this operation. If you do +not want to pass any client controls, specify NULL for +this argument. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the control. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_LOCAL_ERROR if an error occurred +when receiving the results from the server. +LDAP_DECODING_ERROR if an error occurred +when decoding the BER-encoded results from the server. +LDAP_NOT_SUPPORTED if controls are +included in your request (for example, as a session preference) and your LDAP +client does not specify that it is using the LDAP v3. Make sure that you set +the version of your LDAP client to version 3 before calling this function. + + +&cnDirectoryServer; and other LDAP server products may send result +codes in addition to those described. For example, the server may have loaded +a plug-in that returns custom result codes. Check your LDAP server documentation +for other result codes. + +Description +The ldap_modify_ext_s modifies an entry in the +directory. ldap_modify_ext_s is a synchronous function, +which directly returns the results of the operation. If you want to perform +other operations while waiting for the results of this operation, call the +asynchronous function ldap_modify_ext instead. +To make changes to an entry to the directory, you need to specify the +following information: + +A unique DN identifying the new entryUse the + dn argument to specify the DN of the entry that you want +to modify. +A set of attributes for the new entryCreate an LDAPMod structure for change that you want to make +to an attribute. Create an array of these LDAPMod structures +and pass the array as the mods argument. + + +See Also +ldap_modify_ext, +LDAPMod +
+<function>ldap_modify_s</function> +The ldap_modify_s function modifies an existing +entry in the directory synchronously. +This is an older function that is included in the SDK for backward-compatibility. +If you are writing a new LDAP client, use ldap_modify_ext_s + instead. +Syntax +#include <ldap.h> + int ldap_modify_s( LDAP *ld, const char *dn, LDAPMod **mods ); + +Parameters +<function>ldap_modify_s</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the entry to modify. + + + +mods + +Pointer to a NULL terminated array of pointers to LDAPMod structures representing the attributes that +you want to modify. + + + +
+
+Returns +For a list of possible result codes for an LDAP modify operation, see ldap_modify_ext_s. +Description +Use the newer version of this function, ldap_modify_ext_s + . +Example +Example 21–35 uses +the synchronous ldap_modify_s function to makes the following +changes to the Barbara Jensen entry: + +Adds the homePhone attribute. + +Changes the telephoneNumber attribute. + +Removes the facsimileTelephoneNumber attribute. + + +Using <function>ldap_modify_s</function> +#include <ldap.h> +... +LDAP *ld; +LDAPMod *list_of_attrs[4]; +LDAPMod attribute1, attribute2, attribute3; +LDAPControl **srvrctrls, **clntctrls; + +/* Distinguished name of the entry that you want to modify. */ +char *dn = "uid=bjensen,ou=People,dc=example,dc=com"; + +/* Values to add or change */ +char *homePhone_values[] = { "555-1212", NULL }; +char *telephoneNumber_values[] = { "869-5309", NULL }; + +... +/* Specify each change in separate LDAPMod structures */ +attribute1.mod_type = "homePhone"; +attribute1.mod_op = LDAP_MOD_ADD; +attribute1.mod_values = homePhone_values; +attribute2.mod_type = "telephoneNumber"; +attribute2.mod_op = LDAP_MOD_REPLACE; +attribute2.mod_values = telephoneNumber_values; +attribute3.mod_type = "facsimileTelephoneNumber"; +attribute3.mod_op = LDAP_MOD_DELETE; +attribute3.mod_values = NULL; +/* NOTE: When removing entire attributes, you need to specify a NULL value + * for the mod_values or mod_bvalues field. */ + +/* Add the pointers to these LDAPMod structures to an array */ +list_of_attrs[0] = &attribute1; +list_of_attrs[1] = &attribute2; +list_of_attrs[2] = &attribute3; +list_of_attrs[3] = NULL; +... +/* Change the entry */ +if ( ldap_modify_s( ld, dn, list_of_attrs ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_modify_s" ); + return( 1 ); +} +... + + +See Also +ldap_modify_ext_s +
+<function>ldap_modrdn</function> +This function is deprecated and should not be used. It is included +in ldap-deprecated.h for backward-compatibility. Use ldap_rename instead. +<function>ldap_modrdn_s</function> +This function is deprecated and should not be used. It is included +in ldap-deprecated.h for backward-compatibility. Use ldap_rename_s instead. + + +<function>ldap_modrdn2</function> +This function is deprecated and should not be used. It is included +in ldap-deprecated.h for backward-compatibility. Use ldap_rename instead. +The ldap_modrdn2 function changes the relative +distinguished name (RDN) of an entry in the directory asynchronously. +Syntax +#include <ldap-deprecated.h> +int ldap_modrdn2( LDAP *ld, const char *dn, const char *newrdn, + int deleteoldrdn ); + +Parameters +<function>ldap_modrdn2</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the entry to modify. + + + +newrdn + +New RDN to assign to the entry. + + + +deleteoldrdn + +If this is a non-zero value, the old RDN is not retained as a value +in the modified entry. If 0, the old RDN is retained as +an attribute in the modified entry. + + + +
+
+Returns +Returns the message ID of the ldap_modrdn2 operation. +To check the result of this operation, call ldap_result and ldap_result2error. For a list of possible result +codes, see ldap_rename. +Description +Please use the newer version of this function, ldap_rename + . +Example +Example 21–36 uses +the asynchronous ldap_modrdn2 function to change the +RDN of an entry from uid=bjensen to uid=babs. +The code removes the existing RDN bjensen from the uid + attribute of the entry. +Using <function>ldap_modrdn2</function> +#include <ldap-deprecated.h> +... +LDAP *ld; +LDAPMessage *result; +int msgid, rc; +struct timeval tv; + +/* Distinguished name of the entry that you want to rename. */ +char *dn = "uid=bjensen,ou=People,dc=example,dc=com"; + +/* New relative distinguished name (RDN) of the entry */ +char *rdn = "uid=babs"; +... +/* Set up the timeout period to wait for the "modify RDN" operation */ +tv.tv_sec = tv.tv_usec = 0; + +/* Rename the entry */ +if ( ( msgid = ldap_modrdn2( ld, dn, rdn, 1 ) ) == -1 ) { + ldap_perror( ld, "ldap_modrdn2" ); + return( 1 ); +} + +/* Check to see if the operation has completed */ +while ( ( rc = ldap_result( ld, msgid, 0, &tv, &result ) ) == 0 ) { + ... + /* do other work while waiting for the operation to complete */ + ... +} + +/* Check the result to see if any errors occurred */ +ldap_result2error( ld, result, 1 ); +ldap_perror( ld, "ldap_modrdn2" ); +... + + +See Also +ldap_rename +
+<function>ldap_modrdn2_s</function> +This function is deprecated and should not be used. It is included +in ldap-deprecated.h for backward-compatibility. Use ldap_rename_s instead. +The ldap_modrdn2_s function changes the relative +distinguished name (RDN) of an entry in the directory synchronously. +Syntax +#include <ldap-deprecated.h> + int ldap_modrdn2_s( LDAP *ld, const char *dn, + const char *newrdn, int deleteoldrdn ); + +Parameters +<function>ldap_modrdn2_s</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the entry to modify. + + + +newrdn + +New RDN to assign to the entry. + + + +deleteoldrdn + +If this is a non-zero value, the old RDN is not retained as a value +in the modified entry. If 0, the old RDN is retained as +an attribute in the modified entry. + + + +
+
+Returns +For a list of possible result codes, see ldap_rename_s + . +Description +Please use the newer version of this function, ldap_rename_s + . +Example +Example 21–37 uses +the synchronous ldap_modrdn2_s function to change the +RDN of an entry from uid=bjensen to uid=babs. +The code removes the existing RDN babs from the uid attribute +of the entry. +Using <function>ldap_modrdn2_s</function> +#include <ldap.h> +... +LDAP *ld; + +/* Distinguished name of the entry that you want to rename. */ +char *dn = "uid=bjensen,ou=People,dc=example,dc=com"; + +/* New relative distinguished name (RDN) of the entry */ +char *rdn = "uid=babs"; +... +/* Rename the entry */ +if ( ldap_modrdn2_s( ld, dn, rdn, 1 ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_modrdn2_s" ); + return( 1 ); +} +... + + +See Also +ldap_rename_s +
+<function>ldap_mods_free</function> +The ldap_mods_free function frees the LDAPMod structures that you’ve allocated to +add or modify entries. +You need to call this function only if you’ve allocated +memory for these structures yourself. For more information, see the ldap-extension.h + header file. +Syntax +#include <ldap.h> + void ldap_mods_free( LDAPMod **mods, int freemods ); + +Parameters +<function>ldap_mods_free</function> Function +Parameters + + + + +Parameter + +Description + + + + + +mods + +Pointer to a NULL terminated array of pointers to LDAPMod structures. + + + +freemods + +If this is a non-zero value, frees the array of pointers as well as +the LDAPMod structures. If 0, +just frees the LDAPMod structures. + + + + +
+
+Example +Example 21–38 allocates +memory for LDAPMod structures and frees them +when done. +Using <function>ldap_mods_free</function> +#include <stdio.h> +#include <ldap.h> +... +LDAP *ld; +char *dn; +int i, msgid; +LDAPMod **mods; +... +/* Construct the array of values to add */ +mods = ( LDAPMod ** ) malloc(( NMODS + 1 ) * sizeof( LDAPMod * )); +if ( mods == NULL ) { + fprintf( stderr, "Cannot allocate memory for mods array\n" ); +} +for ( i = 0; i < NMODS; i++ ) { + if (( mods[ i ] = ( LDAPMod * ) malloc( sizeof( LDAPMod ))) == NULL) { + fprintf( stderr, "Cannot allocate memory for mods element\n" ); + exit( 1 ); + } +} +... +/* Code for filling the structures goes here. */ +... +/* Initiate the add operation */ +if (( msgid = ldap_add( ld, dn, mods )) < 0 ) { + ldap_perror( ld, "ldap_add" ); + ldap_mods_free( mods, 1 ); + return( 1 ); +} +... + + +
+<function>ldap_msgfree</function> +The ldap_msgfree function frees the memory allocated +for a result by ldap_result or ldap_search_s. +Syntax +#include <ldap.h> + int ldap_msgfree( LDAPMessage *lm ); + +Parameters +<function>ldap_msgfree</function> Function +Parameter + + + + +Parameter + +Description + + + + + +lm + +Pointer to the result to be freed from memory. + + + +
+
+Returns +One of the following values: + +LDAP_RES_BIND indicates that the LDAPMessage structure contains the result of an +LDAP bind operation. +LDAP_RES_SEARCH_ENTRY indicates that the LDAPMessage structure contains an entry found during +an LDAP search operation. +LDAP_RES_SEARCH_REFERENCE indicates that +the LDAPMessage structure contains an LDAP +v3 search reference (a referral to another LDAP server) found during an LDAP +search operation. +LDAP_RES_SEARCH_RESULT indicates that the LDAPMessage structure contains the result of an +LDAP search operation. +LDAP_RES_MODIFY indicates that the LDAPMessage structure contains the result of an +LDAP modify operation. +LDAP_RES_ADD indicates that the LDAPMessage structure contains the result of an +LDAP add operation. +LDAP_RES_DELETE indicates that the LDAPMessage structure contains the result of an +LDAP delete operation. +LDAP_RES_MODRDN or LDAP_RES_RENAME indicates +that the LDAPMessage structure contains the +result of an LDAP modify DN operation. +LDAP_RES_COMPARE indicates that the LDAPMessage structure contains the result of an +LDAP compare operation. +LDAP_RES_EXTENDED indicates that the LDAPMessage structure contains the result of an +LDAP v3 extended operation. +LDAP_SUCCESS if the operation times +out. +-1 indicates that the lm argument +is not a pointer to a valid LDAPMessage structure. + +If unsuccessful, returns the LDAP error code for the operation. + + + +Example +Example 21–39 frees +the results of a search. +Using <function>ldap_msgfree</function> +#include <stdio.h> +#include <ldap.h> +... +LDAP *ld; +LDAPMessage *result; +char *my_searchbase = "dc=example,dc=com"; +char *my_filter = "(sn=Jensen)"; +char *get_attr[] = { "cn", "mail", NULL }; +... +/* Search the directory */ +if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter, + get_attr, 0, &result ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search_s" ); + return( 1 ); +} +... +/* Free the results when done */ +ldap_msgfree( result ); +... + + +See Also +ldap_result, ldap_search_s + +
+<function>ldap_msgid</function> +The ldap_msgid function determines the message +ID of a result obtained by calling ldap_result or ldap_search_s. +Syntax +#include <ldap.h> + int ldap_msgid( LDAPMessage *lm ); + +Parameters +<function>ldap_msgid</function> Function +Parameter + + + + +Parameter + +Description + + + + + +lm + +Pointer to the result to check. + + + +
+
+Returns +One of the following values: + +The message ID if successful. +-1 if unsuccessful. + + +Example +Example 21–40 prints +the message ID from the result obtained from a synchronous LDAP search operation. + +Using <function>ldap_msgid</function> +#include <stdio.h> +#include <ldap.h> +... +LDAP *ld; +LDAPMessage *result; +... +/* Perform a search */ +if ( ldap_search_s( ld, MY_SEARCHBASE, LDAP_SCOPE_SUBTREE, MY_FILTER, + NULL, 0, &result ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search_s" ); + return( 1 ); +} + +/* Get and print the message ID */ +if ( ldap_msgid( result ) != -1 ) { + printf( "Message ID: %d\n" ); +} else { + printf( "An error occurred.\n" ); +} +... + + +See Also +ldap_msgtype, ldap_result + , ldap_search_s +
+<function>ldap_msgtype</function> + +C SDK functions +ldap_msgtype + +ldap_msgtype + +The ldap_msgtype function determines the type of +result obtained by calling ldap_result or + ldap_search_s. +Syntax +#include <ldap.h> + int ldap_msgtype( LDAPMessage *lm ); + +Parameters +<function>ldap_msgtype</function> Function +Parameter + + + + +Parameter + +Description + + + + + +lm + +Pointer to the LDAPMessage structure +to check. + + + +
+
+Returns +One of the following values: + +LDAP_RES_BIND indicates that the LDAPMessage structure contains the result of an +LDAP bind operation. +LDAP_RES_SEARCH_ENTRY indicates that the LDAPMessage structure contains an entry found during +an LDAP search operation. +LDAP_RES_SEARCH_REFERENCE indicates that +the LDAPMessage structure contains an LDAP +v3 search reference (a referral to another LDAP server) found during an LDAP +search operation. +LDAP_RES_SEARCH_RESULT indicates that the LDAPMessage structure contains the result of an +LDAP search operation. +LDAP_RES_MODIFY indicates that the LDAPMessage structure contains the result of an +LDAP modify operation. +LDAP_RES_ADD indicates that the LDAPMessage structure contains the result of an +LDAP add operation. +LDAP_RES_DELETE indicates that the LDAPMessage structure contains the result of an +LDAP delete operation. +LDAP_RES_MODRDN or LDAP_RES_RENAME indicates +that the LDAPMessage structure contains the +result of an LDAP modify DN operation. +LDAP_RES_COMPARE indicates that the LDAPMessage structure contains the result of an +LDAP compare operation. +LDAP_RES_EXTENDED indicates that the LDAPMessage structure contains the result of an +LDAP v3 extended operation. +-1 indicates that the lm argument +is not a pointer to a valid LDAPMessage structure. + + + +Example +Example 21–41 prints +the message type for a result obtained from a synchronous LDAP search operation. +Using <function>ldap_msgtype</function> +#include <stdio.h> +#include <ldap.h> +... +LDAP *ld; +LDAPMessage *result; +int msgtype; +... +/* Perform a search */ +if ( ldap_search_s( ld, MY_SEARCHBASE, LDAP_SCOPE_SUBTREE, MY_FILTER, + NULL, 0, &result ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search_s" ); + return( 1 ); +} + +/* Get and print the message type */ +msgtype = ldap_msgtype( result ); +if ( msgtype != -1 ) { + printf( "Message type: %d\n", msgtype ); +} else { + printf( "An error occurred.\n" ); +} +... + + +See Also +ldap_msgid, ldap_result + , ldap_search_s +
+<function>ldap_multisort_entries</function> +The ldap_multisort_entries function sorts a chain +of entries retrieved from an LDAP search call (ldap_search_s + or ldap_result) by either a specified +set of attributes in the entries or DN. +Syntax +#include <ldap.h> + int ldap_multisort_entries( LDAP *ld, LDAPMessage **chain, + char **attr, LDAP_CMP_CALLBACK *cmp ); + +Parameters +<function>ldap_multisort_entries</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +chain + +Chain of entries returned by the ldap_result or ldap_search_s function. + + + +attr + +Array of attributes to use for sorting the results. If NULL, +results are sorted by DN. + + + +cmp + +Comparison function used when sorting the values. + + + +
+
+Returns +One of the following values: + +0 if successful. +-1 if memory cannot be allocated by this +function. (The error code LDAP_NO_MEMORY is set in +the LDAP structure. To get the error code, +call the ldap_get_lderrno function.) + +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function + + +Example +Example 21–42 +sorts entries first by the roomNumber attribute, then by +the telephoneNumber attribute. +Using <function>ldap_multisort_entries +</function> +#include <stdio.h> +#include <string.h> +#include <ldap.h> +... +LDAP *ld; +LDAPMessage *result; +char *my_searchbase = "dc=example,dc=com"; +char *my_filter = "(sn=Jensen)"; +char *attrs[3]; +attrs[0] = "roomNumber"; +attrs[1] = "telephoneNumber"; +attrs[2] = NULL; +... +/* Search the directory */ +if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter, + NULL, 0, &result ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search_s" ); + return( 1 ); +} + +/* Sort the results, using strcasecmp */ +if ( ldap_multisort_entries( ld, &result, attrs, strcasecmp ) != + LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_multisort_entries" ); + return( 1 ); +} +... + + +See Also +ldap_result, ldap_search_s + , ldap_sort_entries, LDAP_CMP_CALLBACK +
+<function>ldap_name2template</function> +The ldap_name2template function obtains a pointer +to the correct ldap_disptmpl structure. +Syntax +#include <disptmpl.h> + struct ldap_disptmpl * ldap_name2template( char *name + struct ldap_disptmpl *tmpllist ); + +Parameters +<function>ldap_name2template</function> Function +Parameters + + + + +Parameter + +Description + + + + + +name + +Name of the template. + + + +tmpllistp + +Pointer to a list of template data structures. + + + +
+
+Returns + +If successful, 0 is returned and tmpllistp + is configured. +Upon error: + +LDAP_TMPL_ERR_VERSION if buf points +to data that is newer than can be handled. +LDAP_TMPL_ERR_MEM if there is a memory +allocation problem. +LDAP_TMPL_ERR_SYNTAX if there is a problem +with the format of the templates buffer or file. +LDAP_TMPL_ERR_FILE if the file cannot be +read. + + + + +Description +ldap_name2template obtains a pointer to the correct + ldap_disptmpl structure. Links to templates can be defined +by name. +
+<function>ldap_next_attribute</function> +The ldap_next_attribute function returns the name +of the next attribute in an entry returned by ldap_first_entry + or ldap_next_entry. +Syntax +#include <ldap.h> +char * ldap_next_attribute( LDAP *ld, LDAPMessage *entry, + BerElement *ber); + +Parameters +<function>ldap_next_attribute</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +entry + +Pointer to the LDAPMessage structure +representing the entry returned by the ldap_first_entry or ldap_next_entry function. + + + +ber + +A pointer to a BerElement allocated +to keep track of its current position. Pass this pointer to subsequent calls +to ldap_next_attribute to step through the entry's attributes. + + + + +
+
+Returns +One of the following values: + +If successful, returns the name of the next attribute in an +entry. When you are done using this data, you should free the memory by calling +the ldap_memfree function. +If no more attributes exist in the entry, returns a NULL + . +If unsuccessful, returns a NULL and sets +the appropriate error code in the LDAP structure. +To get the error code, call the ldap_get_lderrno function. + + + +Description +The ldap_first_attribute function returns +a pointer to a BerElement. You use this pointer +with ldap_next_attribute to iterate through the list +of elements. After the last call to ldap_next_element, +you should free the BerElement pointer using ldap_ber_free. When calling ldap_ber_free +, make sure to specify that the buffer is not freed (pass 0 for +the freebuf parameter). +Example +See the example under ldap_first_attribute. + +See Also +ldap_first_attribute, ldap_getfirstfilter, ldap_next_entry + +
+<function>ldap_next_disptmpl</function> +The ldap_next_disptmpl function returns the next +template in a list. +Syntax +#include <disptmpl.h> + struct ldap_disptmpl * ldap_next_disptmpl( struct ldap_disptmpl *tmpllist, + struct ldap_disptmpl *tmpl );; + +Parameters +<function>ldap_next_disptmpl</function> Function +Parameters + + + + +Parameter + +Description + + + + + +tmpl + +Defines a template from the template list tmpllist. +A NULL pointer is returned if tmpl is +the last template in the list. + + + +tmpllistp + +Pointer to a list of template data structures typically obtained by +calling ldap_init_templates. + + + +
+
+Returns + +If successful, 0 is returned and tmpllistp + is configured. +Upon error: + +LDAP_TMPL_ERR_VERSION if buf points +to data that is newer than can be handled. +LDAP_TMPL_ERR_MEM if there is a memory +allocation problem. +LDAP_TMPL_ERR_SYNTAX if there is a problem +with the format of the templates buffer or file. +LDAP_TMPL_ERR_FILE if the file cannot be +read. + + + + +Description +ldap_next_disptmpl returns the template following +the previous one in the list of templates pointed to by the parameter tmpllistp +. tmpllistp is typically obtained by calling ldap_init_templates . +See Also +ldap_first_disptmpl +
+<function>ldap_next_entry</function> +The ldap_next_entry function returns a pointer +to the LDAPMessage structure representing +the next directory entry in a chain of search results. +Syntax +#include <ldap.h> + LDAPMessage * ldap_next_entry( LDAP *ld, LDAPMessage *entry ); + +Parameters +<function>ldap_next_entry</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +entry + +Pointer to an LDAPMessage structure +in a chain of search results. + + + +
+
+Returns +One of the following values: + +If successful, returns the pointer to the next LDAPMessage structure of the type LDAP_RES_SEARCH_ENTRY + in a chain of search results. +If no more LDAPMessage structures +of the type LDAP_RES_SEARCH_ENTRY are in the chain or if +the function is unsuccessful, returns a NULLMSG. + + + +Description +The ldap_next_entry function returns a pointer +to the LDAPMessage structure representing +the next directory entry in a chain of search results. You can use this function +in conjunction with the ldap_first_entry function +to iterate through the directory entries in a chain of search results. These +functions skip over any messages in the chain that do not have the type +LDAP_RES_SEARCH_ENTRY as messages containing directory entries have +the type LDAP_RES_SEARCH_ENTRY. +See Also +ldap_first_entry +
+<function>ldap_next_message</function> +The ldap_next_message function returns a pointer +to the next LDAPMessage structure in a chain +of search results. +Syntax +#include <ldap.h> + LDAPMessage * ldap_next_message( LDAP *ld, LDAPMessage *msg ); + +Parameters +<function>ldap_next_message</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +msg + +Pointer to an LDAPMessage structure +in a chain of search results. + + + +
+
+Returns +One of the following values: + +If successful, returns the pointer to the next LDAPMessage structure in a chain of search results. + +If no more LDAPMessage structures +are in the chain or if the function is unsuccessful, returns a NULLMSG. + + + +Description +The ldap_next_message function returns a pointer +to the next LDAPMessage structure in a chain +of search results. You can use this function in conjunction with the ldap_first_message function to iterate through +the chain of search results. You can also call the ldap_msgtype + function to determine if each message contains a matching entry (a +message of the type LDAP_RES_SEARCH_ENTRY ) or a search +reference (a message of the type LDAP_RES_SEARCH_REFERENCE). + +See Also +ldap_first_message, ldap_msgtype +
+<function>ldap_next_reference</function> +The ldap_next_reference function returns a pointer +to the LDAPMessage structure representing +the next search reference in a chain of search results. +Syntax +#include <ldap.h> +LDAPMessage * ldap_next_reference( LDAP *ld, LDAPMessage *ref ); + +Parameters +<function>ldap_next_reference</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +msg + +Pointer to an LDAPMessage structure +in a chain of search results. + + + +
+
+Returns +One of the following values: + +If successful, returns the pointer to the next LDAPMessage structure of the type LDAP_RES_SEARCH_REFERENCE + in a chain of search results. +If no more LDAPMessage structures +of the type LDAP_RES_SEARCH_REFERENCE are in the chain +or if the function is unsuccessful, returns a NULLMSG. + + + +Description +The ldap_next_reference function returns a pointer +to the LDAPMessage structure representing +the next search reference in a chain of search results. You can use this function +in conjunction with the ldap_first_reference function +to iterate through the search references in a chain of search results. +These functions skip over any messages in the chain that do not have +the type LDAP_RES_SEARCH_REFERENCE. Messages containing +search references have the type LDAP_RES_SEARCH_REFERENCE, +continuation references as specified in LDAPv3 that are stored as referral +entries. Like a referral, each continuation reference itself may contain a +number of URLs assumed to be equivalent, and the client should use one of +those URLs. +See Also +ldap_first_reference +
+<function>ldap_next_searchobj</function> +The ldap_next_searchobj function returns the following +search preference in a defined list. +Syntax +#include <ldap.h> + struct ldap_searchobj * ldap_next_searchobj + ( struct ldap_searchobj *sollist, struct ldap_searchobj *so ); + +Parameters +<function>ldap_next_searchobj</function> Function +Parameters + + + + +Parameter + +Description + + + + + +sollist + +Pointer to a list of data structures, typically obtained by calling + ldap_init_searchprefs. + + + +so + +Pointer to the most recent search object returned in the template list + sollist. The search object returned by ldap_next_searchobj + follows this one. + + + +
+
+Returns + +If successful, a pointer to an ldap_searchobj structure. + +A NULL pointer is returned if so is +the last entry in the list. + + +Description +The search object returned by ldap_next_searchobj follows +the one defined by the so parameter. +See Also +ldap_init_searchprefs, ldap_first_searchobj +
+<function>ldap_next_tmplcol</function> +The ldap_next_tmplcol function returns a pointer +to the following item (in the column) within a template. +Syntax +#include <disptmpl.h> + struct ldap_tmplitem * ldap_next_tmplcol( struct ldap_disptmpl *tmpl, + struct ldap_tmplitem *row, struct ldap_tmplitem *col ); + +Parameters +<function>ldap_next_tmplcol</function> Function +Parameters + + + + +Parameter + +Description + + + + + +tmpl + +The name of the template to be retrieved. + + + +row + +The row in which the item is to be retrieved from. + + + +col + +The column in which the item is to be retrieved from. + + + +
+
+Returns + +If successful, a pointer to an ldap_tmplitem structure. + +A NULL pointer on error or if col was +the last item. + + +Description +ldap_next_tmplcol returns a pointer to the next +item (in the column) of the row, defined by row, within +the template defined by tmpl. +See Also +ldap_first_tmplcol +
+<function>ldap_next_tmplrow</function> +The ldap_next_tmplrow function returns a pointer +to the following row in a template. +Syntax +#include <disptmpl.h> + struct ldap_tmplitem * ldap_next_tmplrow( struct ldap_disptmpl *tmpl, + struct ldap_tmplitem *row ); + +Parameters +<function>ldap_next_tmplrow</function> Function +Parameters + + + + +Parameter + +Description + + + + + +tmpl + +The name of the template to be retrieved. + + + +row + +The row in the template to be retrieved. + + + +
+
+Returns + +If successful, a pointer to an ldap_tmplitem structure. + +A NULL pointer on error. + + +Description +ldap_next_tmplrow returns a pointer to the row +that follows the one defined by row in the template defined +by tmpl . +
+<function>ldap_oc2template</function> +The ldap_oc2template function obtains a pointer +to the correct ldap_disptmpl structure. +Syntax +#include <disptmpl.h> + struct ldap_disptmpl * ldap_oc2template( char **oclist, + struct ldap_disptmpl *tmpllist ); + +Parameters +<function>ldap_oc2template</function> Function +Parameters + + + + +Parameter + +Description + + + + + +oclist + +A NULL terminated array of strings that contains +the values of the objectClass attribute of the entry. + + + + +tmpllistp + +Pointer to a list of template data structures. + + + +
+
+Returns + +Pointer to the first template where all of the object classes +listed in one of the template's dt_oclist elements are +contained in oclist. +A NULL pointer if no appropriate template +is found. + + +Description +ldap_oc2templatesearches tmpllist for +the best template to use to display an entry that has a specific set of +objectClass values. +
+<function>ldap_open</function> +This function is deprecated and should not be used. Use ldap_init or prldap_init (IPv6) +instead. +The ldap_open function opens a connection to an +LDAP server and allocates an LDAP structure +which is used to identify the connection and maintain per-connection information. + +Syntax +#include <ldap-deprecated.h> + ldap_open( const char *host, int port ); + +Parameters +<function>ldap_open</function> Function +Parameters + + + + +Parameter + +Description + + + + + +host + +The hostname on which the LDAP server is running. It may contain a blank-separated +list of hosts to try to connect to, and each host may optionally be of the +form host:port. If +present, port overrides the port parameter. Upon +successfully making a connection to an LDAP server, ldap_open returns +a pointer to an LDAP structure, which +should be passed to subsequent calls ldap_bind, ldap_search + + + +port + +The port number to which to connect. If the default IANA-assigned port +of 389 is desired, LDAP_PORT should be specified as the +value of port. + + + +
+
+Description +Please use a newer version of this function, ldap_init + or prldap_init (IPv6). +
+<function>ldap_parse_authzid_control +</function> +The ldap_parse_authzid_control function parses +the authorization identity bind response control retrieved from the server +to extract the authorization ID. +Syntax +#include <ldap.h> +LDAP_API(int) LDAP_CALL ldap_parse_authzid_control( LDAP *ld, + LDAPControl **ctrlp, char **authzid ); + +Parameters +<function>ldap_parse_authzid_control</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +ctrlp + +Pointer to an LDAPControl structure +retrieved from the server. + + + +authzid + +Pointer to string holding the authorization ID. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_NO_MEMORY if memory cannot be +allocated to decode the control returned by the server. +LDAP_DECODING_ERROR if an error occurred +when decoding the BER-encoded message. +LDAP_CONTROL_NOT_FOUND if no control +can be found in the response returned from the server. +LDAP_NOT_SUPPORTED if controls are +included in your request (for example, as a session preference) and your LDAP +client does not specify that it is using the LDAP v3. Make sure that you set +the version of your LDAP client to version 3 before calling this function. + + + +See Also +ldap_create_authzid_control + +
+<function>ldap_parse_entrychange_control</function> +The ldap_parse_entrychange_control function examines +a list of controls returned from a persistent search operation, retrieves +an entry change control, and parses that control for information (such as +the type of change made to the entry and the change number). +This function implements an extension to the LDAP v3. Entry change +notification is an optional feature; it may not be supported on all LDAP servers. +Call this function when interacting with LDAP servers that support this LDAP +v3 extension. +Syntax +#include <ldap.h> + int ldap_parse_entrychange_control( LDAP *ld, + LDAPControl **ctrls, int *chgtypep, char **prevdnp, + int *chgnumpresentp, long *chgnump ); + +Parameters +<function>ldap_parse_entrychange_control</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +ctrlp + +An array of controls returned by the server. You obtain these controls +by calling the ldap_get_entry_controls function +on an entry returned by the server. + + + +changetypes + +Pointer to an integer specifying the type of change made to the entry. +This field can have one of the following values: + +LDAP_CHANGETYPE_ADD specifies that the +entry was added to the directory. +LDAP_CHANGETYPE_DELETE specifies that the +entry was deleted from the directory. +LDAP_CHANGETYPE_MODIFY specifies that the +entry was modified. +LDAP_CHANGETYPE_MODDN specifies that the +DN or RDN of the entry was changed (a modify RDN or modify DN operation was +performed). + + + + + +prevdnp + +Pointer to the previous DN of the entry, if the changetypes argument +is LDAP_CHANGETYPE_MODDN. If the changetypes argument +has a different value, this argument is set to NULL. When +done, you can free this by calling the ldap_memfree function. + + + + +chgnumpresentp + +Pointer to an integer specifying whether or not to the change number +is included in the control. The parameter can have the following possible +values: + +0 specifies that the change number is not +included. +A non-zero value specifies that the change number is included +and is available as the chgnump argument. + + + + + +chgnump + +Pointer to the change number identifying the change made to the entry, +if chgnumpresentp points to a non-zero value. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_DECODING_ERROR if an error occurred +when BER-decoding the control. + + +Description +The ldap_parse_entrychange_control function can +be called: + +To parse an entry returned from a persistent search operation +and retrieve an entry change control. +After receiving an entry from a persistent search and retrieving +the controls from the entry. Call ldap_get_entry_controls + to get the controls. + + +See Also +ldap_create_persistentsearch_control, ldap_get_entry_controls +
+<function>ldap_parse_extended_result</function> +The ldap_parse_extended_result function parses +the results of an LDAP extended operation and retrieves the object identifier +(OID) and data returned by the server. +This function implements an extension to the LDAP v3. Extended +operations might not be supported on all LDAP servers. Call this function +only when interacting with LDAP servers that support this LDAP v3 extension. + +Syntax +#include <ldap.h> + int ldap_parse_extended_result( LDAP *ld, LDAPMessage *res, + char **retoidp, struct berval **retdatap, int freeit ); + +Parameters +<function>ldap_parse_extended_result</function> Function +Parameters + + + + +Parameters + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +res + +Pointer to the LDAPMessage structure +containing the results of an LDAP operation. + + + +retoidp + +Pointer to the OID returned by the server after performing the extended +operation. When done, you can free this by calling the ldap_memfree + function. + + + +retdatap + +Pointer to the pointer to a berval structure +containing the data returned by the server after performing the extended operation. +When done, you can free this by calling the ber_bvfree +function. + + + +freeit + +Specifies whether or not to free the results of the operation (the LDAPMessage structure specified by the res argument). +The parameter can have the following possible values: + +0 specifies that the result should not +be freed. +A non-zero value specifies that the result should be freed. + + + + + + +
+
+Returns +One of the following values, which indicates the result of parsing the +server’s response: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_DECODING_ERROR if an error occurred +when decoding the BER-encoded results from the server. +LDAP_NOT_SUPPORTED if controls are +included in your request (for example, as a session preference) and your LDAP +client does not specify that it is using the LDAP v3. Make sure that you set +the version of your LDAP client to version 3 before calling this function. + + +This value does not apply to the operation itself. + +Description +ldap_parse_extended_result parses the server’s +response to an extended operation. After you call the ldap_extended_operation + and the ldap_result functions, +you can pass the results to ldap_parse_extended_result. +This function gets the following data from the server’s response: + +The extended operation OID received from the server is passed +back as the retoidp argument. +The data received from the server is passed back in the berval structure as the retdatap argument. + +The LDAP result code for the LDAP extended operation is placed +in the ld structure. You can get the result code by calling +the ldap_get_lderrno function.For +a list of possible result codes for an LDAP extended operation, see ldap_extended_operation_s . + +The LDAP server must support the extended operation. &cnDirectoryServer; supports +a server plug-in interface that you can use to add support for extended operations. + + +See Also +ldap_extended_operation_s, ldap_get_lderrno +
+<function>ldap_parse_passwd</function> +The ldap_parse_passwd function lets you examine +the result of an LDAP Password Modify extended operation to obtain the password +generated by the server when you reset a password without providing a new +password value. +Syntax +#include <ldap.h> +LDAP_API(int) LDAP_CALL ldap_parse_passwd( LDAP *ld, LDAPMessage *result, + struct berval *genpasswd ); + +Parameters +<function>ldap_parse_passwd</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +result + +Pointer to the message retrieved using the message ID from ldap_passwd. + + + +genpasswd + +Pointer to the BER value structure to hold the password generated by +the server. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_NO_MEMORY if memory cannot be +allocated for the authorization identity. +LDAP_DECODING_ERROR if an error occurred +when decoding the BER-encoded message. +LDAP_NOT_SUPPORTED if your LDAP client +does not specify that it is using LDAP v3.Make sure that you +set the version of your LDAP client to version 3 before calling this function. + + + +
+<function>ldap_parse_passwd_result</function> +The ldap_parse_passwd_result function lets you +examine the result of an LDAP Password Modify extended operation to obtain +the password generated by the server when you reset a password without providing +a new password value. +Syntax +#include <ldap.h> +LDAP_API(int) LDAP_CALL ldap_parse_passwd_result( LDAP *ld, int *msgidp, + struct timeval *timeout, struct berval *genpasswd ); + +Parameters +<function>ldap_parse_passwd_result</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +msgidp + +Pointer to the message ID retrieved using ldap_passwd +. + + + +timeout + +Specifies a maximum interval to wait for the selection to complete. +If timeout is a NULL pointer, the +select blocks indefinitely. To effect a poll, the timeout parameter +should be a non-NULL pointer, pointing to a zero-valued +timeval structure. + + + +genpasswd + +Pointer to the BER value structure to hold the password generated by +the server. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_NO_MEMORY if memory cannot be +allocated for the authorization identity. +LDAP_DECODING_ERROR if an error occurred +when decoding the BER-encoded message. +LDAP_NOT_SUPPORTED if your LDAP client +does not specify that it is using LDAP v3.Make sure that you +set the version of your LDAP client to version 3 before calling this function. + + + +
+<function>ldap_parse_pwdpolicy_control +</function> +The ldap_parse_pwdpolicy_control function parses +information about the password policy relative to a user account contained +in a control returned with a bind, add, modify, or compare result after the ldap_create_userstatus_control is +used to create a request control sent to the server. The ldap_parse_pwdpolicy_control + function populates an LDAPpwdpolicy structure. + +Syntax +#include <ldap.h> +LDAP_API(int) LDAP_CALL ldap_parse_pwdpolicy_control( LDAP *ld, + LDAPControl **ctrlp, LDAPpwdpolicy *pp ); + +Parameters +<function>ldap_parse_pwdpolicy_control</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +ctrlp + +Pointer to an LDAPControl structure +retrieved from the server. + + + +pp + +Pointer to an LDAPpwdpolicy structure +to hold the information about password policy. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_NO_MEMORY if memory cannot be +allocated to decode the control returned by the server. +LDAP_DECODING_ERROR if an error occurred +when decoding the BER-encoded message. +LDAP_CONTROL_NOT_FOUND if no control +can be found in the response returned from the server. +LDAP_NOT_SUPPORTED if controls are +included in your request (for example, as a session preference) and your LDAP +client does not specify that it is using the LDAP v3. Make sure that you set +the version of your LDAP client to version 3 before calling this function. + + + +See Also +ldap_create_pwdpolicy_control +, LDAPpwdpolicy +
+<function>ldap_parse_reference</function> +The ldap_parse_reference function parses search +references from the results received from an LDAP server. +Search references are part of the LDAP v3. When calling this function, +make sure that you are working with a server that supports the LDAP v3. + +Syntax +#include <ldap.h> + int ldap_parse_reference( LDAP *ld, LDAPMessage *ref, + char ***referralsp, LDAPControl ***serverctrlsp, + int freeit ); + +Parameters +<function>ldap_parse_reference</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +ref + +Pointer to an LDAPMessage structure +of the type LDAP_RES_SEARCH_REFERENCE. + + + +referralsp + +Pointer to an array of strings representing the referrals found by an +LDAP search operation and returned by the server (applicable only if the LDAP +operation was a search operation). When done, you can free this by calling +the ldap_value_free function. + + + +serverctrlsp + +Pointer to an array of LDAPControl structures, +which represent the LDAP v3 server controls returned by the server. When done, +you can free this by calling the ldap_controls_free function. + + + + +freeit + +Specifies whether or not to free the results of the operation (the LDAPMessage structure specified by the res argument). +The parameter can have the following possible values: + +0 specifies that the result should not +be freed. +A non-zero value specifies that the result should be freed. + + + + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_DECODING_ERROR if an error occurred +when decoding the BER-encoded results from the server. +LDAP_NO_MEMORY if memory cannot be +allocated. + + +Description +The ldap_parse_reference function parses the referral +URLs from an LDAPMessage structure of the +type LDAP_RES_SEARCH_REFERENCE, continuation references +as specified in LDAPv3 that are stored as referral entries. Like a referral, +each continuation reference itself may contain a number of URLs assumed to +be equivalent, and the client should use one of those URLs. +
+<function>ldap_parse_result</function> +The ldap_parse_result function parses the results +of an LDAP operation received from an LDAP server. +Syntax +#include <ldap.h> +int ldap_parse_result( LDAP *ld, LDAPMessage *res, + int *errcodep, char **matcheddnp, char **errmsgp, + char ***referralsp, LDAPControl ***serverctrlsp, int freeit); + +Parameters +<function>ldap_parse_result</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +res + +Pointer to the LDAPMessage structure +containing the results of an LDAP operation. + + + +errcodep + +Pointer to the LDAP result code specifying the result of the operation. + + + + +matcheddnp + +Pointer to a string specifying the portion of a DN that finds an existing +entry (in cases where the server cannot find the entry specified by a DN). +When done, you can free this by calling the ldap_memfree + function. + + + +errmsgp + +Pointer to an additional error message string sent from the server. +When done, you can free this by calling the ldap_memfree + function. + + + +referralsp + +Pointer to an array of strings representing the referrals returned by +the server. When done, you can free this by calling the +ldap_value_free function. + + + +serverctrlsp + +Pointer to an array of LDAPControl structures, +which represent the LDAPv3 server controls returned by the server. When done, +you can free this by calling the ldap_controls_free function. + + + + +freeit + +Specifies whether or not to automatically free the results of the operation +(the LDAPMessage structure specified by the + res argument). The parameter can have the following possible +values: + +0 specifies that the result should not +be freed. +A non-zero value specifies that the result should be freed. + + + + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_NO_RESULTS_RETURNED if the specified LDAPMessage structure does not contain the result +of an LDAP operation (for example, if it contains an entry, search reference, +or chain of search results instead of the result of an LDAP operation). + +LDAP_MORE_RESULTS_TO_RETURN if the +result in the LDAPMessage structure is part +of a chain of results and the last result is not included. +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_DECODING_ERROR if an error occurred +when decoding the BER-encoded results from the server. +LDAP_NO_MEMORY if memory cannot be +allocated. + + +Description +The ldap_parse_result function parses the results +of an LDAP operation (received from an LDAP server) and retrieves: + +The LDAP result code that indicates the result of the LDAP +operation (errcodep). +An additional error message (optional) +sent by the server (errmsgp). +The portion of the DN that finds an entry, if the server is +unable to find an entry from a DN that you specify (matcheddnp). + +A set of referrals, if the server does not contain the entries +that you’ve specified and if the server is configured to refer clients +to other servers (referralsp). +A set of server response controls that are relevant to the +operation (serverctrlsp).Calling this function +creates an array of LDAPControl structures +that you can pass to subsequent API functions (such as the ldap_parse_sort_control function. + +This function is not intended to be used to parse entries and +search references. Use the ldap_msgtype function +to determine the type of result contained in the LDAPMessage + structure. If the result is an entry returned as a search result, +call the ldap_first_entry function to retrieve +the entry. If the result is a search reference, call the +ldap_parse_reference function to retrieve the reference. + +See Also +ldap_result +
+<function>ldap_parse_sasl_bind_result</function> +The ldap_parse_sasl_bind_result function parses +the results of an LDAP SASL bind operation and retrieves data returned by +the server. +SASL authentication is part of the LDAP v3. When calling this +function, make sure that you are working with a server that supports the LDAP +v3. +Syntax +#include <ldap.h> +int ldap_parse_sasl_bind_result( LDAP *ld, LDAPMessage *res, + struct berval **servercredp, int freeit ); + +Parameters +<function>ldap_parse_sals_bind_result</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +res + +Pointer to the LDAPMessage structure +containing the results of an LDAP operation. + + + +servercredp + +Pointer to a pointer to an berval structure +containing any challenge or credentials returned by the server. When done, +you can free this by calling the ber_bvfree function. + + + + +freeit + +Specifies whether or not to free the results of the operation (the LDAPMessage structure specified by the res argument). +The parameter can have the following possible values: + +0 specifies that the result should not +be freed. +A non-zero value specifies that the result should be freed. + + + + + + +
+
+Returns +One of the following values, which indicates the result of parsing the +server’s response: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_DECODING_ERROR if an error occurred +when decoding the BER-encoded message. +LDAP_NOT_SUPPORTED if controls are +included in your request (for example, as a session preference) and your LDAP +client does not specify that it is using the LDAP v3. Make sure that you set +the version of your LDAP client to version 3 before calling this function. + + +This value does not apply to the SASL bind operation itself) + + +Description +After you call the ldap_sasl_bind function +and the ldap_result function, you can pass +the results to ldap_parse_sasl_bind_result for +parsing. This function gets the following data from the server’s response: + +The challenge or credentials sent back from the server are +passed back in the berval structure as the +servercredp argument. +The LDAP result code for the SASL bind operation is placed +in the ld structure. You can get the result code by calling +the ldap_get_lderrno function. (If the result +code is LDAP_SASL_BIND_IN_PROGRESS , you can call ldap_sasl_bind again to send a response to the server’s +challenge and call ldap_result and ldap_parse_sasl_bind_result again to get the next +challenge from the server. For a list of possible result codes for an LDAP +SASL bind operation, see ldap_sasl_bind. + + +The LDAP server must support authentication through SASL mechanisms. &cnDirectoryServer; supports +a plug-in interface that you can use to add SASL support to the server. + + +See Also +ldap_sasl_bind, +ldap_get_lderrno +
+<function>ldap_parse_sort_control</function> + +C SDK functions +ldap_parse_sort_control + +ldap_parse_sort_control + +The parse_sort_control function parses the result +returned from a search operation that used a server control for sorting search +results. +This function implements an extension to the LDAP v3. Server-side +sorting is an optional feature; it may not be supported on all LDAP servers. +Call this function when interacting with LDAP servers that support this LDAP +v3 extension +Syntax +#include <ldap.h> + int ldap_parse_sort_control( LDAP *ld, LDAPControl **ctrls, + unsigned long *result, char **attribute ); + +Parameters +<function>ldap_parse_sort_control</function> Function +Parameters + + + + +Parameters + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +ctrls + +An array of controls returned by the server. You obtain these controls +by calling the ldap_parse_result function +on the set of results returned by the server. + + + +result + +Pointer to the sort control result code retrieved by this function. + + + + +attribute + +If the sorting operation fails, the function sets this to point to the +name of the attribute that caused the failure. When done, you can free this +by calling the ldap_memfree function. + + + + +
+
+Returns +One of the following values, which indicates the result of parsing the +server’s response: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_NO_MEMORY if memory cannot be +allocated to decode the control returned by the server. +LDAP_DECODING_ERROR if an error occurred +when decoding the BER-encoded message. +LDAP_CONTROL_NOT_FOUND if no control +can be found in the response returned from the server. + + +Description +Call the ldap_parse_sort_control function as part +of the process of retrieving sorted search results from a server. First, though, +call ldap_result to get the results, and + ldap_parse_result to parse the server controls +from the results. +See Also +ldap_create_sort_control +
+<function>ldap_parse_userstatus_control +</function> + +C SDK functions +ldap_parse_userstatus_control + +ldap_parse_userstatus_control + +The ldap_parse_userstatus_control function parses +information about the status of a user account contained in a control returned +with an entry resulting from a search request that included the control created +with ldap_create_userstatus_control +. The ldap_parse_userstatus_control function +populates an LDAPuserstatus structure. +Syntax +#include <ldap.h> +LDAP_API(int) LDAP_CALL ldap_parse_userstatus_control( LDAP *ld, + LDAPControl **ctrlp, LDAPuserstatus *us ); + +Parameters +<function>ldap_parse_userstatus_control</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +ctrlp + +Pointer to an LDAPControl structure +retrieved with ldap_get_entry_controls. + + + + +us + +Pointer to an LDAPuserstatus structure +to hold the information about account status. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_NO_MEMORY if memory cannot be +allocated to decode the control returned by the server. +LDAP_DECODING_ERROR if an error occurred +when decoding the BER-encoded message. +LDAP_CONTROL_NOT_FOUND if no control +can be found in the response returned from the server. +LDAP_NOT_SUPPORTED if controls are +included in your request (for example, as a session preference) and your LDAP +client does not specify that it is using the LDAP v3. Make sure that you set +the version of your LDAP client to version 3 before calling this function. + + + +See Also +ldap_create_userstatus_control +, LDAPuserstatus + +
+<function>ldap_parse_whoami</function> + +C SDK functions +ldap_parse_whoami + +ldap_parse_whoami + +The ldap_parse_whoami function retrieves the authorization +identity from the result of an asynchronous Who am I? extended operation request. + +Syntax +#include <ldap.h> +LDAP_API(int) LDAP_CALL ldap_parse_whoami_result( LDAP *ld, + LDAPMessage *result, char **authzid ); + +Parameters +<function>ldap_parse_whoami</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +result + +Pointer to the message retrieved using the message ID from ldap_whoami. + + + +authzid + +Pointer to the string to hold the authorization identity retrieved for +the connection. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_NO_MEMORY if memory cannot be +allocated for the authorization identity. +LDAP_DECODING_ERROR if an error occurred +when decoding the BER-encoded message. +LDAP_NOT_SUPPORTED if your LDAP client +does not specify that it is using LDAP v3. Make sure that you set the version +of your LDAP client to version 3 before calling this function. + + +
+<function>ldap_parse_whoami_result</function> + +C SDK functions +ldap_parse_whoami_result + +ldap_parse_whoami_result + +The ldap_parse_whoami_result function retrieves +the authorization identity from the result of an asynchronous Who am I? extended +operation request. +Syntax +#include <ldap.h> +LDAP_API(int) LDAP_CALL ldap_parse_whoami_result( LDAP *ld, int *msgidp, + struct timeval *timeout, char **authzid ); + +Parameters +<function>ldap_parse_whoami_result</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +msgidp + +Pointer to the message ID retrieved using ldap_whoami +. + + + +timeout + +Specifies a maximum interval to wait for the selection to complete. +If timeout is a NULL pointer, the +select blocks indefinitely. To effect a poll, the timeout parameter +should be a non-NULL pointer, pointing to a zero-valued +timeval structure. + + + +authzid + +Pointer to the string to hold the authorization identity retrieved for +the connection. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_NO_MEMORY if memory cannot be +allocated for the authorization identity. +LDAP_DECODING_ERROR if an error occurred +when decoding the BER-encoded message. +LDAP_NOT_SUPPORTED if your LDAP client +does not specify that it is using LDAP v3. Make sure that you set the version +of your LDAP client to version 3 before calling this function. + + +
+<function>ldap_parse_virtuallist_control</function> + +C SDK functions +ldap_parse_virtuallist_control + +ldap_parse_virtuallist_control + +The ldap_parse_virtuallist_control function parses +the result returned from a search operation that used a server control for +virtual list views. +This function implements an extension to the LDAP v3. A virtual +list view is an optional LDAP server feature that may not be supported +on all LDAP servers. +Syntax +#include <ldap.h> + int ldap_parse_virtuallist_control( LDAP *ld, + LDAPControl **ctrls, unsigned long *target_posp, + unsigned long *list_sizep, int *errcodep ); + +Parameters +<function>ldap_parse_virtuallist_control</function> Function +Parameters + + + + +Parameters + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +ctrls + +An array of controls returned by the server. You obtain these controls +by calling the ldap_parse_result function +on the set of results returned by the server. + + + +target_posp + +Pointer to an unsigned long that is set by the function. The function +sets this to the index or offset of the selected entry in the list of entries. + + + + +list_sizep + +Pointer to an unsigned long that is set by the function. The function +sets this to the number of entries in the total number of entries in the entire +list (not just the subset). + + + +errcodep + +Pointer to the sort control result code retrieved by this function. + + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_NO_MEMORY if memory cannot be +allocated to decode the control returned by the server. +LDAP_DECODING_ERROR if an error occurred +when decoding the BER-encoded message. +LDAP_CONTROL_NOT_FOUND if no control +can be found in the response returned from the server. +LDAP_NOT_SUPPORTED if controls are +included in your request (for example, as a session preference) and your LDAP +client does not specify that it is using the LDAP v3. Make sure that you set +the version of your LDAP client to version 3 before calling this function. + + + +Description +The ldap_parse_virtuallist_control function can +be called: + +As part of the process of retrieving a subset of entries from +a list when working with a virtual list view box. +After, calling ldap_result to +get the results, and ldap_parse_result to +parse the server controls from the results. + + +See Also +ldap_create_virtuallist_control + +
+<function>ldap_passwd</function> + +C SDK functions +ldap_passwd + +ldap_passwd + +The ldap_passwd asynchronous function allows you +to perform an LDAP Password Modify extended operation, as defined in RFC 3062. +Syntax +#include <ldap.h> +int ldap_passwd( LDAP *ld, struct berval *userid, + struct berval *oldpasswd, struct berval *newpasswd, + LDAPControl **serverctrls, LDAPControl **clientctrls, + int *msgidp ); + +Parameters +<function>ldap_passwd</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +userid + +DN of the user whose password you want to modify. + + + +oldpasswd + +Old password used before expiration. +If the password has not yet expired, this is the current password. + + + + +newpasswd + +New password to use after modification + + + +serverctrls + +Pointer to an array of LDAPControl structures +representing LDAP server controls that apply to this LDAP operation. If you +do not want to pass any server controls, specify NULL for +this argument. + + + +clientctrls + +Pointer to an array of LDAPControl structures +representing LDAP client controls that apply to this LDAP operation. If you +do not want to pass any client controls, specify NULL for +this argument. + + + +msgidp + +Pointer to an integer to be set to the message ID of the operation. +To check the result of this operation, call the ldap_result + and ldap_parse_passwd function, +or ldap_parse_passwd_result function. + + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the control. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_NOT_SUPPORTED if your LDAP client +does not specify that it is using LDAP v3.Make sure that you +set the version of your LDAP client to version 3 before calling this function. + + + +
+<function>ldap_passwd_s</function> + +C SDK functions +ldap_passwd_s + +ldap_passwd_s + +The ldap_passwd_s synchronous function allows you +to perform an LDAP Password Modify extended operation, as defined in RFC 3062. +Syntax +#include <ldap.h> +int ldap_passwd_s( LDAP *ld, struct berval *userid, + struct berval *oldpasswd, struct berval *newpasswd, + struct berval *genpasswd, LDAPControl **serverctrls, + LDAPControl **clientctrls ); + +Parameters +<function>ldap_passwd</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +userid + +DN of the user whose password you want to modify. + + + +oldpasswd + +Old password used before expiration. +If the password has not yet expired, this is the current password. + + + + +newpasswd + +New password to use after modification + + + +genpasswd + +New password generated by the server when an expired password is reset, +but no newpasswd value is provided. + + + +serverctrls + +Pointer to an array of LDAPControl structures +representing LDAP server controls that apply to this LDAP operation. If you +do not want to pass any server controls, specify NULL for +this argument. + + + +clientctrls + +Pointer to an array of LDAPControl structures +representing LDAP client controls that apply to this LDAP operation. If you +do not want to pass any client controls, specify NULL for +this argument. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the control. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_NOT_SUPPORTED if your LDAP client +does not specify that it is using LDAP v3.Make sure that you +set the version of your LDAP client to version 3 before calling this function. + + + +
+<function>ldap_perror</function> + +C SDK functions +ldap_perror + +ldap_perror + +This function is deprecated and should not be used. It is included +in ldap-deprecated.h for backward-compatibility. Use ldap_get_lderrno instead. +The ldap_perror function prints, to standard output, +the last LDAP error message. +Syntax +#include <ldap-deprecated.h> + void ldap_perror( LDAP *ld, const char *s ); + +Parameters +<function>ldap_perror</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +s + +Optional text to print out before printing the error message. + + + + +
+
+Description +Use the newer version of this function, ldap_get_lderrno + . +Example +Example 21–43 prints +out an error message if the search operation cannot complete successfully. +Using <function>ldap_perror</function> +... +if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter, + get_attr, 0, &result ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search_s" ); + return( 1 ); +... + + +See Also +ldap_get_lderrno, ldap_err2string, ldap_result2error +, ldap_set_lderrno +
+<function>ldap_rename</function> + +C SDK functions +ldap_rename + +ldap_rename + +The ldap_rename function changes the DN of an entry +in the directory asynchronously. +ldap_rename is a new version of the ldap_modrdn2 function. If you are writing a new +LDAP client, you should call ldap_rename. +Syntax +#include <ldap.h> +int ldap_rename( LDAP *ld, const char *dn, const char *newrdn, + const char *newparent, int deleteoldrdn, + LDAPControl **serverctrls, LDAPControl **clientctrls, + int *msgidp ); + +Parameters +<function>ldap_rename</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the entry to rename. + + + +newrdn + +New Relative Distinguished Name (RDN) to assign to the entry. + + + + +newparent + +DN of the new parent entry you want to move the entry under. Pass +NULL if you do not want to move the entry to a different location +in the directory tree. + + + +deleteoldrdn + +Specifies whether or not the old RDN is retained as an attribute of +the entry. For example, an entry has the following values for the cn attribute: + +cn: Barbara Jensen +cn: Babs Jensen +If you change the RDN to cn=Barbie Jensen and pass + 1 as deleteoldrdn, the resulting entry +has the following values: +cn: Barbie Jensen +cn: Babs Jensen +If instead you pass 0 as deleteoldrdn, +the Barbara Jensen value is not removed from the entry: +cn: Barbie Jensen +cn: Babs Jensen +cn: Barbara Jensen +So, if this is a non-zero value, the old RDN is not retained as a value +in the entry. If 0, the old RDN is retained as an attribute +in the entry. + + + +serverctrls + +Pointer to an array of LDAPControl structures +representing LDAP server controls that apply to this LDAP operation. If you +do not want to pass any server controls, specify NULL for +this argument. + + + +clientctrls + +Pointer to an array of LDAPControl structures +representing LDAP client controls that apply to this LDAP operation. If you +do not want to pass any client controls, specify NULL for +this argument. + + + +msgidp + +Pointer to an integer that will be set to the message ID of the LDAP +operation. To check the result of this operation, call the ldap_result and ldap_parse_result + functions. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_NO_MEMORY if memory cannot be +allocated to decode the control returned by the server. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the request. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_NOT_SUPPORTED if controls are +included in your request (for example, as a session preference) and your LDAP +client does not specify that it is using the LDAP v3. Make sure that you set +the version of your LDAP client to version 3 before calling this function. + + + +Description +The ldap_rename changes the DN of an entry in the +directory and allows you to move the entry under a different parent entry +in the directory tree. ldap_rename is an asynchronous +function; it does not directly return results. In order to get the results +of the LDAP rename operation, you need to call the ldap_result + function and the ldap_parse_result function. +If you want the results to be returned directly by the function, call the +synchronous function ldap_rename_s instead. + +See Also +ldap_rename_s, ldap_result +, ldap_parse_result +
+<function>ldap_rename_s</function> + +C SDK functions +ldap_rename_s + +ldap_rename_s + +The ldap_rename_s function changes the DN of an +entry in the directory synchronously. +ldap_rename_s is a new version of the ldap_modrdn2_s function. If you are writing a new +LDAP client, you should call ldap_rename_s. +Syntax +#include <ldap.h> + int ldap_rename_s( LDAP *ld, const char *dn, const char *newrdn, + const char *newparent, int deleteoldrdn, + LDAPControl **serverctrls, LDAPControl **clientctrls ); + +Parameters +<function>ldap_rename</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the entry to rename. + + + +newrdn + +New Relative Distinguished Name (RDN) to assign to the entry. + + + + +newparent + +DN of the new parent entry you want to move the entry under. Pass +NULL if you do not want to move the entry to a different location +in the directory tree. + + + +deleteoldrdn + +Specifies whether or not the old RDN is retained as an attribute of +the entry. For example, an entry has the following values for the cn attribute: + +cn: Barbara Jensen +cn: Babs Jensen +If you change the RDN to cn=Barbie Jensen and pass + 1 as deleteoldrdn, the resulting entry +has the following values: +cn: Barbie Jensen +cn: Babs Jensen +If instead you pass 0 as deleteoldrdn, +the Barbara Jensen value is not removed from the entry: +cn: Barbie Jensen +cn: Babs Jensen +cn: Barbara Jensen +So, if this is a non-zero value, the old RDN is not retained as a value +in the entry. If 0, the old RDN is retained as an attribute +in the entry. + + + +serverctrls + +Pointer to an array of LDAPControl structures +representing LDAP server controls that apply to this operation. If you do +not want to pass any server controls, specify NULL for +this argument. + + + +clientctrls + +Pointer to an array of LDAPControl structures +representing LDAP client controls that apply to this operation. If you do +not want to pass any client controls, specify NULL for +this argument. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_NO_MEMORY if memory cannot be +allocated to decode the control returned by the server. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the request. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_LOCAL_ERROR if an error occurred +when receiving the results from the server. +LDAP_DECODING_ERROR if an error occurred +when decoding the BER-encoded results from the server. +LDAP_NOT_SUPPORTED if controls are +included in your request (for example, as a session preference) and your LDAP +client does not specify that it is using the LDAPv3. Make sure that you set +the version of your LDAP client to version 3 before calling this function. + + +&cnDirectoryServer; and other LDAP server products may send result +codes in addition to those described. For example, the server may have loaded +a plug-in that returns custom result codes. Check your LDAP server documentation +for other result codes. + +Description +The ldap_rename_s changes the DN of an entry in +the directory and allows you to move the entry under a different parent entry +in the directory tree. The function ldap_rename_s is +synchronous; it directly returns the results of the operation. If you want +to perform other operations while waiting for the results of this operation, +call the asynchronous function ldap_rename. + +See Also +ldap_rename +
+<function>ldap_result</function> + +C SDK functions +ldap_result + +ldap_result + +The function ldap_result waits for and returns +the result of an LDAP operation initiated by one of the asynchronous LDAP +API functions. +Syntax +#include <ldap.h> + int ldap_result( LDAP *ld, int msgid, int all, + struct timeval *timeout, LDAPMessage **result ); + +Parameters +<function>ldap_result</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +msgid + +Asynchronous functions return a unique message ID. This parameter takes +message ID of the operation for which you want the results. To check any operation, +pass LDAP_RES_ANY as the value of this parameter. + + + + +all + +Specifies how the results of a search are returned. This parameter can +have the following values: + +0 specifies that the results are returned +one entry at a time, using separate calls to ldap_result. + +A non-zero value specifies that all results are returned at +the same time (after the final search result is obtained by the library). + + + + + + +timeout + +Specifies a maximum interval to wait for the selection to complete. +If timeout is a NULL pointer, the +select blocks indefinitely. To effect a poll, the timeout parameter +should be a non-NULL pointer, pointing to a zero-valued +timeval structure. + + + +result + +Result of the operation. To interpret the results, pass this to the +LDAP parsing routines, such as ldap_result2error, + ldap_parse_result, and +ldap_first_entry. + + + +
+
+Returns +One of the following values: + +LDAP_RES_BIND indicates that the LDAPMessage structure contains the result of an +LDAP bind operation. +LDAP_RES_SEARCH_ENTRY indicates that the LDAPMessage structure contains an entry found during +an LDAP search operation. +LDAP_RES_SEARCH_REFERENCE indicates that +the LDAPMessage structure contains an LDAPv3 +search reference (a referral to another LDAP server) found during an LDAP +search operation. +LDAP_RES_SEARCH_RESULT indicates that the LDAPMessage structure contains the result of an +LDAP search operation. +LDAP_RES_MODIFY indicates that the LDAPMessage structure contains the result of an +LDAP modify operation. +LDAP_RES_ADD indicates that the LDAPMessage structure contains the result of an +LDAP add operation. +LDAP_RES_DELETE indicates that the LDAPMessage structure contains the result of an +LDAP delete operation. +LDAP_RES_MODDN or LDAP_RES_RENAME indicates +that the LDAPMessage structure contains the +result of an LDAP modify DN operation. +LDAP_RES_COMPARE indicates that the LDAPMessage structure contains the result of an +LDAP compare operation. +LDAP_RES_EXTENDED indicates that the LDAPMessage structure contains the result of an +LDAP v3 extended operation. +-1 indicates that an error occurred. The +error code is set in the LDAP structure. +To get the error code, call the ldap_get_lderrno function. + +0 indicates that the operation has timed +out. + + +See Also +ldap_add_ext, ldap_compare_ext + , ldap_delete_ext, ldap_modify_ext, ldap_rename, ldap_simple_bind, ldap_url_search + +
+<function>ldap_result2error</function> + +C SDK functions +ldap_result2error + +ldap_result2error + +This function is deprecated and should not be used. It is included +in ldap-deprecated.h for backward-compatibility. Use the +newer version, ldap_parse_result. +The ldap_result2error function returns the corresponding +error code for a result produced by the ldap_result and ldap_search_s functions. +Syntax +#include <ldap-deprecated.h> +int ldap_result2error( LDAP *ld, LDAPMessage *r, int freeit ); + +Parameters +<function>ldap_result2error</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +r + +Pointer to the LDAPMessage structure +representing the results returned by the ldap_result or ldap_search function. + + + +freeit + +Specifies whether or not the result should be freed after the error +code is extracted. The parameter can have the following possible values: + +0 specifies that the result should not +be freed. +A non-zero value specifies that the result should be freed. + + + + + + +
+
+Returns +One of the following values: + +If successful, sets the error code and other error information +in the LDAP structure and returns the error +code. +If unsuccessful, returns LDAP_PARAM_ERROR. + + + +Example +See ldap_result. +See Also +ldap_parse_result, ldap_get_lderrno, ldap_err2string +, ldap_result, +ldap_set_lderrno +
+<function>ldap_sasl_bind</function> + +C SDK functions +ldap_sasl_bind + +ldap_sasl_bind + +The ldap_sasl_bind function authenticates your +client to an LDAP server using an Simple Authentication and Security Layer +(SASL) mechanism. +The LDAP server must support authentication through SASL. &cnDirectoryServer; supports +a server plug-in interface that you can use to add SASL support to the server. + +Syntax +#include <ldap.h> + int ldap_sasl_bind( LDAP *ld, const char *dn, + const char *mechanism, const struct berval *cred, + LDAPControl **serverctrls, LDAPControl **clientctrls, + int *msgidp ); + +Parameters +<function>ldap_sasl_bind</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the user who wants to authenticate. For anonymous authentication, +set this to NULL. + + + +mechanism + +Name of the SASL mechanism that you want to use for authentication. + + + + +cred + +Pointer to the berval structure containing +the credentials that you want to use for authentication. + + + +serverctrls + +Pointer to an array of LDAPControl structures +representing LDAP server controls that apply to this operation. If you do +not want to pass any server controls, specify NULL for +this argument. + + + +clientctrls + +Pointer to an array of LDAPControl structures +representing LDAP client controls that apply to this operation. If you do +not want to pass any client controls, specify NULL for +this argument. + + + +msgidp + +Pointer to an integer that will be set to the message ID of the LDAP +operation. To check the result of this operation, call ldap_result + and ldap_parse_sasl_bind_result functions. + + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if the SASL bind request +was sent successfully. +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_NOT_SUPPORTED if controls are +included in your request—for example, as a session preference—and +your LDAP client does not specify that it is using the LDAP v3. Make sure +that you set the version of your LDAP client to version 3 before calling this +function. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the request to send to the server. +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + + + +Description +The ldap_sasl_bind function authenticates your +client to an LDAP server by using a specified SASL mechanism. ldap_sasl_bind + is an asynchronous function; it does not directly return results. +If you want the results to be returned directly by the function, call the +synchronous function ldap_sasl_bind_s. In +order to get the results of the LDAP SASL bind operation, call the ldap_result, the ldap_parse_sasl_bind_result +, and the ldap_get_lderrno functions. + +See Also +ldap_result, ldap_parse_sasl_bind_result + , ldap_get_lderrno, ldap_sasl_bind_s +
+<function>ldap_sasl_bind_s</function> + +C SDK functions +ldap_sasl_bind_s + +ldap_sasl_bind_s + +The ldap_sasl_bind_s function authenticates your +client to an LDAP server synchronously using an SASL mechanism. +The LDAP server must support authentication through SASL. &cnDirectoryServer; supports +a server plug-in interface that you can use to add SASL support to the server. +Syntax +#include <ldap.h> + int ldap_sasl_bind_s( LDAP *ld, const char *dn, + const char *mechanism, const struct berval *cred, + LDAPControl **serverctrls, LDAPControl **clientctrls, + struct berval **servercredp ); + +Parameters +<function>ldap_sasl_bind_s</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +dn + +DN of the user who wants to authenticate. For anonymous authentication, +set this to NULL. + + + +mechanism + +Name of the SASL mechanism that you want to use for authentication. + + + + +cred + +Pointer to the berval structure containing +the credentials that you want to use for authentication. + + + +serverctrls + +Pointer to an array of LDAPControl structures +representing LDAP server controls that apply to this operation. If you do +not want to pass any server controls, specify NULL for +this argument. + + + +clientctrls + +Pointer to an array of LDAPControl structures +representing LDAP client controls that apply to this operation. If you do +not want to pass any client controls, specify NULL for +this argument. + + + +servercredp + +Pointer to a pointer to an berval structure +containing any credentials returned by the server. When done, you can free +this by calling the ber_alloc function. + + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if the SASL bind request +was sent successfully. +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_NOT_SUPPORTED if controls are +included in your request (for example, as a session preference) and your LDAP +client does not specify that it is using the LDAPv3. Make sure that you set +the version of your LDAP client to version 3 before calling this function. + +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the request to send to the server. +LDAP_DECODING_ERROR if an error occurred +when the LDAP API library was decoding the BER-encoded results received from +the server. +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_LOCAL_ERROR if an error occurred +when receiving the results from the server. + +&cnDirectoryServer; and other LDAP server products may send result +codes in addition to those described. For example, the server may have loaded +a plug-in that returns custom result codes. Check your LDAP server documentation +for other result codes. + +Description +The ldap_sasl_bind_s function authenticates your +client to an LDAP server by using a specified SASL mechanism. It is a synchronous +function, which directly returns the results of the operation. If you want +to perform other operations while waiting for the results of this operation, +call the asynchronous function ldap_sasl_bind. +After authenticating a client through SASL, an LDAP server can return a set +of credentials in the results. The servercredp argument +points to this value. +See Also +ldap_sasl_bind +
+<function>ldap_search</function> + +C SDK functions +ldap_search + +ldap_search + +The ldap_search function searches the directory +asynchronously. +This is an older function that is included in the SDK for backward-compatibility. +If you are writing a new LDAP client, use ldap_search_ext + instead. +Syntax +#include <ldap.h> +int ldap_search( LDAP *ld, const char *base, int scope, + const char* filter, char **attrs, int attrsonly ); + +Parameters +<function>ldap_search</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +base + +DN of the entry that serves as the starting point for the search. For +example, setting base to dc=example,dc=com restricts the +search to entries at example.com. + + + +scope + +Scope of the search, which can be one of the following values: + +LDAP_SCOPE_BASE searches the entry specified +by base. +LDAP_SCOPE_ONELEVEL searches all entries +one level beneath the entry specified by base. +LDAP_SCOPE_SUBTREE searches the entry specified +by base and all entries at all levels beneath the entry specified by base. + + + + + + +filter + +String representation of the filter to apply in the search. You can +specify simple filters with the following syntax: +(attributetype= +attributevalue) + + + +attrs + +A NULL terminated array of attribute types to return +from entries that match filter. If you specify a NULL, +all attributes will be returned. + + + +attrsonly + +Specifies whether or not attribute values are returned along with the +attribute types. This parameter can have the following values: + +0 specifies that both attribute types and +attribute values are returned. +1 specifies that only attribute types are +returned. + + + + + +
+
+Returns +Returns the message ID of the ldap_search operation. +To check the result of this operation, call +ldap_result and ldap_result2error. +See ldap_search_ext_s for a list of possible +result codes. + +Description +Please use the newer version of this function, ldap_search_ext + . +Example +Example 21–44 searches +a directory. +Using <function>ldap_search</function> +#include "examples.h" + +static void do_other_work(); +unsigned long global_counter = 0; + +int +main( int argc, char **argv ) +{ + LDAP *ld; + LDAPMessage *result, *e; + BerElement *ber; + char *a, *dn; + char **vals; + int i, rc, finished, msgid; + int num_entries = 0; + struct timeval zerotime; + + zerotime.tv_sec = zerotime.tv_usec = 0L; + +/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ +if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); +} +/* authenticate to the directory as nobody */ +if ( ldap_simple_bind_s( ld, NULL, NULL ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_simple_bind_s" ); + return( 1 ); +} +/* search for all entries with surname of Jensen */ +if (( msgid = ldap_search( ld, MY_SEARCHBASE, LDAP_SCOPE_SUBTREE, + MY_FILTER, NULL, 0 )) == -1 ) { + ldap_perror( ld, "ldap_search" ); + return( 1 ); +} + +/* Loop, polling for results until finished */ +finished = 0; +while ( !finished ) { + /* + * Poll for results. We call ldap_result with the "all" parameter + * set to zero. This causes ldap_result() to return exactly one + * entry if at least one entry is available. This allows us to + * display the entries as they are received. + */ + result = NULL; + rc = ldap_result( ld, msgid, 0, &zerotime, &result ); + switch ( rc ) { + case -1: + /* some error occurred */ + ldap_perror( ld, "ldap_result" ); + return( 1 ); + case 0: + /* Timeout was exceeded. No entries are ready for retrieval. */ + if ( result != NULL ) { + ldap_msgfree( result ); + } + break; + default: + /* + * Either an entry is ready for retrieval, or all entries have + * been retrieved. + */ + if (( e = ldap_first_entry( ld, result )) == NULL ) { + /* All done */ + finished = 1; + if ( result != NULL ) { + ldap_msgfree( result ); + } + continue; + } + /* for each entry print out name + all attrs and values */ + num_entries++; + if (( dn = ldap_get_dn( ld, e )) != NULL ) { + printf( "dn: %s\n", dn ); + ldap_memfree( dn ); + } + for ( a = ldap_first_attribute( ld, e, &ber ); + a != NULL; a = ldap_next_attribute( ld, e, ber ) ) { + if (( vals = ldap_get_values( ld, e, a )) != NULL ) { + for ( i = 0; vals[ i ] != NULL; i++ ) { + printf( "%s: %s\n", a, vals[ i ] ); + } + ldap_value_free( vals ); + } + ldap_memfree( a ); + } + if ( ber != NULL ) { + ldap_ber_free( ber, 0 ); + } + printf( "\n" ); + ldap_msgfree( result ); + } + /* Do other work here while you are waiting... */ + do_other_work(); +} + +/* All done. Print a summary. */ +printf( "%d entries retrieved. I counted to %ld " + "while waiting.\n", num_entries, global_counter ); +ldap_unbind( ld ); +return( 0 ); +} + +/* + * Perform other work while polling for results. */ +static void +do_other_work() +{ + global_counter++; +} + + +See Also +ldap_search_ext +
+<function>ldap_search_ext</function> + +C SDK functions +ldap_search_ext + +ldap_search_ext + +The ldap_search_ext function searches the directory +asynchronously. +ldap_search_ext is a new version of the ldap_search function. If you are writing a new LDAP +client, you should call ldap_search_ext. +Syntax +#include <ldap.h> + int ldap_search_ext( LDAP *ld, const char *base, int scope, + const char *filter, char **attrs, int attrsonly, + LDAPControl **serverctrls, LDAPControl **clientctrls, + struct timeval *timeoutp, int sizelimit, int *msgidp ); + +Parameters +<function>ldap_search_ext</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +base + +DN of the entry that serves as the starting point for the search. For +example, setting base to dc=example,dc=com restricts the +search to entries at example.com. + + + +scope + +Scope of the search, which can be one of the following values: + +LDAP_SCOPE_BASE searches the entry specified +by base. +LDAP_SCOPE_ONELEVEL searches all entries +one level beneath the entry specified by base. +LDAP_SCOPE_SUBTREE searches the entry specified +by base and all entries at all levels beneath the entry specified by base. + + + + + + +filter + +String representation of the filter to apply in the search. You can +specify simple filters with the following syntax: +(attributetype= +attributevalue) + + + +attrs + +A NULL terminated array of attribute types to return +from entries that match filter. If you specify a NULL, +all attributes will be returned. + + + +attrsonly + +Specifies whether or not attribute values are returned along with the +attribute types. This parameter can have the following values: + +0 specifies that both attribute types and +attribute values are returned. +1 specifies that only attribute types are +returned. + + + + + +serverctrls + +Pointer to an array of LDAPControl structures +representing LDAP server controls that apply to this operation. If you do +not want to pass any server controls, specify NULL for +this argument. + + + +clientctrls + +Pointer to an array of LDAPControl structures +representing LDAP client controls that apply to this operation. If you do +not want to pass any client controls, specify NULL for +this argument. + + + +timeoutp + +Pointer to a timeval structure specifying the maximum +time to wait for the results of the search. Pass NULL to +use the default time limit for the current connection. To specify an infinite +time limit, set the tv_sec and tv_usec fields +in the timeval structure to 0. + + + +sizelimit + +Maximum number of results to return in the search. Pass -1 to +use the default size limit for the current connection. + + + +msgidp + +Pointer to an integer that will be set to the message ID of the LDAP +operation. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if the SASL bind request +was sent successfully. +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_NOT_SUPPORTED if controls are +included in your request—for example, as a session preference—and +your LDAP client does not specify that it is using the LDAP v3. Make sure +that you set the version of your LDAP client to version 3 before calling this +function. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the request to send to the server. +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + + + +Description +The ldap_search_ext function searches the directory +for matching entries. ldap_search_ext is an asynchronous +function; it does not directly return results. If you want the results to +be returned directly by the function, call the synchronous function ldap_search_ext_s . You can also use this function +to pass LDAP server controls to the server if you want the server to sort +the results or if you want to request a persistent search. (See ldap_create_sort_control and ldap_create_persistentsearch_control + for more information.) In order to get the results of the ldap_search_ext + operation, you need to call the ldap_result and +the ldap_parse_result functions. +See Also +ldap_search_ext_s, ldap_result, ldap_parse_result + +
+<function>ldap_search_ext_s</function> + +C SDK functions +ldap_search_ext_s + +ldap_search_ext_s + +The ldap_search_ext_s function searches the directory +synchronously. +ldap_search_ext_s is a new version of the ldap_search_s function. If you are writing a new +LDAP client, you should call ldap_search_ext_s. + +Syntax +#include <ldap.h> + int ldap_search_ext_s( LDAP *ld, const char *base, int scope, + const char *filter, char **attrs, int attrsonly, + LDAPControl **serverctrls, LDAPControl **clientctrls, + struct timeval *timeoutp, int sizelimit, LDAPMessage **res ); + +Parameters +<function>ldap_search_ext_s</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +base + +DN of the entry that serves as the starting point for the search. For +example, setting base to dc=example,dc=com restricts the +search to entries at example.com. + + + +scope + +Scope of the search, which can be one of the following values: + +LDAP_SCOPE_BASE searches the entry specified +by base. +LDAP_SCOPE_ONELEVEL searches all entries +one level beneath the entry specified by base. +LDAP_SCOPE_SUBTREE searches all entries +at all levels beneath the entry specified by base. + + + + + +filter + +String representation of the filter to apply in the search. You can +specify simple filters with the following syntax: +(attributetype= +attributevalue) + + + +attrs + +A NULL terminated array of attribute types to return +from entries that match filter. If you specify a NULL, +all attributes will be returned. + + + +attrsonly + +Specifies whether or not attribute values are returned along with the +attribute types. This parameter can have the following values: + +0 specifies that both attribute types and +attribute values are returned. +1 specifies that only attribute types are +returned. + + + + + +serverctrls + +Pointer to an array of LDAPControl structures +representing LDAP server controls that apply to this operation. If you do +not want to pass any server controls, specify NULL for +this argument. + + + +clientctrls + +Pointer to an array of LDAPControl structures +representing LDAP client controls that apply to this operation. If you do +not want to pass any client controls, specify NULL for +this argument. + + + +timeoutp + +Pointer to a timeval structure specifying the maximum +time to wait for the results of the search. + + + +sizelimit + +Maximum number of results to return in the search. + + + +res + +Results of the search (when the call is completed). + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if the SASL bind request +was sent successfully. +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_NOT_SUPPORTED if controls are +included in your request—for example, as a session preference—and +your LDAP client does not specify that it is using the LDAP v3. Make sure +that you set the version of your LDAP client to version 3 before calling this +function. +LDAP_FILTER_ERROR if an error occurred +when parsing and BER-encoding the search filter specified by the filter argument. + +LDAP_TIMEOUT if the search exceeded +the time specified by the timeoutp argument. + +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the request to send to the server. +LDAP_DECODING_ERROR if an error occurred +when the LDAP API library was decoding the BER-encoded results received from +the server. +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_LOCAL_ERROR if an error occurred +when receiving the results from the server. + +&cnDirectoryServer; and other LDAP server products may send result +codes in addition to those described. For example, the server may have loaded +a plug-in that returns custom result codes. Check your LDAP server documentation +for other result codes. + +Description +The ldap_search_ext_s searches the directory for +matching entries. The function ldap_search_ext_s is synchronous; +it directly returns the results of the operation. If you want to perform other +operations while waiting for the results of this operation, call the asynchronous +function ldap_search_ext. You can also use +ldap_search_ext_s to pass LDAP server controls to the server if +you want the server to sort the results or if you want to request a persistent +search. (See ldap_create_sort_control and ldap_create_persistentsearch_control for more information.) + +See Also +ldap_search_ext +
+<function>ldap_search_s</function> + +C SDK functions +ldap_search_s + +ldap_search_s + +The ldap_search_s function searches the directory +synchronously. +This is an older function that is included in the SDK for backward-compatibility. +If you are writing a new LDAP client, use ldap_search_ext_s + instead. +Syntax +#include <ldap.h> + int ldap_search_s( LDAP *ld, const char *base, int scope, + const char* filter, char **attrs, int attrsonly, + LDAPMessage **res ); + +Parameters +This function has the parameters listed in ldap_search_s + . +<function>ldap_search_s</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +base + +DN of the entry that serves as the starting point for the search. For +example, setting base to dc=example,dc=com restricts the +search to entries at example.com. + + + +scope + +Scope of the search, which can be one of the following values: + +LDAP_SCOPE_BASE searches the entry specified +by base. +LDAP_SCOPE_ONELEVEL searches all entries +one level beneath the entry specified by base. +LDAP_SCOPE_SUBTREE searches all entries +at all levels beneath the entry specified by base. + + + + + +filter + +String representation of the filter to apply in the search. You can +specify simple filters with the following syntax: +(attributetype=attributevalue) + + + + +attrs + +A NULL terminated array of attribute types to return +from entries that match filter. If you specify a NULL, +all attributes will be returned. + + + +attrsonly + +Specifies whether or not attribute values are returned along with the +attribute types. This parameter can have the following values: + +0 specifies that both attribute types and +attribute values are returned. +1 specifies that only attribute types are +returned. + + + + + +res + +Results of the search (when the call is completed). + + + +
+
+Returns +For a list of possible result codes for an LDAP search operation, see ldap_search_ext_s. +Description +Use the newer version of this function, ldap_search_ext_s + . +Example +Example 21–45 searches +the directory for all people whose surname (last name) is Jensen. + +Using <function>ldap_search_s</function> +#include "examples.h" + +int main( int argc, char **argv ) +{ + LDAP *ld; + LDAPMessage *result, *e; + BerElement *ber; + char *a, *dn; + char **vals; + int i; + /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } + /* authenticate to the directory as nobody */ + if ( ldap_simple_bind_s( ld, NULL, NULL ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_simple_bind_s" ); + return( 1 ); + } + /* search for all entries with surname of Jensen */ + if ( ldap_search_s( ld, MY_SEARCHBASE, LDAP_SCOPE_SUBTREE, + MY_FILTER, NULL, 0, &result ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search_s" ); + return( 1 ); + } + /* for each entry print out name + all attrs and values */ + for ( e = ldap_first_entry( ld, result ); e != NULL; + e = ldap_next_entry( ld, e ) ) { + if ( (dn = ldap_get_dn( ld, e )) != NULL ) { + printf( "dn: %s\n", dn ); + ldap_memfree( dn ); + } + for ( a = ldap_first_attribute( ld, e, &ber ); + a != NULL; a = ldap_next_attribute( ld, e, ber ) ) { + if ((vals = ldap_get_values( ld, e, a)) != NULL ) { + for ( i = 0; vals[i] != NULL; i++ ) { + printf( "%s: %s\n", a, vals[i] ); + } + ldap_value_free( vals ); + } + ldap_memfree( a ); + } + if ( ber != NULL ) { + ldap_ber_free( ber, 0 ); + } + printf( "\n" ); + } + ldap_msgfree( result ); + ldap_unbind( ld ); + return( 0 ); +} + + +See Also +ldap_search_ext_s +
+<function>ldap_search_st</function> + +C SDK functions +ldap_search_st + +ldap_search_st + +The ldap_search_st function searches the directory +synchronously within a specified time limit. +This is an older function that is included in the SDK for backward-compatibility. +If you are writing a new LDAP client, use ldap_search_ext_s + instead. +Syntax +#include <ldap.h> +int ldap_search_st( LDAP *ld, const char *base, int scope, + const char* filter, char **attrs, int attrsonly, + struct timeval *timeout, LDAPMessage **res ); + +Parameters +<function>ldap_search_st</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +base + +DN of the entry that serves as the starting point for the search. For +example, setting base to dc=example,dc=com restricts the +search to entries at example.com. + + + +scope + +Scope of the search, which can be one of the following values: + +LDAP_SCOPE_BASE searches the entry specified +by base. +LDAP_SCOPE_ONELEVEL searches all entries +one level beneath the entry specified by base. +LDAP_SCOPE_SUBTREE searches all entries +at all levels beneath the entry specified by base. + + + + + +filter + +String representation of the filter to apply in the search. You can +specify simple filters with the following syntax: +(attributetype=attributevalue) + + + + +attrs + +A NULL terminated array of attribute types to return +from entries that match filter. If you specify a NULL, +all attributes will be returned. + + + +attrsonly + +Specifies whether or not attribute values are returned along with the +attribute types. This parameter can have the following values: + +0 specifies that both attribute types and attribute values +are returned. +1 specifies that only attribute types are returned. + + + + + + +timeout + +Maximum time to wait for the results of the search. + + + +res + +Results of the search (when the call is completed). + + + +
+
+Returns +For a list of possible result codes for an LDAP search operation, see ldap_search_ext_s. +Description +Please use the newer version of this function, ldap_search_ext_s + . +See Also +ldap_search_ext_s +
+<function>ldap_set_filter_additions</function> + +C SDK functions +ldap_set_filter_additions + +ldap_set_filter_additions + +The ldap_set_filter_additions function sets a prefix +to be prepended and a suffix to be appended to all filters returned by the + ldap_getfirstfilter and ldap_getnextfilter function +calls. +Syntax +#include <ldap.h> + int ldap_set_filter_additions( LDAPFiltDesc *lfdp, char *prefix, + char *suffix ); + +Parameters +<function>ldap_set_filter_additions</function> Function +Parameters + + + + +Parameter + +Description + + + + + +lfdp + +Pointer to an LDAPFiltDesc structure. + + + + +prefix + +Prefix to prepend to all filters. If NULL, no prefix +is prepended. + + + +suffix + +Suffix to append to all filters. If NULL, no suffix +is appended. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +If unsuccessful, returns an LDAP error code. + + +Example +Example 21–46 loads +the filter configuration file named myfilters.conf into +memory and adds the prefix "(&(objectClass=person)" and +the suffix ")" to each filter retrieved. +Using <function>ldap_set_filter_additions +</function> +#include <ldap.h> +... +LDAPFiltDesc *lfdp; +char *filter_file = "myfilters.conf"; +char *prefix = "(&(objectClass=person)"; +char *suffix = ")"; +int rc; +... +lfdp = ldap_init_getfilter( filter_file ); +rc = ldap_set_filter_additions( ldfp, prefix, suffix ); +if ( rc != LDAP_SUCCESS ) { + printf( "Error setting filter prefix and suffix\n"); + return( rc ); +} +... + + +See Also +ldap_getfirstfilter, ldap_getnextfilter +
+<function>ldap_setfilteraffixes</function> + +C SDK functions +ldap_setfilteraffixes + +ldap_setfilteraffixes + +This function is deprecated and should not be used. It is included +in ldap-deprecated.h for backward-compatibility. Use ldap_set_filter_additions instead. +See Also +ldap_set_filter_additions + +<function>ldap_set_lderrno</function> + +C SDK functions +ldap_set_lderrno + +ldap_set_lderrno + +The ldap_set_lderrno function sets an error code +and information about an error in an LDAP structure. + +Syntax +#include <ldap.h> +int ldap_set_lderrno( LDAP *ld, int e, char *m, char *s ); + +Parameters +<function>ldap_set_lderrno</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +e + +The error code that you want to set. + + + +m + +In the event that an entry for a specified DN cannot be found, set this +parameter to the portion of the DN that identifies an existing entry. + + + + +s + +The text of the error message that you want associated with this error +code. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +If unsuccessful, returns an LDAP error code. + + +Description +The ldap_set_lderrno function sets an error code +and information about an error in an LDAP structure. +You can call this function to set error information that will be retrieved +by subsequent ldap_get_lderrno function calls. + +Example +Example 21–47 attempts +to perform an operation. If the operation fails, the LDAP_PARAM_ERROR error +code is placed in the LDAP structure. +Using <function>ldap_set_lderrno</function> +#include <ldap.h> +int rc; +char *errmsg = "Invalid parameter"; +... +if ( ldap_my_function() != LDAP_SUCCESS ) { + rc = ldap_set_lderrno( ld, LDAP_PARAM_ERROR, NULL, errmsg ); + if ( rc != LDAP_SUCCESS ) { + printf( "Error: %d\nError code could not be set.\n", rc ); + } + return( rc ); +} +... + + +See Also +ldap_err2string, +ldap_perror, ldap_result2error + +
+<function>ldap_set_option</function> + +C SDK functions +ldap_set_option + +ldap_set_option + +The function ldap_set_option sets session preferences +in the LDAP structure. +Syntax +#include <ldap.h> + int ldap_set_option( LDAP *ld, int option, const void *optdata ); + +Parameters +<function>ldap_set_option</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. If NULL, you are setting +the default options that will apply to any new LDAP connection handles that +are subsequently created. + + + +option + +Option that you want to set. See +Table 21–182 for available options of this parameter. + + + + +optdata + +Pointer to the value of the option that you want to set. Available data +types are also listed in Table +21–182. + + + +
+The option parameter can have one of the values listed +in Table 21–182. +Options for <function>ldap_set_option +</function> + + + + +Option + +Description + + + + + +LDAP_OPT_API_FEATURE_INFO + +Retrieves information about the revision of a supported LDAP feature. +This option is READ-ONLY and cannot be set. +The data type for the optdata parameter is (LDAPAPIFeatureInfo +*). + + + +LDAP_OPT_API_INFO + +Retrieves information about the API implementation at execution time +(API version, protocol version, the names of supported API extensions with +their vendor name version, etc.). For details on the structure returned, refer +to the ldap.h header file. This option is READ-ONLY and +cannot be set. +The data type for the optdata parameter is (LDAPAPIInfo + *). + + + +LDAP_OPT_CLIENT_CONTROLS + +Pointer to an array of LDAPControl structures +representing the LDAP v3 client controls you want sent with every request +by default. +The data type for the optdata parameter is (LDAPControl +***). + + + +LDAP_OPT_DESC + +Socket descriptor underlying the main LDAP connection. The LBER_SOCKET + data type depends on the platform that you are using: + +int in UNIX. +SOCKET in Windows.The data +type for the optdata parameter is (LBER_SOCKET +*). + + + + + +LDAP_OPT_DEREF + +Determines how aliases work during a search. optdata can +be one of the following values: + +LDAP_DEREF_NEVER specifies that aliases +are never dereferenced. +LDAP_DEREF_SEARCHING specifies that aliases +are dereferenced when searching under the base object (but not when finding +the base object). +LDAP_DEREF_FINDING specifies that aliases +are dereferenced when finding the base object (but not when searching under +the base object). +LDAP_DEREF_ALWAYS specifies that aliases +are always dereferenced when finding and searching under the base object. +The data type for the optdata parameter is (int +*). + + + + + +LDAP_OPT_DNS_FN_PTRS + +DEPRECATED OPTION: Lets you use alternate +DNS functions for getting the host entry of the LDAP server. +The data type for the optdata parameter is (struct +ldap_dns_fns *). + + + +LDAP_OPT_ERROR_NUMBER + +Retrieves the result code for the most recent LDAP error that occurred +in this session. +The data type for the optdata parameter is (int +*). + + + +LDAP_OPT_ERROR_STRING + +Retrieves the error message returned with the result code for the most +recent LDAP error that occurred in this session. +The data type for the optdata parameter is (char +**). + + + +LDAP_OPT_EXTRA_THREAD_FN_PTRS + +Lets you specify the locking and semaphore functions that you want called +when getting results from the server. +The data type for the optdata parameter is (struct +ldap_extra_thread_fns *). + + + +LDAP_OPT_HOST_NAME + +Sets the host name (or list of hosts) for the primary LDAP server. +The data type for the optdata parameter is (char +**). + + + +LDAP_OPT_IO_FN_PTRS + +DEPRECATED OPTION: Lets you use alternate +communication stacks. +The data type for the optdata parameter is (struct +ldap_io_fns *). + + + +LDAP_OPT_MATCHED_DN + +Gets the matched DN value returned with the most recent LDAP error that +occurred for this session. +The data type for the optdata parameter is (char +**) + + + +LDAP_OPT_MEMALLOC_FN_PTRS + +Gets a pointer to the callback structure which you previously set. +The data type for the optdata parameter is (struct +ldap_memalloc_fnsldap_io_fns *). + + + +LDAP_OPT_PROTOCOL_VERSION + +Version of the protocol supported by your client. You can specify either +LDAP_VERSION2 or LDAP_VERSION3. If no version +is set, the default is LDAP_VERSION2. In order to use LDAP +v3 features, you need to set the protocol version to LDAP_VERSION3. + +The data type for the optdata parameter is (int +*). + + + +LDAP_OPT_REBIND_ARG + +Lets you set the last argument passed to the routine specified by +LDAP_OPT_REBIND_FN. You can also set this option by calling the ldap_set_rebind_proc function. +The data type for the optdata parameter is (void +*). + + + +LDAP_OPT_REBIND_FN + +Lets you set the routine to be called when you need to authenticate +a connection with another LDAP server (for example, during the course of following +a referral). You can also set this option by calling the +ldap_set_rebind_proc function. +The data type for the optdata parameter is (LDAP_REBINDPROC_CALLBACK +*). + + + +LDAP_OPT_RECONNECT + +If the connection to the server is lost, determines whether or not the +same connection handle should be used to reconnect to the server. By default, +this option is off. To handle failover use following values: + +LDAP_OPT_ON specifies that the same connection +handle can be used to reconnect to the server. +LDAP_OPT_OFF specifies that you want to +create a new connection handle to connect to the server.The data +type for the optdata parameter is (int *). + + + + + + +LDAP_OPT_REFERRALS + +Determines whether or not the client should follow referrals. By default, +the client follows referrals. optdata can be one of the +following values: + +LDAP_OPT_ON specifies that the server should +follow referrals. +LDAP_OPT_OFF specifies that the server +should not follow referrals.The data type for the optdata parameter +is (int *). + + + + + +LDAP_OPT_REFERRAL_HOP_LIMIT + +Maximum number of referrals the client should follow in a sequence. +In other words, the client can only be referred this number of times before +it gives up. By default, the maximum number of referrals that the client can +follow in a sequence is 5 for the initial connection. This limit does not +apply to individual requests that generate multiple referrals in parallel. +The data type for the optdata parameter is (int +*). + + + +LDAP_OPT_RESTART + +Determines whether or not LDAP I/O operations should be restarted automatically +if they are prematurely aborted. optdata can be one of +the following values: + +LDAP_OPT_ON specifies that I/O operations +should be restarted automatically. +LDAP_OPT_OFF specifies that I/O operations +should not be restarted automatically.The data type for the +optdata parameter is (int *). + + + + + +LDAP_OPT_SERVER_CONTROLS + +Pointer to an array of LDAPControl structures +representing the LDAP v3 server controls you want sent with every request +by default. Typically, since controls are specific to the type of request, +you may want to pass the controls using operation-specific functions (such +as ldap_add_ext) instead. +The data type for the optdata parameter is (LDAPControl +***). + + + +LDAP_OPT_SIZELIMIT + +Maximum number of entries that should be returned by the server in search +results. The LDAP server may impose a smaller size limit than the limit you +specify as the server administrator also has the ability to set this limit. +The data type for the optdata parameter is (int +*). + + + +LDAP_OPT_SSL + +Determines whether or not SSL is enabled. optdata can +be one of the following values: + +LDAP_OPT_ON specifies that SSL is enabled. + +LDAP_OPT_OFF specifies that SSL is disabled. +The data type for the optdata parameter is (int +*). + + + + + +LDAP_OPT_THREAD_FN_PTRS + +Lets you specify the thread function pointers. +The data type for the optdata parameter is (struct +ldap_thread_fns *). + + + +LDAP_OPT_TIMELIMIT + +Maximum number of seconds that should be spent by the server when answering +a search request. The LDAP server may impose a shorter time limit than the +limit you specify as the server administrator also has the ability to set +this limit. +The data type for the optdata parameter is (int +*). + + + +LDAP_X_OPT_EXTIO_FN_PTRS + +Extended I/O function callback option. + + + +LDAP_X_OPT_CONNECT_TIMEOUT + +Value of a time out (expressed in milliseconds) for non-blocking connect +call. +The data type for the optdata parameter is (int +*). + + + +LDAP_X_OPT_SOCKBUF + +Socket buffer structure associated to the LDAP connection. + + + +
+See also ldap_set_option +3LDAP for details on LDAP_OPT_X_SASL* + parameters.
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +-1 if unsuccessful. + + +Example +Using <function>ldap_set_option</function> +#include <stdio.h> +#include <ldap.h> +... +LDAP *ld; +int max_ret = 100, max_tim = 30; +char *host = "ldap.sun.com"; +... +/* Initialize a session with the LDAP server ldap.sun.com:389 */ +/* Use prldap_init() for IPv6 support. */ +if ( ( ld = ldap_init( host, LDAP_PORT ) ) == NULL ) { + perror( "ldap_init" ); + return( 1 ); +} + +/* Set the maximum number of entries returned */ +if ( ldap_set_option( ld, LDAP_OPT_SIZELIMIT, &max_ret) ! + LDAP_SUCCESS) { + ldap_perror( ld, "ldap_set_option" ); + return( 1 ); +} +... + + +See Also +ldap_init, prldap_init + (IPv6), ldap_get_option +
+<function>ldap_set_rebind_proc</function> + +C SDK functions +ldap_set_rebind_proc + +ldap_set_rebind_proc + +The ldap_set_rebind_proc function sets a rebind + , which is called by your client to obtain authentication credentials +when following a referral. +Syntax +#include <ldap.h> +void ldap_set_rebind_proc( LDAP *ld, + LDAP_REBINDPROC_CALLBACK *rebindproc, void *arg ); + +Parameters +<function>ldap_set_rebind_proc</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +rebindproc + +Pointer to a function called back to obtain bind credentials when a +new server is contacted during an LDAP referral. + + + +arg + +Pointer to an additional argument that you want to pass to the rebind +function. + + + +
+
+Description +Call ldap_set_rebind_proc to specify the rebind +function. This rebind function is called by the LDAP client when following +a referral to a new LDAP server. It is responsible for obtaining the credentials +used to authenticate to the new server. For example, suppose LDAP server A +sends a referral to your client. The referral points your client to LDAP server +B. When automatically following the referral, your client calls the rebind +function to obtain a DN and credentials; your client uses these to authenticate +to server B. By default, if you do not call ldap_set_rebind_proc or +if you pass NULL for the rebindproc argument, +your client authenticates anonymously when following referrals. +The rebind function that you specify with ldap_set_rebind_proc should +have the following prototype: +int LDAP_CALL LDAP_CALLBACK rebindproc( LDAP *ld, char **dnp, + char **passwdp, int *authmethodp, int freeit, void *arg ); +LDAP_CALL and LDAP_CALLBACK are +used to set up calling conventions, such as Pascal calling conventions on +Windows. These are defined in the lber.h header file. + +The following procedure explains what the rebind function is expected +to do. LDAP clients that are built with &DirectorySDKForC; use this procedure +when following referrals. +To Follow Referrals + +The LDAP server sends a referral back to the client. +The client calls the rebind function, passing + 0 as the freeit argument. + +The rebind function sets the dnp, + passwdp, and + authmethodp arguments to point to the following information: + + +The dnp argument is set to point to the +DN to be used to authenticate to the new LDAP server. + +The passwdp argument is set to point to +the credentials for this DN. +The authmethodp argument is set to point +to the method of authentication used (for example, LDAP_AUTH_SIMPLE). + + + + + +If successful, the rebind function returns + LDAP_SUCCESS + , and referral processing continues. (If any other value is returned, +referral processing stops, and that value is returned as the result code for +the original LDAP request.) +The client gets the DN, credentials, and authentication method +from the arguments of the rebind function and uses this information to authenticate +to the new LDAP server. +The client calls the rebind function again, passing + 1 as the freeit argument. + +The rebind function frees any memory allocated earlier to specify +the DN and credentials.You need to write a rebind function that +does the following: + +If freeit is 0, set +the following pointers: + +Set dnp to point to the DN to be used for +authentication. +Set passwdp to point to the credentials +to be used for authentication. +Set authmethodp to point to the method +of authentication used (for example, LDAP_AUTH_SIMPLE). +You can also make use of the arg argument, which +is a pointer to the argument specified in the ldap_set_rebind_proc function. +If successful, returns LDAP_SUCCESS. Otherwise, returns +the appropriate LDAP error code. + +If freeit is 1, free any memory +that you allocated to create the DN and credentials.After you +have defined this function, pass the function name to ldap_set_rebind_proc + to register your rebind function. + +In order to use the rebind function, the LDAP_OPT_REFERRALS option +must be set to LDAP_OPT_ON, so that your client automatically +follows referrals. This option is set to LDAP_OPT_ON by +default. + + + + +Example +Example 21–49 +demonstrates how to write and register a rebind function. +Using <function>ldap_set_rebind_proc +</function> +#include "ldap.h" +... +/* Declare your rebind function */ +int rebindproc( LDAP *ld, char **dnp, char **passwdp, + int *authmethodp, int freeit, void *arg ); +... +int main( int argc, char **argv ) +{ + LDAP *ld; + /* Additional argument to be passed to the rebind function */ + char *testarg = "cn=admin,cn=Administrators,cn=config"; + /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( "directory.example.com", 389 )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } + /* Specify the function used for reauthentication on referrals */ + ldap_set_rebind_proc( ld, rebindproc, (void *)testarg ); + /* Authenticate */ + if ( ldap_simple_bind_s( ld, "uid=bjensen,ou=People,dc=example,dc=com", + "hifalutin" ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_simple_bind_s" ); + return( 1 ); + } + ... + /* Your code to interact with the LDAP server */ + ... +} +... +/* rebindproc is the rebind function responsible for providing the DN, + credentials, and authentication method used for authenticating the + client to other Directory Servers. + The function should set the following arguments: + - dnp should point to the DN that will be used for authentication. + - passwdp should point to the credentials used for authentication. + - authmethodp should point to the method of authentication to be used + (for example, LDAP_AUTH_SIMPLE). + The function should return LDAP_SUCCESS if successful or an LDAP + error code if an error occurs. + In order to demonstrate how the freeit argument works, this example + uses strdup() to copy the DN and password. You can also just copy + string pointers if the DN and password are already available as + global variables. +*/ +int LDAP_CALL LDAP_CALLBACK rebindproc( + LDAP *ld, char **dnp, char **passwdp, + int *authmethodp, int freeit, void *arg ) +{ + printf( "Rebind function called.\n" ); + switch ( freeit ) { + /* Your client calls the rebind function with freeit==1 when it needs + to free any memory you've allocated. */ + case 1: + printf( "\tFreeing memory.\n" ); + if ( dnp && *dnp ) { + free( *dnp ); + } + if ( passwdp && *passwdp ) { + free( *passwdp ); + } + break; + /* Your client calls the rebind function with freeit==0 when it needs + to get the DN, credentials, and authentication method. */ + case 0: + printf( "\tGetting DN and credentials.\n" ); + *dnp = strdup( "uid=username,o=OtherServerSuffix" ); + *passwdp = strdup( "23skidoo" ); + *authmethodp = LDAP_AUTH_SIMPLE; + break; + default: + printf( "\tUnknown value of freeit argument: %d\n", freeit ); + break; + } + /* If you successfully set the DN and credentials, you should return + LDAP_SUCCESS. (Any other return code will stop the client from + automatically following the referral. */ + return LDAP_SUCCESS; +} + + +See Also +ldap_simple_bind, ldap_simple_bind_s +
+<function>ldap_simple_bind</function> + +C SDK functions +ldap_simple_bind + +ldap_simple_bind + +The ldap_simple_bind function synchronously authenticates +your client to the LDAP server using a DN and a password. +Syntax +#include <ldap.h> + int ldap_simple_bind(LDAP *ld, const char *who, const char *passwd); + +Parameters +<function>ldap_simple_bind</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +who + +DN of the user who wants to authenticate. For anonymous authentication, +set this or the passwd argument to NULL. + + + + +passwd + +Password of the user who wants to authenticate. For anonymous authentication, +set this or the who argument to NULL. + + + +
+
+Returns +Returns the message ID of the ldap_simple_bind operation. +To check the result of this operation, call ldap_result +and ldap_result2error. +Description +The ldap_simple_bind function authenticates to +the LDAP server. It verifies that the password supplied for authentication +matches the userPassword attribute of the given entry. +ldap_simple_bind is an asynchronous function; it does not directly +return results. If you want the results to be returned directly by the function, +call the synchronous function ldap_simple_bind_s. + +If you specify a DN but no password, your client will bind to +the server anonymously. If you want a NULL password to +be rejected as an incorrect password, you need to write code to perform the +check before you call the ldap_simple_bind function. +The use of this function may be a security threat if used on a non-secured +connection as the password is transmitted in clear text. For password-based +authentication, use a secure connection (ldapssl_init or ldapssl_tls_start_s) or SASL Digest-MD5 mechanism +(ldap_sasl_bind or ldap_sasl_bind_s +). + +Example +Example 21–50 calls + ldap_simple_bind to authenticate the user Barbara +Jensen to the directory. +Using <function>ldap_simple_bind</function> +#include <stdio.h> +#include <ldap.h> +... +LDAP *ld; +char *host = "ldap.sun.com"; +char *dn = "uid=bjensen,ou=People,dc=example,dc=com"; +char *pw = "hifalutin"; +struct timeval zerotime; +zerotime.tv_sec = zerotime.tv_usec = 0L; +... +/* Initialize a session with the LDAP server ldap.example.com:389 */ +/* Use prldap_init() for IPv6 support. */ +if ( ( ld = ldap_init( host, LDAP_PORT ) ) == NULL ) { + perror( "ldap_init" ); + return( 1 ); +} +/* Attempt to bind with the LDAP server */ +msgid = ldap_simple_bind( ld, dn, pw ); + +/* Initialize the value returned by ldap_result() */ +rc = 0; + +/* While the operation is still running, do this: */ +while ( rc == 0 ) { + ... /* do other work while waiting */... + + /* Check the status of the LDAP operation */ + rc = ldap_result( ld, msgid, NULL, &zerotime, &result ); + switch( rc ) { + /* If -1 was returned, an error occurred */ + case -1: + ldap_perror( ld, "Error in results: " ); + return( 1 ); + /* If 0 was returned, the operation is still in progress */ + case 0: + continue; + /* If any other value is returned, assume we are done */ + default: + /* Check if the "bind" operation was successful */ + if ( ldap_result2error( result ) != LDAP_SUCCESS ) { + ldap_perror( ld, "Error binding to server: " ); + return( 1 ); + } + } +} +... + + +See Also +ldap_simple_bind_s +
+<function>ldap_simple_bind_s</function> + +C SDK functions +ldap_simple_bind_s + +ldap_simple_bind_s + +The ldap_simple_bind function synchronously authenticates +your client to the LDAP server using a DN and a password. +Syntax +#include <ldap.h> +int ldap_simple_bind_s( LDAP *ld, const char *who, const char *passwd ); + +Parameters +<function>ldap_simple_bind_s</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +who + +DN of the user who wants to authenticate. For anonymous authentication, +set this or the passwd argument to NULL. + + + + +passwd + +Password of the user who wants to authenticate. For anonymous authentication, +set this or the who argument to NULL. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if an invalid parameter +was passed to the function. +LDAP_NOT_SUPPORTED if controls are +included in your request (for example, as a session preference) and your LDAP +client does not specify that it is using the LDAP v3. Make sure that you set +the version of your LDAP client to version 3 before calling this function. + +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the request to send to the server. +LDAP_DECODING_ERROR if an error occurred +when the LDAP API library was decoding the BER-encoded results received from +the server. +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_LOCAL_ERROR if an error occurred +when receiving the results from the server. + +&cnDirectoryServer; and other LDAP server products may send result +codes in addition to those described. For example, the server may have loaded +a plug-in that returns custom result codes. Check your LDAP server documentation +for other result codes. + +Description +The ldap_simple_bind_s function authenticates to +the LDAP server. It verifies that the password supplied for authentication +matches the userPassword attribute of the given entry. +ldap_simple_bind_s is a synchronous function, which directly returns +the results of the operation. If you want to perform other operations while +waiting for the results of this operation, call the asynchronous function ldap_simple_bind instead. +If you specify a DN but no password, your client will bind to +the server anonymously. If you want a NULL password to +be rejected as an incorrect password, you need to write code to perform the +check before you call the ldap_simple_bind_s function. +The use of this function may be a security threat if used on a non-secured +connection as the password is transmitted in clear text. For password-based +authentication, use a secure connection (ldapssl_init or ldapssl_tls_start_s) or SASL Digest-MD5 mechanism +(ldap_sasl_bind or ldap_sasl_bind_s +). + +Example +Example 21–51 +uses the synchronous ldap_simple_bind_s function to authenticate +to the directory as the user Barbara Jensen. +Using <function>ldap_simple_bind_s +</function> +#include <stdio.h> +#include <ldap.h> +... +LDAP *ld; +char *host = "ldap.sun.com"; +char *dn = "uid=bjensen,ou=People,dc=example,dc=com"; +char *pw = "hifalutin"; +... +/* Initialize a session with the LDAP server ldap.sun.com:389 */ +/* Use prldap_init() for IPv6 support. */ +if ( ( ld = ldap_init( host, LDAP_PORT ) ) == NULL ) { + perror( "ldap_init" ); + return( 1 ); +} +/* Attempt to bind with the LDAP server */ +if ( ldap_simple_bind_s( ld, dn, pw ) != LDAP_SUCCESS ) { + ldap_perror( ld, "Authentication failed: " ); + return( 1 ); +} +... + + +See Also +ldap_simple_bind +
+<function>ldap_sort_entries</function> + +C SDK functions +ldap_sort_entries + +ldap_sort_entries + +The ldap_sort_entries function sorts a chain of +entries retrieved from an LDAP search call. +Syntax +#include <ldap.h> + int ldap_sort_entries( LDAP *ld, LDAPMessage *chain, char *attr, + LDAP_CMP_CALLBACK *cmp ); + +Parameters +<function>ldap_sort_entries</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +chain + +Chain of entries returned by the ldap_result or ldap_search_s function. + + + +attr + +Attribute to use when sorting the results. To sort by DN instead of +by attribute, use NULL. + + + +cmp + +Comparison function used when sorting the values. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +If unsuccessful, returns a NULL and sets +the appropriate error code in the LDAP structure. +To get the error code, call ldap_get_lderrno. + + + +Description +The ldap_sort_entries function sorts a chain of +entries retrieved from an LDAP search call (ldap_search_s + or ldap_result) either by DN or +a specified attribute in the entries. +Example +Example 21–52 +sorts entries by the roomNumber attribute. +Using <function>ldap_sort_entries</function> +#include <stdio.h> +#include <string.h> +#include <ldap.h> +LDAP *ld; +LDAPMessage *result; +char *my_searchbase = "dc=example,dc=com"; +char *my_filter = "(sn=Jensen)"; +char *sortby = "roomNumber"; +... +/* Search the directory */ +if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter, + NULL, 0, &result ) != + LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search_s" ); + return( 1 ); +} +/* Sort the results by room number, using strcasecmp */ +if ( ldap_sort_entries( ld, &result, sortby, strcasecmp ) != + LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_sort_entries" ); + return( 1 ); +} +... + + +See Also +ldap_multisort_entries, ldap_result, ldap_search_s, + LDAP_CMP_CALLBACK +
+<function>ldap_start_tls_s</function> + +C SDK functions +ldap_start_tls_s + +ldap_start_tls_s + +The ldap_start_tls_s initiates a Start Transport +Layer Security (TLS) operation as defined in RFC 4513. +Before using this function, call ldapssl_client_init +, ldapssl_clientauth_init, or ldapssl_advclientauth_init to initialize use of +the certificate database. +Syntax +#include <ldap_ssl.h> +int ldap_start_tls_s( LDAP *ld, LDAPControl **serverctrls, + LDAPControl **clientctrls ); + +Parameters +<function>ldap_start_tls_s</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +serverctrls + +List of LDAP server controls. + + + +clientctrls + +List of client controls. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_OPERATIONS_ERROR if TLS has already +been established. +LDAP_PROTOCOL_ERROR if TLS is not supported. + +LDAP_REFERRAL if this server does not +support TLS, but the server referred to may. +LDAP_UNAVAILABLE if the server is shutting +down, or supports TLS but cannot provide it at this time. + + +
+<function>ldap_sort_strcasecmp</function> + +C SDK functions +ldap_sort_strcasecmp + +ldap_sort_strcasecmp + +The ldap_sort_strcasecmp routine compares two strings +and ignores any differences in case when comparing uppercase and lowercase +characters. +Syntax +#include <ldap.h> + int ldap_sort_strcasecmp( const char **a, const char **b ); + +Parameters +<function>ldap_sort_strcasecmp</function> Function +Parameters + + + + +Parameter + +Description + + + + + +a + +Pointer to first string to compare + + + +b + +Pointer to second string to compare + + + +
+
+Returns +One of the following values: + +If a is greater than b, +returns a value greater than 0. +If a is equal to b, +returns 0. +If a is less than b, +returns a value less than 0. + + +Description +The ldap_sort_strcasecmp routine compares two strings +and ignores any differences in case when comparing uppercase and lowercase +characters. This function is similar to the C function strcasecmp. +When sorting attribute values with ldap_sort_strcasecmp, +call ldap_sort_strcasecmp to compare the attribute values. +This function works with ASCII values only. For UTF-8 data, the +comparison result is unspecified. + +See Also +ldap_sort_strcasecmp, LDAP_VALCMP_CALLBACK +
+<function>ldap_sort_values</function> + +C SDK functions +ldap_sort_values + +ldap_sort_values + +The ldap_sort_values function sorts an array of +values retrieved from an ldap_get_values call. +Syntax +#include <ldap.h> +int ldap_sort_values( LDAP *ld, char **vals, + LDAP_VALCMP_CALLBACK cmp ); + +Parameters +<function>ldap_sort_values</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +vals + +The array of values to sort. + + + +cmp + +Comparison function used when sorting the values. In the ldap_sort_strcasecmp function, the comparison function +must pass char ** parameters. Because of this, you need +to use the ldap_sort_strcasecmp function, +rather than a function like strcasecmp. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +If unsuccessful, returns an LDAP error code. + + +Example +Example 21–53 sorts +the values of attributes before printing them. +Using <function>ldap_sort_values</function> +#include <stdio.h> +#include <string.h> +#include <ldap.h> +... +LDAP *ld; +LDAPMessage *result, *e; +BerElement *ber; +char *a, *dn; +char **vals; +int i; +char *my_searchbase = "dc=example,dc=com"; +char *my_filter = "(sn=Jensen)"; +... + if ( ( vals = ldap_get_values( ld, e, a ) ) != NULL ) { + /* Sort the values of the attribute */ + if ( ldap_sort_values( ld, vals, strcasecmp ) ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_sort_values" ); + return( 1 ); + } + /* Print the values of the attribute */ + for ( i = 0; vals[i] != NULL; i++ ) { + printf( "%s: %s\n", a, vals[i] ); + } + /* Free the values from memory */ + ldap_value_free( vals ); + } +... + + +See Also +ldap_get_values, +ldap_sort_strcasecmp, LDAP_VALCMP_CALLBACK. + +
+<function>ldapssl_advclientauth_init</function> + +C SDK functions +ldap_ldapssl_* + +ldap_ldapssl_* + +The ldapssl_advclientauth_init function initialize +the secure parts (Security and SSL) of the runtime for use by a client application +that may want to do SSL client authentication. +Syntax +#include <ldap_ssl.h> + int LDAP_CALL ldapssl_advclientauth_init( char *certdbpath, + void *certdbhandle, int needkeydb, char *keydbpath, + void *keydbhandle, int needsecmoddb, char *secmodpath, + const int sslstrength); + +Parameters +Please see the description of the sslstrength value +and note the potential problems that can be caused by passing in wrong host +and port name values. +<function>ldapssl_advclientauth_init</function> Function +Parameters + + + + +Parameter + +Description + + + + + +certdbpath + +Specifies the path to the database containing certificates for your +client. You can include the database filename in the path (for example, +/usr/mozilla/ cert_file_name.db). + + + + +certdbhandle + +Pass a NULL value for this. (This parameter is not +currently used.) + + + +needkeydb + +Specifies whether or not the private key database needs to be opened +for use. This parameter can have one of the following values: + +If it is a non-zero value, the function opens the private +key database, which is identified by the keydbpath argument. + +If 0, the function does not open the private +key database. + + + + + +keydbpath + +Specifies the path to the database containing the private key certified +by your certificate. You can include the database filename in the path (for +example, /usr/mozilla/key_file_name +.db). + + + +needsecmoddb + +Specifies whether or not the security module database file needs to +be opened for use. This parameter can have one of the following values: + +If it is a non-zero value, the function opens the security +module database, which is identified by the keydbpath argument. + +If 0, the function does not open the security +modules database. + + + + + +secmodpath + +Path to the database containing security modules. You can include the +database filename in the path (for example, /usr/mozilla/ +secmod_file_name .db). + + + +sslstrength + +Specifies how the server certificate is evaluated. It takes one of the +following: + +LDAPSSL_AUTH_WEAK indicates that you accept +the server’s certificate without checking the for certificate authority +(CA) that issued the certificate. +LDAPSSL_AUTH_CERT indicates that you accept +the server’s certificate only if you trust the CA that issued the certificate. + +LDAPSSL_AUTH_CNCHECK indicates that you +accept the server’s certificate only if you trust the CA that issued +the certificate and if the value of the cn attribute is +the DNS hostname of the server. If this option is selected, ensure that the +defhost parameter passed to ldapssl_init consists +of only one hostname and not a list of hosts. Furthermore, the port number +must be passed via the defport parameter, and cannot be +passed via a host: port option. + + + + + + +
+
+Returns +One of the following values: + +0 if successful. +-1 if unsuccessful. + + +Description +You can call ldapssl_advclientauth_init to initialize +your client application for SSL and certificate-based client authentication. +This function is similar to ldapssl_clientauth_init and +allows you to: + +Specify the name and path of a security module database. + +Specify the method used to verify the server’s certificate. + + +You must call ldapssl_advclientauth_init before +calling ldapssl_init to connect to the server. + + +Example +Example 21–54 initializes +a client before connecting with a secure LDAP server. +Using <function>ldapssl_advclientauth_init +</function> +#include <ldap.h> +#include <ldap_ssl.h> +#include <stdio.h> +... +/* Initialize client, using mozilla’s certificate database */ +if ( ldapssl_advclientauth_init( "/u/mozilla/.netscape/ + cert_file_name.db", + NULL, 1, "/u/mozilla/.netscape/ + key_file_name.db", NULL , 1, + "/u/mozilla/.netscape/ + secmod_file_name.db", LDAPSSL_AUTH_CNCHECK) < 0 ) { + perror( "ldap_advclientauth_init" ); + return( 1 ); + } +} +... + + +See Also +ldap_init, prldap_init + (IPv6), ldapssl_clientauth_init, ldapssl_init, ldapssl_install_routines + +
+<function>ldapssl_client_init</function> +The ldapssl_client_init function initializes the +secure parts (Security and SSL) of the runtime for use by your client application +to connect to a secure LDAP server over SSL. +Syntax +#include <ldap_ssl.h> +int ldapssl_client_init( const char *certdbpath, void *certdbhandle ); + +Parameters +<function>ldapssl_client_init</function> Function +Parameters + + + + +Parameter + +Description + + + + + +certdbpath + +Specifies the path to the database containing certificates for your +client. + + + +certdbhandle + +Pass a NULL value for this. (This parameter is not +used currently.) + + + +
+
+Returns +One of the following values: + +0 if successful. +-1 if unsuccessful. + + +Description +You can call the ldapssl_client_init function to +initialize your client application for SSL. It is only called once and returns +0 if all goes well. If you plan to use certificate-based authentication, +you should call either the ldapssl_clientauth_init or +the ldapssl_advclientauth_init function. +You must call ldapssl_client_init before +calling the ldapssl_init function to connect +to the server, or the ldap_start_tls_s function +to start transport layer security. + +Example +Example 21–55 +initializes a client before connecting with a secure LDAP server. +Using <function>ldapssl_client_init +</function> +#include <ldap.h> +#include <ldap_ssl.h> +#include <stdio.h> +... +/* Initialize client using a certificate database + copied from &cnDirectoryServer;. */ +if ( ldapssl_client_init( "/local/client/alias/", NULL ) < 0) { + printf( "Failed to initialize SSL client...\n" ); + return( 1 ); +} +The certdbpath is a path to the file system directory +containing the certificate database files. For example: +$ ls /local/client/alias/*.db +/local/client/alias/cert8.db +/local/client/alias/key3.db +/local/client/alias/secmod.db +$ + + +See Also +ldap_start_tls_s, ldap_init, prldap_init (IPv6), ldapssl_init, ldapssl_install_routines + +
+<function>ldapssl_clientauth_init</function> +The ldapssl_clientauth_init function initializes +your client application to connect to a secure LDAP server over SSL and to +use certificate-based client authentication. +Syntax +#include <ldap_ssl.h> +int ldapssl_clientauth_init( char *certdbpath, void *certdbhandle, + int needkeydb, char *keydbpath, void *keydbhandle ); + +Parameters +<function>ldapssl_clientauth_init</function> Function +Parameters + + + + +Parameter + +Description + + + + + +certdbpath + +Specifies the path to the database containing certificates for your +client. You can include the database filename in the path (for example, +/usr/mozilla/ cert_file_name.db). + + + + +needkeydb + +Specifies whether or not the private key database needs to be opened +for use. This parameter can have one of the following values: + +If it is a non-zero value, the function opens the private +key database, which is identified by the keydbpath argument. +If 0, the function does not open the private +key database. + + + + + +keydbpath + +Specifies the path to the database containing the private key certified +by your certificate. You can include the database filename in the path (for +example, /usr/mozilla/ key_file_name.db). + + + + +certdbhandle + +Pass a NULL value for this. (This parameter is not +currently used.) + + + +
+
+Returns +One of the following values: + +0 if successful. +-1 if unsuccessful. + + +Description +You can call the ldapssl_clientauth_init function +to initialize your client application for SSL and certificate-based client +authentication. However, if you need to specify the name and path of the security +modules database or if you need to specify how the server’s certificate +will be verified, you should call the ldapssl_advclientauth_init function +instead. +You must call ldapssl_clientauth_init before +calling ldapssl_init to connect to the server. + + +Example +Example 21–56 +initializes a client before connecting with a secure LDAP server. +Using <function>ldapssl_clientauth_init +</function> +#include <ldap.h> +#include <ldap_ssl.h> +#include <stdio.h> +... +/* Initialize client, using mozilla’s certificate database */ +if ( ldapssl_clientauth_init( "/u/mozilla/.netscape/ + cert_file_name.db", NULL, 1, + "/u/mozilla/.netscape/ + key_file_name.db", NULL ) < 0 ) { + perror( "ldap_clientauth_init" ); + return( 1 ); + } +} +... + + +See Also +ldap_init, prldap_init + (IPv6), ldapssl_init, ldapssl_install_routines +
+<function>ldapssl_enable_clientauth</function> +The ldapssl_enable_clientauth function enables +SSL client authentication on the given connection (passed using the ld parameter). + +Syntax +#include <ldap_ssl.h> +int ldapssl_enable_clientauth( LDAP *ld, char *keynickname, + char *keypasswd, char *certnickname ); + +Parameters +<function>ldapssl_enable_clientauth</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +keynickname + +Pass an empty string, "", for this value. (This parameter +is not currently used.) + + + +keypasswd + +Password to the encrypted private key database. + + + +certnickname + +Nickname of the certificate that you want to use for client authentication. + + + + +
+
+Returns +One of the following values: + +0 if successful. +-1 if unsuccessful. + + +See Also +ldapssl_clientauth_init +
+<function>ldapssl_err2string</function> +The ldapssl_err2string function returns the corresponding +error message for an SSL-specific error code. +Syntax +#include <ldap_ssl.h> + const char * LDAP_CALL ldapssl_err2string ( const int prerrno ); + +Parameters +<function>ldapssl_err2string</function> Function +Parameters + + + + +Parameter + +Description + + + + + +prerrno + +The SSL error code that you want interpreted into an error message. + + + + +
+
+Returns +One of the following values: + +If successful, returns the corresponding error message for +the given error code. +If unsuccessful (for example, if the error code is not a known +SSL error code), returns a pointer to the string Unknown error. + + + +Description +ldapssl_err2string provides support for SSL-specific +error messages that are not covered by the regular message routine ldap_err2string. If any ldapssl_* function +returns an error code that is unknown to ldap_err2string +–it returns Unknown error– this function +should be called to determine the SSL-specific error message. To check for +SSL errors, call ldapssl_err2string after you call any +of the following SSL initialization functions: + +ldapssl_client_init + +ldapssl_clientauth_init + +ldapssl_advclientauth_init + +ldapssl_pkcs_initThe +errors returned by these functions are usually related to certificate database +corruption, missing certificates in a certificate database, client authentication +failures, and other general SSL errors. + + +See Also +ldapssl_client_init, ldapssl_clientauth_init, ldapssl_advclientauth_init +, ldapssl_pkcs_init, ldap_err2string +
+<function>ldapssl_init</function> +The ldapssl_init function initializes the LDAP +library for SSL and installs the I/O routines for SSL. +Syntax +#include <ldap_ssl.h> + LDAP *ldapssl_init( const char *defhost, int defport, int defsecure ); + +Parameters +<function>ldapssl_init</function> Function +Parameters + + + + +Parameter + +Description + + + + + +defhost + +Connect to this LDAP server, if no other server is specified. + + + + +defport + +Connect to this server port, if no other port is specified. To specify +the default port 389, use LDAP_PORT as the value for this +parameter. + + + +defsecure + +Determines whether or not to establish the default connection over SSL. +Set this to a non-zero value to establish the default connection over SSL. + + + + +
+
+Returns +One of the following values: + +If successful, returns a pointer to an LDAP + structure, which should be passed to subsequent calls to other LDAP +API functions. +If unsuccessful, returns -1. + + + +Description +ldapssl_init allocates an LDAP + structure but does not open an initial connection. Before calling +this function, call ldapssl_client_init to +initialize your client for SSL. +Calling this function is equivalent to calling ldap_init or prldap_init (IPv6) +followed by ldapssl_install_routines and ldap_set_option to set the LDAP_OPT_SSL option +to LDAP_OPT_ON. + +Example +Example 21–57 connects +your client to a secure LDAP server. +Using <function>ldapssl_init</function> +#include <ldap.h> +#include <ldap_ssl.h> +#include <stdio.h> +... +/* Initialize client, using mozilla’s certificate database */ +if ( ldapssl_client_init( "/u/mozilla/.netscape/ + cert_file_name.db", NULL ) < 0) { + printf( "Failed to initialize SSL client...\n" ); + return( 1 ); +} +/* get a handle to an LDAP connection */ +if ( (ld = ldapssl_init( "cert.example.com", LDAPS_PORT, 1 )) == NULL { + perror( "ldapssl_init" ); + return( 1 ); +} +... +/* Client can now perform LDAP operations on the secure LDAP server */ +... + + +See Also +ldap_init, prldap_init + (IPv6), ldapssl_client_init, ldapssl_install_routines +
+<function>ldapssl_install_routines</function> +The ldapssl_install_routines function installs +the I/O routines that enable SSL over LDAP. +Syntax +#include <ldap_ssl.h> + int ldapssl_install_routines( LDAP *ld ); + +Parameters +<function>ldapssl_install_routines</function> Function +Parameter + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +
+
+Returns +One of the following values: + +0 if successful. +-1 if unsuccessful. + + +Description +You need to call ldapssl_install_routines in combination +with ldap_init or prldap_init + (IPv6) and ldap_set_option. As an +alternative, you can call ldapssl_init rather +than these three functions. +As is the case with the ldapssl_init function, +you need to call ldapssl_client_init to initialize +your client for SSL before calling ldapssl_install_routines. + + +Example +Example +21–58 connects your client to a secure LDAP server. +Using <function>ldapssl_install_routines +</function> +#include <ldap.h> +#include <ldap_ssl.h> +#include <stdio.h> +... +/* Initialize client, using mozilla’s certificate database */ +if ( ldapssl_client_init( "/u/mozilla/.netscape/ + cert_file_name.db", NULL ) < 0) { + printf( "Failed to initialize SSL client...\n" ); + return( 1 ); +} +/* Get the handle to an LDAP connection. Use prldap_init() for IPv6. */ +if ( (ld = ldap_init( MY_HOST, 636 )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); +} + +/* Load SSL routines */ +if ( ldapssl_install_routines( ld ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldapssl_install_routines" ); + return( 1 ); +} + +/* Set the option to use SSL with the default connection */ +if (ldap_set_option( ld, LDAP_OPT_SSL, LDAP_OPT_ON ) != LDAP_SUCCESS) { + ldap_perror( ld, "ldap_set_option" ); + return( 1 ); +} +... + + +See Also +ldap_init, prldap_init + (IPv6), ldapssl_init, ldapssl_client_init +
+<function>ldapssl_pkcs_init</function> +This function is deprecated and should not be used. It is included +in ldap-deprecated.h for backward-compatibility. + +The ldap_pcks_init function provides thread-safe +SSL initialization. +Syntax +int ldapssl_pkcs_init( const struct ldapssl_pkcs_fns *pfns); + +Description +The ldap_pkcs_init structure sets up callbacks +for the security library to obtain required runtime information. It should +be used in place of ldapssl_client_init, ldapssl_clientauth_init, and ldapssl_advclientauth_init +. +The &DirectorySDKForC; uses the Public Key Cryptography Standard +(PKCS) API implemented in Network Security Services (NSS) to provide SSL security +support. Specifically, NSS implements the security API as defined in the PKCS#11 +standard. +Because ldap_pkcs_init is based on the ldapssl_pkcs_fns + structure, you do not need to know all of the security parameters +at initialization, unlike the other SSL initialization functions (ldapssl_*_init +), which require all security parameters to be known at the time +of initialization. Example 21–59 + defines the ldapssl_pkcs_fns structure. +<structname>ldapssl_pkcs_fns</structname> Structure +Definition +typedef int (LDAP_PKCS_GET_TOKEN_CALLBACK) + (void *context, char **tokenname); +typedef int (LDAP_PKCS_GET_PIN_CALLBACK) + (void *context, const char *tokenname, char **tokenpin); +typedef int (LDAP_PKCS_GET_CERTPATH_CALLBACK) + (void *context, char **certpath); +typedef int (LDAP_PKCS_GET_KEYPATH_CALLBACK)(void *context, + char **keypath); +typedef int (LDAP_PKCS_GET_MODPATH_CALLBACK) + (void *context, char **modulepath); +typedef int (LDAP_PKCS_GET_CERTNAME_CALLBACK) + (void *context, char **certname); +typedef int (LDAP_PKCS_GET_DONGLEFILENAME_CALLBACK) + (void *context, char **filename); + +#define PKCS_STRUCTURE_ID 1 +struct ldapssl_pkcs_fns { + int local_structure_id; + void *local_data; + LDAP_PKCS_GET_CERTPATH_CALLBACK *pkcs_getcertpath; + LDAP_PKCS_GET_CERTNAME_CALLBACK *pkcs_getcertname; + LDAP_PKCS_GET_KEYPATH_CALLBACK *pkcs_getkeypath; + LDAP_PKCS_GET_MODPATH_CALLBACK *pkcs_getmodpath; + LDAP_PKCS_GET_PIN_CALLBACK *pkcs_getpin; + LDAP_PKCS_GET_TOKEN_CALLBACK *pkcs_gettokenname; + LDAP_PKCS_GET_DONGLEFILENAME_CALLBACK *pkcs_getdonglefilename; +}; + + +Parameters +<function>ldapssl_pkcs_init</function> Function +Parameters + + + + +Parameter + +Description + + + + + +pfns + +Specifies the ldap_pkcs_fns structure for initialization. + + + + +
+
+Returns +One of the following values: + +0 is successful. +-1 if unsuccessful. +n (a positive integer) denotes +a Netscape Portable Runtime (NSPR) error as returned by the PR_GetError + NSPR function. + + +See Also +ldapssl_client_init, ldapssl_clientauth_init, ldapssl_advclientauth_init + +
+<function>ldapssl_serverauth_init</function> +The ldapssl_serverauth_init function is a server-authentication +only version of ldapssl_clientauth_init. +Syntax +#include <ldap_ssl.h> +int ldapssl_serverauth_init( + const char *certdbpath, void *certdbhandle, const int sslstrength ); + +Parameters +Please see the description of the sslstrength value +and note the potential problems that can be caused by passing in wrong host +and port name values. +<function>ldapssl_serverauth_init</function> Function +Parameters + + + + +Parameter + +Description + + + + + +certdbpath + +Specifies the path to the database containing certificates for your +client. You can include the database filename in the path (for example, /usr/mozilla/cert_file_name.db). + + + + +certdbhandle + +Pass a NULL value for this. (This parameter is not +currently used.) + + + +sslstrength + +Specifies how the server certificate is evaluated. It takes one of the +following: + +LDAPSSL_AUTH_WEAK indicates that you accept +the server’s certificate without checking the for certificate authority +(CA) that issued the certificate. +LDAPSSL_AUTH_CERT indicates that you accept +the server’s certificate only if you trust the CA that issued the certificate. + +LDAPSSL_AUTH_CNCHECK indicates that you +accept the server’s certificate only if you trust the CA that issued +the certificate and if the value of the cn attribute is +the DNS hostname of the server. If this option is selected, please ensure +that the defhost parameter passed to +ldapssl_init consists of only one hostname and not a list of hosts. +Furthermore, the port number must be passed via the defport parameter, +and cannot be passed via a host: port option. + + + + + + +
+
+Returns +One of the following values: + +0 if successful. +-1 if unsuccessful. + + +Description +ldapssl_serverauth_init is a server-authentication +only version of ldapssl_clientauth_init. + This function allows the sslstrength parameter to be passed +in. +See Also +ldap_init, prldap_init + (IPv6), ldapssl_init, ldapssl_install_routines, ldapssl_clientauth_init + +
+<function>ldapssl_set_strength</function> +The ldapssl_set_strength sets the SSL strength +for an existing SSL-enabled LDAP session handle. +Syntax +#include <ldap_ssl.h> +int LDAP_CALL ldapssl_set_strength( LDAP *ld, int sslstrength ); + +Parameters +See the description of the sslstrength value +and note the potential problems that can be caused by passing in wrong host +and port name values. +<function>ldapssl_set_strength</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. If value is NULL, +the default for the new LDAP session handles is set. + + + +sslstrength + +Specifies how the server certificate is evaluated. It takes one of the +following: + +LDAPSSL_AUTH_WEAK indicates that you accept +the server’s certificate without checking the for certificate authority +(CA) that issued the certificate. +LDAPSSL_AUTH_CERT indicates that you accept +the server’s certificate only if you trust the CA that issued the certificate. + +LDAPSSL_AUTH_CNCHECK indicates that you +accept the server’s certificate only if you trust the CA that issued +the certificate and if the value of the cn attribute is +the DNS hostname of the server. If this option is selected, please ensure +that the defhost parameter passed to +ldapssl_init consists of only one hostname and not a list of hosts. +Furthermore, the port number must be passed via the defport parameter, +and cannot be passed via a host: port option. + + + + + + +
+
+
+<function>ldapssl_tls_start_s</function> +The ldapssl_tls_start_s function starts an SSL +handshake on a previously established non-secure connection. +Syntax +#include <ldap_ssl.h> + LDAP_API(int) LDAP_CALL ldapssl_tls_start_s( LDAP *ld, int defsecure, + char *certdbpath, char *keydbpath, char ***referralsp ); + +Parameters +<function>ldapssl_tls_start_s</function> Function +Parameter + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +defsecure + +Determines whether or not to establish the default connection over SSL. +Set this to a non-zero value to establish the default connection over SSL. + + + + +certdbpath + +Specifies the path to the database containing certificates for your +client. You can include the database filename in the path (for example, /usr/mozilla/cert_file_name.db). + + + + +keydbpath + +Specifies the path to the database containing the private key certified +by your certificate. You can include the database filename in the path (for +example, /usr/mozilla/key_file_name +.db). + + + +referralsp + +Pointer to an array of strings representing the referrals found by an +LDAP search operation and returned by the server (applicable only if the LDAP +operation was a search operation). When done, you can free this by calling +the ldap_value_free function. + + + +
+
+Description +The ldapssl_tls_start_s function starts an SSL +handshake on a previously established non-secure connection. +
+<function>ldap_str2charray</function> + +C SDK functions +ldap_str2charray + +ldap_str2charray + +This function is deprecated and should not be used. It is included in + ldap-deprecated.h for backward-compatibility. +<function>ldap_tmplattrs</function> + +C SDK functions +ldap_tmplattrs + +ldap_tmplattrs + +The ldap_tmplattrs function obtains a pointer to +the correct ldap_disptmpl structure. +Syntax +#include <disptmpl.h> + char ** ldap_tmplattrs( struct ldap_disptmpl *tmpl, char **includeattrs, + int exclude, unsigned long syntaxmask ); + +Parameters +<function>ldap_tmplattrs</function> Function +Parameters + + + + +Parameter + +Description + + + + + +tmpl + +The name of the template to be retrieved. + + + +includeattrs + +A null terminated array of attributes that should always be included +(it may be NULL if no extra attributes are required). + + + + +exclude + +If 0, only attributes where the logical AND of the +template item syntax id and the syntaxmask is non-zero +are included. If non-zero, attributes where the logical AND of the template +item syntax id and the syntaxmask is non-zero are excluded. + + + + +syntaxmask + +When non-zero, it is used to restrict the attribute set returned. + + + + +
+
+Returns + +A NULL terminated array that contains the +names of attributes that need to be retrieved if the template, defined by +tmpl , is to be used to display an entry. +A NULL pointer on error. + + +Description +The attribute list should be freed using ldap_value_free + . +See Also +ldap_value_free +
+<function>ldap_tmplerr2string</function> + +C SDK functions +ldap_tmplerr2string + +ldap_tmplerr2string + +The ldap_templerr2string function returns a string +representation of the error passed in the parameter. +Syntax +#include <disptmpl.h> + char * ldap_tmplerr2string( int err ); + +Parameters +<function>ldap_tmplerr2string</function> Function +Parameter + + + + +Parameter + +Description + + + + + +err + +Error returned. + + + +
+
+
+<function>ldap_ufn_search_c</function> + +C SDK functions +ldap_ufn_* + +ldap_ufn_* + +This function will be deprecated and should not be used. It is +included in ldap-to-be-deprecated.h for backward-compatibility. + +<function>ldap_ufn_search_ct</function> +This function will be deprecated and should not be used. It is +included in ldap-to-be-deprecated.h for backward-compatibility. + + + +<function>ldap_ufn_search_s</function> +This function will be deprecated and should not be used. It is +included in ldap-to-be-deprecated.h for backward-compatibility. + +<function>ldap_ufn_setfilter</function> +This function will be deprecated and should not be used. It is +included in ldap-to-be-deprecated.h for backward-compatibility. + + + +<function>ldap_ufn_setprefix</function> +This function will be deprecated and should not be used. It is +included in ldap-to-be-deprecated.h for backward-compatibility. + +<function>ldap_ufn_timeout</function> +This function will be deprecated and should not be used. It is +included in ldap-to-be-deprecated.h for backward-compatibility. + + + +<function>ldap_unbind</function> + +C SDK functions +ldap_unbind + +ldap_unbind + +The ldap_unbind function unbinds from the directory, +terminates the current association, and frees the resources contained in the + LDAP structure. +Syntax +#include <ldap.h> +int ldap_unbind( LDAP *ld ); + +Parameters +<function>ldap_unbind</function> Function +Parameter + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +
+
+Returns +For a list of possible results for an LDAP unbind operation, see ldap_unbind_s. +Description +The ldap_unbind function unbinds from the directory, +terminates the current association, and frees the resources contained in the + LDAP structure. The three unbind functions +(ldap_unbind , ldap_unbind_s +, and ldap_unbind_ext) all work +synchronously in the sense that they send an unbind request to the server, +close all open connections associated with the LDAP session handle, and dispose +of all resources associated with the session handle before returning. +There is no server response to an LDAP unbind operation. All three +of the unbind functions return LDAP_SUCCESS (or another +LDAP error code if the request cannot be sent to the LDAP server). After a +call to one of the unbind functions, the session handle ld is +invalid and it is illegal to make any further calls using it. + +Example +Example 21–60 closes +the current connection with the LDAP server. +Using <function>ldap_unbind</function> +#include <ldap.h> +... +LDAP *ld; +... +/* After completing your LDAP operations with the server, close the + connection. */ +if ( ldap_unbind( ld ) != LDAP_SUCCESS ) { + ldap_perror( ld, "Error while unbinding from the directory" ); + return( 1 ); +} +... + + +See Also +ldap_unbind_s, ldap_unbind_ext + +
+<function>ldap_unbind_s</function> + +C SDK functions +ldap_unbind_s + +ldap_unbind_s + +The ldap_unbind_s function unbinds from the directory, +terminates the current association, and frees the resources contained in the LDAP structure. +Syntax +#include <ldap.h> + int ldap_unbind_s( LDAP *ld ); + +Parameters +<function>ldap_unbind_s</function> Function +Parameter + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the request. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_NO_MEMORY if memory cannot be +allocated. + + +Description +The ldap_unbind_s function unbinds from the directory, +terminates the current association, and frees the resources contained in the LDAP structure. The three unbind functions ( ldap_unbind, ldap_unbind_s, +and ldap_unbind_ext) all work synchronously +in the sense that they send an unbind request to the server, close all open +connections associated with the LDAP session handle, and dispose of all resources +associated with the session handle before returning. +There is no server response to an LDAP unbind operation. All three +of the unbind functions return LDAP_SUCCESS (or another +LDAP error code if the request cannot be sent to the LDAP server). After a +call to one of the unbind functions, the session handle ld is +invalid and it is illegal to make any further calls using it. + +Example +Example 21–61 closes +the current connection with the LDAP server. +Using <function>ldap_unbind_s</function> +#include <ldap.h> +... +LDAP *ld; +... +/* After completing your LDAP operations with the server, close the + connection. */ +if ( ldap_unbind_s( ld ) != LDAP_SUCCESS ) { + ldap_perror( ld, "Error while unbinding from the directory" ); + return( 1 ); +} +... + + +See Also +ldap_unbind, ldap_unbind_ext + +
+<function>ldap_unbind_ext</function> + +C SDK functions +ldap_unbind_ext + +ldap_unbind_ext + +The ldap_unbind_ext function unbinds from the directory, +terminates the current association, and frees the resources contained in the LDAP structure. +Syntax +#include <ldap.h> + int ldap_unbind_ext( LDAP *ld, LDAPControl **serverctrls, + LDAPControl **clientctrls ); + +Parameters +<function>ldap_unbind_ext</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +serverctrls + +List of LDAP server controls. + + + +clientctrls + +List of client controls. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the request. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_NOT_SUPPORTED if controls are +included in your request (for example, as a session preference) and your LDAP +client does not specify that it is using the LDAP v3. Make sure that you set +the version of your LDAP client to version 3 before calling this function. + + + +Description +The ldap_unbind_ext function unbinds from the directory, +terminates the current association, and frees the resources contained in the LDAP structure. The three unbind functions (ldap_unbind, ldap_unbind_s, +and ldap_unbind_ext) all work synchronously +in the sense that they send an unbind request to the server, close all open +connections associated with the LDAP session handle, and dispose of all resources +associated with the session handle before returning. +Unlike the other two unbind functions, ldap_unbind_ext allows +you to explicitly include both server and client controls in your unbind request. +However, since there is no server response to an unbind request, there is +no way to receive a response from a server control that is included. + + +See Also +ldap_unbind, ldap_unbind_s + +
+<function>ldap_url_parse</function> + +C SDK functions +ldap_url_parse + +ldap_url_parse + +The ldap_url_parse function parses an LDAP URL +into its components. +Syntax +#include <ldap.h> + int ldap_url_parse( const char *url, LDAPURLDesc **ludpp ); + +Parameters +<function>ldap_url_parse</function> Function +Parameters + + + + +Parameter + +Description + + + + + +url + +The URL that you want to check. + + + +ludpp + +Pointer to a structure containing the components of the URL. + + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_URL_ERR_NOTLDAP if the URL does not +begin with the ldap:// or ldaps:// prefix. + +LDAP_URL_ERR_NODN if the URL missing trailing +slash after host or port. +LDAP_URL_ERR_BADSCOPE if the scope within +the URL is invalid. +LDAP_URL_ERR_MEM if not enough free memory +is available for this operation. +LDAP_URL_ERR_PARAM if an invalid argument +was passed to the function. + + +Example +Example 21–62 parses +an LDAP URL and prints out each component of it. +Using <function>ldap_url_parse</function> +#include <stdio.h> +#include <ldap.h> +... +char *my_url = "ldap://ldap.example.com:1389/dc=example,dc=com? + cn,mail,telephoneNumber?sub?(sn=Jensen)"; +LDAPURLDesc *ludpp; +int res, i; +... +if ( ( res = ldap_url_parse( my_url, &ludpp ) ) != 0 ) { + switch( res ){ + case LDAP_URL_ERR_NOTLDAP: + printf( "URL does not begin with \"ldap://\"\n" ); + break; + case LDAP_URL_ERR_NODN: + printf( "URL missing trailing slash after host or port\n" ); + break; + case LDAP_URL_ERR_BADSCOPE: + printf( "URL contains an invalid scope\n" ); + break; + case LDAP_URL_ERR_MEM: + printf( "Not enough memory\n" ); + break; + default: + printf( "Unknown error\n" ); + } + return( 1 ); +} +printf( "Components of the URL:\n" ); +printf( "Host name: %s\n", ludpp->lud_host ); +printf( "Port number: %d\n", ludpp->lud_port ); +if ( ludpp->lud_dn != NULL ) { + printf( "Base entry: %s\n", ludpp->lud_dn ); +} else { + printf( "Base entry: Root DN\n" ); +} +if ( ludpp->lud_attrs != NULL ) { + printf( "Attributes returned: \n" ); + for ( i=0; ludpp->lud_attrs[i] != NULL; i++ ) { + printf( "\t%s\n", ludpp->lud_attrs[i] ); +} +} else { + printf( "No attributes returned.\n" ); +} +printf( "Scope of the search: " ); +switch( ludpp->lud_scope ) { + case LDAP_SCOPE_BASE: + printf( "base\n" ); + break; + case LDAP_SCOPE_ONELEVEL: + printf( "one\n" ); + break; + case LDAP_SCOPE_SUBTREE: + printf( "sub\n" ); + break; + default: + printf( "Unknown scope\n" ); +} +printf( "Filter: %s\n", ludpp->lud_filter ); +... + + +See Also +ldap_free_urldesc +
+<function>ldap_url_parse_no_defaults</function> + +C SDK functions +ldap_url_parse_no_defaults + +ldap_url_parse_no_defaults + +The ldap_url_parse_no_defaults function parses +an LDAP URL into its components. +Syntax +#include <ldap.h> + int ldap_url_parse_no_defaults( const char *url, LDAPURLDesc **ludpp, + int dn_required ); + +Parameters +<function>ldap_url_parse_no_defaults</function> Function +Parameters + + + + +Parameter + +Description + + + + + +url + +The URL that you want to check. + + + +ludpp + +Pointer to a structure containing the components of the URL. + + + + +dn_required + +Specifies if a DN must be present in the URL. Set to 0, +the DN is not required. Set to 1, the function will return +an error LDAP_URL_ERR_NODN if no DN is present. + + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_URL_ERR_NODN if a required DN is not +present. +LDAP_URL_ERR_NOTLDAP if the URL does not +begin with the ldap:// or ldaps:// prefix. +LDAP_URL_ERR_NODN if the URL missing trailing +slash after host or port. +LDAP_URL_ERR_BADSCOPE if the scope within +the URL is invalid. +LDAP_URL_ERR_MEM if not enough free memory +is available for this operation. +LDAP_URL_ERR_PARAM if an invalid argument +was passed to the function. + + +Description +The ldap_url_parse_no_defaults function does not +set any default value in the fields that would be absent from the URL (for +example, the port number). +
+<function>ldap_url_search</function> + +C SDK functions +ldap_url_search + +ldap_url_search + +The ldap_url_search function searches the directory +asynchronously for matching entries, based on the contents of the URL. +Syntax +#include <ldap.h> + int ldap_url_search( LDAP *ld, const char *url, int attrsonly ); + +Parameters +<function>ldap_url_search</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +url + +LDAP URL specifying a search of the directory. + + + +attrsonly + +Specifies whether or not attribute values are returned along with the +attribute types. This parameter can have the following values: + +0 specifies that both attribute types and +attribute values are returned. +1 specifies that only attribute types are +returned. + + + + + +
+
+Returns +Returns the message ID of the ldap_url_search operation. +To check the result of this operation, call ldap_result +and ldap_result2error. +Description +ldap_url_search searches the directory for matching +entries, based on the contents of the URL. ldap_url_search is +an asynchronous function; it does not directly return results. If you want +the results to be returned directly by the function, call the synchronous +function ldap_url_search_s. +Example +Example 21–63 returns +the message ID. +Using <function>ldap_url_search +</function> +#include "examples.h" + +static void do_other_work(); +unsigned long global_counter = 0; + +int +main( int argc, char **argv ) +{ + char *my_url = "ldap://ldap.example.com/dc=example,dc=com? + cn,mail,telephoneNumber?sub?(sn=Jensen)"; + LDAP *ld; + LDAPMessage *result, *e; + BerElement *ber; + char *a, *dn; + char **vals; + int i, rc, finished, msgid; + int num_entries = 0; + struct timeval zerotime; + + zerotime.tv_sec = zerotime.tv_usec = 0L; + +/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ +if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); +} +/* authenticate to the directory as nobody */ +if ( ldap_simple_bind_s( ld, NULL, NULL ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_simple_bind_s" ); + return( 1 ); +} +/* search for all entries with surname of Jensen */ +if (( msgid = ldap_url_search( ld, my_url, 0 )) == -1 ) { + ldap_perror( ld, "ldap_url_search" ); + return( 1 ); +} + +/* Loop, polling for results until finished */ +finished = 0; +while ( !finished ) { + /* + * Poll for results. We call ldap_result with the "all" parameter + * set to zero. This causes ldap_result() to return exactly one + * entry if at least one entry is available. This allows us to + * display the entries as they are received. + */ + result = NULL; + rc = ldap_result( ld, msgid, 0, &zerotime, &result ); + switch ( rc ) { + case -1: + /* some error occurred */ + ldap_perror( ld, "ldap_result" ); + return( 1 ); + case 0: + /* Timeout was exceeded. No entries are ready for retrieval. */ + if ( result != NULL ) { + ldap_msgfree( result ); + } + break; + default: + /* + * Either an entry is ready for retrieval, or all entries have + * been retrieved. + */ + if (( e = ldap_first_entry( ld, result )) == NULL ) { + /* All done */ + finished = 1; + if ( result != NULL ) { + ldap_msgfree( result ); + } + continue; + } + /* for each entry print out name + all attrs and values */ + num_entries++; + if (( dn = ldap_get_dn( ld, e )) != NULL ) { + printf( "dn: %s\n", dn ); + ldap_memfree( dn ); + } + for ( a = ldap_first_attribute( ld, e, &ber ); + a != NULL; a = ldap_next_attribute( ld, e, ber ) ) { + if (( vals = ldap_get_values( ld, e, a )) != NULL ) { + for ( i = 0; vals[ i ] != NULL; i++ ) { + printf( "%s: %s\n", a, vals[ i ] ); + } + ldap_value_free( vals ); + } + ldap_memfree( a ); + } + if ( ber != NULL ) { + ldap_ber_free( ber, 0 ); + } + printf( "\n" ); + ldap_msgfree( result ); + } + /* Do other work here while you are waiting... */ + do_other_work(); +} + +/* All done. Print a summary. */ +printf( "%d entries retrieved. I counted to %ld " + "while I was waiting.\n", num_entries, + global_counter ); +ldap_unbind( ld ); +return( 0 ); +} + +/* + * Perform other work while polling for results. */ +static void +do_other_work() +{ + global_counter++; +} + + +See Also +ldap_url_search_s, ldap_result, ldap_result2error + +
+<function>ldap_url_search_s</function> + +C SDK functions +ldap_url_search_s + +ldap_url_search_s + +The ldap_url_search_s function searches the directory +synchronously for matching entries, based on the contents of the URL. +Syntax +#include <ldap.h> + int ldap_url_search_s( LDAP *ld, const char *url, + int attrsonly, LDAPMessage **res ); + +Parameters +<function>ldap_url_search_s</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +url + +LDAP URL specifying a search of the directory. + + + +attrsonly + +Specifies whether or not attribute values are returned along with the +attribute types. This parameter can have the following values: + +0 specifies that both attribute types and +attribute values are returned. +1 specifies that only attribute types are +returned. + + + + + +res + +Results of the search (when the call is completed). + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +If unsuccessful, returns the LDAP error code for the operation. + + + +Description +The ldap_url_search_s function searches the directory +for matching entries, based on the contents of the URL. ldap_url_search_s + is a synchronous function, which directly returns the results +of the operation. If you want to perform other operations while waiting for +the results of this operation, call the asynchronous function ldap_url_search. +Example +Example 21–64 +processes a search request from an LDAP URL. +Using <function>ldap_url_search_s</function> +#include <stdio.h> +#include <ldap.h> +... +LDAP *ld; +LDAPMessage *result; +char *my_url = "ldap://ldap.example.com/dc=example,dc=com? + cn,mail,telephoneNumber?sub?(sn=Jensen)"; +... +/* Process the search request in the URL */ +if ( ldap_url_search_s( ld, my_url, 0, &result ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_url_search_s" ); + return( 1 ); +} +... + + +See Also +ldap_search, ldap_search_st + +
+<function>ldap_url_search_st</function> + +C SDK functions +ldap_url_search_st + +ldap_url_search_st + +The ldap_url_search_st function searches the directory, +synchronously within a specified time limit, for matching entries, based on +the contents of the URL. +Syntax +#include <ldap.h> + int ldap_url_search_st( LDAP *ld, const char *url, int attrsonly, + struct timeval *timeout, LDAPMessage **res ); + +Parameters +<function>ldap_url_search_st</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +url + +LDAP URL specifying a search of the directory. + + + +attrsonly + +Specifies whether or not attribute values are returned along with the +attribute types. This parameter can have the following values: + +0 specifies that both attribute types and +attribute values are returned. +1 specifies that only attribute types are +returned. + + + + + +timeout + +Maximum time to wait for the results of the search. + + + +res + +Results of the search (when the call is completed). + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the request. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_NO_MEMORY if memory cannot be +allocated. +LDAP_LOCAL_ERROR if an error occurred +when receiving the results from the server. +LDAP_DECODING_ERROR if an error occurred +when decoding the BER-encoded results from the server. +LDAP_FILTER_ERROR if an error occurred +when parsing and BER-encoding the search filter specified by the filter argument. + +LDAP_TIMEOUT if the search exceeded +the time specified by the timeoutp argument. + +LDAP_NOT_SUPPORTED if controls are +included in your request (for example, as a session preference) and your LDAP +client does not specify that it is using the LDAP v3. Make sure that you set +the version of your LDAP client to version 3 before calling this function. + + +&cnDirectoryServer; and other LDAP server products may send result +codes in addition to those described. For example, the server may have loaded +a plug-in that returns custom result codes. Check your LDAP server documentation +for other result codes. + +Description +The ldap_url_search_st function searches the directory +for matching entries, based on the contents of the URL. This function works +like ldap_url_search_s and lets you specify +a time out period for the search. +See Also +ldap_search, ldap_search_s + +
+<function>ldap_utf8characters</function> + +C SDK functions +ldap_utf8characters + +ldap_utf8characters + +The ldap_utf8characters function accepts a Unicode +string and returns the number of characters. +Syntax +#include <ldap.h> + size_t ldap_utf8characters( const char* ); + +Parameters +<function>ldap_utf8characters</function> Function +Parameter + + + + +Parameter + +Description + + + + + +char + +Pointer to a UTF-8 string. + + + +
+
+Returns +Returns the number of UTF-8 characters in the 0 terminated +array. +
+<function>ldap_utf8copy</function> + +C SDK functions +ldap_utf8copy + +ldap_utf8copy + +The ldap_utf8copy function accepts a Unicode string +and copies the characters to a destination. +Syntax +#include <ldap.h> + int ldap_utf8copy( char* dst, const char* src ); + +Parameters +<function>ldap_utf8copy</function> Function +Parameter + + + + +Parameter + +Description + + + + + +dst + +Pointer to a destination for the copied characters. + + + +src + +Pointer to a UTF-8 string to copy. + + + +
+
+Description +ldap_utf8copy copies a character from src to + dst. This function handles any valid UTF-8 character (including + \0 and ASCII). +Returns +The number of characters copied. +
+<function>ldap_utf8getcc</function> + +C SDK functions +ldap_utf8getcc + +ldap_utf8getcc + +The ldap_utf8getcc function gets one UCS-4 character +and moves the pointer to the next character. +Syntax +#include <ldap.h> + unsigned long ldap_utf8getcc( const char** src ); + +Parameters +<function>ldap_utf8getcc</function> Function +Parameter + + + + +Parameter + +Description + + + + + +src + +Pointer to a UCS-4 character. + + + +
+
+
+<function>ldap_utf8isalnum</function> + +C SDK functions +ldap_utf8isalnum + +ldap_utf8isalnum + +The ldap_utf8isalnum function determines whether +the character is an alphanumeric one. +Syntax +#include <ldap.h> + int ldap_utf8isalnum( char* s ); + +Parameters +<function>ldap_utf8isalnum</function> Function +Parameter + + + + +Parameter + +Description + + + + + +s + +Pointer to a UTF-8 character. + + + +
+
+
+<function>ldap_utf8isalpha</function> + +C SDK functions +ldap_utf8isalpha + +ldap_utf8isalpha + +The ldap_utf8isalpha function determines whether +the character is a letter. +Syntax +#include <ldap.h> + int ldap_utf8isalpha( char* s ); + +Parameters +<function>ldap_utf8isalpha</function> Function +Parameter + + + + +Parameter + +Description + + + + + +s + +Pointer to a UTF-8 character. + + + +
+
+
+<function>ldap_utf8isdigit</function> + +C SDK functions +ldap_utf8isdigit + +ldap_utf8isdigit + +The ldap_utf8isdigit function determines whether +the character is a number. +Syntax +#include <ldap.h> + int ldap_utf8isdigit( char* s ); + +Parameters +<function>ldap_utf8isdigit</function> Function +Parameter + + + + +Parameter + +Description + + + + + +s + +Pointer to a UTF-8 character. + + + +
+
+
+<function>ldap_utf8isspace</function> + +C SDK functions +ldap_utf8isspace + +ldap_utf8isspace + +The ldap_utf8isspace function determines whether +the character is a space, tab, newline, return or formfeed. +Syntax +#include <ldap.h> + int ldap_utf8isspace( char* s ); + +Parameters +<function>ldap_utf8isspace</function> Function +Parameter + + + + +Parameter + +Description + + + + + +s + +Pointer to a UTF-8 character. + + + +
+
+
+<function>ldap_utf8len</function> + +C SDK functions +ldap_utf8len + +ldap_utf8len + +The ldap_utf8len function accepts a Unicode string +and returns the number of bytes it contains. +Syntax +#include <ldap.h> + int ldap_utf8len( const char* ); + +Parameters +<function>ldap_utf8len</function> Function +Parameter + + + + +Parameter + +Description + + + + + +char + +Pointer to a UTF-8 string. + + + +
+
+
+<function>ldap_utf8next</function> + +C SDK functions +ldap_utf8next + +ldap_utf8next + +The ldap_utf8next function accepts a character +and returns a pointer to the character immediately following it. +Syntax +#include <ldap.h> + char* ldap_utf8next( char* ); + +Parameters +<function>ldap_utf8next</function> Function +Parameter + + + + +Parameter + +Description + + + + + +char + +Pointer to a UTF-8 character. + + + +
+
+
+<function>ldap_utf8prev</function> + +C SDK functions +ldap_utf8prev + +ldap_utf8prev + +The ldap_utf8prev function accepts a character +and returns a pointer to the previous character. +Syntax +#include <ldap.h> + char* ldap_utf8prev( char* ); + +Parameters +<function>ldap_utf8prev</function> Function +Parameter + + + + +Parameter + +Description + + + + + +char + +Pointer to a UTF-8 character. + + + +
+
+
+<function>ldap_utf8strtok_r</function> + +C SDK functions +ldap_utf8strtok_r + +ldap_utf8strtok_r + +The ldap_utf8strtok_r function gets the next token +from a string. +Syntax +#include <ldap.h> + char* ldap_utf8strtok_r( char* src, const char* brk, char** next); + +Parameters +<function>ldap_utf8strtok_r</function> Function +Parameter + + + + +Parameter + +Description + + + + + +src + +Pointer to a UTF-8 string from which to extract token. + + + +brk + +Points to a NULL terminated set of delimiter characters. + + + + +next + +Pointer to the next token. + + + +
+
+Returns +Returns a pointer to the next token. If there are no remaining tokens, +returns a NULL pointer. +
+<function>ldap_whoami</function> + +C SDK functions +ldap_whoami + +ldap_whoami + +The ldap_whoami function sends an asynchronous +Who am I? extended operation request to determine the authorization identity +associated with a connection. +Syntax +LDAP_API(int) LDAP_CALL ldap_whoami( LDAP *ld, LDAPControl **serverctrls, + LDAPControl **clientctrls, int *msgidp ); + +Parameters +<function>ldap_whoami</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +serverctrls + +Pointer to an array of LDAPControl structures +representing LDAP server controls that apply to this operation. If you do +not want to pass any server controls, specify NULL for +this argument. + + + +clientctrls + +Pointer to an array of LDAPControl structures +representing LDAP client controls that apply to this operation. If you do +not want to pass any client controls, specify NULL for +this argument. + + + +msgidp + +Pointer to the message ID for this asynchronous call, for use with ldap_parse_whoami_result, or +to retrieve the result for use with ldap_parse_whoami +. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the request. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_NO_MEMORY if memory cannot be +allocated. + + +
+<function>ldap_whoami_s</function> + +C SDK functions +ldap_whoami_s + +ldap_whoami_s + +The ldap_whoami_s function sends a synchronous +Who am I? extended operation request to determine the authorization identity +associated with a connection. +Syntax +LDAP_API(int) LDAP_CALL ldap_whoami_s( LDAP *ld, LDAPControl **serverctrls, + LDAPControl **clientctrls, char **authzid ); + +Parameters +<function>ldap_whoami_s</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +Pointer to an LDAP structure containing +information about the connection to the LDAP server. + + + +serverctrls + +Pointer to an array of LDAPControl structures +representing LDAP server controls that apply to this operation. If you do +not want to pass any server controls, specify NULL for +this argument. + + + +clientctrls + +Pointer to an array of LDAPControl structures +representing LDAP client controls that apply to this operation. If you do +not want to pass any client controls, specify NULL for +this argument. + + + +authzid + +Pointer to the string to hold the authorization identity retrieved from +the server. + + + +
+
+Returns +One of the following values: + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR if any of the arguments +are invalid. +LDAP_ENCODING_ERROR if an error occurred +when BER-encoding the request. +LDAP_SERVER_DOWN if the LDAP server +did not receive the request or if the connection to the server was lost. + +LDAP_NO_MEMORY if memory cannot be +allocated. + + +
+<function>ldap_vals2html</function> + +C SDK functions +ldap_vals2html + +ldap_vals2html + +The ldap_vals2html function writes the HTML representation +of a set of values. +Syntax +#include <disptmpl.h> + int ldap_vals2html( LDAP *ld, char *buf, char **vals, char *label, + int labelwidth, unsigned long syntaxid, writeptype writeproc, + void *writeparm, char *eol, int rdncount, char *urlprefix ); + +Parameters +<function>ldap_vals2html</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +The LDAP pointer obtained by a previous call to ldap_open + . + + + +buf + + + + +vals + +A NULL terminated list of values, usually obtained by a call to ldap_get_values. + + + +label + +A string (usually a friendly form of an LDAP attribute name) shown next +to the values. + + + +labelwidth + +Specifies the label margin (the number of blank spaces displayed to +the left of the values). If zero is passed, a default label width is used. + + + + +syntaxid + +Display template attribute syntax identifier for a list of predefined +LDAP_SYN_... values. + + + +writeproc + +writeproc function should be declared as: +int writeproc( writeparm, p, len ) +void *writeparm; +char *p; +int len; +where p is a pointer to text to be written and +len is the length of the text. p is guaranteed +to be zero terminated. + + + +writeparm + +A pointer to a structure that will be passed as the first parameter +of the writeproc procedure. Typically, this is used to +pass the file descriptor of the file to write to. + + + +eol + +Lines of text are terminated with this string. + + + +rdncount + +Limits the number of components that are displayed for DN attributes. + + + + +urlprefix + +Starting text to use when constructing an LDAP URL. The default +is the string ldap:// + + + +
+
+Returns + +LDAP_SUCCESS if successful. + +An LDAP error code on error. + + +Description +ldap_vals2html produces HTML output of a single +set of LDAP attribute values. +See Also +ldap_vals2text +
+<function>ldap_vals2text</function> + +C SDK functions +ldap_vals2text + +ldap_vals2text + +The ldap_vals2text function writes the text representation +of an LDAP entry. +Syntax +#include <disptmpl.h> + int ldap_vals2text( LDAP *ld, char *buf, char **vals, char *label, + int labelwidth, unsigned long syntaxid, writeptype writeproc, + void *writeparm, char *eol, int rdncount ); + +Parameters +<function>ldap_vals2text</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +The LDAP pointer obtained by a previous call to ldap_open + . + + + +buf + + + + +vals + +A NULL terminated list of values, usually obtained +by a call to ldap_get_values. + + + +label + +A string (usually a friendly form of an LDAP attribute name) shown next +to the values. + + + +labelwidth + +Specifies the label margin (the number of blank spaces displayed to +the left of the values). If zero is passed, a default label width is used. + + + + +syntaxid + +Display template attribute syntax identifier for a list of predefined +LDAP_SYN_... values. + + + +writeproc + +writeproc function should be declared as: +int writeproc( writeparm, p, len ) +void *writeparm; +char *p; +int len; +where p is a pointer to text to be written and +len is the length of the text. p is guaranteed +to be zero terminated. + + + +writeparm + +A pointer to a structure that will be passed as the first parameter +of the writeproc procedure. Typically, this is used to +pass the file descriptor of the file to write to. + + + +eol + +Lines of text are terminated with this string. + + + +rdncount + +Limits the number of components that are displayed for DN attributes. + + + + +
+
+Returns + +LDAP_SUCCESS if successful. + +An LDAP error code on error. + + +Description +ldap_vals2text produces a text representation of +a single set of LDAP attribute values. +See Also +ldap_vals2html +
+<function>ldap_value_free</function> + +C SDK functions +ldap_value_free + +ldap_value_free + +The ldap_value_free function frees an array of +values from memory. +Syntax +#include <ldap.h> + void ldap_value_free( char **values ); + +Parameters +<function>ldap_value_free</function> Function +Parameter + + + + +Parameter + +Description + + + + + +values + +Array of values. + + + +
+
+Description +Use the ldap_value_free_len function +if the values are berval structures. + +Example +See the example under ldap_get_values. + +See Also +ldap_get_values, +ldap_value_free_len +
+<function>ldap_value_free_len</function> + +C SDK functions +ldap_value_free_len + +ldap_value_free_len + +The ldap_value_free_len function frees an array +of berval structures from memory. +Syntax +#include <ldap.h> + void ldap_value_free_len( struct berval **values ); + +Parameters +<function>ldap_value_free_len</function> Function +Parameter + + + + +Parameter + +Description + + + + + +values + +Array of berval structures. + + + +
+
+Description +Use the ldap_value_free function instead +of this function if the values are string values. +Example +See the example under ldap_get_values_len. + +See Also +ldap_get_values, +ldap_get_values_len +
+<function>ldap_version</function> + +C SDK functions +ldap_version + +ldap_version + +This function is deprecated and should not be used. It is included +in ldap-deprecated.h for backward-compatibility. Please +use ldap_get_option with LDAP_OPT_API_INFO + and an LDAPAPIInfo structure. +The ldap_version function gets version information +about the &DirectorySDKForC; libraries. +Syntax +#include <ldap.h> +int ldap_version( LDAPVersion *ver ); + +Parameters +<function>ldap_version</function> Function +Parameter + + + + +Parameter + +Description + + + + + +ver + +LDAPVersion structure returning version +information. If you only want the SDK version, you can pass NULL for +this parameter. + + + +
+
+Returns +The version number of the &DirectorySDKForC;, multiplied by 100. +For example, for version 1.0, the function returns 100. +See Also +ldap_get_option +
+<function>ldap_x_calloc</function> + +C SDK functions +ldap_x_* + +ldap_x_* + +The ldap_x_calloc function allocates space for +an array of elements. +Syntax +#include <ldap-extension.h> +void *ldap_x_calloc( size_t nelem, size_t elsize ); + +Parameters +<function>ldap_x_calloc</function> Function +Parameters + + + + +Parameter + +Description + + + + + +nelem + +Number of elements for which memory is to be allocated. + + + +elsize + +Size of each element. + + + +
+
+Returns + +If successful, returns a pointer to the space. +If there is no available memory, returns a NULL pointer. + + + +See Also +ldap_x_free, ldap_x_malloc + , ldap_x_realloc +
+<function>ldap_x_free</function> +The ldap_x_free function frees allocated memory. +Syntax +#include <ldap-extension.h> +void ldap_x_free( void *ptr ); + +Parameters +<function>ldap_x_free</function> Function +Parameter + + + + +Parameter + +Description + + + + + +ptr + +Pointer to the block of memory to be freed. + + + +
+
+See Also +ldap_x_calloc, ldap_x_malloc +, ldap_x_realloc +
+<function>ldap_x_hostlist_first</function> +The ldap_x_hostlist_first function returns the +first host and port defined in a host list file. +Syntax +#include <ldap-extension.h> + int ldap_x_hostlist_first( char *hostlist, int defport, char **hostp, + int *portp, struct ldap_x_hostlist_status **statusp ); + +Description +ldap_x_hostlist_first parses a space-separated +host list (useful for implementing an extended I/O CONNECT callback function) +and returns the first host and port defined. +Returns + +LDAP_SUCCESS if successful. + +If unsuccessful returns a valid LDAP API error code. + + +A NULL or zero-length hostlist causes +the host 127.0.0.1 to be returned. + +See Also +ldap_x_hostlist_status, LDAP_X_EXTIOF_CONNECT_CALLBACK, + +<function>ldap_x_hostlist_next</function> +The ldap_x_hostlist_next function returns the host +and port defined in a host list file following the previous host and port +returned. +Syntax +#include <ldap-extension.h> + int ldap_x_hostlist_next( char **hostp, int *portp, + struct ldap_x_hostlist_status **statusp ); + +Description +This utility parses a space-separated host list (useful for implementing +an extended I/O CONNECT callback function) and returns the host and port defined +following the previous host and port returned. +Returns + +LDAP_SUCCESS if successful. If no more +hosts are available, LDAP_SUCCESS is returned but hostp + is set to NULL. +If unsuccessful returns a valid LDAP API error code. + + +A NULL or zero-length hostlist causes +the host 127.0.0.1 to be returned. + +See Also +ldap_x_hostlist_status, LDAP_X_EXTIOF_CONNECT_CALLBACK, + +<function>ldap_x_hostlist_status</function> +See Also +ldap_x_hostlist_first, ldap_x_hostlist_next, LDAP_X_EXTIOF_CONNECT_CALLBACK + + +<function>ldap_x_hostlist_statusfree</function> +See Also +ldap_x_hostlist_first, ldap_x_hostlist_next, LDAP_X_EXTIOF_CONNECT_CALLBACK + + +<function>ldap_x_malloc</function> +The ldap_x_malloc function allocates space for +an object. +Syntax +#include <ldap-extension.h> +void *ldap_x_malloc( size_t size ); + +Parameters +<function>ldap_x_malloc</function> Function +Parameter + + + + +Parameter + +Description + + + + + +size + +Specifies the size for the allocated block of memory. + + + +
+
+See Also +ldap_x_free, ldap_x_calloc + , ldap_x_realloc +
+<function>ldap_x_realloc</function> +The ldap_x_realloc function changes the size of +a block of memory. +Syntax +#include <ldap-extension.h> +void *ldap_x_realloc( void *ptr, size_t size ); + +Parameters +<function>ldap_x_realloc</function> Function +Parameter + + + + +Parameter + +Description + + + + + +ptr + +Pointer to a block of memory. + + + +size + +Specifies the new size of the block. + + + +
+
+See Also +ldap_x_free, ldap_x_calloc + , ldap_x_malloc +
+<function>prldap_get_default_socket_info</function> + +C SDK functions +prldap_* + +prldap_* + +The prldap_get_default_socket_info function retrieves +default socket information. +Syntax +#include <ldappr.h> +int prldap_get_default_socket_info( LDAP *ld, PRLDAPSocketInfo *soip ); + +Parameters +<function>prldap_get_default_socket_info</function> Function +Parameters + + + + +Parameter + +Description + + + + + +fd + +The session handle returned from prldap_init. + + + + +soip + +Pointer to a structure containing socket specific information. + + + + +
+
+Returns + +LDAP_SUCCESS if successful. + +An LDAP API error code if an error occurs. +LDAP_PARAM_ERROR is returned if ld + is NULL. + + +See Also +prldap_set_default_socket_info + +
+<function>prldap_get_session_info</function> +The prldap_get_session_info function retrieves +application-specific data. +Syntax +#include <ldappr.h> + int prldap_get_session_info( LDAP *ld, void *sessionarg, + PRLDAPSessionInfo *seip ); + +Parameters +<function>prldap_get_session_info</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +The session handle returned from prldap_init. +If NULL, the functions are installed as the default functions +for all new LDAP handles. + + + +seip + +Pointer to a structure with session information data. + + + +
+
+Returns + +LDAP_SUCCESS if successful. + +An LDAP API error code if an error occurs. + + +Description +The prldap_get_session_option function retrieves +an option for an LDAP session handle or a session argument that is passed +to the CONNECT , POLL, NEWHANDLE, +or DISPOSEHANDLE extended I/O callbacks. +See Also +prldap_set_session_info +
+<function>prldap_get_session_option</function> +The prldap_get_session_option function retrieves +an option specific to the prldap layer. +Syntax +#include <ldappr.h> + int prldap_get_session_option( LDAP *ld, void *sessionarg, + int option, ... ); + +Returns + +LDAP_SUCCESS if successful. + +An LDAP API error code if an error occurs. + + +Description +The prldap_get_session_option function retrieves +an option for an LDAP session handle or a session argument that is passed +to the CONNECT , POLL, NEWHANDLE, +or DISPOSEHANDLE extended I/O callbacks. +See Also +prldap_set_session_option + +<function>prldap_get_socket_info</function> +The prldap_get_socket_info function retrieves socket-specific +information based on parameters passed to the extended I/O callback functions. +Syntax +#include <ldappr.h> + int prldap_get_socket_info( int fd, void *socketarg, + PRLDAPSocketInfo *soip ); + +Parameters +<function>prldap_get_socket_info</function> Function +Parameters + + + + +Parameter + +Description + + + + + +fd + +The session handle returned from prldap_init. + + + + +soip + +Pointer to a structure containing socket information data. + + + +
+
+Returns + +LDAP_SUCCESS if successful. + +An LDAP API error code if an error occurs. + + +See Also +prldap_set_socket_info +
+<function>prldap_init</function> +The prldap_init function creates a new session +handle with Netscape Portable Runtime (NSPR) I/O, threading, support for IPv6, +and DNS functions installed. +Syntax +#include <ldappr.h> + LDAP * prldap_init( const char *defhost, int defport, int shared ); + +Parameters +<function>prldap_init</function> Function +Parameters + + + + +Parameter + +Description + + + + + +defhost + +Space-delimited list of one or more host names (or IP address in dotted +notation, such as 192.168.0.99) of the LDAP servers that +you want the LDAP client to connect to. The names can be in hostname +: portnumber format (in which case, +portnumber overrides the port number specified by the defport + argument. + + + +defport + +Default port number of the LDAP server. To specify the standard LDAP +port (port 389), use LDAP_PORT as the value for this parameter. + + + + +shared + +Pass a non-zero value if you plan to use this LDAP handle for more than +one thread. + + + +
+
+Returns + +Pointer to LDAP session handle if successful. +NULL if an error occurs. + + +Description +To be able to use LDAP over Internet Protocol, version 6, IPv6, +this function should be used rather than ldap_init. + +See Also +prldap_install_routines +
+<function>prldap_install_routines</function> +The prldap_install_routines function installs Netscape +Portable Runtime (NSPR) I/O, threading, and DNS functions so they can be used +by the LDAP session handle. +Syntax +#include <ldappr.h> + int prldap_install_routines( LDAP *ld, int shared ); + +Parameters +<function>prldap_install_routines</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +The session handle returned from prldap_init. +If NULL, the functions are installed as the default functions +for all new LDAP handles. + + + +shared + +Pass a non-zero value if you plan to use this LDAP handle for more than +one thread. + + + +
+
+Returns + +LDAP_SUCCESS if successful. + +An LDAP API error code if an error occurs. + + +See Also +prldap_init +
+<function>prldap_set_default_socket_info</function> +The prldap_set_default_socket_info function sets +default socket information. +Syntax +#include <ldappr.h> + int prldap_set_default_socket_info( LDAP *ld, PRLDAPSocketInfo *soip ); + +Parameters +<function>prldap_set_default_socket_info</function> Function +Parameters + + + + +Parameter + +Description + + + + + +fd + +The session handle returned from prldap_init. + + + + +soip + +Pointer to a structure containing socket specific information. + + + + +
+
+Returns + +LDAP_SUCCESS if successful. + +LDAP_PARAM_ERROR is returned if ld + is NULL. +An LDAP API error code if an error occurs. + + +See Also +prldap_get_socket_info +
+<function>prldap_set_session_info</function> +The prldap_set_session_info function sets application-specific +data. +Syntax +#include <ldappr.h> + int prldap_set_session_info( LDAP *ld, void *sessionarg, + PRLDAPSessionInfo *seip ); + +Parameters +<function>prldap_set_session_info</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +The session handle returned from prldap_init. + + + + +seip + +Pointer to a structure containing session information data. + + + +
+
+Returns + +LDAP_SUCCESS if successful. + +An LDAP API error code if an error occurs. + + +Description +The prldap_set_session_info function sets application-specific +data for an LDAP session handle or a session argument that is passed to the + CONNECT, POLL, NEWHANDLE, +or DISPOSEHANDLE extended I/O callbacks. +See Also +prldap_get_session_info +
+<function>prldap_set_session_option</function> +The prldap_set_session_option function sets a session +option specific to the prldap layer. +Syntax +#include <ldappr.h> + int prldap_set_session_option( LDAP *ld, void *sessionarg, + int option, ... ); + +Parameters +<function>prldap_set_session_option</function> Function +Parameters + + + + +Parameter + +Description + + + + + +ld + +The session handle returned from prldap_init. + + + + +option + + + + +
+
+Returns + +LDAP_SUCCESS if successful. + +An LDAP API error code if an error occurs. + + +Description +The prldap_set_session_option function sets an +option for an LDAP session handle or a session argument that is passed to +the CONNECT , POLL, NEWHANDLE, +or DISPOSEHANDLE extended I/O callbacks. +See Also +prldap_get_session_option +
+<function>prldap_set_socket_info</function> +The prldap_set_socket_info function sets socket +information. +Syntax +#include <ldappr.h> + int prldap_set_socket_info( int fd, void *socketarg, + PRLDAPSocketInfo *soip ); + +Parameters +<function>prldap_set_socket_info</function> Function +Parameters + + + + +Parameter + +Description + + + + + +fd + +The session handle returned from prldap_init. + + + + +soip + +Pointer to a structure containing socket information data. + + + +
+
+Returns + +LDAP_SUCCESS if successful. + +An LDAP API error code if an error occurs. + + +Description +The prldap_set_socket_info function sets socket-specific +information based on parameters passed to the extended I/O callback functions. +For more information, see the ldappr.h header file. + +See Also +prldap_get_socket_info +
+
+
diff --git a/mozilla/directory/docs/ldapcsdk/csdk-ldap-urls.sgm b/mozilla/directory/docs/ldapcsdk/csdk-ldap-urls.sgm new file mode 100644 index 00000000000..88d11473ca9 --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/csdk-ldap-urls.sgm @@ -0,0 +1,312 @@ + +LDAP URLs With &DirectorySDKForC; + +C SDK +LDAP URLs + +This chapter describes how to use LDAP URLs to search and retrieve data +from the directory. + +This chapter covers the following topics: +Checking an LDAP URL With Directory +SDK for C +Getting the Components of an LDAP +URL With Directory SDK for C +Freeing the Components of an LDAP +URL With Directory SDK for C +Processing an LDAP URL With Directory +SDK for C + + +Checking an LDAP URL With &DirectorySDKForC; +To determine whether a URL is an LDAP URL, call the ldap_is_ldap_url + function. This function returns a nonzero value if the URL is +an LDAP URL. If the URL is not an LDAP URL, the function returns 0. +The following example determines if a URL is an LDAP URL. +Determining Whether a URL Is an +LDAP URL +#include <stdio.h> +#include "ldap.h" +... +char *my_url = "ldap://ldap.example.com/dc=example,dc=com"; +... +if ( ldap_is_ldap_url( my_url ) != 0 ) { + printf( "%s is an LDAP URL.\n", my_url ); +} else { + printf( "%s is not an LDAP URL.\n", my_url ); +} +... + +ldap_is_ldap_url determines whether a URL is an +LDAP URL. To verify that an LDAP URL complies with the LDAP URL syntax, you +should call the ldap_url_parse function as detailed in Getting the Components of an LDAP URL With Directory SDK +for C. +Getting the Components of an LDAP URL With &DirectorySDKForC; +To retrieve the individual components of an LDAP URL, call ldap_url_parse +. This function returns the LDAP URL components in an LDAPURLDesc + structure as shown in this example. +<structname>LDAPURLDesc</structname> Structure + +typedef struct ldap_url_desc { + char *lud_host; + int lud_port; + char *lud_dn; + char **lud_attrs; + int lud_scope; + char *lud_filter; + unsigned long lud_options; +} LDAPURLDesc; + +The following table describes the structure's fields. +<structname> +LDAPURLDesc</structname> Field Descriptions + + + + +Field Name + +Description + + + + + +lud_host + +The name of the host in the URL. + + + +lud_port + +The number of the port in the URL. + + + +lud_dn + +The distinguished name in the URL. + + + +lud_attrs + +A pointer to a NULL terminated array of the attributes +specified in the URL. + + + +lud_scope + + +The scope of the search specified in the URL. This field can have the +following values: +LDAP_SCOPE_BASE specifies a search of the +base entry. +LDAP_SCOPE_ONELEVEL specifies a search +of all entries one level under the base entry, not including the base entry. + +LDAP_SCOPE_SUBTREE specifies a search of +all entries at all levels under the base entry, including the base entry. + + + + + + +lud_filter + +Search filter included in the URL. + + + +lud_options + +Options. If LDAP_URL_OPT_SECURE, indicates that the +protocol is ldaps:// instead of ldap://. + + + + +
+The following example parses an LDAP URL. +Parsing an LDAP URL +#include <stdio.h> +#include "ldap.h" +... +char *my_url = + "ldap://ldap.example.com:1389/dc=example,dc=com? + cn,mail,telephoneNumber?sub?(sn=Jensen)"; +LDAPURLDesc *ludpp; +int res, i; +... +if ( ( res = ldap_url_parse( my_url, &ludpp ) ) != 0 ) { + switch( res ){ + case LDAP_URL_ERR_NOTLDAP: + printf( "URL does not begin with \"ldap://\"\n" ); + break; + case LDAP_URL_ERR_NODN: + printf( "URL missing trailing slash after host or port\n" ); + break; + case LDAP_URL_ERR_BADSCOPE: + printf( "URL contains an invalid scope\n" ); + break; + case LDAP_URL_ERR_MEM: + printf( "Not enough memory\n" ); + break; + default: + printf( "Unknown error\n" ); + } + return( 1 ); +} +printf( "Components of the URL:\n" ); +printf( "Host name: %s\n", ludpp->lud_host ); +printf( "Port number: %d\n", ludpp->lud_port ); +if ( ludpp->lud_dn != NULL ) { + printf( "Base entry: %s\n", ludpp->lud_dn ); +} else { + printf( "Base entry: Root DN\n" ); +} +if ( ludpp->lud_attrs != NULL ) { + printf( "Attributes returned: \n" ); + for ( i=0; ludpp->lud_attrs[i] != NULL; i++ ) { + printf( "\t%s\n", ludpp->lud_attrs[i] ); + } +} else { + printf( "No attributes returned.\n" ); +} +printf( "Scope of the search: " ); +switch( ludpp->lud_scope ) { + case LDAP_SCOPE_BASE: + printf( "base\n" ); + break; + case LDAP_SCOPE_ONELEVEL: + printf( "one\n" ); + break; + case LDAP_SCOPE_SUBTREE: + printf( "sub\n" ); + break; + default: + printf( "Unknown scope\n" ); +} +printf( "Filter: %s\n", ludpp->lud_filter ); +... + +The code in Example 13–3 prints +each component of the URL as shown in the following example. +Results of Parsing an LDAP +URL +Components of the URL: +Host name: ldap.example.com +Port number: 1389 +Base entry: dc=example,dc=com +Attributes returned: + cn + mail + telephoneNumber +Scope of the search: sub +Filter: (sn=Jensen) + +
+Freeing the Components of an LDAP URL With &DirectorySDKForC; +When you have finished working with the components of an LDAP URL, you +should free the LDAPURLDesc structure from memory +by calling the ldap_free_urldesc function. The following +example parses an LDAP URL. The example then frees the LDAPURLDesc structure +from memory, after verifying that the LDAP URL is valid. +Freeing the <structname>LDAPURLDesc</structname> Structure +From Memory +#include <stdio.h> +#include "ldap.h" +... +char *my_url = "ldap://ldap.example.com:1389/dc=example,dc=com?cn,mail, + telephoneNumber?sub?(sn=Jensen)"; +LDAPURLDesc *ludpp; +int res, i; +... +if ( ( res = ldap_url_parse( my_url, &ludpp ) ) != 0 ) { + switch( res ){ + case LDAP_URL_ERR_NOTLDAP: + printf( "URL does not begin with \"ldap://\"\n" ); + break; + case LDAP_URL_ERR_NODN: + printf( "URL does not contain a distinguished name\n" ); + break; + case LDAP_URL_ERR_BADSCOPE: + printf( "URL contains an invalid scope\n" ); + break; + case LDAP_URL_ERR_MEM: + printf( "Not enough memory\n" ); + break; + default: + printf( "Unknown error\n" ); + } + return( 1 ); +} +printf( "URL is a valid LDAP URL\n" ); +ldap_free_urldesc( ludpp ); +... + + +Processing an LDAP URL With &DirectorySDKForC; +To process an LDAP URL search request, call one of the following functions: + + +ldap_url_search_s is a synchronous function +that completes the search operation before returning. Call this function if +you need to wait for the operation to finish before continuing other work. +The function returns LDAP_SUCCESS if the operation +completed successfully. If an error occurred, the function returns an error +code. +ldap_url_search_st is a synchronous function +that allows a certain amount of time for the completion of the search operation. +Call this function to wait for the operation to complete, and to set a timeout +period for the operation. +ldap_url_search is an asynchronous function +that initiates the search operation but does not wait for the operation to +complete. Call this function if you want to perform other work in parallel +while waiting for the operation to complete. The function returns a message +ID identifying the search operation. To determine whether the operation is +completed or still in progress, call the ldap_result function. +After the operation is completed, call the ldap_result2error + function to determine if the operation was successful. If the +operation completed successfully, the ldap_result2error function +returns LDAP_SUCCESS. If an error occurred, the function +returns an error code. + +The following example processes a search request from an LDAP URL. +Processing an LDAP URL Search +Request +#include <stdio.h> +#include "ldap.h" +... +LDAP *ld; +LDAPMessage *result; +char *my_url = "ldap://ldap.example.com/dc=example,dc=com?cn,mail, + telephoneNumber?sub?(sn=Jensen)"; +/* Process the search request in the URL. */ +if ( ldap_url_search_s( ld, my_url, 0, &result ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_url_search_s" ); + return( 1 ); +} + + +
diff --git a/mozilla/directory/docs/ldapcsdk/csdk-multithread.sgm b/mozilla/directory/docs/ldapcsdk/csdk-multithread.sgm new file mode 100644 index 00000000000..a9e5d1c3529 --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/csdk-multithread.sgm @@ -0,0 +1,807 @@ + +Writing Multithreaded Clients With &DirectorySDKForC; + +C SDK +multithreaded clients + +This chapter shows how to write multithreaded LDAP client applications. + +This chapter covers the following topics: +Specifying Thread Functions With Directory SDK for C + +POSIX Thread Client Application With Directory SDK for C + + +The &DirectorySDKForC; APIs are thread-safe. By default, the APIs +use POSIX thread-safe primitives. Therefore, unless you specify your own thread +functions, standard best practices for POSIX threading apply. + +Specifying Thread Functions With Directory SDK for +C +You can write a multithreaded client with different threads accessing +the same LDAP structure. Use the POSIX thread API. +Alternatively, set up the session defining your own structures such that threads +do not interfere with data of other threads. +The LDAP_OPT_THREAD_FN_PTRS session option lets you +set up an ldap_thread_fns structure. The structure +identifies the functions that are called in multithreaded environments. For +example, the structure can define functions to lock critical sections of code +and to handle errors. As this structure lets you specify these functions, +you can use &DirectorySDKForC; in different types of threading environments. +Setting Up the <structname>ldap_thread_fns</structname> Structure + +You can write a multithreaded client in which different threads use +the same LDAP connection. Set up the ldap_thread_fns structure. +Then identify the functions that you want to use in the ldap_thread_fns + structure. +<structname>ldap_thread_fns</structname> Structure + +struct ldap_thread_fns { + LDAP_TF_MUTEX_ALLOC_CALLBACK *ltf_mutex_alloc; + LDAP_TF_MUTEX_FREE_CALLBACK *ltf_mutex_free; + LDAP_TF_MUTEX_LOCK_CALLBACK *ltf_mutex_lock; + LDAP_TF_MUTEX_UNLOCK_CALLBACK *ltf_mutex_unlock; + LDAP_TF_GET_ERRNO_CALLBACK *ltf_get_errno; + LDAP_TF_SET_ERRNO_CALLBACK *ltf_set_errno; + LDAP_TF_GET_LDERRNO_CALLBACK *ltf_get_lderrno; + LDAP_TF_SET_LDERRNO_CALLBACK *ltf_set_lderrno; + void *ltf_lderrno_arg; +}; + +The fields of the ldap_thread_fns structure +are described in the following table. +<structname>ldap_thread_fns +</structname> Field Descriptions + + + + +Field + +Description + + + + + +*ltf_mutex_alloc + +Function pointer for allocating a mutex. This function is called by +the client when needed if the function pointer is not NULL. + + + + +*ltf_mutex_free + +Function pointer for freeing a mutex. This function is called by the +client when needed if the function pointer is not NULL. + + + + +*ltf_mutex_lock + +Function pointer for locking critical sections of code. This function +is called by the client when needed if the function pointer is not NULL. + + + + +*ltf_mutex_unlock + +Function pointer for unlocking critical sections of code. This function +is called by the client when needed if the function pointer is not NULL. + + + + +*ltf_get_errno + +Function pointer for getting the value of the errno variable. +This function is called by the client when needed if the function pointer +is not NULL. In a threaded environment, errno is +typically redefined. The error structure has a value for each thread, rather +than a global value for the entire process. This redefinition is done at compile +time. The libldap library does not know what method your +code and your threading environment use to get the value of errno for +each thread. The library therefore calls this function to return the value +of errno. + + + +*ltf_set_errno + +Function pointer for setting the value of the errno variable. +This function is called by the client when needed if the function pointer +is not NULL. In a threaded environment, errno is +typically redefined. The error structure has a value for each thread, rather +than a global value for the entire process. This redefinition is done at compile +time. The libldap library does not know what method your +code and your threading environment use to get the value of errno for +each thread. The library therefore calls this function to set the value of +errno. + + + +*ltf_get_lderrno + +Function pointer for getting error values from calls to functions in +the libldap library. This function is called by the client +when needed if the function pointer is not NULL. If this +function pointer is not set, the libldap library records +these errors in fields in the LDAP structure. + + + + +*ltf_set_lderrno + +Function pointer for setting error values from calls to functions in +the libldap library. This function is called by the client +when needed if the function pointer is not NULL. If this +function pointer is not set, the libldap library records +these errors in fields in the LDAP structure. + + + + +*ltf_lderrno_arg + +Additional parameter passed to the functions for getting and setting +error values from calls to functions in the libldap library. +*ltf_get_lderrno and *ltf_set_lderrno identify +these functions. + + + +
+
+Setting Up the <structname>ldap_extra_thread_fns</structname> Structure + +&DirectorySDKForC; provides a structure, ldap_extra_thread_fns +, that specifies additional thread functions +for locking. The structure also specifies thread functions for semaphores +, which are protected variables. The ldap_extra_thread_fns + structure is defined in the following example. +Declaring the <structname>ldap_extra_thread_fns +</structname> Structure +struct ldap_extra_thread_fns { + LDAP_TF_MUTEX_TRYLOCK_CALLBACK *ltf_mutex_trylock; + LDAP_TF_SEMA_ALLOC_CALLBACK *ltf_sema_alloc; + LDAP_TF_SEMA_FREE_CALLBACK *ltf_sema_free; + LDAP_TF_SEMA_WAIT_CALLBACK *ltf_sema_wait; + LDAP_TF_SEMA_POST_CALLBACK *ltf_sema_post; + LDAP_TF_THREADID_CALLBACK *ltf_threadid_fn; +}; + +&DirectorySDKForC; supports only the LDAP_TF_TREADID_CALLBACK +*ltf_threadid_fn function. You use this function callback in a multithreaded +application to improve the performance of thread locking. The supported function +must return an identifier that is unique to the calling thread, like pthread_self + does. If any of the other extra thread callback functions are +set, the extra functions are ignored. +Setting Session Options +After you set up the ldap_thread_fns structure, +associate the structure with the current session. Call the ldap_set_option + function and pass LDAP_OPT_THREAD_FN_PTRS as +the value of the option parameter. Pass a pointer to the +ldap_thread_fns structure as the value of the optdata parameter. + +Associating the <structname>ldap_thread_fns +</structname> Structure With the Current Session +#include <stdio.h> +#include <malloc.h> +#include <errno.h> +#include <pthread.h> +#include "ldap.h" + +struct ldap_thread_fns tfns; +... + /* Set up the ldap_thread_fns structure with pointers + to the functions that you want called */ + memset( &tfns, '\0', sizeof(struct ldap_thread_fns) ); + + /* Specify the functions that you want called */ + + /* Call the my_mutex_alloc() function whenever mutexes + need to be allocated */ + tfns.ltf_mutex_alloc = (void *(*)(void)) my_mutex_alloc; + + /* Call the my_mutex_free() function whenever mutexes + need to be destroyed */ + tfns.ltf_mutex_free = (void (*)(void *)) my_mutex_free; + + /* Call the pthread_mutex_lock() function whenever a + thread needs to lock a mutex. */ + tfns.ltf_mutex_lock = (int (*)(void *)) pthread_mutex_lock; + + /* Call the pthread_mutex_unlock() function whenever a + thread needs to unlock a mutex. */ + tfns.ltf_mutex_unlock = (int (*)(void *)) pthread_mutex_unlock; + + /* Call the get_errno() function to get the value of errno */ + tfns.ltf_get_errno = get_errno; + + /* Call the set_errno() function to set the value of errno */ + tfns.ltf_set_errno = set_errno; + + /* Call the get_ld_error() function to get error values from + calls to functions in the libldap library */ + tfns.ltf_get_lderrno = get_ld_error; + + /* Call the set_ld_error() function to set error values for + calls to functions in the libldap library */ + tfns.ltf_set_lderrno = set_ld_error; + + /* Don’t pass any extra parameter to the functions for + getting and setting libldap function call errors */ + tfns.ltf_lderrno_arg = NULL; +... +/* Set the session option that specifies the functions to call for + multi-threaded clients */ +if (ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS, (void *) &tfns) != 0) { + ldap_perror( ld, "ldap_set_option: thread pointers" ); +} +... + +If you also set up the ldap_extra_thread_fns + structure, associate the structure with the current session. +Call the ldap_set_option function, passing LDAP_OPT_EXTRA_THREAD_FN_PTRS + as the value of the option parameter. Also pass +a pointer to the ldap_extra_thread_fns structure +as the value of the optdata parameter. +
+POSIX Thread Client Application With Directory SDK +for C + +C SDK +POSIX threading + +The following example which uses pthreads (POSIX +threads) on Solaris systems, is the source code for a multithreaded client. +The client connects to a specified LDAP server. The client then creates several +threads to perform multiple search and update operations simultaneously on +the directory. +Using POSIX Threading on a Solaris System +#include <stdio.h> +#include <malloc.h> +#include <errno.h> +#include <pthread.h> +#include <synch.h> +#include "ldap.h" + +/* Authentication and search information. */ +#define NAME "cn=Directory Manager" +#define PASSWORD "rtfm11111" +#define BASE "dc=example,dc=com" +#define SCOPE LDAP_SCOPE_SUBTREE + +/* Function declarations */ +static void *search_thread(); +static void *modify_thread(); +static void *add_thread(); +static void *delete_thread(); +static void set_ld_error(); +static int get_ld_error(); +static void set_errno(); +static int get_errno(); +static void tsd_setup(); + +/* Linked list of LDAPMessage structs for search results. */ +typedef struct ldapmsgwrapper { + LDAPMessage *lmw_messagep; + struct ldapmsgwrapper *lmw_next; +} ldapmsgwrapper; + +LDAP *ld; +pthread_key_t key; + +main( int argc, char **argv ) +{ + pthread_attr_t attr; + pthread_t search_tid, search_tid2, search_tid3, search_tid4; + pthread_t modify_tid, add_tid, delete_tid; + void *status; + struct ldap_thread_fns tfns; + struct ldap_extra_thread_fns extrafns; + int rc; + + /* Check command-line syntax. */ + if ( argc != 3 ) { + fprintf( stderr, "usage: %s <host> <port>\n", argv[0] ); + exit( 1 ); + } + + /* Create a key. */ + if ( pthread_key_create( &key, free ) != 0 ) { + perror( "pthread_key_create" ); + } + tsd_setup(); + + /* Initialize the LDAP session. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( argv[1], atoi( argv[2] ) )) == NULL ) { + perror( "ldap_init" ); + exit( 1 ); + } + + /* Set the function pointers for dealing with mutexes + and error information. */ + memset( &tfns, '\0', sizeof(struct ldap_thread_fns) ); + tfns.ltf_mutex_alloc = (void *(*)(void)) my_mutex_alloc; + tfns.ltf_mutex_free = (void (*)(void *)) my_mutex_free; + tfns.ltf_mutex_lock = (int (*)(void *)) pthread_mutex_lock; + tfns.ltf_mutex_unlock = (int (*)(void *)) pthread_mutex_unlock; + tfns.ltf_get_errno = get_errno; + tfns.ltf_set_errno = set_errno; + tfns.ltf_get_lderrno = get_ld_error; + tfns.ltf_set_lderrno = set_ld_error; + tfns.ltf_lderrno_arg = NULL; + + /* Set up this session to use those function pointers. */ + rc = ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS, (void *) &tfns ); + if ( rc < 0 ) { + fprintf( stderr, + "ldap_set_option (LDAP_OPT_THREAD_FN_PTRS): %s\n", + ldap_err2string( rc ) ); + exit( 1 ); + } + + /* Set the function pointers for working with semaphores. */ + memset( &extrafns, '\0', sizeof(struct ldap_extra_thread_fns) ); + extrafns.ltf_mutex_trylock = (int (*)(void *)) = null; + extrafns.ltf_sema_alloc = (void *(*)(void)) = null; + extrafns.ltf_sema_free = (void (*)(void *)) = null; + extrafns.ltf_sema_wait = (int (*)(void *)) = null; + extrafns.ltf_sema_post = (int (*)(void *)) = null; + extrafns.ltf_threadid_fn = (void * (*)(void) )pthread_self; + /* Set up this session to use those function pointers. */ + rc = ldap_set_option( ld, + LDAP_OPT_EXTRA_THREAD_FN_PTRS, + (void *) &extrafns ); + if ( rc < 0 ) { + fprintf( stderr, + "ldap_set_option (LDAP_OPT_EXTRA_THREAD_FN_PTRS): %s\n", + ldap_err2string( rc ) ); + exit( 1 ); + } + + /* Attempt to bind to the server. */ + rc = ldap_simple_bind_s( ld, NAME, PASSWORD ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); + exit( 1 ); + } + + /* Initialize the attribute. */ + if ( pthread_attr_init( &attr ) != 0 ) { + perror( "pthread_attr_init" ); + exit( 1 ); + } + + /* Specify that the threads are joinable. */ + pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ); + + /* Create seven threads: one for adding, one for modifying, + one for deleting, and four for searching. */ + if (pthread_create(&search_tid, &attr, search_thread, "1") != 0) { + perror( "pthread_create search_thread" ); + exit( 1 ); + } + if (pthread_create(&modify_tid, &attr, modify_thread, "2") != 0) { + perror( "pthread_create modify_thread" ); + exit( 1 ); + } + if (pthread_create(&search_tid2, &attr, search_thread, "3") != 0) { + perror( "pthread_create search_thread2" ); + exit( 1 ); + } + if (pthread_create(&add_tid, &attr, add_thread, "4" ) != 0) { + perror( "pthread_create add_thread" ); + exit( 1 ); + } + if (pthread_create(&search_tid3, &attr, search_thread, "5") != 0) { + perror( "phread_create search_thread3" ); + exit( 1 ); + } + if (pthread_create(&delete_tid, &attr, delete_thread, "6") != 0) { + perror( "pthread_create delete_thread" ); + exit( 1 ); + } + if (pthread_create(&search_tid4, &attr, search_thread, "7") != 0) { + perror( "pthread_create search_thread4" ); + exit( 1 ); + } + + /* Wait until these threads exit. */ + pthread_join( modify_tid, &status ); + pthread_join( add_tid, &status ); + pthread_join( delete_tid, &status ); + pthread_join( search_tid, &status ); + pthread_join( search_tid2, &status ); + pthread_join( search_tid3, &status ); + pthread_join( search_tid4, &status ); +} + +/* Thread for searching the directory. + The results are not printed out. */ +static void * +search_thread( char *id ) +{ + LDAPMessage *res; + LDAPMessage *e; + char *a; + char **v; + char *dn; + BerElement *ber; + int i, rc, parse_rc, msgid, finished; + int num_entries, num_refs; + void *tsd; + struct timeval zerotime; + zerotime.tv_sec = zerotime.tv_usec = 0L; + + printf( "Starting search_thread %s.\n", id ); + tsd_setup(); + /* Continually search the directory. */ + for ( ;; ) { + printf( "Thread %s: Searching...\n", id ); + finished = 0; + num_entries = 0; + num_refs = 0; + rc = ldap_search_ext( ld, BASE, SCOPE, "(objectclass=*)", + NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &msgid ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "Thread %s error: ldap_search: %s\n", + id, ldap_err2string( rc ) ); + continue; + } + + /* Iterate through the results. In this example, + don't print out all the results. (It's easier + to see the output from the other threads this way.) */ + while ( !finished ) { + rc = ldap_result( ld, msgid, LDAP_MSG_ONE, &zerotime, &res ); + switch ( rc ) { + case -1: + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) ); + finished = 1; + break; + case 0: + break; + /* Keep track of the number of entries found. */ + case LDAP_RES_SEARCH_ENTRY: + num_entries++; + break; + /* Keep track of the number of search references. */ + case LDAP_RES_SEARCH_REFERENCE: + num_refs++; + break; + case LDAP_RES_SEARCH_RESULT: + finished = 1; + parse_rc = ldap_parse_result( ld, res, &rc, + NULL, NULL, NULL, NULL, 1 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, + "Thread %s error: can't parse result code.\n", + id ); + break; + } else { + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, + "Thread %s error: ldap_search: %s\n", + id, ldap_err2string( rc ) ); + } else { + printf( "Thread %s: Got %d results and %d references.\n", + id, num_entries, num_refs ); + } + } + break; + default: + break; + } + } + } +} + +/* Thread for modifying directory entries. +This thread searches for entries and randomly selects entries from +the search results for modification. */ +static void * +modify_thread( char *id ) +{ + LDAPMessage *res; + LDAPMessage *e; + int i, modentry, num_entries, msgid, rc, parse_rc, finished; + LDAPMod mod; + LDAPMod *mods[2]; + char *vals[2]; + char *dn; + ldapmsgwrapper *list, *lmwp, *lastlmwp; + struct timeval zerotime; + zerotime.tv_sec = zerotime.tv_usec = 0L; + + printf( "Starting modify_thread %s.\n", id ); + tsd_setup(); + rc = ldap_search_ext( ld, BASE, SCOPE, "(objectclass=*)", + NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &msgid ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "Thread %s error: Modify thread: " + "ldap_search_ext: %s\n", id, ldap_err2string( rc ) ); + exit( 1 ); + } + list = lastlmwp = NULL; + finished = 0; + num_entries = 0; + while ( !finished ) { + rc = ldap_result( ld, msgid, LDAP_MSG_ONE, &zerotime, &res ); + switch ( rc ) { + case -1: + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) ); + exit( 1 ); + break; + case 0: + break; + + /* Keep track of the number of entries found. */ + case LDAP_RES_SEARCH_ENTRY: + num_entries++; + if (( lmwp = (ldapmsgwrapper *) + malloc( sizeof( ldapmsgwrapper ))) == NULL ) { + fprintf( stderr, "Thread %s: Modify thread: Cannot malloc\n", id ); + exit( 1 ); + } + lmwp->lmw_messagep = res; + lmwp->lmw_next = NULL; + if ( lastlmwp == NULL ) { + list = lastlmwp = lmwp; + } else { + lastlmwp->lmw_next = lmwp; + } + lastlmwp = lmwp; + break; + case LDAP_RES_SEARCH_REFERENCE: + break; + case LDAP_RES_SEARCH_RESULT: + finished = 1; + parse_rc = ldap_parse_result( ld, res, &rc, NULL, NULL, + NULL, NULL, 1 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, + "Thread %s error: can't parse result code.\n", + id ); + exit( 1 ); + } else { + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, + "Thread %s error: ldap_search: %s\n", + id, ldap_err2string( rc ) ); + } else { + printf( "Thread %s: Got %d results.\n", id, num_entries ); + } + } + break; + default: + break; + } + } + + /* Set up the modifications to be made. */ + mods[0] = &mod; + mods[1] = NULL; + vals[0] = "bar"; + vals[1] = NULL; + + /* Modify randomly selected entries. */ + for ( ;; ) { + + /* Randomly select the entries. */ + modentry = rand() % num_entries; + for ( i = 0, lmwp = list; lmwp != NULL && i < modentry; + i++, lmwp = lmwp->lmw_next ) { + /* Keep iterating. */ + } + if ( lmwp == NULL ) { + fprintf( stderr, + "Thread %s: Modify thread could not find entry %d of %d\n", + id, modentry, num_entries ); + continue; + } + e = lmwp->lmw_messagep; + printf( "Thread %s: Modify thread picked entry %d of %d\n", + id, i, num_entries ); + + /* Perform the modification. */ + dn = ldap_get_dn( ld, e ); + mod.mod_op = LDAP_MOD_REPLACE; + mod.mod_type = "description"; + mod.mod_values = vals; + printf( "Thread %s: Modifying (%s)\n", id, dn ); + rc = ldap_modify_ext_s( ld, dn, mods, NULL, NULL ); + if ( rc != LDAP_SUCCESS ) { + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_modify_ext_s: %s\n", ldap_err2string( rc ) ); + } + free( dn ); + } +} + +/* Thread for adding directory entries. + This thread randomly generates DNs for entries and attempts to + add them to the directory. */ +static void * +add_thread( char *id ) +{ + LDAPMod mod[5]; + LDAPMod *mods[6]; + char dn[BUFSIZ], name[40]; + char *cnvals[2], *snvals[2], *ocvals[3]; + int i, rc; + + printf( "Starting add_thread %s.\n", id ); + tsd_setup(); + + /* Set up the entry to be added. */ + for ( i = 0; i < 5; i++ ) { + mods[i] = &mod[i]; + } + mods[5] = NULL; + mod[0].mod_op = 0; + mod[0].mod_type = "cn"; + mod[0].mod_values = cnvals; + cnvals[1] = NULL; + mod[1].mod_op = 0; + mod[1].mod_type = "sn"; + mod[1].mod_values = snvals; + snvals[1] = NULL; + mod[2].mod_op = 0; + mod[2].mod_type = "objectclass"; + mod[2].mod_values = ocvals; + ocvals[0] = "top"; + ocvals[1] = "person"; + ocvals[2] = NULL; + mods[3] = NULL; + + /* Randomly generate DNs and add entries. */ + for ( ;; ) { + sprintf( name, "%d", rand() ); + sprintf( dn, "cn=%s, " BASE, name ); + cnvals[0] = name; + snvals[0] = name; + printf( "Thread %s: Adding entry (%s)\n", id, dn ); + rc = ldap_add_ext_s( ld, dn, mods, NULL, NULL ); + if ( rc != LDAP_SUCCESS ) { + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_add_ext_s: %s\n", ldap_err2string( rc ) ); + } + } +} + +/* Thread for deleting directory entries. +This thread randomly selects entries for deletion. */ +static void * +delete_thread( char *id ) +{ + LDAPMessage *res; + char dn[BUFSIZ], name[40]; + + printf( "Starting delete_thread %s.\n", id ); + tsd_setup(); + + /* Randomly select entries for deletion. */ + for ( ;; ) { + sprintf( name, "%d", rand() ); + sprintf( dn, "cn=%s, " BASE, name ); + printf( "Thread %s: Deleting entry (%s)\n", id, dn ); + if ( ldap_delete_ext_s( ld, dn, NULL, NULL ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_delete_ext_s" ); + } + } +} + +/* Function for allocating a mutex. */ +static void * +my_mutex_alloc( void ) +{ + pthread_mutex_t *mutexp; + if ( (mutexp = malloc( sizeof(pthread_mutex_t) )) != NULL ) { + pthread_mutex_init( mutexp, NULL ); + } + return( mutexp ); +} + +/* Function for freeing a mutex. */ +static void +my_mutex_free( void *mutexp ) +{ + pthread_mutex_destroy( (pthread_mutex_t *) mutexp ); + free( mutexp ); +} + +/* Error structure. */ +struct ldap_error { + int le_errno; + char *le_matched; + char *le_errmsg; +}; + +/* Function to set up thread-specific data. */ +static void +tsd_setup() +{ + void *tsd; + tsd = pthread_getspecific( key ); + if ( tsd != NULL ) { + fprintf( stderr, "tsd non-null!\n" ); + pthread_exit( NULL ); + } + tsd = (void *) calloc( 1, sizeof(struct ldap_error) ); + pthread_setspecific( key, tsd ); +} + +/* Function for setting an LDAP error. */ +static void +set_ld_error( int err, char *matched, char *errmsg, void *dummy ) +{ + struct ldap_error *le; + le = pthread_getspecific( key ); + le->le_errno = err; + if ( le->le_matched != NULL ) { + ldap_memfree( le->le_matched ); + } + le->le_matched = matched; + if ( le->le_errmsg != NULL ) { + ldap_memfree( le->le_errmsg ); + } + le->le_errmsg = errmsg; +} + +/* Function for getting an LDAP error. */ +static int +get_ld_error( char **matched, char **errmsg, void *dummy ) +{ + struct ldap_error *le; + le = pthread_getspecific( key ); + if ( matched != NULL ) { + *matched = le->le_matched; + } + if ( errmsg != NULL ) { + *errmsg = le->le_errmsg; + } + return( le->le_errno ); +} + +/* Function for setting errno. */ +static void +set_errno( int err ) +{ + errno = err; +} + +/* Function for getting errno. */ +static int +get_errno( void ) +{ + return( errno ); +} + + +
diff --git a/mozilla/directory/docs/ldapcsdk/csdk-quickstart.sgm b/mozilla/directory/docs/ldapcsdk/csdk-quickstart.sgm new file mode 100644 index 00000000000..559836ac98d --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/csdk-quickstart.sgm @@ -0,0 +1,171 @@ + +Getting Started With &DirectorySDKForC; + +C SDK +quick start + + +This chapter shows how to start using &DirectorySDKForC;and covers +the following topics: +Sample Directory Client Code + +Compiling Directory SDK for C Client +Applications +Running the Client + + + +Sample Directory Client Code + +example programs +C SDK +directory entry retrieval + +The following sample source code is for a command-line program that +retrieves the full name, last name, email address, and telephone number of +Barbara Jensen. +Retrieving a Directory Entry +#include <stdio.h> +#include "ldap.h" + +/* Adjust these setting for your own LDAP server */ +#define HOSTNAME "localhost" +#define PORT_NUMBER LDAP_PORT +#define FIND_DN "uid=bjensen,ou=People,dc=example,dc=com" + +int +main( int argc, char **argv ) +{ + LDAP *ld; + LDAPMessage *result, *e; + BerElement *ber; + char *a; + char **vals; + int i, rc; + + /* Get a handle to an LDAP connection. */ + /* To get the handle on an IPv6 network, use prldap_init() instead. */ + if ( (ld = ldap_init( HOSTNAME, PORT_NUMBER )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } + + /* Bind anonymously to the LDAP server. */ + rc = ldap_simple_bind_s( ld, NULL, NULL ); + if ( rc != LDAP_SUCCESS ) { + fprintf(stderr, "ldap_simple_bind_s: %s\n", ldap_err2string(rc)); + return( 1 ); + } + + /* Search for the entry. */ + if ( ( rc = ldap_search_ext_s( ld, FIND_DN, LDAP_SCOPE_BASE, + "(objectclass=*)", NULL, 0, NULL, NULL, LDAP_NO_LIMIT, + LDAP_NO_LIMIT, &result ) ) != LDAP_SUCCESS ) { + fprintf(stderr, "ldap_search_ext_s: %s\n", ldap_err2string(rc)); + return( 1 ); + } + + /* Since we are doing a base search, there should be only + one matching entry. */ + e = ldap_first_entry( ld, result ); + if ( e != NULL ) { + printf( "\nFound %s:\n\n", FIND_DN ); + + /* Iterate through each attribute in the entry. */ + for ( a = ldap_first_attribute( ld, e, &ber ); + a != NULL; a = ldap_next_attribute( ld, e, ber ) ) { + + /* For each attribute, print the attribute name and values. */ + if ((vals = ldap_get_values( ld, e, a)) != NULL ) { + for ( i = 0; vals[i] != NULL; i++ ) { + printf( "%s: %s\n", a, vals[i] ); + } + ldap_value_free( vals ); + } + ldap_memfree( a ); + } + if ( ber != NULL ) { + ber_free( ber, 0 ); + } + } + ldap_msgfree( result ); + ldap_unbind( ld ); + return( 0 ); +} + + +Compiling &DirectorySDKForC; Client Applications + +C SDK +compiling applications + +The method used to compile the source code depends on the operating +system on which you run the application. The following sections include instructions +for compiling on UNIX and Windows systems. +Compiling Programs on UNIX Systems +The &DirectorySDKForC; examples/ directory contains +a UNIX Makefile. You can modify the Makefile to +compile the sample by adjusting the flags in the file. The Makefile assumes +that the &DirectorySDKForC; header files are located in the ../include/ + directory. +Compiling Programs on Windows Systems + +If you are compiling the sample client on Windows, set up the build +framework for this application. Make sure to do the following: +If you are using Microsoft development tools, create a new +project workspace for a console application. Then add the source file to the +project. +Set your options to include lib\ as one +of the directories for library files, and include\ as +one of the directories for include files. +Link to nsldap32v60.lib, the LDAP API +import library for Windows. + + + +Running the Client +Before running the sample client, make sure that your LDAP server is +set up with the entry the sample attempts to find. Unless you change the source +code in Example 5–1, the +entry would be for the full name, last name, email address, and telephone +number of Barbara Jensen. +Running Programs on UNIX Systems +If you have linked the client on a UNIX platform, the client requires +the SDK library file. Make sure to set your LD_LIBRARY_PATH to +locate the libldap60.so library file and its dependencies. +As an alternative, when linking the file, specify the option that identifies +the library directories that the runtime linker should search for. For example, +on Solaris systems use the option to specify the location +of the libldap60.so file. +Running Programs on Windows Systems +If you have linked the client with the nsldap32v60.lib library +on a Windows system, copy the &DirectorySDKForC; DLL files to one of the +following directories: + +The directory where the application was loaded +The current directory +The Windows system directory, such as winnt\system32\ + +The Windows directory +The directories listed in the PATH environment +variable + + + + diff --git a/mozilla/directory/docs/ldapcsdk/csdk-resultcodes.sgm b/mozilla/directory/docs/ldapcsdk/csdk-resultcodes.sgm new file mode 100644 index 00000000000..b6e132f84c0 --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/csdk-resultcodes.sgm @@ -0,0 +1,1480 @@ + +&DirectorySDKForC; Result Codes + +result codes +C SDK result codes +error codes +C SDK result codes +C SDK result codes + +C SDK result codes + +This chapter lists some of the result codes that can be returned by +functions in the &DirectorySDKForC;. For ease of use, they are first listed +in numerical order, then in alphabetical order. This chapter contains the +following sections: + +Overview +Result Codes Summary in Numerical +Order +Result Codes Reference in Alphabetical +Order + + +Overview +LDAP result codes are extensible; thus, LDAP v3 extensions may define +their own error codes, and register them with the Internet Assigned Numbers +Authority (IANA). The IANA maintains a list of registered +LDAP parameters, including result codes. This list includes what &DirectorySDKForC; currently +knows in terms of result codes. More information can be found in RFC 4520, +Internet Assigned Numbers Authority (IANA) Considerations +for the Lightweight Directory Access Protocol (LDAP). +Result Codes Summary in Numerical Order +Table 22–1 gives +the decimal and hexadecimal value of all result codes. Values missing from +the sequence are not assigned to a result code. +Numerical Listing of Result +Codes by Value + + + + +Decimal + +Hexadecimal + +Defined Name + + + + + +0 + +0x00 + +LDAP_SUCCESS + + + +1 + +0x01 + +LDAP_OPERATIONS_ERROR + + + +2 + +0x02 + +LDAP_PROTOCOL_ERROR + + + +3 + +0x03 + +LDAP_TIMELIMIT_EXCEEDED + + + +4 + +0x04 + +LDAP_SIZELIMIT_EXCEEDED + + + +5 + +0x05 + +LDAP_COMPARE_FALSE + + + +6 + +0x06 + +LDAP_COMPARE_TRUE + + + +7 + +0x07 + +LDAP_STRONG_AUTH_NOT_SUPPORTED + + + +8 + +0x08 + +LDAP_STRONG_AUTH_REQUIRED + + + +9 + +0x09 + +LDAP_PARTIAL_RESULTS + + + +10 + +0x0a + +LDAP_REFERRAL + + + +11 + +0x0b + +LDAP_ADMINLIMIT_EXCEEDED + + + +12 + +0x0c + +LDAP_UNAVAILABLE_CRITICAL_EXTENSION + + + +13 + +0x0d + +LDAP_CONFIDENTIALITY_REQUIRED + + + +14 + +0x0e + +LDAP_SASL_BIND_IN_PROGRESS + + + + + + + + + +16 + +0x10 + +LDAP_NO_SUCH_ATTRIBUTE + + + +17 + +0x11 + +LDAP_UNDEFINED_TYPE + + + +18 + +0x12 + +LDAP_INAPPROPRIATE_MATCHING + + + +19 + +0x13 + +LDAP_CONSTRAINT_VIOLATION + + + +20 + +0x14 + +LDAP_TYPE_OR_VALUE_EXISTS + + + +21 + +0x15 + +LDAP_INVALID_SYNTAX + + + + + + + + + +32 + +0x20 + +LDAP_NO_SUCH_OBJECT + + + +33 + +0x21 + +LDAP_ALIAS_PROBLEM + + + +34 + +0x22 + +LDAP_INVALID_DN_SYNTAX + + + +35 + +0x23 + +LDAP_IS_LEAF + + + +36 + +0x24 + +LDAP_ALIAS_DEREF_PROBLEM + + + + + + + + + +48 + +0x30 + +LDAP_INAPPROPRIATE_AUTH + + + +49 + +0x31 + +LDAP_INVALID_CREDENTIALS + + + +50 + +0x32 + +LDAP_INSUFFICIENT_ACCESS + + + +51 + +0x33 + +LDAP_BUSY + + + +52 + +0x34 + +LDAP_UNAVAILABLE + + + +53 + +0x35 + +LDAP_UNWILLING_TO_PERFORM + + + +54 + +0x36 + +LDAP_LOOP_DETECT + + + + + + + + + +60 + +0x3C + +LDAP_SORT_CONTROL_MISSING + + + +61 + +0x3D + +LDAP_INDEX_RANGE_ERROR + + + + + + + + + +64 + +0x40 + +LDAP_NAMING_VIOLATION + + + +65 + +0x41 + +LDAP_OBJECT_CLASS_VIOLATION + + + +66 + +0x42 + +LDAP_NOT_ALLOWED_ON_NONLEAF + + + +67 + +0x43 + +LDAP_NOT_ALLOWED_ON_RDN + + + +68 + +0x44 + +LDAP_ALREADY_EXISTS + + + +69 + +0x45 + +LDAP_NO_OBJECT_CLASS_MODS + + + +70 + +0x46 + +LDAP_RESULTS_TOO_LARGE + + + +71 + +0x47 + +LDAP_AFFECTS_MULTIPLE_DSAS + + + + + + + + + +80 + +0x50 + +LDAP_OTHER + + + +81 + +0x51 + +LDAP_SERVER_DOWN + + + +82 + +0x52 + +LDAP_LOCAL_ERROR + + + +83 + +0x53 + +LDAP_ENCODING_ERROR + + + +84 + +0x54 + +LDAP_DECODING_ERROR + + + +85 + +0x55 + +LDAP_TIMEOUT + + + +86 + +0x56 + +LDAP_AUTH_UNKNOWN + + + +87 + +0x57 + +LDAP_FILTER_ERROR + + + +88 + +0x58 + +LDAP_USER_CANCELLED + + + +89 + +0x59 + +LDAP_PARAM_ERROR + + + +90 + +0x5a + +LDAP_NO_MEMORY + + + +91 + +0x5b + +LDAP_CONNECT_ERROR + + + +92 + +0x5c + +LDAP_NOT_SUPPORTED + + + +93 + +0x5d + +LDAP_CONTROL_NOT_FOUND + + + +94 + +0x5e + +LDAP_NO_RESULTS_RETURNED + + + +95 + +0x5f + +LDAP_MORE_RESULTS_TO_RETURN + + + +96 + +0x60 + +LDAP_CLIENT_LOOP + + + +97 + +0x61 + +LDAP_REFERRAL_LIMIT_EXCEEDED + + + +
+
+Result Codes Reference in Alphabetical Order + +result codes +C SDK result codes +error codes +C SDK result codes +C SDK result codes + +C SDK result codes + +The following sections contain the detailed reference information for +each result code listed in alphabetical order by code name. + +LDAP_ADMINLIMIT_EXCEEDED + +This result code indicates that the look-through +limit on a search operation has been exceeded. The look-through +limit is the maximum number of entries that the server will check +when gathering a list of potential search result candidates. +When working with &cnDirectoryServer;, keep in mind the following: + +If you are bound as the root DN, the server sets an infinite +look-through limit. +If you are not bound as the root DN, the server sets a time +limit. + + + +#define LDAP_ADMINLIMIT_EXCEEDED 0x0b +/* 11 */ + + +LDAP_AFFECTS_MULTIPLE_DSAS + +This result code indicates that the requested +operation needs to be performed on multiple servers, where this operation +is not permitted. +#define LDAP_AFFECTS_MULTIPLE_DSAS 0x47 + /* 71 */ + + +LDAP_ALIAS_DEREF_PROBLEM + +This result code indicates that a problem +occurred when dereferencing an alias. +&cnDirectoryServer; does not currently send this result code back +to LDAP clients. + +#define LDAP_ALIAS_DEREF_PROBLEM 0x24 + /* 36 */ + + +LDAP_ALIAS_PROBLEM + +This result code indicates that the alias +is invalid. +&cnDirectoryServer; does not currently send this result code back +to LDAP clients. + +#define LDAP_ALIAS_PROBLEM 0x21 /* +33 */ + + +LDAP_ALREADY_EXISTS + +This result code indicates that the request +is attempting to add an entry that already exists in the directory. &cnDirectoryServer; sends +this result code back to the client in the following situations: + +The request is an add request, and the entry already exists +in the directory. +The request is a modify DN request, and the new DN of the +entry already identifies another entry. +The request is adding an attribute to the schema, and an attribute +with the specified name or object identifier (OID) already exists. + + + +#define LDAP_ALREADY_EXISTS 0x44 /* +68 */ + + +LDAP_AUTH_UNKNOWN + +This result code indicates that an unknown +authentication method was specified. +&DirectorySDKForC; library sets this result code if ldap_bind or ldap_bind_s are +called and an authentication method other than LDAP_AUTH_SIMPLE is +specified. These functions only allow you to use simple authentication. + + +#define LDAP_AUTH_UNKNOWN 0x56 /* 86 +*/ + + +LDAP_BUSY + +This result code indicates that the server +is currently too busy to perform the requested operation. +#define LDAP_BUSY 0x33 /* 51 */ + + + +LDAP_CLIENT_LOOP + +This result code indicates that the LDAP +client detected a loop, for example, when following referrals. + +#define LDAP_CLIENT_LOOP 0x60 /* 96 +*/ + + +LDAP_COMPARE_FALSE + +This result code is returned after an +LDAP compare operation is completed. The result indicates that the specified +attribute value is not present in the specified entry. +#define LDAP_COMPARE_FALSE 0x05 /* +5 */ + + +LDAP_COMPARE_TRUE + +This result code is returned after an +LDAP compare operation is completed. The result indicates that the specified +attribute value is present in the specified entry. +#define LDAP_COMPARE_TRUE 0x06 /* 6 +*/ + + +LDAP_CONFIDENTIALITY_REQUIRED + +This result code indicates that confidentiality +is required for the operation. +#define LDAP_CONFIDENTIALITY_REQUIRED +0x0d /* 13 */ + + +LDAP_CONNECT_ERROR + +This result code indicates that the LDAP +client cannot establish a connection, or has lost the connection, with the +LDAP server. &DirectorySDKForC; sets this result code. If you have not +established an initial connection with the server, verify that you have specified +the correct host name and port number and that the server is running. + +#define LDAP_CONNECT_ERROR 0x5b /* 91 +*/ + + +LDAP_CONSTRAINT_VIOLATION + +This result code indicates that a value +in the request does not comply with certain constraints. &cnDirectoryServer; sends +this result code back to the client in the following situations: + +The request adds or modifies the userpassword attribute, +and one of the following is true: + +The server is configured to check the password syntax, and +the length of the new password is less than the minimum password length. + +The server is configured to check the password syntax, and +the new password is the same as one of the values of the uid, + cn, sn, givenname, +ou, or mail attributes. +The server is configured to keep a history of previous passwords, +and the new password is the same as one of the previous passwords. + + +The request is a bind request, and the user is locked out of the account. +(For example, the server can be configured to lock a user out of the account +after a given number of failed attempts to bind to the server.) + + + +#define LDAP_CONSTRAINT_VIOLATION 0x13 + /* 19 */ + + +LDAP_CONTROL_NOT_FOUND + +This result code indicates that a requested +LDAP control was not found. &DirectorySDKForC; sets this result code when +parsing a server response for controls and not finding the requested controls. +For example: + +ldap_parse_entrychange_control is +called, but no entry change notification control is found in the server’s +response. +ldap_parse_sort_control is +called, but no server-side sorting control is found in the server’s +response. +ldap_parse_virtuallist_control is +called, but no virtual list view response control is found in the server’s +response. + + +#define LDAP_CONTROL_NOT_FOUND 0x5d +/* 93 */ + + +LDAP_DECODING_ERROR + +This result code indicates that the LDAP +client encountered an error when decoding the LDAP response received from +the server. +#define LDAP_DECODING_ERROR 0x54 /* +84 */ + + +LDAP_ENCODING_ERROR + +This result code indicates that the LDAP +client encountered an error when encoding the LDAP request to be sent to the +server. +#define LDAP_ENCODING_ERROR 0x53 /* +83 */ + + +LDAP_FILTER_ERROR + +This result code indicates that an error +occurred when specifying the search filter. &DirectorySDKForC; sets this +result code if it cannot encode the specified search filter in an LDAP search +request. +#define LDAP_FILTER_ERROR 0x57 /* 87 +*/ + + +LDAP_INAPPROPRIATE_AUTH + +This result code indicates that the type +of credentials are not appropriate for the method of authentication used. &cnDirectoryServer; sends +this result code back to the client if simple authentication is used in a +bind request, but the entry has no userpassword attribute; +also, if LDAP_SASL_EXTERNAL is attempted on a non-SSL +connection. +#define LDAP_INAPPROPRIATE_AUTH 0x30 + /* 48 */ + + +LDAP_INAPPROPRIATE_MATCHING + +This result code indicates that an extensible +match filter in a search request contained a matching rule that does not apply +to the specified attribute type. +#define LDAP_INAPPROPRIATE_MATCHING +0x12 /* 18 */ + + +LDAP_INDEX_RANGE_ERROR + +This result code indicates that the search +results exceeded the range specified by the requested offsets. This result +code applies to search requests that contain virtual list view controls. + +#define LDAP_INDEX_RANGE_ERROR 0x3D + /* 61 */ + + +LDAP_INSUFFICIENT_ACCESS + +This result code indicates that the client +has insufficient access to perform the operation. Check that the user you +are authenticating as has the appropriate permissions. +#define LDAP_INSUFFICIENT_ACCESS 0x32 + /* 50 */ + + +LDAP_INVALID_CREDENTIALS + +This result code indicates that the credentials +provided in the request are invalid. &cnDirectoryServer; sends this result +code back to the client if a bind request contains the incorrect credentials +for a user or if a user’s password has already expired. +#define LDAP_INVALID_CREDENTIALS 0x31 + /* 49 */ + + +LDAP_INVALID_DN_SYNTAX + +This result code indicates than an invalid +DN has been specified. &cnDirectoryServer; sends this result code back to +the client if an add request or a modify DN request specifies an invalid DN. +It also sends this code when an LDAP_SASL_EXTERNAL bind +is attempted but certification to DN mapping fails. +#define LDAP_INVALID_DN_SYNTAX 0x22 + /* 34 */ + + +LDAP_INVALID_SYNTAX + +This result code indicates that the request +contains invalid syntax. &cnDirectoryServer; sends this result code back to +the client in the following situations: + +The server encounters an access control instruction (ACI) +with invalid syntax. +The request attempts to add or modify an aci attribute, +and the value of the attribute is an ACI with invalid syntax. +The request is a search request with a substring filter, and +the syntax of the filter is invalid. +The request is a modify request that is attempting to modify +the schema, but no values are provided (for example, the request might be +attempting to delete all values of the objectclass attribute). + + + +#define LDAP_INVALID_SYNTAX 0x15 /* +21 */ + + +LDAP_IS_LEAF + +This result code indicates that the specified +entry is a leaf entry. +&cnDirectoryServer; does not currently send this result code back +to LDAP clients. + +#define LDAP_IS_LEAF 0x23 /* 35 */ + + + +LDAP_LOCAL_ERROR + +This result code indicates that an error +occurred in the LDAP client, though it may also be returned by &cnDirectoryServer;. + +#define LDAP_LOCAL_ERROR 0x52 /* 82 +*/ + + +LDAP_LOOP_DETECT + +This result code indicates that the server +was unable to perform the requested operation because of an internal loop. +&cnDirectoryServer; does not currently send this result code back +to LDAP clients. + +#define LDAP_LOOP_DETECT 0x36 /* 54 +*/ + + +LDAP_MORE_RESULTS_TO_RETURN + +This result code indicates that there +are more results in the chain of results. The &DirectorySDKForC; sets this +result code when the ldap_parse_sasl_bind_result function +is called to retrieve the result code of an operation, and additional result +codes from the server are available in the LDAP structure. + +#define LDAP_MORE_RESULTS_TO_RETURN +0x5f /* 95 */ + + +LDAP_NAMING_VIOLATION + +This result code indicates that the request +violates the structure of the DIT. +&cnDirectoryServer; does not currently send this result code back +to LDAP clients. + +#define LDAP_NAMING_VIOLATION 0x40 +/* 64 */ + + +LDAP_NO_MEMORY + +This result code indicates that no memory +is available. &DirectorySDKForC; sets this result code if a function cannot +allocate memory (for example, when creating an LDAP request or an LDAP control). + +#define LDAP_NO_MEMORY 0x5a /* 90 */ + + + +LDAP_NO_OBJECT_CLASS_MODS + +This result code indicates that the request +is attempting to modify an object class that should not be modified (for example, +a structural object class). +&cnDirectoryServer; does not currently send this result code back +to LDAP clients. + +#define LDAP_NO_OBJECT_CLASS_MODS 0x45 + /* 69 */ + + +LDAP_NO_RESULTS_RETURNED + +This result code indicates that no results +were returned from the server. The &DirectorySDKForC; sets this result +code when the ldap_parse_result function +is called but no result code is included in the server’s response. + +#define LDAP_NO_RESULTS_RETURNED 0x5E + /* 94 */ + + +LDAP_NO_SUCH_ATTRIBUTE + +This result code indicates that the specified +attribute does not exist in the entry. &cnDirectoryServer; might send this +result code back to the client if, for example, a modify request specifies +the modification or removal of a non-existent attribute or if a compare request +specifies a non-existent attribute. +#define LDAP_NO_SUCH_ATTRIBUTE 0x10 + /* 16 */ + + +LDAP_NO_SUCH_OBJECT + +This result code indicates that the server +cannot find an entry specified in the request. &cnDirectoryServer; sends this +result code back to the client if it cannot find a requested entry and it +cannot refer your client to another LDAP server. +#define LDAP_NO_SUCH_OBJECT 0x20 /* +32 */ + + +LDAP_NOT_ALLOWED_ON_NONLEAF + +This result code indicates that the requested +operation is allowed only on entries that do not have child entries (leaf + entries as opposed to branch entries). &cnDirectoryServer; sends +this result code back to the client if the request is a delete request or +a modify DN request and the entry is a parent entry. You cannot delete or +move a branch of entries in a single operation. +#define LDAP_NOT_ALLOWED_ON_NONLEAF +0x42 /* 66 */ + + +LDAP_NOT_ALLOWED_ON_RDN + +This result code indicates that the requested +operation will affect the RDN of the entry. &cnDirectoryServer; sends this +result code back to the client if the request is a modify request that deletes +attribute values from the entry that are used in the RDN of the entry. (For +example, the request removes the attribute value uid=bjensen from +the entry uid=bjensen,ou=People,dc=example,dc=com.) + +#define LDAP_NOT_ALLOWED_ON_RDN 0x43 + /* 67 */ + + +LDAP_NOT_SUPPORTED + +This result code indicates that the LDAP +client is attempting to use functionality that is not supported. &DirectorySDKForC; sets +this result code if the client identifies itself as an LDAP v2 client, and +the client is attempting to use functionality available in LDAP v3. For example: + +You are passing LDAP controls to a function. +You are calling ldap_extended_operation , ldap_extended_operation_s, or +ldap_parse_extended_result to request an extended operation or to +parse an extended response. +You are calling ldap_rename or ldap_rename_s, and you are specifying a new superior +DN as an argument. +You are calling ldap_sasl_bind, ldap_sasl_bind_s, or ldap_parse_sasl_bind_result + to request Simple Authentication and Security Layer (SASL) authentication +or to parse a SASL bind response. +You are calling ldap_parse_virtuallist_control + to parse a virtual list control from the server’s response. +If you want to use these features, make sure to specify that your LDAP +client is an LDAP v3 client. + + +#define LDAP_NOT_SUPPORTED 0x5c /* 92 +*/ + + +LDAP_OBJECT_CLASS_VIOLATION + +This result code indicates that the request +specifies a new entry or a change to an existing entry that does not comply +with the server’s schema. &cnDirectoryServer; sends this result code +back to the client in the following situations: + +The request is an add request, and the new entry does not +comply with the schema. For example, the new entry does not have all the required +attributes, or the entry has attributes that are not allowed in the entry. + +The request is a modify request, and the change will make +the entry non compliant with the schema. For example, the change removes a +required attribute or adds an attribute that is not allowed.Check +the server error logs for more information, and the schema for the type of +entry that you are adding or modifying. + + +#define LDAP_OBJECT_CLASS_VIOLATION +0x41 /* 65 */ + + +LDAP_OPERATIONS_ERROR + +This is a general result code indicating +that an error has occurred. &cnDirectoryServer; might send this code if, for +example, memory cannot be allocated on the server. To troubleshoot this type +of error, check the server’s error logs. You may need to increase the +log level of the server to get additional information. +#define LDAP_OPERATIONS_ERROR 0x01 +/* 1 */ + + +LDAP_OTHER + +This result code indicates than an unknown +error has occurred. This error may be returned by &cnDirectoryServer; when +an error occurs that is not better described using another LDAP error code. +When this error occurs, check the server's error logs. You may need +to increase the log level of the server to get additional information. + +#define LDAP_OTHER 0x50 /* 80 */ + + + +LDAP_PARAM_ERROR + +This result code indicates that an invalid +parameter was specified. &DirectorySDKForC; sets this result code if a +function was called and invalid parameters were specified, for example, if +the LDAP structure is NULL. + +#define LDAP_PARAM_ERROR 0x59 /* 89 +*/ + + +LDAP_PARTIAL_RESULTS + +&cnDirectoryServer; sends this result +code to LDAP v2 clients to refer them to another LDAP server. When sending +this code to a client, the server includes a new line-delimited list of LDAP +URLs that identifies another LDAP server. If the client identifies itself +as an LDAP v3 client in the request, an LDAP_REFERRAL result +code is sent instead of this result code. +#define LDAP_PARTIAL_RESULTS 0x09 /* +9 */ + + +LDAP_PROTOCOL_ERROR + +This result code indicates that the LDAP +client’s request does not comply with the LDAP. &cnDirectoryServer; sends +this result code back to the client in the following situations: + +The server cannot parse the incoming request. +The request specifies an attribute type that uses a syntax +not supported by the server. +The request is a SASL bind request, but your client identifies +itself as an LDAP v2 client. +The request is a bind request that specifies an unsupported +version of the LDAP. Make sure to specify whether your LDAP client is an LDAP +v2 client or an LDAP v3 client. +The request is an add or a modify request that specifies the +addition of an attribute type to an entry, but no values are specified. + +The request is a modify request, and one of the following +is true: + +An unknown modify operation is specified (an operation other +than LDAP_MOD_ADD, LDAP_MOD_DELETE, +and LDAP_MOD_REPLACE). +No modifications are specified. + +The request is a modify DN request, and one of the following is true: + +The new RDN is not a valid RDN. +A new superior DN is specified, but your client identifies +itself as an LDAP v2 client. + +The request is a search request, and one of the following is true: + +An unknown scope is specified, meaning a scope other than +LDAP_SCOPE_BASE , LDAP_SCOPE_ONELEVEL, or LDAP_SCOPE_SUBTREE +. +An unknown filter type is specified. +The filter type LDAP_FILTER_GE or LDAP_FILTER_LE + is specified, but the type of attribute contains values that cannot +be ordered. (For example, if the attribute type uses a binary syntax, the +values of the attribute contain binary data, which cannot be sorted.) + +The request contains an extensible filter (a filter using +matching rules), but your client identifies itself as an LDAP v2 client. + +The request contains an extensible filter (a filter using +matching rules), but the matching rule is not supported by the server. + + +The request is a search request with a server-side sorting control, +and one of the following is true: + +The server does not have a syntax plug-in that supports the +attribute used for sorting. +The syntax plug-in does not have a function for comparing +values of the attribute. (This compare function is used for sorting.) + +The type of attribute specified for sorting contains values +that cannot be sorted in any order. For example, if the attribute type uses +a binary syntax, the values of the attribute contain binary data, which cannot +be sorted. +The server encounters an error when creating the sorting response +control (the control to be sent back to the client). +When sorting the results, the time limit or the look-through +limit is exceeded. The look-through limit is the maximum number of entries +that the server will check when gathering a list of potential search result +candidates. + +The request is an extended operation request, and the server does not +support the extended operation. In &cnDirectoryServer;, extended operations +are supported through extended operation server plug-ins. Make sure that the +server is loading a plug-in that supports the extended operation. Check the +OID of the extended operation in your LDAP client to make sure that it matches +the OID of the extended operation registered in the server plug-in. + +An authentication method other than LDAP_AUTH_SIMPLE or + LDAP_AUTH_SASL is specified.To troubleshoot +this type of error, check the server’s error logs. You may need to increase +the log level of the server to get additional information. + + + +#define LDAP_PROTOCOL_ERROR 0x02 /* +2 */ + + +LDAP_REFERRAL + +This result code indicates that the server +is referring the client to another LDAP server. When sending this code to +a client, the server includes a list of LDAP URLs that identify another LDAP +server. This result code is part of the LDAP v3. For LDAP v2 clients, &cnDirectoryServer; sends +an LDAP_PARTIAL_RESULTS result code instead. + +#define LDAP_REFERRAL 0x0a /* 10 */ + + + +LDAP_REFERRAL_LIMIT_EXCEEDED + +This result code indicates that the +referral hop limit was exceeded. &DirectorySDKForC; sets this +result code, when following referrals, if the client is referred to other +servers more times than allowed by the referral hop limit. + +#define LDAP_REFERRAL_LIMIT_EXCEEDED +0x61 /* 97 */ + + +LDAP_RESULTS_TOO_LARGE + +This result code indicates that the results +of the request are too large. +&cnDirectoryServer; does not currently send this result code back +to LDAP clients. + +#define LDAP_RESULTS_TOO_LARGE 0x46 + /* 70 */ + + +LDAP_SASL_BIND_IN_PROGRESS + +This result code is used in multi stage +SASL bind operations. The server sends this result code back to the client +to indicate that the authentication process has not yet completed. + +#define LDAP_SASL_BIND_IN_PROGRESS 0x0E + /* 14 */ + + +LDAP_SERVER_DOWN + +This result code indicates that &DirectorySDKForC; cannot +establish a connection with, or lost the connection to, the LDAP server. If +you have not established an initial connection with the server, verify that +you have specified the correct host name and port number and that the server +is running. +#define LDAP_SERVER_DOWN 0x51 /* 81 +*/ + + +LDAP_SIZELIMIT_EXCEEDED + +This result code indicates that the maximum +number of search results to return has been exceeded. This limit is specified +in the search request. If you specify no size limit, the server will set one. +When working with &cnDirectoryServer;, keep in mind the following: + +If you are bound as the root DN and specify no size limit, +the server enforces no size limit at all. +If you are not bound as the root DN and specify no size limit, +the server sets the size limit to the value specified by the sizelimit directive +in the server’s slapd.conf configuration file. + +If the size limit that you specify exceeds the value specified +by the sizelimit directive in the server’s slapd.conf + configuration file, the server uses the size limit specified in +the configuration file. + + +#define LDAP_SIZELIMIT_EXCEEDED 0x04 + /* 4 */ + + +LDAP_SORT_CONTROL_MISSING + +This result code indicates that server +did not receive a required server-side sorting control. &cnDirectoryServer; sends +this result code back to the client if the server receives a search request +with a virtual list view control but no server-side +sorting control as the virtual list view control requires +a server-side sorting control. +#define LDAP_SORT_CONTROL_MISSING 0x3C + /* 60 */ + + +LDAP_STRONG_AUTH_NOT_SUPPORTED + +This result code is returned as the result +of a bind operation. It indicates that the server does not recognize or support +the specified authentication method. +#define LDAP_STRONG_AUTH_NOT_SUPPORTED +0x07 /* 7 */ + + +LDAP_STRONG_AUTH_REQUIRED + +This result code indicates that a stronger +method of authentication is required to perform the operation. + +#define LDAP_STRONG_AUTH_REQUIRED 0x08 + /* 8 */ + + +LDAP_SUCCESS + +This result code indicates that the LDAP +operation was successful. +#define LDAP_SUCCESS 0x00 /* 0 */ + + + +LDAP_TIMELIMIT_EXCEEDED + +This result code indicates that the time +limit on a search operation has been exceeded. The time limit is specified +in the search request. If you specify no time limit, the server will set one. +When working with &cnDirectoryServer;, keep in mind the following: + +If you are bound as the root DN and specify no time limit, +the server enforces no limit at all. +If you are not bound as the root DN and specify no time limit, +the server sets the time limit. +If the time limit that you specify exceeds the time limit +specified for the server configuration, the server uses the time limit specified +in its configuration. + + +#define LDAP_TIMELIMIT_EXCEEDED 0x03 + /* 3 */ + + +LDAP_TIMEOUT + +This result code indicates that the LDAP +client timed out while waiting for a response from the server. &DirectorySDKForC; sets +this result code in the LDAP structure if +the time-out period (for example, in a search request) has been exceeded and +the server has not responded. +#define LDAP_TIMEOUT 0x55 /* 85 */ + + + +LDAP_TYPE_OR_VALUE_EXISTS + +This result code indicates that the request +attempted to add an attribute type or value that already exists. &cnDirectoryServer; sends +this result code back to the client in the following situations: + +The request attempts to add values that already exist in the +attribute. +The request is adding an attribute to the schema of the server, +but the OID of the attribute is already used by an object class in the schema. + +The request is adding an object class to the schema of the +server, and one of the following occurs: + +The object class already exists. +The OID of the object class is already used by another object +class or an attribute in the schema. +The superior object class for this new object class does not +exist. + + + + +#define LDAP_TYPE_OR_VALUE_EXISTS 0x14 + /* 20 */ + + +LDAP_UNAVAILABLE + +This result code indicates that the server +is unavailable to perform the requested operation. +At this point, neither &DirectorySDKForC; nor &cnDirectoryServer; return +this result code. + +#define LDAP_UNAVAILABLE 0x34 /* 52 +*/ + + +LDAP_UNAVAILABLE_CRITICAL_EXTENSION + +This result code indicates that the specified +control or matching rule is not supported by the server. &cnDirectoryServer; might +send back this result code if the request includes an unsupported control +or if the filter in the search request specifies an unsupported matching rule. + +#define LDAP_UNAVAILABLE_CRITICAL_EXTENSION +0x0c /* 12 */ + + +LDAP_UNDEFINED_TYPE + +This result code indicates that the request +specifies an undefined attribute type. +&cnDirectoryServer; does not currently send this result code back +to LDAP clients. + +#define LDAP_UNDEFINED_TYPE 0x11 /* +17 */ + + +LDAP_UNWILLING_TO_PERFORM + +This result code indicates that the server +is unwilling to perform the requested operation. &cnDirectoryServer; sends +this result code back to the client in the following situations: + +The client has logged in for the first time and needs to change +its password, but the client is requesting to perform other LDAP operations. +In this situation, the result code is accompanied by an expired password control. + +The request is a modify DN request, and a superior DN is specified. + +The database is in read-only mode, and the request attempts +to write to the directory. +The request is a delete request that attempts to delete the +root DSE. +The request is a modify DN request that attempts to modify +the DN of the root DSE. +The request is a modify request to modify the schema entry, +and one of the following occurs: + +The operation is LDAP_MOD_REPLACE. (The +server does not allow you to replace schema entry attributes.) +The request attempts to delete an object class that is the +parent of another object class. +The request attempts to delete a read-only object class or +attribute. + +The server uses a database plug-in that does not implement the operation +specified in the request. For example, if the database plug-in does not implement +the add operation, sending an add request will return this result code. + + + +#define LDAP_UNWILLING_TO_PERFORM 0x35 + /* 53 */ + + +LDAP_USER_CANCELLED + +This result code indicates that the user +cancelled the LDAP operation. +&cnDirectoryServer; does not currently send this result code back +to LDAP clients. + +#define LDAP_USER_CANCELLED 0x58 /* +88 */ + + + +
diff --git a/mozilla/directory/docs/ldapcsdk/csdk-sasl.sgm b/mozilla/directory/docs/ldapcsdk/csdk-sasl.sgm new file mode 100644 index 00000000000..c20c7155402 --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/csdk-sasl.sgm @@ -0,0 +1,222 @@ + +SASL Authentication With &DirectorySDKForC; + +C SDK +Simple Authentication and Security Layer (SASL) + +This chapter describes the process of using a Simple Authentication +and Security Layer (SASL) mechanism to authenticate an LDAP client to an LDAP +server. + +This chapter covers the following topics: +Understanding SASL and Directory +SDK for C +Determining Supported SASL Mechanisms +With Directory SDK for C +Authenticating Using SASL With Directory +SDK for C + + +Understanding SASL and &DirectorySDKForC; +The ability to authenticate to an LDAP server with a SASL mechanism +is a feature that is new to LDAP v3. LDAP v2 servers do not support this method +of authentication. +SASL is described in RFC 4422, Simple Authentication +and Security Layer (SASL). +Determining Supported SASL Mechanisms With &DirectorySDKForC; + +To determine the SASL mechanisms supported by an LDAP v3 server, get +the root DSE of the server, and check the supportedSASLMechanisms attribute. +The values of this attribute are the names of the SASL mechanisms supported +by the server. +If the root DSE does not have a supportedSASLMechanisms attribute, +the server does not support any SASL mechanisms. +For information about getting the root DSE, see To +Get the Root DSE. +Authenticating Using SASL With &DirectorySDKForC; + +To authenticate to the server with a SASL mechanism, call one of the +following: +The synchronous ldap_sasl_bind_s function + +The asynchronous ldap_sasl_bind function +If you call the asynchronous function ldap_sasl_bind, +you need to call the ldap_result and ldap_parse_sasl_bind_result + functions to get the result of the SASL bind operation. + + +Authentication with a SASL mechanism can take one or more round—trips +between your client and the server. The server might send a number of +challenges to the client. You might need to call ldap_sasl_bind_s + several times, or ldap_sasl_bind, ldap_result +, and ldap_parse_sasl_bind_result several +times in order to respond to each server challenge. +Before calling the function to perform a SASL bind operation, make sure +to specify that your client is LDAP v3 compliant. If you do not, an LDAP_NOT_SUPPORTED + result code is returned. See Specifying +the LDAP Version of Your Client. +Synchronous SASL Bind Operation +If you want to wait for the results of the SASL bind operation to complete +before continuing, call the synchronous ldap_sasl_bind_s function. +This function sends a SASL bind request to the server. This function blocks +other work until the server sends the results of the operation back to your +client. + +ldap_sasl_bind_s returns one of the following values: +LDAP_SUCCESS if your client has successfully +authenticated. +LDAP_SASL_BIND_IN_PROGRESS if the server +sends a challenge to your client. If you receive this result code, check the +servercredp argument for the berval structure +that contains the server’s challenge. Call the ldap_sasl_bind function +again to send a response to that challenge. +An LDAP error code if a problem occurred or if authentication +failed. See the ldap_sasl_bind_s function +documentation for a list of the possible result codes. + + +Asynchronous SASL Bind Operation +If you want to perform other work in parallel while waiting for the +SASL bind operation to complete, use the following procedure. +To Bind Asynchronously Over SASL + +Call the asynchronous ldap_sasl_bind function +to send an LDAP SASL bind request.This function returns an +LDAP_SUCCESS result code if the request was successfully sent, +or an LDAP result code if an error occurred while sending the request. The +function also sets the msgidp argument to point to a message +ID identifying the SASL bind operation. +Call the ldap_result function, passing in +this message ID to determine whether the server sent a response for this operation +to your client.The ldap_result function +uses the message ID to determine if the server sent a SASL bind response. +The function passes back the response in an LDAPMessage structure. + +Call the ldap_parse_sasl_bind_result function +to parse the LDAPMessage structure and retrieve information +from the server’s response.If the server sent a challenge +to your client, the challenge is specified in the berval structure +passed back as the servercredp argument. +Call the ldap_get_lderrno function to get +the LDAP result code for the operation. + +The function can return one of the following values: +LDAP_SUCCESS if your client successfully +authenticated to the server. +LDAP_SASL_BIND_IN_PROGRESS if the server +sent a challenge to your client.If the server returned an +LDAP_SASL_BIND_IN_PROGRESS result code, check the servercredp + argument for the berval structure that +contains the server’s challenge. +An LDAP error code if a problem occurred or if authentication +failed.See the ldap_sasl_bind function documentation +for a list of result codes that the server can return for this operation. + + + +If the result code is LDAP_SASL_BIND_IN_PROGRESS and +if the server passed back another challenge, determine the response to that +challenge by calling the ldap_sasl_bind function again +to send that response to the server.You can call ldap_result + and ldap_parse_sasl_bind_result again to +get the next challenge sent from the server, if the result is again LDAP_SASL_BIND_IN_PROGRESS +. + + +Authenticating Over SASL +This example shows an LDAP client that authenticates using the SASL +mechanism that is named babsmechanism. +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include "ldap.h" + +int +main( int argc, char **argv ) +{ + LDAP *ld; + LDAPMod mod0; + LDAPMod mod1; + LDAPMod *mods[ 3 ]; + char *vals0[ 2 ]; + char *vals1[ 2 ]; + time_t now; + char buf[ 128 ]; + struct berval cred; + struct berval *servcred; + int version; + /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( "localhost", 389 )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } + /* Set the LDAP protocol version supported by the client + to 3. (By default, this is set to 2. SASL authentication + is part of version 3 of the LDAP protocol.) */ + version = LDAP_VERSION3; + ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); + /* authenticate */ + cred.bv_val = "magic"; + cred.bv_len = sizeof( "magic" ) - 1; + if ( ldap_sasl_bind_s( ld, "uid=bjensen,ou=people,dc=example,dc=com", + "babsmechanism", &cred, NULL, NULL, + &servcred ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_sasl_bind_s" ); + return( 1 ); + } + /* get and print the credentials returned by the server */ + printf( "Server credentials: %s\n", servcred->bv_val ); + /* construct the list of modifications to make */ + mod0.mod_op = LDAP_MOD_REPLACE; + mod0.mod_type = "mail"; + vals0[0] = "babs@example.com"; + vals0[1] = NULL; + mod0.mod_values = vals0; + mod1.mod_op = LDAP_MOD_ADD; + mod1.mod_type = "description"; + time( &now ); + sprintf( buf, "This entry was modified with the modattrs program on %s", + ctime( &now )); + /* Get rid of \n which ctime put on the end of the time string */ + if ( buf[ strlen( buf ) - 1 ] == '\n' ) { + buf[ strlen( buf ) - 1 ] = '\0'; + } + vals1[ 0 ] = buf; + vals1[ 1 ] = NULL; + mod1.mod_values = vals1; + mods[ 0 ] = &mod0; + mods[ 1 ] = &mod1; + mods[ 2 ] = NULL; + /* make the change */ + if ( ldap_modify_s(ld, "uid=bjensen,ou=people,dc=example,dc=com", mods) + != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_modify_s" ); + return( 1 ); + } + ldap_unbind( ld ); + printf( "modification was successful\n" ); + return( 0 ); +} + + + + + diff --git a/mozilla/directory/docs/ldapcsdk/csdk-search.sgm b/mozilla/directory/docs/ldapcsdk/csdk-search.sgm new file mode 100644 index 00000000000..836f11dff38 --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/csdk-search.sgm @@ -0,0 +1,1738 @@ + +Searching the Directory With &DirectorySDKForC; + + +C SDK +search LDAP directory + +searching the directory +with C SDK + +This chapter explains how to use the LDAP C API to search the directory +and to retrieve entries. + +This chapter covers the following topics: +Overview of Search Functions for +Directory SDK for C +Sending a Search Request With Directory +SDK for C +Getting the Search Results With Directory +SDK for C +Sorting the Search Results With Directory +SDK for C +Freeing the Search Results With Directory +SDK for C +Examples of Search Operations With +Directory SDK for C + + +Overview of Search Functions for Directory SDK for +C +&DirectorySDKForC; provides functions that allow you to search a +directory and to retrieve results from the server. For example, you can send +a search request by calling the synchronous ldap_search_ext_s function +or the asynchronous ldap_search_ext function and the +server sends back matching results. + +In LDAP v3, a server can send three different types of results, represented +by LDAPMessage structures, back to the client: +Directory entries found by the search +Search references found within the scope of the search +A search reference is a reference to another +LDAP server. +An LDAP result code that specifies the result of the search +operation + +To receive search references from LDAP v3 servers, you must identify +your client as LDAP v3 enabled. If you do not, the server returns the LDAP +error code LDAP_PARTIAL_RESULTS, and a set of referrals. +See Specifying the LDAP Version of Your Client for +details. + +These results can be processed based on the following guidelines: +If you are retrieving the results sequentially, call ldap_result +. This function returns each result, an LDAPMessage structure, +and determines the type of result. A result can be either an entry or a search +reference. +If you are retrieving a chain of results, you can call +ldap_first_message and ldap_next_message to +iterate through the results in the chain.If you are just interested +in entries, you can call ldap_first_entry and ldap_next_entry +.If you are just interested in search references, +you can call ldap_first_reference and ldap_next_refrence +. +To get an entry from a result, an LDAPMessage structure, +call ldap_parse_entry. +To get a search reference from a result, an LDAPMessage + structure, call ldap_parse_reference. + +To get the LDAP result code for the search operation from +a result, an LDAPMessage structure, call ldap_parse_result +. + +To access data from entries found by the search, you need to follow +this general process in your code. + +Get each entry in the results. +Get the attributes from each entry. +Get the values from each attribute. + + + +Sending a Search Request With &DirectorySDKForC; + +C SDK +search LDAP directory +request + +To search the directory, call ldap_search_ext_s or +ldap_search_ext. ldap_search_ext_s is a synchronous +function that blocks other work until all results have been received from +the server. The function is declared as shown here. +<function>ldap_search_ext_s</function> Prototype + +LDAP_API(int) LDAP_CALL ldap_search_ext_s( LDAP *ld, const char *base, + int scope, const char *filter, char **attrs, int attrsonly, + LDAPControl **serverctrls, LDAPControl **clientctrls, + struct timeval *timeoutp, int sizelimit, LDAPMessage **res ); + +ldap_search_ext is an asynchronous function that +sends an LDAP search request to the server. You can do other work while checking +to see if the server has returned any results. The function is declared as +shown here. +<function>ldap_search_ext</function> Prototype + +LDAP_API(int) LDAP_CALL ldap_search_ext( LDAP *ld, const char *base, + int scope, const char *filter, char **attrs, int attrsonly, + LDAPControl **serverctrls, LDAPControl **clientctrls, + struct timeval *timeoutp, int sizelimit, int *msgidp ); + +Sample code for sending a search request can be found in Sending Search Request Using Directory SDK for C. +Search Parameters for Directory SDK for C + +C SDK +search LDAP directory +parameters + +For either of the functions illustrated in Example 9–1 and Example 9–2, you specify +the search criteria by using the parameters as detailed in the following table. +Search +Criteria Parameters + + + + +Parameter Name + +Description + + + + + +base + +Specifies the starting point in the directory, or the base DN, where +the search begins. For example, to search entries under dc=example,dc=com +, the base DN is dc=example,dc=com. See Specifying the Base DN and the Scope With Directory SDK +for C. + + + +scope + +Specifies which entries to search. The search can address the base DN +only, entries one level under the base DN, or all entries under the base DN. +See Specifying the Base DN and the Scope With Directory +SDK for C. + + + +filter + +Specifies a search filter by defining what to search for. A search filter +can be as simple as “find entries with the last name of Jensen” +or as complex as “find entries that belong to Dept. #17 and whose first +names start with the letter F.” See Specifying +a Search Filter With Directory SDK for C. + + + +attrsattrsonly + +Specify what to return. Options are the type of information to return, +and the attributes to retrieve. Also, options include whether to return only +attribute types, or both types and values. You can also specify to return +the names of attributes only, and not the values, by passing a nonzero value +for the attrsonly argument. See Specifying +the Attributes to Retrieve With Directory SDK for C. + + + +serverctrlsclientctrls + +Specify the LDAP v3 controls that are associated with this search operation. +For details on LDAP v3 controls, see Chapter 16, +LDAP Controls With Directory SDK for C. + + + +timeoutpsizelimit + +Specify search constraints that you want applied to the search. For +example, you can specify a different timeout period or maximum number of results +from the values already defined for the current session. See Setting Search Preferences With Directory SDK for C. + + + + +
+
+Specifying the Base DN and the Scope With &DirectorySDKForC; + +When sending a search request, you need to specify the base DN and the +search scope to identify the entries that you want searched. The base DN, +the root argument, is the DN of the entry that serves as the starting point +for the search. + +To specify the scope of the search, pass one of the following values +as the scope parameter: +LDAP_SCOPE_SUBTREE searches the base entry +and all entries at all levels under the base entry. +LDAP_SCOPE_ONELEVEL searches all entries +one level under the base entry. The base entry is not included in the search. +Use this setting if you just want to list the entries under a given entry. + +LDAP_SCOPE_BASE searches only the base +entry. Use this setting if you just want to read the attributes of the base +entry. + + +Specifying a Search Filter With Directory SDK for +C + +C SDK +search LDAP directory +filters + +When you search the directory, you use a search filter to define the +search. The following example illustrates the search filter syntax: + +(attribute operator +value) +(cn=Barbara Jensen) + + + +Compare the syntax to the example. You see that cn is +the attribute, that = is the operator, and that Barbara +Jensen is the value. The filter finds entries with the common name +Barbara Jensen. For a list of valid attributes for your search filter, +see the LDAP schema for the directory server you are using. For a list of +valid operators that you can use in your search filter, see the following +table. +Basic +Operators for Search Filters + + + + +Operator + +Description + +Example + + + + + += + +Returns entries whose attribute is equal to the value. + +(cn=Barbara Jensen) finds the entry with RDN cn=Barbara +Jensen. + + + +>= + +Returns entries whose attribute is greater than or equal to the value. + + +(sn >= jensen) finds all entries with surname (SN) +from jensen to the end of the alphabetical list. + + + + +<= + +Returns entries whose attribute is less than or equal to the value. + + +(sn <= jensen) finds all entries with SN from +the beginning of the alphabetical list to jensen. + + + + +=* + +Returns entries that have a value set for that attribute. + +(sn =*) finds all entries that have the sn attribute. + + + + +~= + +Returns entries whose attribute value approximately matches the specified +value. Typically, the algorithm matches words that sound alike. + +(sn ~= jensen) finds entries with sn = jensen but +also sn = jansen. + + + +
+With boolean operators and with parentheses, you can combine different +sets of conditions into one filter. The following shows boolean search filter +syntax for combining filters, and a simple example: + +(boolean-operator(filter1 +)(filter2)(filter3)) + +(|(sn=Jensen)(sn=Johnson)) + + + +The example uses the boolean or operator, |, to signify +a search for all entries with the last name Jensen or the +last name Johnson. The following table describes the valid +boolean operators that you can use in your search filter. +Boolean +Operators for Search Filters + + + + +Operator + +Description + + + + + +& + +Returns entries that match all specified filter criteria. + + + +| + +Returns entries that match one or more of the filter criteria. + + + + +! + +Returns entries for which the filter is not true. You can only apply +this operator to a single filter. For example: You can use: +(!(filter)) +You cannot use: +(!(filter1)(filter2)) + + + + + +
+You can also include wildcard characters, *, to search +for entries that start with, contain, or end with a given value. For example, +you can use this filter to search for all entries whose names begin with the +letter F: +(givenName=F*) +When comparing values with letters, the value of the letter a is +less than the value z. For example, the following filter +finds all entries with last names beginning with a through +Jensen: +(sn<=jensen) +
+Specifying the Attributes to Retrieve With Directory +SDK for C + +C SDK +search LDAP directory +attributes + +With the attrs argument, you can retrieve all attributes +in the entries returned by the search. Alternatively, you can specify the +attributes from the search results. + +To specify attributes, use the following guidelines: +To return selected attributes, pass an array of the attribute +names as the attrs argument. For example, to return only +email addresses and phone numbers, pass the NULL terminated +array {"mail", "telephoneNumber", NULL} as the attrs argument. + +To return all attributes in an entry, pass NULL as +the attrs argument. +To return no attributes from an entry, pass LDAP_NO_ATTRS + as the attrs argument. + +Sorting Attributes +If you plan to sort the results on your client, you need to return the +attributes that you plan to use for sorting. For example, if you plan to sort +by email address, make sure that the mail attribute is +returned in the search results. See Sorting the Search +Results With Directory SDK for C. +Operational Attributes +Some attributes are used by servers for administering the directory. +For example, the creatorsName attribute specifies the DN +of the user who added the entry. These attributes are called operational +attributes. +Servers do not normally return operational attributes in search results +unless you specify the attributes by name. For example, you can pass NULL + for the attrs argument to retrieve all of the +attributes in entries found by the search. When you pass this value, the operational +attribute creatorsName is not returned to your client. +You need to explicitly specify the creatorsName attribute +in the attrs argument. You can retrieve all attributes +in an entry, as well as selected operational attributes. Pass a NULL terminated +array that contains LDAP_ALL_USER_ATTRS. Also, pass the +names of the operational attributes as the attrs argument. +The following table lists operational attributes and explains the meaning +of their values. +Operational +Attributes and Descriptions of Their Values + + + + +Attribute Name + +Description of Values + + + + + +createTimestamp + +The time that the entry was added to the directory + + + +modifyTimestamp + +The time that the entry was last modified + + + +creatorsName + +DN of the user who added the entry to the directory + + + +modifiersName + +DN of the user who last modified the entry + + + +subschemaSubentry + +DN of the subschema entry, which controls the schema for this entry + + + + +
+
+
+Setting Search Preferences With &DirectorySDKForC; + +C SDK +search LDAP directory +preferences + +For a given search, you can specify the maximum number of results to +be returned. Alternatively, you can specify the maximum amount of time to +wait for a search. + +Use the timeoutp and sizelimit arguments +of the ldap_search_ext_s or the ldap_search_ext functions +with the following guidelines: +To specify an infinite time limit, in other words, no limit, +create a timeval structure with tv_sec = tv_usec += 0. Then pass a pointer to the structure as the timeoutp argument. + +To use the time limit specified by the LDAP_OPT_TIMELIMIT + option for this connection, pass NULL as the +timeoutp argument. +To specify an infinite size limit, in other words, no limit, +pass LDAP_NO_LIMIT as the sizelimit argument. + +To use the size limit specified by the LDAP_OPT_SIZELIMIT + option for this connection, pass NULL as the +sizelimit argument. +To specify preferences for all searches under the current +connection, call ldap_set_option and set the LDAP_OPT_SIZELIMIT + and LDAP_OPT_TIMELIMIT options. If +you do not want to specify a limit, in other words, no limit, set the value +of each option to LDAP_NO_LIMIT. + +The LDAP server administrator might already have configured time +limits and size constraints that you cannot override. +The following example sets these session preferences so that a search +returns no more than 100 entries, and takes no more than 30 seconds. +Sample Code to +Set Session Search Preferences +#include <stdio.h> +#include "ldap.h" +... +LDAP *ld; +int max_ret, max_tim; +char *host = "ldap.example.com"; +... +/* Initialize a session with the LDAP server ldap.example.com:389. */ +/* Use prldap_init() for IPv6 support. */ +if ( ( ld = ldap_init( host, LDAP_PORT ) ) == NULL ) { + perror( "ldap_init" ); + return( 1 ); +} + +/* Set the maximum number of entries returned. */ +max_ret = 100; +ldap_set_option(ld, LDAP_OPT_SIZELIMIT, (void *)&max_ret ); + + +/* Set the maximum number of seconds to wait. */ +max_tim = 30; +ldap_set_option( ld, LDAP_OPT_TIMELIMIT, (void *)&max_tim ); +... + + +
+Getting the Search Results With &DirectorySDKForC; + +C SDK +search LDAP directory +results + + +In LDAP v3, the server returns search results as a chain of LDAPMessage + structures, with each structure containing the following: +The directory entries found by the search. In other words, +those entries that match the search criteria. +Any search references found within the scope of the search. +A search reference is a reference to another LDAP server. + +An LDAP result code that specifies the result of the search +operation. + +Because results are represented as a chain, do not free individual +LDAPMessage structures within the chain. When you are done working +with the results, free the chain, rather than the individual structures. If +you free individual LDAPMessage structures from memory, +you might lose all of the results. + +To retrieve an individual result from a chain of LDAPMessage structures, +you can call one of the following sets of functions: +To get each entry and each search reference in the result, +call ldap_first_message and ldap_next_message. +Both of these functions return a pointer to an LDAPMessage structure +that represents an entry, search reference, or LDAP result code. You can get +the count of the structures in the chain by calling ldap_count_messages +. +If you want to retrieve just the entries from the chain, call +ldap_first_entry and ldap_next_entry. Both +of these functions return a pointer to an LDAPMessage structure +that represents an entry. You can get the count of the entries in the chain +by calling ldap_count_entries. +If you want to retrieve just the search references from the +chain, call ldap_first_reference and ldap_next_reference +. Both of these functions return a pointer to an LDAPMessage + structure that represents a search reference. You can get the +count of the search references in the chain by calling ldap_count_references +. + +Getting Results Synchronously + +C SDK +search LDAP directory +synchronous functions + +If you call ldap_search_ext_s to search the directory +synchronously, the function blocks processes until all results have been received. +The function then returns a chain of results in the result parameter, +a handle to an LDAPMessage structure. The following +example prints the values of all attributes in the entries returned by a synchronous +search. +Synchronous Searching +#include <stdio.h> +#include "ldap.h" +/* Change these as needed. */ +#define HOSTNAME "localhost" +#define PORTNUMBER LDAP_PORT +#define BASEDN "dc=example,dc=com" +#define SCOPE LDAP_SCOPE_SUBTREE +#define FILTER "(sn=Jensen)" +int +main( int argc, char **argv ) +{ + LDAP *ld; + LDAPMessage *res, *msg; + LDAPControl **serverctrls; + BerElement *ber; + char *a, *dn, *matched_msg = NULL, *error_msg = NULL; + char **vals, **referrals; + int version, i, rc, parse_rc, msgtype, num_entries = 0, + num_refs = 0; + /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } + version = LDAP_VERSION3; + if ( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) != + LDAP_SUCCESS ) { + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_set_option: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + /* Bind to the server anonymously. */ + rc = ldap_simple_bind_s( ld, NULL, NULL ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + ldap_unbind_s( ld ); + return( 1 ); + } + /* Perform the search operation. */ + rc = ldap_search_ext_s( ld, BASEDN, SCOPE, FILTER, + NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &res ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_search_ext_s: %s\n", ldap_err2string( rc ) ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + ldap_unbind_s( ld ); + return( 1 ); + } + num_entries = ldap_count_entries( ld, res ); + num_refs = ldap_count_references( ld, res ); + /* Iterate through the results. An LDAPMessage structure sent back from + a search operation can contain either an entry found by the search, + a search reference, or the final result of the search operation. */ + for ( msg = ldap_first_message( ld, res ); + msg != NULL; + msg = ldap_next_message( ld, msg ) ) { + /* Determine what type of message was sent from the server. */ + msgtype = ldap_msgtype( msg ); + switch( msgtype ) { + /* If the result was an entry found by the search, get and print the + attributes and values of the entry. */ + case LDAP_RES_SEARCH_ENTRY: + /* Get and print the DN of the entry. */ + if (( dn = ldap_get_dn( ld, res )) != NULL ) { + printf( "dn: %s\n", dn ); + ldap_memfree( dn ); + } + /* Iterate through each attribute in the entry. */ + for ( a = ldap_first_attribute( ld, res, &ber ); + a != NULL; a = ldap_next_attribute( ld, res, ber ) ) { + /* Get and print all values for each attribute. */ + if (( vals = ldap_get_values( ld, res, a )) != NULL ) { + for ( i = 0; vals[ i ] != NULL; i++ ) { + printf( "%s: %s\n", a, vals[ i ] ); + } + ldap_value_free( vals ); + } + ldap_memfree( a ); + } + if ( ber != NULL ) { + ber_free( ber, 0 ); + } + printf( "\n" ); + break; + case LDAP_RES_SEARCH_REFERENCE: + /* The server sent a search reference encountered during the + search operation. */ + /* Parse the result and print the search references. + Ideally, rather than print them out, you would follow the + references. */ + parse_rc = ldap_parse_reference( ld, msg, &referrals, NULL, 0 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, + "ldap_parse_result: %s\n", + ldap_err2string( parse_rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + if ( referrals != NULL ) { + for ( i = 0; referrals[ i ] != NULL; i++ ) { + printf( "Search reference: %s\n\n", referrals[ i ] ); + } + ldap_value_free( referrals ); + } + break; + case LDAP_RES_SEARCH_RESULT: + /* Parse the final result received from the server. Note the last + argument is a non-zero value, which indicates that the + LDAPMessage structure will be freed when done. (No need + to call ldap_msgfree().) */ + parse_rc = ldap_parse_result( ld, msg, &rc, + &matched_msg, &error_msg, NULL, &serverctrls, 0 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, + "ldap_parse_result: %s\n", + ldap_err2string( parse_rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + /* Check the results of the LDAP search operation. */ + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_search_ext: %s\n", ldap_err2string( rc ) ); + if ( error_msg != NULL & *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + } else { + printf( "Search completed successfully.\n" + "Entries found: %d\n" + "Search references returned: %d\n", + num_entries, num_refs ); + } + + break; + + default: + break; + } + } + /* Disconnect when done. */ + ldap_unbind( ld ); + return( 0 ); +} + + +Getting Results Asynchronously + +C SDK +search LDAP directory +asynchronous functions + +If you use the asynchronous function ldap_search_ext, +you first need to call ldap_result to determine if the +server sent back any results. +<function>ldap_result</function> Prototype +LDAP_API(int) LDAP_CALL ldap_result( LDAP *ld, int msgid, int all, + struct timeval *timeout, LDAPMessage **result ); + +You can specify how you want to get asynchronous results. +Retrieving Search Results Individually +To get the results individually as the client receives the results from +the server, pass LDAP_MSG_ONE as the all argument. + +#include <stdio.h> +#include "ldap.h" +... +#define BASEDN "dc=example,dc=com" +#define SCOPE LDAP_SCOPE_SUBTREE +#define FILTER "(sn=Jensen)" +... +LDAP *ld; +LDAPMessage *res; +int msgid, rc, parse_rc, finished = 0; +struct timeval zerotime; +zerotime.tv_sec = zerotime.tv_usec = 0L; +... +/* Send the LDAP search request. */ +rc = ldap_search_ext( ld, BASEDN, SCOPE, FILTER, NULL, 0, NULL, NULL, + NULL, LDAP_NO_LIMIT, &msgid ); +... +/* Poll the server for the results of the search operation. */ +while ( !finished ) { + rc = ldap_result( ld, msgid, LDAP_MSG_ONE, &zerotime, &res ); + switch ( rc ) { + case -1: + /* An error occurred. */ + ... + case 0: + /* The timeout period specified by zerotime was exceeded. */ + ... + case LDAP_RES_SEARCH_ENTRY: + /* The server sent one of the entries found by the search. */ + ... + case LDAP_RES_SEARCH_REFERENCE: + /* The server sent a search reference .*/ + ... + case LDAP_RES_SEARCH_RESULT: + /* Parse the final result received from the server. */ + ... + } +... +} +... + +To get the results all at once, in other words, to block processes +until all results are received, pass LDAP_MSG_ALL as the +all argument. +To get the results received thus far, pass LDAP_MSG_RECEIVED + as the all argument. + + +If you specify either LDAP_MSG_ALL or LDAP_MSG_RECEIVED +, the function passes back a chain of search results as the result + argument. If you specify LDAP_MSG_ONE, the function +passes back a single search result as the result argument. +The function normally returns the type of the first search result. When the +function returns the type, as only one result is returned, the function returns +the type of that result. +The following example prints the values of all attributes in the entries +returned by an asynchronous search. +Printing Results of an Asynchronous +Search +#include <stdio.h> +#include "ldap.h" +void do_other_work(); +int global_counter = 0; +/* Change these as needed. */ +#define HOSTNAME "localhost" +#define PORTNUMBER LDAP_PORT +#define BASEDN "dc=example,dc=com" +#define SCOPE LDAP_SCOPE_SUBTREE +#define FILTER "(sn=Jensen)" +int +main( int argc, char **argv ) +{ + LDAP *ld; + LDAPMessage *res; + BerElement *ber; + LDAPControl **serverctrls; + char *a, *dn, *matched_msg = NULL, *error_msg = NULL; + char **vals, **referrals; + int version, i, msgid, rc, parse_rc, finished = 0, + num_entries = 0, num_refs = 0; + struct timeval zerotime; + zerotime.tv_sec = zerotime.tv_usec = 0L; + /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } + version = LDAP_VERSION3; + if ( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) != + LDAP_SUCCESS ) { + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_set_option: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + /* Bind to the server anonymously. */ + rc = ldap_simple_bind_s( ld, NULL, NULL ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + /* If the server cannot find an entry, + print the portion of the DN that matches + an existing entry. */ + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + ldap_unbind_s( ld ); + return( 1 ); + } + /* Send the LDAP search request. */ + rc = ldap_search_ext( ld, BASEDN, SCOPE, FILTER, + NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &msgid ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_search_ext: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + /* Poll the server for the results of the search operation. + Passing LDAP_MSG_ONE indicates that you want to receive + the entries one at a time, as they come in. If the next + entry that you retrieve is NULL, there are no more entries. */ + while ( !finished ) { + rc = ldap_result( ld, msgid, LDAP_MSG_ONE, &zerotime, &res ); + /* The server can return three types of results back to the client, + and the return value of ldap_result() indicates the result type: + LDAP_RES_SEARCH_ENTRY identifies an entry found by the search, + LDAP_RES_SEARCH_REFERENCE identifies a search reference returned + by the server, and LDAP_RES_SEARCH_RESULT is the last result + sent from the server to the client after the operation completes. + You need to check for each of these types of results. */ + switch ( rc ) { + case -1: + /* An error occurred. */ + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + case 0: + /* The timeout period specified by zerotime was exceeded. + This means that the server has still not yet sent the + results of the search operation back to your client. + Break out of this switch statement, and continue calling + ldap_result() to poll for results. */ + break; + case LDAP_RES_SEARCH_ENTRY: + /* The server sent one of the entries found by the search + operation. Print the DN, attributes, and values of the entry. */ + /* Keep track of the number of entries found. */ + num_entries++; + /* Get and print the DN of the entry. */ + if (( dn = ldap_get_dn( ld, res )) != NULL ) { + printf( "dn: %s\n", dn ); + ldap_memfree( dn ); + } + /* Iterate through each attribute in the entry. */ + for ( a = ldap_first_attribute( ld, res, &ber ); + a != NULL; a = ldap_next_attribute( ld, res, ber ) ) { + /* Get and print all values for each attribute. */ + if (( vals = ldap_get_values( ld, res, a )) != NULL ) { + for ( i = 0; vals[ i ] != NULL; i++ ) { + printf( "%s: %s\n", a, vals[ i ] ); + } + ldap_value_free( vals ); + } + ldap_memfree( a ); + } + if ( ber != NULL ) { + ber_free( ber, 0 ); + } + printf( "\n" ); + ldap_msgfree( res ); + break; + case LDAP_RES_SEARCH_REFERENCE: + /* The server sent a search reference encountered during the + search operation. */ + /* Keep track of the number of search references returned from + the server. */ + num_refs++; + /* Parse the result and print the search references. + Ideally, rather than print them out, you would follow the + references. */ + parse_rc = ldap_parse_reference( ld, res, &referrals, NULL, 1 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, + "ldap_parse_result: %s\n", + ldap_err2string( parse_rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + if ( referrals != NULL ) { + for ( i = 0; referrals[ i ] != NULL; i++ ) { + printf( "Search reference: %s\n\n", referrals[ i ] ); + } + ldap_value_free( referrals ); + } + break; + case LDAP_RES_SEARCH_RESULT: + /* Parse the final result received from the server. Note the last + argument is a non-zero value, which indicates that the + LDAPMessage structure will be freed when done. (No need + to call ldap_msgfree().) */ + finished = 1; + parse_rc = ldap_parse_result( ld, res, &rc, &matched_msg, + &error_msg, NULL, &serverctrls, 1 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, + "ldap_parse_result: %s\n", + ldap_err2string( parse_rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + /* Check the results of the LDAP search operation. */ + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_search_ext: %s\n", ldap_err2string(rc) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL & *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + } else { + printf( "Search completed successfully.\n" + "Entries found: %d\n" + "Search references returned: %d\n" + "Counted to %d while waiting for the search operation.\n", + num_entries, num_refs, global_counter ); + } + + break; + + default: + break; + } + + /* Do other work here while waiting for the search operation + to complete. */ + if ( !finished ) { + do_other_work(); + } + } + /* Disconnect when done. */ + ldap_unbind( ld ); + return( 0 ); +} +/* + * Perform other work while polling for results. This doesn't do + * anything useful, but it could. + */ +static void +do_other_work() +{ + global_counter++; +} + + +Determining Search Result Types + +C SDK +search LDAP directory +result types + +To determine what type of result was returned, call the ldap_msgtype + function. + +A search result can be one of the following types: +LDAP_RES_SEARCH_ENTRY indicates that the +result is an entry that is found in the search. You can pass the LDAPMessage + structure that represents the entry to ldap_get_dn to +get the DN of the entry. You can pass the structure to ldap_first_attribute + and ldap_next_attribute to get the attributes +of the entry. For details, see Getting Distinguished +Names for Each Entry and Getting Attribute +Types From an Entry. +LDAP_RES_SEARCH_REFERENCE indicates that +the result is a search reference that is found within the scope of the search. +You can pass the LDAPMessage structure representing +the search reference to the ldap_parse_reference function +to get the referrals, LDAP URLs, to other servers. For details, see Getting Referrals From Search References.To +receive search references from an LDAP v3 server, you must identify your client +as LDAP v3 enabled. If not, the server returns the error code LDAP_PARTIAL_RESULTS + and a set of referrals. See Specifying +the LDAP Version of Your Client for details. +LDAP_RES_SEARCH_RESULT indicates that the +result is the final data sent by the server to indicate the end of the LDAP +search operation. You can pass the LDAPMessage structure +that represents the result to the ldap_parse_result function +to get the LDAP result code for the search operation. For a list of possible +result codes for an LDAP search operation, see the ldap_search_ext_s +3ldap man page. For details on parsing the result, see Getting Information From an LDAPMessage Structure. + + +Retrieving a Chain of Results +This example retrieves each result in a chain. The example then determines +its type. +#include <stdio.h> +#include "ldap.h" +... +#define BASEDN "dc=example,dc=com" +#define SCOPE LDAP_SCOPE_SUBTREE +#define FILTER "(sn=Jensen)" +... +LDAP *ld; +LDAPMessage *res, *msg; +BerElement *ber; +char *matched_msg = NULL, *error_msg = NULL; +int rc, msgtype, num_entries = 0, num_refs = 0; +... +/* Perform the search operation. */ +rc = ldap_search_ext_s( ld, BASEDN, SCOPE, FILTER, NULL, 0, NULL, NULL, + NULL, LDAP_NO_LIMIT, &res ); +if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_search_ext_s: %s\n", ldap_err2string( rc ) ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + /* If the server cannot find an entry and returns the portion of + the DN that can find an entry, print it out. */ + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + ldap_unbind_s( ld ); + return( 1 ); +} +... +num_entries = ldap_count_entries( ld, res ); +num_refs = ldap_count_references( ld, res ); +... +/* Iterate through the results. */ +for ( msg = ldap_first_message( ld, res ); msg != NULL; + msg = ldap_next_message( ld, msg ) ) { + + /* Determine what type of message was sent from the server. */ + msgtype = ldap_msgtype( msg ); + switch( msgtype ) { + case LDAP_RES_SEARCH_ENTRY: + /* The result is an entry. */ + ... + case LDAP_RES_SEARCH_REFERENCE: + /* The result is a search reference. */ + ... + case LDAP_RES_SEARCH_RESULT: + /* The result is the final result sent by the server. */ + ... + } +... +} +... + + +Getting Distinguished Names for Each Entry + +C SDK +search LDAP directory +retrieving DNs + +Because the DN of an entry differentiates the entry from other entries, +you might want to access the DN in search results. You might also want to +parse the name into its individual components. The SDK provides functions +for both of these tasks. +Getting the Distinguished Name of an Entry +To get the DN of an entry, call the ldap_get_dn function. +When finished with the DN, free the DN from memory by calling the ldap_memfree + function. +Obtaining the DN for Search Result +Entries +#include <stdio.h> +#include "ldap.h" +... +LDAP *ld; +LDAPMessage *result, *e; +char *dn; +char *my_searchbase = "dc=example,dc=com"; +char *my_filter = "(sn=Jensen)"; +... +/* Search the directory. */ +if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, + my_filter, NULL, 0, &result ) != + LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search_s" ); + return( 1 ); +} + +/* For each matching entry found, print the name of the entry.*/ +for ( e = ldap_first_entry( ld, result ); e != NULL; + e = ldap_next_entry( ld, e ) ) { + if ( ( dn = ldap_get_dn( ld, e ) ) != NULL ) { + printf( "dn: %s\n", dn ); + /* Free the memory used for the DN when done */ + ldap_memfree( dn ); + } +} +/* Free the result from memory when done. */ +ldap_msgfree( result ); + + +Getting the Components of a Distinguished Name +If you want to access individual components of a DN or relative DN, +call the ldap_explode_dn or ldap_explode_rdn function, +respectively. Both functions return a NULL terminated array +that contains the components of the DN. When you are done working with this +array, free the array by calling the ldap_value_free function. + +You can also specify whether or not you want the attribute names included +in the array, by using the notypes parameter. + +Set notypes to 0 if +you want to include attribute names, as in this function call: + +ldap_explode_dn( "uid=bjensen,ou=People,dc=example,dc=com", 0 ) +This function then returns this array: +{ "uid=bjensen", "ou=People", "dc=example,dc=com", NULL } + +Set notypes to 1 if +you do not want to include the attribute names in the array, as in this function +call: + +ldap_explode_dn( "uid=bjensen,ou=People,dc=example,dc=com", 1 ) +This function then returns this array: +{ "bjensen", "People", "example.com", NULL } + + +Getting Attribute Types From an Entry + +C SDK +search LDAP directory +retrieving attribute types + +To retrieve the type, also called the name, of the first attribute in +an entry, call the ldap_first_attribute function. To +get the type of the next attribute, call the ldap_next_attribute function. + +Operational attributes such as creatorsName and +modifyTimestamp are not normally returned in search results. You +must explicitly specify operational attibutes by type in the search request. +For more details, see Operational Attributes. + +When you are finished iterating through the attributes, you need to +free the BerElement structure allocated by the +ldap_first_attribute function, if the structure is not NULL. +To free this structure, call the ldap_ber_free function. +You should also free the attribute type returned by the ldap_first_attribute + function. To free the attribute type, call the ldap_memfree + function. The following example shows how to do this. +Retrieving Entry Attribute Types +#include <stdio.h> +#include "ldap.h" +... +LDAP *ld; +LDAPMessage *result, *e; +BerElement *ber; +char *a; +char *my_searchbase = "dc=example,dc=com"; +char *my_filter = "(sn=Jensen)"; +... +/* Search the directory. */ +if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, my_filter, + NULL, 0, &result ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search_s" ); + return( 1 ); +} + +/* Get the first matching entry.*/ +e = ldap_first_entry( ld, result ); + +/* Retrieve the attributes of the entry. */ + for (a = ldap_first_attribute(ld, e, &ber); a != NULL; + a = ldap_next_attribute(ld, e, ber)){ + ... + /* Code to get and manipulate attribute values */ + ... + } + ldap_memfree( a ); + } + /* Free the BerElement structure from memory when done. */ + if ( ber != NULL ) { + ldap_ber_free( ber, 0 ); + } +... + + +Getting the Values of an Attribute + +C SDK +search LDAP directory +retrieving attribute values + +The values of an attribute are represented by a NULL terminated +array. If the attribute contains string data, such as a name or phone number, +the values are a list of strings. If the attribute contains binary data, the +values are a list of berval structures, such as JPEG +files or audio files. Use the following guidelines to retrieve the values +of an attribute: + +To get the values of an attribute that contains string data, +call the ldap_get_values function. The ldap_get_values + function returns a NULL terminated array of +strings that represent the value of the attribute. +To get the values of an attribute that contains binary data, +call the ldap_get_values_len function. The ldap_get_values_len + function returns a NULL terminated array of +berval structures that represent the value of the attribute. + +To get the number of values in an attribute, call either the +ldap_count_values or ldap_count_values_len function. +Both functions return the number of values in the attribute. + +When you have finished working with the values of the attribute, you +need to free the values from memory. To free the values, call ldap_free_value + or ldap_free_value_len. The following example +gets, then prints the values of an attribute in an entry. The function assumes +that all attributes have string values. +Retrieving Attribute Values +#include <stdio.h> +#include "ldap.h" +... +LDAP *ld; +LDAPMessage *result, *e; +BerElement *ber; +char *a; +char **vals; +char *my_searchbase = "dc=example,dc=com"; +char *my_filter = "(sn=Jensen)"; +int i; +... +/* Search the directory. */ +if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, + my_filter, NULL, 0, &result ) != + LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search_s" ); + return( 1 ); +} + +/* Get the first matching entry.*/ +e = ldap_first_entry( ld, result ); + +/* Get the first matching attribute. */ +a = ldap_first_attribute( ld, e, &ber ); + +/* Get the values of the attribute. */ +if ( ( vals = ldap_get_values( ld, e, a ) ) != NULL ) { + for ( i = 0; vals[i] != NULL; i++ ) { + /* Print the name of the attribute and each value */ + printf( "%s: %s\n", a, vals[i] ); + } + /* Free the attribute values from memory when done. */ + ldap_value_free( vals ); +} +... + +The following example gets the first value of the jpegPhoto attribute +and saves the JPEG data to a file. +Getting and Saving an Attribute +Value +#include <stdio.h> +#include "ldap.h" +... +LDAP *ld; +LDAPMessage *result, *e; +BerElement *ber; +char *a; +struct berval photo_data; +struct berval **list_of_photos; +FILE *out; +char *my_searchbase = "dc=example,dc=com"; +char *my_filter = "(sn=Jensen)"; +... +/* Search the directory. */ +if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, + my_filter, NULL, 0, &result ) != + LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search_s" ); + return( 1 ); +} + +/* Get the first matching entry.*/ +e = ldap_first_entry( ld, result ); + +/* Find the jpegPhoto attribute. */ +a = ldap_first_attribute( ld, e, &ber ); +while ( strcasecmp( a, "jpegphoto" ) != 0 ) { + a = ldap_next_attribute( ld, e, ber ); +} + +/* Get the value of the attribute. */ +if ( ( list_of_photos = ldap_get_values_len( ld, e, a ) ) != + NULL ) { + /* Prepare to write the JPEG data to a file */ + if ( ( out = fopen( "photo.jpg", "wb" ) ) == NULL ) { + perror( "fopen" ); + return( 1 ); + } + /* Get the first JPEG. */ + photo_data = *list_of_photos[0]; + /* Write the JPEG data to a file */ + fwrite( photo_data.bv_val, photo_data.bv_len, 1, out ); + fclose( out ); + /* Free the attribute values from memory when done. */ + ldap_value_free_len( list_of_photos ); +} +... + + +Getting Referrals From Search References + +C SDK +search LDAP directory +retrieving referrals + +C SDK +search LDAP directory +retrieving search references + +A search reference returned from the server contains one or more +referrals, which are LDAP URLs that identify other LDAP servers. +To retrieve these referrals, you need to call the ldap_parse_reference function. +The following example gets and prints the referrals from a search reference. +Obtaining a Referral +#include <stdio.h> +#include "ldap.h" +... +LDAP *ld; +LDAPMessage *msg; +char **referrals; +int i, rc, parse_rc; +... +parse_rc = ldap_parse_reference( ld, msg, &referrals, NULL, 0 ); +if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_parse_result: %s\n", + ldap_err2string( parse_rc ) ); + ldap_unbind( ld ); + return( 1 ); +} +if ( referrals != NULL ) { + for ( i = 0; referrals[ i ] != NULL; i++ ) { + printf( "Search reference: %s\n\n", referrals[ i ] ); + } + ldap_value_free( referrals ); +} +... + + + +Sorting the Search Results With &DirectorySDKForC; + +C SDK +search LDAP directory +client-side sorting + +C SDK +search LDAP directory +server-side sorting + +&DirectorySDKForC; offers functions to sort entries and values in +the search results. You can either specify that the server return sorted results +or you can sort entries on your client. +Server-Side Sorting +To sort results on the server, you need to send a server-side sorting +control with the search request. For details, see Using +the Server-Side Sorting Control With Directory SDK for C for details. + +Client-Side Sorting +First, you need to retrieve the attributes that you plan to use for +sorting. For example, you might plan to sort the results by email address. +Make sure that the mail attribute is one of the attributes +returned in the search. +Sorting Entries by an Attribute +To sort the search results by a particular attribute, call the ldap_sort_entries + function. If you do no’t specify an attribute for sorting, +that is, if you pass NULL for the attr parameter, +the entries are sorted by DN. +Sorting Entries +by an Attribute +This example sorts entries by the roomNumber attribute. +#include <stdio.h> +#include <string.h> +#include "ldap.h" +... +LDAP *ld; +LDAPMessage *result; +char *my_searchbase = "dc=example,dc=com"; +char *my_filter = "(sn=Jensen)"; +char *sortby = "roomNumber"; +... +/* Search the directory. */ +if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, + my_filter, NULL, 0, &result ) != + LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search_s" ); + return( 1 ); +} + +/* Sort the results by room number, using strcasecmp. */ +if ( ldap_sort_entries(ld, &result, sortby, strcasecmp) != + LDAP_SUCCESS ){ + ldap_perror( ld, "ldap_sort_entries" ); + return( 1 ); +} +... + + +Sorting Entries by Multiple Attributes +To sort the search results by multiple attributes, call the ldap_multisort_entries + function. If you do not specify a set of attributes for sorting, +the entries are sorted by DN. To sort entries by DN, pass NULL for +the attr parameter. +Sorting +Entries by Multiple Attributes +This example sorts entries first by the roomNumber attribute, +then by the telephoneNumber attribute. +#include <stdio.h> +#include <string.h> +#include "ldap.h" +LDAP *ld; +LDAPMessage *res; +char *my_searchbase = "dc=example,dc=com"; +char *my_filter = "(sn=Jensen)"; +char *attrs[2]; +attrs[0] = "roomNumber"; +attrs[1] = "telephoneNumber"; +attrs[2] = NULL; +... +/* Search the directory. */ +if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_SUBTREE, + my_filter, NULL, 0, &res ) != + LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search_s" ); + return( 1 ); +} + +/* Sort the results, using strcasecmp. */ +if ( ldap_multisort_entries(ld,&res,attrs, strcasecmp) != + LDAP_SUCCESS ){ + ldap_perror( ld, "ldap_sort_entries" ); + return( 1 ); +} + + +Sorting the Values of an Attribute +You can also sort the values of a particular attribute. To sort the +values, call the ldap_sort_strcasecmp function. In this +function, the comparison function must pass parameters of the type char +**. You should use the ldap_sort_strcasecmp function, +rather than a function like strcasecmp, which passes +parameters of the type char *. The following example sorts +the values of attributes before printing the values. +Sorting Attribute +Values +#include <stdio.h> +#include <string.h> +#include "ldap.h" +LDAP *ld; +LDAPMessage *result, *e; +BerElement *ber; +char *a, *dn; +char **vals; +int i; +char *my_searchbase = "dc=example,dc=com"; +char *my_filter = "(sn=Jensen)"; +... + if ( ( vals = ldap_get_values( ld, e, a ) ) != NULL ) { + /* Sort the values of the attribute */ + if ( ldap_sort_values(ld, vals, strcasecmp)) != + LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_sort_values" ); + return( 1 ); + } + /* Print the values of the attribute. */ + for ( i = 0; vals[i] != NULL; i++ ) { + printf( "%s: %s\n", a, vals[i] ); + } + /* Free the values from memory. */ + ldap_value_free( vals ); + } +... + + + + +Freeing the Search Results With &DirectorySDKForC; + +C SDK +search LDAP directory +freeing results + +The results of the search are returned in an LDAPMessage structure. +After you are done working with the search results, you should free this structure +from memory. To free the search results, call the ldap_msgfree function, +which returns the type of the last message freed from memory. +Examples of Search Operations With &DirectorySDKForC; + + +C SDK +search LDAP directory +examples + +This section contains sample code for various search operations. +Reading an Entry With a Search +You can use the search functions to read a specific entry in the directory. +To read an entry, set the starting point of the search to the entry. Also, +set the scope of the search to LDAP_SCOPE_BASE, specifying +(objectclass=*) as the search filter, as shown in the following +example. +Reading a Specific Entry With +a Search +#include <stdio.h> +#include "ldap.h" +/* Change these as needed. */ +#define HOSTNAME "localhost" +#define PORT_NUMBER LDAP_PORT +#define FIND_DN "uid=bjensen,ou=People,dc=example,dc=com" +int +main( int argc, char **argv ) +{ + LDAP *ld; + LDAPMessage *result, *e; + BerElement *ber; + char *a; + char **vals; + int i, rc; + /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( HOSTNAME, PORT_NUMBER )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } + /* Bind anonymously to the LDAP server. */ + if ( ( rc = ldap_simple_bind_s( ld, NULL, NULL ) ) != + LDAP_SUCCESS ) { + fprintf( stderr, + "ldap_simple_bind_s: %s\n", + ldap_err2string( rc ) ); + return( 1 ); + } + /* Search for the entry. */ + if ( ( rc = ldap_search_ext_s( ld, FIND_DN, LDAP_SCOPE_BASE, + "(objectclass=*)", NULL, 0, NULL, + NULL, LDAP_NO_LIMIT, + LDAP_NO_LIMIT, &result ) ) != + LDAP_SUCCESS ) { + fprintf( stderr, "ldap_search_ext_s: %s\n", ldap_err2string( rc ) ); + return( 1 ); + } + /* Since this is a base search, there should be only one + matching entry. */ + e = ldap_first_entry( ld, result ); + if ( e != NULL ) { + printf( "\nFound %s:\n\n", FIND_DN ); + /* Iterate through each attribute in the entry. */ + for ( a = ldap_first_attribute( ld, e, &ber ); + a != NULL; a = ldap_next_attribute( ld, e, ber ) ) { + /* For each attribute, print the attribute name and values. */ + if ((vals = ldap_get_values( ld, e, a)) != NULL ) { + for ( i = 0; vals[i] != NULL; i++ ) { + printf( "%s: %s\n", a, vals[i] ); + } + ldap_value_free( vals ); + } + ldap_memfree( a ); + } + if ( ber != NULL ) { + ber_free( ber, 0 ); + } + } + ldap_msgfree( result ); + ldap_unbind( ld ); + return( 0 ); +} + + +Listing Subentries With a Search +You can use the search functions to list the subentries under a specific +entry in the directory. To list the subentries, set the starting point of +the search to the entry. Also, set the scope of the search to LDAP_SCOPE_ONELEVEL +. The following lists all entries one level under the dc=example,dc=com + entry in the directory hierarchy. +Listing Subentries +#include <stdio.h> +#include "ldap.h" + +LDAP *ld; +LDAPMessage *result, *e; +BerElement *ber; +char *a, *dn; +char **vals; +char *my_searchbase = "dc=example,dc=com"; +char *my_filter = "(objectclass=*)" + +/* Search one level under the starting point. */ +if ( ldap_search_s( ld, my_searchbase, LDAP_SCOPE_ONELEVEL, my_filter, + NULL, 0, &result ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_search_s" ); + return( 1 ); +} +/* For each matching entry, print the entry name and its attributes. */ +for ( e = ldap_first_entry( ld, result ); e != NULL; + e = ldap_next_entry( ld, e ) ) { + if ( ( dn = ldap_get_dn( ld, e ) ) != NULL ) { + printf( "dn: %s\n", dn ); + ldap_memfree( dn ); + } + for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL; + a = ldap_next_attribute( ld, e, ber ) ) { + if ( ( vals = ldap_get_values( ld, e, a ) ) != NULL ) { + for ( i = 0; vals[i] != NULL; i++ ) { + printf( "%s: %s\n", a, vals[i] ); + } + ldap_value_free( vals ); + } + ldap_memfree( a ); + } + if ( ber != NULL ) { + ldap_ber_free( ber, 0 ); + } + printf( "\n" ); +} +ldap_msgfree( result ); +... + + +Sending Search Request Using &DirectorySDKForC; +The following sample code shows how to search for all entries with the +last name (surname) Jensen in the example.com organization. + +Sending a Search Request +#include <stdio.h> +#include "ldap.h" +... +#define BASEDN "dc=example,dc=com" +#define SCOPE LDAP_SCOPE_SUBTREE +#define FILTER "(sn=Jensen)" +... +LDAP *ld; +int msgid, rc; +... +/* Send the search request. */ +rc = ldap_search_ext( ld, BASEDN, SCOPE, FILTER, NULL, 0, NULL, + NULL, NULL, LDAP_NO_LIMIT, &msgid ); +if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_search_ext: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); +} +... + + + +
diff --git a/mozilla/directory/docs/ldapcsdk/csdk-server-info.sgm b/mozilla/directory/docs/ldapcsdk/csdk-server-info.sgm new file mode 100644 index 00000000000..1d0e23bd92c --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/csdk-server-info.sgm @@ -0,0 +1,374 @@ + +Getting Server Information With &DirectorySDKForC; + + +C SDK +getting server information + +This chapter explains how to access and modify information about your +LDAP server over the LDAP protocol. + +This chapter covers the following topics: +Reading DSEs With Directory SDK for +C +Determining LDAP v3 Support With +Directory SDK for C +Getting Schema Information With Directory +SDK for C + + +Reading DSEs With &DirectorySDKForC; + +C SDK +getting server information +DSE + +A DSA-specific entry, DSE, contains information +specific to the server. In a directory tree, the root of the tree is the root +DSE. The root DSE is not part of any naming context. For example, the root +DSE is superior to dc=example,dc=com in the directory tree. +The root DSE is specified as part of LDAP v3. Note that LDAP v2 servers +do not necessarily have a root DSE. + +The root DSE can contain the following information: +The naming contexts of this server such as, dc=example,dc=com + +URLs of alternate servers to contact if this server is unavailable + +The versions of LDAP supported by this server, version 2 or +version 3 +The LDAP v3 controls supported by the serverSee Chapter 16, LDAP Controls With Directory SDK +for C for details. +The SASL mechanisms supported by the serverSee Chapter 17, SASL Authentication With Directory +SDK for C for details. +The LDAP v3 extended operations supported by the server +See Chapter 18, Extended Operations +With Directory SDK for C for details. + +The following lists root DSE attributes and explains the meaning of +their values. +Root DSE +Attributes and Descriptions of Their Values + + + + +Attribute Name + +Description of Values + + + + + +namingContexts + +The naming contexts supported by this server, such dc=example,dc=com +. + + + +altServer + +LDAP URLs that identify other servers to contact if this server is unavailable. + + + + +supportedExtension + +The object identifiers (OIDs) of the LDAP v3 extended operations supported +by this server. +If this attribute is not in the root DSE, the server does not support +any extended operations. + + + +supportedControl + +The OIDs of the LDAP v3 controls supported by this server. +If this attribute is not in the root DSE, the server does not support +any LDAP v3 controls. + + + +supportedSASLMechanisms + +The names of the SASL mechanisms supported by the server. +If this attribute is not in the root DSE, the server does not support +any SASL mechanisms. + + + +supportedLDAPVersion + +The value of this attribute is the version of LDAP supported by this +server, such as 2 or 3. + + + +
+To Get the Root DSE + +Initialize an LDAP session by calling the ldap_init or +prldap_init function. +Turn off automatic referral handling by calling the ldap_set_option + function and setting the LDAP_OPT_REFERRALS option +to LDAP_OPT_OFF. +Search the directory with the following criteria: + +Set the search scope to a base search. + +Specify an empty string for the base DN. +Use the search filter (objectclass=*). + + +Check the results of the search.If the server returns +a result code, such as LDAP_OPERATIONS_ERROR, LDAP_PROTOCOL_ERROR +, LDAP_REFERRAL, or LDAP_NO_SUCH_OBJECT +, the LDAP server probably does not support LDAP v3.The +following example gets the root DSE for a server and prints the values of +the root DSE attributes. The function assumes that you are passing in a valid +connection handle, an LDAP structure, you have created +by calling ldap_init or prldap_init. +The function returns 0 if successful or 1 if +an error occurred. + + +Getting the Root DSE and Printing its Attribute Values +int printdse( LDAP *ld ) +{ + int rc, i; + char *matched_msg = NULL, *error_msg = NULL; + LDAPMessage *result, *e; + BerElement *ber; + char *a; + char **vals; + char *attrs[3]; + /* Verify that the connection handle is valid. */ + if ( ld == NULL ) { + fprintf( stderr, "Invalid connection handle.\n" ); + return( 1 ); + } + /* Set automatic referral processing off. */ + if ( ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF ) != 0 ) { + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_set_option: %s\n", ldap_err2string( rc ) ); + return( 1 ); + } + /* Search for the root DSE. */ + attrs[0] = "supportedControl"; + attrs[1] = "supportedExtension"; + attrs[2] = NULL; + rc = ldap_search_ext_s( ld, "", LDAP_SCOPE_BASE, "(objectclass=*)", + attrs, 0, NULL, NULL, NULL, 0, &result ); + /* Check the search results. */ + switch( rc ) { + /* If successful, the root DSE was found. */ + case LDAP_SUCCESS: + break; + /* If the root DSE was not found, the server does not comply + with the LDAPv3 protocol. */ + case LDAP_PARTIAL_RESULTS: + case LDAP_NO_SUCH_OBJECT: + case LDAP_OPERATIONS_ERROR: + case LDAP_PROTOCOL_ERROR: + printf( "LDAP server returned result code %d (%s).\n" + "This server does not support the LDAPv3 protocol.\n", + rc, ldap_err2string( rc ) ); + return( 1 ); + /* If any other value is returned, an error must have occurred. */ + default: + fprintf( stderr, "ldap_search_ext_s: %s\n", ldap_err2string( rc ) ); + return( 1 ); + } + /* Since only one entry should have matched, get that entry. */ + e = ldap_first_entry( ld, result ); + if ( e == NULL ) { + fprintf( stderr, "ldap_search_ext_s: Unable to get root DSE.\n"); + ldap_memfree( result ); + return( 1 ); + } + + /* Iterate through each attribute in the entry. */ + for ( a = ldap_first_attribute( ld, e, &ber ); + a != NULL; a = ldap_next_attribute( ld, e, ber ) ) { + + /* Print each value of the attribute. */ + if ((vals = ldap_get_values( ld, e, a)) != NULL ) { + for ( i = 0; vals[i] != NULL; i++ ) { + printf( "%s: %s\n", a, vals[i] ); + } + + /* Free memory allocated by ldap_get_values(). */ + ldap_value_free( vals ); + } + + /* Free memory allocated by ldap_first_attribute(). */ + ldap_memfree( a ); + } + + /* Free memory allocated by ldap_first_attribute(). */ + if ( ber != NULL ) { + ber_free( ber, 0 ); + } + + printf( "\n" ); + /* Free memory allocated by ldap_search_ext_s(). */ + ldap_msgfree( result ); + ldap_unbind( ld ); + return( 0 ); +} + + +
+Determining LDAP v3 Support With &DirectorySDKForC; + +C SDK +getting server information +LDAP v3 support + +You can determine what version an LDAP server supports by getting the +supportedLDAPVersion attribute from the root DSE. This attribute +could contain the value 2 or 3. +You do not need to authenticate or bind before searching the directory. +Unlike LDAP v2, LDAP v3 states that clients do not need to bind to the server +before performing LDAP operations. +The following example connects to an LDAP server. The example code then +determines whether the server supports LDAP v3. +Determining the Supported +LDAP Version +/* Function for determining if the LDAP server supports LDAPv3. + This function returns 1 if the server supports LDAPv3 or + 0 if the server does not support LDAPv3. + */ +int +check_version( char *hostname, int portnum ) +{ + LDAP *ld; + int i, rc, v3supported = 0; + LDAPMessage *result, *e; + BerElement *ber; + LDAPControl **serverctrls = NULL, **clntctrls = NULL; + char *a, *dn; + char **vals; + char *attrs[2]; + char *filter = "(objectClass=*)"; + /* Check arguments */ + if ( !hostname || !hostname[0] || !portnum ) { + printf( "Error: hostname or port number not specified\n" ); + return( -1 ); + } + /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( hostname, portnum )) == NULL ) { + perror( "ldap_init" ); + return( -1 ); + } + /* Set automatic referral processing off. */ + if ( ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF) != + LDAP_SUCCESS) { + ldap_perror( ld, "ldap_set_option" ); + return( -1 ); + } + /* Search for the root DSE and get the supportedLDAPVersion attribute. */ + attrs[0] = "supportedLDAPVersion"; + attrs[1] = NULL; + rc = ldap_search_ext_s( ld, "", LDAP_SCOPE_BASE, filter, attrs, 0, + serverctrls, clntctrls, NULL, 0, &result ); + /* Check the search results. */ + switch( rc ) { + /* If successful, the root DSE was found. */ + case LDAP_SUCCESS: + break; + /* If the root DSE was not found, the server does not comply + with the LDAPv3 protocol. */ + case LDAP_PARTIAL_RESULTS: + case LDAP_NO_SUCH_OBJECT: + case LDAP_OPERATIONS_ERROR: + case LDAP_PROTOCOL_ERROR: + ldap_perror( ld, "ldap_search_ext_s" ); + return( 0 ); + break; + /* If an different result code is returned, an error may have + occurred (for example, the server may be down. */ + default: + ldap_perror( ld, "ldap_search_ext_s" ); + return( -1 ); + break; + } + /* Get the values of the supportedLDAPVersion attribute in the entry. */ + if (( e = ldap_first_entry( ld, result )) != NULL && + ( a = ldap_first_attribute( ld, e, &ber )) != NULL && + (vals = ldap_get_values( ld, e, a)) != NULL ) { + for ( i = 0; vals[i] != NULL; i++ ) { + if ( !strcmp( "3", vals[i] ) ) { + v3supported = 1; + break; + } + } + /* Free any memory allocated. */ + ldap_value_free( vals ); + ldap_memfree( a ); + if ( ber != NULL ) { + ber_free( ber, 0 ); + } + } + /* Free memory allocated by ldap_search_ext_s(). */ + ldap_msgfree( result ); + /* Free the ld structure. */ + ldap_unbind_s( ld ); + /* Return a value indicating whether or not LDAPv3 is supported. */ + return( v3supported ); +} +... + + +Getting Schema Information With &DirectorySDKForC; + +C SDK +getting server information +schema + +In LDAP v3, an entry can specify the schema that defines the object +classes, attributes, and matching rules used by the directory. This entry +is called the subschema entry. To find the DN of the +subschema entry, get the subschemaSubentry operational +attribute from the root DSE or any entry. + +The subschema entry can have the following attributes: +objectClasses specifies the object class +definitions in the schema. Each value of this attribute is an object class +that is known to the server. +attributeTypes specifies the attribute +type definitions in the schema. Each value of this attribute is an attribute +type that is known to the server. +matchingRules specifies the matching rule +definitions in the schema. Each value of this attribute is a matching rule +that is known to the server. +matchingRuleUse specifies the use of a +matching rule in the schema. This rule specifies the attributes that can be +used with this extensible matching rule. Each value of this attribute is a +matching rule use description. + +For information about the format of the attribute values, see RFC +4517, Lightweight Directory Access Protocol (v3): Attribute +Syntax Definitions. +
diff --git a/mozilla/directory/docs/ldapcsdk/csdk-ssl.sgm b/mozilla/directory/docs/ldapcsdk/csdk-ssl.sgm new file mode 100644 index 00000000000..a9cb35954f7 --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/csdk-ssl.sgm @@ -0,0 +1,382 @@ + +SSL Connections With &DirectorySDKForC; + +C SDK +Secure Sockets Layer (SSL) + +This chapter describes the process of enabling an LDAP client to connect +to an LDAP server over the Secure Sockets Layer (SSL) protocol. + +This chapter covers the following topics: +How SSL Works With Directory SDK +for C +Connecting to a Server Over SSL With +Directory SDK for C +Handling Errors With Directory SDK +for C +Starting Transport Layer +Security With Directory SDK for C +Installing Your Own SSL I/O Functions +With Directory SDK for C +Using Certificate-Based Client Authentication +With Directory SDK for C + + +How SSL Works With &DirectorySDKForC; +The primary goal of the SSL protocol is to provide privacy and reliability +between two communicating applications. +SSL is not supported on all LDAP servers.SSL communication +must take place on a separate TCP port unless the server supports Start TLS. + +When an LDAP client connects to an LDAP server over SSL, the server +identifies itself by sending a certificate to the client. The client needs +to determine whether or not the certificate authority (CA) that issued the +certificate is trusted. The client therefore searches a certificate database +for the certificate of the CA. If the client cannot find the certificate, +the client refuses to connect to the server. If the certificate is marked +not trusted, the client also refuses to connect to the server. +The LDAP server can also request that the client send a certificate +to authenticate itself. This part of the process is called certificate-based +client authentication. If the client receives a request for a +certificate from the server, the client retrieves its certificate from the +certificate database. The client sends the certificate to the server for authentication. +After receiving the client’s certificate, the LDAP server determines +whether or not the CA that issued the certificate is trusted. If the server +cannot find the CA certificate in the certificate database, the server refuses +to authenticate the client. If the CA certificate is marked as not +trusted, the server also refuses to authenticate the client. If +the CA is trusted, the server uses the certificate subject name to determine +whether the client has access to perform the requested operation. + +&DirectorySDKForC; includes functions that allow you to connect an +LDAP client to an LDAP server over SSL. The functions make the following assumptions: + +Your client has access to a certificate database. The function +call uses this certificate database to determine if the client can trust the +certificate sent from the server.Different certificate database +versions can be incompatible, which might result in database errors. + + + +The database used contains any one of the following: +The certificate of the CA that issued the server’s certificate + +If the CAs are organized in a hierarchy, the certificate of +any of the CAs in the hierarchy +The certificate of the LDAP server + + +The CA certificate is marked as trusted in +the certificate database. + + +If you plan to use certificate-based client authentication, you also +need the following: +A client certificate in the certificate database issued by +a CA that is trusted by the LDAP server +A public-private key pair in a key file + + + + +The functions allow you to do the following: +Set the session option for communicating with the server over +SSL.See Connecting to a Server Over +SSL With Directory SDK for C for details. +Start transport layer security by using the Start TLS extended +operationSee Starting Transport +Layer Security With Directory SDK for C for details. +Replace the default I/O functions with your own I/O functions +for communicating over SSLSee Installing +Your Own SSL I/O Functions With Directory SDK for C for details. + +Enable your client to send certificates to authenticate itself +See Using Certificate-Based Client Authentication +With Directory SDK for C for details. + + +Connecting to a Server Over SSL With &DirectorySDKForC; + +C SDK +Secure Sockets Layer (SSL) +connecting to the server + +To enable your LDAP client to connect to an LDAP server with SSL, you +need to perform the following procedure. +To Initialize a Client SSL Connection by Using <function>ldapssl_init +</function> + +Initialize your client by calling one of the following functions: + +Call ldapssl_client_init if you do not plan +to use certificate-based client authentication. +Call ldapssl_clientauth_init if you plan +to use certificate-based client authentication. +Call ldapssl_advclientauth_init.If +you use certificate-based client authentication, you need to specify the path +of the security module database, or to specify the method to verify the server +certificate. +You must initialize your client before initializing the LDAP session. +The process of initializing the client opens the certificate database. + +Initialize an LDAP session with the secure server by calling the +ldapssl_init function.For an alternative way to accomplish +this step, see Alternative to ldapssl_init. + + + +To Initialize a Client SSL Connection by using <function>ldapssl_init</function> +This example initializes a client to connect to a secure LDAP server +over SSL. +if ( ldapssl_client_init( "/local/examples/alias/", NULL ) < 0) { + printf( "Failed to initialize SSL client...\n" ); + return( 1 ); +} +/* get a handle to an LDAP connection */ +if ( (ld = ldapssl_init( "cert.example.com", LDAPS_PORT, 1 )) == NULL { + perror( "ldapssl_init" ); + return( 1 ); +} +... +/* Client can now perform LDAP operations on the secure LDAP server. */ +... + + +Alternative to <function>ldapssl_init</function> +As an alternative to calling the ldapssl_init function, +you can use the following procedure. +To Initialize a Client SSL Connection (Alternative Method Using <function> +ldap_init</function> + +After initializing your client, initialize an LDAP session with +the server by calling the standard initialization function ldap_init. + +Install the standard SSL I/O functions by calling ldapssl_install_routines +. +Set the SSL option in the LDAP structure by calling ldap_set_option +. + + +Initializing a Client SSL Initialization (Alternative Method Using <function> +ldap_init</function>) +This example prepares a client to connect to a secure LDAP server over +SSL using ldap_init. +if ( ldapssl_client_init( "/local/examples/alias/", NULL ) < 0) { + printf( "Failed to initialize SSL client...\n" ); + return( 1 ); +} +/* Initialize LDAP session. Use prldap_init() for IPv6. */ +if ( (ld = ldap_init( MY_HOST, LDAPS_PORT )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); +} + +/* Load SSL routines */ +if ( ldapssl_install_routines( ld ) != 0 ) { + ldap_perror( ld, "ldapssl_install_routines" ); + return( 1 ); +} +/* Set up option in LDAP struct for using SSL */ +if ( ldap_set_option( ld, LDAP_OPT_SSL, LDAP_OPT_ON ) != 0 ) { + ldap_perror( ld, "ldap_set_option" ); + return( 1 ); +} +/* Client can now perform LDAP operations on the secure LDAP server. */ +... + + + + +Handling Errors With &DirectorySDKForC; + +C SDK +Secure Sockets Layer (SSL) +handling errors + +After calling any of the SSL initialization functions, you can convert +SSL-specific error codes to text strings by calling ldapssl_err2string. +The ldapssl_err2string function provides support for +special SSL error messages that are not handled by the normal error conversion +routine ldap_err2string. +Starting Transport Layer Security With &DirectorySDKForC; + +C SDK +Secure Sockets Layer (SSL) +start TLS + +RFC +4513, Lightweight Directory Access Protocol (LDAP): Authentication +Methods and Security Mechanisms, describes the extended operation. +Start TLS allows you to connect to a nonsecure port, and then request transport +layer security. +To Use Start TLS + +Initialize your client with ldapssl_client_init. +The process of initializing the client opens the certificate +database. +Get a handle to an LDAP connection. +Request Start TLS with ldap_start_tls_s. + +Authenticate to the directory to perform additional operations. + + + +Using Start TLS +This example connects and uses Start TLS, then requests the Who am I? +extended operation. The example relies on a certificate database directory, /local/examples/alias/. +/* + * Use the Start TLS extended operation. + */ + +#include "examples.h" +#include <ldap_ssl.h> + +/* + * Path to certificate database for SSL + */ +#define CERT_DB_PATH "/local/examples/alias/" + +int +main( int argc, char **argv ) +{ + int version; + LDAP *ld; + int rc; + char *authzid; + + /* Initialize access to the certificate database. */ + if ( ldapssl_client_init( CERT_DB_PATH, NULL ) != 0 ) { + fprintf( stderr, "ldapssl_client_init failed\n" ); + fprintf( stderr, "certificate database path: %s\n", CERT_DB_PATH ); + return( 1 ); + } + + /* Use LDAPv3. */ + version = LDAP_VERSION3; + if ( ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, &version ) + != 0 ) { + fprintf( stderr, + "ldap_set_option protocol version to %d failed\n", + version ); + return( 1 ); + } + + /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( MY_HOST, MY_PORT )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } + + /* Request Start TLS. */ + if ( ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_start_tls_s" ); + return( 1 ); + } + printf( "Start TLS operation successful.\n" ); + + /* Authenticate to the directory. */ + if ( ldap_simple_bind_s( ld, ENTRYDN, ENTRYPW ) != LDAP_SUCCESS ) { + ldap_perror( ld, "ldap_simple_bind_s" ); + return( 1 ); + } + + /* Examine my authorization ID. */ + if ( (rc = ldap_whoami_s( ld, NULL, NULL, &authzid ) ) + != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_whoami_s: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + printf( "Authorization ID: %s\n", authzid ); + + ldap_unbind( ld ); + return( 0 ); +} +See Performing a Who Am I? Extended +Operation With Directory SDK for C for details on using the “Who +am I?” extended operation. + +To troubleshoot Start TLS problems, call the PR_GetError function. +This function gives you access to many Network Security Services (NSS) errors +further documented in the Mozilla.org SSL Reference. + + +Installing Your Own SSL I/O Functions With &DirectorySDKForC; + +C SDK +Secure Sockets Layer (SSL) +custom I/O functions + +The ldapssl_init and ldapssl_install_routines + functions both set up the session to use the standard SSL I/O +functions provided with &DirectorySDKForC;. If you want to use your own +SSL I/O functions, use the ldap_x_ext_io_fns structure. +To Install Your Own SSL I/O Functions + +Create an ldap_x_ext_io_fns structure, +and set the fields to point to your I/O functions. +Call ldap_set_option to point to that structure. + +if (ldap_set_option( ld, LDAP_X_OPT_EXTIO_FN_PTRS, &my_io_struct) != 0 ) { + ldap_perror( ld, "ldap_set_option" ); + return( 1 ); +} + + + + +Using Certificate-Based Client Authentication With &DirectorySDKForC; + +C SDK +Secure Sockets Layer (SSL) +certificate-based authentication + +Some LDAP servers can be configured to use certificate-based client +authentication. The server requests that your client send a certificate to +identify itself. Use the following procedure to configure your client to use +certificates for authentication. +To Use Certificate-Based Client Authentication + +Initialize your LDAP client by calling either ldapssl_clientauth_init + or ldapssl_advclientauth_init, not ldapssl_client_init +.Use ldapssl_advclientauth_init if +you want to specify the path of a security module database, or to specify +the method used to verify the server certificate.You can use +one of these functions to initialize your client even if you do not plan to +use certificate-based client authentication. The functions are equivalent +to ldapssl_client_init. +Initialize an LDAP session with the secure server by calling +ldapssl_init. +Enable your client to authenticate with the secure server by calling +ldapssl_enable_clientauth. +Perform a Simple Authentication and Security Layer (SASL) bind +operation by using the mechanism EXTERNAL. This mechanism +indicates to the directory server that certificates should be used to authenticate +clients.With &cnDirectoryServer;, if you perform a SASL bind +operation, but the server cannot find the corresponding directory entry for +a client certificate, the server returns an LDAP_INVALID_CREDENTIALS result +code with the error message Client Certificate Mapping Failed. + + + + + diff --git a/mozilla/directory/docs/ldapcsdk/csdk-understanding.sgm b/mozilla/directory/docs/ldapcsdk/csdk-understanding.sgm new file mode 100644 index 00000000000..cbc56096b51 --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/csdk-understanding.sgm @@ -0,0 +1,970 @@ + +About &DirectorySDKForC; + + +This chapter introduces &DirectorySDKForC; and covers the following +topics: +Overview of Directory SDK for C + +Files Provided With Directory SDK +for C +Compiling Applications with Directory +SDK for C +Sample Programs for Directory SDK +for C + + +Overview of &DirectorySDKForC; + +C SDK +overview of + +&DirectorySDKForC; includes the C libraries for the LDAP API as well +as sample code that demonstrates how to call many functions. The APIs are +defined by the header files that declare all of the functions, data types, +and code values in the SDK. You use the functions in this API to write C or +C++ client applications that take full advantage of server capabilities. +The APIs are built around core functions of the LDAP v2 and v3 standards. +Therefore, the APIs can be used to interact with any conforming LDAP server. +This API conforms to the standard that is proposed in The C LDAP +Application Programming Interface. +LDAP API + +LDAP Application Programming Interface (API) +LDAP API +LDAP API + +APIs +LDAP + +RFC +4511, Lightweight Directory Access Protocol (v3), +defines a set of operations to access data in an LDAP v3 compliant directory +server. The functionality implemented in &DirectorySDKForC; closely follows +these operations because a C API is defined for each operation. + +With the C API, you can enable client applications to connect to LDAP +v3 compliant directory servers. Client applications can then perform both +standard and extended LDAP operations such as the following: +Search for and retrieve a list of entries. +Add new entries to the database. +Update existing directory entries. +Delete entries. +Rename entries.For example, if you are writing +an email application, you can use the functions in the API to retrieve email +addresses from an LDAP server. + + +Synchronous and Asynchronous Operations + +C SDK +synchronous functions + +C SDK +asynchronous functions + +operations +asynchronous + +operations +synchronous + +The API functions allow you to perform LDAP operations synchronously +or asynchronously. The only differences between these two options are in the +calling convention. The LDAP exchanges are identical. + +Call a synchronous function to wait for the operation to complete +before receiving the return value of a function. +Call an asynchronous function to perform other work while +waiting for an operation to complete. Your application must then poll for +results.For more information, see Synchronous +Examples, and Asynchronous Examples. + + + +Files Provided With Directory SDK for C + +C SDK +files installed + +&DirectorySDKForC; includes a number of sample files, headers, libraries, +and tools. This section helps you to locate the files. All locations are relative +to the directory where the software is installed, which depends on your operating +system. +&DirectorySDKForC; Content + + + + +Directory Location + +Description + + + + + +etc/ + +Contains miscellaneous files for you to use. The files are described +in Miscellaneous Files + + + +examples/ + +Contains sample source code and Makefiles for LDAP clients. See the +README file in this directory for more information. + + + +include/ + +Contains the header files. You must include the files in this directory +in your client source files. The header files are described in Directory SDK for C Header Files + + + +include-nspr/ + +Contains Netscape Portable Runtime (NSPR) header files. NSPR provides +a platform-neutral API for system—level and libc—style +functions. + + + +include-private/ + +Contains private header files that are not documented in this guide. + + + + +lib/ + +Contains the C library files. The specific library used is dependent +on the type of application you are building. For details see Directory SDK for C Libraries. + + + +lib-private/ + +Contains private libraries that are not documented in this guide. + + + + +tools/ + +Contains the LDAP command-line tools. To use these applications, you +must ensure that the tools can find the LDAP API shared library or dynamic +link library. + + + +
+&DirectorySDKForC; Header Files + +C SDK +header files + +header files +C SDK + +The following table describes &DirectorySDKForC; header files that +are in the include/ directory. +All locations are relative to the directory where the software +is installed, which depends on your operating system. +&DirectorySDKForC; Header +Files + + + + +Header File + +Description + + + + + +disptmpl.h + +A header file related to the templates (ldaptemplates.conf). + + + + +lber.h + +Contains prototypes for the standard Basic Encoding Rules (BER) functions, +structures, and defines. For details see lber.h Header +File + + + +ldap-deprecated.h + +Contains deprecated functions that should not be used. This header is +included in ldap.h. + + + +ldap-extension.h + +Contains functions, structures, and defines that extend the standard +LDAP C API specification. This header is included in ldap.h. + + + + +ldap-platform.h + +A private header file that contains platform-specific definitions, which +allow abstraction from the underlying system. + + + +ldap-standard.h + +Contains the standard LDAP functions, structures, and defines. This +header is included in ldap.h. + + + +ldap-to-be-deprecated.h + +Contains functions, structures, and defines that might be deprecated +in future releases. This header is included in ldap.h. + + + + +ldap.h + +This base header contains LDAP functions, structures, and defines to +mirror the latest LDAP C API specifications. + +This header also includes the following header files: +ldap-deprecated.h +ldap-extension.h +ldap-standard.h +ldap-to-be-deprecated.h + +For details, see ldap.h Header File. + + + + +ldap_ssl.h + +Contains prototypes for LDAP over SSL functions, structures, and defines. +For details, see ldap_ssl.h Header File + + + + +ldappr.h + +Contains prototypes for the functions, structures, and defines that +are contained in the Netscape Portable Runtime (NSPR) API. For details seeldappr.h Header File + + + +srchpref.h + +A header file related to the search preferences (ldapsearchprefs.conf + ). + + + +
+<filename>ldap.h</filename> Header File + +ldap.h header file +including +To make use of the &DirectorySDKForC; functions, include the +ldap.h header file in your C source files as shown in this line +of code: +#include "ldap.h" + +By including this file, you also include the following header files: +ldap-deprecated.h +ldap-extension.h +ldap-standard.h +ldap-platform.h +ldap-to-be-deprecated.h + + +<filename>lber.h</filename> Header File + +lber.h header file +including + +lber.h is included in ldap-standard.h. +You do not need to include the header explicitly. Basic Encoding Rules (BER) +is a simple tag-value scheme to encode requests and decode results. + +<filename>ldap_ssl.h</filename> Header File + +ldap_ssl.h header file +including +If you are calling LDAP over SSL functions, you also need to include +the ldap_ssl.h header file, as follows: +#include "ldap_ssl.h" + +<filename>ldappr.h</filename> Header File + +ldappr.h header file +including + +To make use of the Netscape Portable Runtime (NSPR) API with your LDAP +applications, you must include the ldappr.h file. The +NSPR is a set of platform-neutral APIs that provides system functions such +as threads, thread synchronization, I/O, interval timing, and atomic operations. +This header file contains prototypes for functions that tie the LDAP libraries +to NSPR. You include the header file as follows: +#include "ldappr.h" +For more information about NSPR, see the ldappr.h header +file and the Netscape Portable Runtime project page at http://www.mozilla.org/projects/nspr/ +. +
+Miscellaneous Files + +ldapfilter.confsample file + +ldapfriendlysample file + +ldapsearchprefs.confsample file + +ldaptemplates.confsample file + +C SDK +sample files + +&DirectorySDKForC; includes the sample files described in the following +table. Sample files can be retrieved when using certain APIs. Sample files +are located in the etc/ directory. All locations are +relative to the directory where the software is installed, which depends on +your operating system. +Sample Configuration +Files + + + + +File Name + +Description + + + + + +ldapfilter.conf + +This filter configuration file can be used in context with ldap_init_getfilter +. + + + +ldapfriendly + +This file is used to map the two—letter country codes to their +full names by ldap_friendly_name. + + + +ldapsearchprefs.conf + +This configuration file was used in context with a deprecated function. + + + + +ldaptemplates.conf + +This configuration file was used in context with a deprecated function. + + + + +
+
+&DirectorySDKForC; Libraries + +C SDK +libraries + +libraries +C SDK + +&DirectorySDKForC; includes several different libraries. A library +is a set of ready-made functions that are linked into a program. &DirectorySDKForC; uses +shared libraries. Shared libraries are dynamically loaded into +memory when needed, reducing the size of the executable. +Library Naming Conventions +Libraries on different systems have different naming conventions. The +following table shows the&DirectorySDKForC; naming conventions. +Library +Naming Convention by Operating System + + + + + + + +Operating System + +Static Library Name + +Shared Library Name + + + + + +Solaris and Red Hat systems + +liblibraryname.a + + +liblibraryname.so.versionnumber + + + + +HP-UX systems + +liblibraryname.a + + +liblibraryname.sl + + + + +Windows systems + +nslibraryname.lib + + +nslibraryname.dll + + + + +
+On UNIX systems, the shared +library file name can be fully qualified by prefixing path information. +
+Installed Shared Libraries +The following table describes the installed libraries that are in the +lib/ directory. All locations are relative to the directory where +the software is installed, which depends on your operating system. +Shared Libraries + + + + +UNIX Library + +Windows Library + +Description + + + + + +libldap60.so + +nsldap32v60.dll + +LDAP library. + + + +libprldap60.so + +nsldappr32v60.dll + +LDAP library built with NSPR. +This library requires the libnspr4.so library in +the lib-private/ directory. + + + +libssldap60.so + +nsldapssl32v60.dll + +LDAP library that is built with support for the Secure Sockets Layer +protocol. +This library depends on the libnss3.so and libnspr4.so + libraries in the lib-private/ directory. + + + + +
+
+&DirectorySDKForC; Dependencies + +&DirectorySDKForC; resolves dependencies for the following APIs at +run—time: +Netscape Portable Runtime (NSPR) provides core cross-platform +functions. +Netscape Security Services (NSS) provides encryption, cryptographic, +Secure Sockets Layer (SSL), and Public Key Infrastructure (PKI) support. + +Simple Authentication and Security Layer (SASL) provides support +for applications that require SASL. + + +
+LDAP Tools + +LDAP tools + +&DirectorySDKForC; includes several utilities to help you work with +LDAP data sets. These utilities are installed in the tools/ directory. +For details on each tool described in the following table, see the corresponding +man pages. A list of options can be retrieved by typing the tool name at the +command line. +&DirectorySDKForC; LDAP +Tools + + + + +Command + +Description + + + + + +ldapcmp + +Compares the contents of a single LDAP entry or subtree in two directories. + + + + +ldapcompare + +Compares an attribute value against the contents of a given LDAP entry. + + + + +ldapdelete + +Deletes existing LDAP entries. + + + +ldapmodify + +Edits the contents of an LDAP directory, either by adding new entries +or modifying existing ones. + + + +ldappasswd + +Changes user passwords on LDAP entries. + + + +ldapsearch + +Issues search requests to an LDAP directory, then displays the result +as LDAP Data Interchange Format (LDIF) text. + + + +
+
+
+Compiling Applications with Directory SDK for C + +C SDK +compiling applications + +When compiling applications, you must include the header files and link +to the libraries required. Information about including the header files is +in Directory SDK for C Header Files. Linking +to shared libraries is covered in this section. &DirectorySDKForC; is qualified +to work with C compilers. +&DirectorySDKForC; is not guaranteed to work with C++ compilers. + +Compiling on UNIX Platforms +When compiling clients on UNIX platforms, specify link options correctly +to link the application to the appropriate shared libraries. See the Makefile + in the examples/ directory for details on +compiling your applications on UNIX platforms. +Compiling on Windows Systems With &DirectorySDKForC; + +A Windows application can use either a command-line interface or a graphical +user interface (GUI). Windows systems refer to a console application. In a +console application, all user interaction happens through the command shell +interface, with a FILE pointer as found in UNIX systems. +Given this difference, make sure that you define the following: +_CONSOLE if you are writing a console application + +_WINDOWS if you are writing a standard +Windows GUI application + + +Linking Dependencies + +libraries +runtime + +When you run LDAP clients, you must ensure that the operating system +can find the shared libraries that support the functions called by your application. +Generally, these files are referred to as runtime libraries. +Any of the following options ensure that the operating system can find the +shared libraries. + +Make sure that the shared library file, such as libldap60.so +, is in a location specified by environment variables. + +On some platforms, clients can be complied with flags that +let you set the runtime path to load libraries as an environment variable. + +On Solaris and Red Hat systems, you +can use the LD_LIBRARY_PATH environment variable if you use +the -Wl,+s+b flag when compiling and linking. + +On HP-UX system, use the SHLIB_PATH environment +variable. + + +On Windows systems, copy all dynamic link libraries (DLLs) needed for +your application to a directory where your client can find the libraries. +Other software might install a different version of the DLLs in the Windows +system32\ directory. Make sure that your client finds the DLLs +included with &DirectorySDKForC; before your client finds the version in +the system32\ directory. At runtime, your client searches +for the DLL in the following locations in the order shown: +The directory from which the application loaded + +The current directory +The Windows system directory, typically winnt\system32\ +To avoid potential conflicts, do not copy the DLL +to this directory +The directories listed in the PATH environment +variable + + + + +Use a link flag that specifies the path where the executable +can find the library. For example, on Solaris systems, you can use the -R + flag to specify the path where the executable can find the library. +See the Makefile in the examples/ directory +for examples of additional settings for compiling and linking your LDAP client. +Different platforms might require different sets of define statements. + + + + +Sample Programs for Directory SDK for C + +C SDK +sample programs + +example programs +C SDK + +&DirectorySDKForC; includes several examples that demonstrate the +use of the functions that the SDK provides. The examples are located in the +examples/ directory. The example code is designed to run against +the LDAP v3 compliant &cnDirectoryServer;. Furthermore, the example code is +designed to work with sample data that has been properly loaded. For details +on the source files, refer to the README in the examples/ + directory. +The samples use synchronous LDAP calls and their asynchronous counterparts. +Because synchronous LDAP calls are more straightforward than their asynchronous +counterparts, look at the synchronous examples first. +Synchronous Examples + +C SDK +synchronous examples + +example programs +C SDK +synchronous + +The synchronous calls block the calling process until all results have +been returned. As these programs usually rely on event loops, the programs +are not appropriate for use with clients that implement a GUI in a single-threaded +environment. However, these sample programs do work with command-line clients +and CGI programs. +Synchronous +Example Programs + + + + +Example Source + +Description + + + + + +authzid.c + +Shows how to use the authorization ID control, which allows you to get +the authorization ID for an LDAP operation. + + + +compare.c + +Shows how to use ldap_compare_s, which allows you +to test if a particular value is contained in an attribute of an entry. + + + + +crtfilt.c + +Shows how to use the ldap_create_filter function +to generate LDAP filters. + + + +csearch.c + +Like search.c, but enables an in-memory cache. + + + + +effright.c + +Shows how to use the get effective rights control, which allows you +to determine access rights to entries and their attributes. + + + +getattrs.c + +Retrieves specific attributes from an entry. + + + +getfilt.c + +Shows how to use the ldap_getfilter* family of +functions, which generate LDAP filters that are based on an arbitrary search +string provided by a user. + + + +modattrs.c + +Shows how to use ldap_modify_s to replace and add +to values in an attribute. + + + +modrdn.c + +Shows how to use ldap_modrdn2_s to change the relative +distinguished name (RDN) of an entry. + + + +pwdextop.c + +Shows how to use the LDAP password modify extended operation to change +a password. + + + +pwdpolicy.c + +Shows how to use the password policy control. This control allows you +to retrieve information about the password policy that applies to the user +binding to the directory. + + + +rdentry.c + +Shows how to use ldap_search_s to retrieve a particular +entry from the directory. + + + +realattr.c + +Shows how to use the control to retrieve only real attributes during +a search. + + + +search.c + +Shows how to use ldap_search_s to search for all +entries that have an attribute value that exactly matches what you search +for. + + + +srvrsort.c + +Shows how to use server-side sorting in conjunction with the ldap_search_ext_s + function. + + + +ssearch.c + +Like ssnoauth.c, but includes certificate-based +authentication. + + + +ssnoauth.c + +Like search.c, but the search is done over an SSL-protected +TCP connection. + + + +starttls.c + +Shows how to use the Start TLS extended operation. + + + +userstatus.c + +Shows how to use the account status control to retrieve information +about the account of the user binding to the directory. + + + +virtattr.c + +Shows how to use the control to retrieve only virtual attributes during +a search. + + + +whoami.c + +Shows how to use the Who am I? extended operation to retrieve the authorization +ID. + + + +
+
+Asynchronous Examples + +C SDK +asynchronous examples + +example programs +C SDK +asynchronous programs + +These examples use the asynchronous LDAP calls. You begin an operation. +You then periodically poll to see if any results have been returned. +Asynchronous +Example Programs + + + + +Example Source + +Description + + + + + +add.c + +Adds an entry to the directory. + + + +asearch.c + +Initiates a search for entries, printing the results on arrival. + + + + +del.c + +Deletes an entry from the directory. + + + +nsprio.c + +Like asearch. but uses the PerLDAP routines to incorporate +the Netscape Portable Runtime (NSPR) API. + + + +ppolicy.c + +Attempts to bind to the directory and reports back any password expiration +information received. This program demonstrates how clients can process password +policy information. + + + +psearch.c + +Shows how to use Persistent Search, an LDAP v3 extension, to monitor +a directory for changes. + + + +
+
+
+
diff --git a/mozilla/directory/docs/ldapcsdk/csdk-whatsnew.sgm b/mozilla/directory/docs/ldapcsdk/csdk-whatsnew.sgm new file mode 100644 index 00000000000..3937ed0d75c --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/csdk-whatsnew.sgm @@ -0,0 +1,178 @@ + +What's New In &DirectorySDKForC; + +upgrading +C SDK + +This chapter compares the current version of &DirectorySDKForC; API +with the previous version. + +This chapter covers the following topics: +Deprecated and Changed +Directory SDK for C Features +New Directory SDK for +C Features + + +Deprecated and Changed &DirectorySDKForC; Features + + +deprecated features +C SDK + +This section covers the following changes and deprecated features in +this release. Where possible, &DirectorySDKForC; provides replacement features +for deprecated features. + +liblber API +File layout +IPv6 support +NSS and NSPR version updates +NSS security tools + +<filename class="libraryfile">liblber</filename> API + + +APIs +liblber + +libraries +liblber + +The Basic Encoding Rules library, liblber, +changed for portability reasons and to comply with The C LDAP Application +Program Interface Internet draft. In particular, according to +section 17.1., BER Data Structures and Types, the following +structures have changed. +The following additional integral types are defined for use in manipula- +tion of BER encoded ASN.1 values: + + typedef <impl_tag_t> ber_tag_t; /* for BER tags */ + typedef <impl_int_t> ber_int_t; /* for BER ints, enums, and Booleans */ + typedef <impl_unit_t> ber_uint_t; /* unsigned equivalent of ber_uint_t */ + typedef <impl_slen_t> ber_slen_t; /* signed equivalent of ber_len_t */ + +Note that the actual definition for these four integral types is imple- +mentation specific; that is, `<impl_tag_t>', `<impl_int_t>', +`<impl_uint_t>', and `<impl_slen_t>' MUST each be replaced with an +appropriate implementation-specific type. +Programs that do not use the liblber API +directly need not be changed. You can continue to build and use those applications +as before. +If, however, your programs call the liblber API +directly, you must change your application code to reflect the type definitions +in include/lber.h. Compilers typically issue type mismatch +warnings when compiling old code that has not been fixed. +File Layout +The file layout has changed. All files are unpacked in a base directory +that is named according to the platform and to the operating system of the +binary distribution. The file layout is covered in the section on Files Provided With Directory SDK for C. + +IPv6 Support +IPv6 support is provided by means of the NSPR library. Therefore, to +use LDAP over IPv6, use prldap_init instead of ldap_init +. +NSS and NSPR Version Updates +This version of &DirectorySDKForC; uses NSS 3.11and NSPR 4.6. Both +components are included in binary form for your convenience. +NSS Security Tools +NSS security tools, used to maintain NSS databases so your application +can do LDAP over SSL, are not delivered with &DirectorySDKForC;. +For access to NSS security tools, refer to the NSS +security tools project. + +New &DirectorySDKForC; Features + +new features +C SDK + +C SDK +new features of + + +This section describes the features introduced in this release: +LDAP Version 3 Default + +Supported +Controls +Supported Extended +Operations +Additional Directory +SDK for C Examples + +LDAP Version 3 Default +&DirectorySDKForC; now uses LDAP v3 by default. You can therefore +use LDAP v3 features in your applications even if you do not specifically +set the version to 3. +Supported Controls +This version of &DirectorySDKForC; adds support for developing client +applications, including more than 10 LDAP v3 controls. See Table 16–1 for a complete list. +For instructions on using controls supported by &DirectorySDKForC;, +see Chapter 16, LDAP Controls With Directory +SDK for C. +Supported Extended Operations + +extended operations +C SDK support of + +This version of &DirectorySDKForC; adds support for developing client +applications that use the following extended operations. + +LDAP Password Modify Extended Operation +The LDAP Password Modify extended operation lets your client +application modify a user password through LDAP. A user can modify his password +even if the password is not stored as an attribute in the directory, the user +is not identified by a DN, or the user does not have an entry in the directory. +The LDAP Password Modify extended operation is defined in RFC 3062. +The extended operation has identifier 1.3.6.1.4.1.4203.1.11.1. + + + +Start TLS Extended Operation +The Start TLS extended operation lets your client application +connect to a nonsecure port, and then request transport layer security. +The extended operation has identifier 1.3.6.1.4.1.1466.20037. + + + +Who Am I? Extended Operation +The “Who am I?” extended operation lets your client +application determine the authorization identity that the server currently +associates with your client. +The extended operation has identifier 1.3.6.1.4.1.4203.1.11.3. + + + + +For instructions on using extended operations supported by &DirectorySDKForC;, +see Chapter 18, Extended Operations With +Directory SDK for C. +Additional &DirectorySDKForC; Examples + + +example programs +C SDK + +More sample code is provided in the examples/ directory. +The additional samples demonstrate newly supported controls and extended operations. + + + diff --git a/mozilla/directory/docs/ldapcsdk/csdk-write.sgm b/mozilla/directory/docs/ldapcsdk/csdk-write.sgm new file mode 100644 index 00000000000..f6e5ea5c20d --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/csdk-write.sgm @@ -0,0 +1,2118 @@ + +Adding, Updating, and Deleting Entries With &DirectorySDKForC; + + +C SDK +writing to directory entries + +This chapter explains how to use LDAP C API functions to add, update, +delete, and rename entries. + +This chapter covers the following topics: +Specifying Entry Information With +Directory SDK for C +Adding an Entry With Directory SDK +for C +Modifying an Entry With Directory +SDK for C +Deleting an Entry With Directory +SDK for C +Changing the DN of an Entry With +Directory SDK for C + + +Specifying Entry Information With &DirectorySDKForC; + +To add or modify an entry in the directory, you need to specify information +about the entry’s attributes. In most cases, you must specify the following: + +The type of attribute that you are working with. For example, +the sn attribute or the telephoneNumber attribute. + +The values that you are adding, or replacing in the attribute. + +The operation that you are performing when modifying an existing +entry. In other words, determine whether you are adding, modifying, or deleting +the attribute in the existing entry. + +To specify this information, you use an LDAPMod structure +as shown here. +<structname>LDAPMod</structname> Structure + +typedef struct ldapmod { + int mod_op; + char *mod_type; + union { + char **modv_strvals; + struct berval **modv_bvals; + } mod_vals; +#define mod_values mod_vals.modv_strvals +#define mod_bvalues mod_vals.modv_bvals +} LDAPMod; + +The following table details the fields in the LDAPMod data +structure. +<structname>LDAPMod +</structname> Field Descriptions + + + + +Field + +Description + + + + + + +mod_op + + +The operation to be performed on the attribute and the type of data +that is specified as the attribute values. This field can have one of the +following values: +LDAP_MOD_ADD adds a value to the attribute. + +LDAP_MOD_DELETE removes a value from the +attribute. +LDAP_MOD_REPLACE replaces all existing +values of the attribute.Furthermore, if you specify binary values +in the mod_bvalues field, use the bitwise or operator, +|, to combine LDAP_MOD_BVALUES with the operation +type: +mod->mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES +If you are using the structure to add a new entry, you can specify +0 for the mod_op field, unless you are adding +binary values and need to specify LDAP_MOD_BVALUES. See Adding an Entry With Directory SDK for C for details. + + + + + + +mod_type + +Attribute type that you want to add, delete, or replace, such as sn + or telephoneNumber. + + + +mod_values + +Pointer to a NULL terminated array of string values +for the attribute. + + + +mod_bvalues + +Pointer to a NULL terminated array of berval + structures for the attribute. + + + +
+The following precautions pertain to entry modifications and +the fields detailed in Table 11–1. + + +If you specify LDAP_MOD_DELETE in the +mod_op field to remove all values in an attribute, the attribute +is removed from the entry. +If you specify LDAP_MOD_DELETE in the +mod_op field and NULL in the mod_values field, +the attribute is removed from the entry. +If you specify LDAP_MOD_REPLACE in the +mod_op field and NULL in the mod_values field, +the attribute is removed from the entry. +If you specify LDAP_MOD_REPLACE in the +mod_op field, but the attribute does not exist in the entry, the +attribute is added to the entry. +If you specify LDAP_MOD_ADD in the mod_op + field, but the attribute does not exist in the entry, the attribute +is added to the entry. + +If you allocate memory for the structures yourself, free the structures +when you finish by calling the ldap_mods_free function. +
+Adding an Entry With &DirectorySDKForC; + +LDAP entries +adding + +entries +adding + +adding +LDAP entries + +The following procedure provides the general steps for adding a new +entry to the directory. +To Add a New Entry + +Use the LDAPMod structure to specify +the name and values of each attribute. +Create an array of LDAPMod structures +to represent the attributes in the entry. +Call the ldap_add_ext or ldap_add_ext_s + function, passing in the array of LDAPMod structures +and a distinguished name (DN) for the entry. +Call the ldap_mods_free function to free +any LDAPMod structures that you allocated. + + + +Specifying Values for Attributes +You can specify a value for an attribute in three ways. You can specify +a single value. You can specify multiple values. You can add binary data as +the value of an attribute. +Specifying a Single Value in an Attribute +To specify a value in an attribute, set the mod_op, +mod_type, and mod_values fields in an LDAPMod + structure. This example sets up the structure for the sn attribute. + +Setting Up an Attribute Structure +#include "ldap.h" +… +LDAPMod attribute1; +char *sn_values[] = { "Jensen", NULL }; +… +attribute1.mod_op = 0; +attribute1.mod_type = "sn"; +attribute1.mod_values = sn_values; +… + +Because you are specifying an attribute for a new entry, rather than +for an existing entry, you can set the mod_op field to +0. For an existing entry, the mod_op field identifies +the type of change you are making to the entry. +Specifying Multiple Values in an Attribute +If an attribute has more than one value, specify the values in the +mod_values array. This example specifies two values for the cn + attribute. +Specifying Multiple +Values in an Attribute +#include "ldap.h" +… +LDAPMod attribute2, attribute3; +char *cn_values[] = { "Barbara Jensen", "Babs Jensen", NULL }; +char *objectClass_values[] = { "top", "person", + "organizationalPerson", "inetOrgPerson", NULL }; +… +attribute2.mod_op = 0; +attribute2.mod_type = "cn"; +attribute2.mod_values = cn_values; +attribute3.mod_op = 0; +attribute3.mod_type = "objectClass"; +attribute3.mod_values = objectClass_values; +… + + +Specifying Binary Data as the Value of an Attribute +If the attribute contains binary data rather than string values, specify +the data in a berval structure similar to this. +<structname>berval</structname> Structure + +struct berval { + unsigned long bv_len; + char *bv_val; +} + +The berval structure fields and field descriptions +are as follows: + +bv_len +The length of the data + + +bv_val +A pointer to the binary data + + + +After creating the berval structures for the +binary data, you may use the structures. +To Use <structname>berval</structname> Structures + +Add the berval structures to the mod_bvalues + field in the LDAPMod structure. + +Use the bitwise or operator, |, to combine +the value of the mod_op field with LDAP_MOD_BVALUES. +When adding a new entry, you set the mod_op field +to LDAP_MOD_BVALUES because the mod_op field +is 0 in this case.For example, suppose the +file my_photo.jpg contains a JPEG photograph of Barbara +Jensen. The following example sets the jpegPhoto attribute +to the JPEG data of the photograph. + + +Adding a Value to an Attribute +#include <stdio.h> +#include <sys/stat.h> +#include "ldap.h" +… +char *photo_data; +FILE *fp; +struct stat st; +LDAPMod attribute4; +struct berval photo_berval; +struct berval *jpegPhoto_values[2]; +/* Get information about the JPEG file, including its size. */ +if ( stat( "my_photo.jpg", &st ) != 0 ) { + perror( "stat" ); + return( 1 ); +} + +/* Open the JPEG file and read it into memory. */ +if ( ( fp = fopen( "my_photo.jpg", "rb" ) ) == NULL ) { + perror( "fopen" ); + return( 1 ); +} +if ( ( ( photo_data = ( char * )malloc( st.st_size ) ) == NULL ) || + ( fread ( photo_data, st.st_size, 1, fp ) != 1 ) ) { + perror( photo_data ? "fread" : "malloc" ); + return( 1 ); +} + +fclose( fp ); + +attribute4.mod_op = LDAP_MOD_BVALUES; +attribute4.mod_type = "jpegPhoto"; +photo_berval.bv_len = st.st_size; +photo_berval.bv_val = photo_data; +jpegPhoto_values[0] = &photo_berval; +jpegPhoto_values[1] = NULL; +attribute4.mod_values = jpegPhoto_values; + + + + +Specifying Attributes in the Entry +After specifying values for attributes in LDAPMod structures, +as described in Specifying Values for Attributes, +you need to construct an array of these structures. You then pass a pointer +to this array as a parameter to the function for creating a new entry. +Make sure you create LDAPMod structures for +all required attributes in the new entry. + The following example creates an array of LDAPMod structures. + +Adding an Array of +Structures to an Attribute +#include "ldap.h" +LDAPMod *list_of_mods[5] +LDAPMod attribute1, attribute2, attribute3, attribute4; +… +/* Code for filling the LDAPMod structures with values */ +… +list_of_mods[0] = &attribute1; +list_of_mods[1] = &attribute2; +list_of_mods[2] = &attribute3; +list_of_mods[3] = &attribute4; +list_of_mods[4] = NULL; +… + + +Adding the Entry to the Directory + +To add the entry to the directory, call one of the following: +The synchronous ldap_add_ext_s function + +The asynchronous ldap_add_ext function + + +If you have allocated LDAPMod structures yourself, +you should free the structures when you are done. Call the ldap_mods_free + function to free LDAPMod structures. +Synchronous Add Operation + +synchronous functions +add operation + +If you want to wait for the results of the add operation to complete +before continuing, call the synchronous ldap_add_ext_s function. +This function sends an LDAP add request to the server. The function also blocks +other work until the server sends the results of the operation back to your +client. The ldap_add_ext_s function returns LDAP_SUCCESS + if the operation completed successfully, or an error code if +a problem occurred. +The following example calls the synchronous ldap_add_ext_s function +to add the user William Jensen to the directory. +Performing a Synchronous Add Operation + +#include <stdio.h> +#include "ldap.h" +… +#define NEW_DN "uid=wbjensen,ou=People,dc=example,dc=com" +… +LDAP *ld; +LDAPMod **mods; +char *matched_msg = NULL, *error_msg = NULL; +int rc; +… +/* Perform the add operation. */ +rc = ldap_add_ext_s( ld, NEW_DN, mods, NULL, NULL ); +if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_add_ext_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } +} else { + printf( "%s added successfully.\n", NEW_DN ); +} +… + +The following sample program calls the synchronous ldap_add_ext_s + function to add a new user to the directory. +Sample Synchronous Add Program +#include <stdio.h> +#include "ldap.h" +/* Change these as needed. */ +#define HOSTNAME "localhost" +#define PORTNUMBER LDAP_PORT +#define BIND_DN "cn=Directory Manager" +#define BIND_PW "23skidoo" +#define NEW_DN "uid=wbjensen,ou=People,dc=example,dc=com" +#define NUM_MODS 5 +int +main( int argc, char **argv ) +{ + LDAP *ld; + LDAPMod **mods; + char *matched_msg = NULL, *error_msg = NULL; + int i, rc; + char *object_vals[] = { "top", "person", "organizationalPerson", + "inetOrgPerson", NULL }; + +char *cn_vals[] = { "William B Jensen", "William Jensen", "Bill Jensen", + NULL }; + char *sn_vals[] = { "Jensen", NULL }; + char *givenname_vals[] = { "William", "Bill", NULL }; + char *telephonenumber_vals[] = { "+1 415 555 1212", NULL }; + /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } + /* Bind to the server as the Directory Manager. */ + rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + ldap_unbind_s( ld ); + return( 1 ); + } + /* Construct the array of LDAPMod structures representing the attributes + of the new entry. */ + mods = ( LDAPMod ** ) malloc(( NUM_MODS + 1 ) * sizeof( LDAPMod * )); + if ( mods == NULL ) { + fprintf( stderr, "Cannot allocate memory for mods array\n" ); + exit( 1 ); + } + for ( i = 0; i < NUM_MODS; i++ ) { + if (( mods[ i ] = ( LDAPMod * ) malloc( sizeof( LDAPMod ))) == NULL ) { + fprintf( stderr, "Cannot allocate memory for mods element\n" ); + exit( 1 ); + } + } + mods[ 0 ]->mod_op = 0; + mods[ 0 ]->mod_type = "objectclass"; + mods[ 0 ]->mod_values = object_vals; + mods[ 1 ]->mod_op = 0; + mods[ 1 ]->mod_type = "cn"; + mods[ 1 ]->mod_values = cn_vals; + mods[ 2 ]->mod_op = 0; + mods[ 2 ]->mod_type = "sn"; + mods[ 2 ]->mod_values = sn_vals; + mods[ 3 ]->mod_op = 0; + mods[ 3 ]->mod_type = "givenname"; + mods[ 3 ]->mod_values = givenname_vals; + mods[ 4 ]->mod_op = 0; + mods[ 4 ]->mod_type = "telephonenumber"; + mods[ 4 ]->mod_values = telephonenumber_vals; + mods[ 5 ] = NULL; + /* Perform the add operation. */ + rc = ldap_add_ext_s( ld, NEW_DN, mods, NULL, NULL ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_add_ext_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL & *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + } else { + printf( "%s added successfully.\n", NEW_DN ); + } + ldap_unbind_s( ld ); + for ( i = 0; i < NUM_MODS; i++ ) { + free( mods[ i ] ); + } + free( mods ); + return 0; +} + + +Asynchronous Add Operation + +asynchronous functions +add operation + +If you want to perform other work while waiting for the entry to be +added, call the asynchronous ldap_add_ext function. This +function sends an LDAP add request to the server and returns an LDAP_SUCCESS + result code if the request was successfully sent, or an LDAP +result code if an error occurred. +The ldap_add_ext function passes back a message +ID identifying the add operation. To determine whether the server sent a response +for this operation to your client, call the ldap_result function +and pass in this message ID. The ldap_result function +uses the message ID to determine if the server sent the results of the add +operation. The ldap_result function passes back the results +in an LDAPMessage structure. You can call the +ldap_parse_result function to parse the LDAPMessage structure +to determine if the operation was successful. +The following example calls the asynchronous ldap_add_ext function +to add the user William Jensen to the directory. +Performing an Asynchronous Add +Operation +#include <stdio.h> +#include "ldap.h" +… +#define NEW_DN "uid=wbjensen,ou=People,dc=example,dc=com" + +… +LDAP *ld; +LDAPMessage *res; +LDAPControl **serverctrls; +char *matched_msg = NULL, *error_msg = NULL; +char **referrals; +int i, rc, parse_rc, msgid, finished = 0; + +/* Timeout period for the ldap_result() function to wait for results. */ +struct timeval zerotime; +zerotime.tv_sec = zerotime.tv_usec = 0L; +… +/* Send the LDAP add request. */ +rc = ldap_add_ext( ld, NEW_DN, mods, NULL, NULL, &msgid ); +if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_add_ext: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); +} +… +/* Poll the server for the results of the add operation. */ +while ( !finished ) { + rc = ldap_result( ld, msgid, 0, &zerotime, &res ); + switch ( rc ) { + case -1: + /* An error occurred. */ + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + case 0: + /* The timeout period specified by zerotime was exceeded, + so call ldap_result() again and continue polling. */ + break; + default: + /* The function has retrieved the results of the add operation. */ + finished = 1; + + /* Parse the result to determine the result of + the add operation. */ + parse_rc = ldap_parse_result( ld, res, &rc, &matched_msg, + &error_msg, &referrals, &serverctrls, 1 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_parse_result: %s\n", + ldap_err2string( parse_rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + + /* Check the results of the LDAP add operation. */ + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_add_ext: %s\n", ldap_err2string( rc ) ); + if ( error_msg != NULL & *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + } else { + printf( "%s added successfully.\n", NEW_DN ); + } + } +} +… + +The following sample program calls the asynchronous ldap_add_ext function +to add a new user to the directory. +Sample Asynchronous Add +Program +#include <stdio.h> +#include "ldap.h" +void do_other_work(); +int global_counter = 0; +void free_mods( LDAPMod **mods ); +/* Change these as needed. */ +#define HOSTNAME "localhost" +#define PORTNUMBER LDAP_PORT +#define BIND_DN "cn=Directory Manager" +#define BIND_PW "23skidoo" +#define NEW_DN "uid=wbjensen,ou=People,dc=example,dc=com" +#define NUM_MODS 5 +int +main( int argc, char **argv ) +{ + LDAP *ld; + LDAPMessage *res; + LDAPMod **mods; + LDAPControl **serverctrls; + char *matched_msg = NULL, *error_msg = NULL; + char **referrals; + int i, rc, parse_rc, msgid, finished = 0; + struct timeval zerotime; + char *object_vals[] = { "top", "person", "organizationalPerson", + "inetOrgPerson", NULL }; + char *cn_vals[] = { "William B Jensen", "William Jensen", + "Bill Jensen", NULL }; + char *sn_vals[] = { "Jensen", NULL }; + char *givenname_vals[] = { "William", "Bill", NULL }; + char *telephonenumber_vals[] = { "+1 415 555 1212", NULL }; + zerotime.tv_sec = zerotime.tv_usec = 0L; + /* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } + /* Bind to the server as the Directory Manager. */ + rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + ldap_unbind_s( ld ); + return( 1 ); + } + /* Construct the array of LDAPMod structures representing the attributes + of the new entry. */ + mods = ( LDAPMod ** ) malloc(( NUM_MODS + 1 ) * sizeof( LDAPMod * )); + if ( mods == NULL ) { + fprintf( stderr, "Cannot allocate memory for mods array\n" ); + exit( 1 ); + } + for ( i = 0; i < NUM_MODS; i++ ) { + if (( mods[ i ] = ( LDAPMod * ) malloc( sizeof( LDAPMod ))) == NULL ) { + fprintf( stderr, "Cannot allocate memory for mods element\n" ); + exit( 1 ); + } + } + mods[ 0 ]->mod_op = 0; + mods[ 0 ]->mod_type = "objectclass"; + mods[ 0 ]->mod_values = object_vals; + mods[ 1 ]->mod_op = 0; + mods[ 1 ]->mod_type = "cn"; + mods[ 1 ]->mod_values = cn_vals; + mods[ 2 ]->mod_op = 0; + mods[ 2 ]->mod_type = "sn"; + mods[ 2 ]->mod_values = sn_vals; + mods[ 3 ]->mod_op = 0; + mods[ 3 ]->mod_type = "givenname"; + mods[ 3 ]->mod_values = givenname_vals; + mods[ 4 ]->mod_op = 0; + mods[ 4 ]->mod_type = "telephonenumber"; + mods[ 4 ]->mod_values = telephonenumber_vals; + mods[ 5 ] = NULL; + /* Send the LDAP add request. */ + rc = ldap_add_ext( ld, NEW_DN, mods, NULL, NULL, &msgid ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_add_ext: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + free_mods( mods ); + return( 1 ); + } + /* Poll the server for the results of the add operation. */ + while ( !finished ) { + rc = ldap_result( ld, msgid, 0, &zerotime, &res ); + switch ( rc ) { + case -1: + /* An error occurred. */ + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + free_mods( mods ); + return( 1 ); + case 0: + /* The timeout period specified by zerotime was exceeded. + This means that the server has still not yet sent the + results of the add operation back to your client. + Break out of this switch statement, and continue calling + ldap_result() to poll for results. */ + break; + default: + /* The function has retrieved the results of the add operation + from the server. */ + finished = 1; + /* Parse the results received from the server. Note the last + argument is a non-zero value, which indicates that the + LDAPMessage structure will be freed when done. (No need + to call ldap_msgfree().) */ + parse_rc = + ldap_parse_result( ld, res, &rc, &matched_msg, + &error_msg, &referrals, &serverctrls, 1 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, + "ldap_parse_result: %s\n", + ldap_err2string( parse_rc ) ); + ldap_unbind( ld ); + free_mods( mods ); + return( 1 ); + } + /* Check the results of the LDAP add operation. */ + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_add_ext: %s\n", ldap_err2string( rc ) ); + if ( error_msg != NULL & *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + } else { + printf( "%s added successfully.\n" + "Counted to %d while waiting for the add operation.\n", + NEW_DN, global_counter ); + } + } + /* Do other work while waiting for the results of the add operation. */ + if ( !finished ) { + do_other_work(); + } + } + ldap_unbind( ld ); + free_mods( mods ); + return 0; +} +/* + * Free a mods array. + */ +void +free_mods( LDAPMod **mods ) +{ + int i; + for ( i = 0; i < NUM_MODS; i++ ) { + free( mods[ i ] ); + } + free( mods ); +} + +/* + * Perform other work while polling for results. + * This doesn't do anything useful, but it could. + */ +void +do_other_work() +{ + global_counter++; +} + + + + +Modifying an Entry With &DirectorySDKForC; + +LDAP entries +modifying + +modifying +LDAP entries + +entries +modifying + +The following procedure provides the general steps for modifying an +entry. +To Modify an Entry + +Use the LDAPMod structure to specify +a change to an attribute. +Create an array of LDAPMod structures +that represent the changes that need to be made. +Call the ldap_modify_ext or ldap_modify_ext_s + function, passing in the array of LDAPMod structures +and the DN of the entry that you want modified. +Call the ldap_mods_free function to free +any LDAPMod structures that you allocated. + + + +Types of Modifications +You can modify an entry in various ways. The following sections explain +the types of modifications. +Replacing the Values of an Attribute + +To replace all existing values of an attribute, create an LDAPMod + structure with the following values. +Set the mod_type field to the attribute +type that you want to change, such as telephoneNumber. + +Set the mod_values field to the new values +of the attribute. +Set the value of the mod_op field to +LDAP_MOD_REPLACE. + +The following code specifies a change that replaces the values of the +telephoneNumber attribute. +#include "ldap.h" +LDAPMod attribute1; +char *telephoneNumber_values[] = { "+1 800 555 1212", NULL }; +attribute1.mod_type = "telephoneNumber"; +attribute1.mod_op = LDAP_MOD_REPLACE; +attribute1.mod_values = telephoneNumber_values; + +If you want to specify binary data as berval structures +as opposed to string values, you need to do the following: +Use the mod_bvalues field rather than the +mod_values field. +Use the bitwise or operator, |, to combine +the value LDAP_MOD_BVALUES with the value of the mod_op + field. + +If you specify an attribute that does not exist in the entry, +the attribute is added to the entry.You can set a NULL value +for the attribute either by setting the mod_values field +to NULL or by setting the mod_bvalues field +to NULL. When the mod_op field also +contains LDAP_MOD_BVALUES, the attribute is removed from +the entry. + +Removing Values From an Attribute + +To remove values from an attribute, create an LDAPMod structure +with the following values: +Set the mod_type field to the attribute +type that contains the values to remove such as facsimileTelephoneNumber +. +Set the mod_values field to the values +that you want removed from the attribute. +Set the value of the mod_op field to +LDAP_MOD_DELETE.The following code specifies the removal +of one of the values of the facsimileTelephoneNumber attribute +in the entry. +#include "ldap.h" +LDAPMod attribute2; +char *fax_values[] = { "+1 800 555 1212", NULL }; +attribute2.mod_type = "facsimileTelephoneNumber"; +attribute2.mod_op = LDAP_MOD_DELETE; +attribute2.mod_values = fax_values; +… + + + +If you want to specify binary data as berval structures +as opposed to string values, you need to do the following: +Use the mod_bvalues field rather than the +mod_values field. +Use the bitwise or operator, |, to combine +the value LDAP_MOD_BVALUES with the value of the mod_op + field. + +If you remove all values from the attribute, the attribute +is removed from the entry.You can set a NULL value +for the attribute either by setting the mod_values field +to NULL, or by setting the mod_bvalues field +to NULL. When the mod_op field then +contains LDAP_MOD_BVALUES, the attribute is removed from +the entry. + +Adding Values to an Attribute + +To add values to an attribute in an entry, create an LDAPMod structure +with the following: +Set the mod_type field to the attribute +type that you want to add values to, such as audio. + +Set the mod_values field to the new values +of the attribute. +Set the value of the mod_op field to +LDAP_MOD_ADD. + + +If the attribute contains binary data as opposed to string values, you +need to do the following values: +Use the mod_bvalues field rather than the +mod_values field, and put the values in berval structures. + +Use the bitwise or operator, |, to combine +the value LDAP_MOD_BVALUES with the value of the mod_op + field. + +If the attribute does not already exist in the entry, the attribute +is added to the entry. +The following code adds values to the audio attribute +of an entry. +#include <stdio.h> +#include <sys/stat.h> +#include "ldap.h" +… +char *audio_data; +FILE *fp; +struct stat st; +LDAPMod attribute3; +struct berval audio_berval; +struct berval *audio_values[2]; +… +/* Get information about the audio file, including its size. */ +if ( stat( "my_sounds.au", &st ) != 0 ) { + perror( "stat" ); + return( 1 ); +} + +/* Open the audio file and read it into memory. */ +if ( ( fp = fopen( "my_sounds.au", "rb" ) ) == NULL ) { + perror( "fopen" ); + return( 1 ); +} + +if ( ( ( audio_data = ( char * )malloc( st.st_size ) ) == NULL ) || + ( fread ( audio_data, st.st_size, 1, fp ) != 1 ) ) { + perror( audio_data ? "fread" : "malloc" ); + return( 1 ); +} + +fclose( fp ); +attribute3.mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES; +attribute3.mod_type = "audio"; +audio_berval.bv_len = st.st_size; +audio_berval.bv_val = audio_data; +audio_values[0] = &audio_berval; +audio_values[1] = NULL; +attribute3.mod_values = audio_values; +… + +Removing an Attribute With &DirectorySDKForC; + +You can remove an attribute from an entry in either of the following +ways: +Remove all values from the attribute. +Set the mod_op field to LDAP_MOD_REPLACE + or LDAP_MOD_DELETE, and specify NULL for +the mod_values field. + + +Adding an Attribute With &DirectorySDKForC; +If you add or replace values in an attribute that does not yet exist +in the entry, the attribute is added to the entry. + +Creating an Array of Changes +After specifying the changes to attribute values in LDAPMod structures, +you need to construct an array of these structures. You pass a pointer to +this array as a parameter to the function for modifying the entry. The following +example creates an array of LDAPMod structures. +Assembling an Array of <structname> +LDAPMod</structname> Structures +#include "ldap.h" +… +LDAPMod *list_of_mods[4] +LDAPMod attribute1, attribute2, attribute3; +… +/* Code for filling the LDAPMod structures with values */ +… +list_of_mods[0] = &attribute1; +list_of_mods[1] = &attribute2; +list_of_mods[2] = &attribute3; +list_of_mods[3] = NULL; +… + + +Modifying an Entry in the Directory With &DirectorySDKForC; + + +To modify an entry in the directory, call one of the following functions: +The synchronous ldap_modify_ext_s function + +The asynchronous ldap_modify_ext function + + +Synchronous Modify Operation +If you want to wait for the results of the modify operation to complete +before continuing, call the synchronous ldap_modify_ext_s function. +The function sends a modify request to the server. Also, the function blocks +all work until the server sends the results of the operation back to your +client. The function returns LDAP_SUCCESS if the operation +completed successfully, or an error code if a problem occurred. +The following example calls the synchronous ldap_modify_ext_s function +to modify the entry for the user William Jensen in the +directory. +Performing a Synchronous Modify +Operation +#include <stdio.h> +#include "ldap.h" + +#define MODIFY_DN "uid=wbjensen,ou=People,dc=example,dc=com" +… +LDAP *ld; +LDAPMod *mods[ 3 ]; +char *matched_msg = NULL, *error_msg = NULL; +int rc; +… +/* Perform the modify operation. */ +rc = ldap_modify_ext_s( ld, MODIFY_DN, mods, NULL, NULL ); +if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_modify_ext_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } +} else { + printf( "%s modified successfully.\n", MODIFY_DN ); +} +ldap_unbind_s( ld ); +… + +The following sample program calls the synchronous ldap_modify_ext_s + function to modify a user entry in the directory. The program +replaces the values of the mail attribute and adds a +description attribute to the entry. +Sample Synchronous Modify +Program +#include <stdio.h> +#include <time.h> +#include "ldap.h" +/* Change these as needed. */ +#define HOSTNAME "localhost" +#define PORTNUMBER LDAP_PORT +#define BIND_DN "cn=Directory Manager" +#define BIND_PW "23skidoo" +#define MODIFY_DN "uid=wbjensen,ou=People,dc=example,dc=com" +int +main( int argc, char **argv ) +{ + LDAP *ld; + LDAPMod mod0, mod1; + LDAPMod *mods[ 3 ]; + char *matched_msg = NULL, *error_msg = NULL; + char *vals0[ 2 ], *vals1[ 2 ]; + time_t now; + char buf[ 128 ]; + int rc; +/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } +/* Bind to the server as the Directory Manager. */ + rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + ldap_unbind_s( ld ); + return( 1 ); + } +/* Construct the array of LDAPMod structures representing the + changes that you want to make to attributes in the entry. */ +/* Specify the first modification, which replaces all values of the +mail attribute with the value "wbj@example.com". */ + mod0.mod_op = LDAP_MOD_REPLACE; + mod0.mod_type = "mail"; + vals0[0] = "wbj@example.com"; + vals0[1] = NULL; + mod0.mod_values = vals0; +/* Specify the second modification, which adds a value to the + description attribute. If this attribute does not yet exist, + the attribute ia added to the entry. */ + mod1.mod_op = LDAP_MOD_ADD; + mod1.mod_type = "description"; + time( &now ); + sprintf( buf, "This entry was modified with the modattrs program on %s", + ctime( &now )); +/* Get rid of \n which ctime put on the end of the time string */ + if ( buf[ strlen( buf ) - 1 ] == '\n' ) { + buf[ strlen( buf ) - 1 ] = '\0'; + } + vals1[ 0 ] = buf; + vals1[ 1 ] = NULL; + mod1.mod_values = vals1; + mods[ 0 ] = &mod0; + mods[ 1 ] = &mod1; + mods[ 2 ] = NULL; +/* Perform the modify operation. */ + rc = ldap_modify_ext_s( ld, MODIFY_DN, mods, NULL, NULL ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_modify_ext_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + } else { + printf( "%s modified successfully.\n", MODIFY_DN ); + } + ldap_unbind_s( ld ); + return 0; +} + + +Asynchronous Modify Operation + +asynchronous functions +modify operation + +If you want to perform other work in parallel while waiting for the +entry to be modified, call the asynchronous ldap_modify_ext function. +This function sends a modify request to the server and returns an LDAP_SUCCESS + result code if the request was successfully sent, or an LDAP +result code if an error occurred. +The ldap_modify_ext function passes back a message +ID identifying the modify operation. To determine whether the server sent +a response for this operation to your client, call the ldap_result function +and pass in this message ID. The ldap_result function +uses the message ID to determine if the server sent the results of the modify +operation. The ldap_result function passes back the results +in an LDAPMessage structure. You can call the +ldap_parse_result function to parse the LDAPMessage structure +to determine if the operation was successful. +The following example calls the asynchronous ldap_modify_ext function +to modify the entry for the user William Jensen in the +directory. +Performing an Asynchronous Modify +Operation +#include <stdio.h> +#include "ldap.h" +… +#define MODIFY_DN "uid=wbjensen,ou=People,dc=example,dc=com" +… +LDAP *ld; +LDAPMessage *res; +LDAPMod *mods[ 3 ]; +LDAPControl **serverctrls; +char *matched_msg = NULL, *error_msg = NULL; +char **referrals; +int rc, parse_rc, msgid, finished = 0; + +/* Timeout period for the ldap_result() function to wait for results. */ +struct timeval zerotime; +zerotime.tv_sec = zerotime.tv_usec = 0L; +… +/* Send the LDAP modify request. */ +rc = ldap_modify_ext( ld, MODIFY_DN, mods, NULL, NULL, &msgid ); +if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_modify_ext: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); +} + +/* Poll the server for the results of the modify operation. */ +while ( !finished ) { + rc = ldap_result( ld, msgid, 0, &zerotime, &res ); + switch ( rc ) { + case -1: + /* An error occurred. */ + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + case 0: + /* The timeout period specified by zerotime was exceeded, + so call ldap_result() again and continue polling. */ + break; + default: + /* The function has retrieved the results of the + modify operation. */ + finished = 1; + + /* Parse the results received from the server. */ + parse_rc = ldap_parse_result( ld, res, &rc, &matched_msg, + &error_msg, &referrals, &serverctrls, 1 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_parse_result: %s\n", + ldap_err2string( parse_rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + + /* Check the results of the LDAP modify operation. */ + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_modify_ext: %s\n", + ldap_err2string( rc ) ); + if ( error_msg != NULL & *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + } else { + printf( "%s modified successfully.\n", MODIFY_DN ); + } + } +} +ldap_unbind( ld ); +… + +The following sample program calls the asynchronous ldap_modify_ext + function to modify a user entry in the directory. The program +replaces the values of the mail attribute and adds a +description attribute to the entry. +Sample Asynchronous Modify +Program +#include <stdio.h> +#include <time.h> +#include "ldap.h" +void do_other_work(); +int global_counter = 0; +/* Change these as needed. */ +#define HOSTNAME "localhost" +#define PORTNUMBER LDAP_PORT +#define BIND_DN "cn=Directory Manager" +#define BIND_PW "23skidoo" +#define MODIFY_DN "uid=wbjensen,ou=People,dc=example,dc=com" +int +main( int argc, char **argv ) +{ + LDAP *ld; + LDAPMessage *res; + LDAPMod mod0, mod1; + LDAPMod *mods[ 3 ]; + LDAPControl **serverctrls; + char *matched_msg = NULL, *error_msg = NULL; + char **referrals; + char *vals0[ 2 ], *vals1[ 2 ]; + time_t now; + char buf[ 128 ]; + int rc, parse_rc, msgid, finished = 0; + struct timeval zerotime; + zerotime.tv_sec = zerotime.tv_usec = 0L; +/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } +/* Bind to the server as the Directory Manager. */ + rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + ldap_unbind_s( ld ); + return( 1 ); + } +/* Construct the array of LDAPMod structures representing the changes + that you want to make to attributes in the entry. */ +/* Specify the first modification, which replaces all values of the + mail attribute with the value "wbj@example.com". */ + mod0.mod_op = LDAP_MOD_REPLACE; + mod0.mod_type = "mail"; + vals0[0] = "wbj@example.com"; + vals0[1] = NULL; + mod0.mod_values = vals0; +/* Specify the second modification, which adds a value to the description + attribute. If this attribute does not yet exist, the attribute ia added + to the entry. */ + mod1.mod_op = LDAP_MOD_ADD; + mod1.mod_type = "description"; + time( &now ); + sprintf( buf, + "This entry was modified with the modattrs program on %s", + ctime( &now )); +/* Get rid of \n which ctime put on the end of the time string */ + if ( buf[ strlen( buf ) - 1 ] == '\n' ) { + buf[ strlen( buf ) - 1 ] = '\0'; + } + vals1[ 0 ] = buf; + vals1[ 1 ] = NULL; + mod1.mod_values = vals1; + mods[ 0 ] = &mod0; + mods[ 1 ] = &mod1; + mods[ 2 ] = NULL; +/* Send the LDAP modify request. */ + rc = ldap_modify_ext( ld, MODIFY_DN, mods, NULL, NULL, &msgid ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_modify_ext: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + } +/* Poll the server for the results of the modify operation. */ + while ( !finished ) { + rc = ldap_result( ld, msgid, 0, &zerotime, &res ); + switch ( rc ) { + case -1: + /* An error occurred. */ + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + case 0: + /* The timeout period specified by zerotime was exceeded. + This means that the server has still not yet sent the + results of the modify operation back to your client. + Break out of this switch statement, and continue calling + ldap_result() to poll for results. */ + break; + default: + /* The function has retrieved the results of the modify + operation from the server. */ + finished = 1; + /* Parse the results received from the server. Note the last + argument is a non-zero value, which indicates that the + LDAPMessage structure will be freed when done. (No need + to call ldap_msgfree().) */ + parse_rc = ldap_parse_result( ld, res, &rc, &matched_msg, + &error_msg, &referrals, &serverctrls, 1 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, + "ldap_parse_result: %s\n", + ldap_err2string( parse_rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + /* Check the results of the LDAP add operation. */ + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_modify_ext: %s\n", ldap_err2string( rc ) ); + if ( error_msg != NULL & *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + } else { + printf( "%s modified successfully.\n" + "Counted to %d while waiting for the modify operation.\n", + MODIFY_DN, global_counter ); + } + } +/* Do other work while waiting for the results of the modify operation. */ + if ( !finished ) { + do_other_work(); + } + } + ldap_unbind( ld ); + return 0; +} + +/* + * Perform other work while polling for results. This doesn't do anything + * useful, but it could. + */ +void +do_other_work() +{ + global_counter++; +} + + + + +Deleting an Entry With &DirectorySDKForC; + +LDAP entry +delete + +deleting +LDAP entry + +entries +deleting + + +To remove an entry from the directory, call one of the following functions: + +The synchronous ldap_delete_ext_s function + +The asynchronous ldap_delete_ext function + + +Synchronous Delete Operation + +synchronous functions +delete operation + +If you want to wait for the results of the delete operation to complete +before continuing, call the synchronous ldap_delete_ext_s function. +This function sends a delete request to the server. The function also blocks +all other processes until the server sends the results of the operation back +to your client. The ldap_delete_ext_s function returns +LDAP_SUCCESS if the operation completed successfully, or an error +code if a problem occurred. +The following example calls the synchronous ldap_delete_ext_s function +to remove the entry for user William Jensen from the directory. + +Performing a Synchronous Delete +Operation +#include <stdio.h> +#include "ldap.h" +… +#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com" +… +LDAP *ld; +char *matched_msg = NULL, *error_msg = NULL; +int rc; +… +/* Perform the delete operation. */ +rc = ldap_delete_ext_s( ld, DELETE_DN, NULL, NULL ); +if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_delete_ext_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } +} else { + printf( "%s deleted successfully.\n", DELETE_DN ); +} +ldap_unbind_s( ld ); +… + +The following sample program calls the synchronous ldap_delete_ext_s + function to delete a user entry from the directory. +Sample Synchronous Delete +Program +#include <stdio.h> +#include "ldap.h" +/* Change these as needed. */ +#define HOSTNAME "localhost" +#define PORTNUMBER LDAP_PORT +#define BIND_DN "cn=Directory Manager" +#define BIND_PW "23skidoo" +#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com" +int +main( int argc, char **argv ) +{ + LDAP *ld; + char *matched_msg = NULL, *error_msg = NULL; + int rc; +/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } +/* Bind to the server as the Directory Manager. */ + rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + ldap_unbind_s( ld ); + return( 1 ); + } +/* Perform the delete operation. */ + rc = ldap_delete_ext_s( ld, DELETE_DN, NULL, NULL ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_delete_ext_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + } else { + printf( "%s deleted successfully.\n", DELETE_DN ); + } + ldap_unbind_s( ld ); + return 0; +} + + +Asynchronous Delete Operation + +asynchronous functions +delete operation + +If you want to perform other work in parallel while waiting for the +entry to be deleted, call the asynchronous ldap_delete_ext function. +This function sends a delete request to the server and returns an LDAP_SUCCESS + result code if the request was successfully sent, an LDAP result +code if an error occurred. +The ldap_delete_ext function passes back a message +ID identifying the delete operation. To determine whether the server sent +a response for this operation to your client, call the ldap_result function +and pass in this message ID. The ldap_result function +uses the message ID to determine if the server sent the results of the delete +operation. The ldap_result function passes back the results +in an LDAPMessage structure. You can call the +ldap_parse_result function to parse the LDAPMessage structure +to determine if the operation was successful. +The following example calls the asynchronous ldap_delete_ext function +to remove the user William Jensen from the directory. +Performing an Asynchronous Delete +Operation +#include <stdio.h> +#include "ldap.h" +… +#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com" +… +LDAP *ld; +LDAPMessage *res; +LDAPControl **serverctrls; +char *matched_msg = NULL, *error_msg = NULL; +char **referrals; +int rc, parse_rc, msgid, finished = 0; + +/* Timeout period for the ldap_result() function to wait for results. */ +struct timeval zerotime; +zerotime.tv_sec = zerotime.tv_usec = 0L; +… +/* Send the LDAP delete request. */ +rc = ldap_delete_ext( ld, DELETE_DN, NULL, NULL, &msgid ); +if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_delete_ext: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); +} + +/* Poll the server for the results of the delete operation. */ +while ( !finished ) { + rc = ldap_result( ld, msgid, 0, &zerotime, &res ); + switch ( rc ) { + case -1: + /* An error occurred. */ + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + case 0: + /* The timeout period specified by zerotime was exceeded, + so call ldap_result() again and continue polling. */ + break; + default: + /* The function has retrieved the results of the + delete operation. */ + finished = 1; + + /* Parse the results received from the server. */ + parse_rc = ldap_parse_result( ld, res, &rc, &matched_msg, + &error_msg, &referrals, &serverctrls, 1 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_parse_result: %s\n", + ldap_err2string( parse_rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + /* Check the results of the LDAP delete operation. */ + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_delete_ext: %s\n", + ldap_err2string( rc ) ); + if ( error_msg != NULL & *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + } else { + printf( "%s deleted successfully.\n", DELETE_DN ); + } + } +} +ldap_unbind( ld ); +… + +The following sample program calls the asynchronous ldap_delete_ext + function to delete a user entry from the directory. +Sample Asynchronous Delete +Program +#include <stdio.h> +#include "ldap.h" +void do_other_work(); +int global_counter = 0; +/* Change these as needed. */ +#define HOSTNAME "localhost" +#define PORTNUMBER LDAP_PORT +#define BIND_DN "cn=Directory Manager" +#define BIND_PW "23skidoo" +#define DELETE_DN "uid=wjensen,ou=People,dc=example,dc=com" +int +main( int argc, char **argv ) +{ + LDAP *ld; + LDAPMessage *res; + LDAPControl **serverctrls; + char *matched_msg = NULL, *error_msg = NULL; + char **referrals; + int rc, parse_rc, msgid, finished = 0; + struct timeval zerotime; + zerotime.tv_sec = zerotime.tv_usec = 0L; +/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } +/* Bind to the server as the Directory Manager. */ + rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + ldap_unbind_s( ld ); + return( 1 ); + } +/* Send the LDAP delete request. */ + rc = ldap_delete_ext( ld, DELETE_DN, NULL, NULL, &msgid ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_delete_ext: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + } +/* Poll the server for the results of the delete operation. */ + while ( !finished ) { + rc = ldap_result( ld, msgid, 0, &zerotime, &res ); + switch ( rc ) { + case -1: + /* An error occurred. */ + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + case 0: + /* The timeout period specified by zerotime was exceeded. + This means that the server has still not yet sent the + results of the delete operation back to your client. + Break out of this switch statement, and continue calling + ldap_result() to poll for results. */ + break; + default: + /* The function has retrieved the results of the delete operation + from the server. */ + finished = 1; + /* Parse the results received from the server. Note the last + argument is a non-zero value, which indicates that the + LDAPMessage structure will be freed when done. (No need + to call ldap_msgfree().) */ + parse_rc = ldap_parse_result( ld, res, &rc, &matched_msg, + &error_msg, &referrals, &serverctrls, 1 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, + "ldap_parse_result: %s\n", + ldap_err2string( parse_rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + /* Check the results of the LDAP delete operation. */ + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_delete_ext: %s\n", ldap_err2string( rc ) ); + if ( error_msg != NULL & *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + } else { + printf( "%s deleted successfully.\n" + "Counted to %d while waiting for the delete operation.\n", + DELETE_DN, global_counter ); + } + } + /* Do other work while waiting for the results of the + delete operation. */ + if ( !finished ) { + do_other_work(); + } + } + ldap_unbind( ld ); + return 0; +} +/* + * Perform other work while polling for results. This + * doesn't do anything useful, but it could. + */ +void +do_other_work() +{ + global_counter++; +} + + + +Changing the DN of an Entry With &DirectorySDKForC; + +LDAP entry +change DN + +changing +DN of entry + +entries +changing DN of + + +To change the distinguished name (DN) of an entry, call one of the following +functions: +The synchronous ldap_rename_s function + +The asynchronous ldap_rename function + + +For both functions, you can choose to delete the attribute that represents +the old relative distinguished name (RDN). You can also change the location +of the entry in the directory tree. +Synchronous Renaming Operation + +synchronous functions +renaming operation + +If you want to wait for the results of the modify DN operation to complete +before continuing, call the synchronous ldap_rename_s function. +This function sends a modify DN request to the server. The function also blocks +other work until the server sends the results of the operation back to your +client. The ldap_rename_s function returns LDAP_SUCCESS + if the operation completed successfully, or an error code if +a problem occurred. +The following calls the synchronous ldap_rename_s function +to change the RDN of the entry for the user William Jensen in +the directory. +Performing a Synchronous Rename +Operation +#include <stdio.h> +#include "ldap.h" +… +#define OLD_DN "uid=wbjensen,ou=People,dc=example,dc=com" +#define NEW_RDN "uid=wjensen" +… +LDAP *ld; +char *matched_msg = NULL, *error_msg = NULL; +int rc; +… +/* Perform the modify DN operation. */ +rc = ldap_rename_s( ld, OLD_DN, NEW_RDN, NULL, 1, NULL, NULL ); +if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_rename_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } +} else { + printf( "%s renamed successfully.\n", OLD_DN ); +} +ldap_unbind_s( ld ); +… + + +Asynchronous Renaming Operation + +asynchronous functions +renaming operation + +If you want to perform other work in parallel while waiting for the +entry to be renamed, call the asynchronous ldap_rename function. +This function sends a modify DN request to the server and returns an LDAP_SUCCESS + result code if the request was successfully sent, or an LDAP +result code if an error occurred. +The ldap_rename function passes back a message +ID identifying the modify DN operation. To determine whether the server sent +a response for this operation to your client, call the ldap_result function +and pass in this message ID. The ldap_result function +uses the message ID to determine if the server sent the results of the modify +DN operation. The ldap_result function passes back the +results in an LDAPMessage structure. You can call +the ldap_parse_result function to parse the LDAPMessage + structure to determine if the operation was successful. +The following example calls the asynchronous ldap_rename function +to change the RDN of the user William Jensen in the directory. + +Performing an Asynchronous +Rename Operation +#include <stdio.h> +#include "ldap.h" +… +#define OLD_DN "uid=wbjensen,ou=People,dc=example,dc=com" +#define NEW_RDN "uid=wjensen" +… +LDAP *ld; +LDAPMessage *res; +LDAPControl **serverctrls; +char *matched_msg = NULL, *error_msg = NULL; +char **referrals; +int rc, parse_rc, msgid, finished = 0; + +/* Timeout period for the ldap_result() function to wait + for results. */ +struct timeval zerotime; +zerotime.tv_sec = zerotime.tv_usec = 0L; +… +/* Send the LDAP modify DN request. */ +rc = ldap_rename( ld, OLD_DN, NEW_RDN, NULL, 1, NULL, NULL, &msgid ); +if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_rename: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); +} + +/* Poll the server for the results of the modify DN operation. */ +while ( !finished ) { + rc = ldap_result( ld, msgid, 0, &zerotime, &res ); + switch ( rc ) { + case -1: + /* An error occurred. */ + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + case 0: + /* The timeout period specified by zerotime was exceeded, + so call ldap_result() again and continue polling. */ + break; + default: + /* The function has retrieved the results of the + modify DN operation. */ + finished = 1; + + /* Parse the results received from the server. */ + parse_rc = ldap_parse_result( ld, res, &rc, &matched_msg, + &error_msg, &referrals, &serverctrls, 1 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_parse_result: %s\n", + ldap_err2string( parse_rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + + /* Check the results of the LDAP modify DN operation. */ + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_rename: %s\n", ldap_err2string( rc ) ); + if ( error_msg != NULL & *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + } else { + printf( "%s renamed successfully.\n", OLD_DN ); + } + } +} +ldap_unbind( ld ); +… + + +Deleting the Attribute From the Old RDN +Both ldap_rename and ldap_rename_s have +a deleteoldrdn parameter that allows you to remove the +old RDN from the entry. For example, suppose an entry has the following values +for the cn attribute: +cn: Barbara Jensen +cn: Babs Jensen +Then the following function adds the second name and removes the first: +ldap_modrdn2( "cn=Barbara Jensen", "cn=Barbie Jensen", 1 ); +The function adds Barbie Jensen to the list of values. +The function removes the Barbara Jensen value. The resulting +entry has the following values: +cn: Barbie Jensen +cn: Babs Jensen +Suppose 0 is passed for the deleteoldrdn parameter +instead of 1: +ldap_modrdn2( "cn=Barbara Jensen", "cn=Barbie Jensen", 0 ); +The Barbara Jensen value is not removed from the +entry. The resulting entry has the following values: +cn: Barbie Jensen +cn: Babs Jensen +cn: Barbara Jensen + +Changing the Location of the Entry +Both ldap_rename and ldap_rename_s have +a newparent parameter that allows you to specify a new +location for the entry in the directory tree. For example, if you pass ou=Contractors,dc=example,dc=com + as the newparent parameter when renaming the +entry uid=bjensen,ou=People,dc=example,dc=com, the entry +is moved under ou=Contractors,dc=example,dc=com. The new +DN for the entry is uid=bjensen,ou=Contractors,dc=example,dc=com. + +Some LDAP servers do not support this feature. When you specify +this argument, a server might return the LDAP result code LDAP_UNWILLING_TO_PERFORM +, with the error message Server does not support moving +of entries. +Synchronous Relocation of an Entry +The following example calls the synchronous ldap_rename_s function +to change the RDN of a user entry in the directory. +Performing a Synchronous Relocation +of an Entry +#include <stdio.h> +#include "ldap.h" +/* Change these as needed. */ +#define HOSTNAME "localhost" +#define PORTNUMBER LDAP_PORT +#define BIND_DN "cn=Directory Manager" +#define BIND_PW "23skidoo" +#define OLD_DN "uid=wbjensen,ou=People,dc=example,dc=com" +#define NEW_RDN "uid=wjensen" +int +main( int argc, char **argv ) +{ + LDAP *ld; + char *matched_msg = NULL, *error_msg = NULL; + int rc; +/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } +/* Bind to the server as the Directory Manager. */ + rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + ldap_unbind_s( ld ); + return( 1 ); + } +/* Perform the modify DN operation. */ + rc = ldap_rename_s( ld, OLD_DN, NEW_RDN, NULL, 1, NULL, NULL ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_rename_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + } else { + printf( "%s renamed successfully.\n", OLD_DN ); + } + ldap_unbind_s( ld ); + return 0; +} + + +Asynchronous Relocation of an Entry +The following example calls the asynchronous ldap_rename function +to change the RDN of a user entry in the directory. +Performing an Asynchronous +Relocation of an Entry +#include <stdio.h> +#include "ldap.h" +void do_other_work(); +int global_counter = 0; +/* Change these as needed. */ +#define HOSTNAME "localhost" +#define PORTNUMBER LDAP_PORT +#define BIND_DN "cn=Directory Manager" +#define BIND_PW "dougy4444" +#define OLD_DN "uid=wbjensen,ou=People,dc=example,dc=com" +#define NEW_RDN "uid=wjensen" +int +main( int argc, char **argv ) +{ + LDAP *ld; + LDAPMessage *res; + LDAPControl **serverctrls; + char *matched_msg = NULL, *error_msg = NULL; + char **referrals; + int rc, parse_rc, msgid, finished = 0; + struct timeval zerotime; + zerotime.tv_sec = zerotime.tv_usec = 0L; +/* Get a handle to an LDAP connection. Use prldap_init() for IPv6. */ + if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) { + perror( "ldap_init" ); + return( 1 ); + } +/* Bind to the server as the Directory Manager. */ + rc = ldap_simple_bind_s( ld, BIND_DN, BIND_PW ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) ); + ldap_get_lderrno( ld, &matched_msg, &error_msg ); + if ( error_msg != NULL && *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + ldap_unbind_s( ld ); + return( 1 ); + } +/* Send the LDAP modify DN request. */ + rc = ldap_rename( ld, OLD_DN, NEW_RDN, NULL, 1, NULL, NULL, &msgid ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_rename: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + } +/* Poll the server for the results of the modify DN operation. */ + while ( !finished ) { + rc = ldap_result( ld, msgid, 0, &zerotime, &res ); + switch ( rc ) { + case -1: + /* An error occurred. */ + rc = ldap_get_lderrno( ld, NULL, NULL ); + fprintf( stderr, "ldap_result: %s\n", ldap_err2string( rc ) ); + ldap_unbind( ld ); + return( 1 ); + case 0: + /* The timeout period specified by zerotime was exceeded. + This means that the server has still not yet sent the + results of the modify DN operation back to your client. + Break out of this switch statement, and continue calling + ldap_result() to poll for results. */ + break; + default: + /* The function has retrieved the results of the modify DN operation + from the server. */ + finished = 1; + /* Parse the results received from the server. Note the last + argument is a non-zero value, which indicates that the + LDAPMessage structure will be freed when done. (No need + to call ldap_msgfree().) */ + parse_rc = ldap_parse_result( ld, res, &rc, &matched_msg, + &error_msg, &referrals, &serverctrls, 1 ); + if ( parse_rc != LDAP_SUCCESS ) { + fprintf( stderr, + "ldap_parse_result: %s\n", + ldap_err2string( parse_rc ) ); + ldap_unbind( ld ); + return( 1 ); + } + /* Check the results of the LDAP modify DN operation. */ + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ldap_rename: %s\n", ldap_err2string( rc ) ); + if ( error_msg != NULL & *error_msg != '\0' ) { + fprintf( stderr, "%s\n", error_msg ); + } + if ( matched_msg != NULL && *matched_msg != '\0' ) { + fprintf( stderr, + "Part of the DN that matches an existing entry: %s\n", + matched_msg ); + } + } else { + printf( "%s renamed successfully.\n" + "Counted to %d while waiting for the modify DN operation.\n", + OLD_DN, global_counter ); + } + } + /* Do other work while waiting for the results of the + modify DN operation. */ + if ( !finished ) { + do_other_work(); + } + } + ldap_unbind( ld ); + return 0; +} +/* + * Perform other work while polling for results. This doesn't do + * anything useful, but it could. + */ +void +do_other_work() +{ + global_counter++; +} + + + + +
diff --git a/mozilla/directory/docs/ldapcsdk/figures/hierovrw.eps b/mozilla/directory/docs/ldapcsdk/figures/hierovrw.eps new file mode 100644 index 0000000000000000000000000000000000000000..01fe4cba0b412dc922616841def44047ef44333d GIT binary patch literal 378039 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 +Copyright 2000-2007 Sun Microsystems, Inc., 4150 Network Circle, +Santa Clara, California 95054, U.S.A. All rights reserved. Portions +copyright 1999 Netscape Communications Corporations. All rights +reserved. +Sun Microsystems, Inc. has intellectual property rights relating +to technology embodied in the product that is described in this +document. In particular, and without limitation, these intellectual +property rights may include one or more U.S. patents or pending patent +applications in the U.S. and in other countries. +U.S. Government Rights - Commercial software. Government users +are subject to the Sun Microsystems, Inc. standard license agreement +and applicable provisions of the FAR and its supplements. +This distribution may include materials developed by third +parties. +Parts of the product may be derived from Berkeley BSD systems, +licensed from the University of California. UNIX is a registered +trademark in the U.S. and in other countries, exclusively licensed +through X/Open Company, Ltd. +Sun, Sun Microsystems, the Sun logo, Java, Solaris, JavaBeans, +JavaScript and the SunTone Certified logo are trademarks or registered +trademarks of Sun Microsystems, Inc. in the U.S. and other +countries. +All SPARC trademarks are used under license and are trademarks +or registered trademarks of SPARC International, Inc. in the U.S. and +other countries. Products bearing SPARC trademarks are based upon +architecture developed by Sun Microsystems, Inc. +Mozilla, Netscape, and Netscape Navigator are trademarks or +registered trademarks of Netscape Communications Corporation in the +United States and other countries. +Products covered by and information contained in this service +manual are controlled by U.S. Export Control laws and may be subject +to the export or import laws in other countries. Nuclear, missile, +chemical biological weapons or nuclear maritime end uses or end users, +whether direct or indirect, are strictly prohibited. Export or +reexport to countries subject to U.S. embargo or to entities +identified on U.S. export exclusion lists, including, but not limited +to, the denied persons and specially designated nationals lists is +strictly prohibited. +DOCUMENTATION IS PROVIDED “AS IS” AND ALL EXPRESS OR +IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE +OR NON-INFRINGEMENT, ARE DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH +DISCLAIMERS ARE HELD TO BE LEGALLY INVALID. +Copyright 2000-2007 Sun Microsystems, Inc., 4150 Network Circle, +Santa Clara, California 95054, Etats-Unis. Tous droits +réservés. Certaines parties copyright 1999 Netscape +Communications Corporations. Tous droits réservés. +Sun Microsystems, Inc. détient les droits de +propriété intellectuelle relatifs à la +technologie incorporée dans le produit qui est décrit +dans ce document. En particulier, et ce sans limitation, ces droits de +propriété intellectuelle peuvent inclure un ou plusieurs +brevets américains ou des applications de brevet en attente aux +Etats-Unis et dans d'autres pays. +Cette distribution peut comprendre des composants +développés par des tierces parties. +Des parties de ce produit pourront être +dérivées des systèmes Berkeley BSD +licenciés par l'Université de Californie. UNIX est une +marque déposée aux Etats-Unis et dans d'autres pays et +licenciée exclusivement par X/Open Company, Ltd. +Sun, Sun Microsystems, le logo Sun, Java, Solaris, JavaBeans, +JavaScript et le logo SunTone Certified sont des marques de fabrique +ou des marques déposées de Sun Microsystems, Inc. aux +Etats-Unis et dans d'autres pays. +Toutes les marques SPARC sont utilisées sous licence et +sont des marques de fabrique ou des marques déposées de +SPARC International, Inc. aux Etats-Unis et dans d'autres pays. Les +produits portant les marques SPARC sont basés sur une +architecture développée par Sun Microsystems, +Inc. +Mozilla, Netscape, et Netscape Navigator sont des marques de +Netscape Communications Corporation aux Etats-Unis et dans d'autres +pays. +Les produits qui font l'objet de ce manuel d'entretien et les +informations qu'il contient sont regis par la legislation americaine +en matiere de controle des exportations et peuvent etre soumis au +droit d'autres pays dans le domaine des exportations et +importations. Les utilisations finales, ou utilisateurs finaux, pour +des armes nucleaires, des missiles, des armes biologiques et chimiques +ou du nucleaire maritime, directement ou indirectement, sont +strictement interdites. Les exportations ou reexportations vers des +pays sous embargo des Etats-Unis, ou vers des entites figurant sur les +listes d'exclusion d'exportation americaines, y compris, mais de +maniere non exclusive, la liste de personnes qui font objet d'un ordre +de ne pas participer, d'une facon directe ou indirecte, aux +exportations des produits ou des services qui sont regi par la +legislation americaine en matiere de controle des exportations et la +liste de ressortissants specifiquement designes, sont rigoureusement +interdites. +LA DOCUMENTATION EST FOURNIE “EN L'ETAT” ET TOUTES +AUTRES CONDITIONS, DECLARATIONS ET GARANTIES EXPRESSES OU TACITES SONT +FORMELLEMENT EXCLUES, DANS LA MESURE AUTORISEE PAR LA LOI APPLICABLE, +Y COMPRIS NOTAMMENT TOUTE GARANTIE IMPLICITE RELATIVE A LA QUALITE +MARCHANDE, A L'APTITUDE A UNE UTILISATION PARTICULIERE OU A L'ABSENCE +DE CONTREFACON. diff --git a/mozilla/directory/docs/ldapcsdk/license.txt b/mozilla/directory/docs/ldapcsdk/license.txt new file mode 100644 index 00000000000..92f23fd1acf --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/license.txt @@ -0,0 +1,226 @@ +Attribution-ShareAlike 2.5 +CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL +SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN ATTORNEY-CLIENT +RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. +CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE INFORMATION PROVIDED, AND +DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM ITS USE. + +License + +THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS +PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR +OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS +LICENSE OR COPYRIGHT LAW IS PROHIBITED. + +BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE +BOUND BY THE TERMS OF THIS LICENSE. THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED +HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. + +1. Definitions + + 1. "Collective Work" means a work, such as a periodical issue, anthology or +encyclopedia, in which the Work in its entirety in unmodified form, along with a +number of other contributions, constituting separate and independent works in +themselves, are assembled into a collective whole. A work that constitutes a +Collective Work will not be considered a Derivative Work (as defined below) for +the purposes of this License. + 2. "Derivative Work" means a work based upon the Work or upon the Work and +other pre-existing works, such as a translation, musical arrangement, +dramatization, fictionalization, motion picture version, sound recording, art +reproduction, abridgment, condensation, or any other form in which the Work may +be recast, transformed, or adapted, except that a work that constitutes a +Collective Work will not be considered a Derivative Work for the purpose of this +License. For the avoidance of doubt, where the Work is a musical composition or +sound recording, the synchronization of the Work in timed-relation with a moving +image ("synching") will be considered a Derivative Work for the purpose of this +License. + 3. "Licensor" means the individual or entity that offers the Work under the +terms of this License. + 4. "Original Author" means the individual or entity who created the Work. + 5. "Work" means the copyrightable work of authorship offered under the terms +of this License. + 6. "You" means an individual or entity exercising rights under this License +who has not previously violated the terms of this License with respect to the +Work, or who has received express permission from the Licensor to exercise +rights under this License despite a previous violation. + 7. "License Elements" means the following high-level license attributes as +selected by Licensor and indicated in the title of this License: Attribution, +ShareAlike. + +2. Fair Use Rights. Nothing in this license is intended to reduce, limit, or +restrict any rights arising from fair use, first sale or other limitations on +the exclusive rights of the copyright owner under copyright law or other +applicable laws. + +3. License Grant. Subject to the terms and conditions of this License, Licensor +hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the +duration of the applicable copyright) license to exercise the rights in the Work +as stated below: + + 1. to reproduce the Work, to incorporate the Work into one or more Collective +Works, and to reproduce the Work as incorporated in the Collective Works; + 2. to create and reproduce Derivative Works; + 3. to distribute copies or phonorecords of, display publicly, perform +publicly, and perform publicly by means of a digital audio transmission the Work +including as incorporated in Collective Works; + 4. to distribute copies or phonorecords of, display publicly, perform +publicly, and perform publicly by means of a digital audio transmission +Derivative Works. + 5. + + For the avoidance of doubt, where the work is a musical composition: + 1. Performance Royalties Under Blanket Licenses. Licensor waives the +exclusive right to collect, whether individually or via a performance rights +society (e.g. ASCAP, BMI, SESAC), royalties for the public performance or public +digital performance (e.g. webcast) of the Work. + 2. Mechanical Rights and Statutory Royalties. Licensor waives the +exclusive right to collect, whether individually or via a music rights society +or designated agent (e.g. Harry Fox Agency), royalties for any phonorecord You +create from the Work ("cover version") and distribute, subject to the compulsory +license created by 17 USC Section 115 of the US Copyright Act (or the equivalent +in other jurisdictions). + 6. Webcasting Rights and Statutory Royalties. For the avoidance of doubt, +where the Work is a sound recording, Licensor waives the exclusive right to +collect, whether individually or via a performance-rights society (e.g. +SoundExchange), royalties for the public digital performance (e.g. webcast) of +the Work, subject to the compulsory license created by 17 USC Section 114 of the +US Copyright Act (or the equivalent in other jurisdictions). + +The above rights may be exercised in all media and formats whether now known or +hereafter devised. The above rights include the right to make such modifications +as are technically necessary to exercise the rights in other media and formats. +All rights not expressly granted by Licensor are hereby reserved. + +4. Restrictions.The license granted in Section 3 above is expressly made subject +to and limited by the following restrictions: + + 1. You may distribute, publicly display, publicly perform, or publicly +digitally perform the Work only under the terms of this License, and You must +include a copy of, or the Uniform Resource Identifier for, this License with +every copy or phonorecord of the Work You distribute, publicly display, publicly +perform, or publicly digitally perform. You may not offer or impose any terms on +the Work that alter or restrict the terms of this License or the recipients' +exercise of the rights granted hereunder. You may not sublicense the Work. You +must keep intact all notices that refer to this License and to the disclaimer of +warranties. You may not distribute, publicly display, publicly perform, or +publicly digitally perform the Work with any technological measures that control +access or use of the Work in a manner inconsistent with the terms of this +License Agreement. The above applies to the Work as incorporated in a Collective +Work, but this does not require the Collective Work apart from the Work itself +to be made subject to the terms of this License. If You create a Collective +Work, upon notice from any Licensor You must, to the extent practicable, remove +from the Collective Work any credit as required by clause 4(c), as requested. If +You create a Derivative Work, upon notice from any Licensor You must, to the +extent practicable, remove from the Derivative Work any credit as required by +clause 4(c), as requested. + 2. You may distribute, publicly display, publicly perform, or publicly +digitally perform a Derivative Work only under the terms of this License, a +later version of this License with the same License Elements as this License, or +a Creative Commons iCommons license that contains the same License Elements as +this License (e.g. Attribution-ShareAlike 2.5 Japan). You must include a copy +of, or the Uniform Resource Identifier for, this License or other license +specified in the previous sentence with every copy or phonorecord of each +Derivative Work You distribute, publicly display, publicly perform, or publicly +digitally perform. You may not offer or impose any terms on the Derivative Works +that alter or restrict the terms of this License or the recipients' exercise of +the rights granted hereunder, and You must keep intact all notices that refer to +this License and to the disclaimer of warranties. You may not distribute, +publicly display, publicly perform, or publicly digitally perform the Derivative +Work with any technological measures that control access or use of the Work in a +manner inconsistent with the terms of this License Agreement. The above applies +to the Derivative Work as incorporated in a Collective Work, but this does not +require the Collective Work apart from the Derivative Work itself to be made +subject to the terms of this License. + 3. If you distribute, publicly display, publicly perform, or publicly +digitally perform the Work or any Derivative Works or Collective Works, You must +keep intact all copyright notices for the Work and provide, reasonable to the +medium or means You are utilizing: (i) the name of the Original Author (or +pseudonym, if applicable) if supplied, and/or (ii) if the Original Author and/or +Licensor designate another party or parties (e.g. a sponsor institute, +publishing entity, journal) for attribution in Licensor's copyright notice, +terms of service or by other reasonable means, the name of such party or +parties; the title of the Work if supplied; to the extent reasonably +practicable, the Uniform Resource Identifier, if any, that Licensor specifies to +be associated with the Work, unless such URI does not refer to the copyright +notice or licensing information for the Work; and in the case of a Derivative +Work, a credit identifying the use of the Work in the Derivative Work (e.g., +"French translation of the Work by Original Author," or "Screenplay based on +original Work by Original Author"). Such credit may be implemented in any +reasonable manner; provided, however, that in the case of a Derivative Work or +Collective Work, at a minimum such credit will appear where any other comparable +authorship credit appears and in a manner at least as prominent as such other +comparable authorship credit. + +5. Representations, Warranties and Disclaimer + +UNLESS OTHERWISE AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK +AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE +MATERIALS, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT +LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR +PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, +OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME +JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH +EXCLUSION MAY NOT APPLY TO YOU. + +6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN +NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, +INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS +LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. Termination + + 1. This License and the rights granted hereunder will terminate automatically +upon any breach by You of the terms of this License. Individuals or entities who +have received Derivative Works or Collective Works from You under this License, +however, will not have their licenses terminated provided such individuals or +entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, +and 8 will survive any termination of this License. + 2. Subject to the above terms and conditions, the license granted here is +perpetual (for the duration of the applicable copyright in the Work). +Notwithstanding the above, Licensor reserves the right to release the Work under +different license terms or to stop distributing the Work at any time; provided, +however that any such election will not serve to withdraw this License (or any +other license that has been, or is required to be, granted under the terms of +this License), and this License will continue in full force and effect unless +terminated as stated above. + +8. Miscellaneous + + 1. Each time You distribute or publicly digitally perform the Work or a +Collective Work, the Licensor offers to the recipient a license to the Work on +the same terms and conditions as the license granted to You under this License. + 2. Each time You distribute or publicly digitally perform a Derivative Work, +Licensor offers to the recipient a license to the original Work on the same +terms and conditions as the license granted to You under this License. + 3. If any provision of this License is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of the +remainder of the terms of this License, and without further action by the +parties to this agreement, such provision shall be reformed to the minimum +extent necessary to make such provision valid and enforceable. + 4. No term or provision of this License shall be deemed waived and no breach +consented to unless such waiver or consent shall be in writing and signed by the +party to be charged with such waiver or consent. + 5. This License constitutes the entire agreement between the parties with +respect to the Work licensed here. There are no understandings, agreements or +representations with respect to the Work not specified here. Licensor shall not +be bound by any additional provisions that may appear in any communication from +You. This License may not be modified without the mutual written agreement of +the Licensor and You. + +Creative Commons is not a party to this License, and makes no warranty +whatsoever in connection with the Work. Creative Commons will not be liable to +You or any party on any legal theory for any damages whatsoever, including +without limitation any general, special, incidental or consequential damages +arising in connection to this license. Notwithstanding the foregoing two (2) +sentences, if Creative Commons has expressly identified itself as the Licensor +hereunder, it shall have all rights and obligations of Licensor. + +Except for the limited purpose of indicating to the public that the Work is +licensed under the CCPL, neither party will use the trademark "Creative Commons" +or any related trademark or logo of Creative Commons without the prior written +consent of Creative Commons. Any permitted use will be in compliance with +Creative Commons' then-current trademark usage guidelines, as may be published +on its website or otherwise made available upon request from time to time. + +Creative Commons may be contacted at http://creativecommons.org/. diff --git a/mozilla/directory/docs/ldapcsdk/preface.sgm b/mozilla/directory/docs/ldapcsdk/preface.sgm new file mode 100644 index 00000000000..e9e09ad0af6 --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/preface.sgm @@ -0,0 +1,375 @@ + +Preface +&abstract; + +Who Should Use This Book +This guide is intended for developers creating directory client applications. + + +Before using this guide, you must be familiar with the following: +&cnDirectoryServer; functionality +Developing programs in the C programming +language +Specifications for LDAP and related protocols, such as DSML +v2 +Internet and World Wide Web technologies + + +Before You Read This Book +Before developing directory client applications, install &DirectorySDKForJava;. + + + +Additional Recommended Reading + +Directory client application developers might benefit from reading the +following books: +LDAP Programming with Java by Weltman +and Dabhura (ISBN 0-201-65758-96) +LDAP Programming, Management and Integration by +Donley (ISBN 1930110405) +LDAP: Programming Directory-Enabled Applications +with Lightweight Directory Access Protocol by Howes and Smith +(ISBN 1-57870-000-00) +Understanding and Deploying LDAP Directory Services by +Howes, et al. (ISBN 1-57870-070-10) + + +In addition, keep bookmarks to the following IETF documents: + +RFC 2251, Lightweight Directory Access Protocol (v3) + + +RFC 2252, Lightweight Directory Access Protocol (v3): Attribute +Syntax Definitions + +RFC 2253, Lightweight Directory Access Protocol (v3): UTF-8 +String Representation of Distinguished Names + +RFC 2254, The String Representation of LDAP Search Filters + + +RFC 2255, The LDAP URL Format + +RFC 2256, A Summary of the X.500(96) User Schema for use +with LDAPv3 + +RFC 2829, Authentication Methods for LDAP + + +RFC 2830, Lightweight Directory Access Protocol (v3): Extension +for Transport Layer Security + +RFC 2849, The LDAP Data Interchange Format (LDIF) - Technical +Specification + +RFC 3377, Lightweight Directory Access Protocol (v3): Technical +Specification + + +How This Book Is Organized + +This guide includes the following chapters. +Chapter 1, Understanding +LDAP describes LDAP and directory concepts. +Chapter 2, Choosing +a Client SDK covers what to consider when choosing a software development +kit for building directory client applications. +Chapter 3, +Best Practices for Writing Client Applications reviews what and what +not to do when building directory client applications. +Chapter 4, About Directory +SDK for C describes what &DirectorySDKForC; offers you as a directory +client developer. +Chapter 5, Getting +Started With Directory SDK for C gets you started using &DirectorySDKForC;. + +Chapter 6, What's New +In Directory SDK for C presents new features, and changes from previous +versions of &DirectorySDKForC;. +Chapter 7, Writing an +LDAP Client With Directory SDK for C covers the basics of writing +a directory client application. +Chapter 8, Using the LDAP +C API shows how to write an application with &DirectorySDKForC;. + +Chapter 9, Searching +the Directory With Directory SDK for C shows how to write client application +code for searching a directory. +Chapter 10, Using Filter +Configuration Files With Directory SDK for C shows how to write code +to search a directory using filter configuration files. +Chapter 11, Adding, Updating, +and Deleting Entries With Directory SDK for C shows how to write client +application code for changing directory entries. +Chapter 12, Comparing +Attribute Values With Directory SDK for C shows how to compare attribute +values in a directory with known values. +Chapter 13, LDAP URLs With +Directory SDK for C shows how to handle LDAP URLs. +Chapter 14, Getting +Server Information With Directory SDK for C shows how to retrieve +information about the directory and directory service. +Chapter 15, SSL Connections +With Directory SDK for C shows how to write client application code +that connects to the directory over SSL. +Chapter 16, LDAP Controls +With Directory SDK for C shows how to handle supported LDAP controls. + +Chapter 17, SASL Authentication +With Directory SDK for C shows how to connect to the directory by +using SASL. +Chapter 18, Extended Operations +With Directory SDK for C shows how to write client application code +for handling LDAP v3 extended operations. +Chapter 19, Writing +Multithreaded Clients With Directory SDK for C shows how to write +multithreaded client application code. +Chapter 20, Directory SDK for C Data Type Reference covers &DirectorySDKForC; data types + +Chapter 21, Directory SDK for C Function Reference covers &DirectorySDKForC; functions + +Chapter 22, Directory SDK for C Result Codes covers &DirectorySDKForC; function result codes + +Appendix A, Creative Commons Attribution-ShareAlike 2.5 provides the full text of the license governing this guide + + + +Related Reading + +SLAMD Distributed Load Generation Engine +The SLAMD Distributed Load Generation Engine (SLAMD) is a +Java application that is designed to stress test and analyze the +performance of network-based applications. It was originally developed by +Sun Microsystems, Inc. to benchmark and analyze the performance of LDAP directory +servers. SLAMD is available as an open source application under the Sun Public +License, an OSI-approved open source license. To obtain information about +SLAMD, go to . SLAMD +is also available as a java.net project. See . + +Java Naming and Directory Interface +Java Naming and Directory Interface (JNDI) technology supports +accessing the Directory Server using LDAP and DSML v2 from Java applications. +For information about JNDI, see . The JNDI Tutorial contains detailed +descriptions and examples of how to use JNDI. This tutorial is at . + +Typographic Conventions +The following table describes the typographic changes that are used +in this book. +Typographic Conventions + + + + +Typeface + +Meaning + +Example + + + + + +AaBbCc123 + +The names of commands, files, and directories, and onscreen computer +output + +Edit your .login file. +Use ls to list all files. +machine_name% you have mail. + + + + +AaBbCc123 + +What you type, contrasted with onscreen computer output + +machine_name% su +Password: + + + +AaBbCc123 + +A placeholder to be replaced with a real name or value + +The command to remove a file is rm filename +. + + + +AaBbCc123 + +Book titles, new terms, and terms to be emphasized (note that some emphasized +items appear bold online) + +Read Chapter 6 in the User's Guide. +A cache is a copy that is stored locally. +Do not save the file. + + + +
+
+Shell Prompts in Command Examples +The following table shows default system prompts and superuser prompts. +Shell Prompts + + + + +Shell + +Prompt + + + + + +C shell on UNIX and Linux systems + +machine_name% + + + +C shell superuser on UNIX and Linux systems + +machine_name# + + + +Bourne shell and Korn shell on UNIX and Linux systems + +$ + + + +Bourne shell and Korn shell superuser on UNIX and Linux systems + + +# + + + +Microsoft Windows command line + +C:\ + + + +
+
+Symbol Conventions +The following table explains symbols that might be used in this book. +Symbol Conventions + + + + +Symbol + +Description + +Example + +Meaning + + + + + +[ ] + +Contains optional arguments and command options. + +ls [-l] + +The -l option is not required. + + + +{ | } + +Contains a set of choices for a required command option. + +-d {y|n} + +The -d option requires that you use either the +y argument or the n argument. + + + +${ } + +Indicates a variable reference. + +${com.sun.javaRoot} + +References the value of the com.sun.javaRoot variable. + + + + +- + +Joins simultaneous multiple keystrokes. + +Control-A + +Press the Control key while you press the A key. + + + ++ + +Joins consecutive multiple keystrokes. + +Ctrl+A+N + +Press the Control key, release it, and then press the subsequent keys. + + + + +→ + +Indicates menu item selection in a graphical user interface. + + +File → New → Templates + +From the File menu, choose New. From the New submenu, choose Templates. + + + + +
+
+
+ diff --git a/mozilla/directory/docs/ldapcsdk/understanding-ldap.sgm b/mozilla/directory/docs/ldapcsdk/understanding-ldap.sgm new file mode 100644 index 00000000000..c438e95e1bc --- /dev/null +++ b/mozilla/directory/docs/ldapcsdk/understanding-ldap.sgm @@ -0,0 +1,274 @@ + +Understanding LDAP + +LDAP + +Lightweight Directory Access Protocol +LDAP +Lightweight Directory Access Protocol (LDAP) +is the Internet directory protocol. Developed at the University of Michigan +at Ann Arbor in conjunction with the Internet Engineering Task Force, LDAP +is a protocol for accessing and managing directory services. + +This chapter explains the LDAP protocol, and the concepts behind LDAP. +This chapter covers the following topics: +How Directory Services Work + +How LDAP Servers +Organize Directories +How LDAP +Clients and Servers Work +Understanding LDAP +v3 + + +How Directory Services Work + +directory +definition of + +entries +definition of + +attributes +definition of + +A directory consists of entries that +contain descriptive information. For example, a directory might contain entries +that describe people or network resources, such as printers or fax machines. +The descriptive information is stored in the attributes of +the entry. Each attribute describes a specific type of information. For example, +attributes that describe a person might include her name, also referred to +as her common name (CN), telephone number, and email address. + +entries +example of + +attributes +example of +The entry for Barbara Jensen might have the +following attributes: +cn: Barbara Jensen +mail: babs@example.com +telephoneNumber: 555-1212 +roomNumber: 3995 +An attribute can have more than one value. For example, a person might +have two common names, both a formal name and also a nickname: +cn: Barbara Jensen +cn: Babs Jensen +mail: babs@example.com +telephoneNumber: 555-1212 +roomNumber: 3995 +Attributes can also contain binary data. For example, a person's attributes +might include her photo in JPEG format, a recording of her voice as an audio +file, or her SSL certificate. + +directory service +definition of +A directory service is a distributed database +application for managing the entries and attributes in a directory. A directory +service also makes the entries and attributes available to users and other +applications. +&cnDirectoryServer; is an example of a directory service. For example, +a user might use the directory service to look up someone's telephone number. +Another application might use the directory service to retrieve a list of +email addresses. + +LDAP servers + +LDAP clients +LDAP is a protocol that defines a directory service and access +to that service. LDAP is based on a client-server model. LDAP servers provide +the directory service. LDAP clients use the directory service to access entries +and attributes. + +LDAP servers +example of + +LDAP clients +example of +&cnDirectoryServer; is an example of an LDAP server that manages +and provides information about users and organizational structures. Examples +of LDAP clients include Identity Manager, Access Manager, Solaris naming +services, Messaging Server, Portal Server, NameFinder, and the Mozilla mail +client. Such clients use &cnDirectoryServer; to find, update, and add information +about users. +How LDAP Servers Organize Directories + +LDAP +organization of data + +entries +organization in LDAP + +LDAP servers +how data is organized + +Because LDAP is intended to be a global directory service, data is organized +hierarchically, starting at a root and branching down into individual entries. +At the top level of the hierarchy, entries represent larger organizations. +Under larger organizations in the hierarchy, you might find entries for smaller +organizations. The hierarchy might end with entries for individual people, +or resources, as shown in the following figure. +
Hierarchy of Entries in a Directory + + +Simple directory information tree with two organizational +unit entries and two user entries + +
+ +relative distinguished names (RDNs) +definition of + +RDNs +relative distinguished names (RDNs) +distinguished names (DNs) +definition of + +CNs +common names (CNs) +DNs +distinguished names (DNs) +common names (CNs) +Each entry is uniquely identified by a distinguished +name (DN). A DN includes a relative distinguished name (RDN), +that uniquely identifies the entry at that hierarchical level. For example, +bjensen and kjensen are different user IDs that +identify different entries at the same level. Following the RDN is a path +of names that trace the entry back to the root of the tree, such as ou=People,dc=example,dc=com +. DC is short for domain component. The full +DN for this example would be uid=bjensen,ou=People,dc=example,dc=com. +Here, uid is the user ID of the entry. ou is +short for organizational unit. + +LDAP servers +how data is distributed +The data stored in a directory can be distributed among several +LDAP servers. For example, one LDAP server at Example.com might +contain entries representing North American organizational units and employees, +while another LDAP server might contain entries representing European organizational +units and employees. + +LDAP servers +how referrals work + +referrals +Some LDAP servers are set up to refer requests to other LDAP servers. +For example, if the LDAP server at Example.com receives +a request for information about an employee in a Pacific Rim branch, that +server can refer the request to the LDAP server at the Pacific Rim branch. +In this way, LDAP servers can appear to be a single source of directory information. +Even if an LDAP server does not contain the information you request, the server +can refer you to another server that does contain the information. +
+How LDAP Clients and Servers +Work + +LDAP servers +LDAP clients and + +LDAP clients +LDAP servers and + +LDAP clients +operations performed by + +In the LDAP client-server model, LDAP servers such as &cnDirectoryServer; +make information about people, organizations, and resources accessible to +LDAP clients. LDAP defines operations that clients use to search and update +the directory. + +An LDAP client can perform these operations, among others: +Search for and retrieve entries from the directory + +Add new entries to the directory +Update entries in the directory +Delete entries from the directory +Rename entries in the directory + +For example, to update an entry, an LDAP client submits the distinguished +name of the entry with updated attribute information to the LDAP server. The +LDAP server uses the distinguished name to find the entry. The server then +performs a modify operation to update the entry in the directory. + +LDAP servers +connecting with LDAP clients + +LDAP clients +connecting with LDAP servers +To perform any of these LDAP operations, an LDAP client needs +to establish a connection with an LDAP server. The LDAP protocol specifies +the use of TCP/IP port number 389, although servers can run on other ports. + +LDAP servers +authentication + +LDAP clients +authentication +The LDAP protocol also defines a simple method for authentication. +LDAP servers can be set up to restrict permissions to the directory. Before +an LDAP client can perform an operation on an LDAP server, the client must +authenticate to the server. Clients typically authenticate by supplying a +distinguished name and password. If the user identified by the distinguished +name does not have permission to perform the operation, the server does not +execute the operation. +Understanding LDAP v3 + +LDAP +version 3 + +RFC +4511 specifies LDAP version 3. Use this version of the protocol when +writing new client applications. +Many LDAP servers continue to support LDAP version 2 for use with legacy +clients. This version of the protocol is specified in RFC 1777. + +LDAP v3 includes new features not present in version 2: +Clients and servers can specify controls that +extend the functionality of an LDAP operation. +Clients can request that the server perform extended +operations, operations not included in the list of standard LDAP +operations. +Clients can use Simple Authentication and Security +Layer (SASL) mechanisms to authenticate to the directory. SASL +is specified in +RFC 4422. +Servers, known as Directory System Agents (DSAs), +have DSA-specific entries (DSEs). DSEs provide information +about the versions of the LDAP protocol that the server supports. DSEs also +provide a list of the controls, extended operations, and SASL mechanisms supported +by the server. Finally, DSEs specify the naming contexts of the server. Naming +contexts are portions of the directory information tree managed by the server. + +Servers make their schemas, which define +the object classes, attributes, syntaxes, and matching rules enforced by the +directory, available to clients through the root DSE. + +UTF-8 +support of +Both client and server applications can support data in UTF-8. +UTF-8 is a transformation format of the Universal Character Set +standard. UTF-8 is specified in RFC 3269. With UTF-8, clients can request and receive +data that is tagged with language information. + + +
diff --git a/mozilla/directory/docs/ldapjdk/00-Programmers-Guide.book b/mozilla/directory/docs/ldapjdk/00-Programmers-Guide.book new file mode 100644 index 00000000000..993bcde7019 --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/00-Programmers-Guide.book @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]> + +Programmer's Guide for LDAP Java SDK + +MarkCraig + +June 2007 + +Sun Microsystems, Inc. +
+4150 Network Circle +Santa ClaraCA95054 +U.S.A. +
+2000-2007Sun Microsystems, Inc. All Rights Reserved. +License - +The contents of this document are subject to the terms of +the Creative Commons Attribution-ShareAlike 2.5 license or any later version (the +"License"). You may not use this document except in compliance with +the License. +See the License for the specific language governing +permissions and limitations under the License. The full text of the +License is provided at the end of this +document.&legal; + +&abstract; + +
&preface; +&understanding-ldap; +&choose-api; +&best-practices; +&jdk-quickstart; +&jdk-writing-client; +&jdk-common-classes; +&jdk-searching; +&jdk-filter-conf; +&jdk-adding; +&jdk-comparing; +&jdk-ldap-urls; +&jdk-server-info; +&jdk-ssl; +&jdk-controls; +&jdk-sasl; +&jdk-extended-ops; +&jdk-asynchronous; + +Creative Commons Attribution-ShareAlike 2.5 +The contents of this document are subject to the terms of the +Creative Commons Attribution-ShareAlike 2.5 license (the +"License"). You may not use this document except in compliance with +the License. +See the License for the specific language governing permissions +and limitations under the License. The full text of the License is as +follows. +&license; + +Index + +
diff --git a/mozilla/directory/docs/ldapjdk/abstract.sgm b/mozilla/directory/docs/ldapjdk/abstract.sgm new file mode 100644 index 00000000000..5682faae336 --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/abstract.sgm @@ -0,0 +1,20 @@ + +This &BookTitle; shows you how to +create LDAP client applications in the Java language to connect to LDAP servers. +This guide also shows you how to perform standard LDAP operations. diff --git a/mozilla/directory/docs/ldapjdk/best-practices.sgm b/mozilla/directory/docs/ldapjdk/best-practices.sgm new file mode 100644 index 00000000000..8f96271f1d6 --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/best-practices.sgm @@ -0,0 +1,378 @@ + +Best Practices for +Writing Client Applications + + +This chapter includes best practices for developing client applications +and cover the following topics: +Creating Your Application + +Troubleshooting Problems + + + +Creating Your Application + +This section identifies practices to observe when creating directory +client applications. +Specify LDAP v3 + +Authenticate Correctly + +Limit Connection Overhead + +Handle Potential +Inactivity Timeouts +Retrieve Entries Intelligently + +Write Simple, Conforming LDAP +Filters +Performing Specific Modifications + +Trust Result Codes + +Limit Dealings With Groups +and Roles +Read the DSE + +Use Resource-Intensive Features Sparingly +Avoid Hard Coding Certain Information + +Define Schemas Only When Necessary + +Handle Referrals + +Treat a Directory as a Directory + + +Specify LDAP v3 + +Many client libraries default to LDAP v2, but you can elect to use LDAP +v3. To benefit from LDAP v3 features, you can set up the connection, and then +authenticate explicitly using LDAP v3. +With JNDI, you could use LDAP v3 as shown here. +import java.util.Hashtable; +import javax.naming.ldap.InitialLdapContext; + +Hashtable env = new Hashtable(); +env.put("java.naming.ldap.version", "3"); +InitialLdapContext ctx = new InitialLdapContext(env, null); + +With &DirectorySDKForC;, you could use LDAP v3 as shown +here. +#include "ldap.h" + +int version = LDAP_VERSION3; +ldap_set_option( NULL, LDAP_OPT_PROTOCOL_VERSION, &version ); +&DirectorySDKForC; uses LDAP v3 by default. +With &DirectorySDKForJava;, you could use LDAP v3 as shown +here. +import netscape.ldap.LDAPConnection; + +LDAPConnection ld = new LDAPConnection(); +ld.setOption(LDAPv3.PROTOCOL_VERSION, new Integer(3)); + + + + + +Authenticate Correctly +Your SDK uses terminology that is slightly different from LDAP v3. In +LDAP v3, you connect, then you bind and perform LDAP operations, then you +unbind and disconnect. The bind is the authentication operation in LDAP. Your +application can hold onto a connection but change the authentication credentials +by using the bind operation again. +Some directories do not allow anonymous access, even for reads. When +you build your application, keep the option that allows users to authenticate +to the directory. Furthermore, the information sent across the network can +be sensitive. You can protect sensitive data by allowing the application to +secure the connection by using Secure Sockets Layer (SSL) or Start Transport +Layer Security (TLS). +If your application needs to authenticate, obtain a regular account +to authenticate with the directory, rather than using the directory superuser +account such as cn=Directory Manager. When you authenticate +as directory superuser, you often bypass normal access control mechanisms. +Bypassing normal access control renders auditing directory access more difficult. + +When authenticating, have your application use SSL or SASL DIGEST MD5 +to avoid sending passwords over the network in clear text. Furthermore, when +using password-based authentication, have your application check password +policy controls, especially to determine when a password must be renewed. + +Limit Connection Overhead +A new connection requires system resources. The LDAP model allows you +to reuse connections by binding again with a different identity on the same +connection. Thus, you can avoid the costs of new connections, particularly +negotiated connections such as connections that use SSL, by reusing connections. +Your application can use a pool of connections, rebinding when necessary. +Your application can alternatively use the proxy authorization control to +remain authenticated as the application but perform operations on behalf of +a particular user. +When establishing a connection, your application can provide alternate +server host names and port numbers to facilitate failover that is transparent +to the application. You can also set time limits for LDAP operations to avoid +getting blocked. +When finished with a connection, your application should perform an +unbind. +Handle Potential Inactivity Timeouts +Most network equipment can use timeouts to drop stale connections, ensuring +the equipment keeps a maximum number of connections that are available. +If your application pools connections or opens connections for persistent +search, than guard against timeouts that drop those connections. Use the connections +occasionally to reset inactivity timers present in the network. +Alternatively, if you have control over the connection, consider disabling +inactivity time outs for your applications that need to keep persistent connections +open. Load balancers and proxy software often use inactivity timeouts. + +Retrieve Entries Intelligently +&cnDirectoryServer; typically responds quickly to requests for entries. +Yet, &cnDirectoryServer; can respond most quickly when your application asks +it to do only necessary work. If you need to read only a few attributes in +an entry, request each attribute explicitly. Avoid reading the entire entry, +then parsing the entire entry to obtain the required data. +Furthermore, when you do request attributes in an entry, retrieve all +the required attributes at once. Each new request involves a new operation +on the server. +If any of the attributes that you require are operational attributes, +you must request those attributes specifically. Such attributes are identifiable +in directory schema by their USAGE, which is directoryOperation + or dsaOperation. +When retrieving entries and attributes, recognize that you might not +have access to all the attributes that exist. +Write Simple, Conforming LDAP Filters + +LDAP filters +writing + +The best filters use attributes that are indexed according to the way +the attributes are indexed. For example, if employeeNumber is +indexed for equality, your filter should be an equality filter such as (employeeNumber=123456) +. Do not use a substring filter instead. +Avoid deeply nested complex filters when you can. When you must use +complex filters, place the most specific filters first to narrow the list +of candidate entries the directory must check. For best results, use not +, !, only with and, & +, for example (&(cn=Barbara)(!(sn=Jensen))). +When you use not with or in a filter, +the directory must construct a candidate list of everything except what your +filter specifies. +Performing Specific Modifications +Modifications are atomic on the entry to which the modifications apply. +When modifying multivalued attributes, delete and replace specific values. +Do not replace an entire list of multiple values to change only a few values. +Replacing specific values is particularly good practice when the changes must +be replicated across a set of servers. +Moreover, when you have large values to store in an attribute, store +a reference to the data instead of storing the data object. +Trust Result Codes + +result codes +trust + +&cnDirectoryServer; trades tight consistency across replica servers +for very high performance, availability, and scalability. By allowing +loose consistency of data across sets of replica servers, &cnDirectoryServer; instances +can respond very quickly to your application. Yet, data replication is not +instantaneous. A short but detectable delay can ensue after a server returns +success for a write operation, but before the effects are seen on other replicas. + +Therefore, when your application receives a result code from &cnDirectoryServer; to +indicate that an operation was successful, your application should trust the +result code. When application requests are balanced across replicas, reading +from another replica might result in errors due to a slight delay in replication. + +Limit Dealings With Groups and Roles + +groups +working with + +When you want to know whether an account belongs to a group or a role, +read only the necessary attribute values. Do not read the entire list of group +members. + +For dynamic groups, do the following: +Read the URL from the group definition. +Examine the host, DN, and scope of the URL. +Apply the filter part of the URL to the entry for the account. + + + +roles +working with +For roles, compare the DN of the role to the +nsRole attribute of the entry for the account, such as (nsrole=cn=management,ou=people,dc=example,dc=com) +. You can then retrieve all the values of the nsRole attribute +for the account. +Read the DSE + +DSE, root +reading + +The root DSE is the entry that is retrieved by ldapsearch -b +"" -s base "(objectclass=*)". The root DSE describes server capabilities. +The root DSE contains information about supported LDAP protocol versions, +naming contexts (suffixes), LDAP v3 controls, LDAP v3 extensions, and authentication +mechanisms. The root DSE can contain information about the server version. +Some directory administrators protect access to the root DSE. Yet, applications +might read the root DSE to confirm that the server in fact supports functionality +required by applications. +Use Resource-Intensive Features Sparingly +Directories offer powerful features that can nevertheless place a heavy +load on the server. Two such features are persistent search, and server-side +sorting. +Persistent search lets you start a search that does not stop when complete, +but instead allows you to receive updates when entries are modified. To provide +this feature, the server must handle your search when anything happens to +an entry in its scope. +Server-side sorting requires that the server sort the entries that are +returned during a search. Instead of returning entries as quickly as possible, +the server must therefore get the list to return, and sort the list. + +Avoid Hard Coding Certain Information +The container entry for a subtree might be not be identical on different +directories. Rather than hard code the container entry throughout your application, +locate the container entry. Then navigate beneath the container entry in the +tree. +Object classes and attribute types for the same information can also +differ from directory to directory. Use configuration files, properties files, +or other easily modifiable variables rather than hard coding object class +and attribute type identifiers into your application. +Be aware as well that object class and attribute type identifiers are +not case-sensitive in LDAP. Your application should therefore recognize +that inetOrgPerson and inetorgperson are +equivalent, as are isMemberOf and ismemberof. + +Define Schemas Only When Necessary + +schema +defining + +Schemas define the object classes and attribute types that are recognized +by the directory. If your application can use a standard schema, use the standard +schema. &cnDirectoryServer; contains schemas that define numerous standard +object classes, and attribute types. + +When you must define your own schema objects, follow these guidelines: +Extend existing object classes by using AUXILIARY classes. + +Create new attributes rather than redefining existing attributes. +Other applications might depend on existing attributes to keep +their existing semantics. +Obtain new object identifiers for the schema elements you +define, rather than reusing existing object identifiers. +Obtain new names for the schema elements you define, rather +than reusing existing names. +Update &cnDirectoryServer; schema over LDAP if you can. + + + +Handle Referrals + +referrals +following + +LDAP v3 allows directories that are unable to handle your request to +refer your application to other directories. Your application should follow +those referrals. +When following referrals, realize that authentication procedures might +not be exactly the same on different directories. Also, directories that refer +to each other could potentially cause a referral loop. With &DirectorySDKForC; and &DirectorySDKForJava;, +you can limit referral hops to prevent your application from being referred +endlessly from one directory to another directory. The JNDI interface enables +you to follow referrals automatically. +Treat a Directory as a Directory +A directory is typically a repository for identity data, and for information +that you expect to keep for awhile and read often. You might typically find +relational databases better adapted to hold transient data such as session +keys and presence information, or voluminous accumulated data such as application +logs. + +Troubleshooting Problems +This section covers basic troubleshooting approaches and techniques +to use when developing directory client applications. You can check result +codes, check server log files, and inspect network packets. +Check Result Codes + +troubleshooting +result codes + +When an LDAP request from your application fails on the server, the +server sends back a result code, and possibly an explanatory message. Your +application should check the result codes, and for explanatory messages. Common +failure result codes include the following, which are expressed as decimal +values. Others result codes are defined as well. + +1 +LDAP operations error. The server encountered an error while +processing your request. + + +32 +No such object. The entry is not present on the server. Also, +no referral is defined for the entry. + + +49 +Invalid credentials. Your application failed to authenticate +properly. + + +53 +LDAP unwilling to perform. The directory does not support +the request. Alternatively, the directory is not currently in a state in which +to complete your request. For example, the directory might be in read-only +mode when your application requests a modification. + + +65 +Object class violation. Your write request would cause an +entry to no longer conform to the schema defined for the directory. + + +68 +Already exists. Your application is requesting to add an entry +that has the same DN as an entry already present in the directory. + + + +RFC 4511 defines +LDAP error codes, as does Chapter 22, Directory +SDK for C Result Codes. +Check Server Log Files + +troubleshooting +log files + +&cnDirectoryServer; logs messages related to server operation in its +logs/errors file. If you have access to this file, you might find +useful troubleshooting information there. +When debugging your application against &cnDirectoryServer;, you can +adjust the log level, as well. See the server documentation for instructions. + +Inspect Network Packets + +troubleshooting +decoding packets + +Although LDAP is not a textual protocol, tools such as +snoop1M, +ethereal, and tcpdump can decode the packets, +sometimes providing you with important debugging information. + + diff --git a/mozilla/directory/docs/ldapjdk/choose-api.sgm b/mozilla/directory/docs/ldapjdk/choose-api.sgm new file mode 100644 index 00000000000..9db9908e1ee --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/choose-api.sgm @@ -0,0 +1,98 @@ + +Choosing a Client +SDK + +This chapter discusses software development kits to help you select +the appropriate directory SDK for your particular situation. + +This chapter covers the following topics: +Java Naming and Directory Interface + +Directory SDK for Java + +Directory SDK for C + +Operating System libldap Library +Support for Other Programming +Languages + + +Java Naming and Directory Interface + +Java Naming and Directory Interface + +JNDI +Java Naming and Directory Interface +Java Naming and Directory Interface (JNDI) technology supports directory +access through LDAP and DSML v2 from Java applications, +and is part of the Java platform. With JNDI, you can build powerful, portable, +directory-enabled applications that do not depend on classes outside the Java +platform. +JNDI provides an abstract model that lets you access not only directories, +but also naming services in general, including DNS, RMI, COS, and file systems. +For information about JNDI, see . The JNDI +Tutorial contains descriptions and examples of how to use JNDI. +The tutorial is at . +&DirectorySDKForC; +&DirectorySDKForC; lets you access LDAP directories from C and C++ +applications. &DirectorySDKForC; applications depend on &DirectorySDKForC; libraries, +which are available on a wide range of platforms. +&DirectorySDKForC; was the subject of Internet-Draft work but never +became a standard API. &DirectorySDKForC; closely follows LDAP v3, providing +support for core LDAP operations and for LDAP v3 extensions and widely used +controls. &DirectorySDKForC; offers a rich API to the C and C++ developer +familiar with the LDAP model. &cnDirectoryServer; relies on &DirectorySDKForC;. + +This document demonstrates how to use &DirectorySDKForC;. &DirectorySDKForC; code +is published in open source form as part of the Mozilla Directory SDK project. + +&DirectorySDKForJava; +&DirectorySDKForJava; lets you access LDAP directories from Java +applications, but it is not part of the Java platform. +Although not a standard API, &DirectorySDKForJava; closely follows +LDAP v3 idioms. &DirectorySDKForJava; provides a rich set of interfaces +to the Java developer familiar with the LDAP model. +This document demonstrates how to use &DirectorySDKForJava;. &DirectorySDKForJava; code +is published in open source form as part of the Mozilla Directory SDK project. + +Operating System <filename>libldap</filename> Library + + +libraries +libldap + +libldap + +The native LDAP library on Solaris systems provides +essentially the same API as &DirectorySDKForC;. Many &DirectorySDKForC; need +only be recompiled to work with libldap. +The LDAP library is sometimes not compatible with libldap on +many GNU/Linux distributions. Many GNU/Linux distributions provide OpenLDAP +support by default. +Support for Other Programming Languages +Support for directory access is available in a number of contexts where +you do not choose to use the C or Java languages. +For example, Perl has the PerLDAP module and the Net::LDAP collection +of modules. Python has the python-ldap package. PHP can +be compiled with LDAP support. Ruby has the Ruby/LDAP extension module. In +many cases, you can choose the language that fits the task and find that LDAP +support is available. + diff --git a/mozilla/directory/docs/ldapjdk/figures/entries.eps b/mozilla/directory/docs/ldapjdk/figures/entries.eps new file mode 100644 index 0000000000000000000000000000000000000000..4081f95c9684f9a094510c4e34ed804e88fb08cc GIT binary patch literal 425571 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
Z>B{_}TGIjwq{qdqDJ{gP44+OR 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 +%xTdtz*GI0!ZdiuFTP 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

*j>XF7QLv*%Mjbd7L2Cn2HB zF6Yn7$N8 zI?v-<#@1*qFzHx~p0#+wvPd(l300zs<+_alnzFA?@l~e z_RWy%qW(}I4n^Bw_ao|8#^G;JSICzHIKEayUw8I}cQ=8beRciJjV<=3v>UHf?#Fy> zL+^vT;-34IGq=l4?oS(@)oGv5{|-sU&C}+^lt0}b`l~Rb^$@O>*n4?ZFzpM`uAHk3 zQA?yZm@G)BJT8M|R04`G(iT04Jsq!gxA)b}SoF5~yXq(>`;;M1-@xbj8I!g zN8?^yLWB@T~ik;1N7w|r-XylM1GVnEN4A=eU$5A z2`+lMTF-qzPu$yYvb$wnzO;oaP|bw3XDq9BpbqxC!GvM<5Xt#Wzdz88pNo0h zp88fRs*lFH_EgjA;5qJh`?(N}0U$?BbjDz^= zN3DL@1EJ#2c&W~-*r9iN5crIlai2)UCjJo4LY^4`IZ-h47v(s@_%LC@RZ9M7qAnp4zt6u4~pIjxoZc^t}FG>K< z;0&icn1M-rT*ALw;!)r28|I?^Hy}}e)0x1XyiT#GT5|SeQ4ITM%0Gr(kwD1D1$2Ws z-&JQ)ozJ^HI{lTnX(&@${JFf9I)@(Aunu~d<`250HssfcN`=>) zXs`LOy6N6i2O<&@?ggFRTl?~ z7&S&-HpYdb}Jy?Uc~`$@yjGBJ4wHOsa%t)*}!ne`N1= z3;p%LwUMNbVa7LTj8@0nh>{vCSl!$HrnvUt!2nzeqj+P{A)d!f(Ad$V0F z8M9q$<@MA{`&sWF_$TZc&lii7SE8fp;XE6~o5dew>NNeDVuz4Dobql5Mb$qrSwN(4 zQ;c;yl$)pd(b2ym~WxCziwGkSMg*A`q`H!yr-ui-8>fD^6) zB@X%2hjZS9>_QL)TX;vAz9LK}-JA zdv%JET%|m2-q=3-NJhq^tW1;6!Td!!HcS**+N2v~*JnEK>n1returQ&M+3kOoIULZ zy-t~2pN65l>a1nWv@bnIzlxM;KH$yi>NQUTysKOu8?aRax#Ie`u5o+X z;rZXQw~D%tWvv?qT}~ysx03YhJ@p=Ues5=!6x8WT@J;kk&h~Wc=}o?r%PxphVO8c%X+NhQw!YSh^LzV9hFjZkpcY<~u`ANZkxLW6hZO zs!Z`?(O(a$&!MCAP*g{vj-F}^Yab#(@GO_oS}#CTy(>s7xsM&KN5Wa z2uX!odn&?eW3!Se#$;>UU&2#aDDt+f_@Jk{ zy7OEA{3-bhovL7@1$9uj&ra0w`_e;YRU*b1UYWVe&ie1R??<2iI;GBPMr~?ZNxR{{ za^3w5-S!^9*XZA5yv4VL1)lzBi(Pg)zhiuDfDxu)yT5&K=7f8DPqL;+SCvA)w1vf4 zslo!Ko~9S})?YD^wJkL?5GoGvF;>G#q}=xp#Qu^zqq?vKT;UkL^{#nSX-wQ{`MxsM=i3A6GE( z9U}uA@}~P7(SuJraW}&$n7aE~N^a@PGX2Y{_xH*ndTt}0gEI@?SnKMdflfLG|DbNU!=h>ndN?Kys?|44oxF+n{>NGwZ zKvOeYKmcbNSTzBU1bQb-_W2lm)2A`sGyYRdXzVg7t23kmRx}I&!%I@6Fh>u?UW|>> z@IUFuSb|0Vt)O?cb8d2|<;=@Xzu8zz*0*fqV}{a*<+_qDU)N4$mUJJJ&R|>a&5CU~ zO%;ppT57&{TdN*iUdx#rHyVJiym1aGriW+8^>&Frt*>JC3CVg`MGYfGl;!k8&4ul{ zZz;&7Z~Mb#Rm}}>!``R*dATc1Y^D5IPo6&1nchZ=b=`okH~dWXM~z}PaQZ1)or3$a z{446w;9TmmPi5SK9z^wy!eOfCwv`{OTtAgIs{WoRwIlf}0VwG8*E{nn+Kiu!-}@ls z!ku+c8CnhIyIArnp=oa0I=8lde-`!_k9a%lf*H9ruDxBp=@GX{SZas6J)`lL>p)(A zh(%ASdO4eR9NaO-(@OOg`7x z!`lwKfZjsA1{;Ql>Ysk_F6&oLy+9QFWvmwO>86P5E1^+if@+Nk8<^9R zqJ(T~gVpWxX?=fzc2Y{1&$K~>afhH`btO%li$XHzP2by2Z;arh1-1@}O(|V`Q>nD8 zeHIEZo613rcI~UymA3aD+^H`FQY!`9&+Kxtk=yPxTJ<_Ae*QN4if>N8TR=S4c)(Uu zJ(GN_dfN?<3SLTHe|)75N0W4lU2(7%?4>-%7qdT=n=p6DzVG%ecb2Q&4#F}oKrFvG zEFBt;5%B%lC7-Vl6zMlz{4sEk%MrWUI9EHOseedb`*Q;RF7Xz8kX5KtawMs%D;A@5 zte!M&o!_d@Q&@EEtyBIH^K!BR+BNJtn40{13ZAAXK5#lUE`R!w+T@k3UPV{u zm%eJcm+^i9PRufk9SFiawgBC)9L%;$4>QK}uX4%ip8NF=x&K(C_BV2lGS}VRUs%NU ze!nT?f8l$DL#2KJlKw?vIq=2Fv-`z9=9I=lkwf5uv$kkm~i2K*Iw}R1E14^WF7gG*ZRes9r$_$9gjKpY_%9 zGWn*8EleiKOI8oUWah0DwP!tnda(HOZp?lB9#t-L^8pC=fuHHyD}z2~#%+_gLN-?N za+`^ft>HJS3nxE?JW=79zv`?gXFQVru-kS^!szaRek>xC_II4g*13Ikjjy+>{HM2c zaTCJ$Nh;;&yVIu^&~HQB`l4x-wbL4JDt_=6mv6HVJN*#5Xtv#buGMCGIHvH4utnFq zt8w#Mg$eY$m&WH>UF;_kqfN~GiR>ErGwx9fpdBr{;%=Q?ZNz?Uar#ZQkn%+XKlPiD zyVazGsTi^xjrMd8rS@*u)}~YiDn(u-GRP7_M(_1=V~;<*3SREGsj8gB?zZ=Bi}RZf zq#t5h*CJy9-hCkIYd$cp#|##1n9I`&f1$7XXd_8Fc|UAB_;pUR0n?cY=}}&xi~A)z z31admB9r{=L4#4>hk{m5ZvyF&C6D846hP%WZ)}2Gn60>2=!2Sk0MeLY;?KJo<2vfQ z=QHZ(LEd^QVnQU>-*y1O`^sBedD>r7wb@XtD-y&DU{0Ffm-!Ir3`?F|Z|TeT&F(?X zS4forn=y*-lUiLy?px%1f&U@vAv;vn_ivG`cFjt*tW-M4A#xg#gPb07Engpup5SMz zJ8hKMEp;%HQy+f!AInWeOz(#gvp`ltvoSY%@ltpVW2JQ^gvIkGenuaL0wSY7ZYhORYUoWT zNPQ^mz(D%+2Nbq+cuGHx*B-f?&^-#D_uljx^vUPbfSvQNca`Y}lh1r^lhpm0OyGXd z*z`}x{d-phzC;)&e!GP&y8riR?&a6EV}GoJcwHYf)}Vp5Ha@ovlzDyo2kD8^?QI1w znCG!Nvuh{;7~UGhBPzZ}^Utw7x{t(;wdPO7I@1mab)$(5;k1tYSjcvNt$y~3&C3Pl zi|Ch`j?{!6fd#YkE~pGZg^5L*k9YK^k7GnIPohXF!QpZ|2PEiVo1-s3d90}2sH-Xt zr%9XqG8vW!2E9KmZ&liBv}m5Vohs#buYc`W**-h6A7NfhD$+!|9;W(wdB!q_Z%RB$ zYTssj0$)3RG1idr&Tqe6;|RD{XhoLhxmr%{m)m^%A`WmXw@#biL#qaF%j-h($7DnZ zFjiM~qzu^a2&6T=g6pSJQ_FwEjOto;N=N~aeB)bZCoEgf%`&3>Cz~5KfWM@z1UjYb zC#0WasHTb+N=#e$a~PrJ#b!5Y?MH4prtr}5D!~-3cIh(T-i&q5y(Y?!{Tm!2Jm8Ok zFup9V(7qnS@OE`u_47-bBS*zA2OBU=Zx0Zfr+&a-byxl!g?Dk28O%vDlbC%{)X<}+AzJvO*-P0%8jo6J*ffL z`MuOFo*chd`$?Z4?e|v#-RHfZk9W^${8F3aSP3VBdpp=`a)y1+y;&U>0p3bzpeC2! zkT$_e=CRQQ?S((4_vZ_t1Po}W3$Wv+*5WIJ=r5EStHX4CTcSf^G_mvnZy@n}Cj5%j z^tSIN^}DWgYNrpXm9<1d>q93T#MjnTINcKPz7UL#P4!{%r56L|I^7!EbXCoy2rSw7 zMido8&Xc(8H7pqS%``WCp4>{%45*!nIh)9CAQ|~`fB>BdGLwc**(?Y1sX`q4epjOQ zbA-1Vpvt25X}f>8`U}jMdwoCC&c8$Jd-W>GVRY{m zjnA_DD>iDk&g#NYe+XBNoj=K$`6V)d;rc-&uGWFG?roSkW=N>qTY!=XQJ2b!o!oxB z54WPc^Gv2Ik%$3L-^MTQN}Aphqnduh3t&cKJWEw>Jn6&h=oz9Y5O~71N9P=;E6Laq zNk{3sTNO|I*Jm&FO6}YI)c#E99ZSFam&zP2TIm`_JFt;x@c2DQq^1R{SK-5yn}t-K z1!hPCbTnKxOL$g;j7FP%SLzPE`fZ&@X+3ceu~uGbqt(u<=*dca^ur0IhC`0-CQ6C$ za^%%EXZUyCxa3BJo5e~}!?RI3ByoI#S_v9A0A9DA|K{NCU*J*f_-NuT^p|b;Yo1wR z`{I`?uuL7>#i(HueklHlSzYoPl8l5w@wt)rn)d7XS`6oCa0^s*wEce?zI!L}Nwa2u zYJ0K#I(Lr6+;bnGyAS}szajJ5q&#u0=EOXWmh>NPDQApqA8P(@Q6B1faY!DKQMX}@wd#4t>iPf@<`W3;m0KV;Hq94ku zIvBd^*Kn_l@*0pr7ykg*F4! zA>C8M=EhX%S>)oqoCB%Sl0&XfZ)|QXLOobd9;im}QW8oRh9JaayL<_WLMVk)Z`~gMWtcBbZ;C}LCJ8;_*<*NL0 znXsSlAN6$J#?`?q)?)AneXL!hBG2Jkk9#DwH+0ocNM>6ImE*6^X7vZvm#DBa)xY1X zp>@c{`A;l`6kMAL)4c0u%hd+dF-`|;Cyzdw<@#r{T~`xVcIv@z{C2>K$LV7iQH|v5 zy&v#XL`Rtx{stQO zX9Y6vU`v~Q>3VT#QSRV<58n}hsC8&!L|!lSb4jq?I*$+y$Q&cdoLvU7zD~C*sb7!f z&q}#9WMX^qg8lj9lG2B}}oAvGP?wIGXJy&O;pK=XDZoCa}EAPp%v+KDVr866E zKZ~1#>lJ0mT4uZ$gkamvwU4ZeoFzGU(XFOlvC7!iHvH6-UV5$z=xgEqk@dU%oI9mK z(Hsr73#(I=+n;21Xs@=*X83n60NPWLn@{wL0cPbUOy^4Qn4aB%o4iBPEnAK-zaE>D zmz%?Z^p2~2Vh}$i=^>VQ=NK4+O|4AXn^kr3+c&3qQoQUj*98k)xDlx&cCz9gjQ;|+ z@&QJqQyn~jg4dcC2)(*(usdQCQ;Et3I(>lNH?A_P^pYuCySGtxH#>mw@-e!Y_ES~O zZ{IKj?@np*{i9V8Hpw20bBl5dBvUg`Ir=o%->MKHrok8!46A>c`m+ z5V3TL%3!1B7OXjAmId8HEz&n1UZFRUo~E29#1W6duGR|*8vv*WcygnE4@O*YBML-1 z_{L=QTR(>QQ$H9#z=4#H*tgbLuNIH?@FDaYn_57-KfC$sn-YC9S!A$R+K#sZtGT-- zHr}RxJL&m%9~e}6o{CLL08XzR2dZVDxcow$te0_^z1!yfcxfU$v#@T?x#Cp1q(0qu zCdq24@#TUS!R}QaS`UA02&b_=e^ok(*jah=>+Qwj?=qf!j>PN34XcJnu}EW*w^YH<+nXZT8Mba5jB>1Jk5(2p)Gnx+t(9}}gVwvs z3prM5p1&=)ZDVI}cNbvlJRWlfoblZiF4xWkLV)J#+&>LJ?XSM)fnWH3UVZVd>HlH; zJh2U&FZKlhIn-h^M!#KjI+<7I`=VjY=W)nUAPe`$wAdHAYK3ccid8g#qZkipzc{T+ zwdo=pRDPksp8z&Kec&(~pV z)Z2aa?H-8s){`ykdp#=8pmhyT=(;;;)uS><7Y7J8HfD+oTkb9o3(zTbt0m4lhg=Rl zhgVb@)xYvAj)^{Mi zh4C%Y9j-9%7JtqfAsm+a-%^Gs(DR?xn|EMl+|SO*c|=;9_Gi?-ho@uRpf2+cS(I}6 z$ZV6cPyXIQ<9gbFB|+c45n>+t?Tb=lnKUr-EdP~DGZDtTti(|-iH$pt3xc@%<04Qg z@bWrQkMatESaV}QIzX?z~+gm0} z%x`m&ZTYGFt1L_7hnX++(ODqcMGeT^OkY|PIW+qFWapk4&)?n}T7{Pe%(N#)WN^Fa z&_qwIty$CzWDP2eNDY>B`dsdZ!6m=eOB9tO7vWKo68EhWYi1uAgX0G$GyU?(9@WZD zt&}^7CdcrN*h=X60X%YzNEAN|v#Ar~Zhg=kA18CI`&In=UD&r71t{$)#rwna)t{IP zxooM|xlR=U%=WaR^^WSt>4RTy`m@!hy}UrbW3551W?W-D6{&ti5`soG8lPAq%?gaU z8-KqLR*zIc+aL0(Eh?|s(l{+0Fuh(ZKp{vI|0EjF@T#l_@!*i=Eu4f3VEq~q&4B!L zw|Lrg2o@ov+N)EFOiNX%A@tmT8tp0(;}^cx&&#WMv?uGp>josCbggnjLp6s(6q|!j z|NYp_%le*jn*n~f{0MQX@yUwmK9%)t4S2cw4`o*L$O~{_Tw__Fc*3zqrIq2B9z9QH z(!74hkrxur23zi}FKYn-&YnM3K`EbaKJJgllJeW&R4*&%~ZtzQ9t7F&3cW;e5dc^vYG_(Cp zdVN=k1$pcZAXksN^&)^SwHmylQJ;u!J4d|TUfmtjFg@zD?~Yp89)9YjxRn$tkx z*euC)*{un+KGJTP?azl1EBK^sjt3PkERp->-0rhn!yIIzx3FVC*VjcQ)vff0oWLFp zCS`iEdFt ztMM$T57Ir=J5igu5$reVbe`AQ?HBHLOLFZ3y74$X%#!nd75zJp4yTk~gO$8}U^8tuW! zaQ`mt%^Uq~0n*D3i%dh%kZxTzS}ZKbz-&Aq;<&w9ti&W8Rb?|z&2OVd4LXnWXn84M>`*i@h z>%YA!?qBD+pL92*WT3}3E$Z(8DR}D|M96ZV%Gco1{qogQ9oCxeWA@(f9?z&@y@!2o z++q`_@M_No`I$^?SpopCa$aInkP#6jEqtn*eq{F9pi?2=<-8mMyr3lh(c-hTpE}2G zci*r^+v#QPpD4WF*ES{egfzKj3F+VaQ3R6eMR@wUK^8bp;`^(A;OOACEvPYxy84j> zHJNJ_-`XTztm4MH8a=P62Dj|mNeae|>Z^4&yp48RrfP?M933GI(nGYVFWS*i2u7Q( zmD#rj>V;}6A(c>!+S!3qfp48^$duX)_ltV_`UQ%J$+gF$6kOak18C}v+dyvP54F+? z(BWh=d+#3cB>;yCFnnTlLkxkAdL)5DURX%I?`TUJHcwz~$0yX`z4g>^YCD zDnS_L$?$F^rjc2ne$0o%77$L3{OmBP zanZY%9nx}A`nin;Qn1UdaP^zuJ4SXERg(Gk_3Nj^%qF{{9}KKC3-aADKIew8+8Bd+ z$zE<{=hg;N(nQ|bzu9u%KuP7{m99{&SA(-X5Y*HdnjRG(mm<9@!m#mj_S=o8o+%M1 zh&C$WL$w$BvOp}70_*dmDJtjP_+iUlc6$YHb71I4rn)D$%`paMoBd& zw6Y2o7oUNLfjxG?d`JEg`@8Ggvpu=qp69Dor30KPK`pgOgFaP4Avx!(5JkEl5-ZZq zO7qMnTOeG^DI=8wX9T0!;6b0Xkb^z$1f3vw@-38-<=Ry>?kS)4)4zVL>eu*MT2i{$ z9A?U+Zq<2!xl-W`wPe@UYO|c~uAAk|9#UB+24eon@N%fkqBpt=%wp=>(_2%1((lhh zHW21AD&oIrtYhW9oGdokV^aDcbLz0+{J*W|QB*Q*U*1P=G$m4Tf^N5Izt)O-9`h@g-1fA1u5C>pCp=Q-rBLz`TzH z^i+e6=W?0F;(0#0a}jYW;NeA!#OwH}Bxxah*9W)pE9nDOmtKKpC$9^7NB{MuTG zmtKvubyWp`Cp4BPSQpjk?m>m!+?Zp9U39nLZ;7RbiaA59`g&FA@jGYR18j`_WlI{^ zIlf>`I@K8XgO4qY|6Jf(D8)nM$lcpZ(*Io+QLiqEL>bDhq}R-5I=uxu6{Sb|I@$Jl zYqZ?AvFm|;%xO+99ls=>5vbGAW+gef*Ta5U zeR>k`r0DbAEL3joY}`q4zkV*a$ehW|QNQ%~L*=~r;Bn+<65yM>?$h4uR(WuAOOVT8 zg@?{i{mb*WJ3?C@-`76xzhaQ>DgcdAAmQ|sTXP5YJNh8ruCX@m-fkcbBMl}!zg#V4 zZMe6mfc5cbiWB%Rd3ffwfdfPlnD$La{#C3=E|o5n85+b@ zUiI{CcY;p3QjqD{Ynj3BN$#iYaQd(qKP3XHgKW97v=^q`C%kU2tI%ck_Y~Tm2JQ>Y zeh}!~jEZHw6;Pil_15cTPV>V$ic){(^4iJCe$=?bgM|%8yY%`Sl$S?F=xB>7(KE_U z2p~Ub2l`>#>Bx{7_x;Ykox1&eyZC{C43@CLr!UV|$$YgGul1{p6ZaY11EOF0>=*1z zTUi`cf=2kv<2~XJM#}5|)TLtMk)8%oZ*{D_27ScKItj*7A;E74>K#;zlcJm^%U(Km zhDTqi+~2@s#g11efMir2jgqVUkq5fkia}tPVx5);rW;O{!1PK=*)dpi2LQ+fgg3-2F{&&GjhkPiM|H&i#WJX6W6!P(#nZ6Rp6t&2q9{|0-eFoXn zepL0jObtNq3a!;)6AB_yVB&3=rw?h+!9z4QIgqb0^Ng44lhi4#*4$0<(4g-VRDM>v zn#IU2!KAZ_QlO-X@5WN@R|eSy*dP006ns?v$Thl%&DFQzw~Q2*ppmx&zWUvo*pBl$ z#AKEO3=A36LljwpM*^H(3WCX$4u}R*Jw@CJ#w6z4w;bc*2zJG2HtT1F;Ro zKxsA;)$~>`gzVFuu~OKaqhF-59}HaeQ*KUzc>vye(b8AE#@Nt?mW;A-yUPT(7(dA; z2qo}E226ZP4m6OnXYC45Wc|&~huq(ztW2eAx&*qbVvb}>@=q<*>@3FK{Z2B;yUkMv zs$P^(y1u^te(7AQ+Gwime-tM(Sf3y_yX}N6Fw9P6xkjAh}-md!6Huvio5+N z2QyLcTl{I&a&um7N6jB*DV<ELsy9zS z_4M?AaRM-{bdc*m{UL#txb3*-&ABNoI7!0^DTjQVIfzdzr={>p3* zh#4CY2uupZ>uq=4%C7LnomfqnE8_Z)~!ni_v$2dE%rvaVBDBHJv!01btyEf9%=Zw(t>9r^EYw3Bas#=>{b3 zL*X)GoJ+G^nVgQx7l?+*7M}Q;w3VRPcaIiQKA5JrkiIm*rCQi2*NiXff-UYrLRCyH zc86DSNQI6>fj@2AKK1k6UH^|2EynAT4L5n2jYh##8d$R%tNuaxA{VCT-SNO?^)`z2 zliO`3QaSNNZrJ-2^b!Qk5@g0!#;*NfVR?BJyDOjXRgC`4#%>JVA@$z^Pz}Zv{1&}A zT>K8t?cd5hYPIbbd)K@z+C#S z`(?fv-}g{d4fl}bWL0FPlm(@0N$a;M=hXAbd-Suo%}SV_SDILe{gLoz{ryD4Rejp| zoJA>IMgPeLfT|N}Y7hWa;dih5^5$J&McOM|$_Ce>8ca{I4b#z*fj$i1Q?2_QBrVSn zV5+jT)#sMN?|2W=48PjLO_MEMX#qWu+;MKJ?7UofHf2gy23QY(z$4J@Q1SsA2qK`q zjR#)rcKrYfu2}~D5np@V*qfYw9-_RugK{!qfh+m6feR_D2{v8`zPlp0SNHp+!3_ES zO~Z8W42Ia>g#$*qb+v^Z$|b;zH1MTz*^1*<$#bD2H#mL!Z+>ns-VvKp=kl*%kH*&( zHa)&a>!kyBH{UlEDSo(KAq%2qF7g)EkI$VL%z+!?SQ$d|6}DV(a5*S@i#qlI!#y~$ zzv&m4RDe=5y@{XgBWZ4cr91s0?;p`Jc(d&hGzIXLd*dG5?*|2eOuU&z+}D~qJGyqg z58jHQ!KeLl_=vNDsI>gRAxNe7w>y4>+hod6;KVvhCW4=bLKn$%oZF`njtw7DBv3EA zB)5u0Y*<_Us9Zn8c6Z+cz=!J+?$%?Q&zqy-FpJGlo&VuzOMIQH?U6O*aF|Jf(5p7i2mcVK92q3;gl_Z;p^k4Y3T#L z2O&l8k;mrvnX4z}R}!@TS%xng?`J0bcFBV9nEq z3B~aW>TjV=TPZfx8DqqFP>Yx&#fE5PTrzA~a)FW8w)Q~8n$wIVfX!53G`k?eOS%=` z>G>3#7N-WeBTn1VC4BgE0-RXiHK?N=KzzlTPCY4GzyM4-_V}_*K01r>YXdy%Y-0wZ z9 zD-K<(j7@&c;xv@CuvP#q%@m!tL>r%bZ~IgOcfVMb0fj7z>hS~%yL123Rnx1PPVdDY zx>U*HWlDoT3)gmy=d6b9-rnr34eo&G+xN&B->pTc%!glK9wzaSY4pq?IIfRB&*1UU z0Q*@-)4B{g*rn-ew^eBTDSZQ9M_jF_U2BFtkt%$CL0?OEXxPC)UaCp$Ui2;j1NP#1 zr?Z{7a~WyCgl1d8yh(8Fp3$OPf5hq2dF;AuU1;ge+#-Roj|7O~6<|&uvG=YAPqk*n zb?irLCcCaE=H=DXbmbZF^m)F#g2$>v6>FSa470ZyMJJ=efFHxny=!yd&0Ggs2d}+K zg1LiU-6w>1IFibEv8$^9yCBg*H&GZp@6OINRKXy$?>w6HV-weBonWXfG}nh-zwfdt z{g0z_-#1omqwo=Y2Z0n4CHrkf(gu+dijYbvih2Iu{jT5o`(5Uo<$3PS7}t>P4`J^Q zVzVoZM^p!0Ki0;;5H0;Ty=7i`l8pK zFVTuAG(P)V{!i#zlPN4~#Loz?x7dA%{WXkrVLEVCx(7weG|p`!ao=%9dB5>7E}i*t zgcn-dz0s!3I9;$*vT7Co7P~O#L8Y`HL?w|0R^Hcw${oaMS+P)iy#5A6c$|(O$KiT% z9v1Vphta7<#U{PU^zHbi7Z1-Ia1-e<3EOhG^7>DK8<%o!+8GPQ?3tq;(*$ZcgWu4g z>%%vli578x$!KQgf5ldNLRXn%{%co(>Ix&aR~_~YGw&EEq7;rY{d5)hD*Ax>xkmw% z#eXfCxH(va$^N>pVL()9lU5pwGjYYKe+TpRGn=4PL7yvDu3(=@>^Fs&$K4D+qk;3TESW6)RUv%+bIo8^?T%7ViThQzC*eX$aTZj8T^ zgJwonZcU$y#Si+*_o8-M*o9(QXYKi)-pk)kVDUfP9^*CKzm4FpggeD2QzjQZQhL<| z9ev8HIvW8v@w8jj&e#Cho62wde5F|Ti^W}7I93wyVKvIWO7?TrDpY++Nn5db<1bf2 z=JpX={oa4ow)S!7f5^347*hGWTRd6lhJld*QM49MZY-IXK$ zRzI{RlOzvn)f!mrDQjYz3%oN!L!>2C_rDf@sp~%pJe5G?!n?wIE$9>LZ6<@yxo5&e zQU0EXQlbK;z(fLk;7uT2bNMHd=%zX<{Ys}E_tm4zodwF$Y`6bo_HB?N^0{RFXHV`0zvnf1vfH;!HGG z!LW%W@-XPV7L=1#!yRmjSa=6=1T0ui%1-^on>k|sq`xR43$6fg6|LTQm*t@o@NA$) zE3DqWSZHf811}FKEIataEycc%KVDC_iKxx)BJ5lXlhJon(p@RVCyNW=c%PjWZhmhC zWgaK6-|f_6tz1hdgTnK2J%TPJR1Ozwq~2=;fz?Kx3O~vasjw-4ek?7}^ULSRoAXD& z%IPp~zDJ9oo<7Xo&q2p|(|Y3P+UzkZ;Z>sx7R`<}G_!*>l#e6Te7OkN?7w)uVr)FG zKSti@y@W#5mWTPse)-@l00xD=k_6{!QzV(%@Ivo2mL29UO0F0WM{ss@}C*O8UEIvAU@rhD&@Q0~a=ZP1l16JeS+a?A^ppiVP$Q z=KdJ}ad)tFkED&f<#x5@UtaDZtEg(E)#}w1VWO-K+fivk5xJuf=f$g2BtBM=W{(_M zXjwPnNDOx8isVf`i5ho;nX~Vrw+Oxm<)T&`Uf`}2Hg%U1W0Fq~!Gw3U%j;kt@&fYA z-jBniI;JsURJz1ko=^@{j66$Jr7bV2p#80^7P8t~gVCZC!b11&Jn-YFc-&MkGpYbxj`%qoW)aprm$g*OtlgH(H{ww_Y@y`+F1;Q~ zs#gOWJ@d7l*N;(291WI-w~duyrqoiPP)g{NGZDjG;q^x>eg!F#>q z)m`kqrK`8(jv*iP#M6FswJUC^>?8$vof=Z&V<(^4%l?sPDFm1og33r^+zxny?-mfeS+ zw8_o4Y*L#YPBLt)4#}t;OJj2r^a@yhq&@Jro*%zCLeVA7J*WJf?5RxFx!rNFX1%=rU%8N(T?TqidAAnWnmVc|@U;+I}>=DFtZ zT3JjS8`mfLyYgm7Jx-8*?4oU2y5A)0&(>$!>@9Q0BL4j>jvYbDE80JI^s6#qr=id2 zv1uPBKPW4Vk9TKQ*kMbFxJgv*QTJgQ) zx3f@AjaT}SOAB5a!Bn5$$-KQxu8|k>sJxmxA)xBzoDnI5`r`YM#s2KOi01Y6eqGbx zOs4-(YkLfy0mi-QclUjMBdf(~I@X-hW28IOJiVrK%;O4wJFdJZr*wJgr!*Yd7xJk$ zRGTjgB`H6QqlMtK)X-h|!*K%l+R|qxq?A4Lz-EO{fo!&w(~d76)t{B_^#rdI9TUnF zb}NjS*Jt)Kh^jWGT&BrNbT0X1ok84c7Vd0Xe(8ULcF*&hl1?{(h^byF`=0bi+mru7 z6F>|eNk(f&&{^yXws)!fe|tZ4SY|%lm23{_jGmXdL86%0*1GSH@&SW}xx25_Iv3!92yg%4r(AXDG%%^tgDvQqw=9V`=zkVtt??be} zEs|kh2WRuHBc<2-a6wF2k1~={dN`DM5XRJCxCy4D$CxW?<~j*Z{lDA^8-LybaCk2x z<12Ky3_IVG+~(EwgUcM*c9Z23rf^#{=})U%4&AiZJ*i)ISgTgPH|PsvlPk5T-Lq!{ zG;OtAQYYNu^vsrb#X9eN3;E(rl03A$p5S9Sd$p=oOZ{l5{Oi3g(Y_uIk+y_0IF)n*sf3p*~)e|H_g};vKcHA(uicTrHcf)~w>o zCZH9Xud|PiuA2h@1CujMfpSiTKXslvG?6yKL)=+^qIRfks?;g}f}I7M_OsUK%r&Pt zW}xf@c|FgQ3{;G5^~G3`e0|H+OOor!HD|>)lsnBWLOPt@PwMmV z$KoU3q#M0)t7U!FPIBO$y$4R#&ai`MO}nuBoQ;9Pla)5x5%etq|BjmTQc(d6I(3FK z`PS;$jxXkb?(LAACV1biEjkvB4jpha|J2%b99Wmbgl)JtwM_jLHjmaMcXx5W?jDcs z=SZ%sBlnm+zgm;K*p=VAv)Sw)8p3qUwQgpBu>N1sOUjD5yZiT{?ag^lL&@UAD9^qS z!#>L~pUD)3wdHSZb@SP%hkqsNtuCdUB83ld@f^Mey`Ows90sLZ4(V=i;hwG3ps?{$ zSg!SVrm!V-_+5m0niC58hb8XP^V@v#vwbG~CY(_ChHvZgcf?z7c#?YSyQ5{1ti0bx z4!^ARGI6G^v*2$~zArX>y&{cU?K>kr2PMQG%*f5;{2MzJae9?ov^CT$!-C%>;L>}maMG*2(?z#LnRb$-9$9Tq0N zsMTU*eyp}8bz(eDO^^O-kve#VYl~|0BnX#!WBl{~F5up8_SM{Fpp*B47vo?T_;Wg+ zelHPf!iD*kALX^S4j|6(T$rDG#XiV_G4yX%oe7OnusWh=b-U zNw`>?>^d|8Px}4N@t>qtV5G6vCMqvBOBW>aSN!U>e5efpVhU^FJJ{M+jZnK&l6I?) zo`XT&$!j9HfF9ZQW50;mMti(v&NbK_EBQDhsONEEGhOiH*NH!@j7=d3hE|$(1r{|Wp)ao}t$Z233>nF=zX9r*q z<%ooXG%-QtUOyG`)N<1qadr4zjJa{{+wDSYntZ)^)%)b5L(&gyrrPuRX*JyS{6O8a~k zsD<#zU6R-`QtB@{0pt3TySi>$*gi~^!;y^M*8`j87`~1nm1WMTGU20>GvRvXd-CHW zlsw6*7tbMe$y2SJjv(reaW2O#53Bc=i;byu<)EZ*c=za?(fMa9tuhtIAL^P=E)5ZpQ(=s zd_#F8d=@&e!_BY9&BdyIsE?IucZ-xXDkwdRHL4iRAAhMbpKmAaND~F;lMYw_7_`Bu zk<{>XrRO)YJ4*aG(#9dtHcTb#<_W>P*8_XzYb zJa$NJ@C1(6s=+4}Mjt7wn%;yth>Ff;W9{<`XSbHAALGB_sP>sl)9IX;dCON*@XX=0 zH3hV-+gi;90hmdAzCPWbJ-#`jTWLP`6i?OV%z_C?3_()l`%DeG0?eR=sa)ZJ6RTU{QGl}$1V_>1xOVY~tA=5)Pl zun#q=&cf+@1gB*w9#~*0$~m5J`m91k{t?`!K#khd$>?uK1ml_Y$$Lx6gjHK2*tz!P z);MQI9yxhE`!7+VZB)FyCw1yQExGj|DNOfII_mg(tB&r^^NPYE(7&wqrzsO6U;UbW zDonFX9>Vj}P^RcY2RWtlL`M5lv`{u3>o>pBdGD#0>vNCVS9j=lbM?Vz;RAUaU!mph z%!^tunwm^b*W*02l4rN@iwWaz0(J7D=aEsR+H!ZP(6eLLl0WMzCNvM;bILUlXE3PR zh;S0WnH?OCNtkNePA{2tKaEM;;ig7s`==yc3vI`g7wy51Kq^vpDh;fq(rakfO z{gr+9rFHvXO!MXy$xv)qqiqYT>^thqzoPNryZ@#=ck2{|RoJFzC2Ngz{$wVYj@1RD z!{Tcf#cqeKYM(EEtsJA%3_9|SL>`iI!ch9-jB!Ui>%=B!U%%6%OhAgHMx6htunr%uSpB4r`-Ld{jjSN*fJU(? zUJZ`&FE5<9FQ@(gew317i~(sc+;6#7Po{`G-~+-?&d=4SKM0neNA2ceeCIJ|Z7sYg zd8c!qEtdZ7@65pLPzDR_r+eG}D+3ZEs|?_~AFv}925$u?N3}ZY*ZryNkK?Ij8^}ui znFd5LzTd^GJ4U`$zw&Cbrm|&|K0L}%Wn!VXzM`i?@3Q2CCu9dKUZv$}QJz`Ay=H8f zjqaYc%L}H~b}#G@!t5|)gxmJ(+cENB-M$f=f}K$#hI4#$?=13vK5F_3A$YHL0QlWj z;EDZ*-^zP?ro@#!Wa;o*bzx-h#6&ToFH_pOf0zR2w06V?`Dm+?|bv?iQ6fTt8 zuv1|tM`ODZl>U8{G+KP;4X?yRSb4WHbDw=Z=QQLmxA!vAms+=p&)tW--(HAvj-a>B zb&jp>sCp%yhuCb`oNX&1JQqvLj`hc5w{aUcgF{MbrZq-xW3%Dxd`0Ao_CjCGW1cNf zk-%H9n_GK*v)^;m8SGKG>Glkr&#*pLUG-Y`a9H@Gs8efZb8?oRXsQPc#61qx#VRUJ zA)>&3GnWFn?5wCiXa*T=Js~ursf)9Z>udetl8W)D34RFAFTm8CH%%GY6A+C2diVpenrSF$|MGVdcq-#}+2PygV$lw7!)V9}x>K%`c+&ta!n=6^Q?Yt%i4}EmrI|sen7{EG+3ZtPJ^dJXjijpPvFW%d z7)0hc@pV4hx7Mjm_aoBWmrI{BQfrAM$gWoM-gICZJ)$l^l-$(gctDZkrL_LfL`(-TF7b{e1=D=EiA5-S<2?E1N!w+-OeW0>B|-%lk22n zTVbCwyACon&61ptCxd#O*;e&kw+K`J?s_04eBb$~NcGXn$m-%MxE;GuJ=t=cHasT= z$C7))e78DnrN>vd#jc%Dx+L(%1B$8NX#;}@EcbY)t4^H*;&@1#S{S$P)CIoYhaj3D zt|yioznjIu&?A@0y}tk$A9tDu0jQG8y~(m=GBtJDg76AoeZRi@sA-=Bbsq^3#r4gP zmPCEfgza0eCv~iCvrV@5m*He09W$(09dyf-JerWX7m&x?Kmy>|_6JcCls7&!MgVaz zQY-fdX+g*AxFL8p-)NmdiPpWi^sMi3+FmTkqDIZsQ<*H!VWtEPNbo<~ST60I^6}Q(D z_AhI^0$)!*<+d{=indnm{md>-wKKNSwQJ$v$)D5|xcU?&wpYduey z>HVAz1+;4kOZ)QX!}5B)o=0S_e4k!Rw+G&8^3_HAZp(xG@-^@pMXY6lZf{}N_x#n! z(DJW+fhlcO*Y}psI9WLR4qj6dR!uzDX?Sq*A2(0+Z&MZYd|oj+Oy#dK>8A_o&uFlp zDDNY`r+m&j1r;|~_AyCX?80nF0|dD*@sY1>wbLF@6jt|WRH(UY2*ce|DIO#E?^!w< zCB}H3O7JP&c2g|ZYL|v#DwX{Yrp?U*mJRRD^ip0QN!Kn8TKJzjstv-+*L?o4LTH6G zix~YC)Xo5SGGs$u$WwEqa__ByFFewgR&=>$)HId(X}?;K!GdQM>4QUkQMh&}`C zn^G8qR-vYU+r{^s%vW>u!TIkvT4QZz{>)1pGM)CSm98^Ad&as)UcHlAvz}^JHo5TIdi^b*F{+dp1UN$a(aK-o@lRKD{Di)8t4 znVc@CRVeUSg3opr2ok}eM|NDsgdDw`QLIa&KkjTsL|O}C>OLfcgk;WwqB@&z?`D7g z=IFri%^kGUzfE^bjV@!t*bCn)s505289 zZFS0wH>Li>ls{L6@K1#(P~!Lgo&4$S?gxci@NJX|L+rrp$1TH(@H`8**sXmUaQRm} zEgeW5G$dwCE9|i9FW$~cHgo9HvnSlRDVFuNf5JthNZvdCpoTkB(7hlH46am>GXD_qt0$06Rs58*&*6!Z20%ppauGzmd%*$UDs$; z)LT+h?@r7<)>PCXv7N5vO@`<2%L;;LW%%yz$l0tfQF3LqixE2O&71Ryzhf%nLtgHu zjdg(rP3(2ylr|Z917K%+&ZK-Vzh49!>e$4YC*hSQxm;z*6?f}X04p>(go~jkmF!z) zlxD+1<)81>I0U<4@s;cLX85BrUGiN7oikg~FQa#Fj{eQ(3y>Kc8fudu@cJ@tPcioJ z&l}MHy}NCXC(aOWVTRMkv;MPFUhLqW0~Ehbu9Ie`z28g!Q#6}|;s7}FVh0alO$V~~y;zkc z1dUzC2l~9u_uO0ePw;ne!th8g-qm~B5W=jpI1D!8jL`Sg{KJ4Mp3W}6++y}uKt|vF zwvXayjah$e$V0+Md{9FgZjVNf2>)2@A&Hp77oR@5-0^2XM9dN=!zmwR7f>mM-QP-n zJ#j_aP&;{adUgJe!qP`C*&jMSJBT?v9J26RvK1q1HRo5qv~a~*e^EWB6-aA*57TZx zO0w&4S#0hgnp>dsRn+Zm%9y0AeOM#*n(hA;*OWW>yK!#?4~}9R4t=Bp^0(pn#vZ89 zzEKyQSu~b#P?XgkUtT^eRp0l5vzT0IRG~#vs<+s9e3>%}&dwciSVAl;=5=E|d@3>0E6SpLcKJ z>6jaMO(4bvLwHG1CI*0Sv$cS1t3}d>Q2^t+ik24iuKilEa3&x2z4%*TERK8#eXUSU zR(W>JCd~V=$yauBjG03A*!6)A3!NdP%tPjooim+MNm(er+Vcd^6ny#~^>cF@b3h2HH zL|4@AZ4Yr87p`qtVt%R&I>tNK+{KMnnSI2YmiJd$+i>*EP%`sjNZ=fa=FctqIj+NHv$rw^VlpsTP^~44Z`YQWM8$w|8`dvXka2l zm;ByJchox0!421ZVI^cYOQ4rTu_86jKL*HQ|9tN0Hh5#V|MFj21Y!DD|I>#)$qGIB(oVxu9I8 z_`~4Nt>$%JmdCxDDae|}08<5tGiz8*%YRuS^>hx;S){R{USN|)MuYp>Cl~tb%RZKV z*sN?XFO&x>#LN)Q9OR`3#PD!_7t7^R1mHm=jH_z~j{;_Fb=Lij6vs$?usNULgxUL} zMn3OGfB7Ksviy@~OcEm?r$;IdMxmGsN6j3&&W5*8`ErBTEV(F;*ZW}gPCLHKk6-|1 z{@TpW^t%MCf#No@v6E@FVX2ureurIS6HArrix%kpD68vRU;_>h zQB#MpM*>|^sZSy_JX0+i^jr{LKW~s~JTM!%y;qEzb<7^`reB1py}xe<`?#Thzb>xo zG(Bjw@j_VwRSYI6*vO~{dgpl6#5loBD`>0Qplz`wDMxEs#|9h4$_b+!c3jpB@mI@{6XGzppF79 z4#Jm@Zc7e5_zTapV{REiXHn!Ur}XjGe|&l`ykRW-H}~s*>nROY=0>fk)60hyVy_-1 zC^uQ7WVI@%%-qO_%K}!F7d<-wMCQoT#N7~7dumK zt$FLqd}XcuZVq2r4dv>N(E71d8|~lxoM66ZqNze4rFLWgO!krg5`jcTY<=1Z4&9s4 z;KB&x48xEwZujP@oZ(vD-e~;sa%znB@(5iCe6&ONq$_Cl;j8E!VN8yK&$1l(YY9Ub)==%wQ9FV6J zzaYKrr&V)Uu2KgDPYc3JZKv}ZFmb;>505ap6}GuZpWMf*3G|ihsTP%y{mAGS?wjFY$&5VMM*2=a(0vqZaINq4<{ z9M)L(GMW)!*4Y0*W)t<#uo+nhfbs`khTv2{^gM0!ZZCW+ksp5ce2jLhUWr;C!6z1SMKZ=)!B5FmRhbfWj!sgzDW)-P6{)zwM}vSS`;J?!#$2Hoon z=E`OMeUz{-X=-cxQDNenp-`B4`e?VH`7Lq=+d63*Y63NfR0QR)_s1q z#JJ1RN-USX30s3D6nom3QJ-oVmHh&#A465k!Y)0z9Bq*Fl9fV3dB^Ut*2r2~U1^S2 z{vFHmjunn!lc-g``@t;{iltl&5zW)+cq?sW`p~De8XpB?q;i^X3dbr}{%sC2?8VP? zTq=(nYUe$h&)ZGc9lZlaZH0qpy1he6MgIajnc%GKddE{~LnSHPV)PTj5>SQM^@Y5F zSJ|)2KoK&D|Jt{AL3;^~+;lI^CsJs(^=eq=Q$Gv(d14 znsJ@kW`(jL%1n;D(LeXf$Hf?amuZSWXsPUap66U?`h~~wSfMd;%vB~zRuYc70_}G5?^lh4smQ4@yhfr|<~6Y0K#!aT zOWMAXvC;FeTu*tbFncEcya}}-Z;z9HyiJZrC|-+~_4}g)x$U#rDP0wPF(4kvYi-|8 zOYAxy9v+|$DC(!5BwWvZHYiDTZ#=-h-SNr#!6tF~0=+4JySc^NtVbRG`NU%Iwiqq0 z>96n4eq&}h^=-@o3HkEgq_C)Qhr7yX{k!5h@ZIySF5=C}vkB4PqGgs@gY&+ES={z2 zM?>$<$2|2|!(B-gMvq1^88jO?sUTQgUyR1B_owXtky6tvEULGmT-~PM>K6^ra5fbxC;37qq=z;%#r2zswTxFz-BWd=716 z!;N{X`}4ZEewd!zecx(s9sEc>LPigCf`o!Vhjaa@4Jgbga4W z3mZykdwanrd{j8p)7d27Dbebk^~c_3w}-m+1JA{8EdUn3|BG6e&8cUg)7ssfWCD138KyvuaLF&+2hu9*E6o`oR z<&3-mP(SAsK%HK%-o-oI6K=yi;6eMi6m=(CwX51Ilg9<9_0U=KTNQ$JXEwRL?KW?1 zIOCdkB@(G0nB^yUw5v70_4`Q&OKaBp@Jxo&$={&Ln7cY!8jTkm4HFUv(WPBbTYO^q z(;a;a3D9<4*X7vm{Tc;_PhVZb!_(hsZn&Y7sT>BbjfSYSb=V7#8{%(vUIp6)>(_r* zkZtqEb9xERVUUrkRP7IF0*G;N!o+lpj4q@??AP_acdoyH16X-fZlmE8Sd-|K%q@~= z`U-b~vh164nC%Q(uT=J`W)FH!bgk9TsfTiA4Lxv+~GtI~Tx!1qOY{cRyo?ojb-%sm+wwVA%X zZAc~*Q?1meW10r*Q*eZ zPtR2uKuJk?iuGieTv_~K-R(LDa~0z9j-&NTYtX)3R~H@sYfrs!*OXbvz|$|uVfbN; z>!YWJ^`AOkW6L$~NRVH8AIP`;>{|lM2A059{y8BKts7VIh!3^JWiW>>>8vu{x;efC z<0`t>pQU@-lZpQN(_CzOBcEB;NQKLUqvLDq19DsiqpdHE+U~Y;uOIGhJ^S+ud>Djk zVT|i_$Phn%`A-fn<(B%UkyJZLe3&iaM(%cwh$9FU^a_-7Nc)VmRaMe@z-Wx~FoC>V zBp;XGCFij%(%0)RiMU^+S9S|DA{Ksh=*`21{=45Kp&_@#-63#tUPiFK5UK8jRg2QLXfYs(lW^yPN627AyMI7kzY+>lWJmuYjo6(G0Zpg$WLW z?fG;zC@=d<+t{D5<-cSWhaTU@m)ib4o!dpN`Vy!UJV!RH^llv%sRT7qKwn&mEaWoC zvuZ7J#t*+k0_AJ#&NsjL^!yBsW+|HP%rx(&I7SocT($I|5+6_$JNKLm?2#wH$%+9L zzd9N9Ri)T%r0-#~mDuBKXo1B!26v^UtT#rk1>r47oc|@<#ta#YY={#NXiX#?wNp{p1D*&hpEVLWB*%d>uD}gIJc6&n8W&2>> z#)r*Z@F0foy69a;yt;#Z^hM!-I)i7cl^g4|Ti*xVUaeN`BZuBZJROc{p)JcVFc!Gx zo`I>gdVz3yYb)TJRucZ!1fjnB#}xZCKE2*MobY0PP|mC>gr4^B%TXPmnGO0Rs@v@% zZV*BeGS@O!PDx;HDT5cvY0@4_*hOn!={9ymA&VfD)I_dsH zu{p?to(C6(_c36shrqql=lf(Y^)#6i)5sU1-R2CEL;mt}%>ggd1|HS5a~k%dc2Fe& zmTHAb?fGkj{9J0nUHO5bNzVD4u4U}HC35vL7sIP0K?IoDh>7dT+G=#emE(|}+% z^Z>9^_EWv$`i-t4@6AUuZN1a;3g8+rh<-utwsO%4tVDk5>KR2rDXMnVQ3g9Cs<8jn zUV~q;19}O2nKethOLjhVH}MWozoe!*{^wSdC@8&fakYQA2{xSWOJg0d;w48PmhMOZ zlU^1O?T^Q$leDN`dS(w*UsBU*ek?;Pf}Oebeb*9=D*c@7nt|~ue_J_Mv_NibP6pw! zksob8xW1%2CHu0WZ@&~(*vfZ09LV4L!(LvQjWlgS|I!&$`ts{_C{9-;r$OMC+3D$_ zIlFdiA#d_&N#9?9Bn`^6^4!)gdoBR4 z5SyTzx5>nO-IPBm1mafpNU8>UXMh5ZT7F$JM(M*=)m#L$_Av?4@na_ws5xa_fgn z04IzohS8R(RfxziAoa#QZ_LpU*RrSiT7w%pJG}%q$X2~*2MK;oQ!c!A8VqVTtqaE# z4rqaIaYOCFPu92amZh~aWIa!Y{Zgk=t(=_!RX%Y?plQ)`&m6Cz4A?J12n@TA(8EB; zLum7YdY&GpgqVAOXkBX!=PfUz8rV3n!q;byyVaxpSwTjRNPcSUK9^UM5_oWKuC9Ss z?o|O&yx2u#fQ>BSTiGibiU*VHKZyAQwbO#RJV@PXv6IqAzqMA~^>a+!6sC6|PCw6C z=jKF}?k85RunOG{)BDN5LFpjzN529lO$?k}KYum5h0}gnxzDmsdTWv363|WJYj~^|2@i24sHk^n(h9=}f z*!O-0S&B8p3c0xT1(stwoA%24gx9zr?UAS3r}ty|ZQrQX%++>(ImORjJie{&=~PRr z4e0nJqSqO_UCWp9RqE`1u2fdI|5`ob^O5U3?wlK?*(cxTwxM@D;J+PF)JpwIC=Vde z6RWR6jjJt;Ksi80Bc-3=w4SyS;6hFfclPRQbs$0&VK26101blDgEB8j_w5)bxP)29 zHF~-D_`?rNEo*jD8#D9iy=()!j=FJl#TiGytJuCnV?LM^xAVrrz>91orfYrBXtng}-espsDVQUfJHS-0uW3>kW;>FcT z&m>fg%beZ7?Wp&KoWbq$n4cJNnL*9}%59w*z|3@DQLBeW)t-FMz($MRMoX0&YRQd{ zBg0mH9L@f!9m<!k!|kT@ zB(c5J7#PUD_x57O zg#FIX-ZUFr{Z;yXd>)aEH(}0?RSk1G>0;OoYkPT@uAQ2>r}7-NJ`=6jpEI9b zNjlF8Z9g+tyGUsMyiE3nSXaS%Y6}~PH%qt)lV|JN>(h^ik~P&EFHXTWEskwvXy@xe z7gTBh)q5#OY8TdlM_O7mQQzc-%NsRFjmA3L#)ggFnw>}Id1OXCwyBNz7l@WY*pT-=W*9af|`E~yv8$^W}C@8R{=Cw``)_j zPx-=X&?t5#v_5LQ&1*J}yY#qjN#UonEk^LMMwcLR?~WCu_1@Z%e=~q`{$T<2Oi7;cN*5# zZxu@W8HHxk5hNzkcMk}bz1bUolvG+;v+ul2V(1J{n2yWDzCkgHX7T%W{KL5hM~mh#QS;Q25=gReVkjWH|^X|DY+S5O>XfS!Fx+w zyxhAf##9qzE`;}o%d;I`VMt!u?}u$5 zbpX@z>+miFukGQH#IpsDKd+Pb!8jof%oZ|HJOW|0WIPw3YQ0pLp!t5VRjO3cE*M0$ zz_uF1>HD7E^T6;ttd#de4KyYZ?@)1SG;TLzOXpO)tZ%!_vPhT4A(HQ0@vhq87gM4j zoLSUbx9ZaAd3|$g=kgfdFl+mT=?e!?6QEo|a^}E>r{AFtv;uO`+YY+4%V`LG)$1@q zpCYPt&MQe5TUqHE-Dib9`O(Mi5BC`C83@J|=)AUC1`U^7(Gh-r9sl~X9PD*Q=PwKc z+-1@}_VpFU?t21kt6#X?%hbACZ1)>2kWn08ZKvjzN9e?uu!la_ws=&bD@mXG+YO4z zV#S{u9b*H1E{GY7(si}S+OG@o(nlvMO1Is3m@e;4bo=~_^&rh}vv~}zG_yGa_QCI? zKorV1@7ey(leBxeOVzYdkKexpT2+eTfihBv-gSxmYpnh&aks(W@^z~X@AhXdY?hQ= zD(z^bva1%@>|BrU9lTbQWr(DcH^K?NFS+^CTGyd-nynjsnd!FSpTIm;e0KzpspewV z8E(hs2kD+F$G23JqRT@Khqt(JI-F^U<1VdtSFpOdnTqIC$d-D4^U`fWZjb48P&_ZB z(-*X($q?mX?qyabu)+Jk%bdhUc9z`pYoYL}@>=_9C)5ND~V9 zxc?IRN~cWK=VftMLG^o>5NZA(5+Q?=k$(DXpf<+ypy{=1^PYs ze(ATmPjycng}v9BbBro8GOHbJy*pfkO{bmXPCX^%@VKK6uJf$Idv+Tm)k~;eU`RtC zr-(>KY~hRi!7b@Y(T5g0csf5hztnbvjeec1Hhrt5y~6^^!7lFg$v*5!nzlWrDO0yw zU_xK-EpOSP1kR!fTKn2;yM1WcQ8;&}R#Q5K{mHZ5G#m3(1^ZeAba}iyu9BNSY)~)z z%){Kc7vx@DFPiw8N@}8Zt5hrG{Eb)f@?NhV8o2&G-rv9Qs2gYPeO$na$NDRCu$`7o zjQF+Iw$uaf*vF{nu6+fnofRQ!!cDv^m=sr=i+=(g&MPa|M${D|0Ox#TbYiZ+w~m%b z??Aj!L&yVd6(|cA{6-yp-j9f^qQZIXRh$uDgEt^|(COY4Z&=%*rAF6}oyFxKpqpAlmqv0s$wyyoaTxnz ziCp)z&G2^TcC8NP9aM54BP~UHeFe0A!{DAib2GXzj`>soJ~&b6USN}mncusC_B+X< z>veo)STQ~ikwNI#m7^I9v>&ZAJ^$Nu#jIm<(X3~+Rb=Ha4~zaj7;UF@>8+GpxZ*t4 zG@PrtgXMSW4|YO6X?`T-o&Od?I4Ko@I$85PNxwADO{(vFmc^1}M+8s<91}c1wc^HEK`%iD(?LI_!Rj-QI-Gw3cqlqnL8{s2Ezx`9b1@d61zG7Wl#sq9d ztIRycEd9b3J($hx;bGCO4$q_aEr##fFURqI`$e3@uCnhFmHBv(bgZuEupNRQvQK_jH*KZPlOne*VIH@(lklN%hGWn1eHKLX&l zVcZvZLgKZa>-Eup;J3z;gO(?d4v*~fJKdp|%ICf*3`^Wa-j3n4X_5sv!A=W!r#ljb zs-Tulgqs-atmfuIB+d<6Ba>>!~rn z*;QjD7^h{#0 z&BCWrJ)_^Pj}q{+l(EZqH@oLdK5wXbB&axghZ=qli`;mMzu`<3>bblsI#bMql7s#I z=cJ`vx!4&BNr72yuY`#pMUuQ6+N~AQd7Pc={IIOYMXfR2Pw!fOv4Z!0y@AhNx7h4| zj`{NTuDzKUYNs2$@HwIP%S(y2K%_04+2u~7<>rb1j-uzg>rMQ4g|@4uE8G&u<`Rpi z@w76Pv$Q1s>Nfcq2`Je@)mqX%{BI6(&549pTY}xaXyhKVu5dGlJA108(f;Td{Zi)wE#`u6OoTX3nl2^~6JgP0H{X#sc-T}a*7P0lh6ww&3 zNc^ae?y429T)qKZRy%&G+lE_bz$QR!50(DYZw6R;Wrg_-&lyp5d^nB4G{U+Egr8WmC?T?a4=T>2Jb9uk#|zL+#lBJ zF&hY-F%JQc$?sg+ibsibAG1Xn7RxiZiwUX=XY_uwxPS5+=Y}2{{na5#GO0PNn5q7C zQC`{4jlbfr>&oF^Hx!fyt3veWICKx+uGy8*i6inrFbl|NRB9 zqKExU{U){|eC0HIPQ+|Sy0a+0*IdX&^9e)ww_2=L3BJ=kpXv3(Up-nw*f@dq^ptIZ zaVo$H0%r2dsVM=(l$JI9?}0N|KP@xWGV%McwlN})ETo~H+&o4Mi+oB;uo~Fdbzku~ zTL3H?zUMlStApyFcyf=|PtAqj1|U zFOnBW;wpz*SUw%A(^)(u4hew|nonWK0t^3wFWTbm?cUk&ZwskB31MMdeFS14GKG)k z$y1(M2LdD+f9r&}vu1fEM(ow8-P-Mo`*DWkFnSHZY*U_^W|m9^2Ck!1at^-CNBnC3 z#JK&vsTsP7#tXNM>{#ri|e^0y-J##P4KI;3z$a%5i;^s(yfI-EEki5<2@4J;00y+4H z8C?#;J+uscMgSbvN@Ph>TI%b%z&Y3u#FR)mfPH14e9QD`)Mq31yOkv7Zn$GPe|U=* z?^)FGL4C(rHMdyqtLQp%Xp%3W(M9YWOU}ue3 zt-rXd;;JC&$#I(^ulr?jcog}yQ@rXHeNqohXIpo1ycm_tzZtb#UZ<7A+=aPdb0X6T zeN{M8x}dXim%LP=J@Q===L-BR&w^Z#{tBtzBQGg7ReIfPeB15>&J-Iru(>hiIo*6K zwN{aNysS37My_|^ipL`)CC>->u{gYPe-}82oF#=C=e7RJGi_6S$4lTAw2aLoD2b5m z348?|_JTs@y97khm27uGOCZFpsEwrF{tl*1e2MckJi+eBBos650#FGf=5Cpn>;;-x zce=c>MWb?aE^e!zPEyz0=O9}_I-O>NSrV1Muo=0UyNv~fw2PvS9)I2Df-D`CbE7o5 zq)DNe{ptt1>}`mZ{9T_`#mF%|{kd@kVOIRAf2y3$V`vdh>ziQ=8jvfJbUIirts#!a zFML~JifR-jM$dlRFyyVPs1zy0!%VCit!wKu>O*rD3+Gt=@XzcW2;3WwCs{qn@4 zTFC+qyE_eFtgrlfuF4NKg^ksZTcLuw1M4sU`gstZ44J4}LM!JyochX$p0j4R;Jy#v z%p&^@wu4fUE5{j_>6?S{Z5TD@dzc23Rt5&NyTk*H=qUUlVWm8JhA`9s#AuQ14qD?? zrqM%hGOpbdq7Do3MX5IUblNUt61G}4I+3TK57WJV>K=^8WOy(fNwfuz zn*;2awa*P+kuv_ZJX6i_7<-;-@9vp^vK|J6d4}AM>y<}7OMhy9eIPI2R}Vd5trfiY z9hV}ZtJvSdhN&MHw^n|e2R>LH^H^$NEo^N+thHPE zZMmN-B*?M;^^uhyfmwKdks)%PUv~O?qyE*el@83jX%OMI*3Uv>-gKw2!P7-=1am`3 z{_%@2SobS``kSZM;KJ*H|uO8ICvOZfM$n3#!7jl)MoHakkqOp51S2wE7N zqDI3VD9rign+BWZpBM!%_eDS&s^5KIsUg)&t6 z_E^|$fb;RT$-+54GK!lY&LZY5H+j!Mh$ecD^sWzyK@vEswRYO z-dL7;6g8(feijEbX4$muJLO}oA~ehWJv`YVcQMN*oBjA_KFP)H-!piUKMjhd!1yb_E>vuermI)0p^b} z3FJ(qnE@xIV@|IB@ayMA4DQE~!qqnIZiDQ3)kX2gofheRu-i|+*h~vamapV;x%QCs z3gWCNkCxqdIoP%JuOe5c{ClcQAGp%l)-GB*$F~SmoNb9$(GKCv{~7PbSFCV=%lLlk z7Bx?4Erpzm=1ca`0NieSzzNx1x<_wueXd#rPKfm1L^kP2uk5=wuQ!tsEPfQRIUJW} ztGo)Chk?Cd0nc}Z>iaaeRp2}(&Nn~5vCZq-_Go@v*gu)3+aRfocL(y=UG|E96?&$k zyb+vQl)`p@P87Teh10gb#OJIk*q7q6d6+{w4yp%|nwo`5fAa~!jLh{%3ryt7A-s{z z-TQrZe3gqPe5QK zCh@tR?17x`no=M2l$o5({q0{Q-%ro0GQGKQN8W|ozP!#FWx<+~d@(#>2z?oqF1O1* zEAG9*mYNXS%w{)u&iGNpc|f!uEkg%Z5O$ zGN2;X>TIrzb&~EI2!S>9Z@+t4*Ygpo)Q{tL8q6@(?mUl4ziCFYx%vBbn>9CvZGyyw z6OQ(l>VkxTB&Qq(^N$jmr7_iNjXb%&F7w?Y02?{2w8qv6u)Nm~iTOL!9vzj&OCnT& zEUte;k#Fx0*QwKAgLbZm)#wSbnBq*2rZo(5u)S_0z_Dgi-dK{Q3$Z!A()5aj&t79( zP#^oMVpEnD_Wh%^7V|HEQP)@2_%F-y0AgM0w)Hx)$!nI+0R3Ob4L4m#k9?o*CN6tP zLHz)e0k~N-Cj9H#x&0#Js$jAH8Csi?M&$PQ>2|?+RHc2aJ@lY7xXmc8#OGaiPwP?r z0VvWoRGK)rULZI9`c9NKzslB^MXc2){rm0b-WJjC9Y@`0AN;$&fMYdoI=9uSF1%;? zUeR6F;dU9N{942&JG-r9%SSTEF7;})E_@!)Q;J5{LnJ}~Oq#0;$r7ds7x##(l~!bT zH%;5wV(Qi>kH0%R>jm!v%*Xaz!RYMwt4T*D-YYR&EQFFegKzDzqPJRDK0oeD=a%w0 zbLT~zI-0m)=8^oj$bagCegywMGro@PM~BSMcRTHZzugC|`DZMGQJn2oH1%#MuuW(S zxMu(5%TfOT4QabLNKU(J1#KyJGcNIM`dpHyn7AfkYCXgqZFBm2px^N*B3`yMN8bJ91otlN zSxUPY?aIO*2DI5Rzu!?=ztYxz5oCsct-&+&wG4e6dQ+^+>G*9~{8E3)o6W0)8%(9i zr<1!6L*@y&zSW4{lp7JL+jr!)d#&c>M$r54T(>o<46`HkyjG|C3dL-5DC~i{Rp>`E z*0-nyt7DH@Y+fbHAHKNr^&-sp;28xeRXZ?m>nz`@a{=IEUvO5#8Rj;B4S}NwF?@CY zIM_pb&7#ov+EhP({kM4+lG%K+%}(G|80C8F+u#uvKEmptk!Gk*%M@V zT7K|fcM-8U>2dUf&*`=qte-Wtyb4#nXSs_=F~0Axk3F=cSEbgr@tm3W=YrEntE1ds z7*)`Mw4g{Kh&XP;iE-M-o51|gWqKcHcXu#)cb{;!Jng=hOa6kx!5iSklp-+xYtnxH zRNSBrurBU-8)4dL&mm>df$Ty%>e|-R3Kq~Es7CXlaZx@^Ml}AQ-A>Q2xdKg)&+eF? z%}1|$jk4w%wS=j)&18kz7!|*1;ZkSPicnhb3A#B_iU8S|->bij+UHgq0M3kZD}@nV zv#Rv7MSt+JKC^d`m|qV4$+vrWo%-5snzxW(zbfy$)Of2(jqgnc94ovlZ?S&v80+C2 z;QNv)Q=d4l+QW`d z*q0VtE}pkmw`=TH>ylV3bo+RKq*H_}L7Pc3eX7~58Plqv zsC*~K*`1F7JF#~RycPTpd^%Sh@?+~z>NV4z+gCbWE@Rl|^N>)Kft9I|Rt<(h9+1ss z$;vy$mnz=hTKzQ#rCn0D$6mg!7X>!oE}ei`Mj>URRL`pDf=P>uQSYxuccrPsy|WXX zl)ySNu_i7%8oSteaH)^2eKaRTeaH*!?QX0m*71ZpKJTaZcmOdqr^sCWyGq%sHoP%^ zzm&NxO*DpYh*)@GTj8?xi~2L|X=Cee*%N?U7sDNy^OM(iK)4y7(Cgna2={ppdzslwPKvVvGn(B)o*bY(E9~Fc8cA&#S<}nV(^TKCw z?o__PJJ6om?qG|n6&cB&mMc7!``*Cv3RKt+OYpfNZIbHxpvtYT|4kJR8x+Yt`Rg=0 z>67i0ISu09w0kaP#B1Fl*PfwBL0 zZyaT<(YjV`1bqwwi0AoUx5aU_x2`3yX2|bgsQS_T{-=QVuDSBsG9V2Id!oxs$Z7vv zHaBc4eJ+P%?e=?md40kQwy)(G^1&Z(Nxve%3SXT{sI)Y%XbmK@H@V%N zxmDQz_MhFeR;r3Ozl&^O>QHo_m&@;(TYH;`)>b9BiC?+ZaJ6aR%fJ#5G#LHbsmFHE zAno_MePBtk=&&-&sfQBsHm9ZcpiC923t-(?VhTQadTCy4{}2Fn(g?i z#a?o*^;a#s1i#@Ro&JZaH%3ojTYV`VeCl;VrX`yrckH3$fHX$fz-uF1SMGit>Orcw z;Wo}NxnYM|>ze}7Fr zUD5W;zYU$jbFDJkXC>y+viV1S(Z!&?>38GXTpy#o+&Ng9pp`JY{Fa+t;t~?U!-f{qDGmFX=&$z7V_E}XdWD+8({c+Nt6NB0i(Xn^gO7Q= zt5ed>a1$5gY!{_Mf`@ELo%dlgmn6+$X@iJuzERe_mva}ZaFqE_nu4-M37z5kn(Hm% zU_36et!`(>RI#mJt;5gq-rY+=F0D>(N%^`pUoD-ej)^N#t+X6;rH>y91Gw?{+4`K} zs-Mg8@xVGSc{gx3N_#(i`O+46R`_`@?@3(TNj$j2#No2{W?!90KSg*j;leXnkE}3i z2w26X6>2^u*qg`X4$Q8b#|cMV&ViJ_5rk7Ww|X~kH_NSXtL)_YVR3f3JikkT=neXR zBtyGB`-Wd9v7gxfs^6s-?Fp-Ux)P#)emtim@6)UK zo9MGpi|fBN@Gy++$Fs4g#OV1N-2b-za^EHw6zGDbBN^rD{SQhH6O!-wk)6xQ)jf^M zBDsNkrOUbJvIylv#;wz($J8aF$Bc@b-tszHa8>g}np0V%P@u4!rX4DxW&erGYDZ#W z48J~9mu-~tp0(lGSJAJXR@Xw2$p}Qotchy$_8(V8VK$DeY(NZd6fQKgg%E!2X!tN?=|ko!s7j*MfSy^9=X6ugDhdzeF2KPi$c3> z(HNEr-SV~CoVwj-Irdtm{PL#@Em^gI+%kh}TqS7> zQ?Rcbpaw!7@1Lww%Oe9C*_dARq;gNLwu~Q#CN;ReqTtj0aNoKEGv6z~o0MfExKr#u zpXE*MP3+$B7{93(i z_-teU@M;nLTT?;;kO*9yt}rBPv=&@(IH9T(R8+(^5I70XIUXnScz_Ne)rn3U@;`GO zwQ2*X&u(ead%6Hr_v&1jb=9Dh`}1dCVfyHWrBFHKPr_hNwXk?UFUrB*&3V|uVD6Xu z*~IX^j+^c9-2PaN7^aDT2m44BhdtPfUA$sWxWL2MC>3G7`CuFMcI_v6ok$ znRdX*wfpVHx78?KOg_I~_6ru2_@%2FTDy z_E>N{FMZVkP0Qyl5;VD`wgEb*Et6TbatM{9DGAt1!JKy9G2< z#`j(Q?>%$S$;&Ape(>;FF_F%ug174NjPU_QxQ`IbsQoL%x0~UVo@@BO?0#$U`RH(U z?uF_v{5?w6X86r~t1XW@s|Rm(f^+Q!rwgScjZlMFr~LG>-+xz&zr1m=qT-1mhw1K> z@dI7~FI-ig^{8gt$1p21V|S&sK{7M%Eu^ubfg_W6@YC!9p{McdRN}Fk!c3vzuMwX1 zRd#D%sy5ybt~yIGi1F<6sflZ+ZYg=oOWHd`CLxe?Kvd_(_{mGanQ6|$v3YOW^ zXmo_g&bG zFeu0P54we*GIOlM%)Lsg7O`R8dhXQMDr%Gqc>8(2n1Zu!f`<~yLg+E3k$-KD_ijP* z>mCcH;!j3C7{{%ykQ;Z!FGuH=R5#*+FjcbxMD9I7{Jq`WN4@gn=}jqIKgULG)|{kh zU)YSpzb?Ua4lQImXvf@ntj6`HJ?QJ&8=hmmE8f@0C0Hyb>Bqu`x=^YWGwxh?jdG{1 z1lhdtn7s-+cvJ6fCyda2WxzGgy~iQjfJ=hsR~)@<)p!sZwsKnpul3C%*`DLa>Wn-h z4G=q1kcX+1`(m6eua_!r=gzg!@(bZR(@cKtWor-$yW;CC{OnD zWINwOpR(gKwX5{^ud(FUJL?BD{EQ(^(}izWc1Pv2_obQA`|s{m4sf#=vV#}Zxua`+ zZ7xoy1KLiuIQnPg(>n7zP^mayxr24N)Sv|=U&x1-Mo2IbCl1&9+&ZXOkT@W4wmUt{ zhSX|u*a@4N(ddyMUIINI}fO+IW!=8tFpF4?Da-xWaLaXhn+h=ZJ{NcP4lK%@_}wZ}^byiKgE^2xQ3jzNgwPkvi7>;@WYbV z(fMJ2(Okd00qS?JJxgWO727(C!a&)Ce#VnE|~U=PygDiq51c8dg3J6 zEXHGPQ9mrX1_EzS>T@tG)~_6ELsl(@wS=peYw0h3TRD4b@YhX#5OrX3HEcziE3KV> z)@!Mh4$ZH)#a0vGFx3_2J}^^f*ty!hZ*<_9Nia8i+Jt?P&tkG_x1dC__&h_*ZxXuK zOnJJA8+FOOU^{cxJL%~}u2zTr3T#DZ#mOX5UxQtYj*u8034T~16{?Nv8@&1~>3ZJR zo%U=~I~)DUH0o4uK7hi)qEh0Mn%`qCDQhkt%Qc4B<;B0FTkVqFR(yAZCqYj+`UrD^ z>8My5AqsU!S;S0;^=wo)X~*c--42=?_B8ZJ^EO0&jSi*N=863AGf7FLN1;$6WXc$p ztHJ(RXqQ2482gCEoDPRzDW0c7>3hMn1W;zDU7mo?*u++;QITH)lgt&D=zWz#Sa<97 z*ZCYk%Qe2LrIxe=?}0*lL{I#Fjn!n4e`lK{hNeNkNv2j~D|%Yw$r)-L!R%@ho!VVi z+I4zSO0yyN@B891o@Pvv>v=f@gBSDk>3s!??6>NB6V(xPoI3Rv?hZWcEj|MvPM)XD zF|ffHU#rhgGgh~so^?xYqMhPg&gz}S%0ZD9)0Homu-aeK0!$1LLiUP?5M2uv@aBP~ zqR;mPg$qzQy0Rld!VXPii3PRNUFzIl#CA4%{%(@+jt&4_NRarRAYmx;E0?~V39^$b zSIxm`MK)jVzIWheaN{JmdmoaJ4E!VD$3o&M75*T?0xr21(Yyc0uV?M^V!4Dt`Cu~Y z6}NbO(phBJ*o>pPTq={}W}dwNHJR989oqTlu-K{!ppP4d&@}@yIUV1uVr!@D?-ExA6E4(-5;)H0Z?d->WGxjif!u z>2xu1Y(;Fb^HK9YL6x=nYVMg+e>&G@(4(NW2T-jP86hU){I4H8;j(jbsCD&5)m&P- ztA%D@`Y-6d?YLq@TLEl{J5b4YQNXk|dUp)P>tbPjIO_^lG3KqGLv?12A7+fAStREq zs=|k_+~Td*z1ZwR_M|-t5Cttv}AmdsI}HCHU>b>HH{G>eI<0jI4sw zEq149_vbD3=Qmk#+WBz<4Y$khJkR>$|F9xHBK z`wOn<$b#C>B=L*$69WwVW-;$UOA5tu4d|dytG#D`=qb7pc0$Nn(`y9_m-Ywl`x7vS zc-8NSqs_@NC{_I$8*UruI2dWAXPbjjB36j$VpBX4k^$)07WSIaZo!;Y9xy>G72H)qFEzgwMPd|vg#S6NXVkGc)Nb{F;2*AbuJKhbC!ZZOG)0(K0`^U;Yx>bV$8 z8Sy;FZtxt7cW#;P|Z$@t+Ek-{`cP#yGdkb{``I(Bsgm#51 zrU405{u=J3CiK4fb%)6(d?)P|c@3cQ6KV!8o5*<5Yopbm3x3f}Xn~4UYd`pdQfXT` z9$oharHAs``Tna2CsoGgi`12z1GeE4ce=w)+AJ( zu(qK`_b;_2`Xw67$+@>Hwrnm#yeRHrc2PN2RN}pCJ@nz{z1^!2I_&fwI-d_hXbqPo zZ?`HvAe}VDIvk|R8zoRo!1uOp4cm<#M$SIHth3zqP=W{=o{Q&lA<5uXqcfpH(}vkP z^&7%|KLGs@J#9UJYdgJS{n7>eT`F>~{Z;;6jy*zO3q2W;`G(z?#*HhQy7t!kc2=Kn zueUq_9d89gzA{|jwq=QQ-5(!&C})w!{4f)^CLphrJSvdH>LnS40W}%s z>fNlF3lDeqn8IKh!J>{cQ2Xp8jG@Cr?DyqH!ziaJJ~TBb-gB21 z3;GxBT;*aw9lb#cRQzQU5Xe$~JbLo*9J}Z{=}xv=NrElzhnz>Zi}GxIpQXv_kIcc< zu!z*~9eHDJbr#ErKKAW3{`xJEvMr1lVp&;kB&*+;E&%|dKH6mG>C*g8Y+U}V>7aR% zdbPp|W=gFYI4%H`*ozMSA*j2<`nJ#0uy-oukh>J8>-Iy#(XMoWT*boIPJ?4jk0rrl z-Gr^b_i|}^J3SZuqc^Y%pGLb&S~@b6j-cM{XNSMuN36qV48Ar(C4GGE9p@NW_)$#P zG(SNEV=Ie$0G~E}pgvXC*faAYm1lS6d>c)g2o8bp6l61dr(}=2`eNtJ-*9kJf4UTN ze4i*xH4uF1jow(Q!gSPaMYn?Ec+Effz!ofJe%cYuA`zeEEeifwZX)+~%f~$H^MT15 zl}&EjEhmLe)^6s@-BxQ(Zb`1sG#o9z!5NwWhE>lp=+X#(%EMwh%oflageOdkSMFQb zNY-!9VJ^QtB}s2P@vX_S)N8H|8ri)9--H)mbM^HYJy3pZt~2BO*`LP@Fo)Gs>(84N z6m0ywFqn8EIYWOAT?*=|7WkjHRP@78NM$RZwW>z)s0 zb*rbSpSqX=4*9Du1NBfg*F)rkg&Q0Zm-;lE_@(4^GFV#K5T|+O?CVE4iK)Wobi}Yn zkKiV7<6HFE`W{n+yRY1BqaLcu)@G8dt#aijD&evAgi49mW7f_u9H3`2VT$|SO$K0S z>xFesJ6}J`QdWJ{qv6$Ifs0|OTmVwPS@%)xd*Q7VcIS|XxjEl9KH$Wy&PIpkN-4&j z1%Q|XTzkwKGo_GzWE>cx68V0*r{Ua+`D3!M?EX>yb%r;Q^`C;u#U<_;Tp=_0<8EK& z+Z@xxWc|6*TGhd>5%k1Yx#MAYkRG$2cMyTn4sK5-l+ftFJr!n5O6gBlEQ29JDR~sy zpi-nC-|M!P-^tX}IGtBsf7P*_?Q+97&gP7*D*&ByPH;D94O~WJ)$_GBg71Fr>0RpU zhH$!8-okhMO7Q*F`K!vTCm(@rn;$3V(aE}6zv(qwYv$gs=l4c+as7N)ZE$*Er_LzI z!uOa{4^_F*zk@@Qb!*u)MZgrgnqF3;AaSR<#MW*7R=Rd zXCb@Vw`qTvd1&2y7@L4bIY$^)aP1w%j4z?Wpg5rvAj`z&v8i~6hR|8e)Xuj~b3fsdsNLA1o1I#e=WoB-JQw$=yWn>U z-#%rL?4f>*o>7L}B2U?k}q$5%Pl!2v{TeSG{^oTEN zgEExiV0KY>KD)_uw;R+$WIBTxqi+qo)Bwffj$ID!XM7vgvu@8?U zMi$E1Y5#*MzlAAGv2o|JkCw=IxG(Y5 zM)icv`}Xwxbj~7M_Q!0TyS--sejaV!6{;G1!ItM9iTC1d<1D65jqB_$*GEK?9|V$@ z!4((|B3+7}pB`Ksfo$CXx^bM;I0Ko&JqIH#S@U_D&AWQ@<`Z{MSPH&%FrGv1(8fdTdP^e~kXU0RIAFvwVL>S-b!-?_$J z?x2;+FCyrlJY650wm-@8`Kq=$Z=iH%vY`dPg94`!KPFJI@02wA_l30t>|KJ2YWCFhdJSKJQngAuR{-`VJqXmWwNWFHE&HVpZxXcR6nC{>FdZT z7mw3%z@j(m7kZzd@Y;^6RR{T6E~(0bO|BEm<0rRp4IS^rGpl#d*|!zHHlqQig)iO<~H_8bP{0YTQqPX#3<0 zm2a<25UEi56YAOxW-pZ~JYgbk{EQZ}6+9-d$RWfIi%GeJr>$+aa*#F6*dJ;Vo9T0W zhC7Aty!0r8m;Z4QBn{oe~6O)zm2O2n4*ATo6DSit^VH zcIsU}c6%do+T+J2@HVxDKNBK*P2PDC=h$VKsc+aS~=#4s73|3pZw1RdKT^A!dvn0e4W7tZTH~! ziXdTydae9Xybhmq5Ls(jqG&%ABC&eV4qnh3ub+#5mxGcLe-ZjrTK;odrPTYpqBOGE z?|z*Euv>`P0`iH>Ar9Swb#CMf-t=~sK zRU@fK&oku)6{cc=rMt&Wq=xz1>^r!D9=>R3SmB<}G2JZ)m*8=5oyjnLoc}X`4EKII z9^5$1pT|RauRX@|&+~WDwoh@R)?;nFHxOCD|(lzDhlOGSnII(K^<$`pr83$q%JVf~TQt}1Vw$%_S;8R>--{bl;P-x@Q2 za{KC?lv34ud)@P>dvh)ocr`zYy<-@6?&Hs?GmmeRYCZDV9?UKVnaF%_!3&Z|1wt*$ zQ%f+2uBP>~5)2GMG5z~Qnw75GN@>5`px>UT(8$1Yj%*bhJCz)nm5y&Bzfs@vCTX#e zMl`A|9);5{ZKH>tI>5K^9K*aKdgN-ZH@#ivcw^W6x{%)r^-Wz>5+DV~#JreqirKIL zLsnJDfxXWtMX%aG)>wWJqNebbXXU2)qcf*9Dxajw(ElyY6uKzncF#*eoG>>a>1|85 z_onf&r)9ETQa|=_pXGK-&Dl?nS-HBHwdskY-{@*V{=_8H!fyD>pfjt`aaI&f73Na; z^c~@?osu)6Nx57@Zqs6E&S=}v#%Kc(Ar%3Ph>S?PCS*;1X4seZW*yme$GD7(t(JGW zl($oO)7YQZF}N0DYu7c7>Np=RgDryO{rjjMFO*j8pmXLihT)QNLR**&K#%A97Tf@k_d2|3JB(PxpoW z;*z^hj>~p&{s*X{U~rP^WtFSZ-A;8n*2;Ktdlk5)X@`A%15f_`sSJY9t{(g*8GFbO zTaK7!4KLK12De_#C15de)R92XcYm&2U}Cwgi5pXc+QJ({BK-A83h6u<>gg69zaXW> z8!QZt9OwN-5etvXx;cf3;`vFXJEm0o)yH4q`K(}aK?k~7ikC)97q;rluXdSjYbLei z%tCSH4bN&W{~~nPxLezz1j7RNHj*wOr@*Js_yD8 z=3#~af*=We_!tZXfWpdDE@npp&%s1punwm&(F6;N_2ik^VI9iRaoIill!j#5zc%+K zvu?gv4sAtla$xFGd{EJJ=RQVYz}dZE7r@r%3x~GgQZ8w2Bbalst6Hu1V?DZtod$c? zC|MnXFQ6~Jw1~P{J2o*WI$<@dIVg$x~*YK29&<=mJ?dfu;Isg190 z*z54r=R08ic4kVvzfxc1GsS^+K1eXFd~2Cr!@BR+O{e0@wX3ET6Io7AGw9IT|658V;U#v+twm~otUMb$m0`s)Syb0O7k$bM>lSquuI4FGhMuh1+0$5u^(lBGKb+l}?^`*O zaVkW5@oFbqY>m^Vh`37!t@|;o><06`Y!m5(W?`(Fl}sWw=%~uek#mZ1rAV{b9uQCE}NLV|DdSlHc z^!-bHJn?CU%TU#>-WL>6hc}vccVHIaYjT{;95#Au+dGj;J}_%rlbV*X*k;`@vbh@x zd4)+2nV%_7mWHCqr5tsw@mg+V+Lp6=Z)I+;=%WQMjHtG;vvn!TC}5rMh+hx7F=pFt z_f}#q)pfw4Z3b!kP{|4XqO-}vj6F$*#^)?P#Hke*JG?6&eplITN1q(_Ek~F?FS}8m zbh~YBQBZXaoj}bUHR%R1_tiLIX1a>O4&`a}INbwXNdEL1DWP#!8cZW|-c;b`CITmp zLu12I+=C}%T{>!$fU&u{5}Z$JhTS{?%5-XLj;g$_XbGm;_gh7atEP2SGFGrpxm)bS z;D<#~=MonUrA%{J?5yA_PA#poU8`pli6b*q zO$TpWt~K$gLsggse*{-?Uv-n{-m3=N2p0j8svUwOMK?T7iG z^~Q0|B!pbPv@7H{23DcUY?OvMjJ8<^Gxo(aJw{QyZiC*=W(=NrPJvXmWJtm2Cu5!E z!1(75Yv3N^#Zoq%X+G3y`w|-TpKKohF+W@2~5p@2#Bj9kg(peM0RGU!uPIDGoxACeTX$;mR z)AG+HceOKvS(}7iQelbpAX^beDs-+eBiTk$tTN*nEW>-%`^jm|QM;ki%u@Ar!?uFC z@%qUXXt0^?Q3)IpAA_$zLA{!3D(gTucV2;yXU;HIn^F@w+LZ>8q;;Jy{o#|9@8;mw0`48A?#l~B5X zSqN5Ed0^9N{}^%Zz?(^5Nr~5N)|PV^nQ+HKSy!PT=}xD{^Z^@rw<4{4z>A&lMAycg zRnXfLuv(}p*x@r4UZ_FOyT$GqZdO9bf8n(|apG?2CvkX!uvZDaVqHGJUl)%eAB(}W zc&|bGIB8wEEU-fFcoFJj9L%w&s7>IPFYQ-bRi>%lp<6^o>PnkShZ}0&+1~?w%sOx| z&6J>QyI~bRi`X@s!{e<@orqe31*R<2>Y7k5m`zL}Zy2)CmZlAUX<A;<=pl4dK zwO~E-<eCRU(m8Oy~^FFjf^oRYw(3r6Q4E{ zYiL!h0$)MkcE2oGZ|oc#uep(CXIrRPcS>p^0_Re+rhxDLVr!c8I=nl(z22C@KyR0} z2XpLSQaSk)vc!k_e{GFHvv1d zG3ddfnB0N~b{-6;v8>t-^9tlg=JwI;sFqgqtW6zeMr(JV0wWjl(l~0E3%-RiW6KX} zBWwJc&uF~W@H}N3E~O0zYf@~FFwH{5dT{pIegzBt(id%K812LR#iq7#K1WIGc4xXD{RE0``$s)};=tV6;%exlKAQ-aui` z_dpZN_ogN=>-Eja`E})wX4URxuMNHmz2Lcc=?=qEbX_=D*-5Rob|oC%O#&vpb6WC( zW*g55*RCt>f@vdb#Q@9}P`L8bdEf|>ygBt-g{GD>_bhPEq8J?~?4D&=Sk?j#SV^*X z(d)YLgBsp1!gk$nR1-tKzO84jLAKLK%o-+VX*CX(+~*T}ux^~$hOZZ}EUwq8HBRA*b!^YwT+^WPAIc|9ggN;rnw}j(0lX2%Q9y}dRG~yYHP4!&t@T* zu-f1CUiN!-Khw5HljJa3&_{W%t2Zs|a8i)fCIjXx`z*E#C|_n%z`~xOwd@nq0qsW;nch*QGvlU&N7@2@hvoCSilyx|T2^`HOhbLcbcx=x6vb5<*JQ#wt&1goSg7L+??&=C3tE#v^ zmDQd2srI<8&U2f1QY8(Tg|$id>&gH%^ufjFoDOslew9*T|O7 zKu_4E+gY|N>anm~jJgNW11PLr)O*9A6|b_Ee$d|$d85_k%mu3f@P3^@4{zL~pD;^x zF72$B-HKR7^l=u8v*8LKLaxp--A>hrzV1_71&OY(9|k24+xRpK=19nIwEljyGq+ z2?HkV9Cg*CHF7z)lcjON%}w?ag_0zWl#&=Rh#eda=BnaJ&$ znxZedUPx0xvfEBd`4hpKsmezlWSZ<&wAVJ@9_a3}r2?m6_gmJwq+Uj?zD zZDkUcYu%_$rtK?OzvdVR9j4}UH1suFGdV7-CYls1A+_n5VxCoEKFtMH-Kfd3PI;{t z!)AGLsqAVgY)%i_E8Qf+`A&^(w!Es_PKNTbTaWkx5!UYVF-MKseUu8?WFul?oUv&X zd`MRIU_hA}lqYSjwK?W}ne~2R3(b;4eK1lsHk59scO-V~ja1n(W_DHQD#Yl5iA1M4 zHQ8G}OL3ssZMf`I(Z0?boAd@&1!nqZhgLnv%%aI@>8f$VSJJAQy12%XDlB@jPPDl* z>nI-+=T)oka7)2{xv`jQPRE?N01Npv^W$E=Z|-iJ>Qu=q>Qat*->Iy5lV;C6(Uvs6 zM7y#GFF2ubn3US$!6XKk;Rxq}XE|F=Qj<*$RvYt_X^vo&k;cRqeFuwnorW>h-h{!d zwUqXZKUifeZkVg1SW6k2wm}-cf7?>)SXs3T`MI>Nh1$E6s!}az#F1y!Oy`?gZf{E` z1J^!ieTk{B%nm}4apo}Fc10fyN%F>wur{G5b(Hqz#rk9~=``B%*{W%+m;PZy*J~wP zU{q0ba%--uGFM7&ZtYh^@|&`8sF$kM#?G$L4X+n=)H;Pq;Cv{6t~VvnaXXI;Kq1eLU~y0A37jq0PM3PL zNz^NW@=@JO`DdGsADF}w_ff|i{%5luEuiC_kX zd^1j~lW|Rl!F1ml6IC!{(I}d-DE6-DDL-HJO>2I4@G3IwMLSr#3x~cQ=KX9MFT0ND z@H>rh^QyN5h6#2rt0I`EW+}lW)dg7BZ+ldUER!-SgTv-z(^W5n6bSs${os zI535!hM4$SuML{`TqS!G+bjTOd5I3xsmlq_Y?qYxuyqt}qxkFpW@6c~Q2P)k4>v zNLT$Zh`n82#13(fH8q|GLw$$T*PByIlkc>H5y)$ARAIh0y9uqh1=E3l?ohAiYw&@! zc3jo@Fp!N_n=W7&m9WVRN-jBx!SMcB21YTs-Hi88^6Tb>Z5vjxap`ia#kjU}Wan|e zN(C9#N73tKpW8(J?CcQFhM6i~Yb(;#QEKNNDeb*TUel;t?SpxCTJfEnxfZM@Z-7Z& z=f|Dj#F|s>Kw?>Lw@sCdFB;ZnCASKOO=PC-eqL3L?Sd_9_RumMoSOC3cAUkx>)_Gl z1}~#Ypdqm-56nz5&>1pero0~Ul}&%>S5z9|N*BC4JTP)K;o8Hn300>Q-?fS=TWlg~ z4AVo?l2>a&?byYrIJcak@qUrf=3_xuvejBmLq)e{7h%GimEWq{&8I<+*oyU16G`@YY4W;5e6!u=@!gs10E@eOT0E?r|>^k!JJitQRNtTxhtDilQLw1F47x zG}ut!q^rY3qk7c@#t^Ztqb7K0?4}FN&N+oyV^70&ug;DFqPN5tiu!JAc&JzXqboa~ ztn0o>5tc>FZ?@;u(HskS{Re$bU-uQ0R_Ijkz*^|pjAWJiuu7&5W+?P^Y^%`HeBhBKgev1i%2YTWMCa2W}INP9IQ2{S>f7w+EIQr=+$A)(2Y)&N$mP9weA95 zeuq=Ct!yr4X@y5&H|HC1d#rv&j|fR*wvBp!t1BjE?A1IpXSQFa2ba^y&R%`L{ z$mC3Jv|@bd<$^GLTBo!MyGik!ydDZ8apOl-$%g>IE&ni<2X!Jot6g4LQr>1I6{vsB$Ir7bYbIBvBXi|1ZNA)T)c zi{7;ia#NU6A*Y_Kga|Bx*6py&L^X~a+TK_mvZOk zuBtx8Ya)9oJEVPgR|tFjt$}(xO@JLnxu_1TjrFEecROPSd;XN$_SyEP4oe)Fol}^& zB4=1~Vz=VU!H|HaLDxx6!71@@7)2HXrLxz`)+<-&{#P%>i>b9OAGWqqe9ENVzG%cz zHMiY9e!B&I45r908;|v1$Uh2l*7cxgyn^9R537S24NVPa_Ez+p94wBkcAipmSpH(L zjORLxA@5?%FqsvjDTSn1I-(qetH6*tSR8gIrM3C?KAKh?673YMkO-c`RV57Fg%L=_ z3bW3f^o?VCs?aTbSuW*qg$8DD^*pf}^~A>+&VdU9USGZPxRy+7c}I|S*#SEnkJzy> zsazDCOLyf2=N>3S*+9`JF7xx%$1qWdrmr*vL zR2)tvOCz`B+FgE|)~1BPXyqNdY|4VmYJ{}|>+KSZKlUxvEz!;7Vr`R;hm}W|$na#^ zPmY^CzlxMS;A>s3WM&JM0IMx|)SgDfJ8y%BkA*KPI;##W+PBsR4uc&`BW!Xoij+IH z@%Z={jN4trVXEw+*0nK?v!ls$Uo$ZmmHcNbe-X2A(7)Kl8#uDw&`t(?Lf%!g*$tpmH|# zUQ68PEP3*ES6Km5z<~FlVl)hl=O#ff#-o*xcIUA*$E?;B%xreOxh>oZZfk~GL4dDf zhMOt|xms+tgdvn3m&;tJZEL=U&d^&Pt(M%v7%O+RDTmJxTr9Qm<200QfU$OgeEN-|o}yn141oA1&r0EV>!fBa%BTaBwI;@+i zT~2q>F9(6EzQ~0Ai~0_hc7@vKI0ej>S845v&SA-R$>nt!#Q-MTEEjvCZR1&$vk^mz z^;SpKlPes#>eGH0Y>>8#c4M6x81#jnxl&D!ntR*)(oxyXft{OIHrdb5i26>E2M72GLq3_c|JeqsRTk)|sHEDVMhTn!#(BGL6cN?1L~rUyIB*if4n)VgJ7Ax^!gk~+MA=}2Nyd;v2^!1BK) z7r0FNJd({*$b=(_&9ZFjOMBJ6q?)?UV2x>bLV@jNeVXke$!s&aUzU0bja@2lTv2zi zp@?O@u^QONDkp6;sgKo_&XG`QHFMpD{TS{uwJ7+MjQ1vcjk_p(F}?^LXf1cGWH#7G zwY=h#5)7gJ(80ru$0t*ZDYs#EhNicuZW$}vZg3DgYSpd-vmZKpS|#`?Mf2H)R|(6) zABz_2s+tK-Y`psD>Ww1I;Hppf=hw9x7WCp<9q=jc+Re5_qdRpe{N@tO>bV5}dQpF| zsBHm{FR7}WV5zxuanW6$!ZzE)+m7a=*{}_?zKNH+P6B#HH&6yju&$lHV6&+!E|)i& zkfLg(%~m@Y@r&;<;z z^yXC&a;XAgR;oa6!hUZb&80}m+BO8OURcm15=yyMjLzeAapnsQ0e9q0CS~8BOBHQ} z#*!6dD>f(YR{L{1G%*Z|I@Xo!+uE^##@4?sa&tpl28;_Mp zAu9}8y=b#(7{oG@Y15$htJSI52`n8YwXL8j_w8NN!X3NVr+g#k?R)fxz$VA(^(L5$ zAeN5XZ7EM<6I1p*)^2>EF*=}|sN>?iPP;ifQU~naa9LGtpQaj5cn-GyYYr`9@ zN!x^vj%21$&aGYL(okn?iXN@qdNLI=Q8O#1Cus%0Elj~nEfN|hMj^XUZRC5)X|bDB zgH36bbSRPrui>n62)4~S5AXGPWM&91HQ~#iS!~;(&Y)(Qxm2Fhk=a*U(r~b}`xK6H z1g!kNsm~R)TliUH=7S|#OAL70=U|WxOjs6~_N@w?7FN~uYg)^$uFe|s?QYx@0$(UW zyPc&yd)|DRCs>bu&)3TZejKW-J1fiXR5wXcyLppa7AytE@kRjmi7dws$IC`u1FlYH9VQhJwiK{oE zOpgqy2u!fYpXWoSyo@%TXU|M~7&<~B-?qERO$Ec;uI|GaJ2t2R?~d#U%D!1XEj+@y za2ane!;0uR*w>+i$6ivwQkJH9)RX42=kkFO$L8t6?-jO16<~Vq=3>VqV~=OzOseNk zge-=6Z8YaP@zG(bnKu<3-KpK&v%oMG1q?Y3spC4oJ8V|Dy~mlcUL00@DmP5~sM2Xm zj%Iz-8wbICJv@g+K$vP-6-%xCW*F$480)gpgQ7g24>OF<)+;2LP-CZ`>sGVa@@g%Y zb?5OGw0_XX9BXX`-hsW4Iyqas3#F zf#R8(wieEZCh!gk_qOd|HJffbY>7~_Ryug{LFFvGUBz<-MR5r#_r=8(eNIEES(%>o z`Px$3ZYG8o53KeG%SFJ$#I5tXS08}2en3;2ipSlo+w+^5mM@;pCG56#H^t73Q>MQ+ zL;{H_r=FP|VgURq(=eaC!`hb@Ls*c!^&{EKNaHg8Rw4Si1K)+7zi z=rzIS#ib=!EEH0+N_Ag#&GWH~ZaA=J+=6p+GURQh{jA8ehNjj^a2OAU1hki(WfI%( zqD4{HFnGM{u4k^QX!MnQ%2cr=2SPfoou;xvQ|mN2I+|$(W+edcI=6CIYl(J+L)#cv zdgoGWCfO66ZQE*I?1QHI)m<2PnfzEQDmsF_V*u|CW59QD4r6iAeNC0~>m$E6n_c`- z3_AIG(V$+f=S);vlxhbTOn@Vdi}8lNJOZcN(}-8+^BeetnE7oDA>9%c-Rw2aYOZHR zJ-m+UVN{j3H3_fwP-22Ey!4w*&RjAo=;c`KV^I9N~16}IeG0ux?xP8K}5V8oEu z<}mg0fvh{^kB?voUUe;a>#0q;lGE@DRa(L7XEq)@v(?7dQLF92G?|A^YFF*-bhU1# zG3YKueZ>&F?98R=W$3fRQ1)G*tvhS?DVPJoqz+f&;0eiF_F6}_zs+pt+o{8_8f~2_ zSjsK!-zW0!5-icBC~D3yhjw%iW20b6abG*A9(tAvb0@!U<)X^=zTvGEm28m@7dMlH zlhGMq5nT%xO0j8Q&)g~c?9f|nW%xzL6j_y99q?{$8{1`=G$mK-^KHFvky0PrhEk`= zoE$D_pLTnyc1ieQ`2a(PJEzYHBbV3If?~LlwKe_Q;*3`$nA$~CYxQ?Kn4Mu2xoVQ` z1@yj^gjJVwpSuyy#$L!TwZ@3XS{K^`F&%WT>>-yq+^pI>g1J8mH?_u5EHU@31KHrp zXIQdA;;Lce!FpQI*t1qxfn?O>f=M%{3tz-cwpxlVLwQGU18-zqXM2Pddw2Wd%C&Au z*=++%gh8oVX(&yzO1v~&Yx9bLP0j5!RanMpsO(hCo!VYq%w?|bUT`@nN*-g|c!)A( zk9s+C7-PPjXIneKko{~=3Jsf61L(=Cv~>1uY{RTtG1VBGLdxT?&Eax)~WYH|ImX@5~5U ze~|MObK_n7;5st{R#zDh72bwo)mp)#z^$Nv?wiLqeVy$%t-~}xbrWE$a@<8iCGhIu4smNZ&;&~pNiuGKP+pX5pI@GV1r-jOC z0rMVKbAs6}9ERX&A6ADp664S7W>PJlDVt7H-F8wjRcFIuso6-GrBFk#S=@&L+nHJ; zfodSC3G6B`ThVfuU+)zLyQ+S1S0=+|xYF^|^8D56EKKzp1M9R*niUutspi2ODqDy( z$GW|u6mIUk%XF{HPRs{aEHKe9TxXeKm;2z(?Hn%G(ONd(J0^G8tuh%MhutNkF}fRv zjz_)|ZuxWZ*sj|zC%j39JBthGEvT^z&LYmH8V2;S^B|@*7L*oL>D)@$*+v0>JMDG2dOoVy}J$jN{7(O6z?S{F_H!@a^?)QWxE* z&_17iQ-7hwwxxWjT&}xz!6g{m<2h$#o0+QZk~4hHYjqyoh|i@iI~aK;9$OVnQM)sH z``1u6CLESg{fRG$t7BFRJytNsfk~l|_JZK(ZrI93??^ajb$cV^EGYvH$GRQN`sU+p z*5Iy-QTJ8t(T_Nt-xaOFq$lnP2M%4VLK6F-OCVikjKaL125pc}M!-QE*0oKCmarJZ z|EQbEFj(j;gJZ%iY@LOTZyqX&ZXY|VIOm*RJAkE+ORBx2uyQCJ!eHr49ij)He?D)+ z;+dor z?RTtJ9<^bi_Z3s()@GYo!7x(ZL;{y>OBoHA)poaDQ&7Zg-Kg%{MX?B2zT*7$?b0yXj&@ZO5X&OY7eI*U8QY@xf>(m*ubh|Gj0`I7I#8ivC`?!^@_niJ*|Cn zVKke^x@wgVh++@r-qwh4To3neq)ebnD`m;GW8^9=V(;mK_kI|LX9XpMtQN=d5_cSd& zF^x^PWrwdSRJ9eQe-c?biiWkmVim_=x75PC2jVFZaHaDe=9=_W45{7Gzn#X6HqRv# zaqQxJYXL)3ys*frl+jc&ww4&b24;TYyq$J*Dz`E0DQ`EI2@?-Mqq+?HzG^0(*VId~ z-8Q%oicEb6U$5!L7UtqPgcCufkalPX8kh(>E*gi+ZADisMK@eGQVsB}VmqO%B)C~` z+P4j+u0nGkY7Y(d6IeObry`$U9n``|a_?tK{G#x3ewg>h=?Z!|j#p2z3)hBaBF4#$X3*p~(`*Tjmv)O{7&CKjr*bjhv1?c<5WWnKc5xHs66slg zXkGUPjYXoQcEMHV`?)DM&Y7(%{<0qK!#P;_cg7S2et$Ifl$pLR1~V6^mP^jcolL8e zSz%H5g1|>guc2x0TG*H;$F@5B1dQJEVY2Ee#`GmsVBk0?VMPtTy-zo~1@IiUiT%P< z8x-xpcFl%nv&xw2N1c0AQU%Q;eZ_7W!%|=6v>0-39Ro|EJF%$id51A<>I{!+tN%Du zja>mx$vT4tq~n#cFsLv~=D1j;>ehNEn#xEKz*zF^AEfHj;>0)IC>#PGbtk$hv!O82 z+dC(PPBrvjDw1-V@WR5(oTqhX_oCY- zveo?x=B+tQ^5R+#UrGE`8U=PvZLq-^+c2ZbXpkI7yXz9bWGbe&X`OGQ3Qa0q$MCG) zj87qvS?z1VXqL;3OUr>OqcXsltJ+p7<<}-1jJ}R46_G;QqYO!Yqc^zmMtkuj%mluR zRNb8e%rKito2n<#AUXVM%e3JxOGo#DE%04`g$eDOD;SjOLp#=wgv)7XIV$zo!6C(8BZ2xz%{OhEBrKh+^(GBVKlq%jMU_-=pG{uQ zcVK&}v*K!EbUAynHg89boAqR5IO-nyA!NaeyJxdzV39>gmpTlSz|Tt zO;k1BW>ff7;f$Zjuk9nZVNxI2Lj!fVI~wik+q?sura(V-q_cakc|Br8Z^XRO#!b*F z6*^cTLfjpgz{0pS7_5?O;&Go&C!4_5#k1Q|a4pq?LyTD`z;GPCu=cCe&ePwIabzE2*t(+?r-e#Jd z$*^WcN#VC?PwtLCyU{k8RB%3WbKP-1J%nQcqU3M$neRvZvqi>@&hTzWP!eXu+3 zTVVvD2^O`;By3IaP+r<=8+ev|es>*do7G@9;Vh1Y_HYvFwZyJMlE5^&5v}$!vphvr zlYqHU-3pfQU{niiqU~)y8S_sRfvSoFzx7(y=d-Jh0mV?!Z*{!;?&P`@ot0RpWOX;M z(8o7bt;YHl%xsxHsCbds_s}tJynCA^kudzA7HW| z81cQIB(nLo;6F^0FxZh_nb>`jIolgkKP%+dD^DOkQTUsBMSGDx;w+kx!DSrJ8f#|X z%DJCb+Bq>dH7?TXbK{~N`;G(kPMWK1&edu=zD_6oB3uDUQzs5(4`Zg1tS8F|8 zG8ar&R37+xO&%t}V@=n~M+V_gyXIw>ir7;+`P3lPi%#Y>ekM7182`RAmHVS~O%qH< z9r;q%mfINR6tm$S3RstG%dRecP`@NUB3MYN4x z_or4z+$KA*;cRKmG}qB{k7*~^0W6^0ad#R%b3i|g!@zZ|x(}`-Wf;fo3$RkBRuHYT zLj{I@miA5<^lO7RY@iA*{l@iI_0O6DZY2<#85O_FDw0iN~hvS+5A`6n31_>5O9pO*hu zx=iEJMM~@@|5GUZP5-z5llXss``h3C^XrfLSN-+hzy9(oY=8Ut_p=0UCGekLwZB&3 z&;0QJ$C3Ym`~4^U{o~hvA*un_|3ZBKME7651P~dBg@66}zdw}3`^N17#}B{$2~U7K z`3u!W0Nw2e4u@2KdEWXfmB5eA(G=Cs zCBgP@oDGMOzyBBT4*36x@IP@0Afi#<_|bMbM?XdLzkiFM+>P=V_#=ABzYx<8A=I^g z>L!1-_DwkY$I_v({o#Fo-A46pn#)go|2eQtIr<~IGulN+`s%OjZ~RWe|M@NcUx2u8 ztD94frhNSHJ@~-A1flXUrok}b=9|Pgy5m>nKVWZ@)BlF}{&UpuU+pR0&(T=lwBFHX z_K#l$K(+vwAlOBTh(_DV|Na(_$1yFo0Nn9>8b{8@d`O%;pSRx`U(eA5x{v=q;25G% z+x{HN58E{qt*If|Fv7U!H)gEu$v$7OE8VP0NNL{5QiMC1+-$C_HXeR zhdT-5`Tu~U)ra&b-@XTW9n9xu>v)Vx5~AFVyo?)_$jOwmseH=aB>ZoJP0mmd>`w;#G;xN7n zM{fCk#4i4M9Q_jZX&XTKZ}`LZhP;h!0$a#GA?|_G|IqdO*K2=>jQ8o#L}x}FnuVR{ z(kQWR33vYU0mp=gDIXIYAihaF@-ho(eyWS#!t(rRzR#tcqbc?X)(EE}>g0S(c=x75 z(=ev_k{vl4-$(!a@A=5*kn2x;|IQ`wQI1CK0J)Xu7KCRBN29)sdNd-Ia5M|QQTITk zBPI!V({!kt5Um4sagrw88M^h}y`4>5jO^-!DrnAEI}YJP`4uU3`8W z|Fv?Y9DUP;32weTj5(r>85!yIyoj#-dYYH=pd1abxx3xNA|^zP;W4><9eb~F^V4Im zaW$qz98*cSo8Xx8HElC&LE8krKjr5mPBBa*v0-2s zZ6uhU^dBOQiLOoK5xeqyUJrjBN56!9#5rz+LvQjUZQ-T1LU1i_50Bdd>CgEuhlAzh zC%)hNra@$UOlSVbuYZT~#Xdu{OQRiwg)rieK$mPs%x(Vh?eGn_N;pem}P4IQz)&$C#u#1h!G~`!z}0GD&;;jhYCF`{kkZkUQWx zKFnHwtusE((WH+L@reBUxZjZ2nu&cHF;3DT@<|^Ho=do!^eLj<8spHe{W>R;HiPv` z(tRFBlU8v1PdWRkr0oVJ9=j(o4%^d5e01gu5vw zpJVMU-hPRzX*_Z;=J6V5W7->6-}{Z49%|jl;`m4GCUDnJ>i4e~CLE2JyYU~v%}Zg_ z7?2@Ie5>7_0MID1;6wgP^;}`gkItcPN=|4ofvlikJ+qd|au6IBFb2yq}pGu1T zdlJ(i7N1Ir{g299TcKFLCozuhFSmi4ZIFy-AY6{=|C)$KJby%&#=bok&LKK9>GQjt zPdJ~3QR6_IP(Q*ZI^TgUHV z5zl!WizLnKe2i_H>^Hrdh6xuDpAtMu!o=qUzg*}uV*FnN-5=*@EK5>uUnb=o{^j|6 z4o8z#@cch*CsblvzzrqF-IEwccf=9?{)nX5yUDlO$=mIPay9AO!8a>xpqJn^{;c>$ zWFW4--~Kt*qa2M@b8owcMNEfviO1yfE$rPeM$UUV{2B)F+y_12H;HL6{FbErd`~{- z?3cNl=-Q;7(e8@)h9~*c>D`2*zm|8u|M{QC(Jx^iagG~GIWK>tExgoLp0|nD+5#S< z``5Ms+AieyMx7Axjb7kCKEe?hk9F4DSi#5fAJesw3yAJ~|2)(^z9xS;M^o$}PH>Y; z%E#}=)>}OM((#ut`FR+m{QFd5S>JSMs!OB1zaux3Z%HZ<&-lHLJv*2a@j1c%%O4Nn zk2xCAjaVc8%A`G$@}lDk$+$p#X43yB?*}A(iTFK&V+iSSEG@Ky(0p(V;y)hj9K@D= ziznB^v{+|P$05=%N&k5qjnyXKC}%&FwB4Y@WB24s?dGlcFX!yf=5DHgVyz**Y5OJZ z^+&)rA_FmkJKEN83?LaBh^V8_NBRiyDQRCH9wYW>Opo>pwA*1Rpq-kGK}4Gd`bXnA zXs;vJL0cYaH@EBEu7lRR+c-qL9vO#-|IxNW#^vI*ULI#iv4}XrjmnR3H^ty{tkF7t zNxsC@G#=Y6o{JLWUX!GalQd6%e?*7IbCHj+obO4()s)j;;_!bwO(tNj&!cos>VR z7gDZxF2Vd$N%R!bCWzksz~K*Hmhdcpm@iDq(WuiR))1}8vly0-AtXK=ME4~eis@0q zxTUA(lQDy6XQpEkiv55GasA~}Y z2Cw%mIhwSB=l^Ltp;FG-7>D7f665HOZ3TaSL_Tj{Z?%)pZZ9`(zt7!-%kdc5NjoCk zjo3%dCdcqMw&&ji;gqAvz1+qL5*?Y|J4*b%Lq5g!NPI|9Po_JbPxJ&#g}jPSMaK{l zp2f5z9gb1NJV`t)2YL@ApXb-3`C&TB(Eyvf+dV8|Lc|RolgqcT_Z(~F{O9qnVGz$j z%utDGG5nUi;q19S@tm_sn%6iR%l(E$%Gp%PIU3{cgu=VzdieR z&`k(O!c8tIAHN@4|Xdw_!x2de80!L6njtQ%Y00A z>>Dprets?qUsK*D_FeL>hjRYpIR?K4N0a(^oddr1o$z@aOZMFXbG4LnHY`v4}XrjmnR3H^ty{tbHk0Q%oZEFpsar;Foaree6Bu@q5^#+;sK{hUp85h771CAcPGe7-M1IN@l-^ylc%-z%Tb;b@9|Dk=8wNlb%Sd@3pSKPqo+ zg<}1llymXdwgFN%a=qq$y+78W5m}UXpUT(xm$reY@_C!M*9IuI@t*NFDVz5ooO1Nn z=(PBp-}`*Z(G-h_58UoaiovItyJ6}r-hJ!%JuKom6px>U#pk?CFnJ$?1dDj=`TiOY zQw%=G-cvrN;d_|GV-%M!OUlcSCFN@(QSU~3H|ev)vc%_s?XKnIug%d|EcZ6rPN3O?( zt$oPb2_hS6fy^=ZUv&Sd>vK|$2H4!)?qLxVB5v@QT)u_9=U5}>KaZyv#L<*L|Gs|- zK#jnfv)G^Uv>pEO!=Ix^BgS9CKH?lVl$eIf_p}8%FE;IS{V7S`^S3MqEpQ0xA&89c ztpk6?_0Yrbw>489u!h(}tl=h?l#gHHVNCluJLPATi0JSCZSfi9`g?p6ea?MjnNvjn zs2q*@*5_}Ov!BYBIGb`eO4@F)bYIg&|M>5~`#SU=`M%|dzUlhpIevsN>e2X>aSziJ zi*gJi@;}1e6q_ICZ{%pYPREZ^ood}NVx9_!dxR)mYNeBRGV?=LUn3rYOZU(cV^+dVuyu4i(; z_tL$dKRpj|a_|0MzW)96G(VJbL}U0pJK-JT?~mhL@EpV`@rOnZLJI`;6rtZU#$vvR zJv@g0$(TXpB9a%Tqxrn=9_W4km!pBF@97@*u!xX~^=j(%Kblm+C^ zie*B_Qerug5b`Si!t%v2npjR`PFIo^OBGkrqvb))LceoT*2MpuT!)lD*10@?ksoM<2dm=8c*^jV?FUX@ILSuy(UVG!}ICbR5I4%alSM^a?gkltaFktrYHH4RL`%E z$Fbb-IK4M~PLiJd#~w#HqTj|ptb8Ory`PY1ZjWB)nv{)a*T|D zd796?_KVMbi^uCcFf<_g-%vV;yf52c!am{|H-i?}dW5HM_lc!W z?gQfp-Vv{K?X#!PN6x3^fbw=fx3riS_6**xL-0nP`}uR;#-QG;cW>(`q#fZs;B!45 zTSznsR=7(%b=7U8|j+7t46V^V_ z&B^gwnA97VH{u=3?P>m4pX4~HC%oR@AM&HR?yY`E{nPs<5?cnIPwN%=6wgOCyX8yf z4S0$lJWl39B*)2plk%YVOXTa%Nw0H5w4D1$8Qi!~9>z0?T?+4w>cn_WnjYiHlVDrI z^f;FA*8Z?2@c3gr8qX(nPV;$NVm=hlDDT_x5Z@o&C}%&FFLAbJ`Y3sE;C#lJ^|q z3i%J~lFV~L^u}8qBgbN1B%bQr7`l}|$(M#{{`8!iPD;LYd_IyM^wt%(wb~!yQPs*Q9 z<6jR`?0)=uG~bu6i+O)}zBGR-N!xp#A9=q#kEiFoPhy!P3J@8HqmSsYe}wc;Ihr8) zW4iRmxc4=#mg~@%4ojER!~4q>IqOU8(S$SKf1T&|g&cS9{I~7bAHxln$+x?X9MSJ< z1Mh7^H(lthe7~k`-sR}O5tjcLPv1*TIh)F-T#aEoCYSh|?q9~yZKjMjyZ4`Q zpNTh`mmJX_)s=|mj&@GevyhYJ{EaxpFiNWZqkZvlA0e@`%j2=0<@vlGzR%G($KXe8 z(=TBk@r@fwIUm2LEnw-se*ZuD_Or`Jj_7;34PNhlJhc}-w_~DJj@mbgPDtt%t$0L- zBH#U(FNW#<)P8#Zx{vSY1&)5O<5BOW_h9dR-1{Dmru>W&pZDkA_b&nZW%v#3>C^+azhvRQ- zBj2B+U$$3#HW&U;^OJKl-sAgsVqZi&Qad0@{3AXcgqKNvi6FR^1Hmx@Bzob&;R{Dl<@S;kL9@@P5KFM@o!&OexI*$G$8w)_Y%Rg{Qqk_ zjOpZU0@KRd0u58_%O#fX$DZf*Ui-51ut!E-K3|*Pk9WQt(b(SJqq}}iI>OOkd%ZU} z8ti!F3sH_iIp#jjy#&wq&y(xWm<~&q;OlFj^S$Sr;l1!V_49r2`@PTib~-ttzi->7 zb^T>rM7iTFj{fyQGne!6M}EJ?-FOV!##4!LbpOfGw4T17lq33&rxTGj_S${D#nGTq zKd>}n3^yv}oc)^Kfa&m@`<(nzJmu;eN5A$ApLqcfue%y{evo9ZYZ7kF0eEeAVetw*k)ywg3ay01DlxY#sFK;vz#r!=f=VN)B zpqPIuv2^c0_gl~PrN>vF#1Y>#tOv4I1A2#2og3Q$ev_lEiAWNrXo}T|br5w?Zbrj+ci}mq1{!7B7jo-@$%luyad$0Qrjz-JJfBOfY zVvdGC#=$RfGsaVXMoBpOYo71Dbn*!qI<+GDiCn3lhs4eXPkEI@t3?{M6BA zg?`uAe}Mf4Buv^B?I-yA1J~cqC3zv1aa;|0rIDUAydGK&Zudd+`5sb^Xv(3)?tu4; zcZhv_@-{~L{D>c{d<_*W8)A1x|5)PJO8W;%o5hmC5+m2S`BmffumtG!QDPjX$Fjk^ zuvE$UG>molhCTXb#RE(uWfV?EFp*DJLBe`Ozcdg zZ-L?y%N6Sj!?fN>{o(tN)GHn%`A~dNKW37K`Z?3{zo(QV8lMGsdcSzj7?#_asl5}^ z5bGVbQPP)9)6?^x+o?%8kn51VF)c}tJdU}OaS$}_c0I!LB#i&*y}oLX{x7DnjnFwg zD7N3DH&ASToWqf$e{Xvub)1!Yo ztv8CP?r*u5qJ0EN=^VE`}-gh&9UI@5BwtL2S|6TAu0i@8 z@Y{&i+h;%D+xf{6jrWhb58f}{HQp}?lQ%w&1tU5Z>RyDSQD=Ido}7=IOLQ=LKE_i& zY>NBa`IsK_$8y6w@%r?7h+J&@B#h}u`+KJz{lL}KHZ8~8$GP{tIy9!k(k1u#y>!aQ z_Go#zBbQ?Rp(OQy=*Rm)N%zNLOo!>IPK^1X-GqcOA3TqY5v1wJTpQnG4IYZu$5M`H z%F)=~$ompY0NW&hl9mpB^v_ulpzcfY1XW1GSK_vUDMz0vynvr9Rm@%cY< ze_5BJI@i}LIW*I-ti?sW1dyS{p{9}dX zh`#ag=d|OObg3^Hdr0c&`F(weqsez7f%LQgl#eOq?@2i?%i9E|m1CcVv2?M%@mm9R zDWZ$wo1B!*^XGZ#Io})qt@3^E^?(0#azuYGUGFom^HGjQ-=#KK-6-a$d_VsZ?7p0y z^7CVRH2Kyb^^KYwayI)LUw>wK;Ct~i^TYP|W927D^k;MQ_sH+#9F3@=cD!dqEsLO> z{ZwKbzzwCGv*lshPHr4cxf-udc=Yxy@R{XwvqfS4f5lxs$N#s|hrXrm_;HRV9;S%t z_vj52n=fampDj@{_*S~zmvS^> z8b@r&^#{t?FUj|F`E!o`Y<>Bq{HQMT((ylk{0-6He+>HPT=DVTqz~*%?9Olg$KFar zFWD#`)0lfw&dcv<3s|~{q0iNoU(4^YJ(}7&9$%mO#N5m0YyH)~)qDQ^`BFrG1PLEa zOJ>&l=vm(*{VxxF@9*c{m-J_OJmqJUSh}B~8&X~TZHe#K+qVj7PdJY=wksNc)9s(< z_r32|eqZ$dzE1wN5&dtd>6dKNl(U~oId{uB8{=she`7oOy*Zj-m-x&OFEi}hK`l`3 zGb3O7hO~j3FAeIVsM%3pAL18}=hJ-9Z|Ctl;P(yxwGoZFG~rZ=!I$L6c^vco{r#iK zHxXJZiERZjPH>LcB|g*g{sKHk?B$pa&!+zIh+*_UC78z}w|ofK|1os*zdE8Hbejim zMQxh$G2$AxdlJ*gb!ZyC*A}pJzb}71wsj!p@cJl`SIPYlOky1RGo#PsP1nc!ecbPO zv!CObEzFDbMbi1P2(Eu$UcTKwKIgaBa=-l*zEbCgdippA%XMe^TdqT69G32LUG?*I z$D5A)*d9&%+mVZjzdOM;-V+HEotuQw9z~8LN24x_lKoBo|Mt!W(5gB6Plt)>&uobGrB3dr$YCbI;%Yar*wA>$mpWYk&7Tzw_Js>V9X+dOc7M<%IKZ zTMS$qa$=9>YDoVL(G#@$$2i+C%GuOWPDkqOqnxNdog1!B=V{ra6SD(u8(qLZjQ6^dqV8d8h7x%Y5Wkbt_-WsqfO>4rRNflv~kE5}4W!C`K%`JbWu1DvaFY_^f?9mp3hwsO$J{Md3 z97W@2P&qo6v1RIdbZ%q#TpnlT-$i1NHjj3gk}P&k$0&D4Ih%Sb8)wHHoy+eK8e7L6 z9r0-A)8>omSaaTnqw~EUo!b~5-pv0e_UKfPo|F7;2w~&bq$t9}(HPpw>DK^dtee~a zSYM9+OF5@i?(eC2?|Q!;9XV#+4^?wMwm3Q(LsN%G=Qfs2U5~Df_1)a+zwNPj%+YCA zXu_jm=E7f(&h0vj`hGsvH=@TGdvuydC;o06Je?j#RG+(zt3!^?ReTw*N5>wW?$P$X z>1gZ>UsJZV42zu&(|zB{SU1Wab z;k}8yAi0aNV~?)bqwRgu=9|@zp^e{D*Q2pB?+N2wO1A!?u{F<^Xlzm&u{InX$_eF~ zZ-;H_V^x)VI&Y+pVO9MrYPbE?6}8oVUF^{nd-N8GzHb`8CV>_^r=$6P6tS-ImhL&` z{Nd61?p5l-{hbx_TTS_J>%DjSZdvru=TK~qGw*)2_e)Y2?zgk&R`lMX@90zRxBjeg z>KNOL*UrgjPans``0!)STK z*Cu&G-EVCBmTe#Nwyz(ju1Bj}=CzN$&pTSL?}J7!t~b1rebQQH7b$+P@0SLPT$}E< z=G{%YyVTzI%^cxA>`;#Gvo`r^5BjP+s}K8!^JHU>*rO}=X#Q@Trkcjk@H8K+t6T%e z@i(PxU$Jtw`5BlkC#8-{=V;_|Pe2dlP~Gcn^>{3Mrd1z}nWOLNR-T5B;ZrdiAT$RY+-nH;D7 zjTe=z_XCZkjdxS!GcJ6#2077r!})4%kJzKD@M!jBReC9cnGjsqUZZd~lqRe3bt#hXlP8cTBxU|r?tnsZHdB%+Za*R@FQW zHyc-n9G$CJ($>9lHDCRkCl?%Dy}w1Dy{F}BBs(MY@5Wi|YzQag>*kG(5i z>&RYSVZ_eS_JpmH z@rl1rCrX9S)zSA&!^d!RMQB_db9C-GzVO_qWU(ZNDkP(eZk8 z?&Iv*^XOFH<=0r&V)?adi|9TSz9F(RfVW$25ygtGf_m=niI~}9XhY-WD5?!|$y4d; z(Yk*GzhYkndx30ENf>)teYo$#_F_c$afkhLc|0{=N3T7P#!ofwU}rI&sxb&0t$)!9 zkJfb$+O@6#J=#4jUKvkEW9a&^9$n;g)fig$z7d16|1FF~_3gQob?*oJ(e60*t&lx%SjUcKgPXc6$q2XyhdW5;; zv{a5}Esy=swojSo{j4tJT;phc7E#y#w2pD~qb}^9%j3x}M~8g7HAmwQAxHBqQsZm& z^{BTLLLU7ytxX$OM>W?N@|Mm*^PM)J;Pcz6f zC%S)Ac^kb<4$q~Kw|&dxZJ(3%soz+e9F1l0W!Tp^ny4+x(a|_s&v7Am@YXu&`=&F+ z(0qTyx}1OIxAZ+8>E+7$S$%cT_%_O;#<$9~stVu}*v@=fS1A0f_mje8$*p}X zw>6yWiq|}hpF!nli&>SgHAc04_xx?2BF~GPJnA!haJfFi$2Yr1?wa7cbtB&|9B*=? z2up-zIQbzrPQT;eoy?~k&8~g*`yw|6Kc*i@Jsb_f@7Av{u=Y4Qw;ok5X3H2$SH{u! zwLa4VM=OWJms(F*xtp?H18}JJvpRbwW^3+Lz76XsbL}ZV>w7b_PPrJLw)bgJZ~g7J zq_8gRU!8kJ^d6Dh{;@}I)3xDz#nzwG5spq>k5>QGXX}W|)IaqZJo`I==Ck^|p87F- zX=Cl#JjUZ=>7Qs!oZj~BD90YXEgsFcL-XnAIy7}#uXThxtGpQUG2hqBXN|Ybw?jTx z&end$tLglgy4HaYhkTts-pr*Qu}5!E+iwvG2k#~!^+9_@BbYm^%9@vyb%tvNa~N2uw$ERvgc2Oj2=Mb!F(`y@0+&09=7fgay09BL?>`&<*~B;hMoQTL}vNf%gy{9pgzfsJ-T*0 znrNE$)P(Ug938Glvp0g@33a_#V-aF(ehXxcL*J-HFFyE>zWWny=RR89_*&&xKklxs z+`{P>dvxu1bojn$Sbm2da(Xo^^r%I2$o^|43Snn(M!Y5lDbe%_j+i8yf{{u}9agN9%V(i>1vsa>sAVsWzX+j<$C>YN?DYj*r= z9piI%92(bTGhgh{we8Vc1aG*>Jq>{0DDUMi?u4W9J^k?13K2%Q$B*?4tJ6N=er=v_ z(eXNt7@Ru$4iL&U`SlTFkFI@>R-aB?>!>NeX-ta`)r_a|y&kRHUvs@{dYqN_k3G6B zJlcLc#Jb93>9K89+YO>yCo|}=k~8w#Ixn%uU33}{hGIl>3gPXiu_t$(=qj-KWl~g z*W=skarO7e3-wt!uEY9k)mXFqS)foo8h*~7)#91!uLTO#qhpS)zdn^;%?j0{V~)F=I8%sP1 zAO9CyAhtkkfdaO`4eq&VcnmI%@*3re__?CGeDYwZbM%>&Xg;6X#dGJ{0(0E+rR}^& z6E8<&Pkf@H7`mdmTx%Vjk0)d)^ViM8`e;6^jdTD1Er1Vm_IZy!??Avic=}u4o}xK8 zTs?$7e6|SBS@Sk%#_0Q+@@Fg6jkOJ~PxMlKO=phI>J?)K&)?aq>zO(0y3R#TIeL?S zikfoh6RA1la(d!F7P-{5wiU|{^;bPi^HiPnIQ7_KkFMB~gL$KT&j22 zIE}So@_gEY`vf0+mgBLbiR#QXNH6;7T_&Fz$8*<}1&AAv4RZdCqp35$s3>O~jgR2f zR<0{OtCGui0rZIaaC(W@;|AZ$TB?#7w-=rT)C2T>tPEx`sQEEbvc=8HHBT&ldYY?ah!c+fz~c@iF9=d?Clab%q4J~OW<6Wzy&UWD_jCUc8M!L^&|5A z6T6++xs9M4w{-EhKu9oHRGO;#9c?NICt35-$yG*nTf9OT*th>~q^SJs|}Hp@w8gPg3AV z`&>dd)6wir=;Z>smj7JkbB(TQkb;3wLo%c%$&GQNNv4}&CJm5s z?&vjMn#cF2`EnqQdmiRBBP(w1LC&`U*qe)5K61ry604YBie65!T?$G2BxuhM^cKG;hx#YbG zvg7hVF1@395(A%O9$HBBB)KteG|6-`%%lNQ`Yr3_rGYzjyUUjY+38Q;@wuIkd@%(B zp@w8gPm&wsMw3i8!%P|=f_6S?6UVqKDWz+(JAO!Tn#CSt|!Uq=0=lD zH^WRCAZ5s*|MAj1ZrR6|1KD-RJfGWj%}FWfT3ih&iLNKf>E=e0lDZ{y&7=WRhPD2S zmj>?k+RtRzJKdbLrcch0;gd?G**!1Gbthev#K7m6hZYh&Nr4|tE~#5W*Gw8TJz+b! zzQxUwL??~1o2TdqpJN_s3{`{cHkGSRpzBFlwI+wOC}z?Cxg(A}#7hHr-|c)~4rKRH zpZMJFU*430uEo`mlIVJpT#Fk`GV2&-(f}!=kNnt61NXRcUtbPnj}?#l+@3v7PQgH^ zAsNz>MT{CHblyNJ5=%sml>F>TANb~Ox^10@ZG)h6&;%Z1qbUjH+_d4KiUk+riDM$L;-i;TgU?9|x4CzU7W87#`Qn!SznKVGk9k0IO zrFs15-!f(71y0&NZ?%-E-&-v$o;yXRuK#%w1D|6aT1fOHIo;f7lIdocNrQbZ87tFY zxJ#1gq)~SBocfs0F%LC{s==N2f8}dDx}KnFO%7>M%%lNwXMA{!mj>>8#6NsFkbNH* z>~k&mZk&RFP(w1LC&`U*qe*5R!%P|=<-T{ecxfKT|HhZyJl`DUbNdZml!Ad!Lo%c% z$&GQNNv4}&CJm4>YfKL>&Ex96z8pxaKA-wrtCE{j(6zW4QW9NHlGDwNCYf%AnKVGk z+@ofBY2f}p+|QQ-+5d^heeQsEKT5$ss395BljO#@(WInq30*U3fRuSd{^g~C2ktsV z9xb}cNjvb1d*#s;U&=x6y)2JS8JWbu=a`2U5cv-Z$R}urCV;)*a^dtp- zG`Xa130*U3fRvKXw|i+|`@IhE5qzTcMv zIjqa~eD1Kv7pI_WaW$kQx}GGbn;T6s-3&8nfRy*ff9<7#-#O$bz8uJRW_;;$hwm~W z1p}dmWJphv8{m`MYql&zfUrGZCvD)!|-j+%Rn&waO5NeTu+4atz6Bsa#5 zCYf%AnKVGkN4I_MrFp#l5?>Ca<97e?xsJmprl4zaHKZiEo+PK68%;9Z3^Qqfl#R!o z;-z`q(At*+Ir`$KeeURGXQrTQaW$kQx}GGbn;T6^>Xy(olLkoH)NxlY4gB7-!(~(X z3@5Eq@dNVJeFw`i<6e`^y?&p>z~`8U7E-6;nH~c_nru?Hgsz!1K+2ZWhI(n>4@TW9 z-<-3()1dQfBjlT@>*e^fZcD+y*Dwz)q~ms;1OESHmWN~dOXo1y?V)G{)hv)=j^3E_sY`G zQZNu|_$Fz%=#U#__~e(J1`Br_EW2lT154e_@L#NA?=e;ZUkJ?@aJaoO> z+hn-(A2Qpu+^3#z^WxD%D(XZ9ZGWo^La@jRwUCYE~C(0###>g1A26b`cOXSy| z{9As!^5JibaU?Ks@8zg@C!nVkKH z|8XrBy?4BH|NWkF(ZR<^_p5J|zK>oYXRUkEwOla#JUR32outnnJIR@+e<0`e-&4+5 zIl{H{e*9;0#zzmyIluct&X{(t^qjg*PA~87T6!GZR8E_GyL3NpqjY=zJ95Uv$#Uw9 z-Caw!EB-A%`t&vV(SC#dDrna}2gu2DSG$%I9@s2h&zb3c^rVZt$I~(g-{j9y$7_DmUEhg zc>N-2*_LmV_kJ`&TCCk9_dVD}THHKD?*F{G>~q>2*K%KZ4{335Pr2Vk&$JZp*H&7* z_=RgJKJgLRSFV%d0Uc%EEyWF6O1qbj_gWWS^=c9` z*}C|M{?clXwql4KDZ3+Gwbtjj7N{}QYk_k}4MA%J?mRQdV;C}IW&l(`yHlIR$h7Q_hs~&;gZC!caYIv^l;MFjB4X@yU3bPTlgMj z9ahQchq%j>T|Q4n4;(CI_g&{#oXZcGC!>yk*tL|86rU^q%g?oC^_RY9AZvHN-j80} zaXT+Q=#Jl9e-cD#(~QtHpoO}}Xsq0#4iG6tG z*6Iv@ez<};KerZr<61aBla9RBTNG)WpGnO+yB5yRt-XHfkLR{7t&*rmI!>as^-wNmpuIfC)qtm+lE1z3E?R<~;-P9rdndgR^Wa_*P-lF`z zPmWrxjf%(}yh{I3<9AAYSc)Z@AB^WW(aI^1yQ z8kszB9yVy*T_&%2O4iSNR&KxeIa&M3e7WQ521sl3wcI}BS}8yM?{Y`;Q)JEhzsMc8 z4stE4=Y1_x=DqBXhhIZDE-(}G(T6ob!}5VI$)cYg>!htcypt>*_oCPBl`HxuQMG0a z#{sUrd6_JF>r*$TZ2SK5w^y2aX{w&`%jUQC+2%w zzczcetlqV!lsrsSv%cx`Qqt)tDgWwNDfzUeti5`PytWd5!z0M8>$TaptXp)Olnigq zn9glw@s?e@MHi24l0?_yY|PAtWh3Uw;-4Js#*`g$ro6o0a@B3$&yrY`MPYr89bDtS zy@8IEownqdCyJ`U>wS;(Eg(HX=WlK_Iiy7~lLm~LJohL+7A)U=S6^1^P=f|hR1NS% zT0rawI<4Jka!8G0rWlsKzX_K6F<|+Hqh!X?H=VS#B}--6!(+YgaQ)yzpn4VFN)5Q7 zZ%cnYscu|->l<9)`>va`FfoRE6{F#JkIoP7y!=|`>DWl_TycZ9TR_e> zsAroT(xO&rKmZttq=}&W$FA z22rfa-`;)F-Gkj2u>7R!*yeXIB6-QBrotsiifyuIUL{w$z1 zeh2FLVPB)_~-TZM)_&}Bq=l-){$R|?TaI&o1_ek+a+Izf|?#znJ zx(^o1vhV-JdEg*#i?Y(^<*h5Gx|XsbhsyHK2ddrNZw6@3Zw8rcO{_=EVu&3nyLozT z_BqZrHHLb&iJGVZ=?UstAcwRlR;2-v31dLG7j*MDh9!sHqNo-n%Af_LC+N;sVBi*Z@=;kmE?Bs5T(}pasMRpxS^O(xOu0nq?d4ahN16jcLwjTR6M zK-GX8(xObrk}$%{&kIq z%8a(7ytKQgzmUXC8lXRSWkb&C>jymIq;ZwJe%F(J9`19@r*}Yd+-VKz$-NlgY2$wx zL>hN=!>Tmknx?P6ww(r`YCw*8qNq0D8lwe7gSV%4N@(y-x97dIceb2n$bQnD^jDC^ zwyRWjk#D4-yG|Rp5C8alg8?qzAW{D(mv_4^eY0D2Y|t=~cbywFPUKx{gXW36TNi7v uU!+enzb_N{J2lulkq?^h*x-lsasLO+_ioTL>_4^}YIL|%f|h<)%l`q-Qg^!m literal 0 HcmV?d00001 diff --git a/mozilla/directory/docs/ldapjdk/figures/hier1lvl.eps b/mozilla/directory/docs/ldapjdk/figures/hier1lvl.eps new file mode 100644 index 0000000000000000000000000000000000000000..136c3353dc68938415074266d470c84430f203d3 GIT binary patch literal 364963 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
p9q~`G6eV5?QW=$|KGw6kmk}8l zSML?7jwl9&LakSndjF}C)!QQzoHTSh&jv4JG2VC_^zri>pKD+Jb<1hv9Jb)^o_VWV z^>bCOdw?7D$WPK@fZ*uIQ5{>9J~4I4``HkW|Ms6= zk9@GBG7`#VO)zPu$Dv>Q+1KOfx_tb4vOkro$?DZ;!8lrCcfdcdjc->bisJ)3je6lP z-}`V0b+A^Z$nlI~ zd~MLAa<(H#pBOCL%zwj7U(%`6M)Nlz&C(c9P`; z%pCDF*?r%bjEUWT#h|wn<3DQ?3SVwb-9GM5FH6%EcK*|4G+n>-?6oWZs=*Ke{-ui? zj}(5aUx4EYRuJ%qXgI*+qoWBE$4U5__qgd5F&LaL?OUp`7n5rWemCkZ9Xm;BYnBV2mt}J zX$=1L#ot`|@FM8=r@_Cz_xjMk;e&sB@Fc;5ZZT4l3Q&xA=Th*?>raf*;1_`k&;mu@ zSN!FL-(33e(yxR5H-6}E50;{_(hT_|k^zPz?}L54B(MPGjq7MgCK3BnkPzP_L~C26eq(!mIcpa)R**kzfR4)?Y6%WI!}X4>J$GBshpU z)(~of$lfXQ*7!uO@QI@Ov9U6LPR9HKlj|UVlLshlkmRd8tp1@~RbbeHr3>uxeTPCnDU^Co* z-%oK1zIX8LMtVO#Jh2Z`T=70<3v!I%t40_m3F&3{&L(OlgGU zgzlFi(qF&*ayn2K`T&b@XZ_c|`j4mXM^hR{92)0Nj?OsF#n6oR18x6!J+JFt=r|a_ zIgV)fUXk$$)vQcLpJ@sOK8-4g#^w7JhCwk%)Ttc3U4aY_&Q3QR-TeBDfWsA0%kbq5 z0c}*?f6*}J-hPSvQ}DedFhX$hb`R-ZPeB|${n8AH5eDD;K@w9tRIWb!6rO_b z9U=*|ynDZkGNHl!ho5Nq@Zl#qeEjeeBR+rl$)Wh;`%el@eS7?TT@_hAe0%x>)!Xo=rF#Inx^WXlbKd?5B27>?n^am#8<%hgQ z()I}d!3mcjfR|-IjxLw4hx7D_6=?B63HjAtM~ynzhfjZy+!M*YG*G-QvD5iBK3}?j z{PX_5_uipqFU;BfXnVJ(??><4&!tD1geUr+e~=`qv5>65i62Jv`JGo&)i~)15HQMr zZV!{q)8iDM4;Nma`=@adp9wec;K%14Ki{8v^x#p=^Q9i~>pw<~*V}b=*l)l0@0@ZU z960eo{>D@jPZ3f9ERB8aib7*M7A5NlweXTeYb--*RP5=$@6=9ycu-VmmEcrSd%a10 zx=9g~%8SzLP5S*NBfef_-Y??29M9+sNivK~(lXEA9|8@%5`0iuj?VBGz`YlU>|coD zm0{n9BFY@Wi#n%BJgw>yLx_?Ng{#1P#OE|oF-A(M3}gYvnn;8=klsO3BB2@@7vJ|| z=I`A8u}y(xRDw_+w;!zk%WYL<6@=<_RaJCd!KQyzl0{u&Nlj2Fos~pI;3Z9wO(>YA zF_b2XG|i~cDil2ahR3EQPa+@r

5&G(?7z6+zU{rXZ-Af=CBxqIFu~MOo7@qq2%n zh{mWAr^>7>U_87|sFcWaGOcR5!ts($35>uih%K=+AuEh%(n%HTMu>!r0%V-Z!{o=D z@T?$X9yoy)MS>$x20~Rdfz+XJC5aRS0ZYviESh}`qw;wece0=~Mv`e+qc}_vNlCme zf$q_HY@gsofm0NMVHHUhc*-P`j412)CCGOs$7TRlLtIQ_7z({$37L}=71Bk;VxeK4 zrm=h?DKVgF84HazC7BRJ6)qFjj{v0;gpOKhoKCZ{%7FV=PM2krCc_X_M$!eIBQ#k+ zkW3>b&BW=9D2Xy9!!Y3_0mTJjaFB{3QJ8UA<|v6{DM0}3f{zIjDWo*kNmf~dm1R~n zktBzmmf!$hG=g3NCx8qnN|9Nts*d@lMU5s&niM3B5(QEsI4}>*ii)W55~-WONT`g# z7%UCOsD7SNgD_-4FesK+LGCQJ4Jr79qT^*%l}Vk_d6g7VToQd#Ns}&+9M&0$jK&BB z!zk2Qia_r*O~hAaRwqe-4kXxvMZX0Kp+eLe6d9FfSw%I;G$}F?$zx&^35;w^7)3IK z#F4U~$_yq!Mwn8eMMW1BmDYJsJ0gylQyHDnOp?TdEzluGkqHc0MS>TtunZ;Wf(Eye zQ*;%apkPZOhwKtbA_zfeNkQXK`45z30*iv)L4Dv*nn4W$P!r4QIw{LMWC@{QpoEIw zibONA2Fa#DD6$&X7}E=OBNax$it)6_VUYyL42^S(gdP0 zs7IC=@=huO){6xBsF+7i0>N^W(M<+INn%h`62g=hAWvAx5m8iS6URzCNDP-5g^@(8 zJ+vTLiASR(4avvpI>l2wP13ps2ElByge0;A&w!*<)+Aw4cphZPX*5goB?;yB;~ zm_`sA!9jjO@=<~+8p?~1Rhr^VvZ!$e;cAS)>1Yjop=AaG01c8Vhh-!L0<29_B#wa zmS7$PG5Jgo#)8QrmRDB6A+!!&rlA9Lfu>NtlGac&Mw8GPNFW+QSusJn5E_GpV|Y^I zWkj*Dn7YcLGc3VL8YBHJE1i2|Xl&&wtq8VX+!2||J-Fh+uMF)9mjfFy5OS5d44^6Wkw5dxm%kte~i z45%3ssFIS2QDA34jKXLFD?$cKm>Qa=We9N0wm@p=Ip&REAuC{uVexrzIj|lYqhcr% zh20#QN>UI4M*0N}iw06er)9`ALeU_jG?^1Lh%A8+!RHW`c!Fj$9<3+}Wl|}S7FJBf zJnzZN?>`AC8J3M4?2@g=n5{$ zm}O`TP3BbwkAs612y;>gt?-c2V0mK}F;I%-6$msMQ^d0*{CbEK9?}!a9oiG-fh0iq zLOki53}p@30_6#^Bax3GAuU5u(F3d_EE3TmUJfD!qDv>FIe2(MMD^545P=2Za35;cdD15Qd7QdTWC|;TuXq_|!3?v8! zqN|`jBiTkLBpQ|k0mg)lWztX=N2UmwAz-x71RjE6%Rz+^3i4^76<|WKuvruyYzCDf zqhC;yDn=kfpF`_mbSexjXdSRW2XhCOlY}XQjAGCY4z*$knc^7OXwV8IR4fD;58)=u zU=7g((*uML9WC*SWPDI143!4m1p7l`SgagGE-!PU3YZv!05dTV%uraG$S{IQBw#9$ zkjYSr0!&I-(x6nKR#^q~0)GQ)l7TXjbp`TN0e7>S1dc$@MHLd%1d$}dEI@}vUV&JH zF2FY-tz;;7R)$SO3J`UwAu}OzM35DT8^*W_lTIf%kSC-Mg<(O#L6E$dx~or1BM1s1 zFtA%C&X`Pzg3?wnL9jAlhT+SiD2Sr2VQI-1Ut#;320(5wXVEzbJ;SPj7L|mDOxk^V zoWmpV3Q&eh!62ckVF2iYF43@`!QT+^U>p+e3RoB{M}xpvUL1#kP zKuAJcF#;A@##bTKR0?()coG}}!wSX-ln9(NSgtyjm*HV8XfU-D9`>3>Jf>~`Y1;1Q z4on>gQVK?*4BrV0ZD=hHwlahpgeA;FN;SxZM6j^wjl?er zwk>Qx9VV>|J#L6)1uH-^@QE}HRs+`KF`~n-BSP09a9B81q7ESmrvUr~O9)yLc+*u6f1e_$3AwM+^7KuoK z+fad$fb$E{0YjXH-9+GZ0y+{Rh%p=s1==5mtpaU}r2-$CFg6`CNwP0C?eTY0g4Mtb z^CajDdJUWc@y>A2a-b53c*Bu}!vK-On+(I5fk}@l!%QL}o?)gb6h*_^fMDhr1CxQKK7X1h7z9{%Xa;yHP-g@zFbD`}XAX2K z@t6`G2mq8Q>_HBRoq`FZ0+R$L6$>cD6cs{Wrr<&tmOK<2Y^A&3 z49gq_3IX#U_M}X3u#d73fb2ZE z5bbwAeMN9vqyi!wq)%`B?uGMp^>_h56uu$+`U306U#y5d{ zBdA9IWfKT8{L;h$fci@l9E%VdA_FwC3!t>_1O2Jnh==^r0!}@8X+XdzFh!pl`1x@d z*haFz$H{ZezKwRT!yqWMA^fI^k5gd;^FKFn+|GQ{*ESHR1b+3KHa;#G`Q(~J!3>WT z0KOaG`6py!7`E5%hVH5y4#rGju7Oq~a>+gMH2y(g*a%@`^57Z1UAjjmAD37JS0OZw zVCCzJzq$0<7M?P~$A2fm;w3h%?g>kVm_JXJv&qKv$30AjJfYj{pZC-5?#VMR5uf`>t)`FRlKbnA$l8bR z1{e3n9>J%lKVGt=7TW_37I^xY|Ml`5qR)?;_tOZ2N9;~Ge8yGop%IOS-wIC&Kp0RN z4Z?|hH37c<#?nOyK?D{IF9ZIJssN;d1r9sfK!4#&DkSh11WTae4Gj)k0k*peWyvYP zfB*vmU&8KIff89bn!xt}#-RrWfW*-hkUI`uClCS{^R$V@enpt#u+gA{fZxMJ0LIJ1 z(g2hS_=tmJ47e9|0SpSi`upy?{|pWrX50^D4< zYuG6Rzy$^m#sza(2jB}hfJEQ}#ul(31*?nLfdaf0ASpqZ00zQM#7GTm5Pm-iaFm1% z1~?w%fwhG50)z*n24(_O7Pu~~FSwf;I)Ipm3H}bS4I?-PI1`ZQhl4SZ7z$%Vcxb>*003Ux7UlCK-os3AtBoET)*HYgc#|Ti72Lz78z3>u% zZG#fw&mwAu8q}O(0wxRd8{Nc_V?aYR@+GRMeID6sa1?+I4GaV}KTrsu_Ly%H?y%uG z!J-0A4~PKhlK=zE4 zoJhmpGD7x`DKCC{72y{|HGtbAqC~0)lyQa!Vt^A8#2sc?Lwp2M4|EF3gkJW*CC$N*ARhYLvyNYFyS%YZ>JXS{|+ z0OSFY!umliKqTr|VgvC);24|%c#Sczexyjk@i72S6N2(Gq$J>BggDVR2p2>afDZtC zG=j%EzKJVF7y{A^Y)udVdBG=esjxzV30M@OFu<^AkeHEB09gMqIrYzzV=yU%JE%j0 zjsWfo0fW)NcLm}Pc_0{*h1d*GVio`q!XqGiBYFlG((on?egw?|06=^lh#d$GKLI>a zaD|a}U_`h;g#gAW8Syig0W<&+2-E?R3qc^@ThJ6h(U7Kq2nGkO1nQ<37BC?ER?x(w z+qeA`N7f=u>v!NhKu`@60dN3|1KwZ*iQqq0)PM_s8$*r)%mwR;&~qx>cpQ9z5Dw@P z>ju{yA{YKHE1C$b3_=kIrXwK&EfN5SI0Qo&Kx7;bm0&c<$cT&)hL;Q24UjW<2N6P9 zp%u~uH4hIRu@pu})B_9*z|bnBe)RDSFs4m>mXC91G3`Dgv_xFo*#|L*^(tgJcIIj0H>z zlz@l4fFb}$5CEHi$=(qp1`-A#1w(k@JJ1kDS6+nD^3yOLEB%g-qC=Q9 zXl(F0XT-AsH2~N{!AOKJASDnE1|K1qLSq>q>~MrM4QT_4gq=hhP!s~n==L3V!;%;@ z%Ob4$yhANY{X$yj-UV)L1F>@L-+;i?Z zYvaY9xcvG(#28@>!$d(aPi8?JG=lli=?0K$AY(8k!NUf$Mqo@JRWKa_ zJIKfYK#R5s1Q!fk3}H3cvIx=un?huproj`uN&(IjAk<)CL%vcbm?e-W5WKLVq2M*c zw7~QrffV`y<_KmChZstjWdO=|9RY(EaTOyLgHQx#g4#wf1NH${9c)J!yaRw9e1J?S zpoqvr0270dAy5H)Vnt}6VaQPe`?KJ1!1byK3mn!Bj5Xv7!KfF3ngQVeeusP*^cJEX z&?#&Qa6dwZ&`%=t1Yu-cfS!?V0JUj=eIQ>z>IkC&J7`^4hgQ(`!Bp8zyCrSt@8d0xv%Q`FQmR|Z@+lF zmwW$(d&Re3Nd6Ai-+mznJorHczji}J!VhUZ4UG*$;` z(pVHMgb5kaz<_@b0bg(%$o9=xg!eZ8oyad-!vK8MCv1^H7=rp8D)`rcC{mCDNK^dO z!2c2uh5iJX%zSF%4t{>bLxo>aSpcFha43{3km1jr_@#y4Aj7`tPch*Kzr^J_sh6RAh6ZR;rIYxX*vL}O#JnY_i-Zi|7X~D_H>xPbQ1fJ z;1?se{r!_aj}jpL&%JOxA=&(;1rA++mGyHAz>*MI!kbURZy@-m>TGm=X#g8qU;%x6 z-!)mfpMV&nZ%DXjf0~TypYfWuIPCE=$^rM2HpMD3r2%K z&53Kazq}FyEG6tZGB&}z_u93;FD4QYv0w1hokwpz59sH{-^YUt3v8qN)WA;w8Ea2m(5wE~cM6PHg zBi}bxy}a<7OCMhPb*tNdA_4y|L;{kZ%*$7_2}w!7UkslNcB7GHZoq`dlLwRu01AjG zU**3`EgR!n7Wbv@b|DCooRAn&v{~<&1-P%e%F~8b+f5T`rJ+cPg z8~WcEji!gy_^Z)qdRUErW;7b9IWXt{FB^@9b^x*q$qJc{w1M|@fe-3|(O)p`O0&a@I))AbmhkHfA7%tI_KW&@w_y!uOE$LPqDX~N8*jg!-K(30o{&pZ zLLmkPIX1ZQWHCx`Xr-#fgqro|`zFEQXpfDg*v5D-*g&Cx!}0rT#P##`J-Bs-i#*$2 zW~NvF?(cul{;?tisw7;26Pp$w;LlvWslW%c1Ae{E&p@< zk8aS&H@a_-D;$QXO4Kpgq$EIx}vcXQSz0e4Ec_=lcd{ zY#TN9IvZHU8$mwO08pV_99%Z5;{eBLk4%4<{;@*|Jkvk$$3I@?WR8W$qJD1m575VG zxeC)!Y6lznYv64?ExzF!tXEjP3fh)pa|=OUo5nL$XI;cD&rT@f)2% z>zFaz7J?)fgpp2#;L()w585y$6We2Fqn*i~99#U{F}rk$j^(}?9hhDX`&-QDmpuJAVQ{7od;k~_%i+B5;>3Oy6+a7APZ&(V+r~xf( z)cJ8?PpL{WX|m78m4y=54(VB?&rkaCK(9OOsHv8=DOpeLkiTgj$@TtpQ5w3QZCuB3 zj*k8Mh;*hS$C659M@%^#-|L5Y^cq+WkceBY_-DcRN{?kW>a7#o$EfPUWY?#QsgexVRBj6%Kl<#?ew0T4!O5lmC80-$|^RfR?eI^%ZcNy(;v&#-h4RRcayp@nsM$x zYIT0jxo5Rv&=*?<^or}^TQrgm?_pfyah68QWIq(LQ);P%{T4qzTO0?Y=WCy&vL5!? zp0%zQ$#&v)lxb%!t;XFwtE-S-T8pK=7}Zv`HLYx>bfPU$wnlUQ zfn%($hK}}m8F(In*!bfpHkD87$>31R#WU^_E37MxQ^h|D?vKT`AmtOhYg#R{HjR#X z{U^8AJnv>!W;&BoJ-6zZ^^Oiqq3NrZJkorrwWF)6UTzfYVk;D9Le`WT&YJ9*l4yOt z@P5B{ORX$drsp{0r&JoZCuy9v$wDmwEUUro9s68aky9p5;Es^N=)=9`ghUIM$r$; zLUwREwfy9X=9d1T-}B7pBMbGsuu5q*XD3S^@8uzJJb)W%_0+NB+|uJgAImk zW51=hB5;JDEH%I0T|8ZYjT4IfDMro;hku%w?1$jF2 z$D%>iDvsx@;;P2t;&2>J(Uxev6tXV3q;d$lz16Axl9OwJW-vk>(=PY|tUbYS>r4C! ziy&KOwHEE1`Obc&j?1%*G zHBW5QT_{OcY;BWWwk=i@aXMPv8f?0~Ypl)5=N2)s@adeGYWpo-GTWF~1tml6QTG#ptNwZrC&`> zx6Yk&da%}3T~EPeKb?}xVk}sSnAK7>UgwQo^;_A1sLT~veQvF@OV#aBSj!>`p_Ffhqri(J`??!msIk;cAMppG)S$|GRC8KJ8*93#X`$Na6mM8Bhe@d; zuOox-##d;#W9rgmFC;2#FX&5go}jDfPK%cF=H`8-HH*X3_L|MZRKVpE-E2v|D$ZUb z5)O@;)nLR@86D%7BeC92`?YD1lI!vK)cY*C*?wD_Pm=z8{?bj`X3=b<5rck7`u%EP zXO=pSK(v=-kH>w?Cc3k+@Y-LNre@(B5K`3G6VRh)$E;dy;{<_OA>H2}`(m%*DTviV zXB+C!NVr}`#`iR(yRx3#{qE{vB&b1IQ(l@<|`y|u4M z0kWOguSo07lQ^DU)aT>kd1e`w!k$|@P@dbJ;nR_I z_d~)o9wJn9-OoSkv1l!3O$>3mU4(V$%(lqmY}IUq9tSpuUT!=K+9z$VNTi8zY?(Oa z*7ih(k7P-D8Cf{+m2vjui|=Xg!XGLQbWcN;is4S#u?h0GF_$De^{%&(4GXER`=+@& zH=h|Nna-wOzRK^~EKcYeZA;sh%RCauqhz}rGZw!qMx*=!EV+HGDTZr4$FT3I(C#8QqheN^}P z)Z#X7=T^1W+-Z+xXSD6u6vkUmUFYljM7A;rdrkI9%e#+6s@=RVUfkOAy9*VLq+6F6 zQ%yN?voWb1l$2H3aei;@TB&5i#Z$%RX$BN5RyUR$CnwIu>6xTp*gtP@(x!6SZ_>97 zHPQF>QK))|CXyZK%4l;a-DUw7cTQ{EFzdMO3KsDu&6;^>kjv~!{&wEsStc`mqNdfA zL_BfwWUf>!;j3gr@)0 zrO_NKu9N1U+qF}X*Gr*Jypxa?%4o6brW+|o)a}(m4K)x@N4YUuJ#y3Yxp^)Pi{@^g zrIO>Q&+KxpV;aUnBujc%bp+?f!3sxdr3#j1#Hz-7VXEbt1%ut0mtFXkZHaS*eN$&{ z!EYkec448rhoRJn`v+8|I7|tDV0{kw2Fw0DShP8P+^yiGr;cpNWcPA7SW8^s1h~j(bs+Y>T|*f3*CjO? zcNVfP>o#2WjcD6qQBJ$`QCx3TCiz2Tm|nJGXUAM~pC+-&w(0BN*0)W0WIgw5Yz-U3 z3So^(Wsnn#G%eO-uSz(tYa&+0(Lj6Djz*ZUeN!Lsez((Zj;*84vOO6~TPj?a%2;qz zx!vDqYi;u?V3A|?>5Z&EitU*TcN-)DU`M9iR=}IzK+Qr=N!RN zVmukkbg5jo44AdY!ezs`y||KGj(WXv@E*73MLug@C*1|B)!7evrWZmmw^yE^f9V?f zvSMzxQyoL=P_ryk%YfOQ3|gjhB=yDVuH%sPP~ewT%kAf_`Kh@%8c+Kje?Kws*c0Ah z!rC}2ES}m#UJvqWvg2O*V&PkaEAx6SH90*qi;GWJ4s&hjcPR;R(A?XoUcc{)IP^N% zj)~jJR&eF#$z>Y0WkX#ujlH!wWD5y(x*;sCOJYT*mVT;ml)Iu$bVP@$Q_i)Bl1pz0 z)$p1vAMEX7qSB#ygCR>;pGScz*`8L;fq{OrcNklRPYMT1BhoZWQQ9&NZcKK6CA|zs z!j|dw5>R_b;@By;o~Omic`}$JED`T=v2&NQRA`B?a=7n4@2KzwS<*r)Jk9iTe5#eR z_~j9A&2>;4B3}!1pA(@u?=GZ^c}W~zqf)&HY3Xt+-72=o7yPybzu$Xn9lO??k7%|W z8YTC&mMeSCR+93XQf5cGNyvWW881)Uiocf?54%IxXZDzJ^0=%xuK`QGl`;EDY;4sD zindDgV9Sp~8yEC`AyQho1A@Dpv1n-}?5gwmxGk1g2lMHLTaz>Dv>n)rr?rbuGs2=$ zwo^kke&LEZ3kF`Mv+j?kijG2t9^^+#YpCs{qT(54YniFpoTQp<^HK3zOm=>-nkao{ z!WYWJMp|u`#nr$W_oR~h+j%{3xvm+(e^jorG)zU*bE zvO`r#6#Ci38fiK=hU<3&tCdexI%TaFN;ypSB|RSotzpSWCt}auYAayogQIZSGM8;^ zwWUu_IJMsH2+nHzYR5-5QjJ4G)b_+6Ee*q69OYWK3-$vNMP+f^eD0kW!OL?TD)UOD z!^2c7 zt>%U_aBurAe(#=(|!*?L_GKwtt98js~y`*Jv2cNzuz_Rgt2FAXz5bhxj^^JQN&> zNCvk3x?7GWyaC~P!WTPn%IvY+h{-edWV?d_wyQY`n@KQ7M3#&lM!D@04~EogENwgA zDx7PVPV`!Vxye3o1+?DGy>AL?FLgM=2lEHR)zB*7m#AP=DA$yR2c8{F(fPG@J57pJmYZ>>8 zyd&dtRK0H1n<`J{>agdV9Ie}mYrZav*9gu7Ef49vtJk$f+#Lv!(s;~NIzl)$9;U%1 z&;5&ac%h0>@AJ(*b8BWBPEuByx!~BM_Dps)i=(BcA-^}VP9(kOq%^`oT)o_M;Um?> zg54el&-wYvWnb;*IbyaMg)Ny-Em^7yj`p;8soSR2LsHFE%}cYjBwjOB3ny1HVR0*r z&9r|!wmKOn>@jEBp;7bxBpwdAt?^hr%zB&pWIc|gs_jlGN_+Ncn=|E!kK~TWVz!qZ z&t-cj7Z)79Je?7}T&l%&_?A_Eex6VvVq1vMt&w6X5=h3?n2#usxr^>H*(+f_GvYkQ zUN2GG4=iM^IS5;3mU_6koH#D4!E^t*6Is8jHTNa_W9O-WdN2NxTabA{(~y|h+0JEr4fTDMi!p1eBk z>_Hl>XVQs|OqQOEWj}RMLpqbOBxAL1yp$;&p9iTd{H@@2->Bpp`FSYj)OGVfDxK?k zEMB|Di(%CVw1D8wYS=YLql$FBlTxO&Rw7GG1dOHUO7_alSo3J3 z4v{_Cwse^|Dfr6A!PY{ktMqhXX_Ai0ZEUr=^o3(y5Zvu$l9@DO8Qssc9R6nMEQ!g* zv6w!SdbAp*a$B|5IawAu6+gwz&a59?8L{nv7e|K&i#Q5uPP^A$v}c7xbZu`+e3)@* z%_AvnW6$%XqD=j)Qdiss&!RdBXY*OU*JyVKBl+5|s->>%(F0yl?ll|bqlJ>{k=9BM zRfMr05@zaguaM5TFU+&ytvfyq`BqY19kH1;-P+X>wa(NsOIxG6R@B`moZ0f`%2<2) z7Kb2?()m4At69~YENq2H3P5}8;l!A;Wb z#CC|-f zx$Phtf;Su4BwgWrV^cnKE?plv%)=Lp&E!n&Li=OGM0{MiYU+XGX0Di6Zw5w}xS4$} z&s@D?T6PLKj3h;!s7!YkTJ*_F;Vf?FQniv?_!MvQyaKsx01hpNG@o|@*_jv~3c=Hs(o_dYicr35vb+nn;ydaQHZ ze7x%>Qe>F)`9&%bF$a}Hy$lu0#hVdpEc<#A3< z8db?fT8U)eRxWSIO0YhPg$E62v7Ta&O~v+b!Bgo=hYihbwz$nE?R5VF=3T8*4h84t zZmQo{t`x_h+^NnusnqNo>g`mcE?0=g))hSV$HPEkEYypeO$uJRZDtem`*6%o;V|6V zTme_|N-xeovsY~9uvXY+tDJ1K=s>R*L-v4kyAr3TPVAD*%L znNZ$E6o~#NYisRBvuKi;o@}lL5*>CPFFV<}y({b3O6^Dw5p!-mvRLmxcrLs)w~Lc3 z{gJu;+@;c4Jv8=7-Gd^Huk!*5b2aH+a~rX!VmvD%qcy4u9Wm$gb(#~5qU&J>8F zb}VHVU=>GBD%nor!M!$%qpEf9T31i8>2Mnh_n&{W~?F=@u3+QV^o)-#jN zVYqUOJK4s1u+(?TPBLz4do1Nryw5sobwZhGDZqypmYeO; zuGUU%XiG;ZM6EnE=kv-J=*8)EBw!8|6gAvhPFv*_+vu7v&0{h((K_=BxYFy7=C{2J zbC2uc~Qt!ixX$F zG#U8iNoB-#OWpjoQdZ)pn-uk={e)1Dx6A#F##+wp=tvNcrIe&x%YJ=K6tk&V8W<6R~zP+onaK zQx!eaI&Py(t?q6kGq4nl=D9g}t3a-okLUWaUGXWWzEmU^v8dR*P|HIZTCCA9PnzLr z-!`37+3H!P=&s+rmFsnwL#sk~$D~gkbI%_>^djoHIkAP$;lS_`w@xNx7-)Dt98>#K`cx zCoZ;w90>ReGHE%q+(j{+@vG5bdsfF0p$$6MiUpkKXJS+K+(z;u7!LXp``uu;99Hd- zRgW&DM}z*Mk98s4K7_fT8|2%1z4kRxq2~G)k2* zPe;oRVmiOM);X`4w^nmYZ_~SK$Wdb1ovr=7T&29Z^a`0#JyR7z=_U)*TH8={+O_b` zlW|{y9}FwK)zm!Dr>?q%1koTs+RI$jwcwC9$0&^RMS|3x%68pUU8 zs$jp+Q|qKOO*%QY?QANMW}J}{o#%jb4S}1p*U<3RH->>1m~0`wY&|mB+kXq5)v|-h;ViK%qa)8 z?Tfh}k=q~}z~%3zBa>ms5l-Z%LdmsQ_Mhto&(`91Cc1I=#2X!>^0cSuOjxv?Ioju2 zOK!K17yLf&bQ&GYxu)|X`J>etVph*Zk)OBKh{sxkH(tusZxQ|)Jz`zryi2;w*XgMg z>+W3%2zj~CR>o(3t*;LCdak+htwVaW73ye#&T2C_jYgerTdKkep>m$-OIN0*5I6W;Gm@GCPlvE6B&e%Vc}hnavm+=?Yj{cI_I z>^jI!#cHy5E9<0v6)HxX`?|Hc9JQNdwU=HGLsVu$t|jNLo1pB=Vax~TKIWbdLW@!~ z)ExEv)u`IBg}JLW;Br~KA%w#M>AZC7j_LJQJhrxlz`|aGJ8^asz{bx)yaDK3DKW)h zZ5!IMsdb}z=ybzlF)S*pT%|SL2DjJw=}?ayGR{?Fr7BymSxrPk6?PBJQCRFa1T2o-MOLDkLpHkzuHQ;uU;P&NX0VqL7bmo#Z*z!%dLtpJULaD zagPdB3SDXSG-}krlWPq-&cei!4M>&nxSF`e$zFeS@tOO#V3f~A7oI}2ubLS%Wzja{ ztbf8en$DfrD{?MZ**Rc3W&ruedYqAG9v>x4*ImgE7^U47yND!8iNVfq#fGJ$c+Nz; zB}XDVDca+uh>Mo|&cW;&&nt3Ua1#ZWLtiajTOZdGgXGDf6q>1w zCs>-f!YCW;Ee5abfL_M7oqp9bFxkt8b9%RltblSNYWF5E#mlMOZKSy;X~SPW>N}u5@iR{%vo;vk?kukOq}dnj?fl zN|~i-kh=H({jK-^c^${@N0#h|VD#7hD^`{n7J zIDU3XQ*rRvR+-@uuqvY~iS6+@!|i|ZZ8T$`zpyyd@^L%9z!)7&wM=Z*Yu&yKOV0_} z*qqmB**|RS%PlskRno z(CPk7+-CoFk*5sUHaIeMnx)dEm{T_qUyq`9&6-f3(o!ankd|usV@Wl3dugc~*oB_UayN9bRJO15jw?;_l z!NQx<-Vv0;N|#{rCShED=V57obehsT#z+QW-9LBvXpJ^n*Q`(}aB8PR!=w-dWREUZ z8lREdi0#>Rn~C1atuw4$0NNAM^75GvkMZnLCf)=|eaEZOO`bF_vVVLXDk%r6&@F!T z+ECgY;zkDX$W8S2SoL6B@$E)ia3{YFZ^n!FdB-e1W2nCD+jS;P?<3aIEe$xk|3mT; zk#*uvzf5g5e{py^>;nprJ1(Js3-Fa8zlE0PztTtM)ZK*v!Fcc#?Nco3VrP}qw`IJV zPVVwkaNc|73-t!lxDyt-|08YH&OCUu`QS@u68UE{jISEaxHi%x_G=4)K2ASERIA22rc=m1|ke&9ErV9i-fv zJJ5)o%>M5GCfE}54n%Nxd65X+{=RWJw*R&#o$D{6M$@eGdm=c0P~vp;hm@Hx&ZNom zSEqg7HCkn?w6P{M%Ub8S<;8`}S>xL9@7(M#lN-JT=r{(5%uxeiN^GDN(O@(~H(H|V z8_XO={jo9nq3EXav!4eR*}SVEj_rGXJlPS$jWukay)6uW0Ntn8mug9cE>W~|SE~3N>2Z*;o8Ugg zBns{R)%o%gW=}_LfCR6gE^z9Ha)PT=J=F2_Y9&l~u<(|h5>lbmxd|-OCax_upju|J zGd%k{75_6>a*J=dQT)DcT!O5kvs;a^GV7$Dz27Zr&OUhlmui>{tL5u%FllU9F7|Wp zpWrbs1dZ<~ySP(wcg6 z+#nAQ;u5?c87>jtVf9eD6WgN7fzv&ynz^xwbF(iBZ-3RToBUNS=JI{hhPvma^5Xi^ zEaNnGz5|TaX+iQ$*T(1Ikh}j~da1fxsqIO9b=#psT_1ca*yQ;xPMxt{J+hxG%o_G& zrmR+Dn_C3kVM_kd?6nk{fQGEMdoXY17oKuY%+`oxZp7{d=Rd@lzBp<;p5FDdES|NI zfXVjLu|TG9FdlwSS_FSa+L7l)!0?0_KRtM|$HMhXbM*89tPNL)i9%Ar6SmR)wOcPt zYiXQn1N}6qIVgLktS-_8OkzItFseR;@l?^)b>$1s< zCxlh=R&Rv&-1R<*8E^cp)5sM(GD9Zn*2i_2ULKyPg;Go zDB93F>h+0)9LCV>^fcH`kdNC3F+rCyX@ChfK4qIm{3Op|GFH^&M4n-JP;PZgH(}JA zLU(O}=D&5@*1!H4P^2jtrspyR*XJDszA?-CX3#W8#O`dR)fFt<_T~s}!i77DXH#+G zDDGtg_7}kk%SDvaAoT?I66e7}o$>okY*m;K;+yZ(oa_&5^hX zy_Rv>3oU;L^cD-y86NKezKplu)hKG^b@bXZ7yA0NeG7W59N*^i{M0ez((q_5KM8Xw z2_|_2J@|H#K6ACcghAg=miBxjdOr79lv*>ZIDjxowFh@DRM@$L7#TpO8-7PrOng}W z9@)@@2~p$?kiZ>&amHQ;(O*O0t-6s14Et2AzxN`wHZ~msYkmY$JQ&eXzw@2qA^Qb8+uvSuY z*c;%0a2*~Nw?C_oUXPRU-&Sldszm<-rVBE|pOhchAA0aM)OwkCw9qXuphK^NQ_C%g z7KfrRRn>*Z(E0>67n^cJ{{tXFfdF;r1O*f-582mY2Xv&Oy0hu!P&gM$w~g=e2fmvG z1mG*x&Q9>#2Q{ zKj&?^F!Qh+Y?YVR?5X@Nf=+hh6O69vzWc5ZhmZN%2Qy5jzfCoBL*rYzOhb!!_|&;( z#79e*ul0KOuiZtBW!T~68~J2EgRgyem&PiXt>aEIG`sM)e%?*S4E@{YNZGvt+e0j~ zNZE*s#(slsN-;FO|A*9MsV4QCi%$c?9?H)!2Fmsz4ZFv4)1XTm?QOl>)_Ey=6R?)u zp$>u}EI z@P!&xZzc~4TI0JQN99%uk=7YMWM!fJ}RFFTd*SD$=5gClYo1?wYT?* zh-^OpPoRJNvT)``?IqID_D5mdt=nL;IL=Ne&BHay?4PyJZ2EtE)zts$FFuBteY^pR zo=Z^IrShysNPhEg{yLFizsTqH@%8xwnDL~)uazq8 z8V{5zOc}elRc>)oN}B!Nw1Hl?WF#C9IDXwt#ptnZel*WWXGl$ z<1%fb=F%VC%JjV#^d#NebO%Dayz=nsc#u{m(QPp`4p-K8emBdFgnkSUjq6hRRhQ-On(iC|Sp6mQb)Ol#OB0|@LGMG9+te=M z4M?0UfAsV7mv1K$3$XD?N5il=X>Kz!!dl$1H3ktW| zB;>m{0mRO3YyN9RN~;%IcCzH4NL^V6T`cxqH_ItF$s37G2aaQnh>SB+WLTiB0l)mZ z@{JjK?PE0NPkoMSwuNeabxnS|5JKl~4P=JY4t)kNSJSm2Pu%j;lIMGMe9Km+@-pg7 zSKxWsmv$L)Ukt)@ejBu8n;5hGr%ufUt%I5i0&x0giW(um=<{|Z>-O;W9Zslb{M#c& zG2RpN+)2qbWjTW^=%Z`3d5O+pN-qv@%T5O zU97>$9F|uK|H(Msh0+oI|Dc5zi5!&*o*gGy$o`-F~HNKM{^7ll93* z*-U^|0eYOY8r7-UE`$wFatZVqd0Z!TlqvI1X`vRg1`}-wT?Z-lwfee_F44tQ+c#b} zczZl3^kZw>OVFS>16r}Qt~6c=wXOf}zZ#@{dWy9kVCq{P+7QLVLz@UlrkNgJ;Vm)s zC~r0<+b9#+4reSnk9|^{)YQD8M0dko7SFj;>4ofQHg$E326-7wbRN+D>S-%mSBKMrXM&CXHwwva_b;T{`HOj z5&78*-b%B`f7`jO)T#@duJ?ti|5sX+-MgJ@f%bW5eYV^t;9e}+uM!GKvu!GU~ zd3s%5fV+i;6`iL7VxfZGJBX%Ir!gHvMd|Oop1~jMM-20u=Vs(5oD-hp^3Sy!13>wx z55Mi4WqJetGP}Z>z;CiKL|p1D13t0w>T0#dx3M>RryrbDMJ#E39P#Dn+65W=OPgxBYlaxdwoa1r>%Qto>~)T&Dk0uKTeEq* zuRjMcQEl*2yZR@{3+eth*Rn!y^f%h@h~lZUA5>6)kO;KW4WP6a5+*=!^HnJ9i$?Y~ z8&!3lEVZNC`Jbuu7{yU%O5-PtK=>g z5c%$%Gzjgn74W=Z>k(3ow-q6OsUYxcVyYbh`_}$`&Io1B+)d69 zu7mCkVq59HeTRUsAyL(@2d{C z$q?&Y2|w{J=-kCU1o$$uy>f$k*Qsx5H)(ErBX~9|eNT(n z9$&?f{V+T+f$JcHFW$TxBYY}c8{U%?aZ|yXh21>PXFxU}-LLCs+(8x=K1Hw>q5puk zXVgC}ho{-z0$lK{etN2j700b8Z+~RLpY;9~*D}_?-=zFk2@gh{H^xh|p$YZ;j~e3U zG?K4Bq&}x$>7@MD>eihI_pJ%y*#NL>Ab>7cIWQ?H@*h>xx!ic{P`flF>zH?k9ZzYs zrx`^z)&P0$b#rlcV{YwluofDlKKpEF)O|W-)IsljU#mn7Cue8}sA^8$YgCA*W1F6p zAqm6c=jxQB(tk)HcvD)O)2q%q;>UbTcD|R}m6?OkhbSsfD*8>{$P;E8S8wxe|F7S* zEj|KB{>!AumCe5ubO1YLF=~`7^vK4`!*X(JHrIL;Tw&045VTbm0GrTu??qw1_OJ~i z-ujOLOE0Ff!t9n;Z$TDj*vm5_u}(W2T20HUjZ_;CjGP=t+rh0IC>6Ig@sy}PLb)GP z!-520K5JjljzGzAVmf%g3QY^JSN7pa=G(X#YJ(>jVO+KWI)lnVD^-CCsn52_ z?VRPtKXa8dstT4@Rfy6>c)y zolnWD4p?NfRknr@^RS(4F!8S|<=gMB4YH)q4s&XsMwg%UlB4tan^3pYem{A2lm53~ z=?jWfx!^TSrb}fSXp6(7R-cNf(R=`>62k4tDX1_<_?XYd&+a~D19tm!XWd5^HMR7b zor`&PBo~eA`ZDRScU$cUX69v;V#BNC!~3x~+M~^CnK+eZwp=>Rq~sERtFAo!)9b<`EZbFr0Lu zN!11xz$tbbXp=g%AH2WnW^32`*T3r^DFoD(XGTU1#@C(?U6`E&1Ke^}PtTrKQ}|AY z?K^D~pybO#&Djl8rMI8Tr*MLgXV|I+l`1oHL6CET9r#KUmseAUYj1bw0|c`PpK*>#dTV z2S$cLc6{8&72Gze%hw~Ah!6nMZoAa44t>U3ygqCPT-wb&5OEfcX31qw$H;E2c?W>> zI_Ks3YixbaV4?~qU3-&`_uJJc zV=*5MSM_j)bSdndk9DT$V_{`!*3Ym?gJt;oULB%Gz^rEaa2CJE!k_qVkmc>1=6yIU zSXz;yFJk@k@eP@}M*>|y^eS!Th4#`Hd+Ip;W2H;ynxFX@EO-Z%Fj%eTqsduwCpR7Hs2Wsoxp!Yg$4IU+no*VhMvitNN`PHjXa?53B``=eD zwL9N~E@_MUL0$sS$t%?={WX*OU0{PjqaARp02M(3+$4+Yz9f*ZztVID)h1eT0nwGm ziFqGpzUAYS->=!>;0FU7pA$DElvlT^Xs&2Gfqa7vpZ$fnC z;nrp1lW?I?FG1#M!``uIOCA(M>Ac3nWb+2e$?fU2x_u)iK=y#1KTFr#c=`F%=)S9W z;b3@V8{?h_Gx%;{vMitv>rQ+bZ=&`s-9##uGC8H z?K|9@oi)ogH3d|>%TX)Wzo(lnbY@SGc2eSgpGx-0DEQq}9u)GId0OemD{S@5QWL<6 z%Ggp%_fsSOHt7w*eemX_f16@i%uK6;WXL8po7ii{x7vS!eE>)akW0w#(^EJ|AGd;S z)2C7OG0*27{y7eSNDG8-6K|wLGfN9Yb>Kc4{;T{3XvX6J-zCONPU)#BF$i{=h2p2L z*;DTilgRV7jsZZ||B=QKmmEYpji_;<JBE`@)A#lMzymxL@+^5bazpQZMWDBh4ar837*ybh>Kx`TBxFbZeRV=Q}9RoeFlwqraQc>CAnSu z$(?r!jJM@Yt87PwZaUTqT$-PwfyOk#L2UHiletmZjq>$h9j}2c3EV30WZa_|mVner zE~>*TtsK5J%D8rb01QA!I>2(Y(`mYwegX5YK8wDaQDwJcR!#`Q{|I|Y8>A_BDgJVYCO4;_Ld)jL z%-B2Rlf68Ie$#`CHv*b@E#SN)D_-jQf-eWo-Xbt`l$Q7`Ljk`o(}#^O420> zJjW8G&0}Oo-2SEa>yGkAU*ol2`yMK_Q`soKD|t*3A<+w0hoezZ96LGcZ?>o7L*jW+ zD!x#>2H1g|?{kvcJj81sd}Xb|cNU;|dsDDk9Q3T4N?Dh3$umv$eK$C*H@&}7abPJ1 zi^lHt2Fd)c;7f6tX${0{cInTQB3Z8&{_c-ivkNC!05kD2hT8oKkcPU~A_iLMW3yZq zM!fwP1GJ|sU;2FU#NQ{cJINB%U2Zx=uGbfjPWx?VyK+B~t;hMIP`z=nI@v?CND+6! zS$IjtpAtbiED|B0sGaPcTlI)(`Zop~bV($UqD=!HU16OAJ&qp?kCuFO= zPrF*%Ium0C+#&T|hA$s?=0_dVCe2N+r@z+;(xq(-K;fTNXghDT@RrP?$(Bf!u6MLl zbB%o_Nb8Rah?Jk`4+h}dZ@86*i{Y9bLu|MH=_BQrso6iOR*B8n%cSh<5tLVZsI3{3 zYs>I&IlZUZZjF3XAFwRBP#~W(r3=e1d6CD4e988%vD~j#zfbRcfw)U(7XJ`M5?1i0 zoBh~`jfoy}qE=hr$2ut}aj9kMUtd~O7?e_TfVE*aw?Dnt5-PnCCMJ`$)?UNaK0O#H z8LhTUQ|^!Bog|sg$+sA>i^cwN&+JSo}NjmLegJyUPm%ODsc9P#^(YK@tZg%KaxM zu=H6MHEg;aeQR^Di}lNAz$pXAlVw^3wUwn9R;8JE~ga^clcRoRgC<+UqC^rje=LXfIEau^n2BK z%ZR7-O1p!J+NJRr($(hkKdUz)iUS?+wt*zIGVpEFlP0(D??pz=Y3O(df9Cx0$C^(49$LlOZ# zJ_rxXUZ@3YT1$R?M_W9n_w_Co%+D0WOzfWyKUcHvx>$vxthapkJ@v4^w zr8yVz(lOVQQeP8#qt-A~MoEM0muy`9%H*c8`>KHB8^!!rH6LjAjT#*!yRx&-QT=1rZ<#t@n&3}p-CE)WmuK%2*EoZX7+MiES{Anmv_<#nHXU_0r`s1l zut&csyVPW!gK1p)>(^8CD`3;2R3i`Dtt`~;vdlm80^A{P+dt)1U1vZ(+%M|Et$c52 z6?U~S(MqRPuLY0vAY-(##=EqlAQw8%~6=hsBPBB3jsK z7^h`-@(>P4TQVPBn6C%au~>3;@8dic-suzhCxw8+ye&@;uu3_&g!bvbI}mc$z_Y)F z=a8{LBx9@i6|Gd?@}UJ-_T|IhBx`;+SXRy8SDxIT>_e@8Miw^$jkmRDFF9J*hg0k= zh5q>l%v+<`9oVD7SEJ>1NtAhuVAGt=uZztPFo_Tu5pTsyp)b%8X6^IOHG`J=x`3T@ zx}3V*IV+u@W*dt}k9EF%DUGIOK+E)~jDalzAcc80HqT0nf;xyvOcIDh0AJ&Yp*|{E!a&D z^mgEGne#)CKDu52DXE(uN^kiTg;h367W=BUf;{4 z!77!iwJ#Y#yv@;Oa{P3;LC)MN`V(udLS7kl?R|sv>d81mK#d#qioaD~nP_p_XE>~= zP8C%I%FS6S149yxUWGkb)fPmpI(46h59(O|axE>Ejl~J=iVc`ru{I^ipk9PwAleVN zX~3@r2(xLiUwq>)kj+qCY~9NMUVJ=BIR z8(O4J1==>2?9A)H<;Se-O~7tBD}N}c+U4?Ur|>63ZFB-1*=lO&Io9S~`Lu=k#cnK+ zQ~d7@#d`;E)G*4v;Oun%E3_X_PdM|ZD@R}Jx*}D?>sE8>?udM|4VqkosB!P=Mxd{k z3`j_@(*1p2tOvJF02JL}hYkI?;W?F!_4%wyaow6;%=Oi(q{XPiQLu;ftV?n`E-LD zC+sOvKo4*{c>ay_Zbxv@dp}^gGQh{>(=iObTH_Ku(ATeMZ%)CS=!gVKgVE)53l7Ki zWQ?z=PFLOt?@xufkKfEdt{y_KZv(*!sQl5U5ckUEc^>R4^__FfvZKcjmC-Jrm_2p` z5?a8V6n}8$cb_*SQr%U+g@g}P|3F(TVyQfy*Ox8rX1Hn!CvDIIG>4TSrh>Q{Y!g+3b(7+kK-Yfyt5 zp+q4Vsvd4aDSH{f7y6G4#Tn_s*wH;{YpU%?func?toM+w33E(iZThstf z7Pc~Kf63nu?Kz#YhRz1eu2ww~bGo-o+Uv$XpWV2-IAqa|8`COSP@!QtEzSuTEMFn-GdB1K)RVCZ<0UFMxFp4Hx65Js2GIagd_k&~BiLT=i+~*zjwwJ*u`zErN{fb;oW?pc45tg-ybnAc+R?UhN0m&7vI_?{pK=@RN}&)Tm7XqS?= zi`rjTWXiM)$x0u3Ug}<4;<+PVAechr=aZUXU4L)!c3m7<5y8e*T@WL0f4e!z>)jo9 zxN~!UuP#!4Kc<*$x?2LBl0w!Nhg`>uG#`CmeseVDx19lEm@61|>O|>Sih-B?+SXvE zE~gKp?H<`>_=xiHYj>4pAnWQD z^a_;!*6HE4gHf-`{H_g!PVD|*-+P*yzV9f_v5nl?r?cK4TK68{dlJW9&YTe6ikoX| z%9M$hDgY+2SlpwevxWMt_q;LyfbGEY+_Tc@zMs?Kn~0yU>Al0qFhvYx==NFU`=(TO z=aok<{S7aQIUNnCtK%P{2t(HMk_ZohDU-g?mBCZ;b8IdQCSVg^P?bOyE`@aX66+w$ zOB}n1lyciVYFu|MJM)_1aTJv7gGnf zv%^$`4tu=6PC^a@gUio}yu}vuQ7>9CO7+TEKe2MF`9 z?1r5-S3$5dg5P3j|Eh1R_K;vbk>KK;$Q!!bFDc+$jbKrPp!D40o0{?D@W`GX^68lA z#M+3As}%ULVj_OW?ty81wmj75=Q8xHhSSfubfUC(3xw~j+6hdw!-QAT;nedQ=i>mi zuo20N9t>L8e5d*^SAC911PWirEdySjm%{F?A3Nqc7wwLS`y56`KJZ2zQfnCCv z6ziVY($c**&u&QkB@PFU`jjILVtTINo=fdhaHz`f{&U5;WZqsTT3uW|zt21$epYY9 z_ki}J)4TlUKxi~K(egzGd){XyDXm(F6c+OIJOxD8) zz@I)q6dMy{w9EF7cQ*k+dCzM(*CaOYAAUB4zCLF5iH2L#r08>_Uy&Zfcr=J^f1dj` zT4}GiQ5ycytGT(B-LM>f0C>~18N9hsf*SLbj^V2rAphL8UvyS1rr*V%BTmE00OGyq z?{YfxxAMwJ8y$)l6%D=#|sU&?UXBbzgjb z);>3IeaLAH|I*G_17ec@kO$o1LSW~pvmnNfE(UZDh_rt_#C)yJMlGn0_eGVSf}pYe zF<;mBMXfU`cPoF^c|PGv0ccW%v$FE#>%1zL0|sU=P1d*QJP^CiP3-(P@W%f031}-_Rv$PuW=Hvr2Y*sric|Rw0@HU4U9d z82IK~sYJk8pX8&fwla2)P^&@7MLcg>t-i4TyC_yhNw@0${4d&ZwO#1)njH>)G~O51^XV1i=D!qj!)9#;H?U>F$F(jEZij^1vef5 z=-K*DW0#w@Sr}(P`w(PaqK)K z52AKHfs9U456CY24qRd#vTZ#Mkm|R91<7IIstkDK@nL^pnv2bu82Gy%f3^0?`53K- zT}=mIXSCLq@4Ey6-dD-GVwwhzMjVzB?&b%Z9Au8bkA>=usBlA*D1@_M`X2;mcds8U# zX8%SNd(nP^o1Ku| z!Foe^jw9NZSv!oApm(`jgMFpM)S%yf#czUje}aCX6oe8P6P=aw`t+Qpq;SsrbxI|J z$);GxS!M4$O0Q<`E;M_VE0fI_Y_D8tDIw_@gvvfH&y@^Mo-Nyz_CW}>Q8~}$-QK@R z9Y}3~@oA!-$@kyt(_L*_#>9TD%>(qeBCo&>K-#MVQK`Z2y^z(~+_awyI`9NAz*NWp zt%CXN&Eq?i8$V}o?5f13A*tRgL4^A1M3hgLJ3e{Fv+6Ai4=%mDWFYjyY3s&LEw{Ic zHW1dET~kKTESP=lxc~uipvp`jXSSd`dJ$Zk-y;DkKe(WJ#RbPvoI<>VVRzQ-^{rlO zjQ}ohGJJm62WRO&qJ9~!K>J-WH;}C3S0PmbX!{vl6p5D;fjKqdKFEf!jE=zx)4TK3 z2H#18Jl(i@$3TIKAj6eq#K8#F@j3e)B8w9==>Qks)o}|Dhy*l|pAO(G8smXZ=jFkl zNVDgv+IHa>eW3UNFY#ks--+!P=}PtPL%aXEw5&H)-q`WW_c~c$_8yM(LHOmZF;jvK z|Ma(xSyH3nAJ(e|@$+fIl>h|I>Y(q(BYLyH8C1XO?9lQj2jJ3Lw2|xOAsfg23cW_* z!!Ry5mUPSI%g-rSut$3*O&WqS$$obn$Dhm!jDWk41%mv>iFq@?I6JS_J4)XbL1ID2 z0@c!xZu85VEXM8NjN#{9nSZQiAWQ*%wwo3kR!RT!MWb z2)prf_qkEp)ffK}tlM3_4L{{w@NuRJ*E!MU!#j(pmCxuJA!$wTGM$KO% zLInEc7;9>h&_pkiYXH_@P=~l_!ypN^0UXj`7rh+l6Ztn`@3qBWJ(k~wutzk?OVDGJ zY_ijI#rl!n#P370927UJ?v%-|Qh7VIlE!e%)Z1bJxnh=vo%@$ZAFiy!c9gxROjM{c zTYD8f9a(?YOwbzsnaAziIo^@#w2Ey;)zw$_jlq&AcH|l!&PJx0Um8yXM!)(k2)-yw zG|#K+8KHN1oGYMO?h@dD?`QXlHBIMk6w0+#uUf$9RtJhn4Fn_t3Hr`BZPZ!0@|-rt zo!-NK@g25ZZTIN?aPZdMZLDE91ZeP31I8Z|q&ozSlqgkBIC3ABvK{!1d5cW7&tJ5> zF&m6cra%AblkXw>^KZN$p3U!L`Jq19xM#p8-Kv+Y}n&zDLyYHyvJ zFgUaO*9hmx+GF$kEIHcFFY0~-V?fheize4KaR4P2hN01;?VBJ(02S=bdiVRC2J68} z!Y(a3nEdrx2D7aeH^?oLH`VFy5>mczcYp)Pz&%Uaof|-yp`ZJC;$uKwu`F)FlrWyt z40L3t#7z`A9>ez-Z!Oo>s_}bUr8nwOQ~lT2>F4I_5x#5p@}~T|E8EosV0(H|G#I+W zptz;X^l_$v7zuBb%zh!bpuP9Bed~T8^2RS%MYFhNf%lTq0vPM|a6J(tVxqRS*&M_{ zvEb-zE7S+XqEBpxtWd-56rwMN;{@s8Xc?6<=C36U%e-T~wLhXMt)E`+t>v0lH!j;I z!B!>zbp^EiUMwfz+sD1LH#aS}Go#pQ4!_g~13PgUX!ZZN^?BF3#^0e^@$yO+=)Pxo zlz;1BJ@`^2E_wEx>%L~&Q`_V~&T{+mtteAujr}25?O5s>Yim3Ry44Cm;JXM2uITHl zzv1S}C-b+CsXOW|V0(J(-6M3REU~fK0C^%v_il1n#vPr$w?CTMY%XnL*5Zbz>C8?g zwBD<=pnI!zd8LhOzq06a&B%mG-`79afbpBYKPT+3`$*nbfru>(>2jvj7w%Ke;{XInz~PODoP-wRqT;Ds+P8sv+}Uqc(Y)2?h!O* z&D*BGhF+*&2$y-mme#_TY=<2ESBWEwR*_@%UW4|gT(^M*xy5ur64=U{IwPPrSnZr%>Js?ZTJ>dP4D<{10wm=e3P~ZQ z+yDLp`L$S!p>P4e;uNF4+bT9og3g%=ZJnvu*$-Iu)V85+H@p#kT3$8(v4d_qwz16`1 zd*w9_;&&kYluf^7p|Nzsnr!!TuM81*8$)wMfI@1$s4ar_XI_Jp?cZ#5A{}{(Hs+mt zqEVT}=hx?h0&Ai1UWSlcZR6&-+TZQ+* zsO(^ZKwEbBc+}?IqwP^OmTQ#$&ebLhbO@jMWmsZLcu%sa*J!{WEWnHu>EQ5l>os|n zGY;dvrT;c*g14vgq^?|px%c4oLi7*}U6 zj5`YK5MDV|DJ7lD9DWWMLDMHR_z4xbK$rK z!buFl*j5JhHW0CX0bst`6Ad7fAl2*gwP2?BH>@o(Ni(UxiX!DJM1VVuoxEF)<@%AT zSK@`*KAG7xT@nCQ7`LZer!6@9+0_*LZ6yRF(5&NXGe0_sm2LcFr~E9kLEhGM=W9h^ zt;WAeL#-~D4wWzgo}+X`7PmXG>$lSi`K>NWgNR)) zODZ@>?VrB}!H5cxq~>6>Du%T$m@OF(qzAZJn*B|iD6VYuW0Bl%_rW1k`tzRjg8Uvh za1C@|5P1hH>RiaPS39lCMhg2QvA_AId?7(Ck4Y@KfnKE(%IpX>oou`2tQ`o*jD&RH z7wa~%)7%Wt!glpnx7X$|-gM0kfLBkKc_gQ81ormA!XzKN(d(rjz#VA>m}pWr`nLOZ z<8AGV+4b2%78yQ1%1#6r*M_$5_wEH-se%`Akr#NCQQ_!ri~Jp$C?)luZMS)UFM7lWm(Vf%_Lfwt;qgw7#$Z_E!DSw7}n@ zeLy&xQs>5>WpD-Fw~tpHZepgWqSX4g1!jPu1d_COXcl_uu`yUGY20 z!=BA@;{-rjZ?Q8sn{IPjb(WK!fvuaMzd(4I#yjuc>2`Bt9<$B|8!DE&Q_({Cy|O=j zi7P*T*xFzMZh6xWY)Z5@Dr|3a_2`+YCM`g^)*q0-H>oc0RR=Yg{KE9M;n!X;KKdhr z|D)*4yG>=oF#ZYN4biL_xbOvb=KN@8+x95xUS!2_5V$J zbNnu9>zomMvJcuPI{n8%73;YrcVF34iA}fHYp>m0KUswD9f6Tb-wO%3iXP`dei~oZ zH1d?CHaXyR!`@LMaV{8>&Qx+1kJ4g!%DaW(_Xe-!Ep9eQb38F!rB*q;deV??bz;X% zmF-*56brA`GcV~6$KuU_LmHw8Iu6>fK*aNFcB&_hK%W%~{dR)pFfs#d;$Nj->lIL(~oDH409#Vl06q{^P>72^}hS}6}e7(Kjil* zPkPHXChcm}wxnR(2SU%|t*LbK-`06elHc$z{Kyo(92Pe@j{VDnwr996TwkqMDVshH zI`wD#JrCSS%Z*RUUP5Dbi{N#r_zgjH{SFX5-vxLG`nIS(kCLqnC!q+OElt{-{-;C92?AZFn+o zj~#mTztgCD^hLI_UEhMI3&HFt89L|s3YskIPThudNw?MC3TxiQ5{In*J$g8`q+p^r z{v$vju1YTeD*U|De#)%cwbOT4(Fm6cFLid^^$lKR)mC=B{4Tvc;h99SH9;eL=bHf zO?vW|a}=qM#}%~B4(@r4AK-$4{qyf<@9H+fn?SU$N$fCEr}_^>v%kfx=Sg5O*x?To zlIyrq-TLdqqdLgn$Yq-A!G0e!1$=7G%+JPi%3A9hGSz17prVGh|J5%@<(Kt!?BI^O z_#>OgIWxs$stN+GHDzWd+CW3EWjw9^U#sUE8e_K8(l@fYE9zTcxit!)<t!_TmEARLmMHuIi2QHobE-lv(#x}&#L*D7 zh1tC9r>p#FaRu<8(l8sNDMk`x&gI-+iv1%fK?I`}4;rC5_T~kV{-y z{+le;^4Q)szCm)s7s~GA^vJ{NtyHRy6;>NFw=&Wh)MhW;oR)X+T5^)DOxnlEktbjfy+GQe^9`ygUA8M2Q&57|YGF88JTQ`QoEX7+s2R869Fz$>di{#Z=l zYdG^x2UV(PIEPt``Y1h2y$zp!5|zzl8`72C!!2y;=Lv&z$m7s2k1yPI6k7`WT5paG zk;K3jpR2m9-t`QEPiP2!BjBVP;x6Y!i^Y;FE9+qzIogrRUSOMjET)H6dt+bZ#vL+- zIwhYuj`#KHW4#8<_r&@e%qldHafRa3D+cm?zL~(N!tts*D~)4(xM3793@q=|@gho- zMc?4D9@Ys9Tz#Kne|ETb+}wkcz%96{K;qYQ4Y!zk801K6^ZLkEy-rsr=Pi>5OqO_U zW>eu-K7|xO#`@zwhOUlxukcmF_ zu)pkVdwF8sf*ZN>-i7F;VV=TkaYynT=bUw6Ul|k+4n02V?A9GY-M&|fuq-`)A{(}D z71wshd*yG9J}OpeLH@iM)94c6(;ctc5>ot$fBME+E$Sr(fx%0HXy0J={iq)iG|00DJ%MkCuAJO_?1XcrB6xnf9Vf@(Y1`A0E^i0x6 ze)l~i3O~a0soAJBySwRD{eH@|thg_wLpFf1Nh9q4#tcAcA4O_yw>DXCBlfuw=47B8 zW?ET3jE}|~K$^4XeRyg$MtjOAjY~Bn@u#9id^)>i_Nd#r7ynV*PS4gxljGciaF;hR zF|SERpIBGU@mD;j-ikYdyW^H#lEJb6;l4Rj$UR}E)F}6rv?RUO@_Wx__^v(7#<~5h zHedd!vxU)6tNLdW%^^z1r>xq#?sVsD_V;82XEPn-fnkU28qKm%e7O;nwSRreULxDo zLC;S>`&4#zj~VD;sJ2w=CCHP09yW>45JtV<(8TzC!{VXi5!9^ho<5`UBnbaRSuiV; zX>(CME3M)LoFiubwjEAerGgE@g3`TP9>eOM*C~hafc(Sn4(#C&XK=z4=wL-o!eM8u zGL^XUq?H$pn7eh3I(SUSMdG{tp;VnT&Jq8IoxbY>b~j( zjgDB|T*nL2n)LS+ry`a!YM;U%ttS7|zIXbs>z$wd!%5wqDA97H&kZ30;FXqs z(tg`INa(u8l)DpYSH089G+JzjdlhD{zpZ4CVOifFG>hN5PQVXBsIZ4f|ielJR*N>D7^Mxaz)q}xGWRzBUD{{FFuGJaZGkg3Yh zel^~GjDFS)GYKW#S)70ZLmR|7BF~S@`R+_6Nu^gfaA;D2YK(3X?JvUG$S zj9SQs_9uj0dsQX|`7P8;(O2(s!}nv&B(K7lSTv{s7Z-D%^i#aSnS9&jdI?sc+Vu}+ z%}MHZn^r&sf4J!%aAEqw`9aaJ>B4>LM<1RoTe~Xf#0^SZ`e=;~Vcr;f)m0v?1n42( z%l)Fx;?uARr4PE{Nj9i0sX`Tg3-Pv^3s8(r=gEVi^4yB-3eWdc6fLeZv^CdWdDGiF z)Fa>^b=zOM7+f*@<&U2JlK%X@Aa8A=PXV0L82x#1YNX2b{bxNJ4gYe_&1Bg`fm{dG z1rzb0b&XhF8d)%Elj}=I_%iRaxG9Z>=L?YMFR%3!*YtO7=8gK<@>!<1pNgZIbOqvjv+&Vl z-oyNMd>UWI7wGpJ$7y)%j=2+Jyz*s{tz3%qC>4SE`H(Ltkm zIa?!wnx^UBEUo?W{dkd|L)o0VHH zn2>G(B5Ri8j|}%`ulJV^=;v(Rbwe5Yy)ZBXqzz_4?_*~-l z!`h`}IraBO`2beEkRPn`Up6ao@Qx+hWPM4i--dQ9IJL&~s(|*AUp|qfjgzJD#|(yr zI)4$TU2!Jx-)WCD`#L&5F$s?3Iong8h;L zAV>(u64458&wZg)*XQf_jql!@Y-?9~w;li(6&+@MY1d}-2{=t~@IOz$AT#f{Hq&r# zo>uC{M3Bimz~ee$ zIw<_&@h6K9J=nkKDJb^3?RUKhy%_nbSj3ACu-)!>#($lHpSln0vxx^kKKNtxT~zUI zVfS)g*i6kh4sM4HC!)c79=tEz76k3R>QbrC5GGQ}N@?v=Ser|ghu>mdH{P?^Du4gj zG$Ios=l~xCvSql>sR7vETGHxXs1`O5Y&ckt1?%xn?2#$M*9%FKF^{nEml@35XPWJn zcJ_uUq0duYo_oG@FJq z`6)+_;nrS++R{PZNd^=?`p}~2L`9KBF2=Z)2x7k0*#riJA8X4cxw3UMx-){`W=4M zVK*R~XfLPLwM>9%r!ZS=MTe{ZhN}}eI_jxA@mZuMQ_}sJGfn7H8;!@n&Q>s|% zKw8ir#Q=ZhKB~+LVRFn!jVloQ^WfW*vYx#J7J=}~otn2IB3%2ID!yBGs&2s1jVo-D zs$zGt&X^gOelLG&>R96YJ~fpg_`;n-zro&a>!9j7f5en}rMtQE=0}&_Xy~`g;azY_ ztH69%%=xf{3CUs2{aHss(9FkMDBJEY-Ml?v?N_%&tZN1kmhd9jSF~F^lbLocV#l^I z9AlVpCmJ%6j;5#O;o{)Lpo@4_*k@pmCd_&R8DgwH(HjJ%PDj@MF(E+|luSz1?TXa# z!~~PWlzISx_>-Gh-2r&tkNl$?i=kZPn&Bqbx=zLDNt{h#b&`)kuMvBic>h+q_bOdp z`1ex-B8V|($PWfpY?be+;~nV7%zlG1CRHvOXP<(1OA+973;pB@vdWf{zXBd(nPmz2 z_fXdMD9jFWO##>@D#;?kzNhH6W~wmuHe03l$lNVN(q#Q?DE-YF-%+=$xZ?st!{jQx zAKPvUw0D{(espiM8!cg<@th6jNN+p%L;%BmN3iL_%Jc^rcKq0*K0T+)DW7-?F{#s7 zOn%3noix5@@kw1g&|9y!$#uz|K3!fe>AxKUyVvXAm$(=C4Pp4vYk5;oK>!0m`vGv~ z__2!8UXB95CJ^dBL0%J>sd_pfjSYFq6COM~-a#yUFKTucxFU(+E-zR8L%93Y2M29?>es)E^;=LeFmm+Bb9ptE%;_ZaLXV>|wRFuyNm6fk=;YXG2QbJHKr}#I?@DRo=jco7A;ymHqSYDhqYr>XRALtx` zLG(`l!8~>BfjzlxJT@&_0U4(gO&;E4u?z8?3JMY=m6^z-ZMelIvoPzccq5>z{&U{Z zNdJ1zbpx!H1*;iE`u_5STL^$$7Ld7gp!NiA@)wL3Qt`46E*orm(jX1=sQk75`Gyiu zzw`70>iAvK*v;qa@;J@@`I2^vMPdC+Wjw<9?}oNzojF}^-)bJ1h>JaK^b459c8T_J zMzylnJ!gozq(Lfj#doVMz?xLk7b6>V;m`AL(=5xWoeL7$%#mA6)mKAHi;fC4jLhMc zZpavaKLR=0W_sbuPq`Z(F2%cjUA2Kofh;zOLeKXa{a~y5^7FWt+eKpRwR*Kei1P12 zHd87Emi-tj=FR8n7z)2(9Mq^Q)!)DVph<&yaY&9;OIGMQ_TQqq@w<;t z1b(?TJw||%dm8Nzl{qua*vhqd)_SZ$F1X5AzK{1F zIX@hL1Aa}gqPHR66$c>(g~=zcmfWRaCHGD(aK;OsE_%u5qz>olyUu6bCIp^VU@vz5 zgA~-4v{<7A!8CenlZz?CH6y-J#r+wrc2c@`CtG-<{Wga(SnJQ)Ym}G}DzW#Sz&9awl?kbGk0B;3t$2p_aY{nyo4kslp2B0-xo zzx&_l`r*=F-m64Av(vfzMJpEO)H!z$WT&-UIOdnqkCJ#P6+Afe8&UOxO_JbD(17Lq z^RxpCdduc%@Bo=e8GuO@tWk#4kEo)W!Yh)G?xQcl7IN4h({};YnoN$OfhJK2g$Pc^ zYPl+F#8HJ->7C%aAzUR)-xphL?;p<(J2?Zp9N|D&y23ja?kRfykoCf1_&A{3>cebT ziAKNB?5;kQcdc0sdPoOePD=+&q7xoh0wW8X_M+zI%a57bAK$H$=RBLIJcM-mCXhJG zZ({#65H8DaZOBck|3P2LqT*Vp24#{`gG~qNat$j2u2$o>c%>PAZuk=U1^8pm!aRUyOj@@7?2Z*;ELSyI^Eii_z(j52TA zVw(q|`CO#(bvz%o=fBPdK1JZ=EE;Q2$ayiu7NOHyjgaTBPH|E#D>F^lUY^G<$<^m) z`|cE>>QkDCibnb_QX&2Pl8U9_Au zS^&)`UZ;2C99BW4Jr261p1T^epKJliy_->f+xl!doc@=YqVQ2qdLs=^EbGy9Q0c>@ zb)kJW{W9{q7!LQdJ!vB=#rY;&_J#)wywlYvRrg}5<$zs@^xU(v`cyL;KUH$c(5lN_ zVL(Xt>el2`@x5-XW^f~K^K!`z@}n-8;y%<{SYcuHQx2vuF)fU&O+UZ^L!R2?0skuM zyP(Q7t=gSl0A!wS1E~LE zA$_%F6BFlsuF}>q!NSgA5SwjYTdn8dc}KoH_dMkSsSi}U3kZH5hWk{p-%foUVPT4G zx+Jz}=)-(Wa?Gf_*MGgm&aH)C{~J>m83^r#0i~H#gI;dWL2>NWD&55M>HxxH*RSDy zus+X$I=k=J5B}JLfebeZcSAEgJPSZC?{D4Go3ZginI66Zt$mKQ+#)FgQF5?xT~M8G zYSl7csi#%vd}tW!g3vFg)Sio^@{3)D+dw=rFs=!Pg&1lWz4oh(Sndf4Y&i&Id^C~D z49qmjvO&D8U$4E|#~yv_8r-m+KGNat8R}@07Bi!&@z(WS#@iwRk;2#pG(<_a^mbMNS~@a{Qc)%E_NQk19X8<~L%6-PPOAwi#iNjggVuXOl~{bp>yD z_xI?uS-f9GSKr2isS@r#=5h4twp^0T!~L>$%P+ro-X>bR2oL8sJg%+WES@*i{7f2C zvDcSQ)2;Q8zrOtnVzAVem9uAkt;kFV@+g1IzjlL!{&{5vxomJGf!y(?p8w-G=Gq~; z6N?6&5}r*U^_x0f-SO#ip8JEbn$E^63cW}j=EW56$Fb6Q;8p%0)~D50piY+J2ZY+2 z`W-*@ASsX)YY?SO({?4>^d66L|IY%b&PYz*^00D!CH2`J+)ryPH#8LM;>1E{S>YW# zJsaxn%uM@v7NB(H-h8Hn;Meg3&wpg--{`aZ!LSalmQ(EeNV%fDi&k1nssYu*ODG41 zr{jB%tar(6YMh(o@(XjzNA_2HJg=*KoLeiu(Pv1u2t55^ViNws5kx;_7+QfW(NTf$ z4Px+sWZA%6IPm2`5ztO|JNtSa`XMl%zHktgH_$)%3qb4{pl79OsPOIN zc$v;=;}T?0CXWJNAEEi}Ih6a!X zYs2;}fq=lmHs8GA&v&M`NJl>}wWF^0jBJ}w}f-Op|Po^nyW zbKFhV3^ttg1(Ph9P6aBY+rqdioo{u-`Gak%(0`gOREF&v#%^ntF{-zYZ)2N7-}3}m z`Tf1Hr^1tn`8TC1D5oBVp@xmP%48Ouy1Wgf{)=?&R1(CYMphyd2lab*7n!v#50I@R z4mCXDF>z+SyNBikZe*XapENx%K>g1*zR9FN*YEOlo7@XN84reF&>UH1hOJJw!Rq$K zsFIhHIcupT7A^@ufz^(h83i^$@{U^ynd*bD+J|Fnkon+!6*(AD8_Ngv+qTbkN&zY2&+Owv*hYakB47vLm#o4mmtDC4{S7EUFDw2NV~qya}bwS^7moI zfIYHLalJ9|i=CskoFB2q-SL;Nxyvui=rT864dSqS>hHRRu!s(l=|<7e-xB>$Yp|Gaz_<9@Q;LgibMFPr z*A1t5;9C-Kwrdkx;VhD<$t5?b6~Nc9^&SKM`Bm2kO+vzc|6IT?A& zxXq<^(~8ibU@Fa$?K~;m3LhicH-R8kB<%h?`vy>sI^<>sN$+~ zNgh}{6C}Zv$>UOSfU5WAWLoy(#4TSA4rFicj?fSHZv;k)>!h;%W8SC@BPNbGjK_Fkd~70kA4e6-K_8M_$)0 zUmP+4E7#PDSNdB$NQTW_+UZK?d1amw(#(1mHhfhqdBbH&160{i(!MV$|*iy8QM9qQUG zxvhci%VIxQ^cXNT`GiU73?9L1ho4lR$3|nkG@ZQX!2LE+0l?BkOUKz`MK+f8-?C`- zVG7su+sA9Q9QdPU^E6iVv|jHgy2```ffegbNGGZK&0wYWnx&ya3A_Z`=M;k`gdLE8VpY1wOUSkwQuX7jz2eb;Q!i)Xt;c3UNS&_?q z%{D4;c%prgACGN)WsF$go@`3xl+Pf{?b%!P-F>dg6^wnYbyjQ2_O^qn@9oH+Q8jNm zF(d{T*?2(~DZJmyT@{Ha-uN=Em^HOH>}jmD% z4n4={>J)l$Pzlwt9mGtyEZ-iFX7KEfOZnTnV*Tl1RvEG?qRnZ%L_-HNL)-h`1VV+_ zhkg&j%j341g}yTR+g|Fb3`(d7J1E(CG#z(|tmnGS?OI(+7qp50^t{+LbGbFzqdTsX zKsDY&>MGp4RYDg(+&+wYyZfc628QZ2uj3x6c66>JDhGwj8r~dY_ePS;5y~ff;1G$^ z)kpD;ZmHe9gIo%G`78%B<9gTY5N*|LdJEQ`2hqRUGB9VEZ9|H3rccb>=w$pRFLi{< zVA6T%!$;tkAqV-JI|=Rmt+jhv17WxO+W;;R0%-5~O*?Nd>0!%0=f)4v(RY0R43?hq zz=iH)=v&vCMRx+|_gjf72bVR_pmnRg7xT97vj;&Oa>TXtog89JX>>cg9cgVXqQRe)VqBFg<-rF>ZD-HyFdI`S8-eZ#R_9TKqR=@e!%D)d*z z=}vEcoVtD^B3UkCKzINelA-bY6QQEE#4bxZ=AoRALgVDdi(yR zB(x6qu?ScK;DBB>4-jt;`oc3;@899x_m84dXrs)Lzf20P;?8O@$7IvnW2&^7c31V^ z7jX;cKYCQx?!uvoOpbfMiJ$$8*A46DI$j6>YYyTabKM5{%eXq-{N7S(z})x>$e-vS zc5l$VhEhBPFu!}q`cblE`cCIM84BX9iwG01lTI|A=ses_klvMCocGJcS!0{}kPA9m z#5h{Mp(K10&9T&*`gz~kjDs`JeAyN~g&2<{a_W0nGQ*rdZr*QG0wRyu^=1LLHG;ol zm03r{&-eD~6vo`U!%Uq*O!UG_@Mu24h2To3rK&xZ_V^&0S$`_sApjVS59QQ~%YLKE z*6;J)&pm{*&nRi*m@@B^)ai_jU-LO~eAKGJ2=iBqwmVRZy;=7z+OKOXZJIPC{ zf-}4rr^kr^y?fzC|HeeiTzy_FGlx2vk7uuM=dKp8HLqFcq*5MX&uXLBc5OSUXh}n_ zzsb#Y)xvt0WdP?Hq;^)sS?JCVx9p6(t#ONsl{raln8N9()prftTWDuTN+z2Xb}iO& z+7QmMzfN6D+KdxFY@qq#(FT$(`%y>vpY04Ia}DBmrTc z?CitBI;t0PW7wTmA1BzB?Wh2n{4M(|M^)CEef)c02NK0heA@Y`H7yX*2VIg+2X>i%eLSBIY7NP ztR=%XK_Q-3WHW}1)k{30f_>S4domaZa-qJE$G>6!RjnN4>*Xcs>X72bLFbUS{+OS9 zH;c<}e*>`rhQCn$Mysd19DUlVvUh97Em#V3;*#5DZkQSXUte_`QH2}1f6LXYvj7dzKLdl%to^!Jo0w0kRuAjfq2evs8TGmV zif*!d$Vf8aUE*stL3GzB?SM}5$i}ro9-Alhh>0JdgH`4brdDSlCveI}GwSmEs9D&( z3BSsG(NDYG=^%l-StWUZknw}Vl!n2=>w(>wg%zAdm$ndOLcA^qiLT43-sYm~EK|BO zep3=U>MOTI6&&vU+I6N3IA2Sss@yruTQ6fPM^ZtYyv!%71#=ILN|L<{uo7smmt)ab z=6{RP@RiY!D0^S`JF6;x1rh!MJ+o-#Gg>q|yk59;1!h(i@Atv)DI&mC_=7aN2PDJk z6loC6i_C&gfdygJVmnu2|2A04xmIl4KJSHelGyS>j@E~_5Q2k(g@3EeDK}P!`66Gi z7mLM35hz}iUl3YnPs|Sa$3dnY^e@SwhL4*AK(#E(wRZPeEYZzL?(+cCz<#~-TAgSR zEp)*Zh#kZMkHYp&tsO@WWM}>1@byQ+oa9K?gA6O>@fcR>&;$1`^+hRH^!DgLNae3Z zgXZd*({Fk&kBv6H_CD3h@@m$sw*K(uUJ>hLx5JGGtNIi9?9;|MnVKeg+U4u->S}6! z+=W!Q>N2>1@adr#{==QEOW$|@@s6%@xE8pR_WC0|crA~Y5x-iO&EKCf$l7W2_X_mz z%^~W3zsB_DhESuk3S{&ZJmgokK))&o*Q9!W*c|rn%A|nA2(A-lk|Y{ab%TzYNxpGb zCWl|`#%m~UmXUY?^RZU3yxZ@?Rk+}9sKz=Tjgb@S@wo&XljJg>ao_;`A z8~)ry1>oAp2I#yI-Y?GBLOG(EKRx!2=UvK7|H;Z@>W``RJ+5qQq7}@>XCy#M^WKkn zMw_1cacV@lS>%udsth2$6|f{|RQtFZ=w7NL;@%HI%RNLHsINr)=E|xmCQmGb9})Q$Wo!Nh^%SH;Iexy zm5XZb#@Ewnd966k2#NUIs`3k+glUfhjT*QmfA&XQQfhgx8i%>sIJZxeb z+%I+O>|YrtiyOE1dk!7M6{x6QCqxeR%vJR34FwZ@-*1_iu+LXN({!?_DcmoCh`?X_ z{dblq#4SrTr`8B z(|OrgURT`7Hv0+JSbyfwz^eR}S#q^^?vG`+g&*Dm+t0punSas!bY^}*)!~JZS+kYN zimN~|oDzbIckH+b1=HUaE2`Q8qP_ke z68RoUqb_NY(|b3s8qZFZx?Ya;5MLYU;M&^sNAy1Etn>HA%LyTEau@zPEprZfJfI8V z4_zp|_ZCu>hO5Qy{Mb>C*NV_iG|bOe|493 z`jy(QyE|N5H%5)xJk;|HLs@3Q)mkf<_JozAw{|X#vg1yt8-8C=>iYyd5QWV6qMLmU z$Jk17epDBCa}Tef6BmWk%9Sk&!+fS_!9ZazxI_;P=i^4Qb#HLBv9_18%j<8|058`6wON$Fti#l7!N30go<| zjwe>N3jG4#B|w&b{+tkjr;*EWIz$#|?0Y+}Bi@>K@V|_|68y~#pkNC|3v`h(Y)p3- zd?idFP?LA6Z=7ZIM^Rlmyu3yNI*snuxOSP%&xc#x>yHfPSrI2U2aJA$l7?I*+3nP> z<+k(al7}|%_udT=`u*~ERlY2q+N3O$G(#&*4{PcrY-Z3miyZqG-0h*)djQE<^^v#tDmox{H3xl$(?zps)L9= zS=D6d_uV#?NbjO88q*Bku)RD>HrS}sI3VxcO|!tET;4dy?$8q{@5l_W`nHLDOC^)3 zE_+73F_q}3*?UWW7c3eqUem`$l~?sbEyvn&?ysO6+Aah4OB&6(+3Vad6HmLaXhd9% zVc4^(26_klk2W8i0U%eaG zo?k(|xB16d<33+K*2GbroZO6Uzr)0(QbNcW5y*T*99XM<3B^VyPL0JA=Ha^2Zt?fe zvB*u#{D&0c75xEvVv7&Oo4e_}n%Po@Pk*MxPkpp<-Rs;@@>Uz%9BHx0B~%P2+q?G`;H<2q%WWySu7>oW4=FoWvJ#Rs2^8PeH<)fK+!H1w+d1ruWY3X1+Scns;z;$J z7n1seMMD!n1(LM-ksBM0vzb%r+gMYXC5{-8&v^0t#d)St%$#7vK3COKC$W#9AEdYc zVB%`{+Gg7Qa<-M<6Lx&NiEf?$IA2=(3j*e@{A`cgN9@wJZVrvKlW%u>pABj?vwF1J z;$+`KNVrHJ06|4dvt@9$97=}(s{!pGl`jCCpJ}06_1in}+4 zsytutO|Gt4`dlg6tkZ_4RD~g^eb(hw0i2;kzM}pnV^hLmzT}wHsU!`)rRlM7r%Iz! z`t=TPsjKxEi+MMD!Xn4q?w<8PnpATVZ$p6x%zzll_ljZj$^Q!ak&P8vSpN-gI{rL^Hr)vXhez*p+ z&j4)R0Yxco<@$osNrAd+KSc|VaPUK#Ch|f{o{|b|Sb2@an-%Nfp~Iz$;Ct)cJD3%_ zYlB=DX)CQYx(24_IGRjS^IIXVPj*c~Cr**BS{wgn=E{6%iFP(*@;lr0AA+<2utaN+ z!m2F*Z^2uZ85t?DLR`h{?vIM>!7`7F2@*jJvM%vUpnqaQ35$J z1J9p>5>osGagnt_`3+=B?$`KdaQM@v59@*5yLU3y#0 zudJ%ekGE$qQ217T6!5##)T;YHn?9LY`+i8;^^1b%He1kK`C9ztd~7Txt+{h-iT5jd zPL9o&no=vYhnneZRFIv1?hYR2{dv7o%%okPUUA&m!OfYNdKypoI_-58X@`@M7} z57Ae?##p^b-}7{J6c4WMaepHRkoaX!atuxOLOYn%VgFYjv`G&J;FR@BM*lPE)6Zr0M$5$34=&e5{5{X$`z=ApUlv%o{2}V=fx1+VgLS9cD=1MlYLKY3$b)!7 z?A|X}Sb87VSGm3X+D^Z@JfgSOY08hAaE_G;#>l!+p=G`T1&q}54JUA~zkGY3mXz)Q zJzZ_$#!l!SrS0~e{X}Jtwd_MgSwZsc>Z~#&*Uj(Zali17(90`8z5}*35q_^7i5|Zf z&YW^#I$E0z+8^FqT^2<6x%qg~_mmF+8YMj8$-?G#ChI0~wl;iwO*+lRqdUDZcv-90 z^z$v5-Jks1+PA*hy1xVtcu6;6T3mHo$v(3g2LGAT7OlXRhv#QUdBn(HGVc}{xeV*S zu$r7E=KISO910=Uaj1yPVYSk)?3CU(?LyWh)l_v}%edWfG>o)-1k>Cxm}1!t*wN&7 zYUd6G*dDm0%W@4{dYJayR#0XbqiV29DSM2MwnmVOnyFz)wGp+ zbs!9=-#v25{k0i7Kx!L(AIkkqSM|=(yID(G`y;O0Qd~yMA&zXewRXNFkuE5?n++~r zHLkonp0CU{3~_q*&X;OCy*Jyfd#3n?n!jfZS`eRj(>~KBWCSPVK~L-o&gHqMPoQ{v zCpJp0WTn1hI}eXivr$Z3SLpUHc!>z2AAgav%~5jk{tLGI;ifX$Yy33DTiY!)DMjK7 zZ~Wu-)N)1rZ(K@z{ElQJz^vN@dgb#t{{&eq(M@fOHAfk{_J^Y1(wSbuPP5Ie+^c+l zgO4Ao=Wns&OlGhAT*fDzMijDxjSb;~|Dw|F4%Nrt$AKD3;vbvz*EWRdT}9O6G(yB= zNpSg3_qU?$yHaa6KM)Jw`P=wtOfKL4xD-+Q)t-U_7YriwhxXVP1w!2%aBxlsZ&c~! z-r#!44?)5yyb$RORo}mzF70-$Jm1|;1Kb;p?W4pt*oQm_X4-T}+_6`5)hBzieJnqm zDaJn4dO>JYQeMhn^yBt8(EFL+ zzZ0mTaI9HwmgrS+VBO0T(I@xoKZUxTti{N;a0k1U7Uj}V$M-r0*b(ha6}`F=y>EvH zWFrZcfk56U`bRi=uND)vFxRX%<(0ksS<+4%JR#+`m~ zSGtev8j;4O`|&)g!RN4ZR`X~wxtYLOFL);llE7Y!C!|fXxTTiE@A%E#$UM!Zry`)L zKm${sMJl+o*F+aqig5Bb5%c&;jROM}GF5VuGrn(GCt6&bcaL!#vA@N<$-ioAnbVrn zFvxkNG5Yj{cyZ3%*d!kAbd>Qe{@CdXwXsJ8JHLZdJQljFG%R(VhNV8>**~7|b_r!v zoe*`ZuHYxhe_J}$IdA(ay7JiaTGcNf2zQT|FX_&T+*8h{w>rI@@PbAr^>0oVz6E#6 zbSCfN3+Vr`U1?T?`tw%*u05(HA*Ehcm3=Vmz!5_ceI)rza9LsLk*iaN={@~Y81Uv@!=9M8`$fxuXB z-UcOPrFF||5Lf})rO&Zx7=VwuNj)3*TGjg~9WO>>##9U2T(mJNMgpFe?mao^-o{bW zZ;$Tg)2O_z&!GoU{Ge5|+Y0*wnFHV@XZbw7QuP7kV8UtX@Ch{{@&sd@?}_>E(%k~^ z0hU+?7%n^>M;J#0Xq&$kK$&;jFSm9IxZ3P&Nw?9H)EW2NTshvgPQ?KY?Y{6$PELg zin?uVhCAwak>2Yur}E?BO{^TiVkkN&d5YTm3LYO}Ujas4pdhwSb*H)`^yd5PkFn5P z(^n63eI8zA+2}QdU-mYi^_jR9k}LAU;ivU><-^{xHMswp-F6ugwyTh+uCUDoBE*1@ z1!QS$8PS|wxB3gToY5^GE!YL5$Zsn21uYcJ+GSJE-%C{_Q6I+%S>Ev_eSvg#)B94c z-UtI&_)d7Q%D_%962)QC>a5!kNg~K|mrF!(^vRDWRZ#X-;4CKR{JI<$m)mYw09rO&p#NdTFC#Ep$smD%`W9QnDJAHoRIh{asV!fz8p5GE#*cS~!6UI!YMo01IY z{n_FGl`itmnHQ%p2p_2|v?)#~O^y8~Pma)hdC>cKe!x=iZ!31-mZg?uqXO+`22&r)=-oo)#EPWf$giBQonPO^W>8gj4jLUttS4S{J0MN8rRw*4QY|Z zqUySpLv>zm*6C-XB_8|drxD_Wf5CI{Q8AwEa7KJwWs3jW%UmJb0;N6lRU5ZrWZBbs zR+uNXaM5PLuBYym$?Ux{mnVrE%_o#==%1co2~|oyppn^I45eeSu^u4qnn6aEu zYCzX7TPkII>guhwAb>t>pR%7qJ$ZSaa}r;VpNXv<8ZquJ<7D}Z&#g|+{Zt2G`#xM& zM%i+wUVLMYIIYS!apuKCwl8hV#b`px&CEiZo7I|e;j3*hwN9o3N(!IZ%y0rgSY%JZ z>GfiCnnyIatQSioT8H+GAll@Wo6jZ>yr{pvO6R(TvETRuJd)#r_0?NKvvq9-_t~yf zID0QS6c6MTFP`{z;XLLNCckq@|F^KBi_Dk<7McstM-C?5zG1r0QbA=#j(B=4h3<-=#OJ-^J7+HYWM3hhemEB9u+ z*!ZRuU>~3L)n8`Hp(`9m)X??Y;}@o>gIfWi-;eWi22RyvK?2+AR2- z+i!^woyBEI*W*XhK}BW{%(LNUIZ`F`{{D0lDb(&zxvKF*txac+u;F7%mnGl59dt`- zX-;Q8dK+>mtjWc)^s7yx{DJ!VWZNTN(NtH|@l(hK!4Wc2^J_u@Nyc=(X&CQCw%l8w zhYZnwVuySNQuScn-*ju}JPhRYER2Xor^KBs#s%lJy-hr1RL^R~wN#+_mo(1_4G|@0 zX76nPBR-jYP_mSql>HI1f0_*=9qPS{FdTG7XZhUDjRsk}&0^D4SOBd8dzxjKVp3#l zckziOwToGQ4ikL^lvP+B8}HRMb=<=QfcHg-NLHu#46v~}%k=e6Xg#XoFY?cWBJs&7 z)dFcPe|j&vtjMFz^LzBhwdS8gjeuSf>VC-86I;jJuoEGAI2cEdJ0CNZ<#u&E1&_vb zl=K;=?!E7o^EeAU0L!@%b3k;ZHGc<$5IQ*LW$v2!x?p52bNH2Q;>KWK%DisT1h^o5 z*jvU5VTc%z?Rb;oLQ6(<=jx6^@bzpGRH>xyfWZa&js__x_3s8)&Ij26Ath#5gJKpXrKblt-Z}&Xv0|&ouLCx zWZ6MurQ^?hOWyRphPdYn`7x-mR!-Gpdqh80AgyGK`eAhg%3)>IRjnMb)E?tY?mSJ# z%j+jO4i5FU&=5K%X6y$j%Csl#)+#a1aV7|BHc3ZTyZ9*=_k7yEHeidsK6iW5iaF7; z_M~>^f@3qvRh5|`Z!6jNw=^_7v-t#P{V`&UMr3(j$?10>7t}^?>jYBFMm;bgNZV!_ zVRa(MROg#MhKH&4PK#(t2(JUR2BdP-kB`ayJF?2UlBRJrNVyAex$;?UV?#`Aap)ZD zZ}^t3QJo+U1lk#|yH>B1Sz9WbRVzphKv#WlrP^QyBq-X?#bkFn+0d=fEKgBf>YI3L zTsVaz!n;J<`a}oAN<0Uk0Wo%LgS zEtJS9`xRD6atsZ-@ucu=>_mdkSI1eyq5vEwBJm-`?LA)-I$jJ!q3Yn1*C+GA_}IJ$ zpr*W^CTks%G8Ijp?>+?v!f}sRUn7sf_ey=Lf^vphVbxXf9#s{p*$^~}*r)L7R%=NE z7D|;^E*jg+V@F};XngR?FVL>>d&Rx5^-@$ld9|X)wffw-M1Lqp=y$%o&9uqtb}e}9 z9?A1YLsOV(_4Km#-Zb)%S60DlE(hw4|IAA$u<3MKpW;S00?qcXyDX2^O;urA-{NPk zF9^E-px)mXwX4N(WI%(H8D`xM$iAguNZHS>U%Nc(@+L~K6ZA$S2G5*XwOK@%e%FDX z_@Wp8l*ejA5$)EZkuMf9Li2+L1|MX{pNbmSn&8hI7E#EFh-a^AzE+(!4DUHqi{xpV zIJsf!JQo|c-WdEE+csnt_NKJBJMG1ya_+jJ|65`Un8zBc+IaT~7Bdv#FllP_)=ya1 zddOR9#LKr@sdsx+7##1IPIBk<=e_`&$$~x|U+saDKQ^%Q8Yv~$GOWY&>fvr9ae#7f zVn>nl^~vcH2X6wEE95oUZDbwGZ#p9`bDgNu7FQyff*a9#(ek9FRO>KZd3)LW$$gZ?UZWWxl;nubEp3iS5>Am5`cU(CXYk*dkjwg zys@Q>zMsW-U{k#xeUFa`n*VlXt_LeJwra(h*6)ql8IK!xAeJun>r5TV;j7j&@XD=O zxJx&kusemE2tSkFjbcF-^f35gN_o+Qm6?8%n@zWCo?919PZ*gGIX0YAJp&Qc^~G5< zpkGLdQ!{G?Q{kd zkXh=0BqDiVh%-u}igsQn{h#m5!4H9^(!s)(?{l@IPGy|Zy%3Fd^TM`X^C8pYzBV5I zA$P8ghU?ScQJjTlhORX05;gR0j2+IpF33&a$aqe>}SXpdFJthI?TPo+*`fE z_WZb$$pnhAi#HwYVz64}G@va$I?Y!(0MYSiYhI5HhyT4eC~L-8zo{@T$bGb9 z#+5p@SWh$g^&G%4Xlq7di1FQzf3Q}=%)eZAq>9eP$qcpRT%CN&;z%I&7iW_nx|>=Z zRo|+W5Z0C4@OfhKo+vEDg(H_+RW;rW2|XZinC~hW{$era^GG#hoVj>Ersgfe<1{Nj zZZMLoO95o9V%77kw@ZCN`Ignk)Ae~+6{V~3tmjAXQhzpCvLsDYf**Sj$}zEKjb-nS z-XWqzr8|p+Q%cM{ZHmF_z*Ebbd@ki9w9bCp>@{xWK?S{-%5E?OAaQZ~DdkVcvfbUi zdP!wzzT017t4p4z(9qmdvc>GvD||A&?V^-Haqn$p)KUMUzORX%kq+7EippiVZ zl%;_lTbg#Q%p&BVD;nOa$HL?=U?XeTR*BJ3Yl|M5ag?XyK<4Z3o9{H7V4quJMC)?1 z`W=sBOB>W;AgmQbJbJr(w5!UdC%iLYC##<1hSpgG8NlA6pQPA^f;Tufrxn&u>eDy%A0}K1acNIBG7-oP-Hq15!8~bAdR`G5Gfn3Ma)2 z9@tRjdS83@wl&3=pBeh~ntiYCLo54`$G%ktmVJS&!d$PtNcBEZScJsWI5aofr;d{K zQn~yS0emFbXZ22~33oSj(aAT7-Y2sHB&#wCc^~rf;JI{MXE(Y(>r1S#Aw32>bg#+) zkzF(y+Vy31M3{p|cj{|7)qoZUEUd$Gsv-WPCH*+9f@qKIDObQ%RvU` z!|hY-%{+bSQYX0`VBHsXRm(3PPQ&E(sqrY)`#Lg?B6w%8dIiK>8O6K0p{k3D^jNoE zQL??QcU~ucaXbpwar>?g6cHO0DU7%4Pxnx0@3g}V5DcWMZ; z8r$NBC3bAiBqA#Z!+@ExpFy=cmk4cG&JD`q*}%3<-)c@tp-oN-Dv?rMQ4p`4L!5z=X!@7Y`4R;#S?J#wQ=DFxk&5g?rBuw_Ad#7O){Hz z!rJZIj9@ETK4tV=?p16WLEWX_wV|c`vSqWGOrsTqNr$h+LRW%SH&4}Y=0kwgzQS9> zQ2(3x*J2B~ob|%XKliHhe2dRgIRCO{Nyl63PRIV}on`lBQBU2sPu}y}PXKqdTvyA3 z(#RRqvd?*EVN-)yr5m=k1?=i>!ODg|bm+m%pQ|m_!|)1>*lZ2K%X z&83O$CFPpiGmDZcPse!w=ego6$+al!ZMi0|wWqrpR;=7cjYg11YyCNS2i@tpf1P0i z`<2se{kTCvZxnA@A`i8`Q|3WpD5ZlU)#(|V2-j|=7cGowA)V|f(D9BbI73}srqF%$ zua9bsE`oZaQp`6C^c^XmjCql5cvx|Q-oj!1(%P_WrMYTCX74&sRiClHPBmL8!e{||G zBkZ{ByH%(qUgDsSv)*P{g*TFp!MspR(W>(_8Z0cWZm~q=vjb&IQUIo z>U3#ul`dinl%87UcrWHRR_VSDkhqPt+^3^nI&t=(jk8o#->=j+HX73C0-z>QH|lJ- z6fK_yRk(Z`HpPvvU2G9M6?2eqA5W%6!yCSoJ9NYdC1FM5~N9 zs?&#`F-a+KW|?9}x?7j9$x!acE!MYQOe@w#|1F61HrhT9mNMb@0rA=XShk4<4gf!Y zBNS%-?#jh~htJ}sjs}_bPq_2h^|N?00A2IkQny z`V{a8T`T!J;Ad_2#z={@$^NV{D%}zSlB7|HL}mg=2p2CmCwe8wA(!)Sk8v%j^{qaB z-PU#xNq+24Gi)y1sz9A(-?LsR%ZxJX9DxM1^}8$Wl|bC4OdpduA+∾B#;_^hH8VoU3e~n2S*M}`$D7b z&3&AoM`~`y2$nHbC(cailke>*Xeb{zC3Pz^o)s%{rRCL&CR19ll})yn?JtDhX`J4& zNT%ra3P&M#@HBVKFY>1*QRt z?CVPyW3^#D{gWDb-}z;VtlU`N0N-+vJ+Ib7q|$2lfKc5Q?OT4gO>Mru&U+eFTBP!1 z*k-k*5wd6e-j)KD@XQ@nOpne?Kw1|B`=6s%?54(X8qyJ?fLdK&2H9@yyg3u z02Q$Oe%Hky$GaDmzOWmws;G95wd3vuU2FQDE!M|KZ=SRVO{l`T6I!Fo z_BUQjHH0&DB0bpq(2J&Y2++l zy6?`rTH0HsgPC?X^}5MAOSDF7B%Hs&j|ZI*_x+Ky{9F>GCrxS~rS$}|@0Gzv-rMiN zCO#`1M0C&TwGAAs{Dbn9vt|!vP8A1+T{>m=wcnCdw|0C@2@4^ zS^gycx;a&~_zG+YA?+_}dri+zM?omEJ%P{$+OlzfMs5w9^|<)-&Qqc))f*q>J5Afu zCZJ!2A3E)O@7}@-tWy*0vL|oHFiRkN%uz}Wa`j0^jaaH#Ztcyb>}&_tP?l>}IDBt@ z2|n^a;g>g~z&Dk<^aO2>J|`J*=AU}z^%XsPkKueWf}ZrM!9i;DyH2OP(5OsisIXA( zVj23!kIVArRLf|Rb7V-Hn>*TM4yduaxE+KwWQVph)SSTz@7?{NtPZ5VQot*kdWiaZ z!%H`fEm*arhGtb&{RxMbUy1#O+c?6X$3LG)z~{uaB`eX-jcUN|KDGY!42-B@H+^Swpjy>Wgb z-;@lVS;@yGg;zfv_kIpuXRIiO)5EG&GpXO8p5t#{k)@!(I=F%1x6}*-3m=LQrhpX- zItZCyMaD!lK{%RLaP<(!?G3YR7H;eEWi}g=kZZHz8UZz&0t25go8F^L4m|`)Lc`-%t*DYMEVNP!r*-VYs>y_GUpr`jyB^HeP^O}XqRfiFnA{|ECg)=YpL>@>Z zB){0te&?5y(bFBJjkTm$A`pVCXQ935xD)Y2${;!vv&?0M#P~4c7+4@DP2+el`Zok5z3=YSond8U^9DUF2eG1 zJqGjl>w4Yp=-fHTK8Xp;L!(@BCM4-v_i`nB-6`-G*L+#~$q`jVtkRt#e0OVnKgJ6q zKli)e+PINWKDxtLUDU3Xim_dLYC49V_^gsgpc?POmrv{N9RdKGZF+yU-*reK1F3Q8 zaw@pn#_Du}w0l{xx3n8n>Hu=(`@}s;RcCehOfOHgT~zOs1lg#Cx2Cz8cEwJUZtK}6 z;v%dsk8`jUZnANqGCrJiu72&ds!MG{S(bA91?eUHao@)#&2pb)KdVh)g>R-t#1(`R zs+Z6mUe^jsgTQagEqR2(Uv={vMBw|o-J{p8RqtU9qyZi)_mTyER9|svyJ$BTt4VIh zS`6f9^ThABLEqv~k|5au{N_t(i%utbWfQh~0KX5i(Q*PIYjflkkk5x(wY}o0s9i6k zWi&gmaQF;NpwpUP%IMchg7xj>erMjPN$QFzX^6#5uLLHQF!Bllv!Hr;Or%_6n~f#*u)C;XAK7GX zb!{>^=vi_Q=V?Hx%icqkuMAgv?TM3ce9o#q255gS8prchtUpj^d#u{(g~+V5non;^ z0sm4%+PG5nBVO#A?c8{b#HCAMh<*lU7`(RVWcSp2Nafly@~e?_R;jkI&$fPB&<%im zi_eQFXPt8OTmxjnE{R_le%(wONRJypnI{&S9Xy=W-^clO7+kuO8qzj>mqjAsgaAKqi&5 z)V#OM`CV3&y*vhFpc_o{_p+ToN#dSS{=2Y+_b#gagkdVz zuSUUcnAaj`am(#X6WK2zndOix%^|;Fw??#*$$Qh;wHOb|9Tmg)0gQm_QJ&?9iaC{T z%3}L5$LD-}*v9!$cGIurV`8+>4Fg+xxwsZ1aK3f%2()La(;dZ|cfCyMc6$nEG1{rd zpf#&&nPRGaO6r{dk^RgxuAoG*I&+-wale>sM3=M+%6VE}>6v$Dtky;Ly5;NoG#z}m zqa=pf1JT-wNO2&K^P&pIi{~cu5?g@MTBTG*s)n4oXR|kD4(B>ZGZDJk z(QwnI((>e3vNlGk0a;&rrWv83h1RyE88>m?t;US^db)j2*WS8wwjs6ra5lkC1pa9P zt*eF8xs?Y8(;S*?<=Zn}uUi|8iYEzK+toqYC6#h3OiF54``E!KQ54IoW1P9pSfdK* z2Bj(N4(#_qp}6^(S5#UZSFIHA#z@@sUOE8W{Bvg7gUm@oZ9p*Qh50k-$ zW82u`5ISSeN-|HQt?U8bKV-N{o%81jE?6D5jkZ>FEGS1{zhUinX`S6%I_n+=T*sol zvfn9{F~I;NcEw1HTz|iY&U>MLT^Jy&Js?e( zOfK}JA>p;PMsC=gYI#j8Jb3%fHpZ7$waU65i@=uchF(|(o_@H_1LCw4kUYGV>-*kJ z?)}cJHL&6m;x;RnRV{bllqQd#{qNVYPX{`tWr%zStCPb$e-9^VgcE}|N&TsdN7jrc zLxaoH2P8zu^PnMjA$<6?$U@3UIg#u$?8hd~aq`~xbcF@(c4x6}hKqCM8+M8x=dmr$ z!K~d%8q!_X_Yr_(-H0nsOd?~yl-sUoh0G{F_I?K*z%9;rGP+fY*7FgFjfc9;H?uFW zhS^of<=LcJ{2JE$Ojdi37nPo0o9h4mB`h1s22g*`yi)duy)DchhcJ=!J?TPT*O*?| zz9e(GKA&&u{SpKmN2{XpqNT1XWdHqavs%BSrp)j~NHZC1!O<}4g`Va=)4I&1&KR|d zg{jJ?njS>pU~96w_%$enEG?`?L1X!O1KmLl)YXnBF1p@KkaDLL$8&8w%=?2#${XLm#2J`G$ z`4Z-ydanv=?g+RE=a_ds?djj`h+53p)7%v>1I1fg{YdMzsvnlajRQZ+t~ZG=vzFV| zb|_k*q-}g+=Kc4lb)d})H6^9c6|d7~vqi05(8ilK8@cUSTHv>k!ES~3@@@%mX-962+J_Rr*M#~Gf+gyK}FM2Ix{L=sK*d$uqR^)Za zK%&NgmH#ea+ZE~2>)*%n@y_k!h;#FbRj=A}F08j%so!uw09Vcu$H${xC$!z{3n7om zI|p>3Oz9emX*nwJ#NQuYa{TPJ3GWO1>DkLc)uPhnZucp0a)^!LUzTQ1PM zJNI49t;yrf{KQaI0;Gsfv(?e+jZKF)cuU?l?iZ^{O-DJ0dFApAVRPyqCzgdJ@Kp$m zu^Qg0$n9CbFw8?t@Tzv$%*qp>=e4#>vbrfdWyeDD+#0yGo3Gx@Ot9bIV}fY+M)}iP zhQ#*25!kTl8O$J2-(LJ4I1F4J(&Or##=l_?DrhfvRsSw|;KtjUA+0w@eVuw6M>>?B zr8m+)-~K&Djr6izxRBl|@b7+}C7@P+^b?M{aqGney-d3Cnz`U1G*u=uvN`p#;cLv( z#;WtDxHGNbTtX}HXSUwW;$%8T0c>2)BB4=J6w0)&aN^x83op~UkF_Pc`2cqj_`RBR zzO1PzYJHoFTaCyM`LNF|bHK}WGkv*qFaX*6cW+HWtcpUYQ{{{$Ba_ZH8gG#7^pO~DK zAmDePHDN!NYwdy$(<{Eoj1wSMFe{9;f>bXZ1iMI0VU{=+^2z#JJ@aJ<`|0P4kh?t} z^z65~y8S&NF-^2j{_jEL@-DtR|9eUC8qO_Cca^z%i^~IM{$UDF^a+B&1^IoCM|H)v zuvSkRE?;K%9Ewv6Qr6m;aR>sIgI?UnD}m-9D0>Jdlmap_nnrc{v*?j|Vdp=y1ybYotEd3W&AYeT z{~ot|ra^r4w?Jootj>c^X<@-g{@+y`nREYDz5KlvyHiuYkN(Y6&Tuil=JnH2((E6> z(bY70)53KDcB5|P%C?;cia)|tf7{6&+|A-sUli;mDo*FeT=#Hdutt}e)}d!%%+~9Z zOH6aCh~HO})s`E=%{l>$&VpQYyKOi@Ymiw>yaB+qU02&p+;!gUyi^>I{O+l@*Bjy)?WkIyNszTxC-45aF)tGWlqQhoLHG^6JKkUihB6H}Z#u=T+%p~di-@O{_8nsK zAi-)@$pyG@>vU)!%G@6}QQJ>1R4U4LrMjpP?p$&0OG><<%VSEtMW($v)eMp&3ztGb zqXM41h6~>r%(s^m=HFQ-npMpGS3pn2lILZvMnAlL(=W?+Iusa6+|_cBeBmfiD>El~P4w{|aQ z*43sxYfOT0mSb6GF#Ti2*ZYBC1SV2^KopAo#3Npn}R&rEhz zA~kn&2B6PrJwBZ)$DWN~GjVswR4=!ewQfAviCe9cnjiNrok0Kg^A-?QDRzU*#XdTz z+p}aAjeb=GT+z8@YdJdYi~e9o431Fe@2qcwUa&Lgh)vphbmY!Bm> zVBJI2q`Yx=k2?4&9|h~%YOfQHXsiOl$X=?fSCopCGOS`-D3Mg;&*1QDPv&<2es0?k zDw|1uoh+A=uTnHdlzNY+xa=h~$NVK@z6zmtt!I|RA1yHsjB*svvAOw<_Wt7q!zIY?)pzS#JN z?RTDqHJNAxCHY(G91Wm3%`dqeSmLbPiHoQH7C~G_#lFST=n@38S1sB4KnLot!S@cN z17N*5R_(FQdhiDP#?#75F<^8Z1HE(Wk8Ewhivtxp7{gaEHixtQ6T|GgwPb*$F{`hD z*(853@8=t{!-Rf)N0g;Avv^sL&HGFD zFC$htU%Uy}fkw?W>$|sRqs@JCoz@2*%y)N7=&#mh+M2I`N49P?+Qy?zs5c2X@c0M2 zK=53z*PrJIh)&J@<=eFzR@|yAGE>uQ($B3{qEo!?^TxOh-jip6@ZM>vbR?&B zooYAdXS`e6CA08^Lj9rk_;%UO!BNqOvanB{k~3$#WSeulcPPHl`;{G?U|dGAraZ3m zfzChPMJmT8>@IeXq3^B4HV%xdzQQquf?y4)09)oC?=ucG)Dk}~LIWdTW3z1iWef_n za`)i2;4G$fP|coU+`6Vms)Akz-!$wC>q;tzd&LAvoOPM5rVC$Kt>;1G?4BUaf|9S) zp!p$i0KF{(aZ~EcI?on&ug#UH=WCZ*aPeGrxDQ@OOvC!1PmTaynE)IQ3h1{}wwEqf z+OupugJ9VG)%e>}BiFTGu=NtFUA9J9q;)CZ;LQ5o15d8kNyTTZE>lsU55)w>7i@b_zhOE`lG)$ zHfi~VHs-fNql+x+12ABtg?FQA;jRQ(XnPP&XE4SqkpR{yTGGo8pc{s7%zWL&NN981 zAZ@A1?4F?5?zF16wk$V*=%0W5CUVou^)gT)DGl4q%J+iLZt-&#yMBmm1tcK_3Kz-2>_;S}N3$>i3E1@`EFT9@PYy;k;_>3b zY4vePQcw`}D)U0cc7B_HA_>5~c6@*lBWumQXx%mSbbg=sb5M}eCR{^yU?8X6-QR>|1GoW!w#pflu zE7T;&fZ_CxH?56Rat@zcO3B4RyadVc{cafgMcB1>^>u(3bi8^geCio!98Eg}V;jxM z+Wgp$j@Yqifo1oJzqB$KIE5LA@mMSj^U7X#SEdi?A{9Fr-6f(lqdHAcxH+)$ZeFGD z?a1}^><(W)kqQ)Tv?fSTHW#0*AB%od-YLWBO!7scbIJwuOdZ3&FWtCR-(+++@r~w? zk65+4MabT`d^6z*5Vw~$Lx@#gFSl6~A@}>BNkuJ!?cw^9vh;JifE$~}+aY%aPoUc0 z-3srghxH_H+$dt(D6UG3E=yL`@y5AVcmdUoy388zmnqNWl7$#UzptMsklKe$GeCeg zcguo!XaRR>Tyi)X=>7m!_de6NHl*ZML{x4DB_c}i3D!+^LBiHltsI}u4H@7BZwwxf zQf1P+LN96TG+J^bOoqQwVb%4@I)G@bnPqK7b0z~a1~RtM-oN3v!7u2u}^4d1z;z(;mlRJa*HO0ozz*U1q^I+blQZW~cO05f7eAG%@b! zq#U zNfH0PDxJ@{R;GFC@5b!uFhwEF;@3rP2B-*%%NGKW^kH5ZHCF!gz4VdaOk2}ByaM&v za9(!@l8JJ1cwyZ}`&#=0ocH!IlkFgt`{}6a7HsK0ro=Qxvw&YrL28md+tX*$cen>@ z$FJ@g-u)!K`FU6-j(dL?+yVCjK?JFyHhy>N?Jy1SDF%Ld!Hu&!Fx?(o09+TtvL$$a z{}}hFpCi-xj$5X>ka6Jh3E?h*r_ONtb>m&?1&Ai1z!DExX`iIoW>P{&LN*67XK(om zn40cpvJ2<4mXl7V$G@*-c`cR92JHkl*C=d|b$BV{8WM5y215uzzt@g+ypJlQ9OFm7 z=f#cPfSVMi-umc|V|e$S2N0J|zao;+80XPT*Vf3}KHfQ~4{b9iQyz6i%nyOb$M-9e z!SP1VBCGbTMZGtz;Awy~Ws!50b3E@J{Zq}H`#0}?T4bUR;%=BZL2twY>@B0qq&Am| z=F~F*R;gq+y3)SYw8V2<+1ppH%tO8J>pwJq{K}-9)qrZ|(J(oYR5Z%ztz()$AH@{_ za$k`4p$DBEEQR~kw!$n=`PTiizoaKPz0Ub10EzFEy?&emXvGEns>^We_G7F(-j_p0 zJfH|Wp9qa}HJLM&(b^;(e_IwgUQUDNMq#=6F)5SJ8Bw_|X9u!B6q{M$9+#}4SB?88 zw=aMLVzIomPX5@5rh(3XHmfTjc5cvPb*L;Uvn3R{Z(F@?I*|J*^-CHo2=jm^eNB?P zR^>;e;Y-CpN2voCU^|a;4wjKSl4f4iTW_Q+BI6ITp@2s5>t-|SIO4w({7O678iEQo zbc&zdl^oS_6Kh2+d^b)&O(@9Bq*lbs z=WRW^Y~FaoX$~6$pK2OP^Ri+#UhA>7+S+70AEpgKyp|4TQE#UEKps}IXv&cfSCN~% zhx@R*xN6%xtnS!gRb6VOo7%(%QmF7Py5TPBW%69nnWG; zdofr&vQnku%*wW8o$8*QJ)zEyBo}18WAS~{es$tq1?=FLtP+Fr#_c@D4UQ(%fY#Gl zemi-88bMIo?gAX|+K|J$vn)+!$AxD!fFzJ_)kqiqeUYzUcMsuN9L&k=ZM3?^$#tR=IM`OdYOdS+)5G*WtvQc8 z8`GX1A00+4-)B@KIUTQp-kLeX)%f{_1^POqtU9l812}e|fKKbQBG;QR?_%zrBNuAr@>EqbU0p0YdE!JHfVIztTmT+|EC)agn z5G3jbx9S)dO};BPB^B#+R$L{54sp3qh$_?+aoYr%{)z*9yWUcJ>lgdxJhp^lzu7o9 z=RWH}BC4!b?++97mXoWHyB_UpeB9qBMO(!7A0V3*1FWzFl*MZN6^4eCt^>BLFo;!pL0g{r~*<+`bdMYco<8Pbeaz=gNml`_k$EXpq*fZj2 zaA-qtK~XX%eQMOUedM8c!bUaCfa9c393;5}<4h=JI;5q3hFeG!;w0p+??n6b`u6Tt zZ5NX1$bwZr@_-IgmLnRqdoB`x33&G-TS08#$@!U(J-rO;nU7VWP;>#a}D3R!aq*d9%S zb$^KI`&so(C680#O_7JCs(J_n|&6sX(Aurp+zC8Y*K>&H~x6?rfN5vSh-9G%evbgIEFSoG6c)p=~D|3yHMOV@R;2+ zlD1q%O2g5SiJq_PXhA&Z#OP7j_gjmAZPUQ#EX9hty7y*C4x)ya7fL*Lgzg?=5-xK| z9>T&5Dq~{;3e|TFqINU1mxXfh(IqpanGFCfME-w!Umhdda^BVVCSFi5$U@nGp!B}) z`@T%?`@YTeI=xKq%XHg9$$Kc0309N{6oi7Mpdg5%XA5LGLCPOC0qpoCIL}T zCviEht__8kVwYQK<%cx9jI^Bg6x{sQx+To;%npav*i1FUjYMG4RW{Be;-uO-FGO6q zfP(KXC)T{9O5^m@B&yAw5pm>f8C*+Myg{atkhxp=0vtmslB&&q#p+W+v!x(*=w-g? zLhh-Vx`lJtUa(^=dd4Q77fyd&8_X)ML|pbOnw@M0&gRSy8_H2#$CsIB#ij7{WT3D5 zlH;a9J(tU^&D`P$cvyH;=SkuYUa}NzIvh4=mAZs5WGZGF>5)Taoco1vx?qu4=8J1J zoxxg}wQ}xbuclpbrxr1O!IAX~okJlvU7Vf|l4%RfO}Ux97~)XiGBi z;m8Pt*6_UcH> zdFKM1ORdSNEXHv~R&P$j3a!q1VOMU*L~EfQnE zS#H=>-gG}aC=@E(jD8%pDU5}v{{)WmgMD6m!hxd^GaqMlcJX;-7Cx0jtL%jn)l*T- z)w5Y+{46X48+SCqqQOzK2ZHO#Gse-UP z3O-}Z1=@ZU_V}=!Ek@a7LVhfB!;pRUq&(5rV5?(ae=Tq)nhqz7!A7gAbWmN-q*ibW zZDYB#oQ3oA^RRiztEMt5*l#CjE-g!Ke%&_`Fdj}O9I%O3$-E4D3u@jV z!LQFHu5#0q(Zfoz`TA@cP{ST2@`_^Ot;Lnufq*Xvx0k$>PZ3jha3x@7P)>~D$b@3Y ze`H#@G@fZ^sf0evzMOy%kySUAwU#Ejz;0D>q@`QI5=fSd%R5D^K@J7jG z-E7x3Dtbi%PTTaxLano-qyA9aIFcmi!nxNndw`AZ_eB)w3jQqih#<&pWZ)#A;Ba(>cRpAQ#QK3w|PC zFfZURP&hHrkuUe8!_@$mVT^b)TLbpU>==Y_z%)OxUcq}M*ID5v2bI-0Rkge4i_+AU z)tHL8WK^*>4rZfLyp(O%&Z0H5u^~!C{qnw5D+#T=25ALWPoHaI8M!nYc2CxwkOZLY z6O4tS@)Fl2cIJgicH%XKj4*DgQWrwqpyxPMo%GHm!j^t84(8LM*>SJbE)7nnr!t9S z+|!7%rsJ&CyHw9j?emFpeq4F>0O zao*wu9y?MF^>c~dTJlAUb)8cT^Bgq^Q@RnK31I8zc1q2S$xbp&ku2zLIbpN+Rx)8d zZotR=al|t`pNz}LUB6xphxAJG%9Sy9GALA{&IOzkeGa2{{c*71n!s1lX^5vxnQ9|T zDpD;e=jB1mZc=q@2}kOvWtdgsFc4o~n8Rvb)+15Pr)SfQ)iqCZB|5`N&!UqIk53n~ z;y9Rg6ioc2?X1)|6{OeAB0tP6i>Ee~e&y8mpzTkFrk*EeQ_N~QIF7d};M@ESaaP$% znaYK9(=Rrd@km_>?^t(auT=77c!e4Da%xSonT(p_t5~6#_10plI(*m(%uH61ydCcc zs%~e)4f`SJW_h0s+CEH?flZr_{jzFMoROq_A#Kkhay7&~V#9^IG=-7Fpnl<}g1#Eg>GD-t- zn^rsRwed~b1-a{ZeOZYv-40*Ay-v!Gnl5G8R+d>sWt-Xoy^BU?tS-j6ntH-7I9K>10k?GBPfKEa4-6Za@`2^l zTJgZvY+|useyW-pM-@FzC>6Ey`X0}nv*dIh&B{K54~CheZo(jlI0Ums%CB))gEFIC zHPG;J&4@nS*9Eu{bYOLpSB{g%g zK*Qyh!s>v(W#WqLzSPJT3VW*MzD6g}tm|QmV#RgId-=3lDT!)^ysG^)FOfQHMVNCX z)Xf{I#CawKOKzv}W_uzn4^CW#ydYCO)%ZtTjep(H`j(~$th-9uPPNH?X_=V~`TV+6 zEIMh5&QfKWNH!4`-AAWlle{tZWW~C4(bqFulgeCtP|P;qo4B@RZn>=ET6d`Ln1>!& zPHa>kr;JI7)a+7^GXAB&Es}9-s%AA?G;1pgh1o5SM&Q)OVPEZ&^rCU;JgpOCk`*{B ze7dT8lQWB`IxM8^Fg@L?t+W*jC!8%PPuLx4acQyS4fU`?lihW~i_74ZG7Q7Ut}_!? z##0*$_D)Ra7pL+~z9SMpT1xmzZa-D%1#RJ3Wjt%1mAqzkB3oH{?Tf^Dx)eHc3!!|* zh{T<(6x%R1&O0?V^hrtHVA2buR+ua|iU$)7t3MymOLHE0ya^T>k4sXQwPkiyUE^r* z1ZN_5r7Ah=iIr|?+O3)7gYrJ#x{79vM`Kwp$A|ITpnTGmmGt&Fbc4;%Q{p>khT(}J zo{l=i75}l&*_U>MdZQGki1%Y~YXm%$rn0PU3}BZEE_5Bn)=IXSYx^89k=T{X za)(`b>1Z?t&WI)|SW4S|bt|iY(`Hw2AYZjT)IyCp>&{U}0V}IZ8osw!HdNPcZbUs5 zH##0|V43X087W$)avgVM14F$O&blqwCiNr!dEF6Ed#dL{;W%HZB}OLLWV~SZL^Tpu zZwTkYMao`7(LYPO5;6EPQsSn8?<~TOB#=qyxVh8idHFad&I&|`x4K0>FL^pS zF?2F#RV6nfNv)SlNmw;1#K%F!gl|p=g93|XT^&UE!}O%=3&;h2i$$mn_$EWo@o~Kk z^T#}}Kzi0%4pW`{`dECHAFs@*RG*itHOc{ZuDM>T6^i;SGFy(h&3;2(Yn2q|YhzLB z?WEH%dU-zUWx8^hkFMaJ3|5QNg(+U)>Fi@s!PrT!g%PgjB&UM*GR-S}cDW)ZuqsWV zKz#1EcHq3rg5M}k%wg7gA<$C!CTHnI!ldpeN{JpnW{!7^_JB%}&ZO<5z%Vomy{*m8!Ktqk)4)juP6=fC~$mg$AXsG==GI@!BHO z9O-Apu*sV4wS=%cPh4l1Y21T04>n7krZnAV%R2E;>84)(u=y&~g-<7y@%mpJ&o z!jV+4p6jF23XEDibj;TSRyxc$Vc2D~nF9KAU9DRh}%r zDy&Nf`lU5zaPnPtMX#O+Hs=;^LdNe}DsYJM=r~$(7tQLHt?!Vw>PzSwwk0r&0QTVF zw_(U(9P)as8u=^=2b4ue7WZ0TkvhtG*t>Yp2qcV?_^d3RK!1R5k=n;9)4;26pL*QK zr&ed{v?Z1Jif3`LNqf}EMf%pWRLIKn2-NN)zd|zN!?-1{K7y}ewNuS$TC0vIpbe^R zWvlpnG%d~=V&kAQP06ONl|X4)6UUIsBtg3;%L6;hlT09?2JDcFXF9IAtq2y)6#|UBm-?N7wn1*a0Fz) z)gHqto2J%nb9X}dmcAg#Yx!DZ%Pq@=PZfZgQaIt^X1)1tyfO5gD@13Z{`^cA7mBmt zX;uJJ9HY_HN@f-6=fk>q4yQ0o;4@q>pH0H_#d)Ti=?Q!7WF>S0a}^9BzxJG$Sa@24 zcwQrt#rzr3)aa2$hg!|aP#tI{HJyNEYC19)iet%fDeW_d0@ZnTvWl2(QCDYXlJYvi zIP3u#5k~y|N=2!FkFG1fttT}fFD5RraCi>8&8wX7IxDh=<->Idz9D*qNxeP{9SNaL z4o7C%rvvEyXxFe6aY)3~93NZ9=CaNmHLOkpvZT)tmFpyu@B$_{hTv?M0qpW*wEGJV zxyjU7^yX1lHLc{rXb)_w7l)%WVfUicx-Y588ctXjJQ=7e;_AHF%q6;RW6>uHcoT%$`=#4gS+gt555IX`Dj7Zy? z(RC{=k`*Mvw3H8B?a{H3moFK(F_lr_EGGlKXnB#W!utzMQ4D#T2GuIn$;JKd&fKMt zo%#aiCG0BRuEfHo(|HGWwrLu8uv;4}S}J>nVM{|4K6SJW&68+hVl%AtVfc1^l=W+> zul8im(zRm+De+5*7ws;v+jYpauoPZk9rJ&2yQzee3(`EEDw4Cv4 zn&Z>{I8_r^;a~)D$S7*nvx&m69dwVh1y@|6D%9rMNkf#h>(;tx`ncme%6hr7qkPil z&8SQ663ih{XisG6V6irG+t2mZsC)+R4-?*8*s!gXSwj;x#cfp8VXi`Mb65Eez}TWA zD_1ib)xZ;nxd0_Vb! z-r2E*Mdvlonet4eQ4YhYCCqQiCPMOrrW!TESJ9?4pyDfp=8P)ZJ}#a0RAWg~o@^b# zu9*Y%^2D-I8x87o&N*0`4Fg^pIx_l($iM7#B`t+iHVx%qw zRtOcj*r_{E4aDM+VxsHnH7n+jyl3i*{YQh-r0ck<>&NDy1bne-iq@m3csPSTNGwn{ zsE(4ud`;}&FU+l0-&;^7=I)UW-mSFVgy%#*$f)JnZm*EYIOkTq9JZ+#*}6fVeb5!0 z+6+xUYzkRl02#rF)h@nP5?+?8ni0&lO$|NzHY_NKTHK3)DsPj)!O|+@*g1=}TT*+{ z?l_8`>Vw7nz+GIaW3q}eWIYK~7VexLHa&H;j$BcBqc$3k;$>m9S8TN+y5=-m)t*_L z@$#e|KG7-Xz{#@WyxItBJ!Mx4-bF<{d8XT4Xqsx-5{`a23J)U3h56~wq#7B-(({0} zFW^VI-MChv?unXkXtP+MH_N3aQK*97;q_sSq|+b4+96X#XOX2E?vx)+ZG&%oBmQ~H zE)jRV!)XKHXfx!RcON2jxq zdT}=OmeSLSa1o%29w92c)Y}&pINhE%Iw^N0E$jt3v z_GB>i&-772)gUe@9mj(F8PwRKQl4?$D^tY==WN0n8+Yiu+i-M+mZ3B?$kc^pj|V=P zO%vVj07e4he2p!T@rsU8&1Cv4l{uRjvh}L5eqvupVKgPO9(g0f%*YjklaJGVXB4Jr zTHuL1ZNko>^>CwXX;soX$z&8h?}Y4p`2H=Z24OB)U1fkpVgW%z+o<(YkuYo)CpE|t zakbcAu_>yylQypW(|+jKDse&V8C@#vbx(2BPdV;i|w&l~p;cFjtP? zKt!1?7qG@kqv$}b3-r5Y#pzizp{j<@yZ9a1+|Y$Z-hosnZD$JAn(GKgl2t-UZ61IP z;S7A^teeqHe2&VIQ?{!48+G1nnu%6rh4MOeuGPYfSw+O_2*7$FnLBl6OZ#ih#`1X8 zYa64AN=PixS^Y4hJDgA{tEZ(SMOfT53Zrks5VJR8ZKRij&$L!ue{0nWOgo=SBsen8 z6Mcij;XHdqe{Vhe;5GfrK6_Pl_EE?;`z-tHbI-o`+Wl0|-a6o7k6iK=;NpwV-nl@= z>tp7i+#iK@`>O5{`Qq&hRJ=~+fiL!pm;+zzw|-w&>91@5B75jx?6G(8j6?VWd!B6H z;xWFV5^2K%^=+M8|FD`bCU+lt#n9iw`dJhk7J-)Gwk1k@W%mC}KWf{E;~jMfm-NTm(7KASN;f zrpiJL%pc`oJdD4aaSnX3Uld%Gj@qHmY-&AGXHX{yxzx>hkhMT0e#pE!aY3|CG)?U{ z=ZnMm#lzwPHAEQt`Fuh70pAy}UqIc6D{SNFzKjbJha!r^Be*~r_(%H}lrONivg>fOx)U+fnJSEVCgY(BRMUm#i@(+|hH z4&xVBwYNVX!WW1JwvU0|9v<88?TzvwLJr?Y_J;|SO!?w+ALFsRCD@-mjCby>26pkq zCiU+fnbgfG~>#TS_#-lluI@A0zSae3YZP5<_@%2uC- z`rp(%@Wp;{adrISgDc}1cj;?<0NUS`UIqBu<&P-5iT{Bw_KS;6zIYo(Cvz~W^~H;k z%I$BMIQJI6l79}&w?KDdh==jTU`PKf_*3@>7ydX`<8w@0j7Q&jh#Y+Lr14pPLb({u zhM`=PPva8)I`GAQak1IIKt$juIQii>2n@}F`Syo?=&mqYdJFt;>;uEmm&7M-l!4=> z?2q`Pe2kAzE0XSWfH5{75+CE>ACbYvC;sF~!+eF?TW@^7b^ba?-+Uk0)+XDAi6)Q( za9rapMytprgkP{7qyIaMi5e%IL%0HGVd2+wjDzSR;bi;){V0b}6XRokBn%OXX{np! zL&IN(`h8u?NZTbo(@9@|@C9)b4##Kt+YpLct$-c*;$s)>9G@ZB-X#!*CUKKK$|hgD z&7{M=18M*GY@qSUGl=+8&cg6bz94Rr5BeX*FZPSLO}^OdUtnK>v~S8A_;nQZLS|K9 zT*?>df0-{xzXRJl%PRzVn4aK`_8|x#k$g}leuJf9h@%5v>=y&Oq*K1YHh6zO!YxfF7}DVhiTLMyaPJNgIQ7*tNrVxziI93O}n4# zHMif8eYY=^|ByeNW%`i$y{YfT`)*(CE=&)jEu1m*kVqt7aQEAGUxjqk);{xvuM-b? zG57O;Iqtju_Nkla$=*L-JfM;wE9QP4Fw1?{-}7|0&#-;t{lFLd)ZYGN?;GzAjf(?c z+z(a`d~vsj&c5sKezg4ZQeFjL;2f&g^ABcnT)OsMe=o1m`$@5HyzhFBV4gRfBl?)) zG4oX~;bPzQcRyNwc`5tG`z~C(uJcuy`R$i*vG4kOd5zvrihbjK7cK~2?0-J`eRIu$ zFYX6(C}kHekS`w7I+vTSyE*X1esOW&i~FnJeM#E)^YJ>q*j$%_>+d(+ce9h-pLWTh zz1>}5H}PZY>d?Qqm)Wzsa6$M2H9`6q_}sp~z5u)b29-}ux^D+{zpQ!aU)&!%?ZO3p zAHhBbe*OFy{5}UZ+_wRDdSm+@V%UEJ{c!c^7n%J$a9=uN zh+M)$xUUDgaiuod7lf?Yr}<$1_+1pkP!8@Rg8P1a>_ay}Ewi7;M}{w6#RwDS2X@~K z!WnNdd+?y0-A{w;&w+ZyeLYae?9NYQzaMmy^q7wRkdNq^eY%qijZfo{Jz~hdLb$3A z`3u9?_;f!IL7d@%k;>3wA1DB6V!_I(7~CfW0gws+Jg zY4db1Ff{QggSsZ%K{UACrfGVTmdM4nPx=rTmv9B)1iB9y#;9_CTY)=OKqC=G3ef4w9i2H{37X4!`O#F zIW&JX5pyViv+sib7@zK0hVBDj+z%#D$}U{6e1YtIKjWT+FLueJeVM!GgLz!O4*iSU zVPzLCNMC^P0{fi5o15)RY|Fv-oBPV+qcnbTJ8j=Q)h=8RzSz~a@7|^f3ic!Cz!x{y z`-@`k!Ug4v&1XEK7cM_bcR#ef$t}`;bdyUY*B>{=4t|;QPE9*oBKrP3~TuyWSb@ zHG@mS4t()E?Oz}E(70gQ?F>vjLUkcY;_fiIq?jmH!A(6~78#pBWa^Gfp2 zxH#~|^R)4J!X6qI2flbbx_@3t9vT;~f-hdh%%=V4x!?EihsMRL;ERX8$9=wEQQ7-` z|902>Wqm$hP$nWKo}5FFj&3-Yk8xA%Q$MN~k_KlflZ)7JK08TE z_L!roDYl78zF1>A%n`AI`-~Eklwng2k-z<)k#jFA4tI}Yya<=urP+4Td)@ZEf7e~| z!L--kBZkoyOjSC zv|TR4^|)XV^hj}WQAv;5!1}wsb_th1V_Gb+Bm0vl0JdV(JL^y4;q4MXvf7$H9T-hr z%I^FKxy8yM0-1pYo*(`jQD4 zR6Zas2sa|5L)$;e@Aq%Jen?HT zwMpDG&ZdjJqaj9ir9nTUbuvyvB@h$k<3-=|sGEdReUli}MRM6h>}CkE55W(WK}i}-@=#iI-&hy340EE_`lX~eym8ykPq zmyJiTyZPKAVRVdP`^m&U%ZM~G4ngA3Fw(Q642b30%!9U-ZD!j{OWO#Vh<5yKmjd%< zYVZMZfu+DY!S^i8o2@}C&8Caq%Vs}%DtV>)qB8j_CBbM=6{*Nh;}dy+X6N>Ja*IrZCQ1%gW~1wjzuBhqtcY~h>-POUE*H_uBoa{q zxlp5QZft&31~F-Dj7e)1%}x7u3Jlx*CG>uLH_N=8^NU?f*C|QH_woW8VdtgKf8{N%CYM{6fP>JR%QcpjT|A|~y9`R$jgUy$wVaj*l z3tAm7ZDRdx>V*hEU!r+plJ-j5KO%&+V+yKgnvS~Bq`eNJMcVQS%1FO}_CZh*&2Q6> z^+y|Cq--Q#v=ccbjQmGA_rnakrChDE&D@`FXUg{cD6c#e%XpW2+}{nb@Bde|{^DF2 zwu8H<|`Qn-a-_ZNO7dNb^YoZ;NmX%9QfkE7rU@_;ERXH#a-I* zE*)Oycb9w)eDUzOxXW|@It=Xcze_#`zIb?C+@&4w(*JdScgg3#7q0>rxBqT&9R_y! zZ_kn072|rp17AEmF0R+c;|V$N#Q_()(0JgB11@&q;=mX8hYR+3j&l$eqMbdU57$8 zHT%cyzb$mpd6m^?gM?RslujWno zg3Rnhxul#}3SzryUJTj~xOnLrAhnG8B5QK-8BetIa{UXGfU?+qC`fu-rAHBfap*<+ z3j`V0^)FB+K?03W5pvVKn0tBYTDe^tdy`VJxS$%lnR(lEHn?d6_~LeGywT!}Zh0N};vsSIP?)%TJ_o)y;9?hw4t#OI#V%YN_~L+zUAQ>##cgr%YF5!bT(0nz ze0Wbi)WD7!;M~Kdzo)BrPuCaj>3Z*;u3cRHGJc=_G%D%SpXTw<>s$#P` zH>>1w`n$+LSxg}={@u1Lk6F%b?+JBJeux14Ap-D+2*4jA0Dp)8{2>DHhX}wQA^?A= zd!m0@PiX4(z1|nT@ZNif0AfR3yx2}-+$8QtInHhCiA{&vCoI5&3!8`^E;I{pq4`<3 z(EL1HXnqMUG`|WLn(xDf<{!g_Er0vR;aGf;#3z2|d(*Ae8N~YJ$2lLz*wiL*IVXO4*FQr&JRtDiSDNyOpP|Yw#`p4epmlJ z;}U^J>%sp?HVX^nSO``L_T6fHdEae~k0(_f#DJ&qg>{Z-GDj zB-uv3$gOD(^xA%Vd?=oe>JH|4iNlJ}nK_4_j9V6#k zfAR+qa`fkV&bNNzyG#i-O%CV!mW4U@WuIVL37W;9Ib+;UIo)s77~A?2=`Hgq2YtGp zKmX9gnCO1Wq(&P`-87$9g6IcdW=c)Xl;h7B_ft;pCoGJu1nm{?hni0r8{RwmpouZj ze9FPpXhUh6=JQGbQl5bFP#R;le)5MH^C@Q({5OmZ?s&^2b$|?nb%7?tykI0q&DgMP z7(&hGmEf}c^}noMl;AV&Q^xk0KbUTrPdVVj)bWR=`}9H!keabw*3=2H&%Fn35zhwqMcfx6G#; z@L}Xr6Jj!MDBEBBC}X2#qvrEUfKu=dsrj|iyBBrv%^xo_w(tD&KiV>%a?l4aYGO>h zo^miXUbJk~d_f7e?(jX$H!kYnf2nee?JwnjxMe=&fDfZ(YC_Bl96)NuhB+e+E==qd zeBZA!W&1eo8-VLmoWJCJ515R2_{Z3v{8jLHa^e5eV1IgH|0LMI=fVz=pM3nn4ym4e z|AifT4p08}Mx0MGOo;No@5v8d*q;c0^oa-KU_zn#NtTWOlMyV-CncOGaz@MlADnBT ADF6Tf literal 0 HcmV?d00001 diff --git a/mozilla/directory/docs/ldapjdk/jdk-adding.sgm b/mozilla/directory/docs/ldapjdk/jdk-adding.sgm new file mode 100644 index 00000000000..5834402aed7 --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/jdk-adding.sgm @@ -0,0 +1,677 @@ + +Adding, Updating, and Deleting Entries With &DirectorySDKForJava; + +This chapter explains how to use the LDAP Java classes to add, modify, +delete, and rename entries in the directory. + +This chapter covers the following topics: +Adding an Entry With Directory +SDK for Java +Modifying an Entry With Directory SDK for Java +Deleting an Entry With Directory +SDK for Java +Renaming an Entry With Directory +SDK for Java + + +Adding an Entry With &DirectorySDKForJava; + +adding +entries + +entries +adding + + +To add an entry to the directory, follow this general procedure: +Create individual attributes for the entry. +Create the set of attributes that make up the entry and add +each of the attributes to this set. +Create the new entry, specifying a unique distinguished name +(DN) to identify the entry and the set of attributes that make up the entry. + +Add the new entry to directory. +Creating a New Attribute +An attribute can have a single value or multiple values. An attribute +can contain string values or binary data. In the LDAP Java classes, an attribute +is represented by an LDAPAttribute object. +To create a new attribute, use the LDAPAttribute constructor. +You can specify a single string value, multiple string values, or a binary +value when constructing the object. +For example, the following section of code creates a new object for +the attribute cn with the value Jane St. Clair. + +LDAPAttribute attr = new LDAPAttribute("cn", "Jane St. Clair"); +The following section of code creates an attribute objectclass with +the values top, person, organizationalPerson +, and inetOrgPerson. +String objectclasses[] = {"top", "person", "organizationalPerson", + "inetOrgPerson"}; +LDAPAttribute attr = new LDAPAttribute("objectclass", objectclasses); +You can also add string or binary values to an LDAPAttribute object +by invoking the addValue method. +Creating a New Attribute Set +To specify the set of attributes in an entry, you need to create an +attribute set. In the LDAP Java classes, a set of one or more attributes is +represented by an LDAPAttributeSet object. +To create a new attribute set, use the LDAPAttributeSet constructor. +Invoke the add method to add LDAPAttribute objects +to the set. +LDAPAttribute attr1 = new LDAPAttribute("cn", "Jane St. Clair"); +String objectclasses[] = {"top", "person", "organizationalPerson", + "inetOrgPerson"}; +LDAPAttribute attr2 = new LDAPAttribute("objectclass", objectclasses); +LDAPAttributeSet attrSet = new LDAPAttributeSet(); +attrSet.add(attr1); +attrSet.add(attr2); + +Creating a New Entry +An entry contains a distinguished name (DN), which identifies the entry +in the directory, and a set of attributes. In the LDAP Java classes, an entry +is represented by an LDAPEntry object. +To create a new entry, use the LDAPEntry constructor. +LDAPAttribute attr1 = new LDAPAttribute("cn", "Jane St. Clair"); +String objectclasses[] = {"top", "person", "organizationalPerson", + "inetOrgPerson"}; +LDAPAttribute attr2 = new LDAPAttribute("objectclass", objectclasses); +LDAPAttributeSet attrSet = new LDAPAttributeSet(); +attrSet.add(attr1); +attrSet.add(attr2); +String dn = "uid=jsclair,ou=People,dc=example,dc=com"; +LDAPEntry newEntry = new LDAPEntry(dn, attrs); + +Adding the New Entry to the Directory + +Before you add an entry to the directory, make sure that you have done +the following: +You have specified the object classes of the entry using the +objectclass attribute, and have specified the required attributes +for those object classes. + +For example, organizational units might be represented by entries of +the organizationalUnit object class. To add an entry for +an organizational unit, you need to specify the following attributes in the +entry: +objectclass with value top + +objectclass with value organizationalUnit + +ou with the value for the organizational +unit, such as People + + +You have authenticated as a user who has the access permissions +to add the entry to the directory.If you do not have permission +to add the entry, an LDAPException is returned with +result code LDAPException.INSUFFICIENT_ACCESS_RIGHTS. + + +To add the entry to the directory, invoke the add method +of the LDAPConnection object. +try { + LDAPConnection ld = new LDAPConnection(); + ld.connect("localhost", LDAPv3.DEFAULT_PORT); + ld.authenticate(bindDNWithWriteAccess, bindPassword); + LDAPEntry newEntry = new LDAPEntry(dn, attrs); + ld.add(newEntry); +} catch (LDAPException e) { + System.err.println("Could not add " + dn + ":" + e.toString()); +} + +Example of Adding an Entry +The following example adds a new entry to the directory for the user +who is named William Jensen. +import netscape.ldap.*; +import java.util.*; + +public class Add { + public static void main(String[] args) { + /* Specify the DN to add */ + String dn = "uid=wbjensen, ou=People, dc=example,dc=com"; + + /* Specify the attributes of the entry */ + String objectclass_values[] = + {"top", "person", "organizationalPerson", "inetOrgPerson"}; + String cn_values[] = + {"William B Jensen", "William Jensen", "Bill Jensen"}; + String sn_values[] = {"Jensen"}; + String givenname_values[] = {"William", "Bill"}; + String telephonenumber_values[] = {"+1 800 555 1212"}; + + LDAPAttributeSet attrs = new LDAPAttributeSet(); + LDAPAttribute attr = new LDAPAttribute("objectclass"); + for (int i = 0; i < objectclass_values.length; i++) { + attr.addValue(objectclass_values[i]); + } + attrs.add(attr); + attr = new LDAPAttribute("cn"); + for (int i = 0; i < cn_values.length; i++) { + attr.addValue(cn_values[i]); + } + attrs.add(attr); + attr = new LDAPAttribute("sn"); + for (int i = 0; i < sn_values.length; i++) { + attr.addValue(sn_values[i]); + } + attrs.add(attr); + attr = new LDAPAttribute("givenname"); + for (int i = 0; i < givenname_values.length; i++) { + attr.addValue(givenname_values[i]); + } + attrs.add(attr); + attr = new LDAPAttribute("telephonenumber"); + for (int i = 0; i < telephonenumber_values.length; i++) { + attr.addValue(telephonenumber_values[i]); + } + attrs.add(attr); + attrs.add(new LDAPAttribute("uid", "wbjensen")); + + /* Create an entry with this DN and these attributes */ + LDAPEntry myEntry = new LDAPEntry(dn, attrs); + + try { + /* Connect and authenticate as a user with write access. */ + UserArgs userArgs = new UserArgs("Add", args, true); + LDAPConnection ld = new LDAPConnection(); + ld.connect(userArgs.getHost(), userArgs.getPort()); + ld.authenticate(userArgs.getBindDN(), userArgs.getPassword()); + + /* Now add the entry to the directory */ + ld.add(myEntry); + System.out.println("Entry added"); + + ld.disconnect(); + } catch(LDAPException e) { + if (e.getLDAPResultCode() == + LDAPException.ENTRY_ALREADY_EXISTS) { + System.out.println("Error: Entry already present"); + } else { + System.out.println("Error: " + e.toString()); + } + } + } +} + + +Modifying an Entry With &DirectorySDKForJava; + +modifying +entries + +entries +modifying + +attributes +modifying + + +To modify an entry in the directory, follow this general procedure: +Specify each attribute change to make. + +If you are making only one change to the entry, construct +an LDAPModification object that specifies the change +that needs to be made. +If you are making more than one change, you need to construct +an LDAPModificationSet object that specifies the changes +that need to be made. + + +Use the DN of the entry to find and update the +entry in the directory. +Specifying Attribute Changes +You can add new values to an attribute, remove existing attribute values, +or change the values of an existing attribute. You can also remove an attribute +by removing all values for the attribute or by not providing values for the +attribute. +Adding New Attribute Values + +attributes +adding values to + +adding +values to an attribute + + +To add new values to an attribute in an entry, construct a new LDAPAttribute + object. Specify the name of the attribute. Also, specify the +values to add. Then, perform one of the following operations: +If you are making a single change to the entry, construct +a new LDAPModification object to specify that change. +Pass LDAPModification.ADD and the LDAPAttribute object +as arguments to the LDAPModification constructor. + +If you are collecting multiple changes to an entry in an +LDAPModificationSet object, invoke the add method. +This method adds the change to the set of modifications. Pass LDAPModification.ADD + and the LDAPAttribute object as arguments +to this method. + +For example, the following code excerpt adds the value babs@example.com + to the mail attribute: +LDAPModificationSet mods = new LDAPModificationSet(); +LDAPAttribute attrMail = new LDAPAttribute("mail", "babs@example.com"); +mods.add(LDAPModification.ADD, attrMail); +If the specified attribute does not exist in the entry, the attribute +is created for the entry. +Deleting Attribute Values + +attributes +removing values from + +deleting +values from an attribute + +removing +values from an attribute + + +To remove values from an attribute in an entry, construct a new +LDAPAttribute object, specifying the name of the attribute and +the values to remove. Then, perform one of the following operations: +If you are making a single change to the entry, construct +a new LDAPModification object to specify that change. +Pass LDAPModification.DELETE and the LDAPAttribute + object as arguments to the LDAPModification constructor. + +If you are collecting multiple changes to an entry in an +LDAPModificationSet object, invoke the add method. +The method adds the change to the set of modifications. Pass LDAPModification.DELETE + and the LDAPAttribute object as arguments +to this method. + +For example, the following code excerpt removes the value babs@example.com + from the mail attribute: +LDAPModificationSet mods = new LDAPModificationSet(); +LDAPAttribute attrMail = new LDAPAttribute("mail", "babs@example.com"); +mods.add(LDAPModification.DELETE, attrMail); +If you remove all values from an attribute, the attribute is removed +from the entry. If you do not specify any values in the LDAPAttribute object, +the attribute is also removed from the entry. +Replacing Attribute Values + +attributes +replacing values of + +changing +values of an attribute + +modifying +values of an attribute + +replacing +values of an attribute + + +To replace values for an attribute in an entry, construct a new +LDAPAttribute object, specifying the name of the attribute and +the values to replace. Then, perform one of the following operations: +If you are making a single change to the entry, construct +a new LDAPModification object to specify that change. +Pass LDAPModification.REPLACE and the LDAPAttribute + object as arguments to the LDAPModification constructor. + +If you are collecting multiple changes to an entry in an +LDAPModificationSet object, invoke the add method. +The method adds the change to the set of modifications. Pass LDAPModification.REPLACE + and the LDAPAttribute object as arguments +to this method. + +For example, the following code excerpt replaces the existing value +of the mail attribute with babs@example.com: + +LDAPModificationSet mods = new LDAPModificationSet(); +LDAPAttribute attrMail = new LDAPAttribute("mail", "babs@example.com"); +mods.add(LDAPModification.REPLACE, attrMail); +If the specified attribute does not exist in the entry, the attribute +is created for the entry. If you do not specify any values in the LDAPAttribute + object, the attribute is removed from the entry. +Removing an Attribute + +attributes +removing from an entry + +entries +removing attributes from + + +To remove an attribute from an entry, perform one of the following operations: + +Replace the values of the attribute with an LDAPAttribute + object that contains no values. +Remove the values of the attribute with an LDAPAttribute + object that contains no values. +Remove all values for the attribute. + +For example, the following code excerpt demonstrates the first two options +by preparing an LDAPModificationSet object to remove +the mail and description attributes: +LDAPModificationSet mods = new LDAPModificationSet(); +LDAPAttribute attrMail = new LDAPAttribute("mail"); +LDAPAttribute attrDesc = new LDAPAttribute("description"); +mods.add(LDAPModification.REPLACE, attrMail); +mods.add(LDAPModification.DELETE, attrDesc); + + +Modifying the Entry in the Directory + +Before you modify an entry, make sure of the following: +You have not removed any of the required attributes for that +object class. +You have authenticated as a user who has the access permissions +to modify the entry in the directory.If you do not have permission +to modify the entry, an LDAPException is returned with +the result code LDAPException.INSUFFICIENT_ACCESS_RIGHTS. + + +You specify the change with an LDAPModification object. +You specify a list of changes with an LDAPModificationSet object. +When finished specifying the change, pass the object with the DN of the entry +to the modify method of the LDAPConnection object. + +Example of Modifying an Entry +The following example modifies an entry in the directory. +import netscape.ldap.*; +import java.util.*; + +public class ModAttrs { + public static void main(String[] args) { + String ENTRYDN = "uid=bjensen, ou=People, dc=example,dc=com"; + + LDAPModificationSet mods = new LDAPModificationSet(); + LDAPAttribute attrEmail = + new LDAPAttribute("mail", "babs@example.com"); + mods.add(LDAPModification.REPLACE, attrEmail); + LDAPAttribute attrDesc = new LDAPAttribute("description", + "This entry was modified with the ModAttrs program"); + mods.add(LDAPModification.ADD, attrDesc); + + try { + /* Connect and authenticate as a user with write access. */ + UserArgs userArgs = new UserArgs("ModAttrs", args, true); + LDAPConnection ld = new LDAPConnection(); + ld.connect(userArgs.getHost(), userArgs.getPort()); + ld.authenticate(userArgs.getBindDN(), userArgs.getPassword()); + + /* Now modify the entry in the directory */ + ld.modify(ENTRYDN, mods); + System.out.println("Entry modified" ); + + ld.disconnect(); + } catch(LDAPException e) { + if (e.getLDAPResultCode() == LDAPException.NO_SUCH_OBJECT) { + System.out.println("Error: No such entry"); + } else if (e.getLDAPResultCode() == + LDAPException.INSUFFICIENT_ACCESS_RIGHTS) { + System.out.println("Error: Insufficient rights"); + } else if (e.getLDAPResultCode() == + LDAPException.ATTRIBUTE_OR_VALUE_EXISTS) { + System.out.println("Error: Attribute or value exists"); + } else { + System.out.println("Error: " + e.toString()); + } + } + } +} + + +Deleting an Entry With &DirectorySDKForJava; + +deleting an entry + +entries +deleting + +Before you delete an entry, authenticate as a user who has the access +permissions to remove the entry from the directory. If you do not have permission +to delete the entry, an LDAPException is returned with +result code LDAPException.INSUFFICIENT_ACCESS_RIGHTS. +To remove an entry from the directory, invoke the delete method +of the LDAPConnection object. Specify the DN of the +entry that you want to remove. +The following example deletes the entry that is added in Example of Adding an Entry. + +import netscape.ldap.*; +import java.util.*; + +public class Del { + public static void main(String[] args) { + try { + /* Connect and authenticate as a user with write access. */ + UserArgs userArgs = new UserArgs("Del", args, true); + LDAPConnection ld = new LDAPConnection(); + ld.connect(userArgs.getHost(), userArgs.getPort()); + ld.authenticate(userArgs.getBindDN(), userArgs.getPassword()); + + /* Specify the DN we're deleting */ + String dn = "uid=wbjensen, ou=People, dc=example,dc=com"; + + ld.delete(dn); + System.out.println("Entry deleted"); + + ld.disconnect(); + } catch(LDAPException e) { + if (e.getLDAPResultCode() == LDAPException.NO_SUCH_OBJECT) { + System.out.println("Error: No such entry"); + } else if (e.getLDAPResultCode() == + LDAPException.INSUFFICIENT_ACCESS_RIGHTS) { + System.out.println("Error: Insufficient rights"); + } else { + System.out.println("Error: " + e.toString()); + } + } + } +} + +Renaming an Entry With &DirectorySDKForJava; + +changing the name of an entry + +moving an entry + +renaming an entry + +entries +renaming + +Before you rename an entry, authenticate as a user who has the access +permissions to perform the operation. If you do not have permission to rename +the entry, an LDAPException is returned with result +code LDAPException.INSUFFICIENT_ACCESS_RIGHTS. + +To rename an entry, invoke the rename method of the +LDAPConnection object. With this method, you can change the following: + +The relative distinguished name (RDN) of the entry + +The location of the entry in the directory by changing the +DN and not just the RDNSome LDAP servers do not support moving +entries by changing their DNs. Check your LDAP server documentation for further +information. + +Changing the Relative Distinguished +Name +When invoking the rename method of the LDAPConnection + object, you can specify a deleteoldrdn parameter. +The parameter allows you to remove the old RDN from the entry. Suppose an +entry has the following values for the uid attribute: +uid: wbjensen +uid: wbj +The following code excerpt changes the user ID value wbjensen to +wjensen and removes the wbjensen value: +ld.rename("uid=wbjensen,ou=People,dc=example,dc=com", "uid=wjensen", true); + +The resulting values in the entry do not include the old RDN: +uid: wbjensen +uid: wbj +The following code excerpt retains the existing user ID value after +the rename operation: +ld.rename("uid=wbjensen,ou=People,dc=example,dc=com", "uid=wjensen", false); + +In this case, the resulting values in the entry do include +the old RDN: +uid: wbjensen +uid: wjensen +uid: wbj +The DN after the rename operation is, however, uid=wjensen,ou=People,dc=example,dc=com +. +The following example creates an entry and then renames it: +import netscape.ldap.*; +import java.util.*; + +public class ModRdn { + public static void main(String[] args) { + /* Values for creating the entry */ + String objectclass_values[] = + {"top", "person", "organizationalPerson", "inetOrgPerson"}; + String cn_values[] = {"Jacques Smith"}; + String sn_values[] = {"Smith"}; + String givenname_values[] = {"Jacques"}; + + /* Specify the DN to add */ + String base = "ou=People, dc=example,dc=com"; + String dn = "uid=jsmith" + "," + base; + String nrdn = "uid=jmsmith"; // The new RDN + String ndn = nrdn + "," + base; // The target DN + + /* Create an attribute set with all desired attributes */ + LDAPAttributeSet attrs = new LDAPAttributeSet(); + LDAPAttribute attr = + new LDAPAttribute("objectclass", objectclass_values); + attrs.add(attr); + attr = new LDAPAttribute("cn", cn_values); + attrs.add(attr); + attr = new LDAPAttribute("sn", sn_values); + attrs.add(attr); + attr = new LDAPAttribute("givenname", givenname_values); + attrs.add(attr); + attrs.add(new LDAPAttribute("uid", nrdn)); + + /* Create an entry with this DN and these attributes */ + LDAPEntry myEntry = new LDAPEntry(dn, attrs); + + try { + /* Connect and authenticate as a user with write access. */ + UserArgs userArgs = new UserArgs("ModRdn", args, true); + LDAPConnection ld = new LDAPConnection(); + ld.connect(userArgs.getHost(), userArgs.getPort()); + ld.authenticate(userArgs.getBindDN(), userArgs.getPassword()); + + /* Add the entry */ + try { + ld.add(myEntry); + } catch(LDAPException e) { + /* If entry exists already, fine. Ignore this error. */ + if (e.getLDAPResultCode() != + LDAPException.ENTRY_ALREADY_EXISTS) throw e; + } + + /* Delete the destination entry, for this example */ + try { + ld.delete(ndn); + } + catch(LDAPException e) { + /* If entry does not exist, fine. Ignore this error. */ + if (e.getLDAPResultCode() != LDAPException.NO_SUCH_OBJECT) + throw e; + } + + /* Do the modrdn operation */ + ld.rename(dn, nrdn, false); + System.out.println("The modrdn operation was successful. "); + System.out.println( + "Entry " + dn + " has been changed to " + ndn); + + ld.disconnect(); + } + catch(LDAPException e) { + if (e.getLDAPResultCode() == LDAPException.NO_SUCH_OBJECT) { + System.out.println("Error: No such entry"); + } else if (e.getLDAPResultCode() == + LDAPException.INSUFFICIENT_ACCESS_RIGHTS) { + System.out.println("Error: Insufficient rights"); + } else if (e.getLDAPResultCode() == + LDAPException.ATTRIBUTE_OR_VALUE_EXISTS) { + System.out.println("Error: Attribute or value exists"); + } else { + System.out.println("Error: " + e.toString()); + } + } + } +} + +Changing the Distinguished Name +When invoking the rename method of the LDAPConnection + object, you can specify a newParentDN parameter. +The parameter allows you to move the entry from one part of the directory +to another part by changing its DN. You can use the parameter even if the +RDN does not change. +The following example moves Sam Carter's entry from the organizational +unit People, to the organizational unit Special Users: +import netscape.ldap.*; +import java.util.*; + +public class ModDn { + public static void main(String[] args) { + try { + /* Connect and authenticate as a user with write access. */ + UserArgs userArgs = new UserArgs("ModDn", args, true); + LDAPConnection ld = new LDAPConnection(); + ld.connect(userArgs.getHost(), userArgs.getPort()); + ld.authenticate(3, userArgs.getBindDN(),userArgs.getPassword()); + + /* Elevate Sam Carter from mere person to Special User. */ + String rdn = "uid=scarter"; + String oldParent = "ou=people,dc=example,dc=com"; + String newParent = "ou=special users,dc=example,dc=com"; + String dn = rdn + "," + oldParent; + String ndn = rdn + "," + newParent; + + /* Read Sam's entry to make sure it exists before moving it. */ + try { + LDAPEntry le = ld.read(dn); + } + catch(LDAPException e) { + System.err.println( + "Cannot read " + dn + ": " + e.toString()); + throw e; + } + + /* Delete the moved entry if it already exists. */ + try { + ld.delete(ndn); + } + catch(LDAPException e) { + /* Ignore notification that the new entry is not there. */ + if (e.getLDAPResultCode() != e.NO_SUCH_OBJECT) throw e; + } + + /* Move Sam's entry. */ + ld.rename(dn, rdn, newParent, false); + System.out.println("Entry " + dn + " has moved to " + ndn); + + ld.disconnect(); + } + catch(LDAPException e) { + System.err.println("Error: " + e.toString()); + } + } +} + + + diff --git a/mozilla/directory/docs/ldapjdk/jdk-asynchronous.sgm b/mozilla/directory/docs/ldapjdk/jdk-asynchronous.sgm new file mode 100644 index 00000000000..b63584ddc37 --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/jdk-asynchronous.sgm @@ -0,0 +1,277 @@ + +Writing Asynchronous Clients With &DirectorySDKForJava; + +This chapter shows how to use the asynchronous interface to LDAP in +Java applications. + +This chapter covers the following topics: +Synchronous and Asynchronous Connections With Directory SDK for Java +Common Uses for the Asynchronous Interface With Directory SDK for Java +Classes in the Asynchronous Interface for Directory SDK for Java +Performing Asynchronous Searches With Directory SDK for Java + +Further Reading About the Asynchronous Interface for Directory SDK for Java + + +Synchronous and Asynchronous Connections +With Directory SDK for Java + +asynchronous interface +explained + +synchronous interface +explained + +Most operations with &DirectorySDKForJava; are performed synchronously. +A connection is established, a request is sent, the results are returned. +Then the application resumes. Though the &DirectorySDKForJava; can deliver +one search result at a time, other operations block until completion when +accessing an LDAP server. +Sometimes, initiating a new request while another request executes can +be useful. An additional interface is provided to access the built-in support +in &DirectorySDKForJava; for these asynchronous requests. By returning +control to an application before obtaining a response, the asynchronous interface +allows you to perform complex operations requiring access to low-level LDAP +mechanisms. +LDAPConnection methods support both asynchronous +requests and synchronous requests. Synchronous methods wait for response messages +from a server and then process the responses for you. Asynchronous methods +require that you check for the messages. You then perform the processing in +your code. This mechanism allows you to make additional LDAP requests while +waiting for results to return. +Common Uses for the Asynchronous Interface +With Directory SDK for Java + +asynchronous interface +common uses + +Since using the asynchronous interface involves managing more complex +code in an application, use the asynchronous methods only when required. The +most common use is for merging the results of searches that involve multiple +servers or that are executed simultaneously on different subtrees. This method +is sometimes referred to as multiplexing. +A search that multiplexes servers can make a request to an array of +hosts. A search that multiplexes query statements can make different requests +to different subtrees of a server. If you combine these search methods, you +can perform complex searches across a number of servers without having to +wait for individual responses. +The following example illustrates a practical use of multiplexed searches +and the asynchronous interface. +Suppose event notification must be implemented as a generic service +with LDAP persistent search. Synchronous methods require a new thread for +every request to the service. This solution is not scalable and can exhaust +system resources very quickly. +After the search is rewritten using the asynchronous interface, performance +improves dramatically. Since asynchronous searches do not block until completion, +the persistent search results can be multiplexed into one queue and then processed +on a single thread. +Classes in the Asynchronous Interface for Directory +SDK for Java + +asynchronous interface +classes + +&DirectorySDKForJava; handles asynchronous communication through +the LDAPAsynchronousConnection interface and its dependent +classes. These files collectively form the asynchronous extensions to the +LDAP API. +LDAPAsynchronousConnection defines methods for +authenticating to a server, as well as for searching, modifying, comparing, +and deleting entries in the directory. +When you call a method of LDAPAsynchronousConnection, +the method returns a listener object. This object acts as a message queue. +The object accepts search results and server-generated responses to LDAP requests. +The LDAP client has the responsibility to read and process these messages. + +LDAPAsynchronousConnection incorporates the following +classes for handling asynchronous client-server interactions: +LDAPMessage, which is the base class +for LDAP request and response messages. +LDAPResponse, which extends LDAPMessage +, represents a message received from an LDAP server in response +to a request. +LDAPExtendedResponse, which extends +LDAPResponse. This response is the response that an LDAP server +returns when handling an extended operation request. +LDAPResponseListener queues LDAPResponse + messages. +LDAPSearchResult, which extends +LDAPMessage. The response contains a single LDAP entry. The response +is one of the responses an LDAP server can return when handling a search request. + +LDAPSearchResultReference, which extends +LDAPMessage. The response contains a referral. The response is +one of the responses that an LDAP server can return when handling a search +request. +LDAPSearchListener queues search results +and references. + + +Performing Asynchronous Searches With Directory +SDK for Java +One of the most common uses of the asynchronous interface is for performing +multiplexed searches using more than one server or suffix. +To Search Across Multiple Servers + +asynchronous interface +search multiple servers + + +To search on more than one server, perform the following steps. + + +Connect to all the servers. +Create a response listener for one search. +Share the response listener with all the other searches. + +Obtain and process the results. +Disconnect from the servers. + + +Searching Across Multiple Servers +This example demonstrates how to search on two servers at the same time. +import netscape.ldap.*; +import java.util.*; + +public class MultiplexServers { + public static void main(String[] args) { + try { + LDAPConnection[] ld = new LDAPConnection[2]; + String[] hosts = {"server1", "server2"}; + int[] ports = {389, 389}; + String[] bases = {"dc=example,dc=com", "dc=example,dc=com"}; + + /* search for all entries with surname of Jensen */ + String MY_FILTER = "(sn=Jensen)"; + for (int i = 0; i < ld.length; i++) { + ld[i] = new LDAPConnection(); + ld[i].connect(hosts[i], ports[i]); + } + /* Get a response listener for one search */ + LDAPSearchListener l = ld[0].search(bases[0], ld[0].SCOPE_SUB, + MY_FILTER, null, false, (LDAPSearchListener)null); + /* Share the listener */ + for (int i = 1; i < ld.length; i++) { + ld[i].search(bases[i], ld[i].SCOPE_SUB, + MY_FILTER, null, false, l); + } + + /* Loop on results until finished */ + LDAPMessage msg; + while ((msg = l.getResponse()) != null) { + if (msg instanceof LDAPSearchResultReference) { + ; // Ignore referrals + } else if (msg instanceof LDAPSearchResult) { + LDAPEntry entry = ((LDAPSearchResult)msg).getEntry(); + System.out.println("Found entry: " + entry.getDN()); + } else if (msg instanceof LDAPResponse) { + int result = ((LDAPResponse)msg).getResultCode(); + if (result != 0) { + System.out.println("Result code: " + result); + System.out.println("Error message: " + + ((LDAPResponse)msg).getErrorMessage()); + } + } + } + for (int i = 0; i < ld.length; i++) { + ld[i].disconnect(); + } + } catch (LDAPException e) { + System.err.println(e.toString()); + } + } +} + + +To Search Across Multiple Suffixes +on a Single Server + +asynchronous interface +search multiple suffixes + + +To search on more than one suffix, perform the following steps. + + +Connect to the server. +Create a response listener for one search. +Share (multiplex) the response listener with the other searches. + +Obtain and process the results. +Disconnect from the server. + + +Searching Across Multiple Suffixes +This example demonstrates how to search across two suffixes at the same +time. +import netscape.ldap.*; +import java.util.*; + +public class MultiplexSuffixes { + public static void main(String[] args) { + try { + UserArgs userArgs = + new UserArgs("MultipleSuffixes", args, false); + LDAPConnection ld = new LDAPConnection(); + ld.connect(userArgs.getHost(), userArgs.getPort()); + + String[] bases = {"dc=example,dc=com", + "ou=groups,dc=example,dc=com"}; + String MY_FILTER = "(objectclass=*)"; + + /* Get a response listener for one search */ + LDAPSearchListener l = ld.search(bases[0], ld.SCOPE_ONE, + MY_FILTER, null, false, (LDAPSearchListener)null); + /* Share the listener */ + for (int i = 1; i < bases.length; i++) { + ld.search(bases[i], ld.SCOPE_ONE, + MY_FILTER, null, false, l); + } + + /* Loop on results until finished */ + LDAPMessage msg; + while ((msg = l.getResponse()) != null) { + if (msg instanceof LDAPSearchResultReference) { + ; // Ignore referrals + } else if (msg instanceof LDAPSearchResult) { + LDAPEntry entry = ((LDAPSearchResult)msg).getEntry(); + System.out.println("Found entry: " + entry.getDN()); + } else if (msg instanceof LDAPResponse) { + int result = ((LDAPResponse)msg).getResultCode(); + if (result != 0) { + System.out.println("Result code: " + result); + System.out.println("Error message: " + + ((LDAPResponse)msg).getErrorMessage()); + } + } + } + ld.disconnect(); + } catch (LDAPException e) { + System.err.println(e.toString()); + } + } +} + + + +Further Reading About the Asynchronous Interface +for Directory SDK for Java +The asynchronous interface is defined in an Internet Draft, The +Java LDAP Application Programming Interface. + diff --git a/mozilla/directory/docs/ldapjdk/jdk-common-classes.sgm b/mozilla/directory/docs/ldapjdk/jdk-common-classes.sgm new file mode 100644 index 00000000000..07df5f50f07 --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/jdk-common-classes.sgm @@ -0,0 +1,617 @@ + +Using the LDAP Java Classes + +This chapter covers general LDAP Java classes that are commonly used +when writing LDAP clients. + +This chapter covers the following topics: +Getting Information About Directory +SDK for Java +Handling Exceptions +With Directory SDK for Java +Handling Referrals With +Directory SDK for Java +Using In-Memory Cache With +Directory SDK for Java +Cloning a Connection +With Directory SDK for Java +Manipulating Distinguished +Names With Directory SDK for Java + + +Getting Information About &DirectorySDKForJava; + +&DirectorySDKForJava; +getting information about + +You can get information about the version of &DirectorySDKForJava; that +you are using. Version information tells you the version of the LDAP Java +classes. Version information can also tell you the highest version of the +LDAP protocol that &DirectorySDKForJava; supports. +To get this information, use the getProperty method +of the LDAPConnection object. +LDAPConnection ld = new LDAPConnection(); +try { +    System.out.println("LDAP Java Classes Version: " + +        (Float) ld.getProperty(LDAPConnection.LDAP_PROPERTY_SDK)); +    System.out.println("Highest version of LDAP supported: " + +        (Float) ld.getProperty(LDAPConnection.LDAP_PROPERTY_PROTOCOL)); +    System.out.println("Authentication methods supported: " + +        (String) ld.getProperty(LDAPConnection.LDAP_PROPERTY_SECURITY)); +} catch (LDAPException e) { +    System.out.println("Could not get SDK properties."); +    System.out.println("Error: " + e.toString()); +} +Although a setProperty method is provided, currently +no properties exist that you can set. If you invoke the setProperty method, +the method returns an LDAPException. +Handling Exceptions With &DirectorySDKForJava; + +exceptions +handling + +In LDAP, the success or failure of an operation is specified by an LDAP +result code sent back to the client. For example, the result code 0 indicates +that the operation was successful. A non zero result code usually indicates +that an error occurred. +Getting Information About the Error + +exceptions +getting information about + +LDAP result code + +In the LDAP Java classes, when an error occurs, an LDAPException + is returned. Referrals cause an LDAPReferralException to +be returned as described in Handling +Referrals With Directory SDK for Java. + +An LDAPException contains the following information: + +The LDAP result code for the error that occurred + +A message that contains any additional information about the +error from the server + +An error can occur when an entry specified by a DN cannot be found. +The LDAPException then also contains the DN of the +closest matching entry that can be found. + +To get information from the LDAPException, use +one of the following methods: +To get the string representation of the exception, use the +toString method. +To get the LDAP result code, use the getLDAPResultCode method. + +To get any additional information sent by the server, use +the getLDAPErrorMessage method. +To get the closest matching DN in cases where your client +specified a DN to a nonexistent entry, use the getMatchedDN method. + + +To get the error message describing the LDAP result code, use the +errorCodeToString method, as described in Getting the Error Message. +The following section of code gets and prints information about an +LDAPException. +try { +    /* Attempt to perform an LDAP operation here. */ +} catch (LDAPException e) { +    /* Get and print the result code and any other info. */ +    int resultCode = e.getLDAPResultCode(); +    String serverInfo = e.getLDAPErrorMessage(); +    System.out.println("LDAP Result Code: " + resultCode); +    if (serverInfo != null) { +        System.out.println("Additional Info: " + serverInfo); +    } +    /* +     * If the exception was returned because an entry was + * not found, print the DN of the closest entry found. +     */ +    switch (resultCode) { +    case LDAPException.NO_SUCH_OBJECT: +    case LDAPException.ALIAS_PROBLEM: +    case LDAPException.INVALID_DN_SYNTAX: +    case LDAPException.ALIAS_DEREFERENCING_PROBLEM: +        String matchedDN = e.getMatchedDN(); +        if (matchedDN != null) { +            System.out.println("Closest Entry: " + matchedDN); +        } +        break; +    default: +        break; +    } +} + +Getting the Error Message + +LDAP result code +string description for + +To get the error message for an LDAP result code, use the errorCodeToString + method. +try { +    /* Attempt to perform an LDAP operation here. */ +} catch (LDAPException e) { +    /* Get and print the error message. */ +    int resultCode = e.getLDAPResultCode(); +    System.out.println("Error: " + e.errorCodeToString(resultCode)); +} +Error messages corresponding to each LDAP result code are located either +inside the ldapjdk.jar file or under another directory +in your CLASSPATH, in a properties file named netscape/ldap/errors/ErrorCodes.props + or netscape/ldap/errors/ErrorCodes_locale.props +. locale can be a two-letter version +of the locale, such as de, fr, or +ja, or it can be a full version of the locale, such as en_US. + +When you invoke the errorCodeToString method of an +LDAPException, the method retrieves the error message string for +the specified locale. If no locale is specified, the method retrieves the +default locale from the properties file. The errorCodeToString method +looks for locale-specific properties files in the following order, retrieving +the first property that is found: +netscape/ldap/error/ErrorCodes_language_ +country.props +netscape/ldap/error/ErrorCodes_language.props +netscape/ldap/error/ErrorCodes.props + + +Handling Referrals With &DirectorySDKForJava; + +referrals + +An LDAP server can receive a request for a DN that is not under its +directory tree. The server can then refer clients to another LDAP server that +might contain that DN. The response is known as a referral. +This section explains how to set up your LDAP client to handle referrals automatically. + +Understanding Referrals + +Suppose an LDAP server has a directory that starts under dc=example,dc=com +. Your client might send the server a request to modify the entry +with the DN uid=bjensen,ou=People,o=example.com. The entry +is not under dc=example,dc=com. One of the following can +occur. +If the server is not configured to send a referral, an +LDAPException is returned with the LDAP result code LDAPException.NO_SUCH_OBJECT +. +If the server is configured to refer you to another LDAP server, +the server sends a referral back to your client. + +Depending on how your LDAP client is configured, one of the following +can occur: +If your client handles referrals automatically, your client +connects to the LDAP server specified in the referral and requests to modify +the entry. The client binds anonymously to that server. To bind as a specific +user, refer to Enabling or Disabling +Referral Handling. +If your client does not handle referrals automatically, an +LDAPReferralException is returned. You can get the LDAP URL specified +in the referral by catching the exception, and then invoking the getURLs + method. + +By default, clients built with &DirectorySDKForJava; are configured +to follow referrals automatically. + +Another concept that is similar to a referral is a search reference. +A search reference is an entry with the object class +referral. The ref attribute of this object contains +an LDAP URL that points to another LDAP server. +When your client searches a subtree of the directory that contains search +references, the server returns a mix of matching entries and search references. +As you iterate through the enumeration of search results, you can encounter +a search reference although your client does not handle referrals automatically. +An LDAPReferralException is then returned. +Enabling or Disabling Referral Handling + +referrals +handling automatically + +By default, clients built with &DirectorySDKForJava; automatically +follow referrals to other servers. + +To change the way your client handles referrals, use one of two methods. +Use the setOption method of the LDAPConnection object +to change the behavior for all LDAP operations. Alternatively, use the setReferrals + method of the LDAPConstraints object to +change the behavior for a specific search request. +To prevent the client from automatically following referrals, +pass LDAPv3.REFERRALS and false as arguments +to the setOption method. Alternatively, pass false as +the argument to the setReferrals method. +To enable the client to follow referrals automatically again, +pass LDAPv3.REFERRALS and true as arguments +to the setOption method. Alternatively, pass true as +the argument to the setReferrals method. + + +Limiting Referral Hops + +referrals +specifying maximum hops + +You can specify the maximum number of referral hops that should be followed +in a sequence of referrals. You can set the preference for the connection. +You can also set the maximum as a constraint for specific search operations. +The maximum is called the referral hop limit. +For example, suppose you set a limit of two referral hops. If LDAP server +A refers to server B, B to C, and C to D, your client is being referred three +times in a row. Your client does not follow the referral to LDAP server D +because this referral exceeds the referral hop limit. +If the referral hop limit is exceeded, an LDAPReferralException is +returned. +To set the referral hop limit, use either of two methods. Use the +LDAPv3.REFERRALS_HOP_LIMIT preference with the setOption method +of the LDAPConnection object to change the behavior +for all LDAP operations. Alternatively, use the setHopLimit method +of the LDAPConstraints object to change the behavior +for a specific search request. +By default, the maximum number of referral hops is 10. +Binding When Following Referrals + +authentication +authenticating during referrals + +referrals +authenticating + +If the connection is set up so that referrals are always followed, the +LDAP server that you connect to can refer you to another server. By default, +the client binds anonymously such that no user names or passwords are specified +when following referrals. +To authenticate to the LDAP server that you are referred to, specify +how to get the DN and password for authentication. You need to define a class +that implements the LDAPRebind interface. Then, specify +an object of this new class with either of two methods. Use the LDAPv3.REFERRALS_REBIND_PROC + preference with the setOption method of the +LDAPConnection object to set the preference for all LDAP operations. +Alternatively, use the setRebindProc method of the +LDAPConstraints object to change the behavior for a specific search +request. +The LDAPRebind interface specifies a getRebindAuthentication + method that returns an LDAPRebindAuth object. +The getRebindAuthentication method and the LDAPRebindAuth + object that the method returns are used to get the DN and password +for authentication. + +The following steps explain how this works. +The LDAP server sends a referral back to the client. The referral +contains an LDAP URL that points to another LDAP server. +The client creates a new LDAPConnection object. + +The client connects to the host and port specified in the +LDAP URL. +You can use the getRebindProc method to +find your object, the object that implements the LDAPRebind interface. +The client then invokes the getRebindAuthentication method, +passing in the host and port specified in the LDAP URL. +The getRebindAuthentication method in your +object returns an LDAPRebindAuth object. + +The client invokes the getDN and getPassword + methods of the returned LDAPRebindAuth object +to get the DN and password to use for authentication. +The client invokes the authenticate method of the LDAPConnection + object and passes the DN and password to authenticate to the +server. + + +Basically, you need to define the following: +A class that implements the LDAPRebind interface + +A getRebindAuthentication that takes a +host name and port number. +This method creates an LDAPRebindAuth object +that specifies the DN and password to use for authentication. + + + +Using In-Memory Cache With &DirectorySDKForJava; + +cache + +in-memory cache + +connection +caching results + +LDAP session +caching results + +search results +caching + +&DirectorySDKForJava; includes an LDAPCache class +that allows you to create an in-memory cache of search results for your client. +When you send a search request, you receive results. The search request and +its results are then cached. The next time your client issues the same search +request, the results are read from the cache. +How the Cache Operates + +Each item in the cache represents a search request and its results. +When you create the cache, you can specify the maximum size of the cache. +You can also specify the maximum amount of time that an item can be cached. +When an item's age exceeds that time limit, the item is removed +from the cache. The cache is checked once a minute for expired items. + +If adding a new item causes the cache to exceed its maximum +size, items are removed from the cache. Removal makes space for the new item. +Items are removed on a first in, first out basis. + + +Each item is uniquely identified by the search criteria, which includes +the following: +Host name and port number of the LDAP server +Base DN of the search +Search filter +Scope of the search +Attributes to be returned in the search results + +DN used to authenticate the client when binding to the server + +LDAP v3 controls specified in the search request + + +After a search request is cached, if your client performs the same search +again, the results are read from the cache instead of from the server. +Note that if any part of a search request differs from a cached search +request, the results are read from the server. For example, a different DN +might be used when authenticating to the server. Alternatively, the search +request might specify that a different set of attributes should be returned. +In either case, the results are not read from the cache. Instead, the search +request is sent to the server. +Finally, when creating the cache, you can specify a list of the base +DNs in search requests that you want to cache. For example, if you specify +ou=People,dc=example,dc=com as a base DN to cache, your client caches +search requests where the base DN is ou=People,dc=example,dc=com. + +Setting Up an In-Memory Cache + +cache +setting up + + +To set up a cache for your connection, do the following: +Construct a new LDAPCache object that +represents the cache. +Invoke the setCache method of an LDAPConnection + object to associate the cache with the connection. + + +For example, the following section of code creates a cache with the +maximum size of 1 Mbyte. Items in the cache expire and are automatically removed +after one hour. +try { +    LDAPConnection ld = new LDAPConnection(); + +    /* Create a cache for the connection */ +    int MAX_TIME_CACHED = 3600; // 3600 seconds == 1 hour +    int MAX_SIZE = 1000000;     // 1000000 bytes == 1 MB +    LDAPCache myCache = new LDAPCache(MAX_TIME_CACHED, MAX_SIZE); +    ld.setCache(myCache); + +    /* Connect to server */ +    ld.connect("ldap.example.com", LDAPv3.DEFAULT_PORT); + +    /* +     * Perform operations... +     */ +} catch (LDAPException e) { +    System.out.println("Error: " + e.toString()); +} + +Caching Requests by Base DN +If you do not want all search requests cached, specify an array of base +DNs for search requests to cache in the LDAPCache constructor. + +For example, the following section of code constructs a cache that only +tracks search requests that specify the base DNs ou=People,dc=example,dc=com + and ou=Groups,dc=example,dc=com. +/* Create a cache for the connection */ +int MAX_TIME_CACHED = 3600; +int MAX_SIZE = 1000000; +String [] BASE_DN_CACHED = {"ou=People,dc=example,dc=com", +    "ou=Groups,dc=example,dc=com"}; +LDAPCache myCache = new LDAPCache(MAX_TIME_CACHED, MAX_SIZE, +    BASE_DN_CACHED); + +Sharing a Cache Among Connections + +cache +sharing between connections + +You can also share the same in-memory cache among different connections. + +Invoke the getCache method of an LDAPConnection + object to get the LDAPCache object that +is used. +Invoke the setCache method of a different +LDAPConnection object to associate the retrieved LDAPCache + object with the connection. + +When you clone an LDAPConnection object, the +new object automatically shares the same LDAPCache object +with the original object. +Flushing the Cache + +cache +flushing + +To flush items from the cache, invoke the flushEntries method +of the LDAPCache object. You can flush either selected +items or all items from the cache. + +To flush selected items from the cache, specify the base DN +of the search requests that you want to flush. Specify a DN and search scope +as arguments to the flushEntries method. If the base DN +of a cached search request falls within the scope you specified, the search +request is flushed from the cache. + +For example, the following section of code flushes selected search requests +from the cache. If the base DN of a search request falls under the ou=People,dc=example,dc=com + subtree, the item is removed from the cache. +LDAPCache myCache; + +/* Perform search requests... */ + +/* + * Flush search requests with base DNs under + * ou=People,dc=example,dc=com. + */ +myCache.flushEntries("ou=People,dc=example,dc=com", +    LDAPConnection.SCOPE_SUB); + +To flush all items from the cache, pass null as +the first argument of the flushEntries method: + + +myCache.flushEntries(null, 0); + +Getting Cache Statistics + +cache +getting statistics + + +You can invoke the following methods of the LDAPCache object +to get statistics on the cache. +To get the total amount of available space in bytes that are +left in the cache, invoke the getAvailableSize method. + +To get the array of base DNs of the search requests to be +cached, invoke the getBaseDNs method. +To get the total number of items that have been flushed from +the cache, not including items flushed when invoking the flushEntries method, +invoke the getNumFlushes method. +To get the maximum size of the cache in bytes, invoke the +getSize method. +To get the maximum amount of time that an item can be cached +in seconds, get the getTimeToLive method. + + +You can also get a running count of the number of requests that access +the cache. +To get the total number of requests for retrieving items from +the cache, invoke the getTotalOperation method. + +To get the total number of requests that retrieved an item +from the cache, invoke the getNumHits method. + +To get the total number of requests that failed to find and +retrieve an item from the cache, invoke the getNumMisses method. + + +For example, the following section of code gets and prints cache statistics. + +LDAPConnection ld; + +if ((ld != null) && ld.isConnected()) { +    LDAPCache connCache = ld.getCache(); +    if (connCache != null) { +        System.out.println("Cache size:\t\t" + +            connCache.getSize()/1000 + " kbytes"); +        System.out.println("Available:\t\t" + +            connCache.getAvailableSize()/1000 + " kbytes"); +        System.out.println( "Maximum age:\t\t" + +            connCache.getTimeToLive()/1000 + " seconds"); +        System.out.println("Total hits:\t\t" + +            connCache.getNumHits() + " hits" ); +        System.out.println("Total misses:\t\t" + +            connCache.getNumMisses() + " misses" ); +        System.out.println("Total requests:\t\t" + +            connCache.getTotalOperations() + " requests"); +    } else { +        System.out.println( +            "No cache associated with the connection."); +    } +} + + +Cloning a Connection With &DirectorySDKForJava; + +connection +cloning + +You can create several LDAPConnection objects +that share a single physical network connection to the LDAP server by invoking +the LDAPConnection.clone method. + +Clones have the following properties: +If you clone an object before a connection is made to the +server, the cloned object does not share the same connection as the original +object. +Each clone can disconnect from the server without affecting +the connection for the other clones. The network connection remains in an +open state until all clones have either disconnected or gone out of scope. + +If the clone disconnects or reconnects, the clone is completely +dissociated from the source object and other clones. +A cloned LDAPConnection object has +a separate set of session preferences and constraints. In other words, the +clone is associated with its own LDAPSearchConstraints object. +Changes to an option or to a search constraint only affect requests issued +using that object.For example, suppose an LDAPConnection object +allows a maximum of 100 results to be returned from a search. If you clone +an LDAPConnection object, you can change the maximum +number of results in the clone from 100 to 200. Yet, the initial object still +allows only 100 results to be returned. +All clones are authenticated to the server as the same user. +If you authenticate again to the server as a different user, the current clone +is disconnected. The clone connects separately to the server. The LDAPConnection + object is no longer a clone of another LDAPConnection object. + + + +Manipulating Distinguished Names With &DirectorySDKForJava; + +distinguished names +manipulating + +A distinguished name (DN) uniquely identifies an entry in the directory +tree. You can get the DN for an entry as explained in Getting Distinguished +Names. Alternatively, you can specify a DN to read an entry from the +directory as explained in +Reading an Entry With Directory SDK for Java. &DirectorySDKForJava; includes +a utility class, LDAPDN, that provides +methods for manipulating DNs. +If you want to access individual components of a distinguished name +or a relative distinguished name, invoke the LDAPDN.explodeDN method +or the LDAPDN.explodeRDN method. +Both methods return an array of String objects +that represent the individual components of the distinguished name. +You can specify whether or not you want the names of the components +included in the array by using the notypes parameter. + +Set notypes to false if +you want to include component attribute types in the array. +LDAPDN.explodeDN("uid=bjensen,ou=People,dc=example,dc=com", false); + +The method returns the array {"uid=bjensen", "ou=People", "dc=example", +"dc=com"}. +Set notypes to true if +you do not want component attribute types returned in the array. +LDAPDN.explodeDN("uid=bjensen,ou=People,dc=example,dc=com", true); + +The method returns the array {"bjensen", "People", "example", +"com"}. + + + diff --git a/mozilla/directory/docs/ldapjdk/jdk-comparing.sgm b/mozilla/directory/docs/ldapjdk/jdk-comparing.sgm new file mode 100644 index 00000000000..44ba4c4a212 --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/jdk-comparing.sgm @@ -0,0 +1,123 @@ + +Comparing Attribute Values With &DirectorySDKForJava; + +attributes +comparing values + +comparing attribute values + +This chapter explains how to compare the value of an attribute in an +entry against a specified value. + +This chapter covers the following topics: +Specifying the +Attribute and Value With Directory SDK for Java +Performing the Comparison +With Directory SDK for Java +Example Attribute Value +Comparison With Directory SDK for Java + +The LDAP Java classes allow you to compare a specified value against +the value of an entry in the directory. For example, you can check to see +if the mail attribute of an entry contains the value +bjensen@example.com. + +To compare a specified value against an attribute of an entry in the +directory, you need to follow this general procedure. +Specify the name of the attribute that you want to check and +the value that you want to use for comparison. +Use the distinguished name of the entry to find the entry +in the directory. The entry that is found is then used to perform the comparison. + + +Specifying the Attribute and +Value With &DirectorySDKForJava; +Use an LDAPAttribute object to specify the name +of the attribute to check. Also use the object to specify the value to use +in the comparison. +LDAPAttribute attr = new LDAPAttribute("mail", "bjensen@example.com"); + + +Performing the Comparison With &DirectorySDKForJava; +To perform the comparison, use the compare method +of the LDAPConnection object. Specify the distinguished +name of the entry that you want to compare. The method returns true if +the attribute contains the specified value. +try { + LDAPConnection ld = new LDAPConnection(); + ld.connect("localhost", LDAPv3.DEFAULT_PORT); + LDAPAttribute attr = new LDAPAttribute("mail", "bjensen@example.com"); + if (ld.compare("uid=bjensen,ou=People,dc=example,dc=com", attr)) { + System.out.println("Found a match."); + } +} catch (LDAPException e) { + System.err.println("Error:" + e.toString()); +} + +Example Attribute Value Comparison With &DirectorySDKForJava; +The following example compares values for the objectclass attribute +with values on Barbara Jensen's entry. +import netscape.ldap.*; +import java.util.*; + +public class Compare { + public static void main(String[] args) { + try { + UserArgs userArgs = new UserArgs("Compare", args, false); + LDAPConnection ld = new LDAPConnection(); + ld.connect(userArgs.getHost(), userArgs.getPort()); + + /* Entry to compare */ + String ENTRYDN = "uid=bjensen,ou=People,dc=example,dc=com"; + + /* Compare the value "person" and the attr. "objectclass" */ + LDAPAttribute attr = + new LDAPAttribute("objectclass", "person"); + boolean ok = ld.compare(ENTRYDN, attr); + reportResults(ok, attr); + + /* Compare the value "xyzzy" and the attr. objectclass */ + attr = new LDAPAttribute("objectclass", "xyzzy"); + ok = ld.compare(ENTRYDN, attr); + reportResults(ok, attr); + + ld.disconnect(); + } catch(LDAPException e) { + System.out.println("Error: " + e.toString()); + } + } + + private static void reportResults(boolean ok, LDAPAttribute attr) { + String result; + if (ok) { + result = new String(); + } else { + result = new String("not "); + } + Enumeration en = attr.getStringValues(); + if (en != null) { + String val = (String)en.nextElement(); + System.out.println( + "The value *" + val + "* is " + result + + "contained in the " + attr.getName() + " attribute."); + } + } +} + + diff --git a/mozilla/directory/docs/ldapjdk/jdk-controls.sgm b/mozilla/directory/docs/ldapjdk/jdk-controls.sgm new file mode 100644 index 00000000000..78d63170d1d --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/jdk-controls.sgm @@ -0,0 +1,940 @@ + +LDAP Controls With &DirectorySDKForJava; + +This chapter explains how LDAP controls work and how to use the LDAP +controls. + +This chapter covers the following topics: +How LDAP Controls Work +With Directory SDK for Java +Using Controls in the LDAP +Java Classes +Determining the Controls Supported the Server With Directory SDK for Java +Using the Server-Side Sorting +Control With Directory SDK for Java +Using the Persistent Search +Control With Directory SDK for Java +Using the Entry Change +Notification Control With Directory SDK for Java +Using the Virtual List Control With Directory SDK for Java +Using the Manage DSA +IT Control With Directory SDK for Java +Using Password Policy Controls +With Directory SDK for Java +Using the Proxied Authorization +Control With Directory SDK for Java + + +How LDAP Controls Work With &DirectorySDKForJava; +LDAP v3 allows clients and servers to use controls as a mechanism for +extending an LDAP operation. A control is a way to specify additional information +as part of a request and a response. +For example, a client can send a control to a server as part of a search +request. The control indicates that the server should sort the search results +before sending the results back to the client. +Servers can also send controls back to clients. For example, the server +can send a control back to a client during the authentication process. The +control can indicate that the client password has expired. The control can +alternatively indicate that the client password is going to expire. + +A control specifies the following information: +A unique object identifier (OID) +An indication of whether the control is critical to the operation + +Optional data related to the control, such as the server-side +sorting control, where attributes used for sorting search results are needed + + +The OID identifies the control. If you plan to use a control, you need +to make sure that the server supports the control. Refer to Determining the Controls Supported the Server With Directory SDK for Java for instructions. + +When your client includes a control in a request for an LDAP operation, +the server can respond in one of the following ways: +If the server supports this control and if the control is +appropriate, the server should use the control when performing the operation. + + + +If the server does not support the control type or if the control is +not appropriate, the server should do one of the following: +If the control is marked as critical to the operation, the +server should not perform the operation. Instead, the server should send an +unavailable critical extension result code. When receiving this +result code, your client returns an LDAPException with +the result code LDAPException.UNAVAILABLE_CRITICAL_EXTENSION. + +If the control is marked as not critical to the operation, +the server should ignore the control. The server should proceed to perform +the operation. + + + +Servers can also send controls back to clients. + +Two types of controls exist: +Server controls can be included in requests sent by clients +and in responses sent by servers. +Client controls affect the behavior of the LDAP Java classes +only and are never sent to the server.&DirectorySDKForJava; does +not support client controls. + + +Using Controls in the LDAP Java Classes +This section describes how controls are implemented in the LDAP Java +classes. This section also describes which methods to use to create, send, +and parse data from LDAP controls. +In the LDAP Java classes, a control is represented by an object of the +LDAPControl class. + +To include a control in a request, do the following: +Invoke the getSearchConstraints method +of the LDAPConnection object to get a clone of +LDAPSearchConstraints for this connection. +Invoke the setServerControls method of +the cloned constraints object, passing in the LDAPControl object +that represents the control to include. +Invoke the appropriate method to perform the LDAP operation, +passing in the constraints object.For example, if you are performing +a search, invoke the search method. Pass the search constraints +as an argument. +You can also include controls by invoking the setServerControls method +for the default set of search constraints. Alternatively, invoke the setOption + method to set the LDAPv3.SERVERCONTROLS option. +These controls are sent to the server with every request, however. In general, +controls tend to be specific to a type of operation. Include a control in +a request only for the operation to which the control applies. +You can then retrieve data from the returned controls through accessor +methods in the LDAPControl object. +Determining the Controls Supported the +Server With &DirectorySDKForJava; +LDAP v3 states that servers should list any controls that servers support +in the supportedControl attribute in the root DSE. The +following OIDs have corresponding constants that are defined in the LDAP Java +classes. + +1.2.840.113556.1.4.473 +netscape.ldap.controls.LDAPSortControl.SORTREQUEST +For instructions on using this control, refer to Using the Server-Side Sorting Control With Directory SDK for Java. + + +2.16.840.1.113730.3.4.2 +netscape.ldap.LDAPControl.MANAGEDSAIT +For instructions on using this control, refer to Using the Manage DSA +IT Control With Directory SDK for Java. + + +2.16.840.1.113730.3.4.3 +netscape.ldap.controls.LDAPPersistSearchControl.PERSISTENTSEARCH +For instructions on using this control, refer to Using the Persistent Search +Control With Directory SDK for Java. + + +2.16.840.1.113730.3.4.4 +netscape.ldap.LDAPControl.PWEXPIRED +For instructions on using this control, refer to Using Password Policy Controls +With Directory SDK for Java. + + +2.16.840.1.113730.3.4.5 +netscape.ldap.LDAPControl.PWEXPIRING +For instructions on using this control, refer to Using Password Policy Controls +With Directory SDK for Java. + + +2.16.840.1.113730.3.4.9 +netscape.ldap.controls.LDAPVirtualListControl.VIRTUALLIST +For instructions on using this control, refer to Using the Virtual List Control With Directory SDK for Java. + + +2.16.840.1.113730.3.4.12 +netscape.ldap.controls.LDAPProxiedAuthControl.PROXIEDAUTHREQUEST +For instructions on using this control, refer to Using the Proxied Authorization Control With Directory SDK for Java. + + + +The following example searches for the root DSE. Then the example prints +the values of the supportedControl attribute. +import netscape.ldap.*; +import netscape.ldap.controls.*; +import java.util.*; + +public class ListCtrl { + public static void main(String[] args) { + + /* Hashtable mapping OIDs of controls to a description */ + Hashtable knownControls = new Hashtable(); + knownControls.put(LDAPSortControl.SORTREQUEST, + "Sort control"); + knownControls.put(LDAPControl.MANAGEDSAIT, + "ManageDsaIT control"); + knownControls.put(LDAPPersistSearchControl.PERSISTENTSEARCH, + "Persistent Search control"); + knownControls.put(LDAPControl.PWEXPIRED, + "Password Expiration Notification control"); + knownControls.put(LDAPControl.PWEXPIRING, + "Password Expiration Warning control"); + knownControls.put(LDAPVirtualListControl.VIRTUALLIST, + "Virtual List View control"); + knownControls.put(LDAPProxiedAuthControl.PROXIEDAUTHREQUEST, + "Proxied Authorization control"); + + try { + UserArgs userArgs = new UserArgs("ListCtrl", args, false); + LDAPConnection ld = new LDAPConnection(); + ld.connect(userArgs.getHost(), userArgs.getPort()); + + /* Retreive the list of supported controls from the DSE. */ + String getAttrs[] = {"supportedControl"}; + LDAPSearchResults res = ld.search("", LDAPv3.SCOPE_BASE, + "(objectclass=*)", getAttrs, false); + LDAPEntry DSE = (LDAPEntry)res.nextElement(); + LDAPAttributeSet findAttrs = DSE.getAttributeSet(); + Enumeration enumAttrs = findAttrs.getAttributes(); + + while (enumAttrs.hasMoreElements()) { + LDAPAttribute anAttr = + (LDAPAttribute)enumAttrs.nextElement(); + String attrName = anAttr.getName(); + System.out.println(attrName); + + Enumeration enumVals = anAttr.getStringValues(); + if (enumVals == null) { + System.out.println("\tNo values."); + continue; + } + while (enumVals.hasMoreElements()) { + String aVal = (String)enumVals.nextElement(); + /* + * Each value should be the OID of a control. + * Look up its description in the hash table. + */ + String aDesc = (String)knownControls.get(aVal); + if (aDesc != null) { + System.out.println("\t" + aDesc+ " (" + aVal + ")"); + } else { + System.out.println("\t" + aVal); + } + } + } + + ld.disconnect(); + } catch(LDAPException e) { + System.out.println("Error: " + e.toString()); + } + } +} + +Using the Server-Side Sorting Control With &DirectorySDKForJava; + +search results +sorting + +sorting search results + +The control represented with the OID that corresponds to the constant +netscape.ldap.LDAPControl.SORTREQUEST is a server-side sorting +control. The server-side sorting control is defined in RFC 2891. +When you send a search request with this control to the server, the server +should sort the results before sending them back to you. +Specifying the Server-Side Sort Order +With Directory SDK for Java +To specify the sort order of the results, construct one or more +LDAPSortKey objects. Each object represents a sort key that is +generated from a string in the following format: +[-]attrName[:matchingRuleOID +] +Here, attrName represents the name of the +attribute to use for sorting. matchingRuleOID represents +the optional OID of the matching rule to use for sorting. The optional minus +sign (-) indicates that the results should be sorted in +reverse order for that attribute. +For example, the following string specifies that results should be sorted +by first name (givenname) in descending order: +-givenname +Pass this string to the LDAPSortKey constructor +to create a sort key: +LDAPSortKey reverseSortByFirstName = new LDAPSortKey("-givenname"); + +To sort by more than one attribute, construct more than one LDAPSortKey + object and create an array of the objects. +For example, suppose you want to sort the result by last name (sn) +in ascending order. If two or more entries have the same last name, you want +to sort the result by first name (givenname) in ascending +order. To specify this sort order, you construct two LDAPSortKey objects. +Then create an array: +LDAPSortKey sortByLastName = new LDAPSortKey("sn"); +LDAPSortKey sortByFirstName = new LDAPSortKey("givenname"); +LDAPSortKey[] sortOrder = { sortByLastName, sortByFirstName }; + +Creating the Server-Side Sorting Control +With &DirectorySDKForJava; +Next, to create the server-side sorting control, construct a new +LDAPSortControl object. Pass the LDAPSortKey object, +or the array of LDAPSortKey objects, to the LDAPSortControl + constructor. +In the constructor, you can also specify whether or not the control +is critical to the search operation. The control can be marked as critical, +but the server cannot sort the results. If the situation occurs, the server +should not send back any entries. +For example, the following section of code creates a server-side sorting +control. Also, the code specifies that the control is critical to the search +operation: +LDAPSortKey sortOrder = new LDAPSortKey("-givenname"); +LDAPSortControl sortCtrl = new LDAPSortControl(sortOrder, true); + +Performing the Server—Side Sort +With &DirectorySDKForJava; + +To specify that you want the server to sort the results, do the following: +Get a clone of LDAPSearchConstraints for +the current connection by invoking the getSearchConstraints method +of the LDAPConnection object. +Invoke the setServerControls method for +the copied LDAPSearchConstraints object, and pass in +the LDAPSortControl object that you have constructed. + +Invoke the search method of the LDAPConnection + object, passing in the LDAPSearchConstraints object. +The server returns a result for the search operation and a response +control. The response control indicates the success or failure of the sorting. + +Invoke the getResponseControls method of +the LDAPSearchResults object to retrieve any controls +sent back by the server in response to the search.Response controls +are passed back as an array of LDAPControl objects. + +Examine the type of each returned control. + +If a control is an instance of LDAPSortControl, +you can read the result code for the sorting operation with the getResultCode + method. +If the sorting operation failed, the server can also return the name +of the attribute that caused the failure. You can read the name of this attribute +with the getFailedAttribute method. +The server can return the following result codes that apply to the sorting +operation. + +LDAPException.ADMIN_LIMIT_EXCEEDED +Too many entries exist for the server to sort. + + +LDAPException.BUSY +The server is too busy to sort the results. + + +LDAPException.INAPPROPRIATE_MATCHING +The sort key list specifies a matching rule that is not recognized +or appropriate. + + +LDAPException.INSUFFICIENT_ACCESS_RIGHTS +The server did not send the sorted results because the client +has insufficient access rights. + + +LDAPException.NO_SUCH_ATTRIBUTE +The sort key list specifies an attribute that does not exist. + + +LDAPException.OPERATION_ERROR +An internal server error occurred. + + +LDAPException.OTHER +This general result code indicates that the server failed +to sort the results for a reason other than the results listed here. + + +LDAPException.STRONG_AUTH_REQUIRED +The server refused to send back the sorted search results +because the server requires that you use a stronger authentication method. + + +LDAPException.SUCCESS +The results were sorted successfully. + + +LDAPException.TIME_LIMIT_EXCEEDED +The maximum time allowed for a search was exceeded before +the server finished sorting the results. + + +LDAPException.UNWILLING_TO_PERFORM +The server is unable to sort the results. + + + + +Interpreting the Server-Side Sort +Results With &DirectorySDKForJava; +The following table shows the kinds of results to expect from the LDAP +server under different conditions. +Server +Responses to Sort Controls + + + + +Supports sort control? + +Sort control marked critical? + +Any other conditions? + +Results From LDAP Server + + + + + +Server does not support sort control. + +Control is not marked as critical. + +Not applicable + +The server ignores the sorting control. The server returns the entries +unsorted. + + + +Server does not support sort control. + +Control is marked as critical. + +Not applicable + +The server does not send back any entries. + + + +Server does support sort control. + +Control is not marked as critical. + +The server cannot sort the results with the specified sort key list. + + + +The server returns the entries unsorted. +The server sends back the sorting response control. The response +control specifies the result code of the sort attempt and, optionally, the +attribute type that caused the error. + + + + + +Server does support sort control. + +Control is marked as critical. + +The server cannot sort the results with the specified sort key list. + + + +The server does not return any entries. +The server sends back the sorting response control. The response +control specifies the result code of the sort attempt and, optionally, the +attribute type that caused the error. + + + + + +Server does support sort control. + +has no effect on results + +The search failed. + + +The server returns a result code for the search operation. + +The server does not send back the sorting response control. + + + + + + +Server does support sort control. + +has no effect on results + +The server successfully sorted the entries. + + +The server returns the entries in sorted order. + +The server sends back the sorting response control, which +specifies the result code of the sort attempt as LDAPException.SUCCESS +. + + + + + +
+
+Example of Using Server-Side Sorting +With &DirectorySDKForJava; +The following sample program uses the server-side sorting control to +get a list of all users in the directory. The list is sorted in ascending +order by last name, then in descending order by first name. +import netscape.ldap.*; +import netscape.ldap.controls.*; +import java.util.*; + +public class SrchSort { + public static void main(String[] args) { + try { + UserArgs userArgs = new UserArgs("SrchSort", args, false); + LDAPConnection ld = new LDAPConnection(); + ld.connect(userArgs.getHost(), userArgs.getPort()); + ld.authenticate(3, null, null); // Anonymous bind, LDAP v3 + + String filter = "sn=Jen*"; + String baseDN = "ou=People,dc=example,dc=com"; + String[] attrs = {"sn", "givenname"}; + + /* Sort by last name, then in reverse by first name. */ + LDAPSortKey sortByLastName = new LDAPSortKey("sn"); + LDAPSortKey sortByFirstName = new LDAPSortKey("-givenname"); + LDAPSortKey[] sortOrder = {sortByLastName, sortByFirstName}; + + LDAPSortControl sortCtrl = new LDAPSortControl(sortOrder, true); + LDAPSearchConstraints cons = ld.getSearchConstraints(); + cons.setServerControls(sortCtrl); + + /* Perform the search using the control. */ + LDAPSearchResults res = ld.search(baseDN, LDAPv3.SCOPE_SUB, + filter, attrs, false, cons); + + /* Display the results. */ + System.out.println("Sorted results from server"); + System.out.println("=========================="); + while (res.hasMoreElements()) { + LDAPEntry resEntry = null; + try { + resEntry = res.next(); + } catch (LDAPReferralException e) { + continue; // Skip referrals for now. + } catch (LDAPException e) { + System.err.println("Error:" + e.toString()); + continue; + } + + LDAPAttributeSet resAttrs = resEntry.getAttributeSet(); + Enumeration enumAttrs = resAttrs.getAttributes(); + + while (enumAttrs.hasMoreElements()) { + LDAPAttribute attr = + (LDAPAttribute)enumAttrs.nextElement(); + Enumeration enumVals = attr.getStringValues(); + if (enumVals == null) { + System.out.println("\tNo values."); + continue; + } + while (enumVals.hasMoreElements()) { + String val = (String)enumVals.nextElement(); + System.out.print(val); + } + System.out.print(", "); + } + System.out.println(""); + } + + /* Check whether the server sent back a control. */ + LDAPControl[] returnedControls = res.getResponseControls(); + if (returnedControls != null) { + for (int i = 0; i < returnedControls.length; ++i) { + if (!(returnedControls[i] instanceof LDAPSortControl)) { + continue; + } + LDAPSortControl sortRsp = + (LDAPSortControl)returnedControls[i]; + int resultCode = sortRsp.getResultCode(); + + /* Check the result for errors. */ + if (resultCode != 0) { + System.err.println("Result code: " + resultCode); + System.err.println( + LDAPException.errorCodeToString(resultCode)); + + /* Report attribute that caused the failure. */ + String failedAttr = sortRsp.getFailedAttribute(); + if (failedAttr != null) { + System.err.println("Failed on: " + failedAttr); + } else { + System.err.println("Server did not indicate " + + "which attribute caused sorting to fail."); + } + } + } + } + + ld.disconnect(); + } catch(LDAPException e) { + System.out.println("Error: " + e.toString()); + } + } +} + +
+Using the Persistent Search Control With &DirectorySDKForJava; + +persistent searches + +The control represented with the OID that corresponds to the constant +netscape.ldap.LDAPControl.PERSISTENTSEARCH is a persistent search +control. A persistent search, an ongoing search operation, +allows your LDAP client to get notification of changes to the directory. +To use persistent searching for change notification, you create a persistent +search control that specifies the types of changes that you want to track. +You include the control in a search request. If an entry in the directory +is changed, the server determines if the entry matches the search criteria +in your request. The server also determines if the change is the type of change +that you are tracking. If both of the conditions are true, the server sends +the entry to your client. +You can use this control in conjunction with an entry change notification +control, as described in Using the Entry Change Notification Control +With Directory SDK for Java. +Creating the Persistent Search +Control With Directory SDK for Java + +To create a persistent search control, you construct a new LDAPPersistSearchControl + object. When invoking the LDAPPersistSearchControl constructor, +you can specify the following information: + + +The type of change you want to track. You can specify any of the following, +or any combination of the following, using a bitwise OR (|) +operator: +ADD indicates that you want to track added +entries. +DELETE indicates that you want to track +deleted entries. +MODDN indicates that you want to track +renamed entries. +MODIFY indicates that you want to track +modified entries. + + +A preference indicating whether you want the server to return +all entries that initially matched the search criteria +A preference indicating whether or not you want entry change +notification controls included with every modified entry returned by the server + + +This code excerpt shows an example of creating a persistent search control. + +/* Track all types of changes. */ +int op = LDAPPersistSearchControl.ADD | + LDAPPersistSearchControl.MODIFY | + LDAPPersistSearchControl.DELETE | + LDAPPersistSearchControl.MODDN; + +/* Return only entries that have changed. */ +boolean changesOnly = true; + +/* Return an entry change notification control. */ +boolean returnControls = true; + +/* Mark the control as critical. */ +boolean isCritical = true; + +/* Create the control. */ +LDAPPersistSearchControl persistCtrl = + new LDAPPersistSearchControl( + op, changesOnly, returnControls, isCritical); + +Performing the Persistent Search +With Directory SDK for Java + +To specify that you want to start a persistent search, do the following: +Get a clone of LDAPSearchConstraints for +the current connection by invoking the getSearchConstraints method +of the LDAPConnection object. +Invoke the setServerControls method for +the cloned LDAPSearchConstraints object, and pass in +the LDAPPersistSearchControl object that you have constructed. + +Invoke the search method of the LDAPConnection object, +passing in the LDAPSearchConstraints object.The +server returns entries that match as the entries change. If you specified +that you wanted an entry change notification control included with each entry, +you can get these controls from the server's results. For instructions, refer +to Using the +Entry Change Notification Control With Directory SDK for Java. + +To end the persistent search, invoke the abandon method +of the LDAPConnection object. Alternatively, invoke +the disconnect method to disconnect from the server. + +Example of Using the Persistent +Search Control With Directory SDK for Java +The following example performs a persistent search. The example receives +entry change notification controls from the server. +import netscape.ldap.*; +import netscape.ldap.controls.*; +import java.util.*; + +public class SrchPrst implements Runnable { + private static String [] cliArgs; + public static void main(String[] args) { + cliArgs = args; + /* Start up a new thread. */ + Thread th = new Thread(new SrchPrst(), "mainConn"); + th.start(); + System.out.println("Main thread started."); + } + + public void run() { + try { + UserArgs userArgs = new UserArgs("SrchPrst", cliArgs, true); + LDAPConnection ld = new LDAPConnection(); + ld.connect(userArgs.getHost(), userArgs.getPort()); + ld.authenticate(3, userArgs.getBindDN(),userArgs.getPassword()); + + /* Create the control and search constraints. */ + int op = LDAPPersistSearchControl.ADD | + LDAPPersistSearchControl.MODIFY | + LDAPPersistSearchControl.DELETE | + LDAPPersistSearchControl.MODDN; + boolean changesOnly = true; + boolean returnControls = true; + boolean isCritical = true; + LDAPPersistSearchControl persistCtrl = + new LDAPPersistSearchControl(op, changesOnly, + returnControls, isCritical); + LDAPSearchConstraints cons = ld.getSearchConstraints(); + cons.setServerControls(persistCtrl); + + /* Track changes on all entries. */ + String filter = "(objectclass=*)"; + String baseDN = "dc=example,dc=com"; + /* Start the search. */ + LDAPSearchResults res = + ld.search( + baseDN, LDAPv3.SCOPE_SUB, filter, null, false, cons); + + /* Loop through the results until finished. */ + while (res.hasMoreElements()) { + System.out.println("\n===== Changed Entry ====="); + LDAPEntry findEntry = res.next(); + LDAPAttributeSet findAttrs = findEntry.getAttributeSet(); + Enumeration enumAttrs = findAttrs.getAttributes(); + while (enumAttrs.hasMoreElements()) { + LDAPAttribute anAttr = + (LDAPAttribute)enumAttrs.nextElement(); + String attrName = anAttr.getName(); + System.out.println("\t" + attrName); + + Enumeration enumVals = anAttr.getStringValues(); + while (enumVals.hasMoreElements()) { + String aVal = (String)enumVals.nextElement(); + System.out.println("\t\t" + aVal); + } + } + + /* Get any entry change controls. */ + LDAPControl[] responseCtrls = res.getResponseControls(); + if (responseCtrls != null) { + for (int i=0; i < responseCtrls.length; i++){ + if (!(responseCtrls[i] instanceof + LDAPEntryChangeControl)) { + continue; + } + + LDAPEntryChangeControl entryCtrl = + (LDAPEntryChangeControl) responseCtrls[i]; + + /* Get information on the type of change */ + int changeType = entryCtrl.getChangeType(); + if (changeType != -1) { + System.out.print("Change made: "); + switch (changeType) { + case LDAPPersistSearchControl.ADD: + System.out.println("Added new entry."); + break; + case LDAPPersistSearchControl.MODIFY: + System.out.println("Modified entry."); + break; + case LDAPPersistSearchControl.DELETE: + System.out.println("Deleted entry."); + break; + case LDAPPersistSearchControl.MODDN: + System.out.println("Renamed entry."); + break; + default: + System.out.println( + "Unknown change type."); + break; + } + } + + /* Get the change log number, if present */ + int changeNumber = entryCtrl.getChangeNumber(); + if (changeNumber != -1) { + System.out.println( + "Change log number: " + changeNumber); + } + + /* Get the previous DN of the entry, if + a rename operation was performed. */ + String oldDN = entryCtrl.getPreviousDN(); + if (oldDN != null) { + System.out.println("Previous DN: " + oldDN); + } + } + System.out.println("\n"); + } + } + } catch(LDAPException e) { + System.out.println("Error: " + e.toString()); + } + } +} + + +Using the Entry Change Notification +Control With &DirectorySDKForJava; +The control represented with the OID that corresponds to the constant +netscape.ldap.LDAPEntryChangeControl.ENTRYCHANGED is an entry +change notification control. These types of controls can be included +with entries sent back from the server during a persistent search. +Getting the Entry Change Notification +Control With Directory SDK for Java + +To get an entry change notification control that is included with an +entry, do the following: +As you retrieve each entry, invoke the getResponseControls + method of the LDAPConnection object to retrieve +any response controls sent back from the server.Response controls +are passed back as an array of LDAPControl objects. + +Pass this array of LDAPControl objects +as an argument to the LDAPPersistSearchControl.parseResponse static +method to retrieve the entry change notification control. + +An entry change notification control is represented by an object of +the LDAPEntryChangeControl class. To get data from +this control, you can invoke the accessor methods, such as getChangeNumber +, getChangeType, and getPreviousDN. + +Working With Change Log Numbers +With Directory SDK for Java +If the directory server is set up to be a supplier, the server is capable +of replicating changes in the directory to other servers. The server therefore +keeps a record of the changes made to the directory in a change log. Each +record of a change has a number that identifies the change in the log. +You can get the change number for a modified entry from the LDAPEntryChangeControl + object. +To look up the record for a particular change log number to get more +information about the change that took place, search for the record. With +Directory Server, the change log is represented by an entry in the directory. +Individual change records are represented by entries in a subtree beneath +the change log entry. +To determine the DN for the change log entry, search the root DSE to +retrieve the changelog attribute. For example, the value +of this attribute might be cn=changelog, which is the DN +for the change log entry. +Each change log record is an entry under the change log entry. The change +log number is the value of the changenumber attribute of +the record. To get a specific change log record, search with base DN cn=changelog + and filter changenumber=value. +Here, value is the change number of the record. + + +Using the Virtual List Control With &DirectorySDKForJava; +The control represented with the OID that corresponds to the constant +netscape.ldap.controls.LDAPVirtualListControl.VIRTUALLIST is a +virtual list control. When you send a search request with this +control and with a server-side sorting control to the server, the server should +sort the results and return the specified subset of entries back to your client. +After you set the list size with the setListSize method +of the LDAPVirtualListControl object, invoke the +setRange method. The method recreates the control with the new data. +setRange generates the BER-encoded request to be sent to the server. +setListSize does not generate the request. +Using the Manage DSA IT Control With &DirectorySDKForJava; +The control represented with the OID that corresponds to the constant +netscape.ldap.controls.LDAPControl.MANAGEDSAIT is a manage +DSA IT control. The control is for managing search references +in the directory and is defined in RFC +3296. +To create this control, construct a new LDAPControl object. +In the LDAPControl constructor, set the OID of the control +to netscape.ldap.controls.LDAPControl.MANAGEDSAIT. +Add this control to the array of LDAPControl objects. +When you pass the array to a method that performs an LDAP operation, the server +treats search references as ordinary entries. +Rather than returning a reference to you, the server returns the entry +that contains the reference. This mechanism allows your client application +to manage search references in the directory. +Using Password Policy Controls With &DirectorySDKForJava; + +&cnDirectoryServer; uses two server response controls to send information +back to a client after an LDAP bind operation. +The control represented with the OID that corresponds to the +constant netscape.ldap.controls.LDAPControl.PWEXPIRED is +the expired password control.This control +is used if the server is configured to require users to change their passwords +on first login. The control is also used whenever the passwords are reset. +The user might be logging in for the first time. The user password might +have been reset. In either circumstance, the server sends the control to indicate +that the client needs to change the password immediately. When receiving this +control, the only operation that the client can perform is to change the user's +password. If the client requests any other LDAP operation, the server sends +back an LDAP_UNWILLING_TO_PERFORM result code with +an expired password control. +The control represented with the OID that corresponds to the +constant netscape.ldap.controls.LDAPControl.PWEXPIRING is +the password expiring warning control.This +control is used if the server is configured to expire user passwords after +a certain amount of time.The server sends this control back to +the client if the client binds with a password that is soon to expire. If +you invoke the getValue method for this LDAPControl + object, the method returns the number of seconds before the password +expires. + +To get these server response controls when binding, invoke the getResponseControls + method of the LDAPConnection object after +you attempt to authenticate to the server. +Using the Proxied Authorization Control +With &DirectorySDKForJava; +The control represented with the OID that corresponds to the constant +netscape.ldap.controls.LDAPProxiedAuthControl.PROXIEDAUTHREQUEST is +a proxied authorization control. It allows LDAP clients +to use different credentials, without rebinding, when executing LDAP operations. +For example, suppose a messaging server stores its user profiles on +an LDAP server. For certain types of requests the messaging server needs to +use a DN and password other than its own. To use another DN and password without +proxied authorization requires the messaging server to rebind, using the different +credentials, before executing each operation. +If the messaging server uses the proxied authorization control, the +server can act as the user when executing an operation. The messaging server +maintains only its own binding to the LDAP server. This mechanism drastically +improves performance, especially when processing a large number of requests. + +
diff --git a/mozilla/directory/docs/ldapjdk/jdk-extended-ops.sgm b/mozilla/directory/docs/ldapjdk/jdk-extended-ops.sgm new file mode 100644 index 00000000000..926f7c9fc41 --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/jdk-extended-ops.sgm @@ -0,0 +1,156 @@ + +Extended Operations With &DirectorySDKForJava; + +This chapter explains LDAP v3 extended operations. This chapter also +explains how to use the extended operations that are supported by your LDAP +server. + +This chapter covers the following topics: +How Extended Operations +Work With Directory SDK for Java +Implementing Support +for Extended Operations on the Server With Directory SDK for Java + +Determining the +Extended Operations Supported With Directory SDK for Java + +Performing an Extended +Operation With Directory SDK for Java +Example Extended Operation +With Directory SDK for Java + + +How Extended Operations Work With &DirectorySDKForJava; +Extended operations are part of LDAP v3. Each extended operation is +identified by an object identifier (OID). + +LDAP clients can request the operation by sending an extended operation +request. Within the request, the client specifies the following: +The OID of the extended operation to perform +Data specific to the extended operation + + +The server receives the request. The server then performs the extended +operation. The server can send back to the client a response containing: +An OID +Any additional data + + +To use extended operations, both the server and the client must know +the specific extended operation to be performed. +You must write a client that can send requests for a specific +extended operation. The client must also be able to receive extended responses +from the server. +Your LDAP server needs to be able to handle requests for specific +extended operations. The server also must be able to send responses back to +the client. + + +Implementing Support for Extended Operations +on the Server With Directory SDK for Java + +LDAP servers +extended operations and + +&cnDirectoryServer; supports a plug-in API that allows you to write +your own server plug-in to handle extended operations. + +You can write an extended operation that does the following: +Registers the OID of an extended operation as supported, so +the OID appears as a value of the supportedExtension attribute +on the root DSE +Gets information from an extended operation request + +Creates and sends an extended operation response back to the +client + + +Determining the Extended Operations +Supported With &DirectorySDKForJava; +To determine the extended operations supported by the server, get the +root DSE of the server, and check the supportedExtension attribute. +The values of this attribute are the OIDs of the extended operations supported +by this server. +If the root DSE does not have a supportedExtension attribute, +the server does not support any extended operations. For instructions on reading +the root DSE, refer to Getting the Root DSE With Directory SDK for +Java. +Performing an Extended Operation With &DirectorySDKForJava; + +LDAP clients +extended operations and + + +To request an extended operation, do the following: +Construct a new LDAPExtendedOperation object, +specifying the OID of the extended operation and the data that you want applied +to the operation. +Invoke the extendedOperation method of +the LDAPConnection object, passing the method of the +newly constructed LDAPExtendedOperation object. + + +The LDAPExtendedOperation object that is returned +represents the server response. You can invoke the getID and +getValue methods of this object to get the OID and the data from +the server's response. +Example Extended Operation With &DirectorySDKForJava; +The following example shows an LDAP client that requests an extended +operation with the OID 1.2.3.4 from the server. +import netscape.ldap.*; +import java.util.*; +import java.io.*; + +public class ExtOpt { + private static String OID = "1.2.3.4"; + public static void main(String[] args) { + try { + UserArgs userArgs = new UserArgs("ExtOpt", args, true); + LDAPConnection ld = new LDAPConnection(); + ld.connect(userArgs.getHost(), userArgs.getPort()); + ld.authenticate(3, userArgs.getBindDN(),userArgs.getPassword()); + System.out.println("Authenticated to directory."); + + /* Create an extended operation object */ + String myval = "My Value"; + byte vals[] = myval.getBytes("UTF8"); + LDAPExtendedOperation exop = + new LDAPExtendedOperation(OID, vals); + + /* Request the extended operation from the server. */ + LDAPExtendedOperation exres = ld.extendedOperation(exop); + System.out.println("Performed extended operation."); + + /* Get data from the response sent by the server. */ + System.out.println("OID returned: " + exres.getID()); + String retValue = new String(exres.getValue(),"UTF8"); + System.out.println("Value returned: " + retValue); + + ld.disconnect(); + } + catch(LDAPException e) { + System.out.println("Error: " + e.toString()); + } + catch(UnsupportedEncodingException e) { + System.out.println("Error: UTF8 not supported"); + } + } +} + + diff --git a/mozilla/directory/docs/ldapjdk/jdk-filter-conf.sgm b/mozilla/directory/docs/ldapjdk/jdk-filter-conf.sgm new file mode 100644 index 00000000000..71c116aa395 --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/jdk-filter-conf.sgm @@ -0,0 +1,545 @@ + +Using Filter Configuration Files + +This chapter explains how to use API function to work with filter configuration +files. Filter configuration files can help simplify the process of selecting the appropriate +search filter for a search request. The chapter contains the following sections: + +Understanding Filter +Configuration Files +Understanding +the Configuration File Syntax +Understanding Filter +Parameters +Loading Filter Configuration +Files +Retrieving Filters + +Adding Filter Prefixes and +Suffixes + + +Understanding Filter Configuration Files + +Suppose that you are writing a client that allows users to search the directory. +You might want to use different search filters tailored for specific types of search +criteria. For example, suppose the user wants to search for this: +bjensen@example.com +You might want to use this search filter: +(mail=bjensen@example.com) +Similarly, suppose the search term entered by the user contains numbers, like +this: +555-1212 +In this case, you might want to use this search filter: +(telephoneNumber=555-1212) +Rather than write code to construct the search filter explicitly, you can generate +filters using a filter configuration file. A filter configuration +file specifies a list of filters that you can load and use in your searches. + +Understanding the Configuration +File Syntax +filter configuration filessyntax + +A filter configuration file has the following format: +tag + pattern1 delimiters +filter1-1 desc1-1 [scope1 +] + filter1-2 +desc1-2 [scope2] + + pattern2 delimiters +filter2-1 desc2-1 [scope3 +] + … +Each element in the file is a string, surrounded by quotes ("). +Comments consist of lines starting with #. +The format supports these elements: + +tag +Identifies a group of filters. +You can use different tags to distinguish filters for different types of objects. +For example, you can use a "person" tag to identify filters for +person entries, a "organization" tag to represent filters for organization +entries, and so forth. +You can specify multiple tags for the same group of filters in the configuration +file using the keyword and, such as "people and organization" +. +You can specify a tag, or part of a tag, as a parameter. The tag narrows the +list of filters that the function retrieves. + + +pattern +Specifies a regular expression used to determine which filter is selected +based on the search criteria. +For example, if you specify ^[0-9] as the pattern for a filter, +the filter is selected for all search criteria beginning with a number. + + +delimiters +Specify what characters separate one field from another within search +criteria. +For example, if the search criteria consists of a city name and state abbreviation +separated by a comma, specify "," as the delimiter. + + +filter +Specifies an LDAP filter including %v to represent +the search criteria. +For example, to search email addresses, use the filter (mail=%v). +During runtime, if the search criteria bjensen@example.com is entered, +the filter becomes (mail=bjensen@example.com). +If the search criteria consists of a number of delimited fields such as a +surname, first name format +like Jensen, Barbara, use %v1, %v2 +, …, %vn to represent the fields within the search +criteria. For example: +"people" + "^[A-Z]*," "," "(&(sn=%v1)(givenName=%v2))" +In the example, the delimiter is a comma. The word before the delimiter replaces +%v1 in the filter, and the word after the delimiter replaces%v1 +. A search for: +Jensen, Barbararesults in +a filter: +(&(sn=Jensen)(givenName=Barbara)) +You can also specify ranges of fields. For example, to specify the values in +the first three fields, use %v1-3. To specify values from the third +field to the last field, use %v3-. To specify the value in the +last field, use %v$. + + +desc +Specify short text descriptions of the filters. + + +scope +Specify the scope of each search. +This field is optional. It can take the values "base", +"onelevel", or "subtree". + + + +For example, the following section of a filter configuration file specifies +a filter for telephone numbers and two filters for email addresses. The telephone +number filter is used if the search criteria contains one or more numbers. The email +filters are used if the search criteria contains an at sign (@). + +"people" + "^[0-9][0-9-]*$" " " "(telephoneNumber=*%v)" "phone number ends with" + "@" " " "(mail=%v)" "email address is" + "(mail=%v*)" "email address starts with" + +Specify the filters in the order that you want them to be used. For example, +if you want to apply the (mail=%v) filter before the +(mail=%v*) filter, make sure that the filters appear in that order. + +Understanding Filter Parameters + +Configuration file filter specifications support the following parameters: + +%v +Insert the search criterion verbatim in place of %v. + +For example, if the filter specification is (mail=%v), entering +bjensen results in the filter (mail=bjensen). + + +%v$ +Insert the last word of search criterion verbatim in place of +%v. +For example, if the filter specification is (sn=%v$), entering +Barbara Jensen results in the filter (sn=Jensen). + + +%vN +Insert the Nth word of the criteria in +place of %v, where N is a single digit +between 1 and 9. +For example, if the filter specification is (sn=%v2), entering +Barbara Jensen results in the filter (sn=Jensen). + + +%vM- +N +Insert the sequence of the Mth through +Nth words of the criteria in place of %v, where +M and N are single digits between 1 and 9. + +For example, if the filter specification is (cn=%v1-2), entering +Barbara Jensen results in the filter (cn=Barbara Jensen). + + + +%vN- +Insert the sequence of th eNth through +last words of the criteria in place of %v, where +N is a single digit between 1 and 9. +For example, if the filter specification is (cn=%v2-), entering +Ms. Barbara Jensen results in the filter (cn=Barbara Jensen). + + + + + +Loading Filter Configuration Files +filter configuration filesloading + +loading filter configuration files +To use a filter configuration file, you need to create an LDAPFilterDescriptor + object. The LDAPFilterDescriptor constructor allows +you to read in the filter configuration file from one of the following: + +A file in the local file system to which you specify the path + +A file served by a web server to which you specify the URL + +A location in memory where you specify a StringBuffer object +containing the configuration information + +The following section of code reads in a filter configuration file named +ldapfilter.conf in the current directory. +import netscape.ldap.util.*; +… + +LDAPFilterDescriptor filtdesc = null; +try { + /* Read in the filter configuration file. */ + filtdesc = new LDAPFilterDescriptor("ldapfilter.conf"); +} catch ( Exception e ) { + System.out.println( "Error: " + e.toString() ); +} + +Retrieving Filters +After loading a filter configuration file into memory, you can retrieve filters +based on the search criteria. For example, if the search criteria is an email address +such as bjensen@example.com, you can have your client automatically +search for this value in the mail attribute. +Retrieving Filters Using A Filter Configuration +File + +Invoke the LDAPFilterDescriptor constructor to read +in the filter configuration file. +Invoke the getFilters method of the LDAPFilterDescriptor + object.Specify the tag of the section that you want to use +in the filter configuration file.You do not need to invoke the +setupFilter of the LDAPFilter object to generate +the filter. The getFilters method of the LDAPFilterDescriptor + object does this already. You just need to invoke the getFilter + method of the LDAPFilter object to get the generated +filter.This method returns an LDAPFilterList object, +which is an enumeration of LDAPFilter objects containing the +filters for the specified search term. +Invoke the next method of the LDAPFilterList + object to iterate through the LDAPFilter objects. + +For each LDAPFilter object, get the filter by invoking +the getFilter method, passing no arguments.To get +the total number of filter configuration lines that match the specified search term, +invoke the numFilters method of the LDAPFilterList object. +This number decrements each time you invoke the next or nextElement method. + + + +Retrieving Telephone Number and Mail Filters +This example uses a filter configuration file, ldapfilter.conf, +with the following specifications: +"people" + "^[0-9][0-9-]*$" " " "(telephoneNumber=*%v)" "phone number ends with" + "@" " " "(mail=%v)" "email address is" + "(mail=%v*)" "email address starts with" +The following code retrieves, generates, and prints filters matching the criteria: + +String searchTerm = "bjensen@example.com"; +LDAPFilterDescriptor filtdesc = null; +try { + /* Read in the filter configuration file. */ + filtdesc = new LDAPFilterDescriptor("ldapfilt.conf"); + + /* Get filters from the section "people" */ + LDAPFilterList filtlist = null; + try { + filtlist = filtdesc.getFilters("people", searchTerm); + } catch ( Exception e ) { + System.out.println("No matching tag section or filter"); + System.exit(0); + } + + int totalFilters = filtlist.numFilters(); + System.out.println("Found " + totalFilters + " applicable filters.\n"); + + /* Iterate through the lines in the list. */ + while ( filtlist.hasMoreElements() ) { + LDAPFilter filtline = filtlist.next(); + System.out.println("Filter #" + + (totalFilters - filtlist.numFilters())); + + /* Get and print information about the selected line + of filter configuration information. */ + System.out.println(" Description: " + filtline.getDescription()); + System.out.println(" Line #: " + filtline.getLineNumber()); + System.out.println(" Matches pattern: " + + filtline.getMatchPattern()); + System.out.println(" Filter template: " + + filtline.getFilterTemplate()); + System.out.println(" Delimiter: " + filtline.getDelimeter()); + System.out.println(" Scope: " + filtline.getScope()); + + /* Get the generated filter. */ + String filterString = filtline.getFilter(); + System.out.println(" Generated filter string: " + + filterString + "\n"); + } +} catch ( Exception e ) { + System.out.println("Error: " + e.toString()); +} +When built into a program, compiled, and run, this code produces the following +output: +Found 2 applicable filters. + +Filter #1 + Description: email address is + Line #: 3 + Matches pattern: @ + Filter template: (mail=%v) + Delimiter: + Scope: subtree + Generated filter string: (mail=bjensen@example.com) + +Filter #2 + Description: email address starts with + Line #: 4 + Matches pattern: @ + Filter template: (mail=%v*) + Delimiter: + Scope: subtree + Generated filter string: (mail=bjensen@example.com*) + + + +Adding Filter Prefixes and Suffixes +If you need to apply a filter to all searches, you can add a filter prefix and +suffix to all filters rather than adding the criteria to all filters. For example, +if your client searches only for person entries, you can add the following filter +prefix to restrict the search: +(&(l=Sunnyvale) +The filter prefix now requires the following suffix to balance the number of +parentheses: +) +For example, given the following filter: +(sn=Jensen) +You can use the filter prefix (&(l=Sunnyvale and the +filter suffix ) to narrow down the search to only the entries matching +l=Sunnyvale: +(&(l=Sunnyvale)(sn=Jensen)) +You can set up the filter prefix and suffix in several ways: + +To set these for all filters generated from the filter configuration +file, invoke the setFilterAffixes method of the LDAPFilterDescriptor + object. +To set the prefix or suffix for a specific filter, do one of the following: + + +Invoke the setFilterAffixes method of the +LDAPFilter object, then invoke the getFilter method, +passing in the search term again. This builds the filter again, using the specified +search term with the prefix and suffix. +Invoke the getFilter method, passing in the search +term, the prefix, and the suffix. +Invoke the setupFilter method, passing the search +term, the prefix, and the suffix. + +Setting the prefix and suffix for an individual filter overrides any prefix +or suffix set for the entire filter configuration file. + +Adding Affixes for All Filters +The following code loads a filter configuration file ldapfilter.conf + into memory, and adds the prefix (&(l=Sunnyvale and +suffix ) to each filter retrieved from the file: +LDAPFilterDescriptor filtdesc = null; +try { + /* Read in the filter configuration file. */ + filtdesc = new LDAPFilterDescriptor("ldapfilter.conf"); + + /* Add the specified prefix and suffix to all filters. */ + String prefix = "(&(l=Sunnyvale)"; + String suffix = ")"; + filtdesc.setFilterAffixes(prefix, suffix); + + /* Get filters from the section "people" */ + LDAPFilterList filtlist = null; + try { + filtlist = filtdesc.getFilters("people", searchTerm); + } catch (Exception e) { + System.out.println("No matching tag section or filter"); + System.exit(0); + } + + /* Iterate through the lines in the list. */ + while (filtlist.hasMoreElements()) { + LDAPFilter filtline = filtlist.next(); + + /* Get and print each filter. */ + String filterString = filtline.getFilter(); + System.out.println(" Generated filter string: " + + filterString + "\n"); + } +} catch (Exception e) { + System.out.println("Error: " + e.toString()); +} +For example, if the following search term is passed to the LDAPFilterDescriptor.getFilters + method: +bjensen@example.com +and the corresponding filter, not including the prefix or suffix, is: +(mail=bjensen@example.com) +the entire filter string retrieved by the LDAPFilter.getFilter method +is: +(&(l=Sunnyvale)(mail=bjensen@example.com)) + +Adding Affixes Using <literal>setFilterAffixes +</literal> +The following code loads a filter configuration file ldapfilter.conf + into memory, and uses the LDAPFilter.setFilterAffixes method +to add the prefix (&(l=Sunnyvale and suffix ) to +a generated filter: +LDAPFilterDescriptor filtdesc = null; +try { + /* Read in the filter configuration file. */ + filtdesc = new LDAPFilterDescriptor("ldapfilter.conf"); + + /* Get filters from the section "people" */ + LDAPFilterList filtlist = null; + try { + filtlist = filtdesc.getFilters("people", searchTerm); + } catch (Exception e) { + System.out.println("No matching tag section or filter"); + System.exit(0); + } + + /* Iterate through the lines in the list. */ + while (filtlist.hasMoreElements()) { + LDAPFilter filtline = filtlist.next(); + + /* Add the prefix and suffix, and generate the filter. */ + String prefix = "(&(l=Sunnyvale)"; + String suffix = ")"; + filtline.setFilterAffixes(prefix, suffix); + String filterString = filtline.getFilter(searchTerm); + System.out.println(" Generated filter string: " + + filterString + "\n"); + } +} catch ( Exception e ) { + System.out.println( "Error: " + e.toString() ); +} +For example, if the following search term is passed to the LDAPFilterDescriptor.getFilters + method: +bjensen@example.com +and the corresponding filter, not including the prefix or suffix, is: +(mail=bjensen@example.com) +the entire filter string retrieved by the LDAPFilter.getFilter method +is: +(&(l=Sunnyvale)(mail=bjensen@example.com)) + +Adding Affixes Using <literal>getFilter</literal> +The following code loads a filter configuration file ldapfilter.conf + into memory, and uses the LDAPFilter.getFilter method +to add the prefix (&(l=Sunnyvale and suffix ) to +a generated filter: +LDAPFilterDescriptor filtdesc = null; +try { + /* Read in the filter configuration file. */ + filtdesc = new LDAPFilterDescriptor("ldapfilter.conf"); + + /* Get filters from the section "people" */ + LDAPFilterList filtlist = null; + try { + filtlist = filtdesc.getFilters("people", searchTerm); + } catch (Exception e) { + System.out.println("No matching tag section or filter"); + System.exit(0); + } + + /* Iterate through the lines in the list. */ + while (filtlist.hasMoreElements()) { + LDAPFilter filtline = filtlist.next(); + + /* Add the prefix and suffix, and generate the filter. */ + String prefix = "(&(l=Sunnyvale)"; + String suffix = ")"; + String filterString = + filtline.getFilter(searchTerm, prefix, suffix); + System.out.println(" Generated filter string: " + + filterString + "\n"); + } +} catch ( Exception e ) { + System.out.println( "Error: " + e.toString() ); +} +For example, if the following search term is passed to the LDAPFilterDescriptor.getFilters + method: +bjensen@example.com +and the corresponding filter, not including the prefix or suffix, is: +(mail=bjensen@example.com) +the entire filter string retrieved by the LDAPFilter.getFilter method +is: +(&(l=Sunnyvale)(mail=bjensen@example.com)) + +Adding Affixes Using <literal>setupFilter</literal> +The following code loads a filter configuration file ldapfilter.conf + into memory, and uses the LDAPFilter.setupFilter method +to add the prefix (&(l=Sunnyvale and suffix ) to +a generated filter: +LDAPFilterDescriptor filtdesc = null; +try { + /* Read in the filter configuration file. */ + filtdesc = new LDAPFilterDescriptor("ldapfilter.conf"); + + /* Get filters from the section "people" */ + LDAPFilterList filtlist = null; + try { + filtlist = filtdesc.getFilters("people", searchTerm); + } catch (Exception e) { + System.out.println("No matching tag section or filter"); + System.exit(0); + } + + /* Iterate through the lines in the list. */ + while (filtlist.hasMoreElements()) { + LDAPFilter filtline = filtlist.next(); + + /* Add the prefix and suffix, and generate the filter. */ + String prefix = "(&(l=Sunnyvale)"; + String suffix = ")"; + filtline.setupFilter(searchTerm, prefix, suffix); + String filterString = filtline.getFilter(); + System.out.println(" Generated filter string: " + + filterString + "\n"); + } +} catch ( Exception e ) { + System.out.println( "Error: " + e.toString() ); +} +For example, if the following search term is passed to the LDAPFilterDescriptor.getFilters + method: +bjensen@example.com +and the corresponding filter, not including the prefix or suffix, is: +(mail=bjensen@example.com) +the entire filter string retrieved by the LDAPFilter.getFilter method +is: +(&(l=Sunnyvale)(mail=bjensen@example.com)) + + + diff --git a/mozilla/directory/docs/ldapjdk/jdk-ldap-urls.sgm b/mozilla/directory/docs/ldapjdk/jdk-ldap-urls.sgm new file mode 100644 index 00000000000..c2d2678ab4b --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/jdk-ldap-urls.sgm @@ -0,0 +1,202 @@ + +LDAP URLs With &DirectorySDKForJava; + +This chapter describes how to use LDAP URLs to search and retrieve data +from the directory. + +This chapter covers the following topics: +Getting the Components of +an LDAP URL With Directory SDK for Java +Processing an LDAP URL With +Directory SDK for Java +Searching Using an LDAP +URL With Directory SDK for Java + + +Getting the Components of an LDAP URL With &DirectorySDKForJava; + +To get the individual components of an LDAP URL, pass the URL to the +LDAPUrl constructor to create a new LDAPUrl object. +Then, use the following methods: +To get an array of the attributes that should be returned +in the search results, use the getAttributeArray method. +To get these attributes as an enumeration, use the getAttributes method. + +To get the host name of the LDAP server, use the getHost + method. +To get the port number of the LDAP server, use the getPort + method. +To get the base DN, use the getDN method. + +To get the scope of the search, use the getScope method. + +To get the search filter, use the getFilter method. + + + +Processing an LDAP URL With &DirectorySDKForJava; + +To process the search request specified by an LDAP URL, you can invoke +one of the following methods, passing in the LDAPUrl object: + +If the URL specifies a base search for a single entry, invoke +the read method of the LDAPConnection object. +This method reads the entry from the directory. +Otherwise, invoke the search method of +the LDAPConnection object to perform the search. + + +Both methods create a new LDAPConnection object +and connect to the LDAP server specified in the URL. Next, the methods perform +the search. Then the methods disconnect. +Searching Using an LDAP URL With &DirectorySDKForJava; +The following example demonstrates a search that uses an LDAP URL, invoking +the search method of the LDAPConnection object +to perform the search. Before the search is performed, the LDAP URL is exploded +using the methods suggested previously in this chapter. +import netscape.ldap.*; +import netscape.ldap.util.*; +import java.net.MalformedURLException; +import java.util.*; + +public class SrchUrl { + public static void main( String[] args ) { + LDAPConnection ld = null; + LDAPEntry findEntry = null; + int status = -1; + try { + UserArgs userArgs = new UserArgs("SrchUrl", args, false); + ld = new LDAPConnection(); + ld.connect(userArgs.getHost(), userArgs.getPort()); + + LDAPUrl myUrl = new LDAPUrl( + "ldap://" + + userArgs.getHost() + // server host + ":" + + userArgs.getPort() + // server port + "/" + + "dc=example,dc=com" + // base DN + "?" + + "cn,sn,mail,telephonenumber" + // attrs to retrieve + "?" + + "sub" + // search scope + "?" + + "(uid=bjensen)"); // search filter + + System.out.println( "LDAP URL : " + myUrl.toString() ); + System.out.println( " host : " + myUrl.getHost() ); + System.out.println( " port : " + myUrl.getPort() ); + System.out.println( " baseDN: " + myUrl.getDN() ); + String [] myAttrs = myUrl.getAttributeArray(); + for ( String myAttr: myAttrs ) { + System.out.println( " attrs : " + myAttr ); + } + System.out.println( " scope : " + myUrl.getScope() ); + System.out.println( " filter: " + myUrl.getFilter() ); + + LDAPSearchResults res = ld.search( myUrl ); + + /* Loop on results until finished; will only be one! */ + while ( res.hasMoreElements() ) { + + /* Next directory entry, really only one at most */ + try { + findEntry = res.next(); + } catch ( LDAPReferralException e ) { + System.out.println( "Search reference: " ); + LDAPUrl refUrls[] = e.getURLs(); + for (int i=0; i<refUrls.length; i++) { + System.out.println( "\t" + refUrls[i].getUrl() ); + } + continue; + } catch ( LDAPException e ) { + System.err.println( "Error: " + e.toString() ); + continue; + } + + /* Get the attributes of the entry */ + LDAPAttributeSet findAttrs = findEntry.getAttributeSet(); + Enumeration enumAttrs = findAttrs.getAttributes(); + + /* Loop on attributes */ + while ( enumAttrs.hasMoreElements() ) { + LDAPAttribute anAttr = + (LDAPAttribute)enumAttrs.nextElement(); + String attrName = anAttr.getName(); + if ( attrName.equals( "cn" ) ) + System.out.println( "Full name:" ); + else if ( attrName.equals( "sn" ) ) + System.out.println( "Last name (surname):" ); + else if ( attrName.equals( "mail" ) ) + System.out.println( "Email address:" ); + else if ( attrName.equals( "telephonenumber" ) ) + System.out.println( "Telephone number:" ); + /* Loop on values for this attribute */ + Enumeration enumVals = anAttr.getStringValues(); + if (enumVals != null) { + while ( enumVals.hasMoreElements() ) { + String aVal = ( String )enumVals.nextElement(); + System.out.println( "\t" + aVal ); + } + } + } + } + } + catch( LDAPException e ) { + System.err.println( "Error: " + e.toString() ); + } + catch( MalformedURLException e ) { + System.err.println( "Error: " + e.toString() ); + } + + /* Done, so disconnect */ + if ( (ld != null) && ld.isConnected() ) { + try { + ld.disconnect(); + } catch ( LDAPException e ) { + System.out.println( "Error: " + e.toString() ); + } + } + System.exit(status); + } +} +When this program is compiled and run against a directory that holds +Barbara Jensen's entry, the program generates the following output. +$ java SrchUrl -h myhost -p 1389 +LDAP URL : ldap://myhost:1389/dc=example,dc=com?cn,sn,mail,telephonenumber?sub?(uid=bjensen) + host : mykryten + port : 1389 + baseDN: dc=example,dc=com + attrs : cn + attrs : sn + attrs : mail + attrs : telephonenumber + scope : 2 + filter: (uid=bjensen) +Full name: + Barbara Jensen + Babs Jensen +Last name (surname): + Jensen +Email address: + bjensen@example.com +Telephone number: + +1 408 555 1862 + + diff --git a/mozilla/directory/docs/ldapjdk/jdk-quickstart.sgm b/mozilla/directory/docs/ldapjdk/jdk-quickstart.sgm new file mode 100644 index 00000000000..58754638f9c --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/jdk-quickstart.sgm @@ -0,0 +1,212 @@ + +Getting Started With &DirectorySDKForJava; + +This chapter shows how to develop a first LDAP client with the &DirectorySDKForJava;. + + +This chapter covers the following topics: +Understanding +the LDAP Java Classes +Understanding the +Sample Java Client +Sample Java Code + + + +Understanding the LDAP Java +Classes + +packages +summary of + +&DirectorySDKForJava; +packages + +&DirectorySDKForJava; includes the LDAP Java classes, which you use +to build LDAP clients. The LDAP Java classes allow you to write client applications +that connect to LDAP servers. The classes also allow you to perform standard +LDAP operations. For example, you can search for entries. You can also add, +update, or delete entries. +The classes are organized in the following packages. + +com.netscape.sasl +Contains the interfaces and classes that you can use to enable +your client to authenticate by using a SASL mechanism. + + +com.netscape.sasl.mechanisms +Contains an implementation of the EXTERNAL SASL +mechanism driver. + + +netscape.ldap +Contains the main LDAP Java classes, including classes that +allow you to connect to an LDAP server, manipulate entries and attributes, +and retrieve search results. + + + +netscape.ldap.ber.stream +Contains the LDAP Java classes that implement the Basic +Encoding Rules (BER) for transfer syntax. For more information +about BER, see ISO-IEC 8825 at http://www.iso.ch/ +. + + +netscape.ldap.controls +Contains the LDAP Java classes that implement specific LDAP +v3 controls. The implementations include controls to request server-side sorting +and persistent searches. + + +netscape.ldap.factory +Contains classes that allow you to create an SSL socket connection +to a server. + + +netscape.ldap.util +Contains utility classes, such as classes to parse LDIF data +and filters that allow regular expression matching. + + + +Clients typically execute methods in &DirectorySDKForJava; synchronously. +All LDAP operations block until the operations are completed, except for the +search method, which can return information before all the results +have been received. +An asynchronous interface is also provided for circumstances that require +low-level interaction with an LDAP server. The asynchronous interface is discussed +more fully in Chapter 13, Writing Asynchronous Clients With Directory SDK for Java. +Understanding the Sample Java Client +The sample client in this chapter retrieves the full name (cn), +last name (sn), email address (mail), +and telephone number (telephoneNumber) of Barbara Jensen. +You can find the program in the GetAttrs.java file in +the examples/java directory. + +The client does the following: +Creates a new LDAPConnection object, +which represents the connection to the LDAP server +Connects to the server +Searches for a single entry, identified by the DN using the +following search criteria: + +The base DN, the starting point for the search, is uid=bjensen,ou=People,dc=example,dc=com +. +The search scope is LDAPConnection.SCOPE_BASE, +meaning only the base DN. +The search filter is "objectclass=*", meaning +the filter matches any entry.As the scope narrows the search +to a single entry, the search filter does not need to be more specific. + + +To invoke a search on a single entry with these parameters is equivalent +to using the LDAPConnection.read method. + +Iterates through the enumerated search results to retrieve +and print the values of the cn, sn, +mail, and telephoneNumber attributesThis +iteration also allows the client to obtain multiple values for a single attribute. + +Disconnects from the server +Before you compile the sample client, make sure that the packages/ldapjdk.jar + file is in your CLASSPATH. +Sample Java Code +import netscape.ldap.*; +import netscape.ldap.util.*; +import java.util.*; + +public class GetAttrs { + public static void main( String[] args ) { + try { + UserArgs userArgs = new UserArgs("GetAttrs", args, false); + LDAPConnection ld = new LDAPConnection(); + ld.connect(userArgs.getHost(), userArgs.getPort()); + + String ENTRYDN = "uid=bjensen, ou=People, dc=example,dc=com"; + String[] attrNames = { + "cn", // Get canonical name(s) (full name) + "sn", // Get surname(s) (last name) + "mail", // Get email address(es) + "telephonenumber"}; // Get telephone number(s) + LDAPSearchResults res = + ld.search(ENTRYDN, ld.SCOPE_BASE, "(objectclass=*)", + attrNames, false ); + + /* Loop on results until finished; only one entry here */ + while (res.hasMoreElements()) { + LDAPEntry findEntry = null; + try { + findEntry = res.next(); + } catch (LDAPReferralException e) { + System.out.println("Search reference: "); + LDAPUrl refUrls[] = e.getURLs(); + for (int i=0; i < refUrls.length; i++) { + System.out.println("\t" + refUrls[i].getUrl()); + } + continue; + } catch (LDAPException e) { + System.out.println("Error: " + e.toString()); + continue; + } + + /* Get the attributes of the entry */ + LDAPAttributeSet findAttrs = findEntry.getAttributeSet(); + Enumeration enumAttrs = findAttrs.getAttributes(); + + /* Loop on attributes */ + while (enumAttrs.hasMoreElements()) { + LDAPAttribute anAttr = + (LDAPAttribute)enumAttrs.nextElement(); + String attrName = anAttr.getName(); + if (attrName.equals("cn")) { + System.out.println("Full name:"); + } else if (attrName.equals("sn")) { + System.out.println("Last name (surname):"); + } else if (attrName.equals("mail")) { + System.out.println("Email address:"); + } else if (attrName.equals("telephonenumber")) { + System.out.println("Telephone number:"); + } + /* Loop on values for this attribute */ + Enumeration enumVals = anAttr.getStringValues(); + if (enumVals != null) { + while (enumVals.hasMoreElements()) { + String aVal = (String)enumVals.nextElement(); + System.out.println("\t" + aVal); + } + } + } + } + + ld.disconnect(); + } + catch(LDAPException e) { + System.out.println("Error: " + e.toString()); + } + } +} + + diff --git a/mozilla/directory/docs/ldapjdk/jdk-sasl.sgm b/mozilla/directory/docs/ldapjdk/jdk-sasl.sgm new file mode 100644 index 00000000000..09d86bf31e5 --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/jdk-sasl.sgm @@ -0,0 +1,338 @@ + +SASL Authentication With &DirectorySDKForJava; + +This chapter describes the process of using a SASL mechanism to authenticate +an LDAP client to an LDAP server. + +This chapter covers the following topics: +Understanding SASL and Directory +SDK for Java +Preparing to Use SASL Authentication +With Directory SDK for Java +Using SASL in the Client With +Directory SDK for Java +Further Reading About SASL + + + +Understanding SASL and &DirectorySDKForJava; + +SASL +defined + +The Simple Authentication and Security Layer (SASL) is an authentication +method. SASL allows you to use mechanisms other than simple passwords and +SSL for authenticating over connection-based protocols, such as LDAP. +All SASL mechanisms are registered with the Internet Assigned Numbers +Authority (IANA). Included among these mechanisms are KERBEROS_V4, +GSSAPI, and several others. The client implements these mechanisms +through the use of mechanism drivers. These drivers are classes that contain +the code that is required for authenticating over a given mechanism. +When a client attempts to authenticate to an LDAP server with the +LDAPConnection.authenticate method, the client can specify a list +of SASL mechanisms to use. If the client does not specify any mechanisms, &DirectorySDKForJava; queries +the server to find out which mechanisms the server supports. If &DirectorySDKForJava; and +the server have a common mechanism, authentication can occur. +If the server supports a requested mechanism, the server responds with +one or more challenges. To authenticate, the client must correctly respond +to these challenges. Client handling is performed transparently by &DirectorySDKForJava; with +a mechanism driver. +If the server does not support any of the requested mechanisms, the +SDK returns an AuthenticationNotSupportedException. +If the mechanism driver requires additional authentication data from +the client, the driver sends a Callback object to the +client. To prepare for the callback, the client implements a CallbackHandler + and passes the handler to &DirectorySDKForJava;. The SASL +mechanism might need additional client credentials. The SASL mechanism might +also notify the client of errors during the SASL negotiations. For either +purpose, the mechanism calls the CallbackHandler object +with Callback objects for each item to be processed. +The CallbackHandler then determines how to proceed. +&DirectorySDKForJava; includes a package, com.netscape.sasl, +that contains the code necessary to perform all of the steps involved in SASL +authentication. +Preparing to Use SASL Authentication With &DirectorySDKForJava; + +Before performing SASL authentication, you must do the following: +Ensure that your LDAP server supports at least one SASL mechanism + +Ensure that your client environment supports at least one +SASL mechanism supported by the server + +SASL Support on the Server + +SASL +server-side requirements + +&cnDirectoryServer; supports a plug-in API that allows you to write +your own server plug-in to handle SASL authentication. &cnDirectoryServer; also +supports SASL authentication through DIGEST-MD5 and through GSSAPI. + +If you write your own plug-in, your plug-in uses a registered SASL mechanism +to do the following: +Get information from a SASL bind request. +Create and send a SASL bind response back to the client. +This response can take the form of a challenge that requires an answer +from the client. The response can also take the form of an error message. +Finally, the response can take the form of a success message indicating that +authentication is complete. + + +SASL Support on the Client + +SASL +client-side requirements + +To authenticate over SASL, you must have a mechanism in your SASL client +package. If you have obtained a ClientFactory class +that can produce a SASL mechanism that your server supports, you can name +its package in your code. + +This option can be performed in one of two ways: +Request a SASL client. Specify the package in the javax.security.sasl.client.pkgs + property of its Hashtable. +Set the package as the default factory for the session with +the Sasl.setSaslClientFactory method. + +For example, you might have a class, mysecurity.sasl.ClientFactory +, capable of producing a SaslClient object +for one or more mechanisms. You could then write either of the two following +bits of code: +Hashtable props = new Hashtable(); +props.put("javax.security.sasl.client.pkgs", "mysecurity.sasl"); +ld.authenticate(dn, props, cbh); +Sasl.setSaslClientFactory (new mysecurity.sasl.ClientFactory()); +ld.authenticate(dn, props, cbh); +The parameters used have the following descriptions: + +dn +Authentication DN + + +props +Optional properties that the mechanism accepts +Refer to Using +the External Mechanism for details. + + +cbh +Instance of CallbackHandler that is +implemented in your application + + + + +Implementing <literal>javax.security.auth.callback +</literal> + +authentication +implementing SASL callbacks + +callbacks +implementing for SASL + +SASL +implementing callbacks + +Some SASL mechanisms require additional credentials during the authentication +process. To provide this additional information, your SASL client might need +to implement Callback objects and a CallbackHandler + to list credentials. Callback and +CallbackHandler are part of the javax.security.auth.callback + package. +The following example shows Callback and +CallbackHandler implementations. +class SampleCallbackHandler implements CallbackHandler { + SampleCallbackHandler(String userName) { + userName = userName; + } + /** Invoke the requested Callback */ + public void invokeCallback(Callback[] callbacks) + throws java.io.IOException,UnsupportedCallbackException { + for (int i = 0; i < callbacks.length; i++) { + if (callbacks[i] instanceof TextOutputCallback) { + // display the message according to the + // specified STYLE + TextOutputCallback toc = + (TextOutputCallback)callbacks[i]; + switch (toc.getStyle()) { + case TextOutputCallback.ERROR: + System.out.println("ERROR: " + toc.getMessage()); + break; + case TextOutputCallback.INFORMATION: + System.out.println(toc.getMessage()); + break; + case TextOutputCallback.WARNING: + System.out.println("WARNING: " + toc.getMessage()); + break; + } + } else if (callbacks[i] instanceof TextInputCallback){ + // prompt the user for information + TextInputCallback tic = (TextInputCallback)callbacks[i]; + // display the prompt and a default reply + System.err.print(tic.getPrompt() + " [" + + tic.getDefaultText() + "]: "); + System.err.flush(); + BufferedReader reader = new + BufferedReader(new InputStreamReader(System.in)); + tic.setText(reader.readLine()); + } else if (callbacks[i] instanceof NameCallback) { + ((NameCallback)callbacks[i]).setName(_userName); + } else if (callbacks[i] instanceof PasswordCallback){ + // prompt the user for sensitive information + PasswordCallback pc = (PasswordCallback)callbacks[i]; + System.err.print(pc.getPrompt() + " "); + System.err.flush(); + pc.setPassword(readPassword(System.in)); + } else if (callbacks[i] instanceof LanguageCallback){ + // Get the language from the locale + LanguageCallback lc = (LanguageCallback)callbacks[i]; + lc.setLocale(Locale.getDefault()); + } else { + throw new UnsupportedCallbackException( + callbacks[i], "Unrecognized Callback"); + } + } + } + /** Reads user password from given input stream. */ + private char[] readPassword(InputStream in) { + // insert code to read a user password from the + // input stream + } + private String _userName = null; +} + + +Using SASL in the Client With &DirectorySDKForJava; + +You are ready to authenticate when you have done the following: +Determined that at least one SASL mechanism exists in common +between the server and your client environment +Implemented javax.security.auth.callback.CallbackHandler + if you might need to supply additional credentials during authentication + + +The following example shows how to use SASL in an application: +Hashtable props = new Hashtable(); +props.put("javax.security.sasl.client.pkgs", "mysecurity.sasl"); +ld.authenticate(dn, props, new SampleCallbackHandler()); +Using the <literal>External</literal> Mechanism + + +SASL +using the EXTERNAL mechanism with + +SSL +using SASL with + +&DirectorySDKForJava; includes a mechanism called EXTERNAL. +This mechanism verifies that SSL authentication has already completed before +the mechanism allows a client to connect over LDAP. + +To use the EXTERNAL mechanism, do the following: +Bind to the server, and authenticate using SSL.Refer +to Connecting to a +Server Over SSL With Directory SDK for Java for details. + +Call the LDAPConnection.authenticate method +as follows: +ld = new LDAPConnection(); +ld.authenticate( + null, new String[]{"EXTERNAL"}, null, (CallbackHandler)null); +LDAPConnection.authenticate takes the following parameters. + + +dn +Authentication DN + + +mechanisms +List of SASL mechanisms to use for authentication +If null is specified, &DirectorySDKForJava; queries +the server for all available mechanisms. + + +props +Optional properties that the mechanism accepts, which include +the following: + +javax.security.sasl.encryption.minimum +The minimum key length to be used during the session. +The default value is 0, no session protection. A +value of 1 enables integrity protection only. + + +javax.security.sasl.encryption.maximum +The maximum key length to be used during the session. +The default value is 256. + + +javax.security.sasl.server.authentication +A boolean value. +true if a server must authenticate to the client. +The default value is false. + + +javax.security.sasl.ip.local +The client's IP address in dotted decimal format. +This value is required for KERBEROS_V4 authentication. +No default value exists. + + +javax.security.sasl.ip.remote +The server's IP address in dotted decimal format. +This value is required for KERBEROS_V4 authentication. +No default value exists. + + +javax.security.sasl.maxbuffer +The maximum size of the security layer frames. +The default is 0, meaning that the client does not +use the security layer. + + +javax.security.sasl.client.pkgs +A bar-separated list of package names to use when locating +a SaslClientFactory. + + + + + +cbh +Instance of CallbackHandler that is +implemented in your application. + + + + + + +Other SASL Mechanisms +Authentication with a SASL mechanism other than EXTERNAL requires +you to implement classes for the mechanism in the client and on the server. + + +Further Reading About SASL +SASL is described in RFC 4422. +For a current list of registered SASL mechanisms, see http://www.iana.org/assignments/sasl-mechanisms +. + diff --git a/mozilla/directory/docs/ldapjdk/jdk-searching.sgm b/mozilla/directory/docs/ldapjdk/jdk-searching.sgm new file mode 100644 index 00000000000..221ebc3e6c4 --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/jdk-searching.sgm @@ -0,0 +1,970 @@ + +Searching the Directory With &DirectorySDKForJava; + +This chapter explains how to use the LDAP Java classes to search the +directory to retrieve entries. The chapter also describes how to get attributes +and attribute values from an entry. + +This chapter covers the following topics: +Searching With the LDAP +Java Classes +Sending a Search Request +With Directory SDK for Java +Getting the Search Results +With Directory SDK for Java +Sorting the Search Results +With Directory SDK for Java +Abandoning a Search +With Directory SDK for Java +Searching the Directory +With Directory SDK for Java +Reading an Entry With Directory +SDK for Java +Listing Child Entries +With Directory SDK for Java + + +Searching With the LDAP Java Classes + +In &DirectorySDKForJava;, searches are represented by objects of +the following classes: +You can send a search request by invoking the search method +of the LDAPConnection object. +You can specify a set of search constraints by using an +LDAPSearchConstraints object. The constraints can specify the +maximum number of results to return. The constraints can also specify the +maximum amount of time that is allowed for a search. +You can specify different parts of the search criteria in +separate arguments. Alternatively, you can construct an LDAPUrl object +to specify the search criteria. +You can search for a single entry by invoking the read method +of the LDAPConnection object. +The server returns the search results to the LDAP Java classes, +which represents the results as an LDAPSearchResults object. + + + +Sending a Search Request With &DirectorySDKForJava; +To search the directory, use the search method of +the LDAPConnection object. The search results are returned +in the form of an LDAPSearchResults object. +public LDAPSearchResults search(String base, int scope, +    String filter, String attrs[], boolean attrsOnly, +    LDAPSearchConstraints cons) throws LDAPException +You need to specify the following parameters as arguments to the search + method. + +base +Specifies the base DN, which is the entry on and under which +the search is carried out. +For example, when searching entries with DNs such as uid=bjensen,ou=People,dc=example,dc=com +, the base could be ou=People,dc=example,dc=com + or dc=example,dc=com. + + +scope +Specifies the scope of the search. +You can adjust the scope of the search to examine only the entry identified +by the base, only those entries one level down the +tree from the base, or the entire subtree underneath +the base. + + +filter +Specifies what to search for. +A search filter specifies what search results to return. The filter +meaning can be simple, such as “find entries where the last name is +Jensen”. The filter meaning can also be complex, such as “find +entries that belong to Dept. #17 and with first names that start with the +letter F.” + + +attrsattrsOnly + +Specify the entry attributes to retrieve. +For example, you can use attrs to retrieve only +email addresses and phone numbers. Alternatively, you can set up a search +to return all attributes in an entry. You can also specify to return only +the names of attributes, not the values, by setting attrsOnly to +true. + + +cons +Specifies constraints to apply to the search when you do not +want to use the default constraints. + + + +The following figure illustrates how search criteria work. +

Criteria for an LDAP Search + + +How search criteria work + +
+You can also specify the criteria in the form of an LDAP URL. An LDAP +URL allows you to specify the host name and port number of the LDAP server +that you want to search. To search a different LDAP server than the server +you are connected to, you can invoke the search method. You then specify an +LDAP URL in the form of an LDAPUrl object. See Chapter 7, LDAP URLs With Directory SDK for Java for +details. +Specifying the Base DN and Scope + +base DN +explained + +scope +explained + +When sending a search request, you need to specify the base DN and scope +of the search to identify the entries that you want searched. +The base DN is the DN of the entry that serves as the starting point +of the search. + +To specify the scope of the search, you pass one of the following values +as the scope parameter: +LDAPv3.SCOPE_SUB — Search the base +entry and all entries at all levels under the base entry. + + +Subtree scope applies to everything below the base DN. + + + +LDAPv3.SCOPE_ONE — Search all entries +at one level under the base entry. + + +One level scope applies to all entries just below the +base DN. + +The base entry is not included in the search. Use this setting if you +just want a list of the entries under a given entry. +LDAPv3.SCOPE_BASE — Search only +the base entry. + + +Base scope applies only to the base DN entry. + + +Use this setting if you want to read the attributes of only the base +entry. + + +Specifying a Search Filter + +filters + +search filters +specifying + +When you search the directory, you use a search filter to define the +search. Here is the basic syntax for a search filter: +(attribute operator +value) +Here is a simple example of a search filter: +(cn=Barbara Jensen) +In this example, cn is the attribute. = is +the operator. Barbara Jensen is the value. The filter finds +entries with the common name Barbara Jensen. +Valid attributes that you can use in your search filter are provided +in the documentation for the LDAP server. +Following are descriptions of valid operators for search filters, and +example filters that use the operators. + += +Return entries whose attributes are equal to the value provided. +For example, the following filter matches Barbara Jensen's entry: +(cn=Barbara Jensen) + + +>= +Return entries whose attributes are greater than or equal +to the value provided. +For example, the following filter matches Barbara Jensen's entry and +entries for people with surnames following Jensen in alphabetic order, such +as entries with sn=Seuss and sn=Zhivago: +(sn>=jensen) + + +<= +Return entries whose attributes are less than or equal to +the value provided. +For example, the following filter matches Barbara Jensen's entry and +entries for people with surnames that precede Jensen in alphabetic order, +such as entries with sn=Anderson and sn=Cubbins: + +(sn<=jensen) + + +=* +Return entries that have a value set for the attribute (presence). + +For example, the following filter matches all entries that have a value +for the surname: +(sn=*) + + +~= +Return entries whose attribute value approximately matches +the specified value, such as the value sounds like the specified value. +For example, the following filter matches all entries with values for +surname that sound like Jensen, such as Barbara Jensen's entry, but also Emanuel +Johnson's entry: +(sn~=jensen) + + + +With Boolean operators and with parentheses, you can combine different +sets of conditions. Here is the syntax for combining search filters: +(boolean(filter1)( +filter2)(…)) +Following are descriptions of the valid boolean operators. + +& +Return entries that match all specified filters. + + +| +Return entries that match one or more of the specified filters. + + +! +Return entries that do not match the specified filter. +This operator is unary because you can apply the operator only to a +single set of results. In other words, to specify “entries that match +neither filter1 nor filter2,” +use the syntax: +(!(|(filter1)(filter2))) + + + + +You can also include wildcard characters to search for entries that +start with, contain, or end with a given value. For example, you can use the +following filter to search for all entries with first names that begin with +the letter F: +(givenName=F*) + +Specifying the Attributes to Retrieve + +attributes +operational + +attributes +retrieving in a search + +operational attributes + + +With the attrs parameter, you can retrieve all +attributes in entries returned by the search. Alternatively, you can specify +the attributes that you want returned in the search results. For example, +you can specify to return the attributes in one of the following ways: +To return selected attributes, pass an array of the attribute +names as the attrs parameter. For example, to return +only email addresses and phone numbers, pass the array {"mail", "telephoneNumber"} + as the attrs parameter. +To return all attributes in an entry, pass null as +the attrs parameter. +To return no attributes from an entry, pass LDAPv3.NO_ATTRS + as the attrs parameter. + +You might plan to sort the results on your client as described in Sorting the Search Results With Directory SDK +for Java. Return the attributes that you plan to use for sorting. +For example, if you plan to sort by email address, make sure that the mail +attribute is returned in the search results. +Some attributes are used by servers for administering the directory. +For example, the creatorsName attribute specifies the DN +of the user who added the entry. These attributes are called operational +attributes. +Servers do not normally return operational attributes in search results +unless you specify the attributes by name. For example, if you pass null + as the attrs parameter to retrieve all +of the attributes in entries found by the search, the operational attribute +creatorsName is not returned to your client. You need to explicitly +specify the creatorsName attribute in the attrs parameter. + +To return all attributes in an entry with selected operational attributes, +pass a string array containing LDAPv3.ALL_USER_ATTRS, +and also the names of the operational attributes as the attrs parameter. +Following are a few operational attributes and a description of what each +attribute contains. + +createTimestamp +The time when the entry was added to the directory. + + +modifyTimestamp +The time when the entry was last modified. + + +creatorsName +Distinguished name (DN) of the user who added the entry to +the directory. + + +modifiersName +DN of the user who last modified the entry. + + +subschemaSubentry +DN of the subschema entry, that controls the schema for this +entry. + + + + +Setting Search Preferences +For a given search, you can apply a set of preferences that determine +how the search is performed. For example, you can specify the maximum number +of results to be returned or the maximum amount of time to wait for a search. +The LDAPSearchConstraints class represents a +set of search constraints. The methods of this class allow you to get and +set the constraints. +Setting Preferences for All Searches + +search results +setting preferences + +The LDAPConnection object, which represents a +connection to the LDAP server, is associated with a default set of search +constraints. These constraints apply to all searches that you perform over +the connection. + +To get the default set of search constraints for the connection, +you can use the getSearchConstraints method. + +To get or set any of the search constraints individually, +you can use the getOption method and the setOption method. + + +For example, if you want to specify the maximum number of results returned, +you can set this constraint for the connection: +LDAPConnection ld = new LDAPConnection(); +ld.connect("ldap.example.com", LDAPv3.DEFAULT_PORT); +ld.setOption(LDAPv3.SIZELIMIT, new Integer(100)); + +Overriding Preferences for +Individual Searches +To override the default set of search constraints for a given search +request, construct your own LDAPSearchConstraints object. +Pass the object to the search method of the LDAPConnection + object. +You can also modify a copy of the existing search constraints. Pass +the modified set of constraints to the search method. Invoke +the getSearchConstraints method of the LDAPConnection + object to get the default set of constraints for that connection. +Then invoke the clone method of the LDAPSearchConstraints object +to make a copy of the set that you can then modify. +Configuring the Search to Wait +for All Results + +search results +waiting for all + +By default, the search method of the LDAPConnection + object does not block until all results are received. Instead, +the search method returns as soon as one of the results +has been received. + +If you want the search method to block until all +results are received, you can do one of the following: +Use the setOption method of the LDAPConnection + object to set the LDAPv3.BATCHSIZE preference +to 0. +Pass a 0 to the setBatchSize method +of the LDAPSearchConstraints object to change the behavior +for a particular set of search constraints. + +Whether waiting for one or all results of the search method, +you still need to invoke the next method of the returned +LDAPSearchResults object to retrieve each individual result. + +Setting Size and Time Limits + +search results +setting size limits + +search results +setting time limits + +By default, when you search the directory from a client that you built +with &DirectorySDKForJava;, the maximum number of entries to return is +set to 1000. No maximum time limit is set for waiting on +an operation to complete. + +To change these default values, you can do one of the following: +Use the setOption method of the LDAPConnection + object to set the LDAPv3.SIZELIMIT and +LDAPv3.TIMELIMIT preferences. +Use the setMaxResults method and the +setTimeLimit method of the LDAPSearchConstraints object +to change the behavior for a particular set of search constraints. + + + +When you set the size limit or time limit, you might cause an LDAPException + to be returned. The exception is returned when the limit is exceeded. + +If the size limit is exceeded, the server returns an LDAPException.SIZE_LIMIT_EXCEEDED + result code. +If the time limit is exceeded, the server returns an LDAPException.TIME_LIMIT_EXCEEDED + result code. + + + +Search Request Example +The following section of code searches for all entries with surname +Jensen. The search retrieves the names and values of the cn, +mail, and telephoneNumber attributes. +LDAPConnection ld = null; +try { + /* Create a new LDAPConnection object. */ + ld = new LDAPConnection(); + + /* Connect and bind to the server. */ + String HOSTNAME = "localhost"; + ld.connect(HOSTNAME, LDAPv3.DEFAULT_PORT, null, null); + + /* Specify the search criteria. */ + String baseDN = "dc=example,dc=com"; + int searchScope = LDAPv3.SCOPE_SUB; + String searchFilter = "(sn=Jensen)"; + String getAttrs[] = {"cn", "mail", "telephoneNumber"}; + + /* Send the search request. */ + LDAPSearchResults res = ld.search(baseDN, searchScope, + searchFilter, getAttrs, false); +} catch(LDAPException e) { + System.out.println("Error: " + e.toString); +} + + +Getting the Search Results With &DirectorySDKForJava; + +search results +getting + +When you invoke the search method of an LDAPConnection + object to search the directory, the method returns the search +results in the form of an LDAPSearchResults object. +The search results consist of an enumeration of entries, which are represented +by LDAPEntry objects. The search results can also include +smart referrals, also known as search references, and +exceptions. +Each entry contains a set of attributes, which are represented by +LDAPAttributeSet objects. Individual attributes are represented +by LDAPAttribute objects. Each attribute has a set +of values that you can get. +The following figure illustrates the relationship between entries, attributes, +values, and search results. +
Entries, Attributes, and Values in +Search Results + + +Relationship between entries, attributes, values, and +search results + +
+Getting Entries + +entries +getting from search results + +search results +getting entries + +The LDAPSearchResults object represents the results +of the search. These results can include entries found by the search, search +references, and result codes. Your LDAP client can receive an ADMIN_LIMIT_EXCEEDED +, TIME_LIMIT_EXCEEDED, or SIZE_LIMIT_EXCEEDED + result code from the server. When the result code is received, &DirectorySDKForJava; adds +an exception for this result code to the search results. +To get entries from the LDAPSearchResults object, +you can either invoke the next method or the nextElement + method. + +When you invoke the next method, if the +next item in the search results is an entry, the method returns an LDAPEntry + object. + + +referrals +LDAPReferralException and + +referrals +getting from search results +If the next item is a search reference, one of the following can +occur: +If referrals are not followed automatically, an LDAPReferralException + is returned. The exception is also returned if the referral hop +limit is exceeded. +The LDAP Java classes follow the referral when two conditions +are fulfilled. Referrals must be followed automatically, the referral hop +limit must not be exceeded. + +The classes also retrieve the entry for you. The method creates a new +connection to the server that is specified in the referral and attempts to +retrieve the entry from that server.See Handling Referrals With Directory SDK for Java for +more information about referrals and search references.If the +next item is an LDAP result code such as ADMIN_LIMIT_EXCEEDED, +TIME_LIMIT_EXCEEDED, or SIZE_LIMIT_EXCEEDED, +the LDAP Java classes return an LDAPException. + +When you invoke the nextElement method, +the method returns an object that you must cast. The object is an LDAPEntry + object, an LDAPReferralException, or an +LDAPException. + +As you iterate through the search results, you can invoke the hasMoreElements + method to determine if you have reached the end of the search results. + +LDAPConnection ld = null; +try { + /* Create a new LDAPConnection object. */ + ld = new LDAPConnection(); + + /* Set up parameters for the search request... */ + + /* Send the search request. */ + LDAPSearchResults res = ld.search(baseDN, searchScope, + searchFilter, getAttrs, false); + + /* Iterate through the results until finished. */ + while (res.hasMoreElements()) { + + /* Get the next entry in the results. */ + LDAPEntry findEntry = null; + try { + findEntry = res.next(); + + /* If it is a referral, print the LDAP URLs. */ + } catch (LDAPReferralException e) { + System.out.println("Search references: "); + LDAPUrl refUrls[] = e.getURLs(); + for (int i=0; i < refUrls.length; i++) { + System.out.println("\t" + refUrls[i].getUrl()); + } + continue; + } catch (LDAPException e) { + System.out.println("Error: " + e.toString()); + continue; + } + /* Do something with the entry... */ + } +} catch (LDAPException e) { + /* Handle exceptions arising outside the search... */ +} + +Getting Distinguished Names + +distinguished names +getting from search results + +search results +getting distinguished names + +To get the distinguished name of an LDAPEntry object, +invoke the getDN method. This method returns a String +. +LDAPEntry nextEntry = res.next(); +String nextDN = nextEntry.getDN(); +Although the netscape.ldap package includes an +LDAPDN class, you typically do not construct objects of this class +to represent DNs. The LDAPDN class is mainly a utility +class that provides methods for manipulating string DNs. +Getting Attributes + +attributes +getting from search results + +search results +getting attributes + +To get the set of attributes in an LDAPEntry object, +invoke the getAttributeSet method. This method returns +an LDAPAttributeSet object. +LDAPEntry nextEntry = res.next(); +LDAPAttributeSet entryAttrs = nextEntry.getAttributeSet(); +To get individual attributes from an LDAPAttributeSet object, +invoke the getAttributes method. This method returns an +enumeration of attributes. You can then iterate through the elements in this +enumeration to retrieve individual LDAPAttribute objects. +/* Get the set of attributes for an entry. */ +LDAPAttributeSet entryAttrs = nextEntry.getAttributeSet(); + +/* Get an enumeration of those attribute. */ +Enumeration enumAttrs = entryAttrs.getAttributes(); + +/* Loop through the enumeration to get each attribute. */ +while (enumAttrs.hasMoreElements()) { + LDAPAttribute attr = (LDAPAttribute)enumAttrs.nextElement(); + System.out.println("Attribute type: " + attr.getName()); +} +To determine the number of attributes in the LDAPAttributeSet object, +invoke the size method. + +You can also retrieve a specific attribute from the entry or from the +attribute set. +To get a specific attribute from an LDAPEntry object, +invoke the getAttribute method. +To get a specific attribute from an LDAPAttributeSet object, +invoke the getAttribute method. + +Both methods return an LDAPAttribute object. +LDAPEntry nextEntry = res.next(); +LDAPAttribute anAttr = nextEntry.getAttribute("cn"); + +Getting Attribute Types +and Values + +attributes +getting from search results + +search results +getting attribute types + +search results +getting attribute values + +To get the name of an LDAPAttribute object, invoke +the getName method. +LDAPAttribute nextAttr = (LDAPAttribute)enumAttrs.nextElement(); +String attrName = nextAttr.getName(); + +To get the values in an LDAPAttribute object, +you can use the following methods: +To get the String values, invoke the +getStringValues method. +To get the binary values as byte arrays, invoke the getByteValues + method. + +Both methods return an enumeration that you can iterate through to retrieve +individual results. For example, if an error occurs when you invoke getStringValues +, although the values are binary data, the methods return null +. +You can also count the number of values in an attribute by invoking +the size method of the LDAPAttribute object. + +LDAPAttribute nextAttr = (LDAPAttribute)enumAttrs.nextElement(); + +/* Get and print the attribute name. */ +String attrName = nextAttr.getName(); +System.out.println("\t" + attrName + ":"); + +/* Iterate through the attribute's values. */ +Enumeration enumVals = nextAttr.getStringValues(); +if (enumVals != null) { + while (enumVals.hasMoreElements()) { + String nextValue = (String)enumVals.nextElement(); + System.out.println("\t\t" + nextValue); + } +} + +
+Sorting the Search Results With &DirectorySDKForJava; + +search results +sorting + +sorting search results + + +With &DirectorySDKForJava;, you can sort the search results in two +ways. +You can specify that the LDAP server should sort the results +before returning the results to your client.Send a server-side +sort control to the server as described in Chapter 10, +LDAP Controls With Directory SDK for Java. Server-side sorting might +work best if you specify a filter that uses an indexed attribute. + +After you receive the results from the server, you can sort +the results on your client.Specify the names of the attributes +that you want to use for sorting. You also need to specify whether or not +the sorting is done in ascending or descending order. + +You can sort the results on the client by invoking the sort method of +the LDAPSearchResults object. + +LDAPEntryComparator interface +example of + +LDAPEntryCompareAttrNames class +example of +When invoking this method, you need to pass a comparator object, +which is an object of a class that implements the LDAPEntryComparator interface. &DirectorySDKForJava; includes +an LDAPCompareAttrNames class that implements this +interface. This class specifies how entries are compared with each other and +sorted. +To construct an LDAPCompareAttrNames object, +you need to specify the attributes that you want to use for sorting and, optionally, +the sort order. When sorting on the client side, the attributes used for sorting +must be returned in the search results. If you are returning only a subset +of attributes in the search results, include the attributes that you specify +in the LDAPCompareAttrNames constructor. For example, +the following section of code sorts first by surname, sn, +and then by common name, cn, in ascending order: +LDAPConnection ld = new LDAPConnection(); +ld.connect("localhost", LDAPv3.DEFAULT_PORT); +LDAPSearchResults res = ld.search("dc=example,dc=com", LDAPv3.SCOPE_SUB, + "(objectclass=inetOrgPerson)", null, false); +String[] sortAttrs = {"sn", "cn"}; +boolean[] ascending = {true, true}; +res.sort(new LDAPCompareAttrNames(sortAttrs, ascending)); +If all search results have not yet been returned, the sort method +blocks until all results have been received. +Abandoning a Search With &DirectorySDKForJava; + +abandoning a search + +searching the directory +abandoning a search + +At any point during a search operation, you can send a request to the +server to abandon (cancel) the search. To abandon the search, use the abandon + method of the LDAPConnection object. Pass +in the LDAPSearchResults object that was returned to +you when you first invoked the search method. +Searching the Directory With &DirectorySDKForJava; + +searching the directory +example of + +The following example prints the values of all attributes in the entries +returned by a search. +Searching for a Specific Entry +import netscape.ldap.*; +import java.util.*; + +public class Search { + public static void main(String[] args) { + try { + UserArgs userArgs = new UserArgs("Search", args, false); + LDAPConnection ld = new LDAPConnection(); + ld.connect(userArgs.getHost(), userArgs.getPort()); + + /* search for all entries with surname of Jensen */ + String MY_FILTER = "sn=Jensen"; + String MY_SEARCHBASE = "dc=example,dc=com"; + + LDAPSearchConstraints cons = ld.getSearchConstraints(); + /* Setting the batchSize to one will cause the result + enumeration below to block on one result at a time, + enabling an update of a list or other things as + results come in. */ + /* This could be set to 0 in order to get all + results and to block until then. */ + cons.setBatchSize(1); + LDAPSearchResults res = ld.search(MY_SEARCHBASE, + LDAPConnection.SCOPE_SUB, MY_FILTER, null, false, cons); + + /* Loop on results until finished */ + while (res.hasMoreElements()) { + LDAPEntry findEntry = null; + try { + findEntry = res.next(); + } catch (LDAPReferralException e) { + System.out.println("Search reference: "); + LDAPUrl refUrls[] = e.getURLs(); + for (int i=0; i<refUrls.length; i++) { + System.out.println("\t" + refUrls[i].getUrl()); + } + continue; + } catch (LDAPException e) { + System.out.println("Error: " + e.toString()); + continue; + } + System.out.println(findEntry.getDN()); + + /* Get the attributes of the entry */ + LDAPAttributeSet findAttrs = findEntry.getAttributeSet(); + Enumeration enumAttrs = findAttrs.getAttributes(); + System.out.println("\tAttributes: "); + + /* Loop on attributes */ + while (enumAttrs.hasMoreElements()) { + LDAPAttribute anAttr = + (LDAPAttribute)enumAttrs.nextElement(); + String attrName = anAttr.getName(); + System.out.println("\t\t" + attrName); + + /* Loop on values for this attribute */ + Enumeration enumVals = anAttr.getStringValues(); + if (enumVals != null) { + while (enumVals.hasMoreElements()) { + String aVal = (String)enumVals.nextElement(); + System.out.println("\t\t\t" + aVal); + } + } + } + } + ld.disconnect(); + } catch(LDAPException e) { + System.out.println("Error: " + e.toString()); + } + } +} + + +Reading an Entry With &DirectorySDKForJava; + +entries +reading from directory + +reading an entry from the directory + +To get a single entry from the directory, use the read method +of the LDAPConnection object. You can specify the DN +of the entry with the attributes that you want to retrieve, instead of retrieving +all attributes of the entry. You can also specify an LDAP URL that identifies +the entry that you want to retrieve. +To retrieve data from the entry, you can use the same classes with their +methods, as described in Getting +Attributes and in +Getting Attribute Types and Values. +The following example retrieves an entry and prints the values of its +attributes. +Retrieving a Specific Entry +import netscape.ldap.*; +import java.util.*; + +public class RdEntry { + public static void main(String[] args) { + try { + UserArgs userArgs = new UserArgs("PasswordPolicy", args, false); + LDAPConnection ld = new LDAPConnection(); + ld.connect(userArgs.getHost(), userArgs.getPort()); + + String ENTRYDN = "uid=bjensen, ou=People, dc=example,dc=com"; + + /* Read all attributes */ + LDAPEntry findEntry = ld.read(ENTRYDN); + System.out.println(findEntry.getDN()); + + /* Get the attributes of the entry */ + LDAPAttributeSet findAttrs = findEntry.getAttributeSet(); + Enumeration enumAttrs = findAttrs.getAttributes(); + System.out.println("\tAttributes: "); + + /* Loop on attributes */ + while (enumAttrs.hasMoreElements()) { + LDAPAttribute anAttr = + (LDAPAttribute)enumAttrs.nextElement(); + String attrName = anAttr.getName(); + System.out.println("\t\t" + attrName); + + /* Loop on values for this attribute */ + Enumeration enumVals = anAttr.getStringValues(); + if (enumVals != null) { + while (enumVals.hasMoreElements()) { + String aVal = (String)enumVals.nextElement(); + System.out.println("\t\t\t" + aVal); + } + } + } + ld.disconnect(); + } catch(LDAPException e) { + System.out.println("Error: " + e.toString()); + } + } +} + + +Listing Child Entries With &DirectorySDKForJava; + +entries +retrieving child entries of + +To retrieve the entries directly beneath a particular entry, set the +starting point of the search to the entry. Also, set the scope of the search +to LDAPv3.SCOPE_ONE. +
Using Scope of One to Retrieve Child Entries + + +Search for child entries + +
+The following code performs a one-level search: +LDAPConnection ld = null; +try { + ld = new LDAPConnection(); + ld.connect("localhost", LDAPv3.DEFAULT_PORT); + + LDAPSearchResults res = ld.search("dc=example,dc=com", LDAPv3.SCOPE_ONE, + "(objectclass=*)", null, false ); + + /* Loop on results until finished */ + while (res.hasMoreElements()) { + LDAPEntry findEntry = null; + try { + findEntry = res.next(); + + /* If the next result is a referral, print the LDAP URLs. */ + } catch (LDAPReferralException e) { + System.out.println("Search references: "); + LDAPUrl refUrls[] = e.getURLs(); + for (int i=0; i < refUrls.length; i++) { + System.out.println("\t" + refUrls[i].getUrl()); + } + continue; + } catch ( LDAPException e ) { + System.out.println("Error: " + e.toString()); + continue; + } + + /* Print the DN of the entry. */ + System.out.println(findEntry.getDN()); + + /* Get the attributes of the entry */ + LDAPAttributeSet findAttrs = findEntry.getAttributeSet(); + Enumeration enumAttrs = findAttrs.getAttributes(); + System.out.println("\tAttributes: "); + /* Loop on attributes */ + while (enumAttrs.hasMoreElements()) { + LDAPAttribute anAttr = (LDAPAttribute)enumAttrs.nextElement(); + String attrName = anAttr.getName(); + System.out.println("\t\t" + attrName); + + /* Loop on values for this attribute */ + Enumeration enumVals = anAttr.getStringValues(); + if (enumVals != null) { + while (enumVals.hasMoreElements()) { + String aVal = (String)enumVals.nextElement(); + System.out.println("\t\t\t" + aVal); + } + } + } + } +} catch( LDAPException e ) { + System.out.println("Error: " + e.toString()); +} + +/* Done, so disconnect. */ +if ((ld != null) && ld.isConnected()) { + try { + ld.disconnect(); + } catch (LDAPException e) { + System.out.println("Error: " + e.toString()); +} +
+ diff --git a/mozilla/directory/docs/ldapjdk/jdk-server-info.sgm b/mozilla/directory/docs/ldapjdk/jdk-server-info.sgm new file mode 100644 index 00000000000..9af59075a5d --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/jdk-server-info.sgm @@ -0,0 +1,575 @@ + +Getting Server Information With &DirectorySDKForJava; + + +This chapter explains how to access and modify information about your +LDAP server over the LDAP protocol. + +This chapter covers the following topics: +About DSEs + +Getting the Root DSE +With Directory SDK for Java +Checking Support for +LDAP v3 With Directory SDK for Java +Getting Schema Information +With Directory SDK for Java + + +About DSEs +The acronym DSE refers to a DSA-specific +entry in the directory. A DSA is a directory system agent, +an X.500 term for a directory server. A DSE contains information specific +to the server. +LDAP v3 uses the concept of the root DSE. In +a directory tree, the root of the tree is the root DSE. The root DSE is not +part of any naming context. In other words, the entry is superior to dc=example,dc=com +, cn=config, and similar suffixes in the directory +tree. Servers that do not support LDAP v3 therefore do not necessarily have +a root DSE. + +The root DSE can contain the following information: +The naming contexts the server supports, such as dc=example,dc=com + or cn=config +URLs to alternate servers that can be contacted if the server +is unavailable +The LDAP v3 extended operations the server supports + +The LDAP v3 controls the server supports +The SASL mechanisms the server supports +The versions of LDAP the server supports +Additional, server-specific information + + +Getting the Root DSE With &DirectorySDKForJava; + + +DSE +root + +root DSE + +The root DSE for an LDAP server specifies information about the server. +The attributes of the root DSE and what the attributes provide are shown here. + +altServer +LDAP URLs that identify other servers to contact when the +server is not available. + + +namingContexts +Naming contexts, such as dc=example,dc=com, +supported by the server. + + +supportedControl +Object identifiers (OIDs) of LDAP v3 +controls supported by the server. +If this attribute is not present, the server does not support LDAP v3 +controls. + + +supportedExtension +Object identifiers (OIDs) of LDAP v3 extended operations supported +by the server. +If this attribute is not present, the server does not support LDAP v3 +extended operations. + + +supportedLDAPVersion +Versions of LDAP, 2 or 3, +supported by the server. + + +supportedSASLMechanisms +Names of SASL mechanisms supported by the server. +If this attribute is not present, the server does not support any SASL +mechanisms. + + + + +To access the root DSE of an LDAP server, do the following: +Turn off automatic referral handling, and connect to the LDAP +server.See Creating +a Connection and Setting Preferences With Directory SDK for Java and Connecting to an LDAP Server +With Directory SDK for Java. See also Handling Referrals With Directory SDK for Java for +instructions. + + +Search the directory with the following criteria: +Set the search scope to a base search. + +Specify an empty string for the base DN. +Use the search filter (objectclass=*). + + +Refer to Chapter 4, Searching the Directory With Directory SDK for Java for instructions. +If an LDAPException is returned with a result +code such as OPERATION_ERROR, PROTOCOL_ERROR +, REFERRAL, or NO_SUCH_OBJECT +, the LDAP server probably does not support LDAP v3. + + +The following code excerpt retrieves the root DSE, and then displays +the attributes. +/* Create a new connection. */ +LDAPConnection ld = new LDAPConnection(); +String hostname = "localhost"; +int portnumber = LDAPv3.DEFAULT_PORT; + +try { + /* Connect to the LDAP server. */ + ld.connect(3, hostname, portnumber); + + int MY_SCOPE = LDAPv3.SCOPE_BASE; + String MY_FILTER = "(objectclass=*)"; + String MY_SEARCHBASE = ""; + LDAPSearchResults res = ld.search(MY_SEARCHBASE, + MY_SCOPE, MY_FILTER, null, false); + + /* There should be only one result (the root DSE). */ + while (res.hasMoreElements()) { + LDAPEntry findEntry = (LDAPEntry)res.nextElement(); + + /* Get the attributes of the root DSE. */ + LDAPAttributeSet findAttrs = findEntry.getAttributeSet(); + Enumeration enumAttrs = findAttrs.getAttributes(); + + /* Iterate through each attribute. */ + while (enumAttrs.hasMoreElements()) { + LDAPAttribute anAttr = (LDAPAttribute)enumAttrs.nextElement(); + + /* Get and print the attribute name. */ + String attrName = anAttr.getName(); + System.out.println(attrName); + + /* Get the values of the attribute. */ + Enumeration enumVals = anAttr.getStringValues(); + + /* Get and print each value. */ + if (enumVals == null) { + System.out.println("\tNo values found."); + continue; + } + while (enumVals.hasMoreElements()) { + String aVal = (String)enumVals.nextElement(); + System.out.println("\t" + aVal); + } + } + } +} catch( LDAPException e ) { + System.out.println("Error: " + e.toString()); +} + +Checking Support for LDAP v3 With &DirectorySDKForJava; + + +LDAP servers +protocol version supported + +You can determine what version an LDAP server supports by getting the +supportedLDAPVersion attribute from the root DSE. This attribute +should contain the value 3. The attribute can also contain +other values, such as 2, so iterate through the values +of this attribute. +You are not required to authenticate or bind before performing a search. +Unlike LDAP v2, LDAP v3 states that clients do not need to bind to the server +before performing LDAP operations. The following section of code connects +to an LDAP server. The code then determines whether the server supports LDAP +v3. +/* Create a new connection. */ +LDAPConnection ld = new LDAPConnection(); +String hostname = "localhost"; +int portnumber = LDAPv3.DEFAULT_PORT; + +boolean supportsV3 = false; + +try { + /* Connect to the LDAP server. */ + ld.connect( 3, hostname, portnumber ); + + int MY_SCOPE = LDAPv3.SCOPE_BASE; + String MY_FILTER = "(objectclass=*)"; + String MY_SEARCHBASE = ""; + LDAPSearchResults res = ld.search(MY_SEARCHBASE, + MY_SCOPE, MY_FILTER, null, false); + + /* There should be only one result (the root DSE). */ + while (res.hasMoreElements()) { + LDAPEntry findEntry = (LDAPEntry)res.nextElement(); + + /* Get the supportedLDAPVersion attribute values. */ + LDAPAttribute versionAttr = + findEntry.getAttribute("supportedLDAPVersion"); + + /* Check for "3". */ + Enumeration enumVals = versionAttr.getStringValues(); + if (enumVals == null) { + System.out.println("\tNo values found."); + continue; + } + while (enumVals.hasMoreElements()) { + String aVal = (String)enumVals.nextElement(); + if (aVal.equalsIgnoreCase("3")) { + supportsV3 = true; + break; + } + } + } +} catch( LDAPException e ) { + System.out.println("Error: " + e.toString()); +} + +if (supportsV3) { + System.out.println("This server supports LDAP v3."); +} else { + System.out.println("This server does not support LDAP v3."); +} + +Getting Schema Information With &DirectorySDKForJava; + + +LDAP servers +schema + +schema + +In LDAP v3, you can get LDAP schema over LDAP. You can also modify schema +over LDAP. This section explains how to carry out such modifications. +Understanding Schema Over LDAP +An entry can specify the schema that defines the object classes, attributes, +syntaxes, and matching rules used by the directory. This entry is called the +subschema entry. +To find the DN of the subschema entry, get the subschemaSubentry operational +attribute from the root DSE or from any entry. This code excerpt demonstrates +how to retrieve the subschema entry DN. +LDAPConnection ld = null; +try { + ld = new LDAPConnection(); + ld.connect("localhost", LDAPv3.DEFAULT_PORT); + + String [] schemaAttr = {"subschemaSubentry"}; + LDAPEntry rootDSE = ld.read("", schemaAttr); + LDAPAttribute resAttr = rootDSE.getAttribute(schemaAttr[0]); + Enumeration enumVals = resAttr.getStringValues(); + if (enumVals != null) { + while (enumVals.hasMoreElements()) { + System.out.println(schemaAttr[0] + ": " + + (String)enumVals.nextElement()); + } + } + ld.disconnect(); +} catch(LDAPException e) { + System.out.println("Error: " + e.toString()); +} +The subschema entry can have the following attributes. + +objectClasses +Specifies the object class definitions in the schema. +Each value of this attribute is an object class that is known to the +server. + + +attributeTypes +Specifies the attribute type definitions in the schema. +Each value of this attribute is an attribute type that is known to the +server. + + +matchingRules +Specifies the matching rule definitions in the schema. +Each value of this attribute is a matching rule that is known to the +server. + + +matchingRuleUse +Specifies the use of a matching rule in the schema. +Each value of this attribute is a matching rule use description. A matching +rule use description specifies the OIDs of the attributes that can be used +with this extensible matching rule. + + +syntaxes +Specifies the syntax definitions in the schema. +Each value of this attribute is syntax that is known to the server. + + + +In &DirectorySDKForJava;, the schema and elements in the schema are +represented by classes in the netscape.ldap package. These +classes include the following. + +LDAPSchema +Schema used by an LDAP server + + +LDAPSchemaElement +Base class that represents a generic element in the schema + + +LDAPObjectClassSchema +Object class description in the schema + + +LDAPAttributeSchema +Attribute type description in the schema + + +LDAPMatchingRuleSchema +Matching rule description in the schema + + +LDAPMatchingRuleUseSchema +Use of a matching rule in the schema + + +LDAPSyntaxSchema +Syntax description in the schema + + + +These classes with their methods handle the subschema entry by using +standard LDAP operations, such as search and modify. + +Getting Information About LDAP Schema +To get the schema for an LDAP v3 server, construct a new LDAPSchema + object. Then, invoke the fetchSchema method, +passing in an LDAPConnection object. +LDAPConnection ld = new LDAPConnection(); +/* Construct an LDAPSchema object to hold the schema to retrieve. */ +LDAPSchema dirSchema = new LDAPSchema(); +try { + ld.connect(hostname, portnumber, bindDN, bindPW); + /* Get the schema. Anonymous access is OK. */ + dirSchema.fetchSchema(ld); + /* Use the schema. */ +} catch (Exception e) { + System.err.println(e.toString()); +} + +Working With Object Class +Descriptions +In the LDAP Java classes, the object class descriptions in a schema +are represented by objects of the LDAPObjectClassSchema class. + + +To get the object class descriptions from the schema, invoke one of +the following methods: +To get an enumeration of LDAPObjectClassSchema objects +that represent the object classes in the schema, invoke the getObjectClasses + method. +To get a specific object class description, invoke the getObjectClass + method and pass in the name of the object class. +To get an enumeration of the names of object classes in the +schema, invoke the getObjectClassNames method. + + + +An object class description consists of the following information, which +you can retrieve by invoking methods of the LDAPObjectClassSchema object: + +An OID that identifies the object class, retrieved by invoking +the getOID method +A name that identifies the object class, retrieved by invoking +the getName method +A description that identifies the object class, retrieved +by invoking the getDescription method +A name that identifies the parent object class, retrieved +by invoking the getSuperior method +The list of required attributes, retrieved by invoking the +getRequiredAttributes method +The list of optional attributes that are allowed, retrieved +by invoking the getOptionalAttributes method + + +To add an object class description to the schema, construct a new +LDAPObjectClassSchema object. You can specify the pieces of information +in the object as individual arguments or in a description formatted according +to RFC 4517, +Lightweight Directory Access Protocol (LDAP): Syntaxes and Matching Rules. + +Then, you can either invoke the add method of this +object or the addObjectClass method of the LDAPSchema + object. +To remove an object class description, invoke the remove method +of this object. +Working With Attribute +Type Descriptions +In the LDAP Java classes, the attribute type descriptions in a schema +are represented by objects of the LDAPAttributeSchema class. + + +To get the attribute type descriptions from the schema, invoke one of +the following methods: +To get an enumeration of LDAPAttributeSchema objects +that represent the attribute types in the schema, invoke the getAttributes + method. +To get a specific attribute type description, invoke the +getAttribute method and pass in the name of the attribute type. + +To get an enumeration of the names of attribute types in the +schema, invoke the getAttributeNames method. + + + +An attribute type description consists of the following information, +which you can retrieve by invoking methods of the LDAPAttributeSchema object: + +An OID that identifies the attribute type, retrieved by invoking +the getOID method +A name that identifies the attribute type, retrieved by invoking +the getName method +A description that identifies the attribute type, retrieved +by invoking the getDescription method +The syntax used by the attribute type, retrieved by invoking +the getSyntax method +An indication whether the attribute type is single-valued +or multivalued, retrieved by invoking the isSingleValued method + + +To add an attribute type description to the schema, construct a new +LDAPAttributeSchema object. You can specify the pieces of information +in the object as individual arguments or in a description formatted according +to RFC 4517, +Lightweight Directory Access Protocol (LDAP): Syntaxes and Matching Rules. + +Then, you can either invoke the add method of this +object or the addAttributeType method of the LDAPSchema + object. +To remove an attributeType description, invoke the +remove method of this object. +Working With Matching +Rule Descriptions +In the LDAP Java classes, the matching rule and matching rule use descriptions +in a schema are represented by objects of the LDAPMatchingRuleSchema class. + + +To get the matching rule descriptions from the schema, invoke one of +the following methods: +To get an enumeration of LDAPMatchingRuleSchema objects +that represent the matching rules in the schema, invoke the getMatchingRules + method. +To get a specific matching rule description, invoke the +getMatchingRule method and pass in the name of the matching rule. + +To get an enumeration of the names of matching rules in the +schema, invoke the getMatchingRuleNames method. + + + +A matching rule description consists of the following information, which +you can retrieve by invoking methods of the LDAPMatchingRuleSchema object: + +An OID that identifies the matching rule, retrieved by invoking +the getOID method +A name that identifies the matching rule, retrieved by invoking +the getName method +A description that identifies the matching rule, retrieved +by invoking the getDescription method +The syntax of the matching rule, retrieved by invoking the +getSyntax method + +To add a matching rule description to the schema, construct a new +LDAPMatchingSchema object. You can specify the pieces of information +in the object as individual arguments or in a description formatted according +to RFC 4517, Lightweight Directory Access Protocol (LDAP): +Syntaxes and Matching Rules. +Then, you can either invoke the add method of this +object or the addMatchingRule method of the LDAPSchema + object. +To remove a matching rule description, invoke the remove method +of this object. +Example of Working With Schema +The following example illustrates how to get the schema and how to add +object classes and attribute types. +import netscape.ldap.*; +import java.util.*; + +public class GetSchema { + public static void main(String[] args) { + try { + UserArgs userArgs = new UserArgs("GetSchema", args, true); + LDAPConnection ld = new LDAPConnection(); + ld.connect(userArgs.getHost(), userArgs.getPort()); + ld.authenticate(userArgs.getBindDN(), userArgs.getPassword()); + + /* Get the schema. */ + LDAPSchema dirSchema = new LDAPSchema(); + dirSchema.fetchSchema(ld); + + /* Get and print the inetOrgPerson object class. */ + LDAPObjectClassSchema objClass = + dirSchema.getObjectClass("inetOrgPerson"); + if (objClass != null) + System.out.println("inetOrgPerson := " + + objClass.toString()); + + /* Get and print the userPassword attribute. */ + LDAPAttributeSchema attrType = + dirSchema.getAttribute("userpassword"); + if (attrType != null) + System.out.println("userPassword := " + + attrType.toString()); + + /* Add a new object class. Requires write access. */ + String[] requiredAttrs = {"cn", "mail"}; + String[] optionalAttrs = {"sn", "telephoneNumber"}; + LDAPObjectClassSchema newObjClass = + new LDAPObjectClassSchema("newInetOrgPerson", + "1.2.3.4.5.6.7", "top", "Experiment", + requiredAttrs, optionalAttrs); + + /* Add the new object class to the schema. */ + newObjClass.add(ld); + + /* Create a new attribute type "hairColor". */ + LDAPAttributeSchema newAttrType = + new LDAPAttributeSchema("hairColor", + "1.2.3.4.5.4.3.2.1", "Blonde, red, etc", + LDAPAttributeSchema.cis, false); + + /* Add the new attribute type to the schema. */ + newAttrType.add(ld); + + /* Fetch schema again to verify changes */ + dirSchema.fetchSchema(ld); + + /* Get and print the new attribute type. */ + newAttrType = dirSchema.getAttribute("hairColor"); + if (newAttrType != null) + System.out.println("hairColor := " + + newAttrType.toString()); + + /* Get and print the new object class. */ + newObjClass = dirSchema.getObjectClass("newInetOrgPerson"); + if (newObjClass != null) + System.out.println("newInetOrgPerson := " + + newObjClass.toString()); + + ld.disconnect(); + } catch ( Exception e ) { + System.err.println(e.toString()); + System.exit(1); + } + } +} + + + diff --git a/mozilla/directory/docs/ldapjdk/jdk-ssl.sgm b/mozilla/directory/docs/ldapjdk/jdk-ssl.sgm new file mode 100644 index 00000000000..68ec0e8f283 --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/jdk-ssl.sgm @@ -0,0 +1,209 @@ + +SSL Connections With &DirectorySDKForJava; + +This chapter describes the process of enabling an LDAP client to connect +to an LDAP server over the Secure Sockets Layer (SSL) protocol. The chapter +explains how to connect to an LDAP server with SSL. It also covers SSL authentication. + + +This chapter covers the following topics: +How SSL Works With Directory +SDK for Java +Prerequisites for Connecting +Over SSL With Directory SDK for Java +Connecting to a Server Over +SSL With Directory SDK for Java +Using Certificate-Based +Client Authentication With Directory SDK for Java + + +How SSL Works With &DirectorySDKForJava; +&DirectorySDKForJava; includes classes and methods to enable your +application to connect to an LDAP server over a Secure Sockets +Layer (SSL). +Understanding SSL +The primary goal of the SSL Protocol is to provide privacy and reliability +between two communicating applications. For more information about SSL and +Transport Layer Security, refer to RFC 2246, +The TLS Protocol. +The &DirectorySDKForJava; supports SSL 3.0. +SSL and LDAP +When an LDAP client connects to an LDAP server over SSL, the LDAP server +identifies itself by sending its certificate to the +LDAP client. The LDAP client needs to determine whether or not the certificate +authority (CA) who issued the certificate is trusted. +The LDAP server can also request that the client send a certificate +to authenticate. This process is called certificate-based client +authentication. +After receiving the client's certificate, the LDAP server determines +whether or not the CA who issued the certificate is trusted. If the CA is +trusted, the server uses the subject name in the certificate. With the subject +name, the server determines if the client has access rights to perform the +requested operation. +To use SSL, you need a certificate database to +hold the CA certificate. If certificate-based client authentication is used, +you need the client certificate. +Interfaces and Classes for SSL +&DirectorySDKForJava; includes the LDAPSocketFactory interface. +This interface describes a single method, makeSocket, that +returns a socket to a given server specified by a host name and port number. +To establish an SSL connection, you need to create an object of a class that +implements this interface. +Classes that implement this interface rely on a separate class that +implements SSL sockets. In the constructors for objects that implement +LDAPSocketFactory, you typically need to specify the name of a +class that implements SSL sockets. The following classes implement this interface. + + +LDAPSSLSocketFactory +Use this class if you are using the netscape.net.SSLSocket + class to implement SSL sockets. You can also use this class if +the class that implements SSL sockets extends the Socket object. + + + +LDAPSSLSocketWrapFactory +Use this class if the class that implements SSL sockets does +not extend the Socket object. The LDAPSSLSocketWrapFactory + class wraps your SSL socket implementation class in a class that +does extend the Socket object. + + +JSSESocketFactory +Use this class to rely on the standard SSL socket factory +code. + + + +You can construct an object for one of these factory classes. You can +pass the factory object to the constructor for the LDAPConnection object, +to identify the socket factory that is used for the connection. + +Prerequisites for Connecting Over SSL +With &DirectorySDKForJava; + +The LDAP Java classes that enable you to connect over SSL assume the +following: +Your client has access to a Netscape Security Services (NSS) +certificate database.If your client runs in a Netscape or Mozilla +browser, you can use the browser certificate database. With the browser certificate +database, you can determine if you trust the certificate that is sent from +the server. +The database used contains one of the following certificates: + +The certificate of the CA who issued the server certificate + +If the CAs are organized hierarchically, the certificate of +any CA in the hierarchy +The certificate of the server + + +The CA certificate is marked as trusted in +the database. +If you use certificate-based client authentication, you must +have the following data: + +A client certificate issued by a CA trusted by the LDAP server +This certificate must be in the client certificate database. + +A public key, private key pair in an NSS key database on the +client side + + + +When your client sends an initial request to the secure LDAP server, +the server sends its certificate back to your client. Your client determines +which CA issued the server's certificate. Your client then searches the certificate +database for the certificate of the issuing CA. +Your client might not find the CA certificate. Your client might also +find that the CA certificate is marked as not trusted. +If either condition occurs, your client refuses to connect to the server. +If you are using certificate-based client authentication, your client +retrieves its certificate from the certificate database. Your client sends +the certificate to the server for authentication. The server determines which +CA issued the client certificate. The server then searches its certificate +database for the certificate of the issuing CA. +The server might not find the CA certificate. The CA certificate might +be marked as not trusted. If either condition occurs, the +server refuses to authenticate your client. +Connecting to a Server Over SSL With &DirectorySDKForJava; + +To connect to an LDAP server with SSL, do the following: +Construct a new LDAPSSLSocketFactory object +or a new LDAPSSLSocketWrapFactory object.This +object represents the SSL socket factory used to create the sockets for establishing +connections with the LDAP server.The constructors for these classes +allow you to specify the name of the class used to create the actual sockets. + +For the LDAPSSLSocketFactory constructor, +you should specify a class that implements the javax.net.ssl.SSLSocket + interface. By default, if you do not specify a class, the +netscape.net.SSLSocket class is used. +If the SSL socket class does not extend the Socket class, +use the LDAPSSLSocketWrapFactory constructor. + + + +Pass the object that you constructed to the LDAPConnection + constructor.When first you establish a connection +to the LDAP server, use the makeSocket method of the specified +object that you used to construct the socket. + +Using Certificate-Based Client Authentication +With &DirectorySDKForJava; + +authentication +certificate-based + +certificate-based client authentication + +Some LDAP servers might be configured to use certificate-based client +authentication. A server might request that your client sends a certificate +to identify itself. + +With &DirectorySDKForJava;, you can set up your client to perform +certificate-based authentication in either of the following situations: +Your client runs as an applet in a Netscape or Mozilla browser + +Your client uses a class implementing the LDAPSocketFactory + interface and supporting client-based authentication + + + +When using certificate-based client authentication, consider the following: + +The LDAPSSLSocketWrapFactory class +does not support certificate-based client authentication. +The LDAPSSLSocketFactory class relies +on the browser to support certificate-based client authentication. The class +does not support the use of certificates for authentication outside the browser, +in stand-alone Java applications. + + +To enable an applet to use certificate-based client authentication, +do the following: +Construct a new LDAPSSLSocketFactory object. + +Invoke the enableClientAuth method of the +object to enable certificate-based client authentication. +Pass the object that you constructed to the LDAPConnection + constructor. + + diff --git a/mozilla/directory/docs/ldapjdk/jdk-understanding.sgm b/mozilla/directory/docs/ldapjdk/jdk-understanding.sgm new file mode 100644 index 00000000000..ff5649d44b8 --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/jdk-understanding.sgm @@ -0,0 +1,412 @@ + +Understanding the &DirectorySDKForJava; + +This chapter describes the LDAP Java classes and the &DirectorySDKForJava;, +including the following sections: + +Understanding the LDAP +Java Classes +About &DirectorySDKForJava; + + + +Understanding the LDAP Java Classes + + +packages +summary of + +&DirectorySDKForJava; +packages + +The &DirectorySDKForJava; includes the LDAP Java classes, which you use to +build LDAP clients. The LDAP Java classes allow you to write client applications that +connect to LDAP servers and perform standard LDAP operations. For example, you can +search for entries or add, update, or delete entries. +The classes are organized in the following packages: + +com.netscape.sasl +Contains the interfaces and classes that you can use to enable your +client to authenticate by using a SASL mechanism. + + +com.netscape.sasl.mechanisms +Contains an implementation of the EXTERNAL SASL mechanism driver. + + + +netscape.ldap +Contains the main LDAP Java classes, including classes that allow +you to connect to an LDAP server, manipulate entries and attributes, and retrieve +search results + + + +netscape.ldap.ber.stream +Contains the LDAP Java classes that implement the Basic +Encoding Rules (BER) for transfer syntax. For more information on BER, +see ISO/IEC 8825 at http://www.iso.ch/ +. + + +netscape.ldap.controls +Contains the LDAP Java classes that implement specific LDAP v3 controls. +These include controls to request server-side sorting and persistent searches. + + +netscape.ldap.factory +Contains classes that allow you to create an SSL socket connection +to a server. + + +netscape.ldap.util +Contains utility classes, such as classes to parse LDIF data and filters +that allow regular expression matching. + + + +Clients typically execute methods in the &DirectorySDKForJava; synchronously. +All LDAP operations block until they are completed, except for the search + method, which can return information before all the results have been received. + +An asynchronous interface is also provided for circumstances requiring low-level +interaction with an LDAP server. The asynchronous interface is discussed more fully +in Chapter 33, Writing Asynchronous Clients With Directory SDK for Java. +About &DirectorySDKForJava; +This section covers the following topics: + + +Exploring the Directory SDK for Java + +Preparing to Use Directory SDK for +Java + + + +Exploring the &DirectorySDKForJava; + +&DirectorySDKForJava; +contents + +TODO: verify this is all still true +The &DirectorySDKForJava; contains the following directories: + + +packages +This directory contains the following JAR file: + + +ldapjdk.jar +ldapjdk.jar +Contains classes for all packages listed in +Understanding the LDAP Java Classes + + + + + + + +tools +This directory contains Java classes for the LDAPDelete, +LDAPModify, and LDAPSearch commands. + + + + +Preparing to Use &DirectorySDKForJava; + +CLASSPATH +setting + +TODO: is this right? +Before compiling applications, add the following to your CLASSPATH environment +variable: + + +packages/ldapjdk.jar +Containing the main LDAP Java classes + + + + + + + + diff --git a/mozilla/directory/docs/ldapjdk/jdk-writing-client.sgm b/mozilla/directory/docs/ldapjdk/jdk-writing-client.sgm new file mode 100644 index 00000000000..29bf290d7f0 --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/jdk-writing-client.sgm @@ -0,0 +1,361 @@ + +Writing an LDAP Client With &DirectorySDKForJava; + +This chapter describes the general process of writing an LDAP client. +The chapter covers the procedures for connecting to an LDAP server. It covers +authentication, requesting operations, and disconnecting from the server. + +The chapter covers the following topics: +Designing an LDAP Java +Client +Creating a Connection and +Setting Preferences With Directory SDK for Java +Connecting to an LDAP Server +With Directory SDK for Java +Binding and Authenticating +to an LDAP Server With Directory SDK for Java +Performing LDAP Operations +With Directory SDK for Java +Closing the Connection to +an LDAP Server With Directory SDK for Java + + +Designing an LDAP Java Client +The following steps outline the typical process of communicating with +an LDAP server. Follow these steps when writing your LDAP client. + +Create a new LDAPConnection object, +and set any preferences that you want applied to all LDAP operations. + +Connect to an LDAP server. +If necessary, bind to the LDAP server, specifying the version +of LDAP supported by your client. +Perform the LDAP operations, such as searching the directory +or modifying entries in the directory. +When finished performing operations, disconnect from the LDAP +server. + +The following example LDAP client follows these steps to search a directory. +The client connects to the LDAP server running on the local host at port +389. The client then searches the directory for entries with the +surname Jensen. Finally, the client displays the DNs of +matching entries. +import netscape.ldap.*; +import java.util.*; + +public class Search { + public static void main(String[] args) { + try { + UserArgs userArgs = new UserArgs("Search", args, false); + LDAPConnection ld = new LDAPConnection(); + ld.connect(userArgs.getHost(), userArgs.getPort()); + + /* search for all entries with surname of Jensen */ + String MY_FILTER = "sn=Jensen"; + String MY_SEARCHBASE = "dc=example,dc=com"; + + LDAPSearchConstraints cons = ld.getSearchConstraints(); + /* Setting the batchSize to one will cause the result + enumeration below to block on one result at a time, + enabling an update of a list or other things as + results come in. */ + /* This could be set to 0 in order to get all + results and to block until then. */ + cons.setBatchSize(1); + LDAPSearchResults res = ld.search(MY_SEARCHBASE, + LDAPConnection.SCOPE_SUB, MY_FILTER, null, false, cons); + + /* Loop on results until finished */ + while (res.hasMoreElements()) { + LDAPEntry findEntry = null; + try { + findEntry = res.next(); + } catch (LDAPReferralException e) { + System.out.println("Search reference: "); + LDAPUrl refUrls[] = e.getURLs(); + for (int i=0; i<refUrls.length; i++) { + System.out.println("\t" + refUrls[i].getUrl()); + } + continue; + } catch (LDAPException e) { + System.out.println("Error: " + e.toString()); + continue; + } + System.out.println(findEntry.getDN()); + + /* Get the attributes of the entry */ + LDAPAttributeSet findAttrs = findEntry.getAttributeSet(); + Enumeration enumAttrs = findAttrs.getAttributes(); + System.out.println("\tAttributes: "); + + /* Loop on attributes */ + while (enumAttrs.hasMoreElements()) { + LDAPAttribute anAttr = + (LDAPAttribute)enumAttrs.nextElement(); + String attrName = anAttr.getName(); + System.out.println("\t\t" + attrName); + + /* Loop on values for this attribute */ + Enumeration enumVals = anAttr.getStringValues(); + if (enumVals != null) { + while (enumVals.hasMoreElements()) { + String aVal = (String)enumVals.nextElement(); + System.out.println("\t\t\t" + aVal); + } + } + } + } + ld.disconnect(); + } catch(LDAPException e) { + System.out.println("Error: " + e.toString()); + } + } +} + +Creating a Connection and Setting Preferences +With &DirectorySDKForJava; + +connection +creating + +connection +setting preferences + +LDAP session +setting preferences + +The first step in writing an LDAP client is creating an LDAPConnection + object. This object represents the connection to an LDAP server. +LDAPConnection ld = new LDAPConnection(); +If you plan to connect to the LDAP server over the Secure +Sockets Layer (SSL) protocol, you need to specify a class that +implements SSL sockets. Refer to Chapter 9, +SSL Connections With Directory SDK for Java for details. +The LDAPConnection object also contains preferences +for the LDAP session, such as whether referrals are or are not followed automatically. +To get or set the value of a preference, invoke the getOption method +or the setOption method as described in the API specification. + +Connecting to an LDAP Server With &DirectorySDKForJava; + +LDAP servers +connecting to + +LDAP clients +connection to a server + +connection +establishing + +session +starting + +To connect to an LDAP server, use the connect method +of the LDAPConnection object. +LDAPConnection ld = new LDAPConnection(); +ld.connect("ldap.example.com", LDAPv3.DEFAULT_PORT); +DEFAULT_PORT specifies the default LDAP port, port +389. You can also specify a list of LDAP servers to attempt to connect to. +If the first LDAP server in the list does not respond, the client attempts +to connect to the next server in the list. + +connection +specifying multiple LDAP servers + +failover support +Use a space-delimited list of the host names as the first argument +of the connect method. If the server is not using the default LDAP port, specify +the port number in hostname: +portnumber format. +LDAPConnection ld = new LDAPConnection(); +ld.connect("ldap1.example.com ldap2.example.com:3890 + ldap3.example.com:3900", LDAPv3.DEFAULT_PORT); + +Binding and Authenticating to an LDAP Server +With &DirectorySDKForJava; + +LDAP clients +authenticating with LDAP servers + +LDAP servers +authenticating to + +bind operation + +When connecting to the LDAP server, your client might need to send a +bind operation request to the server. This operation is also called binding +to the server. + +An LDAP bind request contains the following information: +LDAP version of the client +DN that is used to authenticate +Authentication method that is requested +Credentials that are used to authenticate + + +The client should send a bind request to the server in the following +situations: +You want to authenticate to the server.For example, +if you want to add or modify entries in the directory, you need to authenticate +as a user with access privileges. +You are connecting to an LDAP v2 server.LDAP +v2 servers typically require clients to bind before any operations can be +performed. + +An LDAP client can also bind as an anonymous client. For example, the +LDAP server might not require authentication if your client is only searching +the directory. +This section explains how to set up your client to bind to an LDAP server. +Using Simple Authentication +Simple authentication can be used when security is not a concern. If +you plan to use simple authentication, use the authenticate method +of the LDAPConnection object. +LDAPConnection ld = new LDAPConnection(); +ld.connect("ldap.example.com", LDAPv3.DEFAULT_PORT); +ld.authenticate("uid=bjensen,ou=People,cd=example,dc=com", "hifalutin"); +The server to which you bind might send back a special control to indicate +that your password has expired. The server might also send back a control +to indicate that your password is to expire in the near future. Refer to Chapter 10, LDAP Controls +With Directory SDK for Java for details. +Binding Anonymously + +anonymous bind + +binding +anonymously + +In some cases, you might not need to authenticate to the LDAP server. +For example, the directory that you search might not require special access +permissions for searches. Therefore, you might not need to authenticate before +performing the search operation. In LDAP v3, the server no longer expects +the client to send a bind request in this type of situation. In LDAP v2, the +server expects the client to send a bind request, even if the operation does +not require the client to authenticate. +In this kind of situation, use the authenticate method. +Specify null for the DN and password. +LDAPConnection ld = new LDAPConnection(); +ld.connect("ldap.example.com", LDAPv3.DEFAULT_PORT); +ld.authenticate(null, null); + +Specifying the LDAP Version + +LDAP clients +specifying protocol version + +As part of the bind request sent to the server, the client includes +the version of the LDAP protocol that the client supports. By default, clients +built with the&DirectorySDKForJava; identify themselves as LDAP v2 clients. +Therefore, explicitly identify your client as an LDAP v3 client. + +To identify your client as an LDAP v3 client, do one of the following: +Specify version 3 when invoking the authenticate method. + +LDAPConnection ld = new LDAPConnection(); +ld.connect("ldap.example.com", LDAPv3.DEFAULT_PORT); +ld.authenticate(3, null, null); + +Invoke the setOption method of the +LDAPConnection object to set the LDAPv3.PROTOCOL_VERSION preference +to 3, then invoke the authenticate method. +LDAPConnection ld = new LDAPConnection(); +ld.connect("ldap.example.com", LDAPv3.DEFAULT_PORT); +ld.setOption(LDAPv3.PROTOCOL_VERSION, 3); +ld.authenticate(null, null); + + + +Authenticating With the <literal>connect +</literal> Method +The connect method of the LDAPConnection object +has a signature that allows you to authenticate and specify the LDAP version +supported by your client. +You can specify all of this information using one method, rather than +invoking several methods. +LDAPConnection ld = new LDAPConnection(); +ld.connect(3, "ldap.example.com", LDAPv3.DEFAULT_PORT, +    "uid=bjensen,ou=People,cd=example,dc=com", "hifalutin"); + + +Performing LDAP Operations With &DirectorySDKForJava; + +LDAP operations + +First, you initialize a session with an LDAP server. Next, you complete +the authentication process. After authentication, you can perform LDAP operations. +For example, you can search the directory, add new entries, update entries +that exist, and remove entries. You can perform the operations provided that +the server access control allows you to request the operations. + +To perform LDAP operations, invoke these methods of the LDAPConnection + object: +To search for entries in the directory, use the search method +as explained in Chapter 4, Searching the +Directory With Directory SDK for Java. +To retrieve a single entry in the directory, use the read + method as explained in Chapter 4, +Searching the Directory With Directory SDK for Java. +To determine whether an attribute contains a certain value, +use the compare method as explained in Chapter 6, Comparing Attribute Values With Directory +SDK for Java. +To add entries to the directory, use the add method +as explained in Chapter 5, Adding, Updating, +and Deleting Entries With Directory SDK for Java. +To modify entries in the directory, use the modify method +as explained in Chapter 5, Adding, Updating, +and Deleting Entries With Directory SDK for Java. +To delete entries from the directory, use the delete method +as explained in Chapter 5, Adding, Updating, +and Deleting Entries With Directory SDK for Java. +To rename entries in the directory, use the rename method +as explained in Chapter 5, Adding, Updating, +and Deleting Entries With Directory SDK for Java. + + +Closing the Connection to an LDAP Server With &DirectorySDKForJava; + +ending an LDAP session + +LDAP session +ending + +closing an LDAP connection + +LDAP servers +closing connection from client + +LDAP clients +closing connection to server + +connection +closing + +When you have finished performing all necessary LDAP operations, close +the connection to the LDAP server. Use the disconnect method +of the LDAPConnection object to disconnect from the +LDAP server. +LDAPConnection ld = new LDAPConnection(); +ld.connect("ldap.example.com", LDAPv3.DEFAULT_PORT); +/* + * Authenticate and perform LDAP operations. + */ +ld.disconnect(); + + diff --git a/mozilla/directory/docs/ldapjdk/legal.sgm b/mozilla/directory/docs/ldapjdk/legal.sgm new file mode 100644 index 00000000000..127dc0071c8 --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/legal.sgm @@ -0,0 +1,113 @@ + +Copyright 2000-2007 Sun Microsystems, Inc., 4150 Network Circle, +Santa Clara, California 95054, U.S.A. All rights reserved. Portions +copyright 1999 Netscape Communications Corporations. All rights +reserved. +Sun Microsystems, Inc. has intellectual property rights relating +to technology embodied in the product that is described in this +document. In particular, and without limitation, these intellectual +property rights may include one or more U.S. patents or pending patent +applications in the U.S. and in other countries. +U.S. Government Rights - Commercial software. Government users +are subject to the Sun Microsystems, Inc. standard license agreement +and applicable provisions of the FAR and its supplements. +This distribution may include materials developed by third +parties. +Parts of the product may be derived from Berkeley BSD systems, +licensed from the University of California. UNIX is a registered +trademark in the U.S. and in other countries, exclusively licensed +through X/Open Company, Ltd. +Sun, Sun Microsystems, the Sun logo, Java, Solaris, JavaBeans, +JavaScript and the SunTone Certified logo are trademarks or registered +trademarks of Sun Microsystems, Inc. in the U.S. and other +countries. +All SPARC trademarks are used under license and are trademarks +or registered trademarks of SPARC International, Inc. in the U.S. and +other countries. Products bearing SPARC trademarks are based upon +architecture developed by Sun Microsystems, Inc. +Mozilla, Netscape, and Netscape Navigator are trademarks or +registered trademarks of Netscape Communications Corporation in the +United States and other countries. +Products covered by and information contained in this service +manual are controlled by U.S. Export Control laws and may be subject +to the export or import laws in other countries. Nuclear, missile, +chemical biological weapons or nuclear maritime end uses or end users, +whether direct or indirect, are strictly prohibited. Export or +reexport to countries subject to U.S. embargo or to entities +identified on U.S. export exclusion lists, including, but not limited +to, the denied persons and specially designated nationals lists is +strictly prohibited. +DOCUMENTATION IS PROVIDED “AS IS” AND ALL EXPRESS OR +IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY +IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE +OR NON-INFRINGEMENT, ARE DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH +DISCLAIMERS ARE HELD TO BE LEGALLY INVALID. +Copyright 2000-2007 Sun Microsystems, Inc., 4150 Network Circle, +Santa Clara, California 95054, Etats-Unis. Tous droits +réservés. Certaines parties copyright 1999 Netscape +Communications Corporations. Tous droits réservés. +Sun Microsystems, Inc. détient les droits de +propriété intellectuelle relatifs à la +technologie incorporée dans le produit qui est décrit +dans ce document. En particulier, et ce sans limitation, ces droits de +propriété intellectuelle peuvent inclure un ou plusieurs +brevets américains ou des applications de brevet en attente aux +Etats-Unis et dans d'autres pays. +Cette distribution peut comprendre des composants +développés par des tierces parties. +Des parties de ce produit pourront être +dérivées des systèmes Berkeley BSD +licenciés par l'Université de Californie. UNIX est une +marque déposée aux Etats-Unis et dans d'autres pays et +licenciée exclusivement par X/Open Company, Ltd. +Sun, Sun Microsystems, le logo Sun, Java, Solaris, JavaBeans, +JavaScript et le logo SunTone Certified sont des marques de fabrique +ou des marques déposées de Sun Microsystems, Inc. aux +Etats-Unis et dans d'autres pays. +Toutes les marques SPARC sont utilisées sous licence et +sont des marques de fabrique ou des marques déposées de +SPARC International, Inc. aux Etats-Unis et dans d'autres pays. Les +produits portant les marques SPARC sont basés sur une +architecture développée par Sun Microsystems, +Inc. +Mozilla, Netscape, et Netscape Navigator sont des marques de +Netscape Communications Corporation aux Etats-Unis et dans d'autres +pays. +Les produits qui font l'objet de ce manuel d'entretien et les +informations qu'il contient sont regis par la legislation americaine +en matiere de controle des exportations et peuvent etre soumis au +droit d'autres pays dans le domaine des exportations et +importations. Les utilisations finales, ou utilisateurs finaux, pour +des armes nucleaires, des missiles, des armes biologiques et chimiques +ou du nucleaire maritime, directement ou indirectement, sont +strictement interdites. Les exportations ou reexportations vers des +pays sous embargo des Etats-Unis, ou vers des entites figurant sur les +listes d'exclusion d'exportation americaines, y compris, mais de +maniere non exclusive, la liste de personnes qui font objet d'un ordre +de ne pas participer, d'une facon directe ou indirecte, aux +exportations des produits ou des services qui sont regi par la +legislation americaine en matiere de controle des exportations et la +liste de ressortissants specifiquement designes, sont rigoureusement +interdites. +LA DOCUMENTATION EST FOURNIE “EN L'ETAT” ET TOUTES +AUTRES CONDITIONS, DECLARATIONS ET GARANTIES EXPRESSES OU TACITES SONT +FORMELLEMENT EXCLUES, DANS LA MESURE AUTORISEE PAR LA LOI APPLICABLE, +Y COMPRIS NOTAMMENT TOUTE GARANTIE IMPLICITE RELATIVE A LA QUALITE +MARCHANDE, A L'APTITUDE A UNE UTILISATION PARTICULIERE OU A L'ABSENCE +DE CONTREFACON. diff --git a/mozilla/directory/docs/ldapjdk/license.txt b/mozilla/directory/docs/ldapjdk/license.txt new file mode 100644 index 00000000000..92f23fd1acf --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/license.txt @@ -0,0 +1,226 @@ +Attribution-ShareAlike 2.5 +CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL +SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN ATTORNEY-CLIENT +RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. +CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE INFORMATION PROVIDED, AND +DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM ITS USE. + +License + +THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS +PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR +OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS +LICENSE OR COPYRIGHT LAW IS PROHIBITED. + +BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE +BOUND BY THE TERMS OF THIS LICENSE. THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED +HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. + +1. Definitions + + 1. "Collective Work" means a work, such as a periodical issue, anthology or +encyclopedia, in which the Work in its entirety in unmodified form, along with a +number of other contributions, constituting separate and independent works in +themselves, are assembled into a collective whole. A work that constitutes a +Collective Work will not be considered a Derivative Work (as defined below) for +the purposes of this License. + 2. "Derivative Work" means a work based upon the Work or upon the Work and +other pre-existing works, such as a translation, musical arrangement, +dramatization, fictionalization, motion picture version, sound recording, art +reproduction, abridgment, condensation, or any other form in which the Work may +be recast, transformed, or adapted, except that a work that constitutes a +Collective Work will not be considered a Derivative Work for the purpose of this +License. For the avoidance of doubt, where the Work is a musical composition or +sound recording, the synchronization of the Work in timed-relation with a moving +image ("synching") will be considered a Derivative Work for the purpose of this +License. + 3. "Licensor" means the individual or entity that offers the Work under the +terms of this License. + 4. "Original Author" means the individual or entity who created the Work. + 5. "Work" means the copyrightable work of authorship offered under the terms +of this License. + 6. "You" means an individual or entity exercising rights under this License +who has not previously violated the terms of this License with respect to the +Work, or who has received express permission from the Licensor to exercise +rights under this License despite a previous violation. + 7. "License Elements" means the following high-level license attributes as +selected by Licensor and indicated in the title of this License: Attribution, +ShareAlike. + +2. Fair Use Rights. Nothing in this license is intended to reduce, limit, or +restrict any rights arising from fair use, first sale or other limitations on +the exclusive rights of the copyright owner under copyright law or other +applicable laws. + +3. License Grant. Subject to the terms and conditions of this License, Licensor +hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the +duration of the applicable copyright) license to exercise the rights in the Work +as stated below: + + 1. to reproduce the Work, to incorporate the Work into one or more Collective +Works, and to reproduce the Work as incorporated in the Collective Works; + 2. to create and reproduce Derivative Works; + 3. to distribute copies or phonorecords of, display publicly, perform +publicly, and perform publicly by means of a digital audio transmission the Work +including as incorporated in Collective Works; + 4. to distribute copies or phonorecords of, display publicly, perform +publicly, and perform publicly by means of a digital audio transmission +Derivative Works. + 5. + + For the avoidance of doubt, where the work is a musical composition: + 1. Performance Royalties Under Blanket Licenses. Licensor waives the +exclusive right to collect, whether individually or via a performance rights +society (e.g. ASCAP, BMI, SESAC), royalties for the public performance or public +digital performance (e.g. webcast) of the Work. + 2. Mechanical Rights and Statutory Royalties. Licensor waives the +exclusive right to collect, whether individually or via a music rights society +or designated agent (e.g. Harry Fox Agency), royalties for any phonorecord You +create from the Work ("cover version") and distribute, subject to the compulsory +license created by 17 USC Section 115 of the US Copyright Act (or the equivalent +in other jurisdictions). + 6. Webcasting Rights and Statutory Royalties. For the avoidance of doubt, +where the Work is a sound recording, Licensor waives the exclusive right to +collect, whether individually or via a performance-rights society (e.g. +SoundExchange), royalties for the public digital performance (e.g. webcast) of +the Work, subject to the compulsory license created by 17 USC Section 114 of the +US Copyright Act (or the equivalent in other jurisdictions). + +The above rights may be exercised in all media and formats whether now known or +hereafter devised. The above rights include the right to make such modifications +as are technically necessary to exercise the rights in other media and formats. +All rights not expressly granted by Licensor are hereby reserved. + +4. Restrictions.The license granted in Section 3 above is expressly made subject +to and limited by the following restrictions: + + 1. You may distribute, publicly display, publicly perform, or publicly +digitally perform the Work only under the terms of this License, and You must +include a copy of, or the Uniform Resource Identifier for, this License with +every copy or phonorecord of the Work You distribute, publicly display, publicly +perform, or publicly digitally perform. You may not offer or impose any terms on +the Work that alter or restrict the terms of this License or the recipients' +exercise of the rights granted hereunder. You may not sublicense the Work. You +must keep intact all notices that refer to this License and to the disclaimer of +warranties. You may not distribute, publicly display, publicly perform, or +publicly digitally perform the Work with any technological measures that control +access or use of the Work in a manner inconsistent with the terms of this +License Agreement. The above applies to the Work as incorporated in a Collective +Work, but this does not require the Collective Work apart from the Work itself +to be made subject to the terms of this License. If You create a Collective +Work, upon notice from any Licensor You must, to the extent practicable, remove +from the Collective Work any credit as required by clause 4(c), as requested. If +You create a Derivative Work, upon notice from any Licensor You must, to the +extent practicable, remove from the Derivative Work any credit as required by +clause 4(c), as requested. + 2. You may distribute, publicly display, publicly perform, or publicly +digitally perform a Derivative Work only under the terms of this License, a +later version of this License with the same License Elements as this License, or +a Creative Commons iCommons license that contains the same License Elements as +this License (e.g. Attribution-ShareAlike 2.5 Japan). You must include a copy +of, or the Uniform Resource Identifier for, this License or other license +specified in the previous sentence with every copy or phonorecord of each +Derivative Work You distribute, publicly display, publicly perform, or publicly +digitally perform. You may not offer or impose any terms on the Derivative Works +that alter or restrict the terms of this License or the recipients' exercise of +the rights granted hereunder, and You must keep intact all notices that refer to +this License and to the disclaimer of warranties. You may not distribute, +publicly display, publicly perform, or publicly digitally perform the Derivative +Work with any technological measures that control access or use of the Work in a +manner inconsistent with the terms of this License Agreement. The above applies +to the Derivative Work as incorporated in a Collective Work, but this does not +require the Collective Work apart from the Derivative Work itself to be made +subject to the terms of this License. + 3. If you distribute, publicly display, publicly perform, or publicly +digitally perform the Work or any Derivative Works or Collective Works, You must +keep intact all copyright notices for the Work and provide, reasonable to the +medium or means You are utilizing: (i) the name of the Original Author (or +pseudonym, if applicable) if supplied, and/or (ii) if the Original Author and/or +Licensor designate another party or parties (e.g. a sponsor institute, +publishing entity, journal) for attribution in Licensor's copyright notice, +terms of service or by other reasonable means, the name of such party or +parties; the title of the Work if supplied; to the extent reasonably +practicable, the Uniform Resource Identifier, if any, that Licensor specifies to +be associated with the Work, unless such URI does not refer to the copyright +notice or licensing information for the Work; and in the case of a Derivative +Work, a credit identifying the use of the Work in the Derivative Work (e.g., +"French translation of the Work by Original Author," or "Screenplay based on +original Work by Original Author"). Such credit may be implemented in any +reasonable manner; provided, however, that in the case of a Derivative Work or +Collective Work, at a minimum such credit will appear where any other comparable +authorship credit appears and in a manner at least as prominent as such other +comparable authorship credit. + +5. Representations, Warranties and Disclaimer + +UNLESS OTHERWISE AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK +AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE +MATERIALS, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT +LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR +PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, +OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME +JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH +EXCLUSION MAY NOT APPLY TO YOU. + +6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN +NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, +INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS +LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +7. Termination + + 1. This License and the rights granted hereunder will terminate automatically +upon any breach by You of the terms of this License. Individuals or entities who +have received Derivative Works or Collective Works from You under this License, +however, will not have their licenses terminated provided such individuals or +entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, +and 8 will survive any termination of this License. + 2. Subject to the above terms and conditions, the license granted here is +perpetual (for the duration of the applicable copyright in the Work). +Notwithstanding the above, Licensor reserves the right to release the Work under +different license terms or to stop distributing the Work at any time; provided, +however that any such election will not serve to withdraw this License (or any +other license that has been, or is required to be, granted under the terms of +this License), and this License will continue in full force and effect unless +terminated as stated above. + +8. Miscellaneous + + 1. Each time You distribute or publicly digitally perform the Work or a +Collective Work, the Licensor offers to the recipient a license to the Work on +the same terms and conditions as the license granted to You under this License. + 2. Each time You distribute or publicly digitally perform a Derivative Work, +Licensor offers to the recipient a license to the original Work on the same +terms and conditions as the license granted to You under this License. + 3. If any provision of this License is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of the +remainder of the terms of this License, and without further action by the +parties to this agreement, such provision shall be reformed to the minimum +extent necessary to make such provision valid and enforceable. + 4. No term or provision of this License shall be deemed waived and no breach +consented to unless such waiver or consent shall be in writing and signed by the +party to be charged with such waiver or consent. + 5. This License constitutes the entire agreement between the parties with +respect to the Work licensed here. There are no understandings, agreements or +representations with respect to the Work not specified here. Licensor shall not +be bound by any additional provisions that may appear in any communication from +You. This License may not be modified without the mutual written agreement of +the Licensor and You. + +Creative Commons is not a party to this License, and makes no warranty +whatsoever in connection with the Work. Creative Commons will not be liable to +You or any party on any legal theory for any damages whatsoever, including +without limitation any general, special, incidental or consequential damages +arising in connection to this license. Notwithstanding the foregoing two (2) +sentences, if Creative Commons has expressly identified itself as the Licensor +hereunder, it shall have all rights and obligations of Licensor. + +Except for the limited purpose of indicating to the public that the Work is +licensed under the CCPL, neither party will use the trademark "Creative Commons" +or any related trademark or logo of Creative Commons without the prior written +consent of Creative Commons. Any permitted use will be in compliance with +Creative Commons' then-current trademark usage guidelines, as may be published +on its website or otherwise made available upon request from time to time. + +Creative Commons may be contacted at http://creativecommons.org/. diff --git a/mozilla/directory/docs/ldapjdk/preface.sgm b/mozilla/directory/docs/ldapjdk/preface.sgm new file mode 100644 index 00000000000..c0112065ab8 --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/preface.sgm @@ -0,0 +1,349 @@ + +Preface +&abstract; + +Who Should Use This Book +This guide is intended for developers creating directory client applications. + + +Before using this guide, you must be familiar with the following: +&cnDirectoryServer; functionality +Developing programs in the Java programming +language +Specifications for LDAP and related protocols, such as DSML +v2 +Internet and World Wide Web technologies + + +Before You Read This Book +Before developing directory client applications, install &DirectorySDKForJava;. + + + +Additional Recommended Reading + +Directory client application developers might benefit from reading the +following books: +LDAP Programming with Java by Weltman +and Dabhura (ISBN 0-201-65758-96) +LDAP Programming, Management and Integration by +Donley (ISBN 1930110405) +LDAP: Programming Directory-Enabled Applications +with Lightweight Directory Access Protocol by Howes and Smith +(ISBN 1-57870-000-00) +Understanding and Deploying LDAP Directory Services by +Howes, et al. (ISBN 1-57870-070-10) + + +In addition, keep bookmarks to the following IETF documents: + +RFC 2251, Lightweight Directory Access Protocol (v3) + + +RFC 2252, Lightweight Directory Access Protocol (v3): Attribute +Syntax Definitions + +RFC 2253, Lightweight Directory Access Protocol (v3): UTF-8 +String Representation of Distinguished Names + +RFC 2254, The String Representation of LDAP Search Filters + + +RFC 2255, The LDAP URL Format + +RFC 2256, A Summary of the X.500(96) User Schema for use +with LDAPv3 + +RFC 2829, Authentication Methods for LDAP + + +RFC 2830, Lightweight Directory Access Protocol (v3): Extension +for Transport Layer Security + +RFC 2849, The LDAP Data Interchange Format (LDIF) - Technical +Specification + +RFC 3377, Lightweight Directory Access Protocol (v3): Technical +Specification + + +How This Book Is Organized + +This guide includes the following chapters. +Chapter 1, Understanding LDAP describes LDAP and directory concepts. +Chapter 2, Choosing a Client SDK covers what to consider when choosing a software development kit for building directory client applications. +Chapter 3, +Best Practices for Writing Client Applications reviews what and what +not to do when building directory client applications. +Chapter 1, Getting +Started With Directory SDK for Java gets you started using &DirectorySDKForJava; + +Chapter 2, Writing an LDAP Client With Directory SDK for Java covers the basics of writing +a directory client application +Chapter 3, Using the LDAP Java Classes provides a look how &DirectorySDKForJava; is +structured +Chapter 4, Searching the Directory With Directory SDK for Java shows you how to write client +application code for searching a directory + +Chapter 5, Adding, Updating, and Deleting Entries With Directory SDK for Java shows you how to +write client application code for changing directory entries +Chapter 6, Comparing Attribute Values With Directory SDK for Java shows you how to comparing attribute +values in a directory with known values +Chapter 7, LDAP URLs With Directory SDK for Java shows you how to handle LDAP URLs + +Chapter 8, Getting Server Information With Directory SDK for Java shows you how to retrieve +information about the directory and directory service +Chapter 9, SSL Connections With Directory SDK for Java shows you how to write client application code +that connects to the directory over SSL +Chapter 10, LDAP Controls With Directory SDK for Java shows you how to handle supported LDAP +controls +Chapter 11, SASL Authentication With Directory SDK for Java shows you how to connect to the directory +by using SASL +Chapter 12, Extended Operations With Directory SDK for Java shows you how to write client +application code for handling LDAP v3 extended operations +Chapter 13, Writing Asynchronous Clients With Directory SDK for Java shows you how to write applications +that do not block waiting for results +Appendix A, Creative Commons Attribution-ShareAlike 2.5 provides the full text of the license governing this guide + + + +Related Reading + +SLAMD Distributed Load Generation Engine +The SLAMD Distributed Load Generation Engine (SLAMD) is a +Java application that is designed to stress test and analyze the +performance of network-based applications. It was originally developed by +Sun Microsystems, Inc. to benchmark and analyze the performance of LDAP directory +servers. SLAMD is available as an open source application under the Sun Public +License, an OSI-approved open source license. To obtain information about +SLAMD, go to . SLAMD +is also available as a java.net project. See . + +Java Naming and Directory Interface +Java Naming and Directory Interface (JNDI) technology supports +accessing the Directory Server using LDAP and DSML v2 from Java applications. +For information about JNDI, see . The JNDI Tutorial contains detailed +descriptions and examples of how to use JNDI. This tutorial is at . + +Typographic Conventions +The following table describes the typographic changes that are used +in this book. +Typographic Conventions + + + + +Typeface + +Meaning + +Example + + + + + +AaBbCc123 + +The names of commands, files, and directories, and onscreen computer +output + +Edit your .login file. +Use ls to list all files. +machine_name% you have mail. + + + + +AaBbCc123 + +What you type, contrasted with onscreen computer output + +machine_name% su +Password: + + + +AaBbCc123 + +A placeholder to be replaced with a real name or value + +The command to remove a file is rm filename +. + + + +AaBbCc123 + +Book titles, new terms, and terms to be emphasized (note that some emphasized +items appear bold online) + +Read Chapter 6 in the User's Guide. +A cache is a copy that is stored locally. +Do not save the file. + + + +
+
+Shell Prompts in Command Examples +The following table shows default system prompts and superuser prompts. +Shell Prompts + + + + +Shell + +Prompt + + + + + +C shell on UNIX and Linux systems + +machine_name% + + + +C shell superuser on UNIX and Linux systems + +machine_name# + + + +Bourne shell and Korn shell on UNIX and Linux systems + +$ + + + +Bourne shell and Korn shell superuser on UNIX and Linux systems + + +# + + + +Microsoft Windows command line + +C:\ + + + +
+
+Symbol Conventions +The following table explains symbols that might be used in this book. +Symbol Conventions + + + + +Symbol + +Description + +Example + +Meaning + + + + + +[ ] + +Contains optional arguments and command options. + +ls [-l] + +The -l option is not required. + + + +{ | } + +Contains a set of choices for a required command option. + +-d {y|n} + +The -d option requires that you use either the +y argument or the n argument. + + + +${ } + +Indicates a variable reference. + +${com.sun.javaRoot} + +References the value of the com.sun.javaRoot variable. + + + + +- + +Joins simultaneous multiple keystrokes. + +Control-A + +Press the Control key while you press the A key. + + + ++ + +Joins consecutive multiple keystrokes. + +Ctrl+A+N + +Press the Control key, release it, and then press the subsequent keys. + + + + +→ + +Indicates menu item selection in a graphical user interface. + + +File → New → Templates + +From the File menu, choose New. From the New submenu, choose Templates. + + + + +
+
+
diff --git a/mozilla/directory/docs/ldapjdk/understanding-ldap.sgm b/mozilla/directory/docs/ldapjdk/understanding-ldap.sgm new file mode 100644 index 00000000000..c438e95e1bc --- /dev/null +++ b/mozilla/directory/docs/ldapjdk/understanding-ldap.sgm @@ -0,0 +1,274 @@ + +Understanding LDAP + +LDAP + +Lightweight Directory Access Protocol +LDAP +Lightweight Directory Access Protocol (LDAP) +is the Internet directory protocol. Developed at the University of Michigan +at Ann Arbor in conjunction with the Internet Engineering Task Force, LDAP +is a protocol for accessing and managing directory services. + +This chapter explains the LDAP protocol, and the concepts behind LDAP. +This chapter covers the following topics: +How Directory Services Work + +How LDAP Servers +Organize Directories +How LDAP +Clients and Servers Work +Understanding LDAP +v3 + + +How Directory Services Work + +directory +definition of + +entries +definition of + +attributes +definition of + +A directory consists of entries that +contain descriptive information. For example, a directory might contain entries +that describe people or network resources, such as printers or fax machines. +The descriptive information is stored in the attributes of +the entry. Each attribute describes a specific type of information. For example, +attributes that describe a person might include her name, also referred to +as her common name (CN), telephone number, and email address. + +entries +example of + +attributes +example of +The entry for Barbara Jensen might have the +following attributes: +cn: Barbara Jensen +mail: babs@example.com +telephoneNumber: 555-1212 +roomNumber: 3995 +An attribute can have more than one value. For example, a person might +have two common names, both a formal name and also a nickname: +cn: Barbara Jensen +cn: Babs Jensen +mail: babs@example.com +telephoneNumber: 555-1212 +roomNumber: 3995 +Attributes can also contain binary data. For example, a person's attributes +might include her photo in JPEG format, a recording of her voice as an audio +file, or her SSL certificate. + +directory service +definition of +A directory service is a distributed database +application for managing the entries and attributes in a directory. A directory +service also makes the entries and attributes available to users and other +applications. +&cnDirectoryServer; is an example of a directory service. For example, +a user might use the directory service to look up someone's telephone number. +Another application might use the directory service to retrieve a list of +email addresses. + +LDAP servers + +LDAP clients +LDAP is a protocol that defines a directory service and access +to that service. LDAP is based on a client-server model. LDAP servers provide +the directory service. LDAP clients use the directory service to access entries +and attributes. + +LDAP servers +example of + +LDAP clients +example of +&cnDirectoryServer; is an example of an LDAP server that manages +and provides information about users and organizational structures. Examples +of LDAP clients include Identity Manager, Access Manager, Solaris naming +services, Messaging Server, Portal Server, NameFinder, and the Mozilla mail +client. Such clients use &cnDirectoryServer; to find, update, and add information +about users. +How LDAP Servers Organize Directories + +LDAP +organization of data + +entries +organization in LDAP + +LDAP servers +how data is organized + +Because LDAP is intended to be a global directory service, data is organized +hierarchically, starting at a root and branching down into individual entries. +At the top level of the hierarchy, entries represent larger organizations. +Under larger organizations in the hierarchy, you might find entries for smaller +organizations. The hierarchy might end with entries for individual people, +or resources, as shown in the following figure. +
Hierarchy of Entries in a Directory + + +Simple directory information tree with two organizational +unit entries and two user entries + +
+ +relative distinguished names (RDNs) +definition of + +RDNs +relative distinguished names (RDNs) +distinguished names (DNs) +definition of + +CNs +common names (CNs) +DNs +distinguished names (DNs) +common names (CNs) +Each entry is uniquely identified by a distinguished +name (DN). A DN includes a relative distinguished name (RDN), +that uniquely identifies the entry at that hierarchical level. For example, +bjensen and kjensen are different user IDs that +identify different entries at the same level. Following the RDN is a path +of names that trace the entry back to the root of the tree, such as ou=People,dc=example,dc=com +. DC is short for domain component. The full +DN for this example would be uid=bjensen,ou=People,dc=example,dc=com. +Here, uid is the user ID of the entry. ou is +short for organizational unit. + +LDAP servers +how data is distributed +The data stored in a directory can be distributed among several +LDAP servers. For example, one LDAP server at Example.com might +contain entries representing North American organizational units and employees, +while another LDAP server might contain entries representing European organizational +units and employees. + +LDAP servers +how referrals work + +referrals +Some LDAP servers are set up to refer requests to other LDAP servers. +For example, if the LDAP server at Example.com receives +a request for information about an employee in a Pacific Rim branch, that +server can refer the request to the LDAP server at the Pacific Rim branch. +In this way, LDAP servers can appear to be a single source of directory information. +Even if an LDAP server does not contain the information you request, the server +can refer you to another server that does contain the information. +
+How LDAP Clients and Servers +Work + +LDAP servers +LDAP clients and + +LDAP clients +LDAP servers and + +LDAP clients +operations performed by + +In the LDAP client-server model, LDAP servers such as &cnDirectoryServer; +make information about people, organizations, and resources accessible to +LDAP clients. LDAP defines operations that clients use to search and update +the directory. + +An LDAP client can perform these operations, among others: +Search for and retrieve entries from the directory + +Add new entries to the directory +Update entries in the directory +Delete entries from the directory +Rename entries in the directory + +For example, to update an entry, an LDAP client submits the distinguished +name of the entry with updated attribute information to the LDAP server. The +LDAP server uses the distinguished name to find the entry. The server then +performs a modify operation to update the entry in the directory. + +LDAP servers +connecting with LDAP clients + +LDAP clients +connecting with LDAP servers +To perform any of these LDAP operations, an LDAP client needs +to establish a connection with an LDAP server. The LDAP protocol specifies +the use of TCP/IP port number 389, although servers can run on other ports. + +LDAP servers +authentication + +LDAP clients +authentication +The LDAP protocol also defines a simple method for authentication. +LDAP servers can be set up to restrict permissions to the directory. Before +an LDAP client can perform an operation on an LDAP server, the client must +authenticate to the server. Clients typically authenticate by supplying a +distinguished name and password. If the user identified by the distinguished +name does not have permission to perform the operation, the server does not +execute the operation. +Understanding LDAP v3 + +LDAP +version 3 + +RFC +4511 specifies LDAP version 3. Use this version of the protocol when +writing new client applications. +Many LDAP servers continue to support LDAP version 2 for use with legacy +clients. This version of the protocol is specified in RFC 1777. + +LDAP v3 includes new features not present in version 2: +Clients and servers can specify controls that +extend the functionality of an LDAP operation. +Clients can request that the server perform extended +operations, operations not included in the list of standard LDAP +operations. +Clients can use Simple Authentication and Security +Layer (SASL) mechanisms to authenticate to the directory. SASL +is specified in +RFC 4422. +Servers, known as Directory System Agents (DSAs), +have DSA-specific entries (DSEs). DSEs provide information +about the versions of the LDAP protocol that the server supports. DSEs also +provide a list of the controls, extended operations, and SASL mechanisms supported +by the server. Finally, DSEs specify the naming contexts of the server. Naming +contexts are portions of the directory information tree managed by the server. + +Servers make their schemas, which define +the object classes, attributes, syntaxes, and matching rules enforced by the +directory, available to clients through the root DSE. + +UTF-8 +support of +Both client and server applications can support data in UTF-8. +UTF-8 is a transformation format of the Universal Character Set +standard. UTF-8 is specified in RFC 3269. With UTF-8, clients can request and receive +data that is tagged with language information. + + +

0jc?Y4PlCC^vB>apk2~9yoVD`IUQ@aNaxcim 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%0A68Fb;$fX`< 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 l$#0%=Uo!FNB_6~Jjde=f40v{a@(CWOD!j literal 0 HcmV?d00001 diff --git a/mozilla/directory/docs/ldapjdk/figures/hierovrw.eps b/mozilla/directory/docs/ldapjdk/figures/hierovrw.eps new file mode 100644 index 0000000000000000000000000000000000000000..01fe4cba0b412dc922616841def44047ef44333d GIT binary patch literal 378039 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