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