This should be the last step. It inlines sbgp_sia_resource_entry() into
sbgp_sia() and dedups the sbgp_sia_resource_{notify,mft,carepo}() using
a new sbgp_sia_location(). Move the GEN_URI check to sbgp_sia_location()
since that seems cleaner.
Index: cert.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
retrieving revision 1.65
diff -u -p -r1.65 cert.c
--- cert.c 11 Apr 2022 08:28:54 -0000 1.65
+++ cert.c 11 Apr 2022 09:27:53 -0000
@@ -125,132 +125,40 @@ sbgp_addr(struct parse *p,
}
/*
- * Parse the SIA notify URL, 4.8.8.1.
- * Returns zero on failure, non-zero on success.
+ * Extract and validate a SIA accessLocation, RFC 6487, 4.8.8 and RFC 8192,
3.2.
+ * Returns 0 on failure and 1 on success.
*/
static int
-sbgp_sia_resource_notify(struct parse *p, const char *d, size_t dsz)
+sbgp_sia_location(const char *fn, const char *descr, const char *proto,
+ GENERAL_NAME *location, char **out)
{
- if (p->res->notify != NULL) {
- warnx("%s: RFC 6487 section 4.8.8: SIA: "
- "Notify location already specified", p->fn);
- return 0;
- }
-
- /* Make sure it's a https:// address. */
- if (!valid_uri(d, dsz, "https://")) {
- warnx("%s: RFC 8182 section 3.2: bad Notify URI", p->fn);
- return 0;
- }
+ ASN1_IA5STRING *uri;
- if ((p->res->notify = strndup(d, dsz)) == NULL)
- err(1, NULL);
-
- return 1;
-}
-
-/*
- * Parse the SIA manifest, 4.8.8.1.
- * Returns zero on failure, non-zero on success.
- */
-static int
-sbgp_sia_resource_mft(struct parse *p, const char *d, size_t dsz)
-{
- if (p->res->mft != NULL) {
- warnx("%s: RFC 6487 section 4.8.8: SIA: "
- "MFT location already specified", p->fn);
+ if (*out != NULL) {
+ warnx("%s: RFC 6487 section 4.8.8: SIA: %s already specified",
+ fn, descr);
return 0;
}
- /* Make sure it's an rsync address. */
- if (!valid_uri(d, dsz, "rsync://")) {
- warnx("%s: RFC 6487 section 4.8.8: bad MFT location", p->fn);
+ if (location->type != GEN_URI) {
+ warnx("%s: RFC 6487 section 4.8.8: SIA: %s not URI", fn, descr);
return 0;
}
- if ((p->res->mft = strndup(d, dsz)) == NULL)
- err(1, NULL);
+ uri = location->d.uniformResourceIdentifier;
- return 1;
-}
-
-/*
- * Parse the SIA manifest, 4.8.8.1.
- * Returns zero on failure, non-zero on success.
- */
-static int
-sbgp_sia_resource_carepo(struct parse *p, const char *d, size_t dsz)
-{
- if (p->res->repo != NULL) {
- warnx("%s: RFC 6487 section 4.8.8: SIA: "
- "CA repository already specified", p->fn);
+ if (!valid_uri(uri->data, uri->length, proto)) {
+ warnx("%s: RFC 6487 section 4.8.8: bad %s location", fn, descr);
return 0;
}
- /* Make sure it's an rsync:// address. */
- if (!valid_uri(d, dsz, "rsync://")) {
- warnx("%s: RFC 6487 section 4.8.8: bad CA repository URI",
- p->fn);
- return 0;
- }
-
- if ((p->res->repo = strndup(d, dsz)) == NULL)
+ if ((*out = strndup(uri->data, uri->length)) == NULL)
err(1, NULL);
return 1;
}
/*
- * Parse the SIA entries, 4.8.8.1.
- * There may be multiple different resources at this location, so throw
- * out all but the matching resource type. Currently only two entries
- * are of interest: rpkiManifest and rpkiNotify.
- * Returns zero on failure, non-zero on success.
- */
-static int
-sbgp_sia_resource_entry(struct parse *p, ACCESS_DESCRIPTION *ad)
-{
- ASN1_OBJECT *oid;
- ASN1_IA5STRING *uri = NULL;
- int rc = 0;
-
- if (ad->location->type == GEN_URI)
- uri = ad->location->d.uniformResourceIdentifier;
-
- oid = ad->method;
-
- if (OBJ_cmp(oid, carepo_oid) == 0) {
- if (uri == NULL) {
- warnx("%s: RFC 6487: 4.8.8.1 caRepository without URI",
- p->fn);
- goto out;
- }
- if (!sbgp_sia_resource_carepo(p, uri->data, uri->length))
- goto out;
- } else if (OBJ_cmp(oid, manifest_oid) == 0) {
- if (uri == NULL) {
- warnx("%s: RFC 6487: 4.8.8 SIA manifest without URI",
- p->fn);
- goto out;
- }
- if (!sbgp_sia_resource_mft(p, uri->data, uri->length))
- goto out;
- } else if (OBJ_cmp(oid, notify_oid) == 0) {
- if (uri == NULL) {
- warnx("%s: RFC 6487: 4.8.8 SIA resourceNotify "
- "without URI", p->fn);
- goto out;
- }
- if (!sbgp_sia_resource_notify(p, uri->data, uri->length))
- goto out;
- }
-
- rc = 1;
- out:
- return rc;
-}
-
-/*
* Parse "Subject Information Access" extension, RFC 6487 4.8.8.
* Returns zero on failure, non-zero on success.
*/
@@ -259,6 +167,7 @@ sbgp_sia(struct parse *p, X509_EXTENSION
{
AUTHORITY_INFO_ACCESS *sia = NULL;
ACCESS_DESCRIPTION *ad;
+ ASN1_OBJECT *oid;
int i, rc = 0;
if (X509_EXTENSION_get_critical(ext)) {
@@ -275,8 +184,22 @@ sbgp_sia(struct parse *p, X509_EXTENSION
for (i = 0; i < sk_ACCESS_DESCRIPTION_num(sia); i++) {
ad = sk_ACCESS_DESCRIPTION_value(sia, i);
- if (!sbgp_sia_resource_entry(p, ad))
- goto out;
+
+ oid = ad->method;
+
+ if (OBJ_cmp(oid, carepo_oid) == 0) {
+ if (!sbgp_sia_location(p->fn, "caRepository",
+ "rsync://", ad->location, &p->res->repo))
+ goto out;
+ } else if (OBJ_cmp(oid, manifest_oid) == 0) {
+ if (!sbgp_sia_location(p->fn, "rpkiManifest",
+ "rsync://", ad->location, &p->res->mft))
+ goto out;
+ } else if (OBJ_cmp(oid, notify_oid) == 0) {
+ if (!sbgp_sia_location(p->fn, "rpkiNotify",
+ "https://", ad->location, &p->res->notify))
+ goto out;
+ }
}
if (p->res->mft == NULL || p->res->repo == NULL) {