diff options
author | Rob Austein <sra@hactrn.net> | 2011-05-27 21:35:38 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2011-05-27 21:35:38 +0000 |
commit | c38b52ee9e51a674b9dfaf2dbf69d31dcc762e95 (patch) | |
tree | fa28150ab9ecff89e0736fe2fc341dd2a06c6430 | |
parent | 0de4b46d40d0da9ba1996502382f11d8130214ac (diff) |
Finally finished moving the entire recursive tree walk off of the call
stack and onto a data stack.
svn path=/rcynic-ng/rcynic.c; revision=3843
-rw-r--r-- | rcynic-ng/rcynic.c | 191 |
1 files changed, 111 insertions, 80 deletions
diff --git a/rcynic-ng/rcynic.c b/rcynic-ng/rcynic.c index 1d11c579..2d63d45c 100644 --- a/rcynic-ng/rcynic.c +++ b/rcynic-ng/rcynic.c @@ -381,10 +381,13 @@ typedef struct rcynic_ctx { * code is still in flux, names (and anything else) may change. */ typedef enum { - walk_pass_current, /* prefix = rc->unauthenticated, first pass */ - walk_pass_backup, /* prefix = rc->old_authenticated, second pass */ - walk_pass_max -} walk_pass_t; + walk_state_initial, /* Initial state */ + walk_state_rsync, /* rsyncing certinfo.sia */ + walk_state_ready, /* Ready to traverse outputs */ + walk_state_current, /* prefix = rc->unauthenticated */ + walk_state_backup, /* prefix = rc->old_authenticated */ + walk_state_done /* Done walking this cert's outputs */ +} walk_state_t; typedef struct walk_ctx { unsigned refcount; @@ -393,7 +396,7 @@ typedef struct walk_ctx { Manifest *manifest; STACK_OF(OPENSSL_STRING) *filenames; int manifest_iteration, filename_iteration; - walk_pass_t pass; + walk_state_t state; } walk_ctx_t; DECLARE_STACK_OF(walk_ctx_t) @@ -1104,7 +1107,7 @@ static int rm_rf(const path_t *name) * see what's missing from a manifest. */ static STACK_OF(OPENSSL_STRING) *directory_filenames(const rcynic_ctx_t *rc, - const walk_pass_t pass, + const walk_state_t state, const uri_t *uri) { STACK_OF(OPENSSL_STRING) *result = NULL; @@ -1116,11 +1119,11 @@ static STACK_OF(OPENSSL_STRING) *directory_filenames(const rcynic_ctx_t *rc, assert(rc && uri); - switch (pass) { - case walk_pass_current: + switch (state) { + case walk_state_current: prefix = &rc->unauthenticated; break; - case walk_pass_backup: + case walk_state_backup: prefix = &rc->old_authenticated; break; default: @@ -1232,12 +1235,12 @@ static void walk_ctx_loop_next(const rcynic_ctx_t *rc, STACK_OF(walk_ctx_t) *wsk return; } - if (w->pass < walk_pass_max) { - w->pass++; + if (w->state < walk_state_done) { + w->state++; w->manifest_iteration = 0; w->filename_iteration = 0; sk_OPENSSL_STRING_pop_free(w->filenames, OPENSSL_STRING_free); - w->filenames = directory_filenames(rc, w->pass, &w->certinfo.sia); + w->filenames = directory_filenames(rc, w->state, &w->certinfo.sia); } } @@ -1249,7 +1252,7 @@ static void walk_ctx_loop_next(const rcynic_ctx_t *rc, STACK_OF(walk_ctx_t) *wsk static int walk_ctx_loop_done(STACK_OF(walk_ctx_t) *wsk) { walk_ctx_t *w = walk_ctx_stack_head(wsk); - return wsk == NULL || w == NULL || w->pass >= walk_pass_max; + return wsk == NULL || w == NULL || w->state >= walk_state_done; } static Manifest *check_manifest(const rcynic_ctx_t *rc, @@ -1263,17 +1266,20 @@ static void walk_ctx_loop_init(const rcynic_ctx_t *rc, STACK_OF(walk_ctx_t) *wsk { walk_ctx_t *w = walk_ctx_stack_head(wsk); - assert(rc != NULL && wsk != NULL && w != NULL && - w->pass == walk_pass_current && - w->manifest_iteration == 0 && - w->filename_iteration == 0 && - w->filenames == NULL && - w->manifest == NULL); + assert(rc && wsk && w && w->state == walk_state_ready); + assert(w->manifest == NULL); if ((w->manifest = check_manifest(rc, wsk)) == NULL) logmsg(rc, log_data_err, "Couldn't get manifest %s, blundering onward", w->certinfo.manifest.s); - w->filenames = directory_filenames(rc, w->pass, &w->certinfo.sia); + assert(w->filenames == NULL); + w->filenames = directory_filenames(rc, w->state, &w->certinfo.sia); + + w->manifest_iteration = 0; + w->filename_iteration = 0; + w->state++; + + assert(w->state == walk_state_current); while (!walk_ctx_loop_done(wsk) && (w->manifest == NULL || w->manifest_iteration >= sk_FileAndHash_num(w->manifest->fileList)) && @@ -1304,8 +1310,8 @@ static int walk_ctx_loop_this(const rcynic_ctx_t *rc, } if (name == NULL) { - logmsg(rc, log_sys_err, "Can't find a URI in walk context, this shouldn't happen: pass %d, manifest_iteration %d, filename_iteration %d", - (int) w->pass, w->manifest_iteration, w->filename_iteration); + logmsg(rc, log_sys_err, "Can't find a URI in walk context, this shouldn't happen: state %d, manifest_iteration %d, filename_iteration %d", + (int) w->state, w->manifest_iteration, w->filename_iteration); return 0; } @@ -2429,13 +2435,13 @@ static X509 *check_cert(rcynic_ctx_t *rc, issuer = &w->certinfo; - switch (w->pass) { - case walk_pass_current: + switch (w->state) { + case walk_state_current: prefix = &rc->unauthenticated; accept_code = current_cert_accepted; reject_code = current_cert_rejected; break; - case walk_pass_backup: + case walk_state_backup: prefix = &rc->old_authenticated; accept_code = backup_cert_accepted; reject_code = backup_cert_rejected; @@ -2451,7 +2457,7 @@ static X509 *check_cert(rcynic_ctx_t *rc, if (uri_to_filename(rc, uri, &path, &rc->authenticated) && !access(path.s, R_OK)) { - if (w->pass == walk_pass_backup || sk_OPENSSL_STRING_find(rc->backup_cache, uri->s) < 0) + if (w->state == walk_state_backup || sk_OPENSSL_STRING_find(rc->backup_cache, uri->s) < 0) return NULL; mib_increment(rc, uri, current_cert_recheck); logmsg(rc, log_telemetry, "Rechecking %s", uri->s); @@ -2467,7 +2473,7 @@ static X509 *check_cert(rcynic_ctx_t *rc, if ((x = check_cert_1(rc, uri, &path, prefix, certs, issuer, subject, hash, hashlen)) != NULL) { install_object(rc, uri, &path); mib_increment(rc, uri, accept_code); - if (w->pass == walk_pass_current) + 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); @@ -3249,83 +3255,108 @@ static void check_ghostbuster(const rcynic_ctx_t *rc, */ static void walk_cert(rcynic_ctx_t *rc, STACK_OF(walk_ctx_t) *wsk) { - walk_ctx_t *w = walk_ctx_stack_head(wsk); const unsigned char *hash = NULL; size_t hashlen; - int n_wsk; + walk_ctx_t *w; uri_t uri; - assert(rc && wsk && w); - - if (!w->certinfo.sia.s[0] || !w->certinfo.ca) - return; + assert(rc && wsk); - if (!w->certinfo.manifest.s[0]) { - logmsg(rc, log_data_err, "Issuer's certificate does not specify a manifest, skipping collection"); - return; - } + while ((w = walk_ctx_stack_head(wsk)) != NULL) { - /* - * Both the log indentation hack and the assertions to track call - * stack against data stack are probably doomed, but leave here - * until they stop being useful. - */ + switch (w->state) { - rc->indent++; - n_wsk = sk_walk_ctx_t_num(wsk); + case walk_state_initial: - /* - * rsync() doesn't take callbacks yet, but this is where the - * callback would go. - */ - rsync_tree(rc, &w->certinfo.sia); + if (!w->certinfo.sia.s[0] || !w->certinfo.ca) { + w->state = walk_state_done; + continue; + } + + if (!w->certinfo.manifest.s[0]) { + logmsg(rc, log_data_err, "Issuer's certificate does not specify a manifest, skipping collection"); + w->state = walk_state_done; + continue; + } - for (walk_ctx_loop_init(rc, wsk); !walk_ctx_loop_done(wsk); walk_ctx_loop_next(rc, wsk)) { + rc->indent++; - if (!walk_ctx_loop_this(rc, wsk, &uri, &hash, &hashlen)) + w->state++; continue; - - if (endswith(uri.s, ".crl") || endswith(uri.s, ".mft") || endswith(uri.s, ".mnf")) - continue; /* CRLs and manifests checked elsewhere */ - if (hash == NULL) { - logmsg(rc, log_telemetry, "Object %s present in publication directory but not in manifest", uri.s); - mib_increment(rc, &uri, object_not_in_manifest); - } + case walk_state_rsync: - if (hash == NULL && !rc->allow_object_not_in_manifest) + rsync_tree(rc, &w->certinfo.sia); + w->state++; continue; + + case walk_state_ready: - if (endswith(uri.s, ".roa")) { - check_roa(rc, &uri, wsk, hash, hashlen); + walk_ctx_loop_init(rc, wsk); /* sets w->state */ continue; - } - if (endswith(uri.s, ".gbr")) { - check_ghostbuster(rc, &uri, wsk, hash, hashlen); - continue; - } + case walk_state_current: + case walk_state_backup: + + if (!walk_ctx_loop_this(rc, wsk, &uri, &hash, &hashlen)) { + walk_ctx_loop_next(rc, wsk); + continue; + } + + if (endswith(uri.s, ".crl") || endswith(uri.s, ".mft") || endswith(uri.s, ".mnf")) { + walk_ctx_loop_next(rc, wsk); + continue; /* CRLs and manifests checked elsewhere */ + } + + if (hash == NULL) { + logmsg(rc, log_telemetry, "Object %s present in publication directory but not in manifest", uri.s); + mib_increment(rc, &uri, object_not_in_manifest); + } + + if (hash == NULL && !rc->allow_object_not_in_manifest) { + walk_ctx_loop_next(rc, wsk); + continue; + } + + if (endswith(uri.s, ".roa")) { + check_roa(rc, &uri, wsk, hash, hashlen); + walk_ctx_loop_next(rc, wsk); + continue; + } - if (endswith(uri.s, ".cer")) { - certinfo_t subject; - X509 *x; + if (endswith(uri.s, ".gbr")) { + check_ghostbuster(rc, &uri, wsk, hash, hashlen); + walk_ctx_loop_next(rc, wsk); + continue; + } - if ((x = check_cert(rc, &uri, wsk, &subject, hash, hashlen)) != NULL && - (w = walk_ctx_stack_push(wsk)) != NULL) { - w->cert = x; - w->certinfo = subject; - walk_cert(rc, wsk); - walk_ctx_stack_pop(wsk); + if (endswith(uri.s, ".cer")) { + certinfo_t subject; + X509 *x; + + if ((x = check_cert(rc, &uri, wsk, &subject, hash, hashlen)) != NULL && + (w = walk_ctx_stack_push(wsk)) != NULL) { + w->cert = x; + w->certinfo = subject; + continue; /* Walk in new child's state */ + } else { + walk_ctx_loop_next(rc, wsk); + continue; + } } + logmsg(rc, log_telemetry, "Don't know how to check object %s, ignoring", uri.s); + walk_ctx_loop_next(rc, wsk); continue; - } - logmsg(rc, log_telemetry, "Don't know how to check object %s, ignoring", uri.s); - } + case walk_state_done: - assert(sk_walk_ctx_t_num(wsk) == n_wsk); - rc->indent--; + rc->indent--; + walk_ctx_stack_pop(wsk); /* Resume our issuer's state */ + continue; + + } + } } |