So here is the cleanup of filemode.c and also a bit of cleanup in parse.c
This should also fix a few bugs in parse_load_certchain() (mainly
memleaks).

-- 
:wq Claudio

Index: cert.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
retrieving revision 1.70
diff -u -p -r1.70 cert.c
--- cert.c      21 Apr 2022 09:53:07 -0000      1.70
+++ cert.c      21 Apr 2022 10:45:17 -0000
@@ -999,6 +999,9 @@ out:
 struct cert *
 cert_parse(const char *fn, struct cert *p)
 {
+       if (p == NULL)
+               return NULL;
+
        if (p->aki == NULL) {
                warnx("%s: RFC 6487 section 8.4.2: "
                    "non-trust anchor missing AKI", fn);
@@ -1032,6 +1035,9 @@ ta_parse(const char *fn, struct cert *p,
        ASN1_TIME       *notBefore, *notAfter;
        EVP_PKEY        *pk, *opk;
 
+       if (p == NULL)
+               return NULL;
+
        /* first check pubkey against the one from the TAL */
        pk = d2i_PUBKEY(NULL, &pkey, pkeysz);
        if (pk == NULL) {
@@ -1207,7 +1213,7 @@ auth_find(struct auth_tree *auths, const
        return RB_FIND(auth_tree, auths, &a);
 }
 
-void
+struct auth *
 auth_insert(struct auth_tree *auths, struct cert *cert, struct auth *parent)
 {
        struct auth *na;
@@ -1221,6 +1227,8 @@ auth_insert(struct auth_tree *auths, str
 
        if (RB_INSERT(auth_tree, auths, na) != NULL)
                err(1, "auth tree corrupted");
+
+       return na;
 }
 
 static void
Index: extern.h
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.131
diff -u -p -r1.131 extern.h
--- extern.h    21 Apr 2022 09:53:07 -0000      1.131
+++ extern.h    21 Apr 2022 10:46:09 -0000
@@ -308,7 +308,7 @@ struct auth {
 RB_HEAD(auth_tree, auth);
 
 struct auth    *auth_find(struct auth_tree *, const char *);
-void            auth_insert(struct auth_tree *, struct cert *, struct auth *);
+struct auth    *auth_insert(struct auth_tree *, struct cert *, struct auth *);
 
 enum http_result {
        HTTP_FAILED,    /* anything else */
Index: filemode.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/filemode.c,v
retrieving revision 1.1
diff -u -p -r1.1 filemode.c
--- filemode.c  21 Apr 2022 09:53:07 -0000      1.1
+++ filemode.c  21 Apr 2022 10:47:24 -0000
@@ -46,80 +46,6 @@ static struct crl_tree        crlt = RB_INITIA
 struct tal             *talobj[TALSZ_MAX];
 
 /*
- * Validate a certificate, if invalid free the resouces and return NULL.
- */
-static struct cert *
-proc_parser_cert_validate(char *file, struct cert *cert)
-{
-       struct auth     *a;
-       struct crl      *crl;
-
-       a = valid_ski_aki(file, &auths, cert->ski, cert->aki);
-       crl = crl_get(&crlt, a);
-
-       if (!valid_x509(file, ctx, cert->x509, a, crl, 0)) {
-               cert_free(cert);
-               return NULL;
-       }
-
-       cert->talid = a->cert->talid;
-
-       /* Validate the cert */
-       if (!valid_cert(file, a, cert)) {
-               cert_free(cert);
-               return NULL;
-       }
-
-       /*
-        * Add validated CA certs to the RPKI auth tree.
-        */
-       if (cert->purpose == CERT_PURPOSE_CA)
-               auth_insert(&auths, cert, a);
-
-       return cert;
-}
-
-/*
- * Root certificates come from TALs (has a pkey and is self-signed).
- * Parse the certificate, ensure that its public key matches the
- * known public key from the TAL, and then validate the RPKI
- * content.
- *
- * This returns a certificate (which must not be freed) or NULL on
- * parse failure.
- */
-static struct cert *
-proc_parser_root_cert(char *file, const unsigned char *der, size_t len,
-    unsigned char *pkey, size_t pkeysz, int talid)
-{
-       struct cert             *cert;
-
-       /* Extract certificate data. */
-
-       cert = cert_parse_pre(file, der, len);
-       if (cert == NULL)
-               return NULL;
-       cert = ta_parse(file, cert, pkey, pkeysz);
-       if (cert == NULL)
-               return NULL;
-
-       if (!valid_ta(file, &auths, cert)) {
-               warnx("%s: certificate not a valid ta", file);
-               cert_free(cert);
-               return NULL;
-       }
-
-       cert->talid = talid;
-
-       /*
-        * Add valid roots to the RPKI auth tree.
-        */
-       auth_insert(&auths, cert, NULL);
-
-       return cert;
-}
-
-/*
  * Use the X509 CRL Distribution Points to locate the CRL needed for
  * verification.
  */
@@ -207,25 +133,25 @@ parse_load_cert(char *uri)
 static void
 parse_load_certchain(char *uri)
 {
-       struct cert *stack[MAX_CERT_DEPTH];
+       struct cert *stack[MAX_CERT_DEPTH] = { 0 };
        char *filestack[MAX_CERT_DEPTH];
        struct cert *cert;
-       int i, failed;
+       struct crl *crl;
+       struct auth *a;
+       int i;
 
        for (i = 0; i < MAX_CERT_DEPTH; i++) {
-               cert = parse_load_cert(uri);
-               if (cert == NULL) {
+               filestack[i] = uri;
+               stack[i] = cert = parse_load_cert(uri);
+               if (cert == NULL || cert->purpose != CERT_PURPOSE_CA) {
                        warnx("failed to build authority chain");
-                       return;
+                       goto fail;
                }
                if (auth_find(&auths, cert->ski) != NULL) {
                        assert(i == 0);
-                       cert_free(cert);
-                       return; /* cert already added */
+                       goto fail;
                }
-               stack[i] = cert;
-               filestack[i] = uri;
-               if (auth_find(&auths, cert->aki) != NULL)
+               if ((a = auth_find(&auths, cert->aki)) != NULL)
                        break;  /* found chain to TA */
                uri = cert->aia;
        }
@@ -233,47 +159,65 @@ parse_load_certchain(char *uri)
        if (i >= MAX_CERT_DEPTH) {
                warnx("authority chain exceeds max depth of %d",
                    MAX_CERT_DEPTH);
+fail:
                for (i = 0; i < MAX_CERT_DEPTH; i++)
                        cert_free(stack[i]);
                return;
        }
 
        /* TA found play back the stack and add all certs */
-       for (failed = 0; i >= 0; i--) {
+       for (; i >= 0; i--) {
                cert = stack[i];
                uri = filestack[i];
 
-               if (failed)
-                       cert_free(cert);
-               else if (proc_parser_cert_validate(uri, cert) == NULL)
-                       failed = 1;
+               crl = crl_get(&crlt, a);
+               if (valid_x509(uri, ctx, cert->x509, a, crl, 0) &&
+                   valid_cert(uri, a, cert)) {
+                       cert->talid = a->cert->talid;
+                       a = auth_insert(&auths, cert, a);
+               } else {
+                       for (; i >= 0; i--)
+                               cert_free(stack[i]);
+               }
        }
 }
 
 static void
 parse_load_ta(struct tal *tal)
 {
-       const char *file;
-       char *nfile, *f;
+       const char *filename;
+       struct cert *cert;
+       unsigned char *f = NULL;
+       char *file;
        size_t flen;
 
        /* does not matter which URI, all end with same filename */
-       file = strrchr(tal->uri[0], '/');
-       assert(file);
+       filename = strrchr(tal->uri[0], '/');
+       assert(filename);
 
-       if (asprintf(&nfile, "ta/%s%s", tal->descr, file) == -1)
+       if (asprintf(&file, "ta/%s%s", tal->descr, filename) == -1)
                err(1, NULL);
 
-       f = load_file(nfile, &flen);
+       f = load_file(file, &flen);
        if (f == NULL) {
-               warn("parse file %s", nfile);
-               free(nfile);
-               return;
+               warn("parse file %s", file);
+               goto out;
        }
 
-       /* if TA is valid it was added as a root which is all we need */
-       proc_parser_root_cert(nfile, f, flen, tal->pkey, tal->pkeysz, tal->id);
-       free(nfile);
+       /* Extract certificate data. */
+       cert = cert_parse_pre(file, f, flen);
+       cert = ta_parse(file, cert, tal->pkey, tal->pkeysz);
+       if (cert == NULL)
+               goto out;
+
+       cert->talid = tal->id;
+
+       if (!valid_ta(file, &auths, cert))
+               cert_free(cert);
+       else
+               auth_insert(&auths, cert, NULL);
+out:
+       free(file);
        free(f);
 }
 
Index: parser.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/parser.c,v
retrieving revision 1.72
diff -u -p -r1.72 parser.c
--- parser.c    21 Apr 2022 09:53:07 -0000      1.72
+++ parser.c    21 Apr 2022 10:45:53 -0000
@@ -389,30 +389,37 @@ proc_parser_mft(struct entity *entp, str
 }
 
 /*
- * Validate a certificate, if invalid free the resouces and return NULL.
+ * Certificates are from manifests (has a digest and is signed with
+ * another certificate) Parse the certificate, make sure its
+ * signatures are valid (with CRLs), then validate the RPKI content.
+ * This returns a certificate (which must not be freed) or NULL on
+ * parse failure.
  */
 static struct cert *
-proc_parser_cert_validate(char *file, struct cert *cert)
+proc_parser_cert(char *file, const unsigned char *der, size_t len)
 {
-       struct auth     *a;
+       struct cert     *cert;
        struct crl      *crl;
+       struct auth     *a;
+
+       /* Extract certificate data. */
+
+       cert = cert_parse_pre(file, der, len);
+       cert = cert_parse(file, cert);
+       if (cert == NULL)
+               return NULL;
 
        a = valid_ski_aki(file, &auths, cert->ski, cert->aki);
        crl = crl_get(&crlt, a);
 
-       if (!valid_x509(file, ctx, cert->x509, a, crl, 0)) {
+       if (!valid_x509(file, ctx, cert->x509, a, crl, 0) ||
+           !valid_cert(file, a, cert)) {
                cert_free(cert);
                return NULL;
        }
 
        cert->talid = a->cert->talid;
 
-       /* Validate the cert */
-       if (!valid_cert(file, a, cert)) {
-               cert_free(cert);
-               return NULL;
-       }
-
        /*
         * Add validated CA certs to the RPKI auth tree.
         */
@@ -423,31 +430,6 @@ proc_parser_cert_validate(char *file, st
 }
 
 /*
- * Certificates are from manifests (has a digest and is signed with
- * another certificate) Parse the certificate, make sure its
- * signatures are valid (with CRLs), then validate the RPKI content.
- * This returns a certificate (which must not be freed) or NULL on
- * parse failure.
- */
-static struct cert *
-proc_parser_cert(char *file, const unsigned char *der, size_t len)
-{
-       struct cert     *cert;
-
-       /* Extract certificate data. */
-
-       cert = cert_parse_pre(file, der, len);
-       if (cert == NULL)
-               return NULL;
-       cert = cert_parse(file, cert);
-       if (cert == NULL)
-               return NULL;
-
-       cert = proc_parser_cert_validate(file, cert);
-       return cert;
-}
-
-/*
  * Root certificates come from TALs (has a pkey and is self-signed).
  * Parse the certificate, ensure that its public key matches the
  * known public key from the TAL, and then validate the RPKI
@@ -465,8 +447,6 @@ proc_parser_root_cert(char *file, const 
        /* Extract certificate data. */
 
        cert = cert_parse_pre(file, der, len);
-       if (cert == NULL)
-               return NULL;
        cert = ta_parse(file, cert, pkey, pkeysz);
        if (cert == NULL)
                return NULL;

Reply via email to