diff options
author | Rob Austein <sra@hactrn.net> | 2014-04-05 22:42:12 +0000 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2014-04-05 22:42:12 +0000 |
commit | fe0bf509f528dbdc50c7182f81057c6a4e15e4bd (patch) | |
tree | 07c9a923d4a0ccdfea11c49cd284f6d5757c5eda /rp/utils/uri.c | |
parent | aa28ef54c271fbe4d52860ff8cf13cab19e2207c (diff) |
Source tree reorg, phase 1. Almost everything moved, no file contents changed.
svn path=/branches/tk685/; revision=5757
Diffstat (limited to 'rp/utils/uri.c')
-rw-r--r-- | rp/utils/uri.c | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/rp/utils/uri.c b/rp/utils/uri.c new file mode 100644 index 00000000..6353e8e5 --- /dev/null +++ b/rp/utils/uri.c @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2014 Dragon Research Labs ("DRL") + * Portions copyright (C) 2006--2008 American Registry for Internet Numbers ("ARIN") + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notices and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DRL AND ARIN DISCLAIM ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DRL OR + * ARIN BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA + * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $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 <getopt.h> + +#include <openssl/bio.h> +#include <openssl/pem.h> +#include <openssl/err.h> +#include <openssl/cms.h> +#include <openssl/x509.h> +#include <openssl/x509v3.h> +#include <openssl/safestack.h> + +static const unsigned char id_ad_caIssuers[] = {0x2b, 0x6, 0x1, 0x5, 0x5, 0x7, 0x30, 0x2}; /* 1.3.6.1.5.5.7.48.2 */ +static const unsigned char id_ad_caRepository[] = {0x2b, 0x6, 0x1, 0x5, 0x5, 0x7, 0x30, 0x5}; /* 1.3.6.1.5.5.7.48.5 */ +static const unsigned char id_ad_signedObjectRepository[] = {0x2b, 0x6, 0x1, 0x5, 0x5, 0x7, 0x30, 0x9}; /* 1.3.6.1.5.5.7.48.9 */ +static const unsigned char id_ad_rpkiManifest[] = {0x2b, 0x6, 0x1, 0x5, 0x5, 0x7, 0x30, 0xa}; /* 1.3.6.1.5.5.7.48.10 */ +static const unsigned char id_ad_signedObject[] = {0x2b, 0x6, 0x1, 0x5, 0x5, 0x7, 0x30, 0xb}; /* 1.3.6.1.5.5.7.48.11 */ + +static X509 *read_cert(const char *filename, int format, int verbose) +{ + BIO *b = BIO_new_file(filename, "r"); + STACK_OF(X509) *certs = NULL; + CMS_ContentInfo *cms = NULL; + X509 *x = NULL; + + if (b == NULL) + return NULL; + + switch (format) { + case 'p': + x = PEM_read_bio_X509(b, NULL, NULL, NULL); + break; + case 'd': + x = d2i_X509_bio(b, NULL); + break; + } + + if (x == NULL) { + BIO_reset(b); + switch (format) { + case 'p': + cms = PEM_read_bio_CMS(b, NULL, NULL, NULL); + break; + case 'd': + cms = d2i_CMS_bio(b, NULL); + break; + } + if (cms != NULL && (certs = CMS_get1_certs(cms)) != NULL) + x = sk_X509_shift(certs); + } + + if (x != NULL && verbose) { + X509_print_fp(stdout, x); + printf("\n"); + } + + sk_X509_pop_free(certs, X509_free); + CMS_ContentInfo_free(cms); + BIO_free(b); + return x; +} + +enum decode_errors { + decode_ok, + decode_no_extension, + decode_not_exactly_one_DistributionPointName, + decode_has_reasons, + decode_has_CRLissuer, + decode_no_distributionPoint, + decode_not_GeneralName, + decode_not_URI, +}; + +static enum decode_errors decode_crldp(X509 *x, int verbose, int spaces) +{ + enum decode_errors err = decode_ok; + STACK_OF(DIST_POINT) *ds = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL); + DIST_POINT *d; + GENERAL_NAME *n; + int i; + + if (!ds) { + err = decode_no_extension; + } else if (sk_DIST_POINT_num(ds) != 1) { + err = decode_not_exactly_one_DistributionPointName; + } else if ((d = sk_DIST_POINT_value(ds, 0))->reasons) { + err = decode_has_reasons; + } else if (d->CRLissuer) { + err = decode_has_CRLissuer; + } else if (!d->distpoint) { + err = decode_no_distributionPoint; + } else if (d->distpoint->type != 0) { + err = decode_not_GeneralName; + } else { + 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) { + err = decode_not_GeneralName; + break; + } + printf(" CRLDP: %s%s", n->d.uniformResourceIdentifier->data, spaces ? "" : "\n"); + } + } + + sk_DIST_POINT_pop_free(ds, DIST_POINT_free); + return err; +} + +#define decode_xia(_x_, _v_, _s_, _tag_, _nid_, _oid_) \ + _decode_xia(_x_, _v_, _s_, _tag_, _nid_, _oid_, sizeof(_oid_)) + +static enum decode_errors _decode_xia(X509 *x, + int verbose, + int spaces, + char *tag, + int nid, + const unsigned char *oid, + int oidlen) +{ + enum decode_errors err = decode_ok; + AUTHORITY_INFO_ACCESS *as = X509_get_ext_d2i(x, nid, NULL, NULL); + ACCESS_DESCRIPTION *a; + int i; + + if (!as) { + err = decode_no_extension; + } else { + for (i = 0; i < sk_ACCESS_DESCRIPTION_num(as); i++) { + a = sk_ACCESS_DESCRIPTION_value(as, i); + if (a->location->type != GEN_URI) { + err = decode_not_URI; + break; + } + if (a->method->length == oidlen && !memcmp(a->method->data, oid, oidlen)) + printf(" %s: %s%s", tag, a->location->d.uniformResourceIdentifier->data, spaces ? "" : "\n"); + } + } + + sk_ACCESS_DESCRIPTION_pop_free(as, ACCESS_DESCRIPTION_free); + return err; +} + + + +const static struct option longopts[] = { + { "der", no_argument, NULL, 'd' }, + { "help", no_argument, NULL, 'h' }, + { "pem", no_argument, NULL, 'p' }, + { "spaces", no_argument, NULL, 's' }, + { "verbose", no_argument, NULL, 'v' }, + { NULL } +}; + +static int usage (const char *jane, const int code) +{ + FILE *out = code ? stderr : stdout; + int i; + + fprintf(out, "usage: %s [-p | -d] cert [cert...]\n", jane); + fprintf(out, "options:\n"); + for (i = 0; longopts[i].name != NULL; i++) + fprintf(out, " -%c --%s\n", longopts[i].val, longopts[i].name); + + return code; +} + +int main(int argc, char *argv[]) +{ + int c, format = 'd', spaces = 0, verbose = 0; + const char *jane = argv[0]; + X509 *x; + + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + + while ((c = getopt(argc, argv, "pdsv")) > 0) { + switch (c) { + case 'v': + verbose = 1; + break; + case 'p': + case 'd': + format = c; + break; + case 's': + spaces = 1; + break; + case 'h': + return usage(jane, 0); + default: + return usage(jane, 1); + } + } + + argc -= optind; + argv += optind; + + if (argc == 0) + return usage(jane, 1); + + while (argc-- > 0) { + printf(spaces ? "%s" : "File: %s\n", *argv); + if ((x = read_cert(*argv++, format, verbose)) == NULL) { + printf("Couldn't read certificate, skipping\n"); + continue; + } + decode_xia(x, verbose, spaces, "AIA:caIssuers", NID_info_access, id_ad_caIssuers); + decode_xia(x, verbose, spaces, "SIA:caRepository", NID_sinfo_access, id_ad_caRepository); + decode_xia(x, verbose, spaces, "SIA:signedObjectRepository", NID_sinfo_access, id_ad_signedObjectRepository); + decode_xia(x, verbose, spaces, "SIA:rpkiManifest", NID_sinfo_access, id_ad_rpkiManifest); + decode_xia(x, verbose, spaces, "SIA:signedObject", NID_sinfo_access, id_ad_signedObject); + decode_crldp(x, verbose, spaces); + if (spaces) + putchar('\n'); + X509_free(x); + } + + return 0; +} |