]> git.sur5r.net Git - openldap/commitdiff
First cut at certificateExactMatch, completely untested and without
authorJulio Sánchez Fernández <jsanchez@openldap.org>
Sat, 20 Oct 2001 10:15:09 +0000 (10:15 +0000)
committerJulio Sánchez Fernández <jsanchez@openldap.org>
Sat, 20 Oct 2001 10:15:09 +0000 (10:15 +0000)
indexing.

servers/slapd/schema_init.c
servers/slapd/schema_prep.c
servers/slapd/slap.h

index 6f56f818691bbd54a8f766294243e17eca88577e..1116854d4d557ebb1276252545918011f11d37cd 100644 (file)
@@ -3427,6 +3427,202 @@ integerBitOrMatch(
        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,
@@ -3905,6 +4101,13 @@ struct syntax_defs_rec syntax_defs[] = {
        {"( 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 */,
@@ -3942,7 +4145,6 @@ struct mrule_defs_rec {
  * 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
@@ -4169,6 +4371,15 @@ struct mrule_defs_rec mrule_defs[] = {
                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,
index 16efb4c1ee26f02cf4db075b8e149b479e08f31a..4ba2607d8423a12de4bb90e4febb51c35cd07b52 100644 (file)
@@ -228,6 +228,28 @@ static AttributeType slap_at_undefined = {
        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 )
 {
@@ -281,6 +303,34 @@ 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;
 }
index 2e7d74a8d9773ccc3ab501d4ae8e4898e44dee6c..a8c770a03facc9990f57a7561155c88663eae33c 100644 (file)
@@ -489,6 +489,14 @@ struct slap_internal_schema {
 
        /* Undefined Attribute Type */
        AttributeType   *si_at_undefined;
+
+       /* Matching Rules */
+       MatchingRule    *si_mr_distinguishedNameMatch;
+       MatchingRule    *si_mr_integerMatch;
+
+       /* Syntaxes */
+       Syntax          *si_syn_distinguishedName;
+       Syntax          *si_syn_integer;
 };
 
 typedef struct slap_attr_assertion {