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