dlz_ldap_driver.c revision 03e200df5dc283f24a6a349f0b31d3eab26da893
dda4bfe6499d09ea8123447579e56069d8176fcbBob Halley * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * Permission to use, copy, modify, and distribute this software for any
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * purpose with or without fee is hereby granted, provided that the
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * above copyright notice and this permission notice appear in all
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * USE OR PERFORMANCE OF THIS SOFTWARE.
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * conceived and contributed by Rob Butler.
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * Permission to use, copy, modify, and distribute this software for any
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * purpose with or without fee is hereby granted, provided that the
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * above copyright notice and this permission notice appear in all
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
364a82f7c25b62967678027043425201a5e5171aBob Halley * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
b3e77535185043f089b346166440402d092030c3David Lawrence * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
b3e77535185043f089b346166440402d092030c3David Lawrence * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * USE OR PERFORMANCE OF THIS SOFTWARE.
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * Copyright (C) 1999-2001 Internet Software Consortium.
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * Permission to use, copy, modify, and distribute this software for any
72166c5cf59db011cce11e98abe377f5aa6f7052Andreas Gustafsson * purpose with or without fee is hereby granted, provided that the above
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister * copyright notice and this permission notice appear in all copies.
b3e77535185043f089b346166440402d092030c3David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
b3e77535185043f089b346166440402d092030c3David Lawrence * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
b3e77535185043f089b346166440402d092030c3David Lawrence * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
b3e77535185043f089b346166440402d092030c3David Lawrence * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
b3e77535185043f089b346166440402d092030c3David Lawrence * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
b3e77535185043f089b346166440402d092030c3David Lawrence * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * Need older API functions from ldap.h.
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerstatic dns_sdlzimplementation_t *dlz_ldap = NULL;
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * Structure to hold everthing needed by this "instance" of the LDAP
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * driver remember, the driver code is only loaded once, but may have
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * many separate instances.
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristertypedef struct {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister int method; /*%< security authentication method */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister char *cred; /*%< password for simple authentication method */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister int protocol; /*%< LDAP communication protocol version */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister/* forward references */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerdlz_ldap_findzone(void *driverarg, void *dbdata, const char *name);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerdlz_ldap_destroy(void *driverarg, void *dbdata);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * Private methods
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister/*% checks that the LDAP URL parameters make sense */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerdlz_ldap_checkURL(char *URL, int attrCnt, const char *msg) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (ldap_result != LDAP_SUCCESS || ldap_url == NULL) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (ldap_count_values(ldap_url->lud_attrs) < attrCnt) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister "%s query must specify at least "
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister "%d attributes to return",
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (ldap_url->lud_dn == NULL || strlen (ldap_url->lud_dn) < 1) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (ldap_url->lud_exts != NULL || ldap_url->lud_crit_exts != 0) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister "%s uses extensions. "
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister "The driver does not support LDAP extensions.",
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister/*% Connects / reconnects to LDAP server */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Bristerdlz_ldap_connect(ldap_instance_t *dbi, dbinstance_t *dbc) {
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* if we have a connection, get ride of it. */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* now connect / reconnect. */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* initialize. */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister dbc->dbconn = ldap_init(dbi->hosts, LDAP_PORT);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* set protocol version. */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister ldap_result = ldap_set_option((LDAP *) dbc->dbconn,
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* "bind" to server. i.e. send username / pass */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister ldap_result = ldap_bind_s((LDAP *) dbc->dbconn, dbi->user,
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* cleanup if failure. */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * Properly cleans up a list of database instances.
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * This function is only used when the driver is compiled for
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * multithreaded operation.
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* get the first DBI in the list */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* loop through the list */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* get the next DBI in the list */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* release DB connection */
b3e77535185043f089b346166440402d092030c3David Lawrence /* release all memory that comprised a DBI */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* release memory for the list structure */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isc_mem_put(ns_g_mctx, dblist, sizeof(db_list_t));
b3e77535185043f089b346166440402d092030c3David Lawrence * Loops through the list of DB instances, attempting to lock
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * on the mutex. If successful, the DBI is reserved for use
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * and the thread can perform queries against the database.
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * If the lock fails, the next one in the list is tried.
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * looping continues until a lock is obtained, or until
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * the list has been searched dbc_search_limit times.
b3e77535185043f089b346166440402d092030c3David Lawrence * This function is only used when the driver is compiled for
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * multithreaded operation.
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* get top of list */
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister /* loop through list */
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister /* try to lock on the mutex */
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister if (isc_mutex_trylock(&dbi->instance_lock) == ISC_R_SUCCESS)
b3e77535185043f089b346166440402d092030c3David Lawrence return dbi; /* success, return the DBI for use. */
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister /* not successful, keep trying */
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister /* check to see if we have gone to the top of the list. */
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
b3e77535185043f089b346166440402d092030c3David Lawrence "LDAP driver unable to find available connection "
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister "after searching %d times",
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister#endif /* ISC_PLATFORM_USETHREADS */
b3e77535185043f089b346166440402d092030c3David Lawrenceldap_process_results(LDAP *dbc, LDAPMessage *msg, char ** attrs,
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister /* make sure there are at least some attributes to process. */
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister /* get the first entry to process */
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
5475a2d296215b7a93bd89804dc33c36a6de7cb5James Brister "LDAP no entries to process.");
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* loop through all entries returned */
b3e77535185043f089b346166440402d092030c3David Lawrence /* reset for this loop */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* determine how much space we need for data string */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* get the list of values for this attribute. */
b3e77535185043f089b346166440402d092030c3David Lawrence vals = ldap_get_values(dbc, entry, attrs[j]);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* skip empty attributes. */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister if (vals == NULL || ldap_count_values(vals) < 1)
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * we only use the first value. this driver
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * does not support multi-valued attributes.
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* free vals for next loop */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister } /* end for (j=0; attrs[j] != NULL, j++) loop */
b3e77535185043f089b346166440402d092030c3David Lawrence /* allocate memory for data string */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
b3e77535185043f089b346166440402d092030c3David Lawrence "LDAP driver unable to allocate memory "
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister "while processing results");
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * Make sure data is null termed at the beginning so
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * we can check if any data was stored to it later.
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* reset j to re-use below */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* loop through the attributes in the order specified. */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* get the list of values for this attribute. */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister vals = ldap_get_values(dbc, entry, attribute);
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* skip empty attributes. */
b3e77535185043f089b346166440402d092030c3David Lawrence /* increment attibute pointer */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister /* start loop over */
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * j initially = 0. Increment j each time we
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * set a field that way next loop will set
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * next field.
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * convert text to int, make sure it
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister * worked right
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister "LDAP driver ttl must "
2cde028c51055c9fd4837337116cd4fdfe8ff623James Brister "be a postive number");
goto cleanup;
vals[0]);
goto cleanup;
goto cleanup;
goto cleanup;
return result;
static isc_result_t
int ldap_result = 0;
int entries;
#ifdef ISC_PLATFORM_USETHREADS
return ISC_R_FAILURE;
goto cleanup;
goto cleanup;
goto cleanup;
switch(query) {
case ALLNODES:
goto cleanup;
case ALLOWXFR:
goto cleanup;
case AUTHORITY:
goto cleanup;
case FINDZONE:
goto cleanup;
case LOOKUP:
goto cleanup;
goto cleanup;
goto cleanup;
goto cleanup;
dbi);
switch(ldap_result) {
case LDAP_NO_SUCH_OBJECT:
goto cleanup;
case LDAP_SERVER_DOWN:
dbi);
goto cleanup;
goto cleanup;
switch(query) {
case ALLNODES:
case AUTHORITY:
case LOOKUP:
case ALLOWXFR:
if (entries == 0)
else if (entries > 0)
case FINDZONE:
if (entries == 0)
else if (entries > 0)
#ifdef ISC_PLATFORM_USETHREADS
return result;
static isc_result_t
const char *client)
return result;
static isc_result_t
static isc_result_t
static isc_result_t
static isc_result_t
static isc_result_t
int protocol;
int method;
#ifdef ISC_PLATFORM_USETHREADS
int dbcount;
char *endp;
#ifdef ISC_PLATFORM_USETHREADS
return (ISC_R_FAILURE);
return (ISC_R_FAILURE);
return (ISC_R_FAILURE);
return (ISC_R_FAILURE);
#ifdef ISC_PLATFORM_USETHREADS
return (ISC_R_FAILURE);
switch(argc) {
return result;
return result;
return result;
return result;
return result;
return (ISC_R_NOMEMORY);
goto cleanup;
goto cleanup;
goto cleanup;
#ifdef ISC_PLATFORM_USETHREADS
goto cleanup;
for (i = 0; i < dbcount; i++) {
switch(argc) {
goto cleanup;
#ifdef ISC_PLATFORM_USETHREADS
switch(result) {
case ISC_R_SUCCESS:
case ISC_R_NOMEMORY:
#ifdef ISC_PLATFORM_USETHREADS
goto cleanup;
case ISC_R_NOPERM:
goto cleanup;
case ISC_R_FAILURE:
#ifdef ISC_PLATFORM_USETHREADS
goto cleanup;
goto cleanup;
#ifdef ISC_PLATFORM_USETHREADS
return(ISC_R_SUCCESS);
return(ISC_R_FAILURE);
#ifdef ISC_PLATFORM_USETHREADS
dlz_ldap_init(void) {
return result;
dlz_ldap_clear(void) {