diff options
author | Rob Austein <sra@hactrn.net> | 2011-07-15 02:08:18 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2011-07-15 02:08:18 +0000 |
commit | bfda0022ffedb5ddff4666eec8f718d770c83f8f (patch) | |
tree | b95d2add9945cbbad2958ae42c16aa1c0e5157c6 | |
parent | 1241dfae04b07305180ea2ae4d68bb166fa46db8 (diff) |
Start factoring the current/backup split out of the event ("MIB
counter") codes, as it confuses the heck out of anything trying to
understand the results. Work in progress, not finished.
svn path=/rcynic-ng/rcynic.c; revision=3933
-rw-r--r-- | rcynic-ng/rcynic.c | 353 |
1 files changed, 210 insertions, 143 deletions
diff --git a/rcynic-ng/rcynic.c b/rcynic-ng/rcynic.c index 11422aa0..21752c16 100644 --- a/rcynic-ng/rcynic.c +++ b/rcynic-ng/rcynic.c @@ -313,6 +313,28 @@ static const long mib_counter_openssl[] = { MIB_COUNTERS 0 }; #undef QQ /** + * Object sources. We always try to get fresh copies of objects using + * rsync, but if that fails we try using backup copies from what + * worked the last time we were run. This means that a URI + * potentially represents two different objects, so we need to + * distinguish them for tracking purposes in our validation log. + */ + +#define OBJECT_GENERATIONS \ + QQ(null) \ + QQ(current) \ + QQ(backup) \ + QQ(unknown) + +#define QQ(x) object_generation_##x , +typedef enum object_generation { OBJECT_GENERATIONS OBJECT_GENERATION_MAX } object_generation_t; +#undef QQ + +#define QQ(x) #x , +static const char * const object_generation_label[] = { OBJECT_GENERATIONS NULL }; +#undef QQ + +/** * Type-safe string wrapper for URIs. */ typedef struct { char s[URI_MAX]; } uri_t; @@ -338,6 +360,7 @@ typedef struct { unsigned char h[EVP_MAX_MD_SIZE]; } hashbuf_t; */ typedef struct validation_status { uri_t uri; + object_generation_t generation; time_t timestamp; unsigned char events[(MIB_COUNTER_T_MAX + 7) / 8]; } validation_status_t; @@ -349,6 +372,7 @@ DECLARE_STACK_OF(validation_status_t) */ typedef struct certinfo { int ca, ta; + object_generation_t generation; uri_t uri, sia, aia, crldp, manifest; } certinfo_t; @@ -864,27 +888,27 @@ static void validation_status_set_code(validation_status_t *v, */ static void log_validation_status(const rcynic_ctx_t *rc, const uri_t *uri, - const mib_counter_t code) + const mib_counter_t code, + const object_generation_t generation) { - validation_status_t *v = NULL; + validation_status_t v_, *v = NULL; - assert(rc && uri && code < MIB_COUNTER_T_MAX); + assert(rc && uri && code < MIB_COUNTER_T_MAX && generation < OBJECT_GENERATION_MAX); if (!rc->validation_status) return; - /* - * Cast here works because uri is first field in validation_status_t. - */ - v = sk_validation_status_t_value(rc->validation_status, - sk_validation_status_t_find(rc->validation_status, - (const validation_status_t *) uri)); + memset(&v_, 0, sizeof(v_)); + v_.uri = *uri; + v_.generation = generation; + + v = sk_validation_status_t_value(rc->validation_status, sk_validation_status_t_find(rc->validation_status, &v_)); if (v == NULL) { if ((v = validation_status_t_new()) == NULL) { logmsg(rc, log_sys_err, "Couldn't allocate validation status entry for %s", uri->s); return; } - v->uri = *uri; + *v = v_; if (!sk_validation_status_t_push(rc->validation_status, v)) { logmsg(rc, log_sys_err, "Couldn't store validation status entry for %s", uri->s); free(v); @@ -895,10 +919,12 @@ static void log_validation_status(const rcynic_ctx_t *rc, v->timestamp = time(0); validation_status_set_code(v, code, 1); - logmsg(rc, log_verbose, "Recording %s for %s", + logmsg(rc, log_verbose, "Recording \"%s\" for %s%s%s", (mib_counter_desc[code] ? mib_counter_desc[code] : X509_verify_cert_error_string(mib_counter_openssl[code])), + (generation != object_generation_null ? object_generation_label[generation] : ""), + (generation != object_generation_null ? " " : ""), uri->s); } @@ -907,7 +933,13 @@ static void log_validation_status(const rcynic_ctx_t *rc, */ static int validation_status_cmp(const validation_status_t * const *a, const validation_status_t * const *b) { - return strcmp((*a)->uri.s, (*b)->uri.s); + int cmp = strcmp((*a)->uri.s, (*b)->uri.s); + if (cmp) + return cmp; + cmp = (int) ((*a)->generation) - (int) ((*b)->generation); + if (cmp) + return cmp; + return 0; } /** @@ -971,7 +1003,8 @@ static int cp_ln(const rcynic_ctx_t *rc, const path_t *source, const path_t *tar static int install_object(const rcynic_ctx_t *rc, const uri_t *uri, const path_t *source, - const mib_counter_t code) + const mib_counter_t code, + const object_generation_t generation) { path_t target; @@ -987,8 +1020,7 @@ static int install_object(const rcynic_ctx_t *rc, if (!cp_ln(rc, source, &target)) return 0; - log_validation_status(rc, uri, code); - logmsg(rc, log_telemetry, "Accepted %s", uri->s); + log_validation_status(rc, uri, code, generation); return 1; } @@ -1877,8 +1909,7 @@ static void rsync_mgr(const rcynic_ctx_t *rc) switch (WEXITSTATUS(pid_status)) { case 0: - logmsg(rc, log_debug, "Successfully fetched %s", ctx->uri.s); - log_validation_status(rc, &ctx->uri, rsync_succeeded); + log_validation_status(rc, &ctx->uri, rsync_succeeded, object_generation_null); break; case 5: @@ -1908,7 +1939,8 @@ static void rsync_mgr(const rcynic_ctx_t *rc) log_validation_status(rc, &ctx->uri, (rc->rsync_timeout && now >= ctx->deadline ? rsync_timed_out - : rsync_failed)); + : rsync_failed), + object_generation_null); break; } @@ -2192,6 +2224,7 @@ static CMS_ContentInfo *read_cms(const path_t *filename, hashbuf_t *hash) */ static void extract_crldp_uri(const rcynic_ctx_t *rc, const uri_t *uri, + const object_generation_t generation, const STACK_OF(DIST_POINT) *crldp, uri_t *result) { @@ -2201,14 +2234,14 @@ static void extract_crldp_uri(const rcynic_ctx_t *rc, assert(crldp); if (sk_DIST_POINT_num(crldp) != 1) { - log_validation_status(rc, uri, malformed_crldp); + log_validation_status(rc, uri, malformed_crldp, generation); return; } d = sk_DIST_POINT_value(crldp, 0); if (d->reasons || d->CRLissuer || !d->distpoint || d->distpoint->type != 0) { - log_validation_status(rc, uri, malformed_crldp); + log_validation_status(rc, uri, malformed_crldp, generation); return; } @@ -2216,7 +2249,7 @@ static void extract_crldp_uri(const rcynic_ctx_t *rc, GENERAL_NAME *n = sk_GENERAL_NAME_value(d->distpoint->name.fullname, i); assert(n != NULL); if (n->type != GEN_URI) { - log_validation_status(rc, uri, malformed_crldp); + log_validation_status(rc, uri, malformed_crldp, generation); return; } if (!is_rsync((char *) n->d.uniformResourceIdentifier->data)) { @@ -2225,7 +2258,7 @@ static void extract_crldp_uri(const rcynic_ctx_t *rc, continue; } if (sizeof(result->s) <= n->d.uniformResourceIdentifier->length) { - log_validation_status(rc, uri, uri_too_long); + log_validation_status(rc, uri, uri_too_long, generation); continue; } strcpy(result->s, (char *) n->d.uniformResourceIdentifier->data); @@ -2238,6 +2271,7 @@ static void extract_crldp_uri(const rcynic_ctx_t *rc, */ static void extract_access_uri(const rcynic_ctx_t *rc, const uri_t *uri, + const object_generation_t generation, const AUTHORITY_INFO_ACCESS *xia, const unsigned char *oid, const int oidlen, @@ -2261,7 +2295,7 @@ static void extract_access_uri(const rcynic_ctx_t *rc, continue; } if (sizeof(result->s) <= a->location->d.uniformResourceIdentifier->length) { - log_validation_status(rc, uri, uri_too_long); + log_validation_status(rc, uri, uri_too_long, generation); continue; } strcpy(result->s, (char *) a->location->d.uniformResourceIdentifier->data); @@ -2272,7 +2306,7 @@ static void extract_access_uri(const rcynic_ctx_t *rc, /** * Parse interesting stuff from a certificate. */ -static void parse_cert(const rcynic_ctx_t *rc, X509 *x, certinfo_t *c, const uri_t *uri) +static void parse_cert(const rcynic_ctx_t *rc, X509 *x, certinfo_t *c, const uri_t *uri, const object_generation_t generation) { STACK_OF(DIST_POINT) *crldp; AUTHORITY_INFO_ACCESS *xia; @@ -2282,20 +2316,21 @@ static void parse_cert(const rcynic_ctx_t *rc, X509 *x, certinfo_t *c, const uri c->ca = X509_check_ca(x) == 1; c->uri = *uri; + c->generation = generation; if ((xia = X509_get_ext_d2i(x, NID_info_access, NULL, NULL)) != NULL) { - extract_access_uri(rc, uri, xia, id_ad_caIssuers, sizeof(id_ad_caIssuers), &c->aia); + extract_access_uri(rc, uri, generation, xia, id_ad_caIssuers, sizeof(id_ad_caIssuers), &c->aia); sk_ACCESS_DESCRIPTION_pop_free(xia, ACCESS_DESCRIPTION_free); } if ((xia = X509_get_ext_d2i(x, NID_sinfo_access, NULL, NULL)) != NULL) { - extract_access_uri(rc, uri, xia, id_ad_caRepository, sizeof(id_ad_caRepository), &c->sia); - extract_access_uri(rc, uri, xia, id_ad_rpkiManifest, sizeof(id_ad_rpkiManifest), &c->manifest); + extract_access_uri(rc, uri, generation, xia, id_ad_caRepository, sizeof(id_ad_caRepository), &c->sia); + extract_access_uri(rc, uri, generation, xia, id_ad_rpkiManifest, sizeof(id_ad_rpkiManifest), &c->manifest); sk_ACCESS_DESCRIPTION_pop_free(xia, ACCESS_DESCRIPTION_free); } if ((crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL)) != NULL) { - extract_crldp_uri(rc, uri, crldp, &c->crldp); + extract_crldp_uri(rc, uri, generation, crldp, &c->crldp); sk_DIST_POINT_pop_free(crldp, DIST_POINT_free); } } @@ -2312,7 +2347,8 @@ static X509_CRL *check_crl_1(const rcynic_ctx_t *rc, const path_t *prefix, X509 *issuer, const unsigned char *hash, - const size_t hashlen) + const size_t hashlen, + const object_generation_t generation) { hashbuf_t hashbuf; X509_CRL *crl = NULL; @@ -2325,7 +2361,7 @@ static X509_CRL *check_crl_1(const rcynic_ctx_t *rc, goto punt; if (hashlen > sizeof(hashbuf.h)) { - log_validation_status(rc, uri, hash_too_long); + log_validation_status(rc, uri, hash_too_long, generation); goto punt; } @@ -2338,7 +2374,7 @@ static X509_CRL *check_crl_1(const rcynic_ctx_t *rc, goto punt; if (hash && memcmp(hashbuf.h, hash, hashlen)) { - log_validation_status(rc, uri, crl_digest_mismatch); + log_validation_status(rc, uri, crl_digest_mismatch, generation); goto punt; } @@ -2377,19 +2413,19 @@ static X509_CRL *check_crl(const rcynic_ctx_t *rc, assert(rsync_cached_uri(rc, uri)); if ((crl = check_crl_1(rc, uri, &path, &rc->unauthenticated, - issuer, hash, hashlen))) { - install_object(rc, uri, &path, current_crl_accepted); + issuer, hash, hashlen, object_generation_current))) { + install_object(rc, uri, &path, current_crl_accepted, object_generation_current); return crl; } else if (!access(path.s, F_OK)) { - log_validation_status(rc, uri, current_crl_rejected); + log_validation_status(rc, uri, current_crl_rejected, object_generation_current); } if ((crl = check_crl_1(rc, uri, &path, &rc->old_authenticated, - issuer, hash, hashlen))) { - install_object(rc, uri, &path, backup_crl_accepted); + issuer, hash, hashlen, object_generation_backup))) { + install_object(rc, uri, &path, backup_crl_accepted, object_generation_backup); return crl; } else if (!access(path.s, F_OK)) { - log_validation_status(rc, uri, backup_crl_rejected); + log_validation_status(rc, uri, backup_crl_rejected, object_generation_backup); } return NULL; @@ -2476,8 +2512,8 @@ static int check_x509_cb(int ok, X509_STORE_CTX *ctx) logmsg(rctx->rc, log_sys_err, "Couldn't cache stale CRLDP %s, blundering onward", rctx->subject->crldp.s); } - log_validation_status(rctx->rc, &rctx->subject->crldp, stale_crl); - log_validation_status(rctx->rc, &rctx->subject->uri, stale_crl); + log_validation_status(rctx->rc, &rctx->subject->crldp, stale_crl, rctx->subject->generation); + log_validation_status(rctx->rc, &rctx->subject->uri, stale_crl, rctx->subject->generation); return ok; case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: @@ -2496,7 +2532,7 @@ static int check_x509_cb(int ok, X509_STORE_CTX *ctx) */ if (rctx->rc->allow_non_self_signed_trust_anchor) ok = 1; - log_validation_status(rctx->rc, &rctx->subject->uri, trust_anchor_not_self_signed); + log_validation_status(rctx->rc, &rctx->subject->uri, trust_anchor_not_self_signed, rctx->subject->generation); return ok; /* @@ -2516,7 +2552,7 @@ static int check_x509_cb(int ok, X509_STORE_CTX *ctx) break; } - log_validation_status(rctx->rc, &rctx->subject->uri, code); + log_validation_status(rctx->rc, &rctx->subject->uri, code, rctx->subject->generation); return ok; } @@ -2549,68 +2585,68 @@ static int check_x509(const rcynic_ctx_t *rc, assert(issuer != NULL); if (subject->sia.s[0] && subject->sia.s[strlen(subject->sia.s) - 1] != '/') { - log_validation_status(rc, &subject->uri, malformed_sia); + log_validation_status(rc, &subject->uri, malformed_sia, subject->generation); goto done; } if (!subject->ta && !subject->aia.s[0]) { - log_validation_status(rc, &subject->uri, aia_missing); + log_validation_status(rc, &subject->uri, aia_missing, subject->generation); goto done; } if (!issuer_certinfo->ta && strcmp(issuer_certinfo->uri.s, subject->aia.s)) { - log_validation_status(rc, &subject->uri, aia_mismatch); + log_validation_status(rc, &subject->uri, aia_mismatch, subject->generation); goto done; } if (subject->ca && !subject->sia.s[0]) { - log_validation_status(rc, &subject->uri, sia_missing); + log_validation_status(rc, &subject->uri, sia_missing, subject->generation); goto done; } if (subject->ca && !subject->manifest.s[0]) { - log_validation_status(rc, &subject->uri, manifest_missing); + log_validation_status(rc, &subject->uri, manifest_missing, subject->generation); goto done; } if (subject->ca && !startswith(subject->manifest.s, subject->sia.s)) { - log_validation_status(rc, &subject->uri, manifest_mismatch); + log_validation_status(rc, &subject->uri, manifest_mismatch, subject->generation); goto done; } if (!check_allowed_extensions(x, !subject->ca)) { - log_validation_status(rc, &subject->uri, disallowed_extension); + log_validation_status(rc, &subject->uri, disallowed_extension, subject->generation); goto done; } if (subject->ta) { if (subject->crldp.s[0]) { - log_validation_status(rc, &subject->uri, trust_anchor_with_crldp); + log_validation_status(rc, &subject->uri, trust_anchor_with_crldp, subject->generation); goto done; } } else { if (!subject->crldp.s[0]) { - log_validation_status(rc, &subject->uri, crldp_missing); + log_validation_status(rc, &subject->uri, crldp_missing, subject->generation); goto done; } if (!subject->ca && !startswith(subject->crldp.s, issuer_certinfo->sia.s)) { - log_validation_status(rc, &subject->uri, crldp_mismatch); + log_validation_status(rc, &subject->uri, crldp_mismatch, subject->generation); goto done; } flags |= X509_V_FLAG_CRL_CHECK; if ((pkey = X509_get_pubkey(issuer)) == NULL || X509_verify(x, pkey) <= 0) { - log_validation_status(rc, &subject->uri, certificate_bad_signature); + log_validation_status(rc, &subject->uri, certificate_bad_signature, subject->generation); goto done; } if ((crl = check_crl(rc, &subject->crldp, issuer, NULL, 0)) == NULL) { - log_validation_status(rc, &subject->uri, certificate_bad_crl); + log_validation_status(rc, &subject->uri, certificate_bad_crl, subject->generation); goto done; } @@ -2633,7 +2669,7 @@ static int check_x509(const rcynic_ctx_t *rc, X509_VERIFY_PARAM_add0_policy(rctx.ctx.param, OBJ_txt2obj(rpki_policy_oid, 1)); if (X509_verify_cert(&rctx.ctx) <= 0) { - log_validation_status(rc, &subject->uri, certificate_failed_validation); + log_validation_status(rc, &subject->uri, certificate_failed_validation, subject->generation); goto done; } @@ -2660,7 +2696,8 @@ static X509 *check_cert_1(const rcynic_ctx_t *rc, const certinfo_t *issuer, certinfo_t *subject, const unsigned char *hash, - const size_t hashlen) + const size_t hashlen, + object_generation_t generation) { hashbuf_t hashbuf; X509 *x = NULL; @@ -2674,7 +2711,7 @@ static X509 *check_cert_1(const rcynic_ctx_t *rc, return NULL; if (hashlen > sizeof(hashbuf.h)) { - log_validation_status(rc, uri, hash_too_long); + log_validation_status(rc, uri, hash_too_long, generation); goto punt; } @@ -2689,11 +2726,11 @@ static X509 *check_cert_1(const rcynic_ctx_t *rc, } if (hash && memcmp(hashbuf.h, hash, hashlen)) { - log_validation_status(rc, uri, certificate_digest_mismatch); + log_validation_status(rc, uri, certificate_digest_mismatch, generation); goto punt; } - parse_cert(rc, x, subject, uri); + parse_cert(rc, x, subject, uri, generation); if (check_x509(rc, certs, x, subject, issuer)) return x; @@ -2716,6 +2753,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; const certinfo_t *issuer = NULL; STACK_OF(X509) *certs = NULL; const path_t *prefix = NULL; @@ -2731,11 +2769,13 @@ static X509 *check_cert(rcynic_ctx_t *rc, prefix = &rc->unauthenticated; accept_code = current_cert_accepted; reject_code = current_cert_rejected; + generation = object_generation_current; break; case walk_state_backup: prefix = &rc->old_authenticated; accept_code = backup_cert_accepted; reject_code = backup_cert_rejected; + generation = object_generation_backup; break; default: return NULL; @@ -2750,7 +2790,8 @@ static X509 *check_cert(rcynic_ctx_t *rc, !access(path.s, R_OK)) { if (w->state == walk_state_backup || sk_OPENSSL_STRING_find(rc->backup_cache, uri->s) < 0) return NULL; - log_validation_status(rc, uri, current_cert_recheck); + assert(generation == object_generation_current); + log_validation_status(rc, uri, current_cert_recheck, generation); logmsg(rc, log_telemetry, "Rechecking %s", uri->s); } else { logmsg(rc, log_telemetry, "Checking %s", uri->s); @@ -2759,15 +2800,15 @@ static X509 *check_cert(rcynic_ctx_t *rc, if ((certs = walk_ctx_stack_certs(wsk)) == NULL) return NULL; - if ((x = check_cert_1(rc, uri, &path, prefix, certs, issuer, subject, hash, hashlen)) != NULL) { - install_object(rc, uri, &path, accept_code); + if ((x = check_cert_1(rc, uri, &path, prefix, certs, issuer, subject, hash, hashlen, generation)) != NULL) { + install_object(rc, uri, &path, accept_code, generation); if (w->state == walk_state_current) sk_OPENSSL_STRING_remove(rc->backup_cache, uri->s); else if (!sk_OPENSSL_STRING_push_strdup(rc->backup_cache, uri->s)) logmsg(rc, log_sys_err, "Couldn't cache URI %s, blundering onward", uri->s); } else if (!access(path.s, F_OK)) { - log_validation_status(rc, uri, reject_code); + log_validation_status(rc, uri, reject_code, generation); } sk_X509_free(certs); @@ -2785,7 +2826,8 @@ static Manifest *check_manifest_1(const rcynic_ctx_t *rc, const uri_t *uri, path_t *path, const path_t *prefix, - STACK_OF(X509) *certs) + STACK_OF(X509) *certs, + const object_generation_t generation) { CMS_ContentInfo *cms = NULL; const ASN1_OBJECT *eContentType = NULL; @@ -2808,7 +2850,7 @@ static Manifest *check_manifest_1(const rcynic_ctx_t *rc, if ((eContentType = CMS_get0_eContentType(cms)) == NULL || oid_cmp(eContentType, id_ct_rpkiManifest, sizeof(id_ct_rpkiManifest))) { - log_validation_status(rc, uri, manifest_bad_econtenttype); + log_validation_status(rc, uri, manifest_bad_econtenttype, generation); goto done; } @@ -2818,40 +2860,40 @@ static Manifest *check_manifest_1(const rcynic_ctx_t *rc, } if (CMS_verify(cms, NULL, NULL, NULL, bio, CMS_NO_SIGNER_CERT_VERIFY) <= 0) { - log_validation_status(rc, uri, manifest_invalid_cms); + log_validation_status(rc, uri, manifest_invalid_cms, generation); goto done; } if ((signers = CMS_get0_signers(cms)) == NULL || sk_X509_num(signers) != 1) { - log_validation_status(rc, uri, manifest_missing_signer); + log_validation_status(rc, uri, manifest_missing_signer, generation); goto done; } - parse_cert(rc, sk_X509_value(signers, 0), &certinfo, uri); + parse_cert(rc, sk_X509_value(signers, 0), &certinfo, uri, generation); if (!certinfo.crldp.s[0]) { - log_validation_status(rc, uri, manifest_missing_crldp); + log_validation_status(rc, uri, manifest_missing_crldp, generation); goto done; } if ((crl_tail = strrchr(certinfo.crldp.s, '/')) == NULL) { - log_validation_status(rc, uri, manifest_malformed_crldp); + log_validation_status(rc, uri, manifest_malformed_crldp, generation); goto done; } crl_tail++; if ((manifest = ASN1_item_d2i_bio(ASN1_ITEM_rptr(Manifest), bio, NULL)) == NULL) { - log_validation_status(rc, uri, manifest_decode_error); + log_validation_status(rc, uri, manifest_decode_error, generation); goto done; } if (manifest->version) { - log_validation_status(rc, uri, manifest_wrong_version); + log_validation_status(rc, uri, manifest_wrong_version, generation); goto done; } if (X509_cmp_current_time(manifest->thisUpdate) > 0) { - log_validation_status(rc, uri, manifest_not_yet_valid); + log_validation_status(rc, uri, manifest_not_yet_valid, generation); goto done; } @@ -2860,10 +2902,10 @@ static Manifest *check_manifest_1(const rcynic_ctx_t *rc, if (!sk_OPENSSL_STRING_push_strdup(rc->stale_cache, uri->s)) logmsg(rc, log_sys_err, "Couldn't cache stale manifest %s, blundering onward", uri->s); if (!rc->allow_stale_manifest) { - log_validation_status(rc, uri, stale_manifest); + log_validation_status(rc, uri, stale_manifest, generation); goto done; } - log_validation_status(rc, uri, stale_manifest); + log_validation_status(rc, uri, stale_manifest, generation); } if (manifest->fileHashAlg == NULL || @@ -2879,7 +2921,7 @@ static Manifest *check_manifest_1(const rcynic_ctx_t *rc, sk_X509_value(certs, sk_X509_num(certs) - 1), fah->hash->data, fah->hash->length); } else { - log_validation_status(rc, uri, crl_not_in_manifest); + log_validation_status(rc, uri, crl_not_in_manifest, generation); if (rc->require_crl_in_manifest) goto done; crl = check_crl(rc, &certinfo.crldp, @@ -2888,7 +2930,7 @@ static Manifest *check_manifest_1(const rcynic_ctx_t *rc, } if (!crl) { - log_validation_status(rc, uri, manifest_bad_crl); + log_validation_status(rc, uri, manifest_bad_crl, generation); goto done; } @@ -2918,7 +2960,7 @@ static Manifest *check_manifest_1(const rcynic_ctx_t *rc, /* * Redundant error message? */ - log_validation_status(rc, uri, manifest_invalid_ee); + log_validation_status(rc, uri, manifest_invalid_ee, generation); goto done; } @@ -2980,18 +3022,18 @@ static Manifest *check_manifest(const rcynic_ctx_t *rc, if (manifest == NULL) { if ((manifest = check_manifest_1(rc, uri, &path, - &rc->unauthenticated, certs)) != NULL) - install_object(rc, uri, &path, current_manifest_accepted); + &rc->unauthenticated, certs, object_generation_current)) != NULL) + install_object(rc, uri, &path, current_manifest_accepted, object_generation_current); else if (!access(path.s, F_OK)) - log_validation_status(rc, uri, current_manifest_rejected); + log_validation_status(rc, uri, current_manifest_rejected, object_generation_current); } if (manifest == NULL) { if ((manifest = check_manifest_1(rc, uri, &path, - &rc->old_authenticated, certs)) != NULL) - install_object(rc, uri, &path, backup_manifest_accepted); + &rc->old_authenticated, certs, object_generation_backup)) != NULL) + install_object(rc, uri, &path, backup_manifest_accepted, object_generation_backup); else if (!access(path.s, F_OK)) - log_validation_status(rc, uri, backup_manifest_rejected); + log_validation_status(rc, uri, backup_manifest_rejected, object_generation_backup); } sk_X509_free(certs); @@ -3045,7 +3087,8 @@ static int check_roa_1(const rcynic_ctx_t *rc, const path_t *prefix, STACK_OF(X509) *certs, const unsigned char *hash, - const size_t hashlen) + const size_t hashlen, + const object_generation_t generation) { unsigned char addrbuf[ADDR_RAW_BUF_LEN]; const ASN1_OBJECT *eContentType = NULL; @@ -3070,7 +3113,7 @@ static int check_roa_1(const rcynic_ctx_t *rc, goto error; if (hashlen > sizeof(hashbuf.h)) { - log_validation_status(rc, uri, hash_too_long); + log_validation_status(rc, uri, hash_too_long, generation); goto error; } @@ -3083,14 +3126,14 @@ static int check_roa_1(const rcynic_ctx_t *rc, goto error; if (hash && memcmp(hashbuf.h, hash, hashlen)) { - log_validation_status(rc, uri, roa_digest_mismatch); + log_validation_status(rc, uri, roa_digest_mismatch, generation); goto error; } if (!(eContentType = CMS_get0_eContentType(cms)) || oid_cmp(eContentType, id_ct_routeOriginAttestation, sizeof(id_ct_routeOriginAttestation))) { - log_validation_status(rc, uri, roa_bad_econtenttype); + log_validation_status(rc, uri, roa_bad_econtenttype, generation); goto error; } @@ -3100,24 +3143,24 @@ static int check_roa_1(const rcynic_ctx_t *rc, } if (CMS_verify(cms, NULL, NULL, NULL, bio, CMS_NO_SIGNER_CERT_VERIFY) <= 0) { - log_validation_status(rc, uri, roa_invalid_cms); + log_validation_status(rc, uri, roa_invalid_cms, generation); goto error; } if (!(signers = CMS_get0_signers(cms)) || sk_X509_num(signers) != 1) { - log_validation_status(rc, uri, roa_missing_signer); + log_validation_status(rc, uri, roa_missing_signer, generation); goto error; } - parse_cert(rc, sk_X509_value(signers, 0), &certinfo, uri); + parse_cert(rc, sk_X509_value(signers, 0), &certinfo, uri, generation); if (!(roa = ASN1_item_d2i_bio(ASN1_ITEM_rptr(ROA), bio, NULL))) { - log_validation_status(rc, uri, roa_decode_error); + log_validation_status(rc, uri, roa_decode_error, generation); goto error; } if (roa->version) { - log_validation_status(rc, uri, roa_wrong_version); + log_validation_status(rc, uri, roa_wrong_version, generation); goto error; } @@ -3138,7 +3181,7 @@ static int check_roa_1(const rcynic_ctx_t *rc, for (i = 0; i < sk_ROAIPAddressFamily_num(roa->ipAddrBlocks); i++) { rf = sk_ROAIPAddressFamily_value(roa->ipAddrBlocks, i); if (!rf || !rf->addressFamily || rf->addressFamily->length < 2 || rf->addressFamily->length > 3) { - log_validation_status(rc, uri, malformed_roa_addressfamily); + log_validation_status(rc, uri, malformed_roa_addressfamily, generation); goto error; } afi = (rf->addressFamily->data[0] << 8) | (rf->addressFamily->data[1]); @@ -3149,7 +3192,7 @@ static int check_roa_1(const rcynic_ctx_t *rc, if (!ra || !extract_roa_prefix(addrbuf, &prefixlen, ra->IPAddress, afi) || !v3_addr_add_prefix(roa_resources, afi, safi, addrbuf, prefixlen)) { - log_validation_status(rc, uri, roa_resources_malformed); + log_validation_status(rc, uri, roa_resources_malformed, generation); goto error; } } @@ -3169,7 +3212,7 @@ static int check_roa_1(const rcynic_ctx_t *rc, IPAddressFamily *f = sk_IPAddressFamily_value(roa_resources, i); if ((afi = v3_addr_get_afi(f)) == 0) { - log_validation_status(rc, uri, roa_bad_afi); + log_validation_status(rc, uri, roa_bad_afi, generation); goto error; } @@ -3187,7 +3230,7 @@ static int check_roa_1(const rcynic_ctx_t *rc, if ((length = v3_addr_get_range(a, afi, a_min, a_max, ADDR_RAW_BUF_LEN)) == 0 || (length = v3_addr_get_range(b, afi, b_min, b_max, ADDR_RAW_BUF_LEN)) == 0) { - log_validation_status(rc, uri, roa_resources_malformed); + log_validation_status(rc, uri, roa_resources_malformed, generation); goto error; } @@ -3201,17 +3244,17 @@ static int check_roa_1(const rcynic_ctx_t *rc, } if (!v3_addr_canonize(roa_resources)) { - log_validation_status(rc, uri, roa_resources_malformed); + log_validation_status(rc, uri, roa_resources_malformed, generation); goto error; } if (!v3_addr_subset(roa_resources, ee_resources)) { - log_validation_status(rc, uri, roa_not_nested); + log_validation_status(rc, uri, roa_not_nested, generation); goto error; } if (!(crl = check_crl(rc, &certinfo.crldp, sk_X509_value(certs, sk_X509_num(certs) - 1), NULL, 0))) { - log_validation_status(rc, uri, roa_bad_crl); + log_validation_status(rc, uri, roa_bad_crl, generation); goto error; } @@ -3241,7 +3284,7 @@ static int check_roa_1(const rcynic_ctx_t *rc, /* * Redundant error message? */ - log_validation_status(rc, uri, roa_invalid_ee); + log_validation_status(rc, uri, roa_invalid_ee, generation); goto error; } @@ -3288,19 +3331,19 @@ static void check_roa(const rcynic_ctx_t *rc, return; if (check_roa_1(rc, uri, &path, &rc->unauthenticated, - certs, hash, hashlen)) { - install_object(rc, uri, &path, current_roa_accepted); + certs, hash, hashlen, object_generation_current)) { + install_object(rc, uri, &path, current_roa_accepted, object_generation_current); goto done; } else if (!access(path.s, F_OK)) { - log_validation_status(rc, uri, current_roa_rejected); + log_validation_status(rc, uri, current_roa_rejected, object_generation_current); } if (check_roa_1(rc, uri, &path, &rc->old_authenticated, - certs, hash, hashlen)) { - install_object(rc, uri, &path, backup_roa_accepted); + certs, hash, hashlen, object_generation_backup)) { + install_object(rc, uri, &path, backup_roa_accepted, object_generation_backup); goto done; } else if (!access(path.s, F_OK)) { - log_validation_status(rc, uri, backup_roa_rejected); + log_validation_status(rc, uri, backup_roa_rejected, object_generation_backup); } done: @@ -3318,7 +3361,8 @@ static int check_ghostbuster_1(const rcynic_ctx_t *rc, const path_t *prefix, STACK_OF(X509) *certs, const unsigned char *hash, - const size_t hashlen) + const size_t hashlen, + const object_generation_t generation) { const ASN1_OBJECT *eContentType = NULL; STACK_OF(X509_CRL) *crls = NULL; @@ -3337,7 +3381,7 @@ static int check_ghostbuster_1(const rcynic_ctx_t *rc, goto error; if (hashlen > sizeof(hashbuf.h)) { - log_validation_status(rc, uri, hash_too_long); + log_validation_status(rc, uri, hash_too_long, generation); goto error; } @@ -3350,14 +3394,14 @@ static int check_ghostbuster_1(const rcynic_ctx_t *rc, goto error; if (hash && memcmp(hashbuf.h, hash, hashlen)) { - log_validation_status(rc, uri, ghostbuster_digest_mismatch); + log_validation_status(rc, uri, ghostbuster_digest_mismatch, generation); goto error; } if (!(eContentType = CMS_get0_eContentType(cms)) || oid_cmp(eContentType, id_ct_rpkiGhostbusters, sizeof(id_ct_rpkiGhostbusters))) { - log_validation_status(rc, uri, ghostbuster_bad_econtenttype); + log_validation_status(rc, uri, ghostbuster_bad_econtenttype, generation); goto error; } @@ -3373,16 +3417,16 @@ static int check_ghostbuster_1(const rcynic_ctx_t *rc, #endif if (CMS_verify(cms, NULL, NULL, NULL, bio, CMS_NO_SIGNER_CERT_VERIFY) <= 0) { - log_validation_status(rc, uri, ghostbuster_invalid_cms); + log_validation_status(rc, uri, ghostbuster_invalid_cms, generation); goto error; } if (!(signers = CMS_get0_signers(cms)) || sk_X509_num(signers) != 1) { - log_validation_status(rc, uri, ghostbuster_missing_signer); + log_validation_status(rc, uri, ghostbuster_missing_signer, generation); goto error; } - parse_cert(rc, sk_X509_value(signers, 0), &certinfo, uri); + parse_cert(rc, sk_X509_value(signers, 0), &certinfo, uri, generation); #if 0 /* @@ -3392,7 +3436,7 @@ static int check_ghostbuster_1(const rcynic_ctx_t *rc, #endif if (!(crl = check_crl(rc, &certinfo.crldp, sk_X509_value(certs, sk_X509_num(certs) - 1), NULL, 0))) { - log_validation_status(rc, uri, ghostbuster_bad_crl); + log_validation_status(rc, uri, ghostbuster_bad_crl, generation); goto error; } @@ -3419,7 +3463,7 @@ static int check_ghostbuster_1(const rcynic_ctx_t *rc, X509_VERIFY_PARAM_add0_policy(rctx.ctx.param, OBJ_txt2obj(rpki_policy_oid, 1)); if (X509_verify_cert(&rctx.ctx) <= 0) { - log_validation_status(rc, uri, ghostbuster_invalid_ee); + log_validation_status(rc, uri, ghostbuster_invalid_ee, generation); goto error; } @@ -3463,19 +3507,19 @@ static void check_ghostbuster(const rcynic_ctx_t *rc, return; if (check_ghostbuster_1(rc, uri, &path, &rc->unauthenticated, - certs, hash, hashlen)) { - install_object(rc, uri, &path, current_ghostbuster_accepted); + certs, hash, hashlen, object_generation_current)) { + install_object(rc, uri, &path, current_ghostbuster_accepted, object_generation_current); goto done; } else if (!access(path.s, F_OK)) { - log_validation_status(rc, uri, current_ghostbuster_rejected); + log_validation_status(rc, uri, current_ghostbuster_rejected, object_generation_current); } if (check_ghostbuster_1(rc, uri, &path, &rc->old_authenticated, - certs, hash, hashlen)) { - install_object(rc, uri, &path, backup_ghostbuster_accepted); + certs, hash, hashlen, object_generation_backup)) { + install_object(rc, uri, &path, backup_ghostbuster_accepted, object_generation_backup); goto done; } else if (!access(path.s, F_OK)) { - log_validation_status(rc, uri, backup_ghostbuster_rejected); + log_validation_status(rc, uri, backup_ghostbuster_rejected, object_generation_backup); } done: @@ -3517,7 +3561,7 @@ static void rsync_sia_callback(const rcynic_ctx_t *rc, return; case rsync_status_failed: - log_validation_status(rc, uri, rsync_failed); + log_validation_status(rc, uri, rsync_failed, object_generation_null); /* Fall through */ case rsync_status_done: @@ -3543,6 +3587,7 @@ static void rsync_sia_callback(const rcynic_ctx_t *rc, static void walk_cert(rcynic_ctx_t *rc, STACK_OF(walk_ctx_t) *wsk) { const unsigned char *hash = NULL; + object_generation_t generation; size_t hashlen; walk_ctx_t *w; uri_t uri; @@ -3552,6 +3597,18 @@ static void walk_cert(rcynic_ctx_t *rc, STACK_OF(walk_ctx_t) *wsk) while ((w = walk_ctx_stack_head(wsk)) != NULL) { switch (w->state) { + case walk_state_current: + generation = object_generation_current; + break; + case walk_state_backup: + generation = object_generation_backup; + break; + default: + generation = object_generation_unknown; + break; + } + + switch (w->state) { case walk_state_initial: @@ -3561,7 +3618,7 @@ static void walk_cert(rcynic_ctx_t *rc, STACK_OF(walk_ctx_t) *wsk) } if (!w->certinfo.manifest.s[0]) { - log_validation_status(rc, &w->certinfo.uri, manifest_missing); + log_validation_status(rc, &w->certinfo.uri, manifest_missing, w->certinfo.generation); w->state = walk_state_done; continue; } @@ -3593,7 +3650,7 @@ static void walk_cert(rcynic_ctx_t *rc, STACK_OF(walk_ctx_t) *wsk) } if (hash == NULL) - log_validation_status(rc, &uri, object_not_in_manifest); + log_validation_status(rc, &uri, object_not_in_manifest, generation); if (hash == NULL && !rc->allow_object_not_in_manifest) { walk_ctx_loop_next(rc, wsk); @@ -3620,7 +3677,7 @@ static void walk_cert(rcynic_ctx_t *rc, STACK_OF(walk_ctx_t) *wsk) continue; } - log_validation_status(rc, &uri, unknown_object_type); + log_validation_status(rc, &uri, unknown_object_type, generation); walk_ctx_loop_next(rc, wsk); continue; @@ -4008,7 +4065,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); + log_validation_status(&rc, &uri, unreadable_trust_anchor, object_generation_unknown); continue; } hash = X509_subject_name_hash(x); @@ -4041,7 +4098,7 @@ int main(int argc, char *argv[]) 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); + log_validation_status(&rc, &uri, unreadable_trust_anchor_locator, object_generation_unknown); BIO_free(bio); bio = NULL; continue; @@ -4050,7 +4107,7 @@ int main(int argc, char *argv[]) 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); + log_validation_status(&rc, &uri, unreadable_trust_anchor_locator, object_generation_unknown); BIO_free_all(bio); bio = NULL; continue; @@ -4064,17 +4121,17 @@ int main(int argc, char *argv[]) BIO_free_all(bio); bio = NULL; if (!pkey) { - log_validation_status(&rc, &uri, unreadable_trust_anchor_locator); + log_validation_status(&rc, &uri, unreadable_trust_anchor_locator, object_generation_unknown); } if (pkey && (x = read_cert(&path1, NULL)) == NULL) - log_validation_status(&rc, &uri, unreadable_trust_anchor); + 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); + 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); + log_validation_status(&rc, &uri, trust_anchor_key_mismatch, object_generation_unknown); X509_free(x); continue; } @@ -4093,7 +4150,7 @@ int main(int argc, char *argv[]) goto done; } - parse_cert(&rc, x, &ta_certinfo, &uri); + parse_cert(&rc, x, &ta_certinfo, &uri, object_generation_unknown); ta_certinfo.ta = 1; if ((w = walk_ctx_stack_push(wsk, x, &ta_certinfo)) == NULL) { @@ -4147,12 +4204,13 @@ int main(int argc, char *argv[]) tad, svn_id, XML_SUMMARY_VERSION, hostname.s) != EOF; for (j = 0; ok && j < MIB_COUNTER_T_MAX; ++j) - ok &= fprintf(f, " <%s kind=\"%s\">%s</%s>\n", - mib_counter_label[j], mib_counter_kind[j], - (mib_counter_desc[j] - ? mib_counter_desc[j] - : X509_verify_cert_error_string(mib_counter_openssl[j])), - mib_counter_label[j]) != EOF; + if (ok) + ok &= fprintf(f, " <%s kind=\"%s\">%s</%s>\n", + mib_counter_label[j], mib_counter_kind[j], + (mib_counter_desc[j] + ? mib_counter_desc[j] + : X509_verify_cert_error_string(mib_counter_openssl[j])), + mib_counter_label[j]) != EOF; if (ok) ok &= fprintf(f, " </labels>\n") != EOF; @@ -4164,10 +4222,19 @@ int main(int argc, char *argv[]) tad_tm = gmtime(&v->timestamp); strftime(tad, sizeof(tad), "%Y-%m-%dT%H:%M:%SZ", tad_tm); - for (code = (mib_counter_t) 0; ok && code < MIB_COUNTER_T_MAX; code++) - if (validation_status_get_code(v, code)) - ok &= fprintf(f, " <validation_status timestamp=\"%s\" status=\"%s\">%s</validation_status>\n", - tad, mib_counter_label[code], v->uri.s) != EOF; + for (code = (mib_counter_t) 0; ok && code < MIB_COUNTER_T_MAX; code++) { + if (validation_status_get_code(v, code)) { + if (ok) + ok &= fprintf(f, " <validation_status timestamp=\"%s\" status=\"%s\"", + tad, mib_counter_label[code]) != EOF; + if (ok && (v->generation == object_generation_current || + v->generation == object_generation_backup)) + ok &= fprintf(f, " generation=\"%s\"", + object_generation_label[v->generation]) != EOF; + if (ok) + ok &= fprintf(f, ">%s</validation_status>\n", v->uri.s) != EOF; + } + } } if (ok) |