]> git.sur5r.net Git - openldap/blob - servers/slapd/back-monitor/log.c
import fix to back-monitor attribute normalization (ITS#3659)
[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-2005 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 /*
35  * log mutex
36  */
37 ldap_pvt_thread_mutex_t         monitor_log_mutex;
38
39 static struct {
40         int i;
41         struct berval s;
42         struct berval n;
43 } int_2_level[] = {
44         { LDAP_DEBUG_TRACE,     BER_BVC("Trace"),       BER_BVNULL },
45         { LDAP_DEBUG_PACKETS,   BER_BVC("Packets"),     BER_BVNULL },
46         { LDAP_DEBUG_ARGS,      BER_BVC("Args"),        BER_BVNULL },
47         { LDAP_DEBUG_CONNS,     BER_BVC("Conns"),       BER_BVNULL },
48         { LDAP_DEBUG_BER,       BER_BVC("BER"), BER_BVNULL },
49         { LDAP_DEBUG_FILTER,    BER_BVC("Filter"),      BER_BVNULL },
50         { LDAP_DEBUG_CONFIG,    BER_BVC("Config"),      BER_BVNULL },   /* useless */
51         { LDAP_DEBUG_ACL,       BER_BVC("ACL"), BER_BVNULL },
52         { LDAP_DEBUG_STATS,     BER_BVC("Stats"),       BER_BVNULL },
53         { LDAP_DEBUG_STATS2,    BER_BVC("Stats2"),      BER_BVNULL },
54         { LDAP_DEBUG_SHELL,     BER_BVC("Shell"),       BER_BVNULL },
55         { LDAP_DEBUG_PARSE,     BER_BVC("Parse"),       BER_BVNULL },
56         { LDAP_DEBUG_CACHE,     BER_BVC("Cache"),       BER_BVNULL },
57         { LDAP_DEBUG_INDEX,     BER_BVC("Index"),       BER_BVNULL },
58         { 0,                    BER_BVNULL,     BER_BVNULL }
59 };
60
61 static int loglevel2int( struct berval *l );
62 static int int2loglevel( int n );
63
64 static int add_values( Entry *e, Modification *mod, int *newlevel );
65 static int delete_values( Entry *e, Modification *mod, int *newlevel );
66 static int replace_values( Entry *e, Modification *mod, int *newlevel );
67
68 /*
69  * initializes log subentry
70  */
71 int
72 monitor_subsys_log_init(
73         BackendDB       *be
74 )
75 {
76         struct monitorinfo      *mi;
77         Entry                   *e;
78         int                     i;
79         struct berval           desc[] = {
80                 BER_BVC("This entry allows to set the log level runtime."),
81                 BER_BVC("Set the attribute 'managedInfo' to the desired log levels."),
82                 BER_BVNULL
83         };
84
85         ldap_pvt_thread_mutex_init( &monitor_log_mutex );
86
87         mi = ( struct monitorinfo * )be->be_private;
88
89         if ( monitor_cache_get( mi, &monitor_subsys[SLAPD_MONITOR_LOG].mss_ndn, 
90                                 &e ) ) {
91 #ifdef NEW_LOGGING
92                 LDAP_LOG( OPERATION, CRIT,
93                         "monitor_subsys_log_init: "
94                         "unable to get entry '%s'\n",
95                         monitor_subsys[SLAPD_MONITOR_LOG].mss_ndn.bv_val, 0, 0 );
96 #else
97                 Debug( LDAP_DEBUG_ANY,
98                         "monitor_subsys_log_init: "
99                         "unable to get entry '%s'\n%s%s",
100                         monitor_subsys[SLAPD_MONITOR_LOG].mss_ndn.bv_val, 
101                         "", "" );
102 #endif
103                 return( -1 );
104         }
105
106         /* initialize the debug level(s) */
107         for ( i = 0; int_2_level[ i ].i != 0; i++ ) {
108
109                 if ( mi->mi_ad_managedInfo->ad_type->sat_equality->smr_normalize ) {
110                         int     rc;
111
112                         rc = (*mi->mi_ad_managedInfo->ad_type->sat_equality->smr_normalize)(
113                                         SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
114                                         mi->mi_ad_managedInfo->ad_type->sat_syntax,
115                                         mi->mi_ad_managedInfo->ad_type->sat_equality,
116                                         &int_2_level[ i ].s,
117                                         &int_2_level[ i ].n, NULL );
118                         if ( rc ) {
119                                 return( -1 );
120                         }
121                 }
122
123                 if ( int_2_level[ i ].i & ldap_syslog ) {
124                         attr_merge_one( e, mi->mi_ad_managedInfo,
125                                         &int_2_level[ i ].s,
126                                         &int_2_level[ i ].n );
127                 }
128         }
129
130         attr_merge_normalize( e, mi->mi_ad_description, desc, NULL );
131
132         monitor_cache_release( mi, e );
133
134         return( 0 );
135 }
136
137 int 
138 monitor_subsys_log_modify( 
139         Operation               *op,
140         Entry                   *e
141 )
142 {
143         struct monitorinfo *mi = (struct monitorinfo *)op->o_bd->be_private;
144         int             rc = LDAP_OTHER;
145         int             newlevel = ldap_syslog;
146         Attribute       *save_attrs;
147         Modifications   *modlist = op->oq_modify.rs_modlist;
148         Modifications   *ml;
149
150         ldap_pvt_thread_mutex_lock( &monitor_log_mutex );
151
152         save_attrs = e->e_attrs;
153         e->e_attrs = attrs_dup( e->e_attrs );
154
155         for ( ml = modlist; ml != NULL; ml = ml->sml_next ) {
156                 Modification    *mod = &ml->sml_mod;
157
158                 /*
159                  * accept all operational attributes
160                  */
161                 if ( is_at_operational( mod->sm_desc->ad_type ) ) {
162                         ( void ) attr_delete( &e->e_attrs, mod->sm_desc );
163                         rc = attr_merge( e, mod->sm_desc, mod->sm_values, mod->sm_nvalues );
164                         if ( rc != 0 ) {
165                                 rc = LDAP_OTHER;
166                                 break;
167                         }
168                         continue;
169
170                 /*
171                  * only the monitor description attribute can be modified
172                  */
173                 } else if ( mod->sm_desc != mi->mi_ad_managedInfo) {
174                         rc = LDAP_UNWILLING_TO_PERFORM;
175                         break;
176                 }
177
178                 switch ( mod->sm_op ) {
179                 case LDAP_MOD_ADD:
180                         rc = add_values( e, mod, &newlevel );
181                         break;
182                         
183                 case LDAP_MOD_DELETE:
184                         rc = delete_values( e, mod, &newlevel );
185                         break;
186
187                 case LDAP_MOD_REPLACE:
188                         rc = replace_values( e, mod, &newlevel );
189                         break;
190
191                 default:
192                         rc = LDAP_OTHER;
193                         break;
194                 }
195
196                 if ( rc != LDAP_SUCCESS ) {
197                         break;
198                 }
199         }
200
201         /* set the new debug level */
202         if ( rc == LDAP_SUCCESS ) {
203                 const char      *text;
204                 static char     textbuf[ BACKMONITOR_BUFSIZE ];
205
206                 /* check for abandon */
207                 if ( op->o_abandon ) {
208                         rc = SLAPD_ABANDON;
209
210                         goto cleanup;
211                 }
212
213                 /* check that the entry still obeys the schema */
214                 rc = entry_schema_check( be_monitor, e, save_attrs, 
215                                 &text, textbuf, sizeof( textbuf ) );
216                 if ( rc != LDAP_SUCCESS ) {
217                         goto cleanup;
218                 }
219
220                 /*
221                  * Do we need to protect this with a mutex?
222                  */
223                 ldap_syslog = newlevel;
224
225 #if 0   /* debug rather than log */
226                 slap_debug = newlevel;
227                 lutil_set_debug_level( "slapd", slap_debug );
228                 ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &slap_debug);
229                 ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &slap_debug);
230                 ldif_debug = slap_debug;
231 #endif
232         }
233
234 cleanup:;
235         if ( rc == LDAP_SUCCESS ) {
236                 attrs_free( save_attrs );
237
238         } else {
239                 attrs_free( e->e_attrs );
240                 e->e_attrs = save_attrs;
241         }
242         
243         ldap_pvt_thread_mutex_unlock( &monitor_log_mutex );
244
245         return( rc );
246 }
247
248 static int
249 loglevel2int( struct berval *l )
250 {
251         int             i;
252         
253         for ( i = 0; int_2_level[ i ].i != 0; i++ ) {
254                 if ( l->bv_len != int_2_level[ i ].s.bv_len ) {
255                         continue;
256                 }
257
258                 if ( strcasecmp( l->bv_val, int_2_level[ i ].s.bv_val ) == 0 ) {
259                         return int_2_level[ i ].i;
260                 }
261         }
262
263         return 0;
264 }
265
266 static int
267 int2loglevel( int n )
268 {
269         int             i;
270         
271         for ( i = 0; int_2_level[ i ].i != 0; i++ ) {
272                 if ( int_2_level[ i ].i == n ) {
273                         return i;
274                 }
275         }
276
277         return -1;
278 }
279
280 static int
281 check_constraints( Modification *mod, int *newlevel )
282 {
283         int             i;
284
285         for ( i = 0; mod->sm_values && mod->sm_values[i].bv_val != NULL; i++ ) {
286                 int             l;
287                 
288                 l = loglevel2int( &mod->sm_values[i] );
289                 if ( !l ) {
290                         return LDAP_CONSTRAINT_VIOLATION;
291                 }
292
293                 if ( ( l = int2loglevel( l ) ) == -1 ) {
294                         return LDAP_OTHER;
295                 }
296
297                 assert( int_2_level[ l ].s.bv_len
298                                 == mod->sm_values[i].bv_len );
299                 
300                 AC_MEMCPY( mod->sm_values[i].bv_val,
301                                 int_2_level[ l ].s.bv_val,
302                                 int_2_level[ l ].s.bv_len );
303
304                 AC_MEMCPY( mod->sm_nvalues[i].bv_val,
305                                 int_2_level[ l ].n.bv_val,
306                                 int_2_level[ l ].n.bv_len );
307
308                 *newlevel |= l;
309         }
310
311         return LDAP_SUCCESS;
312 }       
313
314 static int 
315 add_values( Entry *e, Modification *mod, int *newlevel )
316 {
317         Attribute       *a;
318         int             i, rc;
319         MatchingRule    *mr = mod->sm_desc->ad_type->sat_equality;
320
321         rc = check_constraints( mod, newlevel );
322         if ( rc != LDAP_SUCCESS ) {
323                 return rc;
324         }
325
326         a = attr_find( e->e_attrs, mod->sm_desc );
327
328         if ( a != NULL ) {
329                 /* "description" SHOULD have appropriate rules ... */
330                 if ( mr == NULL || !mr->smr_match ) {
331                         return LDAP_INAPPROPRIATE_MATCHING;
332                 }
333
334                 for ( i = 0; mod->sm_values[i].bv_val != NULL; i++ ) {
335                         int rc;
336                         int j;
337                         const char *text = NULL;
338                         struct berval asserted;
339
340                         rc = asserted_value_validate_normalize(
341                                 mod->sm_desc, mr, SLAP_MR_EQUALITY,
342                                 &mod->sm_values[i], &asserted, &text, NULL );
343
344                         if ( rc != LDAP_SUCCESS ) {
345                                 return rc;
346                         }
347
348                         for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) {
349                                 int match;
350                                 int rc = value_match( &match, mod->sm_desc, mr,
351                                         0, &a->a_vals[j], &asserted, &text );
352
353                                 if ( rc == LDAP_SUCCESS && match == 0 ) {
354                                         free( asserted.bv_val );
355                                         return LDAP_TYPE_OR_VALUE_EXISTS;
356                                 }
357                         }
358
359                         free( asserted.bv_val );
360                 }
361         }
362
363         /* no - add them */
364         rc = attr_merge( e, mod->sm_desc, mod->sm_values, mod->sm_nvalues );
365         if ( rc != LDAP_SUCCESS ) {
366                 /* this should return result of attr_mergeit */
367                 return rc;
368         }
369
370         return LDAP_SUCCESS;
371 }
372
373 static int
374 delete_values( Entry *e, Modification *mod, int *newlevel )
375 {
376         int             i, j, k, found, rc, nl = 0;
377         Attribute       *a;
378         MatchingRule    *mr = mod->sm_desc->ad_type->sat_equality;
379
380         rc = check_constraints( mod, &nl );
381         if ( rc != LDAP_SUCCESS ) {
382                 return rc;
383         }
384
385         *newlevel &= ~nl;
386
387         /* delete the entire attribute */
388         if ( mod->sm_values == NULL ) {
389                 int rc = attr_delete( &e->e_attrs, mod->sm_desc );
390
391                 if ( rc ) {
392                         rc = LDAP_NO_SUCH_ATTRIBUTE;
393                 } else {
394                         *newlevel = 0;
395                         rc = LDAP_SUCCESS;
396                 }
397                 return rc;
398         }
399
400         if ( mr == NULL || !mr->smr_match ) {
401                 /* disallow specific attributes from being deleted if
402                  * no equality rule */
403                 return LDAP_INAPPROPRIATE_MATCHING;
404         }
405
406         /* delete specific values - find the attribute first */
407         if ( (a = attr_find( e->e_attrs, mod->sm_desc )) == NULL ) {
408                 return( LDAP_NO_SUCH_ATTRIBUTE );
409         }
410
411         /* find each value to delete */
412         for ( i = 0; mod->sm_values[i].bv_val != NULL; i++ ) {
413                 int rc;
414                 const char *text = NULL;
415
416                 struct berval asserted;
417
418                 rc = asserted_value_validate_normalize(
419                                 mod->sm_desc, mr, SLAP_MR_EQUALITY,
420                                 &mod->sm_values[i], &asserted, &text, NULL );
421
422                 if( rc != LDAP_SUCCESS ) return rc;
423
424                 found = 0;
425                 for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) {
426                         int match;
427                         int rc = value_match( &match, mod->sm_desc, mr,
428                                 0,
429                                 &a->a_vals[j], &asserted, &text );
430
431                         if( rc == LDAP_SUCCESS && match != 0 ) {
432                                 continue;
433                         }
434
435                         /* found a matching value */
436                         found = 1;
437
438                         /* delete it */
439                         free( a->a_vals[j].bv_val );
440                         for ( k = j + 1; a->a_vals[k].bv_val != NULL; k++ ) {
441                                 a->a_vals[k - 1] = a->a_vals[k];
442                         }
443                         a->a_vals[k - 1].bv_val = NULL;
444
445                         break;
446                 }
447
448                 free( asserted.bv_val );
449
450                 /* looked through them all w/o finding it */
451                 if ( ! found ) {
452                         return LDAP_NO_SUCH_ATTRIBUTE;
453                 }
454         }
455
456         /* if no values remain, delete the entire attribute */
457         if ( a->a_vals[0].bv_val == NULL ) {
458                 /* should already be zero */
459                 *newlevel = 0;
460                 
461                 if ( attr_delete( &e->e_attrs, mod->sm_desc ) ) {
462                         return LDAP_NO_SUCH_ATTRIBUTE;
463                 }
464         }
465
466         return LDAP_SUCCESS;
467 }
468
469 static int
470 replace_values( Entry *e, Modification *mod, int *newlevel )
471 {
472         int rc;
473
474         *newlevel = 0;
475         rc = check_constraints( mod, newlevel );
476         if ( rc != LDAP_SUCCESS ) {
477                 return rc;
478         }
479
480         rc = attr_delete( &e->e_attrs, mod->sm_desc );
481
482         if ( rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_ATTRIBUTE ) {
483                 return rc;
484         }
485
486         if ( mod->sm_values != NULL ) {
487                 rc = attr_merge( e, mod->sm_desc, mod->sm_values, mod->sm_nvalues );
488                 if ( rc != LDAP_SUCCESS ) {
489                         return rc;
490                 }
491         }
492
493         return LDAP_SUCCESS;
494 }
495