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