return ber_bvstrdup(p);
}
+/* Get a DN in RFC2253 format from a X509_NAME internal struct */
static struct berval *
dn_openssl2ldap(X509_NAME *name)
{
bio = BIO_new(BIO_s_mem());
if ( !bio ) {
- fprintf(stderr, ERR_error_string(ERR_get_error(),NULL));
- /* ERR_print_errors(bio_err); */
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+ "dn_openssl2ldap: error creating BIO_s_mem: %s\n",
+ ERR_error_string(ERR_get_error(),NULL)));
+#else
+ Debug( LDAP_DEBUG_ARGS, "dn_openssl2ldap: "
+ "error creating BIO: %s\n",
+ ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
+#endif
return NULL;
}
X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253);
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 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+ "certificateExactConvert: error parsing cert: %s\n",
+ ERR_error_string(ERR_get_error(),NULL)));
+#else
+ Debug( LDAP_DEBUG_ARGS, "certificateExactConvert: "
+ "error parsing cert: %s\n",
+ ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
+#endif
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ serial = asn1_integer2str(xcert->cert_info->serialNumber);
+ if ( !serial ) {
+ X509_free(xcert);
+ return LDAP_INVALID_SYNTAX;
+ }
+ issuer_dn = dn_openssl2ldap(X509_get_issuer_name(xcert));
+ if ( !issuer_dn ) {
+ X509_free(xcert);
+ ber_bvfree(serial);
+ return LDAP_INVALID_SYNTAX;
+ }
+ /* Actually, dn_openssl2ldap returns in a normalized format, but
+ it is different from our normalized format */
+ bv_tmp = issuer_dn;
+ if ( dnNormalize(NULL, bv_tmp, &issuer_dn) != LDAP_SUCCESS ) {
+ X509_free(xcert);
+ ber_bvfree(serial);
+ ber_bvfree(bv_tmp);
+ return LDAP_INVALID_SYNTAX;
+ }
+ ber_bvfree(bv_tmp);
+
+ 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,
/* 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 );
/* 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 );
AC_MEMCPY( q, begin, end-begin+1 );
q[end-begin+1] = '\0';
- *issuer_dn = ber_bvstr(q);
+ *issuer_dn = ber_bvstr(dn_normalize(q));
return LDAP_SUCCESS;
}
xcert = d2i_X509(NULL, &p, value->bv_len);
if ( !xcert ) {
- ERR_error_string(ERR_get_error(),NULL);
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+ "certificateExactMatch: error parsing cert: %s\n",
+ ERR_error_string(ERR_get_error(),NULL)));
+#else
+ Debug( LDAP_DEBUG_ARGS, "certificateExactMatch: "
+ "error parsing cert: %s\n",
+ ERR_error_string(ERR_get_error(),NULL), NULL, NULL );
+#endif
+ return LDAP_INVALID_SYNTAX;
}
serial = asn1_integer2str(xcert->cert_info->serialNumber);
asserted_serial);
if ( ret == LDAP_SUCCESS ) {
if ( *matchp == 0 ) {
+ /* We need to normalize everything for dnMatch */
ret = dnMatch(
matchp,
flags,
}
}
+#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);
return ret;
}
+
+/*
+ * Index generation function
+ * We just index the serials, in most scenarios the issuer DN is one of
+ * a very small set of values.
+ */
+int certificateExactIndexer(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ struct berval **values,
+ struct berval ***keysp )
+{
+ int i;
+ struct berval **keys;
+ X509 *xcert;
+ unsigned char *p;
+ struct berval * serial;
+
+ /* we should have at least one value at this point */
+ assert( values != NULL && values[0] != NULL );
+
+ for( i=0; values[i] != NULL; i++ ) {
+ /* empty -- just count them */
+ }
+
+ keys = ch_malloc( sizeof( struct berval * ) * (i+1) );
+
+ for( i=0; values[i] != NULL; i++ ) {
+ p = values[i]->bv_val;
+ xcert = d2i_X509(NULL, &p, values[i]->bv_len);
+ if ( !xcert ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+ "certificateExactIndexer: error parsing cert: %s\n",
+ ERR_error_string(ERR_get_error(),NULL)));
+#else
+ Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
+ "error parsing cert: %s\n",
+ ERR_error_string(ERR_get_error(),NULL),
+ NULL, NULL );
+#endif
+ /* Do we leak keys on error? */
+ return LDAP_INVALID_SYNTAX;
+ }
+
+ serial = asn1_integer2str(xcert->cert_info->serialNumber);
+ X509_free(xcert);
+ integerNormalize( slap_schema.si_syn_integer,
+ serial,
+ &keys[i] );
+ ber_bvfree(serial);
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "schema", LDAP_LEVEL_ENTRY,
+ "certificateExactIndexer: returning: %s\n",
+ keys[i]->bv_val));
+#else
+ Debug( LDAP_DEBUG_ARGS, "certificateExactIndexer: "
+ "returning: %s\n",
+ keys[i]->bv_val,
+ NULL, NULL );
+#endif
+ }
+
+ keys[i] = NULL;
+ *keysp = keys;
+ return LDAP_SUCCESS;
+}
+
+/* Index generation function */
+/* We think this is always called with a value in matching rule syntax */
+int certificateExactFilter(
+ slap_mask_t use,
+ slap_mask_t flags,
+ Syntax *syntax,
+ MatchingRule *mr,
+ struct berval *prefix,
+ void * assertValue,
+ struct berval ***keysp )
+{
+ struct berval **keys;
+ struct berval *asserted_serial;
+ struct berval *asserted_issuer_dn;
+
+ serial_and_issuer_parse(assertValue,
+ &asserted_serial,
+ &asserted_issuer_dn);
+
+ keys = ch_malloc( sizeof( struct berval * ) * 2 );
+ integerNormalize( syntax, asserted_serial, &keys[0] );
+ keys[1] = NULL;
+ *keysp = keys;
+
+ ber_bvfree(asserted_serial);
+ ber_bvfree(asserted_issuer_dn);
+ return LDAP_SUCCESS;
+}
#endif
static int
{"( 2.5.13.34 NAME 'certificateExactMatch' "
"SYNTAX 1.2.826.0.1.3344810.7.1 )",
SLAP_MR_EQUALITY | SLAP_MR_EXT,
- NULL, NULL,
- certificateExactMatch, NULL, NULL,
+ certificateExactConvert, NULL,
+ certificateExactMatch,
+ certificateExactIndexer, certificateExactFilter,
NULL},
#endif