config.c 35.4 KB
Newer Older
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1
/* config.c - configuration file handling routines */
2
/* $OpenLDAP$ */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
3
4
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
5
 * Copyright 1998-2007 The OpenLDAP Foundation.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
 */
/* Portions Copyright (c) 1995 Regents of the University of Michigan.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that this notice is preserved and that due credit is given
 * to the University of Michigan at Ann Arbor. The name of the University
 * may not be used to endorse or promote products derived from this
 * software without specific prior written permission. This software
 * is provided ``as is'' without express or implied warranty.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
25
 */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
26

Kurt Zeilenga's avatar
Kurt Zeilenga committed
27
28
#include "portable.h"

Kurt Zeilenga's avatar
Kurt Zeilenga committed
29
#include <stdio.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
30
31

#include <ac/string.h>
32
#include <ac/ctype.h>
33
#include <ac/signal.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
34
#include <ac/socket.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
35
#include <ac/errno.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
36

Kurt Zeilenga's avatar
Kurt Zeilenga committed
37
38
39
40
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

41
#include "slap.h"
42
#ifdef LDAP_SLAPI
43
#include "slapi/slapi.h"
44
#endif
45
#include "lutil.h"
46
#include "config.h"
Kurt Zeilenga's avatar
Kurt Zeilenga committed
47

48
#define ARGS_STEP	512
Kurt Zeilenga's avatar
Kurt Zeilenga committed
49
50
51
52

/*
 * defaults for various global variables
 */
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
slap_mask_t		global_allows = 0;
slap_mask_t		global_disallows = 0;
int		global_gentlehup = 0;
int		global_idletimeout = 0;
char	*global_host = NULL;
char	*global_realm = NULL;
char		*ldap_srvtab = "";
char		**default_passwd_hash = NULL;
struct berval default_search_base = BER_BVNULL;
struct berval default_search_nbase = BER_BVNULL;

ber_len_t sockbuf_max_incoming = SLAP_SB_MAX_INCOMING_DEFAULT;
ber_len_t sockbuf_max_incoming_auth= SLAP_SB_MAX_INCOMING_AUTH;

int	slap_conn_max_pending = SLAP_CONN_MAX_PENDING_DEFAULT;
int	slap_conn_max_pending_auth = SLAP_CONN_MAX_PENDING_AUTH;

char   *slapd_pid_file  = NULL;
char   *slapd_args_file = NULL;
72

73
74
75
76
77
78
int use_reverse_lookup = 0;

#ifdef LDAP_SLAPI
int slapi_plugins_used = 0;
#endif

79
80
81
static int fp_getline(FILE *fp, ConfigArgs *c);
static void fp_getline_init(ConfigArgs *c);
static int fp_parse_line(ConfigArgs *c);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
82

Kurt Zeilenga's avatar
Kurt Zeilenga committed
83
static char	*strtok_quote(char *line, char *sep, char **quote_ptr);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
84
static char *strtok_quote_ldif(char **line);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
85

86
ConfigArgs *
87
88
new_config_args( BackendDB *be, const char *fname, int lineno, int argc, char **argv )
{
89
	ConfigArgs *c;
90
91
	c = ch_calloc( 1, sizeof( ConfigArgs ) );
	if ( c == NULL ) return(NULL);
92
93
94
95
96
	c->be     = be; 
	c->fname  = fname;
	c->argc   = argc;
	c->argv   = argv; 
	c->lineno = lineno;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
97
	snprintf( c->log, sizeof( c->log ), "%s: line %d", fname, lineno );
98
99
	return(c);
}
100

