]> git.sur5r.net Git - openldap/blob - servers/slapd/back-monitor/log.c
Merge remote-tracking branch 'origin/mdb.master'
[openldap] / servers / slapd / back-monitor / log.c
1 /* log.c - deal with log subsystem */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2001-2013 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
26 #include <ac/string.h>
27
28 #include "slap.h"
29 #include <lber_pvt.h>
30 #include "lutil.h"
31 #include "ldif.h"
32 #include "back-monitor.h"
33
34 static int 
35 monitor_subsys_log_open( 
36         BackendDB               *be,
37         monitor_subsys_t        *ms );
38
39 static int 
40 monitor_subsys_log_modify( 
41         Operation               *op,
42         SlapReply               *rs,
43         Entry                   *e );
44
45 /*
46  * log mutex
47  */
48 ldap_pvt_thread_mutex_t         monitor_log_mutex;
49
50 static int add_values( Operation *op, Entry *e, Modification *mod, int *newlevel );
51 static int delete_values( Operation *op, Entry *e, Modification *mod, int *newlevel );
52 static int replace_values( Operation *op, Entry *e, Modification *mod, int *newlevel );
53
54 /*
55  * initializes log subentry
56  */
57 int
58 monitor_subsys_log_init(
59         BackendDB               *be,
60         monitor_subsys_t        *ms )
61 {
62         ms->mss_open = monitor_subsys_log_open;
63         ms->mss_modify = monitor_subsys_log_modify;
64
65         ldap_pvt_thread_mutex_init( &monitor_log_mutex );
66
67         return( 0 );
68 }
69
70 /*
71  * opens log subentry
72  */
73 int
74 monitor_subsys_log_open(
75         BackendDB               *be,
76         monitor_subsys_t        *ms )
77 {
78         BerVarray       bva = NULL;
79
80         if ( loglevel2bvarray( ldap_syslog, &bva ) == 0 && bva != NULL ) {
81                 monitor_info_t  *mi;
82                 Entry           *e;
83
84                 mi = ( monitor_info_t * )be->be_private;
85
86                 if ( monitor_cache_get( mi, &ms->mss_ndn, &e ) ) {
87                         Debug( LDAP_DEBUG_ANY,
88                                 "monitor_subsys_log_init: "
89                                 "unable to get entry \"%s\"\n",
90                                 ms->mss_ndn.bv_val, 0, 0 );
91                         ber_bvarray_free( bva );
92                         return( -1 );
93                 }
94
95                 attr_merge_normalize( e, mi->mi_ad_managedInfo, bva, NULL );
96                 ber_bvarray_free( bva );
97
98                 monitor_cache_release( mi, e );
99         }
100
101         return( 0 );
102 }
103
104 static int 
105 monitor_subsys_log_modify( 
106         Operation               *op,
107         SlapReply               *rs,
108         Entry                   *e )
109 {
110         monitor_info_t  *mi = ( monitor_info_t * )op->o_bd->be_private;
111         int             rc = LDAP_OTHER;
112         int             newlevel = ldap_syslog;
113         Attribute       *save_attrs;
114         Modifications   *modlist = op->orm_modlist;
115         Modifications   *ml;
116
117         ldap_pvt_thread_mutex_lock( &monitor_log_mutex );
118
119         save_attrs = e->e_attrs;
120         e->e_attrs = attrs_dup( e->e_attrs );
121
122         for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
123                 Modification    *mod = &ml->sml_mod;
124
125                 /*
126                  * accept all operational attributes;
127                  * this includes modifersName and modifyTimestamp
128                  * if lastmod is "on"
129                  */
130                 if ( is_at_operational( mod->sm_desc->ad_type ) ) {
131                         ( void ) attr_delete( &e->e_attrs, mod->sm_desc );
132                         rc = rs->sr_err = attr_merge( e, mod->sm_desc,
133                                         mod->sm_values, mod->sm_nvalues );
134                         if ( rc != LDAP_SUCCESS ) {
135                                 break;
136                         }
137                         continue;
138
139                 /*
140                  * only the "managedInfo" attribute can be modified
141                  */
142                 } else if ( mod->sm_desc != mi->mi_ad_managedInfo ) {
143                         rc = rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
144                         break;
145                 }
146
147                 switch ( mod->sm_op ) {
148                 case LDAP_MOD_ADD:
149                         rc = add_values( op, e, mod, &newlevel );
150                         break;
151                         
152                 case LDAP_MOD_DELETE:
153                         rc = delete_values( op, e, mod, &newlevel );
154                         break;
155
156                 case LDAP_MOD_REPLACE:
157                         rc = replace_values( op, e, mod, &newlevel );
158                         break;
159
160                 default:
161                         rc = LDAP_OTHER;
162                         break;
163                 }
164
165                 if ( rc != LDAP_SUCCESS ) {
166                         rs->sr_err = rc;
167                         break;
168                 }
169         }
170
171         /* set the new debug level */
172         if ( rc == LDAP_SUCCESS ) {
173                 const char      *text;
174                 static char     textbuf[ BACKMONITOR_BUFSIZE ];
175
176                 /* check for abandon */
177                 if ( op->o_abandon ) {
178                         rc = rs->sr_err = SLAPD_ABANDON;
179
180                         goto cleanup;
181                 }
182
183                 /* check that the entry still obeys the schema */
184                 rc = entry_schema_check( op, e, save_attrs, 0, 0, NULL,
185                         &text, textbuf, sizeof( textbuf ) );
186                 if ( rc != LDAP_SUCCESS ) {
187                         rs->sr_err = rc;
188                         goto cleanup;
189                 }
190
191                 /*
192                  * Do we need to protect this with a mutex?
193                  */
194                 ldap_syslog = newlevel;
195
196 #if 0   /* debug rather than log */
197                 slap_debug = newlevel;
198                 lutil_set_debug_level( "slapd", slap_debug );
199                 ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &slap_debug);
200                 ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &slap_debug);
201                 ldif_debug = slap_debug;
202 #endif
203         }
204
205 cleanup:;
206         if ( rc == LDAP_SUCCESS ) {
207                 attrs_free( save_attrs );
208
209         } else {
210                 attrs_free( e->e_attrs );
211                 e->e_attrs = save_attrs;
212         }
213         
214         ldap_pvt_thread_mutex_unlock( &monitor_log_mutex );
215
216         if ( rc == LDAP_SUCCESS ) {
217                 rc = SLAP_CB_CONTINUE;
218         }
219
220         return rc;
221 }
222
223 static int
224 check_constraints( Modification *mod, int *newlevel )
225 {
226         int             i;
227
228         if ( mod->sm_nvalues != NULL ) {
229                 ber_bvarray_free( mod->sm_nvalues );
230                 mod->sm_nvalues = NULL;
231         }
232
233         for ( i = 0; !BER_BVISNULL( &mod->sm_values[ i ] ); i++ ) {
234                 int             l;
235                 struct berval   bv;
236
237                 if ( str2loglevel( mod->sm_values[ i ].bv_val, &l ) ) {
238                         return LDAP_CONSTRAINT_VIOLATION;
239                 }
240
241                 if ( loglevel2bv( l, &bv ) ) {
242                         return LDAP_CONSTRAINT_VIOLATION;
243                 }
244                 
245                 assert( bv.bv_len == mod->sm_values[ i ].bv_len );
246                 
247                 AC_MEMCPY( mod->sm_values[ i ].bv_val,
248                                 bv.bv_val, bv.bv_len );
249
250                 *newlevel |= l;
251         }
252
253         return LDAP_SUCCESS;
254 }       
255
256 static int 
257 add_values( Operation *op, Entry *e, Modification *mod, int *newlevel )
258 {
259         Attribute       *a;
260         int             i, rc;
261         MatchingRule    *mr = mod->sm_desc->ad_type->sat_equality;
262
263         assert( mod->sm_values != NULL );
264
265         rc = check_constraints( mod, newlevel );
266         if ( rc != LDAP_SUCCESS ) {
267                 return rc;
268         }
269
270         a = attr_find( e->e_attrs, mod->sm_desc );
271
272         if ( a != NULL ) {
273                 /* "managedInfo" SHOULD have appropriate rules ... */
274                 if ( mr == NULL || !mr->smr_match ) {
275                         return LDAP_INAPPROPRIATE_MATCHING;
276                 }
277
278                 for ( i = 0; !BER_BVISNULL( &mod->sm_values[ i ] ); i++ ) {
279                         int rc;
280                         int j;
281                         const char *text = NULL;
282                         struct berval asserted;
283
284                         rc = asserted_value_validate_normalize(
285                                 mod->sm_desc, mr, SLAP_MR_EQUALITY,
286                                 &mod->sm_values[ i ], &asserted, &text,
287                                 op->o_tmpmemctx );
288
289                         if ( rc != LDAP_SUCCESS ) {
290                                 return rc;
291                         }
292
293                         for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ ) {
294                                 int match;
295                                 int rc = value_match( &match, mod->sm_desc, mr,
296                                         0, &a->a_nvals[ j ], &asserted, &text );
297
298                                 if ( rc == LDAP_SUCCESS && match == 0 ) {
299                                         free( asserted.bv_val );
300                                         return LDAP_TYPE_OR_VALUE_EXISTS;
301                                 }
302                         }
303
304                         free( asserted.bv_val );
305                 }
306         }
307
308         /* no - add them */
309         rc = attr_merge_normalize( e, mod->sm_desc, mod->sm_values,
310                 op->o_tmpmemctx );
311         if ( rc != LDAP_SUCCESS ) {
312                 return rc;
313         }
314
315         return LDAP_SUCCESS;
316 }
317
318 static int
319 delete_values( Operation *op, Entry *e, Modification *mod, int *newlevel )
320 {
321         int             i, j, k, found, rc, nl = 0;
322         Attribute       *a;
323         MatchingRule    *mr = mod->sm_desc->ad_type->sat_equality;
324
325         /* delete the entire attribute */
326         if ( mod->sm_values == NULL ) {
327                 int rc = attr_delete( &e->e_attrs, mod->sm_desc );
328
329                 if ( rc ) {
330                         rc = LDAP_NO_SUCH_ATTRIBUTE;
331
332                 } else {
333                         *newlevel = 0;
334                         rc = LDAP_SUCCESS;
335                 }
336                 return rc;
337         }
338
339         rc = check_constraints( mod, &nl );
340         if ( rc != LDAP_SUCCESS ) {
341                 return rc;
342         }
343
344         *newlevel &= ~nl;
345
346         if ( mr == NULL || !mr->smr_match ) {
347                 /* disallow specific attributes from being deleted if
348                  * no equality rule */
349                 return LDAP_INAPPROPRIATE_MATCHING;
350         }
351
352         /* delete specific values - find the attribute first */
353         if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) {
354                 return( LDAP_NO_SUCH_ATTRIBUTE );
355         }
356
357         /* find each value to delete */
358         for ( i = 0; !BER_BVISNULL( &mod->sm_values[ i ] ); i++ ) {
359                 int rc;
360                 const char *text = NULL;
361
362                 struct berval asserted;
363
364                 rc = asserted_value_validate_normalize(
365                                 mod->sm_desc, mr, SLAP_MR_EQUALITY,
366                                 &mod->sm_values[ i ], &asserted, &text,
367                                 op->o_tmpmemctx );
368
369                 if( rc != LDAP_SUCCESS ) return rc;
370
371                 found = 0;
372                 for ( j = 0; !BER_BVISNULL( &a->a_vals[ j ] ); j++ ) {
373                         int match;
374                         int rc = value_match( &match, mod->sm_desc, mr,
375                                 0, &a->a_nvals[ j ], &asserted, &text );
376
377                         if( rc == LDAP_SUCCESS && match != 0 ) {
378                                 continue;
379                         }
380
381                         /* found a matching value */
382                         found = 1;
383
384                         /* delete it */
385                         if ( a->a_nvals != a->a_vals ) {
386                                 free( a->a_nvals[ j ].bv_val );
387                                 for ( k = j + 1; !BER_BVISNULL( &a->a_nvals[ k ] ); k++ ) {
388                                         a->a_nvals[ k - 1 ] = a->a_nvals[ k ];
389                                 }
390                                 BER_BVZERO( &a->a_nvals[ k - 1 ] );
391                         }
392
393                         free( a->a_vals[ j ].bv_val );
394                         for ( k = j + 1; !BER_BVISNULL( &a->a_vals[ k ] ); k++ ) {
395                                 a->a_vals[ k - 1 ] = a->a_vals[ k ];
396                         }
397                         BER_BVZERO( &a->a_vals[ k - 1 ] );
398                         a->a_numvals--;
399
400                         break;
401                 }
402
403                 free( asserted.bv_val );
404
405                 /* looked through them all w/o finding it */
406                 if ( ! found ) {
407                         return LDAP_NO_SUCH_ATTRIBUTE;
408                 }
409         }
410
411         /* if no values remain, delete the entire attribute */
412         if ( BER_BVISNULL( &a->a_vals[ 0 ] ) ) {
413                 assert( a->a_numvals == 0 );
414
415                 /* should already be zero */
416                 *newlevel = 0;
417                 
418                 if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) {
419                         return LDAP_NO_SUCH_ATTRIBUTE;
420                 }
421         }
422
423         return LDAP_SUCCESS;
424 }
425
426 static int
427 replace_values( Operation *op, Entry *e, Modification *mod, int *newlevel )
428 {
429         int rc;
430
431         if ( mod->sm_values != NULL ) {
432                 *newlevel = 0;
433                 rc = check_constraints( mod, newlevel );
434                 if ( rc != LDAP_SUCCESS ) {
435                         return rc;
436                 }
437         }
438
439         rc = attr_delete( &e->e_attrs, mod->sm_desc );
440
441         if ( rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_ATTRIBUTE ) {
442                 return rc;
443         }
444
445         if ( mod->sm_values != NULL ) {
446                 rc = attr_merge_normalize( e, mod->sm_desc, mod->sm_values,
447                                 op->o_tmpmemctx );
448                 if ( rc != LDAP_SUCCESS ) {
449                         return rc;
450                 }
451         }
452
453         return LDAP_SUCCESS;
454 }
455