aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rcynic/rcynic.c106
1 files changed, 76 insertions, 30 deletions
diff --git a/rcynic/rcynic.c b/rcynic/rcynic.c
index 2903315c..4b803c2e 100644
--- a/rcynic/rcynic.c
+++ b/rcynic/rcynic.c
@@ -261,6 +261,59 @@ static int rsync(char *args, ...)
/*
+ * Extract URIs from certificate extensions.
+ */
+
+static char *extract_crldp_uri(STACK_OF(DIST_POINT) *crldp)
+{
+ DIST_POINT *d;
+ int i;
+
+ if (!crldp || sk_DIST_POINT_num(crldp) != 1)
+ return NULL;
+
+ d = sk_DIST_POINT_value(crldp, 0);
+
+ if (d->reasons || d->CRLissuer || !d->distpoint || d->distpoint->type != 0)
+ return NULL;
+
+ for (i = 0; i < sk_GENERAL_NAME_num(d->distpoint->name.fullname); i++) {
+ GENERAL_NAME *n = sk_GENERAL_NAME_value(d->distpoint->name.fullname, i);
+ assert(n != NULL);
+ if (n->type != GEN_URI)
+ return NULL;
+ if (!strncmp(n->d.uniformResourceIdentifier->data,
+ "rsync://", sizeof("rsync://") - 1))
+ return strdup(n->d.uniformResourceIdentifier->data);
+ }
+
+ return NULL;
+}
+
+static char *extract_access_uri(AUTHORITY_INFO_ACCESS *xia,
+ unsigned char *oid, int oidlen)
+{
+ int i;
+
+ if (!xia)
+ return NULL;
+
+ for (i = 0; i < sk_ACCESS_DESCRIPTION_num(xia); i++) {
+ ACCESS_DESCRIPTION *a = sk_ACCESS_DESCRIPTION_value(xia, i);
+ assert(a != NULL);
+ if (a->location->type != GEN_URI)
+ return NULL;
+ if (a->method->length == oidlen &&
+ !memcmp(a->method->data, oid, oidlen) &&
+ !strncmp(a->location->d.uniformResourceIdentifier->data,
+ "rsync://", sizeof("rsync://") - 1))
+ return strdump(a->location->d.uniformResourceIdentifier->data);
+ }
+}
+
+
+
+/*
* Read certificate in DER format.
*/
@@ -284,47 +337,40 @@ static void rpki_cert_free(rpki_cert_t *c)
}
-#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)
{
+ static unsigned char aia_oid[] = {0x2b, 0x6, 0x1, 0x5, 0x5, 0x7, 0x30, 0x2};
+ static unsigned char sia_oid[] = {0x2b, 0x6, 0x1, 0x5, 0x5, 0x7, 0x30, 0x5};
+ STACK_OF(DIST_POINT) *crldp;
+ AUTHORITY_INFO_ACCESS *xia;
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;
+ if ((c->x = read-cert(filename)) == NULL) {
+ rpki_cert_free(c);
+ return NULL;
+ }
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;
-}
+ if ((xia = X509_get_ext_d2i(c->x, NID_info_access, NULL, NULL)) != NULL) {
+ c->aia = extract_access_uri(xia, aia_oid, sizeof(aia_oid));
+ sk_ACCESS_DESCRIPTION_pop_free(xia, ACCESS_DESCRIPTION_free);
+ }
-
+ if ((xia = X509_get_ext_d2i(c->x, NID_sinfo_access, NULL, NULL)) != NULL) {
+ c->sia = extract_access_uri(xia, sia_oid, sizeof(sia_oid));
+ sk_ACCESS_DESCRIPTION_pop_free(xia, ACCESS_DESCRIPTION_free);
+ }
-/*
- * Dunno yet whether Perl parse_cert() has a C equivalent.
- */
+ if ((crldp = X509_get_ext_d2i(c->x, NID_crl_distribution_points,
+ NULL, NULL)) != NULL) {
+ c->crldp = extract_crldp_uri(crldp);
+ sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
+ }
+ return c;
+}