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