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", "e_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", "e_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