From 0ff6dbc8bb491d3693362c30f1b9085f56c81ec8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Love=20H=C3=B6rnquist=20=C3=85strand?= Date: Sun, 27 Jan 2008 13:05:47 +0000 Subject: [PATCH] Add matching on EKU, validate EKUs, add hxtool matching glue, add check. Adapted from pach from Tim Miller of Mitre git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@22538 ec53bebd-3082-4978-b11e-865c3cabbd6b --- lib/hx509/ChangeLog | 5 ++++ lib/hx509/cert.c | 53 ++++++++++++++++++++++++++++++---- lib/hx509/hx_locl.h | 4 ++- lib/hx509/hxtool-commands.in | 6 ++++ lib/hx509/hxtool.c | 11 ++++++++ lib/hx509/print.c | 55 +++++++++++++++++++++++++++++++++--- lib/hx509/test_query.in | 17 +++++++++++ lib/hx509/version-script.map | 1 + 8 files changed, 142 insertions(+), 10 deletions(-) diff --git a/lib/hx509/ChangeLog b/lib/hx509/ChangeLog index cb29cee4e..dbcbf44d9 100644 --- a/lib/hx509/ChangeLog +++ b/lib/hx509/ChangeLog @@ -1,3 +1,8 @@ +2008-01-27 Love Hörnquist Åstrand + + * Add matching on EKU, validate EKUs, add hxtool matching glue, + add check. Adapted from pach from Tim Miller of Mitre + 2008-01-21 Love Hörnquist Åstrand * test_soft_pkcs11.c: use func for more C_ functions. diff --git a/lib/hx509/cert.c b/lib/hx509/cert.c index abe40f5a3..36fbe81c9 100644 --- a/lib/hx509/cert.c +++ b/lib/hx509/cert.c @@ -2609,6 +2609,40 @@ hx509_query_match_friendly_name(hx509_query *q, const char *name) return 0; } +/** + * Set the query controller to require an specific EKU (extended key + * usage). + * + * @param q a hx509 query controller. + * @param eku an EKU to match on + * + * @return An hx509 error code, see hx509_get_error_string(). + * + * @ingroup hx509_cert + */ + +int +hx509_query_match_eku(hx509_query *q, const heim_oid *eku) +{ + int ret; + + if (q->eku) { + der_free_oid(q->eku); + } else { + q->eku = calloc(1, sizeof(*q->eku)); + if (q->eku == NULL) + return ENOMEM; + } + ret = der_copy_oid(eku, q->eku); + if (ret) { + free(q->eku); + q->eku = NULL; + return ret; + } + q->match |= HX509_QUERY_MATCH_EKU; + return 0; +} + /** * Set the query controller to match using a specific match function. * @@ -2648,20 +2682,24 @@ hx509_query_match_cmp_func(hx509_query *q, void hx509_query_free(hx509_context context, hx509_query *q) { + if (q == NULL) + return; + if (q->serial) { der_free_heim_integer(q->serial); free(q->serial); - q->serial = NULL; } if (q->issuer_name) { free_Name(q->issuer_name); free(q->issuer_name); - q->issuer_name = NULL; } - if (q) { + if (q->eku) { + der_free_oid(q->eku); + free(q->eku); + } + if (q->friendlyname) free(q->friendlyname); - memset(q, 0, sizeof(*q)); - } + memset(q, 0, sizeof(*q)); free(q); } @@ -2790,6 +2828,11 @@ _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert return 0; } + /* If an EKU is required, check the cert for it. */ + if ((q->match & HX509_QUERY_MATCH_EKU) && + hx509_cert_check_eku(context, cert, q->eku, 0)) + return 0; + if (q->match & ~HX509_QUERY_MASK) return 0; diff --git a/lib/hx509/hx_locl.h b/lib/hx509/hx_locl.h index 8de99eba0..3bafc9bdb 100644 --- a/lib/hx509/hx_locl.h +++ b/lib/hx509/hx_locl.h @@ -128,7 +128,8 @@ struct hx509_query_data { #define HX509_QUERY_MATCH_FUNCTION 0x080000 #define HX509_QUERY_MATCH_KEY_HASH_SHA1 0x100000 #define HX509_QUERY_MATCH_TIME 0x200000 -#define HX509_QUERY_MASK 0x3fffff +#define HX509_QUERY_MATCH_EKU 0x400000 +#define HX509_QUERY_MASK 0x7fffff Certificate *subject; Certificate *certificate; heim_integer *serial; @@ -142,6 +143,7 @@ struct hx509_query_data { void *cmp_func_ctx; heim_octet_string *keyhash_sha1; time_t timenow; + heim_oid *eku; }; struct hx509_keyset_ops { diff --git a/lib/hx509/hxtool-commands.in b/lib/hx509/hxtool-commands.in index a4cecfa62..af6b19947 100644 --- a/lib/hx509/hxtool-commands.in +++ b/lib/hx509/hxtool-commands.in @@ -437,6 +437,12 @@ command = { argument = "name" help = "match on friendly name" } + option = { + long = "eku" + type = "string" + argument = "oid-string" + help = "match on EKU" + } option = { long = "keyEncipherment" type = "flag" diff --git a/lib/hx509/hxtool.c b/lib/hx509/hxtool.c index b6f347be2..c131ae429 100644 --- a/lib/hx509/hxtool.c +++ b/lib/hx509/hxtool.c @@ -885,6 +885,17 @@ query(struct query_options *opt, int argc, char **argv) if (opt->friendlyname_string) hx509_query_match_friendly_name(q, opt->friendlyname_string); + if (opt->eku_string) { + heim_oid oid; + + parse_oid(opt->eku_string, NULL, &oid); + + ret = hx509_query_match_eku(q, &oid); + if (ret) + errx(1, "hx509_query_match_eku: %d", ret); + der_free_oid(&oid); + } + if (opt->private_key_flag) hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); diff --git a/lib/hx509/print.c b/lib/hx509/print.c index b58c0e9d4..92d781190 100644 --- a/lib/hx509/print.c +++ b/lib/hx509/print.c @@ -335,9 +335,6 @@ check_authorityKeyIdentifier(hx509_validate_ctx ctx, status->haveAKI = 1; check_Null(ctx, status, cf, e); - status->haveSKI = 1; - check_Null(ctx, status, cf, e); - ret = decode_AuthorityKeyIdentifier(e->extnValue.data, e->extnValue.length, &ai, &size); @@ -365,6 +362,56 @@ check_authorityKeyIdentifier(hx509_validate_ctx ctx, return 0; } +static int +check_extKeyUsage(hx509_validate_ctx ctx, + struct cert_status *status, + enum critical_flag cf, + const Extension *e) +{ + ExtKeyUsage eku; + size_t size, i; + int ret; + + check_Null(ctx, status, cf, e); + + ret = decode_ExtKeyUsage(e->extnValue.data, + e->extnValue.length, + &eku, &size); + if (ret) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Decoding ExtKeyUsage failed: %d", ret); + return 1; + } + if (size != e->extnValue.length) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "Padding data in EKU"); + free_ExtKeyUsage(&eku); + return 1; + } + if (eku.len == 0) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "ExtKeyUsage length is 0"); + return 1; + } + + for (i = 0; i < eku.len; i++) { + char *str; + ret = der_print_heim_oid (&eku.val[i], '.', &str); + if (ret) { + validate_print(ctx, HX509_VALIDATE_F_VALIDATE, + "\tEKU: failed to print oid %d", i); + free_ExtKeyUsage(&eku); + return 1; + } + validate_print(ctx, HX509_VALIDATE_F_VERBOSE, + "\teku-%d: %s\n", i, str);; + free(str); + } + + free_ExtKeyUsage(&eku); + + return 0; +} static int check_pkinit_san(hx509_validate_ctx ctx, heim_any *a) @@ -731,7 +778,7 @@ struct { { ext(policyMappings, Null), M_N_C }, { ext(authorityKeyIdentifier, authorityKeyIdentifier), M_N_C }, { ext(policyConstraints, Null), D_C }, - { ext(extKeyUsage, Null), D_C }, + { ext(extKeyUsage, extKeyUsage), D_C }, { ext(freshestCRL, Null), M_N_C }, { ext(inhibitAnyPolicy, Null), M_C }, #undef ext diff --git a/lib/hx509/test_query.in b/lib/hx509/test_query.in index 0530d6b67..74acd459a 100644 --- a/lib/hx509/test_query.in +++ b/lib/hx509/test_query.in @@ -44,8 +44,15 @@ hxtool="${TESTS_ENVIRONMENT} ./hxtool ${stat}" echo "try printing" ${hxtool} print \ --pass=PASS:foobar \ + --info --content \ PKCS12:$srcdir/data/test.p12 >/dev/null 2>/dev/null || exit 1 +echo "try printing" +${hxtool} print \ + --pass=PASS:foobar \ + --info --content \ + FILE:$srcdir/data/kdc.crt || exit 1 + ${hxtool} print \ --pass=PASS:foobar \ --info \ @@ -63,6 +70,16 @@ ${hxtool} query \ --friendlyname=friendlyname-test-not \ PKCS12:$srcdir/data/test.p12 >/dev/null 2>/dev/null && exit 1 +echo "make sure entry is found (eku)" +${hxtool} query \ + --eku=1.3.6.1.5.2.3.5 \ + FILE:$srcdir/data/kdc.crt >/dev/null 2>/dev/null || exit 1 + +echo "make sure entry is not found (eku)" +${hxtool} query \ + --eku=1.3.6.1.5.2.3.6 \ + FILE:$srcdir/data/kdc.crt >/dev/null 2>/dev/null && exit 1 + echo "make sure entry is found (friendlyname, no-pw)" ${hxtool} query \ --friendlyname=friendlyname-cert \ diff --git a/lib/hx509/version-script.map b/lib/hx509/version-script.map index 68ef73e8e..eae27d9d7 100644 --- a/lib/hx509/version-script.map +++ b/lib/hx509/version-script.map @@ -139,6 +139,7 @@ HEIMDAL_X509_1.0 { hx509_query_alloc; hx509_query_free; hx509_query_match_cmp_func; + hx509_query_match_eku; hx509_query_match_friendly_name; hx509_query_match_issuer_serial; hx509_query_match_option;