X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Foverlays%2Faccesslog.c;h=25adbe0f438d8f8e7fa22c311962388830710a45;hb=a47ef8d2b77192a2a9ee1d079393fd6a84e25278;hp=866afd7937763176ed0d5a3e81b3294c979df05a;hpb=92d39f73769040682f708d2ae49d4f630381ba9d;p=openldap diff --git a/servers/slapd/overlays/accesslog.c b/servers/slapd/overlays/accesslog.c index 866afd7937..25adbe0f43 100644 --- a/servers/slapd/overlays/accesslog.c +++ b/servers/slapd/overlays/accesslog.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2005-2008 The OpenLDAP Foundation. + * Copyright 2005-2012 The OpenLDAP Foundation. * Portions copyright 2004-2005 Symas Corporation. * All rights reserved. * @@ -56,6 +56,13 @@ typedef struct log_attr { AttributeDescription *attr; } log_attr; +typedef struct log_base { + struct log_base *lb_next; + slap_mask_t lb_ops; + struct berval lb_base; + struct berval lb_line; +} log_base; + typedef struct log_info { BackendDB *li_db; struct berval li_db_suffix; @@ -66,7 +73,9 @@ typedef struct log_info { Filter *li_oldf; Entry *li_old; log_attr *li_oldattrs; + struct berval li_uuid; int li_success; + log_base *li_bases; ldap_pvt_thread_rmutex_t li_op_rmutex; ldap_pvt_thread_mutex_t li_log_mutex; } log_info; @@ -79,7 +88,8 @@ enum { LOG_PURGE, LOG_SUCCESS, LOG_OLD, - LOG_OLDATTR + LOG_OLDATTR, + LOG_BASE }; static ConfigTable log_cfats[] = { @@ -110,6 +120,12 @@ static ConfigTable log_cfats[] = { "DESC 'Log old values of these attributes even if unmodified' " "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString )", NULL, NULL }, + { "logbase", "op|writes|reads|session|all< = 0 && len < size ); + assert( len >= 0 && (unsigned) len < size ); size -= len; ptr += len; } len = snprintf( ptr, size, "%02d:%02d", hh, mm ); - assert( len >= 0 && len < size ); + assert( len >= 0 && (unsigned) len < size ); size -= len; ptr += len; if ( ss ) { len = snprintf( ptr, size, ":%02d", ss ); - assert( len >= 0 && len < size ); + assert( len >= 0 && (unsigned) len < size ); size -= len; ptr += len; } @@ -580,11 +606,12 @@ log_old_lookup( Operation *op, SlapReply *rs ) a = attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_entryCSN ); if ( a ) { - int len = a->a_vals[0].bv_len; - if ( len > pd->csn.bv_len ) - len = pd->csn.bv_len; - if ( memcmp( a->a_vals[0].bv_val, pd->csn.bv_val, len ) > 0 ) { - AC_MEMCPY( pd->csn.bv_val, a->a_vals[0].bv_val, len ); + ber_len_t len = a->a_nvals[0].bv_len; + /* Paranoid len check, normalized CSNs are always the same length */ + if ( len > LDAP_PVT_CSNSTR_BUFSIZE ) + len = LDAP_PVT_CSNSTR_BUFSIZE; + if ( memcmp( a->a_nvals[0].bv_val, pd->csn.bv_val, len ) > 0 ) { + AC_MEMCPY( pd->csn.bv_val, a->a_nvals[0].bv_val, len ); pd->csn.bv_len = len; } } @@ -615,7 +642,7 @@ accesslog_purge( void *ctx, void *arg ) AttributeAssertion ava = ATTRIBUTEASSERTION_INIT; purge_data pd = {0}; char timebuf[LDAP_LUTIL_GENTIME_BUFSIZE]; - char csnbuf[LDAP_LUTIL_CSNSTR_BUFSIZE]; + char csnbuf[LDAP_PVT_CSNSTR_BUFSIZE]; time_t old = slap_get_time(); connection_fake_init( &conn, &opbuf, ctx ); @@ -663,12 +690,15 @@ accesslog_purge( void *ctx, void *arg ) op->o_tag = LDAP_REQ_DELETE; op->o_callback = &nullsc; op->o_csn = pd.csn; + op->o_dont_replicate = 1; for (i=0; io_req_dn = pd.dn[i]; op->o_req_ndn = pd.ndn[i]; - if ( !slapd_shutdown ) + if ( !slapd_shutdown ) { + rs_reinit( &rs, REP_RESULT ); op->o_bd->be_delete( op, &rs ); + } ch_free( pd.ndn[i].bv_val ); ch_free( pd.dn[i].bv_val ); } @@ -678,6 +708,7 @@ accesslog_purge( void *ctx, void *arg ) { Modifications mod; struct berval bv[2]; + rs_reinit( &rs, REP_RESULT ); /* update context's entryCSN to reflect oldest CSN */ mod.sml_numvals = 1; mod.sml_values = bv; @@ -780,6 +811,16 @@ log_cf_gen(ConfigArgs *c) else rc = 1; break; + case LOG_BASE: + if ( li->li_bases ) { + log_base *lb; + + for ( lb = li->li_bases; lb; lb=lb->lb_next ) + value_add_one( &c->rvalue_vals, &lb->lb_line ); + } + else + rc = 1; + break; } break; case LDAP_MOD_DELETE: @@ -838,6 +879,26 @@ log_cf_gen(ConfigArgs *c) ch_free( la ); } break; + case LOG_BASE: + if ( c->valx < 0 ) { + log_base *lb, *ln; + + for ( lb = li->li_bases; lb; lb = ln ) { + ln = lb->lb_next; + ch_free( lb ); + } + } else { + log_base *lb = NULL, **lp; + int i; + + for ( lp = &li->li_bases, i=0; i < c->valx; i++ ) { + lb = *lp; + lp = &lb->lb_next; + } + *lp = lb->lb_next; + ch_free( lb ); + } + break; } break; default: @@ -921,6 +982,47 @@ log_cf_gen(ConfigArgs *c) } } break; + case LOG_BASE: { + slap_mask_t m = 0; + rc = verbstring_to_mask( logops, c->argv[1], '|', &m ); + if ( rc == 0 ) { + struct berval dn, ndn; + ber_str2bv( c->argv[2], 0, 0, &dn ); + rc = dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL ); + if ( rc == 0 ) { + log_base *lb; + struct berval mbv; + char *ptr; + mask_to_verbstring( logops, m, '|', &mbv ); + lb = ch_malloc( sizeof( log_base ) + mbv.bv_len + ndn.bv_len + 3 + 1 ); + lb->lb_line.bv_val = (char *)(lb + 1); + lb->lb_line.bv_len = mbv.bv_len + ndn.bv_len + 3; + ptr = lutil_strcopy( lb->lb_line.bv_val, mbv.bv_val ); + *ptr++ = ' '; + *ptr++ = '"'; + lb->lb_base.bv_val = ptr; + lb->lb_base.bv_len = ndn.bv_len; + ptr = lutil_strcopy( ptr, ndn.bv_val ); + *ptr++ = '"'; + lb->lb_ops = m; + lb->lb_next = li->li_bases; + li->li_bases = lb; + } else { + snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s invalid DN: %s", + c->argv[0], c->argv[2] ); + Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, + "%s: %s\n", c->log, c->cr_msg, 0 ); + rc = ARG_BAD_CONF; + } + } else { + snprintf( c->cr_msg, sizeof( c->cr_msg ), "%s invalid ops: %s", + c->argv[0], c->argv[1] ); + Debug( LDAP_DEBUG_CONFIG|LDAP_DEBUG_NONE, + "%s: %s\n", c->log, c->cr_msg, 0 ); + rc = ARG_BAD_CONF; + } + } + break; } break; } @@ -933,7 +1035,7 @@ logSchemaControlValidate( struct berval *valp ) { struct berval val, bv; - int i; + ber_len_t i; int rc = LDAP_SUCCESS; assert( valp != NULL ); @@ -1046,6 +1148,8 @@ logSchemaControlValidate( /* extract and check controlValue */ if ( strncasecmp( &val.bv_val[ i ], "controlValue ", STRLENOF( "controlValue " ) ) == 0 ) { + ber_len_t valueStart, valueLen; + i += STRLENOF( "controlValue " ); for ( ; i < val.bv_len; i++ ) { if ( !ASCII_SPACE( val.bv_val[ i ] ) ) { @@ -1061,6 +1165,9 @@ logSchemaControlValidate( return LDAP_INVALID_SYNTAX; } + i++; + valueStart = i; + for ( ; i < val.bv_len; i++ ) { if ( val.bv_val[ i ] == '"' ) { break; @@ -1075,7 +1182,12 @@ logSchemaControlValidate( return LDAP_INVALID_SYNTAX; } - for ( ; i < val.bv_len; i++ ) { + valueLen = i - valueStart; + if ( (valueLen/2)*2 != valueLen ) { + return LDAP_INVALID_SYNTAX; + } + + for ( i++; i < val.bv_len; i++ ) { if ( !ASCII_SPACE( val.bv_val[ i ] ) ) { break; } @@ -1155,28 +1267,12 @@ accesslog_ctrls( } if ( !BER_BVISNULL( &ctrls[ i ]->ldctl_value ) ) { - int j; + ber_len_t j; ptr = lutil_strcopy( ptr, " controlValue \"" ); - for ( j = 0; j < ctrls[ i ]->ldctl_value.bv_len; j++ ) - { - unsigned char o; - - o = ( ( ctrls[ i ]->ldctl_value.bv_val[ j ] >> 4 ) & 0xF ); - if ( o < 10 ) { - *ptr++ = '0' + o; - - } else { - *ptr++ = 'A' + o; - } - - o = ( ctrls[ i ]->ldctl_value.bv_val[ j ] & 0xF ); - if ( o < 10 ) { - *ptr++ = '0' + o; - - } else { - *ptr++ = 'A' + o; - } + for ( j = 0; j < ctrls[ i ]->ldctl_value.bv_len; j++ ) { + *ptr++ = SLAP_ESCAPE_HI(ctrls[ i ]->ldctl_value.bv_val[ j ]); + *ptr++ = SLAP_ESCAPE_LO(ctrls[ i ]->ldctl_value.bv_val[ j ]); } *ptr++ = '"'; @@ -1260,7 +1356,7 @@ static Entry *accesslog_entry( Operation *op, SlapReply *rs, int logop, } rdn.bv_len = snprintf( rdn.bv_val, sizeof( rdnbuf ), "%lu", op->o_connid ); - if ( rdn.bv_len >= 0 || rdn.bv_len < sizeof( rdnbuf ) ) { + if ( rdn.bv_len < sizeof( rdnbuf ) ) { attr_merge_one( e, ad_reqSession, &rdn, NULL ); } /* else? */ @@ -1341,11 +1437,11 @@ static int accesslog_response(Operation *op, SlapReply *rs) { log_info *li = on->on_bi.bi_private; Attribute *a, *last_attr; Modifications *m; - struct berval *b; + struct berval *b, uuid = BER_BVNULL; int i; int logop; slap_verbmasks *lo; - Entry *e = NULL, *old = NULL; + Entry *e = NULL, *old = NULL, *e_uuid = NULL; char timebuf[LDAP_LUTIL_GENTIME_BUFSIZE+8]; struct berval bv; char *ptr; @@ -1370,14 +1466,31 @@ static int accesslog_response(Operation *op, SlapReply *rs) { } /* Unbind and Abandon never reach here */ lo = logops+logop+EN_OFFSET; - if ( !( li->li_ops & lo->mask )) - return SLAP_CB_CONTINUE; + if ( !( li->li_ops & lo->mask )) { + log_base *lb; + + i = 0; + for ( lb = li->li_bases; lb; lb=lb->lb_next ) + if (( lb->lb_ops & lo->mask ) && dnIsSuffix( &op->o_req_ndn, &lb->lb_base )) { + i = 1; + break; + } + if ( !i ) + return SLAP_CB_CONTINUE; + } if ( lo->mask & LOG_OP_WRITES ) { slap_callback *cb; + + /* These internal ops are not logged */ + if ( op->o_dont_replicate && op->orm_no_opattrs ) + return SLAP_CB_CONTINUE; + ldap_pvt_thread_mutex_lock( &li->li_log_mutex ); old = li->li_old; + uuid = li->li_uuid; li->li_old = NULL; + BER_BVZERO( &li->li_uuid ); /* Disarm mod_cleanup */ for ( cb = op->o_callback; cb; cb = cb->sc_next ) { if ( cb->sc_private == (void *)on ) { @@ -1400,13 +1513,14 @@ static int accesslog_response(Operation *op, SlapReply *rs) { attr_merge_one( e, ad_reqMessage, &bv, NULL ); } bv.bv_len = snprintf( timebuf, sizeof( timebuf ), "%d", rs->sr_err ); - if ( bv.bv_len >= 0 && bv.bv_len < sizeof( timebuf ) ) { + if ( bv.bv_len < sizeof( timebuf ) ) { bv.bv_val = timebuf; attr_merge_one( e, ad_reqResult, &bv, NULL ); } last_attr = attr_find( e->e_attrs, ad_reqResult ); + e_uuid = old; switch( logop ) { case LOG_EN_ADD: case LOG_EN_DELETE: { @@ -1415,7 +1529,9 @@ static int accesslog_response(Operation *op, SlapReply *rs) { if ( logop == LOG_EN_ADD ) { e2 = op->ora_e; + e_uuid = op->ora_e; c_op = '+'; + } else { if ( !old ) break; @@ -1551,22 +1667,24 @@ static int accesslog_response(Operation *op, SlapReply *rs) { i += a->a_numvals; } } - vals = ch_malloc( (i + 1) * sizeof( struct berval ) ); - i = 0; - for ( a=old->e_attrs; a; a=a->a_next ) { - if ( a->a_vals && a->a_flags ) { - for (b=a->a_vals; !BER_BVISNULL( b ); b++,i++) { - accesslog_val2val( a->a_desc, b, 0, &vals[i] ); + if ( i ) { + vals = ch_malloc( (i + 1) * sizeof( struct berval ) ); + i = 0; + for ( a=old->e_attrs; a; a=a->a_next ) { + if ( a->a_vals && a->a_flags ) { + for (b=a->a_vals; !BER_BVISNULL( b ); b++,i++) { + accesslog_val2val( a->a_desc, b, 0, &vals[i] ); + } } } + vals[i].bv_val = NULL; + vals[i].bv_len = 0; + a = attr_alloc( ad_reqOld ); + a->a_numvals = i; + a->a_vals = vals; + a->a_nvals = vals; + last_attr->a_next = a; } - vals[i].bv_val = NULL; - vals[i].bv_len = 0; - a = attr_alloc( ad_reqOld ); - a->a_numvals = i; - a->a_vals = vals; - a->a_nvals = vals; - last_attr->a_next = a; } if ( logop == LOG_EN_MODIFY ) { break; @@ -1603,31 +1721,35 @@ static int accesslog_response(Operation *op, SlapReply *rs) { if ( !BER_BVISEMPTY( &op->ors_filterstr )) attr_merge_one( e, ad_reqFilter, &op->ors_filterstr, NULL ); if ( op->ors_attrs ) { + int j; /* count them */ for (i=0; !BER_BVISNULL(&op->ors_attrs[i].an_name );i++) ; vals = op->o_tmpalloc( (i+1) * sizeof(struct berval), op->o_tmpmemctx ); - for (i=0; !BER_BVISNULL(&op->ors_attrs[i].an_name );i++) - vals[i] = op->ors_attrs[i].an_name; - vals[i].bv_val = NULL; - vals[i].bv_len = 0; + for (i=0, j=0; !BER_BVISNULL(&op->ors_attrs[i].an_name );i++) { + if (!BER_BVISEMPTY(&op->ors_attrs[i].an_name)) { + vals[j] = op->ors_attrs[i].an_name; + j++; + } + } + BER_BVZERO(&vals[j]); attr_merge( e, ad_reqAttr, vals, NULL ); op->o_tmpfree( vals, op->o_tmpmemctx ); } bv.bv_val = timebuf; bv.bv_len = snprintf( bv.bv_val, sizeof( timebuf ), "%d", rs->sr_nentries ); - if ( bv.bv_len >= 0 && bv.bv_len < sizeof( timebuf ) ) { + if ( bv.bv_len < sizeof( timebuf ) ) { attr_merge_one( e, ad_reqEntries, &bv, NULL ); } /* else? */ bv.bv_len = snprintf( bv.bv_val, sizeof( timebuf ), "%d", op->ors_tlimit ); - if ( bv.bv_len >= 0 && bv.bv_len < sizeof( timebuf ) ) { + if ( bv.bv_len < sizeof( timebuf ) ) { attr_merge_one( e, ad_reqTimeLimit, &bv, NULL ); } /* else? */ bv.bv_len = snprintf( bv.bv_val, sizeof( timebuf ), "%d", op->ors_slimit ); - if ( bv.bv_len >= 0 && bv.bv_len < sizeof( timebuf ) ) { + if ( bv.bv_len < sizeof( timebuf ) ) { attr_merge_one( e, ad_reqSizeLimit, &bv, NULL ); } /* else? */ break; @@ -1635,7 +1757,7 @@ static int accesslog_response(Operation *op, SlapReply *rs) { case LOG_EN_BIND: bv.bv_val = timebuf; bv.bv_len = snprintf( bv.bv_val, sizeof( timebuf ), "%d", op->o_protocol ); - if ( bv.bv_len >= 0 && bv.bv_len < sizeof( timebuf ) ) { + if ( bv.bv_len < sizeof( timebuf ) ) { attr_merge_one( e, ad_reqVersion, &bv, NULL ); } /* else? */ if ( op->orb_method == LDAP_AUTH_SIMPLE ) { @@ -1664,6 +1786,29 @@ static int accesslog_response(Operation *op, SlapReply *rs) { break; } + if ( e_uuid || !BER_BVISNULL( &uuid ) ) { + struct berval *pbv; + + if ( !BER_BVISNULL( &uuid ) ) { + pbv = &uuid; + + } else { + a = attr_find( e_uuid->e_attrs, slap_schema.si_ad_entryUUID ); + if ( a ) { + pbv = &a->a_vals[0]; + } + } + + if ( pbv ) { + attr_merge_normalize_one( e, ad_reqEntryUUID, pbv, op->o_tmpmemctx ); + } + + if ( !BER_BVISNULL( &uuid ) ) { + ber_memfree( uuid.bv_val ); + BER_BVZERO( &uuid ); + } + } + op2.o_hdr = op->o_hdr; op2.o_tag = LDAP_REQ_ADD; op2.o_bd = li->li_db; @@ -1753,8 +1898,25 @@ accesslog_op_mod( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; log_info *li = on->on_bi.bi_private; + int doit = 0; + + /* These internal ops are not logged */ + if ( op->o_dont_replicate && op->orm_no_opattrs ) + return SLAP_CB_CONTINUE; + if ( li->li_ops & LOG_OP_WRITES ) { + doit = 1; + } else { + log_base *lb; + for ( lb = li->li_bases; lb; lb = lb->lb_next ) + if (( lb->lb_ops & LOG_OP_WRITES ) && dnIsSuffix( &op->o_req_ndn, &lb->lb_base )) { + doit = 1; + break; + } + } + + if ( doit ) { slap_callback *cb = op->o_tmpalloc( sizeof( slap_callback ), op->o_tmpmemctx ), *cb2; cb->sc_cleanup = accesslog_mod_cleanup; cb->sc_response = NULL; @@ -1766,11 +1928,12 @@ accesslog_op_mod( Operation *op, SlapReply *rs ) ldap_pvt_thread_rmutex_lock( &li->li_op_rmutex, op->o_tid ); if ( li->li_oldf && ( op->o_tag == LDAP_REQ_DELETE || op->o_tag == LDAP_REQ_MODIFY || - ( op->o_tag == LDAP_REQ_MODRDN && li->li_oldattrs ))) { + ( op->o_tag == LDAP_REQ_MODRDN && li->li_oldattrs ))) + { int rc; Entry *e; - op->o_bd->bd_info = on->on_info->oi_orig; + op->o_bd->bd_info = (BackendInfo *)on->on_info; rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &e ); if ( e ) { if ( test_filter( op, e, li->li_oldf ) == LDAP_COMPARE_TRUE ) @@ -1778,6 +1941,21 @@ accesslog_op_mod( Operation *op, SlapReply *rs ) be_entry_release_rw( op, e, 0 ); } op->o_bd->bd_info = (BackendInfo *)on; + + } else { + int rc; + Entry *e; + + op->o_bd->bd_info = (BackendInfo *)on->on_info; + rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &e ); + if ( e ) { + Attribute *a = attr_find( e->e_attrs, slap_schema.si_ad_entryUUID ); + if ( a ) { + ber_dupbv( &li->li_uuid, &a->a_vals[0] ); + } + be_entry_release_rw( op, e, 0 ); + } + op->o_bd->bd_info = (BackendInfo *)on; } } return SLAP_CB_CONTINUE; @@ -1797,8 +1975,18 @@ accesslog_unbind( Operation *op, SlapReply *rs ) SlapReply rs2 = {REP_RESULT}; Entry *e; - if ( !( li->li_ops & LOG_OP_UNBIND )) - return SLAP_CB_CONTINUE; + if ( !( li->li_ops & LOG_OP_UNBIND )) { + log_base *lb; + int i = 0; + + for ( lb = li->li_bases; lb; lb=lb->lb_next ) + if (( lb->lb_ops & LOG_OP_UNBIND ) && dnIsSuffix( &op->o_ndn, &lb->lb_base )) { + i = 1; + break; + } + if ( !i ) + return SLAP_CB_CONTINUE; + } e = accesslog_entry( op, rs, LOG_EN_UNBIND, &op2 ); op2.o_hdr = op->o_hdr; @@ -1832,13 +2020,26 @@ accesslog_abandon( Operation *op, SlapReply *rs ) char buf[64]; struct berval bv; - if ( !op->o_time || !( li->li_ops & LOG_OP_ABANDON )) + if ( !op->o_time ) return SLAP_CB_CONTINUE; + if ( !( li->li_ops & LOG_OP_ABANDON )) { + log_base *lb; + int i = 0; + + for ( lb = li->li_bases; lb; lb=lb->lb_next ) + if (( lb->lb_ops & LOG_OP_ABANDON ) && dnIsSuffix( &op->o_ndn, &lb->lb_base )) { + i = 1; + break; + } + if ( !i ) + return SLAP_CB_CONTINUE; + } + e = accesslog_entry( op, rs, LOG_EN_ABANDON, &op2 ); bv.bv_val = buf; bv.bv_len = snprintf( buf, sizeof( buf ), "%d", op->orn_msgid ); - if ( bv.bv_len >= 0 && bv.bv_len < sizeof( buf ) ) { + if ( bv.bv_len < sizeof( buf ) ) { attr_merge_one( e, ad_reqId, &bv, NULL ); } /* else? */ @@ -1964,6 +2165,7 @@ accesslog_db_root( AttributeDescription *ad = NULL; const char *text = NULL; Entry *e_ctx; + BackendDB db; e = entry_alloc(); ber_dupbv( &e->e_name, li->li_db->be_suffix ); @@ -2008,7 +2210,8 @@ accesslog_db_root( } be_entry_release_rw( op, e_ctx, 0 ); } - op->o_bd = li->li_db; + db = *li->li_db; + op->o_bd = &db; op->ora_e = e; op->o_req_dn = e->e_name; @@ -2016,7 +2219,6 @@ accesslog_db_root( op->o_callback = &nullsc; SLAP_DBFLAGS( op->o_bd ) |= SLAP_DBFLAG_NOLASTMOD; rc = op->o_bd->be_add( op, &rs ); - SLAP_DBFLAGS( op->o_bd ) ^= SLAP_DBFLAG_NOLASTMOD; if ( e == op->ora_e ) entry_free( e ); }