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