diff options
author | Rob Austein <sra@hactrn.net> | 2011-07-15 21:20:42 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2011-07-15 21:20:42 +0000 |
commit | 6a1e59c34fbf56a96f6c10427113d939f52302ce (patch) | |
tree | 49c7d0d4badc092ba4df415aff16369c1138c215 | |
parent | bfda0022ffedb5ddff4666eec8f718d770c83f8f (diff) |
Finish adding object_generation tags to all validation_status calls,
and fix weakness that this uncovered in the trust-anchor-locator code
(wasn't falling back to rc.old_authenticated when rc.unauthenticated
copy was farbled or didn't match TAL public key).
svn path=/rcynic-ng/rcynic.c; revision=3934
-rw-r--r-- | rcynic-ng/rcynic.c | 76 |
1 files changed, 51 insertions, 25 deletions
diff --git a/rcynic-ng/rcynic.c b/rcynic-ng/rcynic.c index 21752c16..5ee4ad2a 100644 --- a/rcynic-ng/rcynic.c +++ b/rcynic-ng/rcynic.c @@ -323,8 +323,7 @@ static const long mib_counter_openssl[] = { MIB_COUNTERS 0 }; #define OBJECT_GENERATIONS \ QQ(null) \ QQ(current) \ - QQ(backup) \ - QQ(unknown) + QQ(backup) #define QQ(x) object_generation_##x , typedef enum object_generation { OBJECT_GENERATIONS OBJECT_GENERATION_MAX } object_generation_t; @@ -2753,7 +2752,7 @@ static X509 *check_cert(rcynic_ctx_t *rc, { walk_ctx_t *w = walk_ctx_stack_head(wsk); mib_counter_t accept_code, reject_code; - object_generation_t generation = object_generation_unknown; + object_generation_t generation; const certinfo_t *issuer = NULL; STACK_OF(X509) *certs = NULL; const path_t *prefix = NULL; @@ -3604,7 +3603,7 @@ static void walk_cert(rcynic_ctx_t *rc, STACK_OF(walk_ctx_t) *wsk) generation = object_generation_backup; break; default: - generation = object_generation_unknown; + generation = object_generation_null; break; } @@ -3723,6 +3722,35 @@ static void check_ta(rcynic_ctx_t *rc, STACK_OF(walk_ctx_t) *wsk) /** + * Read a trust anchor from disk and compare with known public key. + * NB: EVP_PKEY_cmp() returns 1 for match, not 0 like every other + * xyz_cmp() function in the entire OpenSSL library. Go figure. + */ +static X509 *read_ta(const rcynic_ctx_t *rc, const uri_t *uri, const path_t *path, const EVP_PKEY *pkey, object_generation_t generation) + +{ + EVP_PKEY *xpkey = NULL; + X509 *x = NULL; + int match = 0; + + if ((x = read_cert(path, NULL)) == NULL || (xpkey = X509_get_pubkey(x)) == NULL) { + log_validation_status(rc, uri, unreadable_trust_anchor, generation); + } else { + match = EVP_PKEY_cmp(pkey, xpkey) == 1; + if (!match) + log_validation_status(rc, uri, trust_anchor_key_mismatch, generation); + } + + EVP_PKEY_free(xpkey); + if (match) + return x; + X509_free(x); + return NULL; +} + + + +/** * Main program. Parse command line, read config file, iterate over * trust anchors found via config file and do a tree walk for each * trust anchor. @@ -4020,6 +4048,7 @@ int main(int argc, char *argv[]) for (i = 0; i < sk_CONF_VALUE_num(cfg_section); i++) { CONF_VALUE *val = sk_CONF_VALUE_value(cfg_section, i); + object_generation_t generation = object_generation_null; path_t path1, path2; certinfo_t ta_certinfo; uri_t uri; @@ -4065,7 +4094,7 @@ int main(int argc, char *argv[]) uri.s[0] = '\0'; if ((x = read_cert(&path1, NULL)) == NULL) { - log_validation_status(&rc, &uri, unreadable_trust_anchor, object_generation_unknown); + log_validation_status(&rc, &uri, unreadable_trust_anchor, generation); continue; } hash = X509_subject_name_hash(x); @@ -4088,17 +4117,15 @@ int main(int argc, char *argv[]) if (!name_cmp(val->name, "trust-anchor-locator")) { /* * Trust anchor locator (URI + public key) method. - * - * NB: EVP_PKEY_cmp() returns 1 for match, not 0 like every - * other xyz_cmp() function in the entire OpenSSL library. - * Go figure. */ - EVP_PKEY *pkey = NULL, *xpkey = NULL; + EVP_PKEY *pkey = NULL; char *fn; + path_t path3; + fn = val->value; bio = BIO_new_file(fn, "r"); if (!bio || BIO_gets(bio, uri.s, sizeof(uri.s)) <= 0) { - log_validation_status(&rc, &uri, unreadable_trust_anchor_locator, object_generation_unknown); + log_validation_status(&rc, &uri, unreadable_trust_anchor_locator, object_generation_null); BIO_free(bio); bio = NULL; continue; @@ -4106,8 +4133,9 @@ int main(int argc, char *argv[]) uri.s[strcspn(uri.s, " \t\r\n")] = '\0'; bio = BIO_push(BIO_new(BIO_f_base64()), bio); if (!uri_to_filename(&rc, &uri, &path1, &rc.unauthenticated) || - !uri_to_filename(&rc, &uri, &path2, &rc.authenticated)) { - log_validation_status(&rc, &uri, unreadable_trust_anchor_locator, object_generation_unknown); + !uri_to_filename(&rc, &uri, &path2, &rc.authenticated) || + !uri_to_filename(&rc, &uri, &path3, &rc.old_authenticated)) { + log_validation_status(&rc, &uri, unreadable_trust_anchor_locator, object_generation_null); BIO_free_all(bio); bio = NULL; continue; @@ -4121,20 +4149,18 @@ int main(int argc, char *argv[]) BIO_free_all(bio); bio = NULL; if (!pkey) { - log_validation_status(&rc, &uri, unreadable_trust_anchor_locator, object_generation_unknown); + log_validation_status(&rc, &uri, unreadable_trust_anchor_locator, object_generation_null); + continue; + } + generation = object_generation_current; + if ((x = read_ta(&rc, &uri, &path1, pkey, generation)) == NULL) { + generation = object_generation_backup; + path1 = path3; + x = read_ta(&rc, &uri, &path1, pkey, generation); } - if (pkey && (x = read_cert(&path1, NULL)) == NULL) - log_validation_status(&rc, &uri, unreadable_trust_anchor, object_generation_unknown); - if (x && (xpkey = X509_get_pubkey(x)) == NULL) - log_validation_status(&rc, &uri, unreadable_trust_anchor_locator, object_generation_unknown); - j = (xpkey && EVP_PKEY_cmp(pkey, xpkey) == 1); EVP_PKEY_free(pkey); - EVP_PKEY_free(xpkey); - if (!j) { - log_validation_status(&rc, &uri, trust_anchor_key_mismatch, object_generation_unknown); - X509_free(x); + if (!x) continue; - } } if (!x) @@ -4150,7 +4176,7 @@ int main(int argc, char *argv[]) goto done; } - parse_cert(&rc, x, &ta_certinfo, &uri, object_generation_unknown); + parse_cert(&rc, x, &ta_certinfo, &uri, generation); ta_certinfo.ta = 1; if ((w = walk_ctx_stack_push(wsk, x, &ta_certinfo)) == NULL) { |