From 61bd10ea850847150449ab8529d490f975faf3da Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Tue, 9 May 2006 19:43:11 +0000 Subject: [PATCH] More changes suggested by Quanah + Added slapd syncrepl mandatory searchbase check + Fixed slapo-accesslog bugs + Added slapo-accesslog oldReq feature + Fixed slapo ppolicy BER tags + Fixed slapo-auditlog missing return codes + Fixed slurpd potential overflow issue + Fixed slapo-translucent modifications + Fixed libldap_r thread debug missing break --- CHANGES | 8 ++ doc/man/man5/slapo-accesslog.5 | 20 ++- libraries/libldap/ppolicy.c | 9 +- libraries/libldap_r/thr_debug.c | 1 + servers/slapd/overlays/accesslog.c | 203 ++++++++++++++++++++------- servers/slapd/overlays/auditlog.c | 2 + servers/slapd/overlays/ppolicy.c | 9 +- servers/slapd/overlays/translucent.c | 5 +- servers/slapd/syncrepl.c | 9 +- servers/slurpd/st.c | 5 +- 10 files changed, 204 insertions(+), 67 deletions(-) diff --git a/CHANGES b/CHANGES index 4c1daca36e..0f089cdb5e 100644 --- a/CHANGES +++ b/CHANGES @@ -11,6 +11,14 @@ OpenLDAP 2.3.22 Engineering Fixed slapd thread pool init issue (ITS#4513) Fixed slapd cn=config olcLimits (ITS#4515) Fixed slapd runqueue use of freed memory (ITS#4517) + Added slapd syncrepl mandatory searchbase check + Fixed slapo-accesslog bugs + Added slapo-accesslog oldReq feature + Fixed slapo ppolicy BER tags + Fixed slapo-auditlog missing return codes + Fixed slurpd potential overflow issue + Fixed slapo-translucent modifications + Fixed libldap_r thread debug missing break OpenLDAP 2.3.21 Release Fixed libldap referral chasing issue (ITS#4448) diff --git a/doc/man/man5/slapo-accesslog.5 b/doc/man/man5/slapo-accesslog.5 index 2a28cd82a4..1c2d6cfe12 100644 --- a/doc/man/man5/slapo-accesslog.5 +++ b/doc/man/man5/slapo-accesslog.5 @@ -49,6 +49,11 @@ abandon, bind, unbind all operations .RE .TP +.B logold +Specify a filter for matching against Deleted and Modified entries. If +the entry matches the filter, the old contents of the entry will be +logged along with the current request. +.TP .B logpurge Specify the maximum age for log entries to be retained in the database, and how often to scan the database for old entries. Both the @@ -94,6 +99,7 @@ succeed or not. The default is FALSE. overlay accesslog logdb cn=log logops writes reads + logold (objectclass=person) .fi .SH SCHEMA @@ -310,7 +316,12 @@ to its deletion. The values are formatted as attribute: value .RE .PD -This option is not yet implemented. +The +.B reqOld +attribute is only populated if the entry being deleted matches the +configured +.B logold +filter. .LP .RS 4 @@ -329,7 +340,12 @@ attribute, which was already described above in the Add operation. It may optionally contain the previous contents of any modified attributes in the .B reqOld attribute, using the same format as described above for the Delete operation. -This option is not yet implemented. +The +.B reqOld +attribute is only populated if the entry being modified matches the +configured +.B logold +filter. .LP .RS 4 diff --git a/libraries/libldap/ppolicy.c b/libraries/libldap/ppolicy.c index dd21aa99d5..11a5a3b1a4 100644 --- a/libraries/libldap/ppolicy.c +++ b/libraries/libldap/ppolicy.c @@ -31,11 +31,12 @@ #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST -#define PPOLICY_WARNING 0xa0L -#define PPOLICY_ERROR 0xa1L +/* IMPLICIT TAGS, all context-specific */ +#define PPOLICY_WARNING 0xa0L /* constructed + 0 */ +#define PPOLICY_ERROR 0x81L /* primitive + 1 */ -#define PPOLICY_EXPIRE 0xa0L -#define PPOLICY_GRACE 0xa1L +#define PPOLICY_EXPIRE 0x80L /* primitive + 0 */ +#define PPOLICY_GRACE 0x81L /* primitive + 1 */ /*--- ldap_create_passwordpolicy_control diff --git a/libraries/libldap_r/thr_debug.c b/libraries/libldap_r/thr_debug.c index fac64616eb..f43c61e7fa 100644 --- a/libraries/libldap_r/thr_debug.c +++ b/libraries/libldap_r/thr_debug.c @@ -455,6 +455,7 @@ adjust_count( int which, int adjust ) resource_counts[which] += adjust; rc = ldap_int_thread_mutex_unlock( &resource_mutexes[which] ); assert( rc == 0 ); + break; case Count_reported: fputs( "...more ldap_debug_thread activity after exit...\n", stderr ); count = Count_reported_more; diff --git a/servers/slapd/overlays/accesslog.c b/servers/slapd/overlays/accesslog.c index bd61096dbb..c0454cf200 100644 --- a/servers/slapd/overlays/accesslog.c +++ b/servers/slapd/overlays/accesslog.c @@ -57,6 +57,8 @@ typedef struct log_info { int li_age; int li_cycle; struct re_s *li_task; + Filter *li_oldf; + Entry *li_old; int li_success; ldap_pvt_thread_mutex_t li_op_mutex; ldap_pvt_thread_mutex_t li_log_mutex; @@ -68,7 +70,8 @@ enum { LOG_DB = 1, LOG_OPS, LOG_PURGE, - LOG_SUCCESS + LOG_SUCCESS, + LOG_OLD }; static ConfigTable log_cfats[] = { @@ -90,6 +93,10 @@ static ConfigTable log_cfats[] = { log_cf_gen, "( OLcfgOvAt:4.4 NAME 'olcAccessLogSuccess' " "DESC 'Log successful ops only' " "SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL }, + { "logold", "filter", 2, 2, 0, ARG_MAGIC|LOG_OLD, + log_cf_gen, "( OLcfgOvAt:4.5 NAME 'olcAccessLogOld' " + "DESC 'Log old values when modifying entries matching the filter' " + "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL }, { NULL } }; @@ -99,7 +106,8 @@ static ConfigOCs log_cfocs[] = { "DESC 'Access log configuration' " "SUP olcOverlayConfig " "MUST olcAccessLogDB " - "MAY ( olcAccessLogOps $ olcAccessLogPurge $ olcAccessLogSuccess ) )", + "MAY ( olcAccessLogOps $ olcAccessLogPurge $ olcAccessLogSuccess $ " + "olcAccessLogOld ) )", Cft_Overlay, log_cfats }, { NULL } }; @@ -396,29 +404,29 @@ log_age_parse(char *agestr) return -1; t1 *= 24; gotdays = 1; - } else if ( *endptr != ':' ) { - /* No valid delimiter found, fail */ - return -1; + agestr = endptr + 1; + } else { + if ( agestr[2] != ':' ) { + /* No valid delimiter found, fail */ + return -1; + } + t1 *= 60; + agestr += 3; } - agestr += 3; t2 = atoi( agestr ); - - /* if there's a delimiter, it can only be a colon */ - if ( agestr[2] && agestr[2] != ':' ) - return -1; - - /* If we're at the end of the string, and we started with days, - * fail because we expected to find minutes too. - */ - if ( gotdays && !agestr[2] ) - return -1; - - t1 *= 60; t1 += t2; - if ( !agestr[2] ) - return t1 * 60; + if ( agestr[2] ) { + /* if there's a delimiter, it can only be a colon */ + if ( agestr[2] != ':' ) + return -1; + } else { + /* If we're at the end of the string, and we started with days, + * fail because we expected to find minutes too. + */ + return gotdays ? -1 : t1 * 60; + } agestr += 3; t2 = atoi( agestr ); @@ -429,12 +437,15 @@ log_age_parse(char *agestr) t1 *= 60; t1 += t2; - t1 *= 60; if ( agestr[2] ) { agestr += 3; if ( agestr[2] ) return -1; + t1 *= 60; t1 += atoi( agestr ); + } else if ( gotdays ) { + /* only got days+hh:mm */ + t1 *= 60; } return t1; } @@ -449,7 +460,7 @@ log_age_unparse( int age, struct berval *agebv ) age /= 60; mm = age % 60; age /= 60; - hh = age % 60; + hh = age % 24; age /= 24; dd = age; @@ -605,6 +616,14 @@ log_cf_gen(ConfigArgs *c) else rc = 1; break; + case LOG_OLD: + if ( li->li_oldf ) { + filter2bv( li->li_oldf, &agebv ); + value_add_one( &c->rvalue_vals, &agebv ); + } + else + rc = 1; + break; } break; case LDAP_MOD_DELETE: @@ -635,6 +654,12 @@ log_cf_gen(ConfigArgs *c) case LOG_SUCCESS: li->li_success = 0; break; + case LOG_OLD: + if ( li->li_oldf ) { + filter_free( li->li_oldf ); + li->li_oldf = NULL; + } + break; } break; default: @@ -680,6 +705,12 @@ log_cf_gen(ConfigArgs *c) case LOG_SUCCESS: li->li_success = c->value_int; break; + case LOG_OLD: + li->li_oldf = str2filter( c->argv[1] ); + if ( !li->li_oldf ) { + sprintf( c->msg, "bad filter!" ); + rc = 1; + } } break; } @@ -782,6 +813,24 @@ static struct berval derefs[] = { static struct berval simple = BER_BVC("SIMPLE"); +static void accesslog_val2val(AttributeDescription *ad, struct berval *val, + char c_op, struct berval *dst) { + char *ptr; + + dst->bv_len = ad->ad_cname.bv_len + val->bv_len + 2; + if ( c_op ) dst->bv_len++; + + dst->bv_val = ch_malloc( dst->bv_len+1 ); + + ptr = lutil_strcopy( dst->bv_val, ad->ad_cname.bv_val ); + *ptr++ = ':'; + if ( c_op ) + *ptr++ = c_op; + *ptr++ = ' '; + AC_MEMCPY( ptr, val->bv_val, val->bv_len ); + dst->bv_val[dst->bv_len] = '\0'; +} + static int accesslog_response(Operation *op, SlapReply *rs) { slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; log_info *li = on->on_bi.bi_private; @@ -791,7 +840,7 @@ static int accesslog_response(Operation *op, SlapReply *rs) { int i; int logop; slap_verbmasks *lo; - Entry *e; + Entry *e = NULL, *old = NULL; char timebuf[LDAP_LUTIL_GENTIME_BUFSIZE+8]; struct berval bv; char *ptr; @@ -821,6 +870,8 @@ static int accesslog_response(Operation *op, SlapReply *rs) { if ( lo->mask & LOG_OP_WRITES ) { ldap_pvt_thread_mutex_lock( &li->li_log_mutex ); + old = li->li_old; + li->li_old = NULL; ldap_pvt_thread_mutex_unlock( &li->li_op_mutex ); } @@ -844,9 +895,22 @@ static int accesslog_response(Operation *op, SlapReply *rs) { switch( logop ) { case LOG_EN_ADD: + case LOG_EN_DELETE: { + char c_op; + Entry *e2; + + if ( logop == LOG_EN_ADD ) { + e2 = op->ora_e; + c_op = '+'; + } else { + if ( !old ) + break; + e2 = old; + c_op = 0; + } /* count all the vals */ i = 0; - for ( a=op->ora_e->e_attrs; a; a=a->a_next ) { + for ( a=e2->e_attrs; a; a=a->a_next ) { if ( a->a_vals ) { for (b=a->a_vals; !BER_BVISNULL( b ); b++) { i++; @@ -855,32 +919,21 @@ static int accesslog_response(Operation *op, SlapReply *rs) { } vals = ch_malloc( (i+1) * sizeof( struct berval )); i = 0; - for ( a=op->ora_e->e_attrs; a; a=a->a_next ) { + for ( a=e2->e_attrs; a; a=a->a_next ) { if ( a->a_vals ) { for (b=a->a_vals; !BER_BVISNULL( b ); b++,i++) { - vals[i].bv_len = a->a_desc->ad_cname.bv_len + b->bv_len +3; - vals[i].bv_val = ch_malloc( vals[i].bv_len+1 ); - ptr = lutil_strcopy( vals[i].bv_val, - a->a_desc->ad_cname.bv_val ); - *ptr++ = ':'; - *ptr++ = '+'; - *ptr++ = ' '; - AC_MEMCPY( ptr, b->bv_val, b->bv_len ); - vals[i].bv_val[vals[i].bv_len] = '\0'; + accesslog_val2val( a->a_desc, b, c_op, &vals[i] ); } } } vals[i].bv_val = NULL; vals[i].bv_len = 0; - a = attr_alloc( ad_reqMod ); + a = attr_alloc( logop == LOG_EN_ADD ? ad_reqMod : ad_reqOld ); a->a_vals = vals; a->a_nvals = vals; last_attr->a_next = a; break; - - case LOG_EN_DELETE: - /* needs nothing else */ - break; + } case LOG_EN_MODIFY: /* count all the mods */ @@ -896,15 +949,24 @@ static int accesslog_response(Operation *op, SlapReply *rs) { } vals = ch_malloc( (i+1) * sizeof( struct berval )); i = 0; + + /* Zero flags on old entry */ + if ( old ) { + for ( a=old->e_attrs; a; a=a->a_next ) + a->a_flags = 0; + } + for ( m=op->orm_modlist; m; m=m->sml_next ) { + /* Mark this attribute as modified */ + if ( old ) { + a = attr_find( old->e_attrs, m->sml_desc ); + if ( a ) + a->a_flags = 1; + } if ( m->sml_values ) { for (b=m->sml_values; !BER_BVISNULL( b ); b++,i++) { char c_op; - vals[i].bv_len = m->sml_desc->ad_cname.bv_len + b->bv_len +3; - vals[i].bv_val = ch_malloc( vals[i].bv_len+1 ); - ptr = lutil_strcopy( vals[i].bv_val, - m->sml_desc->ad_cname.bv_val ); - *ptr++ = ':'; + switch( m->sml_op ) { case LDAP_MOD_ADD: c_op = '+'; break; case LDAP_MOD_DELETE: c_op = '-'; break; @@ -917,10 +979,7 @@ static int accesslog_response(Operation *op, SlapReply *rs) { */ default: c_op = '?'; break; } - *ptr++ = c_op; - *ptr++ = ' '; - AC_MEMCPY( ptr, b->bv_val, b->bv_len ); - vals[i].bv_val[vals[i].bv_len] = '\0'; + accesslog_val2val( m->sml_desc, b, c_op, &vals[i] ); } } else if ( m->sml_op == LDAP_MOD_DELETE ) { vals[i].bv_len = m->sml_desc->ad_cname.bv_len + 2; @@ -939,6 +998,34 @@ static int accesslog_response(Operation *op, SlapReply *rs) { a->a_vals = vals; a->a_nvals = vals; last_attr->a_next = a; + + if ( old ) { + last_attr = a; + /* count all the vals */ + 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++; + } + } + } + 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_vals = vals; + a->a_nvals = vals; + last_attr->a_next = a; + } break; case LOG_EN_MODRDN: @@ -1040,10 +1127,12 @@ static int accesslog_response(Operation *op, SlapReply *rs) { } op2.o_bd->be_add( &op2, &rs2 ); - entry_free( e ); done: - ldap_pvt_thread_mutex_unlock( &li->li_log_mutex ); + if ( lo->mask & LOG_OP_WRITES ) + ldap_pvt_thread_mutex_unlock( &li->li_log_mutex ); + if ( e ) entry_free( e ); + if ( old ) entry_free( old ); return SLAP_CB_CONTINUE; } @@ -1099,6 +1188,20 @@ accesslog_op_mod( Operation *op, SlapReply *rs ) * overlays like refint to keep working. */ ldap_pvt_thread_mutex_lock( &li->li_op_mutex ); + if ( li->li_oldf && ( op->o_tag == LDAP_REQ_DELETE || + op->o_tag == LDAP_REQ_MODIFY )) { + int rc; + Entry *e; + + op->o_bd->bd_info = on->on_info->oi_orig; + 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 ) + li->li_old = entry_dup( e ); + be_entry_release_rw( op, e, 0 ); + } + op->o_bd->bd_info = (BackendInfo *)on; + } } return SLAP_CB_CONTINUE; } diff --git a/servers/slapd/overlays/auditlog.c b/servers/slapd/overlays/auditlog.c index c617bb02ba..dd338bbfa7 100644 --- a/servers/slapd/overlays/auditlog.c +++ b/servers/slapd/overlays/auditlog.c @@ -177,6 +177,7 @@ auditlog_db_close( free( ad->ad_logfile ); ad->ad_logfile = NULL; + return 0; } static int @@ -189,6 +190,7 @@ auditlog_db_destroy( ldap_pvt_thread_mutex_destroy( &ad->ad_mutex ); free( ad ); + return 0; } static int diff --git a/servers/slapd/overlays/ppolicy.c b/servers/slapd/overlays/ppolicy.c index bed5b4b366..fb37f669ad 100644 --- a/servers/slapd/overlays/ppolicy.c +++ b/servers/slapd/overlays/ppolicy.c @@ -259,11 +259,12 @@ account_locked( Operation *op, Entry *e, return 0; } -#define PPOLICY_WARNING 0xa0L -#define PPOLICY_ERROR 0xa1L +/* IMPLICIT TAGS, all context-specific */ +#define PPOLICY_WARNING 0xa0L /* constructed + 0 */ +#define PPOLICY_ERROR 0x81L /* primitive + 1 */ -#define PPOLICY_EXPIRE 0xa0L -#define PPOLICY_GRACE 0xa1L +#define PPOLICY_EXPIRE 0x80L /* primitive + 0 */ +#define PPOLICY_GRACE 0x81L /* primitive + 1 */ static LDAPControl * create_passcontrol( int exptime, int grace, LDAPPasswordPolicyError err ) diff --git a/servers/slapd/overlays/translucent.c b/servers/slapd/overlays/translucent.c index eee8a6d40c..cc1357a57b 100644 --- a/servers/slapd/overlays/translucent.c +++ b/servers/slapd/overlays/translucent.c @@ -208,7 +208,8 @@ static int translucent_delete(Operation *op, SlapReply *rs) { static int translucent_tag_cb( Operation *op, SlapReply *rs ) { - op->o_tag = (ber_tag_t)op->o_callback->sc_private; + op->o_tag = LDAP_REQ_MODIFY; + op->orm_modlist = op->o_callback->sc_private; rs->sr_tag = slap_req2res( op->o_tag ); return SLAP_CB_CONTINUE; @@ -400,7 +401,7 @@ release: glue_parent(&nop); cb.sc_response = translucent_tag_cb; - cb.sc_private = (void *)LDAP_REQ_MODIFY; + cb.sc_private = op->orm_modlist; cb.sc_next = nop.o_callback; nop.o_callback = &cb; rc = on->on_info->oi_orig->bi_op_add(&nop, &nrs); diff --git a/servers/slapd/syncrepl.c b/servers/slapd/syncrepl.c index f19e0a9993..68dcf4e0e4 100644 --- a/servers/slapd/syncrepl.c +++ b/servers/slapd/syncrepl.c @@ -2704,9 +2704,10 @@ syncinfo_free( syncinfo_t *sie ) /* mandatory */ #define GOT_ID 0x0001 #define GOT_PROVIDER 0x0002 +#define GOT_BASE 0x0004 /* check */ -#define GOT_ALL (GOT_ID|GOT_PROVIDER) +#define GOT_ALL (GOT_ID|GOT_PROVIDER|GOT_BASE) static struct { struct berval key; @@ -2811,6 +2812,7 @@ parse_syncrepl_line( Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); return -1; } + gots |= GOT_BASE; } else if ( !strncasecmp( c->argv[ i ], LOGBASESTR "=", STRLENOF( LOGBASESTR "=" ) ) ) { @@ -3127,7 +3129,10 @@ parse_syncrepl_line( if ( gots != GOT_ALL ) { snprintf( c->msg, sizeof( c->msg ), - "Error: Malformed \"syncrepl\" line in slapd config file" ); + "Error: Malformed \"syncrepl\" line in slapd config file, missing%s%s%s", + gots & GOT_ID ? "" : " "IDSTR, + gots & GOT_PROVIDER ? "" : " "PROVIDERSTR, + gots & GOT_BASE ? "" : " "SEARCHBASESTR ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 ); return -1; } diff --git a/servers/slurpd/st.c b/servers/slurpd/st.c index 595b99ea0f..8deaa61c70 100644 --- a/servers/slurpd/st.c +++ b/servers/slurpd/st.c @@ -246,10 +246,9 @@ St_read( } if ( found ) { char tbuf[ 255 ]; - sprintf( tbuf, "%s:%s (timestamp %s.%s)", hostname, port, - timestamp, seq ); + sprintf( tbuf, "%s.%s", timestamp, seq ); Debug( LDAP_DEBUG_ARGS, - "Retrieved state information for %s\n", tbuf, 0, 0 ); + "Retrieved state information for %s:%s (timestamp %s)\n", hostname, port, tbuf ); } else { Debug( LDAP_DEBUG_ANY, "Warning: saved state for %s:%s, not a known replica\n", -- 2.39.5