101
102
103
104
105
106
107
void
init_config_argv( ConfigArgs *c )
{
	c->argv = ch_calloc( ARGS_STEP + 1, sizeof( *c->argv ) );
	c->argv_size = ARGS_STEP + 1;
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
108
109
110
111
112
113
114
115
116
117
ConfigTable *config_find_keyword(ConfigTable *Conf, ConfigArgs *c) {
	int i;

	for(i = 0; Conf[i].name; i++)
		if( (Conf[i].length && (!strncasecmp(c->argv[0], Conf[i].name, Conf[i].length))) ||
			(!strcasecmp(c->argv[0], Conf[i].name)) ) break;
	if ( !Conf[i].name ) return NULL;
	return Conf+i;
}

118
119
int config_check_vals(ConfigTable *Conf, ConfigArgs *c, int check_only ) {
	int rc, arg_user, arg_type, iarg;
120
121
	long larg;
	ber_len_t barg;
122
	
Kurt Zeilenga's avatar
Kurt Zeilenga committed
123
	arg_type = Conf->arg_type;
124
	if(arg_type == ARG_IGNORED) {
125
		Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> ignored\n",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
126
			c->log, Conf->name, 0);
127
		return(0);
128
	}
129
130
131
132
	if((arg_type & ARG_DN) && c->argc == 1) {
		c->argc = 2;
		c->argv[1] = "";
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
133
	if(Conf->min_args && (c->argc < Conf->min_args)) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
134
		snprintf( c->msg, sizeof( c->msg ), "<%s> missing <%s> argument",
135
136
			c->argv[0], Conf->what );
		Debug(LDAP_DEBUG_CONFIG, "%s: keyword %s\n", c->log, c->msg, 0 );
137
		return(ARG_BAD_CONF);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
138
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
139
	if(Conf->max_args && (c->argc > Conf->max_args)) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
140
141
		char	*ignored = " ignored";

Kurt Zeilenga's avatar
Kurt Zeilenga committed
142
		snprintf( c->msg, sizeof( c->msg ), "<%s> extra cruft after <%s>",
143
			c->argv[0], Conf->what );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
144
145
146
147
148
149
150
151
152

#ifdef LDAP_DEVEL
		ignored = "";
#endif /* LDAP_DEVEL */
		Debug(LDAP_DEBUG_CONFIG, "%s: %s%s.\n",
				c->log, c->msg, ignored );
#ifdef LDAP_DEVEL
		return(ARG_BAD_CONF);
#endif /* LDAP_DEVEL */
153
154
	}
	if((arg_type & ARG_DB) && !c->be) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
155
		snprintf( c->msg, sizeof( c->msg ), "<%s> only allowed within database declaration",
156
157
158
			c->argv[0] );
		Debug(LDAP_DEBUG_CONFIG, "%s: keyword %s\n",
			c->log, c->msg, 0);
159
160
		return(ARG_BAD_CONF);
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
161
	if((arg_type & ARG_PRE_BI) && c->bi) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
162
		snprintf( c->msg, sizeof( c->msg ), "<%s> must occur before any backend %sdeclaration",
163
164
165
			c->argv[0], (arg_type & ARG_PRE_DB) ? "or database " : "" );
		Debug(LDAP_DEBUG_CONFIG, "%s: keyword %s\n",
			c->log, c->msg, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
166
167
168
		return(ARG_BAD_CONF);
	}
	if((arg_type & ARG_PRE_DB) && c->be && c->be != frontendDB) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
169
		snprintf( c->msg, sizeof( c->msg ), "<%s> must occur before any database declaration",
170
171
172
			c->argv[0] );
		Debug(LDAP_DEBUG_CONFIG, "%s: keyword %s\n",
			c->log, c->msg, 0);
173
174
175
		return(ARG_BAD_CONF);
	}
	if((arg_type & ARG_PAREN) && *c->argv[1] != '(' /*')'*/) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
176
		snprintf( c->msg, sizeof( c->msg ), "<%s> old format not supported", c->argv[0] );
177
178
		Debug(LDAP_DEBUG_CONFIG, "%s: %s\n",
			c->log, c->msg, 0);
179
180
		return(ARG_BAD_CONF);
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
181
	if((arg_type & ARGS_POINTER) && !Conf->arg_item && !(arg_type & ARG_OFFSET)) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
182
		snprintf( c->msg, sizeof( c->msg ), "<%s> invalid config_table, arg_item is NULL",
183
184
185
			c->argv[0] );
		Debug(LDAP_DEBUG_CONFIG, "%s: %s\n",
			c->log, c->msg, 0);
186
187
188
		return(ARG_BAD_CONF);
	}
	c->type = arg_user = (arg_type & ARGS_USERLAND);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
189
	memset(&c->values, 0, sizeof(c->values));
190
	if(arg_type & ARGS_NUMERIC) {
Howard Chu's avatar
Howard Chu committed
191
		int j;
192
193
		iarg = 0; larg = 0; barg = 0;
		switch(arg_type & ARGS_NUMERIC) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
194
			case ARG_INT:
195
				if ( lutil_atoix( &iarg, c->argv[1], 0 ) != 0 ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
196
197
198
199
200
201
202
203
204
					snprintf( c->msg, sizeof( c->msg ),
						"<%s> unable to parse \"%s\" as int",
						c->argv[0], c->argv[1] );
					Debug(LDAP_DEBUG_CONFIG, "%s: %s\n",
						c->log, c->msg, 0);
					return(ARG_BAD_CONF);
				}
				break;
			case ARG_LONG:
205
				if ( lutil_atolx( &larg, c->argv[1], 0 ) != 0 ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
206
207
208
209
210
211
212
213
214
215
					snprintf( c->msg, sizeof( c->msg ),
						"<%s> unable to parse \"%s\" as long",
						c->argv[0], c->argv[1] );
					Debug(LDAP_DEBUG_CONFIG, "%s: %s\n",
						c->log, c->msg, 0);
					return(ARG_BAD_CONF);
				}
				break;
			case ARG_BER_LEN_T: {
				unsigned long	l;
216
				if ( lutil_atoulx( &l, c->argv[1], 0 ) != 0 ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
217
218
219
220
221
222
223
224
225
					snprintf( c->msg, sizeof( c->msg ),
						"<%s> unable to parse \"%s\" as ber_len_t",
						c->argv[0], c->argv[1] );
					Debug(LDAP_DEBUG_CONFIG, "%s: %s\n",
						c->log, c->msg, 0);
					return(ARG_BAD_CONF);
				}
				barg = (ber_len_t)l;
				} break;
226
			case ARG_ON_OFF:
Kurt Zeilenga's avatar
Kurt Zeilenga committed
227
				if (c->argc == 1) {
228
					iarg = 1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
229
230
231
232
				} else if ( !strcasecmp(c->argv[1], "on") ||
					!strcasecmp(c->argv[1], "true") ||
					!strcasecmp(c->argv[1], "yes") )
				{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
233
					iarg = 1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
234
235
236
237
				} else if ( !strcasecmp(c->argv[1], "off") ||
					!strcasecmp(c->argv[1], "false") ||
					!strcasecmp(c->argv[1], "no") )
				{
238
239
					iarg = 0;
				} else {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
240
					snprintf( c->msg, sizeof( c->msg ), "<%s> invalid value, ignored",
241
242
243
						c->argv[0] );
					Debug(LDAP_DEBUG_CONFIG, "%s: %s\n",
						c->log, c->msg, 0 );
244
245
246
					return(0);
				}
				break;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
247
		}
