On Mon, Nov 28, 2022 at 05:14:48PM +0100, Claudio Jeker wrote:
> On Mon, Nov 28, 2022 at 04:50:24PM +0100, Theo Buehler wrote:
> > On Mon, Nov 28, 2022 at 04:02:11PM +0100, Claudio Jeker wrote:
> > > 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.
> > 
> > I like this a lot.
> > 
> > I was wondering if valid_x509() should have a const char **errstr
> > instead of an int * as last argument. valid_x509() could do the
> > conversion from error code to error string itself. This way we don't
> > have to sprinkle X509_verify_cert_error_string() calls everywhere.
> > 
> > Or we could introduce a warn_invalid_x509(const char *str, int err) that
> > does the conversion from err using X509_verify_cert_error_string().
> > 
> > One downside of X509_verify_cert_error_string() is that it isn't thread
> > safe since it might return a pointer to a static buffer -- it should
> > not, but who can be sure...
> 
> Tough call. It may also help other code paths to do the same. But in many
> cases a dynamic buffer would be needed.
> 
> Not sure if it makes sense to introduce warn_invalid_x509(). What I don't
> like is the verbose check before the warning. I wonder if we still need
> that. My last run has 11 failed roas and 51 failed mfts. The mft errors
> already show up. Shouldn't the roa errors be shown as well?

They should. Unless I'm completely confusing myself, this is a bug in
the diff and all the added if (verbose > 1) should be dropped.

If the last argument (nowarn) of valid_x509() was 0 (everywhere except
in proc_parser_pre()), valid_x509() would print the error independently
of verbose. verbose > 1 would force printing the warning also for mfts,
but there it would be drowned in the other noise.

-       if (!valid_x509(file, ctx, x509, a, crl, 0)) {

...

-               if (!nowarn || verbose > 1)
-                       warnx("%s: %s", file, X509_verify_cert_error_string(c));


>  
> > > 
> > > -- 
> > > :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)

drop 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);
> > > 
> > 
> 
> -- 
> :wq Claudio

Reply via email to