return LDAP_SUCCESS;
}
+#ifdef HAVE_TLS
+#include <openssl/x509.h>
+#include <openssl/err.h>
+char digit[] = "0123456789";
+
+/*
+ * Next function returns a string representation of a ASN1_INTEGER.
+ * It works for unlimited lengths.
+ */
+
+static struct berval *
+asn1_integer2str(ASN1_INTEGER *a)
+{
+ char buf[256];
+ char *p;
+
+ /* We work backwards, make it fill from the end of buf */
+ p = buf + sizeof(buf) - 1;
+ *p = '\0';
+
+ if ( a == NULL || a->length == 0 ) {
+ *--p = '0';
+ } else {
+ int i;
+ int n = a->length;
+ int base = 0;
+ unsigned int *copy;
+
+ /* We want to preserve the original */
+ copy = ch_malloc(n*sizeof(unsigned int));
+ for (i = 0; i<n; i++) {
+ copy[i] = a->data[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;
+ unsigned int temp;
+
+ carry = 0;
+ for (i = base; i<n; i++ ) {
+ copy[i] += carry*256;
+ carry = copy[i] % 10;
+ copy[i] /= 10;
+ }
+ if (p <= buf+1) {
+ /*
+ * Way too large, we need to leave
+ * room for sign if negative
+ */
+ return NULL;
+ }
+ *--p = digit[carry];
+ if (copy[base] == 0)
+ base++;
+ }
+ free(copy);
+ }
+
+ if ( a->type == V_ASN1_NEG_INTEGER ) {
+ *--p = '-';
+ }
+
+ return ber_bvstrdup(p);
+}
+
+static struct berval *
+dn_openssl2ldap(X509_NAME *name)
+{
+ char issuer_dn[1024];
+ BIO *bio;
+
+ bio = BIO_new(BIO_s_mem());
+ if ( !bio ) {
+ fprintf(stderr, ERR_error_string(ERR_get_error(),NULL));
+ /* ERR_print_errors(bio_err); */
+ return NULL;
+ }
+ X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253);
+
+ BIO_gets(bio, issuer_dn, 1024);
+
+ BIO_free(bio);
+ return ber_bvstrdup(issuer_dn);
+}
+
+static int
+serial_and_issuer_parse(
+ struct berval *assertion,
+ struct berval **serial,
+ struct berval **issuer_dn
+)
+{
+ char *begin;
+ char *end;
+ char *p;
+ char *q;
+
+ begin = assertion->bv_val;
+ end = assertion->bv_val+assertion->bv_len-1;
+ for (p=begin; p<=end && *p != '$'; p++)
+ ;
+ 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++))
+ ;
+ end = p;
+ while (ASCII_SPACE(*end--))
+ ;
+
+ q = ch_malloc( (end-begin+1)+1 );
+ AC_MEMCPY( q, begin, end-begin+1 );
+ q[end-begin+1] = '\0';
+ *serial = ber_bvstr(q);
+
+ /* 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++))
+ ;
+ /* should we trim spaces at the end too? is it safe always? */
+
+ q = ch_malloc( (end-begin+1)+1 );
+ AC_MEMCPY( q, begin, end-begin+1 );
+ q[end-begin+1] = '\0';
+ *issuer_dn = ber_bvstr(q);
+
+ 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 ) {
+ ERR_error_string(ERR_get_error(),NULL);
+ }
+
+ serial = asn1_integer2str(xcert->cert_info->serialNumber);
+ issuer_dn = dn_openssl2ldap(X509_get_issuer_name(xcert));
+
+ X509_free(xcert);
+
+ 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 ) {
+ ret = dnMatch(
+ matchp,
+ flags,
+ slap_schema.si_syn_distinguishedName,
+ slap_schema.si_mr_distinguishedNameMatch,
+ issuer_dn,
+ asserted_issuer_dn);
+ }
+ }
+
+ ber_bvfree(serial);
+ ber_bvfree(issuer_dn);
+ ber_bvfree(asserted_serial);
+ ber_bvfree(asserted_issuer_dn);
+
+ return ret;
+}
+#endif
+
static int
check_time_syntax (struct berval *val,
int start,
{"( 1.3.6.1.1.1.0.1 DESC 'RFC2307 Boot Parameter' )",
0, bootParameterValidate, NULL, NULL},
+#ifdef HAVE_TLS
+ /* From PKIX */
+ /* These OIDs are not published yet, but have been assigned */
+ {"( 1.3.6.1.4.1.1466.115.121.1.9999 DESC 'Serial Number and Issuer' )",
+ 0, NULL, NULL, NULL},
+#endif
+
/* 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 */,
* 2.5.13.31 directoryStringFirstComponentMatch
* 2.5.13.32 wordMatch
* 2.5.13.33 keywordMatch
- * 2.5.13.34 certificateExactMatch
* 2.5.13.35 certificateMatch
* 2.5.13.36 certificatePairExactMatch
* 2.5.13.37 certificatePairMatch
objectIdentifierFirstComponentMatch, NULL, NULL,
NULL},
+#ifdef HAVE_TLS
+ {"( 2.5.13.34 NAME 'certificateExactMatch' "
+ "SYNTAX 1.3.6.1.4.1.1466.115.121.1.9999 )",
+ SLAP_MR_EQUALITY | SLAP_MR_EXT,
+ NULL, NULL,
+ certificateExactMatch, NULL, NULL,
+ NULL},
+#endif
+
{"( 1.3.6.1.4.1.1466.109.114.1 NAME 'caseExactIA5Match' "
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT,
NULL /* next */
};
+struct slap_schema_mr_map {
+ char *ssmm_name;
+ size_t ssmm_offset;
+} mr_map[] = {
+ { "distinguishedNameMatch",
+ offsetof(struct slap_internal_schema, si_mr_distinguishedNameMatch) },
+ { "integerMatch",
+ offsetof(struct slap_internal_schema, si_mr_integerMatch) },
+ { NULL, 0 }
+};
+
+struct slap_schema_syn_map {
+ char *sssm_name;
+ size_t sssm_offset;
+} syn_map[] = {
+ { "1.3.6.1.4.1.1466.115.121.1.12",
+ offsetof(struct slap_internal_schema, si_syn_distinguishedName) },
+ { "1.3.6.1.4.1.1466.115.121.1.27",
+ offsetof(struct slap_internal_schema, si_syn_integer) },
+ { NULL, 0 }
+};
+
int
schema_prep( void )
{
}
slap_schema.si_at_undefined = &slap_at_undefined;
+ for( i=0; mr_map[i].ssmm_name; i++ ) {
+ MatchingRule ** mrp = (MatchingRule **)
+ &(((char *) &slap_schema)[mr_map[i].ssmm_offset]);
+
+ *mrp = mr_find( mr_map[i].ssmm_name );
+
+ if( *mrp == NULL ) {
+ fprintf( stderr,
+ "No matching rule \"%s\" defined in schema\n",
+ mr_map[i].ssmm_name );
+ return LDAP_INAPPROPRIATE_MATCHING;
+ }
+ }
+
+ for( i=0; syn_map[i].sssm_name; i++ ) {
+ Syntax ** synp = (Syntax **)
+ &(((char *) &slap_schema)[syn_map[i].sssm_offset]);
+
+ *synp = syn_find( syn_map[i].sssm_name );
+
+ if( *synp == NULL ) {
+ fprintf( stderr,
+ "No syntax \"%s\" defined in schema\n",
+ syn_map[i].sssm_name );
+ return LDAP_INVALID_SYNTAX;
+ }
+ }
+
++schema_init_done;
return LDAP_SUCCESS;
}