/* -*- 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 #include #include #include /* * 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] \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("\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("\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"); }