On Tue, Jan 18, 2022 at 12:16:44PM +0100, Claudio Jeker wrote:
> How X509_verify_cert() is called in rpki-client is mostly the same in all
> places so move all this X509 boilerplate into valid_x509().
>
> This simplifies the x509 validation in the parser a fair but and will also
> make it easier for -f to validate certs.
>
> OK?
ok
I would suggest we merge the three if (crl != NULL) checks into one
(maybe in a follow-up).
The _roa and _gbr paths called the warnx() with the
X509_verify_cert_error_string() only conditionally. I guess we can
adjust that later if this turns out to be too noisy.
> --
> :wq Claudio
>
> Index: parser.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/rpki-client/parser.c,v
> retrieving revision 1.37
> diff -u -p -r1.37 parser.c
> --- parser.c 14 Jan 2022 15:00:23 -0000 1.37
> +++ parser.c 18 Jan 2022 11:01:45 -0000
> @@ -200,52 +200,74 @@ verify_cb(int ok, X509_STORE_CTX *store_
> }
>
> /*
> - * Parse and validate a ROA.
> - * This is standard stuff.
> - * Returns the roa on success, NULL on failure.
> + * 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
> */
> -static struct roa *
> -proc_parser_roa(char *file, const unsigned char *der, size_t len)
> +static int
> +valid_x509(char *file, X509 *x509, struct auth *a, struct crl *crl)
> {
> - struct roa *roa;
> - X509 *x509;
> - int c;
> - struct auth *a;
> STACK_OF(X509) *chain;
> - STACK_OF(X509_CRL) *crls;
> - struct crl *crl;
> -
> - if ((roa = roa_parse(&x509, file, der, len)) == NULL)
> - return NULL;
> + STACK_OF(X509_CRL) *crls = NULL;
> + int c;
>
> - a = valid_ski_aki(file, &auths, roa->ski, roa->aki);
> build_chain(a, &chain);
> - crl = get_crl(a);
> - build_crls(crl, &crls);
> + if (crl != NULL)
> + build_crls(crl, &crls);
>
> assert(x509 != NULL);
> if (!X509_STORE_CTX_init(ctx, NULL, x509, NULL))
> cryptoerrx("X509_STORE_CTX_init");
> +
> X509_STORE_CTX_set_verify_cb(ctx, verify_cb);
> if (!X509_STORE_CTX_set_app_data(ctx, file))
> cryptoerrx("X509_STORE_CTX_set_app_data");
> - X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_CRL_CHECK);
> + if (crl != NULL)
> + X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_CRL_CHECK);
> X509_STORE_CTX_set_depth(ctx, MAX_CERT_DEPTH);
> X509_STORE_CTX_set0_trusted_stack(ctx, chain);
> - X509_STORE_CTX_set0_crls(ctx, crls);
> + if (crl != NULL)
> + X509_STORE_CTX_set0_crls(ctx, crls);
>
> if (X509_verify_cert(ctx) <= 0) {
> c = X509_STORE_CTX_get_error(ctx);
> + warnx("%s: %s", file, X509_verify_cert_error_string(c));
> X509_STORE_CTX_cleanup(ctx);
> - if (verbose > 0 || c != X509_V_ERR_UNABLE_TO_GET_CRL)
> - warnx("%s: %s", file, X509_verify_cert_error_string(c));
> - X509_free(x509);
> - roa_free(roa);
> sk_X509_free(chain);
> sk_X509_CRL_free(crls);
> - return NULL;
> + return 0;
> }
> +
> X509_STORE_CTX_cleanup(ctx);
> + sk_X509_free(chain);
> + sk_X509_CRL_free(crls);
> + return 1;
> +}
> +
> +/*
> + * Parse and validate a ROA.
> + * This is standard stuff.
> + * Returns the roa on success, NULL on failure.
> + */
> +static struct roa *
> +proc_parser_roa(char *file, const unsigned char *der, size_t len)
> +{
> + struct roa *roa;
> + struct crl *crl;
> + struct auth *a;
> + X509 *x509;
> +
> + if ((roa = roa_parse(&x509, file, der, len)) == NULL)
> + return NULL;
> +
> + a = valid_ski_aki(file, &auths, roa->ski, roa->aki);
> + crl = get_crl(a);
> +
> + if (!valid_x509(file, x509, a, crl)) {
> + X509_free(x509);
> + roa_free(roa);
> + return NULL;
> + }
> + X509_free(x509);
>
> /*
> * Check CRL to figure out the soonest transitive expiry moment
> @@ -270,10 +292,6 @@ proc_parser_roa(char *file, const unsign
> if (valid_roa(file, &auths, roa))
> roa->valid = 1;
>
> - sk_X509_free(chain);
> - sk_X509_CRL_free(crls);
> - X509_free(x509);
> -
> return roa;
> }
>
> @@ -336,38 +354,18 @@ proc_parser_mft(char *file, const unsign
> {
> struct mft *mft;
> X509 *x509;
> - int c;
> struct auth *a;
> - STACK_OF(X509) *chain;
>
> if ((mft = mft_parse(&x509, file, der, len)) == NULL)
> return NULL;
>
> a = valid_ski_aki(file, &auths, mft->ski, mft->aki);
> - build_chain(a, &chain);
>
> - if (!X509_STORE_CTX_init(ctx, NULL, x509, NULL))
> - cryptoerrx("X509_STORE_CTX_init");
> -
> - /* CRL checks disabled here because CRL is referenced from mft */
> - X509_STORE_CTX_set_verify_cb(ctx, verify_cb);
> - if (!X509_STORE_CTX_set_app_data(ctx, file))
> - cryptoerrx("X509_STORE_CTX_set_app_data");
> - X509_STORE_CTX_set_depth(ctx, MAX_CERT_DEPTH);
> - X509_STORE_CTX_set0_trusted_stack(ctx, chain);
> -
> - if (X509_verify_cert(ctx) <= 0) {
> - c = X509_STORE_CTX_get_error(ctx);
> - X509_STORE_CTX_cleanup(ctx);
> - warnx("%s: %s", file, X509_verify_cert_error_string(c));
> + if (!valid_x509(file, x509, a, NULL)) {
> mft_free(mft);
> X509_free(x509);
> - sk_X509_free(chain);
> return NULL;
> }
> -
> - X509_STORE_CTX_cleanup(ctx);
> - sk_X509_free(chain);
> X509_free(x509);
>
> mft->repoid = repoid;
> @@ -396,10 +394,8 @@ proc_parser_cert(char *file, const unsig
> {
> struct cert *cert;
> X509 *x509;
> - int c;
> - struct auth *a = NULL;
> - STACK_OF(X509) *chain;
> - STACK_OF(X509_CRL) *crls;
> + struct auth *a;
> + struct crl *crl;
>
> /* Extract certificate data and X509. */
>
> @@ -408,35 +404,13 @@ proc_parser_cert(char *file, const unsig
> return NULL;
>
> a = valid_ski_aki(file, &auths, cert->ski, cert->aki);
> - build_chain(a, &chain);
> - build_crls(get_crl(a), &crls);
> -
> - assert(x509 != NULL);
> - if (!X509_STORE_CTX_init(ctx, NULL, x509, NULL))
> - cryptoerrx("X509_STORE_CTX_init");
> -
> - X509_STORE_CTX_set_verify_cb(ctx, verify_cb);
> - if (!X509_STORE_CTX_set_app_data(ctx, file))
> - cryptoerrx("X509_STORE_CTX_set_app_data");
> - X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_CRL_CHECK);
> - X509_STORE_CTX_set_depth(ctx, MAX_CERT_DEPTH);
> - X509_STORE_CTX_set0_trusted_stack(ctx, chain);
> - X509_STORE_CTX_set0_crls(ctx, crls);
> + crl = get_crl(a);
>
> - if (X509_verify_cert(ctx) <= 0) {
> - c = X509_STORE_CTX_get_error(ctx);
> - warnx("%s: %s", file, X509_verify_cert_error_string(c));
> - X509_STORE_CTX_cleanup(ctx);
> + if (!valid_x509(file, x509, a, crl)) {
> cert_free(cert);
> - sk_X509_free(chain);
> - sk_X509_CRL_free(crls);
> X509_free(x509);
> return NULL;
> }
> -
> - X509_STORE_CTX_cleanup(ctx);
> - sk_X509_free(chain);
> - sk_X509_CRL_free(crls);
> X509_free(x509);
>
> cert->talid = a->cert->talid;
> @@ -597,39 +571,18 @@ proc_parser_gbr(char *file, const unsign
> {
> struct gbr *gbr;
> X509 *x509;
> - int c;
> struct auth *a;
> - STACK_OF(X509) *chain;
> - STACK_OF(X509_CRL) *crls;
> + struct crl *crl;
>
> if ((gbr = gbr_parse(&x509, file, der, len)) == NULL)
> return;
>
> a = valid_ski_aki(file, &auths, gbr->ski, gbr->aki);
> + crl = get_crl(a);
>
> - build_chain(a, &chain);
> - build_crls(get_crl(a), &crls);
> -
> - assert(x509 != NULL);
> - if (!X509_STORE_CTX_init(ctx, NULL, x509, NULL))
> - cryptoerrx("X509_STORE_CTX_init");
> - X509_STORE_CTX_set_verify_cb(ctx, verify_cb);
> - if (!X509_STORE_CTX_set_app_data(ctx, file))
> - cryptoerrx("X509_STORE_CTX_set_app_data");
> - X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_CRL_CHECK);
> - X509_STORE_CTX_set_depth(ctx, MAX_CERT_DEPTH);
> - X509_STORE_CTX_set0_trusted_stack(ctx, chain);
> - X509_STORE_CTX_set0_crls(ctx, crls);
> -
> - if (X509_verify_cert(ctx) <= 0) {
> - c = X509_STORE_CTX_get_error(ctx);
> - if (verbose > 0 || c != X509_V_ERR_UNABLE_TO_GET_CRL)
> - warnx("%s: %s", file, X509_verify_cert_error_string(c));
> - }
> + /* return value can be ignored since nothing happens here */
> + valid_x509(file, x509, a, crl);
>
> - X509_STORE_CTX_cleanup(ctx);
> - sk_X509_free(chain);
> - sk_X509_CRL_free(crls);
> X509_free(x509);
> gbr_free(gbr);
> }
>