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