/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 1998-2009 The OpenLDAP Foundation.
+ * Copyright 1998-2012 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* <http://www.OpenLDAP.org/license.html>.
*/
+/*
+ * Syntaxes - implementation notes:
+ *
+ * Validate function(syntax, value):
+ * Called before the other functions here to check if the value
+ * is valid according to the syntax.
+ *
+ * Pretty function(syntax, input value, output prettified...):
+ * If it exists, maps different notations of the same value to a
+ * unique representation which can be stored in the directory and
+ * possibly be passed to the Match/Indexer/Filter() functions.
+ *
+ * E.g. DN "2.5.4.3 = foo\,bar, o = BAZ" -> "cn=foo\2Cbar,o=BAZ",
+ * but unlike DN normalization, "BAZ" is not mapped to "baz".
+ */
+
+/*
+ * Matching rules - implementation notes:
+ *
+ * Matching rules match an attribute value (often from the directory)
+ * against an asserted value (e.g. from a filter).
+ *
+ * Invoked with validated and commonly pretty/normalized arguments, thus
+ * a number of matching rules can simply use the octetString functions.
+ *
+ * Normalize function(...input value, output normalized...):
+ * If it exists, maps matching values to a unique representation
+ * which is passed to the Match/Indexer/Filter() functions.
+ *
+ * Different matching rules can normalize values of the same syntax
+ * differently. E.g. caseIgnore rules normalize to lowercase,
+ * caseExact rules do not.
+ *
+ * Match function(*output matchp, ...value, asserted value):
+ * On success, set *matchp. 0 means match. For ORDERING/most EQUALITY,
+ * less/greater than 0 means value less/greater than asserted. However:
+ *
+ * In extensible match filters, ORDERING rules match if value<asserted.
+ *
+ * EQUALITY rules may order values differently than ORDERING rules for
+ * speed, since EQUALITY ordering is only used for SLAP_AT_SORTED_VAL.
+ * Some EQUALITY rules do not order values (ITS#6722).
+ *
+ * Indexer function(...attribute values, *output keysp,...):
+ * Generates index keys for the attribute values. Backends can store
+ * them in an index, a {key->entry ID set} mapping, for the attribute.
+ *
+ * A search can look up the DN/scope and asserted values in the
+ * indexes, if any, to narrow down the number of entires to check
+ * against the search criteria.
+ *
+ * Filter function(...asserted value, *output keysp,...):
+ * Generates index key(s) for the asserted value, to be looked up in
+ * the index from the Indexer function. *keysp is an array because
+ * substring matching rules can generate multiple lookup keys.
+ *
+ * Index keys:
+ * A key is usually a hash of match type, attribute value and schema
+ * info, because one index can contain keys for many filtering types.
+ *
+ * Some indexes instead have EQUALITY keys ordered so that if
+ * key(val1) < key(val2), then val1 < val2 by the ORDERING rule.
+ * That way the ORDERING rule can use the EQUALITY index.
+ *
+ * Substring indexing:
+ * This chops the attribute values up in small chunks and indexes all
+ * possible chunks of certain sizes. Substring filtering looks up
+ * SOME of the asserted value's chunks, and the caller uses the
+ * intersection of the resulting entry ID sets.
+ * See the index_substr_* keywords in slapd.conf(5).
+ */
+
#include "portable.h"
#include <stdio.h>
unsigned int index_intlen_strlen = SLAP_INDEX_INTLEN_STRLEN(
SLAP_INDEX_INTLEN_DEFAULT );
+ldap_pvt_thread_mutex_t ad_index_mutex;
ldap_pvt_thread_mutex_t ad_undef_mutex;
ldap_pvt_thread_mutex_t oc_undef_mutex;
}
/* X.509 certificate list validation */
+static int
+checkTime( struct berval *in, struct berval *out );
+
static int
certificateListValidate( Syntax *syntax, struct berval *in )
{
BerElementBuffer berbuf;
BerElement *ber = (BerElement *)&berbuf;
ber_tag_t tag;
- ber_len_t len;
+ ber_len_t len, wrapper_len;
+ char *wrapper_start;
+ int wrapper_ok = 0;
ber_int_t version = SLAP_X509_V1;
+ struct berval bvdn, bvtu;
ber_init2( ber, in, LBER_USE_DER );
- tag = ber_skip_tag( ber, &len ); /* Signed wrapper */
+ tag = ber_skip_tag( ber, &wrapper_len ); /* Signed wrapper */
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+ wrapper_start = ber->ber_ptr;
tag = ber_skip_tag( ber, &len ); /* Sequence */
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
tag = ber_peek_tag( ber, &len );
tag = ber_skip_tag( ber, &len ); /* Signature Algorithm */
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
- tag = ber_skip_tag( ber, &len ); /* Issuer DN */
+ tag = ber_peek_tag( ber, &len ); /* Issuer DN */
if ( tag != LBER_SEQUENCE ) return LDAP_INVALID_SYNTAX;
+ len = ber_ptrlen( ber );
+ bvdn.bv_val = in->bv_val + len;
+ bvdn.bv_len = in->bv_len - len;
+ tag = ber_skip_tag( ber, &len );
ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len ); /* thisUpdate */
/* Time is a CHOICE { UTCTime, GeneralizedTime } */
if ( tag != SLAP_TAG_UTCTIME && tag != SLAP_TAG_GENERALIZEDTIME ) return LDAP_INVALID_SYNTAX;
+ bvtu.bv_val = (char *)ber->ber_ptr;
+ bvtu.bv_len = len;
ber_skip_data( ber, len );
/* Optional nextUpdate */
tag = ber_skip_tag( ber, &len );
/* revokedCertificates - Sequence of Sequence, Optional */
if ( tag == LBER_SEQUENCE ) {
ber_len_t seqlen;
- if ( ber_peek_tag( ber, &seqlen ) == LBER_SEQUENCE ) {
- /* Should NOT be empty */
- ber_skip_data( ber, len );
+ ber_tag_t stag;
+ stag = ber_peek_tag( ber, &seqlen );
+ if ( stag == LBER_SEQUENCE || !len ) {
+ /* RFC5280 requires non-empty, but X.509(2005) allows empty. */
+ if ( len )
+ ber_skip_data( ber, len );
tag = ber_skip_tag( ber, &len );
}
}
/* Signature */
if ( tag != LBER_BITSTRING ) return LDAP_INVALID_SYNTAX;
ber_skip_data( ber, len );
+ if ( ber->ber_ptr == wrapper_start + wrapper_len ) wrapper_ok = 1;
tag = ber_skip_tag( ber, &len );
/* Must be at end now */
/* NOTE: OpenSSL tolerates CL with garbage past the end */
- if ( len || tag != LBER_DEFAULT ) return LDAP_INVALID_SYNTAX;
+ if ( len || tag != LBER_DEFAULT ) {
+ struct berval issuer_dn = BER_BVNULL, thisUpdate;
+ char tubuf[STRLENOF("YYYYmmddHHMMSSZ") + 1];
+ int rc;
+
+ if ( ! wrapper_ok ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ rc = dnX509normalize( &bvdn, &issuer_dn );
+ if ( rc != LDAP_SUCCESS ) {
+ rc = LDAP_INVALID_SYNTAX;
+ goto done;
+ }
+
+ thisUpdate.bv_val = tubuf;
+ thisUpdate.bv_len = sizeof(tubuf);
+ if ( checkTime( &bvtu, &thisUpdate ) ) {
+ rc = LDAP_INVALID_SYNTAX;
+ goto done;
+ }
+
+ Debug( LDAP_DEBUG_ANY,
+ "certificateListValidate issuer=\"%s\", thisUpdate=%s: extra cruft past end of certificateList\n",
+ issuer_dn.bv_val, thisUpdate.bv_val, 0 );
+
+done:;
+ if ( ! BER_BVISNULL( &issuer_dn ) ) {
+ ber_memfree( issuer_dn.bv_val );
+ }
+
+ return rc;
+ }
+
return LDAP_SUCCESS;
}
void *assertedValue )
{
struct berval *asserted = (struct berval *) assertedValue;
- int match = value->bv_len - asserted->bv_len;
+ ber_slen_t d = (ber_slen_t) value->bv_len - (ber_slen_t) asserted->bv_len;
- if( match == 0 ) {
- match = memcmp( value->bv_val, asserted->bv_val, value->bv_len );
- }
+ /* For speed, order first by length, then by contents */
+ *matchp = d ? (sizeof(d) == sizeof(int) ? d : d < 0 ? -1 : 1)
+ : memcmp( value->bv_val, asserted->bv_val, value->bv_len );
- *matchp = match;
return LDAP_SUCCESS;
}
int match = memcmp( value->bv_val, asserted->bv_val,
(v_len < av_len ? v_len : av_len) );
- if( match == 0 ) match = v_len - av_len;
+ if( match == 0 )
+ match = sizeof(v_len) == sizeof(int)
+ ? (int) v_len - (int) av_len
+ : v_len < av_len ? -1 : v_len > av_len;
+
+ /* If used in extensible match filter, match if value < asserted */
+ if ( flags & SLAP_MR_EXT )
+ match = (match >= 0);
*matchp = match;
return LDAP_SUCCESS;
}
+/* Initialize HASHcontext from match type and schema info */
static void
hashPreset(
HASH_CONTEXT *HASHcontext,
return;
}
+/* Set HASHdigest from HASHcontext and value:len */
static void
hashIter(
HASH_CONTEXT *HASHcontext,
HASH_Final( HASHdigest, &ctx );
}
-/* Index generation function */
+/* Index generation function: Attribute values -> index hash keys */
int octetStringIndexer(
slap_mask_t use,
slap_mask_t flags,
return LDAP_SUCCESS;
}
-/* Index generation function */
+/* Index generation function: Asserted value -> index hash key */
int octetStringFilter(
slap_mask_t use,
slap_mask_t flags,
return LDAP_SUCCESS;
}
-/* Substrings Index generation function */
+/* Substring index generation function: Attribute values -> index hash keys */
static int
octetStringSubstringsIndexer(
slap_mask_t use,
return LDAP_SUCCESS;
}
+/* Substring index generation function: Assertion value -> index hash keys */
static int
octetStringSubstringsFilter (
slap_mask_t use,
}
if( valueUID.bv_len && assertedUID.bv_len ) {
- match = valueUID.bv_len - assertedUID.bv_len;
- if ( match ) {
- *matchp = match;
+ ber_slen_t d;
+ d = (ber_slen_t) valueUID.bv_len - (ber_slen_t) assertedUID.bv_len;
+ if ( d ) {
+ *matchp = sizeof(d) == sizeof(int) ? d : d < 0 ? -1 : 1;
return LDAP_SUCCESS;
}
{
/* simplistic matching allowed by rigid validation */
struct berval *asserted = (struct berval *) assertedValue;
- *matchp = value->bv_len != asserted->bv_len;
+ *matchp = (int) asserted->bv_len - (int) value->bv_len;
return LDAP_SUCCESS;
}
? LDAP_UTF8_APPROX : 0;
val = UTF8bvnormalize( val, &tmp, flags, ctx );
+ /* out of memory or syntax error, the former is unlikely */
if( val == NULL ) {
- return LDAP_OTHER;
+ return LDAP_INVALID_SYNTAX;
}
/* collapse spaces (in place) */
}
nvalue.bv_val[nvalue.bv_len] = '\0';
- } else {
+ } else if ( tmp.bv_len ) {
/* string of all spaces is treated as one space */
nvalue.bv_val[0] = ' ';
nvalue.bv_val[1] = '\0';
nvalue.bv_len = 1;
- }
+ } /* should never be entered with 0-length val */
*normalized = nvalue;
return LDAP_SUCCESS;
}
lines[l].bv_len = &val->bv_val[c] - lines[l].bv_val;
- normalized->bv_len = l;
+ normalized->bv_len = c = l;
- for ( l = 0; !BER_BVISNULL( &lines[l] ); l++ ) {
+ for ( l = 0; l <= c; l++ ) {
/* NOTE: we directly normalize each line,
* without unescaping the values, since the special
* values '\24' ('$') and '\5C' ('\') are not affected
* by normalization */
+ if ( !lines[l].bv_len ) {
+ nlines[l].bv_len = 0;
+ nlines[l].bv_val = NULL;
+ continue;
+ }
rc = UTF8StringNormalize( usage, NULL, xmr, &lines[l], &nlines[l], ctx );
if ( rc != LDAP_SUCCESS ) {
rc = LDAP_INVALID_SYNTAX;
normalized->bv_val = slap_sl_malloc( normalized->bv_len + 1, ctx );
p = normalized->bv_val;
- for ( l = 0; !BER_BVISNULL( &nlines[l] ); l++ ) {
- p = lutil_strncopy( p, nlines[l].bv_val, nlines[l].bv_len );
-
+ for ( l = 0; l <= c ; l++ ) {
+ p = lutil_strbvcopy( p, &nlines[l] );
*p++ = '$';
}
*--p = '\0';
if( vsign < 0 ) match = -match;
}
+ /* Ordering rule used in extensible match filter? */
+ if ( (flags & SLAP_MR_EXT) && (mr->smr_usage & SLAP_MR_ORDERING) )
+ match = (match >= 0);
+
*matchp = match;
return LDAP_SUCCESS;
}
struct berval *tmp,
void *ctx )
{
- /* index format:
- * only if too large: one's complement <sign*exponent (chopped bytes)>,
+ /* Integer index key format, designed for memcmp to collate correctly:
+ * if too large: one's complement sign*<approx exponent=chopped bytes>,
* two's complement value (sign-extended or chopped as needed),
- * however the top <number of exponent-bytes + 1> bits of first byte
- * above is the inverse sign. The next bit is the sign as delimiter.
+ * however in first byte above, the top <number of exponent-bytes + 1>
+ * bits are the inverse sign and next bit is the sign as delimiter.
*/
ber_slen_t k = index_intlen_strlen;
ber_len_t chop = 0;
assert( chop == 0 );
memset( key->bv_val, neg, k ); /* sign-extend */
} else if ( k != 0 || ((itmp.bv_val[0] ^ neg) & 0xc0) ) {
+ /* Got exponent -k, or no room for 2 sign bits */
lenp = lenbuf + sizeof(lenbuf);
chop = - (ber_len_t) k;
do {
signmask >>= 1;
} while ( (chop >>= 8) != 0 || (signmask >> 1) & (*lenp ^ neg) );
/* With n bytes in lenbuf, the top n+1 bits of (signmask&0xff)
- * are 1, and the top n+2 bits of lenp[] are the sign bit. */
+ * are 1, and the top n+2 bits of lenp[0] are the sign bit. */
k = (lenbuf + sizeof(lenbuf)) - lenp;
if ( k > (ber_slen_t) index_intlen )
k = index_intlen;
return 0;
}
-/* Index generation function */
+/* Index generation function: Ordered index */
static int
integerIndexer(
slap_mask_t use,
return rc;
}
-/* Index generation function */
+/* Index generation function: Ordered index */
static int
integerFilter(
slap_mask_t use,
p = out->bv_val;
p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
- p = lutil_strncopy( p, sn.bv_val, sn.bv_len );
+ p = lutil_strbvcopy( p, &sn );
p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
- p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
+ p = lutil_strbvcopy( p, &ni );
p = lutil_strcopy( p, /*{*/ "\" }" );
assert( p == &out->bv_val[out->bv_len] );
sn2.bv_val = slap_sl_malloc( sn.bv_len, ctx );
}
sn2.bv_len = sn.bv_len;
- if ( lutil_str2bin( &sn, &sn2, ctx )) {
- rc = LDAP_INVALID_SYNTAX;
- goto func_leave;
- }
-
sn3.bv_val = sbuf3;
sn3.bv_len = sizeof(sbuf3);
- if ( slap_bin2hex( &sn2, &sn3, ctx ) ) {
+ if ( lutil_str2bin( &sn, &sn2, ctx ) || slap_bin2hex( &sn2, &sn3, ctx ) ) {
rc = LDAP_INVALID_SYNTAX;
goto func_leave;
}
out->bv_len = STRLENOF( "{ serialNumber , issuer rdnSequence:\"\" }" )
+ sn3.bv_len + ni.bv_len;
out->bv_val = slap_sl_malloc( out->bv_len + 1, ctx );
-
if ( out->bv_val == NULL ) {
out->bv_len = 0;
rc = LDAP_OTHER;
p = out->bv_val;
p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
- p = lutil_strncopy( p, sn3.bv_val, sn3.bv_len );
+ p = lutil_strbvcopy( p, &sn3 );
p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
- p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
+ p = lutil_strbvcopy( p, &ni );
p = lutil_strcopy( p, /*{*/ "\" }" );
assert( p == &out->bv_val[out->bv_len] );
p = normalized->bv_val;
p = lutil_strcopy( p, "{ serialNumber " /*}*/ );
- p = lutil_strncopy( p, sn2.bv_val, sn2.bv_len );
+ p = lutil_strbvcopy( p, &sn2 );
p = lutil_strcopy( p, ", issuer rdnSequence:\"" );
- p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
+ p = lutil_strbvcopy( p, &issuer_dn );
p = lutil_strcopy( p, /*{*/ "\" }" );
rc = LDAP_SUCCESS;
rc = generalizedTimeValidate( NULL, &bv );
if ( rc == LDAP_SUCCESS && out != NULL ) {
+ if ( out->bv_len > bv.bv_len ) {
+ out->bv_val[ bv.bv_len ] = '\0';
+ }
out->bv_len = bv.bv_len;
}
p = out->bv_val;
p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
- p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
+ p = lutil_strbvcopy( p, &ni );
p = lutil_strcopy( p, "\", thisUpdate \"" );
- p = lutil_strncopy( p, tu.bv_val, tu.bv_len );
+ p = lutil_strbvcopy( p, &tu );
p = lutil_strcopy( p, /*{*/ "\" }" );
assert( p == &out->bv_val[out->bv_len] );
p = out->bv_val;
p = lutil_strcopy( p, "{ issuer rdnSequence:\"" /*}*/ );
- p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
+ p = lutil_strbvcopy( p, &ni );
p = lutil_strcopy( p, "\", thisUpdate \"" );
- p = lutil_strncopy( p, tu2.bv_val, tu2.bv_len );
+ p = lutil_strbvcopy( p, &tu2 );
p = lutil_strcopy( p, /*{*/ "\" }" );
assert( p == &out->bv_val[out->bv_len] );
p = normalized->bv_val;
p = lutil_strcopy( p, "{ issuer rdnSequence:\"" );
- p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
+ p = lutil_strbvcopy( p, &issuer_dn );
p = lutil_strcopy( p, "\", thisUpdate \"" );
- p = lutil_strncopy( p, thisUpdate.bv_val, thisUpdate.bv_len );
+ p = lutil_strbvcopy( p, &thisUpdate );
p = lutil_strcopy( p, /*{*/ "\" }" );
rc = LDAP_SUCCESS;
p = out->bv_val;
p = lutil_strcopy( p, "{ serialNumber " );
- p = lutil_strncopy( p, sn.bv_val, sn.bv_len );
+ p = lutil_strbvcopy( p, &sn );
p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
- p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
+ p = lutil_strbvcopy( p, &ni );
p = lutil_strcopy( p, "\" }, serial " );
- p = lutil_strncopy( p, i_sn.bv_val, i_sn.bv_len );
+ p = lutil_strbvcopy( p, &i_sn );
p = lutil_strcopy( p, " } } }" );
assert( p == &out->bv_val[out->bv_len] );
p = out->bv_val;
p = lutil_strcopy( p, "{ serialNumber " );
- p = lutil_strncopy( p, sn3.bv_val, sn3.bv_len );
+ p = lutil_strbvcopy( p, &sn3 );
p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
- p = lutil_strncopy( p, ni.bv_val, ni.bv_len );
+ p = lutil_strbvcopy( p, &ni );
p = lutil_strcopy( p, "\" }, serial " );
- p = lutil_strncopy( p, i_sn3.bv_val, i_sn3.bv_len );
+ p = lutil_strbvcopy( p, &i_sn3 );
p = lutil_strcopy( p, " } } }" );
assert( p == &out->bv_val[out->bv_len] );
ber_tag_t tag;
ber_len_t len;
char issuer_serialbuf[SLAP_SN_BUFLEN], serialbuf[SLAP_SN_BUFLEN];
- struct berval sn, i_sn, sn2, i_sn2;
+ struct berval sn, i_sn, sn2 = BER_BVNULL, i_sn2 = BER_BVNULL;
struct berval issuer_dn = BER_BVNULL, bvdn;
char *p;
int rc = LDAP_INVALID_SYNTAX;
if ( BER_BVISEMPTY( val ) ) {
- goto done;
+ return rc;
}
if ( SLAP_MR_IS_VALUE_OF_ASSERTION_SYNTAX(usage) ) {
tag = ber_skip_tag( ber, &len ); /* GeneralNames (sequence) */
tag = ber_skip_tag( ber, &len ); /* directoryName (we only accept this form of GeneralName) */
if ( tag != SLAP_X509_GN_DIRECTORYNAME ) {
- rc = LDAP_INVALID_SYNTAX;
- goto done;
+ return LDAP_INVALID_SYNTAX;
}
tag = ber_peek_tag( ber, &len ); /* sequence of RDN */
len = ber_ptrlen( ber );
p = normalized->bv_val;
p = lutil_strcopy( p, "{ serialNumber " );
- p = lutil_strncopy( p, sn2.bv_val, sn2.bv_len );
+ p = lutil_strbvcopy( p, &sn2 );
p = lutil_strcopy( p, ", issuer { baseCertificateID { issuer { directoryName:rdnSequence:\"" );
- p = lutil_strncopy( p, issuer_dn.bv_val, issuer_dn.bv_len );
+ p = lutil_strbvcopy( p, &issuer_dn );
p = lutil_strcopy( p, "\" }, serial " );
- p = lutil_strncopy( p, i_sn2.bv_val, i_sn2.bv_len );
+ p = lutil_strbvcopy( p, &i_sn2 );
p = lutil_strcopy( p, " } } }" );
Debug( LDAP_DEBUG_TRACE, "attributeCertificateExactNormalize: %s\n",
ptr = lutil_strncopy( ptr, >.bv_val[ STRLENOF( "YYYYmmddHH:MM:" ) ],
STRLENOF( "SS" ) );
ptr = lutil_strcopy( ptr, ".000000Z#00" );
- ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
+ ptr = lutil_strbvcopy( ptr, &cnt );
*ptr++ = '#';
*ptr++ = '0';
*ptr++ = '0';
ptr = bv.bv_val;
ptr = lutil_strncopy( ptr, gt.bv_val, gt.bv_len - 1 );
ptr = lutil_strcopy( ptr, ".000000Z#" );
- ptr = lutil_strncopy( ptr, cnt.bv_val, cnt.bv_len );
+ ptr = lutil_strbvcopy( ptr, &cnt );
*ptr++ = '#';
*ptr++ = '0';
for ( i = 0; i < sid.bv_len; i++ ) {
(v_len < av_len ? v_len : av_len) - 1 );
if ( match == 0 ) match = v_len - av_len;
+ /* If used in extensible match filter, match if value < asserted */
+ if ( flags & SLAP_MR_EXT )
+ match = (match >= 0);
+
*matchp = match;
return LDAP_SUCCESS;
}
-/* Index generation function */
+/* Index generation function: Ordered index */
int generalizedTimeIndexer(
slap_mask_t use,
slap_mask_t flags,
return LDAP_SUCCESS;
}
-/* Index generation function */
+/* Index generation function: Ordered index */
int generalizedTimeFilter(
slap_mask_t use,
slap_mask_t flags,
}
static char *country_gen_syn[] = {
- "1.3.6.1.4.1.1466.115.121.1.15",
- "1.3.6.1.4.1.1466.115.121.1.26",
- "1.3.6.1.4.1.1466.115.121.1.44",
+ "1.3.6.1.4.1.1466.115.121.1.15", /* Directory String */
+ "1.3.6.1.4.1.1466.115.121.1.26", /* IA5 String */
+ "1.3.6.1.4.1.1466.115.121.1.44", /* Printable String */
NULL
};
countryStringValidate, NULL},
#endif
{"( 1.3.6.1.4.1.1466.115.121.1.12 DESC 'Distinguished Name' )",
- 0, NULL, dnValidate, dnPretty},
+ SLAP_SYNTAX_DN, NULL, dnValidate, dnPretty},
{"( 1.2.36.79672281.1.5.0 DESC 'RDN' )",
0, NULL, rdnValidate, rdnPretty},
#ifdef LDAP_COMP_MATCH
{"( 1.3.6.1.4.1.1466.115.121.1.33 DESC 'MHS OR Address' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.34 DESC 'Name And Optional UID' )",
- 0, NULL, nameUIDValidate, nameUIDPretty },
+ SLAP_SYNTAX_DN, NULL, nameUIDValidate, nameUIDPretty },
{"( 1.3.6.1.4.1.1466.115.121.1.35 DESC 'Name Form Description' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.36 DESC 'Numeric String' )",
#ifdef LDAP_COMP_MATCH
{"( 1.2.36.79672281.1.13.2 NAME 'componentFilterMatch' "
- "SYNTAX 1.2.36.79672281.1.5.2 )",
+ "SYNTAX 1.2.36.79672281.1.5.2 )", /* componentFilterMatch assertion */
SLAP_MR_EXT|SLAP_MR_COMPONENT, componentFilterMatchSyntaxes,
NULL, NULL , componentFilterMatch,
octetStringIndexer, octetStringFilter,
NULL },
{"( 1.2.36.79672281.1.13.6 NAME 'allComponentsMatch' "
- "SYNTAX 1.2.36.79672281.1.5.3 )",
+ "SYNTAX 1.2.36.79672281.1.5.3 )", /* allComponents */
SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
NULL, NULL , allComponentsMatch,
octetStringIndexer, octetStringFilter,
NULL },
{"( 1.2.36.79672281.1.13.7 NAME 'directoryComponentsMatch' "
- "SYNTAX 1.2.36.79672281.1.5.3 )",
+ "SYNTAX 1.2.36.79672281.1.5.3 )", /* allComponents */
SLAP_MR_EQUALITY|SLAP_MR_EXT|SLAP_MR_COMPONENT, NULL,
NULL, NULL , directoryComponentsMatch,
octetStringIndexer, octetStringFilter,
{"( 2.5.13.3 NAME 'caseIgnoreOrderingMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
- SLAP_MR_ORDERING, directoryStringSyntaxes,
+ SLAP_MR_ORDERING | SLAP_MR_EXT, directoryStringSyntaxes,
NULL, UTF8StringNormalize, octetStringOrderingMatch,
NULL, NULL,
"caseIgnoreMatch" },
{"( 2.5.13.4 NAME 'caseIgnoreSubstringsMatch' "
- "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
SLAP_MR_SUBSTR, directoryStringSyntaxes,
NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
octetStringSubstringsIndexer, octetStringSubstringsFilter,
{"( 2.5.13.6 NAME 'caseExactOrderingMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
- SLAP_MR_ORDERING, directoryStringSyntaxes,
+ SLAP_MR_ORDERING | SLAP_MR_EXT, directoryStringSyntaxes,
NULL, UTF8StringNormalize, octetStringOrderingMatch,
NULL, NULL,
"caseExactMatch" },
{"( 2.5.13.7 NAME 'caseExactSubstringsMatch' "
- "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
SLAP_MR_SUBSTR, directoryStringSyntaxes,
NULL, UTF8StringNormalize, directoryStringSubstringsMatch,
octetStringSubstringsIndexer, octetStringSubstringsFilter,
{"( 2.5.13.9 NAME 'numericStringOrderingMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 )",
- SLAP_MR_ORDERING, NULL,
+ SLAP_MR_ORDERING | SLAP_MR_EXT, NULL,
NULL, numericStringNormalize, octetStringOrderingMatch,
NULL, NULL,
"numericStringMatch" },
{"( 2.5.13.10 NAME 'numericStringSubstringsMatch' "
- "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
SLAP_MR_SUBSTR, NULL,
NULL, numericStringNormalize, octetStringSubstringsMatch,
octetStringSubstringsIndexer, octetStringSubstringsFilter,
"numericStringMatch" },
{"( 2.5.13.11 NAME 'caseIgnoreListMatch' "
- "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )",
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )", /* Postal Address */
SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
NULL, postalAddressNormalize, octetStringMatch,
octetStringIndexer, octetStringFilter,
NULL },
{"( 2.5.13.12 NAME 'caseIgnoreListSubstringsMatch' "
- "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
SLAP_MR_SUBSTR, NULL,
NULL, NULL, NULL, NULL, NULL,
"caseIgnoreListMatch" },
{"( 2.5.13.15 NAME 'integerOrderingMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
- SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
+ SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
NULL, NULL, integerMatch,
NULL, NULL,
"integerMatch" },
{"( 2.5.13.18 NAME 'octetStringOrderingMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )",
- SLAP_MR_ORDERING, NULL,
+ SLAP_MR_ORDERING | SLAP_MR_EXT, NULL,
NULL, NULL, octetStringOrderingMatch,
NULL, NULL,
"octetStringMatch" },
NULL },
{"( 2.5.13.21 NAME 'telephoneNumberSubstringsMatch' "
- "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )",
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.58 )", /* Substring Assertion */
SLAP_MR_SUBSTR, NULL,
NULL, telephoneNumberNormalize, octetStringSubstringsMatch,
octetStringSubstringsIndexer, octetStringSubstringsFilter,
NULL, NULL, NULL, NULL, NULL, NULL },
{"( 2.5.13.23 NAME 'uniqueMemberMatch' "
- "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )",
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )", /* Name And Optional UID */
SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
NULL, uniqueMemberNormalize, uniqueMemberMatch,
uniqueMemberIndexer, uniqueMemberFilter,
{"( 2.5.13.28 NAME 'generalizedTimeOrderingMatch' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )",
- SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
+ SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
NULL, generalizedTimeNormalize, generalizedTimeOrderingMatch,
NULL, NULL,
"generalizedTimeMatch" },
{"( 2.5.13.29 NAME 'integerFirstComponentMatch' "
- "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */
SLAP_MR_EQUALITY | SLAP_MR_EXT,
integerFirstComponentMatchSyntaxes,
NULL, firstComponentNormalize, integerMatch,
NULL },
{"( 2.5.13.30 NAME 'objectIdentifierFirstComponentMatch' "
- "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )",
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )", /* OID */
SLAP_MR_EQUALITY | SLAP_MR_EXT,
objectIdentifierFirstComponentMatchSyntaxes,
NULL, firstComponentNormalize, octetStringMatch,
NULL },
{"( 2.5.13.34 NAME 'certificateExactMatch' "
- "SYNTAX 1.3.6.1.1.15.1 )",
+ "SYNTAX 1.3.6.1.1.15.1 )", /* Certificate Exact Assertion */
SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateExactMatchSyntaxes,
NULL, certificateExactNormalize, octetStringMatch,
octetStringIndexer, octetStringFilter,
NULL },
{"( 2.5.13.35 NAME 'certificateMatch' "
- "SYNTAX 1.3.6.1.1.15.2 )",
+ "SYNTAX 1.3.6.1.1.15.2 )", /* Certificate Assertion */
SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL },
{"( 2.5.13.38 NAME 'certificateListExactMatch' "
- "SYNTAX 1.3.6.1.1.15.5 )",
+ "SYNTAX 1.3.6.1.1.15.5 )", /* Certificate List Exact Assertion */
SLAP_MR_EQUALITY | SLAP_MR_EXT, certificateListExactMatchSyntaxes,
NULL, certificateListExactNormalize, octetStringMatch,
octetStringIndexer, octetStringFilter,
NULL },
{"( 2.5.13.39 NAME 'certificateListMatch' "
- "SYNTAX 1.3.6.1.1.15.6 )",
+ "SYNTAX 1.3.6.1.1.15.6 )", /* Certificate List Assertion */
SLAP_MR_EQUALITY | SLAP_MR_EXT, NULL,
NULL, NULL, NULL, NULL, NULL,
NULL },
#ifdef SLAPD_AUTHPASSWD
/* 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 )",
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )", /* Octet String */
SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
NULL, NULL, authPasswordMatch,
NULL, NULL,
#endif
{"( 1.2.840.113556.1.4.803 NAME 'integerBitAndMatch' "
- "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */
SLAP_MR_EXT, NULL,
NULL, NULL, integerBitAndMatch,
NULL, NULL,
"integerMatch" },
{"( 1.2.840.113556.1.4.804 NAME 'integerBitOrMatch' "
- "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )",
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )", /* Integer */
SLAP_MR_EXT, NULL,
NULL, NULL, integerBitOrMatch,
NULL, NULL,
{"( 1.3.6.1.4.1.4203.666.11.2.3 NAME 'CSNOrderingMatch' "
"SYNTAX 1.3.6.1.4.1.4203.666.11.2.1 )",
- SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_ORDERED_INDEX, NULL,
+ SLAP_MR_HIDE | SLAP_MR_ORDERING | SLAP_MR_EXT | SLAP_MR_ORDERED_INDEX, NULL,
NULL, csnNormalize, csnOrderingMatch,
NULL, NULL,
"CSNMatch" },
/* FIXME: OID is unused, but not registered yet */
{"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
- "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
+ "SYNTAX 1.3.6.1.4.1.4203.666.2.7 )", /* OpenLDAP authz */
SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
NULL, authzNormalize, authzMatch,
NULL, NULL,
syn_destroy();
if( schema_init_done ) {
+ ldap_pvt_thread_mutex_destroy( &ad_index_mutex );
ldap_pvt_thread_mutex_destroy( &ad_undef_mutex );
ldap_pvt_thread_mutex_destroy( &oc_undef_mutex );
}