Since a long time any problem that caused rpki-client to not load a
manifest resulted in the non helpful:
rpki-client: 
rpki.afrinic.net/repository/member_repository/F36505B2/0569917622D711ED862FD6E0F1222468/0nALpPtwFyntPHjkS8xt-VQrqLw.mft:
 no valid mft available

This hides in most cases the cause why the manifest verificatin failed.
The following diff exposes the error from valid_x509() and with that some
manifest errors change to e.g.:
rpki-client: 
parent.rov.koenvanhove.nl/repo/KoenvanHove/1/C1F7424F77FBF669FB750C6DC7B649C5969DCD55.mft:
 CRL has expired

or if the CRL is missing

rpki-client: 
repo.pedjoeang.group/repo/localname/0/EF79F8E55B6A248EF9CF4CE70FF60C017BF1A3B0.mft:
 unable to get certificate CRL

If the certificate is pointing to a manifest that does not exist the old
"no valid mft available" is shown.

I tried to keep original behaviour as much as possible but I think
filemode can be further improved. And maybe we can remove verbose from
other warnings as well.

-- 
:wq Claudio

Index: extern.h
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.161
diff -u -p -r1.161 extern.h
--- extern.h    26 Nov 2022 12:02:36 -0000      1.161
+++ extern.h    28 Nov 2022 10:42:11 -0000
@@ -629,7 +629,7 @@ int          valid_filename(const char *, size_
 int             valid_uri(const char *, size_t, const char *);
 int             valid_origin(const char *, const char *);
 int             valid_x509(char *, X509_STORE_CTX *, X509 *, struct auth *,
-                   struct crl *, int);
+                   struct crl *, int *);
 int             valid_rsc(const char *, struct cert *, struct rsc *);
 int             valid_econtent_version(const char *, const ASN1_INTEGER *);
 int             valid_aspa(const char *, struct cert *, struct aspa *);
Index: filemode.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/filemode.c,v
retrieving revision 1.17
diff -u -p -r1.17 filemode.c
--- filemode.c  26 Nov 2022 12:02:37 -0000      1.17
+++ filemode.c  28 Nov 2022 11:08:31 -0000
@@ -141,7 +141,7 @@ parse_load_certchain(char *uri)
        struct cert *cert;
        struct crl *crl;
        struct auth *a;
