1 /* config.c - ldap backend configuration file routine */ 2 /* $OpenLDAP: pkg/ldap/servers/slapd/back-ldap/config.c,v 1.115.2.9 2008/07/10 00:28:39 quanah Exp $ */ 3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 2003-2008 The OpenLDAP Foundation. 6 * Portions Copyright 1999-2003 Howard Chu. 7 * Portions Copyright 2000-2003 Pierangelo Masarati. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted only as authorized by the OpenLDAP 12 * Public License. 13 * 14 * A copy of this license is available in the file LICENSE in the 15 * top-level directory of the distribution or, alternatively, at 16 * <http://www.OpenLDAP.org/license.html>. 17 */ 18 /* ACKNOWLEDGEMENTS: 19 * This work was initially developed by the Howard Chu for inclusion 20 * in OpenLDAP Software and subsequently enhanced by Pierangelo 21 * Masarati. 22 */ 23 24 #include "portable.h" 25 26 #include <stdio.h> 27 28 #include <ac/string.h> 29 #include <ac/ctype.h> 30 #include <ac/socket.h> 31 32 #include "slap.h" 33 #include "config.h" 34 #include "back-ldap.h" 35 #include "lutil.h" 36 #include "ldif.h" 37 #undef ldap_debug 38 /* for advanced URL parsing */ 39 #include "../../../libraries/libldap/ldap-int.h" 40 41 static SLAP_EXTOP_MAIN_FN ldap_back_exop_whoami; 42 43 static ConfigDriver ldap_back_cf_gen; 44 45 enum { 46 LDAP_BACK_CFG_URI = 1, 47 LDAP_BACK_CFG_TLS, 48 LDAP_BACK_CFG_ACL_AUTHCDN, 49 LDAP_BACK_CFG_ACL_PASSWD, 50 LDAP_BACK_CFG_ACL_METHOD, 51 LDAP_BACK_CFG_ACL_BIND, 52 LDAP_BACK_CFG_IDASSERT_MODE, 53 LDAP_BACK_CFG_IDASSERT_AUTHCDN, 54 LDAP_BACK_CFG_IDASSERT_PASSWD, 55 LDAP_BACK_CFG_IDASSERT_AUTHZFROM, 56 LDAP_BACK_CFG_IDASSERT_METHOD, 57 LDAP_BACK_CFG_IDASSERT_BIND, 58 LDAP_BACK_CFG_REBIND, 59 LDAP_BACK_CFG_CHASE, 60 LDAP_BACK_CFG_T_F, 61 LDAP_BACK_CFG_WHOAMI, 62 LDAP_BACK_CFG_TIMEOUT, 63 LDAP_BACK_CFG_IDLE_TIMEOUT, 64 LDAP_BACK_CFG_CONN_TTL, 65 LDAP_BACK_CFG_NETWORK_TIMEOUT, 66 LDAP_BACK_CFG_VERSION, 67 LDAP_BACK_CFG_SINGLECONN, 68 LDAP_BACK_CFG_USETEMP, 69 LDAP_BACK_CFG_CONNPOOLMAX, 70 LDAP_BACK_CFG_CANCEL, 71 LDAP_BACK_CFG_QUARANTINE, 72 LDAP_BACK_CFG_ST_REQUEST, 73 LDAP_BACK_CFG_NOREFS, 74 75 LDAP_BACK_CFG_REWRITE, 76 77 LDAP_BACK_CFG_LAST 78 }; 79 80 static ConfigTable ldapcfg[] = { 81 { "uri", "uri", 2, 2, 0, 82 ARG_MAGIC|LDAP_BACK_CFG_URI, 83 ldap_back_cf_gen, "( OLcfgDbAt:0.14 " 84 "NAME 'olcDbURI' " 85 "DESC 'URI (list) for remote DSA' " 86 "SYNTAX OMsDirectoryString " 87 "SINGLE-VALUE )", 88 NULL, NULL }, 89 { "tls", "what", 2, 0, 0, 90 ARG_MAGIC|LDAP_BACK_CFG_TLS, 91 ldap_back_cf_gen, "( OLcfgDbAt:3.1 " 92 "NAME 'olcDbStartTLS' " 93 "DESC 'StartTLS' " 94 "SYNTAX OMsDirectoryString " 95 "SINGLE-VALUE )", 96 NULL, NULL }, 97 { "acl-authcDN", "DN", 2, 2, 0, 98 ARG_DN|ARG_MAGIC|LDAP_BACK_CFG_ACL_AUTHCDN, 99 ldap_back_cf_gen, "( OLcfgDbAt:3.2 " 100 "NAME 'olcDbACLAuthcDn' " 101 "DESC 'Remote ACL administrative identity' " 102 "OBSOLETE " 103 "SYNTAX OMsDN " 104 "SINGLE-VALUE )", 105 NULL, NULL }, 106 /* deprecated, will be removed; aliases "acl-authcDN" */ 107 { "binddn", "DN", 2, 2, 0, 108 ARG_DN|ARG_MAGIC|LDAP_BACK_CFG_ACL_AUTHCDN, 109 ldap_back_cf_gen, NULL, NULL, NULL }, 110 { "acl-passwd", "cred", 2, 2, 0, 111 ARG_MAGIC|LDAP_BACK_CFG_ACL_PASSWD, 112 ldap_back_cf_gen, "( OLcfgDbAt:3.3 " 113 "NAME 'olcDbACLPasswd' " 114 "DESC 'Remote ACL administrative identity credentials' " 115 "OBSOLETE " 116 "SYNTAX OMsDirectoryString " 117 "SINGLE-VALUE )", 118 NULL, NULL }, 119 /* deprecated, will be removed; aliases "acl-passwd" */ 120 { "bindpw", "cred", 2, 2, 0, 121 ARG_MAGIC|LDAP_BACK_CFG_ACL_PASSWD, 122 ldap_back_cf_gen, NULL, NULL, NULL }, 123 /* deprecated, will be removed; aliases "acl-bind" */ 124 { "acl-method", "args", 2, 0, 0, 125 ARG_MAGIC|LDAP_BACK_CFG_ACL_METHOD, 126 ldap_back_cf_gen, NULL, NULL, NULL }, 127 { "acl-bind", "args", 2, 0, 0, 128 ARG_MAGIC|LDAP_BACK_CFG_ACL_BIND, 129 ldap_back_cf_gen, "( OLcfgDbAt:3.4 " 130 "NAME 'olcDbACLBind' " 131 "DESC 'Remote ACL administrative identity auth bind configuration' " 132 "SYNTAX OMsDirectoryString " 133 "SINGLE-VALUE )", 134 NULL, NULL }, 135 { "idassert-authcDN", "DN", 2, 2, 0, 136 ARG_DN|ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_AUTHCDN, 137 ldap_back_cf_gen, "( OLcfgDbAt:3.5 " 138 "NAME 'olcDbIDAssertAuthcDn' " 139 "DESC 'Remote Identity Assertion administrative identity' " 140 "OBSOLETE " 141 "SYNTAX OMsDN " 142 "SINGLE-VALUE )", 143 NULL, NULL }, 144 /* deprecated, will be removed; partially aliases "idassert-authcDN" */ 145 { "proxyauthzdn", "DN", 2, 2, 0, 146 ARG_DN|ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_AUTHCDN, 147 ldap_back_cf_gen, NULL, NULL, NULL }, 148 { "idassert-passwd", "cred", 2, 2, 0, 149 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_PASSWD, 150 ldap_back_cf_gen, "( OLcfgDbAt:3.6 " 151 "NAME 'olcDbIDAssertPasswd' " 152 "DESC 'Remote Identity Assertion administrative identity credentials' " 153 "OBSOLETE " 154 "SYNTAX OMsDirectoryString " 155 "SINGLE-VALUE )", 156 NULL, NULL }, 157 /* deprecated, will be removed; partially aliases "idassert-passwd" */ 158 { "proxyauthzpw", "cred", 2, 2, 0, 159 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_PASSWD, 160 ldap_back_cf_gen, NULL, NULL, NULL }, 161 { "idassert-bind", "args", 2, 0, 0, 162 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_BIND, 163 ldap_back_cf_gen, "( OLcfgDbAt:3.7 " 164 "NAME 'olcDbIDAssertBind' " 165 "DESC 'Remote Identity Assertion administrative identity auth bind configuration' " 166 "SYNTAX OMsDirectoryString " 167 "SINGLE-VALUE )", 168 NULL, NULL }, 169 { "idassert-method", "args", 2, 0, 0, 170 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_METHOD, 171 ldap_back_cf_gen, NULL, NULL, NULL }, 172 { "idassert-mode", "mode>|u:<user>|[dn:]<DN", 2, 0, 0, 173 ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_MODE, 174 ldap_back_cf_gen, "( OLcfgDbAt:3.8 " 175 "NAME 'olcDbIDAssertMode' " 176 "DESC 'Remote Identity Assertion mode' " 177 "OBSOLETE " 178 "SYNTAX OMsDirectoryString " 179 "SINGLE-VALUE)", 180 NULL, NULL }, 181 { "idassert-authzFrom", "authzRule", 2, 2, 0, 182 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_AUTHZFROM, 183 ldap_back_cf_gen, "( OLcfgDbAt:3.9 " 184 "NAME 'olcDbIDAssertAuthzFrom' " 185 "DESC 'Remote Identity Assertion authz rules' " 186 "SYNTAX OMsDirectoryString " 187 "X-ORDERED 'VALUES' )", 188 NULL, NULL }, 189 { "rebind-as-user", "true|FALSE", 1, 2, 0, 190 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_REBIND, 191 ldap_back_cf_gen, "( OLcfgDbAt:3.10 " 192 "NAME 'olcDbRebindAsUser' " 193 "DESC 'Rebind as user' " 194 "SYNTAX OMsBoolean " 195 "SINGLE-VALUE )", 196 NULL, NULL }, 197 { "chase-referrals", "true|FALSE", 2, 2, 0, 198 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_CHASE, 199 ldap_back_cf_gen, "( OLcfgDbAt:3.11 " 200 "NAME 'olcDbChaseReferrals' " 201 "DESC 'Chase referrals' " 202 "SYNTAX OMsBoolean " 203 "SINGLE-VALUE )", 204 NULL, NULL }, 205 { "t-f-support", "true|FALSE|discover", 2, 2, 0, 206 ARG_MAGIC|LDAP_BACK_CFG_T_F, 207 ldap_back_cf_gen, "( OLcfgDbAt:3.12 " 208 "NAME 'olcDbTFSupport' " 209 "DESC 'Absolute filters support' " 210 "SYNTAX OMsDirectoryString " 211 "SINGLE-VALUE )", 212 NULL, NULL }, 213 { "proxy-whoami", "true|FALSE", 1, 2, 0, 214 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_WHOAMI, 215 ldap_back_cf_gen, "( OLcfgDbAt:3.13 " 216 "NAME 'olcDbProxyWhoAmI' " 217 "DESC 'Proxy whoAmI exop' " 218 "SYNTAX OMsBoolean " 219 "SINGLE-VALUE )", 220 NULL, NULL }, 221 { "timeout", "timeout(list)", 2, 0, 0, 222 ARG_MAGIC|LDAP_BACK_CFG_TIMEOUT, 223 ldap_back_cf_gen, "( OLcfgDbAt:3.14 " 224 "NAME 'olcDbTimeout' " 225 "DESC 'Per-operation timeouts' " 226 "SYNTAX OMsDirectoryString " 227 "SINGLE-VALUE )", 228 NULL, NULL }, 229 { "idle-timeout", "timeout", 2, 2, 0, 230 ARG_MAGIC|LDAP_BACK_CFG_IDLE_TIMEOUT, 231 ldap_back_cf_gen, "( OLcfgDbAt:3.15 " 232 "NAME 'olcDbIdleTimeout' " 233 "DESC 'connection idle timeout' " 234 "SYNTAX OMsDirectoryString " 235 "SINGLE-VALUE )", 236 NULL, NULL }, 237 { "conn-ttl", "ttl", 2, 2, 0, 238 ARG_MAGIC|LDAP_BACK_CFG_CONN_TTL, 239 ldap_back_cf_gen, "( OLcfgDbAt:3.16 " 240 "NAME 'olcDbConnTtl' " 241 "DESC 'connection ttl' " 242 "SYNTAX OMsDirectoryString " 243 "SINGLE-VALUE )", 244 NULL, NULL }, 245 { "network-timeout", "timeout", 2, 2, 0, 246 ARG_MAGIC|LDAP_BACK_CFG_NETWORK_TIMEOUT, 247 ldap_back_cf_gen, "( OLcfgDbAt:3.17 " 248 "NAME 'olcDbNetworkTimeout' " 249 "DESC 'connection network timeout' " 250 "SYNTAX OMsDirectoryString " 251 "SINGLE-VALUE )", 252 NULL, NULL }, 253 { "protocol-version", "version", 2, 2, 0, 254 ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_VERSION, 255 ldap_back_cf_gen, "( OLcfgDbAt:3.18 " 256 "NAME 'olcDbProtocolVersion' " 257 "DESC 'protocol version' " 258 "SYNTAX OMsInteger " 259 "SINGLE-VALUE )", 260 NULL, NULL }, 261 { "single-conn", "true|FALSE", 2, 2, 0, 262 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_SINGLECONN, 263 ldap_back_cf_gen, "( OLcfgDbAt:3.19 " 264 "NAME 'olcDbSingleConn' " 265 "DESC 'cache a single connection per identity' " 266 "SYNTAX OMsBoolean " 267 "SINGLE-VALUE )", 268 NULL, NULL }, 269 { "cancel", "ABANDON|ignore|exop", 2, 2, 0, 270 ARG_MAGIC|LDAP_BACK_CFG_CANCEL, 271 ldap_back_cf_gen, "( OLcfgDbAt:3.20 " 272 "NAME 'olcDbCancel' " 273 "DESC 'abandon/ignore/exop operations when appropriate' " 274 "SYNTAX OMsDirectoryString " 275 "SINGLE-VALUE )", 276 NULL, NULL }, 277 { "quarantine", "retrylist", 2, 2, 0, 278 ARG_MAGIC|LDAP_BACK_CFG_QUARANTINE, 279 ldap_back_cf_gen, "( OLcfgDbAt:3.21 " 280 "NAME 'olcDbQuarantine' " 281 "DESC 'Quarantine database if connection fails and retry according to rule' " 282 "SYNTAX OMsDirectoryString " 283 "SINGLE-VALUE )", 284 NULL, NULL }, 285 { "use-temporary-conn", "true|FALSE", 2, 2, 0, 286 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_USETEMP, 287 ldap_back_cf_gen, "( OLcfgDbAt:3.22 " 288 "NAME 'olcDbUseTemporaryConn' " 289 "DESC 'Use temporary connections if the cached one is busy' " 290 "SYNTAX OMsBoolean " 291 "SINGLE-VALUE )", 292 NULL, NULL }, 293 { "conn-pool-max", "<n>", 2, 2, 0, 294 ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_CONNPOOLMAX, 295 ldap_back_cf_gen, "( OLcfgDbAt:3.23 " 296 "NAME 'olcDbConnectionPoolMax' " 297 "DESC 'Max size of privileged connections pool' " 298 "SYNTAX OMsInteger " 299 "SINGLE-VALUE )", 300 NULL, NULL }, 301 #ifdef SLAP_CONTROL_X_SESSION_TRACKING 302 { "session-tracking-request", "true|FALSE", 2, 2, 0, 303 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_ST_REQUEST, 304 ldap_back_cf_gen, "( OLcfgDbAt:3.24 " 305 "NAME 'olcDbSessionTrackingRequest' " 306 "DESC 'Add session tracking control to proxied requests' " 307 "SYNTAX OMsBoolean " 308 "SINGLE-VALUE )", 309 NULL, NULL }, 310 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 311 { "norefs", "true|FALSE", 2, 2, 0, 312 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_NOREFS, 313 ldap_back_cf_gen, "( OLcfgDbAt:3.25 " 314 "NAME 'olcDbNorefs' " 315 "DESC 'Do not return search reference responses' " 316 "SYNTAX OMsBoolean " 317 "SINGLE-VALUE )", 318 NULL, NULL }, 319 { "suffixmassage", "[virtual]> <real", 2, 3, 0, 320 ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE, 321 ldap_back_cf_gen, NULL, NULL, NULL }, 322 { "map", "attribute|objectClass> [*|<local>] *|<remote", 3, 4, 0, 323 ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE, 324 ldap_back_cf_gen, NULL, NULL, NULL }, 325 { "rewrite", "<arglist>", 2, 4, STRLENOF( "rewrite" ), 326 ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE, 327 ldap_back_cf_gen, NULL, NULL, NULL }, 328 { NULL, NULL, 0, 0, 0, ARG_IGNORED, 329 NULL, NULL, NULL, NULL } 330 }; 331 332 static ConfigOCs ldapocs[] = { 333 { "( OLcfgDbOc:3.1 " 334 "NAME 'olcLDAPConfig' " 335 "DESC 'LDAP backend configuration' " 336 "SUP olcDatabaseConfig " 337 "MAY ( olcDbURI " 338 "$ olcDbStartTLS " 339 "$ olcDbACLAuthcDn " 340 "$ olcDbACLPasswd " 341 "$ olcDbACLBind " 342 "$ olcDbIDAssertAuthcDn " 343 "$ olcDbIDAssertPasswd " 344 "$ olcDbIDAssertBind " 345 "$ olcDbIDAssertMode " 346 "$ olcDbIDAssertAuthzFrom " 347 "$ olcDbRebindAsUser " 348 "$ olcDbChaseReferrals " 349 "$ olcDbTFSupport " 350 "$ olcDbProxyWhoAmI " 351 "$ olcDbTimeout " 352 "$ olcDbIdleTimeout " 353 "$ olcDbSingleConn " 354 "$ olcDbCancel " 355 "$ olcDbQuarantine " 356 "$ olcDbUseTemporaryConn " 357 "$ olcDbConnectionPoolMax " 358 #ifdef SLAP_CONTROL_X_SESSION_TRACKING 359 "$ olcDbSessionTrackingRequest " 360 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 361 "$ olcDbNorefs " 362 ") )", 363 Cft_Database, ldapcfg}, 364 { NULL, 0, NULL } 365 }; 366 367 static slap_verbmasks idassert_mode[] = { 368 { BER_BVC("self"), LDAP_BACK_IDASSERT_SELF }, 369 { BER_BVC("anonymous"), LDAP_BACK_IDASSERT_ANONYMOUS }, 370 { BER_BVC("none"), LDAP_BACK_IDASSERT_NOASSERT }, 371 { BER_BVC("legacy"), LDAP_BACK_IDASSERT_LEGACY }, 372 { BER_BVNULL, 0 } 373 }; 374 375 static slap_verbmasks tls_mode[] = { 376 { BER_BVC( "propagate" ), LDAP_BACK_F_TLS_PROPAGATE_MASK }, 377 { BER_BVC( "try-propagate" ), LDAP_BACK_F_PROPAGATE_TLS }, 378 { BER_BVC( "start" ), LDAP_BACK_F_TLS_USE_MASK }, 379 { BER_BVC( "try-start" ), LDAP_BACK_F_USE_TLS }, 380 { BER_BVC( "ldaps" ), LDAP_BACK_F_TLS_LDAPS }, 381 { BER_BVC( "none" ), LDAP_BACK_F_NONE }, 382 { BER_BVNULL, 0 } 383 }; 384 385 static slap_verbmasks t_f_mode[] = { 386 { BER_BVC( "yes" ), LDAP_BACK_F_T_F }, 387 { BER_BVC( "discover" ), LDAP_BACK_F_T_F_DISCOVER }, 388 { BER_BVC( "no" ), LDAP_BACK_F_NONE }, 389 { BER_BVNULL, 0 } 390 }; 391 392 static slap_verbmasks cancel_mode[] = { 393 { BER_BVC( "ignore" ), LDAP_BACK_F_CANCEL_IGNORE }, 394 { BER_BVC( "exop" ), LDAP_BACK_F_CANCEL_EXOP }, 395 { BER_BVC( "exop-discover" ), LDAP_BACK_F_CANCEL_EXOP_DISCOVER }, 396 { BER_BVC( "abandon" ), LDAP_BACK_F_CANCEL_ABANDON }, 397 { BER_BVNULL, 0 } 398 }; 399 400 /* see enum in slap.h */ 401 static slap_cf_aux_table timeout_table[] = { 402 { BER_BVC("bind="), SLAP_OP_BIND * sizeof( time_t ), 'u', 0, NULL }, 403 /* unbind makes no sense */ 404 { BER_BVC("add="), SLAP_OP_ADD * sizeof( time_t ), 'u', 0, NULL }, 405 { BER_BVC("delete="), SLAP_OP_DELETE * sizeof( time_t ), 'u', 0, NULL }, 406 { BER_BVC("modrdn="), SLAP_OP_MODRDN * sizeof( time_t ), 'u', 0, NULL }, 407 { BER_BVC("modify="), SLAP_OP_MODIFY * sizeof( time_t ), 'u', 0, NULL }, 408 { BER_BVC("compare="), SLAP_OP_COMPARE * sizeof( time_t ), 'u', 0, NULL }, 409 { BER_BVC("search="), SLAP_OP_SEARCH * sizeof( time_t ), 'u', 0, NULL }, 410 /* abandon makes little sense */ 411 #if 0 /* not implemented yet */ 412 { BER_BVC("extended="), SLAP_OP_EXTENDED * sizeof( time_t ), 'u', 0, NULL }, 413 #endif 414 { BER_BVNULL, 0, 0, 0, NULL } 415 }; 416 417 int 418 slap_retry_info_parse( 419 char *in, 420 slap_retry_info_t *ri, 421 char *buf, 422 ber_len_t buflen ) 423 { 424 char **retrylist = NULL; 425 int rc = 0; 426 int i; 427 428 slap_str2clist( &retrylist, in, " ;" ); 429 if ( retrylist == NULL ) { 430 return 1; 431 } 432 433 for ( i = 0; retrylist[ i ] != NULL; i++ ) 434 /* count */ ; 435 436 ri->ri_interval = ch_calloc( sizeof( time_t ), i + 1 ); 437 ri->ri_num = ch_calloc( sizeof( int ), i + 1 ); 438 439 for ( i = 0; retrylist[ i ] != NULL; i++ ) { 440 unsigned long t; 441 char *sep = strchr( retrylist[ i ], ',' ); 442 443 if ( sep == NULL ) { 444 snprintf( buf, buflen, 445 "missing comma in retry pattern #%d \"%s\"", 446 i, retrylist[ i ] ); 447 rc = 1; 448 goto done; 449 } 450 451 *sep++ = '\0'; 452 453 if ( lutil_parse_time( retrylist[ i ], &t ) ) { 454 snprintf( buf, buflen, 455 "unable to parse interval #%d \"%s\"", 456 i, retrylist[ i ] ); 457 rc = 1; 458 goto done; 459 } 460 ri->ri_interval[ i ] = (time_t)t; 461 462 if ( strcmp( sep, "+" ) == 0 ) { 463 if ( retrylist[ i + 1 ] != NULL ) { 464 snprintf( buf, buflen, 465 "extra cruft after retry pattern " 466 "#%d \"%s,+\" with \"forever\" mark", 467 i, retrylist[ i ] ); 468 rc = 1; 469 goto done; 470 } 471 ri->ri_num[ i ] = SLAP_RETRYNUM_FOREVER; 472 473 } else if ( lutil_atoi( &ri->ri_num[ i ], sep ) ) { 474 snprintf( buf, buflen, 475 "unable to parse retry num #%d \"%s\"", 476 i, sep ); 477 rc = 1; 478 goto done; 479 } 480 } 481 482 ri->ri_num[ i ] = SLAP_RETRYNUM_TAIL; 483 484 ri->ri_idx = 0; 485 ri->ri_count = 0; 486 ri->ri_last = (time_t)(-1); 487 488 done:; 489 ldap_charray_free( retrylist ); 490 491 if ( rc ) { 492 slap_retry_info_destroy( ri ); 493 } 494 495 return rc; 496 } 497 498 int 499 slap_retry_info_unparse( 500 slap_retry_info_t *ri, 501 struct berval *bvout ) 502 { 503 int i; 504 char buf[ BUFSIZ * 2 ], 505 *ptr = buf; 506 struct berval bv = BER_BVNULL; 507 508 assert( ri != NULL ); 509 assert( bvout != NULL ); 510 511 BER_BVZERO( bvout ); 512 513 #define WHATSLEFT ( sizeof( buf ) - ( ptr - buf ) ) 514 515 for ( i = 0; ri->ri_num[ i ] != SLAP_RETRYNUM_TAIL; i++ ) { 516 if ( i > 0 ) { 517 if ( WHATSLEFT <= 1 ) { 518 return 1; 519 } 520 *ptr++ = ';'; 521 } 522 523 if ( lutil_unparse_time( ptr, WHATSLEFT, (long)ri->ri_interval[i] ) ) { 524 return 1; 525 } 526 ptr += strlen( ptr ); 527 528 if ( WHATSLEFT <= 1 ) { 529 return 1; 530 } 531 *ptr++ = ','; 532 533 if ( ri->ri_num[i] == SLAP_RETRYNUM_FOREVER ) { 534 if ( WHATSLEFT <= 1 ) { 535 return 1; 536 } 537 *ptr++ = '+'; 538 539 } else { 540 ptr += snprintf( ptr, WHATSLEFT, "%d", ri->ri_num[i] ); 541 if ( WHATSLEFT <= 0 ) { 542 return 1; 543 } 544 } 545 } 546 547 bv.bv_val = buf; 548 bv.bv_len = ptr - buf; 549 550 ber_dupbv( bvout, &bv ); 551 552 return 0; 553 } 554 555 void 556 slap_retry_info_destroy( 557 slap_retry_info_t *ri ) 558 { 559 assert( ri != NULL ); 560 561 assert( ri->ri_interval != NULL ); 562 ch_free( ri->ri_interval ); 563 ri->ri_interval = NULL; 564 565 assert( ri->ri_num != NULL ); 566 ch_free( ri->ri_num ); 567 ri->ri_num = NULL; 568 } 569 570 static int 571 slap_idassert_authzfrom_parse( ConfigArgs *c, slap_idassert_t *si ) 572 { 573 struct berval bv; 574 struct berval in; 575 int rc; 576 577 if ( strcmp( c->argv[ 1 ], "*" ) == 0 578 || strcmp( c->argv[ 1 ], "dn:*" ) == 0 579 || strcasecmp( c->argv[ 1 ], "dn.regex:.*" ) == 0 ) 580 { 581 if ( si->si_authz != NULL ) { 582 snprintf( c->cr_msg, sizeof( c->cr_msg ), 583 "\"idassert-authzFrom <authz>\": " 584 "\"%s\" conflicts with existing authz rules", 585 c->argv[ 1 ] ); 586 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 587 return 1; 588 } 589 590 si->si_flags |= LDAP_BACK_AUTH_AUTHZ_ALL; 591 592 return 0; 593 594 } else if ( ( si->si_flags & LDAP_BACK_AUTH_AUTHZ_ALL ) ) { 595 snprintf( c->cr_msg, sizeof( c->cr_msg ), 596 "\"idassert-authzFrom <authz>\": " 597 "\"<authz>\" conflicts with \"*\"" ); 598 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 599 return 1; 600 } 601 602 ber_str2bv( c->argv[ 1 ], 0, 0, &in ); 603 rc = authzNormalize( 0, NULL, NULL, &in, &bv, NULL ); 604 if ( rc != LDAP_SUCCESS ) { 605 snprintf( c->cr_msg, sizeof( c->cr_msg ), 606 "\"idassert-authzFrom <authz>\": " 607 "invalid syntax" ); 608 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 609 return 1; 610 } 611 612 ber_bvarray_add( &si->si_authz, &bv ); 613 614 return 0; 615 } 616 617 static int 618 slap_idassert_parse( ConfigArgs *c, slap_idassert_t *si ) 619 { 620 int i; 621 622 for ( i = 1; i < c->argc; i++ ) { 623 if ( strncasecmp( c->argv[ i ], "mode=", STRLENOF( "mode=" ) ) == 0 ) { 624 char *argvi = c->argv[ i ] + STRLENOF( "mode=" ); 625 int j; 626 627 j = verb_to_mask( argvi, idassert_mode ); 628 if ( BER_BVISNULL( &idassert_mode[ j ].word ) ) { 629 snprintf( c->cr_msg, sizeof( c->cr_msg ), 630 "\"idassert-bind <args>\": " 631 "unknown mode \"%s\"", 632 argvi ); 633 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 634 return 1; 635 } 636 637 si->si_mode = idassert_mode[ j ].mask; 638 639 } else if ( strncasecmp( c->argv[ i ], "authz=", STRLENOF( "authz=" ) ) == 0 ) { 640 char *argvi = c->argv[ i ] + STRLENOF( "authz=" ); 641 642 if ( strcasecmp( argvi, "native" ) == 0 ) { 643 if ( si->si_bc.sb_method != LDAP_AUTH_SASL ) { 644 snprintf( c->cr_msg, sizeof( c->cr_msg ), 645 "\"idassert-bind <args>\": " 646 "authz=\"native\" incompatible " 647 "with auth method" ); 648 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 649 return 1; 650 } 651 si->si_flags |= LDAP_BACK_AUTH_NATIVE_AUTHZ; 652 653 } else if ( strcasecmp( argvi, "proxyAuthz" ) == 0 ) { 654 si->si_flags &= ~LDAP_BACK_AUTH_NATIVE_AUTHZ; 655 656 } else { 657 snprintf( c->cr_msg, sizeof( c->cr_msg ), 658 "\"idassert-bind <args>\": " 659 "unknown authz \"%s\"", 660 argvi ); 661 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 662 return 1; 663 } 664 665 } else if ( strncasecmp( c->argv[ i ], "flags=", STRLENOF( "flags=" ) ) == 0 ) { 666 char *argvi = c->argv[ i ] + STRLENOF( "flags=" ); 667 char **flags = ldap_str2charray( argvi, "," ); 668 int j, err = 0; 669 670 if ( flags == NULL ) { 671 snprintf( c->cr_msg, sizeof( c->cr_msg ), 672 "\"idassert-bind <args>\": " 673 "unable to parse flags \"%s\"", 674 argvi ); 675 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 676 return 1; 677 } 678 679 for ( j = 0; flags[ j ] != NULL; j++ ) { 680 681 if ( strcasecmp( flags[ j ], "override" ) == 0 ) { 682 si->si_flags |= LDAP_BACK_AUTH_OVERRIDE; 683 684 } else if ( strcasecmp( flags[ j ], "prescriptive" ) == 0 ) { 685 si->si_flags |= LDAP_BACK_AUTH_PRESCRIPTIVE; 686 687 } else if ( strcasecmp( flags[ j ], "non-prescriptive" ) == 0 ) { 688 si->si_flags &= ( ~LDAP_BACK_AUTH_PRESCRIPTIVE ); 689 690 } else if ( strcasecmp( flags[ j ], "obsolete-proxy-authz" ) == 0 ) { 691 if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) { 692 Debug( LDAP_DEBUG_ANY, 693 "%s: \"obsolete-proxy-authz\" flag " 694 "in \"idassert-mode <args>\" " 695 "incompatible with previously issued \"obsolete-encoding-workaround\" flag.\n", 696 c->log, 0, 0 ); 697 err = 1; 698 break; 699 700 } else { 701 si->si_flags |= LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ; 702 } 703 704 } else if ( strcasecmp( flags[ j ], "obsolete-encoding-workaround" ) == 0 ) { 705 if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) { 706 Debug( LDAP_DEBUG_ANY, 707 "%s: \"obsolete-encoding-workaround\" flag " 708 "in \"idassert-mode <args>\" " 709 "incompatible with previously issued \"obsolete-proxy-authz\" flag.\n", 710 c->log, 0, 0 ); 711 err = 1; 712 break; 713 714 } else { 715 si->si_flags |= LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND; 716 } 717 718 } else { 719 snprintf( c->cr_msg, sizeof( c->cr_msg ), 720 "\"idassert-bind <args>\": " 721 "unknown flag \"%s\"", 722 flags[ j ] ); 723 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 724 err = 1; 725 break; 726 } 727 } 728 729 ldap_charray_free( flags ); 730 if ( err ) { 731 return 1; 732 } 733 734 } else if ( bindconf_parse( c->argv[ i ], &si->si_bc ) ) { 735 return 1; 736 } 737 } 738 bindconf_tls_defaults( &si->si_bc ); 739 740 return 0; 741 } 742 743 /* NOTE: temporary, until back-meta is ported to back-config */ 744 int 745 slap_idassert_authzfrom_parse_cf( const char *fname, int lineno, const char *arg, slap_idassert_t *si ) 746 { 747 ConfigArgs c = { 0 }; 748 char *argv[ 3 ]; 749 750 snprintf( c.log, sizeof( c.log ), "%s: line %d", fname, lineno ); 751 c.argc = 2; 752 c.argv = argv; 753 argv[ 0 ] = "idassert-authzFrom"; 754 argv[ 1 ] = (char *)arg; 755 argv[ 2 ] = NULL; 756 757 return slap_idassert_authzfrom_parse( &c, si ); 758 } 759 760 int 761 slap_idassert_parse_cf( const char *fname, int lineno, int argc, char *argv[], slap_idassert_t *si ) 762 { 763 ConfigArgs c = { 0 }; 764 765 snprintf( c.log, sizeof( c.log ), "%s: line %d", fname, lineno ); 766 c.argc = argc; 767 c.argv = argv; 768 769 return slap_idassert_parse( &c, si ); 770 } 771 772 static int 773 ldap_back_cf_gen( ConfigArgs *c ) 774 { 775 ldapinfo_t *li = ( ldapinfo_t * )c->be->be_private; 776 int rc = 0; 777 int i; 778 779 if ( c->op == SLAP_CONFIG_EMIT ) { 780 struct berval bv = BER_BVNULL; 781 782 if ( li == NULL ) { 783 return 1; 784 } 785 786 switch( c->type ) { 787 case LDAP_BACK_CFG_URI: 788 if ( li->li_uri != NULL ) { 789 struct berval bv, bv2; 790 791 ber_str2bv( li->li_uri, 0, 0, &bv ); 792 bv2.bv_len = bv.bv_len + STRLENOF( "\"\"" ); 793 bv2.bv_val = ch_malloc( bv2.bv_len + 1 ); 794 snprintf( bv2.bv_val, bv2.bv_len + 1, 795 "\"%s\"", bv.bv_val ); 796 ber_bvarray_add( &c->rvalue_vals, &bv2 ); 797 798 } else { 799 rc = 1; 800 } 801 break; 802 803 case LDAP_BACK_CFG_TLS: { 804 struct berval bc = BER_BVNULL, bv2; 805 enum_to_verb( tls_mode, ( li->li_flags & LDAP_BACK_F_TLS_MASK ), &bv ); 806 assert( !BER_BVISNULL( &bv ) ); 807 bindconf_tls_unparse( &li->li_tls, &bc ); 808 809 if ( !BER_BVISEMPTY( &bc )) { 810 bv2.bv_len = bv.bv_len + bc.bv_len + 1; 811 bv2.bv_val = ch_malloc( bv2.bv_len + 1 ); 812 strcpy( bv2.bv_val, bv.bv_val ); 813 bv2.bv_val[bv.bv_len] = ' '; 814 strcpy( &bv2.bv_val[bv.bv_len + 1], bc.bv_val ); 815 ber_bvarray_add( &c->rvalue_vals, &bv2 ); 816 817 } else { 818 value_add_one( &c->rvalue_vals, &bv ); 819 } 820 ber_memfree( bc.bv_val ); 821 } 822 break; 823 824 case LDAP_BACK_CFG_ACL_AUTHCDN: 825 case LDAP_BACK_CFG_ACL_PASSWD: 826 case LDAP_BACK_CFG_ACL_METHOD: 827 /* handled by LDAP_BACK_CFG_ACL_BIND */ 828 rc = 1; 829 break; 830 831 case LDAP_BACK_CFG_ACL_BIND: { 832 int i; 833 834 if ( li->li_acl_authmethod == LDAP_AUTH_NONE ) { 835 return 1; 836 } 837 838 bindconf_unparse( &li->li_acl, &bv ); 839 840 for ( i = 0; isspace( (unsigned char) bv.bv_val[ i ] ); i++ ) 841 /* count spaces */ ; 842 843 if ( i ) { 844 bv.bv_len -= i; 845 AC_MEMCPY( bv.bv_val, &bv.bv_val[ i ], 846 bv.bv_len + 1 ); 847 } 848 849 ber_bvarray_add( &c->rvalue_vals, &bv ); 850 break; 851 } 852 853 case LDAP_BACK_CFG_IDASSERT_MODE: 854 case LDAP_BACK_CFG_IDASSERT_AUTHCDN: 855 case LDAP_BACK_CFG_IDASSERT_PASSWD: 856 case LDAP_BACK_CFG_IDASSERT_METHOD: 857 /* handled by LDAP_BACK_CFG_IDASSERT_BIND */ 858 rc = 1; 859 break; 860 861 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: { 862 int i; 863 864 if ( li->li_idassert_authz == NULL ) { 865 if ( ( li->li_idassert_flags & LDAP_BACK_AUTH_AUTHZ_ALL ) ) { 866 BER_BVSTR( &bv, "*" ); 867 value_add_one( &c->rvalue_vals, &bv ); 868 869 } else { 870 rc = 1; 871 } 872 break; 873 } 874 875 for ( i = 0; !BER_BVISNULL( &li->li_idassert_authz[ i ] ); i++ ) 876 { 877 value_add_one( &c->rvalue_vals, &li->li_idassert_authz[ i ] ); 878 } 879 break; 880 } 881 882 case LDAP_BACK_CFG_IDASSERT_BIND: { 883 int i; 884 struct berval bc = BER_BVNULL; 885 char *ptr; 886 887 if ( li->li_idassert_authmethod == LDAP_AUTH_NONE ) { 888 return 1; 889 } 890 891 if ( li->li_idassert_authmethod != LDAP_AUTH_NONE ) { 892 ber_len_t len; 893 894 switch ( li->li_idassert_mode ) { 895 case LDAP_BACK_IDASSERT_OTHERID: 896 case LDAP_BACK_IDASSERT_OTHERDN: 897 break; 898 899 default: { 900 struct berval mode = BER_BVNULL; 901 902 enum_to_verb( idassert_mode, li->li_idassert_mode, &mode ); 903 if ( BER_BVISNULL( &mode ) ) { 904 /* there's something wrong... */ 905 assert( 0 ); 906 rc = 1; 907 908 } else { 909 bv.bv_len = STRLENOF( "mode=" ) + mode.bv_len; 910 bv.bv_val = ch_malloc( bv.bv_len + 1 ); 911 912 ptr = lutil_strcopy( bv.bv_val, "mode=" ); 913 ptr = lutil_strcopy( ptr, mode.bv_val ); 914 } 915 break; 916 } 917 } 918 919 if ( li->li_idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) { 920 len = bv.bv_len + STRLENOF( "authz=native" ); 921 922 if ( !BER_BVISEMPTY( &bv ) ) { 923 len += STRLENOF( " " ); 924 } 925 926 bv.bv_val = ch_realloc( bv.bv_val, len + 1 ); 927 928 ptr = &bv.bv_val[ bv.bv_len ]; 929 930 if ( !BER_BVISEMPTY( &bv ) ) { 931 ptr = lutil_strcopy( ptr, " " ); 932 } 933 934 (void)lutil_strcopy( ptr, "authz=native" ); 935 } 936 937 len = bv.bv_len + STRLENOF( "flags=non-prescriptive,override,obsolete-encoding-workaround" ); 938 /* flags */ 939 if ( !BER_BVISEMPTY( &bv ) ) { 940 len += STRLENOF( " " ); 941 } 942 943 bv.bv_val = ch_realloc( bv.bv_val, len + 1 ); 944 945 ptr = &bv.bv_val[ bv.bv_len ]; 946 947 if ( !BER_BVISEMPTY( &bv ) ) { 948 ptr = lutil_strcopy( ptr, " " ); 949 } 950 951 ptr = lutil_strcopy( ptr, "flags=" ); 952 953 if ( li->li_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) { 954 ptr = lutil_strcopy( ptr, "prescriptive" ); 955 } else { 956 ptr = lutil_strcopy( ptr, "non-prescriptive" ); 957 } 958 959 if ( li->li_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) { 960 ptr = lutil_strcopy( ptr, ",override" ); 961 } 962 963 if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) { 964 ptr = lutil_strcopy( ptr, ",obsolete-proxy-authz" ); 965 966 } else if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) { 967 ptr = lutil_strcopy( ptr, ",obsolete-encoding-workaround" ); 968 } 969 970 bv.bv_len = ( ptr - bv.bv_val ); 971 /* end-of-flags */ 972 } 973 974 bindconf_unparse( &li->li_idassert.si_bc, &bc ); 975 976 if ( !BER_BVISNULL( &bv ) ) { 977 ber_len_t len = bv.bv_len + bc.bv_len; 978 979 bv.bv_val = ch_realloc( bv.bv_val, len + 1 ); 980 981 assert( bc.bv_val[ 0 ] == ' ' ); 982 983 ptr = lutil_strcopy( &bv.bv_val[ bv.bv_len ], bc.bv_val ); 984 free( bc.bv_val ); 985 bv.bv_len = ptr - bv.bv_val; 986 987 } else { 988 for ( i = 0; isspace( (unsigned char) bc.bv_val[ i ] ); i++ ) 989 /* count spaces */ ; 990 991 if ( i ) { 992 bc.bv_len -= i; 993 AC_MEMCPY( bc.bv_val, &bc.bv_val[ i ], bc.bv_len + 1 ); 994 } 995 996 bv = bc; 997 } 998 999 ber_bvarray_add( &c->rvalue_vals, &bv ); 1000 1001 break; 1002 } 1003 1004 case LDAP_BACK_CFG_REBIND: 1005 c->value_int = LDAP_BACK_SAVECRED( li ); 1006 break; 1007 1008 case LDAP_BACK_CFG_CHASE: 1009 c->value_int = LDAP_BACK_CHASE_REFERRALS( li ); 1010 break; 1011 1012 case LDAP_BACK_CFG_T_F: 1013 enum_to_verb( t_f_mode, (li->li_flags & LDAP_BACK_F_T_F_MASK2), &bv ); 1014 if ( BER_BVISNULL( &bv ) ) { 1015 /* there's something wrong... */ 1016 assert( 0 ); 1017 rc = 1; 1018 1019 } else { 1020 value_add_one( &c->rvalue_vals, &bv ); 1021 } 1022 break; 1023 1024 case LDAP_BACK_CFG_WHOAMI: 1025 c->value_int = LDAP_BACK_PROXY_WHOAMI( li ); 1026 break; 1027 1028 case LDAP_BACK_CFG_TIMEOUT: 1029 BER_BVZERO( &bv ); 1030 1031 for ( i = 0; i < SLAP_OP_LAST; i++ ) { 1032 if ( li->li_timeout[ i ] != 0 ) { 1033 break; 1034 } 1035 } 1036 1037 if ( i == SLAP_OP_LAST ) { 1038 return 1; 1039 } 1040 1041 slap_cf_aux_table_unparse( li->li_timeout, &bv, timeout_table ); 1042 1043 if ( BER_BVISNULL( &bv ) ) { 1044 return 1; 1045 } 1046 1047 for ( i = 0; isspace( (unsigned char) bv.bv_val[ i ] ); i++ ) 1048 /* count spaces */ ; 1049 1050 if ( i ) { 1051 bv.bv_len -= i; 1052 AC_MEMCPY( bv.bv_val, &bv.bv_val[ i ], 1053 bv.bv_len + 1 ); 1054 } 1055 1056 ber_bvarray_add( &c->rvalue_vals, &bv ); 1057 break; 1058 1059 case LDAP_BACK_CFG_IDLE_TIMEOUT: { 1060 char buf[ SLAP_TEXT_BUFLEN ]; 1061 1062 if ( li->li_idle_timeout == 0 ) { 1063 return 1; 1064 } 1065 1066 lutil_unparse_time( buf, sizeof( buf ), li->li_idle_timeout ); 1067 ber_str2bv( buf, 0, 0, &bv ); 1068 value_add_one( &c->rvalue_vals, &bv ); 1069 } break; 1070 1071 case LDAP_BACK_CFG_CONN_TTL: { 1072 char buf[ SLAP_TEXT_BUFLEN ]; 1073 1074 if ( li->li_conn_ttl == 0 ) { 1075 return 1; 1076 } 1077 1078 lutil_unparse_time( buf, sizeof( buf ), li->li_conn_ttl ); 1079 ber_str2bv( buf, 0, 0, &bv ); 1080 value_add_one( &c->rvalue_vals, &bv ); 1081 } break; 1082 1083 case LDAP_BACK_CFG_NETWORK_TIMEOUT: { 1084 char buf[ SLAP_TEXT_BUFLEN ]; 1085 1086 if ( li->li_network_timeout == 0 ) { 1087 return 1; 1088 } 1089 1090 snprintf( buf, sizeof( buf ), "%ld", 1091 (long)li->li_network_timeout ); 1092 ber_str2bv( buf, 0, 0, &bv ); 1093 value_add_one( &c->rvalue_vals, &bv ); 1094 } break; 1095 1096 case LDAP_BACK_CFG_VERSION: 1097 if ( li->li_version == 0 ) { 1098 return 1; 1099 } 1100 1101 c->value_int = li->li_version; 1102 break; 1103 1104 case LDAP_BACK_CFG_SINGLECONN: 1105 c->value_int = LDAP_BACK_SINGLECONN( li ); 1106 break; 1107 1108 case LDAP_BACK_CFG_USETEMP: 1109 c->value_int = LDAP_BACK_USE_TEMPORARIES( li ); 1110 break; 1111 1112 case LDAP_BACK_CFG_CONNPOOLMAX: 1113 c->value_int = li->li_conn_priv_max; 1114 break; 1115 1116 case LDAP_BACK_CFG_CANCEL: { 1117 slap_mask_t mask = LDAP_BACK_F_CANCEL_MASK2; 1118 1119 if ( LDAP_BACK_CANCEL_DISCOVER( li ) ) { 1120 mask &= ~LDAP_BACK_F_CANCEL_EXOP; 1121 } 1122 enum_to_verb( cancel_mode, (li->li_flags & mask), &bv ); 1123 if ( BER_BVISNULL( &bv ) ) { 1124 /* there's something wrong... */ 1125 assert( 0 ); 1126 rc = 1; 1127 1128 } else { 1129 value_add_one( &c->rvalue_vals, &bv ); 1130 } 1131 } break; 1132 1133 case LDAP_BACK_CFG_QUARANTINE: 1134 if ( !LDAP_BACK_QUARANTINE( li ) ) { 1135 rc = 1; 1136 break; 1137 } 1138 1139 rc = slap_retry_info_unparse( &li->li_quarantine, &bv ); 1140 if ( rc == 0 ) { 1141 ber_bvarray_add( &c->rvalue_vals, &bv ); 1142 } 1143 break; 1144 1145 #ifdef SLAP_CONTROL_X_SESSION_TRACKING 1146 case LDAP_BACK_CFG_ST_REQUEST: 1147 c->value_int = LDAP_BACK_ST_REQUEST( li ); 1148 break; 1149 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 1150 1151 case LDAP_BACK_CFG_NOREFS: 1152 c->value_int = LDAP_BACK_NOREFS( li ); 1153 break; 1154 1155 default: 1156 /* FIXME: we need to handle all... */ 1157 assert( 0 ); 1158 break; 1159 } 1160 return rc; 1161 1162 } else if ( c->op == LDAP_MOD_DELETE ) { 1163 switch( c->type ) { 1164 case LDAP_BACK_CFG_URI: 1165 if ( li->li_uri != NULL ) { 1166 ch_free( li->li_uri ); 1167 li->li_uri = NULL; 1168 1169 assert( li->li_bvuri != NULL ); 1170 ber_bvarray_free( li->li_bvuri ); 1171 li->li_bvuri = NULL; 1172 } 1173 1174 /* better cleanup the cached connections... */ 1175 /* NOTE: don't worry about locking: if we got here, 1176 * other threads are suspended. */ 1177 if ( li->li_conninfo.lai_tree != NULL ) { 1178 avl_free( li->li_conninfo.lai_tree, ldap_back_conn_free ); 1179 li->li_conninfo.lai_tree = NULL; 1180 } 1181 1182 break; 1183 1184 case LDAP_BACK_CFG_TLS: 1185 rc = 1; 1186 break; 1187 1188 case LDAP_BACK_CFG_ACL_AUTHCDN: 1189 case LDAP_BACK_CFG_ACL_PASSWD: 1190 case LDAP_BACK_CFG_ACL_METHOD: 1191 /* handled by LDAP_BACK_CFG_ACL_BIND */ 1192 rc = 1; 1193 break; 1194 1195 case LDAP_BACK_CFG_ACL_BIND: 1196 bindconf_free( &li->li_acl ); 1197 break; 1198 1199 case LDAP_BACK_CFG_IDASSERT_MODE: 1200 case LDAP_BACK_CFG_IDASSERT_AUTHCDN: 1201 case LDAP_BACK_CFG_IDASSERT_PASSWD: 1202 case LDAP_BACK_CFG_IDASSERT_METHOD: 1203 /* handled by LDAP_BACK_CFG_IDASSERT_BIND */ 1204 rc = 1; 1205 break; 1206 1207 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: 1208 if ( li->li_idassert_authz != NULL ) { 1209 ber_bvarray_free( li->li_idassert_authz ); 1210 li->li_idassert_authz = NULL; 1211 } 1212 break; 1213 1214 case LDAP_BACK_CFG_IDASSERT_BIND: 1215 bindconf_free( &li->li_idassert.si_bc ); 1216 break; 1217 1218 case LDAP_BACK_CFG_REBIND: 1219 case LDAP_BACK_CFG_CHASE: 1220 case LDAP_BACK_CFG_T_F: 1221 case LDAP_BACK_CFG_WHOAMI: 1222 case LDAP_BACK_CFG_CANCEL: 1223 rc = 1; 1224 break; 1225 1226 case LDAP_BACK_CFG_TIMEOUT: 1227 for ( i = 0; i < SLAP_OP_LAST; i++ ) { 1228 li->li_timeout[ i ] = 0; 1229 } 1230 break; 1231 1232 case LDAP_BACK_CFG_IDLE_TIMEOUT: 1233 li->li_idle_timeout = 0; 1234 break; 1235 1236 case LDAP_BACK_CFG_CONN_TTL: 1237 li->li_conn_ttl = 0; 1238 break; 1239 1240 case LDAP_BACK_CFG_NETWORK_TIMEOUT: 1241 li->li_network_timeout = 0; 1242 break; 1243 1244 case LDAP_BACK_CFG_VERSION: 1245 li->li_version = 0; 1246 break; 1247 1248 case LDAP_BACK_CFG_SINGLECONN: 1249 li->li_flags &= ~LDAP_BACK_F_SINGLECONN; 1250 break; 1251 1252 case LDAP_BACK_CFG_USETEMP: 1253 li->li_flags &= ~LDAP_BACK_F_USE_TEMPORARIES; 1254 break; 1255 1256 case LDAP_BACK_CFG_CONNPOOLMAX: 1257 li->li_conn_priv_max = LDAP_BACK_CONN_PRIV_MIN; 1258 break; 1259 1260 case LDAP_BACK_CFG_QUARANTINE: 1261 if ( !LDAP_BACK_QUARANTINE( li ) ) { 1262 break; 1263 } 1264 1265 slap_retry_info_destroy( &li->li_quarantine ); 1266 ldap_pvt_thread_mutex_destroy( &li->li_quarantine_mutex ); 1267 li->li_isquarantined = 0; 1268 li->li_flags &= ~LDAP_BACK_F_QUARANTINE; 1269 break; 1270 1271 #ifdef SLAP_CONTROL_X_SESSION_TRACKING 1272 case LDAP_BACK_CFG_ST_REQUEST: 1273 li->li_flags &= ~LDAP_BACK_F_ST_REQUEST; 1274 break; 1275 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 1276 1277 case LDAP_BACK_CFG_NOREFS: 1278 li->li_flags &= ~LDAP_BACK_F_NOREFS; 1279 break; 1280 1281 default: 1282 /* FIXME: we need to handle all... */ 1283 assert( 0 ); 1284 break; 1285 } 1286 return rc; 1287 1288 } 1289 1290 switch( c->type ) { 1291 case LDAP_BACK_CFG_URI: { 1292 LDAPURLDesc *tmpludp, *lud; 1293 char **urllist = NULL; 1294 int urlrc = LDAP_URL_SUCCESS, i; 1295 1296 if ( li->li_uri != NULL ) { 1297 ch_free( li->li_uri ); 1298 li->li_uri = NULL; 1299 1300 assert( li->li_bvuri != NULL ); 1301 ber_bvarray_free( li->li_bvuri ); 1302 li->li_bvuri = NULL; 1303 } 1304 1305 /* PARANOID: DN and more are not required nor allowed */ 1306 urlrc = ldap_url_parselist_ext( &lud, c->argv[ 1 ], ", \t", LDAP_PVT_URL_PARSE_NONE ); 1307 if ( urlrc != LDAP_URL_SUCCESS ) { 1308 char *why; 1309 1310 switch ( urlrc ) { 1311 case LDAP_URL_ERR_MEM: 1312 why = "no memory"; 1313 break; 1314 case LDAP_URL_ERR_PARAM: 1315 why = "parameter is bad"; 1316 break; 1317 case LDAP_URL_ERR_BADSCHEME: 1318 why = "URL doesn't begin with \"[c]ldap[si]://\""; 1319 break; 1320 case LDAP_URL_ERR_BADENCLOSURE: 1321 why = "URL is missing trailing \">\""; 1322 break; 1323 case LDAP_URL_ERR_BADURL: 1324 why = "URL is bad"; 1325 break; 1326 case LDAP_URL_ERR_BADHOST: 1327 why = "host/port is bad"; 1328 break; 1329 case LDAP_URL_ERR_BADATTRS: 1330 why = "bad (or missing) attributes"; 1331 break; 1332 case LDAP_URL_ERR_BADSCOPE: 1333 why = "scope string is invalid (or missing)"; 1334 break; 1335 case LDAP_URL_ERR_BADFILTER: 1336 why = "bad or missing filter"; 1337 break; 1338 case LDAP_URL_ERR_BADEXTS: 1339 why = "bad or missing extensions"; 1340 break; 1341 default: 1342 why = "unknown reason"; 1343 break; 1344 } 1345 snprintf( c->cr_msg, sizeof( c->cr_msg), 1346 "unable to parse uri \"%s\" " 1347 "in \"uri <uri>\" line: %s", 1348 c->value_string, why ); 1349 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 1350 urlrc = 1; 1351 goto done_url; 1352 } 1353 1354 for ( i = 0, tmpludp = lud; 1355 tmpludp; 1356 i++, tmpludp = tmpludp->lud_next ) 1357 { 1358 if ( ( tmpludp->lud_dn != NULL 1359 && tmpludp->lud_dn[0] != '\0' ) 1360 || tmpludp->lud_attrs != NULL 1361 /* || tmpludp->lud_scope != LDAP_SCOPE_DEFAULT */ 1362 || tmpludp->lud_filter != NULL 1363 || tmpludp->lud_exts != NULL ) 1364 { 1365 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1366 "warning, only protocol, " 1367 "host and port allowed " 1368 "in \"uri <uri>\" statement " 1369 "for uri #%d of \"%s\"", 1370 i, c->argv[ 1 ] ); 1371 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 1372 } 1373 } 1374 1375 for ( i = 0, tmpludp = lud; 1376 tmpludp; 1377 i++, tmpludp = tmpludp->lud_next ) 1378 /* just count */ 1379 ; 1380 urllist = ch_calloc( sizeof( char * ), i + 1 ); 1381 1382 for ( i = 0, tmpludp = lud; 1383 tmpludp; 1384 i++, tmpludp = tmpludp->lud_next ) 1385 { 1386 LDAPURLDesc tmplud; 1387 1388 tmplud = *tmpludp; 1389 tmplud.lud_dn = ""; 1390 tmplud.lud_attrs = NULL; 1391 tmplud.lud_filter = NULL; 1392 if ( !ldap_is_ldapi_url( tmplud.lud_scheme ) ) { 1393 tmplud.lud_exts = NULL; 1394 tmplud.lud_crit_exts = 0; 1395 } 1396 1397 urllist[ i ] = ldap_url_desc2str( &tmplud ); 1398 1399 if ( urllist[ i ] == NULL ) { 1400 snprintf( c->cr_msg, sizeof( c->cr_msg), 1401 "unable to rebuild uri " 1402 "in \"uri <uri>\" statement " 1403 "for \"%s\"", 1404 c->argv[ 1 ] ); 1405 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 1406 urlrc = 1; 1407 goto done_url; 1408 } 1409 } 1410 1411 li->li_uri = ldap_charray2str( urllist, " " ); 1412 for ( i = 0; urllist[ i ] != NULL; i++ ) { 1413 struct berval bv; 1414 1415 ber_str2bv( urllist[ i ], 0, 0, &bv ); 1416 ber_bvarray_add( &li->li_bvuri, &bv ); 1417 urllist[ i ] = NULL; 1418 } 1419 ldap_memfree( urllist ); 1420 urllist = NULL; 1421 1422 done_url:; 1423 if ( urllist ) { 1424 ldap_charray_free( urllist ); 1425 } 1426 if ( lud ) { 1427 ldap_free_urllist( lud ); 1428 } 1429 if ( urlrc != LDAP_URL_SUCCESS ) { 1430 return 1; 1431 } 1432 break; 1433 } 1434 1435 case LDAP_BACK_CFG_TLS: 1436 i = verb_to_mask( c->argv[1], tls_mode ); 1437 if ( BER_BVISNULL( &tls_mode[i].word ) ) { 1438 return 1; 1439 } 1440 li->li_flags &= ~LDAP_BACK_F_TLS_MASK; 1441 li->li_flags |= tls_mode[i].mask; 1442 if ( c->argc > 2 ) { 1443 for ( i=2; i<c->argc; i++ ) { 1444 if ( bindconf_tls_parse( c->argv[i], &li->li_tls )) 1445 return 1; 1446 } 1447 bindconf_tls_defaults( &li->li_tls ); 1448 } 1449 break; 1450 1451 case LDAP_BACK_CFG_ACL_AUTHCDN: 1452 switch ( li->li_acl_authmethod ) { 1453 case LDAP_AUTH_NONE: 1454 li->li_acl_authmethod = LDAP_AUTH_SIMPLE; 1455 break; 1456 1457 case LDAP_AUTH_SIMPLE: 1458 break; 1459 1460 default: 1461 snprintf( c->cr_msg, sizeof( c->cr_msg), 1462 "\"acl-authcDN <DN>\" incompatible " 1463 "with auth method %d", 1464 li->li_acl_authmethod ); 1465 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 1466 return 1; 1467 } 1468 if ( !BER_BVISNULL( &li->li_acl_authcDN ) ) { 1469 free( li->li_acl_authcDN.bv_val ); 1470 } 1471 ber_memfree_x( c->value_dn.bv_val, NULL ); 1472 li->li_acl_authcDN = c->value_ndn; 1473 BER_BVZERO( &c->value_dn ); 1474 BER_BVZERO( &c->value_ndn ); 1475 break; 1476 1477 case LDAP_BACK_CFG_ACL_PASSWD: 1478 switch ( li->li_acl_authmethod ) { 1479 case LDAP_AUTH_NONE: 1480 li->li_acl_authmethod = LDAP_AUTH_SIMPLE; 1481 break; 1482 1483 case LDAP_AUTH_SIMPLE: 1484 break; 1485 1486 default: 1487 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1488 "\"acl-passwd <cred>\" incompatible " 1489 "with auth method %d", 1490 li->li_acl_authmethod ); 1491 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 1492 return 1; 1493 } 1494 if ( !BER_BVISNULL( &li->li_acl_passwd ) ) { 1495 free( li->li_acl_passwd.bv_val ); 1496 } 1497 ber_str2bv( c->argv[ 1 ], 0, 1, &li->li_acl_passwd ); 1498 break; 1499 1500 case LDAP_BACK_CFG_ACL_METHOD: 1501 case LDAP_BACK_CFG_ACL_BIND: 1502 for ( i = 1; i < c->argc; i++ ) { 1503 if ( bindconf_parse( c->argv[ i ], &li->li_acl ) ) { 1504 return 1; 1505 } 1506 } 1507 bindconf_tls_defaults( &li->li_acl ); 1508 break; 1509 1510 case LDAP_BACK_CFG_IDASSERT_MODE: 1511 i = verb_to_mask( c->argv[1], idassert_mode ); 1512 if ( BER_BVISNULL( &idassert_mode[i].word ) ) { 1513 if ( strncasecmp( c->argv[1], "u:", STRLENOF( "u:" ) ) == 0 ) { 1514 li->li_idassert_mode = LDAP_BACK_IDASSERT_OTHERID; 1515 ber_str2bv( c->argv[1], 0, 1, &li->li_idassert_authzID ); 1516 li->li_idassert_authzID.bv_val[ 0 ] = 'u'; 1517 1518 } else { 1519 struct berval id, ndn; 1520 1521 ber_str2bv( c->argv[1], 0, 0, &id ); 1522 1523 if ( strncasecmp( c->argv[1], "dn:", STRLENOF( "dn:" ) ) == 0 ) { 1524 id.bv_val += STRLENOF( "dn:" ); 1525 id.bv_len -= STRLENOF( "dn:" ); 1526 } 1527 1528 rc = dnNormalize( 0, NULL, NULL, &id, &ndn, NULL ); 1529 if ( rc != LDAP_SUCCESS ) { 1530 Debug( LDAP_DEBUG_ANY, 1531 "%s: line %d: idassert ID \"%s\" is not a valid DN\n", 1532 c->fname, c->lineno, c->argv[1] ); 1533 return 1; 1534 } 1535 1536 li->li_idassert_authzID.bv_len = STRLENOF( "dn:" ) + ndn.bv_len; 1537 li->li_idassert_authzID.bv_val = ch_malloc( li->li_idassert_authzID.bv_len + 1 ); 1538 AC_MEMCPY( li->li_idassert_authzID.bv_val, "dn:", STRLENOF( "dn:" ) ); 1539 AC_MEMCPY( &li->li_idassert_authzID.bv_val[ STRLENOF( "dn:" ) ], ndn.bv_val, ndn.bv_len + 1 ); 1540 ch_free( ndn.bv_val ); 1541 1542 li->li_idassert_mode = LDAP_BACK_IDASSERT_OTHERDN; 1543 } 1544 1545 } else { 1546 li->li_idassert_mode = idassert_mode[i].mask; 1547 } 1548 1549 if ( c->argc > 2 ) { 1550 int i; 1551 1552 for ( i = 2; i < c->argc; i++ ) { 1553 if ( strcasecmp( c->argv[ i ], "override" ) == 0 ) { 1554 li->li_idassert_flags |= LDAP_BACK_AUTH_OVERRIDE; 1555 1556 } else if ( strcasecmp( c->argv[ i ], "prescriptive" ) == 0 ) { 1557 li->li_idassert_flags |= LDAP_BACK_AUTH_PRESCRIPTIVE; 1558 1559 } else if ( strcasecmp( c->argv[ i ], "non-prescriptive" ) == 0 ) { 1560 li->li_idassert_flags &= ( ~LDAP_BACK_AUTH_PRESCRIPTIVE ); 1561 1562 } else if ( strcasecmp( c->argv[ i ], "obsolete-proxy-authz" ) == 0 ) { 1563 if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) { 1564 Debug( LDAP_DEBUG_ANY, 1565 "%s: line %d: \"obsolete-proxy-authz\" flag " 1566 "in \"idassert-mode <args>\" " 1567 "incompatible with previously issued \"obsolete-encoding-workaround\" flag.\n", 1568 c->fname, c->lineno, 0 ); 1569 return 1; 1570 } 1571 li->li_idassert_flags |= LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ; 1572 1573 } else if ( strcasecmp( c->argv[ i ], "obsolete-encoding-workaround" ) == 0 ) { 1574 if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) { 1575 Debug( LDAP_DEBUG_ANY, 1576 "%s: line %d: \"obsolete-encoding-workaround\" flag " 1577 "in \"idassert-mode <args>\" " 1578 "incompatible with previously issued \"obsolete-proxy-authz\" flag.\n", 1579 c->fname, c->lineno, 0 ); 1580 return 1; 1581 } 1582 li->li_idassert_flags |= LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND; 1583 1584 } else { 1585 Debug( LDAP_DEBUG_ANY, 1586 "%s: line %d: unknown flag #%d " 1587 "in \"idassert-mode <args> " 1588 "[<flags>]\" line.\n", 1589 c->fname, c->lineno, i - 2 ); 1590 return 1; 1591 } 1592 } 1593 } 1594 break; 1595 1596 case LDAP_BACK_CFG_IDASSERT_AUTHCDN: 1597 switch ( li->li_idassert_authmethod ) { 1598 case LDAP_AUTH_NONE: 1599 li->li_idassert_authmethod = LDAP_AUTH_SIMPLE; 1600 break; 1601 1602 case LDAP_AUTH_SIMPLE: 1603 break; 1604 1605 default: 1606 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1607 "\"idassert-authcDN <DN>\" incompatible " 1608 "with auth method %d", 1609 li->li_idassert_authmethod ); 1610 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 1611 return 1; 1612 } 1613 if ( !BER_BVISNULL( &li->li_idassert_authcDN ) ) { 1614 free( li->li_idassert_authcDN.bv_val ); 1615 } 1616 ber_memfree_x( c->value_dn.bv_val, NULL ); 1617 li->li_idassert_authcDN = c->value_ndn; 1618 BER_BVZERO( &c->value_dn ); 1619 BER_BVZERO( &c->value_ndn ); 1620 break; 1621 1622 case LDAP_BACK_CFG_IDASSERT_PASSWD: 1623 switch ( li->li_idassert_authmethod ) { 1624 case LDAP_AUTH_NONE: 1625 li->li_idassert_authmethod = LDAP_AUTH_SIMPLE; 1626 break; 1627 1628 case LDAP_AUTH_SIMPLE: 1629 break; 1630 1631 default: 1632 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1633 "\"idassert-passwd <cred>\" incompatible " 1634 "with auth method %d", 1635 li->li_idassert_authmethod ); 1636 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 1637 return 1; 1638 } 1639 if ( !BER_BVISNULL( &li->li_idassert_passwd ) ) { 1640 free( li->li_idassert_passwd.bv_val ); 1641 } 1642 ber_str2bv( c->argv[ 1 ], 0, 1, &li->li_idassert_passwd ); 1643 break; 1644 1645 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: 1646 rc = slap_idassert_authzfrom_parse( c, &li->li_idassert ); 1647 break; 1648 1649 case LDAP_BACK_CFG_IDASSERT_METHOD: 1650 /* no longer supported */ 1651 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1652 "\"idassert-method <args>\": " 1653 "no longer supported; use \"idassert-bind\"" ); 1654 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 1655 return 1; 1656 1657 case LDAP_BACK_CFG_IDASSERT_BIND: 1658 rc = slap_idassert_parse( c, &li->li_idassert ); 1659 break; 1660 1661 case LDAP_BACK_CFG_REBIND: 1662 if ( c->argc == 1 || c->value_int ) { 1663 li->li_flags |= LDAP_BACK_F_SAVECRED; 1664 1665 } else { 1666 li->li_flags &= ~LDAP_BACK_F_SAVECRED; 1667 } 1668 break; 1669 1670 case LDAP_BACK_CFG_CHASE: 1671 if ( c->argc == 1 || c->value_int ) { 1672 li->li_flags |= LDAP_BACK_F_CHASE_REFERRALS; 1673 1674 } else { 1675 li->li_flags &= ~LDAP_BACK_F_CHASE_REFERRALS; 1676 } 1677 break; 1678 1679 case LDAP_BACK_CFG_T_F: { 1680 slap_mask_t mask; 1681 1682 i = verb_to_mask( c->argv[1], t_f_mode ); 1683 if ( BER_BVISNULL( &t_f_mode[i].word ) ) { 1684 return 1; 1685 } 1686 1687 mask = t_f_mode[i].mask; 1688 1689 if ( LDAP_BACK_ISOPEN( li ) 1690 && mask == LDAP_BACK_F_T_F_DISCOVER 1691 && !LDAP_BACK_T_F( li ) ) 1692 { 1693 slap_bindconf sb = { BER_BVNULL }; 1694 int rc; 1695 1696 if ( li->li_uri == NULL ) { 1697 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1698 "need URI to discover absolute filters support " 1699 "in \"t-f-support discover\"" ); 1700 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 1701 return 1; 1702 } 1703 1704 ber_str2bv( li->li_uri, 0, 0, &sb.sb_uri ); 1705 sb.sb_version = li->li_version; 1706 sb.sb_method = LDAP_AUTH_SIMPLE; 1707 BER_BVSTR( &sb.sb_binddn, "" ); 1708 1709 rc = slap_discover_feature( &sb, 1710 slap_schema.si_ad_supportedFeatures->ad_cname.bv_val, 1711 LDAP_FEATURE_ABSOLUTE_FILTERS ); 1712 if ( rc == LDAP_COMPARE_TRUE ) { 1713 mask |= LDAP_BACK_F_T_F; 1714 } 1715 } 1716 1717 li->li_flags &= ~LDAP_BACK_F_T_F_MASK2; 1718 li->li_flags |= mask; 1719 } break; 1720 1721 case LDAP_BACK_CFG_WHOAMI: 1722 if ( c->argc == 1 || c->value_int ) { 1723 li->li_flags |= LDAP_BACK_F_PROXY_WHOAMI; 1724 load_extop( (struct berval *)&slap_EXOP_WHOAMI, 1725 0, ldap_back_exop_whoami ); 1726 1727 } else { 1728 li->li_flags &= ~LDAP_BACK_F_PROXY_WHOAMI; 1729 } 1730 break; 1731 1732 case LDAP_BACK_CFG_TIMEOUT: 1733 for ( i = 1; i < c->argc; i++ ) { 1734 if ( isdigit( (unsigned char) c->argv[ i ][ 0 ] ) ) { 1735 int j; 1736 unsigned u; 1737 1738 if ( lutil_atoux( &u, c->argv[ i ], 0 ) != 0 ) { 1739 snprintf( c->cr_msg, sizeof( c->cr_msg), 1740 "unable to parse timeout \"%s\"", 1741 c->argv[ i ] ); 1742 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 1743 return 1; 1744 } 1745 1746 for ( j = 0; j < SLAP_OP_LAST; j++ ) { 1747 li->li_timeout[ j ] = u; 1748 } 1749 1750 continue; 1751 } 1752 1753 if ( slap_cf_aux_table_parse( c->argv[ i ], li->li_timeout, timeout_table, "slapd-ldap timeout" ) ) { 1754 snprintf( c->cr_msg, sizeof( c->cr_msg), 1755 "unable to parse timeout \"%s\"", 1756 c->argv[ i ] ); 1757 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 1758 return 1; 1759 } 1760 } 1761 break; 1762 1763 case LDAP_BACK_CFG_IDLE_TIMEOUT: { 1764 unsigned long t; 1765 1766 if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) { 1767 snprintf( c->cr_msg, sizeof( c->cr_msg), 1768 "unable to parse idle timeout \"%s\"", 1769 c->argv[ 1 ] ); 1770 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 1771 return 1; 1772 } 1773 li->li_idle_timeout = (time_t)t; 1774 } break; 1775 1776 case LDAP_BACK_CFG_CONN_TTL: { 1777 unsigned long t; 1778 1779 if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) { 1780 snprintf( c->cr_msg, sizeof( c->cr_msg), 1781 "unable to parse conn ttl\"%s\"", 1782 c->argv[ 1 ] ); 1783 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 1784 return 1; 1785 } 1786 li->li_conn_ttl = (time_t)t; 1787 } break; 1788 1789 case LDAP_BACK_CFG_NETWORK_TIMEOUT: { 1790 unsigned long t; 1791 1792 if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) { 1793 snprintf( c->cr_msg, sizeof( c->cr_msg), 1794 "unable to parse network timeout \"%s\"", 1795 c->argv[ 1 ] ); 1796 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 1797 return 1; 1798 } 1799 li->li_network_timeout = (time_t)t; 1800 } break; 1801 1802 case LDAP_BACK_CFG_VERSION: 1803 if ( c->value_int != 0 && ( c->value_int < LDAP_VERSION_MIN || c->value_int > LDAP_VERSION_MAX ) ) { 1804 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1805 "unsupported version \"%s\" " 1806 "in \"protocol-version <version>\"", 1807 c->argv[ 1 ] ); 1808 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 1809 return 1; 1810 } 1811 1812 li->li_version = c->value_int; 1813 break; 1814 1815 case LDAP_BACK_CFG_SINGLECONN: 1816 if ( c->value_int ) { 1817 li->li_flags |= LDAP_BACK_F_SINGLECONN; 1818 1819 } else { 1820 li->li_flags &= ~LDAP_BACK_F_SINGLECONN; 1821 } 1822 break; 1823 1824 case LDAP_BACK_CFG_USETEMP: 1825 if ( c->value_int ) { 1826 li->li_flags |= LDAP_BACK_F_USE_TEMPORARIES; 1827 1828 } else { 1829 li->li_flags &= ~LDAP_BACK_F_USE_TEMPORARIES; 1830 } 1831 break; 1832 1833 case LDAP_BACK_CFG_CONNPOOLMAX: 1834 if ( c->value_int < LDAP_BACK_CONN_PRIV_MIN 1835 || c->value_int > LDAP_BACK_CONN_PRIV_MAX ) 1836 { 1837 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1838 "invalid max size " "of privileged " 1839 "connections pool \"%s\" " 1840 "in \"conn-pool-max <n> " 1841 "(must be between %d and %d)\"", 1842 c->argv[ 1 ], 1843 LDAP_BACK_CONN_PRIV_MIN, 1844 LDAP_BACK_CONN_PRIV_MAX ); 1845 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 1846 return 1; 1847 } 1848 li->li_conn_priv_max = c->value_int; 1849 break; 1850 1851 case LDAP_BACK_CFG_CANCEL: { 1852 slap_mask_t mask; 1853 1854 i = verb_to_mask( c->argv[1], cancel_mode ); 1855 if ( BER_BVISNULL( &cancel_mode[i].word ) ) { 1856 return 1; 1857 } 1858 1859 mask = cancel_mode[i].mask; 1860 1861 if ( LDAP_BACK_ISOPEN( li ) 1862 && mask == LDAP_BACK_F_CANCEL_EXOP_DISCOVER 1863 && !LDAP_BACK_CANCEL( li ) ) 1864 { 1865 slap_bindconf sb = { BER_BVNULL }; 1866 int rc; 1867 1868 if ( li->li_uri == NULL ) { 1869 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1870 "need URI to discover \"cancel\" support " 1871 "in \"cancel exop-discover\"" ); 1872 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 1873 return 1; 1874 } 1875 1876 ber_str2bv( li->li_uri, 0, 0, &sb.sb_uri ); 1877 sb.sb_version = li->li_version; 1878 sb.sb_method = LDAP_AUTH_SIMPLE; 1879 BER_BVSTR( &sb.sb_binddn, "" ); 1880 1881 rc = slap_discover_feature( &sb, 1882 slap_schema.si_ad_supportedExtension->ad_cname.bv_val, 1883 LDAP_EXOP_CANCEL ); 1884 if ( rc == LDAP_COMPARE_TRUE ) { 1885 mask |= LDAP_BACK_F_CANCEL_EXOP; 1886 } 1887 } 1888 1889 li->li_flags &= ~LDAP_BACK_F_CANCEL_MASK2; 1890 li->li_flags |= mask; 1891 } break; 1892 1893 case LDAP_BACK_CFG_QUARANTINE: 1894 if ( LDAP_BACK_QUARANTINE( li ) ) { 1895 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1896 "quarantine already defined" ); 1897 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 1898 return 1; 1899 } 1900 rc = slap_retry_info_parse( c->argv[1], &li->li_quarantine, 1901 c->cr_msg, sizeof( c->cr_msg ) ); 1902 if ( rc ) { 1903 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 1904 1905 } else { 1906 ldap_pvt_thread_mutex_init( &li->li_quarantine_mutex ); 1907 /* give it a chance to retry if the pattern gets reset 1908 * via back-config */ 1909 li->li_isquarantined = 0; 1910 li->li_flags |= LDAP_BACK_F_QUARANTINE; 1911 } 1912 break; 1913 1914 #ifdef SLAP_CONTROL_X_SESSION_TRACKING 1915 case LDAP_BACK_CFG_ST_REQUEST: 1916 if ( c->value_int ) { 1917 li->li_flags |= LDAP_BACK_F_ST_REQUEST; 1918 1919 } else { 1920 li->li_flags &= ~LDAP_BACK_F_ST_REQUEST; 1921 } 1922 break; 1923 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 1924 1925 case LDAP_BACK_CFG_NOREFS: 1926 if ( c->value_int ) { 1927 li->li_flags |= LDAP_BACK_F_NOREFS; 1928 1929 } else { 1930 li->li_flags &= ~LDAP_BACK_F_NOREFS; 1931 } 1932 break; 1933 1934 case LDAP_BACK_CFG_REWRITE: 1935 snprintf( c->cr_msg, sizeof( c->cr_msg ), 1936 "rewrite/remap capabilities have been moved " 1937 "to the \"rwm\" overlay; see slapo-rwm(5) " 1938 "for details (hint: add \"overlay rwm\" " 1939 "and prefix all directives with \"rwm-\")" ); 1940 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 ); 1941 return 1; 1942 1943 default: 1944 /* FIXME: try to catch inconsistencies */ 1945 assert( 0 ); 1946 break; 1947 } 1948 1949 return rc; 1950 } 1951 1952 int 1953 ldap_back_init_cf( BackendInfo *bi ) 1954 { 1955 int rc; 1956 AttributeDescription *ad = NULL; 1957 const char *text; 1958 1959 /* Make sure we don't exceed the bits reserved for userland */ 1960 config_check_userland( LDAP_BACK_CFG_LAST ); 1961 1962 bi->bi_cf_ocs = ldapocs; 1963 1964 rc = config_register_schema( ldapcfg, ldapocs ); 1965 if ( rc ) { 1966 return rc; 1967 } 1968 1969 /* setup olcDbAclPasswd and olcDbIDAssertPasswd 1970 * to be base64-encoded when written in LDIF form; 1971 * basically, we don't care if it fails */ 1972 rc = slap_str2ad( "olcDbACLPasswd", &ad, &text ); 1973 if ( rc ) { 1974 Debug( LDAP_DEBUG_ANY, "config_back_initialize: " 1975 "warning, unable to get \"olcDbACLPasswd\" " 1976 "attribute description: %d: %s\n", 1977 rc, text, 0 ); 1978 } else { 1979 (void)ldif_must_b64_encode_register( ad->ad_cname.bv_val, 1980 ad->ad_type->sat_oid ); 1981 } 1982 1983 ad = NULL; 1984 rc = slap_str2ad( "olcDbIDAssertPasswd", &ad, &text ); 1985 if ( rc ) { 1986 Debug( LDAP_DEBUG_ANY, "config_back_initialize: " 1987 "warning, unable to get \"olcDbIDAssertPasswd\" " 1988 "attribute description: %d: %s\n", 1989 rc, text, 0 ); 1990 } else { 1991 (void)ldif_must_b64_encode_register( ad->ad_cname.bv_val, 1992 ad->ad_type->sat_oid ); 1993 } 1994 1995 return 0; 1996 } 1997 1998 1999 static int 2000 ldap_back_exop_whoami( 2001 Operation *op, 2002 SlapReply *rs ) 2003 { 2004 struct berval *bv = NULL; 2005 2006 if ( op->oq_extended.rs_reqdata != NULL ) { 2007 /* no request data should be provided */ 2008 rs->sr_text = "no request data expected"; 2009 return rs->sr_err = LDAP_PROTOCOL_ERROR; 2010 } 2011 2012 Statslog( LDAP_DEBUG_STATS, "%s WHOAMI\n", 2013 op->o_log_prefix, 0, 0, 0, 0 ); 2014 2015 rs->sr_err = backend_check_restrictions( op, rs, 2016 (struct berval *)&slap_EXOP_WHOAMI ); 2017 if( rs->sr_err != LDAP_SUCCESS ) return rs->sr_err; 2018 2019 /* if auth'd by back-ldap and request is proxied, forward it */ 2020 if ( op->o_conn->c_authz_backend 2021 && !strcmp( op->o_conn->c_authz_backend->be_type, "ldap" ) 2022 && !dn_match( &op->o_ndn, &op->o_conn->c_ndn ) ) 2023 { 2024 ldapconn_t *lc = NULL; 2025 LDAPControl c, *ctrls[2] = {NULL, NULL}; 2026 LDAPMessage *res; 2027 Operation op2 = *op; 2028 ber_int_t msgid; 2029 int doretry = 1; 2030 char *ptr; 2031 2032 ctrls[0] = &c; 2033 op2.o_ndn = op->o_conn->c_ndn; 2034 if ( !ldap_back_dobind( &lc, &op2, rs, LDAP_BACK_SENDERR ) ) { 2035 return -1; 2036 } 2037 c.ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ; 2038 c.ldctl_iscritical = 1; 2039 c.ldctl_value.bv_val = op->o_tmpalloc( 2040 op->o_ndn.bv_len + STRLENOF( "dn:" ) + 1, 2041 op->o_tmpmemctx ); 2042 c.ldctl_value.bv_len = op->o_ndn.bv_len + 3; 2043 ptr = c.ldctl_value.bv_val; 2044 ptr = lutil_strcopy( ptr, "dn:" ); 2045 ptr = lutil_strncopy( ptr, op->o_ndn.bv_val, op->o_ndn.bv_len ); 2046 ptr[ 0 ] = '\0'; 2047 2048 retry: 2049 rs->sr_err = ldap_whoami( lc->lc_ld, ctrls, NULL, &msgid ); 2050 if ( rs->sr_err == LDAP_SUCCESS ) { 2051 if ( ldap_result( lc->lc_ld, msgid, LDAP_MSG_ALL, NULL, &res ) == -1 ) { 2052 ldap_get_option( lc->lc_ld, LDAP_OPT_ERROR_NUMBER, 2053 &rs->sr_err ); 2054 if ( rs->sr_err == LDAP_SERVER_DOWN && doretry ) { 2055 doretry = 0; 2056 if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) { 2057 goto retry; 2058 } 2059 } 2060 2061 } else { 2062 /* NOTE: are we sure "bv" will be malloc'ed 2063 * with the appropriate memory? */ 2064 rs->sr_err = ldap_parse_whoami( lc->lc_ld, res, &bv ); 2065 ldap_msgfree(res); 2066 } 2067 } 2068 op->o_tmpfree( c.ldctl_value.bv_val, op->o_tmpmemctx ); 2069 if ( rs->sr_err != LDAP_SUCCESS ) { 2070 rs->sr_err = slap_map_api2result( rs ); 2071 } 2072 2073 if ( lc != NULL ) { 2074 ldap_back_release_conn( (ldapinfo_t *)op2.o_bd->be_private, lc ); 2075 } 2076 2077 } else { 2078 /* else just do the same as before */ 2079 bv = (struct berval *) ch_malloc( sizeof( struct berval ) ); 2080 if ( !BER_BVISEMPTY( &op->o_dn ) ) { 2081 bv->bv_len = op->o_dn.bv_len + STRLENOF( "dn:" ); 2082 bv->bv_val = ch_malloc( bv->bv_len + 1 ); 2083 AC_MEMCPY( bv->bv_val, "dn:", STRLENOF( "dn:" ) ); 2084 AC_MEMCPY( &bv->bv_val[ STRLENOF( "dn:" ) ], op->o_dn.bv_val, 2085 op->o_dn.bv_len ); 2086 bv->bv_val[ bv->bv_len ] = '\0'; 2087 2088 } else { 2089 bv->bv_len = 0; 2090 bv->bv_val = NULL; 2091 } 2092 } 2093 2094 rs->sr_rspdata = bv; 2095 return rs->sr_err; 2096 } 2097 2098 2099