aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2011-05-23 21:17:09 +0000
committerRob Austein <sra@hactrn.net>2011-05-23 21:17:09 +0000
commite79beff7341bbb32585bcfb9f004711f87456b6b (patch)
tree7b7f1ec2d35a20d1e17431f2697f53f178d123d2
parent21f20c298a4ec9fb107fee09b78b0aa209a09590 (diff)
Checkpoint
svn path=/rcynic-ng/rcynic.c; revision=3823
-rw-r--r--rcynic-ng/rcynic.c253
1 files changed, 142 insertions, 111 deletions
diff --git a/rcynic-ng/rcynic.c b/rcynic-ng/rcynic.c
index 178d41ba..fe192e8d 100644
--- a/rcynic-ng/rcynic.c
+++ b/rcynic-ng/rcynic.c
@@ -497,12 +497,18 @@ static void VALIDATION_STATUS_free(VALIDATION_STATUS *v)
/**
* Allocate a new walk context.
*/
-static walk_ctx_t *walk_ctx_new(rcynic_ctx_t *rc)
+static walk_ctx_t *walk_ctx_new(rcynic_ctx_t *rc, X509 *x)
{
walk_ctx_t *w = malloc(sizeof(*w));
if (w != NULL) {
memset(w, 0, sizeof(*w));
w->rc = rc;
+ w->cert = x;
+
+ /*
+ * Perhaps we should be calling parse_cert() here?
+ */
+
}
return w;
}
@@ -552,9 +558,10 @@ static STACK_OF(walk_ctx_t) *walk_ctx_stack_new(void)
/**
* Push a walk context onto a walk context stack.
*/
-static int walk_ctx_stack_push(STACK_OF(walk_ctx_t) *sk, walk_ctx_t *w)
+static int walk_ctx_stack_push(STACK_OF(walk_ctx_t) *sk, rcynic_ctx_t *rc, X509 *x)
{
- int res = sk_walk_ctx_t_push(sk, w);
+ walk_ctx_t *w = walk_ctx_new(rc, x);
+ int res = (w != NULL) && sk_walk_ctx_t_push(sk, w);
if (res)
walk_ctx_incref(w);
return res;
@@ -1807,6 +1814,47 @@ static X509_CRL *check_crl(const rcynic_ctx_t *rc,
/**
+ * Check whether extensions in a certificate are allowed by profile.
+ * Also returns failure in a few null-pointer cases that can't
+ * possibly conform to profile.
+ */
+static int check_allowed_extensions(const X509 *x, const int allow_eku)
+{
+ int i;
+
+ if (x == NULL || x->cert_info == NULL || x->cert_info->extensions == NULL)
+ return 0;
+
+ for (i = 0; i < sk_X509_EXTENSION_num(x->cert_info->extensions); i++) {
+ switch (OBJ_obj2nid(sk_X509_EXTENSION_value(x->cert_info->extensions,
+ i)->object)) {
+ case NID_basic_constraints:
+ case NID_subject_key_identifier:
+ case NID_authority_key_identifier:
+ case NID_key_usage:
+ case NID_crl_distribution_points:
+ case NID_info_access:
+ case NID_sinfo_access:
+ case NID_certificate_policies:
+ case NID_sbgp_ipAddrBlock:
+ case NID_sbgp_autonomousSysNum:
+ continue;
+ case NID_ext_key_usage:
+ if (allow_eku)
+ continue;
+ else
+ return 0;
+ default:
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+
+
+/**
* Validation callback function for use with x509_verify_cert().
*/
static int check_x509_cb(int ok, X509_STORE_CTX *ctx)
@@ -1909,30 +1957,68 @@ static int check_x509_cb(int ok, X509_STORE_CTX *ctx)
static int check_x509(const rcynic_ctx_t *rc,
STACK_OF(X509) *certs,
X509 *x,
- const certinfo_t *subject)
+ const certinfo_t *subject,
+ const certinfo_t *issuer_certinfo)
{
rcynic_x509_store_ctx_t rctx;
STACK_OF(X509_CRL) *crls = NULL;
EVP_PKEY *pkey = NULL;
X509_CRL *crl = NULL;
- unsigned long flags;
+ unsigned long flags = (X509_V_FLAG_POLICY_CHECK | X509_V_FLAG_EXPLICIT_POLICY | X509_V_FLAG_X509_STRICT);
X509 *issuer;
int ret = 0;
assert(rc && certs && x && subject);
- issuer = sk_X509_value(certs, sk_X509_num(certs) - 1);
- assert(issuer != NULL);
-
- flags = (X509_V_FLAG_POLICY_CHECK |
- X509_V_FLAG_EXPLICIT_POLICY |
- X509_V_FLAG_X509_STRICT);
-
if (!X509_STORE_CTX_init(&rctx.ctx, rc->x509_store, x, NULL))
return 0;
rctx.rc = rc;
rctx.subject = subject;
+ issuer = sk_X509_value(certs, sk_X509_num(certs) - 1);
+ assert(issuer != NULL);
+
+ if (subject->sia[0] && subject->sia[strlen(subject->sia) - 1] != '/') {
+ reject(rc, subject->uri, malformed_sia,
+ "due to malformed SIA %s", subject->sia);
+ goto done;
+ }
+
+ if (!subject->ta && !subject->aia[0]) {
+ reject(rc, subject->uri, aia_missing, "due to missing AIA extension");
+ goto done;
+ }
+ if (!issuer_certinfo->ta && strcmp(issuer_certinfo->uri, subject->aia)) {
+ reject(rc, subject->uri, aia_mismatch,
+ "because AIA %s doesn't match parent", subject->aia);
+ goto done;
+ }
+
+ if (subject->ca && !subject->sia[0]) {
+ reject(rc, subject->uri, sia_missing,
+ "because SIA extension repository pointer is missing");
+ goto done;
+ }
+
+ if (subject->ca && !subject->manifest[0]) {
+ reject(rc, subject->uri, manifest_missing,
+ "because SIA extension manifest pointer is missing");
+ goto done;
+ }
+
+ if (subject->ca && !startswith(subject->manifest, subject->sia)) {
+ reject(rc, subject->uri, manifest_mismatch,
+ "because SIA manifest %s points outside publication point %s",
+ subject->manifest, subject->sia);
+ goto done;
+ }
+
+ if (!check_allowed_extensions(x, !subject->ca)) {
+ reject(rc, subject->uri, disallowed_extension,
+ "due to disallowed X.509v3 extension");
+ goto done;
+ }
+
if (subject->ta) {
if (subject->crldp[0]) {
@@ -1943,7 +2029,17 @@ static int check_x509(const rcynic_ctx_t *rc,
} else {
- assert(subject->crldp[0]);
+ if (!subject->crldp[0]) {
+ reject(rc, subject->uri, crldp_missing, "because CRLDP extension is missing");
+ goto done;
+ }
+
+ if (!subject->ca && !startswith(subject->crldp, issuer_certinfo->sia)) {
+ reject(rc, subject->uri, crldp_mismatch,
+ "because CRLDP %s points outside issuer's publication point %s",
+ subject->crldp, issuer_certinfo->sia);
+ goto done;
+ }
flags |= X509_V_FLAG_CRL_CHECK;
@@ -1998,45 +2094,6 @@ static int check_x509(const rcynic_ctx_t *rc,
}
/**
- * Check whether extensions in a certificate are allowed by profile.
- * Also returns failure in a few null-pointer cases that can't
- * possibly conform to profile.
- */
-static int check_cert_only_allowed_extensions(const X509 *x, const int allow_eku)
-{
- int i;
-
- if (x == NULL || x->cert_info == NULL || x->cert_info->extensions == NULL)
- return 0;
-
- for (i = 0; i < sk_X509_EXTENSION_num(x->cert_info->extensions); i++) {
- switch (OBJ_obj2nid(sk_X509_EXTENSION_value(x->cert_info->extensions,
- i)->object)) {
- case NID_basic_constraints:
- case NID_subject_key_identifier:
- case NID_authority_key_identifier:
- case NID_key_usage:
- case NID_crl_distribution_points:
- case NID_info_access:
- case NID_sinfo_access:
- case NID_certificate_policies:
- case NID_sbgp_ipAddrBlock:
- case NID_sbgp_autonomousSysNum:
- continue;
- case NID_ext_key_usage:
- if (allow_eku)
- continue;
- else
- return 0;
- default:
- return 0;
- }
- }
-
- return 1;
-}
-
-/**
* Check a certificate for conformance to the RPKI certificate profile.
*/
static X509 *check_cert_1(const rcynic_ctx_t *rc,
@@ -2079,63 +2136,12 @@ static X509 *check_cert_1(const rcynic_ctx_t *rc,
goto punt;
}
+ /* This should go away once walk context stack stuff is ready */
parse_cert(rc, x, subject, uri);
- if (subject->sia[0] && subject->sia[strlen(subject->sia) - 1] != '/') {
- reject(rc, uri, malformed_sia,
- "due to malformed SIA %s", subject->sia);
- goto punt;
- }
+ /* Whole lotta stuff moved from here to check_x509() */
- if (!subject->aia[0]) {
- reject(rc, uri, aia_missing, "due to missing AIA extension");
- goto punt;
- }
-
- if (!issuer->ta && strcmp(issuer->uri, subject->aia)) {
- reject(rc, uri, aia_mismatch,
- "because AIA %s doesn't match parent", subject->aia);
- goto punt;
- }
-
- if (subject->ca && !subject->sia[0]) {
- reject(rc, uri, sia_missing,
- "because SIA extension repository pointer is missing");
- goto punt;
- }
-
- if (!subject->crldp[0]) {
- reject(rc, uri, crldp_missing, "because CRLDP extension is missing");
- goto punt;
- }
-
- if (subject->ca && !startswith(subject->crldp, issuer->sia)) {
- reject(rc, uri, crldp_mismatch,
- "because CRLDP %s points outside issuer's publication point %s",
- subject->crldp, issuer->sia);
- goto punt;
- }
-
- if (subject->ca && !subject->manifest[0]) {
- reject(rc, uri, manifest_missing,
- "because SIA extension manifest pointer is missing");
- goto punt;
- }
-
- if (subject->ca && !startswith(subject->manifest, subject->sia)) {
- reject(rc, uri, manifest_mismatch,
- "because SIA manifest %s points outside publication point %s",
- subject->manifest, subject->sia);
- goto punt;
- }
-
- if (!check_cert_only_allowed_extensions(x, !subject->ca)) {
- reject(rc, uri, disallowed_extension,
- "due to disallowed X.509v3 extension");
- goto punt;
- }
-
- if (!check_x509(rc, certs, x, subject)) {
+ if (!check_x509(rc, certs, x, subject, issuer)) {
/*
* Redundant error message?
*/
@@ -3106,7 +3112,9 @@ int main(int argc, char *argv[])
int c, i, j, ret = 1, jitter = 600, lockfd = -1;
STACK_OF(CONF_VALUE) *cfg_section = NULL;
STACK_OF(X509) *certs = NULL;
+ STACK_OF(walk_ctx_t) *walk = NULL;
CONF *cfg_handle = NULL;
+ walk_ctx_t *w = NULL;
time_t start = 0, finish;
unsigned long hash;
rcynic_ctx_t rc;
@@ -3377,7 +3385,6 @@ 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);
char path1[FILENAME_MAX], path2[FILENAME_MAX], uri[URI_MAX];
- certinfo_t ta_info;
X509 *x = NULL;
assert(val && val->name && val->value);
@@ -3494,12 +3501,36 @@ int main(int argc, char *argv[])
goto done;
}
- parse_cert(&rc, x, &ta_info, uri);
- ta_info.ta = 1;
+ if ((walk = walk_ctx_stack_new()) == NULL) {
+ logmsg(&rc, log_sys_err, "Couldn't allocate walk context stack");
+ goto done;
+ }
+
+ if (!walk_ctx_stack_push(walk, &rc, x)) {
+ logmsg(&rc, log_sys_err, "Couldn't push trust anchor onto walk context stack");
+ goto done;
+ }
+
+ w = sk_walk_ctx_t_value(walk, 0);
+ assert(w != NULL);
+
+ parse_cert(&rc, x, &w->certinfo, uri);
+ w->certinfo.ta = 1;
sk_X509_push(certs, x);
- if (check_x509(&rc, certs, x, &ta_info))
- walk_cert(&rc, &ta_info, certs);
+ if (check_x509(&rc, certs, x, &w->certinfo, &w->certinfo))
+ walk_cert(&rc, &w->certinfo, certs);
+
+#if 1
+ w->cert = NULL;
+#endif
+ /*
+ * Temporary? Once this goes async this will have to be handled
+ * elsewhere.
+ */
+ walk_ctx_stack_free(walk);
+ walk = NULL;
+
X509_free(sk_X509_pop(certs));
assert(sk_X509_num(certs) == 0);