aboutsummaryrefslogtreecommitdiff
path: root/rp/utils/uri.c
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2014-04-05 22:42:12 +0000
committerRob Austein <sra@hactrn.net>2014-04-05 22:42:12 +0000
commitfe0bf509f528dbdc50c7182f81057c6a4e15e4bd (patch)
tree07c9a923d4a0ccdfea11c49cd284f6d5757c5eda /rp/utils/uri.c
parentaa28ef54c271fbe4d52860ff8cf13cab19e2207c (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.c248
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;
+}