1/* $NetBSD: config.c,v 1.2 2021/08/14 16:14:59 christos Exp $ */ 2 3/* config.c - configuration parsing for back-asyncmeta */ 4/* $OpenLDAP$ */ 5/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2016-2021 The OpenLDAP Foundation. 8 * Portions Copyright 2016 Symas Corporation. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted only as authorized by the OpenLDAP 13 * Public License. 14 * 15 * A copy of this license is available in the file LICENSE in the 16 * top-level directory of the distribution or, alternatively, at 17 * <http://www.OpenLDAP.org/license.html>. 18 */ 19 20/* ACKNOWLEDGEMENTS: 21 * This work was developed by Symas Corporation 22 * based on back-meta module for inclusion in OpenLDAP Software. 23 * This work was sponsored by Ericsson. */ 24 25#include <sys/cdefs.h> 26__RCSID("$NetBSD: config.c,v 1.2 2021/08/14 16:14:59 christos Exp $"); 27 28#include "portable.h" 29 30#include <stdio.h> 31#include <ctype.h> 32 33#include <ac/string.h> 34#include <ac/socket.h> 35 36#include "slap.h" 37#include "slap-config.h" 38#include "lutil.h" 39#include "ldif.h" 40#include "../back-ldap/back-ldap.h" 41#include "back-asyncmeta.h" 42 43#ifdef LDAP_DEVEL 44#define SLAP_AUTH_DN 1 45#endif 46 47static ConfigDriver asyncmeta_back_cf_gen; 48static ConfigLDAPadd asyncmeta_ldadd; 49static ConfigCfAdd asyncmeta_cfadd; 50 51/* Three sets of enums: 52 * 1) attrs that are only valid in the base config 53 * 2) attrs that are valid in base or target 54 * 3) attrs that are only valid in a target 55 */ 56 57/* Base attrs */ 58enum { 59 LDAP_BACK_CFG_DNCACHE_TTL = 1, 60 LDAP_BACK_CFG_IDLE_TIMEOUT, 61 LDAP_BACK_CFG_ONERR, 62 LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER, 63 LDAP_BACK_CFG_CONNPOOLMAX, 64 LDAP_BACK_CFG_MAX_TIMEOUT_OPS, 65 LDAP_BACK_CFG_MAX_PENDING_OPS, 66 LDAP_BACK_CFG_MAX_TARGET_CONNS, 67 LDAP_BACK_CFG_LAST_BASE, 68}; 69 70/* Base or target */ 71enum { 72 LDAP_BACK_CFG_BIND_TIMEOUT = LDAP_BACK_CFG_LAST_BASE, 73 LDAP_BACK_CFG_CANCEL, 74 LDAP_BACK_CFG_CHASE, 75 LDAP_BACK_CFG_CLIENT_PR, 76 LDAP_BACK_CFG_DEFAULT_T, 77 LDAP_BACK_CFG_NETWORK_TIMEOUT, 78 LDAP_BACK_CFG_NOREFS, 79 LDAP_BACK_CFG_NOUNDEFFILTER, 80 LDAP_BACK_CFG_NRETRIES, 81 LDAP_BACK_CFG_QUARANTINE, 82 LDAP_BACK_CFG_REBIND, 83 LDAP_BACK_CFG_TIMEOUT, 84 LDAP_BACK_CFG_VERSION, 85 LDAP_BACK_CFG_ST_REQUEST, 86 LDAP_BACK_CFG_T_F, 87 LDAP_BACK_CFG_TLS, 88 LDAP_BACK_CFG_LAST_BOTH 89}; 90 91/* Target attrs */ 92enum { 93 LDAP_BACK_CFG_URI = LDAP_BACK_CFG_LAST_BOTH, 94 LDAP_BACK_CFG_IDASSERT_AUTHZFROM, 95 LDAP_BACK_CFG_IDASSERT_BIND, 96 LDAP_BACK_CFG_SUFFIXM, 97 LDAP_BACK_CFG_SUBTREE_EX, 98 LDAP_BACK_CFG_SUBTREE_IN, 99 LDAP_BACK_CFG_KEEPALIVE, 100 LDAP_BACK_CFG_FILTER, 101 LDAP_BACK_CFG_TCP_USER_TIMEOUT, 102 LDAP_BACK_CFG_LAST 103}; 104 105static ConfigTable a_metacfg[] = { 106 { "uri", "uri", 2, 0, 0, 107 ARG_MAGIC|LDAP_BACK_CFG_URI, 108 asyncmeta_back_cf_gen, "( OLcfgDbAt:0.14 " 109 "NAME 'olcDbURI' " 110 "DESC 'URI (list) for remote DSA' " 111 "SYNTAX OMsDirectoryString " 112 "SINGLE-VALUE )", 113 NULL, NULL }, 114 { "tls", "what", 2, 0, 0, 115 ARG_MAGIC|LDAP_BACK_CFG_TLS, 116 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.1 " 117 "NAME 'olcDbStartTLS' " 118 "DESC 'StartTLS' " 119 "SYNTAX OMsDirectoryString " 120 "SINGLE-VALUE )", 121 NULL, NULL }, 122 { "idassert-bind", "args", 2, 0, 0, 123 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_BIND, 124 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.7 " 125 "NAME 'olcDbIDAssertBind' " 126 "DESC 'Remote Identity Assertion administrative identity auth bind configuration' " 127 "SYNTAX OMsDirectoryString " 128 "SINGLE-VALUE )", 129 NULL, NULL }, 130 { "idassert-authzFrom", "authzRule", 2, 2, 0, 131 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_AUTHZFROM, 132 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.9 " 133 "NAME 'olcDbIDAssertAuthzFrom' " 134 "DESC 'Remote Identity Assertion authz rules' " 135 "EQUALITY caseIgnoreMatch " 136 "SYNTAX OMsDirectoryString " 137 "X-ORDERED 'VALUES' )", 138 NULL, NULL }, 139 { "rebind-as-user", "true|FALSE", 1, 2, 0, 140 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_REBIND, 141 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.10 " 142 "NAME 'olcDbRebindAsUser' " 143 "DESC 'Rebind as user' " 144 "SYNTAX OMsBoolean " 145 "SINGLE-VALUE )", 146 NULL, NULL }, 147 { "chase-referrals", "true|FALSE", 2, 2, 0, 148 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_CHASE, 149 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.11 " 150 "NAME 'olcDbChaseReferrals' " 151 "DESC 'Chase referrals' " 152 "SYNTAX OMsBoolean " 153 "SINGLE-VALUE )", 154 NULL, NULL }, 155 { "t-f-support", "true|FALSE|discover", 2, 2, 0, 156 ARG_MAGIC|LDAP_BACK_CFG_T_F, 157 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.12 " 158 "NAME 'olcDbTFSupport' " 159 "DESC 'Absolute filters support' " 160 "SYNTAX OMsDirectoryString " 161 "SINGLE-VALUE )", 162 NULL, NULL }, 163 { "timeout", "timeout(list)", 2, 0, 0, 164 ARG_MAGIC|LDAP_BACK_CFG_TIMEOUT, 165 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.14 " 166 "NAME 'olcDbTimeout' " 167 "DESC 'Per-operation timeouts' " 168 "SYNTAX OMsDirectoryString " 169 "SINGLE-VALUE )", 170 NULL, NULL }, 171 { "idle-timeout", "timeout", 2, 2, 0, 172 ARG_MAGIC|LDAP_BACK_CFG_IDLE_TIMEOUT, 173 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.15 " 174 "NAME 'olcDbIdleTimeout' " 175 "DESC 'connection idle timeout' " 176 "SYNTAX OMsDirectoryString " 177 "SINGLE-VALUE )", 178 NULL, NULL }, 179 { "network-timeout", "timeout", 2, 2, 0, 180 ARG_MAGIC|LDAP_BACK_CFG_NETWORK_TIMEOUT, 181 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.17 " 182 "NAME 'olcDbNetworkTimeout' " 183 "DESC 'connection network timeout' " 184 "SYNTAX OMsDirectoryString " 185 "SINGLE-VALUE )", 186 NULL, NULL }, 187 { "protocol-version", "version", 2, 2, 0, 188 ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_VERSION, 189 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.18 " 190 "NAME 'olcDbProtocolVersion' " 191 "DESC 'protocol version' " 192 "SYNTAX OMsInteger " 193 "SINGLE-VALUE )", 194 NULL, NULL }, 195 196 { "cancel", "ABANDON|ignore|exop", 2, 2, 0, 197 ARG_MAGIC|LDAP_BACK_CFG_CANCEL, 198 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.20 " 199 "NAME 'olcDbCancel' " 200 "DESC 'abandon/ignore/exop operations when appropriate' " 201 "SYNTAX OMsDirectoryString " 202 "SINGLE-VALUE )", 203 NULL, NULL }, 204 { "quarantine", "retrylist", 2, 2, 0, 205 ARG_MAGIC|LDAP_BACK_CFG_QUARANTINE, 206 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.21 " 207 "NAME 'olcDbQuarantine' " 208 "DESC 'Quarantine database if connection fails and retry according to rule' " 209 "SYNTAX OMsDirectoryString " 210 "SINGLE-VALUE )", 211 NULL, NULL }, 212 213 { "conn-pool-max", "<n>", 2, 2, 0, 214 ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_CONNPOOLMAX, 215 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.23 " 216 "NAME 'olcDbConnectionPoolMax' " 217 "DESC 'Max size of privileged connections pool' " 218 "SYNTAX OMsInteger " 219 "SINGLE-VALUE )", 220 NULL, NULL }, 221#ifdef SLAP_CONTROL_X_SESSION_TRACKING 222 { "session-tracking-request", "true|FALSE", 2, 2, 0, 223 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_ST_REQUEST, 224 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.24 " 225 "NAME 'olcDbSessionTrackingRequest' " 226 "DESC 'Add session tracking control to proxied requests' " 227 "SYNTAX OMsBoolean " 228 "SINGLE-VALUE )", 229 NULL, NULL }, 230#endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 231 { "norefs", "true|FALSE", 2, 2, 0, 232 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_NOREFS, 233 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.25 " 234 "NAME 'olcDbNoRefs' " 235 "DESC 'Do not return search reference responses' " 236 "SYNTAX OMsBoolean " 237 "SINGLE-VALUE )", 238 NULL, NULL }, 239 { "noundeffilter", "true|FALSE", 2, 2, 0, 240 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_NOUNDEFFILTER, 241 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.26 " 242 "NAME 'olcDbNoUndefFilter' " 243 "DESC 'Do not propagate undefined search filters' " 244 "SYNTAX OMsBoolean " 245 "SINGLE-VALUE )", 246 NULL, NULL }, 247 248 { "suffixmassage", "local> <remote", 2, 3, 0, 249 ARG_MAGIC|LDAP_BACK_CFG_SUFFIXM, 250 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.117 " 251 "NAME 'olcDbSuffixMassage' " 252 "DESC 'DN suffix massage' " 253 "EQUALITY caseIgnoreMatch " 254 "SYNTAX OMsDirectoryString " 255 "SINGLE-VALUE )", 256 NULL, NULL }, 257 258 { "subtree-exclude", "pattern", 2, 2, 0, 259 ARG_MAGIC|LDAP_BACK_CFG_SUBTREE_EX, 260 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.103 " 261 "NAME 'olcDbSubtreeExclude' " 262 "DESC 'DN of subtree to exclude from target' " 263 "EQUALITY caseIgnoreMatch " 264 "SYNTAX OMsDirectoryString )", 265 NULL, NULL }, 266 { "subtree-include", "pattern", 2, 2, 0, 267 ARG_MAGIC|LDAP_BACK_CFG_SUBTREE_IN, 268 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.104 " 269 "NAME 'olcDbSubtreeInclude' " 270 "DESC 'DN of subtree to include in target' " 271 "EQUALITY caseIgnoreMatch " 272 "SYNTAX OMsDirectoryString )", 273 NULL, NULL }, 274 { "default-target", "[none|<target ID>]", 1, 2, 0, 275 ARG_MAGIC|LDAP_BACK_CFG_DEFAULT_T, 276 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.105 " 277 "NAME 'olcDbDefaultTarget' " 278 "DESC 'Specify the default target' " 279 "SYNTAX OMsDirectoryString " 280 "SINGLE-VALUE )", 281 NULL, NULL }, 282 { "dncache-ttl", "ttl", 2, 2, 0, 283 ARG_MAGIC|LDAP_BACK_CFG_DNCACHE_TTL, 284 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.106 " 285 "NAME 'olcDbDnCacheTtl' " 286 "DESC 'dncache ttl' " 287 "SYNTAX OMsDirectoryString " 288 "SINGLE-VALUE )", 289 NULL, NULL }, 290 { "bind-timeout", "microseconds", 2, 2, 0, 291 ARG_MAGIC|ARG_ULONG|LDAP_BACK_CFG_BIND_TIMEOUT, 292 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.107 " 293 "NAME 'olcDbBindTimeout' " 294 "DESC 'bind timeout' " 295 "SYNTAX OMsDirectoryString " 296 "SINGLE-VALUE )", 297 NULL, NULL }, 298 { "onerr", "CONTINUE|report|stop", 2, 2, 0, 299 ARG_MAGIC|LDAP_BACK_CFG_ONERR, 300 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.108 " 301 "NAME 'olcDbOnErr' " 302 "DESC 'error handling' " 303 "SYNTAX OMsDirectoryString " 304 "SINGLE-VALUE )", 305 NULL, NULL }, 306 { "pseudoroot-bind-defer", "TRUE|false", 2, 2, 0, 307 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER, 308 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.109 " 309 "NAME 'olcDbPseudoRootBindDefer' " 310 "DESC 'error handling' " 311 "SYNTAX OMsBoolean " 312 "SINGLE-VALUE )", 313 NULL, NULL }, 314 { "root-bind-defer", "TRUE|false", 2, 2, 0, 315 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER, 316 asyncmeta_back_cf_gen, NULL, NULL, NULL }, 317 { "nretries", "NEVER|forever|<number>", 2, 2, 0, 318 ARG_MAGIC|LDAP_BACK_CFG_NRETRIES, 319 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.110 " 320 "NAME 'olcDbNretries' " 321 "DESC 'retry handling' " 322 "SYNTAX OMsDirectoryString " 323 "SINGLE-VALUE )", 324 NULL, NULL }, 325 { "client-pr", "accept-unsolicited|disable|<size>", 2, 2, 0, 326 ARG_MAGIC|LDAP_BACK_CFG_CLIENT_PR, 327 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.111 " 328 "NAME 'olcDbClientPr' " 329 "DESC 'PagedResults handling' " 330 "SYNTAX OMsDirectoryString " 331 "SINGLE-VALUE )", 332 NULL, NULL }, 333 334 { "", "", 0, 0, 0, ARG_IGNORED, 335 NULL, "( OLcfgDbAt:3.116 NAME 'olcAsyncMetaSub' " 336 "DESC 'Placeholder to name a Target entry' " 337 "EQUALITY caseIgnoreMatch " 338 "SYNTAX OMsDirectoryString " 339 "SINGLE-VALUE X-ORDERED 'SIBLINGS' )", NULL, NULL }, 340 341 { "keepalive", "keepalive", 2, 2, 0, 342 ARG_MAGIC|LDAP_BACK_CFG_KEEPALIVE, 343 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.29 " 344 "NAME 'olcDbKeepalive' " 345 "DESC 'TCP keepalive' " 346 "SYNTAX OMsDirectoryString " 347 "SINGLE-VALUE )", 348 NULL, NULL }, 349 350 { "tcp-user-timeout", "milliseconds", 2, 2, 0, 351 ARG_MAGIC|ARG_UINT|LDAP_BACK_CFG_TCP_USER_TIMEOUT, 352 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.30 " 353 "NAME 'olcDbTcpUserTimeout' " 354 "DESC 'TCP User Timeout' " 355 "SYNTAX OMsInteger " 356 "SINGLE-VALUE )", 357 NULL, NULL }, 358 359 { "filter", "pattern", 2, 2, 0, 360 ARG_MAGIC|LDAP_BACK_CFG_FILTER, 361 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.112 " 362 "NAME 'olcDbFilter' " 363 "DESC 'Filter regex pattern to include in target' " 364 "EQUALITY caseExactMatch " 365 "SYNTAX OMsDirectoryString )", 366 NULL, NULL }, 367 368 { "max-pending-ops", "<n>", 2, 2, 0, 369 ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_MAX_PENDING_OPS, 370 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.113 " 371 "NAME 'olcDbMaxPendingOps' " 372 "DESC 'Maximum number of pending operations' " 373 "SYNTAX OMsInteger " 374 "SINGLE-VALUE )", 375 NULL, NULL }, 376 377 { "max-target-conns", "<n>", 2, 2, 0, 378 ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_MAX_TARGET_CONNS, 379 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.114 " 380 "NAME 'olcDbMaxTargetConns' " 381 "DESC 'Maximum number of open connections per target' " 382 "SYNTAX OMsInteger " 383 "SINGLE-VALUE )", 384 NULL, NULL }, 385 386 { "max-timeout-ops", "<n>", 2, 2, 0, 387 ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_MAX_TIMEOUT_OPS, 388 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.115 " 389 "NAME 'olcDbMaxTimeoutOps' " 390 "DESC 'Maximum number of consecutive timeout operations after which the connection is reset' " 391 "SYNTAX OMsInteger " 392 "SINGLE-VALUE )", 393 NULL, NULL }, 394 395 { NULL, NULL, 0, 0, 0, ARG_IGNORED, 396 NULL, NULL, NULL, NULL } 397}; 398 399#ifdef SLAP_CONTROL_X_SESSION_TRACKING 400#define ST_ATTR "$ olcDbSessionTrackingRequest " 401#else 402#define ST_ATTR "" 403#endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 404 405#define COMMON_ATTRS \ 406 "$ olcDbBindTimeout " \ 407 "$ olcDbCancel " \ 408 "$ olcDbChaseReferrals " \ 409 "$ olcDbClientPr " \ 410 "$ olcDbDefaultTarget " \ 411 "$ olcDbNetworkTimeout " \ 412 "$ olcDbNoRefs " \ 413 "$ olcDbNoUndefFilter " \ 414 "$ olcDbNretries " \ 415 "$ olcDbProtocolVersion " \ 416 "$ olcDbQuarantine " \ 417 "$ olcDbRebindAsUser " \ 418 ST_ATTR \ 419 "$ olcDbStartTLS " \ 420 "$ olcDbTFSupport " 421 422static ConfigOCs a_metaocs[] = { 423 { "( OLcfgDbOc:3.4 " 424 "NAME 'olcAsyncMetaConfig' " 425 "DESC 'Asyncmeta backend configuration' " 426 "SUP olcDatabaseConfig " 427 "MAY ( olcDbDnCacheTtl " 428 "$ olcDbIdleTimeout " 429 "$ olcDbOnErr " 430 "$ olcDbPseudoRootBindDefer " 431 "$ olcDbConnectionPoolMax " 432 "$ olcDbMaxTimeoutOps" 433 "$ olcDbMaxPendingOps " 434 "$ olcDbMaxTargetConns" 435 /* defaults, may be overridden per-target */ 436 COMMON_ATTRS 437 ") )", 438 Cft_Database, a_metacfg, NULL, asyncmeta_cfadd }, 439 { "( OLcfgDbOc:3.5 " 440 "NAME 'olcAsyncMetaTargetConfig' " 441 "DESC 'Asyncmeta target configuration' " 442 "SUP olcConfig STRUCTURAL " 443 "MUST ( olcAsyncMetaSub $ olcDbURI ) " 444 "MAY ( olcDbIDAssertAuthzFrom " 445 "$ olcDbIDAssertBind " 446 "$ olcDbSuffixMassage " 447 "$ olcDbSubtreeExclude " 448 "$ olcDbSubtreeInclude " 449 "$ olcDbTimeout " 450 "$ olcDbKeepalive " 451 "$ olcDbFilter " 452 "$ olcDbTcpUserTimeout " 453 454 /* defaults may be inherited */ 455 COMMON_ATTRS 456 ") )", 457 Cft_Misc, a_metacfg, asyncmeta_ldadd }, 458 { NULL, 0, NULL } 459}; 460 461static int 462asyncmeta_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *c ) 463{ 464 if ( p->ce_type != Cft_Database || !p->ce_be || 465 p->ce_be->be_cf_ocs != a_metaocs ) 466 return LDAP_CONSTRAINT_VIOLATION; 467 468 c->be = p->ce_be; 469 return LDAP_SUCCESS; 470} 471 472static int 473asyncmeta_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *c ) 474{ 475 a_metainfo_t *mi = ( a_metainfo_t * )c->be->be_private; 476 struct berval bv; 477 int i; 478 479 bv.bv_val = c->cr_msg; 480 for ( i=0; i<mi->mi_ntargets; i++ ) { 481 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), 482 "olcAsyncMetaSub=" SLAP_X_ORDERED_FMT "uri", i ); 483 c->ca_private = mi->mi_targets[i]; 484 c->valx = i; 485 config_build_entry( op, rs, p->e_private, c, 486 &bv, &a_metaocs[1], NULL ); 487 } 488 489 return LDAP_SUCCESS; 490} 491 492static int 493asyncmeta_back_new_target( 494 a_metatarget_t **mtp ) 495{ 496 a_metatarget_t *mt; 497 498 *mtp = NULL; 499 500 mt = ch_calloc( sizeof( a_metatarget_t ), 1 ); 501 502 ldap_pvt_thread_mutex_init( &mt->mt_uri_mutex ); 503 504 mt->mt_idassert_mode = LDAP_BACK_IDASSERT_LEGACY; 505 mt->mt_idassert_authmethod = LDAP_AUTH_NONE; 506 mt->mt_idassert_tls = SB_TLS_DEFAULT; 507 /* by default, use proxyAuthz control on each operation */ 508 mt->mt_idassert_flags = LDAP_BACK_AUTH_PRESCRIPTIVE; 509 510 *mtp = mt; 511 512 return 0; 513} 514 515/* suffixmassage config */ 516static int 517asyncmeta_suffixm_config( 518 ConfigArgs *c, 519 int argc, 520 char **argv, 521 a_metatarget_t *mt 522) 523{ 524 BackendDB *tmp_bd; 525 struct berval dn, nvnc, pvnc, nrnc, prnc; 526 int j; 527 528 /* 529 * syntax: 530 * 531 * suffixmassage <local suffix> <remote suffix> 532 * 533 * the <local suffix> field must be defined as a valid suffix 534 * (or suffixAlias?) for the current database; 535 * the <remote suffix> shouldn't have already been 536 * defined as a valid suffix or suffixAlias for the 537 * current server 538 */ 539 540 ber_str2bv( argv[ 1 ], 0, 0, &dn ); 541 if ( dnPrettyNormal( NULL, &dn, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) { 542 snprintf( c->cr_msg, sizeof( c->cr_msg ), 543 "suffix \"%s\" is invalid", 544 argv[1] ); 545 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 546 return 1; 547 } 548 549 for ( j = 0; !BER_BVISNULL( &c->be->be_nsuffix[ j ] ); j++ ) { 550 if ( dnIsSuffix( &nvnc, &c->be->be_nsuffix[ 0 ] ) ) { 551 break; 552 } 553 } 554 555 if ( BER_BVISNULL( &c->be->be_nsuffix[ j ] ) ) { 556 snprintf( c->cr_msg, sizeof( c->cr_msg ), 557 "suffix \"%s\" must be within the database naming context", 558 argv[1] ); 559 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 560 free( pvnc.bv_val ); 561 free( nvnc.bv_val ); 562 return 1; 563 } 564 565 ber_str2bv( argv[ 2 ], 0, 0, &dn ); 566 if ( dnPrettyNormal( NULL, &dn, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) { 567 snprintf( c->cr_msg, sizeof( c->cr_msg ), 568 "massaged suffix \"%s\" is invalid", 569 argv[2] ); 570 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 571 free( pvnc.bv_val ); 572 free( nvnc.bv_val ); 573 return 1; 574 } 575 576 tmp_bd = select_backend( &nrnc, 0 ); 577 if ( tmp_bd != NULL && tmp_bd->be_private == c->be->be_private ) { 578 Debug( LDAP_DEBUG_ANY, 579 "%s: warning: <massaged suffix> \"%s\" resolves to this database, in " 580 "\"suffixMassage <suffix> <massaged suffix>\"\n", 581 c->log, prnc.bv_val ); 582 } 583 584 mt->mt_lsuffixm = pvnc; 585 mt->mt_rsuffixm = prnc; 586 587 free( nvnc.bv_val ); 588 free( nrnc.bv_val ); 589 590 return 0; 591} 592 593int 594asyncmeta_subtree_free( a_metasubtree_t *ms ) 595{ 596 switch ( ms->ms_type ) { 597 case META_ST_SUBTREE: 598 case META_ST_SUBORDINATE: 599 ber_memfree( ms->ms_dn.bv_val ); 600 break; 601 602 case META_ST_REGEX: 603 regfree( &ms->ms_regex ); 604 ber_memfree( ms->ms_regex_pattern.bv_val ); 605 break; 606 607 default: 608 return -1; 609 } 610 611 ch_free( ms ); 612 return 0; 613} 614 615int 616asyncmeta_subtree_destroy( a_metasubtree_t *ms ) 617{ 618 if ( ms->ms_next ) { 619 asyncmeta_subtree_destroy( ms->ms_next ); 620 } 621 622 return asyncmeta_subtree_free( ms ); 623} 624 625static void 626asyncmeta_filter_free( metafilter_t *mf ) 627{ 628 regfree( &mf->mf_regex ); 629 ber_memfree( mf->mf_regex_pattern.bv_val ); 630 ch_free( mf ); 631} 632 633void 634asyncmeta_filter_destroy( metafilter_t *mf ) 635{ 636 if ( mf->mf_next ) 637 asyncmeta_filter_destroy( mf->mf_next ); 638 asyncmeta_filter_free( mf ); 639} 640 641static struct berval st_styles[] = { 642 BER_BVC("subtree"), 643 BER_BVC("children"), 644 BER_BVC("regex") 645}; 646 647static int 648asyncmeta_subtree_unparse( 649 ConfigArgs *c, 650 a_metatarget_t *mt ) 651{ 652 a_metasubtree_t *ms; 653 struct berval bv, *style; 654 655 if ( !mt->mt_subtree ) 656 return 1; 657 658 /* can only be one of exclude or include */ 659 if (( c->type == LDAP_BACK_CFG_SUBTREE_EX ) ^ mt->mt_subtree_exclude ) 660 return 1; 661 662 bv.bv_val = c->cr_msg; 663 for ( ms=mt->mt_subtree; ms; ms=ms->ms_next ) { 664 if (ms->ms_type == META_ST_SUBTREE) 665 style = &st_styles[0]; 666 else if ( ms->ms_type == META_ST_SUBORDINATE ) 667 style = &st_styles[1]; 668 else if ( ms->ms_type == META_ST_REGEX ) 669 style = &st_styles[2]; 670 else { 671 assert(0); 672 continue; 673 } 674 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), 675 "dn.%s:%s", style->bv_val, ms->ms_dn.bv_val ); 676 value_add_one( &c->rvalue_vals, &bv ); 677 } 678 return 0; 679} 680 681static int 682asyncmeta_subtree_config( 683 a_metatarget_t *mt, 684 ConfigArgs *c ) 685{ 686 meta_st_t type = META_ST_SUBTREE; 687 char *pattern; 688 struct berval ndn = BER_BVNULL; 689 a_metasubtree_t *ms = NULL; 690 691 if ( c->type == LDAP_BACK_CFG_SUBTREE_EX ) { 692 if ( mt->mt_subtree && !mt->mt_subtree_exclude ) { 693 snprintf( c->cr_msg, sizeof(c->cr_msg), 694 "\"subtree-exclude\" incompatible with previous \"subtree-include\" directives" ); 695 return 1; 696 } 697 698 mt->mt_subtree_exclude = 1; 699 700 } else { 701 if ( mt->mt_subtree && mt->mt_subtree_exclude ) { 702 snprintf( c->cr_msg, sizeof(c->cr_msg), 703 "\"subtree-include\" incompatible with previous \"subtree-exclude\" directives" ); 704 return 1; 705 } 706 } 707 708 pattern = c->argv[1]; 709 if ( strncasecmp( pattern, "dn", STRLENOF( "dn" ) ) == 0 ) { 710 char *style; 711 712 pattern = &pattern[STRLENOF( "dn")]; 713 714 if ( pattern[0] == '.' ) { 715 style = &pattern[1]; 716 717 if ( strncasecmp( style, "subtree", STRLENOF( "subtree" ) ) == 0 ) { 718 type = META_ST_SUBTREE; 719 pattern = &style[STRLENOF( "subtree" )]; 720 721 } else if ( strncasecmp( style, "children", STRLENOF( "children" ) ) == 0 ) { 722 type = META_ST_SUBORDINATE; 723 pattern = &style[STRLENOF( "children" )]; 724 725 } else if ( strncasecmp( style, "sub", STRLENOF( "sub" ) ) == 0 ) { 726 type = META_ST_SUBTREE; 727 pattern = &style[STRLENOF( "sub" )]; 728 729 } else if ( strncasecmp( style, "regex", STRLENOF( "regex" ) ) == 0 ) { 730 type = META_ST_REGEX; 731 pattern = &style[STRLENOF( "regex" )]; 732 733 } else { 734 snprintf( c->cr_msg, sizeof(c->cr_msg), "unknown style in \"dn.<style>\"" ); 735 return 1; 736 } 737 } 738 739 if ( pattern[0] != ':' ) { 740 snprintf( c->cr_msg, sizeof(c->cr_msg), "missing colon after \"dn.<style>\"" ); 741 return 1; 742 } 743 pattern++; 744 } 745 746 switch ( type ) { 747 case META_ST_SUBTREE: 748 case META_ST_SUBORDINATE: { 749 struct berval dn; 750 751 ber_str2bv( pattern, 0, 0, &dn ); 752 if ( dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL ) 753 != LDAP_SUCCESS ) 754 { 755 snprintf( c->cr_msg, sizeof(c->cr_msg), "DN=\"%s\" is invalid", pattern ); 756 return 1; 757 } 758 759 if ( !dnIsSuffix( &ndn, &mt->mt_nsuffix ) ) { 760 snprintf( c->cr_msg, sizeof(c->cr_msg), 761 "DN=\"%s\" is not a subtree of target \"%s\"", 762 pattern, mt->mt_nsuffix.bv_val ); 763 ber_memfree( ndn.bv_val ); 764 return( 1 ); 765 } 766 } break; 767 768 default: 769 /* silence warnings */ 770 break; 771 } 772 773 ms = ch_calloc( sizeof( a_metasubtree_t ), 1 ); 774 ms->ms_type = type; 775 776 switch ( ms->ms_type ) { 777 case META_ST_SUBTREE: 778 case META_ST_SUBORDINATE: 779 ms->ms_dn = ndn; 780 break; 781 782 case META_ST_REGEX: { 783 int rc; 784 785 rc = regcomp( &ms->ms_regex, pattern, REG_EXTENDED|REG_ICASE ); 786 if ( rc != 0 ) { 787 char regerr[ SLAP_TEXT_BUFLEN ]; 788 789 regerror( rc, &ms->ms_regex, regerr, sizeof(regerr) ); 790 791 snprintf( c->cr_msg, sizeof( c->cr_msg ), 792 "regular expression \"%s\" bad because of %s", 793 pattern, regerr ); 794 ch_free( ms ); 795 return 1; 796 } 797 ber_str2bv( pattern, 0, 1, &ms->ms_regex_pattern ); 798 } break; 799 } 800 801 if ( mt->mt_subtree == NULL ) { 802 mt->mt_subtree = ms; 803 804 } else { 805 a_metasubtree_t **msp; 806 807 for ( msp = &mt->mt_subtree; *msp; ) { 808 switch ( ms->ms_type ) { 809 case META_ST_SUBTREE: 810 switch ( (*msp)->ms_type ) { 811 case META_ST_SUBTREE: 812 if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) { 813 a_metasubtree_t *tmp = *msp; 814 Debug( LDAP_DEBUG_CONFIG, 815 "%s: previous rule \"dn.subtree:%s\" is contained in rule \"dn.subtree:%s\" (replaced)\n", 816 c->log, pattern, (*msp)->ms_dn.bv_val ); 817 *msp = (*msp)->ms_next; 818 tmp->ms_next = NULL; 819 asyncmeta_subtree_destroy( tmp ); 820 continue; 821 822 } else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) ) { 823 Debug( LDAP_DEBUG_CONFIG, 824 "%s: previous rule \"dn.subtree:%s\" contains rule \"dn.subtree:%s\" (ignored)\n", 825 c->log, (*msp)->ms_dn.bv_val, pattern ); 826 asyncmeta_subtree_destroy( ms ); 827 ms = NULL; 828 return( 0 ); 829 } 830 break; 831 832 case META_ST_SUBORDINATE: 833 if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) { 834 a_metasubtree_t *tmp = *msp; 835 Debug( LDAP_DEBUG_CONFIG, 836 "%s: previous rule \"dn.children:%s\" is contained in rule \"dn.subtree:%s\" (replaced)\n", 837 c->log, pattern, (*msp)->ms_dn.bv_val ); 838 *msp = (*msp)->ms_next; 839 tmp->ms_next = NULL; 840 asyncmeta_subtree_destroy( tmp ); 841 continue; 842 843 } else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) && ms->ms_dn.bv_len > (*msp)->ms_dn.bv_len ) { 844 Debug( LDAP_DEBUG_CONFIG, 845 "%s: previous rule \"dn.children:%s\" contains rule \"dn.subtree:%s\" (ignored)\n", 846 c->log, (*msp)->ms_dn.bv_val, pattern ); 847 asyncmeta_subtree_destroy( ms ); 848 ms = NULL; 849 return( 0 ); 850 } 851 break; 852 853 case META_ST_REGEX: 854 if ( regexec( &(*msp)->ms_regex, ms->ms_dn.bv_val, 0, NULL, 0 ) == 0 ) { 855 Debug( LDAP_DEBUG_CONFIG, 856 "%s: previous rule \"dn.regex:%s\" may contain rule \"dn.subtree:%s\"\n", 857 c->log, (*msp)->ms_regex_pattern.bv_val, ms->ms_dn.bv_val ); 858 } 859 break; 860 } 861 break; 862 863 case META_ST_SUBORDINATE: 864 switch ( (*msp)->ms_type ) { 865 case META_ST_SUBTREE: 866 if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) { 867 a_metasubtree_t *tmp = *msp; 868 Debug( LDAP_DEBUG_CONFIG, 869 "%s: previous rule \"dn.children:%s\" is contained in rule \"dn.subtree:%s\" (replaced)\n", 870 c->log, pattern, (*msp)->ms_dn.bv_val ); 871 *msp = (*msp)->ms_next; 872 tmp->ms_next = NULL; 873 asyncmeta_subtree_destroy( tmp ); 874 continue; 875 876 } else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) && ms->ms_dn.bv_len > (*msp)->ms_dn.bv_len ) { 877 Debug( LDAP_DEBUG_CONFIG, 878 "%s: previous rule \"dn.children:%s\" contains rule \"dn.subtree:%s\" (ignored)\n", 879 c->log, (*msp)->ms_dn.bv_val, pattern ); 880 asyncmeta_subtree_destroy( ms ); 881 ms = NULL; 882 return( 0 ); 883 } 884 break; 885 886 case META_ST_SUBORDINATE: 887 if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) { 888 a_metasubtree_t *tmp = *msp; 889 Debug( LDAP_DEBUG_CONFIG, 890 "%s: previous rule \"dn.children:%s\" is contained in rule \"dn.children:%s\" (replaced)\n", 891 c->log, pattern, (*msp)->ms_dn.bv_val ); 892 *msp = (*msp)->ms_next; 893 tmp->ms_next = NULL; 894 asyncmeta_subtree_destroy( tmp ); 895 continue; 896 897 } else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) ) { 898 Debug( LDAP_DEBUG_CONFIG, 899 "%s: previous rule \"dn.children:%s\" contains rule \"dn.children:%s\" (ignored)\n", 900 c->log, (*msp)->ms_dn.bv_val, pattern ); 901 asyncmeta_subtree_destroy( ms ); 902 ms = NULL; 903 return( 0 ); 904 } 905 break; 906 907 case META_ST_REGEX: 908 if ( regexec( &(*msp)->ms_regex, ms->ms_dn.bv_val, 0, NULL, 0 ) == 0 ) { 909 Debug( LDAP_DEBUG_CONFIG, 910 "%s: previous rule \"dn.regex:%s\" may contain rule \"dn.subtree:%s\"\n", 911 c->log, (*msp)->ms_regex_pattern.bv_val, ms->ms_dn.bv_val ); 912 } 913 break; 914 } 915 break; 916 917 case META_ST_REGEX: 918 switch ( (*msp)->ms_type ) { 919 case META_ST_SUBTREE: 920 case META_ST_SUBORDINATE: 921 if ( regexec( &ms->ms_regex, (*msp)->ms_dn.bv_val, 0, NULL, 0 ) == 0 ) { 922 Debug( LDAP_DEBUG_CONFIG, 923 "%s: previous rule \"dn.subtree:%s\" may be contained in rule \"dn.regex:%s\"\n", 924 c->log, (*msp)->ms_dn.bv_val, ms->ms_regex_pattern.bv_val ); 925 } 926 break; 927 928 case META_ST_REGEX: 929 /* no check possible */ 930 break; 931 } 932 break; 933 } 934 935 msp = &(*msp)->ms_next; 936 } 937 938 *msp = ms; 939 } 940 941 return 0; 942} 943 944static slap_verbmasks idassert_mode[] = { 945 { BER_BVC("self"), LDAP_BACK_IDASSERT_SELF }, 946 { BER_BVC("anonymous"), LDAP_BACK_IDASSERT_ANONYMOUS }, 947 { BER_BVC("none"), LDAP_BACK_IDASSERT_NOASSERT }, 948 { BER_BVC("legacy"), LDAP_BACK_IDASSERT_LEGACY }, 949 { BER_BVNULL, 0 } 950}; 951 952static slap_verbmasks tls_mode[] = { 953 { BER_BVC( "propagate" ), LDAP_BACK_F_TLS_PROPAGATE_MASK }, 954 { BER_BVC( "try-propagate" ), LDAP_BACK_F_PROPAGATE_TLS }, 955 { BER_BVC( "start" ), LDAP_BACK_F_TLS_USE_MASK }, 956 { BER_BVC( "try-start" ), LDAP_BACK_F_USE_TLS }, 957 { BER_BVC( "ldaps" ), LDAP_BACK_F_TLS_LDAPS }, 958 { BER_BVC( "none" ), LDAP_BACK_F_NONE }, 959 { BER_BVNULL, 0 } 960}; 961 962static slap_verbmasks t_f_mode[] = { 963 { BER_BVC( "yes" ), LDAP_BACK_F_T_F }, 964 { BER_BVC( "discover" ), LDAP_BACK_F_T_F_DISCOVER }, 965 { BER_BVC( "no" ), LDAP_BACK_F_NONE }, 966 { BER_BVNULL, 0 } 967}; 968 969static slap_verbmasks cancel_mode[] = { 970 { BER_BVC( "ignore" ), LDAP_BACK_F_CANCEL_IGNORE }, 971 { BER_BVC( "exop" ), LDAP_BACK_F_CANCEL_EXOP }, 972 { BER_BVC( "exop-discover" ), LDAP_BACK_F_CANCEL_EXOP_DISCOVER }, 973 { BER_BVC( "abandon" ), LDAP_BACK_F_CANCEL_ABANDON }, 974 { BER_BVNULL, 0 } 975}; 976 977static slap_verbmasks onerr_mode[] = { 978 { BER_BVC( "stop" ), META_BACK_F_ONERR_STOP }, 979 { BER_BVC( "report" ), META_BACK_F_ONERR_REPORT }, 980 { BER_BVC( "continue" ), LDAP_BACK_F_NONE }, 981 { BER_BVNULL, 0 } 982}; 983 984/* see enum in slap.h */ 985static slap_cf_aux_table timeout_table[] = { 986 { BER_BVC("bind="), SLAP_OP_BIND * sizeof( time_t ), 'u', 0, NULL }, 987 /* unbind makes no sense */ 988 { BER_BVC("add="), SLAP_OP_ADD * sizeof( time_t ), 'u', 0, NULL }, 989 { BER_BVC("delete="), SLAP_OP_DELETE * sizeof( time_t ), 'u', 0, NULL }, 990 { BER_BVC("modrdn="), SLAP_OP_MODRDN * sizeof( time_t ), 'u', 0, NULL }, 991 { BER_BVC("modify="), SLAP_OP_MODIFY * sizeof( time_t ), 'u', 0, NULL }, 992 { BER_BVC("compare="), SLAP_OP_COMPARE * sizeof( time_t ), 'u', 0, NULL }, 993 { BER_BVC("search="), SLAP_OP_SEARCH * sizeof( time_t ), 'u', 0, NULL }, 994 /* abandon makes little sense */ 995#if 0 /* not implemented yet */ 996 { BER_BVC("extended="), SLAP_OP_EXTENDED * sizeof( time_t ), 'u', 0, NULL }, 997#endif 998 { BER_BVNULL, 0, 0, 0, NULL } 999}; 1000 1001static int 1002asyncmeta_cf_cleanup( ConfigArgs *c ) 1003{ 1004 a_metainfo_t *mi = ( a_metainfo_t * )c->be->be_private; 1005 a_metatarget_t *mt = c->ca_private; 1006 1007 return asyncmeta_target_finish( mi, mt, c->log, c->cr_msg, sizeof( c->cr_msg )); 1008} 1009 1010static int 1011asyncmeta_back_cf_gen( ConfigArgs *c ) 1012{ 1013 a_metainfo_t *mi = ( a_metainfo_t * )c->be->be_private; 1014 a_metatarget_t *mt = NULL; 1015 a_metacommon_t *mc = NULL; 1016 1017 int i, rc = 0; 1018 1019 assert( mi != NULL ); 1020 1021 if ( c->op == SLAP_CONFIG_EMIT || c->op == LDAP_MOD_DELETE ) { 1022 if ( !mi ) 1023 return 1; 1024 1025 if ( c->table == Cft_Database ) { 1026 mt = NULL; 1027 mc = &mi->mi_mc; 1028 } else { 1029 mt = c->ca_private; 1030 mc = &mt->mt_mc; 1031 } 1032 } 1033 1034 if ( c->op == SLAP_CONFIG_EMIT ) { 1035 struct berval bv = BER_BVNULL; 1036 1037 switch( c->type ) { 1038 /* Base attrs */ 1039 1040 case LDAP_BACK_CFG_DNCACHE_TTL: 1041 if ( mi->mi_cache.ttl == META_DNCACHE_DISABLED ) { 1042 return 1; 1043 } else if ( mi->mi_cache.ttl == META_DNCACHE_FOREVER ) { 1044 BER_BVSTR( &bv, "forever" ); 1045 } else { 1046 char buf[ SLAP_TEXT_BUFLEN ]; 1047 1048 lutil_unparse_time( buf, sizeof( buf ), mi->mi_cache.ttl ); 1049 ber_str2bv( buf, 0, 0, &bv ); 1050 } 1051 value_add_one( &c->rvalue_vals, &bv ); 1052 break; 1053 1054 case LDAP_BACK_CFG_IDLE_TIMEOUT: 1055 if ( mi->mi_idle_timeout == 0 ) { 1056 return 1; 1057 } else { 1058 char buf[ SLAP_TEXT_BUFLEN ]; 1059 1060 lutil_unparse_time( buf, sizeof( buf ), mi->mi_idle_timeout ); 1061 ber_str2bv( buf, 0, 0, &bv ); 1062 value_add_one( &c->rvalue_vals, &bv ); 1063 } 1064 break; 1065 1066 case LDAP_BACK_CFG_ONERR: 1067 enum_to_verb( onerr_mode, mi->mi_flags & META_BACK_F_ONERR_MASK, &bv ); 1068 if ( BER_BVISNULL( &bv )) { 1069 rc = 1; 1070 } else { 1071 value_add_one( &c->rvalue_vals, &bv ); 1072 } 1073 break; 1074 1075 case LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER: 1076 c->value_int = META_BACK_DEFER_ROOTDN_BIND( mi ); 1077 break; 1078 1079 case LDAP_BACK_CFG_CONNPOOLMAX: 1080 c->value_int = mi->mi_conn_priv_max; 1081 break; 1082 1083 /* common attrs */ 1084 case LDAP_BACK_CFG_BIND_TIMEOUT: 1085 if ( mc->mc_bind_timeout.tv_sec == 0 && 1086 mc->mc_bind_timeout.tv_usec == 0 ) { 1087 return 1; 1088 } else { 1089 c->value_ulong = mc->mc_bind_timeout.tv_sec * 1000000UL + 1090 mc->mc_bind_timeout.tv_usec; 1091 } 1092 break; 1093 1094 case LDAP_BACK_CFG_CANCEL: { 1095 slap_mask_t mask = LDAP_BACK_F_CANCEL_MASK2; 1096 1097 if ( mt && META_BACK_TGT_CANCEL_DISCOVER( mt ) ) { 1098 mask &= ~LDAP_BACK_F_CANCEL_EXOP; 1099 } 1100 enum_to_verb( cancel_mode, (mc->mc_flags & mask), &bv ); 1101 if ( BER_BVISNULL( &bv ) ) { 1102 /* there's something wrong... */ 1103 assert( 0 ); 1104 rc = 1; 1105 1106 } else { 1107 value_add_one( &c->rvalue_vals, &bv ); 1108 } 1109 } break; 1110 1111 case LDAP_BACK_CFG_CHASE: 1112 c->value_int = META_BACK_CMN_CHASE_REFERRALS(mc); 1113 break; 1114 1115#ifdef SLAPD_META_CLIENT_PR 1116 case LDAP_BACK_CFG_CLIENT_PR: 1117 if ( mc->mc_ps == META_CLIENT_PR_DISABLE ) { 1118 return 1; 1119 } else if ( mc->mc_ps == META_CLIENT_PR_ACCEPT_UNSOLICITED ) { 1120 BER_BVSTR( &bv, "accept-unsolicited" ); 1121 } else { 1122 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), "%d", mc->mc_ps ); 1123 bv.bv_val = c->cr_msg; 1124 } 1125 value_add_one( &c->rvalue_vals, &bv ); 1126 break; 1127#endif /* SLAPD_META_CLIENT_PR */ 1128 1129 case LDAP_BACK_CFG_DEFAULT_T: 1130 if ( mt || mi->mi_defaulttarget == META_DEFAULT_TARGET_NONE ) 1131 return 1; 1132 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), "%d", mi->mi_defaulttarget ); 1133 bv.bv_val = c->cr_msg; 1134 value_add_one( &c->rvalue_vals, &bv ); 1135 break; 1136 1137 case LDAP_BACK_CFG_NETWORK_TIMEOUT: 1138 if ( mc->mc_network_timeout == 0 ) { 1139 return 1; 1140 } 1141 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), "%ld", 1142 mc->mc_network_timeout ); 1143 bv.bv_val = c->cr_msg; 1144 value_add_one( &c->rvalue_vals, &bv ); 1145 break; 1146 1147 case LDAP_BACK_CFG_NOREFS: 1148 c->value_int = META_BACK_CMN_NOREFS(mc); 1149 break; 1150 1151 case LDAP_BACK_CFG_NOUNDEFFILTER: 1152 c->value_int = META_BACK_CMN_NOUNDEFFILTER(mc); 1153 break; 1154 1155 case LDAP_BACK_CFG_NRETRIES: 1156 if ( mc->mc_nretries == META_RETRY_FOREVER ) { 1157 BER_BVSTR( &bv, "forever" ); 1158 } else if ( mc->mc_nretries == META_RETRY_NEVER ) { 1159 BER_BVSTR( &bv, "never" ); 1160 } else { 1161 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), "%d", 1162 mc->mc_nretries ); 1163 bv.bv_val = c->cr_msg; 1164 } 1165 value_add_one( &c->rvalue_vals, &bv ); 1166 break; 1167 1168 case LDAP_BACK_CFG_QUARANTINE: 1169 if ( !META_BACK_CMN_QUARANTINE( mc )) { 1170 rc = 1; 1171 break; 1172 } 1173 rc = mi->mi_ldap_extra->retry_info_unparse( &mc->mc_quarantine, &bv ); 1174 if ( rc == 0 ) { 1175 ber_bvarray_add( &c->rvalue_vals, &bv ); 1176 } 1177 break; 1178 1179 case LDAP_BACK_CFG_REBIND: 1180 c->value_int = META_BACK_CMN_SAVECRED(mc); 1181 break; 1182 1183 case LDAP_BACK_CFG_TIMEOUT: 1184 for ( i = 0; i < SLAP_OP_LAST; i++ ) { 1185 if ( mc->mc_timeout[ i ] != META_BACK_CFG_DEFAULT_OPS_TIMEOUT ) { 1186 break; 1187 } 1188 } 1189 1190 if ( i == SLAP_OP_LAST ) { 1191 return 1; 1192 } 1193 1194 BER_BVZERO( &bv ); 1195 slap_cf_aux_table_unparse( mc->mc_timeout, &bv, timeout_table ); 1196 1197 if ( BER_BVISNULL( &bv ) ) { 1198 return 1; 1199 } 1200 1201 for ( i = 0; isspace( (unsigned char) bv.bv_val[ i ] ); i++ ) 1202 /* count spaces */ ; 1203 1204 if ( i ) { 1205 bv.bv_len -= i; 1206 AC_MEMCPY( bv.bv_val, &bv.bv_val[ i ], 1207 bv.bv_len + 1 ); 1208 } 1209 1210 ber_bvarray_add( &c->rvalue_vals, &bv ); 1211 break; 1212 1213 case LDAP_BACK_CFG_VERSION: 1214 if ( mc->mc_version == 0 ) 1215 return 1; 1216 c->value_int = mc->mc_version; 1217 break; 1218 1219#ifdef SLAP_CONTROL_X_SESSION_TRACKING 1220 case LDAP_BACK_CFG_ST_REQUEST: 1221 c->value_int = META_BACK_CMN_ST_REQUEST( mc ); 1222 break; 1223#endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 1224 1225 case LDAP_BACK_CFG_T_F: 1226 enum_to_verb( t_f_mode, (mc->mc_flags & LDAP_BACK_F_T_F_MASK2), &bv ); 1227 if ( BER_BVISNULL( &bv ) ) { 1228 /* there's something wrong... */ 1229 assert( 0 ); 1230 rc = 1; 1231 1232 } else { 1233 value_add_one( &c->rvalue_vals, &bv ); 1234 } 1235 break; 1236 1237 case LDAP_BACK_CFG_TLS: { 1238 struct berval bc = BER_BVNULL, bv2; 1239 1240 if (( mc->mc_flags & LDAP_BACK_F_TLS_MASK ) == LDAP_BACK_F_NONE ) { 1241 rc = 1; 1242 break; 1243 } 1244 enum_to_verb( tls_mode, ( mc->mc_flags & LDAP_BACK_F_TLS_MASK ), &bv ); 1245 assert( !BER_BVISNULL( &bv ) ); 1246 1247 if ( mt ) { 1248 bindconf_tls_unparse( &mt->mt_tls, &bc ); 1249 } 1250 1251 if ( !BER_BVISEMPTY( &bc )) { 1252 bv2.bv_len = bv.bv_len + bc.bv_len + 1; 1253 bv2.bv_val = ch_malloc( bv2.bv_len + 1 ); 1254 strcpy( bv2.bv_val, bv.bv_val ); 1255 bv2.bv_val[bv.bv_len] = ' '; 1256 strcpy( &bv2.bv_val[bv.bv_len + 1], bc.bv_val ); 1257 ber_memfree( bc.bv_val ); 1258 ber_bvarray_add( &c->rvalue_vals, &bv2 ); 1259 } else { 1260 value_add_one( &c->rvalue_vals, &bv ); 1261 } 1262 } break; 1263 1264 /* target attrs */ 1265 case LDAP_BACK_CFG_URI: { 1266 char *p2, *p1 = strchr( mt->mt_uri, ' ' ); 1267 bv.bv_len = strlen( mt->mt_uri ) + 3 + mt->mt_psuffix.bv_len; 1268 bv.bv_val = ch_malloc( bv.bv_len + 1 ); 1269 p2 = bv.bv_val; 1270 *p2++ = '"'; 1271 if ( p1 ) { 1272 p2 = lutil_strncopy( p2, mt->mt_uri, p1 - mt->mt_uri ); 1273 } else { 1274 p2 = lutil_strcopy( p2, mt->mt_uri ); 1275 } 1276 *p2++ = '/'; 1277 p2 = lutil_strcopy( p2, mt->mt_psuffix.bv_val ); 1278 *p2++ = '"'; 1279 if ( p1 ) { 1280 strcpy( p2, p1 ); 1281 } 1282 ber_bvarray_add( &c->rvalue_vals, &bv ); 1283 } break; 1284 1285 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: { 1286 BerVarray *bvp; 1287 int i; 1288 struct berval bv = BER_BVNULL; 1289 char buf[SLAP_TEXT_BUFLEN]; 1290 1291 bvp = &mt->mt_idassert_authz; 1292 if ( *bvp == NULL ) { 1293 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_AUTHZ_ALL ) 1294 { 1295 BER_BVSTR( &bv, "*" ); 1296 value_add_one( &c->rvalue_vals, &bv ); 1297 1298 } else { 1299 rc = 1; 1300 } 1301 break; 1302 } 1303 1304 for ( i = 0; !BER_BVISNULL( &((*bvp)[ i ]) ); i++ ) { 1305 char *ptr; 1306 int len = snprintf( buf, sizeof( buf ), SLAP_X_ORDERED_FMT, i ); 1307 bv.bv_len = ((*bvp)[ i ]).bv_len + len; 1308 bv.bv_val = ber_memrealloc( bv.bv_val, bv.bv_len + 1 ); 1309 ptr = bv.bv_val; 1310 ptr = lutil_strcopy( ptr, buf ); 1311 ptr = lutil_strncopy( ptr, ((*bvp)[ i ]).bv_val, ((*bvp)[ i ]).bv_len ); 1312 value_add_one( &c->rvalue_vals, &bv ); 1313 } 1314 if ( bv.bv_val ) { 1315 ber_memfree( bv.bv_val ); 1316 } 1317 break; 1318 } 1319 1320 case LDAP_BACK_CFG_IDASSERT_BIND: { 1321 int i; 1322 struct berval bc = BER_BVNULL; 1323 char *ptr; 1324 1325 if ( mt->mt_idassert_authmethod == LDAP_AUTH_NONE ) { 1326 return 1; 1327 } else { 1328 ber_len_t len; 1329 1330 switch ( mt->mt_idassert_mode ) { 1331 case LDAP_BACK_IDASSERT_OTHERID: 1332 case LDAP_BACK_IDASSERT_OTHERDN: 1333 break; 1334 1335 default: { 1336 struct berval mode = BER_BVNULL; 1337 1338 enum_to_verb( idassert_mode, mt->mt_idassert_mode, &mode ); 1339 if ( BER_BVISNULL( &mode ) ) { 1340 /* there's something wrong... */ 1341 assert( 0 ); 1342 rc = 1; 1343 1344 } else { 1345 bv.bv_len = STRLENOF( "mode=" ) + mode.bv_len; 1346 bv.bv_val = ch_malloc( bv.bv_len + 1 ); 1347 1348 ptr = lutil_strcopy( bv.bv_val, "mode=" ); 1349 ptr = lutil_strcopy( ptr, mode.bv_val ); 1350 } 1351 break; 1352 } 1353 } 1354 1355 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) { 1356 len = bv.bv_len + STRLENOF( "authz=native" ); 1357 1358 if ( !BER_BVISEMPTY( &bv ) ) { 1359 len += STRLENOF( " " ); 1360 } 1361 1362 bv.bv_val = ch_realloc( bv.bv_val, len + 1 ); 1363 1364 ptr = &bv.bv_val[ bv.bv_len ]; 1365 1366 if ( !BER_BVISEMPTY( &bv ) ) { 1367 ptr = lutil_strcopy( ptr, " " ); 1368 } 1369 1370 (void)lutil_strcopy( ptr, "authz=native" ); 1371 } 1372 1373 len = bv.bv_len + STRLENOF( "flags=non-prescriptive,override,obsolete-encoding-workaround,proxy-authz-non-critical,dn-authzid" ); 1374 /* flags */ 1375 if ( !BER_BVISEMPTY( &bv ) ) { 1376 len += STRLENOF( " " ); 1377 } 1378 1379 bv.bv_val = ch_realloc( bv.bv_val, len + 1 ); 1380 1381 ptr = &bv.bv_val[ bv.bv_len ]; 1382 1383 if ( !BER_BVISEMPTY( &bv ) ) { 1384 ptr = lutil_strcopy( ptr, " " ); 1385 } 1386 1387 ptr = lutil_strcopy( ptr, "flags=" ); 1388 1389 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) { 1390 ptr = lutil_strcopy( ptr, "prescriptive" ); 1391 } else { 1392 ptr = lutil_strcopy( ptr, "non-prescriptive" ); 1393 } 1394 1395 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) { 1396 ptr = lutil_strcopy( ptr, ",override" ); 1397 } 1398 1399 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) { 1400 ptr = lutil_strcopy( ptr, ",obsolete-proxy-authz" ); 1401 1402 } else if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) { 1403 ptr = lutil_strcopy( ptr, ",obsolete-encoding-workaround" ); 1404 } 1405 1406 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PROXYAUTHZ_CRITICAL ) { 1407 ptr = lutil_strcopy( ptr, ",proxy-authz-critical" ); 1408 1409 } else { 1410 ptr = lutil_strcopy( ptr, ",proxy-authz-non-critical" ); 1411 } 1412 1413#ifdef SLAP_AUTH_DN 1414 switch ( mt->mt_idassert_flags & LDAP_BACK_AUTH_DN_MASK ) { 1415 case LDAP_BACK_AUTH_DN_AUTHZID: 1416 ptr = lutil_strcopy( ptr, ",dn-authzid" ); 1417 break; 1418 1419 case LDAP_BACK_AUTH_DN_WHOAMI: 1420 ptr = lutil_strcopy( ptr, ",dn-whoami" ); 1421 break; 1422 1423 default: 1424#if 0 /* implicit */ 1425 ptr = lutil_strcopy( ptr, ",dn-none" ); 1426#endif 1427 break; 1428 } 1429#endif 1430 1431 bv.bv_len = ( ptr - bv.bv_val ); 1432 /* end-of-flags */ 1433 } 1434 1435 bindconf_unparse( &mt->mt_idassert.si_bc, &bc ); 1436 1437 if ( !BER_BVISNULL( &bv ) ) { 1438 ber_len_t len = bv.bv_len + bc.bv_len; 1439 1440 bv.bv_val = ch_realloc( bv.bv_val, len + 1 ); 1441 1442 assert( bc.bv_val[ 0 ] == ' ' ); 1443 1444 ptr = lutil_strcopy( &bv.bv_val[ bv.bv_len ], bc.bv_val ); 1445 free( bc.bv_val ); 1446 bv.bv_len = ptr - bv.bv_val; 1447 1448 } else { 1449 for ( i = 0; isspace( (unsigned char) bc.bv_val[ i ] ); i++ ) 1450 /* count spaces */ ; 1451 1452 if ( i ) { 1453 bc.bv_len -= i; 1454 AC_MEMCPY( bc.bv_val, &bc.bv_val[ i ], bc.bv_len + 1 ); 1455 } 1456 1457 bv = bc; 1458 } 1459 1460 ber_bvarray_add( &c->rvalue_vals, &bv ); 1461 1462 break; 1463 } 1464 1465 case LDAP_BACK_CFG_SUFFIXM: 1466 if ( mt->mt_lsuffixm.bv_val ) { 1467 struct berval bv; 1468 char *ptr; 1469 bv.bv_len = mt->mt_lsuffixm.bv_len + 2 + 1 + mt->mt_rsuffixm.bv_len + 2; 1470 bv.bv_val = ch_malloc( bv.bv_len + 1 ); 1471 ptr = bv.bv_val; 1472 *ptr++ = '"'; 1473 ptr = lutil_strcopy(ptr, mt->mt_lsuffixm.bv_val); 1474 ptr = lutil_strcopy(ptr, "\" \""); 1475 ptr = lutil_strcopy(ptr, mt->mt_rsuffixm.bv_val); 1476 *ptr++ = '"'; 1477 *ptr = '\0'; 1478 ber_bvarray_add( &c->rvalue_vals, &bv ); 1479 rc = 0; 1480 } else 1481 rc = 1; 1482 break; 1483 1484 case LDAP_BACK_CFG_SUBTREE_EX: 1485 case LDAP_BACK_CFG_SUBTREE_IN: 1486 rc = asyncmeta_subtree_unparse( c, mt ); 1487 break; 1488 1489 case LDAP_BACK_CFG_FILTER: 1490 if ( mt->mt_filter == NULL ) { 1491 rc = 1; 1492 } else { 1493 metafilter_t *mf; 1494 for ( mf = mt->mt_filter; mf; mf = mf->mf_next ) 1495 value_add_one( &c->rvalue_vals, &mf->mf_regex_pattern ); 1496 } 1497 break; 1498 case LDAP_BACK_CFG_MAX_PENDING_OPS: 1499 c->value_int = mi->mi_max_pending_ops; 1500 break; 1501 1502 case LDAP_BACK_CFG_MAX_TARGET_CONNS: 1503 c->value_int = mi->mi_max_target_conns; 1504 break; 1505 case LDAP_BACK_CFG_MAX_TIMEOUT_OPS: 1506 c->value_int = mi->mi_max_timeout_ops; 1507 break; 1508 1509 case LDAP_BACK_CFG_KEEPALIVE: { 1510 struct berval bv; 1511 char buf[AC_LINE_MAX]; 1512 bv.bv_len = AC_LINE_MAX; 1513 bv.bv_val = &buf[0]; 1514 slap_keepalive_parse(&bv, &mt->mt_tls.sb_keepalive, 0, 0, 1); 1515 value_add_one( &c->rvalue_vals, &bv ); 1516 break; 1517 } 1518 1519 case LDAP_BACK_CFG_TCP_USER_TIMEOUT: 1520 c->value_uint = mt->mt_tls.sb_tcp_user_timeout; 1521 break; 1522 1523 default: 1524 rc = 1; 1525 } 1526 return rc; 1527 } else if ( c->op == LDAP_MOD_DELETE ) { 1528 switch( c->type ) { 1529 /* Base attrs */ 1530 case LDAP_BACK_CFG_DNCACHE_TTL: 1531 mi->mi_cache.ttl = META_DNCACHE_DISABLED; 1532 break; 1533 1534 case LDAP_BACK_CFG_IDLE_TIMEOUT: 1535 mi->mi_idle_timeout = 0; 1536 break; 1537 1538 case LDAP_BACK_CFG_ONERR: 1539 mi->mi_flags &= ~META_BACK_F_ONERR_MASK; 1540 break; 1541 1542 case LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER: 1543 mi->mi_flags &= ~META_BACK_F_DEFER_ROOTDN_BIND; 1544 break; 1545 1546 case LDAP_BACK_CFG_CONNPOOLMAX: 1547 mi->mi_conn_priv_max = LDAP_BACK_CONN_PRIV_MIN; 1548 break; 1549 1550 /* common attrs */ 1551 case LDAP_BACK_CFG_BIND_TIMEOUT: 1552 mc->mc_bind_timeout.tv_sec = 0; 1553 mc->mc_bind_timeout.tv_usec = 0; 1554 break; 1555 1556 case LDAP_BACK_CFG_CANCEL: 1557 mc->mc_flags &= ~LDAP_BACK_F_CANCEL_MASK2; 1558 break; 1559 1560 case LDAP_BACK_CFG_CHASE: 1561 mc->mc_flags &= ~LDAP_BACK_F_CHASE_REFERRALS; 1562 break; 1563 1564#ifdef SLAPD_META_CLIENT_PR 1565 case LDAP_BACK_CFG_CLIENT_PR: 1566 mc->mc_ps = META_CLIENT_PR_DISABLE; 1567 break; 1568#endif /* SLAPD_META_CLIENT_PR */ 1569 1570 case LDAP_BACK_CFG_DEFAULT_T: 1571 mi->mi_defaulttarget = META_DEFAULT_TARGET_NONE; 1572 break; 1573 1574 case LDAP_BACK_CFG_NETWORK_TIMEOUT: 1575 mc->mc_network_timeout = 0; 1576 break; 1577 1578 case LDAP_BACK_CFG_NOREFS: 1579 mc->mc_flags &= ~LDAP_BACK_F_NOREFS; 1580 break; 1581 1582 case LDAP_BACK_CFG_NOUNDEFFILTER: 1583 mc->mc_flags &= ~LDAP_BACK_F_NOUNDEFFILTER; 1584 break; 1585 1586 case LDAP_BACK_CFG_NRETRIES: 1587 mc->mc_nretries = META_RETRY_DEFAULT; 1588 break; 1589 1590 case LDAP_BACK_CFG_QUARANTINE: 1591 if ( META_BACK_CMN_QUARANTINE( mc )) { 1592 mi->mi_ldap_extra->retry_info_destroy( &mc->mc_quarantine ); 1593 mc->mc_flags &= ~LDAP_BACK_F_QUARANTINE; 1594 if ( mc == &mt->mt_mc ) { 1595 ldap_pvt_thread_mutex_destroy( &mt->mt_quarantine_mutex ); 1596 mt->mt_isquarantined = 0; 1597 } 1598 } 1599 break; 1600 1601 case LDAP_BACK_CFG_REBIND: 1602 mc->mc_flags &= ~LDAP_BACK_F_SAVECRED; 1603 break; 1604 1605 case LDAP_BACK_CFG_TIMEOUT: 1606 for ( i = 0; i < SLAP_OP_LAST; i++ ) { 1607 mc->mc_timeout[ i ] = 0; 1608 } 1609 break; 1610 1611 case LDAP_BACK_CFG_VERSION: 1612 mc->mc_version = 0; 1613 break; 1614 1615#ifdef SLAP_CONTROL_X_SESSION_TRACKING 1616 case LDAP_BACK_CFG_ST_REQUEST: 1617 mc->mc_flags &= ~LDAP_BACK_F_ST_REQUEST; 1618 break; 1619#endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 1620 1621 case LDAP_BACK_CFG_T_F: 1622 mc->mc_flags &= ~LDAP_BACK_F_T_F_MASK2; 1623 break; 1624 1625 case LDAP_BACK_CFG_TLS: 1626 mc->mc_flags &= ~LDAP_BACK_F_TLS_MASK; 1627 if ( mt ) 1628 bindconf_free( &mt->mt_tls ); 1629 break; 1630 1631 /* target attrs */ 1632 case LDAP_BACK_CFG_URI: 1633 if ( mt->mt_uri ) { 1634 ch_free( mt->mt_uri ); 1635 mt->mt_uri = NULL; 1636 } 1637 /* FIXME: should have a way to close all cached 1638 * connections associated with this target. 1639 */ 1640 break; 1641 1642 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: { 1643 BerVarray *bvp; 1644 1645 bvp = &mt->mt_idassert_authz; 1646 if ( c->valx < 0 ) { 1647 if ( *bvp != NULL ) { 1648 ber_bvarray_free( *bvp ); 1649 *bvp = NULL; 1650 } 1651 1652 } else { 1653 if ( *bvp == NULL ) { 1654 rc = 1; 1655 break; 1656 } 1657 1658 for ( i = 0; !BER_BVISNULL( &((*bvp)[ i ]) ); i++ ) 1659 ; 1660 1661 if ( i >= c->valx ) { 1662 rc = 1; 1663 break; 1664 } 1665 ber_memfree( ((*bvp)[ c->valx ]).bv_val ); 1666 for ( i = c->valx; !BER_BVISNULL( &((*bvp)[ i + 1 ]) ); i++ ) { 1667 (*bvp)[ i ] = (*bvp)[ i + 1 ]; 1668 } 1669 BER_BVZERO( &((*bvp)[ i ]) ); 1670 } 1671 } break; 1672 1673 case LDAP_BACK_CFG_IDASSERT_BIND: 1674 bindconf_free( &mt->mt_idassert.si_bc ); 1675 memset( &mt->mt_idassert, 0, sizeof( slap_idassert_t ) ); 1676 break; 1677 1678 case LDAP_BACK_CFG_SUFFIXM: 1679 if ( mt->mt_lsuffixm.bv_val ) { 1680 ch_free( mt->mt_lsuffixm.bv_val ); 1681 ch_free( mt->mt_rsuffixm.bv_val ); 1682 BER_BVZERO( &mt->mt_lsuffixm ); 1683 BER_BVZERO( &mt->mt_rsuffixm ); 1684 } 1685 break; 1686 1687 case LDAP_BACK_CFG_SUBTREE_EX: 1688 case LDAP_BACK_CFG_SUBTREE_IN: 1689 /* can only be one of exclude or include */ 1690 if (( c->type == LDAP_BACK_CFG_SUBTREE_EX ) ^ mt->mt_subtree_exclude ) { 1691 rc = 1; 1692 break; 1693 } 1694 if ( c->valx < 0 ) { 1695 asyncmeta_subtree_destroy( mt->mt_subtree ); 1696 mt->mt_subtree = NULL; 1697 } else { 1698 a_metasubtree_t *ms, **mprev; 1699 for (i=0, mprev = &mt->mt_subtree, ms = *mprev; ms; ms = *mprev) { 1700 if ( i == c->valx ) { 1701 *mprev = ms->ms_next; 1702 asyncmeta_subtree_free( ms ); 1703 break; 1704 } 1705 i++; 1706 mprev = &ms->ms_next; 1707 } 1708 if ( i != c->valx ) 1709 rc = 1; 1710 } 1711 break; 1712 1713 case LDAP_BACK_CFG_FILTER: 1714 if ( c->valx < 0 ) { 1715 asyncmeta_filter_destroy( mt->mt_filter ); 1716 mt->mt_filter = NULL; 1717 } else { 1718 metafilter_t *mf, **mprev; 1719 for (i=0, mprev = &mt->mt_filter, mf = *mprev; mf; mf = *mprev) { 1720 if ( i == c->valx ) { 1721 *mprev = mf->mf_next; 1722 asyncmeta_filter_free( mf ); 1723 break; 1724 } 1725 i++; 1726 mprev = &mf->mf_next; 1727 } 1728 if ( i != c->valx ) 1729 rc = 1; 1730 } 1731 break; 1732 case LDAP_BACK_CFG_MAX_PENDING_OPS: 1733 mi->mi_max_pending_ops = 0; 1734 break; 1735 1736 case LDAP_BACK_CFG_MAX_TARGET_CONNS: 1737 mi->mi_max_target_conns = 0; 1738 break; 1739 1740 case LDAP_BACK_CFG_MAX_TIMEOUT_OPS: 1741 mi->mi_max_timeout_ops = 0; 1742 break; 1743 1744 case LDAP_BACK_CFG_KEEPALIVE: 1745 mt->mt_tls.sb_keepalive.sk_idle = 0; 1746 mt->mt_tls.sb_keepalive.sk_probes = 0; 1747 mt->mt_tls.sb_keepalive.sk_interval = 0; 1748 break; 1749 1750 case LDAP_BACK_CFG_TCP_USER_TIMEOUT: 1751 mt->mt_tls.sb_tcp_user_timeout = 0; 1752 break; 1753 1754 default: 1755 rc = 1; 1756 break; 1757 } 1758 1759 return rc; 1760 } 1761 1762 if ( c->op == SLAP_CONFIG_ADD ) { 1763 if ( c->type >= LDAP_BACK_CFG_LAST_BASE ) { 1764 /* exclude CFG_URI from this check */ 1765 if ( c->type > LDAP_BACK_CFG_LAST_BOTH ) { 1766 if ( !mi->mi_ntargets ) { 1767 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1768 "need \"uri\" directive first" ); 1769 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1770 return 1; 1771 } 1772 } 1773 if ( mi->mi_ntargets ) { 1774 mt = mi->mi_targets[ mi->mi_ntargets-1 ]; 1775 mc = &mt->mt_mc; 1776 } else { 1777 mt = NULL; 1778 mc = &mi->mi_mc; 1779 } 1780 } 1781 } else { 1782 if ( c->table == Cft_Database ) { 1783 mt = NULL; 1784 mc = &mi->mi_mc; 1785 } else { 1786 mt = c->ca_private; 1787 if ( mt ) 1788 mc = &mt->mt_mc; 1789 else 1790 mc = NULL; 1791 } 1792 } 1793 1794 switch( c->type ) { 1795 case LDAP_BACK_CFG_URI: { 1796 LDAPURLDesc *ludp; 1797 struct berval dn; 1798 int j; 1799 1800 char **uris = NULL; 1801 1802 if ( c->be->be_nsuffix == NULL ) { 1803 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1804 "the suffix must be defined before any target" ); 1805 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1806 return 1; 1807 } 1808 1809 i = mi->mi_ntargets++; 1810 1811 mi->mi_targets = ( a_metatarget_t ** )ch_realloc( mi->mi_targets, 1812 sizeof( a_metatarget_t * ) * mi->mi_ntargets ); 1813 if ( mi->mi_targets == NULL ) { 1814 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1815 "out of memory while storing server name" 1816 " in \"%s <protocol>://<server>[:port]/<naming context>\"", 1817 c->argv[0] ); 1818 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1819 return 1; 1820 } 1821 1822 if ( asyncmeta_back_new_target( &mi->mi_targets[ i ] ) != 0 ) { 1823 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1824 "unable to init server" 1825 " in \"%s <protocol>://<server>[:port]/<naming context>\"", 1826 c->argv[0] ); 1827 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1828 return 1; 1829 } 1830 1831 mt = mi->mi_targets[ i ]; 1832 1833 mt->mt_rebind_f = mi->mi_rebind_f; 1834 mt->mt_urllist_f = mi->mi_urllist_f; 1835 mt->mt_urllist_p = mt; 1836 1837 if ( META_BACK_QUARANTINE( mi ) ) { 1838 ldap_pvt_thread_mutex_init( &mt->mt_quarantine_mutex ); 1839 } 1840 mt->mt_mc = mi->mi_mc; 1841 1842 for ( j = 1; j < c->argc; j++ ) { 1843 char **tmpuris = ldap_str2charray( c->argv[ j ], "\t" ); 1844 1845 if ( tmpuris == NULL ) { 1846 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1847 "unable to parse URIs #%d" 1848 " in \"%s <protocol>://<server>[:port]/<naming context>\"", 1849 j-1, c->argv[0] ); 1850 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1851 return 1; 1852 } 1853 1854 if ( j == 1 ) { 1855 uris = tmpuris; 1856 1857 } else { 1858 ldap_charray_merge( &uris, tmpuris ); 1859 ldap_charray_free( tmpuris ); 1860 } 1861 } 1862 1863 for ( j = 0; uris[ j ] != NULL; j++ ) { 1864 char *tmpuri = NULL; 1865 1866 /* 1867 * uri MUST be legal! 1868 */ 1869 if ( ldap_url_parselist_ext( &ludp, uris[ j ], "\t", 1870 LDAP_PVT_URL_PARSE_NONE ) != LDAP_SUCCESS 1871 || ludp->lud_next != NULL ) 1872 { 1873 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1874 "unable to parse URI #%d" 1875 " in \"%s <protocol>://<server>[:port]/<naming context>\"", 1876 j-1, c->argv[0] ); 1877 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1878 ldap_charray_free( uris ); 1879 return 1; 1880 } 1881 1882 if ( j == 0 ) { 1883 1884 /* 1885 * uri MUST have the <dn> part! 1886 */ 1887 if ( ludp->lud_dn == NULL ) { 1888 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1889 "missing <naming context> " 1890 " in \"%s <protocol>://<server>[:port]/<naming context>\"", 1891 c->argv[0] ); 1892 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1893 ldap_free_urllist( ludp ); 1894 ldap_charray_free( uris ); 1895 return 1; 1896 } 1897 1898 /* 1899 * copies and stores uri and suffix 1900 */ 1901 ber_str2bv( ludp->lud_dn, 0, 0, &dn ); 1902 rc = dnPrettyNormal( NULL, &dn, &mt->mt_psuffix, 1903 &mt->mt_nsuffix, NULL ); 1904 if ( rc != LDAP_SUCCESS ) { 1905 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1906 "target DN is invalid \"%s\"", 1907 c->argv[1] ); 1908 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1909 ldap_free_urllist( ludp ); 1910 ldap_charray_free( uris ); 1911 return( 1 ); 1912 } 1913 1914 ludp->lud_dn[ 0 ] = '\0'; 1915 1916 switch ( ludp->lud_scope ) { 1917 case LDAP_SCOPE_DEFAULT: 1918 mt->mt_scope = LDAP_SCOPE_SUBTREE; 1919 break; 1920 1921 case LDAP_SCOPE_SUBTREE: 1922 case LDAP_SCOPE_SUBORDINATE: 1923 mt->mt_scope = ludp->lud_scope; 1924 break; 1925 1926 default: 1927 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1928 "invalid scope for target \"%s\"", 1929 c->argv[1] ); 1930 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1931 ldap_free_urllist( ludp ); 1932 ldap_charray_free( uris ); 1933 return( 1 ); 1934 } 1935 1936 } else { 1937 /* check all, to apply the scope check on the first one */ 1938 if ( ludp->lud_dn != NULL && ludp->lud_dn[ 0 ] != '\0' ) { 1939 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1940 "multiple URIs must have no DN part" ); 1941 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1942 ldap_free_urllist( ludp ); 1943 ldap_charray_free( uris ); 1944 return( 1 ); 1945 1946 } 1947 } 1948 1949 tmpuri = ldap_url_list2urls( ludp ); 1950 ldap_free_urllist( ludp ); 1951 if ( tmpuri == NULL ) { 1952 snprintf( c->cr_msg, sizeof( c->cr_msg ), "no memory?" ); 1953 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1954 ldap_charray_free( uris ); 1955 return( 1 ); 1956 } 1957 ldap_memfree( uris[ j ] ); 1958 uris[ j ] = tmpuri; 1959 } 1960 1961 mt->mt_uri = ldap_charray2str( uris, " " ); 1962 ldap_charray_free( uris ); 1963 if ( mt->mt_uri == NULL) { 1964 snprintf( c->cr_msg, sizeof( c->cr_msg ), "no memory?" ); 1965 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1966 return( 1 ); 1967 } 1968 1969 /* 1970 * uri MUST be a branch of suffix! 1971 */ 1972 for ( j = 0; !BER_BVISNULL( &c->be->be_nsuffix[ j ] ); j++ ) { 1973 if ( dnIsSuffix( &mt->mt_nsuffix, &c->be->be_nsuffix[ j ] ) ) { 1974 break; 1975 } 1976 } 1977 1978 if ( BER_BVISNULL( &c->be->be_nsuffix[ j ] ) ) { 1979 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1980 "<naming context> of URI must be within the naming context of this database." ); 1981 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1982 return 1; 1983 } 1984 c->ca_private = mt; 1985 config_push_cleanup( c, asyncmeta_cf_cleanup ); 1986 } break; 1987 case LDAP_BACK_CFG_SUBTREE_EX: 1988 case LDAP_BACK_CFG_SUBTREE_IN: 1989 /* subtree-exclude */ 1990 if ( asyncmeta_subtree_config( mt, c )) { 1991 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1992 return 1; 1993 } 1994 break; 1995 1996 case LDAP_BACK_CFG_FILTER: { 1997 metafilter_t *mf, **m2; 1998 mf = ch_malloc( sizeof( metafilter_t )); 1999 rc = regcomp( &mf->mf_regex, c->argv[1], REG_EXTENDED ); 2000 if ( rc ) { 2001 char regerr[ SLAP_TEXT_BUFLEN ]; 2002 regerror( rc, &mf->mf_regex, regerr, sizeof(regerr) ); 2003 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2004 "regular expression \"%s\" bad because of %s", 2005 c->argv[1], regerr ); 2006 ch_free( mf ); 2007 return 1; 2008 } 2009 ber_str2bv( c->argv[1], 0, 1, &mf->mf_regex_pattern ); 2010 for ( m2 = &mt->mt_filter; *m2; m2 = &(*m2)->mf_next ) 2011 ; 2012 *m2 = mf; 2013 } break; 2014 case LDAP_BACK_CFG_MAX_PENDING_OPS: 2015 if (c->value_int < 0) { 2016 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2017 "max-pending-ops invalid value %d", 2018 c->value_int); 2019 return 1; 2020 } 2021 mi->mi_max_pending_ops = c->value_int; 2022 break; 2023 case LDAP_BACK_CFG_MAX_TARGET_CONNS: 2024 { 2025 if (c->value_int < 0) { 2026 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2027 "max-target-conns invalid value %d", 2028 c->value_int); 2029 return 1; 2030 } 2031 mi->mi_max_target_conns = c->value_int; 2032 } 2033 break; 2034 case LDAP_BACK_CFG_MAX_TIMEOUT_OPS: 2035 if (c->value_int < 0) { 2036 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2037 "max-timeout-ops invalid value %d", 2038 c->value_int); 2039 return 1; 2040 } 2041 mi->mi_max_timeout_ops = c->value_int; 2042 break; 2043 2044 case LDAP_BACK_CFG_DEFAULT_T: 2045 /* default target directive */ 2046 i = mi->mi_ntargets - 1; 2047 2048 if ( c->argc == 1 ) { 2049 if ( i < 0 ) { 2050 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2051 "\"%s\" alone must be inside a \"uri\" directive", 2052 c->argv[0] ); 2053 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2054 return 1; 2055 } 2056 mi->mi_defaulttarget = i; 2057 2058 } else { 2059 if ( strcasecmp( c->argv[ 1 ], "none" ) == 0 ) { 2060 if ( i >= 0 ) { 2061 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2062 "\"%s none\" should go before uri definitions", 2063 c->argv[0] ); 2064 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2065 } 2066 mi->mi_defaulttarget = META_DEFAULT_TARGET_NONE; 2067 2068 } else { 2069 2070 if ( lutil_atoi( &mi->mi_defaulttarget, c->argv[ 1 ] ) != 0 2071 || mi->mi_defaulttarget < 0 2072 || mi->mi_defaulttarget >= i - 1 ) 2073 { 2074 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2075 "illegal target number %d", 2076 mi->mi_defaulttarget ); 2077 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2078 return 1; 2079 } 2080 } 2081 } 2082 break; 2083 2084 case LDAP_BACK_CFG_DNCACHE_TTL: 2085 /* ttl of dn cache */ 2086 if ( strcasecmp( c->argv[ 1 ], "forever" ) == 0 ) { 2087 mi->mi_cache.ttl = META_DNCACHE_FOREVER; 2088 2089 } else if ( strcasecmp( c->argv[ 1 ], "disabled" ) == 0 ) { 2090 mi->mi_cache.ttl = META_DNCACHE_DISABLED; 2091 2092 } else { 2093 unsigned long t; 2094 2095 if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) { 2096 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2097 "unable to parse dncache ttl \"%s\"", 2098 c->argv[ 1 ] ); 2099 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2100 return 1; 2101 } 2102 mi->mi_cache.ttl = (time_t)t; 2103 } 2104 break; 2105 2106 case LDAP_BACK_CFG_NETWORK_TIMEOUT: { 2107 /* network timeout when connecting to ldap servers */ 2108 unsigned long t; 2109 2110 if ( lutil_parse_time( c->argv[ 1 ], &t ) ) { 2111 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2112 "unable to parse network timeout \"%s\"", 2113 c->argv[ 1 ] ); 2114 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2115 return 1; 2116 } 2117 mc->mc_network_timeout = (time_t)t; 2118 } break; 2119 2120 case LDAP_BACK_CFG_IDLE_TIMEOUT: { 2121 /* idle timeout when connecting to ldap servers */ 2122 unsigned long t; 2123 2124 if ( lutil_parse_time( c->argv[ 1 ], &t ) ) { 2125 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2126 "unable to parse idle timeout \"%s\"", 2127 c->argv[ 1 ] ); 2128 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2129 return 1; 2130 2131 } 2132 mi->mi_idle_timeout = (time_t)t; 2133 } break; 2134 2135 case LDAP_BACK_CFG_BIND_TIMEOUT: 2136 /* bind timeout when connecting to ldap servers */ 2137 mc->mc_bind_timeout.tv_sec = c->value_ulong/1000000; 2138 mc->mc_bind_timeout.tv_usec = c->value_ulong%1000000; 2139 break; 2140 2141 case LDAP_BACK_CFG_REBIND: 2142 /* save bind creds for referral rebinds? */ 2143 if ( c->argc == 1 || c->value_int ) { 2144 mc->mc_flags |= LDAP_BACK_F_SAVECRED; 2145 } else { 2146 mc->mc_flags &= ~LDAP_BACK_F_SAVECRED; 2147 } 2148 break; 2149 2150 case LDAP_BACK_CFG_CHASE: 2151 if ( c->argc == 1 || c->value_int ) { 2152 mc->mc_flags |= LDAP_BACK_F_CHASE_REFERRALS; 2153 } else { 2154 mc->mc_flags &= ~LDAP_BACK_F_CHASE_REFERRALS; 2155 } 2156 break; 2157 2158 case LDAP_BACK_CFG_TLS: 2159 i = verb_to_mask( c->argv[1], tls_mode ); 2160 if ( BER_BVISNULL( &tls_mode[i].word ) ) { 2161 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2162 "%s unknown argument \"%s\"", 2163 c->argv[0], c->argv[1] ); 2164 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2165 return 1; 2166 } 2167 mc->mc_flags &= ~LDAP_BACK_F_TLS_MASK; 2168 mc->mc_flags |= tls_mode[i].mask; 2169 2170 if ( c->argc > 2 ) { 2171 if ( c->op == SLAP_CONFIG_ADD && mi->mi_ntargets == 0 ) { 2172 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2173 "need \"uri\" directive first" ); 2174 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2175 return 1; 2176 } 2177 2178 for ( i = 2; i < c->argc; i++ ) { 2179 if ( bindconf_tls_parse( c->argv[i], &mt->mt_tls )) 2180 return 1; 2181 } 2182 bindconf_tls_defaults( &mt->mt_tls ); 2183 } 2184 break; 2185 2186 case LDAP_BACK_CFG_T_F: 2187 i = verb_to_mask( c->argv[1], t_f_mode ); 2188 if ( BER_BVISNULL( &t_f_mode[i].word ) ) { 2189 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2190 "%s unknown argument \"%s\"", 2191 c->argv[0], c->argv[1] ); 2192 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2193 return 1; 2194 } 2195 mc->mc_flags &= ~LDAP_BACK_F_T_F_MASK2; 2196 mc->mc_flags |= t_f_mode[i].mask; 2197 break; 2198 2199 case LDAP_BACK_CFG_ONERR: 2200 /* onerr? */ 2201 i = verb_to_mask( c->argv[1], onerr_mode ); 2202 if ( BER_BVISNULL( &onerr_mode[i].word ) ) { 2203 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2204 "%s unknown argument \"%s\"", 2205 c->argv[0], c->argv[1] ); 2206 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2207 return 1; 2208 } 2209 mi->mi_flags &= ~META_BACK_F_ONERR_MASK; 2210 mi->mi_flags |= onerr_mode[i].mask; 2211 break; 2212 2213 case LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER: 2214 /* bind-defer? */ 2215 if ( c->argc == 1 || c->value_int ) { 2216 mi->mi_flags |= META_BACK_F_DEFER_ROOTDN_BIND; 2217 } else { 2218 mi->mi_flags &= ~META_BACK_F_DEFER_ROOTDN_BIND; 2219 } 2220 break; 2221 2222 case LDAP_BACK_CFG_CONNPOOLMAX: 2223 /* privileged connections pool max size ? */ 2224 if ( mi->mi_ntargets > 0 ) { 2225 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2226 "\"%s\" must appear before target definitions", 2227 c->argv[0] ); 2228 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2229 return( 1 ); 2230 } 2231 2232 if ( c->value_int < LDAP_BACK_CONN_PRIV_MIN 2233 || c->value_int > LDAP_BACK_CONN_PRIV_MAX ) 2234 { 2235 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2236 "invalid max size " "of privileged " 2237 "connections pool \"%s\" " 2238 "in \"conn-pool-max <n> " 2239 "(must be between %d and %d)\"", 2240 c->argv[ 1 ], 2241 LDAP_BACK_CONN_PRIV_MIN, 2242 LDAP_BACK_CONN_PRIV_MAX ); 2243 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2244 return 1; 2245 } 2246 mi->mi_conn_priv_max = c->value_int; 2247 break; 2248 2249 case LDAP_BACK_CFG_CANCEL: 2250 i = verb_to_mask( c->argv[1], cancel_mode ); 2251 if ( BER_BVISNULL( &cancel_mode[i].word ) ) { 2252 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2253 "%s unknown argument \"%s\"", 2254 c->argv[0], c->argv[1] ); 2255 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2256 return 1; 2257 } 2258 mc->mc_flags &= ~LDAP_BACK_F_CANCEL_MASK2; 2259 mc->mc_flags |= cancel_mode[i].mask; 2260 break; 2261 2262 case LDAP_BACK_CFG_TIMEOUT: 2263 for ( i = 1; i < c->argc; i++ ) { 2264 if ( isdigit( (unsigned char) c->argv[ i ][ 0 ] ) ) { 2265 int j; 2266 unsigned u; 2267 2268 if ( lutil_atoux( &u, c->argv[ i ], 0 ) != 0 ) { 2269 snprintf( c->cr_msg, sizeof( c->cr_msg), 2270 "unable to parse timeout \"%s\"", 2271 c->argv[ i ] ); 2272 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2273 return 1; 2274 } 2275 2276 for ( j = 0; j < SLAP_OP_LAST; j++ ) { 2277 mc->mc_timeout[ j ] = u; 2278 } 2279 2280 continue; 2281 } 2282 2283 if ( slap_cf_aux_table_parse( c->argv[ i ], mc->mc_timeout, timeout_table, "slapd-meta timeout" ) ) { 2284 snprintf( c->cr_msg, sizeof( c->cr_msg), 2285 "unable to parse timeout \"%s\"", 2286 c->argv[ i ] ); 2287 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2288 return 1; 2289 } 2290 } 2291 break; 2292 2293 case LDAP_BACK_CFG_IDASSERT_BIND: 2294 /* idassert-bind */ 2295 rc = mi->mi_ldap_extra->idassert_parse( c, &mt->mt_idassert ); 2296 break; 2297 2298 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: 2299 /* idassert-authzFrom */ 2300 rc = mi->mi_ldap_extra->idassert_authzfrom_parse( c, &mt->mt_idassert ); 2301 break; 2302 2303 case LDAP_BACK_CFG_QUARANTINE: 2304 /* quarantine */ 2305 if ( META_BACK_CMN_QUARANTINE( mc ) ) 2306 { 2307 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2308 "quarantine already defined" ); 2309 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2310 return 1; 2311 } 2312 2313 if ( mt ) { 2314 mc->mc_quarantine.ri_interval = NULL; 2315 mc->mc_quarantine.ri_num = NULL; 2316 if ( !META_BACK_QUARANTINE( mi ) ) { 2317 ldap_pvt_thread_mutex_init( &mt->mt_quarantine_mutex ); 2318 } 2319 } 2320 2321 if ( mi->mi_ldap_extra->retry_info_parse( c->argv[ 1 ], &mc->mc_quarantine, c->cr_msg, sizeof( c->cr_msg ) ) ) { 2322 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2323 return 1; 2324 } 2325 2326 mc->mc_flags |= LDAP_BACK_F_QUARANTINE; 2327 break; 2328 2329#ifdef SLAP_CONTROL_X_SESSION_TRACKING 2330 case LDAP_BACK_CFG_ST_REQUEST: 2331 /* session tracking request */ 2332 if ( c->value_int ) { 2333 mc->mc_flags |= LDAP_BACK_F_ST_REQUEST; 2334 } else { 2335 mc->mc_flags &= ~LDAP_BACK_F_ST_REQUEST; 2336 } 2337 break; 2338#endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 2339 2340 case LDAP_BACK_CFG_SUFFIXM: 2341 rc = asyncmeta_suffixm_config( c, c->argc, c->argv, mt ); 2342 break; 2343 2344 case LDAP_BACK_CFG_NRETRIES: { 2345 int nretries = META_RETRY_UNDEFINED; 2346 2347 if ( strcasecmp( c->argv[ 1 ], "forever" ) == 0 ) { 2348 nretries = META_RETRY_FOREVER; 2349 2350 } else if ( strcasecmp( c->argv[ 1 ], "never" ) == 0 ) { 2351 nretries = META_RETRY_NEVER; 2352 2353 } else { 2354 if ( lutil_atoi( &nretries, c->argv[ 1 ] ) != 0 ) { 2355 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2356 "unable to parse nretries {never|forever|<retries>}: \"%s\"", 2357 c->argv[ 1 ] ); 2358 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2359 return 1; 2360 } 2361 } 2362 2363 mc->mc_nretries = nretries; 2364 } break; 2365 2366 case LDAP_BACK_CFG_VERSION: 2367 if ( c->value_int != 0 && ( c->value_int < LDAP_VERSION_MIN || c->value_int > LDAP_VERSION_MAX ) ) { 2368 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2369 "unsupported protocol version \"%s\"", 2370 c->argv[ 1 ] ); 2371 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2372 return 1; 2373 } 2374 mc->mc_version = c->value_int; 2375 break; 2376 2377 case LDAP_BACK_CFG_NOREFS: 2378 /* do not return search references */ 2379 if ( c->value_int ) { 2380 mc->mc_flags |= LDAP_BACK_F_NOREFS; 2381 } else { 2382 mc->mc_flags &= ~LDAP_BACK_F_NOREFS; 2383 } 2384 break; 2385 2386 case LDAP_BACK_CFG_NOUNDEFFILTER: 2387 /* do not propagate undefined search filters */ 2388 if ( c->value_int ) { 2389 mc->mc_flags |= LDAP_BACK_F_NOUNDEFFILTER; 2390 } else { 2391 mc->mc_flags &= ~LDAP_BACK_F_NOUNDEFFILTER; 2392 } 2393 break; 2394 2395#ifdef SLAPD_META_CLIENT_PR 2396 case LDAP_BACK_CFG_CLIENT_PR: 2397 if ( strcasecmp( c->argv[ 1 ], "accept-unsolicited" ) == 0 ) { 2398 mc->mc_ps = META_CLIENT_PR_ACCEPT_UNSOLICITED; 2399 2400 } else if ( strcasecmp( c->argv[ 1 ], "disable" ) == 0 ) { 2401 mc->mc_ps = META_CLIENT_PR_DISABLE; 2402 2403 } else if ( lutil_atoi( &mc->mc_ps, c->argv[ 1 ] ) || mc->mc_ps < -1 ) { 2404 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2405 "unable to parse client-pr {accept-unsolicited|disable|<size>}: \"%s\"", 2406 c->argv[ 1 ] ); 2407 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2408 return( 1 ); 2409 } 2410 break; 2411#endif /* SLAPD_META_CLIENT_PR */ 2412 2413 case LDAP_BACK_CFG_KEEPALIVE: 2414 slap_keepalive_parse( ber_bvstrdup(c->argv[1]), 2415 &mt->mt_tls.sb_keepalive, 0, 0, 0); 2416 break; 2417 2418 case LDAP_BACK_CFG_TCP_USER_TIMEOUT: 2419 mt->mt_tls.sb_tcp_user_timeout = c->value_uint; 2420 break; 2421 2422 /* anything else */ 2423 default: 2424 return SLAP_CONF_UNKNOWN; 2425 } 2426 2427 return rc; 2428} 2429 2430int 2431asyncmeta_back_init_cf( BackendInfo *bi ) 2432{ 2433 int rc; 2434 2435 /* Make sure we don't exceed the bits reserved for userland */ 2436 config_check_userland( LDAP_BACK_CFG_LAST ); 2437 2438 bi->bi_cf_ocs = a_metaocs; 2439 2440 rc = config_register_schema( a_metacfg, a_metaocs ); 2441 if ( rc ) { 2442 return rc; 2443 } 2444 2445 return 0; 2446} 2447