From 7581e304c0a47766ca90cfc96d17e264094a5386 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Julio=20S=C3=A1nchez=20Fern=C3=A1ndez?= Date: Mon, 22 Oct 2001 06:54:30 +0000 Subject: [PATCH] It now sort of works, but needs some normalization work and proper error reporting to client and syslog. And indexing, of course. Now, the problem is that matching rules get called from different places that are inconsistent in what an assertedValue is. When doing a modify, a full certificate value is passed (to verify it isn't already there). When doing a search or compare, the passed value is in the syntax of the matching rule. Consistency would require that the caller extracts an asserted value from the full value before calling smr_match. It can do this by calling smr_convert (it was unused, was it meant to be used for this?). Unfortunately, the caller is typically value_find, value_match, etc. that have themselves little knowledge of what they are dealing with, so their interface needs to be extended, new flag values or new arguments, so that they know if they have a value in attribute type syntax or in matching rule syntax. --- servers/slapd/schema_init.c | 88 +++++++++++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 8 deletions(-) diff --git a/servers/slapd/schema_init.c b/servers/slapd/schema_init.c index 11e85cae16..7752125458 100644 --- a/servers/slapd/schema_init.c +++ b/servers/slapd/schema_init.c @@ -3497,6 +3497,7 @@ asn1_integer2str(ASN1_INTEGER *a) return ber_bvstrdup(p); } +/* Get a DN in RFC2253 format from a X509_NAME internal struct */ static struct berval * dn_openssl2ldap(X509_NAME *name) { @@ -3517,6 +3518,61 @@ dn_openssl2ldap(X509_NAME *name) return ber_bvstrdup(issuer_dn); } +/* + * Given a certificate in DER format, extract the corresponding + * assertion value for certificateExactMatch + */ +static int +certificateExactConvert( + struct berval * in, + struct berval ** out ) +{ + X509 *xcert; + unsigned char *p = in->bv_val; + struct berval *serial; + struct berval *issuer_dn; + struct berval *bv_tmp; + int ret; + + xcert = d2i_X509(NULL, &p, in->bv_len); + if ( !xcert ) { + ERR_error_string(ERR_get_error(),NULL); + return LDAP_INVALID_SYNTAX; + } + + serial = asn1_integer2str(xcert->cert_info->serialNumber); + issuer_dn = dn_openssl2ldap(X509_get_issuer_name(xcert)); + + X509_free(xcert); + + *out = ch_malloc(sizeof(struct berval)); + (*out)->bv_len = serial->bv_len + 3 + issuer_dn->bv_len + 1; + (*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, " $ ", 3); + p += 3; + AC_MEMCPY(p, issuer_dn->bv_val, issuer_dn->bv_len); + p += issuer_dn->bv_len; + *p++ = '\0'; + +#ifdef NEW_LOGGING + LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY, + "certificateExactConvert: \n %s\n", + (*out)->bv_val)); +#else + Debug( LDAP_DEBUG_ARGS, "certificateExactConvert " + "\n\t\"%s\"\n", + (*out)->bv_val, NULL, NULL ); +#endif + + ber_bvfree(serial); + ber_bvfree(issuer_dn); + + return LDAP_SUCCESS; +} + static int serial_and_issuer_parse( struct berval *assertion, @@ -3538,11 +3594,11 @@ serial_and_issuer_parse( /* 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--)) - ; + while (ASCII_SPACE(*begin)) + begin++; + end = p-1; + while (ASCII_SPACE(*end)) + end--; q = ch_malloc( (end-begin+1)+1 ); AC_MEMCPY( q, begin, end-begin+1 ); @@ -3552,8 +3608,8 @@ serial_and_issuer_parse( /* 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++)) - ; + while (ASCII_SPACE(*begin)) + begin++; /* should we trim spaces at the end too? is it safe always? */ q = ch_malloc( (end-begin+1)+1 ); @@ -3584,6 +3640,7 @@ certificateExactMatch( xcert = d2i_X509(NULL, &p, value->bv_len); if ( !xcert ) { ERR_error_string(ERR_get_error(),NULL); + return LDAP_INVALID_SYNTAX; } serial = asn1_integer2str(xcert->cert_info->serialNumber); @@ -3604,6 +3661,7 @@ certificateExactMatch( asserted_serial); if ( ret == LDAP_SUCCESS ) { if ( *matchp == 0 ) { + /* We need to normalize everything for dnMatch */ ret = dnMatch( matchp, flags, @@ -3614,6 +3672,20 @@ certificateExactMatch( } } +#ifdef NEW_LOGGING + LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY, + "certificateExactMatch: %d\n %s $ %s\n %s $ %s\n", + *matchp, serial->bv_val, issuer_dn->bv_val, + asserted->serial->bv_val, asserted_issuer_dn->bv_val)); +#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 ); +#endif + ber_bvfree(serial); ber_bvfree(issuer_dn); ber_bvfree(asserted_serial); @@ -4378,7 +4450,7 @@ struct mrule_defs_rec mrule_defs[] = { {"( 2.5.13.34 NAME 'certificateExactMatch' " "SYNTAX 1.2.826.0.1.3344810.7.1 )", SLAP_MR_EQUALITY | SLAP_MR_EXT, - NULL, NULL, + certificateExactConvert, NULL, certificateExactMatch, NULL, NULL, NULL}, #endif -- 2.39.5