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