03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Permission to use, copy, modify, and distribute this software for any
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * purpose with or without fee is hereby granted, provided that the
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * above copyright notice and this permission notice appear in all
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * USE OR PERFORMANCE OF THIS SOFTWARE.
5d35a7a2fbcf6bd060b0ce7deb349e427cb59fc1Evan Hunt * The development of Dynamically Loadable Zones (DLZ) for BIND 9 was
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * conceived and contributed by Rob Butler.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Permission to use, copy, modify, and distribute this software for any
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * purpose with or without fee is hereby granted, provided that the
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * above copyright notice and this permission notice appear in all
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * USE OR PERFORMANCE OF THIS SOFTWARE.
02d54949f0f1db4729e14c3322b207f58d2578a4Mark Andrews * Copyright (C) 1999-2001, 2016 Internet Systems Consortium, Inc. ("ISC")
02d54949f0f1db4729e14c3322b207f58d2578a4Mark Andrews * This Source Code Form is subject to the terms of the Mozilla Public
02d54949f0f1db4729e14c3322b207f58d2578a4Mark Andrews * License, v. 2.0. If a copy of the MPL was not distributed with this
02d54949f0f1db4729e14c3322b207f58d2578a4Mark Andrews * file, You can obtain one at http://mozilla.org/MPL/2.0/.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Need older API functions from ldap.h.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsstatic dns_sdlzimplementation_t *dlz_ldap = NULL;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Structure to hold everthing needed by this "instance" of the LDAP
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * driver remember, the driver code is only loaded once, but may have
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * many separate instances.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewstypedef struct {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews int method; /*%< security authentication method */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews char *cred; /*%< password for simple authentication method */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews int protocol; /*%< LDAP communication protocol version */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/* forward references */
abff0f462a758383d012887d3a97da4dac0c5a94Evan Huntdlz_ldap_findzone(void *driverarg, void *dbdata, const char *name,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsdlz_ldap_destroy(void *driverarg, void *dbdata);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Private methods
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/*% checks that the LDAP URL parameters make sense */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsdlz_ldap_checkURL(char *URL, int attrCnt, const char *msg) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (ldap_result != LDAP_SUCCESS || ldap_url == NULL) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (ldap_count_values(ldap_url->lud_attrs) < attrCnt) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "%s query must specify at least "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "%d attributes to return",
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (ldap_url->lud_dn == NULL || strlen (ldap_url->lud_dn) < 1) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (ldap_url->lud_exts != NULL || ldap_url->lud_crit_exts != 0) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "%s uses extensions. "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "The driver does not support LDAP extensions.",
5d35a7a2fbcf6bd060b0ce7deb349e427cb59fc1Evan Hunt/*% Connects / reconnects to LDAP server */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsdlz_ldap_connect(ldap_instance_t *dbi, dbinstance_t *dbc) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if we have a connection, get ride of it. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* now connect / reconnect. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* initialize. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbc->dbconn = ldap_init(dbi->hosts, LDAP_PORT);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* set protocol version. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ldap_result = ldap_set_option((LDAP *) dbc->dbconn,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* "bind" to server. i.e. send username / pass */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ldap_result = ldap_bind_s((LDAP *) dbc->dbconn, dbi->user,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* cleanup if failure. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Properly cleans up a list of database instances.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * This function is only used when the driver is compiled for
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * multithreaded operation.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get the first DBI in the list */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* loop through the list */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get the next DBI in the list */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* release DB connection */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* release all memory that comprised a DBI */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* release memory for the list structure */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_put(ns_g_mctx, dblist, sizeof(db_list_t));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Loops through the list of DB instances, attempting to lock
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * on the mutex. If successful, the DBI is reserved for use
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * and the thread can perform queries against the database.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * If the lock fails, the next one in the list is tried.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * looping continues until a lock is obtained, or until
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * the list has been searched dbc_search_limit times.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * This function is only used when the driver is compiled for
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * multithreaded operation.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get top of list */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* loop through list */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* try to lock on the mutex */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (isc_mutex_trylock(&dbi->instance_lock) == ISC_R_SUCCESS)
5d35a7a2fbcf6bd060b0ce7deb349e427cb59fc1Evan Hunt return (dbi); /* success, return the DBI for use. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* not successful, keep trying */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* check to see if we have gone to the top of the list. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP driver unable to find available connection "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "after searching %d times",
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif /* ISC_PLATFORM_USETHREADS */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsldap_process_results(LDAP *dbc, LDAPMessage *msg, char ** attrs,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* make sure there are at least some attributes to process. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get the first entry to process */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP no entries to process.");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* loop through all entries returned */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* reset for this loop */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* determine how much space we need for data string */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get the list of values for this attribute. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* skip empty attributes. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (vals == NULL || ldap_count_values(vals) < 1)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * we only use the first value. this driver
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * does not support multi-valued attributes.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* free vals for next loop */
5d35a7a2fbcf6bd060b0ce7deb349e427cb59fc1Evan Hunt } /* end for (j = 0; attrs[j] != NULL, j++) loop */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* allocate memory for data string */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP driver unable to allocate memory "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "while processing results");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Make sure data is null termed at the beginning so
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * we can check if any data was stored to it later.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* reset j to re-use below */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* loop through the attributes in the order specified. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get the list of values for this attribute. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* skip empty attributes. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* increment attibute pointer */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* start loop over */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * j initially = 0. Increment j each time we
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * set a field that way next loop will set
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * next field.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * convert text to int, make sure it
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * worked right
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP driver ttl must "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "be a postive number");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } /* end switch(j) */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* free values */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* increment attibute pointer */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } /* end while (attribute != NULL) */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP driver unable "
5d35a7a2fbcf6bd060b0ce7deb349e427cb59fc1Evan Hunt "to retrieve DNS type");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP driver unable "
5d35a7a2fbcf6bd060b0ce7deb349e427cb59fc1Evan Hunt "to retrieve DNS data");
f02b5d87a561ba669bd368a8a6422f364f7702ecEvan Hunt "dlz-ldap: putnamedrr failed "
f02b5d87a561ba669bd368a8a6422f364f7702ecEvan Hunt "for \"%s %s %u %s\", %s",
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = dns_sdlz_putrr((dns_sdlzlookup_t *) ptr,
f02b5d87a561ba669bd368a8a6422f364f7702ecEvan Hunt "dlz-ldap: putrr failed "
f02b5d87a561ba669bd368a8a6422f364f7702ecEvan Hunt "for \"%s %u %s\", %s",
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP driver failed "
f02b5d87a561ba669bd368a8a6422f364f7702ecEvan Hunt "while sending data to BIND.");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* free memory for type, data and host for next loop */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get the next entry to process */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } /* end while (entry != NULL) */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* de-allocate memory */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * This function is the real core of the driver. Zone, record
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * and client strings are passed in (or NULL is passed if the
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * string is not available). The type of query we want to run
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * is indicated by the query flag, and the dbdata object is passed
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * passed in to. dbdata really holds either:
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * 1) a list of database instances (in multithreaded mode) OR
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * 2) a single database instance (in single threaded mode)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * The function will construct the query and obtain an available
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * database instance (DBI). It will then run the query and hopefully
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * obtain a result set.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsldap_get_results(const char *zone, const char *record,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get db instance / connection */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* find an available DBI from the list */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#else /* ISC_PLATFORM_USETHREADS */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * only 1 DBI - no need to lock instance lock either
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * only 1 thread in the whole process, no possible contention.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbi = (dbinstance_t *) ((ldap_instance_t *)dbdata)->db;
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif /* ISC_PLATFORM_USETHREADS */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if DBI is null, can't do anything else */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* set fields */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbi->record = isc_mem_strdup(ns_g_mctx, record);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews dbi->client = isc_mem_strdup(ns_g_mctx, client);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* what type of query are we going to run? */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * if the query was not passed in from the config file
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * then we can't run it. return not_implemented, so
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * it's like the code for that operation was never
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * built into the driver.... AHHH flexibility!!!
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* same as comments as ALLNODES */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* same as comments as ALLNODES */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* this is required. It's the whole point of DLZ! */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "No query specified for findzone. "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Findzone requires a query");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* this is required. It's also a major point of DLZ! */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "No query specified for lookup. "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Lookup requires a query");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * this should never happen. If it does, the code is
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * screwed up!
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Incorrect query flag passed to "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "ldap_get_results");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if the querystring is null, Bummer, outta RAM. UPGRADE TIME!!! */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * output the full query string during debug so we can see
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * what lame error the query has.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* break URL down into it's component parts, if error cleanup */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ldap_result = ldap_url_parse(querystring, &ldap_url);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (ldap_result != LDAP_SUCCESS || ldap_url == NULL) {
5d35a7a2fbcf6bd060b0ce7deb349e427cb59fc1Evan Hunt for (i = 0; i < 3; i++) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * dbi->dbconn may be null if trying to reconnect on a
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * previous query failed.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP driver attempting to re-connect");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = dlz_ldap_connect((ldap_instance_t *) dbdata,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* perform ldap search syncronously */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ldap_result = ldap_search_s((LDAP *) dbi->dbconn,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * check return code. No such object is ok, just
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * didn't find what we wanted
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "No object found matching "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "query requirements");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP driver attempting to re-connect");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = dlz_ldap_connect((ldap_instance_t *) dbdata,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * other errors not ok. Log error message and
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP error: %s",
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } /* close switch(ldap_result) */
5d35a7a2fbcf6bd060b0ce7deb349e427cb59fc1Evan Hunt } /* end for (int i = 0 i < 3; i++) */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ldap_process_results((LDAP *) dbi->dbconn, ldap_msg,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = ldap_process_results((LDAP *) dbi->dbconn, ldap_msg,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews entries = ldap_count_entries((LDAP *) dbi->dbconn, ldap_msg);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews else if (entries > 0)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews entries = ldap_count_entries((LDAP *) dbi->dbconn, ldap_msg);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews else if (entries > 0)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * this should never happen. If it does, the code is
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * screwed up!
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Incorrect query flag passed to "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "ldap_get_results");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* it's always good to cleanup after yourself */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if we retrieved results, free them */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* cleanup */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* release the lock so another thread can use this dbi */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif /* ISC_PLATFORM_USETHREADS */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* release query string */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* return result */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * DLZ methods
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsdlz_ldap_allowzonexfr(void *driverarg, void *dbdata, const char *name,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* check to see if we are authoritative for the zone first */
abff0f462a758383d012887d3a97da4dac0c5a94Evan Hunt result = dlz_ldap_findzone(driverarg, dbdata, name, NULL, NULL);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* get all the zone data */
5d35a7a2fbcf6bd060b0ce7deb349e427cb59fc1Evan Hunt result = ldap_get_results(name, NULL, client, ALLOWXFR, dbdata, NULL);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsdlz_ldap_allnodes(const char *zone, void *driverarg, void *dbdata,
5d35a7a2fbcf6bd060b0ce7deb349e427cb59fc1Evan Hunt return (ldap_get_results(zone, NULL, NULL, ALLNODES, dbdata, allnodes));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsdlz_ldap_authority(const char *zone, void *driverarg, void *dbdata,
5d35a7a2fbcf6bd060b0ce7deb349e427cb59fc1Evan Hunt return (ldap_get_results(zone, NULL, NULL, AUTHORITY, dbdata, lookup));
abff0f462a758383d012887d3a97da4dac0c5a94Evan Huntdlz_ldap_findzone(void *driverarg, void *dbdata, const char *name,
5d35a7a2fbcf6bd060b0ce7deb349e427cb59fc1Evan Hunt return (ldap_get_results(name, NULL, NULL, FINDZONE, dbdata, NULL));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsdlz_ldap_lookup(const char *zone, const char *name, void *driverarg,
793814f80703afdd69b59ade91e63efa81ae4178Evan Hunt dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo)
5d35a7a2fbcf6bd060b0ce7deb349e427cb59fc1Evan Hunt result = ldap_get_results(zone, "~", NULL, LOOKUP,
5d35a7a2fbcf6bd060b0ce7deb349e427cb59fc1Evan Hunt result = ldap_get_results(zone, name, NULL, LOOKUP,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrewsdlz_ldap_create(const char *dlzname, unsigned int argc, char *argv[],
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if multi-threaded, we need a few extra variables. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews/* db_list_t *dblist = NULL; */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif /* ISC_PLATFORM_USETHREADS */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if debugging, let user know we are multithreaded. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP driver running multithreaded");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#else /* ISC_PLATFORM_USETHREADS */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* if debugging, let user know we are single threaded. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP driver running single threaded");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif /* ISC_PLATFORM_USETHREADS */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP driver requires at least "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "8 command line args.");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* no more than 13 arg's should be passed to the driver */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP driver cannot accept more than "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "11 command line args.");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* determine protocol version. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (strncasecmp(argv[2], V2, strlen(V2)) == 0) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } else if (strncasecmp(argv[2], V3, strlen(V3)) == 0) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP driver protocol must be either %s or %s",
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* determine connection method. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (strncasecmp(argv[3], SIMPLE, strlen(SIMPLE)) == 0) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } else if (strncasecmp(argv[3], KRB41, strlen(KRB41)) == 0) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } else if (strncasecmp(argv[3], KRB42, strlen(KRB42)) == 0) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP driver authentication method must be "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "one of %s, %s or %s",
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* multithreaded build can have multiple DB connections */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* check how many db connections we should create */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP driver database connection count "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "must be positive.");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* check that LDAP URL parameters make sense */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = dlz_ldap_checkURL(argv[11], 0, "allow zone transfer");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = dlz_ldap_checkURL(argv[10], 3, "all nodes");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = dlz_ldap_checkURL(argv[9], 3, "authority");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = dlz_ldap_checkURL(argv[8], 3, "lookup");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = dlz_ldap_checkURL(argv[7], 0, "find zone");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* not really needed, should shut up compiler. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* allocate memory for LDAP instance */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ldap_inst = isc_mem_get(ns_g_mctx, sizeof(ldap_instance_t));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* store info needed to automatically re-connect. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ldap_inst->hosts = isc_mem_strdup(ns_g_mctx, argv[6]);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ldap_inst->user = isc_mem_strdup(ns_g_mctx, argv[4]);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ldap_inst->cred = isc_mem_strdup(ns_g_mctx, argv[5]);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* allocate memory for database connection list */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews ldap_inst->db = isc_mem_get(ns_g_mctx, sizeof(db_list_t));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* initialize DB connection list */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * create the appropriate number of database instances (DBI)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * append each new DBI to the end of the list
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews for (i = 0; i < dbcount; i++) {
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif /* ISC_PLATFORM_USETHREADS */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* how many queries were passed in from config file? */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = build_sqldbinstance(ns_g_mctx, argv[10], NULL,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = build_sqldbinstance(ns_g_mctx, argv[10],
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* not really needed, should shut up compiler. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP driver created "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "database instance object.");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } else { /* unsuccessful?, log err msg and cleanup. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP driver could not create "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "database instance object.");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* when multithreaded, build a list of DBI's */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * when single threaded, hold onto the one connection
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* attempt to connect */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * if db connection cannot be created, log err msg and
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* success, do nothing */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * no memory means ldap_init could not
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * allocate memory
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP driver could not allocate memory "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "for connection number %u",
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP driver could not allocate memory "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "for connection");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * no perm means ldap_set_option could not set
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * protocol version
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP driver could not "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "set protocol version.");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* failure means couldn't connect to ldap server */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP driver could not "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "bind connection number %u to server.",
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "LDAP driver could not "
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "bind connection to server.");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * default should never happen. If it does,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * major errors.
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "dlz_ldap_create() failed: %s",
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } /* end switch(result) */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* set DBI = null for next loop through. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews } /* end for loop */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif /* ISC_PLATFORM_USETHREADS */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* set dbdata to the ldap_instance we created. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* hey, we got through all of that ok, return success. */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* cleanup the list of DBI's */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#else /* ISC_PLATFORM_USETHREADS */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (((ldap_instance_t *)dbdata)->db->dbconn != NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews /* destroy single DB instance */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews destroy_sqldbinstance(((ldap_instance_t *)dbdata)->db);
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews#endif /* ISC_PLATFORM_USETHREADS */
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews if (((ldap_instance_t *)dbdata)->hosts != NULL)
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_mem_put(ns_g_mctx, dbdata, sizeof(ldap_instance_t));
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Wrapper around dns_sdlzregister().
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Write debugging message to log
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Registering DLZ ldap driver.");
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews result = dns_sdlzregister("ldap", &dlz_ldap_methods, NULL,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "dns_sdlzregister() failed: %s",
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Wrapper around dns_sdlzunregister().
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews * Write debugging message to log
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
03e200df5dc283f24a6a349f0b31d3eab26da893Mark Andrews "Unregistering DLZ ldap driver.");