1 /* $NetBSD: database.c,v 1.1.1.4 2010/12/12 15:23:14 adam Exp $ */ 2 3 /* database.c - deals with database subsystem */ 4 /* OpenLDAP: pkg/ldap/servers/slapd/back-monitor/database.c,v 1.80.2.16 2010/04/13 20:23:32 kurt Exp */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2001-2010 The OpenLDAP Foundation. 8 * Portions Copyright 2001-2003 Pierangelo Masarati. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted only as authorized by the OpenLDAP 13 * Public License. 14 * 15 * A copy of this license is available in file LICENSE in the 16 * top-level directory of the distribution or, alternatively, at 17 * <http://www.OpenLDAP.org/license.html>. 18 */ 19 /* ACKNOWLEDGEMENTS: 20 * This work was initially developed by Pierangelo Masarati for inclusion 21 * in OpenLDAP Software. 22 */ 23 24 #include "portable.h" 25 26 #include <stdio.h> 27 #include <ac/string.h> 28 #include <ac/unistd.h> 29 30 #include "slap.h" 31 #include "back-monitor.h" 32 33 #if defined(LDAP_SLAPI) 34 #include "slapi.h" 35 static int monitor_back_add_plugin( monitor_info_t *mi, Backend *be, Entry *e ); 36 #endif /* defined(LDAP_SLAPI) */ 37 38 static int 39 monitor_subsys_database_modify( 40 Operation *op, 41 SlapReply *rs, 42 Entry *e ); 43 44 static struct restricted_ops_t { 45 struct berval op; 46 unsigned int tag; 47 } restricted_ops[] = { 48 { BER_BVC( "add" ), SLAP_RESTRICT_OP_ADD }, 49 { BER_BVC( "bind" ), SLAP_RESTRICT_OP_BIND }, 50 { BER_BVC( "compare" ), SLAP_RESTRICT_OP_COMPARE }, 51 { BER_BVC( "delete" ), SLAP_RESTRICT_OP_DELETE }, 52 { BER_BVC( "extended" ), SLAP_RESTRICT_OP_EXTENDED }, 53 { BER_BVC( "modify" ), SLAP_RESTRICT_OP_MODIFY }, 54 { BER_BVC( "rename" ), SLAP_RESTRICT_OP_RENAME }, 55 { BER_BVC( "search" ), SLAP_RESTRICT_OP_SEARCH }, 56 { BER_BVNULL, 0 } 57 }, restricted_exops[] = { 58 { BER_BVC( LDAP_EXOP_START_TLS ), SLAP_RESTRICT_EXOP_START_TLS }, 59 { BER_BVC( LDAP_EXOP_MODIFY_PASSWD ), SLAP_RESTRICT_EXOP_MODIFY_PASSWD }, 60 { BER_BVC( LDAP_EXOP_WHO_AM_I ), SLAP_RESTRICT_EXOP_WHOAMI }, 61 { BER_BVC( LDAP_EXOP_CANCEL ), SLAP_RESTRICT_EXOP_CANCEL }, 62 { BER_BVNULL, 0 } 63 }; 64 65 static int 66 init_readOnly( monitor_info_t *mi, Entry *e, slap_mask_t restrictops ) 67 { 68 struct berval *tf = ( ( restrictops & SLAP_RESTRICT_OP_MASK ) == SLAP_RESTRICT_OP_WRITES ) ? 69 (struct berval *)&slap_true_bv : (struct berval *)&slap_false_bv; 70 71 return attr_merge_one( e, mi->mi_ad_readOnly, tf, NULL ); 72 } 73 74 static int 75 init_restrictedOperation( monitor_info_t *mi, Entry *e, slap_mask_t restrictops ) 76 { 77 int i, rc; 78 79 for ( i = 0; restricted_ops[ i ].op.bv_val; i++ ) { 80 if ( restrictops & restricted_ops[ i ].tag ) { 81 rc = attr_merge_one( e, mi->mi_ad_restrictedOperation, 82 &restricted_ops[ i ].op, 83 &restricted_ops[ i ].op ); 84 if ( rc ) { 85 return rc; 86 } 87 } 88 } 89 90 for ( i = 0; restricted_exops[ i ].op.bv_val; i++ ) { 91 if ( restrictops & restricted_exops[ i ].tag ) { 92 rc = attr_merge_one( e, mi->mi_ad_restrictedOperation, 93 &restricted_exops[ i ].op, 94 &restricted_exops[ i ].op ); 95 if ( rc ) { 96 return rc; 97 } 98 } 99 } 100 101 return LDAP_SUCCESS; 102 } 103 104 static int 105 monitor_subsys_overlay_init_one( 106 monitor_info_t *mi, 107 BackendDB *be, 108 monitor_subsys_t *ms, 109 monitor_subsys_t *ms_overlay, 110 slap_overinst *on, 111 Entry *e_database, 112 Entry **ep_overlay ) 113 { 114 char buf[ BACKMONITOR_BUFSIZE ]; 115 int j, o; 116 Entry *e_overlay; 117 slap_overinst *on2; 118 slap_overinfo *oi = NULL; 119 BackendInfo *bi; 120 monitor_entry_t *mp_overlay; 121 struct berval bv; 122 123 assert( overlay_is_over( be ) ); 124 125 oi = (slap_overinfo *)be->bd_info->bi_private; 126 bi = oi->oi_orig; 127 128 /* find the overlay number, o */ 129 for ( o = 0, on2 = oi->oi_list; on2 && on2 != on; on2 = on2->on_next, o++ ) 130 ; 131 132 if ( on2 == NULL ) { 133 return -1; 134 } 135 136 /* find the overlay type number, j */ 137 for ( on2 = overlay_next( NULL ), j = 0; on2; on2 = overlay_next( on2 ), j++ ) { 138 if ( on2->on_bi.bi_type == on->on_bi.bi_type ) { 139 break; 140 } 141 } 142 assert( on2 != NULL ); 143 144 bv.bv_len = snprintf( buf, sizeof( buf ), "cn=Overlay %d", o ); 145 bv.bv_val = buf; 146 147 e_overlay = monitor_entry_stub( &e_database->e_name, &e_database->e_nname, &bv, 148 mi->mi_oc_monitoredObject, mi, NULL, NULL ); 149 150 if ( e_overlay == NULL ) { 151 Debug( LDAP_DEBUG_ANY, 152 "monitor_subsys_overlay_init_one: " 153 "unable to create entry " 154 "\"cn=Overlay %d,%s\"\n", 155 o, e_database->e_name.bv_val, 0 ); 156 return( -1 ); 157 } 158 ber_str2bv( on->on_bi.bi_type, 0, 0, &bv ); 159 attr_merge_normalize_one( e_overlay, mi->mi_ad_monitoredInfo, &bv, NULL ); 160 161 bv.bv_len = snprintf( buf, sizeof( buf ), "cn=Overlay %d,%s", 162 j, ms_overlay->mss_dn.bv_val ); 163 bv.bv_val = buf; 164 attr_merge_normalize_one( e_overlay, slap_schema.si_ad_seeAlso, 165 &bv, NULL ); 166 167 if ( SLAP_MONITOR( be ) ) { 168 attr_merge( e_overlay, slap_schema.si_ad_monitorContext, 169 be->be_suffix, be->be_nsuffix ); 170 171 } else { 172 attr_merge( e_overlay, slap_schema.si_ad_namingContexts, 173 be->be_suffix, NULL ); 174 } 175 176 mp_overlay = monitor_entrypriv_create(); 177 if ( mp_overlay == NULL ) { 178 return -1; 179 } 180 e_overlay->e_private = ( void * )mp_overlay; 181 mp_overlay->mp_info = ms; 182 mp_overlay->mp_flags = ms->mss_flags | MONITOR_F_SUB; 183 184 if ( monitor_cache_add( mi, e_overlay ) ) { 185 Debug( LDAP_DEBUG_ANY, 186 "monitor_subsys_overlay_init_one: " 187 "unable to add entry " 188 "\"cn=Overlay %d,%s\"\n", 189 o, e_database->e_name.bv_val, 0 ); 190 return -1; 191 } 192 193 *ep_overlay = e_overlay; 194 ep_overlay = &mp_overlay->mp_next; 195 196 return 0; 197 } 198 199 static int 200 monitor_subsys_database_init_one( 201 monitor_info_t *mi, 202 BackendDB *be, 203 monitor_subsys_t *ms, 204 monitor_subsys_t *ms_backend, 205 monitor_subsys_t *ms_overlay, 206 struct berval *rdn, 207 Entry *e_database, 208 Entry ***epp ) 209 { 210 char buf[ BACKMONITOR_BUFSIZE ]; 211 int j; 212 slap_overinfo *oi = NULL; 213 BackendInfo *bi, *bi2; 214 Entry *e; 215 monitor_entry_t *mp; 216 char *rdnval = strchr( rdn->bv_val, '=' ) + 1; 217 struct berval bv; 218 219 bi = be->bd_info; 220 221 if ( overlay_is_over( be ) ) { 222 oi = (slap_overinfo *)be->bd_info->bi_private; 223 bi = oi->oi_orig; 224 } 225 226 e = monitor_entry_stub( &ms->mss_dn, &ms->mss_ndn, rdn, 227 mi->mi_oc_monitoredObject, mi, NULL, NULL ); 228 229 if ( e == NULL ) { 230 Debug( LDAP_DEBUG_ANY, 231 "monitor_subsys_database_init_one: " 232 "unable to create entry \"%s,%s\"\n", 233 rdn->bv_val, ms->mss_dn.bv_val, 0 ); 234 return( -1 ); 235 } 236 237 ber_str2bv( bi->bi_type, 0, 0, &bv ); 238 attr_merge_normalize_one( e, mi->mi_ad_monitoredInfo, &bv, NULL ); 239 attr_merge_one( e, mi->mi_ad_monitorIsShadow, 240 SLAP_SHADOW( be ) ? (struct berval *)&slap_true_bv : 241 (struct berval *)&slap_false_bv, NULL ); 242 243 if ( SLAP_MONITOR( be ) ) { 244 attr_merge( e, slap_schema.si_ad_monitorContext, 245 be->be_suffix, be->be_nsuffix ); 246 attr_merge( e_database, slap_schema.si_ad_monitorContext, 247 be->be_suffix, be->be_nsuffix ); 248 249 } else { 250 if ( be->be_suffix == NULL ) { 251 Debug( LDAP_DEBUG_ANY, 252 "monitor_subsys_database_init_one: " 253 "missing suffix for %s\n", 254 rdnval, 0, 0 ); 255 } else { 256 attr_merge( e, slap_schema.si_ad_namingContexts, 257 be->be_suffix, NULL ); 258 attr_merge( e_database, slap_schema.si_ad_namingContexts, 259 be->be_suffix, NULL ); 260 } 261 262 if ( SLAP_GLUE_SUBORDINATE( be ) ) { 263 BackendDB *sup_be = select_backend( &be->be_nsuffix[ 0 ], 1 ); 264 if ( sup_be == NULL ) { 265 Debug( LDAP_DEBUG_ANY, 266 "monitor_subsys_database_init: " 267 "unable to get superior for %s\n", 268 be->be_suffix[ 0 ].bv_val, 0, 0 ); 269 270 } else { 271 attr_merge( e, mi->mi_ad_monitorSuperiorDN, 272 sup_be->be_suffix, sup_be->be_nsuffix ); 273 } 274 } 275 } 276 277 (void)init_readOnly( mi, e, be->be_restrictops ); 278 (void)init_restrictedOperation( mi, e, be->be_restrictops ); 279 280 if ( SLAP_SHADOW( be ) && be->be_update_refs ) { 281 attr_merge_normalize( e, mi->mi_ad_monitorUpdateRef, 282 be->be_update_refs, NULL ); 283 } 284 285 if ( oi != NULL ) { 286 slap_overinst *on = oi->oi_list, 287 *on1 = on; 288 289 for ( ; on; on = on->on_next ) { 290 slap_overinst *on2; 291 292 for ( on2 = on1; on2 != on; on2 = on2->on_next ) { 293 if ( on2->on_bi.bi_type == on->on_bi.bi_type ) { 294 break; 295 } 296 } 297 298 if ( on2 != on ) { 299 break; 300 } 301 302 ber_str2bv( on->on_bi.bi_type, 0, 0, &bv ); 303 attr_merge_normalize_one( e, mi->mi_ad_monitorOverlay, 304 &bv, NULL ); 305 306 /* find the overlay number, j */ 307 for ( on2 = overlay_next( NULL ), j = 0; on2; on2 = overlay_next( on2 ), j++ ) { 308 if ( on2->on_bi.bi_type == on->on_bi.bi_type ) { 309 break; 310 } 311 } 312 assert( on2 != NULL ); 313 314 snprintf( buf, sizeof( buf ), 315 "cn=Overlay %d,%s", 316 j, ms_overlay->mss_dn.bv_val ); 317 ber_str2bv( buf, 0, 0, &bv ); 318 attr_merge_normalize_one( e, 319 slap_schema.si_ad_seeAlso, 320 &bv, NULL ); 321 } 322 } 323 324 j = -1; 325 LDAP_STAILQ_FOREACH( bi2, &backendInfo, bi_next ) { 326 j++; 327 if ( bi2->bi_type == bi->bi_type ) { 328 snprintf( buf, sizeof( buf ), 329 "cn=Backend %d,%s", 330 j, ms_backend->mss_dn.bv_val ); 331 bv.bv_val = buf; 332 bv.bv_len = strlen( buf ); 333 attr_merge_normalize_one( e, 334 slap_schema.si_ad_seeAlso, 335 &bv, NULL ); 336 break; 337 } 338 } 339 /* we must find it! */ 340 assert( j >= 0 ); 341 342 mp = monitor_entrypriv_create(); 343 if ( mp == NULL ) { 344 return -1; 345 } 346 e->e_private = ( void * )mp; 347 mp->mp_info = ms; 348 mp->mp_flags = ms->mss_flags 349 | MONITOR_F_SUB; 350 351 if ( monitor_cache_add( mi, e ) ) { 352 Debug( LDAP_DEBUG_ANY, 353 "monitor_subsys_database_init_one: " 354 "unable to add entry \"%s,%s\"\n", 355 rdn->bv_val, ms->mss_dn.bv_val, 0 ); 356 return( -1 ); 357 } 358 359 #if defined(LDAP_SLAPI) 360 monitor_back_add_plugin( mi, be, e ); 361 #endif /* defined(LDAP_SLAPI) */ 362 363 if ( oi != NULL ) { 364 Entry **ep_overlay = &mp->mp_children; 365 slap_overinst *on = oi->oi_list; 366 367 for ( ; on; on = on->on_next ) { 368 monitor_subsys_overlay_init_one( mi, be, 369 ms, ms_overlay, on, e, ep_overlay ); 370 } 371 } 372 373 **epp = e; 374 *epp = &mp->mp_next; 375 376 return 0; 377 } 378 379 static int 380 monitor_back_register_database_and_overlay( 381 BackendDB *be, 382 struct slap_overinst *on, 383 struct berval *ndn_out ) 384 { 385 monitor_info_t *mi; 386 Entry *e_database, **ep; 387 int i, rc; 388 monitor_entry_t *mp; 389 monitor_subsys_t *ms_backend, 390 *ms_database, 391 *ms_overlay; 392 struct berval bv; 393 char buf[ BACKMONITOR_BUFSIZE ]; 394 395 assert( be_monitor != NULL ); 396 397 if ( !monitor_subsys_is_opened() ) { 398 if ( on ) { 399 return monitor_back_register_overlay_limbo( be, on, ndn_out ); 400 401 } else { 402 return monitor_back_register_database_limbo( be, ndn_out ); 403 } 404 } 405 406 mi = ( monitor_info_t * )be_monitor->be_private; 407 408 ms_backend = monitor_back_get_subsys( SLAPD_MONITOR_BACKEND_NAME ); 409 if ( ms_backend == NULL ) { 410 Debug( LDAP_DEBUG_ANY, 411 "monitor_back_register_database: " 412 "unable to get " 413 "\"" SLAPD_MONITOR_BACKEND_NAME "\" " 414 "subsystem\n", 415 0, 0, 0 ); 416 return -1; 417 } 418 419 ms_database = monitor_back_get_subsys( SLAPD_MONITOR_DATABASE_NAME ); 420 if ( ms_database == NULL ) { 421 Debug( LDAP_DEBUG_ANY, 422 "monitor_back_register_database: " 423 "unable to get " 424 "\"" SLAPD_MONITOR_DATABASE_NAME "\" " 425 "subsystem\n", 426 0, 0, 0 ); 427 return -1; 428 } 429 430 ms_overlay = monitor_back_get_subsys( SLAPD_MONITOR_OVERLAY_NAME ); 431 if ( ms_overlay == NULL ) { 432 Debug( LDAP_DEBUG_ANY, 433 "monitor_back_register_database: " 434 "unable to get " 435 "\"" SLAPD_MONITOR_OVERLAY_NAME "\" " 436 "subsystem\n", 437 0, 0, 0 ); 438 return -1; 439 } 440 441 if ( monitor_cache_get( mi, &ms_database->mss_ndn, &e_database ) ) { 442 Debug( LDAP_DEBUG_ANY, 443 "monitor_subsys_database_init: " 444 "unable to get entry \"%s\"\n", 445 ms_database->mss_ndn.bv_val, 0, 0 ); 446 return( -1 ); 447 } 448 449 mp = ( monitor_entry_t * )e_database->e_private; 450 for ( i = -1, ep = &mp->mp_children; *ep; i++ ) { 451 Attribute *a; 452 453 a = attr_find( (*ep)->e_attrs, slap_schema.si_ad_namingContexts ); 454 if ( a ) { 455 int j, k; 456 457 /* FIXME: RFC 4512 defines namingContexts without an 458 * equality matching rule, making comparisons 459 * like this one tricky. We use a_vals and 460 * be_suffix instead for now. 461 */ 462 for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ ) { 463 for ( k = 0; !BER_BVISNULL( &be->be_suffix[ k ] ); k++ ) { 464 if ( dn_match( &a->a_vals[ j ], 465 &be->be_suffix[ k ] ) ) { 466 rc = 0; 467 goto done; 468 } 469 } 470 } 471 } 472 473 mp = ( monitor_entry_t * )(*ep)->e_private; 474 475 assert( mp != NULL ); 476 ep = &mp->mp_next; 477 } 478 479 bv.bv_val = buf; 480 bv.bv_len = snprintf( buf, sizeof( buf ), "cn=Database %d", i ); 481 if ( bv.bv_len >= sizeof( buf ) ) { 482 rc = -1; 483 goto done; 484 } 485 486 rc = monitor_subsys_database_init_one( mi, be, 487 ms_database, ms_backend, ms_overlay, &bv, e_database, &ep ); 488 if ( rc != 0 ) { 489 goto done; 490 } 491 /* database_init_one advanced ep past where we want. 492 * But it stored the entry we want in mp->mp_next. 493 */ 494 ep = &mp->mp_next; 495 496 done:; 497 monitor_cache_release( mi, e_database ); 498 if ( rc == 0 && ndn_out && ep && *ep ) { 499 if ( on ) { 500 Entry *e_ov; 501 struct berval ov_type; 502 503 ber_str2bv( on->on_bi.bi_type, 0, 0, &ov_type ); 504 505 mp = ( monitor_entry_t * ) (*ep)->e_private; 506 for ( e_ov = mp->mp_children; e_ov; ) { 507 Attribute *a = attr_find( e_ov->e_attrs, mi->mi_ad_monitoredInfo ); 508 509 if ( a != NULL && bvmatch( &a->a_nvals[ 0 ], &ov_type ) ) { 510 *ndn_out = e_ov->e_nname; 511 break; 512 } 513 514 mp = ( monitor_entry_t * ) e_ov->e_private; 515 e_ov = mp->mp_next; 516 } 517 518 } else { 519 *ndn_out = (*ep)->e_nname; 520 } 521 } 522 523 return rc; 524 } 525 526 int 527 monitor_back_register_database( 528 BackendDB *be, 529 struct berval *ndn_out ) 530 { 531 return monitor_back_register_database_and_overlay( be, NULL, ndn_out ); 532 } 533 534 int 535 monitor_back_register_overlay( 536 BackendDB *be, 537 struct slap_overinst *on, 538 struct berval *ndn_out ) 539 { 540 return monitor_back_register_database_and_overlay( be, on, ndn_out ); 541 } 542 543 int 544 monitor_subsys_database_init( 545 BackendDB *be, 546 monitor_subsys_t *ms ) 547 { 548 monitor_info_t *mi; 549 Entry *e_database, **ep; 550 int i, rc; 551 monitor_entry_t *mp; 552 monitor_subsys_t *ms_backend, 553 *ms_overlay; 554 struct berval bv; 555 556 assert( be != NULL ); 557 558 ms->mss_modify = monitor_subsys_database_modify; 559 560 mi = ( monitor_info_t * )be->be_private; 561 562 ms_backend = monitor_back_get_subsys( SLAPD_MONITOR_BACKEND_NAME ); 563 if ( ms_backend == NULL ) { 564 Debug( LDAP_DEBUG_ANY, 565 "monitor_subsys_database_init: " 566 "unable to get " 567 "\"" SLAPD_MONITOR_BACKEND_NAME "\" " 568 "subsystem\n", 569 0, 0, 0 ); 570 return -1; 571 } 572 573 ms_overlay = monitor_back_get_subsys( SLAPD_MONITOR_OVERLAY_NAME ); 574 if ( ms_overlay == NULL ) { 575 Debug( LDAP_DEBUG_ANY, 576 "monitor_subsys_database_init: " 577 "unable to get " 578 "\"" SLAPD_MONITOR_OVERLAY_NAME "\" " 579 "subsystem\n", 580 0, 0, 0 ); 581 return -1; 582 } 583 584 if ( monitor_cache_get( mi, &ms->mss_ndn, &e_database ) ) { 585 Debug( LDAP_DEBUG_ANY, 586 "monitor_subsys_database_init: " 587 "unable to get entry \"%s\"\n", 588 ms->mss_ndn.bv_val, 0, 0 ); 589 return( -1 ); 590 } 591 592 (void)init_readOnly( mi, e_database, frontendDB->be_restrictops ); 593 (void)init_restrictedOperation( mi, e_database, frontendDB->be_restrictops ); 594 595 mp = ( monitor_entry_t * )e_database->e_private; 596 mp->mp_children = NULL; 597 ep = &mp->mp_children; 598 599 BER_BVSTR( &bv, "cn=Frontend" ); 600 rc = monitor_subsys_database_init_one( mi, frontendDB, 601 ms, ms_backend, ms_overlay, &bv, e_database, &ep ); 602 if ( rc != 0 ) { 603 return rc; 604 } 605 606 i = -1; 607 LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) { 608 char buf[ BACKMONITOR_BUFSIZE ]; 609 610 bv.bv_val = buf; 611 bv.bv_len = snprintf( buf, sizeof( buf ), "cn=Database %d", ++i ); 612 if ( bv.bv_len >= sizeof( buf ) ) { 613 return -1; 614 } 615 616 rc = monitor_subsys_database_init_one( mi, be, 617 ms, ms_backend, ms_overlay, &bv, e_database, &ep ); 618 if ( rc != 0 ) { 619 return rc; 620 } 621 } 622 623 monitor_cache_release( mi, e_database ); 624 625 return( 0 ); 626 } 627 628 /* 629 * v: array of values 630 * cur: must not contain the tags corresponding to the values in v 631 * delta: will contain the tags corresponding to the values in v 632 */ 633 static int 634 value_mask( BerVarray v, slap_mask_t cur, slap_mask_t *delta ) 635 { 636 for ( ; !BER_BVISNULL( v ); v++ ) { 637 struct restricted_ops_t *rops; 638 int i; 639 640 if ( OID_LEADCHAR( v->bv_val[ 0 ] ) ) { 641 rops = restricted_exops; 642 643 } else { 644 rops = restricted_ops; 645 } 646 647 for ( i = 0; !BER_BVISNULL( &rops[ i ].op ); i++ ) { 648 if ( ber_bvstrcasecmp( v, &rops[ i ].op ) != 0 ) { 649 continue; 650 } 651 652 if ( rops[ i ].tag & *delta ) { 653 return LDAP_OTHER; 654 } 655 656 if ( rops[ i ].tag & cur ) { 657 return LDAP_OTHER; 658 } 659 660 cur |= rops[ i ].tag; 661 *delta |= rops[ i ].tag; 662 663 break; 664 } 665 666 if ( BER_BVISNULL( &rops[ i ].op ) ) { 667 return LDAP_INVALID_SYNTAX; 668 } 669 } 670 671 return LDAP_SUCCESS; 672 } 673 674 static int 675 monitor_subsys_database_modify( 676 Operation *op, 677 SlapReply *rs, 678 Entry *e ) 679 { 680 monitor_info_t *mi = (monitor_info_t *)op->o_bd->be_private; 681 int rc = LDAP_OTHER; 682 Attribute *save_attrs, *a; 683 Modifications *ml; 684 Backend *be; 685 int ro_gotval = 1, i, n; 686 slap_mask_t rp_add = 0, rp_delete = 0, rp_cur; 687 struct berval *tf; 688 689 i = sscanf( e->e_nname.bv_val, "cn=database %d,", &n ); 690 if ( i != 1 ) { 691 return SLAP_CB_CONTINUE; 692 } 693 694 if ( n < 0 || n >= nBackendDB ) { 695 rs->sr_text = "invalid database index"; 696 return ( rs->sr_err = LDAP_NO_SUCH_OBJECT ); 697 } 698 699 LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) { 700 if ( n == 0 ) { 701 break; 702 } 703 n--; 704 } 705 /* do not allow some changes on back-monitor (needs work)... */ 706 if ( SLAP_MONITOR( be ) ) { 707 rs->sr_text = "no modifications allowed to monitor database entry"; 708 return ( rs->sr_err = LDAP_UNWILLING_TO_PERFORM ); 709 } 710 711 rp_cur = be->be_restrictops; 712 713 save_attrs = e->e_attrs; 714 e->e_attrs = attrs_dup( e->e_attrs ); 715 716 for ( ml = op->orm_modlist; ml; ml = ml->sml_next ) { 717 Modification *mod = &ml->sml_mod; 718 719 if ( mod->sm_desc == mi->mi_ad_readOnly ) { 720 int val = -1; 721 722 if ( mod->sm_values ) { 723 if ( !BER_BVISNULL( &mod->sm_values[ 1 ] ) ) { 724 rs->sr_text = "attempting to modify multiple values of single-valued attribute"; 725 rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION; 726 goto done; 727 } 728 729 if ( bvmatch( &slap_true_bv, mod->sm_values )) { 730 val = 1; 731 732 } else if ( bvmatch( &slap_false_bv, mod->sm_values )) { 733 val = 0; 734 735 } else { 736 assert( 0 ); 737 rc = rs->sr_err = LDAP_INVALID_SYNTAX; 738 goto done; 739 } 740 } 741 742 switch ( mod->sm_op ) { 743 case LDAP_MOD_DELETE: 744 if ( ro_gotval < 1 ) { 745 rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION; 746 goto done; 747 } 748 ro_gotval--; 749 750 if ( val == 0 && ( rp_cur & SLAP_RESTRICT_OP_WRITES ) == SLAP_RESTRICT_OP_WRITES ) { 751 rc = rs->sr_err = LDAP_NO_SUCH_ATTRIBUTE; 752 goto done; 753 } 754 755 if ( val == 1 && ( rp_cur & SLAP_RESTRICT_OP_WRITES ) != SLAP_RESTRICT_OP_WRITES ) { 756 rc = rs->sr_err = LDAP_NO_SUCH_ATTRIBUTE; 757 goto done; 758 } 759 760 break; 761 762 case LDAP_MOD_REPLACE: 763 ro_gotval = 0; 764 /* fall thru */ 765 766 case LDAP_MOD_ADD: 767 if ( ro_gotval > 0 ) { 768 rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION; 769 goto done; 770 } 771 ro_gotval++; 772 773 if ( val == 1 ) { 774 rp_add |= (~rp_cur) & SLAP_RESTRICT_OP_WRITES; 775 rp_cur |= SLAP_RESTRICT_OP_WRITES; 776 rp_delete &= ~SLAP_RESTRICT_OP_WRITES; 777 778 } else if ( val == 0 ) { 779 rp_delete |= rp_cur & SLAP_RESTRICT_OP_WRITES; 780 rp_cur &= ~SLAP_RESTRICT_OP_WRITES; 781 rp_add &= ~SLAP_RESTRICT_OP_WRITES; 782 } 783 break; 784 785 default: 786 rc = rs->sr_err = LDAP_OTHER; 787 goto done; 788 } 789 790 } else if ( mod->sm_desc == mi->mi_ad_restrictedOperation ) { 791 slap_mask_t mask = 0; 792 793 switch ( mod->sm_op ) { 794 case LDAP_MOD_DELETE: 795 if ( mod->sm_values == NULL ) { 796 rp_delete = rp_cur; 797 rp_cur = 0; 798 rp_add = 0; 799 break; 800 } 801 rc = value_mask( mod->sm_values, ~rp_cur, &mask ); 802 if ( rc == LDAP_SUCCESS ) { 803 rp_delete |= mask; 804 rp_add &= ~mask; 805 rp_cur &= ~mask; 806 807 } else if ( rc == LDAP_OTHER ) { 808 rc = LDAP_NO_SUCH_ATTRIBUTE; 809 } 810 break; 811 812 case LDAP_MOD_REPLACE: 813 rp_delete = rp_cur; 814 rp_cur = 0; 815 rp_add = 0; 816 /* fall thru */ 817 818 case LDAP_MOD_ADD: 819 rc = value_mask( mod->sm_values, rp_cur, &mask ); 820 if ( rc == LDAP_SUCCESS ) { 821 rp_add |= mask; 822 rp_cur |= mask; 823 rp_delete &= ~mask; 824 825 } else if ( rc == LDAP_OTHER ) { 826 rc = rs->sr_err = LDAP_TYPE_OR_VALUE_EXISTS; 827 } 828 break; 829 830 default: 831 rc = rs->sr_err = LDAP_OTHER; 832 break; 833 } 834 835 if ( rc != LDAP_SUCCESS ) { 836 goto done; 837 } 838 839 } else if ( is_at_operational( mod->sm_desc->ad_type )) { 840 /* accept all operational attributes */ 841 attr_delete( &e->e_attrs, mod->sm_desc ); 842 rc = attr_merge( e, mod->sm_desc, mod->sm_values, 843 mod->sm_nvalues ); 844 if ( rc ) { 845 rc = rs->sr_err = LDAP_OTHER; 846 break; 847 } 848 849 } else { 850 rc = rs->sr_err = LDAP_UNWILLING_TO_PERFORM; 851 break; 852 } 853 } 854 855 /* sanity checks: */ 856 if ( ro_gotval < 1 ) { 857 rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION; 858 goto done; 859 } 860 861 if ( ( rp_cur & SLAP_RESTRICT_OP_EXTENDED ) && ( rp_cur & SLAP_RESTRICT_EXOP_MASK ) ) { 862 rc = rs->sr_err = LDAP_CONSTRAINT_VIOLATION; 863 goto done; 864 } 865 866 if ( rp_delete & rp_add ) { 867 rc = rs->sr_err = LDAP_OTHER; 868 goto done; 869 } 870 871 /* check current value of readOnly */ 872 if ( ( rp_cur & SLAP_RESTRICT_OP_WRITES ) == SLAP_RESTRICT_OP_WRITES ) { 873 tf = (struct berval *)&slap_true_bv; 874 875 } else { 876 tf = (struct berval *)&slap_false_bv; 877 } 878 879 a = attr_find( e->e_attrs, mi->mi_ad_readOnly ); 880 if ( a == NULL ) { 881 rc = LDAP_OTHER; 882 goto done; 883 } 884 885 if ( !bvmatch( &a->a_vals[ 0 ], tf ) ) { 886 attr_delete( &e->e_attrs, mi->mi_ad_readOnly ); 887 rc = attr_merge_one( e, mi->mi_ad_readOnly, tf, tf ); 888 } 889 890 if ( rc == LDAP_SUCCESS ) { 891 if ( rp_delete ) { 892 if ( rp_delete == be->be_restrictops ) { 893 attr_delete( &e->e_attrs, mi->mi_ad_restrictedOperation ); 894 895 } else { 896 a = attr_find( e->e_attrs, mi->mi_ad_restrictedOperation ); 897 if ( a == NULL ) { 898 rc = rs->sr_err = LDAP_OTHER; 899 goto done; 900 } 901 902 for ( i = 0; !BER_BVISNULL( &restricted_ops[ i ].op ); i++ ) { 903 if ( rp_delete & restricted_ops[ i ].tag ) { 904 int j; 905 906 for ( j = 0; !BER_BVISNULL( &a->a_nvals[ j ] ); j++ ) { 907 int k; 908 909 if ( !bvmatch( &a->a_nvals[ j ], &restricted_ops[ i ].op ) ) { 910 continue; 911 } 912 913 ch_free( a->a_vals[ j ].bv_val ); 914 ch_free( a->a_nvals[ j ].bv_val ); 915 916 for ( k = j + 1; !BER_BVISNULL( &a->a_nvals[ k ] ); k++ ) { 917 a->a_vals[ k - 1 ] = a->a_vals[ k ]; 918 a->a_nvals[ k - 1 ] = a->a_nvals[ k ]; 919 } 920 921 BER_BVZERO( &a->a_vals[ k - 1 ] ); 922 BER_BVZERO( &a->a_nvals[ k - 1 ] ); 923 a->a_numvals--; 924 } 925 } 926 } 927 928 for ( i = 0; !BER_BVISNULL( &restricted_exops[ i ].op ); i++ ) { 929 if ( rp_delete & restricted_exops[ i ].tag ) { 930 int j; 931 932 for ( j = 0; !BER_BVISNULL( &a->a_nvals[ j ] ); j++ ) { 933 int k; 934 935 if ( !bvmatch( &a->a_nvals[ j ], &restricted_exops[ i ].op ) ) { 936 continue; 937 } 938 939 ch_free( a->a_vals[ j ].bv_val ); 940 ch_free( a->a_nvals[ j ].bv_val ); 941 942 for ( k = j + 1; !BER_BVISNULL( &a->a_nvals[ k ] ); k++ ) { 943 a->a_vals[ k - 1 ] = a->a_vals[ k ]; 944 a->a_nvals[ k - 1 ] = a->a_nvals[ k ]; 945 } 946 947 BER_BVZERO( &a->a_vals[ k - 1 ] ); 948 BER_BVZERO( &a->a_nvals[ k - 1 ] ); 949 a->a_numvals--; 950 } 951 } 952 } 953 954 if ( a->a_vals == NULL ) { 955 assert( a->a_numvals == 0 ); 956 957 attr_delete( &e->e_attrs, mi->mi_ad_restrictedOperation ); 958 } 959 } 960 } 961 962 if ( rp_add ) { 963 for ( i = 0; !BER_BVISNULL( &restricted_ops[ i ].op ); i++ ) { 964 if ( rp_add & restricted_ops[ i ].tag ) { 965 attr_merge_one( e, mi->mi_ad_restrictedOperation, 966 &restricted_ops[ i ].op, 967 &restricted_ops[ i ].op ); 968 } 969 } 970 971 for ( i = 0; !BER_BVISNULL( &restricted_exops[ i ].op ); i++ ) { 972 if ( rp_add & restricted_exops[ i ].tag ) { 973 attr_merge_one( e, mi->mi_ad_restrictedOperation, 974 &restricted_exops[ i ].op, 975 &restricted_exops[ i ].op ); 976 } 977 } 978 } 979 } 980 981 be->be_restrictops = rp_cur; 982 983 done:; 984 if ( rc == LDAP_SUCCESS ) { 985 attrs_free( save_attrs ); 986 rc = SLAP_CB_CONTINUE; 987 988 } else { 989 Attribute *tmp = e->e_attrs; 990 e->e_attrs = save_attrs; 991 attrs_free( tmp ); 992 } 993 return rc; 994 } 995 996 #if defined(LDAP_SLAPI) 997 static int 998 monitor_back_add_plugin( monitor_info_t *mi, Backend *be, Entry *e_database ) 999 { 1000 Slapi_PBlock *pCurrentPB; 1001 int i, rc = LDAP_SUCCESS; 1002 1003 if ( slapi_int_pblock_get_first( be, &pCurrentPB ) != LDAP_SUCCESS ) { 1004 /* 1005 * LDAP_OTHER is returned if no plugins are installed 1006 */ 1007 rc = LDAP_OTHER; 1008 goto done; 1009 } 1010 1011 i = 0; 1012 do { 1013 Slapi_PluginDesc *srchdesc; 1014 char buf[ BACKMONITOR_BUFSIZE ]; 1015 struct berval bv; 1016 1017 rc = slapi_pblock_get( pCurrentPB, SLAPI_PLUGIN_DESCRIPTION, 1018 &srchdesc ); 1019 if ( rc != LDAP_SUCCESS ) { 1020 goto done; 1021 } 1022 if ( srchdesc ) { 1023 snprintf( buf, sizeof(buf), 1024 "plugin %d name: %s; " 1025 "vendor: %s; " 1026 "version: %s; " 1027 "description: %s", 1028 i, 1029 srchdesc->spd_id, 1030 srchdesc->spd_vendor, 1031 srchdesc->spd_version, 1032 srchdesc->spd_description ); 1033 } else { 1034 snprintf( buf, sizeof(buf), 1035 "plugin %d name: <no description available>", i ); 1036 } 1037 1038 ber_str2bv( buf, 0, 0, &bv ); 1039 attr_merge_normalize_one( e_database, 1040 mi->mi_ad_monitoredInfo, &bv, NULL ); 1041 1042 i++; 1043 1044 } while ( ( slapi_int_pblock_get_next( &pCurrentPB ) == LDAP_SUCCESS ) 1045 && ( pCurrentPB != NULL ) ); 1046 1047 done: 1048 return rc; 1049 } 1050 #endif /* defined(LDAP_SLAPI) */ 1051