aboutsummaryrefslogtreecommitdiff
path: root/rcynic/rcynic.c
diff options
context:
space:
mode:
Diffstat (limited to 'rcynic/rcynic.c')
-rw-r--r--rcynic/rcynic.c131
1 files changed, 90 insertions, 41 deletions
diff --git a/rcynic/rcynic.c b/rcynic/rcynic.c
index 10ceee19..9071622e 100644
--- a/rcynic/rcynic.c
+++ b/rcynic/rcynic.c
@@ -1198,7 +1198,7 @@ static void *read_file_with_hash(const char *filename,
if ((b = BIO_new_file(filename, "rb")) == NULL)
goto error;
-
+
if (hash != NULL) {
BIO *b2 = BIO_new(BIO_f_md());
if (b2 == NULL)
@@ -1356,17 +1356,30 @@ static void parse_cert(X509 *x, certinfo_t *c, const char *uri)
static X509_CRL *check_crl_1(const char *uri,
char *path, const int pathlen,
const char *prefix,
- X509 *issuer)
+ X509 *issuer,
+ const unsigned char *hash,
+ const size_t hashlen)
{
+ unsigned char hashbuf[EVP_MAX_MD_SIZE];
X509_CRL *crl = NULL;
EVP_PKEY *pkey;
int ret;
- assert(uri && path && issuer);
+ assert(uri && path && issuer && hashlen <= sizeof(hashbuf));
- if (!uri_to_filename(uri, path, pathlen, prefix) ||
- (crl = read_crl(path, NULL, 0)) == NULL)
- return NULL;
+ if (!uri_to_filename(uri, path, pathlen, prefix))
+ goto punt;
+
+ if (hash)
+ crl = read_crl(path, hashbuf, sizeof(hashbuf));
+ else
+ crl = read_crl(path, NULL, 0);
+
+ if (!crl)
+ goto punt;
+
+ if (hash && memcmp(hashbuf, hash, hashlen))
+ goto punt;
if ((pkey = X509_get_pubkey(issuer)) == NULL)
goto punt;
@@ -1387,21 +1400,29 @@ static X509_CRL *check_crl_1(const char *uri,
*/
static X509_CRL *check_crl(const rcynic_ctx_t *rc,
const char *uri,
- X509 *issuer)
+ X509 *issuer,
+ const unsigned char *hash,
+ const size_t hashlen)
{
char path[FILENAME_MAX];
X509_CRL *crl;
- if (uri_to_filename(uri, path, sizeof(path), rc->authenticated) &&
- (crl = read_crl(path, NULL, 0)) != NULL)
- return crl;
+ if (uri_to_filename(uri, path, sizeof(path), rc->authenticated)) {
+ unsigned char hashbuf[EVP_MAX_MD_SIZE];
+ if (hash)
+ crl = read_crl(path, hashbuf, sizeof(hashbuf));
+ else
+ crl = read_crl(path, NULL, 0);
+ if (crl)
+ return crl;
+ }
logmsg(rc, log_telemetry, "Checking CRL %s", uri);
rsync_crl(rc, uri);
- if ((crl = check_crl_1(uri, path, sizeof(path),
- rc->unauthenticated, issuer))) {
+ if ((crl = check_crl_1(uri, path, sizeof(path), rc->unauthenticated,
+ issuer, hash, hashlen))) {
install_object(rc, uri, path, 5);
mib_increment(rc, uri, current_crl_accepted);
return crl;
@@ -1409,8 +1430,8 @@ static X509_CRL *check_crl(const rcynic_ctx_t *rc,
mib_increment(rc, uri, current_crl_rejected);
}
- if ((crl = check_crl_1(uri, path, sizeof(path),
- rc->old_authenticated, issuer))) {
+ if ((crl = check_crl_1(uri, path, sizeof(path), rc->old_authenticated,
+ issuer, hash, hashlen))) {
install_object(rc, uri, path, 5);
mib_increment(rc, uri, backup_crl_accepted);
return crl;
@@ -1447,6 +1468,8 @@ static Manifest *check_manifest_1(const rcynic_ctx_t *rc,
rcynic_x509_store_ctx_t rctx;
certinfo_t certinfo;
int i, initialized_store_ctx = 0;
+ FileAndHash *fah = NULL;
+ char *crl_tail;
assert(rc && uri && path && prefix && certs && sk_X509_num(certs));
@@ -1461,8 +1484,10 @@ static Manifest *check_manifest_1(const rcynic_ctx_t *rc,
goto done;
}
- if ((bio = BIO_new(BIO_s_mem())) == NULL)
+ if ((bio = BIO_new(BIO_s_mem())) == NULL) {
+ logmsg(rc, log_sys_err, "Couldn't allocate BIO for manifest %s", uri);
goto done;
+ }
if (CMS_verify(cms, NULL, NULL, NULL, bio, CMS_NO_SIGNER_CERT_VERIFY) <= 0) {
logmsg(rc, log_data_err, "Validation failure for manifest %s CMS message", uri);
@@ -1478,8 +1503,55 @@ static Manifest *check_manifest_1(const rcynic_ctx_t *rc,
parse_cert(sk_X509_value(signers, 0), &certinfo, uri);
- if ((crl = check_crl(rc, certinfo.crldp,
- sk_X509_value(certs, sk_X509_num(certs) - 1))) == NULL) {
+ if ((crl_tail = strrchr(certinfo.crldp, '/')) == NULL) {
+ logmsg(rc, log_data_err, "Couldn't find trailing slash in %s CRLDP for manifest %s", certinfo.crldp, uri);
+ goto done;
+ }
+ crl_tail++;
+
+ if ((manifest = ASN1_item_d2i_bio(ASN1_ITEM_rptr(Manifest), bio, NULL)) == NULL) {
+ logmsg(rc, log_data_err, "Failure decoding manifest %s", uri);
+ mib_increment(rc, uri, manifest_decode_error);
+ goto done;
+ }
+
+ if (X509_cmp_current_time(manifest->thisUpdate) > 0) {
+ logmsg(rc, log_data_err, "Manifest %s not yet valid", uri);
+ mib_increment(rc, uri, manifest_not_yet_valid);
+ goto done;
+ }
+
+ if (X509_cmp_current_time(manifest->nextUpdate) < 0) {
+ logmsg(rc, log_data_err, "Stale manifest %s", uri);
+ mib_increment(rc, uri, stale_manifest);
+ if (!rc->allow_stale_manifest)
+ goto done;
+ }
+
+ if (manifest->fileHashAlg == NULL ||
+ oid_cmp(manifest->fileHashAlg, id_sha256, sizeof(id_sha256)))
+ goto done;
+
+ for (i = 0; (fah = sk_FileAndHash_value(manifest->fileList, i)) != NULL; i++)
+ if (!strcmp(fah->file->data, crl_tail))
+ break;
+
+#warning Not enforcing requirement that CRLs be listed in manifests
+ /*
+ * For now we tolerate CRL not listed in manifest. Either clean
+ * this up or turn it into a config option eventually.
+ */
+
+ if (fah) {
+ crl = check_crl(rc, certinfo.crldp, sk_X509_value(certs, sk_X509_num(certs) - 1),
+ fah->hash->data, fah->hash->length);
+ } else {
+ logmsg(rc, log_data_err, "Couldn't find CRL %s in manifest %s, blundering onward", certinfo.crldp, uri);
+ crl = check_crl(rc, certinfo.crldp, sk_X509_value(certs, sk_X509_num(certs) - 1),
+ NULL, 0);
+ }
+
+ if (!crl) {
logmsg(rc, log_data_err, "Bad CRL %s for manifest %s EE certificate", certinfo.crldp, uri);
goto done;
}
@@ -1514,29 +1586,6 @@ static Manifest *check_manifest_1(const rcynic_ctx_t *rc,
goto done;
}
- if ((manifest = ASN1_item_d2i_bio(ASN1_ITEM_rptr(Manifest), bio, NULL)) == NULL) {
- logmsg(rc, log_data_err, "Failure decoding manifest %s", uri);
- mib_increment(rc, uri, manifest_decode_error);
- goto done;
- }
-
- if (X509_cmp_current_time(manifest->thisUpdate) > 0) {
- logmsg(rc, log_data_err, "Manifest %s not yet valid", uri);
- mib_increment(rc, uri, manifest_not_yet_valid);
- goto done;
- }
-
- if (X509_cmp_current_time(manifest->nextUpdate) < 0) {
- logmsg(rc, log_data_err, "Stale manifest %s", uri);
- mib_increment(rc, uri, stale_manifest);
- if (!rc->allow_stale_manifest)
- goto done;
- }
-
- if (manifest->fileHashAlg == NULL ||
- oid_cmp(manifest->fileHashAlg, id_sha256, sizeof(id_sha256)))
- goto done;
-
#warning Still need to check CRL against manifest
result = manifest;
@@ -1705,7 +1754,7 @@ static int check_x509(const rcynic_ctx_t *rc,
goto done;
}
- if ((crl = check_crl(rc, subj->crldp, issuer)) == NULL) {
+ if ((crl = check_crl(rc, subj->crldp, issuer, NULL, 0)) == NULL) {
logmsg(rc, log_data_err, "Bad CRL %s for %s", subj->crldp, subj->uri);
goto done;
}