From 6f9519543e832e6ff7d4001d3067894e83d84084 Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Fri, 24 Aug 2007 23:13:41 +0000 Subject: [PATCH] - fix logging of controls; - add support for Control syntax; - use Control syntax and objectIdentifierFirstComponentMatch with reqControls/reqRespControls --- servers/slapd/overlays/accesslog.c | 355 ++++++++++++++++++++++++++--- 1 file changed, 318 insertions(+), 37 deletions(-) diff --git a/servers/slapd/overlays/accesslog.c b/servers/slapd/overlays/accesslog.c index 6106bc00cb..6ee3380cb7 100644 --- a/servers/slapd/overlays/accesslog.c +++ b/servers/slapd/overlays/accesslog.c @@ -168,6 +168,7 @@ static ObjectClass *log_ocs[LOG_EN__COUNT], *log_container; #define LOG_SCHEMA_AT LOG_SCHEMA_ROOT ".1" #define LOG_SCHEMA_OC LOG_SCHEMA_ROOT ".2" +#define LOG_SCHEMA_SYN LOG_SCHEMA_ROOT ".3" static AttributeDescription *ad_reqDN, *ad_reqStart, *ad_reqEnd, *ad_reqType, *ad_reqSession, *ad_reqResult, *ad_reqAuthzID, *ad_reqControls, @@ -178,6 +179,31 @@ static AttributeDescription *ad_reqDN, *ad_reqStart, *ad_reqEnd, *ad_reqType, *ad_reqId, *ad_reqMessage, *ad_reqVersion, *ad_reqDerefAliases, *ad_reqReferral, *ad_reqOld, *ad_auditContext; +static int +logSchemaControlValidate( + Syntax *syntax, + struct berval *val ); + +char *mrControl[] = { + "objectIdentifierFirstComponentMatch", + NULL +}; + +static struct { + char *oid; + slap_syntax_defs_rec syn; + char **mrs; +} lsyntaxes[] = { + { LOG_SCHEMA_SYN ".1" , + { "( " LOG_SCHEMA_SYN ".1 DESC 'Control' )", + SLAP_SYNTAX_HIDE, + NULL, + logSchemaControlValidate, + NULL }, + mrControl }, + { NULL } +}; + static struct { char *at; AttributeDescription **ad; @@ -231,11 +257,13 @@ static struct { "SUP labeledURI )", &ad_reqReferral }, { "( " LOG_SCHEMA_AT ".10 NAME 'reqControls' " "DESC 'Request controls' " - "SYNTAX OMsOctetString " + "EQUALITY objectIdentifierFirstComponentMatch " + "SYNTAX " LOG_SCHEMA_SYN ".1 " "X-ORDERED 'VALUES' )", &ad_reqControls }, { "( " LOG_SCHEMA_AT ".11 NAME 'reqRespControls' " "DESC 'Response controls of request' " - "SYNTAX OMsOctetString " + "EQUALITY objectIdentifierFirstComponentMatch " + "SYNTAX " LOG_SCHEMA_SYN ".1 " "X-ORDERED 'VALUES' )", &ad_reqRespControls }, { "( " LOG_SCHEMA_AT ".12 NAME 'reqId' " "DESC 'ID of Request to Abandon' " @@ -850,50 +878,269 @@ log_cf_gen(ConfigArgs *c) } static int -accesslog_ctrls( LDAPControl **ctrls, BerVarray *valsp, void *memctx ) +logSchemaControlValidate( + Syntax *syntax, + struct berval *valp ) { - int i, rc = 0; + struct berval val, bv; + int i; + int rc = LDAP_SUCCESS; + + assert( valp != NULL ); + + val = *valp; + + /* check minimal size */ + if ( val.bv_len < STRLENOF( "{*}" ) ) { + return LDAP_INVALID_SYNTAX; + } + + val.bv_len--; + + /* check SEQUENCE boundaries */ + if ( val.bv_val[ 0 ] != '{' /*}*/ || + val.bv_val[ val.bv_len ] != /*{*/ '}' ) + { + return LDAP_INVALID_SYNTAX; + } + + /* extract and check OID */ + for ( i = 1; i < val.bv_len; i++ ) { + if ( !ASCII_SPACE( val.bv_val[ i ] ) ) { + break; + } + } + + bv.bv_val = &val.bv_val[ i ]; + + for ( i++; i < val.bv_len; i++ ) { + if ( ASCII_SPACE( val.bv_val[ i ] ) ) + { + break; + } + } + + bv.bv_len = &val.bv_val[ i ] - bv.bv_val; + + rc = numericoidValidate( NULL, &bv ); + if ( rc != LDAP_SUCCESS ) { + return rc; + } + + if ( i == val.bv_len ) { + return LDAP_SUCCESS; + } + + if ( val.bv_val[ i ] != ' ' ) { + return LDAP_INVALID_SYNTAX; + } + + for ( i++; i < val.bv_len; i++ ) { + if ( !ASCII_SPACE( val.bv_val[ i ] ) ) { + break; + } + } + + if ( i == val.bv_len ) { + return LDAP_SUCCESS; + } + + /* extract and check criticality */ + if ( strncasecmp( &val.bv_val[ i ], "criticality ", STRLENOF( "criticality " ) ) == 0 ) + { + i += STRLENOF( "criticality " ); + for ( ; i < val.bv_len; i++ ) { + if ( !ASCII_SPACE( val.bv_val[ i ] ) ) { + break; + } + } + + if ( i == val.bv_len ) { + return LDAP_INVALID_SYNTAX; + } + + bv.bv_val = &val.bv_val[ i ]; + + for ( ; i < val.bv_len; i++ ) { + if ( ASCII_SPACE( val.bv_val[ i ] ) ) { + break; + } + } + + bv.bv_len = &val.bv_val[ i ] - bv.bv_val; + + if ( !bvmatch( &bv, &slap_true_bv ) && !bvmatch( &bv, &slap_false_bv ) ) + { + return LDAP_INVALID_SYNTAX; + } + + if ( i == val.bv_len ) { + return LDAP_SUCCESS; + } + + if ( val.bv_val[ i ] != ' ' ) { + return LDAP_INVALID_SYNTAX; + } + + for ( i++; i < val.bv_len; i++ ) { + if ( !ASCII_SPACE( val.bv_val[ i ] ) ) { + break; + } + } + + if ( i == val.bv_len ) { + return LDAP_SUCCESS; + } + } + + /* extract and check controlValue */ + if ( strncasecmp( &val.bv_val[ i ], "controlValue ", STRLENOF( "controlValue " ) ) == 0 ) + { + i += STRLENOF( "controlValue " ); + for ( ; i < val.bv_len; i++ ) { + if ( !ASCII_SPACE( val.bv_val[ i ] ) ) { + break; + } + } + + if ( i == val.bv_len ) { + return LDAP_INVALID_SYNTAX; + } + + if ( val.bv_val[ i ] != '"' ) { + return LDAP_INVALID_SYNTAX; + } + + for ( ; i < val.bv_len; i++ ) { + if ( val.bv_val[ i ] == '"' ) { + break; + } + + if ( !ASCII_HEX( val.bv_val[ i ] ) ) { + return LDAP_INVALID_SYNTAX; + } + } + + if ( val.bv_val[ i ] != '"' ) { + return LDAP_INVALID_SYNTAX; + } + + for ( ; i < val.bv_len; i++ ) { + if ( !ASCII_SPACE( val.bv_val[ i ] ) ) { + break; + } + } + + if ( i == val.bv_len ) { + return LDAP_SUCCESS; + } + } + + return LDAP_INVALID_SYNTAX; +} + +static int +accesslog_ctrls( + LDAPControl **ctrls, + BerVarray *valsp, + BerVarray *nvalsp, + void *memctx ) +{ + long i, rc = 0; assert( valsp != NULL ); assert( ctrls != NULL ); *valsp = NULL; + *nvalsp = NULL; for ( i = 0; ctrls[ i ] != NULL; i++ ) { - BerElementBuffer berbuf; - BerElement *ber = (BerElement *)&berbuf; + struct berval idx, + oid, + noid, + bv; + char *ptr, + buf[ 32 ]; + + if ( ctrls[ i ]->ldctl_oid == NULL ) { + return LDAP_PROTOCOL_ERROR; + } - ber_init2( ber, NULL, LBER_USE_DER ); + idx.bv_len = snprintf( buf, sizeof( buf ), "{%ld}", i ); + idx.bv_val = buf; - if ( ldap_pvt_put_control( ctrls[ i ], ber ) != LDAP_SUCCESS ) { - rc++; + ber_str2bv( ctrls[ i ]->ldctl_oid, 0, 0, &oid ); + noid.bv_len = idx.bv_len + oid.bv_len; + ptr = noid.bv_val = ber_memalloc_x( noid.bv_len + 1, memctx ); + ptr = lutil_strcopy( ptr, idx.bv_val ); + ptr = lutil_strcopy( ptr, oid.bv_val ); - } else { - struct berval ctrlbv; + bv.bv_len = idx.bv_len + STRLENOF( "{}" ) + oid.bv_len; + + if ( ctrls[ i ]->ldctl_iscritical ) { + bv.bv_len += STRLENOF( " criticality TRUE" ); + } - if ( ber_flatten2( ber, &ctrlbv, 0 ) == -1 ) { - rc++; + if ( !BER_BVISNULL( &ctrls[ i ]->ldctl_value ) ) { + bv.bv_len += STRLENOF( " controlValue \"\"" ) + + 2 * ctrls[ i ]->ldctl_value.bv_len; + } - } else { - struct berval bv; - char buf[ 32 ], *ptr; - - bv.bv_len = snprintf( buf, - sizeof( buf ), "{%d}", i ); - bv.bv_len += ctrlbv.bv_len; - ptr = bv.bv_val = ch_malloc( bv.bv_len + 1 ); - ptr = lutil_strcopy( ptr, buf ); - AC_MEMCPY( ptr, ctrlbv.bv_val, ctrlbv.bv_len ); - bv.bv_val[ bv.bv_len ] = '\0'; - - ber_bvarray_add_x( valsp, &bv, memctx ); + ptr = bv.bv_val = ber_memalloc_x( bv.bv_len + 1, memctx ); + if ( ptr == NULL ) { + ber_bvarray_free( *valsp ); + *valsp = NULL; + ber_bvarray_free( *nvalsp ); + *nvalsp = NULL; + return LDAP_OTHER; + } + + ptr = lutil_strcopy( ptr, idx.bv_val ); + + *ptr++ = '{' /*}*/ ; + ptr = lutil_strcopy( ptr, oid.bv_val ); + + if ( ctrls[ i ]->ldctl_iscritical ) { + ptr = lutil_strcopy( ptr, " criticality TRUE" ); + } + + if ( !BER_BVISNULL( &ctrls[ i ]->ldctl_value ) ) { + int 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; + } } + + *ptr++ = '"'; } - (void)ber_free_buf( ber ); + *ptr++ = '}'; + *ptr = '\0'; + + ber_bvarray_add_x( valsp, &bv, memctx ); + ber_bvarray_add_x( nvalsp, &noid, memctx ); } return rc; + } static Entry *accesslog_entry( Operation *op, SlapReply *rs, int logop, @@ -974,22 +1221,28 @@ static Entry *accesslog_entry( Operation *op, SlapReply *rs, int logop, /* FIXME: need to add reqControls and reqRespControls */ if ( op->o_ctrls ) { - BerVarray vals = NULL; + BerVarray vals = NULL, + nvals = NULL; - (void)accesslog_ctrls( op->o_ctrls, &vals, op->o_tmpmemctx ); - if ( vals != NULL ) { - attr_merge( e, ad_reqControls, vals, NULL ); + if ( accesslog_ctrls( op->o_ctrls, &vals, &nvals, + op->o_tmpmemctx ) == LDAP_SUCCESS && vals ) + { + attr_merge( e, ad_reqControls, vals, nvals ); ber_bvarray_free_x( vals, op->o_tmpmemctx ); + ber_bvarray_free_x( nvals, op->o_tmpmemctx ); } } if ( rs->sr_ctrls ) { - BerVarray vals = NULL; + BerVarray vals = NULL, + nvals = NULL; - (void)accesslog_ctrls( rs->sr_ctrls, &vals, op->o_tmpmemctx ); - if ( vals != NULL ) { - attr_merge( e, ad_reqRespControls, vals, NULL ); + if ( accesslog_ctrls( rs->sr_ctrls, &vals, &nvals, + op->o_tmpmemctx ) == LDAP_SUCCESS && vals ) + { + attr_merge( e, ad_reqRespControls, vals, nvals ); ber_bvarray_free_x( vals, op->o_tmpmemctx ); + ber_bvarray_free_x( nvals, op->o_tmpmemctx ); } } @@ -1741,23 +1994,51 @@ int accesslog_initialize() if ( rc ) return rc; /* log schema integration */ + for ( i=0; lsyntaxes[i].oid; i++ ) { + int code; + + code = register_syntax( &lsyntaxes[ i ].syn ); + if ( code != 0 ) { + Debug( LDAP_DEBUG_ANY, + "accesslog_init: register_syntax failed\n", + 0, 0, 0 ); + return code; + } + + if ( lsyntaxes[i].mrs != NULL ) { + code = mr_make_syntax_compat_with_mrs( + lsyntaxes[i].oid, lsyntaxes[i].mrs ); + if ( code < 0 ) { + Debug( LDAP_DEBUG_ANY, + "accesslog_init: " + "mr_make_syntax_compat_with_mrs " + "failed\n", + 0, 0, 0 ); + return code; + } + } + } + for ( i=0; lattrs[i].at; i++ ) { int code; code = register_at( lattrs[i].at, lattrs[i].ad, 0 ); if ( code ) { Debug( LDAP_DEBUG_ANY, - "accesslog_init: register_at failed\n", 0, 0, 0 ); + "accesslog_init: register_at failed\n", + 0, 0, 0 ); return -1; } } + for ( i=0; locs[i].ot; i++ ) { int code; code = register_oc( locs[i].ot, locs[i].oc, 0 ); if ( code ) { Debug( LDAP_DEBUG_ANY, - "accesslog_init: register_oc failed\n", 0, 0, 0 ); + "accesslog_init: register_oc failed\n", + 0, 0, 0 ); return -1; } } -- 2.39.5