1 /* $NetBSD: backend.c,v 1.4 2025/09/05 21:16:24 christos Exp $ */ 2 3 /* backend.c - routines for dealing with back-end databases */ 4 /* $OpenLDAP$ */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 1998-2024 The OpenLDAP Foundation. 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 /* Portions Copyright (c) 1995 Regents of the University of Michigan. 19 * All rights reserved. 20 * 21 * Redistribution and use in source and binary forms are permitted 22 * provided that this notice is preserved and that due credit is given 23 * to the University of Michigan at Ann Arbor. The name of the University 24 * may not be used to endorse or promote products derived from this 25 * software without specific prior written permission. This software 26 * is provided ``as is'' without express or implied warranty. 27 */ 28 29 30 #include <sys/cdefs.h> 31 __RCSID("$NetBSD: backend.c,v 1.4 2025/09/05 21:16:24 christos Exp $"); 32 33 #include "portable.h" 34 35 #include <stdio.h> 36 37 #include <ac/string.h> 38 #include <ac/socket.h> 39 #include <sys/stat.h> 40 41 #include "slap.h" 42 #include "slap-config.h" 43 #include "lutil.h" 44 #include "lber_pvt.h" 45 46 /* 47 * If a module is configured as dynamic, its header should not 48 * get included into slapd. While this is a general rule and does 49 * not have much of an effect in UNIX, this rule should be adhered 50 * to for Windows, where dynamic object code should not be implicitly 51 * imported into slapd without appropriate __declspec(dllimport) directives. 52 */ 53 54 int nBackendInfo = 0; 55 slap_bi_head backendInfo = LDAP_STAILQ_HEAD_INITIALIZER(backendInfo); 56 57 int nBackendDB = 0; 58 slap_be_head backendDB = LDAP_STAILQ_HEAD_INITIALIZER(backendDB); 59 60 static int 61 backend_init_controls( BackendInfo *bi ) 62 { 63 if ( bi->bi_controls ) { 64 int i; 65 66 for ( i = 0; bi->bi_controls[ i ]; i++ ) { 67 int cid; 68 69 if ( slap_find_control_id( bi->bi_controls[ i ], &cid ) 70 == LDAP_CONTROL_NOT_FOUND ) 71 { 72 if ( !( slapMode & SLAP_TOOL_MODE ) ) { 73 assert( 0 ); 74 } 75 76 return -1; 77 } 78 79 bi->bi_ctrls[ cid ] = 1; 80 } 81 } 82 83 return 0; 84 } 85 86 extern int syncrepl_monitor_init(void); 87 88 int backend_init(void) 89 { 90 int rc = -1; 91 BackendInfo *bi; 92 93 if((nBackendInfo != 0) || !LDAP_STAILQ_EMPTY(&backendInfo)) { 94 /* already initialized */ 95 Debug( LDAP_DEBUG_ANY, 96 "backend_init: already initialized\n" ); 97 return -1; 98 } 99 100 for( bi=slap_binfo; bi->bi_type != NULL; bi++,nBackendInfo++ ) { 101 assert( bi->bi_init != 0 ); 102 103 rc = bi->bi_init( bi ); 104 105 if(rc != 0) { 106 Debug( LDAP_DEBUG_ANY, 107 "backend_init: initialized for type \"%s\"\n", 108 bi->bi_type ); 109 /* destroy those we've already inited */ 110 for( nBackendInfo--; 111 nBackendInfo >= 0 ; 112 nBackendInfo-- ) 113 { 114 if ( slap_binfo[nBackendInfo].bi_destroy ) { 115 slap_binfo[nBackendInfo].bi_destroy( 116 &slap_binfo[nBackendInfo] ); 117 } 118 } 119 return rc; 120 } 121 122 LDAP_STAILQ_INSERT_TAIL(&backendInfo, bi, bi_next); 123 } 124 /* HACK: need schema defined in deterministic order */ 125 syncrepl_monitor_init(); 126 127 if ( nBackendInfo > 0) { 128 return 0; 129 } 130 131 #ifdef SLAPD_MODULES 132 return 0; 133 #else 134 135 Debug( LDAP_DEBUG_ANY, 136 "backend_init: failed\n" ); 137 138 return rc; 139 #endif /* SLAPD_MODULES */ 140 } 141 142 int backend_add(BackendInfo *aBackendInfo) 143 { 144 int rc = 0; 145 146 if ( aBackendInfo->bi_init == NULL ) { 147 Debug( LDAP_DEBUG_ANY, "backend_add: " 148 "backend type \"%s\" does not have the (mandatory)init function\n", 149 aBackendInfo->bi_type ); 150 return -1; 151 } 152 153 rc = aBackendInfo->bi_init(aBackendInfo); 154 if ( rc != 0) { 155 Debug( LDAP_DEBUG_ANY, 156 "backend_add: initialization for type \"%s\" failed\n", 157 aBackendInfo->bi_type ); 158 return rc; 159 } 160 161 (void)backend_init_controls( aBackendInfo ); 162 163 /* now add the backend type to the Backend Info List */ 164 LDAP_STAILQ_INSERT_TAIL( &backendInfo, aBackendInfo, bi_next ); 165 nBackendInfo++; 166 return 0; 167 } 168 169 static int 170 backend_set_controls( BackendDB *be ) 171 { 172 BackendInfo *bi = be->bd_info; 173 174 /* back-relay takes care of itself; so may do other */ 175 if ( overlay_is_over( be ) ) { 176 bi = ((slap_overinfo *)be->bd_info->bi_private)->oi_orig; 177 } 178 179 if ( bi->bi_controls ) { 180 if ( be->be_ctrls[ SLAP_MAX_CIDS ] == 0 ) { 181 AC_MEMCPY( be->be_ctrls, bi->bi_ctrls, 182 sizeof( be->be_ctrls ) ); 183 be->be_ctrls[ SLAP_MAX_CIDS ] = 1; 184 185 } else { 186 int i; 187 188 for ( i = 0; i < SLAP_MAX_CIDS; i++ ) { 189 if ( bi->bi_ctrls[ i ] ) { 190 be->be_ctrls[ i ] = bi->bi_ctrls[ i ]; 191 } 192 } 193 } 194 195 } 196 197 return 0; 198 } 199 200 /* startup a specific backend database */ 201 int backend_startup_one(Backend *be, ConfigReply *cr) 202 { 203 int rc = 0; 204 205 assert( be != NULL ); 206 207 LDAP_TAILQ_INIT( &be->be_pcsn_st.be_pcsn_list ); 208 209 Debug( LDAP_DEBUG_TRACE, 210 "backend_startup_one: starting \"%s\"\n", 211 be->be_suffix ? be->be_suffix[0].bv_val : "(unknown)" ); 212 213 /* set database controls */ 214 (void)backend_set_controls( be ); 215 216 #if 0 217 if ( !BER_BVISEMPTY( &be->be_rootndn ) 218 && select_backend( &be->be_rootndn, 0 ) == be 219 && BER_BVISNULL( &be->be_rootpw ) ) 220 { 221 /* warning: if rootdn entry is created, 222 * it can take rootdn privileges; 223 * set empty rootpw to prevent */ 224 } 225 #endif 226 227 if ( be->bd_info->bi_db_open ) { 228 rc = be->bd_info->bi_db_open( be, cr ); 229 if ( rc == 0 ) { 230 (void)backend_set_controls( be ); 231 be->be_flags |= SLAP_DBFLAG_OPEN; 232 233 } else { 234 char *type = be->bd_info->bi_type; 235 char *suffix = "(null)"; 236 237 if ( overlay_is_over( be ) ) { 238 slap_overinfo *oi = (slap_overinfo *)be->bd_info->bi_private; 239 type = oi->oi_orig->bi_type; 240 } 241 242 if ( be->be_suffix != NULL && !BER_BVISNULL( &be->be_suffix[0] ) ) { 243 suffix = be->be_suffix[0].bv_val; 244 } 245 246 Debug( LDAP_DEBUG_ANY, 247 "backend_startup_one (type=%s, suffix=\"%s\"): " 248 "bi_db_open failed! (%d)\n", 249 type, suffix, rc ); 250 } 251 } 252 253 return rc; 254 } 255 256 int backend_startup(Backend *be) 257 { 258 int i; 259 int rc = 0; 260 BackendInfo *bi; 261 ConfigReply cr={0, ""}; 262 263 if( ! ( nBackendDB > 0 ) ) { 264 /* no databases */ 265 Debug( LDAP_DEBUG_ANY, 266 "backend_startup: %d databases to startup.\n", 267 nBackendDB ); 268 return 1; 269 } 270 271 if(be != NULL) { 272 /* silent noop if disabled */ 273 if ( SLAP_DBDISABLED( be )) 274 return 0; 275 if ( be->bd_info->bi_open ) { 276 rc = be->bd_info->bi_open( be->bd_info ); 277 if ( rc != 0 ) { 278 Debug( LDAP_DEBUG_ANY, 279 "backend_startup: bi_open failed!\n" ); 280 281 return rc; 282 } 283 } 284 285 return backend_startup_one( be, &cr ); 286 } 287 288 /* open frontend, if required */ 289 if ( frontendDB->bd_info->bi_db_open ) { 290 rc = frontendDB->bd_info->bi_db_open( frontendDB, &cr ); 291 if ( rc != 0 ) { 292 Debug( LDAP_DEBUG_ANY, 293 "backend_startup: bi_db_open(frontend) failed! (%d)\n", 294 rc ); 295 return rc; 296 } 297 frontendDB->be_flags |= SLAP_DBFLAG_OPEN; 298 } 299 300 /* open each backend type */ 301 i = -1; 302 LDAP_STAILQ_FOREACH(bi, &backendInfo, bi_next) { 303 i++; 304 if( bi->bi_nDB == 0) { 305 /* no database of this type, don't open */ 306 continue; 307 } 308 309 if( bi->bi_open ) { 310 rc = bi->bi_open( bi ); 311 if ( rc != 0 ) { 312 Debug( LDAP_DEBUG_ANY, 313 "backend_startup: bi_open %d (%s) failed!\n", 314 i, bi->bi_type ); 315 return rc; 316 } 317 } 318 319 (void)backend_init_controls( bi ); 320 } 321 322 /* open each backend database */ 323 i = -1; 324 LDAP_STAILQ_FOREACH(be, &backendDB, be_next) { 325 i++; 326 if ( SLAP_DBDISABLED( be )) 327 continue; 328 if ( be->be_suffix == NULL ) { 329 Debug( LDAP_DEBUG_ANY, 330 "backend_startup: warning, database %d (%s) " 331 "has no suffix\n", 332 i, be->bd_info->bi_type ); 333 } 334 335 rc = backend_startup_one( be, &cr ); 336 337 if ( rc ) return rc; 338 } 339 340 return rc; 341 } 342 343 int backend_num( Backend *be ) 344 { 345 int i = 0; 346 BackendDB *b2; 347 348 if( be == NULL ) return -1; 349 350 LDAP_STAILQ_FOREACH( b2, &backendDB, be_next ) { 351 if( be == b2 ) return i; 352 i++; 353 } 354 return -1; 355 } 356 357 int backend_shutdown( Backend *be ) 358 { 359 int rc = 0; 360 BackendInfo *bi; 361 362 if( be != NULL ) { 363 /* shutdown a specific backend database */ 364 365 if ( be->bd_info->bi_nDB == 0 ) { 366 /* no database of this type, we never opened it */ 367 return 0; 368 } 369 370 if ( be->bd_info->bi_db_close ) { 371 rc = be->bd_info->bi_db_close( be, NULL ); 372 be->be_flags &= ~SLAP_DBFLAG_OPEN; 373 if ( rc ) return rc; 374 } 375 376 if( be->bd_info->bi_close ) { 377 rc = be->bd_info->bi_close( be->bd_info ); 378 if ( rc ) return rc; 379 } 380 381 return 0; 382 } 383 384 /* close each backend database */ 385 LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) { 386 if ( SLAP_DBDISABLED( be )) 387 continue; 388 if ( be->bd_info->bi_db_close ) { 389 be->bd_info->bi_db_close( be, NULL ); 390 be->be_flags &= ~SLAP_DBFLAG_OPEN; 391 } 392 393 if(rc != 0) { 394 Debug( LDAP_DEBUG_ANY, 395 "backend_close: bi_db_close %s failed!\n", 396 be->be_type ); 397 } 398 } 399 400 /* close each backend type */ 401 LDAP_STAILQ_FOREACH( bi, &backendInfo, bi_next ) { 402 if( bi->bi_nDB == 0 ) { 403 /* no database of this type */ 404 continue; 405 } 406 407 if( bi->bi_close ) { 408 bi->bi_close( bi ); 409 } 410 } 411 412 /* close frontend, if required */ 413 if ( frontendDB->bd_info->bi_db_close ) { 414 rc = frontendDB->bd_info->bi_db_close ( frontendDB, NULL ); 415 frontendDB->be_flags &= ~SLAP_DBFLAG_OPEN; 416 if ( rc != 0 ) { 417 Debug( LDAP_DEBUG_ANY, 418 "backend_startup: bi_db_close(frontend) failed! (%d)\n", 419 rc ); 420 } 421 } 422 423 return 0; 424 } 425 426 /* 427 * This function is supposed to be the exact counterpart 428 * of backend_startup_one(), although this one calls bi_db_destroy() 429 * while backend_startup_one() calls bi_db_open(). 430 * 431 * Make sure backend_stopdown_one() destroys resources allocated 432 * by backend_startup_one(); only call backend_destroy_one() when 433 * all stuff in a BackendDB needs to be destroyed 434 */ 435 void 436 backend_stopdown_one( BackendDB *bd ) 437 { 438 struct slap_csn_entry *csne; 439 csne = LDAP_TAILQ_FIRST( &bd->be_pcsn_st.be_pcsn_list ); 440 while ( csne ) { 441 struct slap_csn_entry *tmp_csne = csne; 442 443 LDAP_TAILQ_REMOVE( &bd->be_pcsn_st.be_pcsn_list, csne, ce_csn_link ); 444 ch_free( csne->ce_csn.bv_val ); 445 csne = LDAP_TAILQ_NEXT( csne, ce_csn_link ); 446 ch_free( tmp_csne ); 447 } 448 449 if ( bd->bd_info->bi_db_destroy ) { 450 bd->bd_info->bi_db_destroy( bd, NULL ); 451 } 452 } 453 454 void backend_destroy_one( BackendDB *bd, int dynamic ) 455 { 456 if ( dynamic ) { 457 LDAP_STAILQ_REMOVE(&backendDB, bd, BackendDB, be_next ); 458 } 459 460 if ( bd->be_syncinfo ) { 461 syncinfo_free( bd->be_syncinfo, 1 ); 462 } 463 464 backend_stopdown_one( bd ); 465 466 ber_bvarray_free( bd->be_suffix ); 467 ber_bvarray_free( bd->be_nsuffix ); 468 if ( !BER_BVISNULL( &bd->be_rootdn ) ) { 469 free( bd->be_rootdn.bv_val ); 470 } 471 if ( !BER_BVISNULL( &bd->be_rootndn ) ) { 472 free( bd->be_rootndn.bv_val ); 473 } 474 if ( !BER_BVISNULL( &bd->be_rootpw ) ) { 475 free( bd->be_rootpw.bv_val ); 476 } 477 acl_destroy( bd->be_acl ); 478 limits_destroy( bd->be_limits ); 479 if ( bd->be_extra_anlist ) { 480 anlist_free( bd->be_extra_anlist, 1, NULL ); 481 } 482 if ( !BER_BVISNULL( &bd->be_update_ndn ) ) { 483 ch_free( bd->be_update_ndn.bv_val ); 484 } 485 if ( bd->be_update_refs ) { 486 ber_bvarray_free( bd->be_update_refs ); 487 } 488 489 ldap_pvt_thread_mutex_destroy( &bd->be_pcsn_st.be_pcsn_mutex ); 490 491 if ( dynamic ) { 492 free( bd ); 493 } 494 } 495 496 int backend_destroy(void) 497 { 498 BackendDB *bd; 499 BackendInfo *bi; 500 501 /* destroy each backend database */ 502 while (( bd = LDAP_STAILQ_FIRST(&backendDB))) { 503 backend_destroy_one( bd, 1 ); 504 } 505 506 /* destroy each backend type */ 507 LDAP_STAILQ_FOREACH( bi, &backendInfo, bi_next ) { 508 if( bi->bi_destroy ) { 509 bi->bi_destroy( bi ); 510 } 511 } 512 513 nBackendInfo = 0; 514 LDAP_STAILQ_INIT(&backendInfo); 515 516 /* destroy frontend database */ 517 bd = frontendDB; 518 if ( bd ) { 519 if ( bd->bd_info->bi_db_destroy ) { 520 bd->bd_info->bi_db_destroy( bd, NULL ); 521 } 522 ber_bvarray_free( bd->be_suffix ); 523 ber_bvarray_free( bd->be_nsuffix ); 524 if ( !BER_BVISNULL( &bd->be_rootdn ) ) { 525 free( bd->be_rootdn.bv_val ); 526 } 527 if ( !BER_BVISNULL( &bd->be_rootndn ) ) { 528 free( bd->be_rootndn.bv_val ); 529 } 530 if ( !BER_BVISNULL( &bd->be_rootpw ) ) { 531 free( bd->be_rootpw.bv_val ); 532 } 533 acl_destroy( bd->be_acl ); 534 frontendDB = NULL; 535 } 536 537 return 0; 538 } 539 540 BackendInfo* backend_info(const char *type) 541 { 542 BackendInfo *bi; 543 544 /* search for the backend type */ 545 LDAP_STAILQ_FOREACH(bi,&backendInfo,bi_next) { 546 if( strcasecmp(bi->bi_type, type) == 0 ) { 547 return bi; 548 } 549 } 550 551 return NULL; 552 } 553 554 void 555 backend_db_insert( 556 BackendDB *be, 557 int idx 558 ) 559 { 560 /* If idx < 0, just add to end of list */ 561 if ( idx < 0 ) { 562 LDAP_STAILQ_INSERT_TAIL(&backendDB, be, be_next); 563 } else if ( idx == 0 ) { 564 LDAP_STAILQ_INSERT_HEAD(&backendDB, be, be_next); 565 } else { 566 int i; 567 BackendDB *b2; 568 569 b2 = LDAP_STAILQ_FIRST(&backendDB); 570 idx--; 571 for (i=0; i<idx; i++) { 572 b2 = LDAP_STAILQ_NEXT(b2, be_next); 573 } 574 LDAP_STAILQ_INSERT_AFTER(&backendDB, b2, be, be_next); 575 } 576 } 577 578 void 579 backend_db_move( 580 BackendDB *be, 581 int idx 582 ) 583 { 584 LDAP_STAILQ_REMOVE(&backendDB, be, BackendDB, be_next); 585 backend_db_insert(be, idx); 586 } 587 588 BackendDB * 589 backend_db_init( 590 const char *type, 591 BackendDB *b0, 592 int idx, 593 ConfigReply *cr) 594 { 595 BackendInfo *bi = backend_info(type); 596 BackendDB *be = b0; 597 int rc = 0; 598 599 if( bi == NULL ) { 600 fprintf( stderr, "Unrecognized database type (%s)\n", type ); 601 return NULL; 602 } 603 604 /* If be is provided, treat it as private. Otherwise allocate 605 * one and add it to the global list. 606 */ 607 if ( !be ) { 608 be = ch_calloc( 1, sizeof(Backend) ); 609 /* Just append */ 610 if ( idx >= nbackends ) 611 idx = -1; 612 nbackends++; 613 backend_db_insert( be, idx ); 614 } 615 616 be->bd_info = bi; 617 be->bd_self = be; 618 619 be->be_def_limit = frontendDB->be_def_limit; 620 be->be_dfltaccess = frontendDB->be_dfltaccess; 621 622 be->be_restrictops = frontendDB->be_restrictops; 623 be->be_requires = frontendDB->be_requires; 624 be->be_ssf_set = frontendDB->be_ssf_set; 625 626 ldap_pvt_thread_mutex_init( &be->be_pcsn_st.be_pcsn_mutex ); 627 be->be_pcsn_p = &be->be_pcsn_st; 628 629 /* assign a default depth limit for alias deref */ 630 be->be_max_deref_depth = SLAPD_DEFAULT_MAXDEREFDEPTH; 631 632 if ( bi->bi_db_init ) { 633 rc = bi->bi_db_init( be, cr ); 634 } 635 636 if ( rc != 0 ) { 637 fprintf( stderr, "database init failed (%s)\n", type ); 638 /* If we created and linked this be, remove it and free it */ 639 if ( !b0 ) { 640 LDAP_STAILQ_REMOVE(&backendDB, be, BackendDB, be_next); 641 ldap_pvt_thread_mutex_destroy( &be->be_pcsn_st.be_pcsn_mutex ); 642 ch_free( be ); 643 be = NULL; 644 nbackends--; 645 } 646 } else { 647 if ( !bi->bi_nDB ) { 648 backend_init_controls( bi ); 649 } 650 bi->bi_nDB++; 651 } 652 return( be ); 653 } 654 655 void 656 be_db_close( void ) 657 { 658 BackendDB *be; 659 660 LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) { 661 if ( be->bd_info->bi_db_close ) { 662 be->bd_info->bi_db_close( be, NULL ); 663 be->be_flags &= ~SLAP_DBFLAG_OPEN; 664 } 665 } 666 667 if ( frontendDB->bd_info->bi_db_close ) { 668 frontendDB->bd_info->bi_db_close( frontendDB, NULL ); 669 } 670 671 } 672 673 Backend * 674 select_backend( 675 struct berval * dn, 676 int noSubs ) 677 { 678 int j; 679 ber_len_t len, dnlen = dn->bv_len; 680 Backend *be; 681 682 LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) { 683 if ( be->be_nsuffix == NULL || SLAP_DBHIDDEN( be ) || SLAP_DBDISABLED( be )) { 684 continue; 685 } 686 687 for ( j = 0; !BER_BVISNULL( &be->be_nsuffix[j] ); j++ ) 688 { 689 if ( ( SLAP_GLUE_SUBORDINATE( be ) ) && noSubs ) 690 { 691 continue; 692 } 693 694 len = be->be_nsuffix[j].bv_len; 695 696 if ( len > dnlen ) { 697 /* suffix is longer than DN */ 698 continue; 699 } 700 701 /* 702 * input DN is normalized, so the separator check 703 * need not look at escaping 704 */ 705 if ( len && len < dnlen && 706 !DN_SEPARATOR( dn->bv_val[(dnlen-len)-1] )) 707 { 708 continue; 709 } 710 711 if ( strcmp( be->be_nsuffix[j].bv_val, 712 &dn->bv_val[dnlen-len] ) == 0 ) 713 { 714 return be; 715 } 716 } 717 } 718 719 return be; 720 } 721 722 int 723 be_issuffix( 724 Backend *be, 725 struct berval *bvsuffix ) 726 { 727 int i; 728 729 if ( be->be_nsuffix == NULL ) { 730 return 0; 731 } 732 733 for ( i = 0; !BER_BVISNULL( &be->be_nsuffix[i] ); i++ ) { 734 if ( bvmatch( &be->be_nsuffix[i], bvsuffix ) ) { 735 return 1; 736 } 737 } 738 739 return 0; 740 } 741 742 int 743 be_issubordinate( 744 Backend *be, 745 struct berval *bvsubordinate ) 746 { 747 int i; 748 749 if ( be->be_nsuffix == NULL ) { 750 return 0; 751 } 752 753 for ( i = 0; !BER_BVISNULL( &be->be_nsuffix[i] ); i++ ) { 754 if ( dnIsSuffix( bvsubordinate, &be->be_nsuffix[i] ) ) { 755 return 1; 756 } 757 } 758 759 return 0; 760 } 761 762 int 763 be_isroot_dn( Backend *be, struct berval *ndn ) 764 { 765 if ( BER_BVISEMPTY( ndn ) || BER_BVISEMPTY( &be->be_rootndn ) ) { 766 return 0; 767 } 768 769 return dn_match( &be->be_rootndn, ndn ); 770 } 771 772 int 773 be_slurp_update( Operation *op ) 774 { 775 return ( SLAP_SLURP_SHADOW( op->o_bd ) && 776 be_isupdate_dn( op->o_bd, &op->o_ndn ) ); 777 } 778 779 int 780 be_shadow_update( Operation *op ) 781 { 782 /* This assumes that all internal ops (connid <= -1000) on a syncrepl 783 * database are syncrepl operations. 784 */ 785 return ( ( SLAP_SYNC_SHADOW( op->o_bd ) && SLAPD_SYNC_IS_SYNCCONN( op->o_connid ) ) || 786 ( SLAP_SHADOW( op->o_bd ) && be_isupdate_dn( op->o_bd, &op->o_ndn ) ) ); 787 } 788 789 int 790 be_isupdate_dn( Backend *be, struct berval *ndn ) 791 { 792 if ( BER_BVISEMPTY( ndn ) || BER_BVISEMPTY( &be->be_update_ndn ) ) { 793 return 0; 794 } 795 796 return dn_match( &be->be_update_ndn, ndn ); 797 } 798 799 struct berval * 800 be_root_dn( Backend *be ) 801 { 802 return &be->be_rootdn; 803 } 804 805 int 806 be_isroot( Operation *op ) 807 { 808 return be_isroot_dn( op->o_bd, &op->o_ndn ); 809 } 810 811 int 812 be_isroot_pw( Operation *op ) 813 { 814 return be_rootdn_bind( op, NULL ) == LDAP_SUCCESS; 815 } 816 817 /* 818 * checks if binding as rootdn 819 * 820 * return value: 821 * SLAP_CB_CONTINUE if not the rootdn, or if rootpw is null 822 * LDAP_SUCCESS if rootdn & rootpw 823 * LDAP_INVALID_CREDENTIALS if rootdn & !rootpw 824 * 825 * if rs != NULL 826 * if LDAP_SUCCESS, op->orb_edn is set 827 * if LDAP_INVALID_CREDENTIALS, response is sent to client 828 */ 829 int 830 be_rootdn_bind( Operation *op, SlapReply *rs ) 831 { 832 int rc; 833 #ifdef SLAPD_SPASSWD 834 void *old_authctx = NULL; 835 #endif 836 837 assert( op->o_tag == LDAP_REQ_BIND ); 838 assert( op->orb_method == LDAP_AUTH_SIMPLE ); 839 840 if ( !be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) { 841 return SLAP_CB_CONTINUE; 842 } 843 844 if ( BER_BVISNULL( &op->o_bd->be_rootpw ) ) { 845 /* give the database a chance */ 846 return SLAP_CB_CONTINUE; 847 } 848 849 if ( BER_BVISEMPTY( &op->o_bd->be_rootpw ) ) { 850 /* rootdn bind explicitly disallowed */ 851 rc = LDAP_INVALID_CREDENTIALS; 852 if ( rs ) { 853 goto send_result; 854 } 855 856 return rc; 857 } 858 859 #ifdef SLAPD_SPASSWD 860 ldap_pvt_thread_pool_setkey( op->o_threadctx, (void *)slap_sasl_bind, 861 op->o_conn->c_sasl_authctx, 0, &old_authctx, NULL ); 862 #endif 863 864 rc = lutil_passwd( &op->o_bd->be_rootpw, &op->orb_cred, NULL, NULL ); 865 866 #ifdef SLAPD_SPASSWD 867 ldap_pvt_thread_pool_setkey( op->o_threadctx, (void *)slap_sasl_bind, 868 old_authctx, 0, NULL, NULL ); 869 #endif 870 871 rc = ( rc == 0 ? LDAP_SUCCESS : LDAP_INVALID_CREDENTIALS ); 872 if ( rs ) { 873 send_result:; 874 rs->sr_err = rc; 875 876 Debug( LDAP_DEBUG_TRACE, "%s: rootdn=\"%s\" bind%s\n", 877 op->o_log_prefix, op->o_bd->be_rootdn.bv_val, 878 rc == LDAP_SUCCESS ? " succeeded" : " failed" ); 879 880 if ( rc == LDAP_SUCCESS ) { 881 /* Set to the pretty rootdn */ 882 ber_dupbv( &op->orb_edn, &op->o_bd->be_rootdn ); 883 884 } else { 885 send_ldap_result( op, rs ); 886 } 887 } 888 889 return rc; 890 } 891 892 /* Inlined in proto-slap.h, sans assertions, when !(USE_RS_ASSERT) */ 893 int 894 (slap_bi_op)( 895 BackendInfo *bi, 896 slap_operation_t which, 897 Operation *op, 898 SlapReply *rs ) 899 { 900 int rc; 901 #ifndef slap_bi_op 902 void (*rsCheck)( const SlapReply *rs ) = 903 which < op_aux_operational ? rs_assert_ready : rs_assert_ok; 904 #else 905 # define rsCheck(rs) ((void) 0) 906 #endif 907 BI_op_func *fn; 908 909 assert( bi != NULL ); 910 assert( (unsigned) which < (unsigned) op_last ); 911 912 fn = (&bi->bi_op_bind)[ which ]; 913 914 assert( op != NULL ); 915 assert( rs != NULL ); 916 assert( fn != 0 ); 917 rsCheck( rs ); 918 919 rc = fn( op, rs ); 920 921 #ifndef slap_bi_op 922 if ( rc != SLAP_CB_CONTINUE && rc != SLAP_CB_BYPASS ) { 923 int err = rs->sr_err; 924 925 if ( 0 ) /* TODO */ 926 if ( err == LDAP_COMPARE_TRUE || err == LDAP_COMPARE_FALSE ) { 927 assert( which == op_compare ); 928 assert( rc == LDAP_SUCCESS ); 929 } 930 931 rsCheck = which < op_extended ? rs_assert_done : rs_assert_ok; 932 if ( which == op_aux_chk_referrals ) { 933 if ( rc == LDAP_SUCCESS ) rsCheck = rs_assert_ready; 934 else if ( rc == LDAP_REFERRAL ) rsCheck = rs_assert_done; 935 } else if ( which == op_bind ) { 936 if ( rc == LDAP_SUCCESS ) rsCheck = rs_assert_ok; 937 } 938 939 /* TODO: Just what is the relation between rc and rs->sr_err? */ 940 if ( rc != err && 941 (rc != LDAP_SUCCESS || 942 (err != LDAP_COMPARE_TRUE && err != LDAP_COMPARE_FALSE)) ) 943 { 944 rs->sr_err = rc; 945 rsCheck( rs ); 946 rs->sr_err = err; 947 } 948 } 949 rsCheck( rs ); 950 #endif 951 952 return rc; 953 } 954 955 int 956 be_entry_release_rw( 957 Operation *op, 958 Entry *e, 959 int rw ) 960 { 961 if ( op->o_bd->be_release ) { 962 /* free and release entry from backend */ 963 return op->o_bd->be_release( op, e, rw ); 964 } else { 965 /* free entry */ 966 entry_free( e ); 967 return 0; 968 } 969 } 970 971 int 972 backend_unbind( Operation *op, SlapReply *rs ) 973 { 974 BackendDB *be; 975 976 LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) { 977 if ( be->be_unbind ) { 978 op->o_bd = be; 979 be->be_unbind( op, rs ); 980 } 981 } 982 983 return 0; 984 } 985 986 int 987 backend_connection_init( 988 Connection *conn ) 989 { 990 BackendDB *be; 991 992 LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) { 993 if ( be->be_connection_init ) { 994 be->be_connection_init( be, conn ); 995 } 996 } 997 998 return 0; 999 } 1000 1001 int 1002 backend_connection_destroy( 1003 Connection *conn ) 1004 { 1005 BackendDB *be; 1006 1007 LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) { 1008 if ( be->be_connection_destroy ) { 1009 be->be_connection_destroy( be, conn); 1010 } 1011 } 1012 1013 return 0; 1014 } 1015 1016 int 1017 backend_check_controls( 1018 Operation *op, 1019 SlapReply *rs ) 1020 { 1021 LDAPControl **ctrls = op->o_ctrls; 1022 rs->sr_err = LDAP_SUCCESS; 1023 1024 if( ctrls ) { 1025 for( ; *ctrls != NULL ; ctrls++ ) { 1026 int cid; 1027 1028 switch ( slap_global_control( op, (*ctrls)->ldctl_oid, &cid ) ) { 1029 case LDAP_CONTROL_NOT_FOUND: 1030 /* unrecognized control */ 1031 if ( (*ctrls)->ldctl_iscritical ) { 1032 /* should not be reachable */ 1033 Debug( LDAP_DEBUG_ANY, "backend_check_controls: " 1034 "unrecognized critical control: %s\n", 1035 (*ctrls)->ldctl_oid ); 1036 assert( 0 ); 1037 } else { 1038 Debug( LDAP_DEBUG_TRACE, "backend_check_controls: " 1039 "unrecognized non-critical control: %s\n", 1040 (*ctrls)->ldctl_oid ); 1041 } 1042 break; 1043 1044 case LDAP_COMPARE_FALSE: 1045 if ( !op->o_bd->be_ctrls[cid] && (*ctrls)->ldctl_iscritical ) { 1046 #ifdef SLAP_CONTROL_X_WHATFAILED 1047 if ( get_whatFailed( op ) ) { 1048 char *oids[ 2 ]; 1049 oids[ 0 ] = (*ctrls)->ldctl_oid; 1050 oids[ 1 ] = NULL; 1051 slap_ctrl_whatFailed_add( op, rs, oids ); 1052 } 1053 #endif 1054 /* RFC 4511 allows unavailableCriticalExtension to be 1055 * returned when the server is unwilling to perform 1056 * an operation extended by a recognized critical 1057 * control. 1058 */ 1059 rs->sr_text = "critical control unavailable in context"; 1060 rs->sr_err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION; 1061 goto done; 1062 } 1063 break; 1064 1065 case LDAP_COMPARE_TRUE: 1066 break; 1067 1068 default: 1069 /* unreachable */ 1070 Debug( LDAP_DEBUG_ANY, 1071 "backend_check_controls: unable to check control: %s\n", 1072 (*ctrls)->ldctl_oid ); 1073 assert( 0 ); 1074 1075 rs->sr_text = "unable to check control"; 1076 rs->sr_err = LDAP_OTHER; 1077 goto done; 1078 } 1079 } 1080 } 1081 1082 #if 0 /* temporarily removed */ 1083 /* check should be generalized */ 1084 if( get_relax(op) && !be_isroot(op)) { 1085 rs->sr_text = "requires manager authorization"; 1086 rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 1087 } 1088 #endif 1089 1090 done:; 1091 return rs->sr_err; 1092 } 1093 1094 int 1095 backend_check_restrictions( 1096 Operation *op, 1097 SlapReply *rs, 1098 struct berval *opdata ) 1099 { 1100 slap_mask_t restrictops; 1101 slap_mask_t requires; 1102 slap_mask_t opflag; 1103 slap_mask_t exopflag = 0; 1104 slap_ssf_set_t ssfs, *ssf; 1105 int updateop = 0; 1106 int starttls = 0; 1107 int session = 0; 1108 1109 restrictops = frontendDB->be_restrictops; 1110 requires = frontendDB->be_requires; 1111 ssfs = frontendDB->be_ssf_set; 1112 ssf = &ssfs; 1113 1114 if ( op->o_bd ) { 1115 slap_ssf_t *fssf, *bssf; 1116 int rc = SLAP_CB_CONTINUE, i; 1117 1118 if ( op->o_bd->be_chk_controls ) { 1119 rc = ( *op->o_bd->be_chk_controls )( op, rs ); 1120 } 1121 1122 if ( rc == SLAP_CB_CONTINUE ) { 1123 rc = backend_check_controls( op, rs ); 1124 } 1125 1126 if ( rc != LDAP_SUCCESS ) { 1127 return rs->sr_err; 1128 } 1129 1130 restrictops |= op->o_bd->be_restrictops; 1131 requires |= op->o_bd->be_requires; 1132 bssf = &op->o_bd->be_ssf_set.sss_ssf; 1133 fssf = &ssfs.sss_ssf; 1134 for ( i=0; i < (int)(sizeof(ssfs)/sizeof(slap_ssf_t)); i++ ) { 1135 if ( bssf[i] ) fssf[i] = bssf[i]; 1136 } 1137 } 1138 1139 switch( op->o_tag ) { 1140 case LDAP_REQ_ADD: 1141 opflag = SLAP_RESTRICT_OP_ADD; 1142 updateop++; 1143 break; 1144 case LDAP_REQ_BIND: 1145 opflag = SLAP_RESTRICT_OP_BIND; 1146 session++; 1147 break; 1148 case LDAP_REQ_COMPARE: 1149 opflag = SLAP_RESTRICT_OP_COMPARE; 1150 break; 1151 case LDAP_REQ_DELETE: 1152 updateop++; 1153 opflag = SLAP_RESTRICT_OP_DELETE; 1154 break; 1155 case LDAP_REQ_EXTENDED: 1156 opflag = SLAP_RESTRICT_OP_EXTENDED; 1157 1158 if( !opdata ) { 1159 /* treat unspecified as a modify */ 1160 opflag = SLAP_RESTRICT_OP_MODIFY; 1161 updateop++; 1162 break; 1163 } 1164 1165 if( bvmatch( opdata, &slap_EXOP_START_TLS ) ) { 1166 session++; 1167 starttls++; 1168 exopflag = SLAP_RESTRICT_EXOP_START_TLS; 1169 break; 1170 } 1171 1172 if( bvmatch( opdata, &slap_EXOP_WHOAMI ) ) { 1173 exopflag = SLAP_RESTRICT_EXOP_WHOAMI; 1174 break; 1175 } 1176 1177 if ( bvmatch( opdata, &slap_EXOP_CANCEL ) ) { 1178 exopflag = SLAP_RESTRICT_EXOP_CANCEL; 1179 break; 1180 } 1181 1182 if ( bvmatch( opdata, &slap_EXOP_MODIFY_PASSWD ) ) { 1183 exopflag = SLAP_RESTRICT_EXOP_MODIFY_PASSWD; 1184 updateop++; 1185 break; 1186 } 1187 1188 /* treat everything else as a modify */ 1189 opflag = SLAP_RESTRICT_OP_MODIFY; 1190 updateop++; 1191 break; 1192 1193 case LDAP_REQ_MODIFY: 1194 updateop++; 1195 opflag = SLAP_RESTRICT_OP_MODIFY; 1196 break; 1197 case LDAP_REQ_RENAME: 1198 updateop++; 1199 opflag = SLAP_RESTRICT_OP_RENAME; 1200 break; 1201 case LDAP_REQ_SEARCH: 1202 opflag = SLAP_RESTRICT_OP_SEARCH; 1203 break; 1204 case LDAP_REQ_UNBIND: 1205 session++; 1206 opflag = 0; 1207 break; 1208 default: 1209 rs->sr_text = "restrict operations internal error"; 1210 rs->sr_err = LDAP_OTHER; 1211 return rs->sr_err; 1212 } 1213 1214 if ( !starttls ) { 1215 /* these checks don't apply to StartTLS */ 1216 1217 rs->sr_err = LDAP_CONFIDENTIALITY_REQUIRED; 1218 if( op->o_transport_ssf < ssf->sss_transport ) { 1219 rs->sr_text = op->o_transport_ssf 1220 ? "stronger transport confidentiality required" 1221 : "transport confidentiality required"; 1222 return rs->sr_err; 1223 } 1224 1225 if( op->o_tls_ssf < ssf->sss_tls ) { 1226 rs->sr_text = op->o_tls_ssf 1227 ? "stronger TLS confidentiality required" 1228 : "TLS confidentiality required"; 1229 return rs->sr_err; 1230 } 1231 1232 1233 if( op->o_tag == LDAP_REQ_BIND && opdata == NULL ) { 1234 /* simple bind specific check */ 1235 if( op->o_ssf < ssf->sss_simple_bind ) { 1236 rs->sr_text = op->o_ssf 1237 ? "stronger confidentiality required" 1238 : "confidentiality required"; 1239 return rs->sr_err; 1240 } 1241 } 1242 1243 if( op->o_tag != LDAP_REQ_BIND || opdata == NULL ) { 1244 /* these checks don't apply to SASL bind */ 1245 1246 if( op->o_sasl_ssf < ssf->sss_sasl ) { 1247 rs->sr_text = op->o_sasl_ssf 1248 ? "stronger SASL confidentiality required" 1249 : "SASL confidentiality required"; 1250 return rs->sr_err; 1251 } 1252 1253 if( op->o_ssf < ssf->sss_ssf ) { 1254 rs->sr_text = op->o_ssf 1255 ? "stronger confidentiality required" 1256 : "confidentiality required"; 1257 return rs->sr_err; 1258 } 1259 } 1260 1261 if( updateop ) { 1262 if( op->o_transport_ssf < ssf->sss_update_transport ) { 1263 rs->sr_text = op->o_transport_ssf 1264 ? "stronger transport confidentiality required for update" 1265 : "transport confidentiality required for update"; 1266 return rs->sr_err; 1267 } 1268 1269 if( op->o_tls_ssf < ssf->sss_update_tls ) { 1270 rs->sr_text = op->o_tls_ssf 1271 ? "stronger TLS confidentiality required for update" 1272 : "TLS confidentiality required for update"; 1273 return rs->sr_err; 1274 } 1275 1276 if( op->o_sasl_ssf < ssf->sss_update_sasl ) { 1277 rs->sr_text = op->o_sasl_ssf 1278 ? "stronger SASL confidentiality required for update" 1279 : "SASL confidentiality required for update"; 1280 return rs->sr_err; 1281 } 1282 1283 if( op->o_ssf < ssf->sss_update_ssf ) { 1284 rs->sr_text = op->o_ssf 1285 ? "stronger confidentiality required for update" 1286 : "confidentiality required for update"; 1287 return rs->sr_err; 1288 } 1289 1290 if( !( global_allows & SLAP_ALLOW_UPDATE_ANON ) && 1291 BER_BVISEMPTY( &op->o_ndn ) ) 1292 { 1293 rs->sr_text = "modifications require authentication"; 1294 rs->sr_err = LDAP_STRONG_AUTH_REQUIRED; 1295 return rs->sr_err; 1296 } 1297 1298 #ifdef SLAP_X_LISTENER_MOD 1299 if ( op->o_conn->c_listener && 1300 ! ( op->o_conn->c_listener->sl_perms & ( !BER_BVISEMPTY( &op->o_ndn ) 1301 ? (S_IWUSR|S_IWOTH) : S_IWOTH ) ) ) 1302 { 1303 /* no "w" mode means readonly */ 1304 rs->sr_text = "modifications not allowed on this listener"; 1305 rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 1306 return rs->sr_err; 1307 } 1308 #endif /* SLAP_X_LISTENER_MOD */ 1309 } 1310 } 1311 1312 if ( !session ) { 1313 /* these checks don't apply to Bind, StartTLS, or Unbind */ 1314 1315 if( requires & SLAP_REQUIRE_STRONG ) { 1316 /* should check mechanism */ 1317 if( ( op->o_transport_ssf < ssf->sss_transport 1318 && op->o_authtype == LDAP_AUTH_SIMPLE ) 1319 || BER_BVISEMPTY( &op->o_dn ) ) 1320 { 1321 rs->sr_text = "strong(er) authentication required"; 1322 rs->sr_err = LDAP_STRONG_AUTH_REQUIRED; 1323 return rs->sr_err; 1324 } 1325 } 1326 1327 if( requires & SLAP_REQUIRE_SASL ) { 1328 if( op->o_authtype != LDAP_AUTH_SASL || BER_BVISEMPTY( &op->o_dn ) ) { 1329 rs->sr_text = "SASL authentication required"; 1330 rs->sr_err = LDAP_STRONG_AUTH_REQUIRED; 1331 return rs->sr_err; 1332 } 1333 } 1334 1335 if( requires & SLAP_REQUIRE_AUTHC ) { 1336 if( BER_BVISEMPTY( &op->o_dn ) ) { 1337 rs->sr_text = "authentication required"; 1338 rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 1339 return rs->sr_err; 1340 } 1341 } 1342 1343 if( requires & SLAP_REQUIRE_BIND ) { 1344 int version; 1345 ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex ); 1346 version = op->o_conn->c_protocol; 1347 ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex ); 1348 1349 if( !version ) { 1350 /* no bind has occurred */ 1351 rs->sr_text = "BIND required"; 1352 rs->sr_err = LDAP_OPERATIONS_ERROR; 1353 return rs->sr_err; 1354 } 1355 } 1356 1357 if( requires & SLAP_REQUIRE_LDAP_V3 ) { 1358 if( op->o_protocol < LDAP_VERSION3 ) { 1359 /* no bind has occurred */ 1360 rs->sr_text = "operation restricted to LDAPv3 clients"; 1361 rs->sr_err = LDAP_OPERATIONS_ERROR; 1362 return rs->sr_err; 1363 } 1364 } 1365 1366 #ifdef SLAP_X_LISTENER_MOD 1367 if ( !starttls && BER_BVISEMPTY( &op->o_dn ) ) { 1368 if ( op->o_conn->c_listener && 1369 !( op->o_conn->c_listener->sl_perms & S_IXOTH )) 1370 { 1371 /* no "x" mode means bind required */ 1372 rs->sr_text = "bind required on this listener"; 1373 rs->sr_err = LDAP_STRONG_AUTH_REQUIRED; 1374 return rs->sr_err; 1375 } 1376 } 1377 1378 if ( !starttls && !updateop ) { 1379 if ( op->o_conn->c_listener && 1380 !( op->o_conn->c_listener->sl_perms & 1381 ( !BER_BVISEMPTY( &op->o_dn ) 1382 ? (S_IRUSR|S_IROTH) : S_IROTH ))) 1383 { 1384 /* no "r" mode means no read */ 1385 rs->sr_text = "read not allowed on this listener"; 1386 rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 1387 return rs->sr_err; 1388 } 1389 } 1390 #endif /* SLAP_X_LISTENER_MOD */ 1391 1392 } 1393 1394 if( ( restrictops & opflag ) 1395 || ( exopflag && ( restrictops & exopflag ) ) 1396 || (( restrictops & SLAP_RESTRICT_READONLY ) && updateop )) { 1397 if( ( restrictops & SLAP_RESTRICT_OP_MASK) == SLAP_RESTRICT_OP_READS ) { 1398 rs->sr_text = "read operations restricted"; 1399 } else if ( restrictops & exopflag ) { 1400 rs->sr_text = "extended operation restricted"; 1401 } else { 1402 rs->sr_text = "operation restricted"; 1403 } 1404 rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 1405 return rs->sr_err; 1406 } 1407 1408 rs->sr_err = LDAP_SUCCESS; 1409 return rs->sr_err; 1410 } 1411 1412 int backend_check_referrals( Operation *op, SlapReply *rs ) 1413 { 1414 rs->sr_err = LDAP_SUCCESS; 1415 1416 if( op->o_bd->be_chk_referrals ) { 1417 rs->sr_err = op->o_bd->be_chk_referrals( op, rs ); 1418 1419 if( rs->sr_err != LDAP_SUCCESS && rs->sr_err != LDAP_REFERRAL ) { 1420 send_ldap_result( op, rs ); 1421 } 1422 } 1423 1424 return rs->sr_err; 1425 } 1426 1427 int 1428 be_entry_get_rw( 1429 Operation *op, 1430 struct berval *ndn, 1431 ObjectClass *oc, 1432 AttributeDescription *at, 1433 int rw, 1434 Entry **e ) 1435 { 1436 *e = NULL; 1437 1438 if ( op->o_bd == NULL ) { 1439 return LDAP_NO_SUCH_OBJECT; 1440 } 1441 1442 if ( op->o_bd->be_fetch ) { 1443 return op->o_bd->be_fetch( op, ndn, oc, at, rw, e ); 1444 } 1445 1446 return LDAP_UNWILLING_TO_PERFORM; 1447 } 1448 1449 int 1450 fe_acl_group( 1451 Operation *op, 1452 Entry *target, 1453 struct berval *gr_ndn, 1454 struct berval *op_ndn, 1455 ObjectClass *group_oc, 1456 AttributeDescription *group_at ) 1457 { 1458 Entry *e; 1459 void *o_priv = op->o_private, *e_priv = NULL; 1460 Attribute *a; 1461 int rc; 1462 GroupAssertion *g; 1463 Backend *be = op->o_bd; 1464 OpExtra *oex; 1465 1466 LDAP_SLIST_FOREACH(oex, &op->o_extra, oe_next) { 1467 if ( oex->oe_key == (void *)backend_group ) 1468 break; 1469 } 1470 1471 if ( oex && ((OpExtraDB *)oex)->oe_db ) 1472 op->o_bd = ((OpExtraDB *)oex)->oe_db; 1473 1474 if ( !op->o_bd || !SLAP_DBHIDDEN( op->o_bd )) 1475 op->o_bd = select_backend( gr_ndn, 0 ); 1476 1477 for ( g = op->o_groups; g; g = g->ga_next ) { 1478 if ( g->ga_be != op->o_bd || g->ga_oc != group_oc || 1479 g->ga_at != group_at || g->ga_len != gr_ndn->bv_len ) 1480 { 1481 continue; 1482 } 1483 if ( strcmp( g->ga_ndn, gr_ndn->bv_val ) == 0 ) { 1484 break; 1485 } 1486 } 1487 1488 if ( g ) { 1489 rc = g->ga_res; 1490 goto done; 1491 } 1492 1493 if ( target && dn_match( &target->e_nname, gr_ndn ) ) { 1494 e = target; 1495 rc = 0; 1496 1497 } else { 1498 op->o_private = NULL; 1499 rc = be_entry_get_rw( op, gr_ndn, group_oc, group_at, 0, &e ); 1500 e_priv = op->o_private; 1501 op->o_private = o_priv; 1502 } 1503 1504 if ( e ) { 1505 a = attr_find( e->e_attrs, group_at ); 1506 if ( a ) { 1507 /* If the attribute is a subtype of labeledURI, 1508 * treat this as a dynamic group ala groupOfURLs 1509 */ 1510 if ( is_at_subtype( group_at->ad_type, 1511 slap_schema.si_ad_labeledURI->ad_type ) ) 1512 { 1513 int i; 1514 LDAPURLDesc *ludp; 1515 struct berval bv, nbase; 1516 Filter *filter; 1517 Entry *user = NULL; 1518 void *user_priv = NULL; 1519 Backend *b2 = op->o_bd; 1520 1521 if ( target && dn_match( &target->e_nname, op_ndn ) ) { 1522 user = target; 1523 } 1524 1525 rc = LDAP_COMPARE_FALSE; 1526 for ( i = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ ) { 1527 if ( ldap_url_parse( a->a_vals[i].bv_val, &ludp ) != 1528 LDAP_URL_SUCCESS ) 1529 { 1530 continue; 1531 } 1532 1533 BER_BVZERO( &nbase ); 1534 1535 /* host, attrs and extensions parts must be empty */ 1536 if ( ( ludp->lud_host && *ludp->lud_host ) 1537 || ludp->lud_attrs 1538 || ludp->lud_exts ) 1539 { 1540 goto loopit; 1541 } 1542 1543 ber_str2bv( ludp->lud_dn, 0, 0, &bv ); 1544 if ( dnNormalize( 0, NULL, NULL, &bv, &nbase, 1545 op->o_tmpmemctx ) != LDAP_SUCCESS ) 1546 { 1547 goto loopit; 1548 } 1549 1550 switch ( ludp->lud_scope ) { 1551 case LDAP_SCOPE_BASE: 1552 if ( !dn_match( &nbase, op_ndn ) ) { 1553 goto loopit; 1554 } 1555 break; 1556 case LDAP_SCOPE_ONELEVEL: 1557 dnParent( op_ndn, &bv ); 1558 if ( !dn_match( &nbase, &bv ) ) { 1559 goto loopit; 1560 } 1561 break; 1562 case LDAP_SCOPE_SUBTREE: 1563 if ( !dnIsSuffix( op_ndn, &nbase ) ) { 1564 goto loopit; 1565 } 1566 break; 1567 case LDAP_SCOPE_SUBORDINATE: 1568 if ( dn_match( &nbase, op_ndn ) || 1569 !dnIsSuffix( op_ndn, &nbase ) ) 1570 { 1571 goto loopit; 1572 } 1573 } 1574 1575 /* NOTE: this could be NULL 1576 * if no filter is provided, 1577 * or if filter parsing fails. 1578 * In the latter case, 1579 * we should give up. */ 1580 if ( ludp->lud_filter != NULL && *ludp->lud_filter != '\0') { 1581 filter = str2filter_x( op, ludp->lud_filter ); 1582 if ( filter == NULL ) { 1583 /* give up... */ 1584 rc = LDAP_OTHER; 1585 goto loopit; 1586 } 1587 1588 /* only get user if required 1589 * and not available yet */ 1590 if ( user == NULL ) { 1591 int rc2; 1592 1593 op->o_bd = select_backend( op_ndn, 0 ); 1594 op->o_private = NULL; 1595 rc2 = be_entry_get_rw( op, op_ndn, NULL, NULL, 0, &user ); 1596 user_priv = op->o_private; 1597 op->o_private = o_priv; 1598 if ( rc2 != 0 ) { 1599 /* give up... */ 1600 rc = (rc2 == LDAP_NO_SUCH_OBJECT) ? rc2 : LDAP_OTHER; 1601 goto nouser; 1602 } 1603 } 1604 1605 if ( test_filter( NULL, user, filter ) == 1606 LDAP_COMPARE_TRUE ) 1607 { 1608 rc = 0; 1609 } 1610 nouser: 1611 filter_free_x( op, filter, 1 ); 1612 } 1613 loopit: 1614 ldap_free_urldesc( ludp ); 1615 if ( !BER_BVISNULL( &nbase ) ) { 1616 op->o_tmpfree( nbase.bv_val, op->o_tmpmemctx ); 1617 } 1618 if ( rc != LDAP_COMPARE_FALSE ) { 1619 break; 1620 } 1621 } 1622 1623 if ( user != NULL && user != target ) { 1624 op->o_private = user_priv; 1625 be_entry_release_r( op, user ); 1626 op->o_private = o_priv; 1627 } 1628 op->o_bd = b2; 1629 1630 } else { 1631 rc = attr_valfind( a, 1632 SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | 1633 SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, 1634 op_ndn, NULL, op->o_tmpmemctx ); 1635 if ( rc == LDAP_NO_SUCH_ATTRIBUTE ) { 1636 rc = LDAP_COMPARE_FALSE; 1637 } 1638 } 1639 1640 } else { 1641 rc = LDAP_NO_SUCH_ATTRIBUTE; 1642 } 1643 1644 if ( e != target ) { 1645 op->o_private = e_priv; 1646 be_entry_release_r( op, e ); 1647 op->o_private = o_priv; 1648 } 1649 1650 } else { 1651 rc = LDAP_NO_SUCH_OBJECT; 1652 } 1653 1654 if ( op->o_tag != LDAP_REQ_BIND && !op->o_do_not_cache ) { 1655 g = op->o_tmpalloc( sizeof( GroupAssertion ) + gr_ndn->bv_len, 1656 op->o_tmpmemctx ); 1657 g->ga_be = op->o_bd; 1658 g->ga_oc = group_oc; 1659 g->ga_at = group_at; 1660 g->ga_res = rc; 1661 g->ga_len = gr_ndn->bv_len; 1662 strcpy( g->ga_ndn, gr_ndn->bv_val ); 1663 g->ga_next = op->o_groups; 1664 op->o_groups = g; 1665 } 1666 1667 done: 1668 op->o_bd = be; 1669 return rc; 1670 } 1671 1672 int 1673 backend_group( 1674 Operation *op, 1675 Entry *target, 1676 struct berval *gr_ndn, 1677 struct berval *op_ndn, 1678 ObjectClass *group_oc, 1679 AttributeDescription *group_at ) 1680 { 1681 int rc; 1682 BackendDB *be_orig; 1683 OpExtraDB oex; 1684 1685 if ( op->o_abandon ) { 1686 return SLAPD_ABANDON; 1687 } 1688 1689 oex.oe_db = op->o_bd; 1690 oex.oe.oe_key = (void *)backend_group; 1691 LDAP_SLIST_INSERT_HEAD(&op->o_extra, &oex.oe, oe_next); 1692 1693 be_orig = op->o_bd; 1694 op->o_bd = frontendDB; 1695 rc = frontendDB->be_group( op, target, gr_ndn, 1696 op_ndn, group_oc, group_at ); 1697 op->o_bd = be_orig; 1698 LDAP_SLIST_REMOVE(&op->o_extra, &oex.oe, OpExtra, oe_next); 1699 1700 return rc; 1701 } 1702 1703 int 1704 fe_acl_attribute( 1705 Operation *op, 1706 Entry *target, 1707 struct berval *edn, 1708 AttributeDescription *entry_at, 1709 BerVarray *vals, 1710 slap_access_t access ) 1711 { 1712 Entry *e = NULL; 1713 void *o_priv = op->o_private, *e_priv = NULL; 1714 Attribute *a = NULL; 1715 int freeattr = 0, i, j, rc = LDAP_SUCCESS; 1716 AccessControlState acl_state = ACL_STATE_INIT; 1717 Backend *be = op->o_bd; 1718 OpExtra *oex; 1719 1720 LDAP_SLIST_FOREACH(oex, &op->o_extra, oe_next) { 1721 if ( oex->oe_key == (void *)backend_attribute ) 1722 break; 1723 } 1724 1725 if ( oex && ((OpExtraDB *)oex)->oe_db ) 1726 op->o_bd = ((OpExtraDB *)oex)->oe_db; 1727 1728 if ( !op->o_bd || !SLAP_DBHIDDEN( op->o_bd )) 1729 op->o_bd = select_backend( edn, 0 ); 1730 1731 if ( target && dn_match( &target->e_nname, edn ) ) { 1732 e = target; 1733 1734 } else { 1735 op->o_private = NULL; 1736 rc = be_entry_get_rw( op, edn, NULL, entry_at, 0, &e ); 1737 e_priv = op->o_private; 1738 op->o_private = o_priv; 1739 } 1740 1741 if ( e ) { 1742 if ( entry_at == slap_schema.si_ad_entry || entry_at == slap_schema.si_ad_children ) { 1743 assert( vals == NULL ); 1744 1745 rc = LDAP_SUCCESS; 1746 if ( op->o_conn && access > ACL_NONE && 1747 access_allowed( op, e, entry_at, NULL, 1748 access, &acl_state ) == 0 ) 1749 { 1750 rc = LDAP_INSUFFICIENT_ACCESS; 1751 } 1752 goto freeit; 1753 } 1754 1755 a = attr_find( e->e_attrs, entry_at ); 1756 if ( a == NULL ) { 1757 SlapReply rs = { REP_SEARCH }; 1758 AttributeName anlist[ 2 ]; 1759 1760 anlist[ 0 ].an_name = entry_at->ad_cname; 1761 anlist[ 0 ].an_desc = entry_at; 1762 BER_BVZERO( &anlist[ 1 ].an_name ); 1763 rs.sr_attrs = anlist; 1764 1765 /* NOTE: backend_operational() is also called 1766 * when returning results, so it's supposed 1767 * to do no harm to entries */ 1768 rs.sr_entry = e; 1769 rc = backend_operational( op, &rs ); 1770 1771 if ( rc == LDAP_SUCCESS ) { 1772 if ( rs.sr_operational_attrs ) { 1773 freeattr = 1; 1774 a = rs.sr_operational_attrs; 1775 1776 } else { 1777 rc = LDAP_NO_SUCH_ATTRIBUTE; 1778 } 1779 } 1780 } 1781 1782 if ( a ) { 1783 BerVarray v; 1784 1785 if ( op->o_conn && access > ACL_NONE && 1786 access_allowed( op, e, entry_at, NULL, 1787 access, &acl_state ) == 0 ) 1788 { 1789 rc = LDAP_INSUFFICIENT_ACCESS; 1790 goto freeit; 1791 } 1792 1793 i = a->a_numvals; 1794 v = op->o_tmpalloc( sizeof(struct berval) * ( i + 1 ), 1795 op->o_tmpmemctx ); 1796 for ( i = 0, j = 0; !BER_BVISNULL( &a->a_vals[i] ); i++ ) 1797 { 1798 if ( op->o_conn && access > ACL_NONE && 1799 access_allowed( op, e, entry_at, 1800 &a->a_nvals[i], 1801 access, 1802 &acl_state ) == 0 ) 1803 { 1804 continue; 1805 } 1806 ber_dupbv_x( &v[j], &a->a_nvals[i], 1807 op->o_tmpmemctx ); 1808 if ( !BER_BVISNULL( &v[j] ) ) { 1809 j++; 1810 } 1811 } 1812 if ( j == 0 ) { 1813 op->o_tmpfree( v, op->o_tmpmemctx ); 1814 *vals = NULL; 1815 rc = LDAP_INSUFFICIENT_ACCESS; 1816 1817 } else { 1818 BER_BVZERO( &v[j] ); 1819 *vals = v; 1820 rc = LDAP_SUCCESS; 1821 } 1822 } 1823 freeit: if ( e != target ) { 1824 op->o_private = e_priv; 1825 be_entry_release_r( op, e ); 1826 op->o_private = o_priv; 1827 } 1828 if ( freeattr ) { 1829 attr_free( a ); 1830 } 1831 } 1832 1833 op->o_bd = be; 1834 return rc; 1835 } 1836 1837 int 1838 backend_attribute( 1839 Operation *op, 1840 Entry *target, 1841 struct berval *edn, 1842 AttributeDescription *entry_at, 1843 BerVarray *vals, 1844 slap_access_t access ) 1845 { 1846 int rc; 1847 BackendDB *be_orig; 1848 OpExtraDB oex; 1849 1850 oex.oe_db = op->o_bd; 1851 oex.oe.oe_key = (void *)backend_attribute; 1852 LDAP_SLIST_INSERT_HEAD(&op->o_extra, &oex.oe, oe_next); 1853 1854 be_orig = op->o_bd; 1855 op->o_bd = frontendDB; 1856 rc = frontendDB->be_attribute( op, target, edn, 1857 entry_at, vals, access ); 1858 op->o_bd = be_orig; 1859 LDAP_SLIST_REMOVE(&op->o_extra, &oex.oe, OpExtra, oe_next); 1860 1861 return rc; 1862 } 1863 1864 int 1865 backend_access( 1866 Operation *op, 1867 Entry *target, 1868 struct berval *edn, 1869 AttributeDescription *entry_at, 1870 struct berval *nval, 1871 slap_access_t access, 1872 slap_mask_t *mask ) 1873 { 1874 Entry *e = NULL; 1875 void *o_priv, *e_priv = NULL; 1876 int rc = LDAP_INSUFFICIENT_ACCESS; 1877 Backend *be; 1878 1879 /* pedantic */ 1880 assert( op != NULL ); 1881 assert( op->o_conn != NULL ); 1882 assert( edn != NULL ); 1883 assert( access > ACL_NONE ); 1884 1885 be = op->o_bd; 1886 o_priv = op->o_private; 1887 1888 if ( !op->o_bd ) { 1889 op->o_bd = select_backend( edn, 0 ); 1890 } 1891 1892 if ( target && dn_match( &target->e_nname, edn ) ) { 1893 e = target; 1894 1895 } else { 1896 op->o_private = NULL; 1897 rc = be_entry_get_rw( op, edn, NULL, entry_at, 0, &e ); 1898 e_priv = op->o_private; 1899 op->o_private = o_priv; 1900 } 1901 1902 if ( e ) { 1903 Attribute *a = NULL; 1904 int freeattr = 0; 1905 1906 if ( entry_at == NULL ) { 1907 entry_at = slap_schema.si_ad_entry; 1908 } 1909 1910 if ( entry_at == slap_schema.si_ad_entry || entry_at == slap_schema.si_ad_children ) 1911 { 1912 if ( access_allowed_mask( op, e, entry_at, 1913 NULL, access, NULL, mask ) == 0 ) 1914 { 1915 rc = LDAP_INSUFFICIENT_ACCESS; 1916 1917 } else { 1918 rc = LDAP_SUCCESS; 1919 } 1920 1921 } else { 1922 a = attr_find( e->e_attrs, entry_at ); 1923 if ( a == NULL ) { 1924 SlapReply rs = { REP_SEARCH }; 1925 AttributeName anlist[ 2 ]; 1926 1927 anlist[ 0 ].an_name = entry_at->ad_cname; 1928 anlist[ 0 ].an_desc = entry_at; 1929 BER_BVZERO( &anlist[ 1 ].an_name ); 1930 rs.sr_attrs = anlist; 1931 1932 rs.sr_attr_flags = slap_attr_flags( rs.sr_attrs ); 1933 1934 /* NOTE: backend_operational() is also called 1935 * when returning results, so it's supposed 1936 * to do no harm to entries */ 1937 rs.sr_entry = e; 1938 rc = backend_operational( op, &rs ); 1939 1940 if ( rc == LDAP_SUCCESS ) { 1941 if ( rs.sr_operational_attrs ) { 1942 freeattr = 1; 1943 a = rs.sr_operational_attrs; 1944 1945 } else { 1946 rc = LDAP_NO_SUCH_OBJECT; 1947 } 1948 } 1949 } 1950 1951 if ( a ) { 1952 if ( access_allowed_mask( op, e, entry_at, 1953 nval, access, NULL, mask ) == 0 ) 1954 { 1955 rc = LDAP_INSUFFICIENT_ACCESS; 1956 goto freeit; 1957 } 1958 rc = LDAP_SUCCESS; 1959 } 1960 } 1961 freeit: if ( e != target ) { 1962 op->o_private = e_priv; 1963 be_entry_release_r( op, e ); 1964 op->o_private = o_priv; 1965 } 1966 if ( freeattr ) { 1967 attr_free( a ); 1968 } 1969 } 1970 1971 op->o_bd = be; 1972 return rc; 1973 } 1974 1975 int 1976 fe_aux_operational( 1977 Operation *op, 1978 SlapReply *rs ) 1979 { 1980 Attribute **ap; 1981 int rc = LDAP_SUCCESS; 1982 BackendDB *be_orig = op->o_bd; 1983 OpExtra *oex; 1984 1985 LDAP_SLIST_FOREACH(oex, &op->o_extra, oe_next) { 1986 if ( oex->oe_key == (void *)backend_operational ) 1987 break; 1988 } 1989 1990 for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next ) 1991 /* just count them */ ; 1992 1993 /* 1994 * If operational attributes (allegedly) are required, 1995 * and the backend supports specific operational attributes, 1996 * add them to the attribute list 1997 */ 1998 if ( !( rs->sr_flags & REP_NO_ENTRYDN ) 1999 && ( SLAP_OPATTRS( rs->sr_attr_flags ) || ( rs->sr_attrs && 2000 ad_inlist( slap_schema.si_ad_entryDN, rs->sr_attrs ) ) ) ) 2001 { 2002 *ap = slap_operational_entryDN( rs->sr_entry ); 2003 ap = &(*ap)->a_next; 2004 } 2005 2006 if ( !( rs->sr_flags & REP_NO_SUBSCHEMA) 2007 && ( SLAP_OPATTRS( rs->sr_attr_flags ) || ( rs->sr_attrs && 2008 ad_inlist( slap_schema.si_ad_subschemaSubentry, rs->sr_attrs ) ) ) ) 2009 { 2010 *ap = slap_operational_subschemaSubentry( op->o_bd ); 2011 ap = &(*ap)->a_next; 2012 } 2013 2014 /* Let the overlays have a chance at this */ 2015 if ( oex && ((OpExtraDB *)oex)->oe_db ) 2016 op->o_bd = ((OpExtraDB *)oex)->oe_db; 2017 2018 if ( !op->o_bd || !SLAP_DBHIDDEN( op->o_bd )) 2019 op->o_bd = select_backend( &op->o_req_ndn, 0 ); 2020 2021 if ( op->o_bd != NULL && !be_match( op->o_bd, frontendDB ) && 2022 ( SLAP_OPATTRS( rs->sr_attr_flags ) || rs->sr_attrs ) && 2023 op->o_bd->be_operational != NULL ) 2024 { 2025 rc = op->o_bd->be_operational( op, rs ); 2026 } 2027 op->o_bd = be_orig; 2028 2029 return rc; 2030 } 2031 2032 int backend_operational( Operation *op, SlapReply *rs ) 2033 { 2034 int rc; 2035 BackendDB *be_orig; 2036 OpExtraDB oex; 2037 2038 oex.oe_db = op->o_bd; 2039 oex.oe.oe_key = (void *)backend_operational; 2040 LDAP_SLIST_INSERT_HEAD(&op->o_extra, &oex.oe, oe_next); 2041 2042 /* Moved this into the frontend so global overlays are called */ 2043 2044 be_orig = op->o_bd; 2045 op->o_bd = frontendDB; 2046 rc = frontendDB->be_operational( op, rs ); 2047 op->o_bd = be_orig; 2048 LDAP_SLIST_REMOVE(&op->o_extra, &oex.oe, OpExtra, oe_next); 2049 2050 return rc; 2051 } 2052 2053 /* helper that calls the bi_tool_entry_first_x() variant with default args; 2054 * use to initialize a backend's bi_tool_entry_first() when appropriate 2055 */ 2056 ID 2057 backend_tool_entry_first( BackendDB *be ) 2058 { 2059 return be->bd_info->bi_tool_entry_first_x( be, 2060 NULL, LDAP_SCOPE_DEFAULT, NULL ); 2061 } 2062