#define berValidate blobValidate
/* unimplemented pretters */
-#define dnPretty NULL
#define integerPretty NULL
+#ifndef USE_LDAP_DN_PARSING
+# define dnPretty NULL
+#else
+# define SLAP_LDAPDN_PRETTY 0x1
+#endif /* !USE_LDAP_DN_PARSING */
/* recycled matching routines */
#define bitStringMatch octetStringMatch
/* recycled indexing/filtering routines */
#define dnIndexer caseExactIgnoreIndexer
#define dnFilter caseExactIgnoreFilter
+#define bitStringFilter octetStringFilter
+#define bitStringIndexer octetStringIndexer
#define telephoneNumberIndexer caseIgnoreIA5Indexer
#define telephoneNumberFilter caseIgnoreIA5Filter
return LDAP_SUCCESS;
}
+#ifdef USE_LDAP_DN_PARSING
+static int
+dnValidate(
+ Syntax *syntax,
+ struct berval *in )
+{
+ int rc;
+ LDAPDN *dn = NULL;
+
+ if ( in->bv_len == 0 ) {
+ return( LDAP_SUCCESS );
+ }
+
+ rc = ldap_str2dn( in->bv_val, &dn, LDAP_DN_FORMAT_LDAP );
+
+ /*
+ * Fixme: should we also validate each DN component?
+ */
+ ldapava_free_dn( dn );
+
+ if ( rc != LDAP_SUCCESS ) {
+ return( LDAP_INVALID_SYNTAX );
+ }
+
+ return( LDAP_SUCCESS );
+}
+
+static void
+AVA_Sort( LDAPRDN *rdn, int iAVA )
+{
+ int i;
+ LDAPAVA *ava_in = rdn[ iAVA ][ 0 ];
+
+ for ( i = 0; i < iAVA; i++ ) {
+ LDAPAVA *ava = rdn[ i ][ 0 ];
+ int a, j;
+
+ a = strcmp( ava_in->la_attr->bv_val, ava->la_attr->bv_val );
+
+ if ( a > 0 ) {
+ break;
+ }
+
+ while ( a == 0 ) {
+ int v, d;
+
+ d = ava_in->la_value->bv_len - ava->la_value->bv_len;
+
+ v = memcmp( ava_in->la_value->bv_val,
+ ava->la_value->bv_val,
+ d <= 0 ? ava_in->la_value->bv_len
+ : ava->la_value->bv_len );
+
+ if ( v == 0 && d != 0 ) {
+ v = d;
+ }
+
+ if ( v <= 0 ) {
+ /*
+ * got it!
+ */
+ break;
+ }
+
+ if ( ++i == iAVA ) {
+ /*
+ * already sorted
+ */
+ return;
+ }
+
+ ava = rdn[ i ][ 0 ];
+ a = strcmp( ava_in->la_value->bv_val,
+ ava->la_value->bv_val );
+ }
+
+ /*
+ * move ahead
+ */
+ for ( j = iAVA; j > i; j-- ) {
+ rdn[ j ][ 0 ] = rdn[ j - 1 ][ 0 ];
+ }
+ rdn[ i ][ 0 ] = ava_in;
+
+ return;
+ }
+}
+
+/*
+ * In-place, schema-aware normalization / "pretty"ing of the
+ * structural representation of a distinguished name.
+ */
+static int
+LDAPDN_rewrite( LDAPDN *dn, unsigned flags )
+{
+ int iRDN;
+ int rc;
+
+ assert( dn );
+
+ for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) {
+ LDAPRDN *rdn = dn[ iRDN ][ 0 ];
+ int iAVA;
+
+ for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) {
+ LDAPAVA *ava = rdn[ iAVA ][ 0 ];
+ AttributeDescription *ad = NULL;
+ const char *text = NULL;
+ slap_syntax_transform_func *transf = NULL;
+ MatchingRule *mr;
+ struct berval *bv = NULL;
+
+ rc = slap_bv2ad( ava->la_attr, &ad, &text );
+ if ( rc != LDAP_SUCCESS ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ /*
+ * Replace attr oid/name with the canonical name
+ */
+ ber_bvfree( ava->la_attr );
+ ava->la_attr = ber_bvdup( &ad->ad_cname );
+
+ if( flags & SLAP_LDAPDN_PRETTY ) {
+ transf = ad->ad_type->sat_syntax->ssyn_pretty;
+ mr = NULL;
+ } else {
+ transf = ad->ad_type->sat_syntax->ssyn_normalize;
+ mr = ad->ad_type->sat_equality;
+ }
+
+ if ( transf ) {
+ /*
+ * transform value by normalize/pretty function
+ */
+ rc = ( *transf )( ad->ad_type->sat_syntax,
+ ava->la_value, &bv );
+
+ if ( rc != LDAP_SUCCESS ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ }
+
+ if( mr && ( mr->smr_usage & SLAP_MR_DN_FOLD ) ) {
+ struct berval *s = bv;
+
+ bv = ber_bvstr( UTF8normalize( bv ? bv : ava->la_value,
+ UTF8_CASEFOLD ) );
+
+ ber_bvfree( s );
+ }
+
+ if( bv ) {
+ ber_bvfree( ava->la_value );
+ ava->la_value = bv;
+ }
+
+ AVA_Sort( rdn, iAVA );
+ }
+ }
+
+ return LDAP_SUCCESS;
+}
+
+int
+dnNormalize(
+ Syntax *syntax,
+ struct berval *val,
+ struct berval **normalized )
+{
+ struct berval *out = NULL;
+
+ Debug( LDAP_DEBUG_TRACE, ">>> dnNormalize: <%s>\n", val->bv_val, 0, 0 );
+
+ if ( val->bv_len != 0 ) {
+ LDAPDN *dn = NULL;
+ char *dn_out = NULL;
+ int rc;
+
+ /*
+ * Go to structural representation
+ */
+ rc = ldap_str2dn( val->bv_val, &dn, LDAP_DN_FORMAT_LDAP );
+ if ( rc != LDAP_SUCCESS ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ /*
+ * Schema-aware rewrite
+ */
+ if ( LDAPDN_rewrite( dn, 0 ) != LDAP_SUCCESS ) {
+ ldapava_free_dn( dn );
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ /*
+ * Back to string representation
+ */
+ rc = ldap_dn2str( dn, &dn_out, LDAP_DN_FORMAT_LDAPV3 );
+
+ ldapava_free_dn( dn );
+
+ if ( rc != LDAP_SUCCESS ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ out = ber_bvstr( dn_out );
+
+ } else {
+ out = ber_bvdup( val );
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "<<< dnNormalize: <%s>\n", out->bv_val, 0, 0 );
+
+ *normalized = out;
+
+ return LDAP_SUCCESS;
+}
+
+int
+dnPretty(
+ Syntax *syntax,
+ struct berval *val,
+ struct berval **pretty)
+{
+ struct berval *out = NULL;
+
+ Debug( LDAP_DEBUG_TRACE, ">>> dnPretty: <%s>\n", val->bv_val, 0, 0 );
+
+ if ( val->bv_len != 0 ) {
+ LDAPDN *dn = NULL;
+ char *dn_out = NULL;
+ int rc;
+
+ /* FIXME: should be liberal in what we accept */
+ rc = ldap_str2dn( val->bv_val, &dn, LDAP_DN_FORMAT_LDAP );
+ if ( rc != LDAP_SUCCESS ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ /*
+ * Schema-aware rewrite
+ */
+ if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY ) != LDAP_SUCCESS ) {
+ ldapava_free_dn( dn );
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ /* FIXME: not sure why the default isn't pretty */
+ rc = ldap_dn2str( dn, &dn_out,
+ LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY );
+
+ ldapava_free_dn( dn );
+
+ if ( rc != LDAP_SUCCESS ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ out = ber_bvstr( dn_out );
+
+ } else {
+ out = ber_bvdup( val );
+ }
+
+ Debug( LDAP_DEBUG_TRACE, "<<< dnPretty: <%s>\n", out->bv_val, 0, 0 );
+
+ *pretty = out;
+
+ return LDAP_SUCCESS;
+}
+
+int
+dnMatch(
+ int *matchp,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *value,
+ void *assertedValue )
+{
+ int match;
+ struct berval *asserted = (struct berval *) assertedValue;
+
+ match = value->bv_len - asserted->bv_len;
+
+ if ( match == 0 ) {
+ match = strcmp( value->bv_val, asserted->bv_val );
+ }
+
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+ "dnMatch: %d\n %s\n %s\n", match,
+ value->bv_val, asserted->bv_val ));
+#else
+ Debug( LDAP_DEBUG_ARGS, "dnMatch %d\n\t\"%s\"\n\t\"%s\"\n",
+ match, value->bv_val, asserted->bv_val );
+#endif
+
+ *matchp = match;
+ return( LDAP_SUCCESS );
+}
+
+#else /* !USE_LDAP_DN_PARSING */
+
static int
dnValidate(
Syntax *syntax,
return LDAP_SUCCESS;
}
-static int
+int
dnMatch(
int *matchp,
slap_mask_t flags,
return LDAP_SUCCESS;
}
+#endif /* !USE_LDAP_DN_PARSING */
+
static int
nameUIDValidate(
Syntax *syntax,
return LDAP_INVALID_SYNTAX;
}
- if( in->bv_val[0] != 'B' ||
- in->bv_val[1] != '\'' ||
- in->bv_val[in->bv_len-1] != '\'' )
+ /*
+ * rfc 2252 section 6.3 Bit String
+ * bitstring = "'" *binary-digit "'"
+ * binary-digit = "0" / "1"
+ * example: '0101111101'B
+ */
+
+ if( in->bv_val[0] != '\'' ||
+ in->bv_val[in->bv_len-2] != '\'' ||
+ in->bv_val[in->bv_len-1] != 'B' )
{
return LDAP_INVALID_SYNTAX;
}
- for( i=in->bv_len-2; i>1; i-- ) {
+ for( i=in->bv_len-3; i>0; i-- ) {
if( in->bv_val[i] != '0' && in->bv_val[i] != '1' ) {
return LDAP_INVALID_SYNTAX;
}
return LDAP_SUCCESS;
}
+static int
+bitStringNormalize(
+ Syntax *syntax,
+ struct berval *val,
+ struct berval **normalized )
+{
+ /*
+ * A normalized bitString is has no extaneous (leading) zero bits.
+ * That is, '00010'B is normalized to '10'B
+ * However, as a special case, '0'B requires no normalization.
+ */
+ struct berval *newval;
+ char *p;
+
+ /* start at the first bit */
+ p = &val->bv_val[1];
+
+ /* Find the first non-zero bit */
+ while ( *p == '0' ) p++;
+
+ newval = (struct berval *) ch_malloc( sizeof(struct berval) );
+
+ if( *p == '\'' ) {
+ /* no non-zero bits */
+ newval->bv_val = ch_strdup("\'0\'B");
+ newval->bv_len = sizeof("\'0\'B") - 1;
+ goto done;
+ }
+
+ newval->bv_val = ch_malloc( val->bv_len + 1 );
+
+ newval->bv_val[0] = '\'';
+ newval->bv_len = 1;
+
+ for( ; *p != '\0'; p++ ) {
+ newval->bv_val[newval->bv_len++] = *p;
+ }
+
+ newval->bv_val[newval->bv_len] = '\0';
+
+done:
+ *normalized = newval;
+ return LDAP_SUCCESS;
+}
+
/*
* Handling boolean syntax and matching is quite rigid.
* A more flexible approach would be to allow a variety
void *assertedValue )
{
int match = 0;
- SubstringsAssertion *sub;
+ SubstringsAssertion *sub = NULL;
struct berval left;
int i;
ber_len_t inlen=0;
*/
while (base < n) {
unsigned int carry;
- unsigned int temp;
carry = 0;
for (i = base; i<n; i++ ) {
struct berval *serial;
struct berval *issuer_dn;
struct berval *bv_tmp;
- int ret;
xcert = d2i_X509(NULL, &p, in->bv_len);
if ( !xcert ) {
return LBER_ERROR_MEMORY;
}
- sprintf( out->bv_val, "%02ld%02ld%02ld%02ld%02ld%02ldZ",
+ sprintf( out->bv_val, "%02d%02d%02d%02d%02d%02dZ",
parts[1], parts[2] + 1, parts[3] + 1,
parts[4], parts[5], parts[6] );
out->bv_len = 13;
return LBER_ERROR_MEMORY;
}
- sprintf( out->bv_val, "%02ld%02ld%02ld%02ld%02ld%02ld%02ldZ",
+ sprintf( out->bv_val, "%02d%02d%02d%02d%02d%02d%02dZ",
parts[0], parts[1], parts[2] + 1, parts[3] + 1,
parts[4], parts[5], parts[6] );
out->bv_len = 15;
{"( 1.3.6.1.4.1.1466.115.121.1.5 DESC 'Binary' " X_NOT_H_R ")",
SLAP_SYNTAX_BER, berValidate, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.6 DESC 'Bit String' )",
- 0, bitStringValidate, NULL, NULL },
+ 0, bitStringValidate, bitStringNormalize, NULL },
{"( 1.3.6.1.4.1.1466.115.121.1.7 DESC 'Boolean' )",
0, booleanValidate, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.8 DESC 'Certificate' "
/* OpenLDAP Experimental Syntaxes */
{"( 1.3.6.1.4.1.4203.666.2.1 DESC 'OpenLDAP Experimental ACI' )",
- 0, UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
+ SLAP_SYNTAX_HIDE,
+ UTF8StringValidate /* THIS WILL CHANGE FOR NEW ACI SYNTAX */,
NULL, NULL},
+
+ /* needs updating */
{"( 1.3.6.1.4.1.4203.666.2.2 DESC 'OpenLDAP authPassword' )",
- 0, NULL, NULL, NULL},
+ SLAP_SYNTAX_HIDE, NULL, NULL, NULL},
/* OpenLDAP Void Syntax */
{"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
{"( 2.5.13.2 NAME 'caseIgnoreMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
- SLAP_MR_EQUALITY | SLAP_MR_EXT,
+ SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
NULL, NULL,
caseIgnoreMatch, caseExactIgnoreIndexer, caseExactIgnoreFilter,
directoryStringApproxMatchOID },
{"( 2.5.13.8 NAME 'numericStringMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
- SLAP_MR_EQUALITY | SLAP_MR_EXT,
+ SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
NULL, NULL,
caseIgnoreIA5Match,
caseIgnoreIA5Indexer,
{"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
- SLAP_MR_EQUALITY | SLAP_MR_EXT,
+ SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
NULL, NULL,
caseIgnoreListMatch, NULL, NULL,
NULL},
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT,
NULL, NULL,
- bitStringMatch, NULL, NULL,
+ bitStringMatch, bitStringIndexer, bitStringFilter,
NULL},
{"( 2.5.13.17 NAME 'octetStringMatch' "
{"( 2.5.13.20 NAME 'telephoneNumberMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.50 )",
- SLAP_MR_EQUALITY | SLAP_MR_EXT,
+ SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
NULL, NULL,
telephoneNumberMatch,
telephoneNumberIndexer,
{"( 1.3.6.1.4.1.1466.109.114.2 NAME 'caseIgnoreIA5Match' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
- SLAP_MR_EQUALITY | SLAP_MR_EXT,
+ SLAP_MR_EQUALITY | SLAP_MR_EXT | SLAP_MR_DN_FOLD,
NULL, NULL,
caseIgnoreIA5Match, caseIgnoreIA5Indexer, caseIgnoreIA5Filter,
IA5StringApproxMatchOID },
caseExactIA5SubstringsFilter,
NULL},
+ /* 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,