Commit 61bd10ea authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

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
parent ed2f5c56
......@@ -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)
......
......@@ -49,6 +49,11 @@ abandon, bind, unbind
all operations
.RE
.TP
.B logold <filter>
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 <age> <interval>
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
......
......@@ -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
......
......@@ -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;
......
......@@ -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;
}
......
......@@ -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
......
......@@ -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 )
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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",
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment