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