diff options
author | Rob Austein <sra@hactrn.net> | 2006-09-21 18:53:37 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2006-09-21 18:53:37 +0000 |
commit | 54946b21c19d876e4c672f515cb35950500e1051 (patch) | |
tree | 773d6347bbfc51c2ead6059958d0e20858833ce8 | |
parent | c8ff38610f46051d1f4013ac6607d4e94af3c203 (diff) |
Checkpoint
svn path=/rcynic/rcynic.c; revision=302
-rw-r--r-- | rcynic/rcynic.c | 70 | ||||
-rw-r--r-- | tests/uri/Makefile | 19 | ||||
-rw-r--r-- | tests/uri/uri.c | 142 |
3 files changed, 228 insertions, 3 deletions
diff --git a/rcynic/rcynic.c b/rcynic/rcynic.c index a3d3eeef..2903315c 100644 --- a/rcynic/rcynic.c +++ b/rcynic/rcynic.c @@ -48,6 +48,7 @@ typedef struct rpki_cert { int ca, ta; char *uri, *file, *sia, *aia, *crldp; + X509 *x; } rpki_cert_t; static char *jane; @@ -115,10 +116,9 @@ static int mkdir_maybe(char *name) { char *b, buffer[FILENAME_MAX]; - if (!name || strlen(name) >= sizeof(buffer) - 2) + assert(name != NULL); + if (snprintf(buffer, sizeof(buffer), "%s/.", name) >= sizeof(buffer)) return 0; - strcpy(buffer, name); - strcat(buffer, "/."); if (access(buffer, F_OK) == 0) return 1; if ((b = strrchr(strrchr(buffer, '/'), '/')) != 0) { @@ -261,6 +261,70 @@ static int rsync(char *args, ...) /* + * Read certificate in DER format. + */ + +static X509 *read_cert(const char *filename) +{ + X509 *x = NULL; + BIO *b; + + if ((b = BIO_new_file(filename, "r")) != NULL) + x = d2i_X509_bio(b, NULL); + + BIO_free(b); + return x; +} + +static void rpki_cert_free(rpki_cert_t *c) +{ + if (!c) + return; + X509_free(c->x); + +} + +#error continue here + +/* + * This should turn into rpki_cert_read(), with an accompanying + * rpki_cert_free(), and should return a filled-in rpki_cert_t. + */ + +/* + * Conclusion when Randy and I discussed it was that we should just + * read certs from the disk every time we need them, at least until + * we've proven that failing to cache them in memory is a performance + * problem. + */ + +static rpki_cert_t *rpki_cert_read(const char *filename) +{ + rpki_cert_t *c; + + if ((c = malloc(sizeof(*c))) == NULL) + return NULL; + memset(c, 0, sizeof(*c)); + + if ((c->x = read-cert(filename)) == NULL) + goto err; + + c->ca = X509_check_ca(c->x) == 1; + + NID_sinfo_access; /* sia */ + NID_info_access; /* aia */ + NID_crl_distribution_points; /* crldp */ + + return c; + + err: + rpki_cert_free(c); + return NULL; +} + + + +/* * Dunno yet whether Perl parse_cert() has a C equivalent. */ diff --git a/tests/uri/Makefile b/tests/uri/Makefile new file mode 100644 index 00000000..3bb08771 --- /dev/null +++ b/tests/uri/Makefile @@ -0,0 +1,19 @@ +# $Id$ + +OPENSSL_DIR = ../../openssl/trunk + +CFLAGS = -g -I${OPENSSL_DIR}/include + +# -H -Wl,-t + +BIN = uri +OBJ = uri.o +LIB = ${OPENSSL_DIR}/libcrypto.a + +all: ${BIN} + +clean: + rm -f ${BIN} ${OBJ} + +${BIN}: ${OBJ} ${LIB} Makefile + ${CC} -g -o $@ ${OBJ} ${LIB} diff --git a/tests/uri/uri.c b/tests/uri/uri.c new file mode 100644 index 00000000..dc86bb6c --- /dev/null +++ b/tests/uri/uri.c @@ -0,0 +1,142 @@ +/* $Id$ */ + +/* + * Extract and test URIs from certificates. This is a unit test of + * rcynic code, a utility, or both, depending on how it turns out. + * + * NB: OpenSSL insures that IA5 strings are null-terminated, so it's safe + * for us to ignore the length count. + */ + +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <openssl/bio.h> +#include <openssl/pem.h> +#include <openssl/err.h> +#include <openssl/x509.h> +#include <openssl/x509v3.h> +#include <openssl/safestack.h> + +static X509 *read_cert(const char *filename, int format, int verbose) +{ + X509 *x = NULL; + BIO *b; + + if ((b = BIO_new_file(filename, "r")) == NULL) + goto done; + + switch (format) { + case 'p': + x = PEM_read_bio_X509_AUX(b, NULL, NULL, NULL); + break; + case 'd': + x = d2i_X509_bio(b, NULL); + break; + } + + if (verbose && x != NULL) { + X509_print_fp(stdout, x); + printf("\n"); + } + + + done: + BIO_free(b); + return x; +} + +#define lose(msg) do { printf("Lost: %s\n", msg); goto done; } while (0) + +static void decode_crldp(X509 *x, int verbose) +{ + STACK_OF(DIST_POINT) *ds = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL); + DIST_POINT *d; + GENERAL_NAME *n; + char *s; + int i; + + if (!ds) + lose("No CRLDP sequence"); + + if (sk_DIST_POINT_num(ds) != 1) + lose("CRLDP sequence does not have exactly one member"); + + d = sk_DIST_POINT_value(ds, 0); + + if (d->reasons) + lose("CRLDP has reasons"); + + if (d->CRLissuer) + lose("CRLDP has CRLissuer"); + + if (!d->distpoint) + lose("CRLDP has no distributionPoint"); + + if (d->distpoint->type != 0) + lose("CRLDP does not contain general names"); + + for (i = 0; i < sk_GENERAL_NAME_num(d->distpoint->name.fullname); i++) { + n = sk_GENERAL_NAME_value(d->distpoint->name.fullname, i); + if (n->type != GEN_URI) { + printf("CRDLP name %d is type %d, not URI, skipping\n", i, n->type); + continue; + } + s = n->d.uniformResourceIdentifier->data; + if (strncmp(s, "rsync://", sizeof("rsync://") - 1)) { + printf("CRLDP name %d is not an rsync URI, skipping\n", i); + continue; + } + printf("CRLDP name %d: \"%s\"\n", i, s); + } + + done: + sk_DIST_POINT_pop_free(ds, DIST_POINT_free); +} + +int main(int argc, char *argv[]) +{ + int c, format = 'p', ret = 0, verbose = 0; + X509 *x; + + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + + while ((c = getopt(argc, argv, "pdv")) > 0) { + switch (c) { + case 'v': + verbose = 1; + break; + case 'p': + case 'd': + format = c; + break; + default: + fprintf(stderr, "usage: %s [-p | -d] cert [cert...]\n", argv[0]); + ret = 1; + goto done; + } + } + + argc -= optind; + argv += optind; + + while (argc-- > 0) { + printf("File %s\n", *argv); + if ((x = read_cert(*argv++, format, verbose)) == NULL) { + printf("Couldn't read certificate, skipping\n"); + continue; + } +#if 0 + decode_aia(x, verbose); + decode_sia(x, verbose); +#endif + decode_crldp(x, verbose); + X509_free(x); + } + + done: + EVP_cleanup(); + ERR_free_strings(); + return ret; +} |