On Wed, Jan 19, 2022 at 02:57:44PM +0100, Claudio Jeker wrote:
> > > + return;
> > > + }
> > > +
> > > + /* TA found play back the stack and add all certs */
> > > + do {
> > > + if (parser_cert_validate(nfile, cert) == NULL)
> > > + break;
> >
> > I think this also needs a cert_free(cert).
>
> Certs are special and never released once valid. The are added to the
> auths tree. If parser_cert_validate() fails then cert is already freed so
> that should also be fine.
Indeed. I got it now.
>
> > > + free(nfile);
> > > + cert = stack[stacksz - 1];
> > > + nfile = filestack[stacksz - 1];
> >
> > I'm probably missing something, but I don't see why we don't hit this
> > in the last iteration where stacksz == 0 (which would be bad).
> >
> > > + } while (stacksz-- > 0);
> >
> > It's probably related to my above confusion: We don't need to free cert
> > if parser_cert_validate() fails but do need to free it if we exit the
> > while loop because stacksz == 0.
>
> Yeah, I'm also confused. I think the code currently underflows the stack
> which seems to result in a NULL cert.
>
> Anyway I totally rewrote that bit without recursion. Have a look below.
> Only think I dislike is the fact that parse_load_certchain() is using the
> URI instead of the filename (but should be easy enough to convert between
> the two).
This is much clearer to me and I like the non-recursive version better.
ok tb
Some tiny nits for your consideration. Apart from the %i do as you
prefer :)
> Index: parser.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/parser.c,v
> retrieving revision 1.44
> diff -u -p -r1.44 parser.c
> --- parser.c 18 Jan 2022 18:19:47 -0000 1.44
> +++ parser.c 19 Jan 2022 13:54:06 -0000
> @@ -383,24 +383,13 @@ proc_parser_mft(char *file, const unsign
> }
>
> /*
> - * 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.
> + * Validate a certificate, if invalid free the resouces and return NULL.
> */
> static struct cert *
> -proc_parser_cert(char *file, const unsigned char *der, size_t len)
> +parser_cert_validate(char *file, struct cert *cert)
This is the only function with a parser_ prefix.
Should this be proc_parser_cert_validate()?
(parse_cert_validate would be a bad name).
[...]
> +/*
> + * Build the certificate chain by using the Authority Information Access.
> + * This requires that the TA are already validated and added to the auths
> + * tree. Once the TA is located in the chain the chain is validated in
> + * reverse order.
> + */
> +static void
> +parse_load_certchain(char *uri)
> +{
> + struct cert *stack[MAX_CERT_DEPTH];
> + char *filestack[MAX_CERT_DEPTH];
> + struct cert *cert;
> + int i, failed;
> +
> + for (i = 0; i < MAX_CERT_DEPTH; i++) {
> + cert = parse_load_cert(uri);
> + if (cert == NULL) {
> + warnx("failed to build authority chain");
> + return;
> + }
> + stack[i] = cert;
> + filestack[i] = uri;
> + if (auth_find(&auths, cert->aki) != NULL) {
no need for braces
> + break; /* found the TA */
> + }
> + uri = cert->aia;
> + }
> +
> + if (i >= MAX_CERT_DEPTH) {
> + warnx("authority chain exceeds max depth of %i",
use %d instead of %i
> + MAX_CERT_DEPTH);
> + for (i = 0; i < MAX_CERT_DEPTH; i++) {
no need for braces
> + cert_free(stack[i]);
> + }
> + return;
> + }