/* -*- C -*-
*
* Copyright 2000 Compaq Computer Corporation
*
* COMPAQ Registered in U.S. Patent and Trademark Office.
*
* Consistent with FAR 12.211 and 12.212, Commercial Computer Software,
* Computer Software Documentation, and Technical Data for Commercial Items
* are licensed to the U.S. Government under vendor's standard commercial
* license.
*
* This software is subject to change without notice and is provided "AS IS"
* WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK ARISING OUT OF THE USE OF
* THIS SOFTWARE REMAINS WITH RECIPIENT. IN NO EVENT SHALL COMPAQ BE LIABLE
* FOR ANY DIRECT, CONSEQUENTIAL, INCIDENTAL, SPECIAL, PUNITIVE OR OTHER
* DAMAGES WHATSOEVER (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF
* BUSINESS PROFITS, BUSINESS INTERRUPTION OR LOSS OF BUSINESS INFORMATION),
* EVEN IF COMPAQ HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. THE
* FOREGOING SHALL APPLY REGARDLESS OF THE NEGLIGENCE OR OTHER FAULT OF
* EITHER PARTY AND REGARDLESS OF WHETHER SUCH LIABILITY SOUNDS IN CONTRACT,
* NEGLIGENCE, TORT, OR ANY OTHER THEORY OF LEGAL LIABILITY, AND
* NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF ANY LIMITED REMEDY.
*
* The limited warranties for Compaq products are exclusively set forth in
* the documentation accompanying such products. Nothing herein should be
* construed as constituting a further or additional warranty.
*
*
*/
/*
* Compaq revision history
*
* Rev Author Date Comments
* --- ------ ---- --------
* 001 Nick Hudson 08-Sep-2000 Initial version
*/
/*
* This program demonstrates the use of the OpenVMS LDAP API from a client
* application.
*
* The program may be compiled using either C or C++.
*
* The program may be compiled with either 32 or 64 bit pointers (providing
* that the compiler supports it).
*
* To build this program use:
* $ cc ldap_example
* $ link ldap_example
*
* The program expects to run as a foreign command. To define the foreign
* command use the following syntax:
*
* $ ldap_example := $disk1:[mydir]ldap_example.exe ! define foreign command
*
* The program expects the following arguments:
*
* server The node which is providing LDAP access to a directory
*
* base The base object in the directory for the search operation
*
* filter The search filter to be used
*
* attributes An optional list of one or more attributes to be returned
* for each matching record. If no attributes are specified,
* then all user attributes will be returned.
*
* An example of a search command would be:
*
* $ ldap_example server "o=acme, c=us" "(sn=s*)" cn sn
*
* Given the parameters above, the program will attempt to make contact
* with an LDAP server on node "server", and request a search for all
* records below the object "o=acme, c=us" that match the filter "sn=s*".
* For each matching record, the attributes "cn" and "sn" will be displayed.
*/
#include <ldap.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* Generic routine to display an error message and return any
* supplementary information from the LDAP handle
*/
void report_error(const char *operation, int result, LDAP *ld)
{
int stat;
char *errmsgp = NULL;
printf("%s returned error %d (\"%s\")\n",operation,
result, ldap_err2string(result));
stat = ldap_get_option(ld,LDAP_OPT_ERROR_STRING,&errmsgp);
if ((stat == -1) || (strlen(errmsgp) == 0)) {
printf("No supplementary error text available\n");
}
else {
printf("Error text : \"%s\"\n",errmsgp);
}
if (errmsgp != NULL) {
ldap_memfree(errmsgp);
errmsgp = NULL;
}
}
void main(int argc, char *argv[])
{
int stat;
int i;
int num_entries;
char **attrs_array = NULL;
int attribute_count;
/*
* For servers which don't support version 3 of the protocol, edit
* the line below to use LDAP_VERSION2. Both of these constants
* are defined inside LDAP.H
*/
int protocol = LDAP_VERSION3;
/*
* The following pointers may be allocated by the LDAP API, and
* should be free'd using an appropriate mechanism
*/
LDAP *ld = NULL;
LDAPMessage *result = NULL;
LDAPMessage *one_entry = NULL;
char *dn = NULL;
char *attr_name = NULL;
char **values = NULL;
BerElement *ber = NULL;
if (argc < 4) {
printf("Usage : %s [server] [base] [filter] <attributes>\n",argv[0]);
goto finished;
}
/*
* If the user requested any particular attributes, then build up
* an array to pass to the search routine. If no attributes are
* specified, then "attrs_array" will be NULL, and the server should
* return all user attributes for each matching entry
*/
attribute_count = (argc - 4);
if (attribute_count != 0) {
i = 0;
/*
* Allocate enough room for a pointer to each attribute, plus
* a NULL terminating pointer.
*/
attrs_array = (char **)calloc((attribute_count + 1),sizeof(char *));
while (i < attribute_count) {
attrs_array[i] = strdup(argv[i+4]);
i++;
}
}
/*
* Establish a context with the library specifying an LDAP server name
* and using the default LDAP port number.
* No connection is made with the server at this stage, so a failure here
* would indicate a problem with the library, rather than a network or
* server related issue.
*/
ld = ldap_init(argv[1], LDAP_PORT);
if (ld == NULL) {
printf("ldap_init failed\n");
goto finished;
}
/*
* Having been provided with a LDAP context, it is possible now to
* specify options for this session
*/
stat = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &protocol);
if (stat != LDAP_SUCCESS) {
report_error("ldap_set_option",stat,ld);
goto finished;
}
/*
* Execute a simple bind, without specifying any authorization
* information, i.e. an anonymous bind
*/
stat = ldap_simple_bind_s(ld,NULL,NULL);
if (stat != LDAP_SUCCESS) {
report_error("simple_bind",stat,ld);
goto finished;
}
/*
* Issue a synchronous search request; this call will not return
* until the server has responded.
*/
stat = ldap_search_s(ld, /* ld */
argv[2], /* base */
LDAP_SCOPE_SUBTREE, /* scope */
argv[3], /* filter */
attrs_array, /* attrs */
0, /* attrsonly */
&result); /* res */
if (stat != LDAP_SUCCESS) {
report_error("ldap_search_s",stat,ld);
goto finished;
}
num_entries = ldap_count_entries(ld,result);
if (num_entries == 0) {
printf("No matching entries found\n");
goto finished;
}
printf("Number of entries returned : %d\n",num_entries);
/*
* Now look at the results that came back
*/
one_entry = ldap_first_entry(ld,result);
while (one_entry != NULL) {
/*
* The distinguished name of this entry
*/
dn = ldap_get_dn(ld,one_entry);
if (dn != NULL) {
printf("\ndn = %s\n",ldap_get_dn(ld,one_entry));
ldap_memfree(dn);
dn = NULL;
/*
* Step through each attribute
*/
attr_name = ldap_first_attribute(ld,one_entry,&ber);
if (attr_name == NULL) {
printf("<No attributes returned>\n");
}
/*
* Extract the values for each attribute returned. This program
* assumes that such values will be "printable" value strings. For
* non-printable (binary) data, ldap_get_values_len() should
* be used.
*/
while (attr_name != NULL) {
values = ldap_get_values(ld,one_entry,attr_name);
if (values == NULL) {
printf("<no values returned>\n");
}
else {
i = 0;
while (values[i] != NULL) {
printf("%s : %s\n",attr_name,values[i]);
i++;
}
}
ldap_memfree(attr_name);
attr_name = NULL;
ldap_value_free(values);
values = NULL;
attr_name = ldap_next_attribute(ld,one_entry,ber);
}
/*
* The BerElement pointer is no longer needed and so can be
* released. Since this pointer was just being used as an
* iterator and doesn't point to any memory that the program
* has allocated itself, use zero as the second parameter to
* ber_free().
*/
if (ber != NULL) {
ber_free(ber, 0);
ber = NULL;
}
}
else {
report_error("ldap_get_dn",0,ld);
}
one_entry = ldap_next_entry(ld,one_entry);
}
/*
* All exit paths should come through here, where free up any data
* structures that the library has allocated using the appropriate
* functions.
* It is a good habit to set pointers to NULL after releasing them,
* although in the cases below it isn't strictly necessary.
*/
finished:
/*
* "dn" may have been allocated by ldap_get_dn()
*/
if (dn != NULL) {
ldap_memfree(dn);
dn = NULL;
}
/*
* "attr_name" may have been allocated by ldap_first_attribute() or
* ldap_next_attribute()
*/
if (attr_name != NULL) {
ldap_memfree(attr_name);
attr_name = NULL;
}
/*
* "values" may have been allocated by ldap_get_values()
*/
if (values != NULL) {
ldap_value_free(values);
values = NULL;
}
/*
* "ber" may have been allocated by ldap_first_attribute() or
* ldap_next_attribute()
* Since this pointer was just being used as an iterator and
* doesn't point to any memory that the program has allocated
* itself, use zero as the second parameter to ber_free()
*/
if (ber != NULL) {
ber_free(ber, 0);
ber = NULL;
}
/*
* "one_entry" may have been allocated by ldap_first_entry() or
* ldap_next_entry()
*/
if (one_entry != NULL) {
ldap_msgfree(one_entry);
one_entry = NULL;
}
/*
* "result" may have been allocated by ldap_search_s()
*/
if (result != NULL) {
ldap_msgfree(result);
result = NULL;
}
/*
* "ld" was returned from ldap_init()
*/
if (ld != NULL) {
ldap_unbind(ld);
ld = NULL;
}
/*
* "attrs_array" was allocated by this program
*/
if (attrs_array != NULL) {
i = 0;
while (attrs_array[i] != NULL) {
free(attrs_array[i]);
attrs_array[i] = NULL;
i++;
}
free(attrs_array);
attrs_array = NULL;
}
printf("\nProgram terminating\n");
}
Back to
Home
Neil Rieck
Waterloo, Ontario, Canada.