]> git.sur5r.net Git - openldap/blob - servers/slapd/back-monitor/database.c
f0d907a227e045635c48792e423f3f7b0bf90f81
[openldap] / servers / slapd / back-monitor / database.c
1 /* database.c - deals with database subsystem */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2001-2004 The OpenLDAP Foundation.
6  * Portions Copyright 2001-2003 Pierangelo Masarati.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 /* ACKNOWLEDGEMENTS:
18  * This work was initially developed by Pierangelo Masarati for inclusion
19  * in OpenLDAP Software.
20  */
21
22 #include "portable.h"
23
24 #include <stdio.h>
25 #include <ac/string.h>
26
27 #include "slap.h"
28 #include "back-monitor.h"
29
30 #if defined(LDAP_SLAPI)
31 #include "slapi.h"
32 static int monitor_back_add_plugin( Backend *be, Entry *e );
33 #endif /* defined(LDAP_SLAPI) */
34
35 #if defined(SLAPD_LDAP) 
36 #include "../back-ldap/back-ldap.h"
37 #endif /* defined(SLAPD_LDAP) */
38
39 static struct restricted_ops_t {
40         struct berval   op;
41         unsigned int    tag;
42 } restricted_ops[] = {
43         { BER_BVC( "add" ),                     SLAP_RESTRICT_OP_ADD },
44         { BER_BVC( "bind" ),                    SLAP_RESTRICT_OP_BIND },
45         { BER_BVC( "compare" ),                 SLAP_RESTRICT_OP_COMPARE },
46         { BER_BVC( "delete" ),                  SLAP_RESTRICT_OP_DELETE },
47         { BER_BVC( "extended" ),                SLAP_RESTRICT_OP_EXTENDED },
48         { BER_BVC( "modify" ),                  SLAP_RESTRICT_OP_MODIFY },
49         { BER_BVC( "rename" ),                  SLAP_RESTRICT_OP_RENAME },
50         { BER_BVC( "search" ),                  SLAP_RESTRICT_OP_SEARCH },
51         { BER_BVNULL,                           0 }
52 }, restricted_exops[] = {
53         { BER_BVC( LDAP_EXOP_START_TLS ),       SLAP_RESTRICT_EXOP_START_TLS },
54         { BER_BVC( LDAP_EXOP_MODIFY_PASSWD ),   SLAP_RESTRICT_EXOP_MODIFY_PASSWD },
55         { BER_BVC( LDAP_EXOP_X_WHO_AM_I ),      SLAP_RESTRICT_EXOP_WHOAMI },
56         { BER_BVC( LDAP_EXOP_X_CANCEL ),        SLAP_RESTRICT_EXOP_CANCEL },
57         { BER_BVNULL,                           0 }
58 };
59
60 static int
61 init_readOnly( struct monitorinfo *mi, Entry *e, slap_mask_t restrictops )
62 {
63         struct berval   *tf = ( ( restrictops & SLAP_RESTRICT_OP_MASK ) == SLAP_RESTRICT_OP_WRITES ) ?
64                 (struct berval *)&slap_true_bv : (struct berval *)&slap_false_bv;
65
66         return attr_merge_one( e, mi->mi_ad_readOnly, tf, tf );
67 }
68
69 static int
70 init_restrictedOperation( struct monitorinfo *mi, Entry *e, slap_mask_t restrictops )
71 {
72         int     i, rc;
73
74         for ( i = 0; restricted_ops[ i ].op.bv_val; i++ ) {
75                 if ( restrictops & restricted_ops[ i ].tag ) {
76                         rc = attr_merge_one( e, mi->mi_ad_restrictedOperation,
77                                         &restricted_ops[ i ].op, &restricted_ops[ i ].op );
78                         if ( rc ) {
79                                 return rc;
80                         }
81                 }
82         }
83
84         for ( i = 0; restricted_exops[ i ].op.bv_val; i++ ) {
85                 if ( restrictops & restricted_exops[ i ].tag ) {
86                         rc = attr_merge_one( e, mi->mi_ad_restrictedOperation,
87                                         &restricted_exops[ i ].op, &restricted_exops[ i ].op );
88                         if ( rc ) {
89                                 return rc;
90                         }
91                 }
92         }
93
94         return LDAP_SUCCESS;
95 }
96
97 int
98 monitor_subsys_database_init(
99         BackendDB       *be
100 )
101 {
102         struct monitorinfo      *mi;
103         Entry                   *e, *e_database, *e_tmp;
104         int                     i;
105         struct monitorentrypriv *mp;
106
107         assert( be != NULL );
108
109         mi = ( struct monitorinfo * )be->be_private;
110
111         if ( monitor_cache_get( mi, 
112                                 &monitor_subsys[SLAPD_MONITOR_DATABASE].mss_ndn, 
113                                 &e_database ) ) {
114 #ifdef NEW_LOGGING
115                 LDAP_LOG( OPERATION, CRIT,
116                         "monitor_subsys_database_init: "
117                         "unable to get entry '%s'\n",
118                         monitor_subsys[SLAPD_MONITOR_DATABASE].mss_ndn.bv_val, 0, 0 );
119 #else
120                 Debug( LDAP_DEBUG_ANY,
121                         "monitor_subsys_database_init: "
122                         "unable to get entry '%s'\n%s%s",
123                         monitor_subsys[SLAPD_MONITOR_DATABASE].mss_ndn.bv_val, 
124                         "", "" );
125 #endif
126                 return( -1 );
127         }
128
129         (void)init_readOnly( mi, e_database, global_restrictops );
130         (void)init_restrictedOperation( mi, e_database, global_restrictops );
131
132         e_tmp = NULL;
133         for ( i = nBackendDB; i--; ) {
134                 char            buf[ BACKMONITOR_BUFSIZE ];
135                 int             j;
136                 slap_overinfo   *oi = NULL;
137                 BackendInfo     *bi;
138
139                 be = &backendDB[i];
140
141                 bi = be->bd_info;
142
143                 if ( strcmp( be->bd_info->bi_type, "over" ) == 0 ) {
144                         oi = (slap_overinfo *)be->bd_info->bi_private;
145                         bi = oi->oi_orig;
146                 }
147
148                 /* Subordinates are not exposed as their own naming context */
149                 if ( SLAP_GLUE_SUBORDINATE( be ) ) {
150                         continue;
151                 }
152
153                 snprintf( buf, sizeof( buf ),
154                                 "dn: cn=Database %d,%s\n"
155                                 "objectClass: %s\n"
156                                 "structuralObjectClass: %s\n"
157                                 "cn: Database %d\n"
158                                 "description: This object contains the type of the database.\n"
159                                 "%s: %s\n"
160                                 "createTimestamp: %s\n"
161                                 "modifyTimestamp: %s\n",
162                                 i,
163                                 monitor_subsys[SLAPD_MONITOR_DATABASE].mss_dn.bv_val,
164                                 mi->mi_oc_monitoredObject->soc_cname.bv_val,
165                                 mi->mi_oc_monitoredObject->soc_cname.bv_val,
166                                 i,
167                                 mi->mi_ad_monitoredInfo->ad_cname.bv_val,
168                                 bi->bi_type,
169                                 mi->mi_startTime.bv_val,
170                                 mi->mi_startTime.bv_val );
171                 
172                 e = str2entry( buf );
173                 if ( e == NULL ) {
174 #ifdef NEW_LOGGING
175                         LDAP_LOG( OPERATION, CRIT,
176                                 "monitor_subsys_database_init: "
177                                 "unable to create entry 'cn=Database %d,%s'\n",
178                                 i, monitor_subsys[SLAPD_MONITOR_DATABASE].mss_ndn.bv_val, 0 );
179 #else
180                         Debug( LDAP_DEBUG_ANY,
181                                 "monitor_subsys_database_init: "
182                                 "unable to create entry 'cn=Database %d,%s'\n%s",
183                                 i, 
184                                 monitor_subsys[SLAPD_MONITOR_DATABASE].mss_ndn.bv_val,
185                                 "" );
186 #endif
187                         return( -1 );
188                 }
189                 
190                 if ( SLAP_MONITOR(be) ) {
191                         attr_merge( e, slap_schema.si_ad_monitorContext,
192                                         be->be_suffix, be->be_nsuffix );
193                         attr_merge( e_database, slap_schema.si_ad_monitorContext,
194                                         be->be_suffix, be->be_nsuffix );
195                 } else {
196                         attr_merge( e, slap_schema.si_ad_namingContexts,
197                                         be->be_suffix, be->be_nsuffix );
198                         attr_merge( e_database, slap_schema.si_ad_namingContexts,
199                                         be->be_suffix, be->be_nsuffix );
200                 }
201
202                 (void)init_readOnly( mi, e, be->be_restrictops );
203                 (void)init_restrictedOperation( mi, e, be->be_restrictops );
204
205                 if ( oi != NULL ) {
206                         slap_overinst *on = oi->oi_list;
207
208                         for ( ; on; on = on->on_next ) {
209                                 struct berval           bv;
210                                 slap_overinst           *on2;
211                                 
212                                 bv.bv_val = on->on_bi.bi_type;
213                                 bv.bv_len = strlen( bv.bv_val );
214                                 attr_merge_normalize_one( e, mi->mi_ad_monitorOverlay,
215                                                 &bv, NULL );
216
217                                 for ( on2 = overlay_next( NULL ), j = 0; on2; on2 = overlay_next( on2 ), j++ ) {
218                                         if ( on2->on_bi.bi_type == on->on_bi.bi_type ) {
219                                                 break;
220                                         }
221                                 }
222                                 assert( on2 );
223
224                                 snprintf( buf, sizeof( buf ), 
225                                         "cn=Overlay %d,%s", 
226                                         j, monitor_subsys[SLAPD_MONITOR_OVERLAY].mss_dn.bv_val );
227                                 bv.bv_val = buf;
228                                 bv.bv_len = strlen( buf );
229                                 attr_merge_normalize_one( e, mi->mi_ad_seeAlso,
230                                                 &bv, NULL );
231                         }
232                 }
233
234 #if defined(SLAPD_LDAP) 
235                 if ( strcmp( bi->bi_type, "ldap" ) == 0 ) {
236                         struct ldapinfo         *li = (struct ldapinfo *)be->be_private;
237                         struct berval           bv;
238
239                         bv.bv_val = li->url;
240                         bv.bv_len = strlen( bv.bv_val );
241                         attr_merge_normalize_one( e, mi->mi_ad_labeledURI,
242                                         &bv, NULL );
243                 }
244 #endif /* defined(SLAPD_LDAP) */
245
246                 for ( j = nBackendInfo; j--; ) {
247                         if ( backendInfo[ j ].bi_type == bi->bi_type ) {
248                                 struct berval           bv;
249
250                                 snprintf( buf, sizeof( buf ), 
251                                         "cn=Backend %d,%s", 
252                                         j, monitor_subsys[SLAPD_MONITOR_BACKEND].mss_dn.bv_val );
253                                 bv.bv_val = buf;
254                                 bv.bv_len = strlen( buf );
255                                 attr_merge_normalize_one( e, mi->mi_ad_seeAlso,
256                                                 &bv, NULL );
257                                 break;
258                         }
259                 }
260                 /* we must find it! */
261                 assert( j >= 0 );
262
263                 mp = ( struct monitorentrypriv * )ch_calloc( sizeof( struct monitorentrypriv ), 1 );
264                 e->e_private = ( void * )mp;
265                 mp->mp_next = e_tmp;
266                 mp->mp_children = NULL;
267                 mp->mp_info = &monitor_subsys[SLAPD_MONITOR_DATABASE];
268                 mp->mp_flags = monitor_subsys[SLAPD_MONITOR_DATABASE].mss_flags
269                         | MONITOR_F_SUB;
270
271                 if ( monitor_cache_add( mi, e ) ) {
272 #ifdef NEW_LOGGING
273                         LDAP_LOG( OPERATION, CRIT,
274                                 "monitor_subsys_database_init: "
275                                 "unable to add entry 'cn=Database %d,%s'\n",
276                                 i, monitor_subsys[SLAPD_MONITOR_DATABASE].mss_ndn.bv_val, 0 );
277 #else
278                         Debug( LDAP_DEBUG_ANY,
279                                 "monitor_subsys_database_init: "
280                                 "unable to add entry 'cn=Database %d,%s'\n",
281                                 i, 
282                                 monitor_subsys[SLAPD_MONITOR_DATABASE].mss_ndn.bv_val,
283                                 0 );
284 #endif
285                         return( -1 );
286                 }
287
288 #if defined(LDAP_SLAPI)
289                 monitor_back_add_plugin( be, e );
290 #endif /* defined(LDAP_SLAPI) */
291
292                 e_tmp = e;
293         }
294         
295         mp = ( struct monitorentrypriv * )e_database->e_private;
296         mp->mp_children = e_tmp;
297
298         monitor_cache_release( mi, e_database );
299
300         return( 0 );
301 }
302
303 /*
304  * v: array of values
305  * cur: must not contain the tags corresponding to the values in v
306  * delta: will contain the tags corresponding to the values in v
307  */
308 static int
309 value_mask( BerVarray v, slap_mask_t cur, slap_mask_t *delta )
310 {
311         for ( ; !BER_BVISNULL( v ); v++ ) {
312                 struct restricted_ops_t         *rops;
313                 int                             i;
314
315                 if ( OID_LEADCHAR( v->bv_val[ 0 ] ) ) {
316                         rops = restricted_exops;
317
318                 } else {
319                         rops = restricted_ops;
320                 }
321
322                 for ( i = 0; !BER_BVISNULL( &rops[ i ].op ); i++ ) {
323                         if ( ber_bvstrcasecmp( v, &rops[ i ].op ) != 0 ) {
324                                 continue;
325                         }
326
327                         if ( rops[ i ].tag & *delta ) {
328                                 return LDAP_OTHER;
329                         }
330
331                         if ( rops[ i ].tag & cur ) {
332                                 return LDAP_OTHER;
333                         }
334
335                         cur |= rops[ i ].tag;
336                         *delta |= rops[ i ].tag;
337
338                         break;
339                 }
340
341                 if ( BER_BVISNULL( &rops[ i ].op ) ) {
342                         return LDAP_INVALID_SYNTAX;
343                 }
344         }
345
346         return LDAP_SUCCESS;
347 }
348
349 int
350 monitor_subsys_database_modify(
351         Operation       *op,
352         Entry           *e
353 )
354 {
355         struct monitorinfo *mi = (struct monitorinfo *)op->o_bd->be_private;
356         int rc = LDAP_OTHER;
357         Attribute *save_attrs, *a;
358         Modifications *modlist = op->oq_modify.rs_modlist;
359         Modifications *ml;
360         Backend *be;
361         int ro_gotval = 1, i, n;
362         slap_mask_t     rp_add = 0, rp_delete = 0, rp_cur;
363         struct berval *tf;
364         
365         i = sscanf( e->e_nname.bv_val, "cn=database %d,", &n );
366         if ( i != 1 )
367                 return LDAP_UNWILLING_TO_PERFORM;
368
369         if ( n < 0 || n >= nBackendDB )
370                 return LDAP_NO_SUCH_OBJECT;
371
372         /* do not allow some changes on back-monitor (needs work)... */
373         be = &backendDB[n];
374         if ( SLAP_MONITOR( be ) )
375                 return LDAP_UNWILLING_TO_PERFORM;
376                 
377         rp_cur = be->be_restrictops;
378
379         save_attrs = e->e_attrs;
380         e->e_attrs = attrs_dup( e->e_attrs );
381
382         for ( ml=modlist; ml; ml=ml->sml_next ) {
383                 Modification *mod = &ml->sml_mod;
384
385                 if ( mod->sm_desc == mi->mi_ad_readOnly ) {
386                         int     val = -1;
387
388                         if ( mod->sm_values ) {
389                                 if ( !BER_BVISNULL( &mod->sm_values[ 1 ] ) ) {
390                                         rc = LDAP_CONSTRAINT_VIOLATION;
391                                         goto done;
392                                 }
393
394                                 if ( bvmatch( &slap_true_bv, mod->sm_values )) {
395                                         val = 1;
396
397                                 } else if ( bvmatch( &slap_false_bv, mod->sm_values )) {
398                                         val = 0;
399
400                                 } else {
401                                         rc = LDAP_INVALID_SYNTAX;
402                                         goto done;
403                                 }
404                         }
405
406                         switch ( mod->sm_op ) {
407                         case LDAP_MOD_DELETE:
408                                 if ( ro_gotval < 1 ) {
409                                         rc = LDAP_CONSTRAINT_VIOLATION;
410                                         goto done;
411                                 }
412                                 ro_gotval--;
413
414                                 if ( val == 0 && ( rp_cur & SLAP_RESTRICT_OP_WRITES ) == SLAP_RESTRICT_OP_WRITES ) {
415                                         rc = LDAP_NO_SUCH_ATTRIBUTE;
416                                         goto done;
417                                 }
418                                 
419                                 if ( val == 1 && ( rp_cur & SLAP_RESTRICT_OP_WRITES ) != SLAP_RESTRICT_OP_WRITES ) {
420                                         rc = LDAP_NO_SUCH_ATTRIBUTE;
421                                         goto done;
422                                 }
423                                 
424                                 break;
425
426                         case LDAP_MOD_REPLACE:
427                                 ro_gotval = 0;
428                                 /* fall thru */
429
430                         case LDAP_MOD_ADD:
431                                 if ( ro_gotval > 0 ) {
432                                         rc = LDAP_CONSTRAINT_VIOLATION;
433                                         goto done;
434                                 }
435                                 ro_gotval++;
436
437                                 if ( val == 1 ) {
438                                         rp_add |= (~rp_cur) & SLAP_RESTRICT_OP_WRITES;
439                                         rp_cur |= SLAP_RESTRICT_OP_WRITES;
440                                         rp_delete &= ~SLAP_RESTRICT_OP_WRITES;
441                                         
442                                 } else if ( val == 0 ) {
443                                         rp_delete |= rp_cur & SLAP_RESTRICT_OP_WRITES;
444                                         rp_cur &= ~SLAP_RESTRICT_OP_WRITES;
445                                         rp_add &= ~SLAP_RESTRICT_OP_WRITES;
446                                 }
447                                 break;
448
449                         default:
450                                 rc = LDAP_OTHER;
451                                 goto done;
452                         }
453
454                 } else if ( mod->sm_desc == mi->mi_ad_restrictedOperation ) {
455                         slap_mask_t     mask = 0;
456
457                         switch ( mod->sm_op ) {
458                         case LDAP_MOD_DELETE:
459                                 if ( mod->sm_values == NULL ) {
460                                         rp_delete = rp_cur;
461                                         rp_cur = 0;
462                                         rp_add = 0;
463                                         break;
464                                 }
465                                 rc = value_mask( mod->sm_values, ~rp_cur, &mask );
466                                 if ( rc == LDAP_SUCCESS ) {
467                                         rp_delete |= mask;
468                                         rp_add &= ~mask;
469                                         rp_cur &= ~mask;
470
471                                 } else if ( rc == LDAP_OTHER ) {
472                                         rc = LDAP_NO_SUCH_ATTRIBUTE;
473                                 }
474                                 break;
475
476                         case LDAP_MOD_REPLACE:
477                                 rp_delete = rp_cur;
478                                 rp_cur = 0;
479                                 rp_add = 0;
480                                 /* fall thru */
481
482                         case LDAP_MOD_ADD:
483                                 rc = value_mask( mod->sm_values, rp_cur, &mask );
484                                 if ( rc == LDAP_SUCCESS ) {
485                                         rp_add |= mask;
486                                         rp_cur |= mask;
487                                         rp_delete &= ~mask;
488
489                                 } else if ( rc == LDAP_OTHER ) {
490                                         rc = LDAP_TYPE_OR_VALUE_EXISTS;
491                                 }
492                                 break;
493
494                         default:
495                                 rc = LDAP_OTHER;
496                                 break;
497                         }
498
499                         if ( rc != LDAP_SUCCESS ) {
500                                 goto done;
501                         }
502
503                 } else if ( is_at_operational( mod->sm_desc->ad_type )) {
504                 /* accept all operational attributes */
505                         attr_delete( &e->e_attrs, mod->sm_desc );
506                         rc = attr_merge( e, mod->sm_desc, mod->sm_values,
507                                 mod->sm_nvalues );
508                         if ( rc ) {
509                                 rc = LDAP_OTHER;
510                                 break;
511                         }
512
513                 } else {
514                         rc = LDAP_UNWILLING_TO_PERFORM;
515                         break;
516                 }
517         }
518
519         /* sanity checks: */
520         if ( ro_gotval < 1 ) {
521                 rc = LDAP_CONSTRAINT_VIOLATION;
522                 goto done;
523         }
524
525         if ( ( rp_cur & SLAP_RESTRICT_OP_EXTENDED ) && ( rp_cur & SLAP_RESTRICT_EXOP_MASK ) ) {
526                 rc = LDAP_CONSTRAINT_VIOLATION;
527                 goto done;
528         }
529
530         if ( rp_delete & rp_add ) {
531                 rc = LDAP_OTHER;
532                 goto done;
533         }
534
535         /* check current value of readOnly */
536         if ( ( rp_cur & SLAP_RESTRICT_OP_WRITES ) == SLAP_RESTRICT_OP_WRITES ) {
537                 tf = (struct berval *)&slap_true_bv;
538
539         } else {
540                 tf = (struct berval *)&slap_false_bv;
541         }
542
543         a = attr_find( e->e_attrs, mi->mi_ad_readOnly );
544         if ( a == NULL ) {
545                 rc = LDAP_OTHER;
546                 goto done;
547         }
548
549         if ( !bvmatch( &a->a_vals[0], tf ) ) {
550                 attr_delete( &e->e_attrs, mi->mi_ad_readOnly );
551                 rc = attr_merge_one( e, mi->mi_ad_readOnly, tf, tf );
552         }
553
554         if ( rc == LDAP_SUCCESS ) {
555                 if ( rp_delete ) {
556                         if ( rp_delete == be->be_restrictops ) {
557                                 attr_delete( &e->e_attrs, mi->mi_ad_restrictedOperation );
558
559                         } else {
560                                 a = attr_find( e->e_attrs, mi->mi_ad_restrictedOperation );
561                                 if ( a == NULL ) {
562                                         rc = LDAP_OTHER;
563                                         goto done;
564                                 }
565
566                                 for ( i = 0; !BER_BVISNULL( &restricted_ops[ i ].op ); i++ ) {
567                                         if ( rp_delete & restricted_ops[ i ].tag ) {
568                                                 int     j;
569                                         
570                                                 for ( j = 0; !BER_BVISNULL( &a->a_nvals[ j ] ); j++ ) {
571                                                         int             k;
572
573                                                         if ( !bvmatch( &a->a_nvals[ j ], &restricted_ops[ i ].op ) ) {
574                                                                 continue;
575                                                         }
576
577                                                         ch_free( a->a_vals[ j ].bv_val );
578                                                         ch_free( a->a_nvals[ j ].bv_val );
579
580                                                         for ( k = j + 1; !BER_BVISNULL( &a->a_nvals[ k ] ); k++ ) {
581                                                                 a->a_vals[ k - 1 ] = a->a_vals[ k ];
582                                                                 a->a_nvals[ k - 1 ] = a->a_nvals[ k ];
583                                                         }
584         
585                                                         BER_BVZERO( &a->a_vals[ k - 1 ] );
586                                                         BER_BVZERO( &a->a_nvals[ k - 1 ] );
587                                                 }
588                                         }
589                                 }
590                                 
591                                 for ( i = 0; !BER_BVISNULL( &restricted_exops[ i ].op ); i++ ) {
592                                         if ( rp_delete & restricted_exops[ i ].tag ) {
593                                                 int     j;
594                                         
595                                                 for ( j = 0; !BER_BVISNULL( &a->a_nvals[ j ] ); j++ ) {
596                                                         int             k;
597
598                                                         if ( !bvmatch( &a->a_nvals[ j ], &restricted_exops[ i ].op ) ) {
599                                                                 continue;
600                                                         }
601
602                                                         ch_free( a->a_vals[ j ].bv_val );
603                                                         ch_free( a->a_nvals[ j ].bv_val );
604
605                                                         for ( k = j + 1; !BER_BVISNULL( &a->a_nvals[ k ] ); k++ ) {
606                                                                 a->a_vals[ k - 1 ] = a->a_vals[ k ];
607                                                                 a->a_nvals[ k - 1 ] = a->a_nvals[ k ];
608                                                         }
609         
610                                                         BER_BVZERO( &a->a_vals[ k - 1 ] );
611                                                         BER_BVZERO( &a->a_nvals[ k - 1 ] );
612                                                 }
613                                         }
614                                 }
615                         }
616                 }
617
618                 if ( rp_add ) {
619                         for ( i = 0; !BER_BVISNULL( &restricted_ops[ i ].op ); i++ ) {
620                                 if ( rp_add & restricted_ops[ i ].tag ) {
621                                         attr_merge_one( e, mi->mi_ad_restrictedOperation,
622                                                         &restricted_ops[ i ].op, &restricted_ops[ i ].op );
623                                 }
624                         }
625
626                         for ( i = 0; !BER_BVISNULL( &restricted_exops[ i ].op ); i++ ) {
627                                 if ( rp_add & restricted_exops[ i ].tag ) {
628                                         attr_merge_one( e, mi->mi_ad_restrictedOperation,
629                                                         &restricted_exops[ i ].op, &restricted_exops[ i ].op );
630                                 }
631                         }
632                 }
633         }
634
635         be->be_restrictops = rp_cur;
636
637 done:;
638         if ( rc == LDAP_SUCCESS ) {
639                 attrs_free( save_attrs );
640
641         } else {
642                 Attribute *tmp = e->e_attrs;
643                 e->e_attrs = save_attrs;
644                 attrs_free( tmp );
645         }
646         return rc;
647 }
648
649 #if defined(LDAP_SLAPI)
650 static int
651 monitor_back_add_plugin( Backend *be, Entry *e_database )
652 {
653         Slapi_PBlock            *pCurrentPB; 
654         int                     i, rc = LDAP_SUCCESS;
655         struct monitorinfo      *mi = ( struct monitorinfo * )be->be_private;
656
657         if ( slapi_int_pblock_get_first( be, &pCurrentPB ) != LDAP_SUCCESS ) {
658                 /*
659                  * LDAP_OTHER is returned if no plugins are installed
660                  */
661                 rc = LDAP_OTHER;
662                 goto done;
663         }
664
665         i = 0;
666         do {
667                 Slapi_PluginDesc        *srchdesc;
668                 char                    buf[ BACKMONITOR_BUFSIZE ];
669                 struct berval           bv;
670
671                 rc = slapi_pblock_get( pCurrentPB, SLAPI_PLUGIN_DESCRIPTION,
672                                 &srchdesc );
673                 if ( rc != LDAP_SUCCESS ) {
674                         goto done;
675                 }
676
677                 snprintf( buf, sizeof(buf),
678                                 "plugin %d name: %s; "
679                                 "vendor: %s; "
680                                 "version: %s; "
681                                 "description: %s", 
682                                 i,
683                                 srchdesc->spd_id,
684                                 srchdesc->spd_vendor,
685                                 srchdesc->spd_version,
686                                 srchdesc->spd_description );
687
688                 bv.bv_val = buf;
689                 bv.bv_len = strlen( buf );
690                 attr_merge_normalize_one( e_database,
691                                 mi->mi_ad_monitoredInfo, &bv, NULL );
692
693                 i++;
694
695         } while ( ( slapi_int_pblock_get_next( &pCurrentPB ) == LDAP_SUCCESS )
696                         && ( pCurrentPB != NULL ) );
697
698 done:
699         return rc;
700 }
701 #endif /* defined(LDAP_SLAPI) */