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