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