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