X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fschema_init.c;h=8369a43204a121943b7c366f538d7e1168b5e2fe;hb=b0b3eff457f0e431c4fd094d3d9cfeb6383df91d;hp=d76eb84c01495e19646e4c7d4dc9dc612f9528b7;hpb=5cd994ed215904a7e3ec2d1561df05a2e4bf53f4;p=openldap diff --git a/servers/slapd/schema_init.c b/servers/slapd/schema_init.c index d76eb84c01..8369a43204 100644 --- a/servers/slapd/schema_init.c +++ b/servers/slapd/schema_init.c @@ -1,8 +1,17 @@ /* schema_init.c - init builtin schema */ /* $OpenLDAP$ */ -/* - * Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved. - * COPYING RESTRICTIONS APPLY, see COPYRIGHT file +/* This work is part of OpenLDAP Software . + * + * Copyright 1998-2003 The OpenLDAP Foundation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . */ #include "portable.h" @@ -21,6 +30,18 @@ #include "ldap_utf8.h" +#ifdef HAVE_TLS +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + #include "lutil_hash.h" #define HASH_BYTES LUTIL_HASH_BYTES #define HASH_CONTEXT lutil_HASH_CTX @@ -28,27 +49,17 @@ #define HASH_Update(c,buf,len) lutil_HASHUpdate(c,buf,len) #define HASH_Final(d,c) lutil_HASHFinal(d,c) -#define SLAP_NVALUES 1 - -/* not yet implemented */ -#define uniqueMemberMatch NULL - #define OpenLDAPaciMatch NULL /* approx matching rules */ -#ifdef SLAP_NVALUES -#define directoryStringApproxMatchOID NULL -#define IA5StringApproxMatchOID NULL -#else #define directoryStringApproxMatchOID "1.3.6.1.4.1.4203.666.4.4" -#define directoryStringApproxMatch approxMatch +#define directoryStringApproxMatch approxMatch #define directoryStringApproxIndexer approxIndexer -#define directoryStringApproxFilter approxFilter +#define directoryStringApproxFilter approxFilter #define IA5StringApproxMatchOID "1.3.6.1.4.1.4203.666.4.5" #define IA5StringApproxMatch approxMatch #define IA5StringApproxIndexer approxIndexer #define IA5StringApproxFilter approxFilter -#endif static int inValidate( @@ -70,6 +81,33 @@ blobValidate( #define berValidate blobValidate +static int +sequenceValidate( + Syntax *syntax, + struct berval *in ) +{ + if ( in->bv_len < 2 ) return LDAP_INVALID_SYNTAX; + if ( in->bv_val[0] != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX; + + return LDAP_SUCCESS; +} + + +#ifdef HAVE_TLS +static int certificateValidate( Syntax *syntax, struct berval *in ) +{ + X509 *xcert=NULL; + unsigned char *p = in->bv_val; + + xcert = d2i_X509(NULL, &p, in->bv_len); + if ( !xcert ) return LDAP_INVALID_SYNTAX; + X509_free(xcert); + return LDAP_SUCCESS; +} +#else +#define certificateValidate sequenceValidate +#endif + static int octetStringMatch( int *matchp, @@ -739,6 +777,87 @@ nameUIDValidate( return rc; } +int +nameUIDPretty( + Syntax *syntax, + struct berval *val, + struct berval *out, + void *ctx ) +{ + assert( val ); + assert( out ); + + +#ifdef NEW_LOGGING + LDAP_LOG( OPERATION, ARGS, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, ">>> nameUIDPretty: <%s>\n", val->bv_val, 0, 0 ); +#endif + + if( val->bv_len == 0 ) { + ber_dupbv_x( out, val, ctx ); + + } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) { + return LDAP_INVALID_SYNTAX; + + } else { + int rc; + struct berval dnval = *val; + struct berval uidval = { 0, NULL }; + + if( val->bv_val[val->bv_len-1] == 'B' + && val->bv_val[val->bv_len-2] == '\'' ) + { + uidval.bv_val=strrchr( val->bv_val, '#' ); + if( uidval.bv_val ) { + dnval.bv_len = uidval.bv_val - dnval.bv_val; + uidval.bv_len = val->bv_len - dnval.bv_len; + + uidval.bv_len--; + uidval.bv_val++; + } + } + + rc = dnPretty( syntax, &dnval, out, ctx ); + if( rc != LDAP_SUCCESS ) return rc; + + if( uidval.bv_val ) { + char *tmp = sl_realloc( out->bv_val, out->bv_len + uidval.bv_len + 2, ctx ); + int i, c, got1; + if( tmp == NULL ) { + ber_memfree_x( out->bv_val, ctx ); + return LDAP_OTHER; + } + out->bv_val = tmp; + out->bv_val[out->bv_len++] = '#'; + + got1 = uidval.bv_len < sizeof("'0'B"); + for(i=0; ibv_val[out->bv_len++] = c; + break; + case '1': + got1 = 1; + default: + out->bv_val[out->bv_len++] = c; + } + } + + out->bv_val[out->bv_len] = '\0'; + } + } + +#ifdef NEW_LOGGING + LDAP_LOG( OPERATION, ARGS, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, "<<< nameUIDPretty: <%s>\n", out->bv_val, 0, 0 ); +#endif + + return LDAP_SUCCESS; +} + static int uniqueMemberNormalize( slap_mask_t usage, @@ -751,6 +870,8 @@ uniqueMemberNormalize( struct berval out; int rc; + assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage )); + ber_dupbv( &out, val ); if( out.bv_len != 0 ) { struct berval uid = { 0, NULL }; @@ -802,6 +923,77 @@ uniqueMemberNormalize( return LDAP_SUCCESS; } +static int +uniqueMemberMatch( + int *matchp, + slap_mask_t flags, + Syntax *syntax, + MatchingRule *mr, + struct berval *value, + void *assertedValue ) +{ + int match; + struct berval *asserted = (struct berval *) assertedValue; + struct berval assertedDN = { 0, NULL }; + struct berval assertedUID = { 0, NULL }; + struct berval valueDN = { 0, NULL }; + struct berval valueUID = { 0, NULL }; + + if( asserted->bv_len != 0 ) { + assertedDN = *asserted; + + if( assertedDN.bv_val[assertedDN.bv_len-1] == 'B' + && assertedDN.bv_val[assertedDN.bv_len-2] == '\'' ) + { + /* assume presence of optional UID */ + assertedUID.bv_val = strrchr( assertedDN.bv_val, '#' ); + + if( assertedUID.bv_val == NULL ) { + return LDAP_INVALID_SYNTAX; + } + + assertedUID.bv_len = assertedDN.bv_len - + (assertedUID.bv_val - assertedDN.bv_val); + assertedDN.bv_len -= assertedUID.bv_len--; + + /* trim the separator */ + assertedUID.bv_val++; + } + } + + if( value->bv_len != 0 ) { + valueDN = *value; + + if( valueDN.bv_val[valueDN.bv_len-1] == 'B' + && valueDN.bv_val[valueDN.bv_len-2] == '\'' ) + { + /* assume presence of optional UID */ + valueUID.bv_val = strrchr( valueDN.bv_val, '#' ); + + if( valueUID.bv_val == NULL ) { + return LDAP_INVALID_SYNTAX; + } + + valueUID.bv_len = valueDN.bv_len - + (assertedUID.bv_val - assertedDN.bv_val); + valueDN.bv_len -= valueUID.bv_len--; + + /* trim the separator */ + valueUID.bv_val++; + } + } + + if( valueUID.bv_len && assertedUID.bv_len ) { + match = memcmp( valueUID.bv_val, assertedUID.bv_val, valueUID.bv_len ); + if( match ) { + *matchp = match; + return LDAP_SUCCESS; + } + } + + return dnMatch( matchp, flags, syntax, mr, &valueDN, &assertedDN ); +} + /* * Handling boolean syntax and matching is quite rigid. * A more flexible approach would be to allow a variety @@ -989,6 +1181,8 @@ UTF8StringNormalize( int flags; int i, wasspace; + assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use )); + if( val->bv_val == NULL ) { /* assume we're dealing with a syntax (e.g., UTF8String) * which allows empty strings @@ -1043,15 +1237,12 @@ UTF8StringNormalize( return LDAP_SUCCESS; } -#ifndef SLAP_NVALUES - -#ifndef SLAPD_APPROX_OLDSINGLESTRING #if defined(SLAPD_APPROX_INITIALS) -#define SLAPD_APPROX_DELIMITER "._ " -#define SLAPD_APPROX_WORDLEN 2 +# define SLAPD_APPROX_DELIMITER "._ " +# define SLAPD_APPROX_WORDLEN 2 #else -#define SLAPD_APPROX_DELIMITER " " -#define SLAPD_APPROX_WORDLEN 1 +# define SLAPD_APPROX_DELIMITER " " +# define SLAPD_APPROX_WORDLEN 1 #endif static int @@ -1068,7 +1259,7 @@ approxMatch( int i, count, len, nextchunk=0, nextavail=0; /* Yes, this is necessary */ - nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX ); + nval = UTF8bvnormalize( value, NULL, LDAP_UTF8_APPROX, NULL ); if( nval == NULL ) { *matchp = 1; return LDAP_SUCCESS; @@ -1076,7 +1267,7 @@ approxMatch( /* Yes, this is necessary */ assertv = UTF8bvnormalize( ((struct berval *)assertedValue), - NULL, LDAP_UTF8_APPROX ); + NULL, LDAP_UTF8_APPROX, NULL ); if( assertv == NULL ) { ber_bvfree( nval ); *matchp = 1; @@ -1171,7 +1362,8 @@ approxIndexer( MatchingRule *mr, struct berval *prefix, BerVarray values, - BerVarray *keysp ) + BerVarray *keysp, + void *ctx ) { char *c; int i,j, len, wordcount, keycount=0; @@ -1181,7 +1373,7 @@ approxIndexer( for( j=0; values[j].bv_val != NULL; j++ ) { struct berval val = { 0, NULL }; /* Yes, this is necessary */ - UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX ); + UTF8bvnormalize( &values[j], &val, LDAP_UTF8_APPROX, NULL ); assert( val.bv_val != NULL ); /* Isolate how many words there are. There will be a key for each */ @@ -1225,7 +1417,8 @@ approxFilter( MatchingRule *mr, struct berval *prefix, void * assertedValue, - BerVarray *keysp ) + BerVarray *keysp, + void *ctx ) { char *c; int i, count, len; @@ -1234,7 +1427,7 @@ approxFilter( /* Yes, this is necessary */ val = UTF8bvnormalize( ((struct berval *)assertedValue), - NULL, LDAP_UTF8_APPROX ); + NULL, LDAP_UTF8_APPROX, NULL ); if( val == NULL || val->bv_val == NULL ) { keys = (struct berval *)ch_malloc( sizeof(struct berval) ); keys[0].bv_val = NULL; @@ -1271,122 +1464,6 @@ approxFilter( return LDAP_SUCCESS; } -#else -/* No other form of Approximate Matching is defined */ - -static int -approxMatch( - int *matchp, - slap_mask_t flags, - Syntax *syntax, - MatchingRule *mr, - struct berval *value, - void *assertedValue ) -{ - char *vapprox, *avapprox; - char *s, *t; - - /* Yes, this is necessary */ - s = UTF8normalize( value, UTF8_NOCASEFOLD ); - if( s == NULL ) { - *matchp = 1; - return LDAP_SUCCESS; - } - - /* Yes, this is necessary */ - t = UTF8normalize( ((struct berval *)assertedValue), - UTF8_NOCASEFOLD ); - if( t == NULL ) { - free( s ); - *matchp = -1; - return LDAP_SUCCESS; - } - - vapprox = phonetic( strip8bitChars( s ) ); - avapprox = phonetic( strip8bitChars( t ) ); - - free( s ); - free( t ); - - *matchp = strcmp( vapprox, avapprox ); - - ch_free( vapprox ); - ch_free( avapprox ); - - return LDAP_SUCCESS; -} - -static int -approxIndexer( - slap_mask_t use, - slap_mask_t flags, - Syntax *syntax, - MatchingRule *mr, - struct berval *prefix, - BerVarray values, - BerVarray *keysp ) -{ - int i; - BerVarray *keys; - char *s; - - for( i=0; values[i].bv_val != NULL; i++ ) { - /* empty - just count them */ - } - - /* we should have at least one value at this point */ - assert( i > 0 ); - - keys = (struct berval *)ch_malloc( sizeof( struct berval ) * (i+1) ); - - /* Copy each value and run it through phonetic() */ - for( i=0; values[i].bv_val != NULL; i++ ) { - /* Yes, this is necessary */ - s = UTF8normalize( &values[i], UTF8_NOCASEFOLD ); - - /* strip 8-bit chars and run through phonetic() */ - ber_str2bv( phonetic( strip8bitChars( s ) ), 0, 0, &keys[i] ); - free( s ); - } - keys[i].bv_val = NULL; - - *keysp = keys; - return LDAP_SUCCESS; -} - -static int -approxFilter( - slap_mask_t use, - slap_mask_t flags, - Syntax *syntax, - MatchingRule *mr, - struct berval *prefix, - void * assertedValue, - BerVarray *keysp ) -{ - BerVarray keys; - char *s; - - keys = (struct berval *)ch_malloc( sizeof( struct berval * ) * 2 ); - - /* Yes, this is necessary */ - s = UTF8normalize( ((struct berval *)assertedValue), - UTF8_NOCASEFOLD ); - if( s == NULL ) { - keys[0] = NULL; - } else { - /* strip 8-bit chars and run through phonetic() */ - keys[0] = ber_bvstr( phonetic( strip8bitChars( s ) ) ); - free( s ); - keys[1] = NULL; - } - - *keysp = keys; - return LDAP_SUCCESS; -} -#endif -#endif /* !SLAP_NVALUES */ - /* Remove all spaces and '-' characters */ static int telephoneNumberNormalize( @@ -1399,6 +1476,8 @@ telephoneNumberNormalize( { char *p, *q; + assert( SLAP_MR_IS_VALUE_OF_SYNTAX( usage )); + /* validator should have refused an empty string */ assert( val->bv_len ); @@ -1415,6 +1494,7 @@ telephoneNumberNormalize( if( normalized->bv_len == 0 ) { sl_free( normalized->bv_val, ctx ); + normalized->bv_val = NULL; return LDAP_INVALID_SYNTAX; } @@ -1643,10 +1723,12 @@ IA5StringNormalize( void *ctx ) { char *p, *q; - int casefold = SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match); + int casefold = !SLAP_MR_ASSOCIATED(mr, slap_schema.si_mr_caseExactIA5Match); assert( val->bv_len ); + assert( SLAP_MR_IS_VALUE_OF_SYNTAX( use )); + p = val->bv_val; /* Ignore initial whitespace */ @@ -1697,6 +1779,86 @@ IA5StringNormalize( return LDAP_SUCCESS; } +static int +UUIDValidate( + Syntax *syntax, + struct berval *in ) +{ + int i; + if( in->bv_len != 36 ) { + assert(0); + return LDAP_INVALID_SYNTAX; + } + + for( i=0; i<36; i++ ) { + switch(i) { + case 8: + case 13: + case 18: + case 23: + if( in->bv_val[i] != '-' ) { + return LDAP_INVALID_SYNTAX; + } + break; + default: + if( !ASCII_HEX( in->bv_val[i]) ) { + return LDAP_INVALID_SYNTAX; + } + } + } + + return LDAP_SUCCESS; +} + +static int +UUIDNormalize( + slap_mask_t usage, + Syntax *syntax, + MatchingRule *mr, + struct berval *val, + struct berval *normalized, + void *ctx ) +{ + unsigned char octet; + int i; + int j; + normalized->bv_len = 16; + normalized->bv_val = sl_malloc( normalized->bv_len+1, ctx ); + + for( i=0, j=0; i<36; i++ ) { + unsigned char nibble; + if( val->bv_val[i] == '-' ) { + continue; + + } else if( ASCII_DIGIT( val->bv_val[i] ) ) { + nibble = val->bv_val[i] - '0'; + + } else if( ASCII_HEXLOWER( val->bv_val[i] ) ) { + nibble = val->bv_val[i] - ('a'-10); + + } else if( ASCII_HEXUPPER( val->bv_val[i] ) ) { + nibble = val->bv_val[i] - ('A'-10); + + } else { + sl_free( normalized->bv_val, ctx ); + return LDAP_INVALID_SYNTAX; + } + + if( j & 1 ) { + octet |= nibble; + normalized->bv_val[j>>1] = octet; + } else { + octet = nibble << 4; + } + j++; + } + + normalized->bv_val[normalized->bv_len] = 0; + return LDAP_SUCCESS; +} + + + static int numericStringValidate( Syntax *syntax, @@ -1761,6 +1923,22 @@ numericStringNormalize( return LDAP_SUCCESS; } +/* + * Integer conversion macros that will use the largest available + * type. + */ +#if defined(HAVE_STRTOLL) && defined(LLONG_MAX) && defined(LLONG_MIN) && defined(HAVE_LONG_LONG) +# define SLAP_STRTOL(n,e,b) strtoll(n,e,b) +# define SLAP_LONG_MAX LLONG_MAX +# define SLAP_LONG_MIN LLONG_MIN +# define SLAP_LONG long long +#else +# define SLAP_STRTOL(n,e,b) strtol(n,e,b) +# define SLAP_LONG_MAX LONG_MAX +# define SLAP_LONG_MIN LONG_MIN +# define SLAP_LONG long +#endif /* HAVE_STRTOLL ... */ + static int integerBitAndMatch( int *matchp, @@ -1770,16 +1948,16 @@ integerBitAndMatch( struct berval *value, void *assertedValue ) { - long lValue, lAssertedValue; + SLAP_LONG lValue, lAssertedValue; /* safe to assume integers are NUL terminated? */ - lValue = strtol(value->bv_val, NULL, 10); - if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) { + lValue = SLAP_STRTOL(value->bv_val, NULL, 10); + if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX) && errno == ERANGE ) { return LDAP_CONSTRAINT_VIOLATION; } - lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10); - if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX) + lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, NULL, 10); + if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) && errno == ERANGE ) { return LDAP_CONSTRAINT_VIOLATION; @@ -1798,16 +1976,16 @@ integerBitOrMatch( struct berval *value, void *assertedValue ) { - long lValue, lAssertedValue; + SLAP_LONG lValue, lAssertedValue; /* safe to assume integers are NUL terminated? */ - lValue = strtol(value->bv_val, NULL, 10); - if(( lValue == LONG_MIN || lValue == LONG_MAX) && errno == ERANGE ) { + lValue = SLAP_STRTOL(value->bv_val, NULL, 10); + if(( lValue == SLAP_LONG_MIN || lValue == SLAP_LONG_MAX ) && errno == ERANGE ) { return LDAP_CONSTRAINT_VIOLATION; } - lAssertedValue = strtol(((struct berval *)assertedValue)->bv_val, NULL, 10); - if(( lAssertedValue == LONG_MIN || lAssertedValue == LONG_MAX) + lAssertedValue = SLAP_STRTOL(((struct berval *)assertedValue)->bv_val, NULL, 10); + if(( lAssertedValue == SLAP_LONG_MIN || lAssertedValue == SLAP_LONG_MAX ) && errno == ERANGE ) { return LDAP_CONSTRAINT_VIOLATION; @@ -1817,538 +1995,458 @@ integerBitOrMatch( return LDAP_SUCCESS; } -#ifndef SLAP_NVALUES -#ifdef HAVE_TLS -#include -#include +static int +serialNumberAndIssuerValidate( + Syntax *syntax, + struct berval *in ) +{ + int rc; + int state; + ber_len_t n; + struct berval sn, i; + if( in->bv_len < 3 ) return LDAP_INVALID_SYNTAX; -/* - * Next function returns a string representation of a ASN1_INTEGER. - * It works for unlimited lengths. - */ + i.bv_val = strchr( in->bv_val, '$' ); + if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX; -static struct berval * -asn1_integer2str(ASN1_INTEGER *a, struct berval *bv) -{ - char buf[256]; - char *p; - static char digit[] = "0123456789"; - - /* We work backwards, make it fill from the end of buf */ - p = buf + sizeof(buf) - 1; - *p = '\0'; + sn.bv_val = in->bv_val; + sn.bv_len = i.bv_val - in->bv_val; - if ( a == NULL || a->length == 0 ) { - *--p = '0'; - } else { - int i; - int n = a->length; - int base = 0; - unsigned int *copy; + i.bv_val++; + i.bv_len = in->bv_len - (sn.bv_len + 1); - /* We want to preserve the original */ - copy = ch_malloc(n*sizeof(unsigned int)); - for (i = 0; idata[i]; - } - - /* - * base indicates the index of the most significant - * byte that might be nonzero. When it goes off the - * end, we now there is nothing left to do. - */ - while (base < n) { - unsigned int carry; - - carry = 0; - for (i = base; itype == V_ASN1_NEG_INTEGER ) { - *--p = '-'; - } + /* validate DN */ + rc = dnValidate( NULL, &i ); + if( rc ) return LDAP_INVALID_SYNTAX; - return ber_str2bv( p, 0, 1, bv ); + return LDAP_SUCCESS; } -/* - * Given a certificate in DER format, extract the corresponding - * assertion value for certificateExactMatch - */ -static int -certificateExactConvert( - struct berval * in, - struct berval * out ) +int +serialNumberAndIssuerPretty( + Syntax *syntax, + struct berval *val, + struct berval *out, + void *ctx ) { - X509 *xcert; - unsigned char *p = in->bv_val; - struct berval serial; - struct berval issuer_dn; + int rc; + int state; + ber_len_t n; + struct berval sn, i, newi; + + assert( val ); + assert( out ); - xcert = d2i_X509(NULL, &p, in->bv_len); - if ( !xcert ) { #ifdef NEW_LOGGING - LDAP_LOG( CONFIG, ENTRY, - "certificateExactConvert: error parsing cert: %s\n", - ERR_error_string(ERR_get_error(),NULL), 0, 0 ); + LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerPretty: <%s>\n", + val->bv_val, 0, 0 ); #else - Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: " - "error parsing cert: %s\n", - ERR_error_string(ERR_get_error(),NULL), NULL, NULL ); + Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerPretty: <%s>\n", + val->bv_val, 0, 0 ); #endif - return LDAP_INVALID_SYNTAX; - } - if ( !asn1_integer2str(xcert->cert_info->serialNumber, &serial) ) { - X509_free(xcert); - return LDAP_INVALID_SYNTAX; + if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX; + + i.bv_val = strchr( val->bv_val, '$' ); + if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX; + + sn.bv_val = val->bv_val; + sn.bv_len = i.bv_val - val->bv_val; + + i.bv_val++; + i.bv_len = val->bv_len - (sn.bv_len + 1); + + /* eat leading zeros */ + for( n=0; n < (sn.bv_len-1); n++ ) { + if( sn.bv_val[n] != '0' ) break; } - if ( dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn ) - != LDAP_SUCCESS ) - { - X509_free(xcert); - ber_memfree(serial.bv_val); - return LDAP_INVALID_SYNTAX; + sn.bv_val += n; + sn.bv_len -= n; + + for( n=0; n < sn.bv_len; n++ ) { + if( !ASCII_DIGIT(sn.bv_val[n]) ) { + return LDAP_INVALID_SYNTAX; + } } - X509_free(xcert); + /* pretty DN */ + rc = dnPretty( syntax, &i, &newi, ctx ); + if( rc ) return LDAP_INVALID_SYNTAX; - out->bv_len = serial.bv_len + issuer_dn.bv_len + sizeof(" $ "); - out->bv_val = ch_malloc(out->bv_len); - p = out->bv_val; - AC_MEMCPY(p, serial.bv_val, serial.bv_len); - p += serial.bv_len; - AC_MEMCPY(p, " $ ", sizeof(" $ ")-1); - p += 3; - AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len); - p += issuer_dn.bv_len; - *p++ = '\0'; + /* make room from sn + "$" */ + out->bv_len = sn.bv_len + newi.bv_len + 1; + out->bv_val = sl_realloc( newi.bv_val, out->bv_len + 1, ctx ); + + if( out->bv_val == NULL ) { + sl_free( newi.bv_val, ctx ); + return LDAP_OTHER; + } + + /* push issuer over */ + AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len ); + /* insert sn and "$" */ + AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len ); + out->bv_val[sn.bv_len] = '$'; + /* terminate */ + out->bv_val[out->bv_len] = '\0'; #ifdef NEW_LOGGING - LDAP_LOG( CONFIG, ARGS, - "certificateExactConvert: \n %s\n", out->bv_val, 0, 0 ); + LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerPretty: <%s>\n", + out->bv_val, 0, 0 ); #else - Debug( LDAP_DEBUG_ARGS, "certificateExactConvert " - "\n\t\"%s\"\n", - out->bv_val, NULL, NULL ); + Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerPretty: <%s>\n", + out->bv_val, 0, 0 ); #endif - ber_memfree(serial.bv_val); - ber_memfree(issuer_dn.bv_val); - return LDAP_SUCCESS; } +/* + * This routine is called by certificateExactNormalize when + * certificateExactNormalize receives a search string instead of + * a certificate. This routine checks if the search value is valid + * and then returns the normalized value + */ static int -serial_and_issuer_parse( - struct berval *assertion, - struct berval *serial, - struct berval *issuer_dn ) +serialNumberAndIssuerNormalize( + slap_mask_t usage, + Syntax *syntax, + MatchingRule *mr, + struct berval *val, + struct berval *out, + void *ctx ) { - char *begin; - char *end; - char *p; - struct berval bv; - - begin = assertion->bv_val; - end = assertion->bv_val+assertion->bv_len-1; - for (p=begin; p<=end && *p != '$'; p++) /* empty */ ; - if ( p > end ) return LDAP_INVALID_SYNTAX; - - /* p now points at the $ sign, now use - * begin and end to delimit the serial number - */ - while (ASCII_SPACE(*begin)) begin++; - end = p-1; - while (ASCII_SPACE(*end)) end--; + int rc; + int state; + ber_len_t n; + struct berval sn, i, newi; - if( end <= begin ) return LDAP_INVALID_SYNTAX; + assert( val ); + assert( out ); + +#ifdef NEW_LOGGING + LDAP_LOG( OPERATION, ARGS, ">>> serialNumberAndIssuerNormalize: <%s>\n", + val->bv_val, 0, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, ">>> serialNumberAndIssuerNormalize: <%s>\n", + val->bv_val, 0, 0 ); +#endif - bv.bv_len = end-begin+1; - bv.bv_val = begin; - ber_dupbv(serial, &bv); + if( val->bv_len < 3 ) return LDAP_INVALID_SYNTAX; - /* now extract the issuer, remember p was at the dollar sign */ - begin = p+1; - end = assertion->bv_val+assertion->bv_len-1; - while (ASCII_SPACE(*begin)) begin++; - /* should we trim spaces at the end too? is it safe always? no, no */ + i.bv_val = strchr( val->bv_val, '$' ); + if( i.bv_val == NULL ) return LDAP_INVALID_SYNTAX; - if( end <= begin ) return LDAP_INVALID_SYNTAX; + sn.bv_val = val->bv_val; + sn.bv_len = i.bv_val - val->bv_val; - if ( issuer_dn ) { - bv.bv_len = end-begin+1; - bv.bv_val = begin; + i.bv_val++; + i.bv_len = val->bv_len - (sn.bv_len + 1); - return dnNormalize( 0, NULL, NULL, &bv, issuer_dn ); + /* eat leading zeros */ + for( n=0; n < (sn.bv_len-1); n++ ) { + if( sn.bv_val[n] != '0' ) break; } + sn.bv_val += n; + sn.bv_len -= n; - return LDAP_SUCCESS; -} - -static int -certificateExactMatch( - int *matchp, - slap_mask_t flags, - Syntax *syntax, - MatchingRule *mr, - struct berval *value, - void *assertedValue ) -{ - X509 *xcert; - unsigned char *p = value->bv_val; - struct berval serial; - struct berval issuer_dn; - struct berval asserted_serial; - struct berval asserted_issuer_dn; - int ret; - - xcert = d2i_X509(NULL, &p, value->bv_len); - if ( !xcert ) { -#ifdef NEW_LOGGING - LDAP_LOG( CONFIG, ENTRY, - "certificateExactMatch: error parsing cert: %s\n", - ERR_error_string(ERR_get_error(),NULL), 0, 0 ); -#else - Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: " - "error parsing cert: %s\n", - ERR_error_string(ERR_get_error(),NULL), NULL, NULL ); -#endif - return LDAP_INVALID_SYNTAX; + for( n=0; n < sn.bv_len; n++ ) { + if( !ASCII_DIGIT(sn.bv_val[n]) ) { + return LDAP_INVALID_SYNTAX; + } } - asn1_integer2str(xcert->cert_info->serialNumber, &serial); - dnX509normalize(X509_get_issuer_name(xcert), &issuer_dn); + /* pretty DN */ + rc = dnNormalize( usage, syntax, mr, &i, &newi, ctx ); + if( rc ) return LDAP_INVALID_SYNTAX; - X509_free(xcert); + /* make room from sn + "$" */ + out->bv_len = sn.bv_len + newi.bv_len + 1; + out->bv_val = sl_realloc( newi.bv_val, out->bv_len + 1, ctx ); - serial_and_issuer_parse(assertedValue, - &asserted_serial, &asserted_issuer_dn); - - ret = integerMatch( - matchp, - flags, - slap_schema.si_syn_integer, - slap_schema.si_mr_integerMatch, - &serial, - &asserted_serial); - if ( ret == LDAP_SUCCESS ) { - if ( *matchp == 0 ) { - /* We need to normalize everything for dnMatch */ - ret = dnMatch( - matchp, - flags, - slap_schema.si_syn_distinguishedName, - slap_schema.si_mr_distinguishedNameMatch, - &issuer_dn, - &asserted_issuer_dn); - } + if( out->bv_val == NULL ) { + sl_free( newi.bv_val, ctx ); + return LDAP_OTHER; } + /* push issuer over */ + AC_MEMCPY( &out->bv_val[sn.bv_len+1], newi.bv_val, newi.bv_len ); + /* insert sn and "$" */ + AC_MEMCPY( out->bv_val, sn.bv_val, sn.bv_len ); + out->bv_val[sn.bv_len] = '$'; + /* terminate */ + out->bv_val[out->bv_len] = '\0'; + #ifdef NEW_LOGGING - LDAP_LOG( CONFIG, ARGS, "certificateExactMatch " - "%d\n\t\"%s $ %s\"\n", - *matchp, serial.bv_val, issuer_dn.bv_val ); - LDAP_LOG( CONFIG, ARGS, "\t\"%s $ %s\"\n", - asserted_serial.bv_val, asserted_issuer_dn.bv_val, - 0 ); + LDAP_LOG( OPERATION, ARGS, "<<< serialNumberAndIssuerNormalize: <%s>\n", + out->bv_val, 0, 0 ); #else - Debug( LDAP_DEBUG_ARGS, "certificateExactMatch " - "%d\n\t\"%s $ %s\"\n", - *matchp, serial.bv_val, issuer_dn.bv_val ); - Debug( LDAP_DEBUG_ARGS, "\t\"%s $ %s\"\n", - asserted_serial.bv_val, asserted_issuer_dn.bv_val, - NULL ); + Debug( LDAP_DEBUG_TRACE, "<<< serialNumberAndIssuerNormalize: <%s>\n", + out->bv_val, 0, 0 ); #endif - ber_memfree(serial.bv_val); - ber_memfree(issuer_dn.bv_val); - ber_memfree(asserted_serial.bv_val); - ber_memfree(asserted_issuer_dn.bv_val); - - return ret; + return rc; } -/* - * Index generation function - * We just index the serials, in most scenarios the issuer DN is one of - * a very small set of values. - */ -static int certificateExactIndexer( - slap_mask_t use, - slap_mask_t flags, +#ifdef HAVE_TLS +static int +certificateExactNormalize( + slap_mask_t usage, Syntax *syntax, MatchingRule *mr, - struct berval *prefix, - BerVarray values, - BerVarray *keysp ) + struct berval *val, + struct berval *normalized, + void *ctx ) { - int i; - BerVarray keys; - X509 *xcert; + int rc = LDAP_INVALID_SYNTAX; unsigned char *p; - struct berval serial; + char *serial = NULL; + ber_len_t seriallen; + struct berval issuer_dn = { 0, NULL }; + X509_NAME *name = NULL; + ASN1_INTEGER *sn = NULL; + X509 *xcert = NULL; - /* we should have at least one value at this point */ - assert( values != NULL && values[0].bv_val != NULL ); + if( val->bv_len == 0 ) goto done; - for( i=0; values[i].bv_val != NULL; i++ ) { - /* empty -- just count them */ + if( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) { + return serialNumberAndIssuerNormalize(0,NULL,NULL,val,normalized,ctx); } - keys = ch_malloc( sizeof( struct berval ) * (i+1) ); + assert( SLAP_MR_IS_VALUE_OF_ATTRIBUTE_SYNTAX(usage) ); - for( i=0; values[i].bv_val != NULL; i++ ) { - p = values[i].bv_val; - xcert = d2i_X509(NULL, &p, values[i].bv_len); - if ( !xcert ) { -#ifdef NEW_LOGGING - LDAP_LOG( CONFIG, ENTRY, - "certificateExactIndexer: error parsing cert: %s\n", - ERR_error_string(ERR_get_error(),NULL), 0, 0); -#else - Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: " - "error parsing cert: %s\n", - ERR_error_string(ERR_get_error(),NULL), - NULL, NULL ); -#endif - /* Do we leak keys on error? */ - return LDAP_INVALID_SYNTAX; - } + p = val->bv_val; + xcert = d2i_X509( NULL, &p, val->bv_len); + if( xcert == NULL ) goto done; + + sn=X509_get_serialNumber(xcert); + if ( sn == NULL ) goto done; + serial=i2s_ASN1_INTEGER(0, sn ); + if( serial == NULL ) goto done; + seriallen=strlen(serial); + + name=X509_get_issuer_name(xcert); + if( name == NULL ) goto done; + rc = dnX509normalize( name, &issuer_dn ); + if( rc != LDAP_SUCCESS ) goto done; + + normalized->bv_len = seriallen + issuer_dn.bv_len + 1; + p = normalized->bv_val = ch_malloc(normalized->bv_len+1); + AC_MEMCPY(p, serial, seriallen); + p += seriallen; + *p++ = '$'; + AC_MEMCPY(p, issuer_dn.bv_val, issuer_dn.bv_len); + p += issuer_dn.bv_len; + *p = '\0'; - asn1_integer2str(xcert->cert_info->serialNumber, &serial); - X509_free(xcert); - xintegerNormalize( slap_schema.si_syn_integer, - &serial, &keys[i] ); - ber_memfree(serial.bv_val); #ifdef NEW_LOGGING - LDAP_LOG( CONFIG, ENTRY, - "certificateExactIndexer: returning: %s\n", keys[i].bv_val, 0, 0); + LDAP_LOG( CONFIG, ARGS, "certificateExactNormalize: %s\n", + normalized->bv_val, 0, 0 ); #else - Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: " - "returning: %s\n", - keys[i].bv_val, - NULL, NULL ); + Debug( LDAP_DEBUG_TRACE, "certificateExactNormalize: %s\n", + normalized->bv_val, NULL, NULL ); #endif - } - keys[i].bv_val = NULL; - *keysp = keys; - return LDAP_SUCCESS; -} - -/* Index generation function */ -/* We think this is always called with a value in matching rule syntax */ -static int certificateExactFilter( - slap_mask_t use, - slap_mask_t flags, - Syntax *syntax, - MatchingRule *mr, - struct berval *prefix, - void * assertedValue, - BerVarray *keysp ) -{ - BerVarray keys; - struct berval asserted_serial; - int ret; +done: + if (xcert) X509_free(xcert); + if (serial) ch_free(serial); + if (issuer_dn.bv_val) ber_memfree(issuer_dn.bv_val); - ret = serial_and_issuer_parse( assertedValue, &asserted_serial, NULL ); - if( ret != LDAP_SUCCESS ) return ret; + return rc; +} +#endif /* HAVE_TLS */ - keys = ch_malloc( sizeof( struct berval ) * 2 ); - xintegerNormalize( syntax, &asserted_serial, &keys[0] ); - keys[1].bv_val = NULL; - *keysp = keys; - ber_memfree(asserted_serial.bv_val); - return LDAP_SUCCESS; -} -#endif +#ifndef SUPPORT_OBSOLETE_UTC_SYNTAX +/* slight optimization - does not need the start parameter */ +#define check_time_syntax(v, start, p, f) (check_time_syntax)(v, p, f) +enum { start = 0 }; #endif static int check_time_syntax (struct berval *val, int start, - int *parts) + int *parts, + struct berval *fraction) { - static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 }; - static int mdays[2][12] = { + /* + * start=0 GeneralizedTime YYYYmmddHH[MM[SS]][(./,)d...](Z|(+/-)HH[MM]) + * start=1 UTCTime YYmmddHHMM[SS][Z|(+/-)HHMM] + * GeneralizedTime supports leap seconds, UTCTime does not. + */ + static const int ceiling[9] = { 100, 100, 12, 31, 24, 60, 60, 24, 60 }; + static const int mdays[2][12] = { /* non-leap years */ - { 30, 27, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 }, + { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, /* leap years */ - { 30, 28, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30 } + { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } }; char *p, *e; - int part, c, tzoffset, leapyear = 0 ; + int part, c, c1, c2, tzoffset, leapyear = 0; - if( val->bv_len == 0 ) { - return LDAP_INVALID_SYNTAX; - } - - p = (char *)val->bv_val; + p = val->bv_val; e = p + val->bv_len; - /* Ignore initial whitespace */ - while ( ( p < e ) && ASCII_SPACE( *p ) ) { - p++; - } - - if (e - p < 13 - (2 * start)) { - return LDAP_INVALID_SYNTAX; - } - - for (part = 0; part < 9; part++) { - parts[part] = 0; - } - - for (part = start; part < 7; part++) { - c = *p; - if ((part == 6) && (c == 'Z' || c == '+' || c == '-')) { - part++; +#ifdef SUPPORT_OBSOLETE_UTC_SYNTAX + parts[0] = 20; /* century - any multiple of 4 from 04 to 96 */ +#endif + for (part = start; part < 7 && p < e; part++) { + c1 = *p; + if (!ASCII_DIGIT(c1)) { break; } p++; - c -= '0'; if (p == e) { return LDAP_INVALID_SYNTAX; } - if (c < 0 || c > 9) { + c = *p++; + if (!ASCII_DIGIT(c)) { return LDAP_INVALID_SYNTAX; } - parts[part] = c; - - c = *p++ - '0'; - if (p == e) { - return LDAP_INVALID_SYNTAX; - } - if (c < 0 || c > 9) { - return LDAP_INVALID_SYNTAX; - } - parts[part] *= 10; - parts[part] += c; - - if (part == 2 || part == 3) { - parts[part]--; - } - if (parts[part] < 0) { - return LDAP_INVALID_SYNTAX; + c += c1 * 10 - '0' * 11; + if ((part | 1) == 3) { + --c; + if (c < 0) { + return LDAP_INVALID_SYNTAX; + } } - if (parts[part] > ceiling[part]) { - return LDAP_INVALID_SYNTAX; + if (c >= ceiling[part]) { + if (! (c == 60 && part == 6 && start == 0)) + return LDAP_INVALID_SYNTAX; } + parts[part] = c; + } + if (part < 5 + start) { + return LDAP_INVALID_SYNTAX; + } + for (; part < 9; part++) { + parts[part] = 0; } /* leapyear check for the Gregorian calendar (year>1581) */ - if (((parts[1] % 4 == 0) && (parts[1] != 0)) || - ((parts[0] % 4 == 0) && (parts[1] == 0))) + if (parts[parts[1] == 0 ? 0 : 1] % 4 == 0) { leapyear = 1; } - if (parts[3] > mdays[leapyear][parts[2]]) { + if (parts[3] >= mdays[leapyear][parts[2]]) { return LDAP_INVALID_SYNTAX; } - - c = *p++; - if (c == 'Z') { - tzoffset = 0; /* UTC */ - } else if (c != '+' && c != '-') { - return LDAP_INVALID_SYNTAX; - } else { - if (c == '-') { - tzoffset = -1; - } else /* c == '+' */ { - tzoffset = 1; - } - - if (p > e - 4) { - return LDAP_INVALID_SYNTAX; - } - for (part = 7; part < 9; part++) { - c = *p++ - '0'; - if (c < 0 || c > 9) { - return LDAP_INVALID_SYNTAX; - } - parts[part] = c; - - c = *p++ - '0'; - if (c < 0 || c > 9) { - return LDAP_INVALID_SYNTAX; - } - parts[part] *= 10; - parts[part] += c; - if (parts[part] < 0 || parts[part] > ceiling[part]) { + if (start == 0) { + fraction->bv_val = p; + fraction->bv_len = 0; + if (p < e && (*p == '.' || *p == ',')) { + char *end_num; + while (++p < e && ASCII_DIGIT(*p)) + ; + if (p - fraction->bv_val == 1) { return LDAP_INVALID_SYNTAX; } + for (end_num = p; end_num[-1] == '0'; --end_num) + ; + c = end_num - fraction->bv_val; + if (c != 1) + fraction->bv_len = c; } } - /* Ignore trailing whitespace */ - while ( ( p < e ) && ASCII_SPACE( *p ) ) { - p++; - } - if (p != e) { - return LDAP_INVALID_SYNTAX; + if (p == e) { + /* no time zone */ + return start == 0 ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS; } - switch ( tzoffset ) { - case -1: /* negativ offset to UTC, ie west of Greenwich */ - parts[4] += parts[7]; - parts[5] += parts[8]; - for (part = 6; --part > 0; ) { /* offset is just hhmm, no seconds */ - if (part != 3) { - c = ceiling[part]; - } else { - c = mdays[leapyear][parts[2]]; + tzoffset = *p++; + switch (tzoffset) { + default: + return LDAP_INVALID_SYNTAX; + case 'Z': + /* UTC */ + break; + case '+': + case '-': + for (part = 7; part < 9 && p < e; part++) { + c1 = *p; + if (!ASCII_DIGIT(c1)) { + break; + } + p++; + if (p == e) { + return LDAP_INVALID_SYNTAX; } - if (parts[part] > c) { - parts[part] -= c + 1; - parts[part - 1]++; + c2 = *p++; + if (!ASCII_DIGIT(c2)) { + return LDAP_INVALID_SYNTAX; + } + parts[part] = c1 * 10 + c2 - '0' * 11; + if (parts[part] >= ceiling[part]) { + return LDAP_INVALID_SYNTAX; } } - break; - case 1: /* positive offset to UTC, ie east of Greenwich */ - parts[4] -= parts[7]; - parts[5] -= parts[8]; - for (part = 6; --part > 0; ) { - if (part != 3) { - c = ceiling[part]; - } else { - /* first arg to % needs to be non negativ */ - c = mdays[leapyear][(parts[2] - 1 + 12) % 12]; + if (part < 8 + start) { + return LDAP_INVALID_SYNTAX; + } + + if (tzoffset == '-') { + /* negative offset to UTC, ie west of Greenwich */ + parts[4] += parts[7]; + parts[5] += parts[8]; + /* offset is just hhmm, no seconds */ + for (part = 6; --part >= 0; ) { + if (part != 3) { + c = ceiling[part]; + } else { + c = mdays[leapyear][parts[2]]; + } + if (parts[part] >= c) { + if (part == 0) { + return LDAP_INVALID_SYNTAX; + } + parts[part] -= c; + parts[part - 1]++; + continue; + } else if (part != 5) { + break; + } } - if (parts[part] < 0) { - parts[part] += c + 1; - parts[part - 1]--; + } else { + /* positive offset to UTC, ie east of Greenwich */ + parts[4] -= parts[7]; + parts[5] -= parts[8]; + for (part = 6; --part >= 0; ) { + if (parts[part] < 0) { + if (part == 0) { + return LDAP_INVALID_SYNTAX; + } + if (part != 3) { + c = ceiling[part]; + } else { + /* make first arg to % non-negative */ + c = mdays[leapyear][(parts[2] - 1 + 12) % 12]; + } + parts[part] += c; + parts[part - 1]--; + continue; + } else if (part != 5) { + break; + } } } - break; - case 0: /* already UTC */ - break; } - return LDAP_SUCCESS; + return p != e ? LDAP_INVALID_SYNTAX : LDAP_SUCCESS; } #ifdef SUPPORT_OBSOLETE_UTC_SYNTAX + +#if 0 static int xutcTimeNormalize( Syntax *syntax, @@ -2357,7 +2455,7 @@ xutcTimeNormalize( { int parts[9], rc; - rc = check_time_syntax(val, 1, parts); + rc = check_time_syntax(val, 1, parts, NULL); if (rc != LDAP_SUCCESS) { return rc; } @@ -2374,6 +2472,7 @@ xutcTimeNormalize( return LDAP_SUCCESS; } +#endif /* 0 */ static int utcTimeValidate( @@ -2381,9 +2480,10 @@ utcTimeValidate( struct berval *in ) { int parts[9]; - return check_time_syntax(in, 1, parts); + return check_time_syntax(in, 1, parts, NULL); } -#endif + +#endif /* SUPPORT_OBSOLETE_UTC_SYNTAX */ static int generalizedTimeValidate( @@ -2391,7 +2491,8 @@ generalizedTimeValidate( struct berval *in ) { int parts[9]; - return check_time_syntax(in, 0, parts); + struct berval fraction; + return check_time_syntax(in, 0, parts, &fraction); } static int @@ -2404,25 +2505,56 @@ generalizedTimeNormalize( void *ctx ) { int parts[9], rc; + unsigned int len; + struct berval fraction; - rc = check_time_syntax(val, 0, parts); + rc = check_time_syntax(val, 0, parts, &fraction); if (rc != LDAP_SUCCESS) { return rc; } - normalized->bv_val = sl_malloc( 16, ctx ); + len = sizeof("YYYYmmddHHMMSSZ")-1 + fraction.bv_len; + normalized->bv_val = sl_malloc( len + 1, ctx ); if ( normalized->bv_val == NULL ) { return LBER_ERROR_MEMORY; } - sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ", + sprintf( normalized->bv_val, "%02d%02d%02d%02d%02d%02d%02d", parts[0], parts[1], parts[2] + 1, parts[3] + 1, parts[4], parts[5], parts[6] ); - normalized->bv_len = 15; + if ( fraction.bv_len ) { + memcpy( normalized->bv_val + sizeof("YYYYmmddHHMMSSZ")-2, + fraction.bv_val, fraction.bv_len ); + normalized->bv_val[sizeof("YYYYmmddHHMMSSZ")-2] = '.'; + } + strcpy( normalized->bv_val + len-1, "Z" ); + normalized->bv_len = len; return LDAP_SUCCESS; } +static int +generalizedTimeOrderingMatch( + int *matchp, + slap_mask_t flags, + Syntax *syntax, + MatchingRule *mr, + struct berval *value, + void *assertedValue ) +{ + struct berval *asserted = (struct berval *) assertedValue; + ber_len_t v_len = value->bv_len; + ber_len_t av_len = asserted->bv_len; + + /* ignore trailing 'Z' when comparing */ + int match = memcmp( value->bv_val, asserted->bv_val, + (v_len < av_len ? v_len : av_len) - 1 ); + if ( match == 0 ) match = v_len - av_len; + + *matchp = match; + return LDAP_SUCCESS; +} + static int nisNetgroupTripleValidate( Syntax *syntax, @@ -2568,6 +2700,7 @@ firstComponentNormalize( return rc; } + #define X_BINARY "X-BINARY-TRANSFER-REQUIRED 'TRUE' " #define X_NOT_H_R "X-NOT-HUMAN-READABLE 'TRUE' " @@ -2591,13 +2724,13 @@ static slap_syntax_defs_rec syntax_defs[] = { 0, booleanValidate, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' " X_BINARY X_NOT_H_R ")", - SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL}, + SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, certificateValidate, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.9 DESC 'Certificate List' " X_BINARY X_NOT_H_R ")", - SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL}, + SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.10 DESC 'Certificate Pair' " X_BINARY X_NOT_H_R ")", - SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, berValidate, NULL}, + SLAP_SYNTAX_BINARY|SLAP_SYNTAX_BER, sequenceValidate, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.11 DESC 'Country String' )", 0, countryStringValidate, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )", @@ -2643,7 +2776,7 @@ static slap_syntax_defs_rec syntax_defs[] = { {"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )", 0, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )", - 0, nameUIDValidate, NULL}, + 0, nameUIDValidate, nameUIDPretty }, {"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )", 0, NULL, NULL}, {"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )", @@ -2697,18 +2830,14 @@ static slap_syntax_defs_rec syntax_defs[] = { {"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )", 0, bootParameterValidate, NULL}, -#ifdef HAVE_TLS - /* From PKIX */ - /* These OIDs are not published yet, but will be in the next - * I-D for PKIX LDAPv3 schema as have been advanced by David - * Chadwick in private mail. - */ - {"( 1.2.826.0.1.3344810.7.1 DESC 'Serial Number and Issuer' )", - 0, UTF8StringValidate, NULL}, -#endif + /* From PKIX *//* This OID is not published yet. */ + {"( 1.2.826.0.1.3344810.7.1 DESC 'Certificate Serial Number and Issuer' )", + SLAP_SYNTAX_HIDE, + serialNumberAndIssuerValidate, + serialNumberAndIssuerPretty}, - /* OpenLDAP Experimental Syntaxes */ #ifdef SLAPD_ACI_ENABLED + /* OpenLDAP Experimental Syntaxes */ {"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )", SLAP_SYNTAX_HIDE, UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */, @@ -2721,18 +2850,19 @@ static slap_syntax_defs_rec syntax_defs[] = { SLAP_SYNTAX_HIDE, NULL, NULL}, #endif + {"( 1.3.6.1.4.1.4203.666.2.6 DESC 'UUID' )", + SLAP_SYNTAX_HIDE, UUIDValidate, NULL}, + /* OpenLDAP Void Syntax */ {"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" , SLAP_SYNTAX_HIDE, inValidate, NULL}, {NULL, 0, NULL, NULL} }; -#ifdef HAVE_TLS char *certificateExactMatchSyntaxes[] = { "1.3.6.1.4.1.1466.115.121.1.8" /* certificate */, NULL }; -#endif char *directoryStringSyntaxes[] = { "1.3.6.1.4.1.1466.115.121.1.44" /* printableString */, NULL @@ -2763,7 +2893,6 @@ char *objectIdentifierFirstComponentMatchSyntaxes[] = { * 2.5.13.31 directoryStringFirstComponentMatch * 2.5.13.32 wordMatch * 2.5.13.33 keywordMatch - * 2.5.13.35 certificateMatch * 2.5.13.36 certificatePairExactMatch * 2.5.13.37 certificatePairMatch * 2.5.13.38 certificateListExactMatch @@ -2779,7 +2908,6 @@ 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. */ -#ifndef SLAP_NVALUES {"( " directoryStringApproxMatchOID " NAME 'directoryStringApproxMatch' " "SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )", SLAP_MR_HIDE | SLAP_MR_EQUALITY_APPROX | SLAP_MR_EXT, NULL, @@ -2793,7 +2921,6 @@ static slap_mrule_defs_rec mrule_defs[] = { NULL, NULL, IA5StringApproxMatch, IA5StringApproxIndexer, IA5StringApproxFilter, NULL}, -#endif /* * Other matching rules @@ -2971,7 +3098,7 @@ static slap_mrule_defs_rec mrule_defs[] = { {"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' " "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )", SLAP_MR_ORDERING, NULL, - NULL, generalizedTimeNormalize, octetStringOrderingMatch, + NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch, NULL, NULL, "generalizedTimeMatch" }, @@ -2991,16 +3118,27 @@ static slap_mrule_defs_rec mrule_defs[] = { octetStringIndexer, octetStringFilter, NULL }, -#ifndef SLAP_NVALUES -#ifdef HAVE_TLS {"( 2.5.13.34 NAME 'certificateExactMatch' " "SYNTAX 1.2.826.0.1.3344810.7.1 )", SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes, - certificateExactConvert, NULL, certificateExactMatch, - certificateExactIndexer, certificateExactFilter, - NULL }, +#ifdef HAVE_TLS + NULL, certificateExactNormalize, octetStringMatch, + octetStringIndexer, octetStringFilter, +#else + NULL, NULL, NULL, NULL, NULL, #endif + NULL }, + + {"( 2.5.13.35 NAME 'certificateMatch' " + "SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )", + SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL, +#ifdef HAVE_TLS + NULL, NULL, octetStringMatch, + octetStringIndexer, octetStringFilter, +#else + NULL, NULL, NULL, NULL, NULL, #endif + NULL }, {"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' " "SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )", @@ -3034,7 +3172,7 @@ static slap_mrule_defs_rec mrule_defs[] = { /* needs updating */ {"( 1.3.6.1.4.1.4203.666.4.1 NAME 'authPasswordMatch' " "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", - SLAP_MR_EQUALITY, NULL, + SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL, NULL, NULL, authPasswordMatch, NULL, NULL, NULL}, @@ -3043,7 +3181,7 @@ static slap_mrule_defs_rec mrule_defs[] = { #ifdef SLAPD_ACI_ENABLED {"( 1.3.6.1.4.1.4203.666.4.2 NAME 'OpenLDAPaciMatch' " "SYNTAX 1.3.6.1.4.1.4203.666.2.1 )", - SLAP_MR_EQUALITY, NULL, + SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL, NULL, NULL, OpenLDAPaciMatch, NULL, NULL, NULL}, @@ -3063,6 +3201,20 @@ static slap_mrule_defs_rec mrule_defs[] = { NULL, NULL, "integerMatch" }, + {"( 1.3.6.1.4.1.4203.666.4.6 NAME 'UUIDMatch' " + "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )", + SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL, + NULL, UUIDNormalize, octetStringMatch, + octetStringIndexer, octetStringFilter, + NULL}, + + {"( 1.3.6.1.4.1.4203.666.4.7 NAME 'UUIDOrderingMatch' " + "SYNTAX 1.3.6.1.4.1.4203.666.2.6 )", + SLAP_MR_HIDE | SLAP_MR_ORDERING, NULL, + NULL, UUIDNormalize, octetStringOrderingMatch, + octetStringIndexer, octetStringFilter, + "UUIDMatch"}, + {NULL, SLAP_MR_NONE, NULL, NULL, NULL, NULL, NULL, NULL, NULL }