1 /* $NetBSD: log.c,v 1.2 2020/08/11 13:15:41 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-2020 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.2 2020/08/11 13:15:41 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 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 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, 0, 0 ); 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 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 modifersName 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 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 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 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 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