xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/config.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /*	$NetBSD: config.c,v 1.1.1.4 2014/05/28 09:58:46 tron Exp $	*/
2 
3 /* config.c - configuration file handling routines */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 1998-2014 The OpenLDAP Foundation.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
19  * All rights reserved.
20  *
21  * Redistribution and use in source and binary forms are permitted
22  * provided that this notice is preserved and that due credit is given
23  * to the University of Michigan at Ann Arbor. The name of the University
24  * may not be used to endorse or promote products derived from this
25  * software without specific prior written permission. This software
26  * is provided ``as is'' without express or implied warranty.
27  */
28 
29 #include "portable.h"
30 
31 #include <stdio.h>
32 
33 #include <ac/string.h>
34 #include <ac/ctype.h>
35 #include <ac/signal.h>
36 #include <ac/socket.h>
37 #include <ac/errno.h>
38 #include <ac/unistd.h>
39 
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 
43 #ifndef S_ISREG
44 #define	S_ISREG(m)	(((m) & _S_IFMT) == _S_IFREG)
45 #endif
46 
47 #include "slap.h"
48 #ifdef LDAP_SLAPI
49 #include "slapi/slapi.h"
50 #endif
51 #include "lutil.h"
52 #include "lutil_ldap.h"
53 #include "config.h"
54 
55 #define ARGS_STEP	512
56 
57 /*
58  * defaults for various global variables
59  */
60 slap_mask_t		global_allows = 0;
61 slap_mask_t		global_disallows = 0;
62 int		global_gentlehup = 0;
63 int		global_idletimeout = 0;
64 int		global_writetimeout = 0;
65 char	*global_host = NULL;
66 struct berval global_host_bv = BER_BVNULL;
67 char	*global_realm = NULL;
68 char	*sasl_host = NULL;
69 char		**default_passwd_hash = NULL;
70 struct berval default_search_base = BER_BVNULL;
71 struct berval default_search_nbase = BER_BVNULL;
72 
73 ber_len_t sockbuf_max_incoming = SLAP_SB_MAX_INCOMING_DEFAULT;
74 ber_len_t sockbuf_max_incoming_auth= SLAP_SB_MAX_INCOMING_AUTH;
75 
76 int	slap_conn_max_pending = SLAP_CONN_MAX_PENDING_DEFAULT;
77 int	slap_conn_max_pending_auth = SLAP_CONN_MAX_PENDING_AUTH;
78 
79 char   *slapd_pid_file  = NULL;
80 char   *slapd_args_file = NULL;
81 
82 int use_reverse_lookup = 0;
83 
84 #ifdef LDAP_SLAPI
85 int slapi_plugins_used = 0;
86 #endif
87 
88 static int fp_getline(FILE *fp, ConfigArgs *c);
89 static void fp_getline_init(ConfigArgs *c);
90 
91 static char	*strtok_quote(char *line, char *sep, char **quote_ptr);
92 static char *strtok_quote_ldif(char **line);
93 
94 ConfigArgs *
95 new_config_args( BackendDB *be, const char *fname, int lineno, int argc, char **argv )
96 {
97 	ConfigArgs *c;
98 	c = ch_calloc( 1, sizeof( ConfigArgs ) );
99 	if ( c == NULL ) return(NULL);
100 	c->be     = be;
101 	c->fname  = fname;
102 	c->argc   = argc;
103 	c->argv   = argv;
104 	c->lineno = lineno;
105 	snprintf( c->log, sizeof( c->log ), "%s: line %d", fname, lineno );
106 	return(c);
107 }
108 
109 void
110 init_config_argv( ConfigArgs *c )
111 {
112 	c->argv = ch_calloc( ARGS_STEP + 1, sizeof( *c->argv ) );
113 	c->argv_size = ARGS_STEP + 1;
114 }
115 
116 ConfigTable *config_find_keyword(ConfigTable *Conf, ConfigArgs *c) {
117 	int i;
118 
119 	for(i = 0; Conf[i].name; i++)
120 		if( (Conf[i].length && (!strncasecmp(c->argv[0], Conf[i].name, Conf[i].length))) ||
121 			(!strcasecmp(c->argv[0], Conf[i].name)) ) break;
122 	if ( !Conf[i].name ) return NULL;
123 	return Conf+i;
124 }
125 
126 int config_check_vals(ConfigTable *Conf, ConfigArgs *c, int check_only ) {
127 	int rc, arg_user, arg_type, arg_syn, iarg;
128 	unsigned uiarg;
129 	long larg;
130 	unsigned long ularg;
131 	ber_len_t barg;
132 
133 	if(Conf->arg_type == ARG_IGNORED) {
134 		Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> ignored\n",
135 			c->log, Conf->name, 0);
136 		return(0);
137 	}
138 	arg_type = Conf->arg_type & ARGS_TYPES;
139 	arg_user = Conf->arg_type & ARGS_USERLAND;
140 	arg_syn = Conf->arg_type & ARGS_SYNTAX;
141 
142 	if((arg_type == ARG_DN) && c->argc == 1) {
143 		c->argc = 2;
144 		c->argv[1] = "";
145 	}
146 	if(Conf->min_args && (c->argc < Conf->min_args)) {
147 		snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> missing <%s> argument",
148 			c->argv[0], Conf->what ? Conf->what : "" );
149 		Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n", c->log, c->cr_msg, 0 );
150 		return(ARG_BAD_CONF);
151 	}
152 	if(Conf->max_args && (c->argc > Conf->max_args)) {
153 		char	*ignored = " ignored";
154 
155 		snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> extra cruft after <%s>",
156 			c->argv[0], Conf->what );
157 
158 		ignored = "";
159 		Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s%s.\n",
160 				c->log, c->cr_msg, ignored );
161 		return(ARG_BAD_CONF);
162 	}
163 	if((arg_syn & ARG_DB) && !c->be) {
164 		snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> only allowed within database declaration",
165 			c->argv[0] );
166 		Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n",
167 			c->log, c->cr_msg, 0);
168 		return(ARG_BAD_CONF);
169 	}
170 	if((arg_syn & ARG_PRE_BI) && c->bi) {
171 		snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> must occur before any backend %sdeclaration",
172 			c->argv[0], (arg_syn & ARG_PRE_DB) ? "or database " : "" );
173 		Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n",
174 			c->log, c->cr_msg, 0 );
175 		return(ARG_BAD_CONF);
176 	}
177 	if((arg_syn & ARG_PRE_DB) && c->be && c->be != frontendDB) {
178 		snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> must occur before any database declaration",
179 			c->argv[0] );
180 		Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n",
181 			c->log, c->cr_msg, 0);
182 		return(ARG_BAD_CONF);
183 	}
184 	if((arg_syn & ARG_PAREN) && *c->argv[1] != '(' /*')'*/) {
185 		snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> old format not supported", c->argv[0] );
186 		Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
187 			c->log, c->cr_msg, 0);
188 		return(ARG_BAD_CONF);
189 	}
190 	if(arg_type && !Conf->arg_item && !(arg_syn & ARG_OFFSET)) {
191 		snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid config_table, arg_item is NULL",
192 			c->argv[0] );
193 		Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
194 			c->log, c->cr_msg, 0);
195 		return(ARG_BAD_CONF);
196 	}
197 	c->type = arg_user;
198 	memset(&c->values, 0, sizeof(c->values));
199 	if(arg_type == ARG_STRING) {
200 		assert( c->argc == 2 );
201 		if ( !check_only )
202 			c->value_string = ch_strdup(c->argv[1]);
203 	} else if(arg_type == ARG_BERVAL) {
204 		assert( c->argc == 2 );
205 		if ( !check_only )
206 			ber_str2bv( c->argv[1], 0, 1, &c->value_bv );
207 	} else if(arg_type == ARG_DN) {
208 		struct berval bv;
209 		assert( c->argc == 2 );
210 		ber_str2bv( c->argv[1], 0, 0, &bv );
211 		rc = dnPrettyNormal( NULL, &bv, &c->value_dn, &c->value_ndn, NULL );
212 		if ( rc != LDAP_SUCCESS ) {
213 			snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid DN %d (%s)",
214 				c->argv[0], rc, ldap_err2string( rc ));
215 			Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n" , c->log, c->cr_msg, 0);
216 			return(ARG_BAD_CONF);
217 		}
218 		if ( check_only ) {
219 			ch_free( c->value_ndn.bv_val );
220 			ch_free( c->value_dn.bv_val );
221 		}
222 	} else if(arg_type == ARG_ATDESC) {
223 		const char *text = NULL;
224 		assert( c->argc == 2 );
225 		c->value_ad = NULL;
226 		rc = slap_str2ad( c->argv[1], &c->value_ad, &text );
227 		if ( rc != LDAP_SUCCESS ) {
228 			snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid AttributeDescription %d (%s)",
229 				c->argv[0], rc, text );
230 			Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n" , c->log, c->cr_msg, 0);
231 			return(ARG_BAD_CONF);
232 		}
233 	} else {	/* all numeric */
234 		int j;
235 		iarg = 0; larg = 0; barg = 0;
236 		switch(arg_type) {
237 			case ARG_INT:
238 				assert( c->argc == 2 );
239 				if ( lutil_atoix( &iarg, c->argv[1], 0 ) != 0 ) {
240 					snprintf( c->cr_msg, sizeof( c->cr_msg ),
241 						"<%s> unable to parse \"%s\" as int",
242 						c->argv[0], c->argv[1] );
243 					Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
244 						c->log, c->cr_msg, 0);
245 					return(ARG_BAD_CONF);
246 				}
247 				break;
248 			case ARG_UINT:
249 				assert( c->argc == 2 );
250 				if ( lutil_atoux( &uiarg, c->argv[1], 0 ) != 0 ) {
251 					snprintf( c->cr_msg, sizeof( c->cr_msg ),
252 						"<%s> unable to parse \"%s\" as unsigned int",
253 						c->argv[0], c->argv[1] );
254 					Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
255 						c->log, c->cr_msg, 0);
256 					return(ARG_BAD_CONF);
257 				}
258 				break;
259 			case ARG_LONG:
260 				assert( c->argc == 2 );
261 				if ( lutil_atolx( &larg, c->argv[1], 0 ) != 0 ) {
262 					snprintf( c->cr_msg, sizeof( c->cr_msg ),
263 						"<%s> unable to parse \"%s\" as long",
264 						c->argv[0], c->argv[1] );
265 					Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
266 						c->log, c->cr_msg, 0);
267 					return(ARG_BAD_CONF);
268 				}
269 				break;
270 			case ARG_ULONG:
271 				assert( c->argc == 2 );
272 				if ( lutil_atoulx( &ularg, c->argv[1], 0 ) != 0 ) {
273 					snprintf( c->cr_msg, sizeof( c->cr_msg ),
274 						"<%s> unable to parse \"%s\" as unsigned long",
275 						c->argv[0], c->argv[1] );
276 					Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
277 						c->log, c->cr_msg, 0);
278 					return(ARG_BAD_CONF);
279 				}
280 				break;
281 			case ARG_BER_LEN_T: {
282 				unsigned long	l;
283 				assert( c->argc == 2 );
284 				if ( lutil_atoulx( &l, c->argv[1], 0 ) != 0 ) {
285 					snprintf( c->cr_msg, sizeof( c->cr_msg ),
286 						"<%s> unable to parse \"%s\" as ber_len_t",
287 						c->argv[0], c->argv[1] );
288 					Debug(LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n",
289 						c->log, c->cr_msg, 0);
290 					return(ARG_BAD_CONF);
291 				}
292 				barg = (ber_len_t)l;
293 				} break;
294 			case ARG_ON_OFF:
295 				/* note: this is an explicit exception
296 				 * to the "need exactly 2 args" rule */
297 				if (c->argc == 1) {
298 					iarg = 1;
299 				} else if ( !strcasecmp(c->argv[1], "on") ||
300 					!strcasecmp(c->argv[1], "true") ||
301 					!strcasecmp(c->argv[1], "yes") )
302 				{
303 					iarg = 1;
304 				} else if ( !strcasecmp(c->argv[1], "off") ||
305 					!strcasecmp(c->argv[1], "false") ||
306 					!strcasecmp(c->argv[1], "no") )
307 				{
308 					iarg = 0;
309 				} else {
310 					snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid value",
311 						c->argv[0] );
312 					Debug(LDAP_DEBUG_ANY|LDAP_DEBUG_NONE, "%s: %s\n",
313 						c->log, c->cr_msg, 0 );
314 					return(ARG_BAD_CONF);
315 				}
316 				break;
317 		}
318 		j = (arg_type & ARG_NONZERO) ? 1 : 0;
319 		if(iarg < j && larg < j && barg < (unsigned)j ) {
320 			larg = larg ? larg : (barg ? (long)barg : iarg);
321 			snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> invalid value",
322 				c->argv[0] );
323 			Debug(LDAP_DEBUG_ANY|LDAP_DEBUG_NONE, "%s: %s\n",
324 				c->log, c->cr_msg, 0 );
325 			return(ARG_BAD_CONF);
326 		}
327 		switch(arg_type) {
328 			case ARG_ON_OFF:
329 			case ARG_INT:		c->value_int = iarg;		break;
330 			case ARG_UINT:		c->value_uint = uiarg;		break;
331 			case ARG_LONG:		c->value_long = larg;		break;
332 			case ARG_ULONG:		c->value_ulong = ularg;		break;
333 			case ARG_BER_LEN_T:	c->value_ber_t = barg;		break;
334 		}
335 	}
336 	return 0;
337 }
338 
339 int config_set_vals(ConfigTable *Conf, ConfigArgs *c) {
340 	int rc, arg_type;
341 	void *ptr = NULL;
342 
343 	arg_type = Conf->arg_type;
344 	if(arg_type & ARG_MAGIC) {
345 		if(!c->be) c->be = frontendDB;
346 		c->cr_msg[0] = '\0';
347 		rc = (*((ConfigDriver*)Conf->arg_item))(c);
348 #if 0
349 		if(c->be == frontendDB) c->be = NULL;
350 #endif
351 		if(rc) {
352 			if ( !c->cr_msg[0] ) {
353 				snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> handler exited with %d",
354 					c->argv[0], rc );
355 				Debug(LDAP_DEBUG_CONFIG, "%s: %s!\n",
356 					c->log, c->cr_msg, 0 );
357 			}
358 			return(ARG_BAD_CONF);
359 		}
360 		return(0);
361 	}
362 	if(arg_type & ARG_OFFSET) {
363 		if (c->be && c->table == Cft_Database)
364 			ptr = c->be->be_private;
365 		else if (c->bi)
366 			ptr = c->bi->bi_private;
367 		else {
368 			snprintf( c->cr_msg, sizeof( c->cr_msg ), "<%s> offset is missing base pointer",
369 				c->argv[0] );
370 			Debug(LDAP_DEBUG_CONFIG, "%s: %s!\n",
371 				c->log, c->cr_msg, 0);
372 			return(ARG_BAD_CONF);
373 		}
374 		ptr = (void *)((char *)ptr + (long)Conf->arg_item);
375 	} else if (arg_type & ARGS_TYPES) {
376 		ptr = Conf->arg_item;
377 	}
378 	if(arg_type & ARGS_TYPES)
379 		switch(arg_type & ARGS_TYPES) {
380 			case ARG_ON_OFF:
381 			case ARG_INT: 		*(int*)ptr = c->value_int;			break;
382 			case ARG_UINT: 		*(unsigned*)ptr = c->value_uint;			break;
383 			case ARG_LONG:  	*(long*)ptr = c->value_long;			break;
384 			case ARG_ULONG:  	*(unsigned long*)ptr = c->value_ulong;			break;
385 			case ARG_BER_LEN_T: 	*(ber_len_t*)ptr = c->value_ber_t;			break;
386 			case ARG_STRING: {
387 				char *cc = *(char**)ptr;
388 				if(cc) {
389 					if ((arg_type & ARG_UNIQUE) && c->op == SLAP_CONFIG_ADD ) {
390 						Debug(LDAP_DEBUG_CONFIG, "%s: already set %s!\n",
391 							c->log, Conf->name, 0 );
392 						return(ARG_BAD_CONF);
393 					}
394 					ch_free(cc);
395 				}
396 				*(char **)ptr = c->value_string;
397 				break;
398 				}
399 			case ARG_BERVAL:
400 				*(struct berval *)ptr = c->value_bv;
401 				break;
402 			case ARG_ATDESC:
403 				*(AttributeDescription **)ptr = c->value_ad;
404 				break;
405 		}
406 	return(0);
407 }
408 
409 int config_add_vals(ConfigTable *Conf, ConfigArgs *c) {
410 	int rc, arg_type;
411 
412 	arg_type = Conf->arg_type;
413 	if(arg_type == ARG_IGNORED) {
414 		Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> ignored\n",
415 			c->log, Conf->name, 0);
416 		return(0);
417 	}
418 	rc = config_check_vals( Conf, c, 0 );
419 	if ( rc ) return rc;
420 	return config_set_vals( Conf, c );
421 }
422 
423 int
424 config_del_vals(ConfigTable *cf, ConfigArgs *c)
425 {
426 	int rc = 0;
427 
428 	/* If there is no handler, just ignore it */
429 	if ( cf->arg_type & ARG_MAGIC ) {
430 		c->argv[0] = cf->ad->ad_cname.bv_val;
431 		c->op = LDAP_MOD_DELETE;
432 		c->type = cf->arg_type & ARGS_USERLAND;
433 		rc = (*((ConfigDriver*)cf->arg_item))(c);
434 	}
435 	return rc;
436 }
437 
438 int
439 config_get_vals(ConfigTable *cf, ConfigArgs *c)
440 {
441 	int rc = 0;
442 	struct berval bv;
443 	void *ptr;
444 
445 	if ( cf->arg_type & ARG_IGNORED ) {
446 		return 1;
447 	}
448 
449 	memset(&c->values, 0, sizeof(c->values));
450 	c->rvalue_vals = NULL;
451 	c->rvalue_nvals = NULL;
452 	c->op = SLAP_CONFIG_EMIT;
453 	c->type = cf->arg_type & ARGS_USERLAND;
454 
455 	if ( cf->arg_type & ARG_MAGIC ) {
456 		rc = (*((ConfigDriver*)cf->arg_item))(c);
457 		if ( rc ) return rc;
458 	} else {
459 		if ( cf->arg_type & ARG_OFFSET ) {
460 			if (c->be && c->table == Cft_Database)
461 				ptr = c->be->be_private;
462 			else if ( c->bi )
463 				ptr = c->bi->bi_private;
464 			else
465 				return 1;
466 			ptr = (void *)((char *)ptr + (long)cf->arg_item);
467 		} else {
468 			ptr = cf->arg_item;
469 		}
470 
471 		switch(cf->arg_type & ARGS_TYPES) {
472 		case ARG_ON_OFF:
473 		case ARG_INT:	c->value_int = *(int *)ptr; break;
474 		case ARG_UINT:	c->value_uint = *(unsigned *)ptr; break;
475 		case ARG_LONG:	c->value_long = *(long *)ptr; break;
476 		case ARG_ULONG:	c->value_ulong = *(unsigned long *)ptr; break;
477 		case ARG_BER_LEN_T:	c->value_ber_t = *(ber_len_t *)ptr; break;
478 		case ARG_STRING:
479 			if ( *(char **)ptr )
480 				c->value_string = ch_strdup(*(char **)ptr);
481 			break;
482 		case ARG_BERVAL:
483 			c->value_bv = *((struct berval *)ptr); break;
484 		case ARG_ATDESC:
485 			c->value_ad = *(AttributeDescription **)ptr; break;
486 		}
487 	}
488 	if ( cf->arg_type & ARGS_TYPES) {
489 		bv.bv_len = 0;
490 		bv.bv_val = c->log;
491 		switch(cf->arg_type & ARGS_TYPES) {
492 		case ARG_INT: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%d", c->value_int); break;
493 		case ARG_UINT: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%u", c->value_uint); break;
494 		case ARG_LONG: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%ld", c->value_long); break;
495 		case ARG_ULONG: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%lu", c->value_ulong); break;
496 		case ARG_BER_LEN_T: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%ld", c->value_ber_t); break;
497 		case ARG_ON_OFF: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%s",
498 			c->value_int ? "TRUE" : "FALSE"); break;
499 		case ARG_STRING:
500 			if ( c->value_string && c->value_string[0]) {
501 				ber_str2bv( c->value_string, 0, 0, &bv);
502 			} else {
503 				return 1;
504 			}
505 			break;
506 		case ARG_BERVAL:
507 			if ( !BER_BVISEMPTY( &c->value_bv )) {
508 				bv = c->value_bv;
509 			} else {
510 				return 1;
511 			}
512 			break;
513 		case ARG_ATDESC:
514 			if ( c->value_ad ) {
515 				bv = c->value_ad->ad_cname;
516 			} else {
517 				return 1;
518 			}
519 			break;
520 		default:
521 			bv.bv_val = NULL;
522 			break;
523 		}
524 		if (bv.bv_val == c->log && bv.bv_len >= sizeof( c->log ) ) {
525 			return 1;
526 		}
527 		if (( cf->arg_type & ARGS_TYPES ) == ARG_STRING ) {
528 			ber_bvarray_add(&c->rvalue_vals, &bv);
529 		} else if ( !BER_BVISNULL( &bv ) ) {
530 			value_add_one(&c->rvalue_vals, &bv);
531 		}
532 		/* else: maybe c->rvalue_vals already set? */
533 	}
534 	return rc;
535 }
536 
537 int
538 init_config_attrs(ConfigTable *ct) {
539 	int i, code;
540 
541 	for (i=0; ct[i].name; i++ ) {
542 		if ( !ct[i].attribute ) continue;
543 		code = register_at( ct[i].attribute, &ct[i].ad, 1 );
544 		if ( code ) {
545 			fprintf( stderr, "init_config_attrs: register_at failed\n" );
546 			return code;
547 		}
548 	}
549 
550 	return 0;
551 }
552 
553 int
554 init_config_ocs( ConfigOCs *ocs ) {
555 	int i, code;
556 
557 	for (i=0;ocs[i].co_def;i++) {
558 		code = register_oc( ocs[i].co_def, &ocs[i].co_oc, 1 );
559 		if ( code ) {
560 			fprintf( stderr, "init_config_ocs: register_oc failed\n" );
561 			return code;
562 		}
563 	}
564 	return 0;
565 }
566 
567 /* Split an LDIF line into space-separated tokens. Words may be grouped
568  * by quotes. A quoted string may begin in the middle of a word, but must
569  * end at the end of the word (be followed by whitespace or EOS). Any other
570  * quotes are passed through unchanged. All other characters are passed
571  * through unchanged.
572  */
573 static char *
574 strtok_quote_ldif( char **line )
575 {
576 	char *beg, *ptr, *quote=NULL;
577 	int inquote=0;
578 
579 	ptr = *line;
580 
581 	if ( !ptr || !*ptr )
582 		return NULL;
583 
584 	while( isspace( (unsigned char) *ptr )) ptr++;
585 
586 	if ( *ptr == '"' ) {
587 		inquote = 1;
588 		ptr++;
589 	}
590 
591 	beg = ptr;
592 
593 	for (;*ptr;ptr++) {
594 		if ( *ptr == '"' ) {
595 			if ( inquote && ( !ptr[1] || isspace((unsigned char) ptr[1]))) {
596 				*ptr++ = '\0';
597 				break;
598 			}
599 			inquote = 1;
600 			quote = ptr;
601 			continue;
602 		}
603 		if ( inquote )
604 			continue;
605 		if ( isspace( (unsigned char) *ptr )) {
606 			*ptr++ = '\0';
607 			break;
608 		}
609 	}
610 	if ( quote ) {
611 		while ( quote < ptr ) {
612 			*quote = quote[1];
613 			quote++;
614 		}
615 	}
616 	if ( !*ptr ) {
617 		*line = NULL;
618 	} else {
619 		while ( isspace( (unsigned char) *ptr )) ptr++;
620 		*line = ptr;
621 	}
622 	return beg;
623 }
624 
625 static void
626 config_parse_ldif( ConfigArgs *c )
627 {
628 	char *next;
629 	c->tline = ch_strdup(c->line);
630 	next = c->tline;
631 
632 	while ((c->argv[c->argc] = strtok_quote_ldif( &next )) != NULL) {
633 		c->argc++;
634 		if ( c->argc >= c->argv_size ) {
635 			char **tmp = ch_realloc( c->argv, (c->argv_size + ARGS_STEP) *
636 				sizeof( *c->argv ));
637 			c->argv = tmp;
638 			c->argv_size += ARGS_STEP;
639 		}
640 	}
641 	c->argv[c->argc] = NULL;
642 }
643 
644 int
645 config_parse_vals(ConfigTable *ct, ConfigArgs *c, int valx)
646 {
647 	int 	rc = 0;
648 
649 	snprintf( c->log, sizeof( c->log ), "%s: value #%d",
650 		ct->ad->ad_cname.bv_val, valx );
651 	c->argc = 1;
652 	c->argv[0] = ct->ad->ad_cname.bv_val;
653 
654 	if ( ( ct->arg_type & ARG_QUOTE ) && c->line[ 0 ] != '"' ) {
655 		c->argv[c->argc] = c->line;
656 		c->argc++;
657 		c->argv[c->argc] = NULL;
658 		c->tline = NULL;
659 	} else {
660 		config_parse_ldif( c );
661 	}
662 	rc = config_check_vals( ct, c, 1 );
663 	ch_free( c->tline );
664 	c->tline = NULL;
665 
666 	if ( rc )
667 		rc = LDAP_CONSTRAINT_VIOLATION;
668 
669 	return rc;
670 }
671 
672 int
673 config_parse_add(ConfigTable *ct, ConfigArgs *c, int valx)
674 {
675 	int	rc = 0;
676 
677 	snprintf( c->log, sizeof( c->log ), "%s: value #%d",
678 		ct->ad->ad_cname.bv_val, valx );
679 	c->argc = 1;
680 	c->argv[0] = ct->ad->ad_cname.bv_val;
681 
682 	if ( ( ct->arg_type & ARG_QUOTE ) && c->line[ 0 ] != '"' ) {
683 		c->argv[c->argc] = c->line;
684 		c->argc++;
685 		c->argv[c->argc] = NULL;
686 		c->tline = NULL;
687 	} else {
688 		config_parse_ldif( c );
689 	}
690 	c->op = LDAP_MOD_ADD;
691 	rc = config_add_vals( ct, c );
692 	ch_free( c->tline );
693 
694 	return rc;
695 }
696 
697 int
698 read_config_file(const char *fname, int depth, ConfigArgs *cf, ConfigTable *cft)
699 {
700 	FILE *fp;
701 	ConfigTable *ct;
702 	ConfigArgs *c;
703 	int rc;
704 	struct stat s;
705 
706 	c = ch_calloc( 1, sizeof( ConfigArgs ) );
707 	if ( c == NULL ) {
708 		return 1;
709 	}
710 
711 	if ( depth ) {
712 		memcpy( c, cf, sizeof( ConfigArgs ) );
713 	} else {
714 		c->depth = depth; /* XXX */
715 		c->bi = NULL;
716 		c->be = NULL;
717 	}
718 
719 	c->valx = -1;
720 	c->fname = fname;
721 	init_config_argv( c );
722 
723 	if ( stat( fname, &s ) != 0 ) {
724 		ldap_syslog = 1;
725 		Debug(LDAP_DEBUG_ANY,
726 		    "could not stat config file \"%s\": %s (%d)\n",
727 		    fname, strerror(errno), errno);
728 		ch_free( c );
729 		return(1);
730 	}
731 
732 	if ( !S_ISREG( s.st_mode ) ) {
733 		ldap_syslog = 1;
734 		Debug(LDAP_DEBUG_ANY,
735 		    "regular file expected, got \"%s\"\n",
736 		    fname, 0, 0 );
737 		ch_free( c );
738 		return(1);
739 	}
740 
741 	fp = fopen( fname, "r" );
742 	if ( fp == NULL ) {
743 		ldap_syslog = 1;
744 		Debug(LDAP_DEBUG_ANY,
745 		    "could not open config file \"%s\": %s (%d)\n",
746 		    fname, strerror(errno), errno);
747 		ch_free( c );
748 		return(1);
749 	}
750 
751 	Debug(LDAP_DEBUG_CONFIG, "reading config file %s\n", fname, 0, 0);
752 
753 	fp_getline_init(c);
754 
755 	c->tline = NULL;
756 
757 	while ( fp_getline( fp, c ) ) {
758 		/* skip comments and blank lines */
759 		if ( c->line[0] == '#' || c->line[0] == '\0' ) {
760 			continue;
761 		}
762 
763 		snprintf( c->log, sizeof( c->log ), "%s: line %d",
764 				c->fname, c->lineno );
765 
766 		c->argc = 0;
767 		ch_free( c->tline );
768 		if ( config_fp_parse_line( c ) ) {
769 			rc = 1;
770 			goto done;
771 		}
772 
773 		if ( c->argc < 1 ) {
774 			Debug( LDAP_DEBUG_ANY, "%s: bad config line.\n",
775 				c->log, 0, 0);
776 			rc = 1;
777 			goto done;
778 		}
779 
780 		c->op = SLAP_CONFIG_ADD;
781 
782 		ct = config_find_keyword( cft, c );
783 		if ( ct ) {
784 			c->table = Cft_Global;
785 			rc = config_add_vals( ct, c );
786 			if ( !rc ) continue;
787 
788 			if ( rc & ARGS_USERLAND ) {
789 				/* XXX a usertype would be opaque here */
790 				Debug(LDAP_DEBUG_CONFIG, "%s: unknown user type <%s>\n",
791 					c->log, c->argv[0], 0);
792 				rc = 1;
793 				goto done;
794 
795 			} else if ( rc == ARG_BAD_CONF ) {
796 				rc = 1;
797 				goto done;
798 			}
799 
800 		} else if ( c->bi && !c->be ) {
801 			rc = SLAP_CONF_UNKNOWN;
802 			if ( c->bi->bi_cf_ocs ) {
803 				ct = config_find_keyword( c->bi->bi_cf_ocs->co_table, c );
804 				if ( ct ) {
805 					c->table = c->bi->bi_cf_ocs->co_type;
806 					rc = config_add_vals( ct, c );
807 				}
808 			}
809 			if ( c->bi->bi_config && rc == SLAP_CONF_UNKNOWN ) {
810 				rc = (*c->bi->bi_config)(c->bi, c->fname, c->lineno,
811 					c->argc, c->argv);
812 			}
813 			if ( rc ) {
814 				switch(rc) {
815 				case SLAP_CONF_UNKNOWN:
816 					Debug( LDAP_DEBUG_ANY, "%s: unknown directive "
817 						"<%s> inside backend info definition.\n",
818 						c->log, *c->argv, 0);
819 				default:
820 					rc = 1;
821 					goto done;
822 				}
823 			}
824 
825 		} else if ( c->be && c->be != frontendDB ) {
826 			rc = SLAP_CONF_UNKNOWN;
827 			if ( c->be->be_cf_ocs ) {
828 				ct = config_find_keyword( c->be->be_cf_ocs->co_table, c );
829 				if ( ct ) {
830 					c->table = c->be->be_cf_ocs->co_type;
831 					rc = config_add_vals( ct, c );
832 				}
833 			}
834 			if ( c->be->be_config && rc == SLAP_CONF_UNKNOWN ) {
835 				rc = (*c->be->be_config)(c->be, c->fname, c->lineno,
836 					c->argc, c->argv);
837 			}
838 			if ( rc == SLAP_CONF_UNKNOWN && SLAP_ISGLOBALOVERLAY( frontendDB ) )
839 			{
840 				/* global overlays may need
841 				 * definitions inside other databases...
842 				 */
843 				rc = (*frontendDB->be_config)( frontendDB,
844 					c->fname, (int)c->lineno, c->argc, c->argv );
845 			}
846 
847 			switch ( rc ) {
848 			case 0:
849 				break;
850 
851 			case SLAP_CONF_UNKNOWN:
852 				Debug( LDAP_DEBUG_ANY, "%s: unknown directive "
853 					"<%s> inside backend database definition.\n",
854 					c->log, *c->argv, 0);
855 
856 			default:
857 				rc = 1;
858 				goto done;
859 			}
860 
861 		} else if ( frontendDB->be_config ) {
862 			rc = (*frontendDB->be_config)( frontendDB,
863 				c->fname, (int)c->lineno, c->argc, c->argv);
864 			if ( rc ) {
865 				switch(rc) {
866 				case SLAP_CONF_UNKNOWN:
867 					Debug( LDAP_DEBUG_ANY, "%s: unknown directive "
868 						"<%s> inside global database definition.\n",
869 						c->log, *c->argv, 0);
870 
871 				default:
872 					rc = 1;
873 					goto done;
874 				}
875 			}
876 
877 		} else {
878 			Debug( LDAP_DEBUG_ANY, "%s: unknown directive "
879 				"<%s> outside backend info and database definitions.\n",
880 				c->log, *c->argv, 0);
881 			rc = 1;
882 			goto done;
883 		}
884 	}
885 
886 	rc = 0;
887 
888 done:
889 	if ( cf ) {
890 		cf->be = c->be;
891 		cf->bi = c->bi;
892 	}
893 	ch_free(c->tline);
894 	fclose(fp);
895 	ch_free(c->argv);
896 	ch_free(c);
897 	return(rc);
898 }
899 
900 /* restrictops, allows, disallows, requires, loglevel */
901 
902 int
903 bverb_to_mask(struct berval *bword, slap_verbmasks *v) {
904 	int i;
905 	for(i = 0; !BER_BVISNULL(&v[i].word); i++) {
906 		if(!ber_bvstrcasecmp(bword, &v[i].word)) break;
907 	}
908 	return(i);
909 }
910 
911 int
912 verb_to_mask(const char *word, slap_verbmasks *v) {
913 	struct berval	bword;
914 	ber_str2bv( word, 0, 0, &bword );
915 	return bverb_to_mask( &bword, v );
916 }
917 
918 int
919 verbs_to_mask(int argc, char *argv[], slap_verbmasks *v, slap_mask_t *m) {
920 	int i, j;
921 	for(i = 1; i < argc; i++) {
922 		j = verb_to_mask(argv[i], v);
923 		if(BER_BVISNULL(&v[j].word)) return i;
924 		while (!v[j].mask) j--;
925 		*m |= v[j].mask;
926 	}
927 	return(0);
928 }
929 
930 /* Mask keywords that represent multiple bits should occur before single
931  * bit keywords in the verbmasks array.
932  */
933 int
934 mask_to_verbs(slap_verbmasks *v, slap_mask_t m, BerVarray *bva) {
935 	int i, rc = 1;
936 
937 	if (m) {
938 		for (i=0; !BER_BVISNULL(&v[i].word); i++) {
939 			if (!v[i].mask) continue;
940 			if (( m & v[i].mask ) == v[i].mask ) {
941 				value_add_one( bva, &v[i].word );
942 				rc = 0;
943 				m ^= v[i].mask;
944 				if ( !m ) break;
945 			}
946 		}
947 	}
948 	return rc;
949 }
950 
951 /* Return the verbs as a single string, separated by delim */
952 int
953 mask_to_verbstring(slap_verbmasks *v, slap_mask_t m0, char delim, struct berval *bv)
954 {
955 	int i, rc = 1;
956 
957 	BER_BVZERO( bv );
958 	if (m0) {
959 		slap_mask_t m = m0;
960 		char *ptr;
961 		for (i=0; !BER_BVISNULL(&v[i].word); i++) {
962 			if (!v[i].mask) continue;
963 			if (( m & v[i].mask ) == v[i].mask ) {
964 				bv->bv_len += v[i].word.bv_len + 1;
965 				rc = 0;
966 				m ^= v[i].mask;
967 				if ( !m ) break;
968 			}
969 		}
970 		bv->bv_val = ch_malloc(bv->bv_len);
971 		bv->bv_len--;
972 		ptr = bv->bv_val;
973 		m = m0;
974 		for (i=0; !BER_BVISNULL(&v[i].word); i++) {
975 			if (!v[i].mask) continue;
976 			if (( m & v[i].mask ) == v[i].mask ) {
977 				ptr = lutil_strcopy(ptr, v[i].word.bv_val);
978 				*ptr++ = delim;
979 				m ^= v[i].mask;
980 				if ( !m ) break;
981 			}
982 		}
983 		ptr[-1] = '\0';
984 	}
985 	return rc;
986 }
987 
988 /* Parse a verbstring */
989 int
990 verbstring_to_mask(slap_verbmasks *v, char *str, char delim, slap_mask_t *m) {
991 	int j;
992 	char *d;
993 	struct berval bv;
994 
995 	do {
996 		bv.bv_val = str;
997 		d = strchr( str, delim );
998 		if ( d )
999 			bv.bv_len = d - str;
1000 		else
1001 			bv.bv_len = strlen( str );
1002 		j = bverb_to_mask( &bv, v );
1003 		if(BER_BVISNULL(&v[j].word)) return 1;
1004 		while (!v[j].mask) j--;
1005 		*m |= v[j].mask;
1006 		str += bv.bv_len + 1;
1007 	} while ( d );
1008 	return(0);
1009 }
1010 
1011 int
1012 slap_verbmasks_init( slap_verbmasks **vp, slap_verbmasks *v )
1013 {
1014 	int		i;
1015 
1016 	assert( *vp == NULL );
1017 
1018 	for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) /* EMPTY */;
1019 
1020 	*vp = ch_calloc( i + 1, sizeof( slap_verbmasks ) );
1021 
1022 	for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) {
1023 		ber_dupbv( &(*vp)[ i ].word, &v[ i ].word );
1024 		*((slap_mask_t *)&(*vp)[ i ].mask) = v[ i ].mask;
1025 	}
1026 
1027 	BER_BVZERO( &(*vp)[ i ].word );
1028 
1029 	return 0;
1030 }
1031 
1032 int
1033 slap_verbmasks_destroy( slap_verbmasks *v )
1034 {
1035 	int		i;
1036 
1037 	assert( v != NULL );
1038 
1039 	for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) {
1040 		ch_free( v[ i ].word.bv_val );
1041 	}
1042 
1043 	ch_free( v );
1044 
1045 	return 0;
1046 }
1047 
1048 int
1049 slap_verbmasks_append(
1050 	slap_verbmasks	**vp,
1051 	slap_mask_t	m,
1052 	struct berval	*v,
1053 	slap_mask_t	*ignore )
1054 {
1055 	int	i;
1056 
1057 	if ( !m ) {
1058 		return LDAP_OPERATIONS_ERROR;
1059 	}
1060 
1061 	for ( i = 0; !BER_BVISNULL( &(*vp)[ i ].word ); i++ ) {
1062 		if ( !(*vp)[ i ].mask ) continue;
1063 
1064 		if ( ignore != NULL ) {
1065 			int	j;
1066 
1067 			for ( j = 0; ignore[ j ] != 0; j++ ) {
1068 				if ( (*vp)[ i ].mask == ignore[ j ] ) {
1069 					goto check_next;
1070 				}
1071 			}
1072 		}
1073 
1074 		if ( ( m & (*vp)[ i ].mask ) == (*vp)[ i ].mask ) {
1075 			if ( ber_bvstrcasecmp( v, &(*vp)[ i ].word ) == 0 ) {
1076 				/* already set; ignore */
1077 				return LDAP_SUCCESS;
1078 			}
1079 			/* conflicts */
1080 			return LDAP_TYPE_OR_VALUE_EXISTS;
1081 		}
1082 
1083 		if ( m & (*vp)[ i ].mask ) {
1084 			/* conflicts */
1085 			return LDAP_CONSTRAINT_VIOLATION;
1086 		}
1087 check_next:;
1088 	}
1089 
1090 	*vp = ch_realloc( *vp, sizeof( slap_verbmasks ) * ( i + 2 ) );
1091 	ber_dupbv( &(*vp)[ i ].word, v );
1092 	*((slap_mask_t *)&(*vp)[ i ].mask) = m;
1093 	BER_BVZERO( &(*vp)[ i + 1 ].word );
1094 
1095 	return LDAP_SUCCESS;
1096 }
1097 
1098 int
1099 enum_to_verb(slap_verbmasks *v, slap_mask_t m, struct berval *bv) {
1100 	int i;
1101 
1102 	for (i=0; !BER_BVISNULL(&v[i].word); i++) {
1103 		if ( m == v[i].mask ) {
1104 			if ( bv != NULL ) {
1105 				*bv = v[i].word;
1106 			}
1107 			return i;
1108 		}
1109 	}
1110 	return -1;
1111 }
1112 
1113 /* register a new verbmask */
1114 static int
1115 slap_verbmask_register( slap_verbmasks *vm_, slap_verbmasks **vmp, struct berval *bv, int mask )
1116 {
1117 	slap_verbmasks	*vm = *vmp;
1118 	int		i;
1119 
1120 	/* check for duplicate word */
1121 	/* NOTE: we accept duplicate codes; the first occurrence will be used
1122 	 * when mapping from mask to verb */
1123 	i = verb_to_mask( bv->bv_val, vm );
1124 	if ( !BER_BVISNULL( &vm[ i ].word ) ) {
1125 		return -1;
1126 	}
1127 
1128 	for ( i = 0; !BER_BVISNULL( &vm[ i ].word ); i++ )
1129 		;
1130 
1131 	if ( vm == vm_ ) {
1132 		/* first time: duplicate array */
1133 		vm = ch_calloc( i + 2, sizeof( slap_verbmasks ) );
1134 		for ( i = 0; !BER_BVISNULL( &vm_[ i ].word ); i++ )
1135 		{
1136 			ber_dupbv( &vm[ i ].word, &vm_[ i ].word );
1137 			*((slap_mask_t*)&vm[ i ].mask) = vm_[ i ].mask;
1138 		}
1139 
1140 	} else {
1141 		vm = ch_realloc( vm, (i + 2) * sizeof( slap_verbmasks ) );
1142 	}
1143 
1144 	ber_dupbv( &vm[ i ].word, bv );
1145 	*((slap_mask_t*)&vm[ i ].mask) = mask;
1146 
1147 	BER_BVZERO( &vm[ i+1 ].word );
1148 
1149 	*vmp = vm;
1150 
1151 	return i;
1152 }
1153 
1154 static slap_verbmasks slap_ldap_response_code_[] = {
1155 	{ BER_BVC("success"),				LDAP_SUCCESS },
1156 
1157 	{ BER_BVC("operationsError"),			LDAP_OPERATIONS_ERROR },
1158 	{ BER_BVC("protocolError"),			LDAP_PROTOCOL_ERROR },
1159 	{ BER_BVC("timelimitExceeded"),			LDAP_TIMELIMIT_EXCEEDED },
1160 	{ BER_BVC("sizelimitExceeded"),			LDAP_SIZELIMIT_EXCEEDED },
1161 	{ BER_BVC("compareFalse"),			LDAP_COMPARE_FALSE },
1162 	{ BER_BVC("compareTrue"),			LDAP_COMPARE_TRUE },
1163 
1164 	{ BER_BVC("authMethodNotSupported"),		LDAP_AUTH_METHOD_NOT_SUPPORTED },
1165 	{ BER_BVC("strongAuthNotSupported"),		LDAP_STRONG_AUTH_NOT_SUPPORTED },
1166 	{ BER_BVC("strongAuthRequired"),		LDAP_STRONG_AUTH_REQUIRED },
1167 	{ BER_BVC("strongerAuthRequired"),		LDAP_STRONGER_AUTH_REQUIRED },
1168 #if 0 /* not LDAPv3 */
1169 	{ BER_BVC("partialResults"),			LDAP_PARTIAL_RESULTS },
1170 #endif
1171 
1172 	{ BER_BVC("referral"),				LDAP_REFERRAL },
1173 	{ BER_BVC("adminlimitExceeded"),		LDAP_ADMINLIMIT_EXCEEDED },
1174 	{ BER_BVC("unavailableCriticalExtension"),	LDAP_UNAVAILABLE_CRITICAL_EXTENSION },
1175 	{ BER_BVC("confidentialityRequired"),		LDAP_CONFIDENTIALITY_REQUIRED },
1176 	{ BER_BVC("saslBindInProgress"),		LDAP_SASL_BIND_IN_PROGRESS },
1177 
1178 	{ BER_BVC("noSuchAttribute"),			LDAP_NO_SUCH_ATTRIBUTE },
1179 	{ BER_BVC("undefinedType"),			LDAP_UNDEFINED_TYPE },
1180 	{ BER_BVC("inappropriateMatching"),		LDAP_INAPPROPRIATE_MATCHING },
1181 	{ BER_BVC("constraintViolation"),		LDAP_CONSTRAINT_VIOLATION },
1182 	{ BER_BVC("typeOrValueExists"),			LDAP_TYPE_OR_VALUE_EXISTS },
1183 	{ BER_BVC("invalidSyntax"),			LDAP_INVALID_SYNTAX },
1184 
1185 	{ BER_BVC("noSuchObject"),			LDAP_NO_SUCH_OBJECT },
1186 	{ BER_BVC("aliasProblem"),			LDAP_ALIAS_PROBLEM },
1187 	{ BER_BVC("invalidDnSyntax"),			LDAP_INVALID_DN_SYNTAX },
1188 #if 0 /* not LDAPv3 */
1189 	{ BER_BVC("isLeaf"),				LDAP_IS_LEAF },
1190 #endif
1191 	{ BER_BVC("aliasDerefProblem"),			LDAP_ALIAS_DEREF_PROBLEM },
1192 
1193 	{ BER_BVC("proxyAuthzFailure"),			LDAP_X_PROXY_AUTHZ_FAILURE },
1194 	{ BER_BVC("inappropriateAuth"),			LDAP_INAPPROPRIATE_AUTH },
1195 	{ BER_BVC("invalidCredentials"),		LDAP_INVALID_CREDENTIALS },
1196 	{ BER_BVC("insufficientAccess"),		LDAP_INSUFFICIENT_ACCESS },
1197 
1198 	{ BER_BVC("busy"),				LDAP_BUSY },
1199 	{ BER_BVC("unavailable"),			LDAP_UNAVAILABLE },
1200 	{ BER_BVC("unwillingToPerform"),		LDAP_UNWILLING_TO_PERFORM },
1201 	{ BER_BVC("loopDetect"),			LDAP_LOOP_DETECT },
1202 
1203 	{ BER_BVC("namingViolation"),			LDAP_NAMING_VIOLATION },
1204 	{ BER_BVC("objectClassViolation"),		LDAP_OBJECT_CLASS_VIOLATION },
1205 	{ BER_BVC("notAllowedOnNonleaf"),		LDAP_NOT_ALLOWED_ON_NONLEAF },
1206 	{ BER_BVC("notAllowedOnRdn"),			LDAP_NOT_ALLOWED_ON_RDN },
1207 	{ BER_BVC("alreadyExists"),			LDAP_ALREADY_EXISTS },
1208 	{ BER_BVC("noObjectClassMods"),			LDAP_NO_OBJECT_CLASS_MODS },
1209 	{ BER_BVC("resultsTooLarge"),			LDAP_RESULTS_TOO_LARGE },
1210 	{ BER_BVC("affectsMultipleDsas"),		LDAP_AFFECTS_MULTIPLE_DSAS },
1211 
1212 	{ BER_BVC("other"),				LDAP_OTHER },
1213 
1214 	/* extension-specific */
1215 
1216 	{ BER_BVC("cupResourcesExhausted"),		LDAP_CUP_RESOURCES_EXHAUSTED },
1217 	{ BER_BVC("cupSecurityViolation"),		LDAP_CUP_SECURITY_VIOLATION },
1218 	{ BER_BVC("cupInvalidData"),			LDAP_CUP_INVALID_DATA },
1219 	{ BER_BVC("cupUnsupportedScheme"),		LDAP_CUP_UNSUPPORTED_SCHEME },
1220 	{ BER_BVC("cupReloadRequired"),			LDAP_CUP_RELOAD_REQUIRED },
1221 
1222 	{ BER_BVC("cancelled"),				LDAP_CANCELLED },
1223 	{ BER_BVC("noSuchOperation"),			LDAP_NO_SUCH_OPERATION },
1224 	{ BER_BVC("tooLate"),				LDAP_TOO_LATE },
1225 	{ BER_BVC("cannotCancel"),			LDAP_CANNOT_CANCEL },
1226 
1227 	{ BER_BVC("assertionFailed"),			LDAP_ASSERTION_FAILED },
1228 
1229 	{ BER_BVC("proxiedAuthorizationDenied"),	LDAP_PROXIED_AUTHORIZATION_DENIED },
1230 
1231 	{ BER_BVC("syncRefreshRequired"),		LDAP_SYNC_REFRESH_REQUIRED },
1232 
1233 	{ BER_BVC("noOperation"),			LDAP_X_NO_OPERATION },
1234 
1235 	{ BER_BVNULL,				0 }
1236 };
1237 
1238 slap_verbmasks *slap_ldap_response_code = slap_ldap_response_code_;
1239 
1240 int
1241 slap_ldap_response_code_register( struct berval *bv, int err )
1242 {
1243 	return slap_verbmask_register( slap_ldap_response_code_,
1244 		&slap_ldap_response_code, bv, err );
1245 }
1246 
1247 #ifdef HAVE_TLS
1248 static slap_verbmasks tlskey[] = {
1249 	{ BER_BVC("no"),	SB_TLS_OFF },
1250 	{ BER_BVC("yes"),	SB_TLS_ON },
1251 	{ BER_BVC("critical"),	SB_TLS_CRITICAL },
1252 	{ BER_BVNULL, 0 }
1253 };
1254 
1255 static slap_verbmasks crlkeys[] = {
1256 		{ BER_BVC("none"),	LDAP_OPT_X_TLS_CRL_NONE },
1257 		{ BER_BVC("peer"),	LDAP_OPT_X_TLS_CRL_PEER },
1258 		{ BER_BVC("all"),	LDAP_OPT_X_TLS_CRL_ALL },
1259 		{ BER_BVNULL, 0 }
1260 	};
1261 
1262 static slap_verbmasks vfykeys[] = {
1263 		{ BER_BVC("never"),	LDAP_OPT_X_TLS_NEVER },
1264 		{ BER_BVC("allow"),	LDAP_OPT_X_TLS_ALLOW },
1265 		{ BER_BVC("try"),	LDAP_OPT_X_TLS_TRY },
1266 		{ BER_BVC("demand"),	LDAP_OPT_X_TLS_DEMAND },
1267 		{ BER_BVC("hard"),	LDAP_OPT_X_TLS_HARD },
1268 		{ BER_BVC("true"),	LDAP_OPT_X_TLS_HARD },
1269 		{ BER_BVNULL, 0 }
1270 	};
1271 #endif
1272 
1273 static slap_verbmasks methkey[] = {
1274 	{ BER_BVC("none"),	LDAP_AUTH_NONE },
1275 	{ BER_BVC("simple"),	LDAP_AUTH_SIMPLE },
1276 #ifdef HAVE_CYRUS_SASL
1277 	{ BER_BVC("sasl"),	LDAP_AUTH_SASL },
1278 #endif
1279 	{ BER_BVNULL, 0 }
1280 };
1281 
1282 static slap_verbmasks versionkey[] = {
1283 	{ BER_BVC("2"),		LDAP_VERSION2 },
1284 	{ BER_BVC("3"),		LDAP_VERSION3 },
1285 	{ BER_BVNULL, 0 }
1286 };
1287 
1288 int
1289 slap_keepalive_parse(
1290 	struct berval *val,
1291 	void *bc,
1292 	slap_cf_aux_table *tab0,
1293 	const char *tabmsg,
1294 	int unparse )
1295 {
1296 	if ( unparse ) {
1297 		slap_keepalive *sk = (slap_keepalive *)bc;
1298 		int rc = snprintf( val->bv_val, val->bv_len, "%d:%d:%d",
1299 			sk->sk_idle, sk->sk_probes, sk->sk_interval );
1300 		if ( rc < 0 ) {
1301 			return -1;
1302 		}
1303 
1304 		if ( (unsigned)rc >= val->bv_len ) {
1305 			return -1;
1306 		}
1307 
1308 		val->bv_len = rc;
1309 
1310 	} else {
1311 		char *s = val->bv_val;
1312 		char *next;
1313 		slap_keepalive *sk = (slap_keepalive *)bc;
1314 		slap_keepalive sk2;
1315 
1316 		if ( s[0] == ':' ) {
1317 			sk2.sk_idle = 0;
1318 			s++;
1319 
1320 		} else {
1321 			sk2.sk_idle = strtol( s, &next, 10 );
1322 			if ( next == s || next[0] != ':' ) {
1323 				return -1;
1324 			}
1325 
1326 			if ( sk2.sk_idle < 0 ) {
1327 				return -1;
1328 			}
1329 
1330 			s = ++next;
1331 		}
1332 
1333 		if ( s[0] == ':' ) {
1334 			sk2.sk_probes = 0;
1335 			s++;
1336 
1337 		} else {
1338 			sk2.sk_probes = strtol( s, &next, 10 );
1339 			if ( next == s || next[0] != ':' ) {
1340 				return -1;
1341 			}
1342 
1343 			if ( sk2.sk_probes < 0 ) {
1344 				return -1;
1345 			}
1346 
1347 			s = ++next;
1348 		}
1349 
1350 		if ( s == '\0' ) {
1351 			sk2.sk_interval = 0;
1352 			s++;
1353 
1354 		} else {
1355 			sk2.sk_interval = strtol( s, &next, 10 );
1356 			if ( next == s || next[0] != '\0' ) {
1357 				return -1;
1358 			}
1359 
1360 			if ( sk2.sk_interval < 0 ) {
1361 				return -1;
1362 			}
1363 		}
1364 
1365 		*sk = sk2;
1366 
1367 		ber_memfree( val->bv_val );
1368 		BER_BVZERO( val );
1369 	}
1370 
1371 	return 0;
1372 }
1373 
1374 static int
1375 slap_sb_uri(
1376 	struct berval *val,
1377 	void *bcp,
1378 	slap_cf_aux_table *tab0,
1379 	const char *tabmsg,
1380 	int unparse )
1381 {
1382 	slap_bindconf *bc = bcp;
1383 	if ( unparse ) {
1384 		if ( bc->sb_uri.bv_len >= val->bv_len )
1385 			return -1;
1386 		val->bv_len = bc->sb_uri.bv_len;
1387 		AC_MEMCPY( val->bv_val, bc->sb_uri.bv_val, val->bv_len );
1388 	} else {
1389 		bc->sb_uri = *val;
1390 #ifdef HAVE_TLS
1391 		if ( ldap_is_ldaps_url( val->bv_val ))
1392 			bc->sb_tls_do_init = 1;
1393 #endif
1394 	}
1395 	return 0;
1396 }
1397 
1398 static slap_cf_aux_table bindkey[] = {
1399 	{ BER_BVC("uri="), 0, 'x', 1, slap_sb_uri },
1400 	{ BER_BVC("version="), offsetof(slap_bindconf, sb_version), 'i', 0, versionkey },
1401 	{ BER_BVC("bindmethod="), offsetof(slap_bindconf, sb_method), 'i', 0, methkey },
1402 	{ BER_BVC("timeout="), offsetof(slap_bindconf, sb_timeout_api), 'i', 0, NULL },
1403 	{ BER_BVC("network-timeout="), offsetof(slap_bindconf, sb_timeout_net), 'i', 0, NULL },
1404 	{ BER_BVC("binddn="), offsetof(slap_bindconf, sb_binddn), 'b', 1, (slap_verbmasks *)dnNormalize },
1405 	{ BER_BVC("credentials="), offsetof(slap_bindconf, sb_cred), 'b', 1, NULL },
1406 	{ BER_BVC("saslmech="), offsetof(slap_bindconf, sb_saslmech), 'b', 0, NULL },
1407 	{ BER_BVC("secprops="), offsetof(slap_bindconf, sb_secprops), 's', 0, NULL },
1408 	{ BER_BVC("realm="), offsetof(slap_bindconf, sb_realm), 'b', 0, NULL },
1409 	{ BER_BVC("authcID="), offsetof(slap_bindconf, sb_authcId), 'b', 1, NULL },
1410 	{ BER_BVC("authzID="), offsetof(slap_bindconf, sb_authzId), 'b', 1, (slap_verbmasks *)authzNormalize },
1411 	{ BER_BVC("keepalive="), offsetof(slap_bindconf, sb_keepalive), 'x', 0, (slap_verbmasks *)slap_keepalive_parse },
1412 #ifdef HAVE_TLS
1413 	/* NOTE: replace "13" with the actual index
1414 	 * of the first TLS-related line */
1415 #define aux_TLS (bindkey+13)	/* beginning of TLS keywords */
1416 
1417 	{ BER_BVC("starttls="), offsetof(slap_bindconf, sb_tls), 'i', 0, tlskey },
1418 	{ BER_BVC("tls_cert="), offsetof(slap_bindconf, sb_tls_cert), 's', 1, NULL },
1419 	{ BER_BVC("tls_key="), offsetof(slap_bindconf, sb_tls_key), 's', 1, NULL },
1420 	{ BER_BVC("tls_cacert="), offsetof(slap_bindconf, sb_tls_cacert), 's', 1, NULL },
1421 	{ BER_BVC("tls_cacertdir="), offsetof(slap_bindconf, sb_tls_cacertdir), 's', 1, NULL },
1422 	{ BER_BVC("tls_reqcert="), offsetof(slap_bindconf, sb_tls_reqcert), 's', 0, NULL },
1423 	{ BER_BVC("tls_cipher_suite="), offsetof(slap_bindconf, sb_tls_cipher_suite), 's', 0, NULL },
1424 	{ BER_BVC("tls_protocol_min="), offsetof(slap_bindconf, sb_tls_protocol_min), 's', 0, NULL },
1425 #ifdef HAVE_OPENSSL_CRL
1426 	{ BER_BVC("tls_crlcheck="), offsetof(slap_bindconf, sb_tls_crlcheck), 's', 0, NULL },
1427 #endif
1428 #endif
1429 	{ BER_BVNULL, 0, 0, 0, NULL }
1430 };
1431 
1432 /*
1433  * 's':	char *
1434  * 'b':	struct berval; if !NULL, normalize using ((slap_mr_normalize_func *)aux)
1435  * 'i':	int; if !NULL, compute using ((slap_verbmasks *)aux)
1436  * 'u':	unsigned
1437  * 'I':	long
1438  * 'U':	unsigned long
1439  */
1440 
1441 int
1442 slap_cf_aux_table_parse( const char *word, void *dst, slap_cf_aux_table *tab0, LDAP_CONST char *tabmsg )
1443 {
1444 	int rc = SLAP_CONF_UNKNOWN;
1445 	slap_cf_aux_table *tab;
1446 
1447 	for ( tab = tab0; !BER_BVISNULL( &tab->key ); tab++ ) {
1448 		if ( !strncasecmp( word, tab->key.bv_val, tab->key.bv_len ) ) {
1449 			char **cptr;
1450 			int *iptr, j;
1451 			unsigned *uptr;
1452 			long *lptr;
1453 			unsigned long *ulptr;
1454 			struct berval *bptr;
1455 			const char *val = word + tab->key.bv_len;
1456 
1457 			switch ( tab->type ) {
1458 			case 's':
1459 				cptr = (char **)((char *)dst + tab->off);
1460 				*cptr = ch_strdup( val );
1461 				rc = 0;
1462 				break;
1463 
1464 			case 'b':
1465 				bptr = (struct berval *)((char *)dst + tab->off);
1466 				if ( tab->aux != NULL ) {
1467 					struct berval	dn;
1468 					slap_mr_normalize_func *normalize = (slap_mr_normalize_func *)tab->aux;
1469 
1470 					ber_str2bv( val, 0, 0, &dn );
1471 					rc = normalize( 0, NULL, NULL, &dn, bptr, NULL );
1472 
1473 				} else {
1474 					ber_str2bv( val, 0, 1, bptr );
1475 					rc = 0;
1476 				}
1477 				break;
1478 
1479 			case 'i':
1480 				iptr = (int *)((char *)dst + tab->off);
1481 
1482 				if ( tab->aux != NULL ) {
1483 					slap_verbmasks *aux = (slap_verbmasks *)tab->aux;
1484 
1485 					assert( aux != NULL );
1486 
1487 					rc = 1;
1488 					for ( j = 0; !BER_BVISNULL( &aux[j].word ); j++ ) {
1489 						if ( !strcasecmp( val, aux[j].word.bv_val ) ) {
1490 							*iptr = aux[j].mask;
1491 							rc = 0;
1492 							break;
1493 						}
1494 					}
1495 
1496 				} else {
1497 					rc = lutil_atoix( iptr, val, 0 );
1498 				}
1499 				break;
1500 
1501 			case 'u':
1502 				uptr = (unsigned *)((char *)dst + tab->off);
1503 
1504 				rc = lutil_atoux( uptr, val, 0 );
1505 				break;
1506 
1507 			case 'I':
1508 				lptr = (long *)((char *)dst + tab->off);
1509 
1510 				rc = lutil_atolx( lptr, val, 0 );
1511 				break;
1512 
1513 			case 'U':
1514 				ulptr = (unsigned long *)((char *)dst + tab->off);
1515 
1516 				rc = lutil_atoulx( ulptr, val, 0 );
1517 				break;
1518 
1519 			case 'x':
1520 				if ( tab->aux != NULL ) {
1521 					struct berval value;
1522 					slap_cf_aux_table_parse_x *func = (slap_cf_aux_table_parse_x *)tab->aux;
1523 
1524 					ber_str2bv( val, 0, 1, &value );
1525 
1526 					rc = func( &value, (void *)((char *)dst + tab->off), tab, tabmsg, 0 );
1527 
1528 				} else {
1529 					rc = 1;
1530 				}
1531 				break;
1532 			}
1533 
1534 			if ( rc ) {
1535 				Debug( LDAP_DEBUG_ANY, "invalid %s value %s\n",
1536 					tabmsg, word, 0 );
1537 			}
1538 
1539 			return rc;
1540 		}
1541 	}
1542 
1543 	return rc;
1544 }
1545 
1546 int
1547 slap_cf_aux_table_unparse( void *src, struct berval *bv, slap_cf_aux_table *tab0 )
1548 {
1549 	char buf[AC_LINE_MAX], *ptr;
1550 	slap_cf_aux_table *tab;
1551 	struct berval tmp;
1552 
1553 	ptr = buf;
1554 	for (tab = tab0; !BER_BVISNULL(&tab->key); tab++ ) {
1555 		char **cptr;
1556 		int *iptr, i;
1557 		unsigned *uptr;
1558 		long *lptr;
1559 		unsigned long *ulptr;
1560 		struct berval *bptr;
1561 
1562 		cptr = (char **)((char *)src + tab->off);
1563 
1564 		switch ( tab->type ) {
1565 		case 'b':
1566 			bptr = (struct berval *)((char *)src + tab->off);
1567 			cptr = &bptr->bv_val;
1568 
1569 		case 's':
1570 			if ( *cptr ) {
1571 				*ptr++ = ' ';
1572 				ptr = lutil_strcopy( ptr, tab->key.bv_val );
1573 				if ( tab->quote ) *ptr++ = '"';
1574 				ptr = lutil_strcopy( ptr, *cptr );
1575 				if ( tab->quote ) *ptr++ = '"';
1576 			}
1577 			break;
1578 
1579 		case 'i':
1580 			iptr = (int *)((char *)src + tab->off);
1581 
1582 			if ( tab->aux != NULL ) {
1583 				slap_verbmasks *aux = (slap_verbmasks *)tab->aux;
1584 
1585 				for ( i = 0; !BER_BVISNULL( &aux[i].word ); i++ ) {
1586 					if ( *iptr == aux[i].mask ) {
1587 						*ptr++ = ' ';
1588 						ptr = lutil_strcopy( ptr, tab->key.bv_val );
1589 						ptr = lutil_strcopy( ptr, aux[i].word.bv_val );
1590 						break;
1591 					}
1592 				}
1593 
1594 			} else {
1595 				*ptr++ = ' ';
1596 				ptr = lutil_strcopy( ptr, tab->key.bv_val );
1597 				ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), "%d", *iptr );
1598 			}
1599 			break;
1600 
1601 		case 'u':
1602 			uptr = (unsigned *)((char *)src + tab->off);
1603 			*ptr++ = ' ';
1604 			ptr = lutil_strcopy( ptr, tab->key.bv_val );
1605 			ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), "%u", *uptr );
1606 			break;
1607 
1608 		case 'I':
1609 			lptr = (long *)((char *)src + tab->off);
1610 			*ptr++ = ' ';
1611 			ptr = lutil_strcopy( ptr, tab->key.bv_val );
1612 			ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), "%ld", *lptr );
1613 			break;
1614 
1615 		case 'U':
1616 			ulptr = (unsigned long *)((char *)src + tab->off);
1617 			*ptr++ = ' ';
1618 			ptr = lutil_strcopy( ptr, tab->key.bv_val );
1619 			ptr += snprintf( ptr, sizeof( buf ) - ( ptr - buf ), "%lu", *ulptr );
1620 			break;
1621 
1622 		case 'x':
1623 			{
1624 				char *saveptr=ptr;
1625 				*ptr++ = ' ';
1626 				ptr = lutil_strcopy( ptr, tab->key.bv_val );
1627 				if ( tab->quote ) *ptr++ = '"';
1628 				if ( tab->aux != NULL ) {
1629 					struct berval value;
1630 					slap_cf_aux_table_parse_x *func = (slap_cf_aux_table_parse_x *)tab->aux;
1631 					int rc;
1632 
1633 					value.bv_val = ptr;
1634 					value.bv_len = buf + sizeof( buf ) - ptr;
1635 
1636 					rc = func( &value, (void *)((char *)src + tab->off), tab, "(unparse)", 1 );
1637 					if ( rc == 0 ) {
1638 						if (value.bv_len) {
1639 							ptr += value.bv_len;
1640 						} else {
1641 							ptr = saveptr;
1642 							break;
1643 						}
1644 					}
1645 				}
1646 				if ( tab->quote ) *ptr++ = '"';
1647 			}
1648 			break;
1649 
1650 		default:
1651 			assert( 0 );
1652 		}
1653 	}
1654 	tmp.bv_val = buf;
1655 	tmp.bv_len = ptr - buf;
1656 	ber_dupbv( bv, &tmp );
1657 	return 0;
1658 }
1659 
1660 int
1661 slap_tls_get_config( LDAP *ld, int opt, char **val )
1662 {
1663 #ifdef HAVE_TLS
1664 	slap_verbmasks *keys;
1665 	int i, ival;
1666 
1667 	*val = NULL;
1668 	switch( opt ) {
1669 	case LDAP_OPT_X_TLS_CRLCHECK:
1670 		keys = crlkeys;
1671 		break;
1672 	case LDAP_OPT_X_TLS_REQUIRE_CERT:
1673 		keys = vfykeys;
1674 		break;
1675 	case LDAP_OPT_X_TLS_PROTOCOL_MIN: {
1676 		char buf[8];
1677 		ldap_pvt_tls_get_option( ld, opt, &ival );
1678 		snprintf( buf, sizeof( buf ), "%d.%d",
1679 			( ival >> 8 ) & 0xff, ival & 0xff );
1680 		*val = ch_strdup( buf );
1681 		return 0;
1682 		}
1683 	default:
1684 		return -1;
1685 	}
1686 	ldap_pvt_tls_get_option( ld, opt, &ival );
1687 	for (i=0; !BER_BVISNULL(&keys[i].word); i++) {
1688 		if (keys[i].mask == ival) {
1689 			*val = ch_strdup( keys[i].word.bv_val );
1690 			return 0;
1691 		}
1692 	}
1693 #endif
1694 	return -1;
1695 }
1696 
1697 int
1698 bindconf_tls_parse( const char *word, slap_bindconf *bc )
1699 {
1700 #ifdef HAVE_TLS
1701 	if ( slap_cf_aux_table_parse( word, bc, aux_TLS, "tls config" ) == 0 ) {
1702 		bc->sb_tls_do_init = 1;
1703 		return 0;
1704 	}
1705 #endif
1706 	return -1;
1707 }
1708 
1709 int
1710 bindconf_tls_unparse( slap_bindconf *bc, struct berval *bv )
1711 {
1712 #ifdef HAVE_TLS
1713 	return slap_cf_aux_table_unparse( bc, bv, aux_TLS );
1714 #endif
1715 	return -1;
1716 }
1717 
1718 int
1719 bindconf_parse( const char *word, slap_bindconf *bc )
1720 {
1721 #ifdef HAVE_TLS
1722 	/* Detect TLS config changes explicitly */
1723 	if ( bindconf_tls_parse( word, bc ) == 0 ) {
1724 		return 0;
1725 	}
1726 #endif
1727 	return slap_cf_aux_table_parse( word, bc, bindkey, "bind config" );
1728 }
1729 
1730 int
1731 bindconf_unparse( slap_bindconf *bc, struct berval *bv )
1732 {
1733 	return slap_cf_aux_table_unparse( bc, bv, bindkey );
1734 }
1735 
1736 void bindconf_free( slap_bindconf *bc ) {
1737 	if ( !BER_BVISNULL( &bc->sb_uri ) ) {
1738 		ch_free( bc->sb_uri.bv_val );
1739 		BER_BVZERO( &bc->sb_uri );
1740 	}
1741 	if ( !BER_BVISNULL( &bc->sb_binddn ) ) {
1742 		ch_free( bc->sb_binddn.bv_val );
1743 		BER_BVZERO( &bc->sb_binddn );
1744 	}
1745 	if ( !BER_BVISNULL( &bc->sb_cred ) ) {
1746 		ch_free( bc->sb_cred.bv_val );
1747 		BER_BVZERO( &bc->sb_cred );
1748 	}
1749 	if ( !BER_BVISNULL( &bc->sb_saslmech ) ) {
1750 		ch_free( bc->sb_saslmech.bv_val );
1751 		BER_BVZERO( &bc->sb_saslmech );
1752 	}
1753 	if ( bc->sb_secprops ) {
1754 		ch_free( bc->sb_secprops );
1755 		bc->sb_secprops = NULL;
1756 	}
1757 	if ( !BER_BVISNULL( &bc->sb_realm ) ) {
1758 		ch_free( bc->sb_realm.bv_val );
1759 		BER_BVZERO( &bc->sb_realm );
1760 	}
1761 	if ( !BER_BVISNULL( &bc->sb_authcId ) ) {
1762 		ch_free( bc->sb_authcId.bv_val );
1763 		BER_BVZERO( &bc->sb_authcId );
1764 	}
1765 	if ( !BER_BVISNULL( &bc->sb_authzId ) ) {
1766 		ch_free( bc->sb_authzId.bv_val );
1767 		BER_BVZERO( &bc->sb_authzId );
1768 	}
1769 #ifdef HAVE_TLS
1770 	if ( bc->sb_tls_cert ) {
1771 		ch_free( bc->sb_tls_cert );
1772 		bc->sb_tls_cert = NULL;
1773 	}
1774 	if ( bc->sb_tls_key ) {
1775 		ch_free( bc->sb_tls_key );
1776 		bc->sb_tls_key = NULL;
1777 	}
1778 	if ( bc->sb_tls_cacert ) {
1779 		ch_free( bc->sb_tls_cacert );
1780 		bc->sb_tls_cacert = NULL;
1781 	}
1782 	if ( bc->sb_tls_cacertdir ) {
1783 		ch_free( bc->sb_tls_cacertdir );
1784 		bc->sb_tls_cacertdir = NULL;
1785 	}
1786 	if ( bc->sb_tls_reqcert ) {
1787 		ch_free( bc->sb_tls_reqcert );
1788 		bc->sb_tls_reqcert = NULL;
1789 	}
1790 	if ( bc->sb_tls_cipher_suite ) {
1791 		ch_free( bc->sb_tls_cipher_suite );
1792 		bc->sb_tls_cipher_suite = NULL;
1793 	}
1794 	if ( bc->sb_tls_protocol_min ) {
1795 		ch_free( bc->sb_tls_protocol_min );
1796 		bc->sb_tls_protocol_min = NULL;
1797 	}
1798 #ifdef HAVE_OPENSSL_CRL
1799 	if ( bc->sb_tls_crlcheck ) {
1800 		ch_free( bc->sb_tls_crlcheck );
1801 		bc->sb_tls_crlcheck = NULL;
1802 	}
1803 #endif
1804 	if ( bc->sb_tls_ctx ) {
1805 		ldap_pvt_tls_ctx_free( bc->sb_tls_ctx );
1806 		bc->sb_tls_ctx = NULL;
1807 	}
1808 #endif
1809 }
1810 
1811 void
1812 bindconf_tls_defaults( slap_bindconf *bc )
1813 {
1814 #ifdef HAVE_TLS
1815 	if ( bc->sb_tls_do_init ) {
1816 		if ( !bc->sb_tls_cacert )
1817 			ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CACERTFILE,
1818 				&bc->sb_tls_cacert );
1819 		if ( !bc->sb_tls_cacertdir )
1820 			ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CACERTDIR,
1821 				&bc->sb_tls_cacertdir );
1822 		if ( !bc->sb_tls_cert )
1823 			ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CERTFILE,
1824 				&bc->sb_tls_cert );
1825 		if ( !bc->sb_tls_key )
1826 			ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_KEYFILE,
1827 				&bc->sb_tls_key );
1828 		if ( !bc->sb_tls_cipher_suite )
1829 			ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CIPHER_SUITE,
1830 				&bc->sb_tls_cipher_suite );
1831 		if ( !bc->sb_tls_reqcert )
1832 			bc->sb_tls_reqcert = ch_strdup("demand");
1833 #ifdef HAVE_OPENSSL_CRL
1834 		if ( !bc->sb_tls_crlcheck )
1835 			slap_tls_get_config( slap_tls_ld, LDAP_OPT_X_TLS_CRLCHECK,
1836 				&bc->sb_tls_crlcheck );
1837 #endif
1838 	}
1839 #endif
1840 }
1841 
1842 #ifdef HAVE_TLS
1843 static struct {
1844 	const char *key;
1845 	size_t offset;
1846 	int opt;
1847 } bindtlsopts[] = {
1848 	{ "tls_cert", offsetof(slap_bindconf, sb_tls_cert), LDAP_OPT_X_TLS_CERTFILE },
1849 	{ "tls_key", offsetof(slap_bindconf, sb_tls_key), LDAP_OPT_X_TLS_KEYFILE },
1850 	{ "tls_cacert", offsetof(slap_bindconf, sb_tls_cacert), LDAP_OPT_X_TLS_CACERTFILE },
1851 	{ "tls_cacertdir", offsetof(slap_bindconf, sb_tls_cacertdir), LDAP_OPT_X_TLS_CACERTDIR },
1852 	{ "tls_cipher_suite", offsetof(slap_bindconf, sb_tls_cipher_suite), LDAP_OPT_X_TLS_CIPHER_SUITE },
1853 	{ "tls_protocol_min", offsetof(slap_bindconf, sb_tls_protocol_min), LDAP_OPT_X_TLS_PROTOCOL_MIN },
1854 	{0, 0}
1855 };
1856 
1857 int bindconf_tls_set( slap_bindconf *bc, LDAP *ld )
1858 {
1859 	int i, rc, newctx = 0, res = 0;
1860 	char *ptr = (char *)bc, **word;
1861 
1862 	bc->sb_tls_do_init = 0;
1863 
1864 	for (i=0; bindtlsopts[i].opt; i++) {
1865 		word = (char **)(ptr + bindtlsopts[i].offset);
1866 		if ( *word ) {
1867 			rc = ldap_set_option( ld, bindtlsopts[i].opt, *word );
1868 			if ( rc ) {
1869 				Debug( LDAP_DEBUG_ANY,
1870 					"bindconf_tls_set: failed to set %s to %s\n",
1871 						bindtlsopts[i].key, *word, 0 );
1872 				res = -1;
1873 			} else
1874 				newctx = 1;
1875 		}
1876 	}
1877 	if ( bc->sb_tls_reqcert ) {
1878 		rc = ldap_int_tls_config( ld, LDAP_OPT_X_TLS_REQUIRE_CERT,
1879 			bc->sb_tls_reqcert );
1880 		if ( rc ) {
1881 			Debug( LDAP_DEBUG_ANY,
1882 				"bindconf_tls_set: failed to set tls_reqcert to %s\n",
1883 					bc->sb_tls_reqcert, 0, 0 );
1884 			res = -1;
1885 		} else
1886 			newctx = 1;
1887 	}
1888 	if ( bc->sb_tls_protocol_min ) {
1889 		rc = ldap_int_tls_config( ld, LDAP_OPT_X_TLS_PROTOCOL_MIN,
1890 			bc->sb_tls_protocol_min );
1891 		if ( rc ) {
1892 			Debug( LDAP_DEBUG_ANY,
1893 				"bindconf_tls_set: failed to set tls_protocol_min to %s\n",
1894 					bc->sb_tls_protocol_min, 0, 0 );
1895 			res = -1;
1896 		} else
1897 			newctx = 1;
1898 	}
1899 #ifdef HAVE_OPENSSL_CRL
1900 	if ( bc->sb_tls_crlcheck ) {
1901 		rc = ldap_int_tls_config( ld, LDAP_OPT_X_TLS_CRLCHECK,
1902 			bc->sb_tls_crlcheck );
1903 		if ( rc ) {
1904 			Debug( LDAP_DEBUG_ANY,
1905 				"bindconf_tls_set: failed to set tls_crlcheck to %s\n",
1906 					bc->sb_tls_crlcheck, 0, 0 );
1907 			res = -1;
1908 		} else
1909 			newctx = 1;
1910 	}
1911 #endif
1912 	if ( newctx ) {
1913 		int opt = 0;
1914 
1915 		if ( bc->sb_tls_ctx ) {
1916 			ldap_pvt_tls_ctx_free( bc->sb_tls_ctx );
1917 			bc->sb_tls_ctx = NULL;
1918 		}
1919 		rc = ldap_set_option( ld, LDAP_OPT_X_TLS_NEWCTX, &opt );
1920 		if ( rc )
1921 			res = rc;
1922 		else
1923 			ldap_get_option( ld, LDAP_OPT_X_TLS_CTX, &bc->sb_tls_ctx );
1924 	}
1925 
1926 	return res;
1927 }
1928 #endif
1929 
1930 /*
1931  * set connection keepalive options
1932  */
1933 void
1934 slap_client_keepalive(LDAP *ld, slap_keepalive *sk)
1935 {
1936 	if (!sk) return;
1937 
1938 	if ( sk->sk_idle ) {
1939 		ldap_set_option( ld, LDAP_OPT_X_KEEPALIVE_IDLE, &sk->sk_idle );
1940 	}
1941 
1942 	if ( sk->sk_probes ) {
1943 		ldap_set_option( ld, LDAP_OPT_X_KEEPALIVE_PROBES, &sk->sk_probes );
1944 	}
1945 
1946 	if ( sk->sk_interval ) {
1947 		ldap_set_option( ld, LDAP_OPT_X_KEEPALIVE_INTERVAL, &sk->sk_interval );
1948 	}
1949 
1950 	return;
1951 }
1952 
1953 /*
1954  * connect to a client using the bindconf data
1955  * note: should move "version" into bindconf...
1956  */
1957 int
1958 slap_client_connect( LDAP **ldp, slap_bindconf *sb )
1959 {
1960 	LDAP		*ld = NULL;
1961 	int		rc;
1962 	struct timeval tv;
1963 
1964 	/* Init connection to master */
1965 	rc = ldap_initialize( &ld, sb->sb_uri.bv_val );
1966 	if ( rc != LDAP_SUCCESS ) {
1967 		Debug( LDAP_DEBUG_ANY,
1968 			"slap_client_connect: "
1969 			"ldap_initialize(%s) failed (%d)\n",
1970 			sb->sb_uri.bv_val, rc, 0 );
1971 		return rc;
1972 	}
1973 
1974 	if ( sb->sb_version != 0 ) {
1975 		ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION,
1976 			(const void *)&sb->sb_version );
1977 	}
1978 
1979 	if ( sb->sb_timeout_api ) {
1980 		tv.tv_sec = sb->sb_timeout_api;
1981 		tv.tv_usec = 0;
1982 		ldap_set_option( ld, LDAP_OPT_TIMEOUT, &tv );
1983 	}
1984 
1985 	if ( sb->sb_timeout_net ) {
1986 		tv.tv_sec = sb->sb_timeout_net;
1987 		tv.tv_usec = 0;
1988 		ldap_set_option( ld, LDAP_OPT_NETWORK_TIMEOUT, &tv );
1989 	}
1990 
1991 	/* setting network keepalive options */
1992 	slap_client_keepalive(ld, &sb->sb_keepalive);
1993 
1994 #ifdef HAVE_TLS
1995 	if ( sb->sb_tls_do_init ) {
1996 		rc = bindconf_tls_set( sb, ld );
1997 
1998 	} else if ( sb->sb_tls_ctx ) {
1999 		rc = ldap_set_option( ld, LDAP_OPT_X_TLS_CTX,
2000 			sb->sb_tls_ctx );
2001 	}
2002 
2003 	if ( rc ) {
2004 		Debug( LDAP_DEBUG_ANY,
2005 			"slap_client_connect: "
2006 			"URI=%s TLS context initialization failed (%d)\n",
2007 			sb->sb_uri.bv_val, rc, 0 );
2008 		return rc;
2009 	}
2010 #endif
2011 
2012 	/* Bind */
2013 	if ( sb->sb_tls ) {
2014 		rc = ldap_start_tls_s( ld, NULL, NULL );
2015 		if ( rc != LDAP_SUCCESS ) {
2016 			Debug( LDAP_DEBUG_ANY,
2017 				"slap_client_connect: URI=%s "
2018 				"%s, ldap_start_tls failed (%d)\n",
2019 				sb->sb_uri.bv_val,
2020 				sb->sb_tls == SB_TLS_CRITICAL ?
2021 					"Error" : "Warning",
2022 				rc );
2023 			if ( sb->sb_tls == SB_TLS_CRITICAL ) {
2024 				goto done;
2025 			}
2026 		}
2027 	}
2028 
2029 	if ( sb->sb_method == LDAP_AUTH_SASL ) {
2030 #ifdef HAVE_CYRUS_SASL
2031 		void *defaults;
2032 
2033 		if ( sb->sb_secprops != NULL ) {
2034 			rc = ldap_set_option( ld,
2035 				LDAP_OPT_X_SASL_SECPROPS, sb->sb_secprops);
2036 
2037 			if( rc != LDAP_OPT_SUCCESS ) {
2038 				Debug( LDAP_DEBUG_ANY,
2039 					"slap_client_connect: "
2040 					"error, ldap_set_option "
2041 					"(%s,SECPROPS,\"%s\") failed!\n",
2042 					sb->sb_uri.bv_val, sb->sb_secprops, 0 );
2043 				goto done;
2044 			}
2045 		}
2046 
2047 		defaults = lutil_sasl_defaults( ld,
2048 			sb->sb_saslmech.bv_val,
2049 			sb->sb_realm.bv_val,
2050 			sb->sb_authcId.bv_val,
2051 			sb->sb_cred.bv_val,
2052 			sb->sb_authzId.bv_val );
2053 		if ( defaults == NULL ) {
2054 			rc = LDAP_OTHER;
2055 			goto done;
2056 		}
2057 
2058 		rc = ldap_sasl_interactive_bind_s( ld,
2059 				sb->sb_binddn.bv_val,
2060 				sb->sb_saslmech.bv_val,
2061 				NULL, NULL,
2062 				LDAP_SASL_QUIET,
2063 				lutil_sasl_interact,
2064 				defaults );
2065 
2066 		lutil_sasl_freedefs( defaults );
2067 
2068 		/* FIXME: different error behaviors according to
2069 		 *	1) return code
2070 		 *	2) on err policy : exit, retry, backoff ...
2071 		 */
2072 		if ( rc != LDAP_SUCCESS ) {
2073 			static struct berval bv_GSSAPI = BER_BVC( "GSSAPI" );
2074 
2075 			Debug( LDAP_DEBUG_ANY, "slap_client_connect: URI=%s "
2076 				"ldap_sasl_interactive_bind_s failed (%d)\n",
2077 				sb->sb_uri.bv_val, rc, 0 );
2078 
2079 			/* FIXME (see above comment) */
2080 			/* if Kerberos credentials cache is not active, retry */
2081 			if ( ber_bvcmp( &sb->sb_saslmech, &bv_GSSAPI ) == 0 &&
2082 				rc == LDAP_LOCAL_ERROR )
2083 			{
2084 				rc = LDAP_SERVER_DOWN;
2085 			}
2086 
2087 			goto done;
2088 		}
2089 #else /* HAVE_CYRUS_SASL */
2090 		/* Should never get here, we trapped this at config time */
2091 		assert(0);
2092 		Debug( LDAP_DEBUG_SYNC, "not compiled with SASL support\n", 0, 0, 0 );
2093 		rc = LDAP_OTHER;
2094 		goto done;
2095 #endif
2096 
2097 	} else if ( sb->sb_method == LDAP_AUTH_SIMPLE ) {
2098 		rc = ldap_sasl_bind_s( ld,
2099 			sb->sb_binddn.bv_val, LDAP_SASL_SIMPLE,
2100 			&sb->sb_cred, NULL, NULL, NULL );
2101 		if ( rc != LDAP_SUCCESS ) {
2102 			Debug( LDAP_DEBUG_ANY, "slap_client_connect: "
2103 				"URI=%s DN=\"%s\" "
2104 				"ldap_sasl_bind_s failed (%d)\n",
2105 				sb->sb_uri.bv_val, sb->sb_binddn.bv_val, rc );
2106 			goto done;
2107 		}
2108 	}
2109 
2110 done:;
2111 	if ( rc ) {
2112 		if ( ld ) {
2113 			ldap_unbind_ext( ld, NULL, NULL );
2114 			*ldp = NULL;
2115 		}
2116 
2117 	} else {
2118 		*ldp = ld;
2119 	}
2120 
2121 	return rc;
2122 }
2123 
2124 /* -------------------------------------- */
2125 
2126 
2127 static char *
2128 strtok_quote( char *line, char *sep, char **quote_ptr )
2129 {
2130 	int		inquote;
2131 	char		*tmp;
2132 	static char	*next;
2133 
2134 	*quote_ptr = NULL;
2135 	if ( line != NULL ) {
2136 		next = line;
2137 	}
2138 	while ( *next && strchr( sep, *next ) ) {
2139 		next++;
2140 	}
2141 
2142 	if ( *next == '\0' ) {
2143 		next = NULL;
2144 		return( NULL );
2145 	}
2146 	tmp = next;
2147 
2148 	for ( inquote = 0; *next; ) {
2149 		switch ( *next ) {
2150 		case '"':
2151 			if ( inquote ) {
2152 				inquote = 0;
2153 			} else {
2154 				inquote = 1;
2155 			}
2156 			AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 );
2157 			break;
2158 
2159 		case '\\':
2160 			if ( next[1] )
2161 				AC_MEMCPY( next,
2162 					    next + 1, strlen( next + 1 ) + 1 );
2163 			next++;		/* dont parse the escaped character */
2164 			break;
2165 
2166 		default:
2167 			if ( ! inquote ) {
2168 				if ( strchr( sep, *next ) != NULL ) {
2169 					*quote_ptr = next;
2170 					*next++ = '\0';
2171 					return( tmp );
2172 				}
2173 			}
2174 			next++;
2175 			break;
2176 		}
2177 	}
2178 
2179 	return( tmp );
2180 }
2181 
2182 static char	buf[AC_LINE_MAX];
2183 static char	*line;
2184 static size_t lmax, lcur;
2185 
2186 #define CATLINE( buf ) \
2187 	do { \
2188 		size_t len = strlen( buf ); \
2189 		while ( lcur + len + 1 > lmax ) { \
2190 			lmax += AC_LINE_MAX; \
2191 			line = (char *) ch_realloc( line, lmax ); \
2192 		} \
2193 		strcpy( line + lcur, buf ); \
2194 		lcur += len; \
2195 	} while( 0 )
2196 
2197 static void
2198 fp_getline_init(ConfigArgs *c) {
2199 	c->lineno = -1;
2200 	buf[0] = '\0';
2201 }
2202 
2203 static int
2204 fp_getline( FILE *fp, ConfigArgs *c )
2205 {
2206 	char	*p;
2207 
2208 	lcur = 0;
2209 	CATLINE(buf);
2210 	c->lineno++;
2211 
2212 	/* avoid stack of bufs */
2213 	if ( strncasecmp( line, "include", STRLENOF( "include" ) ) == 0 ) {
2214 		buf[0] = '\0';
2215 		c->line = line;
2216 		return(1);
2217 	}
2218 
2219 	while ( fgets( buf, sizeof( buf ), fp ) ) {
2220 		p = strchr( buf, '\n' );
2221 		if ( p ) {
2222 			if ( p > buf && p[-1] == '\r' ) {
2223 				--p;
2224 			}
2225 			*p = '\0';
2226 		}
2227 		/* XXX ugly */
2228 		c->line = line;
2229 		if ( line[0]
2230 				&& ( p = line + strlen( line ) - 1 )[0] == '\\'
2231 				&& p[-1] != '\\' )
2232 		{
2233 			p[0] = '\0';
2234 			lcur--;
2235 
2236 		} else {
2237 			if ( !isspace( (unsigned char)buf[0] ) ) {
2238 				return(1);
2239 			}
2240 			buf[0] = ' ';
2241 		}
2242 		CATLINE(buf);
2243 		c->lineno++;
2244 	}
2245 
2246 	buf[0] = '\0';
2247 	c->line = line;
2248 	return(line[0] ? 1 : 0);
2249 }
2250 
2251 int
2252 config_fp_parse_line(ConfigArgs *c)
2253 {
2254 	char *token;
2255 	static char *const hide[] = {
2256 		"rootpw", "replica", "syncrepl",  /* in slapd */
2257 		"acl-bind", "acl-method", "idassert-bind",  /* in back-ldap */
2258 		"acl-passwd", "bindpw",  /* in back-<ldap/meta> */
2259 		"pseudorootpw",  /* in back-meta */
2260 		"dbpasswd",  /* in back-sql */
2261 		NULL
2262 	};
2263 	char *quote_ptr;
2264 	int i = (int)(sizeof(hide)/sizeof(hide[0])) - 1;
2265 
2266 	c->tline = ch_strdup(c->line);
2267 	token = strtok_quote(c->tline, " \t", &quote_ptr);
2268 
2269 	if(token) for(i = 0; hide[i]; i++) if(!strcasecmp(token, hide[i])) break;
2270 	if(quote_ptr) *quote_ptr = ' ';
2271 	Debug(LDAP_DEBUG_CONFIG, "line %d (%s%s)\n", c->lineno,
2272 		hide[i] ? hide[i] : c->line, hide[i] ? " ***" : "");
2273 	if(quote_ptr) *quote_ptr = '\0';
2274 
2275 	for(;; token = strtok_quote(NULL, " \t", &quote_ptr)) {
2276 		if(c->argc >= c->argv_size) {
2277 			char **tmp;
2278 			tmp = ch_realloc(c->argv, (c->argv_size + ARGS_STEP) * sizeof(*c->argv));
2279 			if(!tmp) {
2280 				Debug(LDAP_DEBUG_ANY, "line %d: out of memory\n", c->lineno, 0, 0);
2281 				return -1;
2282 			}
2283 			c->argv = tmp;
2284 			c->argv_size += ARGS_STEP;
2285 		}
2286 		if(token == NULL)
2287 			break;
2288 		c->argv[c->argc++] = token;
2289 	}
2290 	c->argv[c->argc] = NULL;
2291 	return(0);
2292 }
2293 
2294 void
2295 config_destroy( )
2296 {
2297 	ucdata_unload( UCDATA_ALL );
2298 	if ( frontendDB ) {
2299 		/* NOTE: in case of early exit, frontendDB can be NULL */
2300 		if ( frontendDB->be_schemandn.bv_val )
2301 			free( frontendDB->be_schemandn.bv_val );
2302 		if ( frontendDB->be_schemadn.bv_val )
2303 			free( frontendDB->be_schemadn.bv_val );
2304 		if ( frontendDB->be_acl )
2305 			acl_destroy( frontendDB->be_acl );
2306 	}
2307 	free( line );
2308 	if ( slapd_args_file )
2309 		free ( slapd_args_file );
2310 	if ( slapd_pid_file )
2311 		free ( slapd_pid_file );
2312 	if ( default_passwd_hash )
2313 		ldap_charray_free( default_passwd_hash );
2314 }
2315 
2316 char **
2317 slap_str2clist( char ***out, char *in, const char *brkstr )
2318 {
2319 	char	*str;
2320 	char	*s;
2321 	char	*lasts;
2322 	int	i, j;
2323 	char	**new;
2324 
2325 	/* find last element in list */
2326 	for (i = 0; *out && (*out)[i]; i++);
2327 
2328 	/* protect the input string from strtok */
2329 	str = ch_strdup( in );
2330 
2331 	if ( *str == '\0' ) {
2332 		free( str );
2333 		return( *out );
2334 	}
2335 
2336 	/* Count words in string */
2337 	j=1;
2338 	for ( s = str; *s; s++ ) {
2339 		if ( strchr( brkstr, *s ) != NULL ) {
2340 			j++;
2341 		}
2342 	}
2343 
2344 	*out = ch_realloc( *out, ( i + j + 1 ) * sizeof( char * ) );
2345 	new = *out + i;
2346 	for ( s = ldap_pvt_strtok( str, brkstr, &lasts );
2347 		s != NULL;
2348 		s = ldap_pvt_strtok( NULL, brkstr, &lasts ) )
2349 	{
2350 		*new = ch_strdup( s );
2351 		new++;
2352 	}
2353 
2354 	*new = NULL;
2355 	free( str );
2356 	return( *out );
2357 }
2358 
2359 int config_generic_wrapper( Backend *be, const char *fname, int lineno,
2360 	int argc, char **argv )
2361 {
2362 	ConfigArgs c = { 0 };
2363 	ConfigTable *ct;
2364 	int rc;
2365 
2366 	c.be = be;
2367 	c.fname = fname;
2368 	c.lineno = lineno;
2369 	c.argc = argc;
2370 	c.argv = argv;
2371 	c.valx = -1;
2372 	c.line = line;
2373 	c.op = SLAP_CONFIG_ADD;
2374 	snprintf( c.log, sizeof( c.log ), "%s: line %d", fname, lineno );
2375 
2376 	rc = SLAP_CONF_UNKNOWN;
2377 	ct = config_find_keyword( be->be_cf_ocs->co_table, &c );
2378 	if ( ct ) {
2379 		c.table = be->be_cf_ocs->co_type;
2380 		rc = config_add_vals( ct, &c );
2381 	}
2382 	return rc;
2383 }
2384 
2385 /* See if the given URL (in plain and parsed form) matches
2386  * any of the server's listener addresses. Return matching
2387  * Listener or NULL for no match.
2388  */
2389 Listener *config_check_my_url( const char *url, LDAPURLDesc *lud )
2390 {
2391 	Listener **l = slapd_get_listeners();
2392 	int i, isMe;
2393 
2394 	/* Try a straight compare with Listener strings */
2395 	for ( i=0; l && l[i]; i++ ) {
2396 		if ( !strcasecmp( url, l[i]->sl_url.bv_val )) {
2397 			return l[i];
2398 		}
2399 	}
2400 
2401 	isMe = 0;
2402 	/* If hostname is empty, or is localhost, or matches
2403 	 * our hostname, this url refers to this host.
2404 	 * Compare it against listeners and ports.
2405 	 */
2406 	if ( !lud->lud_host || !lud->lud_host[0] ||
2407 		!strncasecmp("localhost", lud->lud_host,
2408 			STRLENOF("localhost")) ||
2409 		!strcasecmp( global_host, lud->lud_host )) {
2410 
2411 		for ( i=0; l && l[i]; i++ ) {
2412 			LDAPURLDesc *lu2;
2413 			ldap_url_parse( l[i]->sl_url.bv_val, &lu2 );
2414 			do {
2415 				if ( strcasecmp( lud->lud_scheme,
2416 					lu2->lud_scheme ))
2417 					break;
2418 				if ( lud->lud_port != lu2->lud_port )
2419 					break;
2420 				/* Listener on ANY address */
2421 				if ( !lu2->lud_host || !lu2->lud_host[0] ) {
2422 					isMe = 1;
2423 					break;
2424 				}
2425 				/* URL on ANY address */
2426 				if ( !lud->lud_host || !lud->lud_host[0] ) {
2427 					isMe = 1;
2428 					break;
2429 				}
2430 				/* Listener has specific host, must
2431 				 * match it
2432 				 */
2433 				if ( !strcasecmp( lud->lud_host,
2434 					lu2->lud_host )) {
2435 					isMe = 1;
2436 					break;
2437 				}
2438 			} while(0);
2439 			ldap_free_urldesc( lu2 );
2440 			if ( isMe ) {
2441 				return l[i];
2442 			}
2443 		}
2444 	}
2445 	return NULL;
2446 }
2447