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