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