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