X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fschema_init.c;h=eef80beb30279966ba231ff6d1af3911b2c07fa6;hb=925714ceeff035c596ad3d3c899ff631986c6757;hp=aa15dc33120d457e86eacdcac00ffef9adc2da38;hpb=82540c5cc1be5bf17b22f3a41d12d1bc56180654;p=openldap diff --git a/servers/slapd/schema_init.c b/servers/slapd/schema_init.c index aa15dc3312..eef80beb30 100644 --- a/servers/slapd/schema_init.c +++ b/servers/slapd/schema_init.c @@ -5,52 +5,6 @@ * COPYING RESTRICTIONS APPLY, see COPYRIGHT file */ -/**** -LDAP/X.500 string syntax / matching rules have a few oddities. This -comment attempts to detail how slapd(8) treats them. - -Directory String - - In X.500(93), a directory string can be either a PrintableString, - a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)). - In later versions, more CHOICEs were added. In all cases the string - must be non-empty. - - In LDPAv3, a directory string is a UTF-8 encoded UCS string. - - For matching, there are both case ignore and exact rules. Both - also require that "insignificant" spaces be ignored. - spaces before the first non-space are ignored; - spaces after the last non-space are ignored; - spaces after a space are ignored. - Note: by these rules (and as clarified in X.520), a string of only - spaces is to be treated as if held one space, not empty (which would - be a syntax error). - -NumericString - In ASN.1, numeric string is just a string of digits and spaces and - could be empty. However, in X.500, all attribute values of numeric - string carry a non-empty constraint. Unfornately, some assertion - values are don't carry this constraint (but its unclear how such - an assertion could ever be true). In LDAP, there is one syntax - (numericString) not two (numericString with constraint, numericString - without constraint). This should be treated as numericString with - non-empty constraint. - - In matching, spaces are ignored. - -PrintableString - In ASN.1, Printable string is just a string of printable characters and - can be empty. In X.500, semantics much like NumericString excepting - uses insignificant space handling instead of ingore all spaces. - -IA5String - Basically same as PrintableString. - -****/ - - - - #include "portable.h" #include @@ -288,8 +242,8 @@ inValidate( Syntax *syntax, struct berval *in ) { - /* any value allowed */ - return LDAP_OTHER; + /* no value allowed */ + return LDAP_INVALID_SYNTAX; } static int @@ -534,6 +488,76 @@ booleanMatch( return LDAP_SUCCESS; } +/*------------------------------------------------------------------- +LDAP/X.500 string syntax / matching rules have a few oddities. This +comment attempts to detail how slapd(8) treats them. + +Summary: + StringSyntax X.500 LDAP Matching + DirectoryString CHOICE UTF8 i/e + ignore insignificant spaces + PrintableString subset subset i/e + ignore insignificant spaces + NumericString subset subset ignore all spaces + IA5String ASCII ASCII i/e + ignore insignificant spaces + TeletexString T.61 T.61 i/e + ignore insignificant spaces + + TelephoneNumber subset subset i + ignore all spaces and "-" + + See draft-ietf-ldapbis-strpro for details (once published). + + +Directory String - + In X.500(93), a directory string can be either a PrintableString, + a bmpString, or a UniversalString (e.g., UCS (a subset of Unicode)). + In later versions, more CHOICEs were added. In all cases the string + must be non-empty. + + In LDPAv3, a directory string is a UTF-8 encoded UCS string. + + For matching, there are both case ignore and exact rules. Both + also require that "insignificant" spaces be ignored. + spaces before the first non-space are ignored; + spaces after the last non-space are ignored; + spaces after a space are ignored. + Note: by these rules (and as clarified in X.520), a string of only + spaces is to be treated as if held one space, not empty (which + would be a syntax error). + +NumericString + In ASN.1, numeric string is just a string of digits and spaces + and could be empty. However, in X.500, all attribute values of + numeric string carry a non-empty constraint. For example: + + internationalISDNNumber ATTRIBUTE ::= { + WITH SYNTAX InternationalISDNNumber + EQUALITY MATCHING RULE numericStringMatch + SUBSTRINGS MATCHING RULE numericStringSubstringsMatch + ID id-at-internationalISDNNumber } + InternationalISDNNumber ::= + NumericString (SIZE(1..ub-international-isdn-number)) + + Unforunately, some assertion values are don't carry the same + constraint (but its unclear how such an assertion could ever + be true). In LDAP, there is one syntax (numericString) not two + (numericString with constraint, numericString without constraint). + This should be treated as numericString with non-empty constraint. + Note that while someone may have no ISDN number, there are no ISDN + numbers which are zero length. + + In matching, spaces are ignored. + +PrintableString + In ASN.1, Printable string is just a string of printable characters + and can be empty. In X.500, semantics much like NumericString (see + serialNumber for a like example) excepting uses insignificant space + handling instead of ignore all spaces. + +IA5String + Basically same as PrintableString. There are no examples in X.500, + but same logic applies. So we require them to be non-empty as + well. + +-------------------------------------------------------------------*/ + static int UTF8StringValidate( Syntax *syntax, @@ -597,6 +621,9 @@ UTF8StringNormalize( char *p, *q, *s, *e; int len = 0; + /* validator should have refused an empty string */ + assert( val->bv_len ); + p = val->bv_val; /* Ignore initial whitespace */ @@ -604,6 +631,12 @@ UTF8StringNormalize( for ( ; p < val->bv_val + val->bv_len && ASCII_SPACE( p[ 0 ] ); p++ ); normalized->bv_len = val->bv_len - (p - val->bv_val); + + if( !normalized->bv_len ) { + ber_mem2bv( " ", 1, 1, normalized ); + return LDAP_SUCCESS; + } + ber_mem2bv( p, normalized->bv_len, 1, normalized ); e = normalized->bv_val + normalized->bv_len; @@ -634,7 +667,7 @@ UTF8StringNormalize( assert( q+len <= p ); /* cannot start with a space */ - assert( !ASCII_SPACE(normalized->bv_val[0]) ); + assert( !ASCII_SPACE( normalized->bv_val[0] ) ); /* * If the string ended in space, backup the pointer one @@ -686,10 +719,12 @@ UTF8SubstringsassertionNormalize( for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) { /* empty */ } - nsa->sa_any = (struct berval *)ch_malloc( (i + 1) * sizeof(struct berval) ); + nsa->sa_any = (struct berval *) + ch_malloc( (i + 1) * sizeof(struct berval) ); + for( i=0; sa->sa_any[i].bv_val != NULL; i++ ) { UTF8bvnormalize( &sa->sa_any[i], &nsa->sa_any[i], - casefold ); + casefold ); if( nsa->sa_any[i].bv_val == NULL ) { goto err; } @@ -708,7 +743,7 @@ UTF8SubstringsassertionNormalize( err: if ( nsa->sa_final.bv_val ) free( nsa->sa_final.bv_val ); - if ( nsa->sa_any )ber_bvarray_free( nsa->sa_any ); + if ( nsa->sa_any ) ber_bvarray_free( nsa->sa_any ); if ( nsa->sa_initial.bv_val ) free( nsa->sa_initial.bv_val ); ch_free( nsa ); return NULL; @@ -745,7 +780,8 @@ approxMatch( } /* Yes, this is necessary */ - assertv = UTF8bvnormalize( ((struct berval *)assertedValue), NULL, LDAP_UTF8_APPROX ); + assertv = UTF8bvnormalize( ((struct berval *)assertedValue), + NULL, LDAP_UTF8_APPROX ); if( assertv == NULL ) { ber_bvfree( nval ); *matchp = 1; @@ -902,7 +938,8 @@ approxFilter( BerVarray keys; /* Yes, this is necessary */ - val = UTF8bvnormalize( ((struct berval *)assertValue), NULL, LDAP_UTF8_APPROX ); + val = UTF8bvnormalize( ((struct berval *)assertValue), + NULL, LDAP_UTF8_APPROX ); if( val == NULL || val->bv_val == NULL ) { keys = (struct berval *)ch_malloc( sizeof(struct berval) ); keys[0].bv_val = NULL; @@ -1729,15 +1766,25 @@ telephoneNumberNormalize( { char *p, *q; + /* validator should have refused an empty string */ + assert( val->bv_len ); + q = normalized->bv_val = ch_malloc( val->bv_len + 1 ); - for( p = val->bv_val; *p; p++ ) - if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) + for( p = val->bv_val; *p; p++ ) { + if ( ! ( ASCII_SPACE( *p ) || *p == '-' )) { *q++ = *p; + } + } *q = '\0'; normalized->bv_len = q - normalized->bv_val; + if( normalized->bv_len == 0 ) { + free( normalized->bv_val ); + return LDAP_INVALID_SYNTAX; + } + return LDAP_SUCCESS; } @@ -2039,6 +2086,8 @@ printableStringValidate( { ber_len_t i; + if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX; + for(i=0; i < val->bv_len; i++) { if( !SLAP_PRINTABLE(val->bv_val[i]) ) { return LDAP_INVALID_SYNTAX; @@ -2053,14 +2102,30 @@ printablesStringValidate( Syntax *syntax, struct berval *val ) { - ber_len_t i; + ber_len_t i, len; - for(i=0; i < val->bv_len; i++) { - if( !SLAP_PRINTABLES(val->bv_val[i]) ) { + if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX; + + for(i=0,len=0; i < val->bv_len; i++) { + int c = val->bv_val[i]; + + if( c == '$' ) { + if( len == 0 ) { + return LDAP_INVALID_SYNTAX; + } + len = 0; + + } else if ( SLAP_PRINTABLE(c) ) { + len++; + } else { return LDAP_INVALID_SYNTAX; } } + if( len == 0 ) { + return LDAP_INVALID_SYNTAX; + } + return LDAP_SUCCESS; } @@ -2071,6 +2136,8 @@ IA5StringValidate( { ber_len_t i; + if( val->bv_len == 0 ) return LDAP_INVALID_SYNTAX; + for(i=0; i < val->bv_len; i++) { if( !LDAP_ASCII(val->bv_val[i]) ) { return LDAP_INVALID_SYNTAX; @@ -2088,6 +2155,8 @@ IA5StringNormalize( { char *p, *q; + assert( val->bv_len ); + p = val->bv_val; /* Ignore initial whitespace */ @@ -2129,6 +2198,13 @@ IA5StringNormalize( normalized->bv_len = q - normalized->bv_val; + if( normalized->bv_len == 0 ) { + normalized->bv_val = ch_realloc( normalized->bv_val, 2 ); + normalized->bv_val[0] = ' '; + normalized->bv_val[1] = '\0'; + normalized->bv_len = 1; + } + return LDAP_SUCCESS; } @@ -3305,6 +3381,8 @@ numericStringValidate( { ber_len_t i; + if( in->bv_len == 0 ) return LDAP_INVALID_SYNTAX; + for(i=0; i < in->bv_len; i++) { if( !SLAP_NUMERIC(in->bv_val[i]) ) { return LDAP_INVALID_SYNTAX; @@ -3323,6 +3401,8 @@ numericStringNormalize( /* removal all spaces */ char *p, *q; + assert( val->bv_len ); + normalized->bv_val = ch_malloc( val->bv_len + 1 ); p = val->bv_val; @@ -3345,6 +3425,13 @@ numericStringNormalize( normalized->bv_len = q - normalized->bv_val; + if( normalized->bv_len == 0 ) { + normalized->bv_val = ch_realloc( normalized->bv_val, 2 ); + normalized->bv_val[0] = ' '; + normalized->bv_val[1] = '\0'; + normalized->bv_len = 1; + } + return LDAP_SUCCESS; } @@ -4179,19 +4266,10 @@ bootParameterValidate( return LDAP_SUCCESS; } -static struct syntax_defs_rec { - char *sd_desc; #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' " #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' " - int sd_flags; - slap_syntax_validate_func *sd_validate; - slap_syntax_transform_func *sd_normalize; - slap_syntax_transform_func *sd_pretty; -#ifdef SLAPD_BINARY_CONVERSION - slap_syntax_transform_func *sd_ber2str; - slap_syntax_transform_func *sd_str2ber; -#endif -} syntax_defs[] = { + +static slap_syntax_defs_rec syntax_defs[] = { {"( 1.3.6.1.4.1.1466.115.121.1.1 DESC 'ACI Item' " X_BINARY X_NOT_H_R ")", SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, NULL, NULL, NULL}, @@ -4369,17 +4447,7 @@ static struct syntax_defs_rec { * 2.5.13.43 readerAndKeyIDMatch * 2.5.13.44 attributeIntegrityMatch */ -static struct mrule_defs_rec { - char * mrd_desc; - slap_mask_t mrd_usage; - slap_mr_convert_func * mrd_convert; - slap_mr_normalize_func * mrd_normalize; - slap_mr_match_func * mrd_match; - slap_mr_indexer_func * mrd_indexer; - slap_mr_filter_func * mrd_filter; - - char * mrd_associated; -} mrule_defs[] = { +static slap_mrule_defs_rec mrule_defs[] = { /* * EQUALITY matching rules must be listed after associated APPROX * matching rules. So, we list all APPROX matching rules first. @@ -4688,17 +4756,7 @@ slap_schema_init( void ) assert( schema_init_done == 0 ); for ( i=0; syntax_defs[i].sd_desc != NULL; i++ ) { - res = register_syntax( syntax_defs[i].sd_desc, - syntax_defs[i].sd_flags, - syntax_defs[i].sd_validate, - syntax_defs[i].sd_normalize, - syntax_defs[i].sd_pretty -#ifdef SLAPD_BINARY_CONVERSION - , - syntax_defs[i].sd_ber2str, - syntax_defs[i].sd_str2ber -#endif - ); + res = register_syntax( &syntax_defs[i] ); if ( res ) { fprintf( stderr, "slap_schema_init: Error registering syntax %s\n", @@ -4715,15 +4773,7 @@ slap_schema_init( void ) continue; } - res = register_matching_rule( - mrule_defs[i].mrd_desc, - mrule_defs[i].mrd_usage, - mrule_defs[i].mrd_convert, - mrule_defs[i].mrd_normalize, - mrule_defs[i].mrd_match, - mrule_defs[i].mrd_indexer, - mrule_defs[i].mrd_filter, - mrule_defs[i].mrd_associated ); + res = register_matching_rule( &mrule_defs[i] ); if ( res ) { fprintf( stderr,