-       int i;
+       int i, e;
 
        for (i = 0; i < MAX_CERT_DEPTH; i++) {
                filestack[i] = uri;
@@ -171,9 +171,13 @@ parse_load_certchain(char *uri)
                uri = filestack[i];
 
                crl = crl_get(&crlt, a);
-               if (!valid_x509(uri, ctx, cert->x509, a, crl, 0) ||
-                   !valid_cert(uri, a, cert))
+               if (!valid_x509(uri, ctx, cert->x509, a, crl, &e) ||
+                   !valid_cert(uri, a, cert)) {
+                       if (verbose > 1)
+                               warnx("%s: %s", uri,
+                                   X509_verify_cert_error_string(e));
                        goto fail;
+               }
                cert->talid = a->cert->talid;
                a = auth_insert(&auths, cert, a);
                stack[i] = NULL;
@@ -275,7 +279,7 @@ proc_parser_file(char *file, unsigned ch
        char filehash[SHA256_DIGEST_LENGTH];
        char *hash;
        enum rtype type;
-       int is_ta = 0;
+       int is_ta = 0, e;
 
        if (num++ > 0) {
                if ((outformats & FORMAT_JSON) == 0)
@@ -418,7 +422,7 @@ proc_parser_file(char *file, unsigned ch
                a = auth_find(&auths, aki);
                c = crl_get(&crlt, a);
 
-               if ((status = valid_x509(file, ctx, x509, a, c, 0))) {
+               if ((status = valid_x509(file, ctx, x509, a, c, &e))) {
                        switch (type) {
                        case RTYPE_ROA:
                                status = roa->valid;
@@ -438,8 +442,12 @@ proc_parser_file(char *file, unsigned ch
                }
                if (status)
                        printf("OK");
-               else
+               else {
+                       if (verbose > 1)
+                               warnx("%s: %s", file,
+                                   X509_verify_cert_error_string(e));
                        printf("Failed");
+               }
        } else if (is_ta) {
                if ((tal = find_tal(cert)) != NULL) {
                        cert = ta_parse(file, cert, tal->pkey, tal->pkeysz);
Index: parser.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/parser.c,v
retrieving revision 1.78
diff -u -p -r1.78 parser.c
--- parser.c    2 Nov 2022 12:43:02 -0000       1.78
+++ parser.c    28 Nov 2022 14:39:37 -0000
@@ -132,6 +132,7 @@ proc_parser_roa(char *file, const unsign
        struct auth             *a;
        struct crl              *crl;
        X509                    *x509;
+       int                      e;
 
        if ((roa = roa_parse(&x509, file, der, len)) == NULL)
                return NULL;
@@ -139,7 +140,9 @@ proc_parser_roa(char *file, const unsign
        a = valid_ski_aki(file, &auths, roa->ski, roa->aki);
        crl = crl_get(&crlt, a);
 
-       if (!valid_x509(file, ctx, x509, a, crl, 0)) {
+       if (!valid_x509(file, ctx, x509, a, crl, &e)) {
+               if (verbose > 1)
+                       warnx("%s: %s", file, X509_verify_cert_error_string(e));
                X509_free(x509);
                roa_free(roa);
                return NULL;
@@ -232,6 +235,7 @@ parse_load_crl_from_mft(struct entity *e
                if (!valid_hash(f, flen, mft->crlhash, sizeof(mft->crlhash)))
                        goto next;
                crl = crl_parse(fn, f, flen);
+
 next:
                free(f);
                free(fn);
@@ -255,19 +259,20 @@ next:
  */
 static struct mft *
 proc_parser_mft_pre(char *file, const unsigned char *der, size_t len,
-    struct entity *entp, enum location loc, struct crl **crl)
+    struct entity *entp, enum location loc, struct crl **crl, int *err)
 {
        struct mft      *mft;
        X509            *x509;
        struct auth     *a;
 
        *crl = NULL;
+       *err = 0;
        if ((mft = mft_parse(&x509, file, der, len)) == NULL)
                return NULL;
        *crl = parse_load_crl_from_mft(entp, mft, loc);
 
        a = valid_ski_aki(file, &auths, mft->ski, mft->aki);
-       if (!valid_x509(file, ctx, x509, a, *crl, 1)) {
+       if (!valid_x509(file, ctx, x509, a, *crl, err)) {
                X509_free(x509);
                mft_free(mft);
                crl_free(*crl);
@@ -285,13 +290,17 @@ proc_parser_mft_pre(char *file, const un
  * Return the mft on success or NULL on failure.
  */
 static struct mft *
-proc_parser_mft_post(char *file, struct mft *mft, const char *path)
+proc_parser_mft_post(char *file, struct mft *mft, const char *path, int error)
 {
        /* check that now is not before from */
        time_t now = time(NULL);
 
        if (mft == NULL) {
-               warnx("%s: no valid mft available", file);
+               if (error != 0)
+                       warnx("%s: %s", file,
+                           X509_verify_cert_error_string(error));
+               else
+                       warnx("%s: no valid mft available", file);
                return NULL;
        }
 
@@ -331,6 +340,7 @@ proc_parser_mft(struct entity *entp, str
        struct crl      *crl, *crl1 = NULL, *crl2 = NULL;
        char            *f, *file, *file1, *file2;
        size_t           flen;
+       int              err1, err2;
 
        *mp = NULL;
        file1 = parse_filepath(entp->repoid, entp->path, entp->file, DIR_VALID);
@@ -341,7 +351,7 @@ proc_parser_mft(struct entity *entp, str
                if (f == NULL && errno != ENOENT)
                        warn("parse file %s", file1);
                mft1 = proc_parser_mft_pre(file1, f, flen, entp, DIR_VALID,
-                   &crl1);
+                   &crl1, &err1);
                free(f);
        }
        if (file2 != NULL) {
@@ -349,22 +359,27 @@ proc_parser_mft(struct entity *entp, str
                if (f == NULL && errno != ENOENT)
                        warn("parse file %s", file2);
                mft2 = proc_parser_mft_pre(file2, f, flen, entp, DIR_TEMP,
-                   &crl2);
+                   &crl2, &err2);
                free(f);
        }
 
+       /* overload error from temp file if it is set */
+       if (mft1 == NULL && mft2 == NULL)
+               if (err2 != 0)
+                       err1 = err2;
+
        if (mft_compare(mft1, mft2) == 1) {
                mft_free(mft2);
                crl_free(crl2);
                free(file2);
-               *mp = proc_parser_mft_post(file1, mft1, entp->path);
+               *mp = proc_parser_mft_post(file1, mft1, entp->path, err1);
                crl = crl1;
                file = file1;
        } else {
                mft_free(mft1);
                crl_free(crl1);
                free(file1);
-               *mp = proc_parser_mft_post(file2, mft2, entp->path);
+               *mp = proc_parser_mft_post(file2, mft2, entp->path, err2);
                crl = crl2;
                file = file2;
        }
@@ -393,6 +408,7 @@ proc_parser_cert(char *file, const unsig
        struct cert     *cert;
        struct crl      *crl;
        struct auth     *a;
+       int              e;
 
        /* Extract certificate data. */
 
@@ -404,8 +420,10 @@ proc_parser_cert(char *file, const unsig
        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, &e) ||
            !valid_cert(file, a, cert)) {
+               if (verbose > 1)
+                       warnx("%s: %s", file, X509_verify_cert_error_string(e));
                cert_free(cert);
                return NULL;
        }
@@ -469,6 +487,7 @@ proc_parser_gbr(char *file, const unsign
        X509                    *x509;
        struct crl              *crl;
        struct auth             *a;
+       int                      e;
 
        if ((gbr = gbr_parse(&x509, file, der, len)) == NULL)
                return;
@@ -477,7 +496,9 @@ proc_parser_gbr(char *file, const unsign
        crl = crl_get(&crlt, a);
 
        /* return value can be ignored since nothing happens here */
-       valid_x509(file, ctx, x509, a, crl, 0);
+       if (!valid_x509(file, ctx, x509, a, crl, &e))
+               if (verbose > 1)
+                       warnx("%s: %s", file, X509_verify_cert_error_string(e));
 
        X509_free(x509);
        gbr_free(gbr);
@@ -493,6 +514,7 @@ proc_parser_aspa(char *file, const unsig
        struct auth             *a;
        struct crl              *crl;
        X509                    *x509;
+       int                      e;
 
        if ((aspa = aspa_parse(&x509, file, der, len)) == NULL)
                return NULL;
@@ -500,7 +522,9 @@ proc_parser_aspa(char *file, const unsig
        a = valid_ski_aki(file, &auths, aspa->ski, aspa->aki);
        crl = crl_get(&crlt, a);
 
-       if (!valid_x509(file, ctx, x509, a, crl, 0)) {
+       if (!valid_x509(file, ctx, x509, a, crl, &e)) {
+               if (verbose > 1)
+                       warnx("%s: %s", file, X509_verify_cert_error_string(e));
                X509_free(x509);
                aspa_free(aspa);
                return NULL;
@@ -530,7 +554,7 @@ proc_parser_tak(char *file, const unsign
        X509                    *x509;
        struct crl              *crl;
        struct auth             *a;
-       int                      rc = 0;
+       int                      rc = 0, e;
 
        if ((tak = tak_parse(&x509, file, der, len)) == NULL)
                return NULL;
@@ -538,8 +562,11 @@ proc_parser_tak(char *file, const unsign
        a = valid_ski_aki(file, &auths, tak->ski, tak->aki);
        crl = crl_get(&crlt, a);
 
-       if (!valid_x509(file, ctx, x509, a, crl, 0))
+       if (!valid_x509(file, ctx, x509, a, crl, &e)) {
+               if (verbose > 1)
+                       warnx("%s: %s", file, X509_verify_cert_error_string(e));
                goto out;
+       }
 
        /* TAK EE must be signed by self-signed CA */
        if (a->parent != NULL)
Index: validate.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/validate.c,v
retrieving revision 1.47
diff -u -p -r1.47 validate.c
--- validate.c  26 Nov 2022 12:02:37 -0000      1.47
+++ validate.c  28 Nov 2022 14:48:26 -0000
@@ -369,17 +369,17 @@ build_crls(const struct crl *crl, STACK_
 /*
  * Validate the X509 certificate.  If crl is NULL don't check CRL.
  * Returns 1 for valid certificates, returns 0 if there is a verify error
+ * and sets err pointer to the error returned by X509_verify_cert().
  */
 int
 valid_x509(char *file, X509_STORE_CTX *store_ctx, X509 *x509, struct auth *a,
-    struct crl *crl, int nowarn)
+    struct crl *crl, int *err)
 {
        X509_VERIFY_PARAM       *params;
        ASN1_OBJECT             *cp_oid;
        STACK_OF(X509)          *chain;
        STACK_OF(X509_CRL)      *crls = NULL;
        unsigned long            flags;
-       int                      c;
 
        build_chain(a, &chain);
        build_crls(crl, &crls);
@@ -405,9 +405,7 @@ valid_x509(char *file, X509_STORE_CTX *s
        X509_STORE_CTX_set0_crls(store_ctx, crls);
 
        if (X509_verify_cert(store_ctx) <= 0) {
-               c = X509_STORE_CTX_get_error(store_ctx);
-               if (!nowarn || verbose > 1)
-                       warnx("%s: %s", file, X509_verify_cert_error_string(c));
+               *err = X509_STORE_CTX_get_error(store_ctx);
                X509_STORE_CTX_cleanup(store_ctx);
                sk_X509_free(chain);
                sk_X509_CRL_free(crls);

Reply via email to