Howard Chu's avatar
Howard Chu committed
248
		j = (arg_type & ARG_NONZERO) ? 1 : 0;
249
		if(iarg < j && larg < j && barg < j ) {
250
			larg = larg ? larg : (barg ? barg : iarg);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
251
			snprintf( c->msg, sizeof( c->msg ), "<%s> invalid value, ignored",
252
253
254
				c->argv[0] );
			Debug(LDAP_DEBUG_CONFIG, "%s: %s\n",
				c->log, c->msg, 0 );
255
			return(ARG_BAD_CONF);
256
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
257
258
259
260
261
262
263
		switch(arg_type & ARGS_NUMERIC) {
			case ARG_ON_OFF:
			case ARG_INT:		c->value_int = iarg;		break;
			case ARG_LONG:		c->value_long = larg;		break;
			case ARG_BER_LEN_T:	c->value_ber_t = barg;		break;
		}
	} else if(arg_type & ARG_STRING) {
264
265
		if ( !check_only )
			c->value_string = ch_strdup(c->argv[1]);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
266
	} else if(arg_type & ARG_BERVAL) {
267
268
		if ( !check_only )
			ber_str2bv( c->argv[1], 0, 1, &c->value_bv );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
269
270
271
272
273
	} else if(arg_type & ARG_DN) {
		struct berval bv;
		ber_str2bv( c->argv[1], 0, 0, &bv );
		rc = dnPrettyNormal( NULL, &bv, &c->value_dn, &c->value_ndn, NULL );
		if ( rc != LDAP_SUCCESS ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
274
			snprintf( c->msg, sizeof( c->msg ), "<%s> invalid DN %d (%s)",
275
276
				c->argv[0], rc, ldap_err2string( rc ));
			Debug(LDAP_DEBUG_CONFIG, "%s: %s\n" , c->log, c->msg, 0);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
277
278
			return(ARG_BAD_CONF);
		}
279
280
281
282
		if ( check_only ) {
			ch_free( c->value_ndn.bv_val );
			ch_free( c->value_dn.bv_val );
		}
283
	}
284
285
286
287
288
	return 0;
}

