1 /* $NetBSD: config.c,v 1.3 2021/08/14 16:15:00 christos Exp $ */ 2 3 /* $OpenLDAP$ */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1999-2021 The OpenLDAP Foundation. 7 * Portions Copyright 2001-2003 Pierangelo Masarati. 8 * Portions Copyright 1999-2003 Howard Chu. 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 /* ACKNOWLEDGEMENTS: 20 * This work was initially developed by the Howard Chu for inclusion 21 * in OpenLDAP Software and subsequently enhanced by Pierangelo 22 * Masarati. 23 */ 24 25 #include <sys/cdefs.h> 26 __RCSID("$NetBSD: config.c,v 1.3 2021/08/14 16:15:00 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-meta.h" 42 43 #ifdef LDAP_DEVEL 44 #define SLAP_AUTH_DN 1 45 #endif 46 47 static ConfigDriver meta_back_cf_gen; 48 static ConfigLDAPadd meta_ldadd; 49 static ConfigCfAdd meta_cfadd; 50 51 static int ldap_back_map_config( 52 ConfigArgs *c, 53 struct ldapmap *oc_map, 54 struct ldapmap *at_map ); 55 56 /* Three sets of enums: 57 * 1) attrs that are only valid in the base config 58 * 2) attrs that are valid in base or target 59 * 3) attrs that are only valid in a target 60 */ 61 62 /* Base attrs */ 63 enum { 64 LDAP_BACK_CFG_CONN_TTL = 1, 65 LDAP_BACK_CFG_DNCACHE_TTL, 66 LDAP_BACK_CFG_IDLE_TIMEOUT, 67 LDAP_BACK_CFG_ONERR, 68 LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER, 69 LDAP_BACK_CFG_SINGLECONN, 70 LDAP_BACK_CFG_USETEMP, 71 LDAP_BACK_CFG_CONNPOOLMAX, 72 LDAP_BACK_CFG_LAST_BASE 73 }; 74 75 /* Base or target */ 76 enum { 77 LDAP_BACK_CFG_BIND_TIMEOUT = LDAP_BACK_CFG_LAST_BASE, 78 LDAP_BACK_CFG_CANCEL, 79 LDAP_BACK_CFG_CHASE, 80 LDAP_BACK_CFG_CLIENT_PR, 81 LDAP_BACK_CFG_DEFAULT_T, 82 LDAP_BACK_CFG_NETWORK_TIMEOUT, 83 LDAP_BACK_CFG_NOREFS, 84 LDAP_BACK_CFG_NOUNDEFFILTER, 85 LDAP_BACK_CFG_NRETRIES, 86 LDAP_BACK_CFG_QUARANTINE, 87 LDAP_BACK_CFG_REBIND, 88 LDAP_BACK_CFG_TIMEOUT, 89 LDAP_BACK_CFG_VERSION, 90 LDAP_BACK_CFG_ST_REQUEST, 91 LDAP_BACK_CFG_T_F, 92 LDAP_BACK_CFG_TLS, 93 LDAP_BACK_CFG_LAST_BOTH 94 }; 95 96 /* Target attrs */ 97 enum { 98 LDAP_BACK_CFG_URI = LDAP_BACK_CFG_LAST_BOTH, 99 LDAP_BACK_CFG_IDASSERT_AUTHZFROM, 100 LDAP_BACK_CFG_IDASSERT_BIND, 101 LDAP_BACK_CFG_REWRITE, 102 LDAP_BACK_CFG_SUFFIXM, 103 LDAP_BACK_CFG_MAP, 104 LDAP_BACK_CFG_SUBTREE_EX, 105 LDAP_BACK_CFG_SUBTREE_IN, 106 LDAP_BACK_CFG_PSEUDOROOTDN, 107 LDAP_BACK_CFG_PSEUDOROOTPW, 108 LDAP_BACK_CFG_KEEPALIVE, 109 LDAP_BACK_CFG_TCP_USER_TIMEOUT, 110 LDAP_BACK_CFG_FILTER, 111 112 LDAP_BACK_CFG_LAST 113 }; 114 115 static ConfigTable metacfg[] = { 116 { "uri", "uri", 2, 0, 0, 117 ARG_MAGIC|LDAP_BACK_CFG_URI, 118 meta_back_cf_gen, "( OLcfgDbAt:0.14 " 119 "NAME 'olcDbURI' " 120 "DESC 'URI (list) for remote DSA' " 121 "EQUALITY caseExactMatch " 122 "SYNTAX OMsDirectoryString " 123 "SINGLE-VALUE )", 124 NULL, NULL }, 125 { "tls", "what", 2, 0, 0, 126 ARG_MAGIC|LDAP_BACK_CFG_TLS, 127 meta_back_cf_gen, "( OLcfgDbAt:3.1 " 128 "NAME 'olcDbStartTLS' " 129 "DESC 'StartTLS' " 130 "EQUALITY caseExactMatch " 131 "SYNTAX OMsDirectoryString " 132 "SINGLE-VALUE )", 133 NULL, NULL }, 134 { "idassert-bind", "args", 2, 0, 0, 135 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_BIND, 136 meta_back_cf_gen, "( OLcfgDbAt:3.7 " 137 "NAME 'olcDbIDAssertBind' " 138 "DESC 'Remote Identity Assertion administrative identity auth bind configuration' " 139 "EQUALITY caseIgnoreMatch " 140 "SYNTAX OMsDirectoryString " 141 "SINGLE-VALUE )", 142 NULL, NULL }, 143 { "idassert-authzFrom", "authzRule", 2, 2, 0, 144 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_AUTHZFROM, 145 meta_back_cf_gen, "( OLcfgDbAt:3.9 " 146 "NAME 'olcDbIDAssertAuthzFrom' " 147 "DESC 'Remote Identity Assertion authz rules' " 148 "EQUALITY caseIgnoreMatch " 149 "SYNTAX OMsDirectoryString " 150 "X-ORDERED 'VALUES' )", 151 NULL, NULL }, 152 { "rebind-as-user", "true|FALSE", 1, 2, 0, 153 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_REBIND, 154 meta_back_cf_gen, "( OLcfgDbAt:3.10 " 155 "NAME 'olcDbRebindAsUser' " 156 "DESC 'Rebind as user' " 157 "EQUALITY booleanMatch " 158 "SYNTAX OMsBoolean " 159 "SINGLE-VALUE )", 160 NULL, NULL }, 161 { "chase-referrals", "true|FALSE", 2, 2, 0, 162 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_CHASE, 163 meta_back_cf_gen, "( OLcfgDbAt:3.11 " 164 "NAME 'olcDbChaseReferrals' " 165 "DESC 'Chase referrals' " 166 "EQUALITY booleanMatch " 167 "SYNTAX OMsBoolean " 168 "SINGLE-VALUE )", 169 NULL, NULL }, 170 { "t-f-support", "true|FALSE|discover", 2, 2, 0, 171 ARG_MAGIC|LDAP_BACK_CFG_T_F, 172 meta_back_cf_gen, "( OLcfgDbAt:3.12 " 173 "NAME 'olcDbTFSupport' " 174 "DESC 'Absolute filters support' " 175 "EQUALITY caseIgnoreMatch " 176 "SYNTAX OMsDirectoryString " 177 "SINGLE-VALUE )", 178 NULL, NULL }, 179 { "timeout", "timeout(list)", 2, 0, 0, 180 ARG_MAGIC|LDAP_BACK_CFG_TIMEOUT, 181 meta_back_cf_gen, "( OLcfgDbAt:3.14 " 182 "NAME 'olcDbTimeout' " 183 "DESC 'Per-operation timeouts' " 184 "EQUALITY caseIgnoreMatch " 185 "SYNTAX OMsDirectoryString " 186 "SINGLE-VALUE )", 187 NULL, NULL }, 188 { "idle-timeout", "timeout", 2, 2, 0, 189 ARG_MAGIC|LDAP_BACK_CFG_IDLE_TIMEOUT, 190 meta_back_cf_gen, "( OLcfgDbAt:3.15 " 191 "NAME 'olcDbIdleTimeout' " 192 "DESC 'connection idle timeout' " 193 "EQUALITY caseIgnoreMatch " 194 "SYNTAX OMsDirectoryString " 195 "SINGLE-VALUE )", 196 NULL, NULL }, 197 { "conn-ttl", "ttl", 2, 2, 0, 198 ARG_MAGIC|LDAP_BACK_CFG_CONN_TTL, 199 meta_back_cf_gen, "( OLcfgDbAt:3.16 " 200 "NAME 'olcDbConnTtl' " 201 "DESC 'connection ttl' " 202 "EQUALITY caseIgnoreMatch " 203 "SYNTAX OMsDirectoryString " 204 "SINGLE-VALUE )", 205 NULL, NULL }, 206 { "network-timeout", "timeout", 2, 2, 0, 207 ARG_MAGIC|LDAP_BACK_CFG_NETWORK_TIMEOUT, 208 meta_back_cf_gen, "( OLcfgDbAt:3.17 " 209 "NAME 'olcDbNetworkTimeout' " 210 "DESC 'connection network timeout' " 211 "SYNTAX OMsDirectoryString " 212 "SINGLE-VALUE )", 213 NULL, NULL }, 214 { "protocol-version", "version", 2, 2, 0, 215 ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_VERSION, 216 meta_back_cf_gen, "( OLcfgDbAt:3.18 " 217 "NAME 'olcDbProtocolVersion' " 218 "DESC 'protocol version' " 219 "EQUALITY integerMatch " 220 "SYNTAX OMsInteger " 221 "SINGLE-VALUE )", 222 NULL, NULL }, 223 { "single-conn", "true|FALSE", 2, 2, 0, 224 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_SINGLECONN, 225 meta_back_cf_gen, "( OLcfgDbAt:3.19 " 226 "NAME 'olcDbSingleConn' " 227 "DESC 'cache a single connection per identity' " 228 "EQUALITY booleanMatch " 229 "SYNTAX OMsBoolean " 230 "SINGLE-VALUE )", 231 NULL, NULL }, 232 { "cancel", "ABANDON|ignore|exop", 2, 2, 0, 233 ARG_MAGIC|LDAP_BACK_CFG_CANCEL, 234 meta_back_cf_gen, "( OLcfgDbAt:3.20 " 235 "NAME 'olcDbCancel' " 236 "DESC 'abandon/ignore/exop operations when appropriate' " 237 "EQUALITY caseIgnoreMatch " 238 "SYNTAX OMsDirectoryString " 239 "SINGLE-VALUE )", 240 NULL, NULL }, 241 { "quarantine", "retrylist", 2, 2, 0, 242 ARG_MAGIC|LDAP_BACK_CFG_QUARANTINE, 243 meta_back_cf_gen, "( OLcfgDbAt:3.21 " 244 "NAME 'olcDbQuarantine' " 245 "DESC 'Quarantine database if connection fails and retry according to rule' " 246 "EQUALITY caseIgnoreMatch " 247 "SYNTAX OMsDirectoryString " 248 "SINGLE-VALUE )", 249 NULL, NULL }, 250 { "use-temporary-conn", "true|FALSE", 2, 2, 0, 251 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_USETEMP, 252 meta_back_cf_gen, "( OLcfgDbAt:3.22 " 253 "NAME 'olcDbUseTemporaryConn' " 254 "DESC 'Use temporary connections if the cached one is busy' " 255 "EQUALITY booleanMatch " 256 "SYNTAX OMsBoolean " 257 "SINGLE-VALUE )", 258 NULL, NULL }, 259 { "conn-pool-max", "<n>", 2, 2, 0, 260 ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_CONNPOOLMAX, 261 meta_back_cf_gen, "( OLcfgDbAt:3.23 " 262 "NAME 'olcDbConnectionPoolMax' " 263 "DESC 'Max size of privileged connections pool' " 264 "EQUALITY integerMatch " 265 "SYNTAX OMsInteger " 266 "SINGLE-VALUE )", 267 NULL, NULL }, 268 #ifdef SLAP_CONTROL_X_SESSION_TRACKING 269 { "session-tracking-request", "true|FALSE", 2, 2, 0, 270 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_ST_REQUEST, 271 meta_back_cf_gen, "( OLcfgDbAt:3.24 " 272 "NAME 'olcDbSessionTrackingRequest' " 273 "DESC 'Add session tracking control to proxied requests' " 274 "EQUALITY booleanMatch " 275 "SYNTAX OMsBoolean " 276 "SINGLE-VALUE )", 277 NULL, NULL }, 278 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 279 { "norefs", "true|FALSE", 2, 2, 0, 280 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_NOREFS, 281 meta_back_cf_gen, "( OLcfgDbAt:3.25 " 282 "NAME 'olcDbNoRefs' " 283 "DESC 'Do not return search reference responses' " 284 "EQUALITY booleanMatch " 285 "SYNTAX OMsBoolean " 286 "SINGLE-VALUE )", 287 NULL, NULL }, 288 { "noundeffilter", "true|FALSE", 2, 2, 0, 289 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_NOUNDEFFILTER, 290 meta_back_cf_gen, "( OLcfgDbAt:3.26 " 291 "NAME 'olcDbNoUndefFilter' " 292 "DESC 'Do not propagate undefined search filters' " 293 "EQUALITY booleanMatch " 294 "SYNTAX OMsBoolean " 295 "SINGLE-VALUE )", 296 NULL, NULL }, 297 298 { "rewrite", "arglist", 2, 0, STRLENOF( "rewrite" ), 299 ARG_MAGIC|LDAP_BACK_CFG_REWRITE, 300 meta_back_cf_gen, "( OLcfgDbAt:3.101 " 301 "NAME 'olcDbRewrite' " 302 "DESC 'DN rewriting rules' " 303 "EQUALITY caseIgnoreMatch " 304 "SYNTAX OMsDirectoryString " 305 "X-ORDERED 'VALUES' )", 306 NULL, NULL }, 307 { "suffixmassage", "virtual> <real", 2, 3, 0, 308 ARG_MAGIC|LDAP_BACK_CFG_SUFFIXM, 309 meta_back_cf_gen, NULL, NULL, NULL }, 310 311 { "map", "attribute|objectClass> [*|<local>] *|<remote", 3, 4, 0, 312 ARG_MAGIC|LDAP_BACK_CFG_MAP, 313 meta_back_cf_gen, "( OLcfgDbAt:3.102 " 314 "NAME 'olcDbMap' " 315 "DESC 'Map attribute and objectclass names' " 316 "EQUALITY caseIgnoreMatch " 317 "SYNTAX OMsDirectoryString " 318 "X-ORDERED 'VALUES' )", 319 NULL, NULL }, 320 321 { "subtree-exclude", "pattern", 2, 2, 0, 322 ARG_MAGIC|LDAP_BACK_CFG_SUBTREE_EX, 323 meta_back_cf_gen, "( OLcfgDbAt:3.103 " 324 "NAME 'olcDbSubtreeExclude' " 325 "DESC 'DN of subtree to exclude from target' " 326 "EQUALITY caseIgnoreMatch " 327 "SYNTAX OMsDirectoryString )", 328 NULL, NULL }, 329 { "subtree-include", "pattern", 2, 2, 0, 330 ARG_MAGIC|LDAP_BACK_CFG_SUBTREE_IN, 331 meta_back_cf_gen, "( OLcfgDbAt:3.104 " 332 "NAME 'olcDbSubtreeInclude' " 333 "DESC 'DN of subtree to include in target' " 334 "EQUALITY caseIgnoreMatch " 335 "SYNTAX OMsDirectoryString )", 336 NULL, NULL }, 337 { "default-target", "[none|<target ID>]", 1, 2, 0, 338 ARG_MAGIC|LDAP_BACK_CFG_DEFAULT_T, 339 meta_back_cf_gen, "( OLcfgDbAt:3.105 " 340 "NAME 'olcDbDefaultTarget' " 341 "DESC 'Specify the default target' " 342 "EQUALITY caseIgnoreMatch " 343 "SYNTAX OMsDirectoryString " 344 "SINGLE-VALUE )", 345 NULL, NULL }, 346 { "dncache-ttl", "ttl", 2, 2, 0, 347 ARG_MAGIC|LDAP_BACK_CFG_DNCACHE_TTL, 348 meta_back_cf_gen, "( OLcfgDbAt:3.106 " 349 "NAME 'olcDbDnCacheTtl' " 350 "DESC 'dncache ttl' " 351 "EQUALITY caseIgnoreMatch " 352 "SYNTAX OMsDirectoryString " 353 "SINGLE-VALUE )", 354 NULL, NULL }, 355 { "bind-timeout", "microseconds", 2, 2, 0, 356 ARG_MAGIC|ARG_ULONG|LDAP_BACK_CFG_BIND_TIMEOUT, 357 meta_back_cf_gen, "( OLcfgDbAt:3.107 " 358 "NAME 'olcDbBindTimeout' " 359 "DESC 'bind timeout' " 360 "EQUALITY integerMatch " 361 "SYNTAX OMsInteger " 362 "SINGLE-VALUE )", 363 NULL, NULL }, 364 { "onerr", "CONTINUE|report|stop", 2, 2, 0, 365 ARG_MAGIC|LDAP_BACK_CFG_ONERR, 366 meta_back_cf_gen, "( OLcfgDbAt:3.108 " 367 "NAME 'olcDbOnErr' " 368 "DESC 'error handling' " 369 "EQUALITY caseIgnoreMatch " 370 "SYNTAX OMsDirectoryString " 371 "SINGLE-VALUE )", 372 NULL, NULL }, 373 { "pseudoroot-bind-defer", "TRUE|false", 2, 2, 0, 374 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER, 375 meta_back_cf_gen, "( OLcfgDbAt:3.109 " 376 "NAME 'olcDbPseudoRootBindDefer' " 377 "DESC 'error handling' " 378 "EQUALITY booleanMatch " 379 "SYNTAX OMsBoolean " 380 "SINGLE-VALUE )", 381 NULL, NULL }, 382 { "root-bind-defer", "TRUE|false", 2, 2, 0, 383 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER, 384 meta_back_cf_gen, NULL, NULL, NULL }, 385 { "pseudorootdn", "dn", 2, 2, 0, 386 ARG_MAGIC|ARG_DN|ARG_QUOTE|LDAP_BACK_CFG_PSEUDOROOTDN, 387 meta_back_cf_gen, NULL, NULL, NULL }, 388 { "pseudorootpw", "password", 2, 2, 0, 389 ARG_MAGIC|ARG_STRING|LDAP_BACK_CFG_PSEUDOROOTPW, 390 meta_back_cf_gen, NULL, NULL, NULL }, 391 { "nretries", "NEVER|forever|<number>", 2, 2, 0, 392 ARG_MAGIC|LDAP_BACK_CFG_NRETRIES, 393 meta_back_cf_gen, "( OLcfgDbAt:3.110 " 394 "NAME 'olcDbNretries' " 395 "DESC 'retry handling' " 396 "EQUALITY caseIgnoreMatch " 397 "SYNTAX OMsDirectoryString " 398 "SINGLE-VALUE )", 399 NULL, NULL }, 400 { "client-pr", "accept-unsolicited|disable|<size>", 2, 2, 0, 401 ARG_MAGIC|LDAP_BACK_CFG_CLIENT_PR, 402 meta_back_cf_gen, "( OLcfgDbAt:3.111 " 403 "NAME 'olcDbClientPr' " 404 "DESC 'PagedResults handling' " 405 "EQUALITY caseIgnoreMatch " 406 "SYNTAX OMsDirectoryString " 407 "SINGLE-VALUE )", 408 NULL, NULL }, 409 410 { "", "", 0, 0, 0, ARG_IGNORED, 411 NULL, "( OLcfgDbAt:3.100 NAME 'olcMetaSub' " 412 "DESC 'Placeholder to name a Target entry' " 413 "EQUALITY caseIgnoreMatch " 414 "SYNTAX OMsDirectoryString " 415 "SINGLE-VALUE X-ORDERED 'SIBLINGS' )", NULL, NULL }, 416 417 { "keepalive", "keepalive", 2, 2, 0, 418 ARG_MAGIC|LDAP_BACK_CFG_KEEPALIVE, 419 meta_back_cf_gen, "( OLcfgDbAt:3.29 " 420 "NAME 'olcDbKeepalive' " 421 "DESC 'TCP keepalive' " 422 "EQUALITY caseIgnoreMatch " 423 "SYNTAX OMsDirectoryString " 424 "SINGLE-VALUE )", 425 NULL, NULL }, 426 427 { "tcp-user-timeout", "milliseconds", 2, 2, 0, 428 ARG_MAGIC|ARG_UINT|LDAP_BACK_CFG_TCP_USER_TIMEOUT, 429 meta_back_cf_gen, "( OLcfgDbAt:3.30 " 430 "NAME 'olcDbTcpUserTimeout' " 431 "DESC 'TCP User Timeout' " 432 "SYNTAX OMsInteger " 433 "SINGLE-VALUE )", 434 NULL, NULL }, 435 436 { "filter", "pattern", 2, 2, 0, 437 ARG_MAGIC|LDAP_BACK_CFG_FILTER, 438 meta_back_cf_gen, "( OLcfgDbAt:3.112 " 439 "NAME 'olcDbFilter' " 440 "DESC 'Filter regex pattern to include in target' " 441 "EQUALITY caseExactMatch " 442 "SYNTAX OMsDirectoryString )", 443 NULL, NULL }, 444 445 { NULL, NULL, 0, 0, 0, ARG_IGNORED, 446 NULL, NULL, NULL, NULL } 447 }; 448 449 #ifdef SLAP_CONTROL_X_SESSION_TRACKING 450 #define ST_ATTR "$ olcDbSessionTrackingRequest " 451 #else 452 #define ST_ATTR "" 453 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 454 455 #define COMMON_ATTRS \ 456 "$ olcDbBindTimeout " \ 457 "$ olcDbCancel " \ 458 "$ olcDbChaseReferrals " \ 459 "$ olcDbClientPr " \ 460 "$ olcDbDefaultTarget " \ 461 "$ olcDbNetworkTimeout " \ 462 "$ olcDbNoRefs " \ 463 "$ olcDbNoUndefFilter " \ 464 "$ olcDbNretries " \ 465 "$ olcDbProtocolVersion " \ 466 "$ olcDbQuarantine " \ 467 "$ olcDbRebindAsUser " \ 468 ST_ATTR \ 469 "$ olcDbStartTLS " \ 470 "$ olcDbTFSupport " 471 472 static ConfigOCs metaocs[] = { 473 { "( OLcfgDbOc:3.2 " 474 "NAME 'olcMetaConfig' " 475 "DESC 'Meta backend configuration' " 476 "SUP olcDatabaseConfig " 477 "MAY ( olcDbConnTtl " 478 "$ olcDbDnCacheTtl " 479 "$ olcDbIdleTimeout " 480 "$ olcDbOnErr " 481 "$ olcDbPseudoRootBindDefer " 482 "$ olcDbSingleConn " 483 "$ olcDbUseTemporaryConn " 484 "$ olcDbConnectionPoolMax " 485 486 /* defaults, may be overridden per-target */ 487 COMMON_ATTRS 488 ") )", 489 Cft_Database, metacfg, NULL, meta_cfadd }, 490 { "( OLcfgDbOc:3.3 " 491 "NAME 'olcMetaTargetConfig' " 492 "DESC 'Meta target configuration' " 493 "SUP olcConfig STRUCTURAL " 494 "MUST ( olcMetaSub $ olcDbURI ) " 495 "MAY ( olcDbIDAssertAuthzFrom " 496 "$ olcDbIDAssertBind " 497 "$ olcDbMap " 498 "$ olcDbRewrite " 499 "$ olcDbSubtreeExclude " 500 "$ olcDbSubtreeInclude " 501 "$ olcDbTimeout " 502 "$ olcDbKeepalive " 503 "$ olcDbTcpUserTimeout " 504 "$ olcDbFilter " 505 506 /* defaults may be inherited */ 507 COMMON_ATTRS 508 ") )", 509 Cft_Misc, metacfg, meta_ldadd }, 510 { NULL, 0, NULL } 511 }; 512 513 static int 514 meta_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *c ) 515 { 516 if ( p->ce_type != Cft_Database || !p->ce_be || 517 p->ce_be->be_cf_ocs != metaocs ) 518 return LDAP_CONSTRAINT_VIOLATION; 519 520 c->be = p->ce_be; 521 return LDAP_SUCCESS; 522 } 523 524 static int 525 meta_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *c ) 526 { 527 metainfo_t *mi = ( metainfo_t * )c->be->be_private; 528 struct berval bv; 529 int i; 530 531 bv.bv_val = c->cr_msg; 532 for ( i=0; i<mi->mi_ntargets; i++ ) { 533 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), 534 "olcMetaSub=" SLAP_X_ORDERED_FMT "uri", i ); 535 c->ca_private = mi->mi_targets[i]; 536 c->valx = i; 537 config_build_entry( op, rs, p->e_private, c, 538 &bv, &metaocs[1], NULL ); 539 } 540 541 return LDAP_SUCCESS; 542 } 543 544 static int 545 meta_rwi_init( struct rewrite_info **rwm_rw ) 546 { 547 char *rargv[ 3 ]; 548 549 *rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT ); 550 if ( *rwm_rw == NULL ) { 551 return -1; 552 } 553 /* 554 * the filter rewrite as a string must be disabled 555 * by default; it can be re-enabled by adding rules; 556 * this creates an empty rewriteContext 557 */ 558 rargv[ 0 ] = "rewriteContext"; 559 rargv[ 1 ] = "searchFilter"; 560 rargv[ 2 ] = NULL; 561 rewrite_parse( *rwm_rw, "<suffix massage>", 1, 2, rargv ); 562 563 rargv[ 0 ] = "rewriteContext"; 564 rargv[ 1 ] = "default"; 565 rargv[ 2 ] = NULL; 566 rewrite_parse( *rwm_rw, "<suffix massage>", 1, 2, rargv ); 567 568 return 0; 569 } 570 571 static int 572 meta_back_new_target( 573 metatarget_t **mtp ) 574 { 575 metatarget_t *mt; 576 577 *mtp = NULL; 578 579 mt = ch_calloc( sizeof( metatarget_t ), 1 ); 580 581 if ( meta_rwi_init( &mt->mt_rwmap.rwm_rw )) { 582 ch_free( mt ); 583 return -1; 584 } 585 586 ldap_pvt_thread_mutex_init( &mt->mt_uri_mutex ); 587 588 mt->mt_idassert_mode = LDAP_BACK_IDASSERT_LEGACY; 589 mt->mt_idassert_authmethod = LDAP_AUTH_NONE; 590 mt->mt_idassert_tls = SB_TLS_DEFAULT; 591 592 /* by default, use proxyAuthz control on each operation */ 593 mt->mt_idassert_flags = LDAP_BACK_AUTH_PRESCRIPTIVE; 594 595 *mtp = mt; 596 597 return 0; 598 } 599 600 /* Validation for suffixmassage_config */ 601 static int 602 meta_suffixm_config( 603 ConfigArgs *c, 604 int argc, 605 char **argv, 606 metatarget_t *mt 607 ) 608 { 609 BackendDB *tmp_bd; 610 struct berval dn, nvnc, pvnc, nrnc, prnc; 611 int j, rc; 612 613 /* 614 * syntax: 615 * 616 * suffixmassage <suffix> <massaged suffix> 617 * 618 * the <suffix> field must be defined as a valid suffix 619 * (or suffixAlias?) for the current database; 620 * the <massaged suffix> shouldn't have already been 621 * defined as a valid suffix or suffixAlias for the 622 * current server 623 */ 624 625 ber_str2bv( argv[ 1 ], 0, 0, &dn ); 626 if ( dnPrettyNormal( NULL, &dn, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) { 627 snprintf( c->cr_msg, sizeof( c->cr_msg ), 628 "suffix \"%s\" is invalid", 629 argv[1] ); 630 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 631 return 1; 632 } 633 634 for ( j = 0; !BER_BVISNULL( &c->be->be_nsuffix[ j ] ); j++ ) { 635 if ( dnIsSuffix( &nvnc, &c->be->be_nsuffix[ 0 ] ) ) { 636 break; 637 } 638 } 639 640 if ( BER_BVISNULL( &c->be->be_nsuffix[ j ] ) ) { 641 snprintf( c->cr_msg, sizeof( c->cr_msg ), 642 "suffix \"%s\" must be within the database naming context", 643 argv[1] ); 644 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 645 free( pvnc.bv_val ); 646 free( nvnc.bv_val ); 647 return 1; 648 } 649 650 ber_str2bv( argv[ 2 ], 0, 0, &dn ); 651 if ( dnPrettyNormal( NULL, &dn, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) { 652 snprintf( c->cr_msg, sizeof( c->cr_msg ), 653 "massaged suffix \"%s\" is invalid", 654 argv[2] ); 655 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 656 free( pvnc.bv_val ); 657 free( nvnc.bv_val ); 658 return 1; 659 } 660 661 tmp_bd = select_backend( &nrnc, 0 ); 662 if ( tmp_bd != NULL && tmp_bd->be_private == c->be->be_private ) { 663 Debug( LDAP_DEBUG_ANY, 664 "%s: warning: <massaged suffix> \"%s\" resolves to this database, in " 665 "\"suffixMassage <suffix> <massaged suffix>\"\n", 666 c->log, prnc.bv_val ); 667 } 668 669 /* 670 * The suffix massaging is emulated by means of the 671 * rewrite capabilities 672 */ 673 rc = suffix_massage_config( mt->mt_rwmap.rwm_rw, 674 &pvnc, &nvnc, &prnc, &nrnc ); 675 676 free( pvnc.bv_val ); 677 free( nvnc.bv_val ); 678 free( prnc.bv_val ); 679 free( nrnc.bv_val ); 680 681 return rc; 682 } 683 684 int 685 meta_subtree_free( metasubtree_t *ms ) 686 { 687 switch ( ms->ms_type ) { 688 case META_ST_SUBTREE: 689 case META_ST_SUBORDINATE: 690 ber_memfree( ms->ms_dn.bv_val ); 691 break; 692 693 case META_ST_REGEX: 694 regfree( &ms->ms_regex ); 695 ber_memfree( ms->ms_regex_pattern.bv_val ); 696 break; 697 698 default: 699 return -1; 700 } 701 702 ch_free( ms ); 703 return 0; 704 } 705 706 int 707 meta_subtree_destroy( metasubtree_t *ms ) 708 { 709 if ( ms->ms_next ) { 710 meta_subtree_destroy( ms->ms_next ); 711 } 712 713 return meta_subtree_free( ms ); 714 } 715 716 static void 717 meta_filter_free( metafilter_t *mf ) 718 { 719 regfree( &mf->mf_regex ); 720 ber_memfree( mf->mf_regex_pattern.bv_val ); 721 ch_free( mf ); 722 } 723 724 void 725 meta_filter_destroy( metafilter_t *mf ) 726 { 727 if ( mf->mf_next ) 728 meta_filter_destroy( mf->mf_next ); 729 meta_filter_free( mf ); 730 } 731 732 static struct berval st_styles[] = { 733 BER_BVC("subtree"), 734 BER_BVC("children"), 735 BER_BVC("regex") 736 }; 737 738 static int 739 meta_subtree_unparse( 740 ConfigArgs *c, 741 metatarget_t *mt ) 742 { 743 metasubtree_t *ms; 744 struct berval bv, *style; 745 746 if ( !mt->mt_subtree ) 747 return 1; 748 749 /* can only be one of exclude or include */ 750 if (( c->type == LDAP_BACK_CFG_SUBTREE_EX ) ^ mt->mt_subtree_exclude ) 751 return 1; 752 753 bv.bv_val = c->cr_msg; 754 for ( ms=mt->mt_subtree; ms; ms=ms->ms_next ) { 755 if (ms->ms_type == META_ST_SUBTREE) 756 style = &st_styles[0]; 757 else if ( ms->ms_type == META_ST_SUBORDINATE ) 758 style = &st_styles[1]; 759 else if ( ms->ms_type == META_ST_REGEX ) 760 style = &st_styles[2]; 761 else { 762 assert(0); 763 continue; 764 } 765 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), 766 "dn.%s:%s", style->bv_val, ms->ms_dn.bv_val ); 767 value_add_one( &c->rvalue_vals, &bv ); 768 } 769 return 0; 770 } 771 772 static int 773 meta_subtree_config( 774 metatarget_t *mt, 775 ConfigArgs *c ) 776 { 777 meta_st_t type = META_ST_SUBTREE; 778 char *pattern; 779 struct berval ndn = BER_BVNULL; 780 metasubtree_t *ms = NULL; 781 782 if ( c->type == LDAP_BACK_CFG_SUBTREE_EX ) { 783 if ( mt->mt_subtree && !mt->mt_subtree_exclude ) { 784 snprintf( c->cr_msg, sizeof(c->cr_msg), 785 "\"subtree-exclude\" incompatible with previous \"subtree-include\" directives" ); 786 return 1; 787 } 788 789 mt->mt_subtree_exclude = 1; 790 791 } else { 792 if ( mt->mt_subtree && mt->mt_subtree_exclude ) { 793 snprintf( c->cr_msg, sizeof(c->cr_msg), 794 "\"subtree-include\" incompatible with previous \"subtree-exclude\" directives" ); 795 return 1; 796 } 797 } 798 799 pattern = c->argv[1]; 800 if ( strncasecmp( pattern, "dn", STRLENOF( "dn" ) ) == 0 ) { 801 char *style; 802 803 pattern = &pattern[STRLENOF( "dn")]; 804 805 if ( pattern[0] == '.' ) { 806 style = &pattern[1]; 807 808 if ( strncasecmp( style, "subtree", STRLENOF( "subtree" ) ) == 0 ) { 809 type = META_ST_SUBTREE; 810 pattern = &style[STRLENOF( "subtree" )]; 811 812 } else if ( strncasecmp( style, "children", STRLENOF( "children" ) ) == 0 ) { 813 type = META_ST_SUBORDINATE; 814 pattern = &style[STRLENOF( "children" )]; 815 816 } else if ( strncasecmp( style, "sub", STRLENOF( "sub" ) ) == 0 ) { 817 type = META_ST_SUBTREE; 818 pattern = &style[STRLENOF( "sub" )]; 819 820 } else if ( strncasecmp( style, "regex", STRLENOF( "regex" ) ) == 0 ) { 821 type = META_ST_REGEX; 822 pattern = &style[STRLENOF( "regex" )]; 823 824 } else { 825 snprintf( c->cr_msg, sizeof(c->cr_msg), "unknown style in \"dn.<style>\"" ); 826 return 1; 827 } 828 } 829 830 if ( pattern[0] != ':' ) { 831 snprintf( c->cr_msg, sizeof(c->cr_msg), "missing colon after \"dn.<style>\"" ); 832 return 1; 833 } 834 pattern++; 835 } 836 837 switch ( type ) { 838 case META_ST_SUBTREE: 839 case META_ST_SUBORDINATE: { 840 struct berval dn; 841 842 ber_str2bv( pattern, 0, 0, &dn ); 843 if ( dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL ) 844 != LDAP_SUCCESS ) 845 { 846 snprintf( c->cr_msg, sizeof(c->cr_msg), "DN=\"%s\" is invalid", pattern ); 847 return 1; 848 } 849 850 if ( !dnIsSuffix( &ndn, &mt->mt_nsuffix ) ) { 851 snprintf( c->cr_msg, sizeof(c->cr_msg), 852 "DN=\"%s\" is not a subtree of target \"%s\"", 853 pattern, mt->mt_nsuffix.bv_val ); 854 ber_memfree( ndn.bv_val ); 855 return( 1 ); 856 } 857 } break; 858 859 default: 860 /* silence warnings */ 861 break; 862 } 863 864 ms = ch_calloc( sizeof( metasubtree_t ), 1 ); 865 ms->ms_type = type; 866 867 switch ( ms->ms_type ) { 868 case META_ST_SUBTREE: 869 case META_ST_SUBORDINATE: 870 ms->ms_dn = ndn; 871 break; 872 873 case META_ST_REGEX: { 874 int rc; 875 876 rc = regcomp( &ms->ms_regex, pattern, REG_EXTENDED|REG_ICASE ); 877 if ( rc != 0 ) { 878 char regerr[ SLAP_TEXT_BUFLEN ]; 879 880 regerror( rc, &ms->ms_regex, regerr, sizeof(regerr) ); 881 882 snprintf( c->cr_msg, sizeof( c->cr_msg ), 883 "regular expression \"%s\" bad because of %s", 884 pattern, regerr ); 885 ch_free( ms ); 886 return 1; 887 } 888 ber_str2bv( pattern, 0, 1, &ms->ms_regex_pattern ); 889 } break; 890 } 891 892 if ( mt->mt_subtree == NULL ) { 893 mt->mt_subtree = ms; 894 895 } else { 896 metasubtree_t **msp; 897 898 for ( msp = &mt->mt_subtree; *msp; ) { 899 switch ( ms->ms_type ) { 900 case META_ST_SUBTREE: 901 switch ( (*msp)->ms_type ) { 902 case META_ST_SUBTREE: 903 if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) { 904 metasubtree_t *tmp = *msp; 905 Debug( LDAP_DEBUG_CONFIG, 906 "%s: previous rule \"dn.subtree:%s\" is contained in rule \"dn.subtree:%s\" (replaced)\n", 907 c->log, pattern, (*msp)->ms_dn.bv_val ); 908 *msp = (*msp)->ms_next; 909 tmp->ms_next = NULL; 910 meta_subtree_destroy( tmp ); 911 continue; 912 913 } else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) ) { 914 Debug( LDAP_DEBUG_CONFIG, 915 "%s: previous rule \"dn.subtree:%s\" contains rule \"dn.subtree:%s\" (ignored)\n", 916 c->log, (*msp)->ms_dn.bv_val, pattern ); 917 meta_subtree_destroy( ms ); 918 ms = NULL; 919 return( 0 ); 920 } 921 break; 922 923 case META_ST_SUBORDINATE: 924 if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) { 925 metasubtree_t *tmp = *msp; 926 Debug( LDAP_DEBUG_CONFIG, 927 "%s: previous rule \"dn.children:%s\" is contained in rule \"dn.subtree:%s\" (replaced)\n", 928 c->log, pattern, (*msp)->ms_dn.bv_val ); 929 *msp = (*msp)->ms_next; 930 tmp->ms_next = NULL; 931 meta_subtree_destroy( tmp ); 932 continue; 933 934 } else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) && ms->ms_dn.bv_len > (*msp)->ms_dn.bv_len ) { 935 Debug( LDAP_DEBUG_CONFIG, 936 "%s: previous rule \"dn.children:%s\" contains rule \"dn.subtree:%s\" (ignored)\n", 937 c->log, (*msp)->ms_dn.bv_val, pattern ); 938 meta_subtree_destroy( ms ); 939 ms = NULL; 940 return( 0 ); 941 } 942 break; 943 944 case META_ST_REGEX: 945 if ( regexec( &(*msp)->ms_regex, ms->ms_dn.bv_val, 0, NULL, 0 ) == 0 ) { 946 Debug( LDAP_DEBUG_CONFIG, 947 "%s: previous rule \"dn.regex:%s\" may contain rule \"dn.subtree:%s\"\n", 948 c->log, (*msp)->ms_regex_pattern.bv_val, ms->ms_dn.bv_val ); 949 } 950 break; 951 } 952 break; 953 954 case META_ST_SUBORDINATE: 955 switch ( (*msp)->ms_type ) { 956 case META_ST_SUBTREE: 957 if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) { 958 metasubtree_t *tmp = *msp; 959 Debug( LDAP_DEBUG_CONFIG, 960 "%s: previous rule \"dn.children:%s\" is contained in rule \"dn.subtree:%s\" (replaced)\n", 961 c->log, pattern, (*msp)->ms_dn.bv_val ); 962 *msp = (*msp)->ms_next; 963 tmp->ms_next = NULL; 964 meta_subtree_destroy( tmp ); 965 continue; 966 967 } else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) && ms->ms_dn.bv_len > (*msp)->ms_dn.bv_len ) { 968 Debug( LDAP_DEBUG_CONFIG, 969 "%s: previous rule \"dn.children:%s\" contains rule \"dn.subtree:%s\" (ignored)\n", 970 c->log, (*msp)->ms_dn.bv_val, pattern ); 971 meta_subtree_destroy( ms ); 972 ms = NULL; 973 return( 0 ); 974 } 975 break; 976 977 case META_ST_SUBORDINATE: 978 if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) { 979 metasubtree_t *tmp = *msp; 980 Debug( LDAP_DEBUG_CONFIG, 981 "%s: previous rule \"dn.children:%s\" is contained in rule \"dn.children:%s\" (replaced)\n", 982 c->log, pattern, (*msp)->ms_dn.bv_val ); 983 *msp = (*msp)->ms_next; 984 tmp->ms_next = NULL; 985 meta_subtree_destroy( tmp ); 986 continue; 987 988 } else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) ) { 989 Debug( LDAP_DEBUG_CONFIG, 990 "%s: previous rule \"dn.children:%s\" contains rule \"dn.children:%s\" (ignored)\n", 991 c->log, (*msp)->ms_dn.bv_val, pattern ); 992 meta_subtree_destroy( ms ); 993 ms = NULL; 994 return( 0 ); 995 } 996 break; 997 998 case META_ST_REGEX: 999 if ( regexec( &(*msp)->ms_regex, ms->ms_dn.bv_val, 0, NULL, 0 ) == 0 ) { 1000 Debug( LDAP_DEBUG_CONFIG, 1001 "%s: previous rule \"dn.regex:%s\" may contain rule \"dn.subtree:%s\"\n", 1002 c->log, (*msp)->ms_regex_pattern.bv_val, ms->ms_dn.bv_val ); 1003 } 1004 break; 1005 } 1006 break; 1007 1008 case META_ST_REGEX: 1009 switch ( (*msp)->ms_type ) { 1010 case META_ST_SUBTREE: 1011 case META_ST_SUBORDINATE: 1012 if ( regexec( &ms->ms_regex, (*msp)->ms_dn.bv_val, 0, NULL, 0 ) == 0 ) { 1013 Debug( LDAP_DEBUG_CONFIG, 1014 "%s: previous rule \"dn.subtree:%s\" may be contained in rule \"dn.regex:%s\"\n", 1015 c->log, (*msp)->ms_dn.bv_val, ms->ms_regex_pattern.bv_val ); 1016 } 1017 break; 1018 1019 case META_ST_REGEX: 1020 /* no check possible */ 1021 break; 1022 } 1023 break; 1024 } 1025 1026 msp = &(*msp)->ms_next; 1027 } 1028 1029 *msp = ms; 1030 } 1031 1032 return 0; 1033 } 1034 1035 static slap_verbmasks idassert_mode[] = { 1036 { BER_BVC("self"), LDAP_BACK_IDASSERT_SELF }, 1037 { BER_BVC("anonymous"), LDAP_BACK_IDASSERT_ANONYMOUS }, 1038 { BER_BVC("none"), LDAP_BACK_IDASSERT_NOASSERT }, 1039 { BER_BVC("legacy"), LDAP_BACK_IDASSERT_LEGACY }, 1040 { BER_BVNULL, 0 } 1041 }; 1042 1043 static slap_verbmasks tls_mode[] = { 1044 { BER_BVC( "propagate" ), LDAP_BACK_F_TLS_PROPAGATE_MASK }, 1045 { BER_BVC( "try-propagate" ), LDAP_BACK_F_PROPAGATE_TLS }, 1046 { BER_BVC( "start" ), LDAP_BACK_F_TLS_USE_MASK }, 1047 { BER_BVC( "try-start" ), LDAP_BACK_F_USE_TLS }, 1048 { BER_BVC( "ldaps" ), LDAP_BACK_F_TLS_LDAPS }, 1049 { BER_BVC( "none" ), LDAP_BACK_F_NONE }, 1050 { BER_BVNULL, 0 } 1051 }; 1052 1053 static slap_verbmasks t_f_mode[] = { 1054 { BER_BVC( "yes" ), LDAP_BACK_F_T_F }, 1055 { BER_BVC( "discover" ), LDAP_BACK_F_T_F_DISCOVER }, 1056 { BER_BVC( "no" ), LDAP_BACK_F_NONE }, 1057 { BER_BVNULL, 0 } 1058 }; 1059 1060 static slap_verbmasks cancel_mode[] = { 1061 { BER_BVC( "ignore" ), LDAP_BACK_F_CANCEL_IGNORE }, 1062 { BER_BVC( "exop" ), LDAP_BACK_F_CANCEL_EXOP }, 1063 { BER_BVC( "exop-discover" ), LDAP_BACK_F_CANCEL_EXOP_DISCOVER }, 1064 { BER_BVC( "abandon" ), LDAP_BACK_F_CANCEL_ABANDON }, 1065 { BER_BVNULL, 0 } 1066 }; 1067 1068 static slap_verbmasks onerr_mode[] = { 1069 { BER_BVC( "stop" ), META_BACK_F_ONERR_STOP }, 1070 { BER_BVC( "report" ), META_BACK_F_ONERR_REPORT }, 1071 { BER_BVC( "continue" ), LDAP_BACK_F_NONE }, 1072 { BER_BVNULL, 0 } 1073 }; 1074 1075 /* see enum in slap.h */ 1076 static slap_cf_aux_table timeout_table[] = { 1077 { BER_BVC("bind="), SLAP_OP_BIND * sizeof( time_t ), 'u', 0, NULL }, 1078 /* unbind makes no sense */ 1079 { BER_BVC("add="), SLAP_OP_ADD * sizeof( time_t ), 'u', 0, NULL }, 1080 { BER_BVC("delete="), SLAP_OP_DELETE * sizeof( time_t ), 'u', 0, NULL }, 1081 { BER_BVC("modrdn="), SLAP_OP_MODRDN * sizeof( time_t ), 'u', 0, NULL }, 1082 { BER_BVC("modify="), SLAP_OP_MODIFY * sizeof( time_t ), 'u', 0, NULL }, 1083 { BER_BVC("compare="), SLAP_OP_COMPARE * sizeof( time_t ), 'u', 0, NULL }, 1084 { BER_BVC("search="), SLAP_OP_SEARCH * sizeof( time_t ), 'u', 0, NULL }, 1085 /* abandon makes little sense */ 1086 #if 0 /* not implemented yet */ 1087 { BER_BVC("extended="), SLAP_OP_EXTENDED * sizeof( time_t ), 'u', 0, NULL }, 1088 #endif 1089 { BER_BVNULL, 0, 0, 0, NULL } 1090 }; 1091 1092 static int 1093 meta_cf_cleanup( ConfigArgs *c ) 1094 { 1095 metainfo_t *mi = ( metainfo_t * )c->be->be_private; 1096 metatarget_t *mt = c->ca_private; 1097 1098 return meta_target_finish( mi, mt, c->log, c->cr_msg, sizeof( c->cr_msg )); 1099 } 1100 1101 static int 1102 meta_back_cf_gen( ConfigArgs *c ) 1103 { 1104 metainfo_t *mi = ( metainfo_t * )c->be->be_private; 1105 metatarget_t *mt; 1106 metacommon_t *mc; 1107 1108 int i, rc = 0; 1109 1110 assert( mi != NULL ); 1111 1112 if ( c->op == SLAP_CONFIG_EMIT || c->op == LDAP_MOD_DELETE ) { 1113 if ( !mi ) 1114 return 1; 1115 1116 if ( c->table == Cft_Database ) { 1117 mt = NULL; 1118 mc = &mi->mi_mc; 1119 } else { 1120 mt = c->ca_private; 1121 mc = &mt->mt_mc; 1122 } 1123 } 1124 1125 if ( c->op == SLAP_CONFIG_EMIT ) { 1126 struct berval bv = BER_BVNULL; 1127 1128 switch( c->type ) { 1129 /* Base attrs */ 1130 case LDAP_BACK_CFG_CONN_TTL: 1131 if ( mi->mi_conn_ttl == 0 ) { 1132 return 1; 1133 } else { 1134 char buf[ SLAP_TEXT_BUFLEN ]; 1135 1136 lutil_unparse_time( buf, sizeof( buf ), mi->mi_conn_ttl ); 1137 ber_str2bv( buf, 0, 0, &bv ); 1138 value_add_one( &c->rvalue_vals, &bv ); 1139 } 1140 break; 1141 1142 case LDAP_BACK_CFG_DNCACHE_TTL: 1143 if ( mi->mi_cache.ttl == META_DNCACHE_DISABLED ) { 1144 return 1; 1145 } else if ( mi->mi_cache.ttl == META_DNCACHE_FOREVER ) { 1146 BER_BVSTR( &bv, "forever" ); 1147 } else { 1148 char buf[ SLAP_TEXT_BUFLEN ]; 1149 1150 lutil_unparse_time( buf, sizeof( buf ), mi->mi_cache.ttl ); 1151 ber_str2bv( buf, 0, 0, &bv ); 1152 } 1153 value_add_one( &c->rvalue_vals, &bv ); 1154 break; 1155 1156 case LDAP_BACK_CFG_IDLE_TIMEOUT: 1157 if ( mi->mi_idle_timeout == 0 ) { 1158 return 1; 1159 } else { 1160 char buf[ SLAP_TEXT_BUFLEN ]; 1161 1162 lutil_unparse_time( buf, sizeof( buf ), mi->mi_idle_timeout ); 1163 ber_str2bv( buf, 0, 0, &bv ); 1164 value_add_one( &c->rvalue_vals, &bv ); 1165 } 1166 break; 1167 1168 case LDAP_BACK_CFG_ONERR: 1169 enum_to_verb( onerr_mode, mi->mi_flags & META_BACK_F_ONERR_MASK, &bv ); 1170 if ( BER_BVISNULL( &bv )) { 1171 rc = 1; 1172 } else { 1173 value_add_one( &c->rvalue_vals, &bv ); 1174 } 1175 break; 1176 1177 case LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER: 1178 c->value_int = META_BACK_DEFER_ROOTDN_BIND( mi ); 1179 break; 1180 1181 case LDAP_BACK_CFG_SINGLECONN: 1182 c->value_int = LDAP_BACK_SINGLECONN( mi ); 1183 break; 1184 1185 case LDAP_BACK_CFG_USETEMP: 1186 c->value_int = LDAP_BACK_USE_TEMPORARIES( mi ); 1187 break; 1188 1189 case LDAP_BACK_CFG_CONNPOOLMAX: 1190 c->value_int = mi->mi_conn_priv_max; 1191 break; 1192 1193 /* common attrs */ 1194 case LDAP_BACK_CFG_BIND_TIMEOUT: 1195 if ( mc->mc_bind_timeout.tv_sec == 0 && 1196 mc->mc_bind_timeout.tv_usec == 0 ) { 1197 return 1; 1198 } else { 1199 c->value_ulong = mc->mc_bind_timeout.tv_sec * 1000000UL + 1200 mc->mc_bind_timeout.tv_usec; 1201 } 1202 break; 1203 1204 case LDAP_BACK_CFG_CANCEL: { 1205 slap_mask_t mask = LDAP_BACK_F_CANCEL_MASK2; 1206 1207 if ( mt && META_BACK_TGT_CANCEL_DISCOVER( mt ) ) { 1208 mask &= ~LDAP_BACK_F_CANCEL_EXOP; 1209 } 1210 enum_to_verb( cancel_mode, (mc->mc_flags & mask), &bv ); 1211 if ( BER_BVISNULL( &bv ) ) { 1212 /* there's something wrong... */ 1213 assert( 0 ); 1214 rc = 1; 1215 1216 } else { 1217 value_add_one( &c->rvalue_vals, &bv ); 1218 } 1219 } break; 1220 1221 case LDAP_BACK_CFG_CHASE: 1222 c->value_int = META_BACK_CMN_CHASE_REFERRALS(mc); 1223 break; 1224 1225 #ifdef SLAPD_META_CLIENT_PR 1226 case LDAP_BACK_CFG_CLIENT_PR: 1227 if ( mc->mc_ps == META_CLIENT_PR_DISABLE ) { 1228 return 1; 1229 } else if ( mc->mc_ps == META_CLIENT_PR_ACCEPT_UNSOLICITED ) { 1230 BER_BVSTR( &bv, "accept-unsolicited" ); 1231 } else { 1232 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), "%d", mc->mc_ps ); 1233 bv.bv_val = c->cr_msg; 1234 } 1235 value_add_one( &c->rvalue_vals, &bv ); 1236 break; 1237 #endif /* SLAPD_META_CLIENT_PR */ 1238 1239 case LDAP_BACK_CFG_DEFAULT_T: 1240 if ( mt || mi->mi_defaulttarget == META_DEFAULT_TARGET_NONE ) 1241 return 1; 1242 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), "%d", mi->mi_defaulttarget ); 1243 bv.bv_val = c->cr_msg; 1244 value_add_one( &c->rvalue_vals, &bv ); 1245 break; 1246 1247 case LDAP_BACK_CFG_NETWORK_TIMEOUT: 1248 if ( mc->mc_network_timeout == 0 ) { 1249 return 1; 1250 } else { 1251 char buf[ SLAP_TEXT_BUFLEN ]; 1252 lutil_unparse_time( buf, sizeof( buf ), mc->mc_network_timeout ); 1253 ber_str2bv( buf, 0, 0, &bv ); 1254 value_add_one( &c->rvalue_vals, &bv ); 1255 } 1256 break; 1257 1258 case LDAP_BACK_CFG_NOREFS: 1259 c->value_int = META_BACK_CMN_NOREFS(mc); 1260 break; 1261 1262 case LDAP_BACK_CFG_NOUNDEFFILTER: 1263 c->value_int = META_BACK_CMN_NOUNDEFFILTER(mc); 1264 break; 1265 1266 case LDAP_BACK_CFG_NRETRIES: 1267 if ( mc->mc_nretries == META_RETRY_FOREVER ) { 1268 BER_BVSTR( &bv, "forever" ); 1269 } else if ( mc->mc_nretries == META_RETRY_NEVER ) { 1270 BER_BVSTR( &bv, "never" ); 1271 } else { 1272 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), "%d", 1273 mc->mc_nretries ); 1274 bv.bv_val = c->cr_msg; 1275 } 1276 value_add_one( &c->rvalue_vals, &bv ); 1277 break; 1278 1279 case LDAP_BACK_CFG_QUARANTINE: 1280 if ( !META_BACK_CMN_QUARANTINE( mc )) { 1281 rc = 1; 1282 break; 1283 } 1284 rc = mi->mi_ldap_extra->retry_info_unparse( &mc->mc_quarantine, &bv ); 1285 if ( rc == 0 ) { 1286 ber_bvarray_add( &c->rvalue_vals, &bv ); 1287 } 1288 break; 1289 1290 case LDAP_BACK_CFG_REBIND: 1291 c->value_int = META_BACK_CMN_SAVECRED(mc); 1292 break; 1293 1294 case LDAP_BACK_CFG_TIMEOUT: 1295 for ( i = 0; i < SLAP_OP_LAST; i++ ) { 1296 if ( mc->mc_timeout[ i ] != 0 ) { 1297 break; 1298 } 1299 } 1300 1301 if ( i == SLAP_OP_LAST ) { 1302 return 1; 1303 } 1304 1305 BER_BVZERO( &bv ); 1306 slap_cf_aux_table_unparse( mc->mc_timeout, &bv, timeout_table ); 1307 1308 if ( BER_BVISNULL( &bv ) ) { 1309 return 1; 1310 } 1311 1312 for ( i = 0; isspace( (unsigned char) bv.bv_val[ i ] ); i++ ) 1313 /* count spaces */ ; 1314 1315 if ( i ) { 1316 bv.bv_len -= i; 1317 AC_MEMCPY( bv.bv_val, &bv.bv_val[ i ], 1318 bv.bv_len + 1 ); 1319 } 1320 1321 ber_bvarray_add( &c->rvalue_vals, &bv ); 1322 break; 1323 1324 case LDAP_BACK_CFG_VERSION: 1325 if ( mc->mc_version == 0 ) 1326 return 1; 1327 c->value_int = mc->mc_version; 1328 break; 1329 1330 #ifdef SLAP_CONTROL_X_SESSION_TRACKING 1331 case LDAP_BACK_CFG_ST_REQUEST: 1332 c->value_int = META_BACK_CMN_ST_REQUEST( mc ); 1333 break; 1334 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 1335 1336 case LDAP_BACK_CFG_T_F: 1337 enum_to_verb( t_f_mode, (mc->mc_flags & LDAP_BACK_F_T_F_MASK2), &bv ); 1338 if ( BER_BVISNULL( &bv ) ) { 1339 /* there's something wrong... */ 1340 assert( 0 ); 1341 rc = 1; 1342 1343 } else { 1344 value_add_one( &c->rvalue_vals, &bv ); 1345 } 1346 break; 1347 1348 case LDAP_BACK_CFG_TLS: { 1349 struct berval bc = BER_BVNULL, bv2; 1350 1351 if (( mc->mc_flags & LDAP_BACK_F_TLS_MASK ) == LDAP_BACK_F_NONE ) { 1352 rc = 1; 1353 break; 1354 } 1355 enum_to_verb( tls_mode, ( mc->mc_flags & LDAP_BACK_F_TLS_MASK ), &bv ); 1356 assert( !BER_BVISNULL( &bv ) ); 1357 1358 if ( mt ) { 1359 bindconf_tls_unparse( &mt->mt_tls, &bc ); 1360 } 1361 1362 if ( !BER_BVISEMPTY( &bc )) { 1363 bv2.bv_len = bv.bv_len + bc.bv_len + 1; 1364 bv2.bv_val = ch_malloc( bv2.bv_len + 1 ); 1365 strcpy( bv2.bv_val, bv.bv_val ); 1366 bv2.bv_val[bv.bv_len] = ' '; 1367 strcpy( &bv2.bv_val[bv.bv_len + 1], bc.bv_val ); 1368 ber_memfree( bc.bv_val ); 1369 ber_bvarray_add( &c->rvalue_vals, &bv2 ); 1370 } else { 1371 value_add_one( &c->rvalue_vals, &bv ); 1372 } 1373 } break; 1374 1375 /* target attrs */ 1376 case LDAP_BACK_CFG_URI: { 1377 char *p2, *p1 = strchr( mt->mt_uri, ' ' ); 1378 bv.bv_len = strlen( mt->mt_uri ) + 3 + mt->mt_psuffix.bv_len; 1379 bv.bv_val = ch_malloc( bv.bv_len + 1 ); 1380 p2 = bv.bv_val; 1381 *p2++ = '"'; 1382 if ( p1 ) { 1383 p2 = lutil_strncopy( p2, mt->mt_uri, p1 - mt->mt_uri ); 1384 } else { 1385 p2 = lutil_strcopy( p2, mt->mt_uri ); 1386 } 1387 *p2++ = '/'; 1388 p2 = lutil_strcopy( p2, mt->mt_psuffix.bv_val ); 1389 *p2++ = '"'; 1390 if ( p1 ) { 1391 strcpy( p2, p1 ); 1392 } 1393 ber_bvarray_add( &c->rvalue_vals, &bv ); 1394 } break; 1395 1396 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: { 1397 BerVarray *bvp; 1398 int i; 1399 struct berval bv = BER_BVNULL; 1400 char buf[SLAP_TEXT_BUFLEN]; 1401 1402 bvp = &mt->mt_idassert_authz; 1403 if ( *bvp == NULL ) { 1404 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_AUTHZ_ALL ) 1405 { 1406 BER_BVSTR( &bv, "*" ); 1407 value_add_one( &c->rvalue_vals, &bv ); 1408 1409 } else { 1410 rc = 1; 1411 } 1412 break; 1413 } 1414 1415 for ( i = 0; !BER_BVISNULL( &((*bvp)[ i ]) ); i++ ) { 1416 char *ptr; 1417 int len = snprintf( buf, sizeof( buf ), SLAP_X_ORDERED_FMT, i ); 1418 bv.bv_len = ((*bvp)[ i ]).bv_len + len; 1419 bv.bv_val = ch_realloc( bv.bv_val, bv.bv_len + 1 ); 1420 ptr = bv.bv_val; 1421 ptr = lutil_strcopy( ptr, buf ); 1422 ptr = lutil_strncopy( ptr, ((*bvp)[ i ]).bv_val, ((*bvp)[ i ]).bv_len ); 1423 value_add_one( &c->rvalue_vals, &bv ); 1424 } 1425 if ( bv.bv_val ) { 1426 ber_memfree( bv.bv_val ); 1427 } 1428 break; 1429 } 1430 1431 case LDAP_BACK_CFG_IDASSERT_BIND: { 1432 int i; 1433 struct berval bc = BER_BVNULL; 1434 char *ptr; 1435 1436 if ( mt->mt_idassert_authmethod == LDAP_AUTH_NONE ) { 1437 return 1; 1438 } else { 1439 ber_len_t len; 1440 1441 switch ( mt->mt_idassert_mode ) { 1442 case LDAP_BACK_IDASSERT_OTHERID: 1443 case LDAP_BACK_IDASSERT_OTHERDN: 1444 break; 1445 1446 default: { 1447 struct berval mode = BER_BVNULL; 1448 1449 enum_to_verb( idassert_mode, mt->mt_idassert_mode, &mode ); 1450 if ( BER_BVISNULL( &mode ) ) { 1451 /* there's something wrong... */ 1452 assert( 0 ); 1453 rc = 1; 1454 1455 } else { 1456 bv.bv_len = STRLENOF( "mode=" ) + mode.bv_len; 1457 bv.bv_val = ch_malloc( bv.bv_len + 1 ); 1458 1459 ptr = lutil_strcopy( bv.bv_val, "mode=" ); 1460 ptr = lutil_strcopy( ptr, mode.bv_val ); 1461 } 1462 break; 1463 } 1464 } 1465 1466 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) { 1467 len = bv.bv_len + STRLENOF( "authz=native" ); 1468 1469 if ( !BER_BVISEMPTY( &bv ) ) { 1470 len += STRLENOF( " " ); 1471 } 1472 1473 bv.bv_val = ch_realloc( bv.bv_val, len + 1 ); 1474 1475 ptr = &bv.bv_val[ bv.bv_len ]; 1476 1477 if ( !BER_BVISEMPTY( &bv ) ) { 1478 ptr = lutil_strcopy( ptr, " " ); 1479 } 1480 1481 (void)lutil_strcopy( ptr, "authz=native" ); 1482 } 1483 1484 len = bv.bv_len + STRLENOF( "flags=non-prescriptive,override,obsolete-encoding-workaround,proxy-authz-non-critical,dn-authzid" ); 1485 /* flags */ 1486 if ( !BER_BVISEMPTY( &bv ) ) { 1487 len += STRLENOF( " " ); 1488 } 1489 1490 bv.bv_val = ch_realloc( bv.bv_val, len + 1 ); 1491 1492 ptr = &bv.bv_val[ bv.bv_len ]; 1493 1494 if ( !BER_BVISEMPTY( &bv ) ) { 1495 ptr = lutil_strcopy( ptr, " " ); 1496 } 1497 1498 ptr = lutil_strcopy( ptr, "flags=" ); 1499 1500 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) { 1501 ptr = lutil_strcopy( ptr, "prescriptive" ); 1502 } else { 1503 ptr = lutil_strcopy( ptr, "non-prescriptive" ); 1504 } 1505 1506 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) { 1507 ptr = lutil_strcopy( ptr, ",override" ); 1508 } 1509 1510 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) { 1511 ptr = lutil_strcopy( ptr, ",obsolete-proxy-authz" ); 1512 1513 } else if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) { 1514 ptr = lutil_strcopy( ptr, ",obsolete-encoding-workaround" ); 1515 } 1516 1517 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PROXYAUTHZ_CRITICAL ) { 1518 ptr = lutil_strcopy( ptr, ",proxy-authz-critical" ); 1519 1520 } else { 1521 ptr = lutil_strcopy( ptr, ",proxy-authz-non-critical" ); 1522 } 1523 1524 #ifdef SLAP_AUTH_DN 1525 switch ( mt->mt_idassert_flags & LDAP_BACK_AUTH_DN_MASK ) { 1526 case LDAP_BACK_AUTH_DN_AUTHZID: 1527 ptr = lutil_strcopy( ptr, ",dn-authzid" ); 1528 break; 1529 1530 case LDAP_BACK_AUTH_DN_WHOAMI: 1531 ptr = lutil_strcopy( ptr, ",dn-whoami" ); 1532 break; 1533 1534 default: 1535 #if 0 /* implicit */ 1536 ptr = lutil_strcopy( ptr, ",dn-none" ); 1537 #endif 1538 break; 1539 } 1540 #endif 1541 1542 bv.bv_len = ( ptr - bv.bv_val ); 1543 /* end-of-flags */ 1544 } 1545 1546 bindconf_unparse( &mt->mt_idassert.si_bc, &bc ); 1547 1548 if ( !BER_BVISNULL( &bv ) ) { 1549 ber_len_t len = bv.bv_len + bc.bv_len; 1550 1551 bv.bv_val = ch_realloc( bv.bv_val, len + 1 ); 1552 1553 assert( bc.bv_val[ 0 ] == ' ' ); 1554 1555 ptr = lutil_strcopy( &bv.bv_val[ bv.bv_len ], bc.bv_val ); 1556 free( bc.bv_val ); 1557 bv.bv_len = ptr - bv.bv_val; 1558 1559 } else { 1560 for ( i = 0; isspace( (unsigned char) bc.bv_val[ i ] ); i++ ) 1561 /* count spaces */ ; 1562 1563 if ( i ) { 1564 bc.bv_len -= i; 1565 AC_MEMCPY( bc.bv_val, &bc.bv_val[ i ], bc.bv_len + 1 ); 1566 } 1567 1568 bv = bc; 1569 } 1570 1571 ber_bvarray_add( &c->rvalue_vals, &bv ); 1572 1573 break; 1574 } 1575 1576 case LDAP_BACK_CFG_SUFFIXM: /* unused */ 1577 case LDAP_BACK_CFG_REWRITE: 1578 if ( mt->mt_rwmap.rwm_bva_rewrite == NULL ) { 1579 rc = 1; 1580 } else { 1581 rc = slap_bv_x_ordered_unparse( mt->mt_rwmap.rwm_bva_rewrite, &c->rvalue_vals ); 1582 } 1583 break; 1584 1585 case LDAP_BACK_CFG_MAP: 1586 if ( mt->mt_rwmap.rwm_bva_map == NULL ) { 1587 rc = 1; 1588 } else { 1589 rc = slap_bv_x_ordered_unparse( mt->mt_rwmap.rwm_bva_map, &c->rvalue_vals ); 1590 } 1591 break; 1592 1593 case LDAP_BACK_CFG_SUBTREE_EX: 1594 case LDAP_BACK_CFG_SUBTREE_IN: 1595 rc = meta_subtree_unparse( c, mt ); 1596 break; 1597 1598 case LDAP_BACK_CFG_FILTER: 1599 if ( mt->mt_filter == NULL ) { 1600 rc = 1; 1601 } else { 1602 metafilter_t *mf; 1603 for ( mf = mt->mt_filter; mf; mf = mf->mf_next ) 1604 value_add_one( &c->rvalue_vals, &mf->mf_regex_pattern ); 1605 } 1606 break; 1607 1608 /* replaced by idassert */ 1609 case LDAP_BACK_CFG_PSEUDOROOTDN: 1610 case LDAP_BACK_CFG_PSEUDOROOTPW: 1611 rc = 1; 1612 break; 1613 1614 case LDAP_BACK_CFG_KEEPALIVE: { 1615 struct berval bv; 1616 char buf[AC_LINE_MAX]; 1617 bv.bv_len = AC_LINE_MAX; 1618 bv.bv_val = &buf[0]; 1619 slap_keepalive_parse(&bv, &mt->mt_tls.sb_keepalive, 0, 0, 1); 1620 value_add_one( &c->rvalue_vals, &bv ); 1621 break; 1622 } 1623 1624 case LDAP_BACK_CFG_TCP_USER_TIMEOUT: 1625 c->value_uint = mt->mt_tls.sb_tcp_user_timeout; 1626 break; 1627 1628 1629 default: 1630 rc = 1; 1631 } 1632 return rc; 1633 } else if ( c->op == LDAP_MOD_DELETE ) { 1634 switch( c->type ) { 1635 /* Base attrs */ 1636 case LDAP_BACK_CFG_CONN_TTL: 1637 mi->mi_conn_ttl = 0; 1638 break; 1639 1640 case LDAP_BACK_CFG_DNCACHE_TTL: 1641 mi->mi_cache.ttl = META_DNCACHE_DISABLED; 1642 break; 1643 1644 case LDAP_BACK_CFG_IDLE_TIMEOUT: 1645 mi->mi_idle_timeout = 0; 1646 break; 1647 1648 case LDAP_BACK_CFG_ONERR: 1649 mi->mi_flags &= ~META_BACK_F_ONERR_MASK; 1650 break; 1651 1652 case LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER: 1653 mi->mi_flags &= ~META_BACK_F_DEFER_ROOTDN_BIND; 1654 break; 1655 1656 case LDAP_BACK_CFG_SINGLECONN: 1657 mi->mi_flags &= ~LDAP_BACK_F_SINGLECONN; 1658 break; 1659 1660 case LDAP_BACK_CFG_USETEMP: 1661 mi->mi_flags &= ~LDAP_BACK_F_USE_TEMPORARIES; 1662 break; 1663 1664 case LDAP_BACK_CFG_CONNPOOLMAX: 1665 mi->mi_conn_priv_max = LDAP_BACK_CONN_PRIV_MIN; 1666 break; 1667 1668 /* common attrs */ 1669 case LDAP_BACK_CFG_BIND_TIMEOUT: 1670 mc->mc_bind_timeout.tv_sec = 0; 1671 mc->mc_bind_timeout.tv_usec = 0; 1672 break; 1673 1674 case LDAP_BACK_CFG_CANCEL: 1675 mc->mc_flags &= ~LDAP_BACK_F_CANCEL_MASK2; 1676 break; 1677 1678 case LDAP_BACK_CFG_CHASE: 1679 mc->mc_flags &= ~LDAP_BACK_F_CHASE_REFERRALS; 1680 break; 1681 1682 #ifdef SLAPD_META_CLIENT_PR 1683 case LDAP_BACK_CFG_CLIENT_PR: 1684 mc->mc_ps = META_CLIENT_PR_DISABLE; 1685 break; 1686 #endif /* SLAPD_META_CLIENT_PR */ 1687 1688 case LDAP_BACK_CFG_DEFAULT_T: 1689 mi->mi_defaulttarget = META_DEFAULT_TARGET_NONE; 1690 break; 1691 1692 case LDAP_BACK_CFG_NETWORK_TIMEOUT: 1693 mc->mc_network_timeout = 0; 1694 break; 1695 1696 case LDAP_BACK_CFG_NOREFS: 1697 mc->mc_flags &= ~LDAP_BACK_F_NOREFS; 1698 break; 1699 1700 case LDAP_BACK_CFG_NOUNDEFFILTER: 1701 mc->mc_flags &= ~LDAP_BACK_F_NOUNDEFFILTER; 1702 break; 1703 1704 case LDAP_BACK_CFG_NRETRIES: 1705 mc->mc_nretries = META_RETRY_DEFAULT; 1706 break; 1707 1708 case LDAP_BACK_CFG_QUARANTINE: 1709 if ( META_BACK_CMN_QUARANTINE( mc )) { 1710 mi->mi_ldap_extra->retry_info_destroy( &mc->mc_quarantine ); 1711 mc->mc_flags &= ~LDAP_BACK_F_QUARANTINE; 1712 if ( mc == &mt->mt_mc ) { 1713 ldap_pvt_thread_mutex_destroy( &mt->mt_quarantine_mutex ); 1714 mt->mt_isquarantined = 0; 1715 } 1716 } 1717 break; 1718 1719 case LDAP_BACK_CFG_REBIND: 1720 mc->mc_flags &= ~LDAP_BACK_F_SAVECRED; 1721 break; 1722 1723 case LDAP_BACK_CFG_TIMEOUT: 1724 for ( i = 0; i < SLAP_OP_LAST; i++ ) { 1725 mc->mc_timeout[ i ] = 0; 1726 } 1727 break; 1728 1729 case LDAP_BACK_CFG_VERSION: 1730 mc->mc_version = 0; 1731 break; 1732 1733 #ifdef SLAP_CONTROL_X_SESSION_TRACKING 1734 case LDAP_BACK_CFG_ST_REQUEST: 1735 mc->mc_flags &= ~LDAP_BACK_F_ST_REQUEST; 1736 break; 1737 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 1738 1739 case LDAP_BACK_CFG_T_F: 1740 mc->mc_flags &= ~LDAP_BACK_F_T_F_MASK2; 1741 break; 1742 1743 case LDAP_BACK_CFG_TLS: 1744 mc->mc_flags &= ~LDAP_BACK_F_TLS_MASK; 1745 if ( mt ) 1746 bindconf_free( &mt->mt_tls ); 1747 break; 1748 1749 /* target attrs */ 1750 case LDAP_BACK_CFG_URI: 1751 if ( mt->mt_uri ) { 1752 ch_free( mt->mt_uri ); 1753 mt->mt_uri = NULL; 1754 } 1755 /* FIXME: should have a way to close all cached 1756 * connections associated with this target. 1757 */ 1758 break; 1759 1760 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: { 1761 BerVarray *bvp; 1762 1763 bvp = &mt->mt_idassert_authz; 1764 if ( c->valx < 0 ) { 1765 if ( *bvp != NULL ) { 1766 ber_bvarray_free( *bvp ); 1767 *bvp = NULL; 1768 } 1769 1770 } else { 1771 if ( *bvp == NULL ) { 1772 rc = 1; 1773 break; 1774 } 1775 1776 for ( i = 0; !BER_BVISNULL( &((*bvp)[ i ]) ); i++ ) 1777 ; 1778 1779 if ( i >= c->valx ) { 1780 rc = 1; 1781 break; 1782 } 1783 ber_memfree( ((*bvp)[ c->valx ]).bv_val ); 1784 for ( i = c->valx; !BER_BVISNULL( &((*bvp)[ i + 1 ]) ); i++ ) { 1785 (*bvp)[ i ] = (*bvp)[ i + 1 ]; 1786 } 1787 BER_BVZERO( &((*bvp)[ i ]) ); 1788 } 1789 } break; 1790 1791 case LDAP_BACK_CFG_IDASSERT_BIND: 1792 bindconf_free( &mt->mt_idassert.si_bc ); 1793 memset( &mt->mt_idassert, 0, sizeof( slap_idassert_t ) ); 1794 break; 1795 1796 case LDAP_BACK_CFG_SUFFIXM: /* unused */ 1797 case LDAP_BACK_CFG_REWRITE: 1798 { 1799 if ( c->valx >= 0 ) { 1800 int i; 1801 1802 for ( i = 0; !BER_BVISNULL( &mt->mt_rwmap.rwm_bva_rewrite[ i ] ); i++ ); 1803 1804 if ( c->valx >= i ) { 1805 rc = 1; 1806 break; 1807 } 1808 1809 ber_memfree( mt->mt_rwmap.rwm_bva_rewrite[ c->valx ].bv_val ); 1810 for ( i = c->valx; !BER_BVISNULL( &mt->mt_rwmap.rwm_bva_rewrite[ i + 1 ] ); i++ ) 1811 { 1812 mt->mt_rwmap.rwm_bva_rewrite[ i ] = mt->mt_rwmap.rwm_bva_rewrite[ i + 1 ]; 1813 } 1814 BER_BVZERO( &mt->mt_rwmap.rwm_bva_rewrite[ i ] ); 1815 1816 rewrite_info_delete( &mt->mt_rwmap.rwm_rw ); 1817 assert( mt->mt_rwmap.rwm_rw == NULL ); 1818 1819 rc = meta_rwi_init( &mt->mt_rwmap.rwm_rw ); 1820 1821 for ( i = 0; !BER_BVISNULL( &mt->mt_rwmap.rwm_bva_rewrite[ i ] ); i++ ) 1822 { 1823 ConfigArgs ca = { 0 }; 1824 1825 ca.line = mt->mt_rwmap.rwm_bva_rewrite[ i ].bv_val; 1826 init_config_argv( &ca ); 1827 config_parse_ldif( &ca ); 1828 1829 if ( !strcasecmp( ca.argv[0], "suffixmassage" )) { 1830 rc = meta_suffixm_config( &ca, ca.argc, ca.argv, mt ); 1831 } else { 1832 rc = rewrite_parse( mt->mt_rwmap.rwm_rw, 1833 c->fname, c->lineno, ca.argc, ca.argv ); 1834 } 1835 1836 1837 ch_free( ca.tline ); 1838 ch_free( ca.argv ); 1839 1840 assert( rc == 0 ); 1841 } 1842 1843 } else if ( mt->mt_rwmap.rwm_rw != NULL ) { 1844 if ( mt->mt_rwmap.rwm_bva_rewrite ) { 1845 ber_bvarray_free( mt->mt_rwmap.rwm_bva_rewrite ); 1846 mt->mt_rwmap.rwm_bva_rewrite = NULL; 1847 } 1848 if ( mt->mt_rwmap.rwm_rw ) 1849 rewrite_info_delete( &mt->mt_rwmap.rwm_rw ); 1850 1851 meta_rwi_init( &mt->mt_rwmap.rwm_rw ); 1852 } 1853 } 1854 break; 1855 1856 case LDAP_BACK_CFG_MAP: 1857 if ( mt->mt_rwmap.rwm_bva_map ) { 1858 ber_bvarray_free( mt->mt_rwmap.rwm_bva_map ); 1859 mt->mt_rwmap.rwm_bva_map = NULL; 1860 } 1861 meta_back_map_free( &mt->mt_rwmap.rwm_oc ); 1862 meta_back_map_free( &mt->mt_rwmap.rwm_at ); 1863 mt->mt_rwmap.rwm_oc.drop_missing = 0; 1864 mt->mt_rwmap.rwm_at.drop_missing = 0; 1865 break; 1866 1867 case LDAP_BACK_CFG_SUBTREE_EX: 1868 case LDAP_BACK_CFG_SUBTREE_IN: 1869 /* can only be one of exclude or include */ 1870 if (( c->type == LDAP_BACK_CFG_SUBTREE_EX ) ^ mt->mt_subtree_exclude ) { 1871 rc = 1; 1872 break; 1873 } 1874 if ( c->valx < 0 ) { 1875 meta_subtree_destroy( mt->mt_subtree ); 1876 mt->mt_subtree = NULL; 1877 } else { 1878 metasubtree_t *ms, **mprev; 1879 for (i=0, mprev = &mt->mt_subtree, ms = *mprev; ms; ms = *mprev) { 1880 if ( i == c->valx ) { 1881 *mprev = ms->ms_next; 1882 meta_subtree_free( ms ); 1883 break; 1884 } 1885 i++; 1886 mprev = &ms->ms_next; 1887 } 1888 if ( i != c->valx ) 1889 rc = 1; 1890 } 1891 break; 1892 1893 case LDAP_BACK_CFG_FILTER: 1894 if ( c->valx < 0 ) { 1895 meta_filter_destroy( mt->mt_filter ); 1896 mt->mt_filter = NULL; 1897 } else { 1898 metafilter_t *mf, **mprev; 1899 for (i=0, mprev = &mt->mt_filter, mf = *mprev; mf; mf = *mprev) { 1900 if ( i == c->valx ) { 1901 *mprev = mf->mf_next; 1902 meta_filter_free( mf ); 1903 break; 1904 } 1905 i++; 1906 mprev = &mf->mf_next; 1907 } 1908 if ( i != c->valx ) 1909 rc = 1; 1910 } 1911 break; 1912 1913 case LDAP_BACK_CFG_KEEPALIVE: 1914 mt->mt_tls.sb_keepalive.sk_idle = 0; 1915 mt->mt_tls.sb_keepalive.sk_probes = 0; 1916 mt->mt_tls.sb_keepalive.sk_interval = 0; 1917 break; 1918 1919 case LDAP_BACK_CFG_TCP_USER_TIMEOUT: 1920 mt->mt_tls.sb_tcp_user_timeout = 0; 1921 break; 1922 1923 default: 1924 rc = 1; 1925 break; 1926 } 1927 1928 return rc; 1929 } 1930 1931 if ( c->op == SLAP_CONFIG_ADD ) { 1932 if ( c->type >= LDAP_BACK_CFG_LAST_BASE ) { 1933 /* exclude CFG_URI from this check */ 1934 if ( c->type > LDAP_BACK_CFG_LAST_BOTH ) { 1935 if ( !mi->mi_ntargets ) { 1936 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1937 "need \"uri\" directive first" ); 1938 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1939 return 1; 1940 } 1941 } 1942 if ( mi->mi_ntargets ) { 1943 mt = mi->mi_targets[ mi->mi_ntargets-1 ]; 1944 mc = &mt->mt_mc; 1945 } else { 1946 mt = NULL; 1947 mc = &mi->mi_mc; 1948 } 1949 } 1950 } else { 1951 if ( c->table == Cft_Database ) { 1952 mt = NULL; 1953 mc = &mi->mi_mc; 1954 } else { 1955 mt = c->ca_private; 1956 if ( mt ) 1957 mc = &mt->mt_mc; 1958 else 1959 mc = NULL; 1960 } 1961 } 1962 1963 switch( c->type ) { 1964 case LDAP_BACK_CFG_URI: { 1965 LDAPURLDesc *ludp; 1966 struct berval dn; 1967 int j; 1968 1969 char **uris = NULL; 1970 1971 if ( c->be->be_nsuffix == NULL ) { 1972 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1973 "the suffix must be defined before any target" ); 1974 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1975 return 1; 1976 } 1977 1978 i = mi->mi_ntargets++; 1979 1980 mi->mi_targets = ( metatarget_t ** )ch_realloc( mi->mi_targets, 1981 sizeof( metatarget_t * ) * mi->mi_ntargets ); 1982 if ( mi->mi_targets == NULL ) { 1983 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1984 "out of memory while storing server name" 1985 " in \"%s <protocol>://<server>[:port]/<naming context>\"", 1986 c->argv[0] ); 1987 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1988 return 1; 1989 } 1990 1991 if ( meta_back_new_target( &mi->mi_targets[ i ] ) != 0 ) { 1992 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1993 "unable to init server" 1994 " in \"%s <protocol>://<server>[:port]/<naming context>\"", 1995 c->argv[0] ); 1996 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 1997 return 1; 1998 } 1999 2000 mt = mi->mi_targets[ i ]; 2001 2002 mt->mt_rebind_f = mi->mi_rebind_f; 2003 mt->mt_urllist_f = mi->mi_urllist_f; 2004 mt->mt_urllist_p = mt; 2005 2006 if ( META_BACK_QUARANTINE( mi ) ) { 2007 ldap_pvt_thread_mutex_init( &mt->mt_quarantine_mutex ); 2008 } 2009 mt->mt_mc = mi->mi_mc; 2010 2011 for ( j = 1; j < c->argc; j++ ) { 2012 char **tmpuris = ldap_str2charray( c->argv[ j ], "\t" ); 2013 2014 if ( tmpuris == NULL ) { 2015 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2016 "unable to parse URIs #%d" 2017 " in \"%s <protocol>://<server>[:port]/<naming context>\"", 2018 j-1, c->argv[0] ); 2019 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2020 return 1; 2021 } 2022 2023 if ( j == 1 ) { 2024 uris = tmpuris; 2025 2026 } else { 2027 ldap_charray_merge( &uris, tmpuris ); 2028 ldap_charray_free( tmpuris ); 2029 } 2030 } 2031 2032 for ( j = 0; uris[ j ] != NULL; j++ ) { 2033 char *tmpuri = NULL; 2034 2035 /* 2036 * uri MUST be legal! 2037 */ 2038 if ( ldap_url_parselist_ext( &ludp, uris[ j ], "\t", 2039 LDAP_PVT_URL_PARSE_NONE ) != LDAP_SUCCESS 2040 || ludp->lud_next != NULL ) 2041 { 2042 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2043 "unable to parse URI #%d" 2044 " in \"%s <protocol>://<server>[:port]/<naming context>\"", 2045 j-1, c->argv[0] ); 2046 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2047 ldap_charray_free( uris ); 2048 return 1; 2049 } 2050 2051 if ( j == 0 ) { 2052 2053 /* 2054 * uri MUST have the <dn> part! 2055 */ 2056 if ( ludp->lud_dn == NULL ) { 2057 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2058 "missing <naming context> " 2059 " in \"%s <protocol>://<server>[:port]/<naming context>\"", 2060 c->argv[0] ); 2061 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2062 ldap_free_urllist( ludp ); 2063 ldap_charray_free( uris ); 2064 return 1; 2065 } 2066 2067 /* 2068 * copies and stores uri and suffix 2069 */ 2070 ber_str2bv( ludp->lud_dn, 0, 0, &dn ); 2071 rc = dnPrettyNormal( NULL, &dn, &mt->mt_psuffix, 2072 &mt->mt_nsuffix, NULL ); 2073 if ( rc != LDAP_SUCCESS ) { 2074 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2075 "target DN is invalid \"%s\"", 2076 c->argv[1] ); 2077 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2078 ldap_free_urllist( ludp ); 2079 ldap_charray_free( uris ); 2080 return( 1 ); 2081 } 2082 2083 ludp->lud_dn[ 0 ] = '\0'; 2084 2085 switch ( ludp->lud_scope ) { 2086 case LDAP_SCOPE_DEFAULT: 2087 mt->mt_scope = LDAP_SCOPE_SUBTREE; 2088 break; 2089 2090 case LDAP_SCOPE_SUBTREE: 2091 case LDAP_SCOPE_SUBORDINATE: 2092 mt->mt_scope = ludp->lud_scope; 2093 break; 2094 2095 default: 2096 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2097 "invalid scope for target \"%s\"", 2098 c->argv[1] ); 2099 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2100 ldap_free_urllist( ludp ); 2101 ldap_charray_free( uris ); 2102 return( 1 ); 2103 } 2104 2105 } else { 2106 /* check all, to apply the scope check on the first one */ 2107 if ( ludp->lud_dn != NULL && ludp->lud_dn[ 0 ] != '\0' ) { 2108 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2109 "multiple URIs must have no DN part" ); 2110 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2111 ldap_free_urllist( ludp ); 2112 ldap_charray_free( uris ); 2113 return( 1 ); 2114 2115 } 2116 } 2117 2118 tmpuri = ldap_url_list2urls( ludp ); 2119 ldap_free_urllist( ludp ); 2120 if ( tmpuri == NULL ) { 2121 snprintf( c->cr_msg, sizeof( c->cr_msg ), "no memory?" ); 2122 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2123 ldap_charray_free( uris ); 2124 return( 1 ); 2125 } 2126 ldap_memfree( uris[ j ] ); 2127 uris[ j ] = tmpuri; 2128 } 2129 2130 mt->mt_uri = ldap_charray2str( uris, " " ); 2131 ldap_charray_free( uris ); 2132 if ( mt->mt_uri == NULL) { 2133 snprintf( c->cr_msg, sizeof( c->cr_msg ), "no memory?" ); 2134 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2135 return( 1 ); 2136 } 2137 2138 /* 2139 * uri MUST be a branch of suffix! 2140 */ 2141 for ( j = 0; !BER_BVISNULL( &c->be->be_nsuffix[ j ] ); j++ ) { 2142 if ( dnIsSuffix( &mt->mt_nsuffix, &c->be->be_nsuffix[ j ] ) ) { 2143 break; 2144 } 2145 } 2146 2147 if ( BER_BVISNULL( &c->be->be_nsuffix[ j ] ) ) { 2148 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2149 "<naming context> of URI must be within the naming context of this database." ); 2150 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2151 return 1; 2152 } 2153 c->ca_private = mt; 2154 config_push_cleanup( c, meta_cf_cleanup ); 2155 } break; 2156 case LDAP_BACK_CFG_SUBTREE_EX: 2157 case LDAP_BACK_CFG_SUBTREE_IN: 2158 /* subtree-exclude */ 2159 if ( meta_subtree_config( mt, c )) { 2160 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2161 return 1; 2162 } 2163 break; 2164 2165 case LDAP_BACK_CFG_FILTER: { 2166 metafilter_t *mf, **m2; 2167 mf = ch_calloc( 1, sizeof( metafilter_t )); 2168 rc = regcomp( &mf->mf_regex, c->argv[1], REG_EXTENDED ); 2169 if ( rc ) { 2170 char regerr[ SLAP_TEXT_BUFLEN ]; 2171 regerror( rc, &mf->mf_regex, regerr, sizeof(regerr) ); 2172 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2173 "regular expression \"%s\" bad because of %s", 2174 c->argv[1], regerr ); 2175 ch_free( mf ); 2176 return 1; 2177 } 2178 ber_str2bv( c->argv[1], 0, 1, &mf->mf_regex_pattern ); 2179 for ( m2 = &mt->mt_filter; *m2; m2 = &(*m2)->mf_next ) 2180 ; 2181 *m2 = mf; 2182 } break; 2183 2184 case LDAP_BACK_CFG_DEFAULT_T: 2185 /* default target directive */ 2186 i = mi->mi_ntargets - 1; 2187 2188 if ( c->argc == 1 ) { 2189 if ( i < 0 ) { 2190 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2191 "\"%s\" alone must be inside a \"uri\" directive", 2192 c->argv[0] ); 2193 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2194 return 1; 2195 } 2196 mi->mi_defaulttarget = i; 2197 2198 } else { 2199 if ( strcasecmp( c->argv[ 1 ], "none" ) == 0 ) { 2200 if ( i >= 0 ) { 2201 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2202 "\"%s none\" should go before uri definitions", 2203 c->argv[0] ); 2204 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2205 } 2206 mi->mi_defaulttarget = META_DEFAULT_TARGET_NONE; 2207 2208 } else { 2209 2210 if ( lutil_atoi( &mi->mi_defaulttarget, c->argv[ 1 ] ) != 0 2211 || mi->mi_defaulttarget < 0 2212 || mi->mi_defaulttarget >= i - 1 ) 2213 { 2214 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2215 "illegal target number %d", 2216 mi->mi_defaulttarget ); 2217 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2218 return 1; 2219 } 2220 } 2221 } 2222 break; 2223 2224 case LDAP_BACK_CFG_DNCACHE_TTL: 2225 /* ttl of dn cache */ 2226 if ( strcasecmp( c->argv[ 1 ], "forever" ) == 0 ) { 2227 mi->mi_cache.ttl = META_DNCACHE_FOREVER; 2228 2229 } else if ( strcasecmp( c->argv[ 1 ], "disabled" ) == 0 ) { 2230 mi->mi_cache.ttl = META_DNCACHE_DISABLED; 2231 2232 } else { 2233 unsigned long t; 2234 2235 if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) { 2236 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2237 "unable to parse dncache ttl \"%s\"", 2238 c->argv[ 1 ] ); 2239 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2240 return 1; 2241 } 2242 mi->mi_cache.ttl = (time_t)t; 2243 } 2244 break; 2245 2246 case LDAP_BACK_CFG_NETWORK_TIMEOUT: { 2247 /* network timeout when connecting to ldap servers */ 2248 unsigned long t; 2249 2250 if ( lutil_parse_time( c->argv[ 1 ], &t ) ) { 2251 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2252 "unable to parse network timeout \"%s\"", 2253 c->argv[ 1 ] ); 2254 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2255 return 1; 2256 } 2257 mc->mc_network_timeout = (time_t)t; 2258 } break; 2259 2260 case LDAP_BACK_CFG_IDLE_TIMEOUT: { 2261 /* idle timeout when connecting to ldap servers */ 2262 unsigned long t; 2263 2264 if ( lutil_parse_time( c->argv[ 1 ], &t ) ) { 2265 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2266 "unable to parse idle timeout \"%s\"", 2267 c->argv[ 1 ] ); 2268 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2269 return 1; 2270 2271 } 2272 mi->mi_idle_timeout = (time_t)t; 2273 } break; 2274 2275 case LDAP_BACK_CFG_CONN_TTL: { 2276 /* conn ttl */ 2277 unsigned long t; 2278 2279 if ( lutil_parse_time( c->argv[ 1 ], &t ) ) { 2280 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2281 "unable to parse conn ttl \"%s\"", 2282 c->argv[ 1 ] ); 2283 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2284 return 1; 2285 2286 } 2287 mi->mi_conn_ttl = (time_t)t; 2288 } break; 2289 2290 case LDAP_BACK_CFG_BIND_TIMEOUT: 2291 /* bind timeout when connecting to ldap servers */ 2292 mc->mc_bind_timeout.tv_sec = c->value_ulong/1000000; 2293 mc->mc_bind_timeout.tv_usec = c->value_ulong%1000000; 2294 break; 2295 2296 case LDAP_BACK_CFG_REBIND: 2297 /* save bind creds for referral rebinds? */ 2298 if ( c->argc == 1 || c->value_int ) { 2299 mc->mc_flags |= LDAP_BACK_F_SAVECRED; 2300 } else { 2301 mc->mc_flags &= ~LDAP_BACK_F_SAVECRED; 2302 } 2303 break; 2304 2305 case LDAP_BACK_CFG_CHASE: 2306 if ( c->argc == 1 || c->value_int ) { 2307 mc->mc_flags |= LDAP_BACK_F_CHASE_REFERRALS; 2308 } else { 2309 mc->mc_flags &= ~LDAP_BACK_F_CHASE_REFERRALS; 2310 } 2311 break; 2312 2313 case LDAP_BACK_CFG_TLS: 2314 i = verb_to_mask( c->argv[1], tls_mode ); 2315 if ( BER_BVISNULL( &tls_mode[i].word ) ) { 2316 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2317 "%s unknown argument \"%s\"", 2318 c->argv[0], c->argv[1] ); 2319 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2320 return 1; 2321 } 2322 mc->mc_flags &= ~LDAP_BACK_F_TLS_MASK; 2323 mc->mc_flags |= tls_mode[i].mask; 2324 2325 if ( c->argc > 2 ) { 2326 if ( c->op == SLAP_CONFIG_ADD && mi->mi_ntargets == 0 ) { 2327 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2328 "need \"uri\" directive first" ); 2329 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2330 return 1; 2331 } 2332 2333 for ( i = 2; i < c->argc; i++ ) { 2334 if ( bindconf_tls_parse( c->argv[i], &mt->mt_tls )) 2335 return 1; 2336 } 2337 bindconf_tls_defaults( &mt->mt_tls ); 2338 } 2339 break; 2340 2341 case LDAP_BACK_CFG_T_F: 2342 i = verb_to_mask( c->argv[1], t_f_mode ); 2343 if ( BER_BVISNULL( &t_f_mode[i].word ) ) { 2344 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2345 "%s unknown argument \"%s\"", 2346 c->argv[0], c->argv[1] ); 2347 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2348 return 1; 2349 } 2350 mc->mc_flags &= ~LDAP_BACK_F_T_F_MASK2; 2351 mc->mc_flags |= t_f_mode[i].mask; 2352 break; 2353 2354 case LDAP_BACK_CFG_ONERR: 2355 /* onerr? */ 2356 i = verb_to_mask( c->argv[1], onerr_mode ); 2357 if ( BER_BVISNULL( &onerr_mode[i].word ) ) { 2358 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2359 "%s unknown argument \"%s\"", 2360 c->argv[0], c->argv[1] ); 2361 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2362 return 1; 2363 } 2364 mi->mi_flags &= ~META_BACK_F_ONERR_MASK; 2365 mi->mi_flags |= onerr_mode[i].mask; 2366 break; 2367 2368 case LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER: 2369 /* bind-defer? */ 2370 if ( c->argc == 1 || c->value_int ) { 2371 mi->mi_flags |= META_BACK_F_DEFER_ROOTDN_BIND; 2372 } else { 2373 mi->mi_flags &= ~META_BACK_F_DEFER_ROOTDN_BIND; 2374 } 2375 break; 2376 2377 case LDAP_BACK_CFG_SINGLECONN: 2378 /* single-conn? */ 2379 if ( mi->mi_ntargets > 0 ) { 2380 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2381 "\"%s\" must appear before target definitions", 2382 c->argv[0] ); 2383 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2384 return( 1 ); 2385 } 2386 if ( c->value_int ) { 2387 mi->mi_flags |= LDAP_BACK_F_SINGLECONN; 2388 } else { 2389 mi->mi_flags &= ~LDAP_BACK_F_SINGLECONN; 2390 } 2391 break; 2392 2393 case LDAP_BACK_CFG_USETEMP: 2394 /* use-temporaries? */ 2395 if ( mi->mi_ntargets > 0 ) { 2396 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2397 "\"%s\" must appear before target definitions", 2398 c->argv[0] ); 2399 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2400 return( 1 ); 2401 } 2402 if ( c->value_int ) { 2403 mi->mi_flags |= LDAP_BACK_F_USE_TEMPORARIES; 2404 } else { 2405 mi->mi_flags &= ~LDAP_BACK_F_USE_TEMPORARIES; 2406 } 2407 break; 2408 2409 case LDAP_BACK_CFG_CONNPOOLMAX: 2410 /* privileged connections pool max size ? */ 2411 if ( mi->mi_ntargets > 0 ) { 2412 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2413 "\"%s\" must appear before target definitions", 2414 c->argv[0] ); 2415 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2416 return( 1 ); 2417 } 2418 2419 if ( c->value_int < LDAP_BACK_CONN_PRIV_MIN 2420 || c->value_int > LDAP_BACK_CONN_PRIV_MAX ) 2421 { 2422 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2423 "invalid max size " "of privileged " 2424 "connections pool \"%s\" " 2425 "in \"conn-pool-max <n> " 2426 "(must be between %d and %d)\"", 2427 c->argv[ 1 ], 2428 LDAP_BACK_CONN_PRIV_MIN, 2429 LDAP_BACK_CONN_PRIV_MAX ); 2430 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2431 return 1; 2432 } 2433 mi->mi_conn_priv_max = c->value_int; 2434 break; 2435 2436 case LDAP_BACK_CFG_CANCEL: 2437 i = verb_to_mask( c->argv[1], cancel_mode ); 2438 if ( BER_BVISNULL( &cancel_mode[i].word ) ) { 2439 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2440 "%s unknown argument \"%s\"", 2441 c->argv[0], c->argv[1] ); 2442 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2443 return 1; 2444 } 2445 mc->mc_flags &= ~LDAP_BACK_F_CANCEL_MASK2; 2446 mc->mc_flags |= cancel_mode[i].mask; 2447 break; 2448 2449 case LDAP_BACK_CFG_TIMEOUT: 2450 for ( i = 1; i < c->argc; i++ ) { 2451 if ( isdigit( (unsigned char) c->argv[ i ][ 0 ] ) ) { 2452 int j; 2453 unsigned u; 2454 2455 if ( lutil_atoux( &u, c->argv[ i ], 0 ) != 0 ) { 2456 snprintf( c->cr_msg, sizeof( c->cr_msg), 2457 "unable to parse timeout \"%s\"", 2458 c->argv[ i ] ); 2459 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2460 return 1; 2461 } 2462 2463 for ( j = 0; j < SLAP_OP_LAST; j++ ) { 2464 mc->mc_timeout[ j ] = u; 2465 } 2466 2467 continue; 2468 } 2469 2470 if ( slap_cf_aux_table_parse( c->argv[ i ], mc->mc_timeout, timeout_table, "slapd-meta timeout" ) ) { 2471 snprintf( c->cr_msg, sizeof( c->cr_msg), 2472 "unable to parse timeout \"%s\"", 2473 c->argv[ i ] ); 2474 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2475 return 1; 2476 } 2477 } 2478 break; 2479 2480 case LDAP_BACK_CFG_PSEUDOROOTDN: 2481 /* name to use as pseudo-root dn */ 2482 /* 2483 * exact replacement: 2484 * 2485 2486 idassert-bind bindmethod=simple 2487 binddn=<pseudorootdn> 2488 credentials=<pseudorootpw> 2489 mode=none 2490 flags=non-prescriptive 2491 idassert-authzFrom "dn:<rootdn>" 2492 2493 * so that only when authc'd as <rootdn> the proxying occurs 2494 * rebinding as the <pseudorootdn> without proxyAuthz. 2495 */ 2496 2497 Debug( LDAP_DEBUG_ANY, 2498 "%s: \"pseudorootdn\", \"pseudorootpw\" are no longer supported; " 2499 "use \"idassert-bind\" and \"idassert-authzFrom\" instead.\n", 2500 c->log ); 2501 2502 { 2503 char binddn[ SLAP_TEXT_BUFLEN ]; 2504 char *cargv[] = { 2505 "idassert-bind", 2506 "bindmethod=simple", 2507 NULL, 2508 "mode=none", 2509 "flags=non-prescriptive", 2510 NULL 2511 }; 2512 char **oargv; 2513 int oargc; 2514 int cargc = 5; 2515 int rc; 2516 2517 2518 if ( BER_BVISNULL( &c->be->be_rootndn ) ) { 2519 Debug( LDAP_DEBUG_ANY, "%s: \"pseudorootpw\": \"rootdn\" must be defined first.\n", 2520 c->log ); 2521 return 1; 2522 } 2523 2524 if ( sizeof( binddn ) <= (unsigned) snprintf( binddn, 2525 sizeof( binddn ), "binddn=%s", c->argv[ 1 ] )) 2526 { 2527 Debug( LDAP_DEBUG_ANY, "%s: \"pseudorootdn\" too long.\n", 2528 c->log ); 2529 return 1; 2530 } 2531 cargv[ 2 ] = binddn; 2532 2533 oargv = c->argv; 2534 oargc = c->argc; 2535 c->argv = cargv; 2536 c->argc = cargc; 2537 rc = mi->mi_ldap_extra->idassert_parse( c, &mt->mt_idassert ); 2538 c->argv = oargv; 2539 c->argc = oargc; 2540 if ( rc == 0 ) { 2541 struct berval bv; 2542 2543 if ( mt->mt_idassert_authz != NULL ) { 2544 Debug( LDAP_DEBUG_ANY, "%s: \"idassert-authzFrom\" already defined (discarded).\n", 2545 c->log ); 2546 ber_bvarray_free( mt->mt_idassert_authz ); 2547 mt->mt_idassert_authz = NULL; 2548 } 2549 2550 assert( !BER_BVISNULL( &mt->mt_idassert_authcDN ) ); 2551 2552 bv.bv_len = STRLENOF( "dn:" ) + c->be->be_rootndn.bv_len; 2553 bv.bv_val = ch_malloc( bv.bv_len + 1 ); 2554 AC_MEMCPY( bv.bv_val, "dn:", STRLENOF( "dn:" ) ); 2555 AC_MEMCPY( &bv.bv_val[ STRLENOF( "dn:" ) ], c->be->be_rootndn.bv_val, c->be->be_rootndn.bv_len + 1 ); 2556 2557 ber_bvarray_add( &mt->mt_idassert_authz, &bv ); 2558 } 2559 2560 return rc; 2561 } 2562 break; 2563 2564 case LDAP_BACK_CFG_PSEUDOROOTPW: 2565 /* password to use as pseudo-root */ 2566 Debug( LDAP_DEBUG_ANY, 2567 "%s: \"pseudorootdn\", \"pseudorootpw\" are no longer supported; " 2568 "use \"idassert-bind\" and \"idassert-authzFrom\" instead.\n", 2569 c->log ); 2570 2571 if ( BER_BVISNULL( &mt->mt_idassert_authcDN ) ) { 2572 Debug( LDAP_DEBUG_ANY, "%s: \"pseudorootpw\": \"pseudorootdn\" must be defined first.\n", 2573 c->log ); 2574 return 1; 2575 } 2576 2577 if ( !BER_BVISNULL( &mt->mt_idassert_passwd ) ) { 2578 memset( mt->mt_idassert_passwd.bv_val, 0, 2579 mt->mt_idassert_passwd.bv_len ); 2580 ber_memfree( mt->mt_idassert_passwd.bv_val ); 2581 } 2582 ber_str2bv( c->argv[ 1 ], 0, 1, &mt->mt_idassert_passwd ); 2583 break; 2584 2585 case LDAP_BACK_CFG_IDASSERT_BIND: 2586 /* idassert-bind */ 2587 rc = mi->mi_ldap_extra->idassert_parse( c, &mt->mt_idassert ); 2588 break; 2589 2590 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: 2591 /* idassert-authzFrom */ 2592 rc = mi->mi_ldap_extra->idassert_authzfrom_parse( c, &mt->mt_idassert ); 2593 break; 2594 2595 case LDAP_BACK_CFG_QUARANTINE: 2596 /* quarantine */ 2597 if ( META_BACK_CMN_QUARANTINE( mc ) ) 2598 { 2599 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2600 "quarantine already defined" ); 2601 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2602 return 1; 2603 } 2604 2605 if ( mt ) { 2606 mc->mc_quarantine.ri_interval = NULL; 2607 mc->mc_quarantine.ri_num = NULL; 2608 if ( !META_BACK_QUARANTINE( mi ) ) { 2609 ldap_pvt_thread_mutex_init( &mt->mt_quarantine_mutex ); 2610 } 2611 } 2612 2613 if ( mi->mi_ldap_extra->retry_info_parse( c->argv[ 1 ], &mc->mc_quarantine, c->cr_msg, sizeof( c->cr_msg ) ) ) { 2614 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2615 return 1; 2616 } 2617 2618 mc->mc_flags |= LDAP_BACK_F_QUARANTINE; 2619 break; 2620 2621 #ifdef SLAP_CONTROL_X_SESSION_TRACKING 2622 case LDAP_BACK_CFG_ST_REQUEST: 2623 /* session tracking request */ 2624 if ( c->value_int ) { 2625 mc->mc_flags |= LDAP_BACK_F_ST_REQUEST; 2626 } else { 2627 mc->mc_flags &= ~LDAP_BACK_F_ST_REQUEST; 2628 } 2629 break; 2630 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 2631 2632 case LDAP_BACK_CFG_SUFFIXM: /* FALLTHRU */ 2633 case LDAP_BACK_CFG_REWRITE: { 2634 /* rewrite stuff ... */ 2635 ConfigArgs ca = { 0 }; 2636 char *line, **argv; 2637 struct rewrite_info *rwi; 2638 int cnt = 0, argc, ix = c->valx; 2639 2640 if ( mt->mt_rwmap.rwm_bva_rewrite ) { 2641 for ( ; !BER_BVISNULL( &mt->mt_rwmap.rwm_bva_rewrite[ cnt ] ); cnt++ ) 2642 /* count */ ; 2643 } 2644 2645 if ( ix >= cnt || ix < 0 ) { 2646 ix = cnt; 2647 } else { 2648 rwi = mt->mt_rwmap.rwm_rw; 2649 2650 mt->mt_rwmap.rwm_rw = NULL; 2651 rc = meta_rwi_init( &mt->mt_rwmap.rwm_rw ); 2652 2653 /* re-parse all rewrite rules, up to the one 2654 * that needs to be added */ 2655 ca.be = c->be; 2656 ca.fname = c->fname; 2657 ca.lineno = c->lineno; 2658 for ( i = 0; i < ix; i++ ) { 2659 ca.line = mt->mt_rwmap.rwm_bva_rewrite[ i ].bv_val; 2660 ca.argc = 0; 2661 config_fp_parse_line( &ca ); 2662 2663 if ( !strcasecmp( ca.argv[0], "suffixmassage" )) { 2664 rc = meta_suffixm_config( &ca, ca.argc, ca.argv, mt ); 2665 } else { 2666 rc = rewrite_parse( mt->mt_rwmap.rwm_rw, 2667 c->fname, c->lineno, ca.argc, ca.argv ); 2668 } 2669 assert( rc == 0 ); 2670 ch_free( ca.argv ); 2671 ch_free( ca.tline ); 2672 } 2673 } 2674 argc = c->argc; 2675 argv = c->argv; 2676 if ( c->op != SLAP_CONFIG_ADD ) { 2677 argc--; 2678 argv++; 2679 } 2680 /* add the new rule */ 2681 if ( !strcasecmp( argv[0], "suffixmassage" )) { 2682 rc = meta_suffixm_config( c, argc, argv, mt ); 2683 } else { 2684 rc = rewrite_parse( mt->mt_rwmap.rwm_rw, 2685 c->fname, c->lineno, argc, argv ); 2686 } 2687 if ( rc ) { 2688 if ( ix < cnt ) { 2689 rewrite_info_delete( &mt->mt_rwmap.rwm_rw ); 2690 mt->mt_rwmap.rwm_rw = rwi; 2691 } 2692 return 1; 2693 } 2694 if ( ix < cnt ) { 2695 for ( ; i < cnt; i++ ) { 2696 ca.line = mt->mt_rwmap.rwm_bva_rewrite[ i ].bv_val; 2697 ca.argc = 0; 2698 config_fp_parse_line( &ca ); 2699 2700 if ( !strcasecmp( ca.argv[0], "suffixmassage" )) { 2701 rc = meta_suffixm_config( &ca, ca.argc, ca.argv, mt ); 2702 } else { 2703 rc = rewrite_parse( mt->mt_rwmap.rwm_rw, 2704 c->fname, c->lineno, ca.argc, argv ); 2705 } 2706 assert( rc == 0 ); 2707 ch_free( ca.argv ); 2708 ch_free( ca.tline ); 2709 } 2710 } 2711 2712 /* save the rule info */ 2713 line = ldap_charray2str( argv, "\" \"" ); 2714 if ( line != NULL ) { 2715 struct berval bv; 2716 int len = strlen( argv[ 0 ] ); 2717 2718 ber_str2bv( line, 0, 0, &bv ); 2719 AC_MEMCPY( &bv.bv_val[ len ], &bv.bv_val[ len + 1 ], 2720 bv.bv_len - ( len + 1 )); 2721 bv.bv_val[ bv.bv_len - 1] = '"'; 2722 ber_bvarray_add( &mt->mt_rwmap.rwm_bva_rewrite, &bv ); 2723 /* move it to the right slot */ 2724 if ( ix < cnt ) { 2725 for ( i=cnt; i>ix; i-- ) 2726 mt->mt_rwmap.rwm_bva_rewrite[i+1] = mt->mt_rwmap.rwm_bva_rewrite[i]; 2727 mt->mt_rwmap.rwm_bva_rewrite[i] = bv; 2728 2729 /* destroy old rules */ 2730 rewrite_info_delete( &rwi ); 2731 } 2732 } 2733 } break; 2734 2735 case LDAP_BACK_CFG_MAP: { 2736 /* objectclass/attribute mapping */ 2737 ConfigArgs ca = { 0 }; 2738 char *argv[5]; 2739 struct ldapmap rwm_oc; 2740 struct ldapmap rwm_at; 2741 int cnt = 0, ix = c->valx; 2742 2743 if ( mt->mt_rwmap.rwm_bva_map ) { 2744 for ( ; !BER_BVISNULL( &mt->mt_rwmap.rwm_bva_map[ cnt ] ); cnt++ ) 2745 /* count */ ; 2746 } 2747 2748 if ( ix >= cnt || ix < 0 ) { 2749 ix = cnt; 2750 } else { 2751 rwm_oc = mt->mt_rwmap.rwm_oc; 2752 rwm_at = mt->mt_rwmap.rwm_at; 2753 2754 memset( &mt->mt_rwmap.rwm_oc, 0, sizeof( mt->mt_rwmap.rwm_oc ) ); 2755 memset( &mt->mt_rwmap.rwm_at, 0, sizeof( mt->mt_rwmap.rwm_at ) ); 2756 2757 /* re-parse all mappings, up to the one 2758 * that needs to be added */ 2759 argv[0] = c->argv[0]; 2760 ca.fname = c->fname; 2761 ca.lineno = c->lineno; 2762 for ( i = 0; i < ix; i++ ) { 2763 ca.line = mt->mt_rwmap.rwm_bva_map[ i ].bv_val; 2764 ca.argc = 0; 2765 config_fp_parse_line( &ca ); 2766 2767 argv[1] = ca.argv[0]; 2768 argv[2] = ca.argv[1]; 2769 argv[3] = ca.argv[2]; 2770 argv[4] = ca.argv[3]; 2771 ch_free( ca.argv ); 2772 ca.argv = argv; 2773 ca.argc++; 2774 rc = ldap_back_map_config( &ca, &mt->mt_rwmap.rwm_oc, 2775 &mt->mt_rwmap.rwm_at ); 2776 2777 ch_free( ca.tline ); 2778 ca.tline = NULL; 2779 ca.argv = NULL; 2780 2781 /* in case of failure, restore 2782 * the existing mapping */ 2783 if ( rc ) { 2784 goto map_fail; 2785 } 2786 } 2787 } 2788 /* add the new mapping */ 2789 rc = ldap_back_map_config( c, &mt->mt_rwmap.rwm_oc, 2790 &mt->mt_rwmap.rwm_at ); 2791 if ( rc ) { 2792 goto map_fail; 2793 } 2794 2795 if ( ix < cnt ) { 2796 for ( ; i<cnt ; cnt++ ) { 2797 ca.line = mt->mt_rwmap.rwm_bva_map[ i ].bv_val; 2798 ca.argc = 0; 2799 config_fp_parse_line( &ca ); 2800 2801 argv[1] = ca.argv[0]; 2802 argv[2] = ca.argv[1]; 2803 argv[3] = ca.argv[2]; 2804 argv[4] = ca.argv[3]; 2805 2806 ch_free( ca.argv ); 2807 ca.argv = argv; 2808 ca.argc++; 2809 rc = ldap_back_map_config( &ca, &mt->mt_rwmap.rwm_oc, 2810 &mt->mt_rwmap.rwm_at ); 2811 2812 ch_free( ca.tline ); 2813 ca.tline = NULL; 2814 ca.argv = NULL; 2815 2816 /* in case of failure, restore 2817 * the existing mapping */ 2818 if ( rc ) { 2819 goto map_fail; 2820 } 2821 } 2822 } 2823 2824 /* save the map info */ 2825 argv[0] = ldap_charray2str( &c->argv[ 1 ], " " ); 2826 if ( argv[0] != NULL ) { 2827 struct berval bv; 2828 ber_str2bv( argv[0], 0, 0, &bv ); 2829 ber_bvarray_add( &mt->mt_rwmap.rwm_bva_map, &bv ); 2830 /* move it to the right slot */ 2831 if ( ix < cnt ) { 2832 for ( i=cnt; i>ix; i-- ) 2833 mt->mt_rwmap.rwm_bva_map[i+1] = mt->mt_rwmap.rwm_bva_map[i]; 2834 mt->mt_rwmap.rwm_bva_map[i] = bv; 2835 2836 /* destroy old mapping */ 2837 meta_back_map_free( &rwm_oc ); 2838 meta_back_map_free( &rwm_at ); 2839 } 2840 } 2841 break; 2842 2843 map_fail:; 2844 if ( ix < cnt ) { 2845 meta_back_map_free( &mt->mt_rwmap.rwm_oc ); 2846 meta_back_map_free( &mt->mt_rwmap.rwm_at ); 2847 mt->mt_rwmap.rwm_oc = rwm_oc; 2848 mt->mt_rwmap.rwm_at = rwm_at; 2849 } 2850 } break; 2851 2852 case LDAP_BACK_CFG_NRETRIES: { 2853 int nretries = META_RETRY_UNDEFINED; 2854 2855 if ( strcasecmp( c->argv[ 1 ], "forever" ) == 0 ) { 2856 nretries = META_RETRY_FOREVER; 2857 2858 } else if ( strcasecmp( c->argv[ 1 ], "never" ) == 0 ) { 2859 nretries = META_RETRY_NEVER; 2860 2861 } else { 2862 if ( lutil_atoi( &nretries, c->argv[ 1 ] ) != 0 ) { 2863 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2864 "unable to parse nretries {never|forever|<retries>}: \"%s\"", 2865 c->argv[ 1 ] ); 2866 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2867 return 1; 2868 } 2869 } 2870 2871 mc->mc_nretries = nretries; 2872 } break; 2873 2874 case LDAP_BACK_CFG_VERSION: 2875 if ( c->value_int != 0 && ( c->value_int < LDAP_VERSION_MIN || c->value_int > LDAP_VERSION_MAX ) ) { 2876 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2877 "unsupported protocol version \"%s\"", 2878 c->argv[ 1 ] ); 2879 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2880 return 1; 2881 } 2882 mc->mc_version = c->value_int; 2883 break; 2884 2885 case LDAP_BACK_CFG_NOREFS: 2886 /* do not return search references */ 2887 if ( c->value_int ) { 2888 mc->mc_flags |= LDAP_BACK_F_NOREFS; 2889 } else { 2890 mc->mc_flags &= ~LDAP_BACK_F_NOREFS; 2891 } 2892 break; 2893 2894 case LDAP_BACK_CFG_NOUNDEFFILTER: 2895 /* do not propagate undefined search filters */ 2896 if ( c->value_int ) { 2897 mc->mc_flags |= LDAP_BACK_F_NOUNDEFFILTER; 2898 } else { 2899 mc->mc_flags &= ~LDAP_BACK_F_NOUNDEFFILTER; 2900 } 2901 break; 2902 2903 #ifdef SLAPD_META_CLIENT_PR 2904 case LDAP_BACK_CFG_CLIENT_PR: 2905 if ( strcasecmp( c->argv[ 1 ], "accept-unsolicited" ) == 0 ) { 2906 mc->mc_ps = META_CLIENT_PR_ACCEPT_UNSOLICITED; 2907 2908 } else if ( strcasecmp( c->argv[ 1 ], "disable" ) == 0 ) { 2909 mc->mc_ps = META_CLIENT_PR_DISABLE; 2910 2911 } else if ( lutil_atoi( &mc->mc_ps, c->argv[ 1 ] ) || mc->mc_ps < -1 ) { 2912 snprintf( c->cr_msg, sizeof( c->cr_msg ), 2913 "unable to parse client-pr {accept-unsolicited|disable|<size>}: \"%s\"", 2914 c->argv[ 1 ] ); 2915 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2916 return( 1 ); 2917 } 2918 break; 2919 #endif /* SLAPD_META_CLIENT_PR */ 2920 2921 case LDAP_BACK_CFG_KEEPALIVE: 2922 slap_keepalive_parse( ber_bvstrdup(c->argv[1]), 2923 &mt->mt_tls.sb_keepalive, 0, 0, 0); 2924 break; 2925 2926 case LDAP_BACK_CFG_TCP_USER_TIMEOUT: 2927 mt->mt_tls.sb_tcp_user_timeout = c->value_uint; 2928 break; 2929 2930 /* anything else */ 2931 default: 2932 return SLAP_CONF_UNKNOWN; 2933 } 2934 2935 return rc; 2936 } 2937 2938 int 2939 meta_back_init_cf( BackendInfo *bi ) 2940 { 2941 int rc; 2942 2943 /* Make sure we don't exceed the bits reserved for userland */ 2944 config_check_userland( LDAP_BACK_CFG_LAST ); 2945 2946 bi->bi_cf_ocs = metaocs; 2947 2948 rc = config_register_schema( metacfg, metaocs ); 2949 if ( rc ) { 2950 return rc; 2951 } 2952 2953 return 0; 2954 } 2955 2956 static int 2957 ldap_back_map_config( 2958 ConfigArgs *c, 2959 struct ldapmap *oc_map, 2960 struct ldapmap *at_map ) 2961 { 2962 struct ldapmap *map; 2963 struct ldapmapping *mapping; 2964 char *src, *dst; 2965 int is_oc = 0; 2966 2967 if ( strcasecmp( c->argv[ 1 ], "objectclass" ) == 0 ) { 2968 map = oc_map; 2969 is_oc = 1; 2970 2971 } else if ( strcasecmp( c->argv[ 1 ], "attribute" ) == 0 ) { 2972 map = at_map; 2973 2974 } else { 2975 snprintf( c->cr_msg, sizeof(c->cr_msg), 2976 "%s unknown argument \"%s\"", 2977 c->argv[0], c->argv[1] ); 2978 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 2979 return 1; 2980 } 2981 2982 if ( !is_oc && map->map == NULL ) { 2983 /* only init if required */ 2984 ldap_back_map_init( map, &mapping ); 2985 } 2986 2987 if ( strcmp( c->argv[ 2 ], "*" ) == 0 ) { 2988 if ( c->argc < 4 || strcmp( c->argv[ 3 ], "*" ) == 0 ) { 2989 map->drop_missing = ( c->argc < 4 ); 2990 goto success_return; 2991 } 2992 src = dst = c->argv[ 3 ]; 2993 2994 } else if ( c->argc < 4 ) { 2995 src = ""; 2996 dst = c->argv[ 2 ]; 2997 2998 } else { 2999 src = c->argv[ 2 ]; 3000 dst = ( strcmp( c->argv[ 3 ], "*" ) == 0 ? src : c->argv[ 3 ] ); 3001 } 3002 3003 if ( ( map == at_map ) 3004 && ( strcasecmp( src, "objectclass" ) == 0 3005 || strcasecmp( dst, "objectclass" ) == 0 ) ) 3006 { 3007 snprintf( c->cr_msg, sizeof(c->cr_msg), 3008 "objectclass attribute cannot be mapped" ); 3009 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 3010 return 1; 3011 } 3012 3013 mapping = (struct ldapmapping *)ch_calloc( 2, 3014 sizeof(struct ldapmapping) ); 3015 if ( mapping == NULL ) { 3016 snprintf( c->cr_msg, sizeof(c->cr_msg), 3017 "out of memory" ); 3018 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 3019 return 1; 3020 } 3021 ber_str2bv( src, 0, 1, &mapping[ 0 ].src ); 3022 ber_str2bv( dst, 0, 1, &mapping[ 0 ].dst ); 3023 mapping[ 1 ].src = mapping[ 0 ].dst; 3024 mapping[ 1 ].dst = mapping[ 0 ].src; 3025 3026 /* 3027 * schema check 3028 */ 3029 if ( is_oc ) { 3030 if ( src[ 0 ] != '\0' ) { 3031 if ( oc_bvfind( &mapping[ 0 ].src ) == NULL ) { 3032 Debug( LDAP_DEBUG_ANY, 3033 "%s: warning, source objectClass '%s' should be defined in schema\n", 3034 c->log, src ); 3035 3036 /* 3037 * FIXME: this should become an err 3038 */ 3039 goto error_return; 3040 } 3041 } 3042 3043 if ( oc_bvfind( &mapping[ 0 ].dst ) == NULL ) { 3044 Debug( LDAP_DEBUG_ANY, 3045 "%s: warning, destination objectClass '%s' is not defined in schema\n", 3046 c->log, dst ); 3047 } 3048 } else { 3049 int rc; 3050 const char *text = NULL; 3051 AttributeDescription *ad = NULL; 3052 3053 if ( src[ 0 ] != '\0' ) { 3054 rc = slap_bv2ad( &mapping[ 0 ].src, &ad, &text ); 3055 if ( rc != LDAP_SUCCESS ) { 3056 Debug( LDAP_DEBUG_ANY, 3057 "%s: warning, source attributeType '%s' should be defined in schema\n", 3058 c->log, src ); 3059 3060 /* 3061 * FIXME: this should become an err 3062 */ 3063 /* 3064 * we create a fake "proxied" ad 3065 * and add it here. 3066 */ 3067 3068 rc = slap_bv2undef_ad( &mapping[ 0 ].src, 3069 &ad, &text, SLAP_AD_PROXIED ); 3070 if ( rc != LDAP_SUCCESS ) { 3071 snprintf( c->cr_msg, sizeof( c->cr_msg ), 3072 "source attributeType \"%s\": %d (%s)", 3073 src, rc, text ? text : "" ); 3074 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 3075 goto error_return; 3076 } 3077 } 3078 3079 ad = NULL; 3080 } 3081 3082 rc = slap_bv2ad( &mapping[ 0 ].dst, &ad, &text ); 3083 if ( rc != LDAP_SUCCESS ) { 3084 Debug( LDAP_DEBUG_ANY, 3085 "%s: warning, destination attributeType '%s' is not defined in schema\n", 3086 c->log, dst ); 3087 3088 /* 3089 * we create a fake "proxied" ad 3090 * and add it here. 3091 */ 3092 3093 rc = slap_bv2undef_ad( &mapping[ 0 ].dst, 3094 &ad, &text, SLAP_AD_PROXIED ); 3095 if ( rc != LDAP_SUCCESS ) { 3096 snprintf( c->cr_msg, sizeof( c->cr_msg ), 3097 "destination attributeType \"%s\": %d (%s)\n", 3098 dst, rc, text ? text : "" ); 3099 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 3100 return 1; 3101 } 3102 } 3103 } 3104 3105 if ( (src[ 0 ] != '\0' && ldap_avl_find( map->map, (caddr_t)&mapping[ 0 ], mapping_cmp ) != NULL) 3106 || ldap_avl_find( map->remap, (caddr_t)&mapping[ 1 ], mapping_cmp ) != NULL) 3107 { 3108 snprintf( c->cr_msg, sizeof( c->cr_msg ), 3109 "duplicate mapping found." ); 3110 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); 3111 goto error_return; 3112 } 3113 3114 if ( src[ 0 ] != '\0' ) { 3115 ldap_avl_insert( &map->map, (caddr_t)&mapping[ 0 ], 3116 mapping_cmp, mapping_dup ); 3117 } 3118 ldap_avl_insert( &map->remap, (caddr_t)&mapping[ 1 ], 3119 mapping_cmp, mapping_dup ); 3120 3121 success_return:; 3122 return 0; 3123 3124 error_return:; 3125 if ( mapping ) { 3126 ch_free( mapping[ 0 ].src.bv_val ); 3127 ch_free( mapping[ 0 ].dst.bv_val ); 3128 ch_free( mapping ); 3129 } 3130 3131 return 1; 3132 } 3133 3134 3135 static char * 3136 suffix_massage_regexize( const char *s ) 3137 { 3138 char *res, *ptr; 3139 const char *p, *r; 3140 int i; 3141 3142 if ( s[ 0 ] == '\0' ) { 3143 return ch_strdup( "^(.+)$" ); 3144 } 3145 3146 for ( i = 0, p = s; 3147 ( r = strchr( p, ',' ) ) != NULL; 3148 p = r + 1, i++ ) 3149 ; 3150 3151 res = ch_calloc( sizeof( char ), 3152 strlen( s ) 3153 + STRLENOF( "((.+),)?" ) 3154 + STRLENOF( "[ ]?" ) * i 3155 + STRLENOF( "$" ) + 1 ); 3156 3157 ptr = lutil_strcopy( res, "((.+),)?" ); 3158 for ( i = 0, p = s; 3159 ( r = strchr( p, ',' ) ) != NULL; 3160 p = r + 1 , i++ ) { 3161 ptr = lutil_strncopy( ptr, p, r - p + 1 ); 3162 ptr = lutil_strcopy( ptr, "[ ]?" ); 3163 3164 if ( r[ 1 ] == ' ' ) { 3165 r++; 3166 } 3167 } 3168 ptr = lutil_strcopy( ptr, p ); 3169 ptr[ 0 ] = '$'; 3170 ptr++; 3171 ptr[ 0 ] = '\0'; 3172 3173 return res; 3174 } 3175 3176 static char * 3177 suffix_massage_patternize( const char *s, const char *p ) 3178 { 3179 ber_len_t len; 3180 char *res, *ptr; 3181 3182 len = strlen( p ); 3183 3184 if ( s[ 0 ] == '\0' ) { 3185 len++; 3186 } 3187 3188 res = ch_calloc( sizeof( char ), len + STRLENOF( "%1" ) + 1 ); 3189 if ( res == NULL ) { 3190 return NULL; 3191 } 3192 3193 ptr = lutil_strcopy( res, ( p[ 0 ] == '\0' ? "%2" : "%1" ) ); 3194 if ( s[ 0 ] == '\0' ) { 3195 ptr[ 0 ] = ','; 3196 ptr++; 3197 } 3198 lutil_strcopy( ptr, p ); 3199 3200 return res; 3201 } 3202 3203 int 3204 suffix_massage_config( 3205 struct rewrite_info *info, 3206 struct berval *pvnc, 3207 struct berval *nvnc, 3208 struct berval *prnc, 3209 struct berval *nrnc 3210 ) 3211 { 3212 char *rargv[ 5 ]; 3213 int line = 0; 3214 3215 rargv[ 0 ] = "rewriteEngine"; 3216 rargv[ 1 ] = "on"; 3217 rargv[ 2 ] = NULL; 3218 rewrite_parse( info, "<suffix massage>", ++line, 2, rargv ); 3219 3220 rargv[ 0 ] = "rewriteContext"; 3221 rargv[ 1 ] = "default"; 3222 rargv[ 2 ] = NULL; 3223 rewrite_parse( info, "<suffix massage>", ++line, 2, rargv ); 3224 3225 rargv[ 0 ] = "rewriteRule"; 3226 rargv[ 1 ] = suffix_massage_regexize( pvnc->bv_val ); 3227 rargv[ 2 ] = suffix_massage_patternize( pvnc->bv_val, prnc->bv_val ); 3228 rargv[ 3 ] = ":"; 3229 rargv[ 4 ] = NULL; 3230 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv ); 3231 ch_free( rargv[ 1 ] ); 3232 ch_free( rargv[ 2 ] ); 3233 3234 if ( BER_BVISEMPTY( pvnc ) ) { 3235 rargv[ 0 ] = "rewriteRule"; 3236 rargv[ 1 ] = "^$"; 3237 rargv[ 2 ] = prnc->bv_val; 3238 rargv[ 3 ] = ":"; 3239 rargv[ 4 ] = NULL; 3240 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv ); 3241 } 3242 3243 rargv[ 0 ] = "rewriteContext"; 3244 rargv[ 1 ] = "searchEntryDN"; 3245 rargv[ 2 ] = NULL; 3246 rewrite_parse( info, "<suffix massage>", ++line, 2, rargv ); 3247 3248 rargv[ 0 ] = "rewriteRule"; 3249 rargv[ 1 ] = suffix_massage_regexize( prnc->bv_val ); 3250 rargv[ 2 ] = suffix_massage_patternize( prnc->bv_val, pvnc->bv_val ); 3251 rargv[ 3 ] = ":"; 3252 rargv[ 4 ] = NULL; 3253 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv ); 3254 ch_free( rargv[ 1 ] ); 3255 ch_free( rargv[ 2 ] ); 3256 3257 if ( BER_BVISEMPTY( prnc ) ) { 3258 rargv[ 0 ] = "rewriteRule"; 3259 rargv[ 1 ] = "^$"; 3260 rargv[ 2 ] = pvnc->bv_val; 3261 rargv[ 3 ] = ":"; 3262 rargv[ 4 ] = NULL; 3263 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv ); 3264 } 3265 3266 /* backward compatibility */ 3267 rargv[ 0 ] = "rewriteContext"; 3268 rargv[ 1 ] = "searchResult"; 3269 rargv[ 2 ] = "alias"; 3270 rargv[ 3 ] = "searchEntryDN"; 3271 rargv[ 4 ] = NULL; 3272 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv ); 3273 3274 rargv[ 0 ] = "rewriteContext"; 3275 rargv[ 1 ] = "matchedDN"; 3276 rargv[ 2 ] = "alias"; 3277 rargv[ 3 ] = "searchEntryDN"; 3278 rargv[ 4 ] = NULL; 3279 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv ); 3280 3281 rargv[ 0 ] = "rewriteContext"; 3282 rargv[ 1 ] = "searchAttrDN"; 3283 rargv[ 2 ] = "alias"; 3284 rargv[ 3 ] = "searchEntryDN"; 3285 rargv[ 4 ] = NULL; 3286 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv ); 3287 3288 /* NOTE: this corresponds to #undef'ining RWM_REFERRAL_REWRITE; 3289 * see servers/slapd/overlays/rwm.h for details */ 3290 rargv[ 0 ] = "rewriteContext"; 3291 rargv[ 1 ] = "referralAttrDN"; 3292 rargv[ 2 ] = NULL; 3293 rewrite_parse( info, "<suffix massage>", ++line, 2, rargv ); 3294 3295 rargv[ 0 ] = "rewriteContext"; 3296 rargv[ 1 ] = "referralDN"; 3297 rargv[ 2 ] = NULL; 3298 rewrite_parse( info, "<suffix massage>", ++line, 2, rargv ); 3299 3300 return 0; 3301 } 3302