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