xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/back-monitor/log.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
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