Commit 9fec1299 authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

Second round of schema changes

Revert normalization to matching rule per discussions with Julio.
May need separate normalization routines for stored value and asserted
value. Currently rely on passed in syntax/mr to allow "special" behavior.
Reworked filters to pass struct berval * instead of char *. (needs work)
Validation, normalization and matching needed.
parent f3cb97e9
......@@ -20,7 +20,8 @@ static ID_BLOCK *presence_candidates( Backend *be, char *type );
static ID_BLOCK *approx_candidates( Backend *be, Ava *ava );
static ID_BLOCK *list_candidates( Backend *be, Filter *flist, int ftype );
static ID_BLOCK *substring_candidates( Backend *be, Filter *f );
static ID_BLOCK *substring_comp_candidates( Backend *be, char *type, char *val, int prepost );
static ID_BLOCK *substring_comp_candidates( Backend *be, char *type,
struct berval *val, int prepost );
/*
* test_filter - test a filter against a single entry.
......@@ -247,7 +248,7 @@ substring_candidates(
/* initial */
if ( f->f_sub_initial != NULL ) {
if ( (int) strlen( f->f_sub_initial ) < SUBLEN - 1 ) {
if ( f->f_sub_initial->bv_len < SUBLEN - 1 ) {
idl = idl_allids( be );
} else if ( (idl = substring_comp_candidates( be, f->f_sub_type,
f->f_sub_initial, '^' )) == NULL ) {
......@@ -257,7 +258,7 @@ substring_candidates(
/* final */
if ( f->f_sub_final != NULL ) {
if ( (int) strlen( f->f_sub_final ) < SUBLEN - 1 ) {
if ( f->f_sub_final->bv_len < SUBLEN - 1 ) {
tmp = idl_allids( be );
} else if ( (tmp = substring_comp_candidates( be, f->f_sub_type,
f->f_sub_final, '$' )) == NULL ) {
......@@ -275,22 +276,24 @@ substring_candidates(
}
}
for ( i = 0; f->f_sub_any != NULL && f->f_sub_any[i] != NULL; i++ ) {
if ( (int) strlen( f->f_sub_any[i] ) < SUBLEN ) {
tmp = idl_allids( be );
} else if ( (tmp = substring_comp_candidates( be, f->f_sub_type,
f->f_sub_any[i], 0 )) == NULL ) {
idl_free( idl );
return( NULL );
}
if ( idl == NULL ) {
idl = tmp;
} else {
tmp2 = idl;
idl = idl_intersection( be, idl, tmp );
idl_free( tmp );
idl_free( tmp2 );
if( f->f_sub_any != NULL ) {
for ( i = 0; f->f_sub_any[i] != NULL; i++ ) {
if ( f->f_sub_any[i]->bv_len < SUBLEN ) {
tmp = idl_allids( be );
} else if ( (tmp = substring_comp_candidates( be, f->f_sub_type,
f->f_sub_any[i], 0 )) == NULL ) {
idl_free( idl );
return( NULL );
}
if ( idl == NULL ) {
idl = tmp;
} else {
tmp2 = idl;
idl = idl_intersection( be, idl, tmp );
idl_free( tmp );
idl_free( tmp2 );
}
}
}
......@@ -303,7 +306,7 @@ static ID_BLOCK *
substring_comp_candidates(
Backend *be,
char *type,
char *val,
struct berval *bv,
int prepost
)
{
......@@ -311,10 +314,12 @@ substring_comp_candidates(
ID_BLOCK *idl, *tmp, *tmp2;
char *p;
char buf[SUBLEN + 1];
char *val;
Debug( LDAP_DEBUG_TRACE, "=> substring_comp_candidates\n", 0, 0, 0 );
len = strlen( val );
val = bv->bv_val;
len = bv->bv_len;
idl = NULL;
/* prepend ^ for initial substring */
......
......@@ -229,7 +229,8 @@ get_substring_filter(
ber_tag_t tag;
ber_len_t len;
ber_tag_t rc;
char *val, *last;
struct berval *val;
char *last;
int syntax;
Debug( LDAP_DEBUG_FILTER, "begin get_substring_filter\n", 0, 0, 0 );
......@@ -237,73 +238,107 @@ get_substring_filter(
if ( ber_scanf( ber, "{a" /*}*/, &f->f_sub_type ) == LBER_ERROR ) {
return( -1 );
}
attr_normalize( f->f_sub_type );
/* should get real syntax and see if we have a substring matching rule */
syntax = attr_syntax( f->f_sub_type );
f->f_sub_initial = NULL;
f->f_sub_any = NULL;
f->f_sub_final = NULL;
*fstr = ch_malloc( strlen( f->f_sub_type ) + 3 );
sprintf( *fstr, "(%s=", f->f_sub_type );
if( fstr ) {
*fstr = ch_malloc( strlen( f->f_sub_type ) + 3 );
sprintf( *fstr, "(%s=", f->f_sub_type );
}
for ( tag = ber_first_element( ber, &len, &last ); tag != LBER_DEFAULT;
tag = ber_next_element( ber, &len, last ) )
{
rc = ber_scanf( ber, "a", &val );
rc = ber_scanf( ber, "O", &val );
if ( rc == LBER_ERROR ) {
return( -1 );
}
if ( val == NULL || *val == '\0' ) {
if ( val != NULL ) {
free( val );
}
if ( val == NULL || val->bv_len == 0 ) {
ber_bvfree( val );
return( LDAP_INVALID_SYNTAX );
}
value_normalize( val, syntax );
/* we should call a substring syntax normalization routine */
value_normalize( val->bv_val, syntax );
/* this is bogus, value_normalize should take a berval */
val->bv_len = strlen( val->bv_val );
switch ( tag ) {
case LDAP_SUBSTRING_INITIAL:
Debug( LDAP_DEBUG_FILTER, " INITIAL\n", 0, 0, 0 );
if ( f->f_sub_initial != NULL ) {
return( LDAP_PROTOCOL_ERROR );
ber_bvfree( val );
goto return_error;
}
f->f_sub_initial = val;
*fstr = ch_realloc( *fstr, strlen( *fstr ) +
strlen( val ) + 1 );
strcat( *fstr, val );
if( fstr ) {
*fstr = ch_realloc( *fstr,
strlen( *fstr ) + val->bv_len + 1 );
strcat( *fstr, val->bv_val );
}
break;
case LDAP_SUBSTRING_ANY:
Debug( LDAP_DEBUG_FILTER, " ANY\n", 0, 0, 0 );
charray_add( &f->f_sub_any, val );
*fstr = ch_realloc( *fstr, strlen( *fstr ) +
strlen( val ) + 2 );
strcat( *fstr, "*" );
strcat( *fstr, val );
charray_add( (char ***) &f->f_sub_any, (char *) val );
if( fstr ) {
*fstr = ch_realloc( *fstr,
strlen( *fstr ) + val->bv_len + 2 );
strcat( *fstr, "*" );
strcat( *fstr, val->bv_val );
}
break;
case LDAP_SUBSTRING_FINAL:
Debug( LDAP_DEBUG_FILTER, " FINAL\n", 0, 0, 0 );
if ( f->f_sub_final != NULL ) {
return( LDAP_PROTOCOL_ERROR );
ber_bvfree( val );
goto return_error;
}
f->f_sub_final = val;
*fstr = ch_realloc( *fstr, strlen( *fstr ) +
strlen( val ) + 2 );
strcat( *fstr, "*" );
strcat( *fstr, val );
if( fstr ) {
*fstr = ch_realloc( *fstr,
strlen( *fstr ) + val->bv_len + 2 );
strcat( *fstr, "*" );
strcat( *fstr, val->bv_val );
}
break;
default:
Debug( LDAP_DEBUG_FILTER, " unknown type\n", tag, 0,
0 );
return_error:
if( fstr ) {
free( *fstr );
*fstr = NULL;
}
ch_free( f->f_sub_type );
ber_bvfree( f->f_sub_initial );
ber_bvecfree( f->f_sub_any );
ber_bvfree( f->f_sub_final );
return( LDAP_PROTOCOL_ERROR );
}
}
*fstr = ch_realloc( *fstr, strlen( *fstr ) + 3 );
if ( f->f_sub_final == NULL ) {
strcat( *fstr, "*" );
if( fstr ) {
*fstr = ch_realloc( *fstr, strlen( *fstr ) + 3 );
if ( f->f_sub_final == NULL ) {
strcat( *fstr, "*" );
}
strcat( *fstr, ")" );
}
strcat( *fstr, ")" );
Debug( LDAP_DEBUG_FILTER, "end get_substring_filter\n", 0, 0, 0 );
return( LDAP_SUCCESS );
......@@ -331,11 +366,11 @@ filter_free( Filter *f )
free( f->f_sub_type );
}
if ( f->f_sub_initial != NULL ) {
free( f->f_sub_initial );
ber_bvfree( f->f_sub_initial );
}
charray_free( f->f_sub_any );
ber_bvecfree( f->f_sub_any );
if ( f->f_sub_final != NULL ) {
free( f->f_sub_final );
ber_bvfree( f->f_sub_final );
}
break;
......@@ -398,16 +433,15 @@ filter_print( Filter *f )
case LDAP_FILTER_SUBSTRINGS:
fprintf( stderr, "(%s=", f->f_sub_type );
if ( f->f_sub_initial != NULL ) {
fprintf( stderr, "%s", f->f_sub_initial );
fprintf( stderr, "%s", f->f_sub_initial->bv_val );
}
if ( f->f_sub_any != NULL ) {
for ( i = 0; f->f_sub_any[i] != NULL; i++ ) {
fprintf( stderr, "*%s", f->f_sub_any[i] );
fprintf( stderr, "*%s", f->f_sub_any[i]->bv_val );
}
}
charray_free( f->f_sub_any );
if ( f->f_sub_final != NULL ) {
fprintf( stderr, "*%s", f->f_sub_final );
fprintf( stderr, "*%s", f->f_sub_final->bv_val );
}
break;
......
......@@ -358,38 +358,38 @@ test_substring_filter(
strcpy( p, "^" );
p = strchr( p, '\0' );
/* 2 * in case every char is special */
if ( p + 2 * strlen( f->f_sub_initial ) > end ) {
if ( p + 2 * f->f_sub_initial->bv_len > end ) {
Debug( LDAP_DEBUG_ANY, "not enough pattern space\n",
0, 0, 0 );
return( -1 );
}
strcpy_regex( p, f->f_sub_initial );
strcpy_regex( p, f->f_sub_initial->bv_val );
p = strchr( p, '\0' );
}
if ( f->f_sub_any != NULL ) {
for ( i = 0; f->f_sub_any[i] != NULL; i++ ) {
/* ".*" + value */
if ( p + 2 * strlen( f->f_sub_any[i] ) + 2 > end ) {
if ( p + 2 * f->f_sub_any[i]->bv_len + 2 > end ) {
Debug( LDAP_DEBUG_ANY,
"not enough pattern space\n", 0, 0, 0 );
return( -1 );
}
strcpy( p, ".*" );
p = strchr( p, '\0' );
strcpy_regex( p, f->f_sub_any[i] );
strcpy_regex( p, f->f_sub_any[i]->bv_val );
p = strchr( p, '\0' );
}
}
if ( f->f_sub_final != NULL ) {
/* ".*" + value */
if ( p + 2 * strlen( f->f_sub_final ) + 2 > end ) {
if ( p + 2 * f->f_sub_final->bv_len + 2 > end ) {
Debug( LDAP_DEBUG_ANY, "not enough pattern space\n",
0, 0, 0 );
return( -1 );
}
strcpy( p, ".*" );
p = strchr( p, '\0' );
strcpy_regex( p, f->f_sub_final );
strcpy_regex( p, f->f_sub_final->bv_val );
p = strchr( p, '\0' );
strcpy( p, "$" );
}
......
......@@ -449,18 +449,22 @@ LIBSLAPD_F (Syntax *) syn_find LDAP_P((const char *synname));
LIBSLAPD_F (Syntax *) syn_find_desc LDAP_P((const char *syndesc, int *slen));
LIBSLAPD_F (int) syn_add LDAP_P((LDAP_SYNTAX *syn,
slap_syntax_validate_func *validate,
slap_syntax_normalize_func *normalize,
slap_syntax_transform_func *ber2str,
slap_syntax_transform_func *str2ber,
const char **err));
LIBSLAPD_F (MatchingRule *) mr_find LDAP_P((const char *mrname));
LIBSLAPD_F (int) mr_add LDAP_P((LDAP_MATCHING_RULE *mr,
slap_mr_normalize_func *normalize,
slap_mr_match_func *match,
const char **err));
LIBSLAPD_F (int) register_syntax LDAP_P((char *desc,
slap_syntax_validate_func *validate,
slap_syntax_normalize_func *normalize ));
slap_syntax_transform_func *ber2str,
slap_syntax_transform_func *str2ber ));
LIBSLAPD_F (int) register_matching_rule LDAP_P((char * desc,
slap_mr_normalize_func *normalize,
slap_mr_match_func *match ));
LIBSLAPD_F (void) schema_info LDAP_P((Connection *conn, Operation *op,
......
......@@ -651,7 +651,8 @@ int
syn_add(
LDAP_SYNTAX *syn,
slap_syntax_validate_func *validate,
slap_syntax_normalize_func *normalize,
slap_syntax_transform_func *ber2str,
slap_syntax_transform_func *str2ber,
const char **err
)
{
......@@ -660,8 +661,11 @@ syn_add(
ssyn = (Syntax *) ch_calloc( 1, sizeof(Syntax) );
memcpy( &ssyn->ssyn_syn, syn, sizeof(LDAP_SYNTAX));
ssyn->ssyn_validate = validate;
ssyn->ssyn_normalize = normalize;
ssyn->ssyn_ber2str = ber2str;
ssyn->ssyn_str2ber = str2ber;
code = syn_insert(ssyn,err);
return code;
}
......@@ -759,6 +763,7 @@ mr_insert(
int
mr_add(
LDAP_MATCHING_RULE *mr,
slap_mr_normalize_func *normalize,
slap_mr_match_func *match,
const char **err
)
......@@ -769,7 +774,10 @@ mr_add(
smr = (MatchingRule *) ch_calloc( 1, sizeof(MatchingRule) );
memcpy( &smr->smr_mrule, mr, sizeof(LDAP_MATCHING_RULE));
smr->smr_normalize = normalize;
smr->smr_match = match;
if ( smr->smr_syntax_oid ) {
if ( (syn = syn_find(smr->smr_syntax_oid)) ) {
smr->smr_syntax = syn;
......@@ -786,20 +794,24 @@ mr_add(
}
static int
octetStringValidate( struct berval *val )
octetStringValidate(
Syntax *syntax,
struct berval *in )
{
/* any value allowed */
return 0;
}
static int
UTF8StringValidate( struct berval *val )
UTF8StringValidate(
Syntax *syntax,
struct berval *in )
{
ber_len_t count;
int len;
unsigned char *u = val->bv_val;
unsigned char *u = in->bv_val;
for( count = val->bv_len; count > 0; count+=len, u+=len ) {
for( count = in->bv_len; count > 0; count+=len, u+=len ) {
/* get the length indicated by the first byte */
len = LDAP_UTF8_CHARLEN( u );
......@@ -818,9 +830,10 @@ UTF8StringValidate( struct berval *val )
static int
UTF8StringNormalize(
Syntax *syntax,
MatchingRule *mr,
struct berval *val,
struct berval **normalized
)
struct berval **normalized )
{
struct berval *newval;
char *p, *q, *s;
......@@ -894,9 +907,11 @@ UTF8StringNormalize(
}
static int
IA5StringValidate( struct berval *val )
IA5StringValidate(
Syntax *syntax,
struct berval *val )
{
int i;
ber_len_t i;
for(i=0; i < val->bv_len; i++) {
if( !isascii(val->bv_val[i]) ) return -1;
......@@ -907,9 +922,10 @@ IA5StringValidate( struct berval *val )
static int
IA5StringNormalize(
Syntax *syntax,
MatchingRule *mr,
struct berval *val,
struct berval **normalized
)
struct berval **normalized )
{
struct berval *newval;
char *p, *q;
......@@ -975,27 +991,30 @@ IA5StringNormalize(
static int
caseExactIA5Match(
struct berval *val1,
struct berval *val2
)
Syntax *syntax,
MatchingRule *mr,
struct berval *value,
struct berval *assertedValue )
{
return strcmp( val1->bv_val, val2->bv_val );
return strcmp( value->bv_val, assertedValue->bv_val );
}
static int
caseIgnoreIA5Match(
struct berval *val1,
struct berval *val2
)
Syntax *syntax,
MatchingRule *mr,
struct berval *value,
struct berval *assertedValue )
{
return strcasecmp( val1->bv_val, val2->bv_val );
return strcasecmp( value->bv_val, assertedValue->bv_val );
}
int
register_syntax(
char * desc,
slap_syntax_validate_func *validate,
slap_syntax_normalize_func *normalize )
slap_syntax_transform_func *ber2str,
slap_syntax_transform_func *str2ber )
{
LDAP_SYNTAX *syn;
int code;
......@@ -1007,18 +1026,21 @@ register_syntax(
ldap_scherr2str(code), err, desc );
return( -1 );
}
code = syn_add( syn, validate, normalize, &err );
code = syn_add( syn, validate, ber2str, str2ber, &err );
if ( code ) {
Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s %s in %s\n",
scherr2str(code), err, desc );
return( -1 );
}
return( 0 );
}
int
register_matching_rule(
char * desc,
slap_mr_normalize_func *normalize,
slap_mr_match_func *match )
{
LDAP_MATCHING_RULE *mr;
......@@ -1031,7 +1053,8 @@ register_matching_rule(
ldap_scherr2str(code), err, desc );
return( -1 );
}
code = mr_add( mr, match, &err );
code = mr_add( mr, normalize, match, &err );
if ( code ) {
Debug( LDAP_DEBUG_ANY, "Error in register_syntax: %s for %s in %s\n",
scherr2str(code), err, desc );
......@@ -1043,98 +1066,100 @@ register_matching_rule(
struct syntax_defs_rec {
char *sd_desc;
slap_syntax_validate_func *sd_validate;
slap_syntax_normalize_func *sd_normalize;
slap_syntax_transform_func *sd_ber2str;
slap_syntax_transform_func *sd_str2ber;
};
struct syntax_defs_rec syntax_defs[] = {
{"( 1.3.6.1.4.1.1466.115.121.1.3 DESC 'AttributeTypeDescription' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.4 DESC 'Audio' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'BitString' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'CertificateList' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'CertificatePair' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'DN' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.14 DESC 'DeliveryMethod' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.15 DESC 'DirectoryString' )",
UTF8StringValidate, UTF8StringNormalize},
UTF8StringValidate, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.16 DESC 'DITContentRuleDescription' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.17 DESC 'DITStructureRuleDescription' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.21 DESC 'EnhancedGuide' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.22 DESC 'FacsimileTelephoneNumber' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'GeneralizedTime' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5String' )",
IA5StringValidate, IA5StringNormalize},
IA5StringValidate, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.27 DESC 'Integer' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.28 DESC 'JPEG' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.30 DESC 'MatchingRuleDescription' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.31 DESC 'MatchingRuleUseDescription' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.32 DESC 'MailPreference' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'NameAndOptionalUID' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'NameFormDescription' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'NumericString' )",
NULL, NULL},
NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.37 DESC 'ObjectClassDescription' )",
NULL, NULL},