xref: /minix3/external/bsd/bind/dist/contrib/dlz/drivers/dlz_ldap_driver.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: dlz_ldap_driver.c,v 1.7 2014/12/10 04:37:55 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
5*00b67f09SDavid van Moolenbroek  *
6*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and distribute this software for any
7*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the
8*00b67f09SDavid van Moolenbroek  * above copyright notice and this permission notice appear in all
9*00b67f09SDavid van Moolenbroek  * copies.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
12*00b67f09SDavid van Moolenbroek  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
13*00b67f09SDavid van Moolenbroek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
14*00b67f09SDavid van Moolenbroek  * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
15*00b67f09SDavid van Moolenbroek  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
16*00b67f09SDavid van Moolenbroek  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
17*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
18*00b67f09SDavid van Moolenbroek  * USE OR PERFORMANCE OF THIS SOFTWARE.
19*00b67f09SDavid van Moolenbroek  *
20*00b67f09SDavid van Moolenbroek  * The development of Dynamically Loadable Zones (DLZ) for BIND 9 was
21*00b67f09SDavid van Moolenbroek  * conceived and contributed by Rob Butler.
22*00b67f09SDavid van Moolenbroek  *
23*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and distribute this software for any
24*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the
25*00b67f09SDavid van Moolenbroek  * above copyright notice and this permission notice appear in all
26*00b67f09SDavid van Moolenbroek  * copies.
27*00b67f09SDavid van Moolenbroek  *
28*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
29*00b67f09SDavid van Moolenbroek  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
30*00b67f09SDavid van Moolenbroek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
31*00b67f09SDavid van Moolenbroek  * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
32*00b67f09SDavid van Moolenbroek  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
33*00b67f09SDavid van Moolenbroek  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
34*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
35*00b67f09SDavid van Moolenbroek  * USE OR PERFORMANCE OF THIS SOFTWARE.
36*00b67f09SDavid van Moolenbroek  */
37*00b67f09SDavid van Moolenbroek 
38*00b67f09SDavid van Moolenbroek /*
39*00b67f09SDavid van Moolenbroek  * Copyright (C) 1999-2001  Internet Software Consortium.
40*00b67f09SDavid van Moolenbroek  *
41*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and distribute this software for any
42*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
43*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
44*00b67f09SDavid van Moolenbroek  *
45*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
46*00b67f09SDavid van Moolenbroek  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
47*00b67f09SDavid van Moolenbroek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
48*00b67f09SDavid van Moolenbroek  * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
49*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
50*00b67f09SDavid van Moolenbroek  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
51*00b67f09SDavid van Moolenbroek  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
52*00b67f09SDavid van Moolenbroek  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
53*00b67f09SDavid van Moolenbroek  */
54*00b67f09SDavid van Moolenbroek 
55*00b67f09SDavid van Moolenbroek #ifdef DLZ_LDAP
56*00b67f09SDavid van Moolenbroek 
57*00b67f09SDavid van Moolenbroek #include <config.h>
58*00b67f09SDavid van Moolenbroek #include <stdio.h>
59*00b67f09SDavid van Moolenbroek #include <string.h>
60*00b67f09SDavid van Moolenbroek #include <stdlib.h>
61*00b67f09SDavid van Moolenbroek 
62*00b67f09SDavid van Moolenbroek #include <dns/log.h>
63*00b67f09SDavid van Moolenbroek #include <dns/sdlz.h>
64*00b67f09SDavid van Moolenbroek #include <dns/result.h>
65*00b67f09SDavid van Moolenbroek 
66*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
67*00b67f09SDavid van Moolenbroek #include <isc/platform.h>
68*00b67f09SDavid van Moolenbroek #include <isc/print.h>
69*00b67f09SDavid van Moolenbroek #include <isc/result.h>
70*00b67f09SDavid van Moolenbroek #include <isc/string.h>
71*00b67f09SDavid van Moolenbroek #include <isc/util.h>
72*00b67f09SDavid van Moolenbroek 
73*00b67f09SDavid van Moolenbroek #include <named/globals.h>
74*00b67f09SDavid van Moolenbroek 
75*00b67f09SDavid van Moolenbroek #include <dlz/sdlz_helper.h>
76*00b67f09SDavid van Moolenbroek #include <dlz/dlz_ldap_driver.h>
77*00b67f09SDavid van Moolenbroek 
78*00b67f09SDavid van Moolenbroek /*
79*00b67f09SDavid van Moolenbroek  * Need older API functions from ldap.h.
80*00b67f09SDavid van Moolenbroek  */
81*00b67f09SDavid van Moolenbroek #define LDAP_DEPRECATED 1
82*00b67f09SDavid van Moolenbroek 
83*00b67f09SDavid van Moolenbroek #include <ldap.h>
84*00b67f09SDavid van Moolenbroek 
85*00b67f09SDavid van Moolenbroek #define SIMPLE "simple"
86*00b67f09SDavid van Moolenbroek #define KRB41 "krb41"
87*00b67f09SDavid van Moolenbroek #define KRB42 "krb42"
88*00b67f09SDavid van Moolenbroek #define V2 "v2"
89*00b67f09SDavid van Moolenbroek #define V3 "v3"
90*00b67f09SDavid van Moolenbroek 
91*00b67f09SDavid van Moolenbroek static dns_sdlzimplementation_t *dlz_ldap = NULL;
92*00b67f09SDavid van Moolenbroek 
93*00b67f09SDavid van Moolenbroek #define dbc_search_limit 30
94*00b67f09SDavid van Moolenbroek #define ALLNODES 1
95*00b67f09SDavid van Moolenbroek #define ALLOWXFR 2
96*00b67f09SDavid van Moolenbroek #define AUTHORITY 3
97*00b67f09SDavid van Moolenbroek #define FINDZONE 4
98*00b67f09SDavid van Moolenbroek #define LOOKUP 5
99*00b67f09SDavid van Moolenbroek 
100*00b67f09SDavid van Moolenbroek /*%
101*00b67f09SDavid van Moolenbroek  * Structure to hold everthing needed by this "instance" of the LDAP
102*00b67f09SDavid van Moolenbroek  * driver remember, the driver code is only loaded once, but may have
103*00b67f09SDavid van Moolenbroek  * many separate instances.
104*00b67f09SDavid van Moolenbroek  */
105*00b67f09SDavid van Moolenbroek 
106*00b67f09SDavid van Moolenbroek typedef struct {
107*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
108*00b67f09SDavid van Moolenbroek 	db_list_t    *db; /*%< handle to a list of DB */
109*00b67f09SDavid van Moolenbroek #else
110*00b67f09SDavid van Moolenbroek 	dbinstance_t *db; /*%< handle to db */
111*00b67f09SDavid van Moolenbroek #endif
112*00b67f09SDavid van Moolenbroek 	int method;	/*%< security authentication method */
113*00b67f09SDavid van Moolenbroek 	char *user;	/*%< who is authenticating */
114*00b67f09SDavid van Moolenbroek 	char *cred;	/*%< password for simple authentication method */
115*00b67f09SDavid van Moolenbroek 	int protocol;	/*%< LDAP communication protocol version */
116*00b67f09SDavid van Moolenbroek 	char *hosts;	/*%< LDAP server hosts */
117*00b67f09SDavid van Moolenbroek } ldap_instance_t;
118*00b67f09SDavid van Moolenbroek 
119*00b67f09SDavid van Moolenbroek /* forward references */
120*00b67f09SDavid van Moolenbroek 
121*00b67f09SDavid van Moolenbroek static isc_result_t
122*00b67f09SDavid van Moolenbroek dlz_ldap_findzone(void *driverarg, void *dbdata, const char *name,
123*00b67f09SDavid van Moolenbroek 		  dns_clientinfomethods_t *methods,
124*00b67f09SDavid van Moolenbroek 		  dns_clientinfo_t *clientinfo);
125*00b67f09SDavid van Moolenbroek 
126*00b67f09SDavid van Moolenbroek static void
127*00b67f09SDavid van Moolenbroek dlz_ldap_destroy(void *driverarg, void *dbdata);
128*00b67f09SDavid van Moolenbroek 
129*00b67f09SDavid van Moolenbroek /*
130*00b67f09SDavid van Moolenbroek  * Private methods
131*00b67f09SDavid van Moolenbroek  */
132*00b67f09SDavid van Moolenbroek 
133*00b67f09SDavid van Moolenbroek /*% checks that the LDAP URL parameters make sense */
134*00b67f09SDavid van Moolenbroek static isc_result_t
dlz_ldap_checkURL(char * URL,int attrCnt,const char * msg)135*00b67f09SDavid van Moolenbroek dlz_ldap_checkURL(char *URL, int attrCnt, const char *msg) {
136*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
137*00b67f09SDavid van Moolenbroek 	int ldap_result;
138*00b67f09SDavid van Moolenbroek 	LDAPURLDesc *ldap_url = NULL;
139*00b67f09SDavid van Moolenbroek 
140*00b67f09SDavid van Moolenbroek 	if (!ldap_is_ldap_url(URL)) {
141*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
142*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
143*00b67f09SDavid van Moolenbroek 			      "%s query is not a valid LDAP URL", msg);
144*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
145*00b67f09SDavid van Moolenbroek 		goto cleanup;
146*00b67f09SDavid van Moolenbroek 	}
147*00b67f09SDavid van Moolenbroek 
148*00b67f09SDavid van Moolenbroek 	ldap_result = ldap_url_parse(URL, &ldap_url);
149*00b67f09SDavid van Moolenbroek 	if (ldap_result != LDAP_SUCCESS || ldap_url == NULL) {
150*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
151*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
152*00b67f09SDavid van Moolenbroek 			      "parsing %s query failed", msg);
153*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
154*00b67f09SDavid van Moolenbroek 		goto cleanup;
155*00b67f09SDavid van Moolenbroek 	}
156*00b67f09SDavid van Moolenbroek 
157*00b67f09SDavid van Moolenbroek 	if (ldap_count_values(ldap_url->lud_attrs) < attrCnt) {
158*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
159*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
160*00b67f09SDavid van Moolenbroek 			      "%s query must specify at least "
161*00b67f09SDavid van Moolenbroek 			      "%d attributes to return",
162*00b67f09SDavid van Moolenbroek 			      msg, attrCnt);
163*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
164*00b67f09SDavid van Moolenbroek 		goto cleanup;
165*00b67f09SDavid van Moolenbroek 	}
166*00b67f09SDavid van Moolenbroek 
167*00b67f09SDavid van Moolenbroek 	if (ldap_url->lud_host != NULL) {
168*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
169*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
170*00b67f09SDavid van Moolenbroek 			      "%s query must not specify a host", msg);
171*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
172*00b67f09SDavid van Moolenbroek 		goto cleanup;
173*00b67f09SDavid van Moolenbroek 	}
174*00b67f09SDavid van Moolenbroek 
175*00b67f09SDavid van Moolenbroek 	if (ldap_url->lud_port != 389) {
176*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
177*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
178*00b67f09SDavid van Moolenbroek 			      "%s query must not specify a port", msg);
179*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
180*00b67f09SDavid van Moolenbroek 		goto cleanup;
181*00b67f09SDavid van Moolenbroek 	}
182*00b67f09SDavid van Moolenbroek 
183*00b67f09SDavid van Moolenbroek 	if (ldap_url->lud_dn == NULL || strlen (ldap_url->lud_dn) < 1) {
184*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
185*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
186*00b67f09SDavid van Moolenbroek 			      "%s query must specify a search base", msg);
187*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
188*00b67f09SDavid van Moolenbroek 		goto cleanup;
189*00b67f09SDavid van Moolenbroek 	}
190*00b67f09SDavid van Moolenbroek 
191*00b67f09SDavid van Moolenbroek 	if (ldap_url->lud_exts != NULL || ldap_url->lud_crit_exts != 0) {
192*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
193*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
194*00b67f09SDavid van Moolenbroek 			      "%s uses extensions. "
195*00b67f09SDavid van Moolenbroek 			      "The driver does not support LDAP extensions.",
196*00b67f09SDavid van Moolenbroek 			      msg);
197*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
198*00b67f09SDavid van Moolenbroek 		goto cleanup;
199*00b67f09SDavid van Moolenbroek 	}
200*00b67f09SDavid van Moolenbroek 
201*00b67f09SDavid van Moolenbroek  cleanup:
202*00b67f09SDavid van Moolenbroek 	if (ldap_url != NULL)
203*00b67f09SDavid van Moolenbroek 		ldap_free_urldesc(ldap_url);
204*00b67f09SDavid van Moolenbroek 
205*00b67f09SDavid van Moolenbroek 	return (result);
206*00b67f09SDavid van Moolenbroek }
207*00b67f09SDavid van Moolenbroek 
208*00b67f09SDavid van Moolenbroek /*% Connects / reconnects to LDAP server */
209*00b67f09SDavid van Moolenbroek static isc_result_t
dlz_ldap_connect(ldap_instance_t * dbi,dbinstance_t * dbc)210*00b67f09SDavid van Moolenbroek dlz_ldap_connect(ldap_instance_t *dbi, dbinstance_t *dbc) {
211*00b67f09SDavid van Moolenbroek 	isc_result_t result;
212*00b67f09SDavid van Moolenbroek 	int ldap_result;
213*00b67f09SDavid van Moolenbroek 
214*00b67f09SDavid van Moolenbroek 	/* if we have a connection, get ride of it. */
215*00b67f09SDavid van Moolenbroek 	if (dbc->dbconn != NULL) {
216*00b67f09SDavid van Moolenbroek 		ldap_unbind_s((LDAP *) dbc->dbconn);
217*00b67f09SDavid van Moolenbroek 		dbc->dbconn = NULL;
218*00b67f09SDavid van Moolenbroek 	}
219*00b67f09SDavid van Moolenbroek 
220*00b67f09SDavid van Moolenbroek 	/* now connect / reconnect. */
221*00b67f09SDavid van Moolenbroek 
222*00b67f09SDavid van Moolenbroek 	/* initialize. */
223*00b67f09SDavid van Moolenbroek 	dbc->dbconn = ldap_init(dbi->hosts, LDAP_PORT);
224*00b67f09SDavid van Moolenbroek 	if (dbc->dbconn == NULL)
225*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
226*00b67f09SDavid van Moolenbroek 
227*00b67f09SDavid van Moolenbroek 	/* set protocol version. */
228*00b67f09SDavid van Moolenbroek 	ldap_result = ldap_set_option((LDAP *) dbc->dbconn,
229*00b67f09SDavid van Moolenbroek 				      LDAP_OPT_PROTOCOL_VERSION,
230*00b67f09SDavid van Moolenbroek 				      &(dbi->protocol));
231*00b67f09SDavid van Moolenbroek 	if (ldap_result != LDAP_SUCCESS) {
232*00b67f09SDavid van Moolenbroek 		result = ISC_R_NOPERM;
233*00b67f09SDavid van Moolenbroek 		goto cleanup;
234*00b67f09SDavid van Moolenbroek 	}
235*00b67f09SDavid van Moolenbroek 
236*00b67f09SDavid van Moolenbroek 	/* "bind" to server.  i.e. send username / pass */
237*00b67f09SDavid van Moolenbroek 	ldap_result = ldap_bind_s((LDAP *) dbc->dbconn, dbi->user,
238*00b67f09SDavid van Moolenbroek 				  dbi->cred, dbi->method);
239*00b67f09SDavid van Moolenbroek 	if (ldap_result != LDAP_SUCCESS) {
240*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
241*00b67f09SDavid van Moolenbroek 		goto cleanup;
242*00b67f09SDavid van Moolenbroek 	}
243*00b67f09SDavid van Moolenbroek 
244*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
245*00b67f09SDavid van Moolenbroek 
246*00b67f09SDavid van Moolenbroek  cleanup:
247*00b67f09SDavid van Moolenbroek 
248*00b67f09SDavid van Moolenbroek 	/* cleanup if failure. */
249*00b67f09SDavid van Moolenbroek 	if (dbc->dbconn != NULL) {
250*00b67f09SDavid van Moolenbroek 		ldap_unbind_s((LDAP *) dbc->dbconn);
251*00b67f09SDavid van Moolenbroek 		dbc->dbconn = NULL;
252*00b67f09SDavid van Moolenbroek 	}
253*00b67f09SDavid van Moolenbroek 
254*00b67f09SDavid van Moolenbroek 	return (result);
255*00b67f09SDavid van Moolenbroek }
256*00b67f09SDavid van Moolenbroek 
257*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
258*00b67f09SDavid van Moolenbroek 
259*00b67f09SDavid van Moolenbroek 
260*00b67f09SDavid van Moolenbroek /*%
261*00b67f09SDavid van Moolenbroek  * Properly cleans up a list of database instances.
262*00b67f09SDavid van Moolenbroek  * This function is only used when the driver is compiled for
263*00b67f09SDavid van Moolenbroek  * multithreaded operation.
264*00b67f09SDavid van Moolenbroek  */
265*00b67f09SDavid van Moolenbroek static void
ldap_destroy_dblist(db_list_t * dblist)266*00b67f09SDavid van Moolenbroek ldap_destroy_dblist(db_list_t *dblist) {
267*00b67f09SDavid van Moolenbroek 	dbinstance_t *ndbi = NULL;
268*00b67f09SDavid van Moolenbroek 	dbinstance_t *dbi = NULL;
269*00b67f09SDavid van Moolenbroek 
270*00b67f09SDavid van Moolenbroek 	/* get the first DBI in the list */
271*00b67f09SDavid van Moolenbroek 	ndbi = ISC_LIST_HEAD(*dblist);
272*00b67f09SDavid van Moolenbroek 
273*00b67f09SDavid van Moolenbroek 	/* loop through the list */
274*00b67f09SDavid van Moolenbroek 	while (ndbi != NULL) {
275*00b67f09SDavid van Moolenbroek 		dbi = ndbi;
276*00b67f09SDavid van Moolenbroek 		/* get the next DBI in the list */
277*00b67f09SDavid van Moolenbroek 		ndbi = ISC_LIST_NEXT(dbi, link);
278*00b67f09SDavid van Moolenbroek 		/* release DB connection */
279*00b67f09SDavid van Moolenbroek 		if (dbi->dbconn != NULL)
280*00b67f09SDavid van Moolenbroek 			ldap_unbind_s((LDAP *) dbi->dbconn);
281*00b67f09SDavid van Moolenbroek 		/* release all memory that comprised a DBI */
282*00b67f09SDavid van Moolenbroek 		destroy_sqldbinstance(dbi);
283*00b67f09SDavid van Moolenbroek 	}
284*00b67f09SDavid van Moolenbroek 	/* release memory for the list structure */
285*00b67f09SDavid van Moolenbroek 	isc_mem_put(ns_g_mctx, dblist, sizeof(db_list_t));
286*00b67f09SDavid van Moolenbroek }
287*00b67f09SDavid van Moolenbroek 
288*00b67f09SDavid van Moolenbroek /*%
289*00b67f09SDavid van Moolenbroek  * Loops through the list of DB instances, attempting to lock
290*00b67f09SDavid van Moolenbroek  * on the mutex.  If successful, the DBI is reserved for use
291*00b67f09SDavid van Moolenbroek  * and the thread can perform queries against the database.
292*00b67f09SDavid van Moolenbroek  * If the lock fails, the next one in the list is tried.
293*00b67f09SDavid van Moolenbroek  * looping continues until a lock is obtained, or until
294*00b67f09SDavid van Moolenbroek  * the list has been searched dbc_search_limit times.
295*00b67f09SDavid van Moolenbroek  * This function is only used when the driver is compiled for
296*00b67f09SDavid van Moolenbroek  * multithreaded operation.
297*00b67f09SDavid van Moolenbroek  */
298*00b67f09SDavid van Moolenbroek static dbinstance_t *
ldap_find_avail_conn(db_list_t * dblist)299*00b67f09SDavid van Moolenbroek ldap_find_avail_conn(db_list_t *dblist) {
300*00b67f09SDavid van Moolenbroek 	dbinstance_t *dbi = NULL;
301*00b67f09SDavid van Moolenbroek 	dbinstance_t *head;
302*00b67f09SDavid van Moolenbroek 	int count = 0;
303*00b67f09SDavid van Moolenbroek 
304*00b67f09SDavid van Moolenbroek 	/* get top of list */
305*00b67f09SDavid van Moolenbroek 	head = dbi = ISC_LIST_HEAD(*dblist);
306*00b67f09SDavid van Moolenbroek 
307*00b67f09SDavid van Moolenbroek 	/* loop through list */
308*00b67f09SDavid van Moolenbroek 	while (count < dbc_search_limit) {
309*00b67f09SDavid van Moolenbroek 		/* try to lock on the mutex */
310*00b67f09SDavid van Moolenbroek 		if (isc_mutex_trylock(&dbi->instance_lock) == ISC_R_SUCCESS)
311*00b67f09SDavid van Moolenbroek 			return (dbi); /* success, return the DBI for use. */
312*00b67f09SDavid van Moolenbroek 
313*00b67f09SDavid van Moolenbroek 		/* not successful, keep trying */
314*00b67f09SDavid van Moolenbroek 		dbi = ISC_LIST_NEXT(dbi, link);
315*00b67f09SDavid van Moolenbroek 
316*00b67f09SDavid van Moolenbroek 		/* check to see if we have gone to the top of the list. */
317*00b67f09SDavid van Moolenbroek 		if (dbi == NULL) {
318*00b67f09SDavid van Moolenbroek 			count++;
319*00b67f09SDavid van Moolenbroek 			dbi = head;
320*00b67f09SDavid van Moolenbroek 		}
321*00b67f09SDavid van Moolenbroek 	}
322*00b67f09SDavid van Moolenbroek 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
323*00b67f09SDavid van Moolenbroek 		      DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
324*00b67f09SDavid van Moolenbroek 		      "LDAP driver unable to find available connection "
325*00b67f09SDavid van Moolenbroek 		      "after searching %d times",
326*00b67f09SDavid van Moolenbroek 		      count);
327*00b67f09SDavid van Moolenbroek 	return (NULL);
328*00b67f09SDavid van Moolenbroek }
329*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
330*00b67f09SDavid van Moolenbroek 
331*00b67f09SDavid van Moolenbroek static isc_result_t
ldap_process_results(LDAP * dbc,LDAPMessage * msg,char ** attrs,void * ptr,isc_boolean_t allnodes)332*00b67f09SDavid van Moolenbroek ldap_process_results(LDAP *dbc, LDAPMessage *msg, char ** attrs,
333*00b67f09SDavid van Moolenbroek 		     void *ptr, isc_boolean_t allnodes)
334*00b67f09SDavid van Moolenbroek {
335*00b67f09SDavid van Moolenbroek 	isc_result_t result = ISC_R_SUCCESS;
336*00b67f09SDavid van Moolenbroek 	int i = 0;
337*00b67f09SDavid van Moolenbroek 	int j;
338*00b67f09SDavid van Moolenbroek 	int len;
339*00b67f09SDavid van Moolenbroek 	char *attribute = NULL;
340*00b67f09SDavid van Moolenbroek 	LDAPMessage *entry;
341*00b67f09SDavid van Moolenbroek 	char *endp = NULL;
342*00b67f09SDavid van Moolenbroek 	char *host = NULL;
343*00b67f09SDavid van Moolenbroek 	char *type = NULL;
344*00b67f09SDavid van Moolenbroek 	char *data = NULL;
345*00b67f09SDavid van Moolenbroek 	char **vals = NULL;
346*00b67f09SDavid van Moolenbroek 	int ttl;
347*00b67f09SDavid van Moolenbroek 
348*00b67f09SDavid van Moolenbroek 	/* make sure there are at least some attributes to process. */
349*00b67f09SDavid van Moolenbroek 	REQUIRE(attrs != NULL || attrs[0] != NULL);
350*00b67f09SDavid van Moolenbroek 
351*00b67f09SDavid van Moolenbroek 	/* get the first entry to process */
352*00b67f09SDavid van Moolenbroek 	entry = ldap_first_entry(dbc, msg);
353*00b67f09SDavid van Moolenbroek 	if (entry == NULL) {
354*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
355*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
356*00b67f09SDavid van Moolenbroek 			      "LDAP no entries to process.");
357*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
358*00b67f09SDavid van Moolenbroek 	}
359*00b67f09SDavid van Moolenbroek 
360*00b67f09SDavid van Moolenbroek 	/* loop through all entries returned */
361*00b67f09SDavid van Moolenbroek 	while (entry != NULL) {
362*00b67f09SDavid van Moolenbroek 		/* reset for this loop */
363*00b67f09SDavid van Moolenbroek 		ttl = 0;
364*00b67f09SDavid van Moolenbroek 		len = 0;
365*00b67f09SDavid van Moolenbroek 		i = 0;
366*00b67f09SDavid van Moolenbroek 		attribute = attrs[i];
367*00b67f09SDavid van Moolenbroek 
368*00b67f09SDavid van Moolenbroek 		/* determine how much space we need for data string */
369*00b67f09SDavid van Moolenbroek 		for (j = 0; attrs[j] != NULL; j++) {
370*00b67f09SDavid van Moolenbroek 			/* get the list of values for this attribute. */
371*00b67f09SDavid van Moolenbroek 			vals = ldap_get_values(dbc, entry, attrs[j]);
372*00b67f09SDavid van Moolenbroek 			/* skip empty attributes. */
373*00b67f09SDavid van Moolenbroek 			if (vals == NULL || ldap_count_values(vals) < 1)
374*00b67f09SDavid van Moolenbroek 				continue;
375*00b67f09SDavid van Moolenbroek 			/*
376*00b67f09SDavid van Moolenbroek 			 * we only use the first value.  this driver
377*00b67f09SDavid van Moolenbroek 			 * does not support multi-valued attributes.
378*00b67f09SDavid van Moolenbroek 			 */
379*00b67f09SDavid van Moolenbroek 			len = len + strlen(vals[0]) + 1;
380*00b67f09SDavid van Moolenbroek 			/* free vals for next loop */
381*00b67f09SDavid van Moolenbroek 			ldap_value_free(vals);
382*00b67f09SDavid van Moolenbroek 		} /* end for (j = 0; attrs[j] != NULL, j++) loop */
383*00b67f09SDavid van Moolenbroek 
384*00b67f09SDavid van Moolenbroek 		/* allocate memory for data string */
385*00b67f09SDavid van Moolenbroek 		data = isc_mem_allocate(ns_g_mctx, len + 1);
386*00b67f09SDavid van Moolenbroek 		if (data == NULL) {
387*00b67f09SDavid van Moolenbroek 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
388*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
389*00b67f09SDavid van Moolenbroek 				      "LDAP driver unable to allocate memory "
390*00b67f09SDavid van Moolenbroek 				      "while processing results");
391*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
392*00b67f09SDavid van Moolenbroek 			goto cleanup;
393*00b67f09SDavid van Moolenbroek 		}
394*00b67f09SDavid van Moolenbroek 
395*00b67f09SDavid van Moolenbroek 		/*
396*00b67f09SDavid van Moolenbroek 		 * Make sure data is null termed at the beginning so
397*00b67f09SDavid van Moolenbroek 		 * we can check if any data was stored to it later.
398*00b67f09SDavid van Moolenbroek 		 */
399*00b67f09SDavid van Moolenbroek 		data[0] = '\0';
400*00b67f09SDavid van Moolenbroek 
401*00b67f09SDavid van Moolenbroek 		/* reset j to re-use below */
402*00b67f09SDavid van Moolenbroek 		j = 0;
403*00b67f09SDavid van Moolenbroek 
404*00b67f09SDavid van Moolenbroek 		/* loop through the attributes in the order specified. */
405*00b67f09SDavid van Moolenbroek 		while (attribute != NULL) {
406*00b67f09SDavid van Moolenbroek 			/* get the list of values for this attribute. */
407*00b67f09SDavid van Moolenbroek 			vals = ldap_get_values(dbc, entry, attribute);
408*00b67f09SDavid van Moolenbroek 
409*00b67f09SDavid van Moolenbroek 			/* skip empty attributes. */
410*00b67f09SDavid van Moolenbroek 			if (vals == NULL || vals[0] == NULL) {
411*00b67f09SDavid van Moolenbroek 				/* increment attibute pointer */
412*00b67f09SDavid van Moolenbroek 				attribute = attrs[++i];
413*00b67f09SDavid van Moolenbroek 				/* start loop over */
414*00b67f09SDavid van Moolenbroek 				continue;
415*00b67f09SDavid van Moolenbroek 			}
416*00b67f09SDavid van Moolenbroek 
417*00b67f09SDavid van Moolenbroek 			/*
418*00b67f09SDavid van Moolenbroek 			 * j initially = 0.  Increment j each time we
419*00b67f09SDavid van Moolenbroek 			 * set a field that way next loop will set
420*00b67f09SDavid van Moolenbroek 			 * next field.
421*00b67f09SDavid van Moolenbroek 			 */
422*00b67f09SDavid van Moolenbroek 			switch(j) {
423*00b67f09SDavid van Moolenbroek 			case 0:
424*00b67f09SDavid van Moolenbroek 				j++;
425*00b67f09SDavid van Moolenbroek 				/*
426*00b67f09SDavid van Moolenbroek 				 * convert text to int, make sure it
427*00b67f09SDavid van Moolenbroek 				 * worked right
428*00b67f09SDavid van Moolenbroek 				 */
429*00b67f09SDavid van Moolenbroek 				ttl = strtol(vals[0], &endp, 10);
430*00b67f09SDavid van Moolenbroek 				if (*endp != '\0' || ttl < 0) {
431*00b67f09SDavid van Moolenbroek 					isc_log_write(dns_lctx,
432*00b67f09SDavid van Moolenbroek 						      DNS_LOGCATEGORY_DATABASE,
433*00b67f09SDavid van Moolenbroek 						      DNS_LOGMODULE_DLZ,
434*00b67f09SDavid van Moolenbroek 						      ISC_LOG_ERROR,
435*00b67f09SDavid van Moolenbroek 						      "LDAP driver ttl must "
436*00b67f09SDavid van Moolenbroek 						      "be a postive number");
437*00b67f09SDavid van Moolenbroek 					goto cleanup;
438*00b67f09SDavid van Moolenbroek 				}
439*00b67f09SDavid van Moolenbroek 				break;
440*00b67f09SDavid van Moolenbroek 			case 1:
441*00b67f09SDavid van Moolenbroek 				j++;
442*00b67f09SDavid van Moolenbroek 				type = isc_mem_strdup(ns_g_mctx, vals[0]);
443*00b67f09SDavid van Moolenbroek 				break;
444*00b67f09SDavid van Moolenbroek 			case 2:
445*00b67f09SDavid van Moolenbroek 				j++;
446*00b67f09SDavid van Moolenbroek 				if (allnodes)
447*00b67f09SDavid van Moolenbroek 					host = isc_mem_strdup(ns_g_mctx,
448*00b67f09SDavid van Moolenbroek 							      vals[0]);
449*00b67f09SDavid van Moolenbroek 				else
450*00b67f09SDavid van Moolenbroek 					strcpy(data, vals[0]);
451*00b67f09SDavid van Moolenbroek 				break;
452*00b67f09SDavid van Moolenbroek 			case 3:
453*00b67f09SDavid van Moolenbroek 				j++;
454*00b67f09SDavid van Moolenbroek 				if (allnodes)
455*00b67f09SDavid van Moolenbroek 					strcpy(data, vals[0]);
456*00b67f09SDavid van Moolenbroek 				else {
457*00b67f09SDavid van Moolenbroek 					strcat(data, " ");
458*00b67f09SDavid van Moolenbroek 					strcat(data, vals[0]);
459*00b67f09SDavid van Moolenbroek 				}
460*00b67f09SDavid van Moolenbroek 				break;
461*00b67f09SDavid van Moolenbroek 			default:
462*00b67f09SDavid van Moolenbroek 				strcat(data, " ");
463*00b67f09SDavid van Moolenbroek 				strcat(data, vals[0]);
464*00b67f09SDavid van Moolenbroek 				break;
465*00b67f09SDavid van Moolenbroek 			} /* end switch(j) */
466*00b67f09SDavid van Moolenbroek 
467*00b67f09SDavid van Moolenbroek 			/* free values */
468*00b67f09SDavid van Moolenbroek 			ldap_value_free(vals);
469*00b67f09SDavid van Moolenbroek 			vals = NULL;
470*00b67f09SDavid van Moolenbroek 
471*00b67f09SDavid van Moolenbroek 			/* increment attibute pointer */
472*00b67f09SDavid van Moolenbroek 			attribute = attrs[++i];
473*00b67f09SDavid van Moolenbroek 		}	/* end while (attribute != NULL) */
474*00b67f09SDavid van Moolenbroek 
475*00b67f09SDavid van Moolenbroek 		if (type == NULL) {
476*00b67f09SDavid van Moolenbroek 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
477*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
478*00b67f09SDavid van Moolenbroek 				      "LDAP driver unable "
479*00b67f09SDavid van Moolenbroek 				      "to retrieve DNS type");
480*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
481*00b67f09SDavid van Moolenbroek 			goto cleanup;
482*00b67f09SDavid van Moolenbroek 		}
483*00b67f09SDavid van Moolenbroek 
484*00b67f09SDavid van Moolenbroek 		if (strlen(data) < 1) {
485*00b67f09SDavid van Moolenbroek 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
486*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
487*00b67f09SDavid van Moolenbroek 				      "LDAP driver unable "
488*00b67f09SDavid van Moolenbroek 				      "to retrieve DNS data");
489*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
490*00b67f09SDavid van Moolenbroek 			goto cleanup;
491*00b67f09SDavid van Moolenbroek 		}
492*00b67f09SDavid van Moolenbroek 
493*00b67f09SDavid van Moolenbroek 		if (allnodes && host != NULL) {
494*00b67f09SDavid van Moolenbroek 			if (strcasecmp(host, "~") == 0)
495*00b67f09SDavid van Moolenbroek 				result = dns_sdlz_putnamedrr(
496*00b67f09SDavid van Moolenbroek 						(dns_sdlzallnodes_t *) ptr,
497*00b67f09SDavid van Moolenbroek 						"*", type, ttl, data);
498*00b67f09SDavid van Moolenbroek 			else
499*00b67f09SDavid van Moolenbroek 				result = dns_sdlz_putnamedrr(
500*00b67f09SDavid van Moolenbroek 						(dns_sdlzallnodes_t *) ptr,
501*00b67f09SDavid van Moolenbroek 						host, type, ttl, data);
502*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS)
503*00b67f09SDavid van Moolenbroek 				isc_log_write(dns_lctx,
504*00b67f09SDavid van Moolenbroek 					DNS_LOGCATEGORY_DATABASE,
505*00b67f09SDavid van Moolenbroek 					DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
506*00b67f09SDavid van Moolenbroek 					"dlz-ldap: putnamedrr failed "
507*00b67f09SDavid van Moolenbroek 					"for \"%s %s %u %s\", %s",
508*00b67f09SDavid van Moolenbroek 					host, type, ttl, data,
509*00b67f09SDavid van Moolenbroek 					isc_result_totext(result));
510*00b67f09SDavid van Moolenbroek 		} else {
511*00b67f09SDavid van Moolenbroek 			result = dns_sdlz_putrr((dns_sdlzlookup_t *) ptr,
512*00b67f09SDavid van Moolenbroek 						type, ttl, data);
513*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS)
514*00b67f09SDavid van Moolenbroek 				isc_log_write(dns_lctx,
515*00b67f09SDavid van Moolenbroek 					DNS_LOGCATEGORY_DATABASE,
516*00b67f09SDavid van Moolenbroek 					DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
517*00b67f09SDavid van Moolenbroek 					"dlz-ldap: putrr failed "
518*00b67f09SDavid van Moolenbroek 					"for \"%s %u %s\", %s",
519*00b67f09SDavid van Moolenbroek 					type, ttl, data,
520*00b67f09SDavid van Moolenbroek 					isc_result_totext(result));
521*00b67f09SDavid van Moolenbroek 		}
522*00b67f09SDavid van Moolenbroek 
523*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
524*00b67f09SDavid van Moolenbroek 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
525*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
526*00b67f09SDavid van Moolenbroek 				      "LDAP driver failed "
527*00b67f09SDavid van Moolenbroek 				      "while sending data to BIND.");
528*00b67f09SDavid van Moolenbroek 			goto cleanup;
529*00b67f09SDavid van Moolenbroek 		}
530*00b67f09SDavid van Moolenbroek 
531*00b67f09SDavid van Moolenbroek 		/* free memory for type, data and host for next loop */
532*00b67f09SDavid van Moolenbroek 		isc_mem_free(ns_g_mctx, type);
533*00b67f09SDavid van Moolenbroek 		isc_mem_free(ns_g_mctx, data);
534*00b67f09SDavid van Moolenbroek 		if (host != NULL)
535*00b67f09SDavid van Moolenbroek 			isc_mem_free(ns_g_mctx, host);
536*00b67f09SDavid van Moolenbroek 
537*00b67f09SDavid van Moolenbroek 		/* get the next entry to process */
538*00b67f09SDavid van Moolenbroek 		entry = ldap_next_entry(dbc, entry);
539*00b67f09SDavid van Moolenbroek 	} /* end while (entry != NULL) */
540*00b67f09SDavid van Moolenbroek 
541*00b67f09SDavid van Moolenbroek  cleanup:
542*00b67f09SDavid van Moolenbroek 	/* de-allocate memory */
543*00b67f09SDavid van Moolenbroek 	if (vals != NULL)
544*00b67f09SDavid van Moolenbroek 		ldap_value_free(vals);
545*00b67f09SDavid van Moolenbroek 	if (host != NULL)
546*00b67f09SDavid van Moolenbroek 		isc_mem_free(ns_g_mctx, host);
547*00b67f09SDavid van Moolenbroek 	if (type != NULL)
548*00b67f09SDavid van Moolenbroek 		isc_mem_free(ns_g_mctx, type);
549*00b67f09SDavid van Moolenbroek 	if (data != NULL)
550*00b67f09SDavid van Moolenbroek 		isc_mem_free(ns_g_mctx, data);
551*00b67f09SDavid van Moolenbroek 
552*00b67f09SDavid van Moolenbroek 	return (result);
553*00b67f09SDavid van Moolenbroek }
554*00b67f09SDavid van Moolenbroek 
555*00b67f09SDavid van Moolenbroek /*%
556*00b67f09SDavid van Moolenbroek  * This function is the real core of the driver.   Zone, record
557*00b67f09SDavid van Moolenbroek  * and client strings are passed in (or NULL is passed if the
558*00b67f09SDavid van Moolenbroek  * string is not available).  The type of query we want to run
559*00b67f09SDavid van Moolenbroek  * is indicated by the query flag, and the dbdata object is passed
560*00b67f09SDavid van Moolenbroek  * passed in to.  dbdata really holds either:
561*00b67f09SDavid van Moolenbroek  *		1) a list of database instances (in multithreaded mode) OR
562*00b67f09SDavid van Moolenbroek  *		2) a single database instance (in single threaded mode)
563*00b67f09SDavid van Moolenbroek  * The function will construct the query and obtain an available
564*00b67f09SDavid van Moolenbroek  * database instance (DBI).  It will then run the query and hopefully
565*00b67f09SDavid van Moolenbroek  * obtain a result set.
566*00b67f09SDavid van Moolenbroek  */
567*00b67f09SDavid van Moolenbroek static isc_result_t
ldap_get_results(const char * zone,const char * record,const char * client,unsigned int query,void * dbdata,void * ptr)568*00b67f09SDavid van Moolenbroek ldap_get_results(const char *zone, const char *record,
569*00b67f09SDavid van Moolenbroek 		 const char *client, unsigned int query,
570*00b67f09SDavid van Moolenbroek 		 void *dbdata, void *ptr)
571*00b67f09SDavid van Moolenbroek {
572*00b67f09SDavid van Moolenbroek 	isc_result_t result;
573*00b67f09SDavid van Moolenbroek 	dbinstance_t *dbi = NULL;
574*00b67f09SDavid van Moolenbroek 	char *querystring = NULL;
575*00b67f09SDavid van Moolenbroek 	LDAPURLDesc *ldap_url = NULL;
576*00b67f09SDavid van Moolenbroek 	int ldap_result = 0;
577*00b67f09SDavid van Moolenbroek 	LDAPMessage *ldap_msg = NULL;
578*00b67f09SDavid van Moolenbroek 	int i;
579*00b67f09SDavid van Moolenbroek 	int entries;
580*00b67f09SDavid van Moolenbroek 
581*00b67f09SDavid van Moolenbroek 	/* get db instance / connection */
582*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
583*00b67f09SDavid van Moolenbroek 
584*00b67f09SDavid van Moolenbroek 	/* find an available DBI from the list */
585*00b67f09SDavid van Moolenbroek 	dbi = ldap_find_avail_conn((db_list_t *)
586*00b67f09SDavid van Moolenbroek 				   ((ldap_instance_t *)dbdata)->db);
587*00b67f09SDavid van Moolenbroek 
588*00b67f09SDavid van Moolenbroek #else /* ISC_PLATFORM_USETHREADS */
589*00b67f09SDavid van Moolenbroek 
590*00b67f09SDavid van Moolenbroek 	/*
591*00b67f09SDavid van Moolenbroek 	 * only 1 DBI - no need to lock instance lock either
592*00b67f09SDavid van Moolenbroek 	 * only 1 thread in the whole process, no possible contention.
593*00b67f09SDavid van Moolenbroek 	 */
594*00b67f09SDavid van Moolenbroek 	dbi =  (dbinstance_t *) ((ldap_instance_t *)dbdata)->db;
595*00b67f09SDavid van Moolenbroek 
596*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
597*00b67f09SDavid van Moolenbroek 
598*00b67f09SDavid van Moolenbroek 	/* if DBI is null, can't do anything else */
599*00b67f09SDavid van Moolenbroek 	if (dbi == NULL)
600*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
601*00b67f09SDavid van Moolenbroek 
602*00b67f09SDavid van Moolenbroek 	/* set fields */
603*00b67f09SDavid van Moolenbroek 	if (zone != NULL) {
604*00b67f09SDavid van Moolenbroek 		dbi->zone = isc_mem_strdup(ns_g_mctx, zone);
605*00b67f09SDavid van Moolenbroek 		if (dbi->zone == NULL) {
606*00b67f09SDavid van Moolenbroek 			result = ISC_R_NOMEMORY;
607*00b67f09SDavid van Moolenbroek 			goto cleanup;
608*00b67f09SDavid van Moolenbroek 		}
609*00b67f09SDavid van Moolenbroek 	} else {
610*00b67f09SDavid van Moolenbroek 		dbi->zone = NULL;
611*00b67f09SDavid van Moolenbroek 	}
612*00b67f09SDavid van Moolenbroek 	if (record != NULL) {
613*00b67f09SDavid van Moolenbroek 		dbi->record = isc_mem_strdup(ns_g_mctx, record);
614*00b67f09SDavid van Moolenbroek 		if (dbi->record == NULL) {
615*00b67f09SDavid van Moolenbroek 			result = ISC_R_NOMEMORY;
616*00b67f09SDavid van Moolenbroek 			goto cleanup;
617*00b67f09SDavid van Moolenbroek 		}
618*00b67f09SDavid van Moolenbroek 	} else {
619*00b67f09SDavid van Moolenbroek 		dbi->record = NULL;
620*00b67f09SDavid van Moolenbroek 	}
621*00b67f09SDavid van Moolenbroek 	if (client != NULL) {
622*00b67f09SDavid van Moolenbroek 		dbi->client = isc_mem_strdup(ns_g_mctx, client);
623*00b67f09SDavid van Moolenbroek 		if (dbi->client == NULL) {
624*00b67f09SDavid van Moolenbroek 			result = ISC_R_NOMEMORY;
625*00b67f09SDavid van Moolenbroek 			goto cleanup;
626*00b67f09SDavid van Moolenbroek 		}
627*00b67f09SDavid van Moolenbroek 	} else {
628*00b67f09SDavid van Moolenbroek 		dbi->client = NULL;
629*00b67f09SDavid van Moolenbroek 	}
630*00b67f09SDavid van Moolenbroek 
631*00b67f09SDavid van Moolenbroek 	/* what type of query are we going to run? */
632*00b67f09SDavid van Moolenbroek 	switch(query) {
633*00b67f09SDavid van Moolenbroek 	case ALLNODES:
634*00b67f09SDavid van Moolenbroek 		/*
635*00b67f09SDavid van Moolenbroek 		 * if the query was not passed in from the config file
636*00b67f09SDavid van Moolenbroek 		 * then we can't run it.  return not_implemented, so
637*00b67f09SDavid van Moolenbroek 		 * it's like the code for that operation was never
638*00b67f09SDavid van Moolenbroek 		 * built into the driver.... AHHH flexibility!!!
639*00b67f09SDavid van Moolenbroek 		 */
640*00b67f09SDavid van Moolenbroek 		if (dbi->allnodes_q == NULL) {
641*00b67f09SDavid van Moolenbroek 			result = ISC_R_NOTIMPLEMENTED;
642*00b67f09SDavid van Moolenbroek 			goto cleanup;
643*00b67f09SDavid van Moolenbroek 		} else {
644*00b67f09SDavid van Moolenbroek 			querystring = build_querystring(ns_g_mctx,
645*00b67f09SDavid van Moolenbroek 			dbi->allnodes_q);
646*00b67f09SDavid van Moolenbroek 		}
647*00b67f09SDavid van Moolenbroek 		break;
648*00b67f09SDavid van Moolenbroek 	case ALLOWXFR:
649*00b67f09SDavid van Moolenbroek 		/* same as comments as ALLNODES */
650*00b67f09SDavid van Moolenbroek 		if (dbi->allowxfr_q == NULL) {
651*00b67f09SDavid van Moolenbroek 			result = ISC_R_NOTIMPLEMENTED;
652*00b67f09SDavid van Moolenbroek 			goto cleanup;
653*00b67f09SDavid van Moolenbroek 		} else {
654*00b67f09SDavid van Moolenbroek 			querystring = build_querystring(ns_g_mctx,
655*00b67f09SDavid van Moolenbroek 			dbi->allowxfr_q);
656*00b67f09SDavid van Moolenbroek 		}
657*00b67f09SDavid van Moolenbroek 		break;
658*00b67f09SDavid van Moolenbroek 	case AUTHORITY:
659*00b67f09SDavid van Moolenbroek 		/* same as comments as ALLNODES */
660*00b67f09SDavid van Moolenbroek 		if (dbi->authority_q == NULL) {
661*00b67f09SDavid van Moolenbroek 			result = ISC_R_NOTIMPLEMENTED;
662*00b67f09SDavid van Moolenbroek 			goto cleanup;
663*00b67f09SDavid van Moolenbroek 		} else {
664*00b67f09SDavid van Moolenbroek 			querystring = build_querystring(ns_g_mctx,
665*00b67f09SDavid van Moolenbroek 			dbi->authority_q);
666*00b67f09SDavid van Moolenbroek 		}
667*00b67f09SDavid van Moolenbroek 		break;
668*00b67f09SDavid van Moolenbroek 	case FINDZONE:
669*00b67f09SDavid van Moolenbroek 		/* this is required.  It's the whole point of DLZ! */
670*00b67f09SDavid van Moolenbroek 		if (dbi->findzone_q == NULL) {
671*00b67f09SDavid van Moolenbroek 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
672*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
673*00b67f09SDavid van Moolenbroek 				      "No query specified for findzone.  "
674*00b67f09SDavid van Moolenbroek 				      "Findzone requires a query");
675*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
676*00b67f09SDavid van Moolenbroek 			goto cleanup;
677*00b67f09SDavid van Moolenbroek 		} else {
678*00b67f09SDavid van Moolenbroek 			querystring = build_querystring(ns_g_mctx,
679*00b67f09SDavid van Moolenbroek 			dbi->findzone_q);
680*00b67f09SDavid van Moolenbroek 		}
681*00b67f09SDavid van Moolenbroek 		break;
682*00b67f09SDavid van Moolenbroek 	case LOOKUP:
683*00b67f09SDavid van Moolenbroek 		/* this is required.  It's also a major point of DLZ! */
684*00b67f09SDavid van Moolenbroek 		if (dbi->lookup_q == NULL) {
685*00b67f09SDavid van Moolenbroek 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
686*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
687*00b67f09SDavid van Moolenbroek 				      "No query specified for lookup.  "
688*00b67f09SDavid van Moolenbroek 				      "Lookup requires a query");
689*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
690*00b67f09SDavid van Moolenbroek 			goto cleanup;
691*00b67f09SDavid van Moolenbroek 		} else {
692*00b67f09SDavid van Moolenbroek 			querystring = build_querystring(ns_g_mctx,
693*00b67f09SDavid van Moolenbroek 							dbi->lookup_q);
694*00b67f09SDavid van Moolenbroek 		}
695*00b67f09SDavid van Moolenbroek 		break;
696*00b67f09SDavid van Moolenbroek 	default:
697*00b67f09SDavid van Moolenbroek 		/*
698*00b67f09SDavid van Moolenbroek 		 * this should never happen.  If it does, the code is
699*00b67f09SDavid van Moolenbroek 		 * screwed up!
700*00b67f09SDavid van Moolenbroek 		 */
701*00b67f09SDavid van Moolenbroek 		UNEXPECTED_ERROR(__FILE__, __LINE__,
702*00b67f09SDavid van Moolenbroek 				 "Incorrect query flag passed to "
703*00b67f09SDavid van Moolenbroek 				 "ldap_get_results");
704*00b67f09SDavid van Moolenbroek 		result = ISC_R_UNEXPECTED;
705*00b67f09SDavid van Moolenbroek 		goto cleanup;
706*00b67f09SDavid van Moolenbroek 	}
707*00b67f09SDavid van Moolenbroek 
708*00b67f09SDavid van Moolenbroek 	/* if the querystring is null, Bummer, outta RAM.  UPGRADE TIME!!!   */
709*00b67f09SDavid van Moolenbroek 	if (querystring  == NULL) {
710*00b67f09SDavid van Moolenbroek 		result = ISC_R_NOMEMORY;
711*00b67f09SDavid van Moolenbroek 		goto cleanup;
712*00b67f09SDavid van Moolenbroek 	}
713*00b67f09SDavid van Moolenbroek 
714*00b67f09SDavid van Moolenbroek 	/*
715*00b67f09SDavid van Moolenbroek 	 * output the full query string during debug so we can see
716*00b67f09SDavid van Moolenbroek 	 * what lame error the query has.
717*00b67f09SDavid van Moolenbroek 	 */
718*00b67f09SDavid van Moolenbroek 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
719*00b67f09SDavid van Moolenbroek 		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
720*00b67f09SDavid van Moolenbroek 		      "\nQuery String: %s\n", querystring);
721*00b67f09SDavid van Moolenbroek 
722*00b67f09SDavid van Moolenbroek         /* break URL down into it's component parts, if error cleanup */
723*00b67f09SDavid van Moolenbroek 	ldap_result = ldap_url_parse(querystring, &ldap_url);
724*00b67f09SDavid van Moolenbroek 	if (ldap_result != LDAP_SUCCESS || ldap_url == NULL) {
725*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
726*00b67f09SDavid van Moolenbroek 		goto cleanup;
727*00b67f09SDavid van Moolenbroek 	}
728*00b67f09SDavid van Moolenbroek 
729*00b67f09SDavid van Moolenbroek 	for (i = 0; i < 3; i++) {
730*00b67f09SDavid van Moolenbroek 
731*00b67f09SDavid van Moolenbroek 		/*
732*00b67f09SDavid van Moolenbroek 		 * dbi->dbconn may be null if trying to reconnect on a
733*00b67f09SDavid van Moolenbroek 		 * previous query failed.
734*00b67f09SDavid van Moolenbroek 		 */
735*00b67f09SDavid van Moolenbroek 		if (dbi->dbconn == NULL) {
736*00b67f09SDavid van Moolenbroek 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
737*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
738*00b67f09SDavid van Moolenbroek 				      "LDAP driver attempting to re-connect");
739*00b67f09SDavid van Moolenbroek 
740*00b67f09SDavid van Moolenbroek 			result = dlz_ldap_connect((ldap_instance_t *) dbdata,
741*00b67f09SDavid van Moolenbroek 						  dbi);
742*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS) {
743*00b67f09SDavid van Moolenbroek 				result = ISC_R_FAILURE;
744*00b67f09SDavid van Moolenbroek 				continue;
745*00b67f09SDavid van Moolenbroek 			}
746*00b67f09SDavid van Moolenbroek 		}
747*00b67f09SDavid van Moolenbroek 
748*00b67f09SDavid van Moolenbroek 		/* perform ldap search syncronously */
749*00b67f09SDavid van Moolenbroek 		ldap_result = ldap_search_s((LDAP *) dbi->dbconn,
750*00b67f09SDavid van Moolenbroek 					    ldap_url->lud_dn,
751*00b67f09SDavid van Moolenbroek 					    ldap_url->lud_scope,
752*00b67f09SDavid van Moolenbroek 					    ldap_url->lud_filter,
753*00b67f09SDavid van Moolenbroek 					    ldap_url->lud_attrs, 0, &ldap_msg);
754*00b67f09SDavid van Moolenbroek 
755*00b67f09SDavid van Moolenbroek 		/*
756*00b67f09SDavid van Moolenbroek 		 * check return code.  No such object is ok, just
757*00b67f09SDavid van Moolenbroek 		 * didn't find what we wanted
758*00b67f09SDavid van Moolenbroek 		 */
759*00b67f09SDavid van Moolenbroek 		switch(ldap_result) {
760*00b67f09SDavid van Moolenbroek 		case LDAP_NO_SUCH_OBJECT:
761*00b67f09SDavid van Moolenbroek     			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
762*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
763*00b67f09SDavid van Moolenbroek 				      "No object found matching "
764*00b67f09SDavid van Moolenbroek 				      "query requirements");
765*00b67f09SDavid van Moolenbroek 			result = ISC_R_NOTFOUND;
766*00b67f09SDavid van Moolenbroek 			goto cleanup;
767*00b67f09SDavid van Moolenbroek 			break;
768*00b67f09SDavid van Moolenbroek 		case LDAP_SUCCESS:	/* on success do nothing */
769*00b67f09SDavid van Moolenbroek 			result = ISC_R_SUCCESS;
770*00b67f09SDavid van Moolenbroek 			i = 3;
771*00b67f09SDavid van Moolenbroek 			break;
772*00b67f09SDavid van Moolenbroek 		case LDAP_SERVER_DOWN:
773*00b67f09SDavid van Moolenbroek 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
774*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
775*00b67f09SDavid van Moolenbroek 				      "LDAP driver attempting to re-connect");
776*00b67f09SDavid van Moolenbroek 			result = dlz_ldap_connect((ldap_instance_t *) dbdata,
777*00b67f09SDavid van Moolenbroek 						  dbi);
778*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS)
779*00b67f09SDavid van Moolenbroek 				result = ISC_R_FAILURE;
780*00b67f09SDavid van Moolenbroek 			break;
781*00b67f09SDavid van Moolenbroek 		default:
782*00b67f09SDavid van Moolenbroek 			/*
783*00b67f09SDavid van Moolenbroek 			 * other errors not ok.  Log error message and
784*00b67f09SDavid van Moolenbroek 			 * get out
785*00b67f09SDavid van Moolenbroek 			 */
786*00b67f09SDavid van Moolenbroek     			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
787*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
788*00b67f09SDavid van Moolenbroek 				      "LDAP error: %s",
789*00b67f09SDavid van Moolenbroek 				      ldap_err2string(ldap_result));
790*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
791*00b67f09SDavid van Moolenbroek 			goto cleanup;
792*00b67f09SDavid van Moolenbroek 			break;
793*00b67f09SDavid van Moolenbroek 		} /* close switch(ldap_result) */
794*00b67f09SDavid van Moolenbroek 	} /* end for (int i = 0 i < 3; i++) */
795*00b67f09SDavid van Moolenbroek 
796*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
797*00b67f09SDavid van Moolenbroek 		goto cleanup;
798*00b67f09SDavid van Moolenbroek 
799*00b67f09SDavid van Moolenbroek 	switch(query) {
800*00b67f09SDavid van Moolenbroek 	case ALLNODES:
801*00b67f09SDavid van Moolenbroek 		result = ldap_process_results((LDAP *) dbi->dbconn, ldap_msg,
802*00b67f09SDavid van Moolenbroek 					      ldap_url->lud_attrs,
803*00b67f09SDavid van Moolenbroek 					      ptr, isc_boolean_true);
804*00b67f09SDavid van Moolenbroek 		break;
805*00b67f09SDavid van Moolenbroek 	case AUTHORITY:
806*00b67f09SDavid van Moolenbroek 	case LOOKUP:
807*00b67f09SDavid van Moolenbroek 		result = ldap_process_results((LDAP *) dbi->dbconn, ldap_msg,
808*00b67f09SDavid van Moolenbroek 					      ldap_url->lud_attrs,
809*00b67f09SDavid van Moolenbroek 					      ptr, isc_boolean_false);
810*00b67f09SDavid van Moolenbroek 		break;
811*00b67f09SDavid van Moolenbroek 	case ALLOWXFR:
812*00b67f09SDavid van Moolenbroek 		entries = ldap_count_entries((LDAP *) dbi->dbconn, ldap_msg);
813*00b67f09SDavid van Moolenbroek 		if (entries == 0)
814*00b67f09SDavid van Moolenbroek 			result = ISC_R_NOPERM;
815*00b67f09SDavid van Moolenbroek 		else if (entries > 0)
816*00b67f09SDavid van Moolenbroek 			result = ISC_R_SUCCESS;
817*00b67f09SDavid van Moolenbroek 		else
818*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
819*00b67f09SDavid van Moolenbroek 		break;
820*00b67f09SDavid van Moolenbroek 	case FINDZONE:
821*00b67f09SDavid van Moolenbroek 		entries = ldap_count_entries((LDAP *) dbi->dbconn, ldap_msg);
822*00b67f09SDavid van Moolenbroek 		if (entries == 0)
823*00b67f09SDavid van Moolenbroek 			result = ISC_R_NOTFOUND;
824*00b67f09SDavid van Moolenbroek 		else if (entries > 0)
825*00b67f09SDavid van Moolenbroek 			result = ISC_R_SUCCESS;
826*00b67f09SDavid van Moolenbroek 		else
827*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
828*00b67f09SDavid van Moolenbroek 		break;
829*00b67f09SDavid van Moolenbroek 	default:
830*00b67f09SDavid van Moolenbroek 		/*
831*00b67f09SDavid van Moolenbroek 		 * this should never happen.  If it does, the code is
832*00b67f09SDavid van Moolenbroek 		 * screwed up!
833*00b67f09SDavid van Moolenbroek 		 */
834*00b67f09SDavid van Moolenbroek 		UNEXPECTED_ERROR(__FILE__, __LINE__,
835*00b67f09SDavid van Moolenbroek 				 "Incorrect query flag passed to "
836*00b67f09SDavid van Moolenbroek 				 "ldap_get_results");
837*00b67f09SDavid van Moolenbroek 		result = ISC_R_UNEXPECTED;
838*00b67f09SDavid van Moolenbroek 	}
839*00b67f09SDavid van Moolenbroek 
840*00b67f09SDavid van Moolenbroek  cleanup:
841*00b67f09SDavid van Moolenbroek 	/* it's always good to cleanup after yourself */
842*00b67f09SDavid van Moolenbroek 
843*00b67f09SDavid van Moolenbroek         /* if we retrieved results, free them */
844*00b67f09SDavid van Moolenbroek 	if (ldap_msg != NULL)
845*00b67f09SDavid van Moolenbroek 		ldap_msgfree(ldap_msg);
846*00b67f09SDavid van Moolenbroek 
847*00b67f09SDavid van Moolenbroek 	if (ldap_url != NULL)
848*00b67f09SDavid van Moolenbroek 		ldap_free_urldesc(ldap_url);
849*00b67f09SDavid van Moolenbroek 
850*00b67f09SDavid van Moolenbroek 	/* cleanup */
851*00b67f09SDavid van Moolenbroek 	if (dbi->zone != NULL)
852*00b67f09SDavid van Moolenbroek 		isc_mem_free(ns_g_mctx, dbi->zone);
853*00b67f09SDavid van Moolenbroek 	if (dbi->record != NULL)
854*00b67f09SDavid van Moolenbroek 		isc_mem_free(ns_g_mctx, dbi->record);
855*00b67f09SDavid van Moolenbroek 	if (dbi->client != NULL)
856*00b67f09SDavid van Moolenbroek 		isc_mem_free(ns_g_mctx, dbi->client);
857*00b67f09SDavid van Moolenbroek 
858*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
859*00b67f09SDavid van Moolenbroek 
860*00b67f09SDavid van Moolenbroek 	/* release the lock so another thread can use this dbi */
861*00b67f09SDavid van Moolenbroek 	isc_mutex_unlock(&dbi->instance_lock);
862*00b67f09SDavid van Moolenbroek 
863*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
864*00b67f09SDavid van Moolenbroek 
865*00b67f09SDavid van Moolenbroek         /* release query string */
866*00b67f09SDavid van Moolenbroek 	if (querystring  != NULL)
867*00b67f09SDavid van Moolenbroek 		isc_mem_free(ns_g_mctx, querystring );
868*00b67f09SDavid van Moolenbroek 
869*00b67f09SDavid van Moolenbroek 	/* return result */
870*00b67f09SDavid van Moolenbroek 	return (result);
871*00b67f09SDavid van Moolenbroek }
872*00b67f09SDavid van Moolenbroek 
873*00b67f09SDavid van Moolenbroek /*
874*00b67f09SDavid van Moolenbroek  * DLZ methods
875*00b67f09SDavid van Moolenbroek  */
876*00b67f09SDavid van Moolenbroek static isc_result_t
dlz_ldap_allowzonexfr(void * driverarg,void * dbdata,const char * name,const char * client)877*00b67f09SDavid van Moolenbroek dlz_ldap_allowzonexfr(void *driverarg, void *dbdata, const char *name,
878*00b67f09SDavid van Moolenbroek 		      const char *client)
879*00b67f09SDavid van Moolenbroek {
880*00b67f09SDavid van Moolenbroek 	isc_result_t result;
881*00b67f09SDavid van Moolenbroek 
882*00b67f09SDavid van Moolenbroek 	UNUSED(driverarg);
883*00b67f09SDavid van Moolenbroek 
884*00b67f09SDavid van Moolenbroek 	/* check to see if we are authoritative for the zone first */
885*00b67f09SDavid van Moolenbroek 	result = dlz_ldap_findzone(driverarg, dbdata, name, NULL, NULL);
886*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
887*00b67f09SDavid van Moolenbroek 		return (result);
888*00b67f09SDavid van Moolenbroek 	}
889*00b67f09SDavid van Moolenbroek 
890*00b67f09SDavid van Moolenbroek         /* get all the zone data */
891*00b67f09SDavid van Moolenbroek 	result = ldap_get_results(name, NULL, client, ALLOWXFR, dbdata, NULL);
892*00b67f09SDavid van Moolenbroek 	return (result);
893*00b67f09SDavid van Moolenbroek }
894*00b67f09SDavid van Moolenbroek 
895*00b67f09SDavid van Moolenbroek static isc_result_t
dlz_ldap_allnodes(const char * zone,void * driverarg,void * dbdata,dns_sdlzallnodes_t * allnodes)896*00b67f09SDavid van Moolenbroek dlz_ldap_allnodes(const char *zone, void *driverarg, void *dbdata,
897*00b67f09SDavid van Moolenbroek 		  dns_sdlzallnodes_t *allnodes)
898*00b67f09SDavid van Moolenbroek {
899*00b67f09SDavid van Moolenbroek 	UNUSED(driverarg);
900*00b67f09SDavid van Moolenbroek 	return (ldap_get_results(zone, NULL, NULL, ALLNODES, dbdata, allnodes));
901*00b67f09SDavid van Moolenbroek }
902*00b67f09SDavid van Moolenbroek 
903*00b67f09SDavid van Moolenbroek static isc_result_t
dlz_ldap_authority(const char * zone,void * driverarg,void * dbdata,dns_sdlzlookup_t * lookup)904*00b67f09SDavid van Moolenbroek dlz_ldap_authority(const char *zone, void *driverarg, void *dbdata,
905*00b67f09SDavid van Moolenbroek 		   dns_sdlzlookup_t *lookup)
906*00b67f09SDavid van Moolenbroek {
907*00b67f09SDavid van Moolenbroek 	UNUSED(driverarg);
908*00b67f09SDavid van Moolenbroek 	return (ldap_get_results(zone, NULL, NULL, AUTHORITY, dbdata, lookup));
909*00b67f09SDavid van Moolenbroek }
910*00b67f09SDavid van Moolenbroek 
911*00b67f09SDavid van Moolenbroek static isc_result_t
dlz_ldap_findzone(void * driverarg,void * dbdata,const char * name,dns_clientinfomethods_t * methods,dns_clientinfo_t * clientinfo)912*00b67f09SDavid van Moolenbroek dlz_ldap_findzone(void *driverarg, void *dbdata, const char *name,
913*00b67f09SDavid van Moolenbroek 		  dns_clientinfomethods_t *methods,
914*00b67f09SDavid van Moolenbroek 		  dns_clientinfo_t *clientinfo)
915*00b67f09SDavid van Moolenbroek {
916*00b67f09SDavid van Moolenbroek 	UNUSED(driverarg);
917*00b67f09SDavid van Moolenbroek 	UNUSED(methods);
918*00b67f09SDavid van Moolenbroek 	UNUSED(clientinfo);
919*00b67f09SDavid van Moolenbroek 	return (ldap_get_results(name, NULL, NULL, FINDZONE, dbdata, NULL));
920*00b67f09SDavid van Moolenbroek }
921*00b67f09SDavid van Moolenbroek 
922*00b67f09SDavid van Moolenbroek static isc_result_t
dlz_ldap_lookup(const char * zone,const char * name,void * driverarg,void * dbdata,dns_sdlzlookup_t * lookup,dns_clientinfomethods_t * methods,dns_clientinfo_t * clientinfo)923*00b67f09SDavid van Moolenbroek dlz_ldap_lookup(const char *zone, const char *name, void *driverarg,
924*00b67f09SDavid van Moolenbroek 		void *dbdata, dns_sdlzlookup_t *lookup,
925*00b67f09SDavid van Moolenbroek 		dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo)
926*00b67f09SDavid van Moolenbroek {
927*00b67f09SDavid van Moolenbroek 	isc_result_t result;
928*00b67f09SDavid van Moolenbroek 
929*00b67f09SDavid van Moolenbroek 	UNUSED(driverarg);
930*00b67f09SDavid van Moolenbroek 	UNUSED(methods);
931*00b67f09SDavid van Moolenbroek 	UNUSED(clientinfo);
932*00b67f09SDavid van Moolenbroek 
933*00b67f09SDavid van Moolenbroek 	if (strcmp(name, "*") == 0)
934*00b67f09SDavid van Moolenbroek 		result = ldap_get_results(zone, "~", NULL, LOOKUP,
935*00b67f09SDavid van Moolenbroek 					  dbdata, lookup);
936*00b67f09SDavid van Moolenbroek 	else
937*00b67f09SDavid van Moolenbroek 		result = ldap_get_results(zone, name, NULL, LOOKUP,
938*00b67f09SDavid van Moolenbroek 					  dbdata, lookup);
939*00b67f09SDavid van Moolenbroek 	return (result);
940*00b67f09SDavid van Moolenbroek }
941*00b67f09SDavid van Moolenbroek 
942*00b67f09SDavid van Moolenbroek 
943*00b67f09SDavid van Moolenbroek static isc_result_t
dlz_ldap_create(const char * dlzname,unsigned int argc,char * argv[],void * driverarg,void ** dbdata)944*00b67f09SDavid van Moolenbroek dlz_ldap_create(const char *dlzname, unsigned int argc, char *argv[],
945*00b67f09SDavid van Moolenbroek 		void *driverarg, void **dbdata)
946*00b67f09SDavid van Moolenbroek {
947*00b67f09SDavid van Moolenbroek 	isc_result_t result;
948*00b67f09SDavid van Moolenbroek 	ldap_instance_t *ldap_inst = NULL;
949*00b67f09SDavid van Moolenbroek 	dbinstance_t *dbi = NULL;
950*00b67f09SDavid van Moolenbroek 	int protocol;
951*00b67f09SDavid van Moolenbroek 	int method;
952*00b67f09SDavid van Moolenbroek 
953*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
954*00b67f09SDavid van Moolenbroek 	/* if multi-threaded, we need a few extra variables. */
955*00b67f09SDavid van Moolenbroek 	int dbcount;
956*00b67f09SDavid van Moolenbroek 	char *endp;
957*00b67f09SDavid van Moolenbroek /* db_list_t *dblist = NULL; */
958*00b67f09SDavid van Moolenbroek 	int i;
959*00b67f09SDavid van Moolenbroek 
960*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
961*00b67f09SDavid van Moolenbroek 
962*00b67f09SDavid van Moolenbroek 	UNUSED(dlzname);
963*00b67f09SDavid van Moolenbroek 	UNUSED(driverarg);
964*00b67f09SDavid van Moolenbroek 
965*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
966*00b67f09SDavid van Moolenbroek 	/* if debugging, let user know we are multithreaded. */
967*00b67f09SDavid van Moolenbroek 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
968*00b67f09SDavid van Moolenbroek 		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
969*00b67f09SDavid van Moolenbroek 		      "LDAP driver running multithreaded");
970*00b67f09SDavid van Moolenbroek #else /* ISC_PLATFORM_USETHREADS */
971*00b67f09SDavid van Moolenbroek 	/* if debugging, let user know we are single threaded. */
972*00b67f09SDavid van Moolenbroek 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
973*00b67f09SDavid van Moolenbroek 		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
974*00b67f09SDavid van Moolenbroek 		      "LDAP driver running single threaded");
975*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
976*00b67f09SDavid van Moolenbroek 
977*00b67f09SDavid van Moolenbroek 	if (argc < 9) {
978*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
979*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
980*00b67f09SDavid van Moolenbroek 			      "LDAP driver requires at least "
981*00b67f09SDavid van Moolenbroek 			      "8 command line args.");
982*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
983*00b67f09SDavid van Moolenbroek 	}
984*00b67f09SDavid van Moolenbroek 
985*00b67f09SDavid van Moolenbroek 	/* no more than 13 arg's should be passed to the driver */
986*00b67f09SDavid van Moolenbroek 	if (argc > 12) {
987*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
988*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
989*00b67f09SDavid van Moolenbroek 			      "LDAP driver cannot accept more than "
990*00b67f09SDavid van Moolenbroek 			      "11 command line args.");
991*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
992*00b67f09SDavid van Moolenbroek 	}
993*00b67f09SDavid van Moolenbroek 
994*00b67f09SDavid van Moolenbroek 	/* determine protocol version. */
995*00b67f09SDavid van Moolenbroek 	if (strncasecmp(argv[2], V2, strlen(V2)) == 0) {
996*00b67f09SDavid van Moolenbroek 		protocol = 2;
997*00b67f09SDavid van Moolenbroek 	} else if (strncasecmp(argv[2], V3, strlen(V3)) == 0) {
998*00b67f09SDavid van Moolenbroek 		protocol = 3;
999*00b67f09SDavid van Moolenbroek 	} else {
1000*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1001*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
1002*00b67f09SDavid van Moolenbroek 			      "LDAP driver protocol must be either %s or %s",
1003*00b67f09SDavid van Moolenbroek 			      V2, V3);
1004*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
1005*00b67f09SDavid van Moolenbroek 	}
1006*00b67f09SDavid van Moolenbroek 
1007*00b67f09SDavid van Moolenbroek 	/* determine connection method. */
1008*00b67f09SDavid van Moolenbroek 	if (strncasecmp(argv[3], SIMPLE, strlen(SIMPLE)) == 0) {
1009*00b67f09SDavid van Moolenbroek 		method = LDAP_AUTH_SIMPLE;
1010*00b67f09SDavid van Moolenbroek 	} else if (strncasecmp(argv[3], KRB41, strlen(KRB41)) == 0) {
1011*00b67f09SDavid van Moolenbroek 		method = LDAP_AUTH_KRBV41;
1012*00b67f09SDavid van Moolenbroek 	} else if (strncasecmp(argv[3], KRB42, strlen(KRB42)) == 0) {
1013*00b67f09SDavid van Moolenbroek 		method = LDAP_AUTH_KRBV42;
1014*00b67f09SDavid van Moolenbroek 	} else {
1015*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1016*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
1017*00b67f09SDavid van Moolenbroek 			      "LDAP driver authentication method must be "
1018*00b67f09SDavid van Moolenbroek 			      "one of %s, %s or %s",
1019*00b67f09SDavid van Moolenbroek 			      SIMPLE, KRB41, KRB42);
1020*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
1021*00b67f09SDavid van Moolenbroek 	}
1022*00b67f09SDavid van Moolenbroek 
1023*00b67f09SDavid van Moolenbroek 	/* multithreaded build can have multiple DB connections */
1024*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
1025*00b67f09SDavid van Moolenbroek 
1026*00b67f09SDavid van Moolenbroek 	/* check how many db connections we should create */
1027*00b67f09SDavid van Moolenbroek 	dbcount = strtol(argv[1], &endp, 10);
1028*00b67f09SDavid van Moolenbroek 	if (*endp != '\0' || dbcount < 0) {
1029*00b67f09SDavid van Moolenbroek 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1030*00b67f09SDavid van Moolenbroek 			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
1031*00b67f09SDavid van Moolenbroek 			      "LDAP driver database connection count "
1032*00b67f09SDavid van Moolenbroek 			      "must be positive.");
1033*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
1034*00b67f09SDavid van Moolenbroek 	}
1035*00b67f09SDavid van Moolenbroek #endif
1036*00b67f09SDavid van Moolenbroek 
1037*00b67f09SDavid van Moolenbroek 	/* check that LDAP URL parameters make sense */
1038*00b67f09SDavid van Moolenbroek 	switch(argc) {
1039*00b67f09SDavid van Moolenbroek 	case 12:
1040*00b67f09SDavid van Moolenbroek 		result = dlz_ldap_checkURL(argv[11], 0, "allow zone transfer");
1041*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
1042*00b67f09SDavid van Moolenbroek 			return (result);
1043*00b67f09SDavid van Moolenbroek 	case 11:
1044*00b67f09SDavid van Moolenbroek 		result = dlz_ldap_checkURL(argv[10], 3, "all nodes");
1045*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
1046*00b67f09SDavid van Moolenbroek 			return (result);
1047*00b67f09SDavid van Moolenbroek 	case 10:
1048*00b67f09SDavid van Moolenbroek 		if (strlen(argv[9]) > 0) {
1049*00b67f09SDavid van Moolenbroek 			result = dlz_ldap_checkURL(argv[9], 3, "authority");
1050*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS)
1051*00b67f09SDavid van Moolenbroek 				return (result);
1052*00b67f09SDavid van Moolenbroek 		}
1053*00b67f09SDavid van Moolenbroek 	case 9:
1054*00b67f09SDavid van Moolenbroek 		result = dlz_ldap_checkURL(argv[8], 3, "lookup");
1055*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
1056*00b67f09SDavid van Moolenbroek 			return (result);
1057*00b67f09SDavid van Moolenbroek 		result = dlz_ldap_checkURL(argv[7], 0, "find zone");
1058*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
1059*00b67f09SDavid van Moolenbroek 			return (result);
1060*00b67f09SDavid van Moolenbroek 		break;
1061*00b67f09SDavid van Moolenbroek 	default:
1062*00b67f09SDavid van Moolenbroek 		/* not really needed, should shut up compiler. */
1063*00b67f09SDavid van Moolenbroek 		result = ISC_R_FAILURE;
1064*00b67f09SDavid van Moolenbroek 	}
1065*00b67f09SDavid van Moolenbroek 
1066*00b67f09SDavid van Moolenbroek 	/* allocate memory for LDAP instance */
1067*00b67f09SDavid van Moolenbroek 	ldap_inst = isc_mem_get(ns_g_mctx, sizeof(ldap_instance_t));
1068*00b67f09SDavid van Moolenbroek 	if (ldap_inst == NULL)
1069*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
1070*00b67f09SDavid van Moolenbroek 	memset(ldap_inst, 0, sizeof(ldap_instance_t));
1071*00b67f09SDavid van Moolenbroek 
1072*00b67f09SDavid van Moolenbroek 	/* store info needed to automatically re-connect. */
1073*00b67f09SDavid van Moolenbroek 	ldap_inst->protocol = protocol;
1074*00b67f09SDavid van Moolenbroek 	ldap_inst->method = method;
1075*00b67f09SDavid van Moolenbroek 	ldap_inst->hosts = isc_mem_strdup(ns_g_mctx, argv[6]);
1076*00b67f09SDavid van Moolenbroek 	if (ldap_inst->hosts == NULL) {
1077*00b67f09SDavid van Moolenbroek 		result = ISC_R_NOMEMORY;
1078*00b67f09SDavid van Moolenbroek 		goto cleanup;
1079*00b67f09SDavid van Moolenbroek 	}
1080*00b67f09SDavid van Moolenbroek 	ldap_inst->user = isc_mem_strdup(ns_g_mctx, argv[4]);
1081*00b67f09SDavid van Moolenbroek 	if (ldap_inst->user == NULL) {
1082*00b67f09SDavid van Moolenbroek 		result = ISC_R_NOMEMORY;
1083*00b67f09SDavid van Moolenbroek 		goto cleanup;
1084*00b67f09SDavid van Moolenbroek 	}
1085*00b67f09SDavid van Moolenbroek 	ldap_inst->cred = isc_mem_strdup(ns_g_mctx, argv[5]);
1086*00b67f09SDavid van Moolenbroek 	if (ldap_inst->cred == NULL) {
1087*00b67f09SDavid van Moolenbroek 		result = ISC_R_NOMEMORY;
1088*00b67f09SDavid van Moolenbroek 		goto cleanup;
1089*00b67f09SDavid van Moolenbroek 	}
1090*00b67f09SDavid van Moolenbroek 
1091*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
1092*00b67f09SDavid van Moolenbroek 	/* allocate memory for database connection list */
1093*00b67f09SDavid van Moolenbroek 	ldap_inst->db = isc_mem_get(ns_g_mctx, sizeof(db_list_t));
1094*00b67f09SDavid van Moolenbroek 	if (ldap_inst->db == NULL) {
1095*00b67f09SDavid van Moolenbroek 		result = ISC_R_NOMEMORY;
1096*00b67f09SDavid van Moolenbroek 		goto cleanup;
1097*00b67f09SDavid van Moolenbroek 	}
1098*00b67f09SDavid van Moolenbroek 
1099*00b67f09SDavid van Moolenbroek 	/* initialize DB connection list */
1100*00b67f09SDavid van Moolenbroek 	ISC_LIST_INIT(*(ldap_inst->db));
1101*00b67f09SDavid van Moolenbroek 
1102*00b67f09SDavid van Moolenbroek 	/*
1103*00b67f09SDavid van Moolenbroek 	 * create the appropriate number of database instances (DBI)
1104*00b67f09SDavid van Moolenbroek 	 * append each new DBI to the end of the list
1105*00b67f09SDavid van Moolenbroek 	 */
1106*00b67f09SDavid van Moolenbroek 	for (i = 0; i < dbcount; i++) {
1107*00b67f09SDavid van Moolenbroek 
1108*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
1109*00b67f09SDavid van Moolenbroek 
1110*00b67f09SDavid van Moolenbroek 		/* how many queries were passed in from config file? */
1111*00b67f09SDavid van Moolenbroek 		switch(argc) {
1112*00b67f09SDavid van Moolenbroek 		case 9:
1113*00b67f09SDavid van Moolenbroek 			result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
1114*00b67f09SDavid van Moolenbroek 						     NULL, argv[7], argv[8],
1115*00b67f09SDavid van Moolenbroek 						     NULL, &dbi);
1116*00b67f09SDavid van Moolenbroek 			break;
1117*00b67f09SDavid van Moolenbroek 		case 10:
1118*00b67f09SDavid van Moolenbroek 			result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
1119*00b67f09SDavid van Moolenbroek 						     argv[9], argv[7], argv[8],
1120*00b67f09SDavid van Moolenbroek 						     NULL, &dbi);
1121*00b67f09SDavid van Moolenbroek 			break;
1122*00b67f09SDavid van Moolenbroek 		case 11:
1123*00b67f09SDavid van Moolenbroek 			result = build_sqldbinstance(ns_g_mctx, argv[10], NULL,
1124*00b67f09SDavid van Moolenbroek 						     argv[9], argv[7], argv[8],
1125*00b67f09SDavid van Moolenbroek 						     NULL, &dbi);
1126*00b67f09SDavid van Moolenbroek 			break;
1127*00b67f09SDavid van Moolenbroek 		case 12:
1128*00b67f09SDavid van Moolenbroek 			result = build_sqldbinstance(ns_g_mctx, argv[10],
1129*00b67f09SDavid van Moolenbroek 						     argv[11], argv[9],
1130*00b67f09SDavid van Moolenbroek 						     argv[7], argv[8],
1131*00b67f09SDavid van Moolenbroek 						     NULL, &dbi);
1132*00b67f09SDavid van Moolenbroek 			break;
1133*00b67f09SDavid van Moolenbroek 		default:
1134*00b67f09SDavid van Moolenbroek 			/* not really needed, should shut up compiler. */
1135*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
1136*00b67f09SDavid van Moolenbroek 		}
1137*00b67f09SDavid van Moolenbroek 
1138*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_SUCCESS) {
1139*00b67f09SDavid van Moolenbroek 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1140*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1141*00b67f09SDavid van Moolenbroek 				      "LDAP driver created "
1142*00b67f09SDavid van Moolenbroek 				      "database instance object.");
1143*00b67f09SDavid van Moolenbroek 		} else { /* unsuccessful?, log err msg and cleanup. */
1144*00b67f09SDavid van Moolenbroek 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1145*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
1146*00b67f09SDavid van Moolenbroek 				      "LDAP driver could not create "
1147*00b67f09SDavid van Moolenbroek 				      "database instance object.");
1148*00b67f09SDavid van Moolenbroek 			goto cleanup;
1149*00b67f09SDavid van Moolenbroek 		}
1150*00b67f09SDavid van Moolenbroek 
1151*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
1152*00b67f09SDavid van Moolenbroek 		/* when multithreaded, build a list of DBI's */
1153*00b67f09SDavid van Moolenbroek 		ISC_LINK_INIT(dbi, link);
1154*00b67f09SDavid van Moolenbroek 		ISC_LIST_APPEND(*(ldap_inst->db), dbi, link);
1155*00b67f09SDavid van Moolenbroek #else
1156*00b67f09SDavid van Moolenbroek 		/*
1157*00b67f09SDavid van Moolenbroek 		 * when single threaded, hold onto the one connection
1158*00b67f09SDavid van Moolenbroek 		 * instance.
1159*00b67f09SDavid van Moolenbroek 		 */
1160*00b67f09SDavid van Moolenbroek 		ldap_inst->db = dbi;
1161*00b67f09SDavid van Moolenbroek 
1162*00b67f09SDavid van Moolenbroek #endif
1163*00b67f09SDavid van Moolenbroek 		/* attempt to connect */
1164*00b67f09SDavid van Moolenbroek 		result = dlz_ldap_connect(ldap_inst, dbi);
1165*00b67f09SDavid van Moolenbroek 
1166*00b67f09SDavid van Moolenbroek 		/*
1167*00b67f09SDavid van Moolenbroek 		 * if db connection cannot be created, log err msg and
1168*00b67f09SDavid van Moolenbroek 		 * cleanup.
1169*00b67f09SDavid van Moolenbroek 		 */
1170*00b67f09SDavid van Moolenbroek 		switch(result) {
1171*00b67f09SDavid van Moolenbroek 			/* success, do nothing */
1172*00b67f09SDavid van Moolenbroek 		case ISC_R_SUCCESS:
1173*00b67f09SDavid van Moolenbroek 			break;
1174*00b67f09SDavid van Moolenbroek 			/*
1175*00b67f09SDavid van Moolenbroek 			 * no memory means ldap_init could not
1176*00b67f09SDavid van Moolenbroek 			 * allocate memory
1177*00b67f09SDavid van Moolenbroek 			 */
1178*00b67f09SDavid van Moolenbroek 		case ISC_R_NOMEMORY:
1179*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
1180*00b67f09SDavid van Moolenbroek 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1181*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
1182*00b67f09SDavid van Moolenbroek 				      "LDAP driver could not allocate memory "
1183*00b67f09SDavid van Moolenbroek 				      "for connection number %u",
1184*00b67f09SDavid van Moolenbroek 				      i+1);
1185*00b67f09SDavid van Moolenbroek #else
1186*00b67f09SDavid van Moolenbroek 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1187*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
1188*00b67f09SDavid van Moolenbroek 				      "LDAP driver could not allocate memory "
1189*00b67f09SDavid van Moolenbroek 				      "for connection");
1190*00b67f09SDavid van Moolenbroek #endif
1191*00b67f09SDavid van Moolenbroek 			goto cleanup;
1192*00b67f09SDavid van Moolenbroek 			break;
1193*00b67f09SDavid van Moolenbroek 			/*
1194*00b67f09SDavid van Moolenbroek 			 * no perm means ldap_set_option could not set
1195*00b67f09SDavid van Moolenbroek 			 * protocol version
1196*00b67f09SDavid van Moolenbroek 			 */
1197*00b67f09SDavid van Moolenbroek 		case ISC_R_NOPERM:
1198*00b67f09SDavid van Moolenbroek 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1199*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
1200*00b67f09SDavid van Moolenbroek 				      "LDAP driver could not "
1201*00b67f09SDavid van Moolenbroek 				      "set protocol version.");
1202*00b67f09SDavid van Moolenbroek 			result = ISC_R_FAILURE;
1203*00b67f09SDavid van Moolenbroek 			goto cleanup;
1204*00b67f09SDavid van Moolenbroek 			break;
1205*00b67f09SDavid van Moolenbroek 			/* failure means couldn't connect to ldap server */
1206*00b67f09SDavid van Moolenbroek 		case ISC_R_FAILURE:
1207*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
1208*00b67f09SDavid van Moolenbroek 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1209*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
1210*00b67f09SDavid van Moolenbroek 				      "LDAP driver could not "
1211*00b67f09SDavid van Moolenbroek 				      "bind connection number %u to server.",
1212*00b67f09SDavid van Moolenbroek 				      i+1);
1213*00b67f09SDavid van Moolenbroek #else
1214*00b67f09SDavid van Moolenbroek 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1215*00b67f09SDavid van Moolenbroek 				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
1216*00b67f09SDavid van Moolenbroek 				      "LDAP driver could not "
1217*00b67f09SDavid van Moolenbroek 				      "bind connection to server.");
1218*00b67f09SDavid van Moolenbroek #endif
1219*00b67f09SDavid van Moolenbroek 			goto cleanup;
1220*00b67f09SDavid van Moolenbroek 			break;
1221*00b67f09SDavid van Moolenbroek 			/*
1222*00b67f09SDavid van Moolenbroek 			 * default should never happen.  If it does,
1223*00b67f09SDavid van Moolenbroek 			 * major errors.
1224*00b67f09SDavid van Moolenbroek 			 */
1225*00b67f09SDavid van Moolenbroek 		default:
1226*00b67f09SDavid van Moolenbroek 			UNEXPECTED_ERROR(__FILE__, __LINE__,
1227*00b67f09SDavid van Moolenbroek 					 "dlz_ldap_create() failed: %s",
1228*00b67f09SDavid van Moolenbroek 					 isc_result_totext(result));
1229*00b67f09SDavid van Moolenbroek 			result = ISC_R_UNEXPECTED;
1230*00b67f09SDavid van Moolenbroek 			goto cleanup;
1231*00b67f09SDavid van Moolenbroek 			break;
1232*00b67f09SDavid van Moolenbroek 		} /* end switch(result) */
1233*00b67f09SDavid van Moolenbroek 
1234*00b67f09SDavid van Moolenbroek 
1235*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
1236*00b67f09SDavid van Moolenbroek 
1237*00b67f09SDavid van Moolenbroek 		/* set DBI = null for next loop through. */
1238*00b67f09SDavid van Moolenbroek 		dbi = NULL;
1239*00b67f09SDavid van Moolenbroek 	}	/* end for loop */
1240*00b67f09SDavid van Moolenbroek 
1241*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
1242*00b67f09SDavid van Moolenbroek 
1243*00b67f09SDavid van Moolenbroek 
1244*00b67f09SDavid van Moolenbroek 	/* set dbdata to the ldap_instance we created. */
1245*00b67f09SDavid van Moolenbroek 	*dbdata = ldap_inst;
1246*00b67f09SDavid van Moolenbroek 
1247*00b67f09SDavid van Moolenbroek 	/* hey, we got through all of that ok, return success. */
1248*00b67f09SDavid van Moolenbroek 	return(ISC_R_SUCCESS);
1249*00b67f09SDavid van Moolenbroek 
1250*00b67f09SDavid van Moolenbroek  cleanup:
1251*00b67f09SDavid van Moolenbroek 	dlz_ldap_destroy(NULL, ldap_inst);
1252*00b67f09SDavid van Moolenbroek 
1253*00b67f09SDavid van Moolenbroek 	return(ISC_R_FAILURE);
1254*00b67f09SDavid van Moolenbroek }
1255*00b67f09SDavid van Moolenbroek 
1256*00b67f09SDavid van Moolenbroek void
dlz_ldap_destroy(void * driverarg,void * dbdata)1257*00b67f09SDavid van Moolenbroek dlz_ldap_destroy(void *driverarg, void *dbdata) {
1258*00b67f09SDavid van Moolenbroek 	UNUSED(driverarg);
1259*00b67f09SDavid van Moolenbroek 
1260*00b67f09SDavid van Moolenbroek 	if (dbdata != NULL) {
1261*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
1262*00b67f09SDavid van Moolenbroek 		/* cleanup the list of DBI's */
1263*00b67f09SDavid van Moolenbroek 		ldap_destroy_dblist((db_list_t *)
1264*00b67f09SDavid van Moolenbroek 				    ((ldap_instance_t *)dbdata)->db);
1265*00b67f09SDavid van Moolenbroek 
1266*00b67f09SDavid van Moolenbroek #else /* ISC_PLATFORM_USETHREADS */
1267*00b67f09SDavid van Moolenbroek 		if (((ldap_instance_t *)dbdata)->db->dbconn != NULL)
1268*00b67f09SDavid van Moolenbroek 			ldap_unbind_s((LDAP *)
1269*00b67f09SDavid van Moolenbroek 				      ((ldap_instance_t *)dbdata)->db->dbconn);
1270*00b67f09SDavid van Moolenbroek 
1271*00b67f09SDavid van Moolenbroek 		/* destroy single DB instance */
1272*00b67f09SDavid van Moolenbroek 		destroy_sqldbinstance(((ldap_instance_t *)dbdata)->db);
1273*00b67f09SDavid van Moolenbroek #endif /* ISC_PLATFORM_USETHREADS */
1274*00b67f09SDavid van Moolenbroek 
1275*00b67f09SDavid van Moolenbroek 		if (((ldap_instance_t *)dbdata)->hosts != NULL)
1276*00b67f09SDavid van Moolenbroek 			isc_mem_free(ns_g_mctx,
1277*00b67f09SDavid van Moolenbroek 				     ((ldap_instance_t *)dbdata)->hosts);
1278*00b67f09SDavid van Moolenbroek 
1279*00b67f09SDavid van Moolenbroek 		if (((ldap_instance_t *)dbdata)->user != NULL)
1280*00b67f09SDavid van Moolenbroek 			isc_mem_free(ns_g_mctx,
1281*00b67f09SDavid van Moolenbroek 				     ((ldap_instance_t *)dbdata)->user);
1282*00b67f09SDavid van Moolenbroek 
1283*00b67f09SDavid van Moolenbroek 		if (((ldap_instance_t *)dbdata)->cred != NULL)
1284*00b67f09SDavid van Moolenbroek 			isc_mem_free(ns_g_mctx,
1285*00b67f09SDavid van Moolenbroek 				     ((ldap_instance_t *)dbdata)->cred);
1286*00b67f09SDavid van Moolenbroek 
1287*00b67f09SDavid van Moolenbroek 		isc_mem_put(ns_g_mctx, dbdata, sizeof(ldap_instance_t));
1288*00b67f09SDavid van Moolenbroek 	}
1289*00b67f09SDavid van Moolenbroek }
1290*00b67f09SDavid van Moolenbroek 
1291*00b67f09SDavid van Moolenbroek static dns_sdlzmethods_t dlz_ldap_methods = {
1292*00b67f09SDavid van Moolenbroek 	dlz_ldap_create,
1293*00b67f09SDavid van Moolenbroek 	dlz_ldap_destroy,
1294*00b67f09SDavid van Moolenbroek 	dlz_ldap_findzone,
1295*00b67f09SDavid van Moolenbroek 	dlz_ldap_lookup,
1296*00b67f09SDavid van Moolenbroek 	dlz_ldap_authority,
1297*00b67f09SDavid van Moolenbroek 	dlz_ldap_allnodes,
1298*00b67f09SDavid van Moolenbroek 	dlz_ldap_allowzonexfr,
1299*00b67f09SDavid van Moolenbroek 	NULL,
1300*00b67f09SDavid van Moolenbroek 	NULL,
1301*00b67f09SDavid van Moolenbroek 	NULL,
1302*00b67f09SDavid van Moolenbroek 	NULL,
1303*00b67f09SDavid van Moolenbroek 	NULL,
1304*00b67f09SDavid van Moolenbroek 	NULL,
1305*00b67f09SDavid van Moolenbroek 	NULL,
1306*00b67f09SDavid van Moolenbroek };
1307*00b67f09SDavid van Moolenbroek 
1308*00b67f09SDavid van Moolenbroek /*%
1309*00b67f09SDavid van Moolenbroek  * Wrapper around dns_sdlzregister().
1310*00b67f09SDavid van Moolenbroek  */
1311*00b67f09SDavid van Moolenbroek isc_result_t
dlz_ldap_init(void)1312*00b67f09SDavid van Moolenbroek dlz_ldap_init(void) {
1313*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1314*00b67f09SDavid van Moolenbroek 
1315*00b67f09SDavid van Moolenbroek 	/*
1316*00b67f09SDavid van Moolenbroek 	 * Write debugging message to log
1317*00b67f09SDavid van Moolenbroek 	 */
1318*00b67f09SDavid van Moolenbroek 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1319*00b67f09SDavid van Moolenbroek 		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1320*00b67f09SDavid van Moolenbroek 		      "Registering DLZ ldap driver.");
1321*00b67f09SDavid van Moolenbroek 
1322*00b67f09SDavid van Moolenbroek 	result = dns_sdlzregister("ldap", &dlz_ldap_methods, NULL,
1323*00b67f09SDavid van Moolenbroek 				  DNS_SDLZFLAG_RELATIVEOWNER |
1324*00b67f09SDavid van Moolenbroek 				  DNS_SDLZFLAG_RELATIVERDATA,
1325*00b67f09SDavid van Moolenbroek 				  ns_g_mctx, &dlz_ldap);
1326*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
1327*00b67f09SDavid van Moolenbroek 		UNEXPECTED_ERROR(__FILE__, __LINE__,
1328*00b67f09SDavid van Moolenbroek 				 "dns_sdlzregister() failed: %s",
1329*00b67f09SDavid van Moolenbroek 				 isc_result_totext(result));
1330*00b67f09SDavid van Moolenbroek 		result = ISC_R_UNEXPECTED;
1331*00b67f09SDavid van Moolenbroek 	}
1332*00b67f09SDavid van Moolenbroek 
1333*00b67f09SDavid van Moolenbroek 	return (result);
1334*00b67f09SDavid van Moolenbroek }
1335*00b67f09SDavid van Moolenbroek 
1336*00b67f09SDavid van Moolenbroek /*%
1337*00b67f09SDavid van Moolenbroek  * Wrapper around dns_sdlzunregister().
1338*00b67f09SDavid van Moolenbroek  */
1339*00b67f09SDavid van Moolenbroek void
dlz_ldap_clear(void)1340*00b67f09SDavid van Moolenbroek dlz_ldap_clear(void) {
1341*00b67f09SDavid van Moolenbroek 	/*
1342*00b67f09SDavid van Moolenbroek 	 * Write debugging message to log
1343*00b67f09SDavid van Moolenbroek 	 */
1344*00b67f09SDavid van Moolenbroek 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1345*00b67f09SDavid van Moolenbroek 		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1346*00b67f09SDavid van Moolenbroek 		      "Unregistering DLZ ldap driver.");
1347*00b67f09SDavid van Moolenbroek 
1348*00b67f09SDavid van Moolenbroek 	if (dlz_ldap != NULL)
1349*00b67f09SDavid van Moolenbroek 		dns_sdlzunregister(&dlz_ldap);
1350*00b67f09SDavid van Moolenbroek }
1351*00b67f09SDavid van Moolenbroek 
1352*00b67f09SDavid van Moolenbroek #endif
1353