1 /* $OpenLDAP: pkg/ldap/servers/slapd/back-meta/config.c,v 1.74.2.13 2008/07/10 00:28:39 quanah Exp $ */ 2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 3 * 4 * Copyright 1999-2008 The OpenLDAP Foundation. 5 * Portions Copyright 2001-2003 Pierangelo Masarati. 6 * Portions Copyright 1999-2003 Howard Chu. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted only as authorized by the OpenLDAP 11 * Public License. 12 * 13 * A copy of this license is available in the file LICENSE in the 14 * top-level directory of the distribution or, alternatively, at 15 * <http://www.OpenLDAP.org/license.html>. 16 */ 17 /* ACKNOWLEDGEMENTS: 18 * This work was initially developed by the Howard Chu for inclusion 19 * in OpenLDAP Software and subsequently enhanced by Pierangelo 20 * Masarati. 21 */ 22 23 #include "portable.h" 24 25 #include <stdio.h> 26 27 #include <ac/string.h> 28 #include <ac/socket.h> 29 30 #include "slap.h" 31 #include "lutil.h" 32 #include "../back-ldap/back-ldap.h" 33 #undef ldap_debug /* silence a warning in ldap-int.h */ 34 #include "../../../libraries/libldap/ldap-int.h" 35 #include "back-meta.h" 36 37 static int 38 meta_back_new_target( 39 metatarget_t **mtp ) 40 { 41 char *rargv[ 3 ]; 42 metatarget_t *mt; 43 44 *mtp = NULL; 45 46 mt = ch_calloc( sizeof( metatarget_t ), 1 ); 47 48 mt->mt_rwmap.rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT ); 49 if ( mt->mt_rwmap.rwm_rw == NULL ) { 50 ch_free( mt ); 51 return -1; 52 } 53 54 /* 55 * the filter rewrite as a string must be disabled 56 * by default; it can be re-enabled by adding rules; 57 * this creates an empty rewriteContext 58 */ 59 rargv[ 0 ] = "rewriteContext"; 60 rargv[ 1 ] = "searchFilter"; 61 rargv[ 2 ] = NULL; 62 rewrite_parse( mt->mt_rwmap.rwm_rw, "<suffix massage>", 1, 2, rargv ); 63 64 rargv[ 0 ] = "rewriteContext"; 65 rargv[ 1 ] = "default"; 66 rargv[ 2 ] = NULL; 67 rewrite_parse( mt->mt_rwmap.rwm_rw, "<suffix massage>", 1, 2, rargv ); 68 69 ldap_pvt_thread_mutex_init( &mt->mt_uri_mutex ); 70 71 mt->mt_idassert_mode = LDAP_BACK_IDASSERT_LEGACY; 72 mt->mt_idassert_authmethod = LDAP_AUTH_NONE; 73 mt->mt_idassert_tls = SB_TLS_DEFAULT; 74 75 /* by default, use proxyAuthz control on each operation */ 76 mt->mt_idassert_flags = LDAP_BACK_AUTH_PRESCRIPTIVE; 77 78 *mtp = mt; 79 80 return 0; 81 } 82 83 static int 84 check_true_false( char *str ) 85 { 86 if ( strcasecmp( str, "true" ) == 0 || strcasecmp( str, "yes" ) == 0 ) { 87 return 1; 88 } 89 90 if ( strcasecmp( str, "false" ) == 0 || strcasecmp( str, "no" ) == 0 ) { 91 return 0; 92 } 93 94 return -1; 95 } 96 97 98 int 99 meta_back_db_config( 100 BackendDB *be, 101 const char *fname, 102 int lineno, 103 int argc, 104 char **argv 105 ) 106 { 107 metainfo_t *mi = ( metainfo_t * )be->be_private; 108 109 assert( mi != NULL ); 110 111 /* URI of server to query */ 112 if ( strcasecmp( argv[ 0 ], "uri" ) == 0 ) { 113 int i = mi->mi_ntargets; 114 LDAPURLDesc *ludp; 115 struct berval dn; 116 int rc; 117 int c; 118 119 metatarget_t *mt; 120 121 char **uris = NULL; 122 123 if ( argc == 1 ) { 124 Debug( LDAP_DEBUG_ANY, 125 "%s: line %d: missing URI " 126 "in \"uri <protocol>://<server>[:port]/<naming context>\" line\n", 127 fname, lineno, 0 ); 128 return 1; 129 } 130 131 if ( be->be_nsuffix == NULL ) { 132 Debug( LDAP_DEBUG_ANY, 133 "%s: line %d: the suffix must be defined before any target.\n", 134 fname, lineno, 0 ); 135 return 1; 136 } 137 138 ++mi->mi_ntargets; 139 140 mi->mi_targets = ( metatarget_t ** )ch_realloc( mi->mi_targets, 141 sizeof( metatarget_t * ) * mi->mi_ntargets ); 142 if ( mi->mi_targets == NULL ) { 143 Debug( LDAP_DEBUG_ANY, 144 "%s: line %d: out of memory while storing server name" 145 " in \"uri <protocol>://<server>[:port]/<naming context>\" line\n", 146 fname, lineno, 0 ); 147 return 1; 148 } 149 150 if ( meta_back_new_target( &mi->mi_targets[ i ] ) != 0 ) { 151 Debug( LDAP_DEBUG_ANY, 152 "%s: line %d: unable to init server" 153 " in \"uri <protocol>://<server>[:port]/<naming context>\" line\n", 154 fname, lineno, 0 ); 155 return 1; 156 } 157 158 mt = mi->mi_targets[ i ]; 159 160 mt->mt_rebind_f = mi->mi_rebind_f; 161 mt->mt_urllist_f = mi->mi_urllist_f; 162 mt->mt_urllist_p = mt; 163 164 mt->mt_nretries = mi->mi_nretries; 165 mt->mt_quarantine = mi->mi_quarantine; 166 if ( META_BACK_QUARANTINE( mi ) ) { 167 ldap_pvt_thread_mutex_init( &mt->mt_quarantine_mutex ); 168 } 169 mt->mt_flags = mi->mi_flags; 170 mt->mt_version = mi->mi_version; 171 mt->mt_network_timeout = mi->mi_network_timeout; 172 mt->mt_bind_timeout = mi->mi_bind_timeout; 173 for ( c = 0; c < SLAP_OP_LAST; c++ ) { 174 mt->mt_timeout[ c ] = mi->mi_timeout[ c ]; 175 } 176 177 for ( c = 1; c < argc; c++ ) { 178 char **tmpuris = ldap_str2charray( argv[ c ], "\t" ); 179 180 if ( tmpuris == NULL ) { 181 Debug( LDAP_DEBUG_ANY, 182 "%s: line %d: unable to parse URIs #%d" 183 " in \"uri <protocol>://<server>[:port]/<naming context>\" line\n", 184 fname, lineno, c - 1 ); 185 return 1; 186 } 187 188 if ( c == 0 ) { 189 uris = tmpuris; 190 191 } else { 192 ldap_charray_merge( &uris, tmpuris ); 193 ldap_charray_free( tmpuris ); 194 } 195 } 196 197 for ( c = 0; uris[ c ] != NULL; c++ ) { 198 char *tmpuri = NULL; 199 200 /* 201 * uri MUST be legal! 202 */ 203 if ( ldap_url_parselist_ext( &ludp, uris[ c ], "\t", 204 LDAP_PVT_URL_PARSE_NONE ) != LDAP_SUCCESS 205 || ludp->lud_next != NULL ) 206 { 207 Debug( LDAP_DEBUG_ANY, 208 "%s: line %d: unable to parse URI #%d" 209 " in \"uri <protocol>://<server>[:port]/<naming context>\" line\n", 210 fname, lineno, c ); 211 ldap_charray_free( uris ); 212 return 1; 213 } 214 215 if ( c == 0 ) { 216 217 /* 218 * uri MUST have the <dn> part! 219 */ 220 if ( ludp->lud_dn == NULL ) { 221 Debug( LDAP_DEBUG_ANY, 222 "%s: line %d: missing <naming context> " 223 " in \"uri <protocol>://<server>[:port]/<naming context>\" line\n", 224 fname, lineno, 0 ); 225 ldap_free_urllist( ludp ); 226 ldap_charray_free( uris ); 227 return 1; 228 } 229 230 /* 231 * copies and stores uri and suffix 232 */ 233 ber_str2bv( ludp->lud_dn, 0, 0, &dn ); 234 rc = dnPrettyNormal( NULL, &dn, &mt->mt_psuffix, 235 &mt->mt_nsuffix, NULL ); 236 if ( rc != LDAP_SUCCESS ) { 237 Debug( LDAP_DEBUG_ANY, "%s: line %d: " 238 "target \"%s\" DN is invalid\n", 239 fname, lineno, argv[ 1 ] ); 240 ldap_free_urllist( ludp ); 241 ldap_charray_free( uris ); 242 return( 1 ); 243 } 244 245 ludp->lud_dn[ 0 ] = '\0'; 246 247 switch ( ludp->lud_scope ) { 248 case LDAP_SCOPE_DEFAULT: 249 mt->mt_scope = LDAP_SCOPE_SUBTREE; 250 break; 251 252 case LDAP_SCOPE_SUBTREE: 253 case LDAP_SCOPE_SUBORDINATE: 254 mt->mt_scope = ludp->lud_scope; 255 break; 256 257 default: 258 Debug( LDAP_DEBUG_ANY, "%s: line %d: " 259 "invalid scope for target \"%s\"\n", 260 fname, lineno, argv[ 1 ] ); 261 ldap_free_urllist( ludp ); 262 ldap_charray_free( uris ); 263 return( 1 ); 264 } 265 266 } else { 267 /* check all, to apply the scope check on the first one */ 268 if ( ludp->lud_dn != NULL && ludp->lud_dn[ 0 ] != '\0' ) { 269 Debug( LDAP_DEBUG_ANY, "%s: line %d: " 270 "multiple URIs must have " 271 "no DN part\n", 272 fname, lineno, 0 ); 273 ldap_free_urllist( ludp ); 274 ldap_charray_free( uris ); 275 return( 1 ); 276 277 } 278 } 279 280 tmpuri = ldap_url_list2urls( ludp ); 281 ldap_free_urllist( ludp ); 282 if ( tmpuri == NULL ) { 283 Debug( LDAP_DEBUG_ANY, "%s: line %d: no memory?\n", 284 fname, lineno, 0 ); 285 ldap_charray_free( uris ); 286 return( 1 ); 287 } 288 ldap_memfree( uris[ c ] ); 289 uris[ c ] = tmpuri; 290 } 291 292 mt->mt_uri = ldap_charray2str( uris, " " ); 293 ldap_charray_free( uris ); 294 if ( mt->mt_uri == NULL) { 295 Debug( LDAP_DEBUG_ANY, "%s: line %d: no memory?\n", 296 fname, lineno, 0 ); 297 return( 1 ); 298 } 299 300 /* 301 * uri MUST be a branch of suffix! 302 */ 303 for ( c = 0; !BER_BVISNULL( &be->be_nsuffix[ c ] ); c++ ) { 304 if ( dnIsSuffix( &mt->mt_nsuffix, &be->be_nsuffix[ c ] ) ) { 305 break; 306 } 307 } 308 309 if ( BER_BVISNULL( &be->be_nsuffix[ c ] ) ) { 310 Debug( LDAP_DEBUG_ANY, 311 "%s: line %d: <naming context> of URI must be within the naming context of this database.\n", 312 fname, lineno, 0 ); 313 return 1; 314 } 315 316 /* subtree-exclude */ 317 } else if ( strcasecmp( argv[ 0 ], "subtree-exclude" ) == 0 ) { 318 int i = mi->mi_ntargets - 1; 319 struct berval dn, ndn; 320 321 if ( i < 0 ) { 322 Debug( LDAP_DEBUG_ANY, 323 "%s: line %d: need \"uri\" directive first\n", 324 fname, lineno, 0 ); 325 return 1; 326 } 327 328 switch ( argc ) { 329 case 1: 330 Debug( LDAP_DEBUG_ANY, 331 "%s: line %d: missing DN in \"subtree-exclude <DN>\" line\n", 332 fname, lineno, 0 ); 333 return 1; 334 335 case 2: 336 break; 337 338 default: 339 Debug( LDAP_DEBUG_ANY, 340 "%s: line %d: too many args in \"subtree-exclude <DN>\" line\n", 341 fname, lineno, 0 ); 342 return 1; 343 } 344 345 ber_str2bv( argv[ 1 ], 0, 0, &dn ); 346 if ( dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL ) 347 != LDAP_SUCCESS ) 348 { 349 Debug( LDAP_DEBUG_ANY, "%s: line %d: " 350 "subtree-exclude DN=\"%s\" is invalid\n", 351 fname, lineno, argv[ 1 ] ); 352 return( 1 ); 353 } 354 355 if ( !dnIsSuffix( &ndn, &mi->mi_targets[ i ]->mt_nsuffix ) ) { 356 Debug( LDAP_DEBUG_ANY, "%s: line %d: " 357 "subtree-exclude DN=\"%s\" " 358 "must be subtree of target\n", 359 fname, lineno, argv[ 1 ] ); 360 ber_memfree( ndn.bv_val ); 361 return( 1 ); 362 } 363 364 if ( mi->mi_targets[ i ]->mt_subtree_exclude != NULL ) { 365 int j; 366 367 for ( j = 0; !BER_BVISNULL( &mi->mi_targets[ i ]->mt_subtree_exclude[ j ] ); j++ ) 368 { 369 if ( dnIsSuffix( &mi->mi_targets[ i ]->mt_subtree_exclude[ j ], &ndn ) ) { 370 Debug( LDAP_DEBUG_ANY, "%s: line %d: " 371 "subtree-exclude DN=\"%s\" " 372 "is suffix of another subtree-exclude\n", 373 fname, lineno, argv[ 1 ] ); 374 /* reject, because it might be superior 375 * to more than one subtree-exclude */ 376 ber_memfree( ndn.bv_val ); 377 return( 1 ); 378 379 } else if ( dnIsSuffix( &ndn, &mi->mi_targets[ i ]->mt_subtree_exclude[ j ] ) ) { 380 Debug( LDAP_DEBUG_ANY, "%s: line %d: " 381 "another subtree-exclude is suffix of " 382 "subtree-exclude DN=\"%s\"\n", 383 fname, lineno, argv[ 1 ] ); 384 ber_memfree( ndn.bv_val ); 385 return( 0 ); 386 } 387 } 388 } 389 390 ber_bvarray_add( &mi->mi_targets[ i ]->mt_subtree_exclude, &ndn ); 391 392 /* default target directive */ 393 } else if ( strcasecmp( argv[ 0 ], "default-target" ) == 0 ) { 394 int i = mi->mi_ntargets - 1; 395 396 if ( argc == 1 ) { 397 if ( i < 0 ) { 398 Debug( LDAP_DEBUG_ANY, 399 "%s: line %d: \"default-target\" alone need be" 400 " inside a \"uri\" directive\n", 401 fname, lineno, 0 ); 402 return 1; 403 } 404 mi->mi_defaulttarget = i; 405 406 } else { 407 if ( strcasecmp( argv[ 1 ], "none" ) == 0 ) { 408 if ( i >= 0 ) { 409 Debug( LDAP_DEBUG_ANY, 410 "%s: line %d: \"default-target none\"" 411 " should go before uri definitions\n", 412 fname, lineno, 0 ); 413 } 414 mi->mi_defaulttarget = META_DEFAULT_TARGET_NONE; 415 416 } else { 417 418 if ( lutil_atoi( &mi->mi_defaulttarget, argv[ 1 ] ) != 0 419 || mi->mi_defaulttarget < 0 420 || mi->mi_defaulttarget >= i - 1 ) 421 { 422 Debug( LDAP_DEBUG_ANY, 423 "%s: line %d: illegal target number %d\n", 424 fname, lineno, mi->mi_defaulttarget ); 425 return 1; 426 } 427 } 428 } 429 430 /* ttl of dn cache */ 431 } else if ( strcasecmp( argv[ 0 ], "dncache-ttl" ) == 0 ) { 432 if ( argc != 2 ) { 433 Debug( LDAP_DEBUG_ANY, 434 "%s: line %d: missing ttl in \"dncache-ttl <ttl>\" line\n", 435 fname, lineno, 0 ); 436 return 1; 437 } 438 439 if ( strcasecmp( argv[ 1 ], "forever" ) == 0 ) { 440 mi->mi_cache.ttl = META_DNCACHE_FOREVER; 441 442 } else if ( strcasecmp( argv[ 1 ], "disabled" ) == 0 ) { 443 mi->mi_cache.ttl = META_DNCACHE_DISABLED; 444 445 } else { 446 unsigned long t; 447 448 if ( lutil_parse_time( argv[ 1 ], &t ) != 0 ) { 449 Debug( LDAP_DEBUG_ANY, 450 "%s: line %d: unable to parse ttl \"%s\" in \"dncache-ttl <ttl>\" line\n", 451 fname, lineno, argv[ 1 ] ); 452 return 1; 453 } 454 mi->mi_cache.ttl = (time_t)t; 455 } 456 457 /* network timeout when connecting to ldap servers */ 458 } else if ( strcasecmp( argv[ 0 ], "network-timeout" ) == 0 ) { 459 unsigned long t; 460 time_t *tp = mi->mi_ntargets ? 461 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_network_timeout 462 : &mi->mi_network_timeout; 463 464 if ( argc != 2 ) { 465 Debug( LDAP_DEBUG_ANY, 466 "%s: line %d: missing network timeout in \"network-timeout <seconds>\" line\n", 467 fname, lineno, 0 ); 468 return 1; 469 } 470 471 if ( lutil_parse_time( argv[ 1 ], &t ) ) { 472 Debug( LDAP_DEBUG_ANY, 473 "%s: line %d: unable to parse timeout \"%s\" in \"network-timeout <seconds>\" line\n", 474 fname, lineno, argv[ 1 ] ); 475 return 1; 476 477 } 478 479 *tp = (time_t)t; 480 481 /* idle timeout when connecting to ldap servers */ 482 } else if ( strcasecmp( argv[ 0 ], "idle-timeout" ) == 0 ) { 483 unsigned long t; 484 485 switch ( argc ) { 486 case 1: 487 Debug( LDAP_DEBUG_ANY, 488 "%s: line %d: missing timeout value in \"idle-timeout <seconds>\" line\n", 489 fname, lineno, 0 ); 490 return 1; 491 case 2: 492 break; 493 default: 494 Debug( LDAP_DEBUG_ANY, 495 "%s: line %d: extra cruft after timeout value in \"idle-timeout <seconds>\" line\n", 496 fname, lineno, 0 ); 497 return 1; 498 } 499 500 if ( lutil_parse_time( argv[ 1 ], &t ) ) { 501 Debug( LDAP_DEBUG_ANY, 502 "%s: line %d: unable to parse timeout \"%s\" in \"idle-timeout <seconds>\" line\n", 503 fname, lineno, argv[ 1 ] ); 504 return 1; 505 506 } 507 508 mi->mi_idle_timeout = (time_t)t; 509 510 /* conn ttl */ 511 } else if ( strcasecmp( argv[ 0 ], "conn-ttl" ) == 0 ) { 512 unsigned long t; 513 514 switch ( argc ) { 515 case 1: 516 Debug( LDAP_DEBUG_ANY, 517 "%s: line %d: missing ttl value in \"conn-ttl <seconds>\" line\n", 518 fname, lineno, 0 ); 519 return 1; 520 case 2: 521 break; 522 default: 523 Debug( LDAP_DEBUG_ANY, 524 "%s: line %d: extra cruft after ttl value in \"conn-ttl <seconds>\" line\n", 525 fname, lineno, 0 ); 526 return 1; 527 } 528 529 if ( lutil_parse_time( argv[ 1 ], &t ) ) { 530 Debug( LDAP_DEBUG_ANY, 531 "%s: line %d: unable to parse ttl \"%s\" in \"conn-ttl <seconds>\" line\n", 532 fname, lineno, argv[ 1 ] ); 533 return 1; 534 535 } 536 537 mi->mi_conn_ttl = (time_t)t; 538 539 /* bind timeout when connecting to ldap servers */ 540 } else if ( strcasecmp( argv[ 0 ], "bind-timeout" ) == 0 ) { 541 unsigned long t; 542 struct timeval *tp = mi->mi_ntargets ? 543 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_bind_timeout 544 : &mi->mi_bind_timeout; 545 546 switch ( argc ) { 547 case 1: 548 Debug( LDAP_DEBUG_ANY, 549 "%s: line %d: missing timeout value in \"bind-timeout <microseconds>\" line\n", 550 fname, lineno, 0 ); 551 return 1; 552 case 2: 553 break; 554 default: 555 Debug( LDAP_DEBUG_ANY, 556 "%s: line %d: extra cruft after timeout value in \"bind-timeout <microseconds>\" line\n", 557 fname, lineno, 0 ); 558 return 1; 559 } 560 561 if ( lutil_atoul( &t, argv[ 1 ] ) != 0 ) { 562 Debug( LDAP_DEBUG_ANY, 563 "%s: line %d: unable to parse timeout \"%s\" in \"bind-timeout <microseconds>\" line\n", 564 fname, lineno, argv[ 1 ] ); 565 return 1; 566 567 } 568 569 tp->tv_sec = t/1000000; 570 tp->tv_usec = t%1000000; 571 572 /* name to use for meta_back_group */ 573 } else if ( strcasecmp( argv[ 0 ], "acl-authcDN" ) == 0 574 || strcasecmp( argv[ 0 ], "binddn" ) == 0 ) 575 { 576 int i = mi->mi_ntargets - 1; 577 struct berval dn; 578 579 if ( i < 0 ) { 580 Debug( LDAP_DEBUG_ANY, 581 "%s: line %d: need \"uri\" directive first\n", 582 fname, lineno, 0 ); 583 return 1; 584 } 585 586 if ( argc != 2 ) { 587 Debug( LDAP_DEBUG_ANY, 588 "%s: line %d: missing name in \"binddn <name>\" line\n", 589 fname, lineno, 0 ); 590 return 1; 591 } 592 593 if ( strcasecmp( argv[ 0 ], "binddn" ) == 0 ) { 594 Debug( LDAP_DEBUG_ANY, "%s: line %d: " 595 "\"binddn\" statement is deprecated; " 596 "use \"acl-authcDN\" instead\n", 597 fname, lineno, 0 ); 598 /* FIXME: some day we'll need to throw an error */ 599 } 600 601 ber_str2bv( argv[ 1 ], 0, 0, &dn ); 602 if ( dnNormalize( 0, NULL, NULL, &dn, &mi->mi_targets[ i ]->mt_binddn, 603 NULL ) != LDAP_SUCCESS ) 604 { 605 Debug( LDAP_DEBUG_ANY, "%s: line %d: " 606 "bind DN '%s' is invalid\n", 607 fname, lineno, argv[ 1 ] ); 608 return( 1 ); 609 } 610 611 /* password to use for meta_back_group */ 612 } else if ( strcasecmp( argv[ 0 ], "acl-passwd" ) == 0 613 || strcasecmp( argv[ 0 ], "bindpw" ) == 0 ) 614 { 615 int i = mi->mi_ntargets - 1; 616 617 if ( i < 0 ) { 618 Debug( LDAP_DEBUG_ANY, 619 "%s: line %d: need \"uri\" directive first\n", 620 fname, lineno, 0 ); 621 return 1; 622 } 623 624 if ( argc != 2 ) { 625 Debug( LDAP_DEBUG_ANY, 626 "%s: line %d: missing password in \"bindpw <password>\" line\n", 627 fname, lineno, 0 ); 628 return 1; 629 } 630 631 if ( strcasecmp( argv[ 0 ], "bindpw" ) == 0 ) { 632 Debug( LDAP_DEBUG_ANY, "%s: line %d: " 633 "\"bindpw\" statement is deprecated; " 634 "use \"acl-passwd\" instead\n", 635 fname, lineno, 0 ); 636 /* FIXME: some day we'll need to throw an error */ 637 } 638 639 ber_str2bv( argv[ 1 ], 0L, 1, &mi->mi_targets[ i ]->mt_bindpw ); 640 641 /* save bind creds for referral rebinds? */ 642 } else if ( strcasecmp( argv[ 0 ], "rebind-as-user" ) == 0 ) { 643 if ( argc > 2 ) { 644 Debug( LDAP_DEBUG_ANY, 645 "%s: line %d: \"rebind-as-user {NO|yes}\" takes 1 argument.\n", 646 fname, lineno, 0 ); 647 return( 1 ); 648 } 649 650 if ( argc == 1 ) { 651 Debug( LDAP_DEBUG_ANY, 652 "%s: line %d: deprecated use of \"rebind-as-user {FALSE|true}\" with no arguments.\n", 653 fname, lineno, 0 ); 654 mi->mi_flags |= LDAP_BACK_F_SAVECRED; 655 656 } else { 657 switch ( check_true_false( argv[ 1 ] ) ) { 658 case 0: 659 mi->mi_flags &= ~LDAP_BACK_F_SAVECRED; 660 break; 661 662 case 1: 663 mi->mi_flags |= LDAP_BACK_F_SAVECRED; 664 break; 665 666 default: 667 Debug( LDAP_DEBUG_ANY, 668 "%s: line %d: \"rebind-as-user {FALSE|true}\" unknown argument \"%s\".\n", 669 fname, lineno, argv[ 1 ] ); 670 return 1; 671 } 672 } 673 674 } else if ( strcasecmp( argv[ 0 ], "chase-referrals" ) == 0 ) { 675 unsigned *flagsp = mi->mi_ntargets ? 676 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags 677 : &mi->mi_flags; 678 679 if ( argc != 2 ) { 680 Debug( LDAP_DEBUG_ANY, 681 "%s: line %d: \"chase-referrals {TRUE|false}\" needs 1 argument.\n", 682 fname, lineno, 0 ); 683 return( 1 ); 684 } 685 686 /* this is the default; we add it because the default might change... */ 687 switch ( check_true_false( argv[ 1 ] ) ) { 688 case 1: 689 *flagsp |= LDAP_BACK_F_CHASE_REFERRALS; 690 break; 691 692 case 0: 693 *flagsp &= ~LDAP_BACK_F_CHASE_REFERRALS; 694 break; 695 696 default: 697 Debug( LDAP_DEBUG_ANY, 698 "%s: line %d: \"chase-referrals {TRUE|false}\": unknown argument \"%s\".\n", 699 fname, lineno, argv[ 1 ] ); 700 return( 1 ); 701 } 702 703 } else if ( strcasecmp( argv[ 0 ], "tls" ) == 0 ) { 704 unsigned *flagsp = mi->mi_ntargets ? 705 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags 706 : &mi->mi_flags; 707 708 if ( argc != 2 ) { 709 Debug( LDAP_DEBUG_ANY, 710 "%s: line %d: \"tls <what>\" needs 1 argument.\n", 711 fname, lineno, 0 ); 712 return( 1 ); 713 } 714 715 /* start */ 716 if ( strcasecmp( argv[ 1 ], "start" ) == 0 ) { 717 *flagsp |= ( LDAP_BACK_F_USE_TLS | LDAP_BACK_F_TLS_CRITICAL ); 718 719 /* try start tls */ 720 } else if ( strcasecmp( argv[ 1 ], "try-start" ) == 0 ) { 721 *flagsp &= ~LDAP_BACK_F_TLS_CRITICAL; 722 *flagsp |= LDAP_BACK_F_USE_TLS; 723 724 /* propagate start tls */ 725 } else if ( strcasecmp( argv[ 1 ], "propagate" ) == 0 ) { 726 *flagsp |= ( LDAP_BACK_F_PROPAGATE_TLS | LDAP_BACK_F_TLS_CRITICAL ); 727 728 /* try start tls */ 729 } else if ( strcasecmp( argv[ 1 ], "try-propagate" ) == 0 ) { 730 *flagsp &= ~LDAP_BACK_F_TLS_CRITICAL; 731 *flagsp |= LDAP_BACK_F_PROPAGATE_TLS; 732 733 } else { 734 Debug( LDAP_DEBUG_ANY, 735 "%s: line %d: \"tls <what>\": unknown argument \"%s\".\n", 736 fname, lineno, argv[ 1 ] ); 737 return( 1 ); 738 } 739 740 } else if ( strcasecmp( argv[ 0 ], "t-f-support" ) == 0 ) { 741 unsigned *flagsp = mi->mi_ntargets ? 742 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags 743 : &mi->mi_flags; 744 745 if ( argc != 2 ) { 746 Debug( LDAP_DEBUG_ANY, 747 "%s: line %d: \"t-f-support {FALSE|true|discover}\" needs 1 argument.\n", 748 fname, lineno, 0 ); 749 return( 1 ); 750 } 751 752 switch ( check_true_false( argv[ 1 ] ) ) { 753 case 0: 754 *flagsp &= ~LDAP_BACK_F_T_F_MASK2; 755 break; 756 757 case 1: 758 *flagsp |= LDAP_BACK_F_T_F; 759 break; 760 761 default: 762 if ( strcasecmp( argv[ 1 ], "discover" ) == 0 ) { 763 *flagsp |= LDAP_BACK_F_T_F_DISCOVER; 764 765 } else { 766 Debug( LDAP_DEBUG_ANY, 767 "%s: line %d: unknown value \"%s\" for \"t-f-support {no|yes|discover}\".\n", 768 fname, lineno, argv[ 1 ] ); 769 return 1; 770 } 771 break; 772 } 773 774 /* onerr? */ 775 } else if ( strcasecmp( argv[ 0 ], "onerr" ) == 0 ) { 776 if ( argc != 2 ) { 777 Debug( LDAP_DEBUG_ANY, 778 "%s: line %d: \"onerr {CONTINUE|report|stop}\" takes 1 argument\n", 779 fname, lineno, 0 ); 780 return( 1 ); 781 } 782 783 if ( strcasecmp( argv[ 1 ], "continue" ) == 0 ) { 784 mi->mi_flags &= ~META_BACK_F_ONERR_MASK; 785 786 } else if ( strcasecmp( argv[ 1 ], "stop" ) == 0 ) { 787 mi->mi_flags |= META_BACK_F_ONERR_STOP; 788 789 } else if ( strcasecmp( argv[ 1 ], "report" ) == 0 ) { 790 mi->mi_flags |= META_BACK_F_ONERR_REPORT; 791 792 } else { 793 Debug( LDAP_DEBUG_ANY, 794 "%s: line %d: \"onerr {CONTINUE|report|stop}\": invalid arg \"%s\".\n", 795 fname, lineno, argv[ 1 ] ); 796 return 1; 797 } 798 799 /* bind-defer? */ 800 } else if ( strcasecmp( argv[ 0 ], "pseudoroot-bind-defer" ) == 0 801 || strcasecmp( argv[ 0 ], "root-bind-defer" ) == 0 ) 802 { 803 if ( argc != 2 ) { 804 Debug( LDAP_DEBUG_ANY, 805 "%s: line %d: \"[pseudo]root-bind-defer {TRUE|false}\" takes 1 argument\n", 806 fname, lineno, 0 ); 807 return( 1 ); 808 } 809 810 switch ( check_true_false( argv[ 1 ] ) ) { 811 case 0: 812 mi->mi_flags &= ~META_BACK_F_DEFER_ROOTDN_BIND; 813 break; 814 815 case 1: 816 mi->mi_flags |= META_BACK_F_DEFER_ROOTDN_BIND; 817 break; 818 819 default: 820 Debug( LDAP_DEBUG_ANY, 821 "%s: line %d: \"[pseudo]root-bind-defer {TRUE|false}\": invalid arg \"%s\".\n", 822 fname, lineno, argv[ 1 ] ); 823 return 1; 824 } 825 826 /* single-conn? */ 827 } else if ( strcasecmp( argv[ 0 ], "single-conn" ) == 0 ) { 828 if ( argc != 2 ) { 829 Debug( LDAP_DEBUG_ANY, 830 "%s: line %d: \"single-conn {FALSE|true}\" takes 1 argument\n", 831 fname, lineno, 0 ); 832 return( 1 ); 833 } 834 835 if ( mi->mi_ntargets > 0 ) { 836 Debug( LDAP_DEBUG_ANY, 837 "%s: line %d: \"single-conn\" must appear before target definitions\n", 838 fname, lineno, 0 ); 839 return( 1 ); 840 } 841 842 switch ( check_true_false( argv[ 1 ] ) ) { 843 case 0: 844 mi->mi_flags &= ~LDAP_BACK_F_SINGLECONN; 845 break; 846 847 case 1: 848 mi->mi_flags |= LDAP_BACK_F_SINGLECONN; 849 break; 850 851 default: 852 Debug( LDAP_DEBUG_ANY, 853 "%s: line %d: \"single-conn {FALSE|true}\": invalid arg \"%s\".\n", 854 fname, lineno, argv[ 1 ] ); 855 return 1; 856 } 857 858 /* use-temporaries? */ 859 } else if ( strcasecmp( argv[ 0 ], "use-temporary-conn" ) == 0 ) { 860 if ( argc != 2 ) { 861 Debug( LDAP_DEBUG_ANY, 862 "%s: line %d: \"use-temporary-conn {FALSE|true}\" takes 1 argument\n", 863 fname, lineno, 0 ); 864 return( 1 ); 865 } 866 867 if ( mi->mi_ntargets > 0 ) { 868 Debug( LDAP_DEBUG_ANY, 869 "%s: line %d: \"use-temporary-conn\" must appear before target definitions\n", 870 fname, lineno, 0 ); 871 return( 1 ); 872 } 873 874 switch ( check_true_false( argv[ 1 ] ) ) { 875 case 0: 876 mi->mi_flags &= ~LDAP_BACK_F_USE_TEMPORARIES; 877 break; 878 879 case 1: 880 mi->mi_flags |= LDAP_BACK_F_USE_TEMPORARIES; 881 break; 882 883 default: 884 Debug( LDAP_DEBUG_ANY, 885 "%s: line %d: \"use-temporary-conn {FALSE|true}\": invalid arg \"%s\".\n", 886 fname, lineno, argv[ 1 ] ); 887 return 1; 888 } 889 890 /* privileged connections pool max size ? */ 891 } else if ( strcasecmp( argv[ 0 ], "conn-pool-max" ) == 0 ) { 892 if ( argc != 2 ) { 893 Debug( LDAP_DEBUG_ANY, 894 "%s: line %d: \"conn-pool-max <n>\" takes 1 argument\n", 895 fname, lineno, 0 ); 896 return( 1 ); 897 } 898 899 if ( mi->mi_ntargets > 0 ) { 900 Debug( LDAP_DEBUG_ANY, 901 "%s: line %d: \"conn-pool-max\" must appear before target definitions\n", 902 fname, lineno, 0 ); 903 return( 1 ); 904 } 905 906 if ( lutil_atoi( &mi->mi_conn_priv_max, argv[1] ) 907 || mi->mi_conn_priv_max < LDAP_BACK_CONN_PRIV_MIN 908 || mi->mi_conn_priv_max > LDAP_BACK_CONN_PRIV_MAX ) 909 { 910 Debug( LDAP_DEBUG_ANY, 911 "%s: line %d: \"conn-pool-max <n>\": invalid arg \"%s\".\n", 912 fname, lineno, argv[ 1 ] ); 913 return 1; 914 } 915 916 } else if ( strcasecmp( argv[ 0 ], "cancel" ) == 0 ) { 917 unsigned flag = 0; 918 unsigned *flagsp = mi->mi_ntargets ? 919 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags 920 : &mi->mi_flags; 921 922 if ( argc != 2 ) { 923 Debug( LDAP_DEBUG_ANY, 924 "%s: line %d: \"cancel {abandon|ignore|exop}\" takes 1 argument\n", 925 fname, lineno, 0 ); 926 return( 1 ); 927 } 928 929 if ( strcasecmp( argv[ 1 ], "abandon" ) == 0 ) { 930 flag = LDAP_BACK_F_CANCEL_ABANDON; 931 932 } else if ( strcasecmp( argv[ 1 ], "ignore" ) == 0 ) { 933 flag = LDAP_BACK_F_CANCEL_IGNORE; 934 935 } else if ( strcasecmp( argv[ 1 ], "exop" ) == 0 ) { 936 flag = LDAP_BACK_F_CANCEL_EXOP; 937 938 } else if ( strcasecmp( argv[ 1 ], "exop-discover" ) == 0 ) { 939 flag = LDAP_BACK_F_CANCEL_EXOP_DISCOVER; 940 941 } else { 942 Debug( LDAP_DEBUG_ANY, 943 "%s: line %d: \"cancel {abandon|ignore|exop[-discover]}\": unknown mode \"%s\" \n", 944 fname, lineno, argv[ 1 ] ); 945 return( 1 ); 946 } 947 948 *flagsp &= ~LDAP_BACK_F_CANCEL_MASK2; 949 *flagsp |= flag; 950 951 } else if ( strcasecmp( argv[ 0 ], "timeout" ) == 0 ) { 952 char *sep; 953 time_t *tv = mi->mi_ntargets ? 954 mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_timeout 955 : mi->mi_timeout; 956 int c; 957 958 if ( argc < 2 ) { 959 Debug( LDAP_DEBUG_ANY, 960 "%s: line %d: \"timeout [{add|bind|delete|modify|modrdn}=]<val> [...]\" takes at least 1 argument\n", 961 fname, lineno, 0 ); 962 return( 1 ); 963 } 964 965 for ( c = 1; c < argc; c++ ) { 966 time_t *t = NULL; 967 unsigned long val; 968 969 sep = strchr( argv[ c ], '=' ); 970 if ( sep != NULL ) { 971 size_t len = sep - argv[ c ]; 972 973 if ( strncasecmp( argv[ c ], "bind", len ) == 0 ) { 974 t = &tv[ SLAP_OP_BIND ]; 975 /* unbind makes little sense */ 976 } else if ( strncasecmp( argv[ c ], "add", len ) == 0 ) { 977 t = &tv[ SLAP_OP_ADD ]; 978 } else if ( strncasecmp( argv[ c ], "delete", len ) == 0 ) { 979 t = &tv[ SLAP_OP_DELETE ]; 980 } else if ( strncasecmp( argv[ c ], "modrdn", len ) == 0 ) { 981 t = &tv[ SLAP_OP_MODRDN ]; 982 } else if ( strncasecmp( argv[ c ], "modify", len ) == 0 ) { 983 t = &tv[ SLAP_OP_MODIFY ]; 984 } else if ( strncasecmp( argv[ c ], "compare", len ) == 0 ) { 985 t = &tv[ SLAP_OP_COMPARE ]; 986 } else if ( strncasecmp( argv[ c ], "search", len ) == 0 ) { 987 t = &tv[ SLAP_OP_SEARCH ]; 988 /* abandon makes little sense */ 989 #if 0 /* not implemented yet */ 990 } else if ( strncasecmp( argv[ c ], "extended", len ) == 0 ) { 991 t = &tv[ SLAP_OP_EXTENDED ]; 992 #endif 993 } else { 994 char buf[ SLAP_TEXT_BUFLEN ]; 995 snprintf( buf, sizeof( buf ), 996 "unknown/unhandled operation \"%s\" for timeout #%d", 997 argv[ c ], c - 1 ); 998 Debug( LDAP_DEBUG_ANY, 999 "%s: line %d: %s.\n", 1000 fname, lineno, buf ); 1001 return 1; 1002 } 1003 sep++; 1004 1005 } else { 1006 sep = argv[ c ]; 1007 } 1008 1009 if ( lutil_parse_time( sep, &val ) != 0 ) { 1010 Debug( LDAP_DEBUG_ANY, 1011 "%s: line %d: unable to parse value \"%s\" for timeout.\n", 1012 fname, lineno, sep ); 1013 return 1; 1014 } 1015 1016 if ( t ) { 1017 *t = (time_t)val; 1018 1019 } else { 1020 int i; 1021 1022 for ( i = 0; i < SLAP_OP_LAST; i++ ) { 1023 tv[ i ] = (time_t)val; 1024 } 1025 } 1026 } 1027 1028 /* name to use as pseudo-root dn */ 1029 } else if ( strcasecmp( argv[ 0 ], "pseudorootdn" ) == 0 ) { 1030 int i = mi->mi_ntargets - 1; 1031 1032 if ( i < 0 ) { 1033 Debug( LDAP_DEBUG_ANY, 1034 "%s: line %d: need \"uri\" directive first\n", 1035 fname, lineno, 0 ); 1036 return 1; 1037 } 1038 1039 if ( argc != 2 ) { 1040 Debug( LDAP_DEBUG_ANY, 1041 "%s: line %d: missing name in \"pseudorootdn <name>\" line\n", 1042 fname, lineno, 0 ); 1043 return 1; 1044 } 1045 1046 /* 1047 * exact replacement: 1048 * 1049 1050 idassert-bind bindmethod=simple 1051 binddn=<pseudorootdn> 1052 credentials=<pseudorootpw> 1053 mode=none 1054 flags=non-prescriptive 1055 idassert-authzFrom "dn:<rootdn>" 1056 1057 * so that only when authc'd as <rootdn> the proxying occurs 1058 * rebinding as the <pseudorootdn> without proxyAuthz. 1059 */ 1060 1061 Debug( LDAP_DEBUG_ANY, 1062 "%s: line %d: \"pseudorootdn\", \"pseudorootpw\" are no longer supported; " 1063 "use \"idassert-bind\" and \"idassert-authzFrom\" instead.\n", 1064 fname, lineno, 0 ); 1065 1066 { 1067 char binddn[ SLAP_TEXT_BUFLEN ]; 1068 char *cargv[] = { 1069 "idassert-bind", 1070 "bindmethod=simple", 1071 NULL, 1072 "mode=none", 1073 "flags=non-prescriptive", 1074 NULL 1075 }; 1076 int cargc = 5; 1077 int rc; 1078 1079 if ( BER_BVISNULL( &be->be_rootndn ) ) { 1080 Debug( LDAP_DEBUG_ANY, "%s: line %d: \"pseudorootpw\": \"rootdn\" must be defined first.\n", 1081 fname, lineno, 0 ); 1082 return 1; 1083 } 1084 1085 if ( snprintf( binddn, sizeof( binddn ), "binddn=%s", argv[ 1 ] ) >= sizeof( binddn ) ) { 1086 Debug( LDAP_DEBUG_ANY, "%s: line %d: \"pseudorootdn\" too long.\n", 1087 fname, lineno, 0 ); 1088 return 1; 1089 } 1090 cargv[ 2 ] = binddn; 1091 1092 rc = mi->mi_ldap_extra->idassert_parse_cf( fname, lineno, cargc, cargv, &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert ); 1093 if ( rc == 0 ) { 1094 struct berval bv; 1095 1096 if ( mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert_authz != NULL ) { 1097 Debug( LDAP_DEBUG_ANY, "%s: line %d: \"idassert-authzFrom\" already defined (discarded).\n", 1098 fname, lineno, 0 ); 1099 ber_bvarray_free( mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert_authz ); 1100 mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert_authz = NULL; 1101 } 1102 1103 assert( !BER_BVISNULL( &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert_authcDN ) ); 1104 1105 bv.bv_len = STRLENOF( "dn:" ) + be->be_rootndn.bv_len; 1106 bv.bv_val = ber_memalloc( bv.bv_len + 1 ); 1107 AC_MEMCPY( bv.bv_val, "dn:", STRLENOF( "dn:" ) ); 1108 AC_MEMCPY( &bv.bv_val[ STRLENOF( "dn:" ) ], be->be_rootndn.bv_val, be->be_rootndn.bv_len + 1 ); 1109 1110 ber_bvarray_add( &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert_authz, &bv ); 1111 } 1112 1113 return rc; 1114 } 1115 1116 /* password to use as pseudo-root */ 1117 } else if ( strcasecmp( argv[ 0 ], "pseudorootpw" ) == 0 ) { 1118 int i = mi->mi_ntargets - 1; 1119 1120 if ( i < 0 ) { 1121 Debug( LDAP_DEBUG_ANY, 1122 "%s: line %d: need \"uri\" directive first\n", 1123 fname, lineno, 0 ); 1124 return 1; 1125 } 1126 1127 if ( argc != 2 ) { 1128 Debug( LDAP_DEBUG_ANY, 1129 "%s: line %d: missing password in \"pseudorootpw <password>\" line\n", 1130 fname, lineno, 0 ); 1131 return 1; 1132 } 1133 1134 Debug( LDAP_DEBUG_ANY, 1135 "%s: line %d: \"pseudorootdn\", \"pseudorootpw\" are no longer supported; " 1136 "use \"idassert-bind\" and \"idassert-authzFrom\" instead.\n", 1137 fname, lineno, 0 ); 1138 1139 if ( BER_BVISNULL( &mi->mi_targets[ i ]->mt_idassert_authcDN ) ) { 1140 Debug( LDAP_DEBUG_ANY, "%s: line %d: \"pseudorootpw\": \"pseudorootdn\" must be defined first.\n", 1141 fname, lineno, 0 ); 1142 return 1; 1143 } 1144 1145 if ( !BER_BVISNULL( &mi->mi_targets[ i ]->mt_idassert_passwd ) ) { 1146 memset( mi->mi_targets[ i ]->mt_idassert_passwd.bv_val, 0, 1147 mi->mi_targets[ i ]->mt_idassert_passwd.bv_len ); 1148 ber_memfree( mi->mi_targets[ i ]->mt_idassert_passwd.bv_val ); 1149 } 1150 ber_str2bv( argv[ 1 ], 0, 1, &mi->mi_targets[ i ]->mt_idassert_passwd ); 1151 1152 /* idassert-bind */ 1153 } else if ( strcasecmp( argv[ 0 ], "idassert-bind" ) == 0 ) { 1154 if ( mi->mi_ntargets == 0 ) { 1155 Debug( LDAP_DEBUG_ANY, 1156 "%s: line %d: \"idassert-bind\" " 1157 "must appear inside a target specification.\n", 1158 fname, lineno, 0 ); 1159 return 1; 1160 } 1161 1162 return mi->mi_ldap_extra->idassert_parse_cf( fname, lineno, argc, argv, &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert ); 1163 1164 /* idassert-authzFrom */ 1165 } else if ( strcasecmp( argv[ 0 ], "idassert-authzFrom" ) == 0 ) { 1166 if ( mi->mi_ntargets == 0 ) { 1167 Debug( LDAP_DEBUG_ANY, 1168 "%s: line %d: \"idassert-bind\" " 1169 "must appear inside a target specification.\n", 1170 fname, lineno, 0 ); 1171 return 1; 1172 } 1173 1174 switch ( argc ) { 1175 case 2: 1176 break; 1177 1178 case 1: 1179 Debug( LDAP_DEBUG_ANY, 1180 "%s: line %d: missing <id> in \"idassert-authzFrom <id>\".\n", 1181 fname, lineno, 0 ); 1182 return 1; 1183 1184 default: 1185 Debug( LDAP_DEBUG_ANY, 1186 "%s: line %d: extra cruft after <id> in \"idassert-authzFrom <id>\".\n", 1187 fname, lineno, 0 ); 1188 return 1; 1189 } 1190 1191 return mi->mi_ldap_extra->idassert_authzfrom_parse_cf( fname, lineno, argv[ 1 ], &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert ); 1192 1193 /* quarantine */ 1194 } else if ( strcasecmp( argv[ 0 ], "quarantine" ) == 0 ) { 1195 char buf[ SLAP_TEXT_BUFLEN ] = { '\0' }; 1196 slap_retry_info_t *ri = mi->mi_ntargets ? 1197 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_quarantine 1198 : &mi->mi_quarantine; 1199 1200 if ( ( mi->mi_ntargets == 0 && META_BACK_QUARANTINE( mi ) ) 1201 || ( mi->mi_ntargets > 0 && META_BACK_TGT_QUARANTINE( mi->mi_targets[ mi->mi_ntargets - 1 ] ) ) ) 1202 { 1203 Debug( LDAP_DEBUG_ANY, 1204 "%s: line %d: quarantine already defined.\n", 1205 fname, lineno, 0 ); 1206 return 1; 1207 } 1208 1209 switch ( argc ) { 1210 case 2: 1211 break; 1212 1213 case 1: 1214 Debug( LDAP_DEBUG_ANY, 1215 "%s: line %d: missing arg in \"quarantine <pattern list>\".\n", 1216 fname, lineno, 0 ); 1217 return 1; 1218 1219 default: 1220 Debug( LDAP_DEBUG_ANY, 1221 "%s: line %d: extra cruft after \"quarantine <pattern list>\".\n", 1222 fname, lineno, 0 ); 1223 return 1; 1224 } 1225 1226 if ( ri != &mi->mi_quarantine ) { 1227 ri->ri_interval = NULL; 1228 ri->ri_num = NULL; 1229 } 1230 1231 if ( mi->mi_ntargets > 0 && !META_BACK_QUARANTINE( mi ) ) { 1232 ldap_pvt_thread_mutex_init( &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_quarantine_mutex ); 1233 } 1234 1235 if ( mi->mi_ldap_extra->retry_info_parse( argv[ 1 ], ri, buf, sizeof( buf ) ) ) { 1236 Debug( LDAP_DEBUG_ANY, 1237 "%s line %d: %s.\n", 1238 fname, lineno, buf ); 1239 return 1; 1240 } 1241 1242 if ( mi->mi_ntargets == 0 ) { 1243 mi->mi_flags |= LDAP_BACK_F_QUARANTINE; 1244 1245 } else { 1246 mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags |= LDAP_BACK_F_QUARANTINE; 1247 } 1248 1249 #ifdef SLAP_CONTROL_X_SESSION_TRACKING 1250 /* session tracking request */ 1251 } else if ( strcasecmp( argv[ 0 ], "session-tracking-request" ) == 0 ) { 1252 unsigned *flagsp = mi->mi_ntargets ? 1253 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags 1254 : &mi->mi_flags; 1255 1256 if ( argc != 2 ) { 1257 Debug( LDAP_DEBUG_ANY, 1258 "%s: line %d: \"session-tracking-request {TRUE|false}\" needs 1 argument.\n", 1259 fname, lineno, 0 ); 1260 return( 1 ); 1261 } 1262 1263 /* this is the default; we add it because the default might change... */ 1264 switch ( check_true_false( argv[ 1 ] ) ) { 1265 case 1: 1266 *flagsp |= LDAP_BACK_F_ST_REQUEST; 1267 break; 1268 1269 case 0: 1270 *flagsp &= ~LDAP_BACK_F_ST_REQUEST; 1271 break; 1272 1273 default: 1274 Debug( LDAP_DEBUG_ANY, 1275 "%s: line %d: \"session-tracking-request {TRUE|false}\": unknown argument \"%s\".\n", 1276 fname, lineno, argv[ 1 ] ); 1277 return( 1 ); 1278 } 1279 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */ 1280 1281 /* dn massaging */ 1282 } else if ( strcasecmp( argv[ 0 ], "suffixmassage" ) == 0 ) { 1283 BackendDB *tmp_bd; 1284 int i = mi->mi_ntargets - 1, c, rc; 1285 struct berval dn, nvnc, pvnc, nrnc, prnc; 1286 1287 if ( i < 0 ) { 1288 Debug( LDAP_DEBUG_ANY, 1289 "%s: line %d: need \"uri\" directive first\n", 1290 fname, lineno, 0 ); 1291 return 1; 1292 } 1293 1294 /* 1295 * syntax: 1296 * 1297 * suffixmassage <suffix> <massaged suffix> 1298 * 1299 * the <suffix> field must be defined as a valid suffix 1300 * (or suffixAlias?) for the current database; 1301 * the <massaged suffix> shouldn't have already been 1302 * defined as a valid suffix or suffixAlias for the 1303 * current server 1304 */ 1305 if ( argc != 3 ) { 1306 Debug( LDAP_DEBUG_ANY, 1307 "%s: line %d: syntax is \"suffixMassage <suffix> <massaged suffix>\"\n", 1308 fname, lineno, 0 ); 1309 return 1; 1310 } 1311 1312 ber_str2bv( argv[ 1 ], 0, 0, &dn ); 1313 if ( dnPrettyNormal( NULL, &dn, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) { 1314 Debug( LDAP_DEBUG_ANY, "%s: line %d: " 1315 "suffix \"%s\" is invalid\n", 1316 fname, lineno, argv[ 1 ] ); 1317 return 1; 1318 } 1319 1320 for ( c = 0; !BER_BVISNULL( &be->be_nsuffix[ c ] ); c++ ) { 1321 if ( dnIsSuffix( &nvnc, &be->be_nsuffix[ 0 ] ) ) { 1322 break; 1323 } 1324 } 1325 1326 if ( BER_BVISNULL( &be->be_nsuffix[ c ] ) ) { 1327 Debug( LDAP_DEBUG_ANY, "%s: line %d: " 1328 "<suffix> \"%s\" must be within the database naming context, in " 1329 "\"suffixMassage <suffix> <massaged suffix>\"\n", 1330 fname, lineno, pvnc.bv_val ); 1331 free( pvnc.bv_val ); 1332 free( nvnc.bv_val ); 1333 return 1; 1334 } 1335 1336 ber_str2bv( argv[ 2 ], 0, 0, &dn ); 1337 if ( dnPrettyNormal( NULL, &dn, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) { 1338 Debug( LDAP_DEBUG_ANY, "%s: line %d: " 1339 "massaged suffix \"%s\" is invalid\n", 1340 fname, lineno, argv[ 2 ] ); 1341 free( pvnc.bv_val ); 1342 free( nvnc.bv_val ); 1343 return 1; 1344 } 1345 1346 tmp_bd = select_backend( &nrnc, 0 ); 1347 if ( tmp_bd != NULL && tmp_bd->be_private == be->be_private ) { 1348 Debug( LDAP_DEBUG_ANY, 1349 "%s: line %d: warning: <massaged suffix> \"%s\" resolves to this database, in " 1350 "\"suffixMassage <suffix> <massaged suffix>\"\n", 1351 fname, lineno, prnc.bv_val ); 1352 } 1353 1354 /* 1355 * The suffix massaging is emulated by means of the 1356 * rewrite capabilities 1357 */ 1358 rc = suffix_massage_config( mi->mi_targets[ i ]->mt_rwmap.rwm_rw, 1359 &pvnc, &nvnc, &prnc, &nrnc ); 1360 1361 free( pvnc.bv_val ); 1362 free( nvnc.bv_val ); 1363 free( prnc.bv_val ); 1364 free( nrnc.bv_val ); 1365 1366 return rc; 1367 1368 /* rewrite stuff ... */ 1369 } else if ( strncasecmp( argv[ 0 ], "rewrite", 7 ) == 0 ) { 1370 int i = mi->mi_ntargets - 1; 1371 1372 if ( i < 0 ) { 1373 Debug( LDAP_DEBUG_ANY, "%s: line %d: \"rewrite\" " 1374 "statement outside target definition.\n", 1375 fname, lineno, 0 ); 1376 return 1; 1377 } 1378 1379 return rewrite_parse( mi->mi_targets[ i ]->mt_rwmap.rwm_rw, 1380 fname, lineno, argc, argv ); 1381 1382 /* objectclass/attribute mapping */ 1383 } else if ( strcasecmp( argv[ 0 ], "map" ) == 0 ) { 1384 int i = mi->mi_ntargets - 1; 1385 1386 if ( i < 0 ) { 1387 Debug( LDAP_DEBUG_ANY, 1388 "%s: line %d: need \"uri\" directive first\n", 1389 fname, lineno, 0 ); 1390 return 1; 1391 } 1392 1393 return ldap_back_map_config( &mi->mi_targets[ i ]->mt_rwmap.rwm_oc, 1394 &mi->mi_targets[ i ]->mt_rwmap.rwm_at, 1395 fname, lineno, argc, argv ); 1396 1397 } else if ( strcasecmp( argv[ 0 ], "nretries" ) == 0 ) { 1398 int i = mi->mi_ntargets - 1; 1399 int nretries = META_RETRY_UNDEFINED; 1400 1401 if ( argc != 2 ) { 1402 Debug( LDAP_DEBUG_ANY, 1403 "%s: line %d: need value in \"nretries <value>\"\n", 1404 fname, lineno, 0 ); 1405 return 1; 1406 } 1407 1408 if ( strcasecmp( argv[ 1 ], "forever" ) == 0 ) { 1409 nretries = META_RETRY_FOREVER; 1410 1411 } else if ( strcasecmp( argv[ 1 ], "never" ) == 0 ) { 1412 nretries = META_RETRY_NEVER; 1413 1414 } else { 1415 if ( lutil_atoi( &nretries, argv[ 1 ] ) != 0 ) { 1416 Debug( LDAP_DEBUG_ANY, 1417 "%s: line %d: unable to parse value \"%s\" in \"nretries <value>\"\n", 1418 fname, lineno, argv[ 1 ] ); 1419 return 1; 1420 } 1421 } 1422 1423 if ( i < 0 ) { 1424 mi->mi_nretries = nretries; 1425 1426 } else { 1427 mi->mi_targets[ i ]->mt_nretries = nretries; 1428 } 1429 1430 } else if ( strcasecmp( argv[ 0 ], "protocol-version" ) == 0 ) { 1431 int *version = mi->mi_ntargets ? 1432 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_version 1433 : &mi->mi_version; 1434 1435 if ( argc != 2 ) { 1436 Debug( LDAP_DEBUG_ANY, 1437 "%s: line %d: need value in \"protocol-version <version>\"\n", 1438 fname, lineno, 0 ); 1439 return 1; 1440 } 1441 1442 if ( lutil_atoi( version, argv[ 1 ] ) != 0 ) { 1443 Debug( LDAP_DEBUG_ANY, 1444 "%s: line %d: unable to parse version \"%s\" in \"protocol-version <version>\"\n", 1445 fname, lineno, argv[ 1 ] ); 1446 return 1; 1447 } 1448 1449 if ( *version != 0 && ( *version < LDAP_VERSION_MIN || *version > LDAP_VERSION_MAX ) ) { 1450 Debug( LDAP_DEBUG_ANY, 1451 "%s: line %d: unsupported version \"%s\" in \"protocol-version <version>\"\n", 1452 fname, lineno, argv[ 1 ] ); 1453 return 1; 1454 } 1455 1456 /* do not return search references */ 1457 } else if ( strcasecmp( argv[ 0 ], "norefs" ) == 0 ) { 1458 unsigned *flagsp = mi->mi_ntargets ? 1459 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags 1460 : &mi->mi_flags; 1461 1462 if ( argc != 2 ) { 1463 Debug( LDAP_DEBUG_ANY, 1464 "%s: line %d: \"norefs {TRUE|false}\" needs 1 argument.\n", 1465 fname, lineno, 0 ); 1466 return( 1 ); 1467 } 1468 1469 /* this is the default; we add it because the default might change... */ 1470 switch ( check_true_false( argv[ 1 ] ) ) { 1471 case 1: 1472 *flagsp |= LDAP_BACK_F_NOREFS; 1473 break; 1474 1475 case 0: 1476 *flagsp &= ~LDAP_BACK_F_NOREFS; 1477 break; 1478 1479 default: 1480 Debug( LDAP_DEBUG_ANY, 1481 "%s: line %d: \"norefs {TRUE|false}\": unknown argument \"%s\".\n", 1482 fname, lineno, argv[ 1 ] ); 1483 return( 1 ); 1484 } 1485 1486 /* anything else */ 1487 } else { 1488 return SLAP_CONF_UNKNOWN; 1489 } 1490 return 0; 1491 } 1492 1493 int 1494 ldap_back_map_config( 1495 struct ldapmap *oc_map, 1496 struct ldapmap *at_map, 1497 const char *fname, 1498 int lineno, 1499 int argc, 1500 char **argv ) 1501 { 1502 struct ldapmap *map; 1503 struct ldapmapping *mapping; 1504 char *src, *dst; 1505 int is_oc = 0; 1506 1507 if ( argc < 3 || argc > 4 ) { 1508 Debug( LDAP_DEBUG_ANY, 1509 "%s: line %d: syntax is \"map {objectclass | attribute} [<local> | *] {<foreign> | *}\"\n", 1510 fname, lineno, 0 ); 1511 return 1; 1512 } 1513 1514 if ( strcasecmp( argv[ 1 ], "objectclass" ) == 0 ) { 1515 map = oc_map; 1516 is_oc = 1; 1517 1518 } else if ( strcasecmp( argv[ 1 ], "attribute" ) == 0 ) { 1519 map = at_map; 1520 1521 } else { 1522 Debug( LDAP_DEBUG_ANY, "%s: line %d: syntax is " 1523 "\"map {objectclass | attribute} [<local> | *] " 1524 "{<foreign> | *}\"\n", 1525 fname, lineno, 0 ); 1526 return 1; 1527 } 1528 1529 if ( strcmp( argv[ 2 ], "*" ) == 0 ) { 1530 if ( argc < 4 || strcmp( argv[ 3 ], "*" ) == 0 ) { 1531 map->drop_missing = ( argc < 4 ); 1532 goto success_return; 1533 } 1534 src = dst = argv[ 3 ]; 1535 1536 } else if ( argc < 4 ) { 1537 src = ""; 1538 dst = argv[ 2 ]; 1539 1540 } else { 1541 src = argv[ 2 ]; 1542 dst = ( strcmp( argv[ 3 ], "*" ) == 0 ? src : argv[ 3 ] ); 1543 } 1544 1545 if ( ( map == at_map ) 1546 && ( strcasecmp( src, "objectclass" ) == 0 1547 || strcasecmp( dst, "objectclass" ) == 0 ) ) 1548 { 1549 Debug( LDAP_DEBUG_ANY, 1550 "%s: line %d: objectclass attribute cannot be mapped\n", 1551 fname, lineno, 0 ); 1552 } 1553 1554 mapping = (struct ldapmapping *)ch_calloc( 2, 1555 sizeof(struct ldapmapping) ); 1556 if ( mapping == NULL ) { 1557 Debug( LDAP_DEBUG_ANY, 1558 "%s: line %d: out of memory\n", 1559 fname, lineno, 0 ); 1560 return 1; 1561 } 1562 ber_str2bv( src, 0, 1, &mapping[ 0 ].src ); 1563 ber_str2bv( dst, 0, 1, &mapping[ 0 ].dst ); 1564 mapping[ 1 ].src = mapping[ 0 ].dst; 1565 mapping[ 1 ].dst = mapping[ 0 ].src; 1566 1567 /* 1568 * schema check 1569 */ 1570 if ( is_oc ) { 1571 if ( src[ 0 ] != '\0' ) { 1572 if ( oc_bvfind( &mapping[ 0 ].src ) == NULL ) { 1573 Debug( LDAP_DEBUG_ANY, 1574 "%s: line %d: warning, source objectClass '%s' " 1575 "should be defined in schema\n", 1576 fname, lineno, src ); 1577 1578 /* 1579 * FIXME: this should become an err 1580 */ 1581 goto error_return; 1582 } 1583 } 1584 1585 if ( oc_bvfind( &mapping[ 0 ].dst ) == NULL ) { 1586 Debug( LDAP_DEBUG_ANY, 1587 "%s: line %d: warning, destination objectClass '%s' " 1588 "is not defined in schema\n", 1589 fname, lineno, dst ); 1590 } 1591 } else { 1592 int rc; 1593 const char *text = NULL; 1594 AttributeDescription *ad = NULL; 1595 1596 if ( src[ 0 ] != '\0' ) { 1597 rc = slap_bv2ad( &mapping[ 0 ].src, &ad, &text ); 1598 if ( rc != LDAP_SUCCESS ) { 1599 Debug( LDAP_DEBUG_ANY, 1600 "%s: line %d: warning, source attributeType '%s' " 1601 "should be defined in schema\n", 1602 fname, lineno, src ); 1603 1604 /* 1605 * FIXME: this should become an err 1606 */ 1607 /* 1608 * we create a fake "proxied" ad 1609 * and add it here. 1610 */ 1611 1612 rc = slap_bv2undef_ad( &mapping[ 0 ].src, 1613 &ad, &text, SLAP_AD_PROXIED ); 1614 if ( rc != LDAP_SUCCESS ) { 1615 char buf[ SLAP_TEXT_BUFLEN ]; 1616 1617 snprintf( buf, sizeof( buf ), 1618 "source attributeType \"%s\": %d (%s)", 1619 src, rc, text ? text : "" ); 1620 Debug( LDAP_DEBUG_ANY, 1621 "%s: line %d: %s\n", 1622 fname, lineno, buf ); 1623 goto error_return; 1624 } 1625 } 1626 1627 ad = NULL; 1628 } 1629 1630 rc = slap_bv2ad( &mapping[ 0 ].dst, &ad, &text ); 1631 if ( rc != LDAP_SUCCESS ) { 1632 Debug( LDAP_DEBUG_ANY, 1633 "%s: line %d: warning, destination attributeType '%s' " 1634 "is not defined in schema\n", 1635 fname, lineno, dst ); 1636 1637 /* 1638 * we create a fake "proxied" ad 1639 * and add it here. 1640 */ 1641 1642 rc = slap_bv2undef_ad( &mapping[ 0 ].dst, 1643 &ad, &text, SLAP_AD_PROXIED ); 1644 if ( rc != LDAP_SUCCESS ) { 1645 char buf[ SLAP_TEXT_BUFLEN ]; 1646 1647 snprintf( buf, sizeof( buf ), 1648 "source attributeType \"%s\": %d (%s)\n", 1649 dst, rc, text ? text : "" ); 1650 Debug( LDAP_DEBUG_ANY, 1651 "%s: line %d: %s\n", 1652 fname, lineno, buf ); 1653 return 1; 1654 } 1655 } 1656 } 1657 1658 if ( (src[ 0 ] != '\0' && avl_find( map->map, (caddr_t)&mapping[ 0 ], mapping_cmp ) != NULL) 1659 || avl_find( map->remap, (caddr_t)&mapping[ 1 ], mapping_cmp ) != NULL) 1660 { 1661 Debug( LDAP_DEBUG_ANY, 1662 "%s: line %d: duplicate mapping found.\n", 1663 fname, lineno, 0 ); 1664 goto error_return; 1665 } 1666 1667 if ( src[ 0 ] != '\0' ) { 1668 avl_insert( &map->map, (caddr_t)&mapping[ 0 ], 1669 mapping_cmp, mapping_dup ); 1670 } 1671 avl_insert( &map->remap, (caddr_t)&mapping[ 1 ], 1672 mapping_cmp, mapping_dup ); 1673 1674 success_return:; 1675 if ( !is_oc && map->map == NULL ) { 1676 /* only init if required */ 1677 ldap_back_map_init( map, &mapping ); 1678 } 1679 1680 return 0; 1681 1682 error_return:; 1683 if ( mapping ) { 1684 ch_free( mapping[ 0 ].src.bv_val ); 1685 ch_free( mapping[ 0 ].dst.bv_val ); 1686 ch_free( mapping ); 1687 } 1688 1689 return 1; 1690 } 1691 1692 1693 #ifdef ENABLE_REWRITE 1694 static char * 1695 suffix_massage_regexize( const char *s ) 1696 { 1697 char *res, *ptr; 1698 const char *p, *r; 1699 int i; 1700 1701 if ( s[ 0 ] == '\0' ) { 1702 return ch_strdup( "^(.+)$" ); 1703 } 1704 1705 for ( i = 0, p = s; 1706 ( r = strchr( p, ',' ) ) != NULL; 1707 p = r + 1, i++ ) 1708 ; 1709 1710 res = ch_calloc( sizeof( char ), 1711 strlen( s ) 1712 + STRLENOF( "((.+),)?" ) 1713 + STRLENOF( "[ ]?" ) * i 1714 + STRLENOF( "$" ) + 1 ); 1715 1716 ptr = lutil_strcopy( res, "((.+),)?" ); 1717 for ( i = 0, p = s; 1718 ( r = strchr( p, ',' ) ) != NULL; 1719 p = r + 1 , i++ ) { 1720 ptr = lutil_strncopy( ptr, p, r - p + 1 ); 1721 ptr = lutil_strcopy( ptr, "[ ]?" ); 1722 1723 if ( r[ 1 ] == ' ' ) { 1724 r++; 1725 } 1726 } 1727 ptr = lutil_strcopy( ptr, p ); 1728 ptr[ 0 ] = '$'; 1729 ptr++; 1730 ptr[ 0 ] = '\0'; 1731 1732 return res; 1733 } 1734 1735 static char * 1736 suffix_massage_patternize( const char *s, const char *p ) 1737 { 1738 ber_len_t len; 1739 char *res, *ptr; 1740 1741 len = strlen( p ); 1742 1743 if ( s[ 0 ] == '\0' ) { 1744 len++; 1745 } 1746 1747 res = ch_calloc( sizeof( char ), len + STRLENOF( "%1" ) + 1 ); 1748 if ( res == NULL ) { 1749 return NULL; 1750 } 1751 1752 ptr = lutil_strcopy( res, ( p[ 0 ] == '\0' ? "%2" : "%1" ) ); 1753 if ( s[ 0 ] == '\0' ) { 1754 ptr[ 0 ] = ','; 1755 ptr++; 1756 } 1757 lutil_strcopy( ptr, p ); 1758 1759 return res; 1760 } 1761 1762 int 1763 suffix_massage_config( 1764 struct rewrite_info *info, 1765 struct berval *pvnc, 1766 struct berval *nvnc, 1767 struct berval *prnc, 1768 struct berval *nrnc 1769 ) 1770 { 1771 char *rargv[ 5 ]; 1772 int line = 0; 1773 1774 rargv[ 0 ] = "rewriteEngine"; 1775 rargv[ 1 ] = "on"; 1776 rargv[ 2 ] = NULL; 1777 rewrite_parse( info, "<suffix massage>", ++line, 2, rargv ); 1778 1779 rargv[ 0 ] = "rewriteContext"; 1780 rargv[ 1 ] = "default"; 1781 rargv[ 2 ] = NULL; 1782 rewrite_parse( info, "<suffix massage>", ++line, 2, rargv ); 1783 1784 rargv[ 0 ] = "rewriteRule"; 1785 rargv[ 1 ] = suffix_massage_regexize( pvnc->bv_val ); 1786 rargv[ 2 ] = suffix_massage_patternize( pvnc->bv_val, prnc->bv_val ); 1787 rargv[ 3 ] = ":"; 1788 rargv[ 4 ] = NULL; 1789 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv ); 1790 ch_free( rargv[ 1 ] ); 1791 ch_free( rargv[ 2 ] ); 1792 1793 if ( BER_BVISEMPTY( pvnc ) ) { 1794 rargv[ 0 ] = "rewriteRule"; 1795 rargv[ 1 ] = "^$"; 1796 rargv[ 2 ] = prnc->bv_val; 1797 rargv[ 3 ] = ":"; 1798 rargv[ 4 ] = NULL; 1799 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv ); 1800 } 1801 1802 rargv[ 0 ] = "rewriteContext"; 1803 rargv[ 1 ] = "searchEntryDN"; 1804 rargv[ 2 ] = NULL; 1805 rewrite_parse( info, "<suffix massage>", ++line, 2, rargv ); 1806 1807 rargv[ 0 ] = "rewriteRule"; 1808 rargv[ 1 ] = suffix_massage_regexize( prnc->bv_val ); 1809 rargv[ 2 ] = suffix_massage_patternize( prnc->bv_val, pvnc->bv_val ); 1810 rargv[ 3 ] = ":"; 1811 rargv[ 4 ] = NULL; 1812 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv ); 1813 ch_free( rargv[ 1 ] ); 1814 ch_free( rargv[ 2 ] ); 1815 1816 if ( BER_BVISEMPTY( prnc ) ) { 1817 rargv[ 0 ] = "rewriteRule"; 1818 rargv[ 1 ] = "^$"; 1819 rargv[ 2 ] = pvnc->bv_val; 1820 rargv[ 3 ] = ":"; 1821 rargv[ 4 ] = NULL; 1822 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv ); 1823 } 1824 1825 /* backward compatibility */ 1826 rargv[ 0 ] = "rewriteContext"; 1827 rargv[ 1 ] = "searchResult"; 1828 rargv[ 2 ] = "alias"; 1829 rargv[ 3 ] = "searchEntryDN"; 1830 rargv[ 4 ] = NULL; 1831 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv ); 1832 1833 rargv[ 0 ] = "rewriteContext"; 1834 rargv[ 1 ] = "matchedDN"; 1835 rargv[ 2 ] = "alias"; 1836 rargv[ 3 ] = "searchEntryDN"; 1837 rargv[ 4 ] = NULL; 1838 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv ); 1839 1840 rargv[ 0 ] = "rewriteContext"; 1841 rargv[ 1 ] = "searchAttrDN"; 1842 rargv[ 2 ] = "alias"; 1843 rargv[ 3 ] = "searchEntryDN"; 1844 rargv[ 4 ] = NULL; 1845 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv ); 1846 1847 /* NOTE: this corresponds to #undef'ining RWM_REFERRAL_REWRITE; 1848 * see servers/slapd/overlays/rwm.h for details */ 1849 rargv[ 0 ] = "rewriteContext"; 1850 rargv[ 1 ] = "referralAttrDN"; 1851 rargv[ 2 ] = NULL; 1852 rewrite_parse( info, "<suffix massage>", ++line, 2, rargv ); 1853 1854 rargv[ 0 ] = "rewriteContext"; 1855 rargv[ 1 ] = "referralDN"; 1856 rargv[ 2 ] = NULL; 1857 rewrite_parse( info, "<suffix massage>", ++line, 2, rargv ); 1858 1859 return 0; 1860 } 1861 #endif /* ENABLE_REWRITE */ 1862 1863