aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2011-05-19 01:08:24 +0000
committerRob Austein <sra@hactrn.net>2011-05-19 01:08:24 +0000
commit46cf2621a1311730d9b4501a4219456942224175 (patch)
tree29900a4982a0b81b431e41c8b8411c29976fe6af
parent9ed77ed647b3db595e432667ca4c63ad923b3769 (diff)
Checkpoint new code. Fix some contorted logic dealing with a case
that should never occur in the first place. svn path=/rcynic-ng/defstack.awk; revision=3819
-rw-r--r--rcynic-ng/defstack.awk1
-rw-r--r--rcynic-ng/rcynic.c163
2 files changed, 145 insertions, 19 deletions
diff --git a/rcynic-ng/defstack.awk b/rcynic-ng/defstack.awk
index 130bc48d..a2874f6e 100644
--- a/rcynic-ng/defstack.awk
+++ b/rcynic-ng/defstack.awk
@@ -63,5 +63,6 @@ BEGIN {
define_stack("FileAndHash");
define_stack("ROAIPAddress");
define_stack("ROAIPAddressFamily");
+ define_stack("walk_ctx_t");
print "#endif /* __DEFSTACK_H__ */";
}
diff --git a/rcynic-ng/rcynic.c b/rcynic-ng/rcynic.c
index 7bc5747d..be9cbdc9 100644
--- a/rcynic-ng/rcynic.c
+++ b/rcynic-ng/rcynic.c
@@ -352,6 +352,30 @@ typedef struct rcynic_ctx {
} rcynic_ctx_t;
/**
+ * Context for certificate tree walks. This includes all the stuff
+ * that we would keep as automatic variables on the call stack if we
+ * didn't have to use callbacks to support multiple rsync processes.
+ *
+ * Mapping between fields here and automatic variables in the older
+ * code is still in flux, names (and anything else) may change.
+ */
+typedef struct walk_ctx {
+ unsigned refcount;
+ rcynic_ctx_t *rc;
+ certinfo_t certinfo;
+ X509 *cert;
+ Manifest *manifest;
+ STACK_OF(OPENSSL_STRING) *filenames;
+ int manifest_iteration, filename_iteration;
+ enum {
+ walk_pass_current, /* prefix = rc->unauthenticated, first pass */
+ walk_pass_backup /* prefix = rc->old_authenticated, second pass */
+ } pass;
+} walk_ctx_t;
+
+DECLARE_STACK_OF(walk_ctx_t)
+
+/**
* Extended context for verify callbacks. This is a wrapper around
* OpenSSL's X509_STORE_CTX, and the embedded X509_STORE_CTX @em must be
* the first element of this structure in order for the evil cast to
@@ -470,6 +494,103 @@ static void VALIDATION_STATUS_free(VALIDATION_STATUS *v)
free(v);
}
+/**
+ * Allocate a new walk context.
+ */
+static walk_ctx_t *walk_ctx_new(rcynic_ctx_t *rc)
+{
+ walk_ctx_t *w = malloc(sizeof(*w));
+ if (w != NULL) {
+ memset(w, 0, sizeof(*w));
+ w->rc = rc;
+ }
+ return w;
+}
+
+/**
+ * Free a walk context.
+ */
+static void walk_ctx_free(walk_ctx_t *w)
+{
+ if (w == NULL)
+ return;
+ assert(w->refcount == 0);
+ X509_free(w->cert);
+ Manifest_free(w->manifest);
+ sk_OPENSSL_STRING_pop_free(w->filenames, OPENSSL_STRING_free);
+ free(w);
+}
+
+/**
+ * Increment walk context reference count.
+ */
+static void walk_ctx_incref(walk_ctx_t *w)
+{
+ if (w != NULL) {
+ w->refcount++;
+ assert(w->refcount != 0);
+ }
+}
+
+/**
+ * Decrement walk context reference count.
+ */
+static void walk_ctx_decref(walk_ctx_t *w)
+{
+ if (w != NULL && --(w->refcount) == 0)
+ walk_ctx_free(w);
+}
+
+/**
+ * Create a new walk context stack.
+ */
+static STACK_OF(walk_ctx_t) *walk_ctx_stack_new(void)
+{
+ return sk_walk_ctx_t_new_null();
+}
+
+/**
+ * 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)
+{
+ int res = sk_walk_ctx_t_push(sk, w);
+ if (res)
+ walk_ctx_incref(w);
+ return res;
+}
+
+/**
+ * Pop and discard a walk context from a walk context stack.
+ */
+static void walk_ctx_stack_pop(STACK_OF(walk_ctx_t) *sk)
+{
+ walk_ctx_decref(sk_walk_ctx_t_pop(sk));
+}
+
+/**
+ * Clone a stack of walk contexts.
+ */
+static STACK_OF(walk_ctx_t) *walk_ctx_stack_clone(STACK_OF(walk_ctx_t) *old_sk)
+{
+ STACK_OF(walk_ctx_t) *new_sk;
+ int i;
+ if (old_sk == NULL || (new_sk = sk_walk_ctx_t_dup(old_sk)) == NULL)
+ return NULL;
+ for (i = 0; i < sk_walk_ctx_t_num(new_sk); i++)
+ walk_ctx_incref(sk_walk_ctx_t_value(new_sk, i));
+ return new_sk;
+}
+
+/**
+ * Free a walk context stack, decrementing reference counts of each
+ * frame on it.
+ */
+static void walk_ctx_stack_free(STACK_OF(walk_ctx_t) *sk)
+{
+ sk_walk_ctx_t_pop_free(sk, walk_ctx_decref);
+}
+
/**
@@ -1769,14 +1890,19 @@ static int check_x509(const rcynic_ctx_t *rc,
STACK_OF(X509_CRL) *crls = NULL;
EVP_PKEY *pkey = NULL;
X509_CRL *crl = NULL;
+ unsigned long flags;
X509 *issuer;
int ret = 0;
- assert(rc && certs && x && subject && subject->crldp[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;
@@ -1792,6 +1918,10 @@ static int check_x509(const rcynic_ctx_t *rc,
} else {
+ assert(subject->crldp[0]);
+
+ flags |= X509_V_FLAG_CRL_CHECK;
+
if ((pkey = X509_get_pubkey(issuer)) == NULL || X509_verify(x, pkey) <= 0) {
reject(rc, subject->uri, certificate_bad_signature,
"because it failed signature check prior to CRL fetch");
@@ -1803,25 +1933,22 @@ static int check_x509(const rcynic_ctx_t *rc,
"due to bad CRL %s", subject->crldp);
goto done;
}
- }
- if ((crls = sk_X509_CRL_new_null()) == NULL ||
- !sk_X509_CRL_push(crls, crl)) {
- logmsg(rc, log_sys_err,
- "Internal allocation error setting up CRL for validation");
- goto done;
+ if ((crls = sk_X509_CRL_new_null()) == NULL || !sk_X509_CRL_push(crls, crl)) {
+ logmsg(rc, log_sys_err,
+ "Internal allocation error setting up CRL for validation");
+ goto done;
+ }
+ crl = NULL;
+
+ X509_STORE_CTX_set0_crls(&rctx.ctx, crls);
+
}
- crl = NULL;
X509_STORE_CTX_trusted_stack(&rctx.ctx, certs);
- X509_STORE_CTX_set0_crls(&rctx.ctx, crls);
X509_STORE_CTX_set_verify_cb(&rctx.ctx, check_x509_cb);
- X509_VERIFY_PARAM_set_flags(rctx.ctx.param,
- X509_V_FLAG_CRL_CHECK |
- X509_V_FLAG_POLICY_CHECK |
- X509_V_FLAG_EXPLICIT_POLICY |
- X509_V_FLAG_X509_STRICT);
+ X509_VERIFY_PARAM_set_flags(rctx.ctx.param, flags);
X509_VERIFY_PARAM_add0_policy(rctx.ctx.param, OBJ_txt2obj(rpki_policy_oid, 1));
@@ -3259,6 +3386,7 @@ int main(int argc, char *argv[])
logmsg(&rc, log_sys_err, "Couldn't find a free name for trust anchor %s", path1);
goto done;
}
+ uri[0] = '\0';
}
if (!name_cmp(val->name, "trust-anchor-uri-with-key") ||
@@ -3341,15 +3469,12 @@ int main(int argc, char *argv[])
goto done;
}
- parse_cert(&rc, x, &ta_info, "");
+ parse_cert(&rc, x, &ta_info, uri);
ta_info.ta = 1;
sk_X509_push(certs, x);
- if (ta_info.crldp[0] && !check_x509(&rc, certs, x, &ta_info)) {
- logmsg(&rc, log_data_err, "Couldn't get CRL for trust anchor %s", path1);
- } else {
+ if (check_x509(&rc, certs, x, &ta_info))
walk_cert(&rc, &ta_info, certs);
- }
X509_free(sk_X509_pop(certs));
assert(sk_X509_num(certs) == 0);