aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2006-09-21 18:53:37 +0000
committerRob Austein <sra@hactrn.net>2006-09-21 18:53:37 +0000
commit54946b21c19d876e4c672f515cb35950500e1051 (patch)
tree773d6347bbfc51c2ead6059958d0e20858833ce8
parentc8ff38610f46051d1f4013ac6607d4e94af3c203 (diff)
Checkpoint
svn path=/rcynic/rcynic.c; revision=302
-rw-r--r--rcynic/rcynic.c70
-rw-r--r--tests/uri/Makefile19
-rw-r--r--tests/uri/uri.c142
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;
+}