int config_set_vals(ConfigTable *Conf, ConfigArgs *c) {
	int rc, arg_type;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
289
	void *ptr = NULL;
290
291

	arg_type = Conf->arg_type;
292
293
	if(arg_type & ARG_MAGIC) {
		if(!c->be) c->be = frontendDB;
294
		c->msg[0] = '\0';
Kurt Zeilenga's avatar
Kurt Zeilenga committed
295
		rc = (*((ConfigDriver*)Conf->arg_item))(c);
296
#if 0
297
		if(c->be == frontendDB) c->be = NULL;
298
#endif
299
		if(rc) {
300
			if ( !c->msg[0] ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
301
				snprintf( c->msg, sizeof( c->msg ), "<%s> handler exited with %d",
302
303
304
305
					c->argv[0], rc );
				Debug(LDAP_DEBUG_CONFIG, "%s: %s!\n",
					c->log, c->msg, 0 );
			}
306
			return(ARG_BAD_CONF);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
307
		}
308
309
		return(0);
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
310
	if(arg_type & ARG_OFFSET) {
311
		if (c->be && c->table == Cft_Database)
Kurt Zeilenga's avatar
Kurt Zeilenga committed
312
313
314
315
			ptr = c->be->be_private;
		else if (c->bi)
			ptr = c->bi->bi_private;
		else {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
316
			snprintf( c->msg, sizeof( c->msg ), "<%s> offset is missing base pointer",
317
318
319
				c->argv[0] );
			Debug(LDAP_DEBUG_CONFIG, "%s: %s!\n",
				c->log, c->msg, 0);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
320
321
			return(ARG_BAD_CONF);
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
322
		ptr = (void *)((char *)ptr + (long)Conf->arg_item);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
323
	} else if (arg_type & ARGS_POINTER) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
324
		ptr = Conf->arg_item;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
325
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
326
327
	if(arg_type & ARGS_POINTER)
		switch(arg_type & ARGS_POINTER) {
328
			case ARG_ON_OFF:
329
330
331
			case ARG_INT: 		*(int*)ptr = c->value_int;			break;
			case ARG_LONG:  	*(long*)ptr = c->value_long;			break;
			case ARG_BER_LEN_T: 	*(ber_len_t*)ptr = c->value_ber_t;			break;
332
			case ARG_STRING: {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
333
334
				char *cc = *(char**)ptr;
				if(cc) {
335
					if ((arg_type & ARG_UNIQUE) && c->op == SLAP_CONFIG_ADD ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
336
						Debug(LDAP_DEBUG_CONFIG, "%s: already set %s!\n",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
337
							c->log, Conf->name, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
338
339
						return(ARG_BAD_CONF);
					}
340
					ch_free(cc);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
341
342
				}
				*(char **)ptr = c->value_string;
343
344
				break;
				}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
345
346
347
348
			case ARG_BERVAL:
				*(struct berval *)ptr = c->value_bv;
				break;
		}
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
	return(0);
}

int config_add_vals(ConfigTable *Conf, ConfigArgs *c) {
	int rc, arg_type;

	arg_type = Conf->arg_type;
	if(arg_type == ARG_IGNORED) {
		Debug(LDAP_DEBUG_CONFIG, "%s: keyword <%s> ignored\n",
			c->log, Conf->name, 0);
		return(0);
	}
	rc = config_check_vals( Conf, c, 0 );
	if ( rc ) return rc;
	return config_set_vals( Conf, c );
364
}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
365

Kurt Zeilenga's avatar
Kurt Zeilenga committed
366
367
368
369
int
config_del_vals(ConfigTable *cf, ConfigArgs *c)
{
	int rc = 0;
370
371
372
373
374
375
376
377

	/* If there is no handler, just ignore it */
	if ( cf->arg_type & ARG_MAGIC ) {
		c->op = LDAP_MOD_DELETE;
		c->type = cf->arg_type & ARGS_USERLAND;
		rc = (*((ConfigDriver*)cf->arg_item))(c);
	}
	return rc;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
378
379
}

380
int
Kurt Zeilenga's avatar
Kurt Zeilenga committed
381
382
383
384
385
386
387
388
389
390
391
392
393
config_get_vals(ConfigTable *cf, ConfigArgs *c)
{
	int rc = 0;
	struct berval bv;
	void *ptr;

	if ( cf->arg_type & ARG_IGNORED ) {
		return 1;
	}

	memset(&c->values, 0, sizeof(c->values));
	c->rvalue_vals = NULL;
	c->rvalue_nvals = NULL;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
394
	c->op = SLAP_CONFIG_EMIT;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
395
396
397
398
399
400
401
	c->type = cf->arg_type & ARGS_USERLAND;

	if ( cf->arg_type & ARG_MAGIC ) {
		rc = (*((ConfigDriver*)cf->arg_item))(c);
		if ( rc ) return rc;
	} else {
		if ( cf->arg_type & ARG_OFFSET ) {
402
			if (c->be && c->table == Cft_Database)
Kurt Zeilenga's avatar
Kurt Zeilenga committed
403
404
405
406
407
				ptr = c->be->be_private;
			else if ( c->bi )
				ptr = c->bi->bi_private;
			else
				return 1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
408
			ptr = (void *)((char *)ptr + (long)cf->arg_item);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
409
410
411
412
413
414
415
416
417
418
419
420
421
		} else {
			ptr = cf->arg_item;
		}
		
		switch(cf->arg_type & ARGS_POINTER) {
		case ARG_ON_OFF:
		case ARG_INT:	c->value_int = *(int *)ptr; break;
		case ARG_LONG:	c->value_long = *(long *)ptr; break;
		case ARG_BER_LEN_T:	c->value_ber_t = *(ber_len_t *)ptr; break;
		case ARG_STRING:
			if ( *(char **)ptr )
				c->value_string = ch_strdup(*(char **)ptr);
			break;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
422
423
		case ARG_BERVAL:
			ber_dupbv( &c->value_bv, (struct berval *)ptr ); break;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
424
425
426
427
428
		}
	}
	if ( cf->arg_type & ARGS_POINTER) {
		bv.bv_val = c->log;
		switch(cf->arg_type & ARGS_POINTER) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
429
430
431
432
		case ARG_INT: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%d", c->value_int); break;
		case ARG_LONG: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%ld", c->value_long); break;
		case ARG_BER_LEN_T: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%ld", c->value_ber_t); break;
		case ARG_ON_OFF: bv.bv_len = snprintf(bv.bv_val, sizeof( c->log ), "%s",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
433
434
435
436
437
438
439
440
			c->value_int ? "TRUE" : "FALSE"); break;
		case ARG_STRING:
			if ( c->value_string && c->value_string[0]) {
				ber_str2bv( c->value_string, 0, 0, &bv);
			} else {
				return 1;
			}
			break;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
441
442
443
444
445
446
447
		case ARG_BERVAL:
			if ( !BER_BVISEMPTY( &c->value_bv )) {
				bv = c->value_bv;
			} else {
				return 1;
			}
			break;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
448
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
449
450
451
		if (bv.bv_val == c->log && bv.bv_len >= sizeof( c->log ) ) {
			return 1;
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
		if (( cf->arg_type & ARGS_POINTER ) == ARG_STRING )
			ber_bvarray_add(&c->rvalue_vals, &bv);
		else
			value_add_one(&c->rvalue_vals, &bv);
	}
	return rc;
}

int
init_config_attrs(ConfigTable *ct) {
	LDAPAttributeType *at;
	int i, code;
	const char *err;

	for (i=0; ct[i].name; i++ ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
467
468
		int		freeit = 0;

Kurt Zeilenga's avatar
Kurt Zeilenga committed
469
470
471
472
473
474
475
476
		if ( !ct[i].attribute ) continue;
		at = ldap_str2attributetype( ct[i].attribute,
			&code, &err, LDAP_SCHEMA_ALLOW_ALL );
		if ( !at ) {
			fprintf( stderr, "init_config_attrs: AttributeType \"%s\": %s, %s\n",
				ct[i].attribute, ldap_scherr2str(code), err );
			return code;
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
477

478
		code = at_add( at, 0, NULL, &err );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
479
480
481
482
483
		if ( code ) {
			if ( code == SLAP_SCHERR_ATTR_DUP ) {
				freeit = 1;

			} else {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
484
				ldap_attributetype_free( at );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
485
486
487
488
				fprintf( stderr, "init_config_attrs: AttributeType \"%s\": %s, %s\n",
					ct[i].attribute, scherr2str(code), err );
				return code;
			}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
489
490
		}
		code = slap_str2ad( at->at_names[0], &ct[i].ad, &err );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
491
492
493
494
495
		if ( freeit ) {
			ldap_attributetype_free( at );
		} else {
			ldap_memfree( at );
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
496
497
498
499
500
501
502
503
504
505
506
507
508
509
		if ( code ) {
			fprintf( stderr, "init_config_attrs: AttributeType \"%s\": %s\n",
				ct[i].attribute, err );
			return code;
		}
	}

	return 0;
}

int
init_config_ocs( ConfigOCs *ocs ) {
	int i;

510
	for (i=0;ocs[i].co_def;i++) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
511
512
513
514
		LDAPObjectClass *oc;
		int code;
		const char *err;

515
		oc = ldap_str2objectclass( ocs[i].co_def, &code, &err,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
516
517
518
			LDAP_SCHEMA_ALLOW_ALL );
		if ( !oc ) {
			fprintf( stderr, "init_config_ocs: objectclass \"%s\": %s, %s\n",
519
				ocs[i].co_def, ldap_scherr2str(code), err );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
520
521
			return code;
		}
522
		code = oc_add(oc,0,NULL,&err);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
523
524
		if ( code && code != SLAP_SCHERR_CLASS_DUP ) {
			fprintf( stderr, "init_config_ocs: objectclass \"%s\": %s, %s\n",
525
				ocs[i].co_def, scherr2str(code), err );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
526
527
			return code;
		}
528
		ocs[i].co_oc = oc_find(oc->oc_names[0]);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
529
530
531
		ldap_memfree(oc);
	}
	return 0;
532
}
533

Kurt Zeilenga's avatar
Kurt Zeilenga committed
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
/* Split an LDIF line into space-separated tokens. Words may be grouped
 * by quotes. A quoted string may begin in the middle of a word, but must
 * end at the end of the word (be followed by whitespace or EOS). Any other
 * quotes are passed through unchanged. All other characters are passed
 * through unchanged.
 */
static char *
strtok_quote_ldif( char **line )
{
	char *beg, *ptr, *quote=NULL;
	int inquote=0;

	ptr = *line;

	if ( !ptr || !*ptr )
		return NULL;

	while( isspace( *ptr )) ptr++;

	if ( *ptr == '"' ) {
		inquote = 1;
		ptr++;
	}

	beg = ptr;

	for (;*ptr;ptr++) {
		if ( *ptr == '"' ) {
			if ( inquote && ( !ptr[1] || isspace(ptr[1]))) {
				*ptr++ = '\0';
				break;
			}
			inquote = 1;
			quote = ptr;
			continue;
		}
		if ( inquote )
			continue;
		if ( isspace( *ptr )) {
			*ptr++ = '\0';
			break;
		}
	}
	if ( quote ) {
		while ( quote < ptr ) {
			*quote = quote[1];
			quote++;
		}
	}
	if ( !*ptr ) {
		*line = NULL;
	} else {
		while ( isspace( *ptr )) ptr++;
		*line = ptr;
	}
	return beg;
}

static void
config_parse_ldif( ConfigArgs *c )
{
	char *next;
	c->tline = ch_strdup(c->line);
	next = c->tline;

	while ((c->argv[c->argc] = strtok_quote_ldif( &next )) != NULL) {
		c->argc++;
		if ( c->argc >= c->argv_size ) {
			char **tmp = ch_realloc( c->argv, (c->argv_size + ARGS_STEP) *
				sizeof( *c->argv ));
			c->argv = tmp;
			c->argv_size += ARGS_STEP;
		}
	}
	c->argv[c->argc] = NULL;
}

611
612
613
int
config_parse_vals(ConfigTable *ct, ConfigArgs *c, int valx)
{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
614
	int 	rc = 0;
615
616
617
618
619

	snprintf( c->log, sizeof( c->log ), "%s: value #%d",
		ct->ad->ad_cname.bv_val, valx );
	c->argc = 1;
	c->argv[0] = ct->ad->ad_cname.bv_val;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
620
621

	if ( ( ct->arg_type & ARG_QUOTE ) && c->line[ 0 ] != '"' ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
622
623
624
625
		c->argv[c->argc] = c->line;
		c->argc++;
		c->argv[c->argc] = NULL;
		c->tline = NULL;
626
	} else {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
627
		config_parse_ldif( c );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
628
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
629
630
	rc = config_check_vals( ct, c, 1 );
	ch_free( c->tline );
631
	c->tline = NULL;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
632

633
634
635
636
637
638
639
640
641
	if ( rc )
		rc = LDAP_CONSTRAINT_VIOLATION;

	return rc;
}

int
config_parse_add(ConfigTable *ct, ConfigArgs *c)
{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
642
	int	rc = 0;
643
644
645
646
647

	snprintf( c->log, sizeof( c->log ), "%s: value #%d",
		ct->ad->ad_cname.bv_val, c->valx );
	c->argc = 1;
	c->argv[0] = ct->ad->ad_cname.bv_val;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
648
649

	if ( ( ct->arg_type & ARG_QUOTE ) && c->line[ 0 ] != '"' ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
650
651
652
653
		c->argv[c->argc] = c->line;
		c->argc++;
		c->argv[c->argc] = NULL;
		c->tline = NULL;
654
	} else {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
655
		config_parse_ldif( c );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
656
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
657
658
	c->op = LDAP_MOD_ADD;
	rc = config_add_vals( ct, c );
659
	ch_free( c->tline );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
660

661
662
663
	return rc;
}

664
int
665
read_config_file(const char *fname, int depth, ConfigArgs *cf, ConfigTable *cft)
666
667
{
	FILE *fp;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
668
	ConfigTable *ct;
669
	ConfigArgs *c;
670
	int rc;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
671
	struct stat s;
672

673
674
675
676
	c = ch_calloc( 1, sizeof( ConfigArgs ) );
	if ( c == NULL ) {
		return 1;
	}
677

678
679
	if ( depth ) {
		memcpy( c, cf, sizeof( ConfigArgs ) );
680
681
682
683
684
	} else {
		c->depth = depth; /* XXX */
		c->bi = NULL;
		c->be = NULL;
	}
685

686
	c->valx = -1;
687
	c->fname = fname;
688
	init_config_argv( c );
Gary Williams's avatar
Gary Williams committed
689

Kurt Zeilenga's avatar
Kurt Zeilenga committed
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
	if ( stat( fname, &s ) != 0 ) {
		ldap_syslog = 1;
		Debug(LDAP_DEBUG_ANY,
		    "could not stat config file \"%s\": %s (%d)\n",
		    fname, strerror(errno), errno);
		return(1);
	}

	if ( !S_ISREG( s.st_mode ) ) {
		ldap_syslog = 1;
		Debug(LDAP_DEBUG_ANY,
		    "regular file expected, got \"%s\"\n",
		    fname, 0, 0 );
		return(1);
	}

706
707
	fp = fopen( fname, "r" );
	if ( fp == NULL ) {
708
709
710
711
712
713
		ldap_syslog = 1;
		Debug(LDAP_DEBUG_ANY,
		    "could not open config file \"%s\": %s (%d)\n",
		    fname, strerror(errno), errno);
		return(1);
	}
714

715
	Debug(LDAP_DEBUG_CONFIG, "reading config file %s\n", fname, 0, 0);
716

717
	fp_getline_init(c);
Gary Williams's avatar
Gary Williams committed
718

719
720
	c->tline = NULL;

721
	while ( fp_getline( fp, c ) ) {
722
		/* skip comments and blank lines */
723
724
725
		if ( c->line[0] == '#' || c->line[0] == '\0' ) {
			continue;
		}
726

Kurt Zeilenga's avatar
Kurt Zeilenga committed
727
		snprintf( c->log, sizeof( c->log ), "%s: line %d",
728
729
				c->fname, c->lineno );

Kurt Zeilenga's avatar
Kurt Zeilenga committed
730
		c->argc = 0;
731
		ch_free( c->tline );
732
		if ( fp_parse_line( c ) ) {
733
			rc = 1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
734
			goto done;
735
		}
736

737
		if ( c->argc < 1 ) {
738
			Debug( SLAPD_DEBUG_CONFIG_ERROR, "%s: bad config line" 
Kurt Zeilenga's avatar
Kurt Zeilenga committed
739
740
741
742
				SLAPD_CONF_UNKNOWN_IGNORED ".\n",
				c->log, 0, 0);
#ifdef SLAPD_CONF_UNKNOWN_BAILOUT
			rc = 1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
743
			goto done;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
744
#else /* ! SLAPD_CONF_UNKNOWN_BAILOUT */
745
			continue;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
746
#endif /* ! SLAPD_CONF_UNKNOWN_BAILOUT */
747
		}
Gary Williams's avatar
Gary Williams committed
748

749
		c->op = SLAP_CONFIG_ADD;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
750

751
		ct = config_find_keyword( cft, c );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
752
		if ( ct ) {
753
			c->table = Cft_Global;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
754
755
756
757
758
759
760
			rc = config_add_vals( ct, c );
			if ( !rc ) continue;

			if ( rc & ARGS_USERLAND ) {
				/* XXX a usertype would be opaque here */
				Debug(LDAP_DEBUG_CONFIG, "%s: unknown user type <%s>\n",
					c->log, c->argv[0], 0);
761
				rc = 1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
762
				goto done;
763

Kurt Zeilenga's avatar
Kurt Zeilenga committed
764
			} else if ( rc == ARG_BAD_CONF ) {
765
				rc = 1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
766
				goto done;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
767
			}
768
			
769
		} else if ( c->bi && !c->be ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
770
			rc = SLAP_CONF_UNKNOWN;
771
772
			if ( c->bi->bi_cf_ocs ) {
				ct = config_find_keyword( c->bi->bi_cf_ocs->co_table, c );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
773
				if ( ct ) {
774
					c->table = c->bi->bi_cf_ocs->co_type;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
775
776
777
778
779
780
781
					rc = config_add_vals( ct, c );
				}
			}
			if ( c->bi->bi_config && rc == SLAP_CONF_UNKNOWN ) {
				rc = (*c->bi->bi_config)(c->bi, c->fname, c->lineno,
					c->argc, c->argv);
			}
782
783
			if ( rc ) {
				switch(rc) {
784
				case SLAP_CONF_UNKNOWN:
785
					Debug( SLAPD_DEBUG_CONFIG_ERROR, "%s: "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
786
787
						"unknown directive <%s> inside backend info definition"
						SLAPD_CONF_UNKNOWN_IGNORED ".\n",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
788
						c->log, *c->argv, 0);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
789
#ifndef SLAPD_CONF_UNKNOWN_BAILOUT
790
					continue;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
791
#endif /* ! SLAPD_CONF_UNKNOWN_BAILOUT */
792
				default:
793
					rc = 1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
794
					goto done;
795
				}
796
			}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
797

Kurt Zeilenga's avatar
Kurt Zeilenga committed
798
		} else if ( c->be ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
799
			rc = SLAP_CONF_UNKNOWN;
800
801
			if ( c->be->be_cf_ocs ) {
				ct = config_find_keyword( c->be->be_cf_ocs->co_table, c );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
802
				if ( ct ) {
803
					c->table = c->be->be_cf_ocs->co_type;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
804
805
					rc = config_add_vals( ct, c );
				}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
806
			}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
807
			if ( c->be->be_config && rc == SLAP_CONF_UNKNOWN ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
808
809
				rc = (*c->be->be_config)(c->be, c->fname, c->lineno,
					c->argc, c->argv);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
810
811
812
813
			}
			if ( rc ) {
				switch(rc) {
				case SLAP_CONF_UNKNOWN:
814
					Debug( SLAPD_DEBUG_CONFIG_ERROR, "%s: "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
815
						"unknown directive <%s> inside backend database "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
816
						"definition" SLAPD_CONF_UNKNOWN_IGNORED ".\n",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
817
						c->log, *c->argv, 0);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
818
#ifndef SLAPD_CONF_UNKNOWN_BAILOUT
Kurt Zeilenga's avatar
Kurt Zeilenga committed
819
					continue;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
820
#endif /* ! SLAPD_CONF_UNKNOWN_BAILOUT */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
821
				default:
822
					rc = 1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
823
					goto done;
824
				}
825
			}
826
827
828
829
830

		} else if ( frontendDB->be_config ) {
			rc = (*frontendDB->be_config)(frontendDB, c->fname, (int)c->lineno, c->argc, c->argv);
			if ( rc ) {
				switch(rc) {
831
				case SLAP_CONF_UNKNOWN:
832
					Debug( SLAPD_DEBUG_CONFIG_ERROR, "%s: "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
833
834
						"unknown directive <%s> inside global database definition"
						SLAPD_CONF_UNKNOWN_IGNORED ".\n",
835
						c->log, *c->argv, 0);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
836
#ifndef SLAPD_CONF_UNKNOWN_BAILOUT
837
					continue;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
838
#endif /* ! SLAPD_CONF_UNKNOWN_BAILOUT */
839
				default:
840
					rc = 1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
841
					goto done;
842
				}
843
			}
844
			
845
		} else {
846
			Debug( SLAPD_DEBUG_CONFIG_ERROR, "%s: "
Kurt Zeilenga's avatar
Kurt Zeilenga committed
847
848
				"unknown directive <%s> outside backend info and database definitions"
				SLAPD_CONF_UNKNOWN_IGNORED ".\n",
849
				c->log, *c->argv, 0);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
850
851
#ifdef SLAPD_CONF_UNKNOWN_BAILOUT
			rc = 1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
852
			goto done;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
853
#else /* ! SLAPD_CONF_UNKNOWN_BAILOUT */
854
			continue;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
855
#endif /* ! SLAPD_CONF_UNKNOWN_BAILOUT */
856
857
		}
	}
858

859
	rc = 0;
Gary Williams's avatar
Gary Williams committed
860

Kurt Zeilenga's avatar
Kurt Zeilenga committed
861
done:
Howard Chu's avatar
Howard Chu committed
862
863
864
865
	if ( cf ) {
		cf->be = c->be;
		cf->bi = c->bi;
	}
866
	ch_free(c->tline);
867
868
869
	fclose(fp);
	ch_free(c->argv);
	ch_free(c);
870
	return(rc);
871
}
Gary Williams's avatar
Gary Williams committed
872

873
/* restrictops, allows, disallows, requires, loglevel */
874

875
int
Kurt Zeilenga's avatar
Kurt Zeilenga committed
876
877
878
879
verb_to_mask(const char *word, slap_verbmasks *v) {
	int i;
	for(i = 0; !BER_BVISNULL(&v[i].word); i++)
		if(!strcasecmp(word, v[i].word.bv_val))
880
			break;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
881
	return(i);
882
}
Gary Williams's avatar
Gary Williams committed
883

884
int
Kurt Zeilenga's avatar
Kurt Zeilenga committed
885
verbs_to_mask(int argc, char *argv[], slap_verbmasks *v, slap_mask_t *m) {
886
	int i, j;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
887
888
	for(i = 1; i < argc; i++) {
		j = verb_to_mask(argv[i], v);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
889
		if(BER_BVISNULL(&v[j].word)) return i;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
890
		while (!v[j].mask) j--;
891
892
893
894
		*m |= v[j].mask;
	}
	return(0);
}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
895

Kurt Zeilenga's avatar
Kurt Zeilenga committed
896
897
898
/* Mask keywords that represent multiple bits should occur before single
 * bit keywords in the verbmasks array.
 */
899
int
Kurt Zeilenga's avatar
Kurt Zeilenga committed
900
mask_to_verbs(slap_verbmasks *v, slap_mask_t m, BerVarray *bva) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
901
902
903
904
905
906
907
908
909
910
911
	int i, rc = 1;

	if (m) {
		for (i=0; !BER_BVISNULL(&v[i].word); i++) {
			if (!v[i].mask) continue;
			if (( m & v[i].mask ) == v[i].mask ) {
				value_add_one( bva, &v[i].word );
				rc = 0;
				m ^= v[i].mask;
				if ( !m ) break;
			}
912
913
		}
	}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
914
	return rc;
915
}
916

Kurt Zeilenga's avatar
Kurt Zeilenga committed
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
int
slap_verbmasks_init( slap_verbmasks **vp, slap_verbmasks *v )
{
	int		i;

	assert( *vp == NULL );

	for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ )
		;

	*vp = ch_calloc( i + 1, sizeof( slap_verbmasks ) );

	for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) {
		ber_dupbv( &(*vp)[ i ].word, &v[ i ].word );
		*((slap_mask_t *)&(*vp)[ i ].mask) = v[ i ].mask;
	}

	BER_BVZERO( &(*vp)[ i ].word );

	return 0;		
}

int
slap_verbmasks_destroy( slap_verbmasks *v )
{
	int		i;

	assert( v != NULL );

	for ( i = 0; !BER_BVISNULL( &v[ i ].word ); i++ ) {
		ch_free( v[ i ].word.bv_val );
	}

	ch_free( v );

	return 0;
}

int
slap_verbmasks_append(
	slap_verbmasks	**vp,
	slap_mask_t	m,
	struct berval	*v,
	slap_mask_t	*ignore )
{
	int	i;

	if ( !m ) {
		return LDAP_OPERATIONS_ERROR;
	}

	for ( i = 0; !BER_BVISNULL( &(*vp)[ i ].word ); i++ ) {
		if ( !(*vp)[ i ].mask ) continue;

		if ( ignore != NULL ) {
			int	j;

			for ( j = 0; ignore[ j ] != 0; j++ ) {
				if ( (*vp)[ i ].mask == ignore[ j ] ) {
					goto check_next;
				}
			}
		}

		if ( ( m & (*vp)[ i ].mask ) == (*vp)[ i ].mask ) {
			if ( ber_bvstrcasecmp( v, &(*vp)[ i ].word ) == 0 ) {
				/* already set; ignore */
				return LDAP_SUCCESS;
			}
			/* conflicts */
			return LDAP_TYPE_OR_VALUE_EXISTS;
		}

		if ( m & (*vp)[ i ].mask ) {
			/* conflicts */
			return LDAP_CONSTRAINT_VIOLATION;
		}
check_next:;
	}

	*vp = ch_realloc( *vp, sizeof( slap_verbmasks ) * ( i + 2 ) );
	ber_dupbv( &(*vp)[ i ].word, v );
	*((slap_mask_t *)&(*vp)[ i ].mask) = m;
	BER_BVZERO( &(*vp)[ i + 1 ].word );

	return LDAP_SUCCESS;
}

1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
int
enum_to_verb(slap_verbmasks *v, slap_mask_t m, struct berval *bv) {
	int i;

	for (i=0; !BER_BVISNULL(&v[i].word); i++) {
		if ( m == v[i].mask ) {
			if ( bv != NULL ) {
				*bv = v[i].word;
			}
			return i;
		}
	}
	return -1;
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
1020
static slap_verbmasks tlskey[] = {
1021
1022
	{ BER_BVC("no"),	SB_TLS_OFF },
	{ BER_BVC("yes"),	SB_TLS_ON },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1023
1024
1025
	{ BER_BVC("critical"),	SB_TLS_CRITICAL },
	{ BER_BVNULL, 0 }
};
1026

Kurt Zeilenga's avatar
Kurt Zeilenga committed
1027
static slap_verbmasks methkey[] = {
1028
	{ BER_BVC("none"),	LDAP_AUTH_NONE },
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1029
1030
1031
1032
1033
1034
	{ BER_BVC("simple"),	LDAP_AUTH_SIMPLE },
#ifdef HAVE_CYRUS_SASL
	{ BER_BVC("sasl"),	LDAP_AUTH_SASL },
#endif
	{ BER_BVNULL, 0 }
};
1035

Kurt Zeilenga's avatar
Kurt Zeilenga committed
1036
static slap_cf_aux_table bindkey[] = {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1037
	{ BER_BVC("uri="), offsetof(slap_bindconf, sb_uri), 'b', 1, NULL },
1038
1039
1040
	{ BER_BVC("starttls="), offsetof(slap_bindconf, sb_tls), 'i', 0, tlskey },
	{ BER_BVC("bindmethod="), offsetof(slap_bindconf, sb_method), 'i', 0, methkey },
	{ BER_BVC("binddn="), offsetof(slap_bindconf, sb_binddn), 'b', 1, dnNormalize },
1041
1042
1043
1044
	{ BER_BVC("credentials="), offsetof(slap_bindconf, sb_cred), 'b', 1, NULL },
	{ BER_BVC("saslmech="), offsetof(slap_bindconf, sb_saslmech), 'b', 0, NULL },
	{ BER_BVC("secprops="), offsetof(slap_bindconf, sb_secprops), 's', 0, NULL },
	{ BER_BVC("realm="), offsetof(slap_bindconf, sb_realm), 'b', 0, NULL },
1045
#ifndef SLAP_AUTHZ_SYNTAX
1046
1047
	{ BER_BVC("authcID="), offsetof(slap_bindconf, sb_authcId), 'b', 0, NULL },
	{ BER_BVC("authzID="), offsetof(slap_bindconf, sb_authzId), 'b', 1, NULL },
1048
1049
1050
1051
1052
#else /* SLAP_AUTHZ_SYNTAX */
	{ BER_BVC("authcID="), offsetof(slap_bindconf, sb_authcId), 'b', 0, authzNormalize },
	{ BER_BVC("authzID="), offsetof(slap_bindconf, sb_authzId), 'b', 1, authzNormalize },
#endif /* SLAP_AUTHZ_SYNTAX */

1053
	{