1 /* $NetBSD: config.c,v 1.2 2021/08/14 16:14:58 christos Exp $ */ 2 3 /* config.c - configuration file handling routines */ 4 /* $OpenLDAP$ */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 1998-2021 The OpenLDAP Foundation. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted only as authorized by the OpenLDAP 12 * Public License. 13 * 14 * A copy of this license is available in the file LICENSE in the 15 * top-level directory of the distribution or, alternatively, at 16 * <http://www.OpenLDAP.org/license.html>. 17 */ 18 /* Portions Copyright (c) 1995 Regents of the University of Michigan. 19 * All rights reserved. 20 * 21 * Redistribution and use in source and binary forms are permitted 22 * provided that this notice is preserved and that due credit is given 23 * to the University of Michigan at Ann Arbor. The name of the University 24 * may not be used to endorse or promote products derived from this 25 * software without specific prior written permission. This software 26 * is provided ``as is'' without express or implied warranty. 27 */ 28 29 #include <sys/cdefs.h> 30 __RCSID("$NetBSD: config.c,v 1.2 2021/08/14 16:14:58 christos Exp $"); 31 32 #include "portable.h" 33 34 #include <stdio.h> 35 36 #include <ac/string.h> 37 #include <ac/ctype.h> 38 #include <ac/signal.h> 39 #include <ac/socket.h> 40 #include <ac/errno.h> 41 #include <ac/unistd.h> 42 43 #include <sys/types.h> 44 #include <sys/stat.h> 45 46 #ifndef S_ISREG 47 #define S_ISREG(m) ( ((m) & _S_IFMT ) == _S_IFREG ) 48 #endif 49 50 #include "lload.h" 51 #include "lutil.h" 52 #include "lutil_ldap.h" 53 #include "lload-config.h" 54 55 #ifdef _WIN32 56 #define LUTIL_ATOULX lutil_atoullx 57 #define Z "I" 58 #else 59 #define LUTIL_ATOULX lutil_atoulx 60 #define Z "z" 61 #endif 62 63 #define ARGS_STEP 512 64 65 /* 66 * defaults for various global variables 67 */ 68 #ifdef BALANCER_MODULE 69 char *listeners_list = NULL; 70 #else /* !BALANCER_MODULE */ 71 slap_mask_t global_allows = 0; 72 slap_mask_t global_disallows = 0; 73 int global_gentlehup = 0; 74 int global_idletimeout = 0; 75 char *global_host = NULL; 76 77 char *slapd_pid_file = NULL; 78 char *slapd_args_file = NULL; 79 #endif /* !BALANCER_MODULE */ 80 81 static FILE *logfile; 82 static char *logfileName; 83 84 static struct timeval timeout_api_tv, timeout_net_tv, 85 timeout_write_tv = { 10, 0 }; 86 87 lload_features_t lload_features; 88 89 ber_len_t sockbuf_max_incoming_client = LLOAD_SB_MAX_INCOMING_CLIENT; 90 ber_len_t sockbuf_max_incoming_upstream = LLOAD_SB_MAX_INCOMING_UPSTREAM; 91 92 int lload_conn_max_pdus_per_cycle = LLOAD_CONN_MAX_PDUS_PER_CYCLE_DEFAULT; 93 94 struct timeval *lload_timeout_api = NULL; 95 struct timeval *lload_timeout_net = NULL; 96 struct timeval *lload_write_timeout = &timeout_write_tv; 97 98 static slap_verbmasks tlskey[]; 99 100 static int fp_getline( FILE *fp, ConfigArgs *c ); 101 static void fp_getline_init( ConfigArgs *c ); 102 103 static char *strtok_quote( 104 char *line, 105 char *sep, 106 char **quote_ptr, 107 int *inquote ); 108 109 typedef struct ConfigFile { 110 struct ConfigFile *c_sibs; 111 struct ConfigFile *c_kids; 112 struct berval c_file; 113 BerVarray c_dseFiles; 114 } ConfigFile; 115 116 static ConfigFile *cfn; 117 118 static ConfigDriver config_fname; 119 static ConfigDriver config_generic; 120 static ConfigDriver config_backend; 121 static ConfigDriver config_bindconf; 122 #ifdef LDAP_TCP_BUFFER 123 static ConfigDriver config_tcp_buffer; 124 #endif /* LDAP_TCP_BUFFER */ 125 static ConfigDriver config_restrict; 126 static ConfigDriver config_loglevel; 127 static ConfigDriver config_include; 128 static ConfigDriver config_feature; 129 #ifdef HAVE_TLS 130 static ConfigDriver config_tls_option; 131 static ConfigDriver config_tls_config; 132 #endif 133 #ifdef BALANCER_MODULE 134 static ConfigDriver config_share_tls_ctx; 135 static ConfigDriver backend_cf_gen; 136 #endif /* BALANCER_MODULE */ 137 138 lload_b_head backend = LDAP_CIRCLEQ_HEAD_INITIALIZER(backend); 139 ldap_pvt_thread_mutex_t backend_mutex; 140 LloadBackend *current_backend = NULL; 141 142 struct slap_bindconf bindconf = {}; 143 struct berval lloadd_identity = BER_BVNULL; 144 145 enum { 146 CFG_ACL = 1, 147 CFG_BACKEND, 148 CFG_BINDCONF, 149 CFG_LISTEN, 150 CFG_LISTEN_URI, 151 CFG_TLS_RAND, 152 CFG_TLS_CIPHER, 153 CFG_TLS_PROTOCOL_MIN, 154 CFG_TLS_CERT_FILE, 155 CFG_TLS_CERT_KEY, 156 CFG_TLS_CA_PATH, 157 CFG_TLS_CA_FILE, 158 CFG_TLS_DH_FILE, 159 CFG_TLS_VERIFY, 160 CFG_TLS_CRLCHECK, 161 CFG_TLS_CRL_FILE, 162 CFG_TLS_SHARE_CTX, 163 CFG_CONCUR, 164 CFG_THREADS, 165 CFG_LOGFILE, 166 CFG_MIRRORMODE, 167 CFG_IOTHREADS, 168 CFG_MAXBUF_CLIENT, 169 CFG_MAXBUF_UPSTREAM, 170 CFG_FEATURE, 171 CFG_THREADQS, 172 CFG_TLS_ECNAME, 173 CFG_TLS_CACERT, 174 CFG_TLS_CERT, 175 CFG_TLS_KEY, 176 CFG_RESCOUNT, 177 CFG_IOTIMEOUT, 178 CFG_URI, 179 CFG_NUMCONNS, 180 CFG_BINDCONNS, 181 CFG_RETRY, 182 CFG_MAX_PENDING_OPS, 183 CFG_MAX_PENDING_CONNS, 184 CFG_STARTTLS, 185 CFG_CLIENT_PENDING, 186 187 CFG_LAST 188 }; 189 190 /* alphabetical ordering */ 191 192 static ConfigTable config_back_cf_table[] = { 193 /* This attr is read-only */ 194 { "", "", 0, 0, 0, 195 ARG_MAGIC, 196 &config_fname, 197 NULL, NULL, NULL 198 }, 199 { "argsfile", "file", 2, 2, 0, 200 ARG_STRING, 201 &slapd_args_file, 202 NULL, NULL, NULL 203 }, 204 { "concurrency", "level", 2, 2, 0, 205 ARG_UINT|ARG_MAGIC|CFG_CONCUR, 206 &config_generic, 207 NULL, NULL, NULL 208 }, 209 /* conf-file only option */ 210 { "backend-server", "backend options", 2, 0, 0, 211 ARG_MAGIC|CFG_BACKEND, 212 &config_backend, 213 NULL, NULL, NULL 214 }, 215 { "bindconf", "backend credentials", 2, 0, 0, 216 ARG_MAGIC|CFG_BINDCONF, 217 &config_bindconf, 218 "( OLcfgBkAt:13.2 " 219 "NAME 'olcBkLloadBindconf' " 220 "DESC 'Backend credentials' " 221 /* No EQUALITY since this is a compound attribute (and needs 222 * splitting up anyway - which is a TODO) */ 223 "SYNTAX OMsDirectoryString " 224 "SINGLE-VALUE )", 225 NULL, NULL 226 }, 227 { "gentlehup", "on|off", 2, 2, 0, 228 #ifdef SIGHUP 229 ARG_ON_OFF, 230 &global_gentlehup, 231 #else 232 ARG_IGNORED, 233 NULL, 234 #endif 235 NULL, NULL, NULL 236 }, 237 { "idletimeout", "timeout", 2, 2, 0, 238 ARG_UINT, 239 &global_idletimeout, 240 "( OLcfgBkAt:13.3 " 241 "NAME 'olcBkLloadIdleTimeout' " 242 "DESC 'Connection idle timeout' " 243 "EQUALITY integerMatch " 244 "SYNTAX OMsInteger " 245 "SINGLE-VALUE )", 246 NULL, NULL 247 }, 248 { "include", "file", 2, 2, 0, 249 ARG_MAGIC, 250 &config_include, 251 NULL, NULL, NULL 252 }, 253 { "io-threads", "count", 2, 0, 0, 254 ARG_UINT|ARG_MAGIC|CFG_IOTHREADS, 255 &config_generic, 256 "( OLcfgBkAt:13.4 " 257 "NAME 'olcBkLloadIOThreads' " 258 "DESC 'I/O thread count' " 259 "EQUALITY integerMatch " 260 "SYNTAX OMsInteger " 261 "SINGLE-VALUE )", 262 NULL, NULL 263 }, 264 #ifdef BALANCER_MODULE 265 { "listen", "uri list", 2, 2, 0, 266 ARG_STRING|ARG_MAGIC|CFG_LISTEN, 267 &config_generic, 268 NULL, NULL, NULL 269 }, 270 { "", "uri", 2, 2, 0, 271 ARG_MAGIC|CFG_LISTEN_URI, 272 &config_generic, 273 "( OLcfgBkAt:13.5 " 274 "NAME 'olcBkLloadListen' " 275 "DESC 'A listener adress' " 276 /* We don't handle adding/removing a value, so no EQUALITY yet */ 277 "SYNTAX OMsDirectoryString )", 278 NULL, NULL 279 }, 280 #endif /* BALANCER_MODULE */ 281 { "logfile", "file", 2, 2, 0, 282 ARG_STRING|ARG_MAGIC|CFG_LOGFILE, 283 &config_generic, 284 NULL, NULL, NULL 285 }, 286 { "loglevel", "level", 2, 0, 0, 287 ARG_MAGIC, 288 &config_loglevel, 289 NULL, NULL, NULL 290 }, 291 { "pidfile", "file", 2, 2, 0, 292 ARG_STRING, 293 &slapd_pid_file, 294 NULL, NULL, NULL 295 }, 296 { "restrict", "op_list", 2, 0, 0, 297 ARG_MAGIC, 298 &config_restrict, 299 NULL, NULL, NULL 300 }, 301 { "sockbuf_max_incoming_client", "max", 2, 2, 0, 302 ARG_BER_LEN_T|ARG_MAGIC|CFG_MAXBUF_CLIENT, 303 &config_generic, 304 "( OLcfgBkAt:13.6 " 305 "NAME 'olcBkLloadSockbufMaxClient' " 306 "DESC 'The maximum LDAP PDU size accepted coming from clients' " 307 "EQUALITY integerMatch " 308 "SYNTAX OMsInteger " 309 "SINGLE-VALUE )", 310 NULL, 311 { .v_ber_t = LLOAD_SB_MAX_INCOMING_CLIENT } 312 }, 313 { "sockbuf_max_incoming_upstream", "max", 2, 2, 0, 314 ARG_BER_LEN_T|ARG_MAGIC|CFG_MAXBUF_UPSTREAM, 315 &config_generic, 316 "( OLcfgBkAt:13.7 " 317 "NAME 'olcBkLloadSockbufMaxUpstream' " 318 "DESC 'The maximum LDAP PDU size accepted coming from upstream' " 319 "EQUALITY integerMatch " 320 "SYNTAX OMsInteger " 321 "SINGLE-VALUE )", 322 NULL, 323 { .v_ber_t = LLOAD_SB_MAX_INCOMING_UPSTREAM } 324 }, 325 { "tcp-buffer", "[listener=<listener>] [{read|write}=]size", 0, 0, 0, 326 #ifdef LDAP_TCP_BUFFER 327 ARG_MAGIC, 328 &config_tcp_buffer, 329 #else 330 ARG_IGNORED, 331 NULL, 332 #endif 333 "( OLcfgBkAt:13.8 " 334 "NAME 'olcBkLloadTcpBuffer' " 335 "DESC 'TCP Buffer size' " 336 "EQUALITY caseIgnoreMatch " 337 "SYNTAX OMsDirectoryString " 338 "SINGLE-VALUE )", 339 NULL, NULL 340 }, 341 { "threads", "count", 2, 2, 0, 342 ARG_UINT|ARG_MAGIC|CFG_THREADS, 343 &config_generic, 344 NULL, NULL, NULL 345 }, 346 { "threadqueues", "count", 2, 2, 0, 347 ARG_UINT|ARG_MAGIC|CFG_THREADQS, 348 &config_generic, 349 NULL, NULL, NULL 350 }, 351 { "max_pdus_per_cycle", "count", 2, 2, 0, 352 ARG_UINT|ARG_MAGIC|CFG_RESCOUNT, 353 &config_generic, 354 "( OLcfgBkAt:13.9 " 355 "NAME 'olcBkLloadMaxPDUPerCycle' " 356 "DESC 'Maximum number of PDUs to handle in a single cycle' " 357 "EQUALITY integerMatch " 358 "SYNTAX OMsInteger " 359 "SINGLE-VALUE )", 360 NULL, NULL 361 }, 362 { "feature", "name", 2, 0, 0, 363 ARG_MAGIC|CFG_FEATURE, 364 &config_feature, 365 "( OLcfgBkAt:13.10 " 366 "NAME 'olcBkLloadFeature' " 367 "DESC 'Lload features enabled' " 368 "EQUALITY caseIgnoreMatch " 369 "SYNTAX OMsDirectoryString )", 370 NULL, NULL 371 }, 372 { "TLSCACertificate", NULL, 2, 2, 0, 373 #ifdef HAVE_TLS 374 CFG_TLS_CACERT|ARG_BINARY|ARG_MAGIC, 375 &config_tls_option, 376 #else 377 ARG_IGNORED, 378 NULL, 379 #endif 380 "( OLcfgBkAt:13.11 " 381 "NAME 'olcBkLloadTLSCACertificate' " 382 "DESC 'X.509 certificate, must use ;binary' " 383 "EQUALITY certificateExactMatch " 384 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 " 385 "SINGLE-VALUE )", 386 NULL, NULL 387 }, 388 { "TLSCACertificateFile", NULL, 2, 2, 0, 389 #ifdef HAVE_TLS 390 CFG_TLS_CA_FILE|ARG_STRING|ARG_MAGIC, 391 &config_tls_option, 392 #else 393 ARG_IGNORED, 394 NULL, 395 #endif 396 "( OLcfgBkAt:13.12 " 397 "NAME 'olcBkLloadTLSCACertificateFile' " 398 "EQUALITY caseExactMatch " 399 "SYNTAX OMsDirectoryString " 400 "SINGLE-VALUE )", 401 NULL, NULL 402 }, 403 { "TLSCACertificatePath", NULL, 2, 2, 0, 404 #ifdef HAVE_TLS 405 CFG_TLS_CA_PATH|ARG_STRING|ARG_MAGIC, 406 &config_tls_option, 407 #else 408 ARG_IGNORED, 409 NULL, 410 #endif 411 "( OLcfgBkAt:13.13 " 412 "NAME 'olcBkLloadTLSCACertificatePath' " 413 "EQUALITY caseExactMatch " 414 "SYNTAX OMsDirectoryString " 415 "SINGLE-VALUE )", 416 NULL, NULL 417 }, 418 { "TLSCertificate", NULL, 2, 2, 0, 419 #ifdef HAVE_TLS 420 CFG_TLS_CERT|ARG_BINARY|ARG_MAGIC, 421 &config_tls_option, 422 #else 423 ARG_IGNORED, 424 NULL, 425 #endif 426 "( OLcfgBkAt:13.14 " 427 "NAME 'olcBkLloadTLSCertificate' " 428 "DESC 'X.509 certificate, must use ;binary' " 429 "EQUALITY certificateExactMatch " 430 "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 " 431 "SINGLE-VALUE )", 432 NULL, NULL 433 }, 434 { "TLSCertificateFile", NULL, 2, 2, 0, 435 #ifdef HAVE_TLS 436 CFG_TLS_CERT_FILE|ARG_STRING|ARG_MAGIC, 437 &config_tls_option, 438 #else 439 ARG_IGNORED, 440 NULL, 441 #endif 442 "( OLcfgBkAt:13.15 " 443 "NAME 'olcBkLloadTLSCertificateFile' " 444 "EQUALITY caseExactMatch " 445 "SYNTAX OMsDirectoryString " 446 "SINGLE-VALUE )", 447 NULL, NULL 448 }, 449 { "TLSCertificateKey", NULL, 2, 2, 0, 450 #ifdef HAVE_TLS 451 CFG_TLS_KEY|ARG_BINARY|ARG_MAGIC, 452 &config_tls_option, 453 #else 454 ARG_IGNORED, 455 NULL, 456 #endif 457 "( OLcfgBkAt:13.16 " 458 "NAME 'olcBkLloadTLSCertificateKey' " 459 "DESC 'X.509 privateKey, must use ;binary' " 460 "EQUALITY privateKeyMatch " 461 "SYNTAX 1.2.840.113549.1.8.1.1 " 462 "SINGLE-VALUE )", 463 NULL, NULL 464 }, 465 { "TLSCertificateKeyFile", NULL, 2, 2, 0, 466 #ifdef HAVE_TLS 467 CFG_TLS_CERT_KEY|ARG_STRING|ARG_MAGIC, 468 &config_tls_option, 469 #else 470 ARG_IGNORED, 471 NULL, 472 #endif 473 "( OLcfgBkAt:13.17 " 474 "NAME 'olcBkLloadTLSCertificateKeyFile' " 475 "EQUALITY caseExactMatch " 476 "SYNTAX OMsDirectoryString " 477 "SINGLE-VALUE )", 478 NULL, NULL 479 }, 480 { "TLSCipherSuite", NULL, 2, 2, 0, 481 #ifdef HAVE_TLS 482 CFG_TLS_CIPHER|ARG_STRING|ARG_MAGIC, 483 &config_tls_option, 484 #else 485 ARG_IGNORED, 486 NULL, 487 #endif 488 "( OLcfgBkAt:13.18 " 489 "NAME 'olcBkLloadTLSCipherSuite' " 490 "EQUALITY caseExactMatch " 491 "SYNTAX OMsDirectoryString " 492 "SINGLE-VALUE )", 493 NULL, NULL 494 }, 495 { "TLSCRLCheck", NULL, 2, 2, 0, 496 #if defined(HAVE_TLS) && defined(HAVE_OPENSSL) 497 CFG_TLS_CRLCHECK|ARG_STRING|ARG_MAGIC, 498 &config_tls_config, 499 #else 500 ARG_IGNORED, 501 NULL, 502 #endif 503 "( OLcfgBkAt:13.19 " 504 "NAME 'olcBkLloadTLSCRLCheck' " 505 "EQUALITY caseIgnoreMatch " 506 "SYNTAX OMsDirectoryString " 507 "SINGLE-VALUE )", 508 NULL, NULL 509 }, 510 { "TLSCRLFile", NULL, 2, 2, 0, 511 #if defined(HAVE_GNUTLS) 512 CFG_TLS_CRL_FILE|ARG_STRING|ARG_MAGIC, 513 &config_tls_option, 514 #else 515 ARG_IGNORED, 516 NULL, 517 #endif 518 "( OLcfgBkAt:13.20 " 519 "NAME 'olcBkLloadTLSCRLFile' " 520 "EQUALITY caseExactMatch " 521 "SYNTAX OMsDirectoryString " 522 "SINGLE-VALUE )", 523 NULL, NULL 524 }, 525 { "TLSRandFile", NULL, 2, 2, 0, 526 #ifdef HAVE_TLS 527 CFG_TLS_RAND|ARG_STRING|ARG_MAGIC, 528 &config_tls_option, 529 #else 530 ARG_IGNORED, 531 NULL, 532 #endif 533 "( OLcfgBkAt:13.21 " 534 "NAME 'olcBkLloadTLSRandFile' " 535 "EQUALITY caseExactMatch " 536 "SYNTAX OMsDirectoryString " 537 "SINGLE-VALUE )", 538 NULL, NULL 539 }, 540 { "TLSVerifyClient", NULL, 2, 2, 0, 541 #ifdef HAVE_TLS 542 CFG_TLS_VERIFY|ARG_STRING|ARG_MAGIC, 543 &config_tls_config, 544 #else 545 ARG_IGNORED, 546 NULL, 547 #endif 548 "( OLcfgBkAt:13.22 " 549 "NAME 'olcBkLloadVerifyClient' " 550 "EQUALITY caseIgnoreMatch " 551 "SYNTAX OMsDirectoryString " 552 "SINGLE-VALUE )", 553 NULL, NULL 554 }, 555 { "TLSDHParamFile", NULL, 2, 2, 0, 556 #ifdef HAVE_TLS 557 CFG_TLS_DH_FILE|ARG_STRING|ARG_MAGIC, 558 &config_tls_option, 559 #else 560 ARG_IGNORED, 561 NULL, 562 #endif 563 "( OLcfgBkAt:13.23 " 564 "NAME 'olcBkLloadTLSDHParamFile' " 565 "EQUALITY caseExactMatch " 566 "SYNTAX OMsDirectoryString " 567 "SINGLE-VALUE )", 568 NULL, NULL 569 }, 570 { "TLSECName", NULL, 2, 2, 0, 571 #ifdef HAVE_TLS 572 CFG_TLS_ECNAME|ARG_STRING|ARG_MAGIC, 573 &config_tls_option, 574 #else 575 ARG_IGNORED, 576 NULL, 577 #endif 578 "( OLcfgBkAt:13.24 " 579 "NAME 'olcBkLloadTLSECName' " 580 "EQUALITY caseExactMatch " 581 "SYNTAX OMsDirectoryString " 582 "SINGLE-VALUE )", 583 NULL, NULL 584 }, 585 { "TLSProtocolMin", NULL, 2, 2, 0, 586 #ifdef HAVE_TLS 587 CFG_TLS_PROTOCOL_MIN|ARG_STRING|ARG_MAGIC, 588 &config_tls_config, 589 #else 590 ARG_IGNORED, 591 NULL, 592 #endif 593 "( OLcfgBkAt:13.25 " 594 "NAME 'olcBkLloadTLSProtocolMin' " 595 "EQUALITY caseIgnoreMatch " 596 "SYNTAX OMsDirectoryString " 597 "SINGLE-VALUE )", 598 NULL, NULL 599 }, 600 { "TLSShareSlapdCTX", NULL, 2, 2, 0, 601 #if defined(HAVE_TLS) && defined(BALANCER_MODULE) 602 CFG_TLS_SHARE_CTX|ARG_ON_OFF|ARG_MAGIC, 603 &config_share_tls_ctx, 604 #else 605 ARG_IGNORED, 606 NULL, 607 #endif 608 "( OLcfgBkAt:13.33 " 609 "NAME 'olcBkLloadTLSShareSlapdCTX' " 610 "DESC 'Share slapd TLS context (all other lloadd TLS options cease to take effect)' " 611 "EQUALITY booleanMatch " 612 "SYNTAX OMsBoolean " 613 "SINGLE-VALUE )", 614 NULL, NULL 615 }, 616 { "iotimeout", "ms timeout", 2, 2, 0, 617 ARG_UINT|ARG_MAGIC|CFG_IOTIMEOUT, 618 &config_generic, 619 "( OLcfgBkAt:13.26 " 620 "NAME 'olcBkLloadIOTimeout' " 621 "DESC 'I/O timeout threshold in miliseconds' " 622 "EQUALITY integerMatch " 623 "SYNTAX OMsInteger " 624 "SINGLE-VALUE )", 625 NULL, NULL 626 }, 627 { "client_max_pending", NULL, 2, 2, 0, 628 ARG_MAGIC|ARG_UINT|CFG_CLIENT_PENDING, 629 &config_generic, 630 "( OLcfgBkAt:13.35 " 631 "NAME 'olcBkLloadClientMaxPending' " 632 "DESC 'Maximum pending operations per client connection' " 633 "EQUALITY integerMatch " 634 "SYNTAX OMsInteger " 635 "SINGLE-VALUE )", 636 NULL, 637 { .v_uint = 0 } 638 }, 639 640 /* cn=config only options */ 641 #ifdef BALANCER_MODULE 642 { "", "uri", 2, 2, 0, 643 ARG_BERVAL|ARG_MAGIC|CFG_URI, 644 &backend_cf_gen, 645 "( OLcfgBkAt:13.27 " 646 "NAME 'olcBkLloadBackendUri' " 647 "DESC 'URI to contact the server on' " 648 "EQUALITY caseIgnoreMatch " 649 "SYNTAX OMsDirectoryString " 650 "SINGLE-VALUE )", 651 NULL, NULL 652 }, 653 { "", NULL, 2, 2, 0, 654 ARG_UINT|ARG_MAGIC|CFG_NUMCONNS, 655 &backend_cf_gen, 656 "( OLcfgBkAt:13.28 " 657 "NAME 'olcBkLloadNumconns' " 658 "DESC 'Number of regular connections to maintain' " 659 "EQUALITY integerMatch " 660 "SYNTAX OMsInteger " 661 "SINGLE-VALUE )", 662 NULL, NULL 663 }, 664 { "", NULL, 2, 2, 0, 665 ARG_UINT|ARG_MAGIC|CFG_BINDCONNS, 666 &backend_cf_gen, 667 "( OLcfgBkAt:13.29 " 668 "NAME 'olcBkLloadBindconns' " 669 "DESC 'Number of bind connections to maintain' " 670 "EQUALITY integerMatch " 671 "SYNTAX OMsInteger " 672 "SINGLE-VALUE )", 673 NULL, NULL 674 }, 675 { "", NULL, 2, 2, 0, 676 ARG_UINT|ARG_MAGIC|CFG_RETRY, 677 &backend_cf_gen, 678 "( OLcfgBkAt:13.30 " 679 "NAME 'olcBkLloadRetry' " 680 "DESC 'Number of seconds to wait before trying to reconnect' " 681 "EQUALITY integerMatch " 682 "SYNTAX OMsInteger " 683 "SINGLE-VALUE )", 684 NULL, NULL 685 }, 686 { "", NULL, 2, 2, 0, 687 ARG_UINT|ARG_MAGIC|CFG_MAX_PENDING_OPS, 688 &backend_cf_gen, 689 "( OLcfgBkAt:13.31 " 690 "NAME 'olcBkLloadMaxPendingOps' " 691 "DESC 'Maximum number of pending operations for this backend' " 692 "EQUALITY integerMatch " 693 "SYNTAX OMsInteger " 694 "SINGLE-VALUE )", 695 NULL, NULL 696 }, 697 { "", NULL, 2, 2, 0, 698 ARG_UINT|ARG_MAGIC|CFG_MAX_PENDING_CONNS, 699 &backend_cf_gen, 700 "( OLcfgBkAt:13.32 " 701 "NAME 'olcBkLloadMaxPendingConns' " 702 "DESC 'Maximum number of pending operations on each connection' " 703 "EQUALITY integerMatch " 704 "SYNTAX OMsInteger " 705 "SINGLE-VALUE )", 706 NULL, NULL 707 }, 708 { "", NULL, 2, 2, 0, 709 ARG_BERVAL|ARG_MAGIC|CFG_STARTTLS, 710 &backend_cf_gen, 711 "( OLcfgBkAt:13.34 " 712 "NAME 'olcBkLloadStartTLS' " 713 "DESC 'Whether StartTLS should be attempted on the connection' " 714 "EQUALITY caseIgnoreMatch " 715 "SYNTAX OMsDirectoryString " 716 "SINGLE-VALUE )", 717 NULL, NULL 718 }, 719 #endif /* BALANCER_MODULE */ 720 721 { NULL, NULL, 0, 0, 0, ARG_IGNORED, NULL } 722 }; 723 724 #ifdef BALANCER_MODULE 725 static ConfigCfAdd lload_cfadd; 726 static ConfigLDAPadd lload_backend_ldadd; 727 #ifdef SLAP_CONFIG_DELETE 728 static ConfigLDAPdel lload_backend_lddel; 729 #endif /* SLAP_CONFIG_DELETE */ 730 731 static ConfigOCs lloadocs[] = { 732 { "( OLcfgBkOc:13.1 " 733 "NAME 'olcBkLloadConfig' " 734 "DESC 'Lload backend configuration' " 735 "SUP olcBackendConfig " 736 "MUST ( olcBkLloadBindconf " 737 "$ olcBkLloadIOThreads " 738 "$ olcBkLloadListen " 739 "$ olcBkLloadSockbufMaxClient " 740 "$ olcBkLloadSockbufMaxUpstream " 741 "$ olcBkLloadMaxPDUPerCycle " 742 "$ olcBkLloadIOTimeout ) " 743 "MAY ( olcBkLloadFeature " 744 "$ olcBkLloadTcpBuffer " 745 "$ olcBkLloadTLSCACertificateFile " 746 "$ olcBkLloadTLSCACertificatePath " 747 "$ olcBkLloadTLSCertificateFile " 748 "$ olcBkLloadTLSCertificateKeyFile " 749 "$ olcBkLloadTLSCipherSuite " 750 "$ olcBkLloadTLSCRLCheck " 751 "$ olcBkLloadTLSRandFile " 752 "$ olcBkLloadVerifyClient " 753 "$ olcBkLloadTLSDHParamFile " 754 "$ olcBkLloadTLSECName " 755 "$ olcBkLloadTLSProtocolMin " 756 "$ olcBkLloadTLSCRLFile " 757 "$ olcBkLloadTLSShareSlapdCTX " 758 "$ olcBkLloadClientMaxPending " 759 ") )", 760 Cft_Backend, config_back_cf_table, 761 NULL, 762 lload_cfadd, 763 }, 764 { "( OLcfgBkOc:13.2 " 765 "NAME 'olcBkLloadBackendConfig' " 766 "DESC 'Lload backend server configuration' " 767 "SUP olcConfig STRUCTURAL " 768 "MUST ( cn " 769 "$ olcBkLloadBackendUri " 770 "$ olcBkLloadNumconns " 771 "$ olcBkLloadBindconns " 772 "$ olcBkLloadRetry " 773 "$ olcBkLloadMaxPendingOps " 774 "$ olcBkLloadMaxPendingConns ) " 775 "MAY ( olcBkLloadStartTLS " 776 ") )", 777 Cft_Misc, config_back_cf_table, 778 lload_backend_ldadd, 779 NULL, 780 #ifdef SLAP_CONFIG_DELETE 781 lload_backend_lddel, 782 #endif /* SLAP_CONFIG_DELETE */ 783 }, 784 { NULL, 0, NULL } 785 }; 786 #endif /* BALANCER_MODULE */ 787 788 static int 789 config_generic( ConfigArgs *c ) 790 { 791 enum lcf_daemon flag = 0; 792 int rc = LDAP_SUCCESS; 793 794 if ( c->op == SLAP_CONFIG_EMIT ) { 795 switch ( c->type ) { 796 case CFG_IOTHREADS: 797 c->value_uint = lload_daemon_threads; 798 break; 799 case CFG_LISTEN_URI: { 800 LloadListener **ll = lloadd_get_listeners(); 801 struct berval bv = BER_BVNULL; 802 803 for ( ; ll && *ll; ll++ ) { 804 /* The same url could have spawned several consecutive 805 * listeners */ 806 if ( !BER_BVISNULL( &bv ) && 807 !ber_bvcmp( &bv, &(*ll)->sl_url ) ) { 808 continue; 809 } 810 ber_dupbv( &bv, &(*ll)->sl_url ); 811 ber_bvarray_add( &c->rvalue_vals, &bv ); 812 } 813 } break; 814 case CFG_MAXBUF_CLIENT: 815 c->value_uint = sockbuf_max_incoming_client; 816 break; 817 case CFG_MAXBUF_UPSTREAM: 818 c->value_uint = sockbuf_max_incoming_upstream; 819 break; 820 case CFG_RESCOUNT: 821 c->value_uint = lload_conn_max_pdus_per_cycle; 822 break; 823 case CFG_IOTIMEOUT: 824 c->value_uint = 1000 * lload_write_timeout->tv_sec + 825 lload_write_timeout->tv_usec / 1000; 826 break; 827 case CFG_CLIENT_PENDING: 828 c->value_uint = lload_client_max_pending; 829 break; 830 default: 831 rc = 1; 832 break; 833 } 834 return rc; 835 836 } else if ( c->op == LDAP_MOD_DELETE ) { 837 /* We only need to worry about deletions to multi-value or MAY 838 * attributes that belong to the lloadd module - we don't have any at 839 * the moment */ 840 return rc; 841 } 842 843 lload_change.type = LLOAD_CHANGE_MODIFY; 844 lload_change.object = LLOAD_DAEMON; 845 846 switch ( c->type ) { 847 case CFG_CONCUR: 848 ldap_pvt_thread_set_concurrency( c->value_uint ); 849 break; 850 case CFG_LISTEN: 851 if ( lloadd_inited ) { 852 snprintf( c->cr_msg, sizeof(c->cr_msg), 853 "listen directive can only be specified once" ); 854 ch_free( c->value_string ); 855 return 1; 856 } 857 if ( lloadd_listeners_init( c->value_string ) ) { 858 snprintf( c->cr_msg, sizeof(c->cr_msg), 859 "could not open one of the listener sockets: %s", 860 c->value_string ); 861 ch_free( c->value_string ); 862 return 1; 863 } 864 ch_free( c->value_string ); 865 break; 866 case CFG_LISTEN_URI: { 867 LDAPURLDesc *lud; 868 LloadListener *l; 869 870 if ( ldap_url_parse_ext( 871 c->line, &lud, LDAP_PVT_URL_PARSE_DEF_PORT ) ) { 872 snprintf( c->cr_msg, sizeof(c->cr_msg), 873 "string %s could not be parsed as an LDAP URL", 874 c->line ); 875 goto fail; 876 } 877 878 /* A sanity check, although it will not catch everything */ 879 if ( ( l = lload_config_check_my_url( c->line, lud ) ) ) { 880 snprintf( c->cr_msg, sizeof(c->cr_msg), 881 "Load Balancer already configured to listen on %s " 882 "(while adding %s)", 883 l->sl_url.bv_val, c->line ); 884 goto fail; 885 } 886 887 if ( !lloadd_inited ) { 888 if ( lload_open_new_listener( c->line, lud ) ) { 889 snprintf( c->cr_msg, sizeof(c->cr_msg), 890 "could not open a listener for %s", c->line ); 891 goto fail; 892 } 893 } else { 894 snprintf( c->cr_msg, sizeof(c->cr_msg), 895 "listener changes will not take effect until restart: " 896 "%s", 897 c->line ); 898 Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg ); 899 } 900 } break; 901 case CFG_THREADS: 902 if ( c->value_uint < 2 ) { 903 snprintf( c->cr_msg, sizeof(c->cr_msg), 904 "threads=%d smaller than minimum value 2", 905 c->value_uint ); 906 goto fail; 907 908 } else if ( c->value_uint > 2 * SLAP_MAX_WORKER_THREADS ) { 909 snprintf( c->cr_msg, sizeof(c->cr_msg), 910 "warning, threads=%d larger than twice the default " 911 "(2*%d=%d); YMMV", 912 c->value_uint, SLAP_MAX_WORKER_THREADS, 913 2 * SLAP_MAX_WORKER_THREADS ); 914 Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg ); 915 } 916 if ( slapMode & SLAP_SERVER_MODE ) 917 ldap_pvt_thread_pool_maxthreads( 918 &connection_pool, c->value_uint ); 919 connection_pool_max = c->value_uint; /* save for reference */ 920 break; 921 922 case CFG_THREADQS: 923 if ( c->value_uint < 1 ) { 924 snprintf( c->cr_msg, sizeof(c->cr_msg), 925 "threadqueues=%d smaller than minimum value 1", 926 c->value_uint ); 927 goto fail; 928 } 929 if ( slapMode & SLAP_SERVER_MODE ) 930 ldap_pvt_thread_pool_queues( &connection_pool, c->value_uint ); 931 connection_pool_queues = c->value_uint; /* save for reference */ 932 break; 933 934 case CFG_IOTHREADS: { 935 int mask = 0; 936 /* use a power of two */ 937 while ( c->value_uint > 1 ) { 938 c->value_uint >>= 1; 939 mask <<= 1; 940 mask |= 1; 941 } 942 if ( !lloadd_inited ) { 943 lload_daemon_mask = mask; 944 lload_daemon_threads = mask + 1; 945 flag = LLOAD_DAEMON_MOD_THREADS; 946 } else { 947 snprintf( c->cr_msg, sizeof(c->cr_msg), 948 "io thread changes will not take effect until " 949 "restart" ); 950 Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg ); 951 } 952 } break; 953 954 case CFG_LOGFILE: { 955 if ( logfileName ) ch_free( logfileName ); 956 logfileName = c->value_string; 957 logfile = fopen( logfileName, "w" ); 958 if ( logfile ) lutil_debug_file( logfile ); 959 } break; 960 961 case CFG_RESCOUNT: 962 lload_conn_max_pdus_per_cycle = c->value_uint; 963 break; 964 965 case CFG_IOTIMEOUT: 966 if ( c->value_uint > 0 ) { 967 timeout_write_tv.tv_sec = c->value_uint / 1000; 968 timeout_write_tv.tv_usec = 1000 * ( c->value_uint % 1000 ); 969 lload_write_timeout = &timeout_write_tv; 970 } else { 971 lload_write_timeout = NULL; 972 } 973 break; 974 case CFG_MAXBUF_CLIENT: 975 sockbuf_max_incoming_client = c->value_uint; 976 break; 977 case CFG_MAXBUF_UPSTREAM: 978 sockbuf_max_incoming_upstream = c->value_uint; 979 break; 980 case CFG_CLIENT_PENDING: 981 lload_client_max_pending = c->value_uint; 982 break; 983 default: 984 Debug( LDAP_DEBUG_ANY, "%s: unknown CFG_TYPE %d\n", 985 c->log, c->type ); 986 return 1; 987 } 988 989 lload_change.flags.daemon |= flag; 990 991 return 0; 992 993 fail: 994 if ( lload_change.type == LLOAD_CHANGE_ADD ) { 995 /* Abort the ADD */ 996 lload_change.type = LLOAD_CHANGE_DEL; 997 } 998 999 Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg ); 1000 return 1; 1001 } 1002 1003 static int 1004 lload_backend_finish( ConfigArgs *ca ) 1005 { 1006 LloadBackend *b = ca->ca_private; 1007 1008 if ( ca->reply.err != LDAP_SUCCESS ) { 1009 /* Not reached since cleanup is only called on success */ 1010 goto fail; 1011 } 1012 1013 if ( b->b_numconns <= 0 || b->b_numbindconns <= 0 ) { 1014 Debug( LDAP_DEBUG_ANY, "lload_backend_finish: " 1015 "invalid connection pool configuration\n" ); 1016 goto fail; 1017 } 1018 1019 if ( b->b_retry_timeout < 0 ) { 1020 Debug( LDAP_DEBUG_ANY, "lload_backend_finish: " 1021 "invalid retry timeout configuration\n" ); 1022 goto fail; 1023 } 1024 1025 b->b_retry_tv.tv_sec = b->b_retry_timeout / 1000; 1026 b->b_retry_tv.tv_usec = ( b->b_retry_timeout % 1000 ) * 1000; 1027 1028 /* daemon_base is only allocated after initial configuration happens, those 1029 * events are allocated on startup, we only deal with online Adds */ 1030 if ( !b->b_retry_event && daemon_base ) { 1031 struct event *event; 1032 assert( CONFIG_ONLINE_ADD( ca ) ); 1033 event = evtimer_new( daemon_base, backend_connect, b ); 1034 if ( !event ) { 1035 Debug( LDAP_DEBUG_ANY, "lload_backend_finish: " 1036 "failed to allocate retry event\n" ); 1037 goto fail; 1038 } 1039 b->b_retry_event = event; 1040 } 1041 1042 return LDAP_SUCCESS; 1043 1044 fail: 1045 if ( lload_change.type == LLOAD_CHANGE_ADD ) { 1046 /* Abort the ADD */ 1047 lload_change.type = LLOAD_CHANGE_DEL; 1048 } 1049 1050 lload_backend_destroy( b ); 1051 return -1; 1052 } 1053 1054 static LloadBackend * 1055 backend_alloc( void ) 1056 { 1057 LloadBackend *b; 1058 1059 b = ch_calloc( 1, sizeof(LloadBackend) ); 1060 1061 LDAP_CIRCLEQ_INIT( &b->b_conns ); 1062 LDAP_CIRCLEQ_INIT( &b->b_bindconns ); 1063 LDAP_CIRCLEQ_INIT( &b->b_preparing ); 1064 1065 b->b_numconns = 1; 1066 b->b_numbindconns = 1; 1067 1068 b->b_retry_timeout = 5000; 1069 1070 ldap_pvt_thread_mutex_init( &b->b_mutex ); 1071 1072 LDAP_CIRCLEQ_INSERT_TAIL( &backend, b, b_next ); 1073 return b; 1074 } 1075 1076 static int 1077 backend_config_url( LloadBackend *b, struct berval *uri ) 1078 { 1079 LDAPURLDesc *lud = NULL; 1080 char *host = NULL; 1081 int rc, proto, tls = b->b_tls_conf; 1082 1083 /* Effect no changes until we've checked everything */ 1084 1085 rc = ldap_url_parse_ext( uri->bv_val, &lud, LDAP_PVT_URL_PARSE_DEF_PORT ); 1086 if ( rc != LDAP_URL_SUCCESS ) { 1087 Debug( LDAP_DEBUG_ANY, "backend_config_url: " 1088 "listen URL \"%s\" parse error=%d\n", 1089 uri->bv_val, rc ); 1090 return -1; 1091 } 1092 1093 if ( ldap_pvt_url_scheme2tls( lud->lud_scheme ) ) { 1094 #ifdef HAVE_TLS 1095 /* Specifying ldaps:// overrides starttls= settings */ 1096 tls = LLOAD_LDAPS; 1097 #else /* ! HAVE_TLS */ 1098 1099 Debug( LDAP_DEBUG_ANY, "backend_config_url: " 1100 "TLS not supported (%s)\n", 1101 uri->bv_val ); 1102 rc = -1; 1103 goto done; 1104 #endif /* ! HAVE_TLS */ 1105 } 1106 1107 proto = ldap_pvt_url_scheme2proto( lud->lud_scheme ); 1108 if ( proto == LDAP_PROTO_IPC ) { 1109 #ifdef LDAP_PF_LOCAL 1110 if ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) { 1111 host = LDAPI_SOCK; 1112 } 1113 #else /* ! LDAP_PF_LOCAL */ 1114 1115 Debug( LDAP_DEBUG_ANY, "backend_config_url: " 1116 "URL scheme not supported: %s", 1117 url ); 1118 rc = -1; 1119 goto done; 1120 #endif /* ! LDAP_PF_LOCAL */ 1121 } else { 1122 if ( lud->lud_host == NULL || lud->lud_host[0] == '\0' ) { 1123 Debug( LDAP_DEBUG_ANY, "backend_config_url: " 1124 "backend url missing hostname: '%s'\n", 1125 uri->bv_val ); 1126 rc = -1; 1127 goto done; 1128 } 1129 } 1130 if ( !host ) { 1131 host = lud->lud_host; 1132 } 1133 1134 if ( b->b_host ) { 1135 ch_free( b->b_host ); 1136 } 1137 1138 b->b_proto = proto; 1139 b->b_tls = tls; 1140 b->b_port = lud->lud_port; 1141 b->b_host = ch_strdup( host ); 1142 1143 done: 1144 ldap_free_urldesc( lud ); 1145 return rc; 1146 } 1147 1148 static int 1149 config_backend( ConfigArgs *c ) 1150 { 1151 LloadBackend *b; 1152 int i, rc = 0; 1153 1154 b = backend_alloc(); 1155 1156 for ( i = 1; i < c->argc; i++ ) { 1157 if ( lload_backend_parse( c->argv[i], b ) ) { 1158 Debug( LDAP_DEBUG_ANY, "config_backend: " 1159 "error parsing backend configuration item '%s'\n", 1160 c->argv[i] ); 1161 return -1; 1162 } 1163 } 1164 1165 if ( BER_BVISNULL( &b->b_uri ) ) { 1166 Debug( LDAP_DEBUG_ANY, "config_backend: " 1167 "backend address not specified\n" ); 1168 rc = -1; 1169 goto done; 1170 } 1171 1172 if ( backend_config_url( b, &b->b_uri ) ) { 1173 rc = -1; 1174 goto done; 1175 } 1176 1177 c->ca_private = b; 1178 rc = lload_backend_finish( c ); 1179 done: 1180 if ( rc ) { 1181 ch_free( b ); 1182 } 1183 return rc; 1184 } 1185 1186 static int 1187 config_bindconf( ConfigArgs *c ) 1188 { 1189 int i; 1190 1191 if ( c->op == SLAP_CONFIG_EMIT ) { 1192 struct berval bv; 1193 1194 lload_bindconf_unparse( &bindconf, &bv ); 1195 1196 for ( i = 0; isspace( (unsigned char)bv.bv_val[i] ); i++ ) 1197 /* count spaces */; 1198 1199 if ( i ) { 1200 bv.bv_len -= i; 1201 AC_MEMCPY( bv.bv_val, &bv.bv_val[i], bv.bv_len + 1 ); 1202 } 1203 1204 value_add_one( &c->rvalue_vals, &bv ); 1205 ber_memfree( bv.bv_val ); 1206 return LDAP_SUCCESS; 1207 } else if ( c->op == LDAP_MOD_DELETE ) { 1208 /* It's a MUST single-valued attribute, noop for now */ 1209 lload_bindconf_free( &bindconf ); 1210 return LDAP_SUCCESS; 1211 } 1212 1213 lload_change.type = LLOAD_CHANGE_MODIFY; 1214 lload_change.object = LLOAD_DAEMON; 1215 lload_change.flags.daemon |= LLOAD_DAEMON_MOD_BINDCONF; 1216 1217 for ( i = 1; i < c->argc; i++ ) { 1218 if ( lload_bindconf_parse( c->argv[i], &bindconf ) ) { 1219 Debug( LDAP_DEBUG_ANY, "config_bindconf: " 1220 "error parsing backend configuration item '%s'\n", 1221 c->argv[i] ); 1222 return -1; 1223 } 1224 } 1225 1226 if ( bindconf.sb_method == LDAP_AUTH_SASL ) { 1227 #ifndef HAVE_CYRUS_SASL 1228 Debug( LDAP_DEBUG_ANY, "config_bindconf: " 1229 "no sasl support available\n" ); 1230 return -1; 1231 #endif 1232 } 1233 1234 if ( !BER_BVISNULL( &bindconf.sb_authzId ) ) { 1235 ber_dupbv( &lloadd_identity, &bindconf.sb_authzId ); 1236 } else if ( !BER_BVISNULL( &bindconf.sb_authcId ) ) { 1237 ber_dupbv( &lloadd_identity, &bindconf.sb_authcId ); 1238 } else if ( !BER_BVISNULL( &bindconf.sb_binddn ) ) { 1239 char *ptr; 1240 1241 lloadd_identity.bv_len = STRLENOF("dn:") + bindconf.sb_binddn.bv_len; 1242 lloadd_identity.bv_val = ch_malloc( lloadd_identity.bv_len + 1 ); 1243 1244 ptr = lutil_strcopy( lloadd_identity.bv_val, "dn:" ); 1245 ptr = lutil_strncopy( 1246 ptr, bindconf.sb_binddn.bv_val, bindconf.sb_binddn.bv_len ); 1247 *ptr = '\0'; 1248 } 1249 1250 if ( bindconf.sb_timeout_api ) { 1251 timeout_api_tv.tv_sec = bindconf.sb_timeout_api; 1252 lload_timeout_api = &timeout_api_tv; 1253 if ( lload_timeout_event ) { 1254 event_add( lload_timeout_event, lload_timeout_api ); 1255 } 1256 } else { 1257 lload_timeout_api = NULL; 1258 if ( lload_timeout_event ) { 1259 event_del( lload_timeout_event ); 1260 } 1261 } 1262 1263 if ( bindconf.sb_timeout_net ) { 1264 timeout_net_tv.tv_sec = bindconf.sb_timeout_net; 1265 lload_timeout_net = &timeout_net_tv; 1266 } else { 1267 lload_timeout_net = NULL; 1268 } 1269 1270 #ifdef HAVE_TLS 1271 if ( bindconf.sb_tls_do_init ) { 1272 lload_bindconf_tls_set( &bindconf, lload_tls_backend_ld ); 1273 } 1274 #endif /* HAVE_TLS */ 1275 return 0; 1276 } 1277 1278 static int 1279 config_fname( ConfigArgs *c ) 1280 { 1281 return 0; 1282 } 1283 1284 /* 1285 * [listener=<listener>] [{read|write}=]<size> 1286 */ 1287 1288 #ifdef LDAP_TCP_BUFFER 1289 static BerVarray tcp_buffer; 1290 int tcp_buffer_num; 1291 1292 #define SLAP_TCP_RMEM ( 0x1U ) 1293 #define SLAP_TCP_WMEM ( 0x2U ) 1294 1295 static int 1296 tcp_buffer_parse( 1297 struct berval *val, 1298 int argc, 1299 char **argv, 1300 int *size, 1301 int *rw, 1302 LloadListener **l ) 1303 { 1304 int i, rc = LDAP_SUCCESS; 1305 LDAPURLDesc *lud = NULL; 1306 char *ptr; 1307 1308 if ( val != NULL && argv == NULL ) { 1309 char *s = val->bv_val; 1310 1311 argv = ldap_str2charray( s, " \t" ); 1312 if ( argv == NULL ) { 1313 return LDAP_OTHER; 1314 } 1315 } 1316 1317 i = 0; 1318 if ( strncasecmp( argv[i], "listener=", STRLENOF("listener=") ) == 0 ) { 1319 char *url = argv[i] + STRLENOF("listener="); 1320 1321 if ( ldap_url_parse_ext( url, &lud, LDAP_PVT_URL_PARSE_DEF_PORT ) ) { 1322 rc = LDAP_INVALID_SYNTAX; 1323 goto done; 1324 } 1325 1326 *l = lload_config_check_my_url( url, lud ); 1327 if ( *l == NULL ) { 1328 rc = LDAP_NO_SUCH_ATTRIBUTE; 1329 goto done; 1330 } 1331 1332 i++; 1333 } 1334 1335 ptr = argv[i]; 1336 if ( strncasecmp( ptr, "read=", STRLENOF("read=") ) == 0 ) { 1337 *rw |= SLAP_TCP_RMEM; 1338 ptr += STRLENOF("read="); 1339 1340 } else if ( strncasecmp( ptr, "write=", STRLENOF("write=") ) == 0 ) { 1341 *rw |= SLAP_TCP_WMEM; 1342 ptr += STRLENOF("write="); 1343 1344 } else { 1345 *rw |= ( SLAP_TCP_RMEM | SLAP_TCP_WMEM ); 1346 } 1347 1348 /* accept any base */ 1349 if ( lutil_atoix( size, ptr, 0 ) ) { 1350 rc = LDAP_INVALID_SYNTAX; 1351 goto done; 1352 } 1353 1354 done:; 1355 if ( val != NULL && argv != NULL ) { 1356 ldap_charray_free( argv ); 1357 } 1358 1359 if ( lud != NULL ) { 1360 ldap_free_urldesc( lud ); 1361 } 1362 1363 return rc; 1364 } 1365 1366 #ifdef BALANCER_MODULE 1367 static int 1368 tcp_buffer_delete_one( struct berval *val ) 1369 { 1370 int rc = 0; 1371 int size = -1, rw = 0; 1372 LloadListener *l = NULL; 1373 1374 rc = tcp_buffer_parse( val, 0, NULL, &size, &rw, &l ); 1375 if ( rc != 0 ) { 1376 return rc; 1377 } 1378 1379 if ( l != NULL ) { 1380 int i; 1381 LloadListener **ll = lloadd_get_listeners(); 1382 1383 for ( i = 0; ll[i] != NULL; i++ ) { 1384 if ( ll[i] == l ) break; 1385 } 1386 1387 if ( ll[i] == NULL ) { 1388 return LDAP_NO_SUCH_ATTRIBUTE; 1389 } 1390 1391 if ( rw & SLAP_TCP_RMEM ) l->sl_tcp_rmem = -1; 1392 if ( rw & SLAP_TCP_WMEM ) l->sl_tcp_wmem = -1; 1393 1394 for ( i++; ll[i] != NULL && bvmatch( &l->sl_url, &ll[i]->sl_url ); 1395 i++ ) { 1396 if ( rw & SLAP_TCP_RMEM ) ll[i]->sl_tcp_rmem = -1; 1397 if ( rw & SLAP_TCP_WMEM ) ll[i]->sl_tcp_wmem = -1; 1398 } 1399 1400 } else { 1401 /* NOTE: this affects listeners without a specific setting, 1402 * does not reset all listeners. If a listener without 1403 * specific settings was assigned a buffer because of 1404 * a global setting, it will not be reset. In any case, 1405 * buffer changes will only take place at restart. */ 1406 if ( rw & SLAP_TCP_RMEM ) slapd_tcp_rmem = -1; 1407 if ( rw & SLAP_TCP_WMEM ) slapd_tcp_wmem = -1; 1408 } 1409 1410 return rc; 1411 } 1412 1413 static int 1414 tcp_buffer_delete( BerVarray vals ) 1415 { 1416 int i; 1417 1418 for ( i = 0; !BER_BVISNULL( &vals[i] ); i++ ) { 1419 tcp_buffer_delete_one( &vals[i] ); 1420 } 1421 1422 return 0; 1423 } 1424 #endif /* BALANCER_MODULE */ 1425 1426 static int 1427 tcp_buffer_unparse( int size, int rw, LloadListener *l, struct berval *val ) 1428 { 1429 char buf[sizeof("2147483648")], *ptr; 1430 1431 /* unparse for later use */ 1432 val->bv_len = snprintf( buf, sizeof(buf), "%d", size ); 1433 if ( l != NULL ) { 1434 val->bv_len += STRLENOF( "listener=" 1435 " " ) + 1436 l->sl_url.bv_len; 1437 } 1438 1439 if ( rw != ( SLAP_TCP_RMEM | SLAP_TCP_WMEM ) ) { 1440 if ( rw & SLAP_TCP_RMEM ) { 1441 val->bv_len += STRLENOF("read="); 1442 } else if ( rw & SLAP_TCP_WMEM ) { 1443 val->bv_len += STRLENOF("write="); 1444 } 1445 } 1446 1447 val->bv_val = SLAP_MALLOC( val->bv_len + 1 ); 1448 1449 ptr = val->bv_val; 1450 1451 if ( l != NULL ) { 1452 ptr = lutil_strcopy( ptr, "listener=" ); 1453 ptr = lutil_strncopy( ptr, l->sl_url.bv_val, l->sl_url.bv_len ); 1454 *ptr++ = ' '; 1455 } 1456 1457 if ( rw != ( SLAP_TCP_RMEM | SLAP_TCP_WMEM ) ) { 1458 if ( rw & SLAP_TCP_RMEM ) { 1459 ptr = lutil_strcopy( ptr, "read=" ); 1460 } else if ( rw & SLAP_TCP_WMEM ) { 1461 ptr = lutil_strcopy( ptr, "write=" ); 1462 } 1463 } 1464 1465 ptr = lutil_strcopy( ptr, buf ); 1466 *ptr = '\0'; 1467 1468 assert( val->bv_val + val->bv_len == ptr ); 1469 1470 return LDAP_SUCCESS; 1471 } 1472 1473 static int 1474 tcp_buffer_add_one( int argc, char **argv ) 1475 { 1476 int rc = 0; 1477 int size = -1, rw = 0; 1478 LloadListener *l = NULL; 1479 1480 struct berval val; 1481 1482 /* parse */ 1483 rc = tcp_buffer_parse( NULL, argc, argv, &size, &rw, &l ); 1484 if ( rc != 0 ) { 1485 return rc; 1486 } 1487 1488 /* unparse for later use */ 1489 rc = tcp_buffer_unparse( size, rw, l, &val ); 1490 if ( rc != LDAP_SUCCESS ) { 1491 return rc; 1492 } 1493 1494 /* use parsed values */ 1495 if ( l != NULL ) { 1496 int i; 1497 LloadListener **ll = lloadd_get_listeners(); 1498 1499 for ( i = 0; ll[i] != NULL; i++ ) { 1500 if ( ll[i] == l ) break; 1501 } 1502 1503 if ( ll[i] == NULL ) { 1504 return LDAP_NO_SUCH_ATTRIBUTE; 1505 } 1506 1507 /* buffer only applies to TCP listeners; 1508 * we do not do any check here, and delegate them 1509 * to setsockopt(2) */ 1510 if ( rw & SLAP_TCP_RMEM ) l->sl_tcp_rmem = size; 1511 if ( rw & SLAP_TCP_WMEM ) l->sl_tcp_wmem = size; 1512 1513 for ( i++; ll[i] != NULL && bvmatch( &l->sl_url, &ll[i]->sl_url ); 1514 i++ ) { 1515 if ( rw & SLAP_TCP_RMEM ) ll[i]->sl_tcp_rmem = size; 1516 if ( rw & SLAP_TCP_WMEM ) ll[i]->sl_tcp_wmem = size; 1517 } 1518 1519 } else { 1520 /* NOTE: this affects listeners without a specific setting, 1521 * does not set all listeners */ 1522 if ( rw & SLAP_TCP_RMEM ) slapd_tcp_rmem = size; 1523 if ( rw & SLAP_TCP_WMEM ) slapd_tcp_wmem = size; 1524 } 1525 1526 tcp_buffer = SLAP_REALLOC( 1527 tcp_buffer, sizeof(struct berval) * ( tcp_buffer_num + 2 ) ); 1528 /* append */ 1529 tcp_buffer[tcp_buffer_num] = val; 1530 1531 tcp_buffer_num++; 1532 BER_BVZERO( &tcp_buffer[tcp_buffer_num] ); 1533 1534 return rc; 1535 } 1536 1537 static int 1538 config_tcp_buffer( ConfigArgs *c ) 1539 { 1540 int rc = LDAP_SUCCESS; 1541 1542 #ifdef BALANCER_MODULE 1543 if ( c->op == SLAP_CONFIG_EMIT ) { 1544 if ( tcp_buffer == NULL || BER_BVISNULL( &tcp_buffer[0] ) ) { 1545 return 1; 1546 } 1547 value_add( &c->rvalue_vals, tcp_buffer ); 1548 value_add( &c->rvalue_nvals, tcp_buffer ); 1549 1550 return 0; 1551 } else if ( c->op == LDAP_MOD_DELETE ) { 1552 if ( !c->line ) { 1553 tcp_buffer_delete( tcp_buffer ); 1554 ber_bvarray_free( tcp_buffer ); 1555 tcp_buffer = NULL; 1556 tcp_buffer_num = 0; 1557 1558 } else { 1559 int size = -1, rw = 0; 1560 LloadListener *l = NULL; 1561 1562 struct berval val = BER_BVNULL; 1563 1564 int i; 1565 1566 if ( tcp_buffer_num == 0 ) { 1567 return 1; 1568 } 1569 1570 /* parse */ 1571 rc = tcp_buffer_parse( 1572 NULL, c->argc - 1, &c->argv[1], &size, &rw, &l ); 1573 if ( rc != 0 ) { 1574 return 1; 1575 } 1576 1577 /* unparse for later use */ 1578 rc = tcp_buffer_unparse( size, rw, l, &val ); 1579 if ( rc != LDAP_SUCCESS ) { 1580 return 1; 1581 } 1582 1583 for ( i = 0; !BER_BVISNULL( &tcp_buffer[i] ); i++ ) { 1584 if ( bvmatch( &tcp_buffer[i], &val ) ) { 1585 break; 1586 } 1587 } 1588 1589 if ( BER_BVISNULL( &tcp_buffer[i] ) ) { 1590 /* not found */ 1591 rc = 1; 1592 goto done; 1593 } 1594 1595 tcp_buffer_delete_one( &tcp_buffer[i] ); 1596 ber_memfree( tcp_buffer[i].bv_val ); 1597 for ( ; i < tcp_buffer_num; i++ ) { 1598 tcp_buffer[i] = tcp_buffer[i + 1]; 1599 } 1600 tcp_buffer_num--; 1601 1602 done:; 1603 if ( !BER_BVISNULL( &val ) ) { 1604 SLAP_FREE(val.bv_val); 1605 } 1606 } 1607 1608 return rc; 1609 } 1610 #endif /* BALANCER_MODULE */ 1611 1612 rc = tcp_buffer_add_one( c->argc - 1, &c->argv[1] ); 1613 if ( rc ) { 1614 snprintf( c->cr_msg, sizeof(c->cr_msg), "<%s> unable to add value #%d", 1615 c->argv[0], tcp_buffer_num ); 1616 Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg ); 1617 return 1; 1618 } 1619 1620 return 0; 1621 } 1622 #endif /* LDAP_TCP_BUFFER */ 1623 1624 static int 1625 config_restrict( ConfigArgs *c ) 1626 { 1627 slap_mask_t restrictops = 0; 1628 int i; 1629 slap_verbmasks restrictable_ops[] = { 1630 { BER_BVC("bind"), SLAP_RESTRICT_OP_BIND }, 1631 { BER_BVC("add"), SLAP_RESTRICT_OP_ADD }, 1632 { BER_BVC("modify"), SLAP_RESTRICT_OP_MODIFY }, 1633 { BER_BVC("rename"), SLAP_RESTRICT_OP_RENAME }, 1634 { BER_BVC("modrdn"), 0 }, 1635 { BER_BVC("delete"), SLAP_RESTRICT_OP_DELETE }, 1636 { BER_BVC("search"), SLAP_RESTRICT_OP_SEARCH }, 1637 { BER_BVC("compare"), SLAP_RESTRICT_OP_COMPARE }, 1638 { BER_BVC("read"), SLAP_RESTRICT_OP_READS }, 1639 { BER_BVC("write"), SLAP_RESTRICT_OP_WRITES }, 1640 { BER_BVC("extended"), SLAP_RESTRICT_OP_EXTENDED }, 1641 { BER_BVC("extended=" LDAP_EXOP_START_TLS), SLAP_RESTRICT_EXOP_START_TLS }, 1642 { BER_BVC("extended=" LDAP_EXOP_MODIFY_PASSWD), SLAP_RESTRICT_EXOP_MODIFY_PASSWD }, 1643 { BER_BVC("extended=" LDAP_EXOP_X_WHO_AM_I), SLAP_RESTRICT_EXOP_WHOAMI }, 1644 { BER_BVC("extended=" LDAP_EXOP_X_CANCEL), SLAP_RESTRICT_EXOP_CANCEL }, 1645 { BER_BVC("all"), SLAP_RESTRICT_OP_ALL }, 1646 { BER_BVNULL, 0 } 1647 }; 1648 1649 i = verbs_to_mask( c->argc, c->argv, restrictable_ops, &restrictops ); 1650 if ( i ) { 1651 snprintf( c->cr_msg, sizeof(c->cr_msg), "<%s> unknown operation", 1652 c->argv[0] ); 1653 Debug( LDAP_DEBUG_ANY, "%s: %s %s\n", 1654 c->log, c->cr_msg, c->argv[i] ); 1655 return 1; 1656 } 1657 if ( restrictops & SLAP_RESTRICT_OP_EXTENDED ) 1658 restrictops &= ~SLAP_RESTRICT_EXOP_MASK; 1659 return 0; 1660 } 1661 1662 static slap_verbmasks *loglevel_ops; 1663 1664 static int 1665 loglevel_init( void ) 1666 { 1667 slap_verbmasks lo[] = { 1668 { BER_BVC("Any"), (slap_mask_t)LDAP_DEBUG_ANY }, 1669 { BER_BVC("Trace"), LDAP_DEBUG_TRACE }, 1670 { BER_BVC("Packets"), LDAP_DEBUG_PACKETS }, 1671 { BER_BVC("Args"), LDAP_DEBUG_ARGS }, 1672 { BER_BVC("Conns"), LDAP_DEBUG_CONNS }, 1673 { BER_BVC("BER"), LDAP_DEBUG_BER }, 1674 { BER_BVC("Filter"), LDAP_DEBUG_FILTER }, 1675 { BER_BVC("Config"), LDAP_DEBUG_CONFIG }, 1676 { BER_BVC("ACL"), LDAP_DEBUG_ACL }, 1677 { BER_BVC("Stats"), LDAP_DEBUG_STATS }, 1678 { BER_BVC("Stats2"), LDAP_DEBUG_STATS2 }, 1679 { BER_BVC("Shell"), LDAP_DEBUG_SHELL }, 1680 { BER_BVC("Parse"), LDAP_DEBUG_PARSE }, 1681 { BER_BVC("Sync"), LDAP_DEBUG_SYNC }, 1682 { BER_BVC("None"), LDAP_DEBUG_NONE }, 1683 { BER_BVNULL, 0 } 1684 }; 1685 1686 return slap_verbmasks_init( &loglevel_ops, lo ); 1687 } 1688 1689 static void 1690 loglevel_destroy( void ) 1691 { 1692 if ( loglevel_ops ) { 1693 (void)slap_verbmasks_destroy( loglevel_ops ); 1694 } 1695 loglevel_ops = NULL; 1696 } 1697 1698 int 1699 str2loglevel( const char *s, int *l ) 1700 { 1701 int i; 1702 1703 if ( loglevel_ops == NULL ) { 1704 loglevel_init(); 1705 } 1706 1707 i = verb_to_mask( s, loglevel_ops ); 1708 1709 if ( BER_BVISNULL( &loglevel_ops[i].word ) ) { 1710 return -1; 1711 } 1712 1713 *l = loglevel_ops[i].mask; 1714 1715 return 0; 1716 } 1717 1718 int 1719 loglevel2bvarray( int l, BerVarray *bva ) 1720 { 1721 if ( loglevel_ops == NULL ) { 1722 loglevel_init(); 1723 } 1724 1725 if ( l == 0 ) { 1726 struct berval bv = BER_BVC("0"); 1727 return value_add_one( bva, &bv ); 1728 } 1729 1730 return mask_to_verbs( loglevel_ops, l, bva ); 1731 } 1732 1733 int 1734 loglevel_print( FILE *out ) 1735 { 1736 int i; 1737 1738 if ( loglevel_ops == NULL ) { 1739 loglevel_init(); 1740 } 1741 1742 fprintf( out, "Installed log subsystems:\n\n" ); 1743 for ( i = 0; !BER_BVISNULL( &loglevel_ops[i].word ); i++ ) { 1744 unsigned mask = loglevel_ops[i].mask & 0xffffffffUL; 1745 fprintf( out, 1746 ( mask == ( (slap_mask_t)-1 & 0xffffffffUL ) ? 1747 "\t%-30s (-1, 0xffffffff)\n" : 1748 "\t%-30s (%u, 0x%x)\n" ), 1749 loglevel_ops[i].word.bv_val, mask, mask ); 1750 } 1751 1752 fprintf( out, 1753 "\nNOTE: custom log subsystems may be later installed " 1754 "by specific code\n\n" ); 1755 1756 return 0; 1757 } 1758 1759 static int config_syslog; 1760 1761 static int 1762 config_loglevel( ConfigArgs *c ) 1763 { 1764 int i; 1765 1766 if ( loglevel_ops == NULL ) { 1767 loglevel_init(); 1768 } 1769 1770 if ( c->op == SLAP_CONFIG_EMIT ) { 1771 /* Get default or commandline slapd setting */ 1772 if ( ldap_syslog && !config_syslog ) config_syslog = ldap_syslog; 1773 return loglevel2bvarray( config_syslog, &c->rvalue_vals ); 1774 1775 } else if ( c->op == LDAP_MOD_DELETE ) { 1776 if ( !c->line ) { 1777 config_syslog = 0; 1778 } else { 1779 i = verb_to_mask( c->line, loglevel_ops ); 1780 config_syslog &= ~loglevel_ops[i].mask; 1781 } 1782 if ( slapMode & SLAP_SERVER_MODE ) { 1783 ldap_syslog = config_syslog; 1784 } 1785 return 0; 1786 } 1787 1788 for ( i = 1; i < c->argc; i++ ) { 1789 int level; 1790 1791 if ( isdigit( (unsigned char)c->argv[i][0] ) || c->argv[i][0] == '-' ) { 1792 if ( lutil_atoix( &level, c->argv[i], 0 ) != 0 ) { 1793 snprintf( c->cr_msg, sizeof(c->cr_msg), 1794 "<%s> unable to parse level", 1795 c->argv[0] ); 1796 Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", 1797 c->log, c->cr_msg, c->argv[i] ); 1798 return 1; 1799 } 1800 } else { 1801 if ( str2loglevel( c->argv[i], &level ) ) { 1802 snprintf( c->cr_msg, sizeof(c->cr_msg), "<%s> unknown level", 1803 c->argv[0] ); 1804 Debug( LDAP_DEBUG_ANY, "%s: %s \"%s\"\n", 1805 c->log, c->cr_msg, c->argv[i] ); 1806 return 1; 1807 } 1808 } 1809 /* Explicitly setting a zero clears all the levels */ 1810 if ( level ) 1811 config_syslog |= level; 1812 else 1813 config_syslog = 0; 1814 } 1815 if ( slapMode & SLAP_SERVER_MODE ) { 1816 ldap_syslog = config_syslog; 1817 } 1818 return 0; 1819 } 1820 1821 static int 1822 config_include( ConfigArgs *c ) 1823 { 1824 int savelineno = c->lineno; 1825 int rc; 1826 ConfigFile *cf; 1827 ConfigFile *cfsave = cfn; 1828 ConfigFile *cf2 = NULL; 1829 1830 /* Leftover from RE23. No dynamic config for include files */ 1831 if ( c->op == SLAP_CONFIG_EMIT || c->op == LDAP_MOD_DELETE ) return 1; 1832 1833 cf = ch_calloc( 1, sizeof(ConfigFile) ); 1834 if ( cfn->c_kids ) { 1835 for ( cf2 = cfn->c_kids; cf2 && cf2->c_sibs; cf2 = cf2->c_sibs ) 1836 /* empty */; 1837 cf2->c_sibs = cf; 1838 } else { 1839 cfn->c_kids = cf; 1840 } 1841 cfn = cf; 1842 ber_str2bv( c->argv[1], 0, 1, &cf->c_file ); 1843 rc = lload_read_config_file( 1844 c->argv[1], c->depth + 1, c, config_back_cf_table ); 1845 c->lineno = savelineno - 1; 1846 cfn = cfsave; 1847 if ( rc ) { 1848 if ( cf2 ) 1849 cf2->c_sibs = NULL; 1850 else 1851 cfn->c_kids = NULL; 1852 ch_free( cf->c_file.bv_val ); 1853 ch_free( cf ); 1854 } else { 1855 c->ca_private = cf; 1856 } 1857 return rc; 1858 } 1859 1860 static int 1861 config_feature( ConfigArgs *c ) 1862 { 1863 slap_verbmasks features[] = { 1864 #ifdef LDAP_API_FEATURE_VERIFY_CREDENTIALS 1865 { BER_BVC("vc"), LLOAD_FEATURE_VC }, 1866 #endif /* LDAP_API_FEATURE_VERIFY_CREDENTIALS */ 1867 { BER_BVC("proxyauthz"), LLOAD_FEATURE_PROXYAUTHZ }, 1868 { BER_BVC("read_pause"), LLOAD_FEATURE_PAUSE }, 1869 { BER_BVNULL, 0 } 1870 }; 1871 slap_mask_t mask = 0; 1872 int i; 1873 1874 if ( c->op == SLAP_CONFIG_EMIT ) { 1875 return mask_to_verbs( features, lload_features, &c->rvalue_vals ); 1876 } 1877 1878 lload_change.type = LLOAD_CHANGE_MODIFY; 1879 lload_change.object = LLOAD_DAEMON; 1880 lload_change.flags.daemon |= LLOAD_DAEMON_MOD_FEATURES; 1881 if ( !lload_change.target ) { 1882 lload_change.target = (void *)(uintptr_t)~lload_features; 1883 } 1884 1885 if ( c->op == LDAP_MOD_DELETE ) { 1886 if ( !c->line ) { 1887 /* Last value has been deleted */ 1888 lload_features = 0; 1889 } else { 1890 i = verb_to_mask( c->line, features ); 1891 lload_features &= ~features[i].mask; 1892 } 1893 return 0; 1894 } 1895 1896 i = verbs_to_mask( c->argc, c->argv, features, &mask ); 1897 if ( i ) { 1898 Debug( LDAP_DEBUG_ANY, "%s: <%s> unknown feature %s\n", c->log, 1899 c->argv[0], c->argv[i] ); 1900 return 1; 1901 } 1902 1903 if ( mask & ~LLOAD_FEATURE_SUPPORTED_MASK ) { 1904 for ( i = 1; i < c->argc; i++ ) { 1905 int j = verb_to_mask( c->argv[i], features ); 1906 if ( features[j].mask & ~LLOAD_FEATURE_SUPPORTED_MASK ) { 1907 Debug( LDAP_DEBUG_ANY, "%s: <%s> " 1908 "experimental feature %s is undocumented, unsupported " 1909 "and can change or disappear at any time!\n", 1910 c->log, c->argv[0], c->argv[i] ); 1911 } 1912 } 1913 } 1914 1915 lload_features |= mask; 1916 return 0; 1917 } 1918 1919 #ifdef HAVE_TLS 1920 static int 1921 config_tls_cleanup( ConfigArgs *c ) 1922 { 1923 int rc = 0; 1924 1925 if ( lload_tls_ld ) { 1926 int opt = 1; 1927 1928 ldap_pvt_tls_ctx_free( lload_tls_ctx ); 1929 lload_tls_ctx = NULL; 1930 1931 /* Force new ctx to be created */ 1932 rc = ldap_pvt_tls_set_option( 1933 lload_tls_ld, LDAP_OPT_X_TLS_NEWCTX, &opt ); 1934 if ( rc == 0 ) { 1935 /* The ctx's refcount is bumped up here */ 1936 ldap_pvt_tls_get_option( 1937 lload_tls_ld, LDAP_OPT_X_TLS_CTX, &lload_tls_ctx ); 1938 } else { 1939 if ( rc == LDAP_NOT_SUPPORTED ) 1940 rc = LDAP_UNWILLING_TO_PERFORM; 1941 else 1942 rc = LDAP_OTHER; 1943 } 1944 } 1945 return rc; 1946 } 1947 1948 static int 1949 config_tls_option( ConfigArgs *c ) 1950 { 1951 int flag; 1952 int berval = 0; 1953 LDAP *ld = lload_tls_ld; 1954 1955 switch ( c->type ) { 1956 case CFG_TLS_RAND: 1957 flag = LDAP_OPT_X_TLS_RANDOM_FILE; 1958 ld = NULL; 1959 break; 1960 case CFG_TLS_CIPHER: 1961 flag = LDAP_OPT_X_TLS_CIPHER_SUITE; 1962 break; 1963 case CFG_TLS_CERT_FILE: 1964 flag = LDAP_OPT_X_TLS_CERTFILE; 1965 break; 1966 case CFG_TLS_CERT_KEY: 1967 flag = LDAP_OPT_X_TLS_KEYFILE; 1968 break; 1969 case CFG_TLS_CA_PATH: 1970 flag = LDAP_OPT_X_TLS_CACERTDIR; 1971 break; 1972 case CFG_TLS_CA_FILE: 1973 flag = LDAP_OPT_X_TLS_CACERTFILE; 1974 break; 1975 case CFG_TLS_DH_FILE: 1976 flag = LDAP_OPT_X_TLS_DHFILE; 1977 break; 1978 case CFG_TLS_ECNAME: 1979 flag = LDAP_OPT_X_TLS_ECNAME; 1980 break; 1981 #ifdef HAVE_GNUTLS 1982 case CFG_TLS_CRL_FILE: 1983 flag = LDAP_OPT_X_TLS_CRLFILE; 1984 break; 1985 #endif 1986 case CFG_TLS_CACERT: 1987 flag = LDAP_OPT_X_TLS_CACERT; 1988 berval = 1; 1989 break; 1990 case CFG_TLS_CERT: 1991 flag = LDAP_OPT_X_TLS_CERT; 1992 berval = 1; 1993 break; 1994 case CFG_TLS_KEY: 1995 flag = LDAP_OPT_X_TLS_KEY; 1996 berval = 1; 1997 break; 1998 default: 1999 Debug( LDAP_DEBUG_ANY, "%s: " 2000 "unknown tls_option <0x%x>\n", 2001 c->log, c->type ); 2002 return 1; 2003 } 2004 if ( c->op == SLAP_CONFIG_EMIT ) { 2005 return ldap_pvt_tls_get_option( ld, flag, 2006 berval ? (void *)&c->value_bv : (void *)&c->value_string ); 2007 } 2008 2009 lload_change.type = LLOAD_CHANGE_MODIFY; 2010 lload_change.object = LLOAD_DAEMON; 2011 lload_change.flags.daemon |= LLOAD_DAEMON_MOD_TLS; 2012 2013 config_push_cleanup( c, config_tls_cleanup ); 2014 if ( c->op == LDAP_MOD_DELETE ) { 2015 return ldap_pvt_tls_set_option( ld, flag, NULL ); 2016 } 2017 if ( !berval ) ch_free( c->value_string ); 2018 return ldap_pvt_tls_set_option( 2019 ld, flag, berval ? (void *)&c->value_bv : (void *)c->argv[1] ); 2020 } 2021 2022 /* FIXME: this ought to be provided by libldap */ 2023 static int 2024 config_tls_config( ConfigArgs *c ) 2025 { 2026 int i, flag; 2027 2028 switch ( c->type ) { 2029 case CFG_TLS_CRLCHECK: 2030 flag = LDAP_OPT_X_TLS_CRLCHECK; 2031 break; 2032 case CFG_TLS_VERIFY: 2033 flag = LDAP_OPT_X_TLS_REQUIRE_CERT; 2034 break; 2035 case CFG_TLS_PROTOCOL_MIN: 2036 flag = LDAP_OPT_X_TLS_PROTOCOL_MIN; 2037 break; 2038 default: 2039 Debug( LDAP_DEBUG_ANY, "%s: " 2040 "unknown tls_option <0x%x>\n", 2041 c->log, c->type ); 2042 return 1; 2043 } 2044 if ( c->op == SLAP_CONFIG_EMIT ) { 2045 return lload_tls_get_config( lload_tls_ld, flag, &c->value_string ); 2046 } 2047 2048 lload_change.type = LLOAD_CHANGE_MODIFY; 2049 lload_change.object = LLOAD_DAEMON; 2050 lload_change.flags.daemon |= LLOAD_DAEMON_MOD_TLS; 2051 2052 config_push_cleanup( c, config_tls_cleanup ); 2053 if ( c->op == LDAP_MOD_DELETE ) { 2054 int i = 0; 2055 return ldap_pvt_tls_set_option( lload_tls_ld, flag, &i ); 2056 } 2057 ch_free( c->value_string ); 2058 if ( isdigit( (unsigned char)c->argv[1][0] ) && 2059 c->type != CFG_TLS_PROTOCOL_MIN ) { 2060 if ( lutil_atoi( &i, c->argv[1] ) != 0 ) { 2061 Debug( LDAP_DEBUG_ANY, "%s: " 2062 "unable to parse %s \"%s\"\n", 2063 c->log, c->argv[0], c->argv[1] ); 2064 return 1; 2065 } 2066 return ldap_pvt_tls_set_option( lload_tls_ld, flag, &i ); 2067 } else { 2068 return ldap_pvt_tls_config( lload_tls_ld, flag, c->argv[1] ); 2069 } 2070 } 2071 #endif 2072 2073 #ifdef BALANCER_MODULE 2074 static int 2075 config_share_tls_ctx( ConfigArgs *c ) 2076 { 2077 int rc = LDAP_SUCCESS; 2078 2079 if ( c->op == SLAP_CONFIG_EMIT ) { 2080 c->value_int = lload_use_slap_tls_ctx; 2081 return rc; 2082 } 2083 2084 lload_change.type = LLOAD_CHANGE_MODIFY; 2085 lload_change.object = LLOAD_DAEMON; 2086 lload_change.flags.daemon |= LLOAD_DAEMON_MOD_TLS; 2087 2088 if ( c->op == LDAP_MOD_DELETE ) { 2089 lload_use_slap_tls_ctx = 0; 2090 return rc; 2091 } 2092 2093 lload_use_slap_tls_ctx = c->value_int; 2094 return rc; 2095 } 2096 #endif /* BALANCER_MODULE */ 2097 2098 void 2099 lload_init_config_argv( ConfigArgs *c ) 2100 { 2101 c->argv = ch_calloc( ARGS_STEP + 1, sizeof(*c->argv) ); 2102 c->argv_size = ARGS_STEP + 1; 2103 } 2104 2105 ConfigTable * 2106 lload_config_find_keyword( ConfigTable *Conf, ConfigArgs *c ) 2107 { 2108 int i; 2109 2110 for ( i = 0; Conf[i].name; i++ ) 2111 if ( ( Conf[i].length && 2112 ( !strncasecmp( 2113 c->argv[0], Conf[i].name, Conf[i].length ) ) ) || 2114 ( !strcasecmp( c->argv[0], Conf[i].name ) ) ) 2115 break; 2116 if ( !Conf[i].name ) return NULL; 2117 if ( (Conf[i].arg_type & ARGS_TYPES) == ARG_BINARY ) { 2118 size_t decode_len = LUTIL_BASE64_DECODE_LEN( c->linelen ); 2119 ch_free( c->tline ); 2120 c->tline = ch_malloc( decode_len + 1 ); 2121 c->linelen = lutil_b64_pton( c->line, c->tline, decode_len ); 2122 if ( c->linelen < 0 ) { 2123 ch_free( c->tline ); 2124 c->tline = NULL; 2125 return NULL; 2126 } 2127 c->line = c->tline; 2128 } 2129 return Conf + i; 2130 } 2131 2132 int 2133 lload_config_check_vals( ConfigTable *Conf, ConfigArgs *c, int check_only ) 2134 { 2135 int arg_user, arg_type, arg_syn, iarg; 2136 unsigned uiarg; 2137 long larg; 2138 unsigned long ularg; 2139 ber_len_t barg; 2140 2141 if ( Conf->arg_type == ARG_IGNORED ) { 2142 Debug( LDAP_DEBUG_CONFIG, "%s: keyword <%s> ignored\n", 2143 c->log, Conf->name ); 2144 return 0; 2145 } 2146 arg_type = Conf->arg_type & ARGS_TYPES; 2147 arg_user = Conf->arg_type & ARGS_USERLAND; 2148 arg_syn = Conf->arg_type & ARGS_SYNTAX; 2149 2150 if ( Conf->min_args && ( c->argc < Conf->min_args ) ) { 2151 snprintf( c->cr_msg, sizeof(c->cr_msg), "<%s> missing <%s> argument", 2152 c->argv[0], Conf->what ? Conf->what : "" ); 2153 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: keyword %s\n", 2154 c->log, c->cr_msg ); 2155 return ARG_BAD_CONF; 2156 } 2157 if ( Conf->max_args && ( c->argc > Conf->max_args ) ) { 2158 char *ignored = " ignored"; 2159 2160 snprintf( c->cr_msg, sizeof(c->cr_msg), "<%s> extra cruft after <%s>", 2161 c->argv[0], Conf->what ); 2162 2163 ignored = ""; 2164 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s%s\n", 2165 c->log, c->cr_msg, ignored ); 2166 return ARG_BAD_CONF; 2167 } 2168 if ( (arg_syn & ARG_PAREN) && *c->argv[1] != '(' /*')'*/ ) { 2169 snprintf( c->cr_msg, sizeof(c->cr_msg), "<%s> old format not supported", 2170 c->argv[0] ); 2171 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n", 2172 c->log, c->cr_msg ); 2173 return ARG_BAD_CONF; 2174 } 2175 if ( arg_type && !Conf->arg_item && !(arg_syn & ARG_OFFSET) ) { 2176 snprintf( c->cr_msg, sizeof(c->cr_msg), 2177 "<%s> invalid config_table, arg_item is NULL", 2178 c->argv[0] ); 2179 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n", 2180 c->log, c->cr_msg ); 2181 return ARG_BAD_CONF; 2182 } 2183 c->type = arg_user; 2184 memset( &c->values, 0, sizeof(c->values) ); 2185 if ( arg_type == ARG_STRING ) { 2186 assert( c->argc == 2 ); 2187 if ( !check_only ) c->value_string = ch_strdup( c->argv[1] ); 2188 } else if ( arg_type == ARG_BERVAL ) { 2189 assert( c->argc == 2 ); 2190 if ( !check_only ) ber_str2bv( c->argv[1], 0, 1, &c->value_bv ); 2191 } else if ( arg_type == ARG_BINARY ) { 2192 assert( c->argc == 2 ); 2193 if ( !check_only ) { 2194 c->value_bv.bv_len = c->linelen; 2195 c->value_bv.bv_val = ch_malloc( c->linelen ); 2196 AC_MEMCPY( c->value_bv.bv_val, c->line, c->linelen ); 2197 } 2198 } else { /* all numeric */ 2199 int j; 2200 iarg = 0; 2201 larg = 0; 2202 barg = 0; 2203 switch ( arg_type ) { 2204 case ARG_INT: 2205 assert( c->argc == 2 ); 2206 if ( lutil_atoix( &iarg, c->argv[1], 0 ) != 0 ) { 2207 snprintf( c->cr_msg, sizeof(c->cr_msg), 2208 "<%s> unable to parse \"%s\" as int", 2209 c->argv[0], c->argv[1] ); 2210 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n", 2211 c->log, c->cr_msg ); 2212 return ARG_BAD_CONF; 2213 } 2214 break; 2215 case ARG_UINT: 2216 assert( c->argc == 2 ); 2217 if ( lutil_atoux( &uiarg, c->argv[1], 0 ) != 0 ) { 2218 snprintf( c->cr_msg, sizeof(c->cr_msg), 2219 "<%s> unable to parse \"%s\" as unsigned int", 2220 c->argv[0], c->argv[1] ); 2221 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n", 2222 c->log, c->cr_msg ); 2223 return ARG_BAD_CONF; 2224 } 2225 break; 2226 case ARG_LONG: 2227 assert( c->argc == 2 ); 2228 if ( lutil_atolx( &larg, c->argv[1], 0 ) != 0 ) { 2229 snprintf( c->cr_msg, sizeof(c->cr_msg), 2230 "<%s> unable to parse \"%s\" as long", 2231 c->argv[0], c->argv[1] ); 2232 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n", 2233 c->log, c->cr_msg ); 2234 return ARG_BAD_CONF; 2235 } 2236 break; 2237 case ARG_ULONG: 2238 assert( c->argc == 2 ); 2239 if ( LUTIL_ATOULX( &ularg, c->argv[1], 0 ) != 0 ) { 2240 snprintf( c->cr_msg, sizeof(c->cr_msg), 2241 "<%s> unable to parse \"%s\" as unsigned long", 2242 c->argv[0], c->argv[1] ); 2243 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n", 2244 c->log, c->cr_msg ); 2245 return ARG_BAD_CONF; 2246 } 2247 break; 2248 case ARG_BER_LEN_T: { 2249 unsigned long l; 2250 assert( c->argc == 2 ); 2251 if ( lutil_atoulx( &l, c->argv[1], 0 ) != 0 ) { 2252 snprintf( c->cr_msg, sizeof(c->cr_msg), 2253 "<%s> unable to parse \"%s\" as ber_len_t", 2254 c->argv[0], c->argv[1] ); 2255 Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, "%s: %s\n", 2256 c->log, c->cr_msg ); 2257 return ARG_BAD_CONF; 2258 } 2259 barg = (ber_len_t)l; 2260 } break; 2261 case ARG_ON_OFF: 2262 /* note: this is an explicit exception 2263 * to the "need exactly 2 args" rule */ 2264 if ( c->argc == 1 ) { 2265 iarg = 1; 2266 } else if ( !strcasecmp( c->argv[1], "on" ) || 2267 !strcasecmp( c->argv[1], "true" ) || 2268 !strcasecmp( c->argv[1], "yes" ) ) { 2269 iarg = 1; 2270 } else if ( !strcasecmp( c->argv[1], "off" ) || 2271 !strcasecmp( c->argv[1], "false" ) || 2272 !strcasecmp( c->argv[1], "no" ) ) { 2273 iarg = 0; 2274 } else { 2275 snprintf( c->cr_msg, sizeof(c->cr_msg), 2276 "<%s> invalid value", 2277 c->argv[0] ); 2278 Debug( LDAP_DEBUG_ANY|LDAP_DEBUG_NONE, "%s: %s\n", 2279 c->log, c->cr_msg ); 2280 return ARG_BAD_CONF; 2281 } 2282 break; 2283 } 2284 j = (arg_type & ARG_NONZERO) ? 1 : 0; 2285 if ( iarg < j && larg < j && barg < (unsigned)j ) { 2286 larg = larg ? larg : ( barg ? (long)barg : iarg ); 2287 snprintf( c->cr_msg, sizeof(c->cr_msg), "<%s> invalid value", 2288 c->argv[0] ); 2289 Debug( LDAP_DEBUG_ANY|LDAP_DEBUG_NONE, "%s: %s\n", 2290 c->log, c->cr_msg ); 2291 return ARG_BAD_CONF; 2292 } 2293 switch ( arg_type ) { 2294 case ARG_ON_OFF: 2295 case ARG_INT: 2296 c->value_int = iarg; 2297 break; 2298 case ARG_UINT: 2299 c->value_uint = uiarg; 2300 break; 2301 case ARG_LONG: 2302 c->value_long = larg; 2303 break; 2304 case ARG_ULONG: 2305 c->value_ulong = ularg; 2306 break; 2307 case ARG_BER_LEN_T: 2308 c->value_ber_t = barg; 2309 break; 2310 } 2311 } 2312 return 0; 2313 } 2314 2315 int 2316 lload_config_set_vals( ConfigTable *Conf, ConfigArgs *c ) 2317 { 2318 int rc, arg_type; 2319 void *ptr = NULL; 2320 2321 arg_type = Conf->arg_type; 2322 if ( arg_type & ARG_MAGIC ) { 2323 c->cr_msg[0] = '\0'; 2324 rc = ( *( (ConfigDriver *)Conf->arg_item ) )( c ); 2325 if ( rc ) { 2326 if ( !c->cr_msg[0] ) { 2327 snprintf( c->cr_msg, sizeof(c->cr_msg), 2328 "<%s> handler exited with %d", 2329 c->argv[0], rc ); 2330 Debug( LDAP_DEBUG_CONFIG, "%s: %s!\n", c->log, c->cr_msg ); 2331 } 2332 return ARG_BAD_CONF; 2333 } 2334 return 0; 2335 } 2336 if ( arg_type & ARG_OFFSET ) { 2337 { 2338 snprintf( c->cr_msg, sizeof(c->cr_msg), 2339 "<%s> offset is missing base pointer", 2340 c->argv[0] ); 2341 Debug( LDAP_DEBUG_CONFIG, "%s: %s!\n", c->log, c->cr_msg ); 2342 return ARG_BAD_CONF; 2343 } 2344 ptr = (void *)( (char *)ptr + (long)Conf->arg_item ); 2345 } else if ( arg_type & ARGS_TYPES ) { 2346 ptr = Conf->arg_item; 2347 } 2348 if ( arg_type & ARGS_TYPES ) switch ( arg_type & ARGS_TYPES ) { 2349 case ARG_ON_OFF: 2350 case ARG_INT: 2351 *(int *)ptr = c->value_int; 2352 break; 2353 case ARG_UINT: 2354 *(unsigned *)ptr = c->value_uint; 2355 break; 2356 case ARG_LONG: 2357 *(long *)ptr = c->value_long; 2358 break; 2359 case ARG_ULONG: 2360 *(size_t *)ptr = c->value_ulong; 2361 break; 2362 case ARG_BER_LEN_T: 2363 *(ber_len_t *)ptr = c->value_ber_t; 2364 break; 2365 case ARG_STRING: { 2366 char *cc = *(char **)ptr; 2367 if ( cc ) { 2368 if ( (arg_type & ARG_UNIQUE) && 2369 c->op == SLAP_CONFIG_ADD ) { 2370 Debug( LDAP_DEBUG_CONFIG, "%s: already set %s!\n", 2371 c->log, Conf->name ); 2372 return ARG_BAD_CONF; 2373 } 2374 ch_free( cc ); 2375 } 2376 *(char **)ptr = c->value_string; 2377 break; 2378 } 2379 case ARG_BERVAL: 2380 case ARG_BINARY: 2381 *(struct berval *)ptr = c->value_bv; 2382 break; 2383 } 2384 return 0; 2385 } 2386 2387 int 2388 lload_config_add_vals( ConfigTable *Conf, ConfigArgs *c ) 2389 { 2390 int rc, arg_type; 2391 2392 arg_type = Conf->arg_type; 2393 if ( arg_type == ARG_IGNORED ) { 2394 Debug( LDAP_DEBUG_CONFIG, "%s: keyword <%s> ignored\n", 2395 c->log, Conf->name ); 2396 return 0; 2397 } 2398 rc = lload_config_check_vals( Conf, c, 0 ); 2399 if ( rc ) return rc; 2400 return lload_config_set_vals( Conf, c ); 2401 } 2402 2403 int 2404 lload_read_config_file( 2405 const char *fname, 2406 int depth, 2407 ConfigArgs *cf, 2408 ConfigTable *cft ) 2409 { 2410 FILE *fp; 2411 ConfigTable *ct; 2412 ConfigArgs *c; 2413 int rc; 2414 struct stat s; 2415 2416 c = ch_calloc( 1, sizeof(ConfigArgs) ); 2417 if ( c == NULL ) { 2418 return 1; 2419 } 2420 2421 if ( depth ) { 2422 memcpy( c, cf, sizeof(ConfigArgs) ); 2423 } else { 2424 c->depth = depth; /* XXX */ 2425 } 2426 2427 c->valx = -1; 2428 c->fname = fname; 2429 lload_init_config_argv( c ); 2430 2431 if ( stat( fname, &s ) != 0 ) { 2432 char ebuf[128]; 2433 int saved_errno = errno; 2434 ldap_syslog = 1; 2435 Debug( LDAP_DEBUG_ANY, "could not stat config file \"%s\": %s (%d)\n", 2436 fname, AC_STRERROR_R( saved_errno, ebuf, sizeof(ebuf) ), 2437 saved_errno ); 2438 ch_free( c->argv ); 2439 ch_free( c ); 2440 return 1; 2441 } 2442 2443 if ( !S_ISREG(s.st_mode) ) { 2444 ldap_syslog = 1; 2445 Debug( LDAP_DEBUG_ANY, "regular file expected, got \"%s\"\n", fname ); 2446 ch_free( c->argv ); 2447 ch_free( c ); 2448 return 1; 2449 } 2450 2451 fp = fopen( fname, "r" ); 2452 if ( fp == NULL ) { 2453 char ebuf[128]; 2454 int saved_errno = errno; 2455 ldap_syslog = 1; 2456 Debug( LDAP_DEBUG_ANY, "could not open config file \"%s\": %s (%d)\n", 2457 fname, AC_STRERROR_R( saved_errno, ebuf, sizeof(ebuf) ), 2458 saved_errno ); 2459 ch_free( c->argv ); 2460 ch_free( c ); 2461 return 1; 2462 } 2463 2464 Debug( LDAP_DEBUG_CONFIG, "reading config file %s\n", fname ); 2465 2466 fp_getline_init( c ); 2467 2468 c->tline = NULL; 2469 2470 while ( fp_getline( fp, c ) ) { 2471 /* skip comments and blank lines */ 2472 if ( c->line[0] == '#' || c->line[0] == '\0' ) { 2473 continue; 2474 } 2475 2476 snprintf( c->log, sizeof(c->log), "%s: line %d", 2477 c->fname, c->lineno ); 2478 2479 c->argc = 0; 2480 ch_free( c->tline ); 2481 if ( lload_config_fp_parse_line( c ) ) { 2482 rc = 1; 2483 goto done; 2484 } 2485 2486 if ( c->argc < 1 ) { 2487 Debug( LDAP_DEBUG_ANY, "%s: bad config line\n", c->log ); 2488 rc = 1; 2489 goto done; 2490 } 2491 2492 c->op = SLAP_CONFIG_ADD; 2493 2494 ct = lload_config_find_keyword( cft, c ); 2495 if ( ct ) { 2496 c->table = Cft_Global; 2497 rc = lload_config_add_vals( ct, c ); 2498 if ( !rc ) continue; 2499 2500 if ( rc & ARGS_USERLAND ) { 2501 /* XXX a usertype would be opaque here */ 2502 Debug( LDAP_DEBUG_CONFIG, "%s: unknown user type <%s>\n", 2503 c->log, c->argv[0] ); 2504 rc = 1; 2505 goto done; 2506 2507 } else if ( rc == ARG_BAD_CONF ) { 2508 rc = 1; 2509 goto done; 2510 } 2511 2512 } else { 2513 Debug( LDAP_DEBUG_ANY, "%s: unknown directive " 2514 "<%s> outside backend info and database definitions\n", 2515 c->log, *c->argv ); 2516 rc = 1; 2517 goto done; 2518 } 2519 } 2520 2521 rc = 0; 2522 2523 done: 2524 ch_free( c->tline ); 2525 fclose( fp ); 2526 ch_free( c->argv ); 2527 ch_free( c ); 2528 return rc; 2529 } 2530 2531 int 2532 lload_read_config( const char *fname, const char *dir ) 2533 { 2534 if ( !fname ) fname = LLOADD_DEFAULT_CONFIGFILE; 2535 2536 cfn = ch_calloc( 1, sizeof(ConfigFile) ); 2537 2538 return lload_read_config_file( fname, 0, NULL, config_back_cf_table ); 2539 } 2540 2541 /* restrictops, allows, disallows, requires, loglevel */ 2542 2543 int 2544 bverb_to_mask( struct berval *bword, slap_verbmasks *v ) 2545 { 2546 int i; 2547 for ( i = 0; !BER_BVISNULL( &v[i].word ); i++ ) { 2548 if ( !ber_bvstrcasecmp( bword, &v[i].word ) ) break; 2549 } 2550 return i; 2551 } 2552 2553 int 2554 verb_to_mask( const char *word, slap_verbmasks *v ) 2555 { 2556 struct berval bword; 2557 ber_str2bv( word, 0, 0, &bword ); 2558 return bverb_to_mask( &bword, v ); 2559 } 2560 2561 int 2562 verbs_to_mask( int argc, char *argv[], slap_verbmasks *v, slap_mask_t *m ) 2563 { 2564 int i, j; 2565 for ( i = 1; i < argc; i++ ) { 2566 j = verb_to_mask( argv[i], v ); 2567 if ( BER_BVISNULL( &v[j].word ) ) return i; 2568 while ( !v[j].mask ) 2569 j--; 2570 *m |= v[j].mask; 2571 } 2572 return 0; 2573 } 2574 2575 /* Mask keywords that represent multiple bits should occur before single 2576 * bit keywords in the verbmasks array. 2577 */ 2578 int 2579 mask_to_verbs( slap_verbmasks *v, slap_mask_t m, BerVarray *bva ) 2580 { 2581 int i, rc = 1; 2582 2583 if ( m ) { 2584 for ( i = 0; !BER_BVISNULL( &v[i].word ); i++ ) { 2585 if ( !v[i].mask ) continue; 2586 if ( (m & v[i].mask) == v[i].mask ) { 2587 value_add_one( bva, &v[i].word ); 2588 rc = 0; 2589 m ^= v[i].mask; 2590 if ( !m ) break; 2591 } 2592 } 2593 } 2594 return rc; 2595 } 2596 2597 int 2598 slap_verbmasks_init( slap_verbmasks **vp, slap_verbmasks *v ) 2599 { 2600 int i; 2601 2602 assert( *vp == NULL ); 2603 2604 for ( i = 0; !BER_BVISNULL( &v[i].word ); i++ ) /* EMPTY */; 2605 2606 *vp = ch_calloc( i + 1, sizeof(slap_verbmasks) ); 2607 2608 for ( i = 0; !BER_BVISNULL( &v[i].word ); i++ ) { 2609 ber_dupbv( &(*vp)[i].word, &v[i].word ); 2610 *( (slap_mask_t *)&(*vp)[i].mask ) = v[i].mask; 2611 } 2612 2613 BER_BVZERO( &(*vp)[i].word ); 2614 2615 return 0; 2616 } 2617 2618 int 2619 slap_verbmasks_destroy( slap_verbmasks *v ) 2620 { 2621 int i; 2622 2623 assert( v != NULL ); 2624 2625 for ( i = 0; !BER_BVISNULL( &v[i].word ); i++ ) { 2626 ch_free( v[i].word.bv_val ); 2627 } 2628 2629 ch_free( v ); 2630 2631 return 0; 2632 } 2633 2634 #ifndef BALANCER_MODULE 2635 int 2636 config_push_cleanup( ConfigArgs *ca, ConfigDriver *cleanup ) 2637 { 2638 /* Stub, cleanups only run in online config */ 2639 return 0; 2640 } 2641 #endif /* !BALANCER_MODULE */ 2642 2643 static slap_verbmasks tlskey[] = { 2644 { BER_BVC("no"), LLOAD_CLEARTEXT }, 2645 { BER_BVC("yes"), LLOAD_STARTTLS_OPTIONAL }, 2646 { BER_BVC("critical"), LLOAD_STARTTLS }, 2647 { BER_BVNULL, 0 } 2648 }; 2649 2650 static slap_verbmasks crlkeys[] = { 2651 { BER_BVC("none"), LDAP_OPT_X_TLS_CRL_NONE }, 2652 { BER_BVC("peer"), LDAP_OPT_X_TLS_CRL_PEER }, 2653 { BER_BVC("all"), LDAP_OPT_X_TLS_CRL_ALL }, 2654 { BER_BVNULL, 0 } 2655 }; 2656 2657 static slap_verbmasks vfykeys[] = { 2658 { BER_BVC("never"), LDAP_OPT_X_TLS_NEVER }, 2659 { BER_BVC("allow"), LDAP_OPT_X_TLS_ALLOW }, 2660 { BER_BVC("try"), LDAP_OPT_X_TLS_TRY }, 2661 { BER_BVC("demand"), LDAP_OPT_X_TLS_DEMAND }, 2662 { BER_BVC("hard"), LDAP_OPT_X_TLS_HARD }, 2663 { BER_BVC("true"), LDAP_OPT_X_TLS_HARD }, 2664 { BER_BVNULL, 0 } 2665 }; 2666 2667 static slap_verbmasks methkey[] = { 2668 { BER_BVC("none"), LDAP_AUTH_NONE }, 2669 { BER_BVC("simple"), LDAP_AUTH_SIMPLE }, 2670 #ifdef HAVE_CYRUS_SASL 2671 { BER_BVC("sasl"), LDAP_AUTH_SASL }, 2672 #endif 2673 { BER_BVNULL, 0 } 2674 }; 2675 2676 int 2677 lload_keepalive_parse( 2678 struct berval *val, 2679 void *bc, 2680 slap_cf_aux_table *tab0, 2681 const char *tabmsg, 2682 int unparse ) 2683 { 2684 if ( unparse ) { 2685 slap_keepalive *sk = (slap_keepalive *)bc; 2686 int rc = snprintf( val->bv_val, val->bv_len, "%d:%d:%d", 2687 sk->sk_idle, sk->sk_probes, sk->sk_interval ); 2688 if ( rc < 0 ) { 2689 return -1; 2690 } 2691 2692 if ( (unsigned)rc >= val->bv_len ) { 2693 return -1; 2694 } 2695 2696 val->bv_len = rc; 2697 2698 } else { 2699 char *s = val->bv_val; 2700 char *next; 2701 slap_keepalive *sk = (slap_keepalive *)bc; 2702 slap_keepalive sk2; 2703 2704 if ( s[0] == ':' ) { 2705 sk2.sk_idle = 0; 2706 s++; 2707 2708 } else { 2709 sk2.sk_idle = strtol( s, &next, 10 ); 2710 if ( next == s || next[0] != ':' ) { 2711 return -1; 2712 } 2713 2714 if ( sk2.sk_idle < 0 ) { 2715 return -1; 2716 } 2717 2718 s = ++next; 2719 } 2720 2721 if ( s[0] == ':' ) { 2722 sk2.sk_probes = 0; 2723 s++; 2724 2725 } else { 2726 sk2.sk_probes = strtol( s, &next, 10 ); 2727 if ( next == s || next[0] != ':' ) { 2728 return -1; 2729 } 2730 2731 if ( sk2.sk_probes < 0 ) { 2732 return -1; 2733 } 2734 2735 s = ++next; 2736 } 2737 2738 if ( *s == '\0' ) { 2739 sk2.sk_interval = 0; 2740 2741 } else { 2742 sk2.sk_interval = strtol( s, &next, 10 ); 2743 if ( next == s || next[0] != '\0' ) { 2744 return -1; 2745 } 2746 2747 if ( sk2.sk_interval < 0 ) { 2748 return -1; 2749 } 2750 } 2751 2752 *sk = sk2; 2753 2754 ber_memfree( val->bv_val ); 2755 BER_BVZERO( val ); 2756 } 2757 2758 return 0; 2759 } 2760 2761 static slap_cf_aux_table backendkey[] = { 2762 { BER_BVC("uri="), offsetof(LloadBackend, b_uri), 'b', 1, NULL }, 2763 2764 { BER_BVC("numconns="), offsetof(LloadBackend, b_numconns), 'i', 0, NULL }, 2765 { BER_BVC("bindconns="), offsetof(LloadBackend, b_numbindconns), 'i', 0, NULL }, 2766 { BER_BVC("retry="), offsetof(LloadBackend, b_retry_timeout), 'i', 0, NULL }, 2767 2768 { BER_BVC("max-pending-ops="), offsetof(LloadBackend, b_max_pending), 'i', 0, NULL }, 2769 { BER_BVC("conn-max-pending="), offsetof(LloadBackend, b_max_conn_pending), 'i', 0, NULL }, 2770 { BER_BVC("starttls="), offsetof(LloadBackend, b_tls_conf), 'i', 0, tlskey }, 2771 { BER_BVNULL, 0, 0, 0, NULL } 2772 }; 2773 2774 static slap_cf_aux_table bindkey[] = { 2775 { BER_BVC("bindmethod="), offsetof(slap_bindconf, sb_method), 'i', 0, methkey }, 2776 { BER_BVC("timeout="), offsetof(slap_bindconf, sb_timeout_api), 'i', 0, NULL }, 2777 { BER_BVC("network-timeout="), offsetof(slap_bindconf, sb_timeout_net), 'i', 0, NULL }, 2778 { BER_BVC("binddn="), offsetof(slap_bindconf, sb_binddn), 'b', 1, NULL }, 2779 { BER_BVC("credentials="), offsetof(slap_bindconf, sb_cred), 'b', 1, NULL }, 2780 { BER_BVC("saslmech="), offsetof(slap_bindconf, sb_saslmech), 'b', 0, NULL }, 2781 { BER_BVC("secprops="), offsetof(slap_bindconf, sb_secprops), 's', 0, NULL }, 2782 { BER_BVC("realm="), offsetof(slap_bindconf, sb_realm), 'b', 0, NULL }, 2783 { BER_BVC("authcID="), offsetof(slap_bindconf, sb_authcId), 'b', 1, NULL }, 2784 { BER_BVC("authzID="), offsetof(slap_bindconf, sb_authzId), 'b', 1, NULL }, 2785 { BER_BVC("keepalive="), offsetof(slap_bindconf, sb_keepalive), 'x', 0, (slap_verbmasks *)lload_keepalive_parse }, 2786 { BER_BVC("tcp-user-timeout="), offsetof(slap_bindconf, sb_tcp_user_timeout), 'u', 0, NULL }, 2787 #ifdef HAVE_TLS 2788 /* NOTE: replace "12" with the actual index 2789 * of the first TLS-related line */ 2790 #define aux_TLS (bindkey+12) /* beginning of TLS keywords */ 2791 2792 { BER_BVC("tls_cert="), offsetof(slap_bindconf, sb_tls_cert), 's', 1, NULL }, 2793 { BER_BVC("tls_key="), offsetof(slap_bindconf, sb_tls_key), 's', 1, NULL }, 2794 { BER_BVC("tls_cacert="), offsetof(slap_bindconf, sb_tls_cacert), 's', 1, NULL }, 2795 { BER_BVC("tls_cacertdir="), offsetof(slap_bindconf, sb_tls_cacertdir), 's', 1, NULL }, 2796 { BER_BVC("tls_reqcert="), offsetof(slap_bindconf, sb_tls_reqcert), 's', 0, NULL }, 2797 { BER_BVC("tls_reqsan="), offsetof(slap_bindconf, sb_tls_reqsan), 's', 0, NULL }, 2798 { BER_BVC("tls_cipher_suite="), offsetof(slap_bindconf, sb_tls_cipher_suite), 's', 0, NULL }, 2799 { BER_BVC("tls_protocol_min="), offsetof(slap_bindconf, sb_tls_protocol_min), 's', 0, NULL }, 2800 { BER_BVC("tls_ecname="), offsetof(slap_bindconf, sb_tls_ecname), 's', 0, NULL }, 2801 #ifdef HAVE_OPENSSL 2802 { BER_BVC("tls_crlcheck="), offsetof(slap_bindconf, sb_tls_crlcheck), 's', 0, NULL }, 2803 #endif 2804 #endif 2805 { BER_BVNULL, 0, 0, 0, NULL } 2806 }; 2807 2808 /* 2809 * 's': char * 2810 * 'b': struct berval 2811 * 'i': int; if !NULL, compute using ((slap_verbmasks *)aux) 2812 * 'u': unsigned 2813 * 'I': long 2814 * 'U': unsigned long 2815 */ 2816 2817 int 2818 lload_cf_aux_table_parse( 2819 const char *word, 2820 void *dst, 2821 slap_cf_aux_table *tab0, 2822 LDAP_CONST char *tabmsg ) 2823 { 2824 int rc = SLAP_CONF_UNKNOWN; 2825 slap_cf_aux_table *tab; 2826 2827 for ( tab = tab0; !BER_BVISNULL( &tab->key ); tab++ ) { 2828 if ( !strncasecmp( word, tab->key.bv_val, tab->key.bv_len ) ) { 2829 char **cptr; 2830 int *iptr, j; 2831 unsigned *uptr; 2832 long *lptr; 2833 unsigned long *ulptr; 2834 struct berval *bptr; 2835 const char *val = word + tab->key.bv_len; 2836 2837 switch ( tab->type ) { 2838 case 's': 2839 cptr = (char **)( (char *)dst + tab->off ); 2840 *cptr = ch_strdup( val ); 2841 rc = 0; 2842 break; 2843 2844 case 'b': 2845 bptr = (struct berval *)( (char *)dst + tab->off ); 2846 assert( tab->aux == NULL ); 2847 ber_str2bv( val, 0, 1, bptr ); 2848 rc = 0; 2849 break; 2850 2851 case 'i': 2852 iptr = (int *)( (char *)dst + tab->off ); 2853 2854 if ( tab->aux != NULL ) { 2855 slap_verbmasks *aux = (slap_verbmasks *)tab->aux; 2856 2857 assert( aux != NULL ); 2858 2859 rc = 1; 2860 for ( j = 0; !BER_BVISNULL( &aux[j].word ); j++ ) { 2861 if ( !strcasecmp( val, aux[j].word.bv_val ) ) { 2862 *iptr = aux[j].mask; 2863 rc = 0; 2864 break; 2865 } 2866 } 2867 2868 } else { 2869 rc = lutil_atoix( iptr, val, 0 ); 2870 } 2871 break; 2872 2873 case 'u': 2874 uptr = (unsigned *)( (char *)dst + tab->off ); 2875 2876 rc = lutil_atoux( uptr, val, 0 ); 2877 break; 2878 2879 case 'I': 2880 lptr = (long *)( (char *)dst + tab->off ); 2881 2882 rc = lutil_atolx( lptr, val, 0 ); 2883 break; 2884 2885 case 'U': 2886 ulptr = (unsigned long *)( (char *)dst + tab->off ); 2887 2888 rc = lutil_atoulx( ulptr, val, 0 ); 2889 break; 2890 2891 case 'x': 2892 if ( tab->aux != NULL ) { 2893 struct berval value; 2894 lload_cf_aux_table_parse_x *func = 2895 (lload_cf_aux_table_parse_x *)tab->aux; 2896 2897 ber_str2bv( val, 0, 1, &value ); 2898 2899 rc = func( &value, (void *)( (char *)dst + tab->off ), 2900 tab, tabmsg, 0 ); 2901 2902 } else { 2903 rc = 1; 2904 } 2905 break; 2906 } 2907 2908 if ( rc ) { 2909 Debug( LDAP_DEBUG_ANY, "invalid %s value %s\n", tabmsg, word ); 2910 } 2911 2912 return rc; 2913 } 2914 } 2915 2916 return rc; 2917 } 2918 2919 int 2920 lload_cf_aux_table_unparse( 2921 void *src, 2922 struct berval *bv, 2923 slap_cf_aux_table *tab0 ) 2924 { 2925 char buf[AC_LINE_MAX], *ptr; 2926 slap_cf_aux_table *tab; 2927 struct berval tmp; 2928 2929 ptr = buf; 2930 for ( tab = tab0; !BER_BVISNULL( &tab->key ); tab++ ) { 2931 char **cptr; 2932 int *iptr, i; 2933 unsigned *uptr; 2934 long *lptr; 2935 unsigned long *ulptr; 2936 struct berval *bptr; 2937 2938 cptr = (char **)( (char *)src + tab->off ); 2939 2940 switch ( tab->type ) { 2941 case 'b': 2942 bptr = (struct berval *)( (char *)src + tab->off ); 2943 cptr = &bptr->bv_val; 2944 2945 case 's': 2946 if ( *cptr ) { 2947 *ptr++ = ' '; 2948 ptr = lutil_strcopy( ptr, tab->key.bv_val ); 2949 if ( tab->quote ) *ptr++ = '"'; 2950 ptr = lutil_strcopy( ptr, *cptr ); 2951 if ( tab->quote ) *ptr++ = '"'; 2952 } 2953 break; 2954 2955 case 'i': 2956 iptr = (int *)( (char *)src + tab->off ); 2957 2958 if ( tab->aux != NULL ) { 2959 slap_verbmasks *aux = (slap_verbmasks *)tab->aux; 2960 2961 for ( i = 0; !BER_BVISNULL( &aux[i].word ); i++ ) { 2962 if ( *iptr == aux[i].mask ) { 2963 *ptr++ = ' '; 2964 ptr = lutil_strcopy( ptr, tab->key.bv_val ); 2965 ptr = lutil_strcopy( ptr, aux[i].word.bv_val ); 2966 break; 2967 } 2968 } 2969 2970 } else { 2971 *ptr++ = ' '; 2972 ptr = lutil_strcopy( ptr, tab->key.bv_val ); 2973 ptr += snprintf( ptr, sizeof(buf) - ( ptr - buf ), "%d", 2974 *iptr ); 2975 } 2976 break; 2977 2978 case 'u': 2979 uptr = (unsigned *)( (char *)src + tab->off ); 2980 *ptr++ = ' '; 2981 ptr = lutil_strcopy( ptr, tab->key.bv_val ); 2982 ptr += snprintf( ptr, sizeof(buf) - ( ptr - buf ), "%u", 2983 *uptr ); 2984 break; 2985 2986 case 'I': 2987 lptr = (long *)( (char *)src + tab->off ); 2988 *ptr++ = ' '; 2989 ptr = lutil_strcopy( ptr, tab->key.bv_val ); 2990 ptr += snprintf( ptr, sizeof(buf) - ( ptr - buf ), "%ld", 2991 *lptr ); 2992 break; 2993 2994 case 'U': 2995 ulptr = (unsigned long *)( (char *)src + tab->off ); 2996 *ptr++ = ' '; 2997 ptr = lutil_strcopy( ptr, tab->key.bv_val ); 2998 ptr += snprintf( ptr, sizeof(buf) - ( ptr - buf ), "%lu", 2999 *ulptr ); 3000 break; 3001 3002 case 'x': { 3003 char *saveptr = ptr; 3004 *ptr++ = ' '; 3005 ptr = lutil_strcopy( ptr, tab->key.bv_val ); 3006 if ( tab->quote ) *ptr++ = '"'; 3007 if ( tab->aux != NULL ) { 3008 struct berval value; 3009 lload_cf_aux_table_parse_x *func = 3010 (lload_cf_aux_table_parse_x *)tab->aux; 3011 int rc; 3012 3013 value.bv_val = ptr; 3014 value.bv_len = buf + sizeof(buf) - ptr; 3015 3016 rc = func( &value, (void *)( (char *)src + tab->off ), tab, 3017 "(unparse)", 1 ); 3018 if ( rc == 0 ) { 3019 if ( value.bv_len ) { 3020 ptr += value.bv_len; 3021 } else { 3022 ptr = saveptr; 3023 break; 3024 } 3025 } 3026 } 3027 if ( tab->quote ) *ptr++ = '"'; 3028 } break; 3029 3030 default: 3031 assert(0); 3032 } 3033 } 3034 tmp.bv_val = buf; 3035 tmp.bv_len = ptr - buf; 3036 ber_dupbv( bv, &tmp ); 3037 return 0; 3038 } 3039 3040 int 3041 lload_tls_get_config( LDAP *ld, int opt, char **val ) 3042 { 3043 #ifdef HAVE_TLS 3044 slap_verbmasks *keys; 3045 int i, ival; 3046 3047 *val = NULL; 3048 switch ( opt ) { 3049 case LDAP_OPT_X_TLS_CRLCHECK: 3050 keys = crlkeys; 3051 break; 3052 case LDAP_OPT_X_TLS_REQUIRE_CERT: 3053 keys = vfykeys; 3054 break; 3055 case LDAP_OPT_X_TLS_PROTOCOL_MIN: { 3056 char buf[8]; 3057 ldap_pvt_tls_get_option( ld, opt, &ival ); 3058 snprintf( buf, sizeof(buf), "%d.%d", 3059 ( ival >> 8 ) & 0xff, ival & 0xff ); 3060 *val = ch_strdup( buf ); 3061 return 0; 3062 } 3063 default: 3064 return -1; 3065 } 3066 ldap_pvt_tls_get_option( ld, opt, &ival ); 3067 for ( i = 0; !BER_BVISNULL( &keys[i].word ); i++ ) { 3068 if ( keys[i].mask == ival ) { 3069 *val = ch_strdup( keys[i].word.bv_val ); 3070 return 0; 3071 } 3072 } 3073 #endif 3074 return -1; 3075 } 3076 3077 #ifdef HAVE_TLS 3078 static struct { 3079 const char *key; 3080 size_t offset; 3081 int opt; 3082 } bindtlsopts[] = { 3083 { "tls_cert", offsetof(slap_bindconf, sb_tls_cert), LDAP_OPT_X_TLS_CERTFILE }, 3084 { "tls_key", offsetof(slap_bindconf, sb_tls_key), LDAP_OPT_X_TLS_KEYFILE }, 3085 { "tls_cacert", offsetof(slap_bindconf, sb_tls_cacert), LDAP_OPT_X_TLS_CACERTFILE }, 3086 { "tls_cacertdir", offsetof(slap_bindconf, sb_tls_cacertdir), LDAP_OPT_X_TLS_CACERTDIR }, 3087 { "tls_cipher_suite", offsetof(slap_bindconf, sb_tls_cipher_suite), LDAP_OPT_X_TLS_CIPHER_SUITE }, 3088 { "tls_ecname", offsetof(slap_bindconf, sb_tls_ecname), LDAP_OPT_X_TLS_ECNAME }, 3089 { NULL, 0 } 3090 }; 3091 3092 int 3093 lload_bindconf_tls_set( slap_bindconf *bc, LDAP *ld ) 3094 { 3095 int i, rc, newctx = 0, res = 0; 3096 char *ptr = (char *)bc, **word; 3097 3098 if ( bc->sb_tls_do_init ) { 3099 for ( i = 0; bindtlsopts[i].opt; i++ ) { 3100 word = (char **)( ptr + bindtlsopts[i].offset ); 3101 if ( *word ) { 3102 rc = ldap_set_option( ld, bindtlsopts[i].opt, *word ); 3103 if ( rc ) { 3104 Debug( LDAP_DEBUG_ANY, "lload_bindconf_tls_set: " 3105 "failed to set %s to %s\n", 3106 bindtlsopts[i].key, *word ); 3107 res = -1; 3108 } else 3109 newctx = 1; 3110 } 3111 } 3112 if ( bc->sb_tls_reqcert ) { 3113 rc = ldap_pvt_tls_config( 3114 ld, LDAP_OPT_X_TLS_REQUIRE_CERT, bc->sb_tls_reqcert ); 3115 if ( rc ) { 3116 Debug( LDAP_DEBUG_ANY, "lload_bindconf_tls_set: " 3117 "failed to set tls_reqcert to %s\n", 3118 bc->sb_tls_reqcert ); 3119 res = -1; 3120 } else { 3121 newctx = 1; 3122 /* retrieve the parsed setting for later use */ 3123 ldap_get_option( ld, LDAP_OPT_X_TLS_REQUIRE_CERT, 3124 &bc->sb_tls_int_reqcert ); 3125 } 3126 } 3127 if ( bc->sb_tls_reqsan ) { 3128 rc = ldap_pvt_tls_config( 3129 ld, LDAP_OPT_X_TLS_REQUIRE_SAN, bc->sb_tls_reqsan ); 3130 if ( rc ) { 3131 Debug( LDAP_DEBUG_ANY, "lload_bindconf_tls_set: " 3132 "failed to set tls_reqsan to %s\n", 3133 bc->sb_tls_reqsan ); 3134 res = -1; 3135 } else { 3136 newctx = 1; 3137 /* retrieve the parsed setting for later use */ 3138 ldap_get_option( ld, LDAP_OPT_X_TLS_REQUIRE_SAN, 3139 &bc->sb_tls_int_reqsan ); 3140 } 3141 } 3142 if ( bc->sb_tls_protocol_min ) { 3143 rc = ldap_pvt_tls_config( 3144 ld, LDAP_OPT_X_TLS_PROTOCOL_MIN, bc->sb_tls_protocol_min ); 3145 if ( rc ) { 3146 Debug( LDAP_DEBUG_ANY, "lload_bindconf_tls_set: " 3147 "failed to set tls_protocol_min to %s\n", 3148 bc->sb_tls_protocol_min ); 3149 res = -1; 3150 } else 3151 newctx = 1; 3152 } 3153 #ifdef HAVE_OPENSSL 3154 if ( bc->sb_tls_crlcheck ) { 3155 rc = ldap_pvt_tls_config( 3156 ld, LDAP_OPT_X_TLS_CRLCHECK, bc->sb_tls_crlcheck ); 3157 if ( rc ) { 3158 Debug( LDAP_DEBUG_ANY, "lload_bindconf_tls_set: " 3159 "failed to set tls_crlcheck to %s\n", 3160 bc->sb_tls_crlcheck ); 3161 res = -1; 3162 } else 3163 newctx = 1; 3164 } 3165 #endif 3166 if ( !res ) bc->sb_tls_do_init = 0; 3167 } 3168 3169 if ( newctx ) { 3170 int opt = 0; 3171 3172 if ( bc->sb_tls_ctx ) { 3173 ldap_pvt_tls_ctx_free( bc->sb_tls_ctx ); 3174 bc->sb_tls_ctx = NULL; 3175 } 3176 rc = ldap_set_option( ld, LDAP_OPT_X_TLS_NEWCTX, &opt ); 3177 if ( rc ) 3178 res = rc; 3179 else 3180 ldap_get_option( ld, LDAP_OPT_X_TLS_CTX, &bc->sb_tls_ctx ); 3181 } else if ( bc->sb_tls_ctx ) { 3182 rc = ldap_set_option( ld, LDAP_OPT_X_TLS_CTX, bc->sb_tls_ctx ); 3183 if ( rc == LDAP_SUCCESS ) { 3184 /* these options aren't actually inside the ctx, so have to be set again */ 3185 ldap_set_option( 3186 ld, LDAP_OPT_X_TLS_REQUIRE_CERT, &bc->sb_tls_int_reqcert ); 3187 ldap_set_option( 3188 ld, LDAP_OPT_X_TLS_REQUIRE_SAN, &bc->sb_tls_int_reqsan ); 3189 } else 3190 res = rc; 3191 } 3192 3193 return res; 3194 } 3195 #endif 3196 3197 int 3198 lload_bindconf_tls_parse( const char *word, slap_bindconf *bc ) 3199 { 3200 #ifdef HAVE_TLS 3201 if ( lload_cf_aux_table_parse( word, bc, aux_TLS, "tls config" ) == 0 ) { 3202 bc->sb_tls_do_init = 1; 3203 return 0; 3204 } 3205 #endif 3206 return -1; 3207 } 3208 3209 int 3210 lload_backend_parse( const char *word, LloadBackend *b ) 3211 { 3212 return lload_cf_aux_table_parse( word, b, backendkey, "backend config" ); 3213 } 3214 3215 int 3216 lload_bindconf_parse( const char *word, slap_bindconf *bc ) 3217 { 3218 #ifdef HAVE_TLS 3219 /* Detect TLS config changes explicitly */ 3220 if ( lload_bindconf_tls_parse( word, bc ) == 0 ) { 3221 return 0; 3222 } 3223 #endif 3224 return lload_cf_aux_table_parse( word, bc, bindkey, "bind config" ); 3225 } 3226 3227 int 3228 lload_bindconf_unparse( slap_bindconf *bc, struct berval *bv ) 3229 { 3230 return lload_cf_aux_table_unparse( bc, bv, bindkey ); 3231 } 3232 3233 void 3234 lload_bindconf_free( slap_bindconf *bc ) 3235 { 3236 if ( !BER_BVISNULL( &bc->sb_uri ) ) { 3237 ch_free( bc->sb_uri.bv_val ); 3238 BER_BVZERO( &bc->sb_uri ); 3239 } 3240 if ( !BER_BVISNULL( &bc->sb_binddn ) ) { 3241 ch_free( bc->sb_binddn.bv_val ); 3242 BER_BVZERO( &bc->sb_binddn ); 3243 } 3244 if ( !BER_BVISNULL( &bc->sb_cred ) ) { 3245 ch_free( bc->sb_cred.bv_val ); 3246 BER_BVZERO( &bc->sb_cred ); 3247 } 3248 if ( !BER_BVISNULL( &bc->sb_saslmech ) ) { 3249 ch_free( bc->sb_saslmech.bv_val ); 3250 BER_BVZERO( &bc->sb_saslmech ); 3251 } 3252 if ( bc->sb_secprops ) { 3253 ch_free( bc->sb_secprops ); 3254 bc->sb_secprops = NULL; 3255 } 3256 if ( !BER_BVISNULL( &bc->sb_realm ) ) { 3257 ch_free( bc->sb_realm.bv_val ); 3258 BER_BVZERO( &bc->sb_realm ); 3259 } 3260 if ( !BER_BVISNULL( &bc->sb_authcId ) ) { 3261 ch_free( bc->sb_authcId.bv_val ); 3262 BER_BVZERO( &bc->sb_authcId ); 3263 } 3264 if ( !BER_BVISNULL( &bc->sb_authzId ) ) { 3265 ch_free( bc->sb_authzId.bv_val ); 3266 BER_BVZERO( &bc->sb_authzId ); 3267 } 3268 #ifdef HAVE_TLS 3269 if ( bc->sb_tls_cert ) { 3270 ch_free( bc->sb_tls_cert ); 3271 bc->sb_tls_cert = NULL; 3272 } 3273 if ( bc->sb_tls_key ) { 3274 ch_free( bc->sb_tls_key ); 3275 bc->sb_tls_key = NULL; 3276 } 3277 if ( bc->sb_tls_cacert ) { 3278 ch_free( bc->sb_tls_cacert ); 3279 bc->sb_tls_cacert = NULL; 3280 } 3281 if ( bc->sb_tls_cacertdir ) { 3282 ch_free( bc->sb_tls_cacertdir ); 3283 bc->sb_tls_cacertdir = NULL; 3284 } 3285 if ( bc->sb_tls_reqcert ) { 3286 ch_free( bc->sb_tls_reqcert ); 3287 bc->sb_tls_reqcert = NULL; 3288 } 3289 if ( bc->sb_tls_cipher_suite ) { 3290 ch_free( bc->sb_tls_cipher_suite ); 3291 bc->sb_tls_cipher_suite = NULL; 3292 } 3293 if ( bc->sb_tls_protocol_min ) { 3294 ch_free( bc->sb_tls_protocol_min ); 3295 bc->sb_tls_protocol_min = NULL; 3296 } 3297 #ifdef HAVE_OPENSSL_CRL 3298 if ( bc->sb_tls_crlcheck ) { 3299 ch_free( bc->sb_tls_crlcheck ); 3300 bc->sb_tls_crlcheck = NULL; 3301 } 3302 #endif 3303 if ( bc->sb_tls_ctx ) { 3304 ldap_pvt_tls_ctx_free( bc->sb_tls_ctx ); 3305 bc->sb_tls_ctx = NULL; 3306 } 3307 #endif 3308 } 3309 3310 void 3311 lload_bindconf_tls_defaults( slap_bindconf *bc ) 3312 { 3313 #ifdef HAVE_TLS 3314 if ( bc->sb_tls_do_init ) { 3315 if ( !bc->sb_tls_cacert ) 3316 ldap_pvt_tls_get_option( lload_tls_ld, LDAP_OPT_X_TLS_CACERTFILE, 3317 &bc->sb_tls_cacert ); 3318 if ( !bc->sb_tls_cacertdir ) 3319 ldap_pvt_tls_get_option( lload_tls_ld, LDAP_OPT_X_TLS_CACERTDIR, 3320 &bc->sb_tls_cacertdir ); 3321 if ( !bc->sb_tls_cert ) 3322 ldap_pvt_tls_get_option( 3323 lload_tls_ld, LDAP_OPT_X_TLS_CERTFILE, &bc->sb_tls_cert ); 3324 if ( !bc->sb_tls_key ) 3325 ldap_pvt_tls_get_option( 3326 lload_tls_ld, LDAP_OPT_X_TLS_KEYFILE, &bc->sb_tls_key ); 3327 if ( !bc->sb_tls_cipher_suite ) 3328 ldap_pvt_tls_get_option( lload_tls_ld, LDAP_OPT_X_TLS_CIPHER_SUITE, 3329 &bc->sb_tls_cipher_suite ); 3330 if ( !bc->sb_tls_reqcert ) bc->sb_tls_reqcert = ch_strdup( "demand" ); 3331 #ifdef HAVE_OPENSSL_CRL 3332 if ( !bc->sb_tls_crlcheck ) 3333 lload_tls_get_config( lload_tls_ld, LDAP_OPT_X_TLS_CRLCHECK, 3334 &bc->sb_tls_crlcheck ); 3335 #endif 3336 } 3337 #endif 3338 } 3339 3340 /* -------------------------------------- */ 3341 3342 static char * 3343 strtok_quote( char *line, char *sep, char **quote_ptr, int *iqp ) 3344 { 3345 int inquote; 3346 char *tmp; 3347 static char *next; 3348 3349 *quote_ptr = NULL; 3350 if ( line != NULL ) { 3351 next = line; 3352 } 3353 while ( *next && strchr( sep, *next ) ) { 3354 next++; 3355 } 3356 3357 if ( *next == '\0' ) { 3358 next = NULL; 3359 return NULL; 3360 } 3361 tmp = next; 3362 3363 for ( inquote = 0; *next; ) { 3364 switch ( *next ) { 3365 case '"': 3366 if ( inquote ) { 3367 inquote = 0; 3368 } else { 3369 inquote = 1; 3370 } 3371 AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 ); 3372 break; 3373 3374 case '\\': 3375 if ( next[1] ) 3376 AC_MEMCPY( next, next + 1, strlen( next + 1 ) + 1 ); 3377 next++; /* dont parse the escaped character */ 3378 break; 3379 3380 default: 3381 if ( !inquote ) { 3382 if ( strchr( sep, *next ) != NULL ) { 3383 *quote_ptr = next; 3384 *next++ = '\0'; 3385 return tmp; 3386 } 3387 } 3388 next++; 3389 break; 3390 } 3391 } 3392 *iqp = inquote; 3393 3394 return tmp; 3395 } 3396 3397 static char buf[AC_LINE_MAX]; 3398 static char *line; 3399 static size_t lmax, lcur; 3400 3401 #define CATLINE( buf ) \ 3402 do { \ 3403 size_t len = strlen( buf ); \ 3404 while ( lcur + len + 1 > lmax ) { \ 3405 lmax += AC_LINE_MAX; \ 3406 line = (char *)ch_realloc( line, lmax ); \ 3407 } \ 3408 strcpy( line + lcur, buf ); \ 3409 lcur += len; \ 3410 } while (0) 3411 3412 static void 3413 fp_getline_init( ConfigArgs *c ) 3414 { 3415 c->lineno = -1; 3416 buf[0] = '\0'; 3417 } 3418 3419 static int 3420 fp_getline( FILE *fp, ConfigArgs *c ) 3421 { 3422 char *p; 3423 3424 lcur = 0; 3425 CATLINE( buf ); 3426 c->lineno++; 3427 3428 /* avoid stack of bufs */ 3429 if ( strncasecmp( line, "include", STRLENOF("include") ) == 0 ) { 3430 buf[0] = '\0'; 3431 c->line = line; 3432 return 1; 3433 } 3434 3435 while ( fgets( buf, sizeof(buf), fp ) ) { 3436 p = strchr( buf, '\n' ); 3437 if ( p ) { 3438 if ( p > buf && p[-1] == '\r' ) { 3439 --p; 3440 } 3441 *p = '\0'; 3442 } 3443 /* XXX ugly */ 3444 c->line = line; 3445 if ( line[0] && ( p = line + strlen( line ) - 1 )[0] == '\\' && 3446 p[-1] != '\\' ) { 3447 p[0] = '\0'; 3448 lcur--; 3449 3450 } else { 3451 if ( !isspace( (unsigned char)buf[0] ) ) { 3452 return 1; 3453 } 3454 buf[0] = ' '; 3455 } 3456 CATLINE( buf ); 3457 c->lineno++; 3458 } 3459 3460 buf[0] = '\0'; 3461 c->line = line; 3462 return ( line[0] ? 1 : 0 ); 3463 } 3464 3465 int 3466 lload_config_fp_parse_line( ConfigArgs *c ) 3467 { 3468 char *token; 3469 static char *const hide[] = { "bindconf", NULL }; 3470 static char *const raw[] = { NULL }; 3471 char *quote_ptr; 3472 int i = (int)( sizeof(hide) / sizeof(hide[0]) ) - 1; 3473 int inquote = 0; 3474 3475 c->tline = ch_strdup( c->line ); 3476 c->linelen = strlen( c->line ); 3477 token = strtok_quote( c->tline, " \t", "e_ptr, &inquote ); 3478 3479 if ( token ) 3480 for ( i = 0; hide[i]; i++ ) 3481 if ( !strcasecmp( token, hide[i] ) ) break; 3482 if ( quote_ptr ) *quote_ptr = ' '; 3483 Debug( LDAP_DEBUG_CONFIG, "%s (%s%s)\n", 3484 c->log, hide[i] ? hide[i] : c->line, hide[i] ? " ***" : "" ); 3485 if ( quote_ptr ) *quote_ptr = '\0'; 3486 3487 for ( ;; token = strtok_quote( NULL, " \t", "e_ptr, &inquote ) ) { 3488 if ( c->argc >= c->argv_size ) { 3489 char **tmp; 3490 tmp = ch_realloc( c->argv, 3491 ( c->argv_size + ARGS_STEP ) * sizeof(*c->argv) ); 3492 if ( !tmp ) { 3493 Debug( LDAP_DEBUG_ANY, "%s: out of memory\n", c->log ); 3494 return -1; 3495 } 3496 c->argv = tmp; 3497 c->argv_size += ARGS_STEP; 3498 } 3499 if ( token == NULL ) break; 3500 c->argv[c->argc++] = token; 3501 } 3502 c->argv[c->argc] = NULL; 3503 if ( inquote ) { 3504 /* these directives parse c->line independently of argv tokenizing */ 3505 for ( i = 0; raw[i]; i++ ) 3506 if ( !strcasecmp( c->argv[0], raw[i] ) ) return 0; 3507 3508 Debug( LDAP_DEBUG_ANY, "%s: unterminated quoted string \"%s\"\n", 3509 c->log, c->argv[c->argc - 1] ); 3510 return -1; 3511 } 3512 return 0; 3513 } 3514 3515 void 3516 lload_config_destroy( void ) 3517 { 3518 free( line ); 3519 if ( slapd_args_file ) free( slapd_args_file ); 3520 if ( slapd_pid_file ) free( slapd_pid_file ); 3521 loglevel_destroy(); 3522 } 3523 3524 /* See if the given URL (in plain and parsed form) matches 3525 * any of the server's listener addresses. Return matching 3526 * LloadListener or NULL for no match. 3527 */ 3528 LloadListener * 3529 lload_config_check_my_url( const char *url, LDAPURLDesc *lud ) 3530 { 3531 LloadListener **l = lloadd_get_listeners(); 3532 int i, isMe; 3533 3534 /* Try a straight compare with LloadListener strings */ 3535 for ( i = 0; l && l[i]; i++ ) { 3536 if ( !strcasecmp( url, l[i]->sl_url.bv_val ) ) { 3537 return l[i]; 3538 } 3539 } 3540 3541 isMe = 0; 3542 /* If hostname is empty, or is localhost, or matches 3543 * our hostname, this url refers to this host. 3544 * Compare it against listeners and ports. 3545 */ 3546 if ( !lud->lud_host || !lud->lud_host[0] || 3547 !strncasecmp( 3548 "localhost", lud->lud_host, STRLENOF("localhost") ) || 3549 !strcasecmp( global_host, lud->lud_host ) ) { 3550 for ( i = 0; l && l[i]; i++ ) { 3551 LDAPURLDesc *lu2; 3552 ldap_url_parse_ext( 3553 l[i]->sl_url.bv_val, &lu2, LDAP_PVT_URL_PARSE_DEF_PORT ); 3554 do { 3555 if ( strcasecmp( lud->lud_scheme, lu2->lud_scheme ) ) break; 3556 if ( lud->lud_port != lu2->lud_port ) break; 3557 /* Listener on ANY address */ 3558 if ( !lu2->lud_host || !lu2->lud_host[0] ) { 3559 isMe = 1; 3560 break; 3561 } 3562 /* URL on ANY address */ 3563 if ( !lud->lud_host || !lud->lud_host[0] ) { 3564 isMe = 1; 3565 break; 3566 } 3567 /* Listener has specific host, must 3568 * match it 3569 */ 3570 if ( !strcasecmp( lud->lud_host, lu2->lud_host ) ) { 3571 isMe = 1; 3572 break; 3573 } 3574 } while (0); 3575 ldap_free_urldesc( lu2 ); 3576 if ( isMe ) { 3577 return l[i]; 3578 } 3579 } 3580 } 3581 return NULL; 3582 } 3583 3584 #ifdef BALANCER_MODULE 3585 static int 3586 backend_cf_gen( ConfigArgs *c ) 3587 { 3588 LloadBackend *b = c->ca_private; 3589 enum lcf_backend flag = 0; 3590 int rc = LDAP_SUCCESS; 3591 3592 assert( b != NULL ); 3593 3594 if ( c->op == SLAP_CONFIG_EMIT ) { 3595 switch ( c->type ) { 3596 case CFG_URI: 3597 c->value_bv = b->b_uri; 3598 break; 3599 case CFG_NUMCONNS: 3600 c->value_uint = b->b_numconns; 3601 break; 3602 case CFG_BINDCONNS: 3603 c->value_uint = b->b_numbindconns; 3604 break; 3605 case CFG_RETRY: 3606 c->value_uint = b->b_retry_timeout; 3607 break; 3608 case CFG_MAX_PENDING_CONNS: 3609 c->value_uint = b->b_max_conn_pending; 3610 break; 3611 case CFG_MAX_PENDING_OPS: 3612 c->value_uint = b->b_max_pending; 3613 break; 3614 case CFG_STARTTLS: 3615 enum_to_verb( tlskey, b->b_tls_conf, &c->value_bv ); 3616 break; 3617 default: 3618 rc = 1; 3619 break; 3620 } 3621 3622 return rc; 3623 } else if ( c->op == LDAP_MOD_DELETE ) { 3624 /* We only need to worry about deletions to multi-value or MAY 3625 * attributes */ 3626 switch ( c->type ) { 3627 case CFG_STARTTLS: 3628 b->b_tls_conf = LLOAD_CLEARTEXT; 3629 break; 3630 default: 3631 break; 3632 } 3633 return rc; 3634 } 3635 3636 switch ( c->type ) { 3637 case CFG_URI: 3638 rc = backend_config_url( b, &c->value_bv ); 3639 if ( rc ) { 3640 backend_config_url( b, &b->b_uri ); 3641 goto fail; 3642 } 3643 if ( !BER_BVISNULL( &b->b_uri ) ) { 3644 ch_free( b->b_uri.bv_val ); 3645 } 3646 b->b_uri = c->value_bv; 3647 flag = LLOAD_BACKEND_MOD_OTHER; 3648 break; 3649 case CFG_NUMCONNS: 3650 if ( !c->value_uint ) { 3651 snprintf( c->cr_msg, sizeof(c->cr_msg), 3652 "invalid connection pool configuration" ); 3653 goto fail; 3654 } 3655 b->b_numconns = c->value_uint; 3656 flag = LLOAD_BACKEND_MOD_CONNS; 3657 break; 3658 case CFG_BINDCONNS: 3659 if ( !c->value_uint ) { 3660 snprintf( c->cr_msg, sizeof(c->cr_msg), 3661 "invalid connection pool configuration" ); 3662 goto fail; 3663 } 3664 b->b_numbindconns = c->value_uint; 3665 flag = LLOAD_BACKEND_MOD_CONNS; 3666 break; 3667 case CFG_RETRY: 3668 b->b_retry_timeout = c->value_uint; 3669 break; 3670 case CFG_MAX_PENDING_CONNS: 3671 b->b_max_conn_pending = c->value_uint; 3672 break; 3673 case CFG_MAX_PENDING_OPS: 3674 b->b_max_pending = c->value_uint; 3675 break; 3676 case CFG_STARTTLS: { 3677 int i = bverb_to_mask( &c->value_bv, tlskey ); 3678 if ( BER_BVISNULL( &tlskey[i].word ) ) { 3679 snprintf( c->cr_msg, sizeof(c->cr_msg), 3680 "invalid starttls configuration" ); 3681 goto fail; 3682 } 3683 #ifndef HAVE_TLS 3684 if ( tlskey[i].mask == LLOAD_STARTTLS_OPTIONAL ) { 3685 Debug( LDAP_DEBUG_ANY, "%s: " 3686 "lloadd compiled without TLS but starttls specified, " 3687 "it will be ignored\n", 3688 c->log ); 3689 } else if ( tlskey[i].mask != LLOAD_CLEARTEXT ) { 3690 snprintf( c->cr_msg, sizeof(c->cr_msg), 3691 "invalid starttls configuration when compiled without " 3692 "TLS support" ); 3693 goto fail; 3694 } 3695 #endif /* ! HAVE_TLS */ 3696 b->b_tls_conf = tlskey[i].mask; 3697 } break; 3698 default: 3699 rc = 1; 3700 break; 3701 } 3702 3703 /* do not set this if it has already been set by another callback, e.g. 3704 * lload_backend_ldadd */ 3705 if ( lload_change.type == LLOAD_CHANGE_UNDEFINED ) { 3706 lload_change.type = LLOAD_CHANGE_MODIFY; 3707 } 3708 lload_change.object = LLOAD_BACKEND; 3709 lload_change.target = b; 3710 lload_change.flags.backend |= flag; 3711 3712 config_push_cleanup( c, lload_backend_finish ); 3713 return rc; 3714 3715 fail: 3716 if ( lload_change.type == LLOAD_CHANGE_ADD ) { 3717 /* Abort the ADD */ 3718 lload_change.type = LLOAD_CHANGE_DEL; 3719 } 3720 3721 Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg ); 3722 return 1; 3723 } 3724 3725 int 3726 lload_back_init_cf( BackendInfo *bi ) 3727 { 3728 /* Make sure we don't exceed the bits reserved for userland */ 3729 config_check_userland( CFG_LAST ); 3730 3731 bi->bi_cf_ocs = lloadocs; 3732 3733 return config_register_schema( config_back_cf_table, lloadocs ); 3734 } 3735 3736 static int 3737 lload_backend_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *ca ) 3738 { 3739 LloadBackend *b; 3740 Attribute *a; 3741 AttributeDescription *ad = NULL; 3742 struct berval bv, type, rdn; 3743 const char *text; 3744 char *name; 3745 3746 Debug( LDAP_DEBUG_TRACE, "lload_backend_ldadd: " 3747 "a new backend-server is being added\n" ); 3748 3749 if ( p->ce_type != Cft_Backend || !p->ce_bi || 3750 p->ce_bi->bi_cf_ocs != lloadocs ) 3751 return LDAP_CONSTRAINT_VIOLATION; 3752 3753 dnRdn( &e->e_name, &rdn ); 3754 type.bv_len = strchr( rdn.bv_val, '=' ) - rdn.bv_val; 3755 type.bv_val = rdn.bv_val; 3756 3757 /* Find attr */ 3758 slap_bv2ad( &type, &ad, &text ); 3759 if ( ad != slap_schema.si_ad_cn ) return LDAP_NAMING_VIOLATION; 3760 3761 a = attr_find( e->e_attrs, ad ); 3762 if ( !a || a->a_numvals != 1 ) return LDAP_NAMING_VIOLATION; 3763 bv = a->a_vals[0]; 3764 3765 if ( bv.bv_val[0] == '{' && ( name = strchr( bv.bv_val, '}' ) ) ) { 3766 name++; 3767 bv.bv_len -= name - bv.bv_val; 3768 bv.bv_val = name; 3769 } 3770 3771 b = backend_alloc(); 3772 ber_dupbv( &b->b_name, &bv ); 3773 3774 ca->bi = p->ce_bi; 3775 ca->ca_private = b; 3776 config_push_cleanup( ca, lload_backend_finish ); 3777 3778 /* ca cleanups are only run in the case of online config but we use it to 3779 * save the new config when done with the entry */ 3780 ca->lineno = 0; 3781 3782 lload_change.type = LLOAD_CHANGE_ADD; 3783 lload_change.object = LLOAD_BACKEND; 3784 lload_change.target = b; 3785 3786 return LDAP_SUCCESS; 3787 } 3788 3789 #ifdef SLAP_CONFIG_DELETE 3790 static int 3791 lload_backend_lddel( CfEntryInfo *ce, Operation *op ) 3792 { 3793 LloadBackend *b = ce->ce_private; 3794 3795 lload_change.type = LLOAD_CHANGE_DEL; 3796 lload_change.object = LLOAD_BACKEND; 3797 lload_change.target = b; 3798 3799 return LDAP_SUCCESS; 3800 } 3801 #endif /* SLAP_CONFIG_DELETE */ 3802 3803 static int 3804 lload_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *c ) 3805 { 3806 struct berval bv; 3807 LloadBackend *b; 3808 int i = 0; 3809 3810 bv.bv_val = c->cr_msg; 3811 LDAP_CIRCLEQ_FOREACH ( b, &backend, b_next ) { 3812 char buf[STRLENOF( "server 4294967295" ) + 1] = { 0 }; 3813 3814 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), 3815 "cn=" SLAP_X_ORDERED_FMT "server %d", i, i + 1 ); 3816 3817 snprintf( buf, sizeof(buf), "server %d", i + 1 ); 3818 ber_str2bv( buf, 0, 1, &b->b_name ); 3819 3820 c->ca_private = b; 3821 c->valx = i; 3822 3823 config_build_entry( op, rs, p->e_private, c, &bv, &lloadocs[1], NULL ); 3824 3825 i++; 3826 } 3827 return LDAP_SUCCESS; 3828 } 3829 #endif /* BALANCER_MODULE */ 3830