diff --git a/lib/libfetch/common.c b/lib/libfetch/common.c --- a/lib/libfetch/common.c +++ b/lib/libfetch/common.c @@ -137,6 +137,8 @@ /* End-of-Line */ static const char ENDL[2] = "\r\n"; +/* SSL global options for callback use */ +static int ssl_crl_present_only; /*** Error-reporting functions ***********************************************/ @@ -1057,9 +1059,10 @@ static int fetch_ssl_setup_peer_verification(SSL_CTX *ctx, int verbose) { + const char *ca_cert_file, *ca_cert_path, *crl_file, *crl_verify; X509_LOOKUP *crl_lookup; X509_STORE *crl_store; - const char *ca_cert_file, *ca_cert_path, *crl_file; + int crl_flags; if (getenv("SSL_NO_VERIFY_PEER") == NULL) { ca_cert_file = getenv("SSL_CA_CERT_FILE"); @@ -1083,6 +1086,33 @@ ca_cert_path); else SSL_CTX_set_default_verify_paths(ctx); + if ((crl_verify = getenv("SSL_CRL_VERIFY")) != NULL) { + if (strcasecmp(crl_verify, "leaf") && + strcasecmp(crl_verify, "chain") && + strcasecmp(crl_verify, "present")) { + fprintf(stderr, + "Unknown CRL verify value: %s\n", + crl_verify); + return (0); + } + if (verbose) + fetch_info("Using CRL verify: %s", crl_verify); + crl_flags = X509_V_FLAG_CRL_CHECK; + switch (crl_verify[0]) { + case 'P': + case 'p': + ssl_crl_present_only = 1; + /* FALLTRHOUGH */ + case 'C': + case 'c': + crl_flags |= X509_V_FLAG_CRL_CHECK_ALL; + break; + default: + break; + } + X509_VERIFY_PARAM_set_flags(SSL_CTX_get0_param(ctx), + crl_flags); + } if ((crl_file = getenv("SSL_CRL_FILE")) != NULL) { if (verbose) fetch_info("Using CRL file: %s", crl_file); @@ -1153,14 +1183,39 @@ char *str; str = NULL; + + /* + * CLRs may be defined explicitly but not always. The absence of a + * CRL distribution point is no indication that a CRL does not exist + * which also means the CRL check being enforced will require to have + * proper CRLs in place for the certificates to be checked which can + * not be guaranteed for a random hostname on the Internet. This may + * disable the specific OpenSSL error that deals with this case given + * the best effort on the user side to supply a full batch of relevant + * CRLs that are required to verify the certificate validity while + * retaining visibility in the form of the displayed error message. + */ + if (ssl_crl_present_only && !verified && + X509_STORE_CTX_get_error(ctx) == X509_V_ERR_UNABLE_TO_GET_CRL) { + if ((crt = X509_STORE_CTX_get_current_cert(ctx)) != NULL && + (name = X509_get_subject_name(crt)) != NULL) + str = X509_NAME_oneline(name, 0, 0); + fprintf(stderr, "No CRL was provided for %s\n", str); + OPENSSL_free(str); + + verified = 1; + } + if (!verified) { if ((crt = X509_STORE_CTX_get_current_cert(ctx)) != NULL && (name = X509_get_subject_name(crt)) != NULL) str = X509_NAME_oneline(name, 0, 0); - fprintf(stderr, "Certificate verification failed for %s\n", - str != NULL ? str : "no relevant certificate"); + fprintf(stderr, "Certificate verification failed for %s (%d)\n", + str != NULL ? str : "no relevant certificate", + X509_STORE_CTX_get_error(ctx)); OPENSSL_free(str); } + return (verified); } diff --git a/lib/libfetch/fetch.3 b/lib/libfetch/fetch.3 --- a/lib/libfetch/fetch.3 +++ b/lib/libfetch/fetch.3 @@ -24,7 +24,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd October 7, 2023 +.Dd November 4, 2024 .Dt FETCH 3 .Os .Sh NAME @@ -420,8 +420,33 @@ A certificate revocation list (CRL) can be used by setting the environment variable .Ev SSL_CRL_FILE +to the respective file containing the CRL, +or by setting the environment variable +.Ev SSL_CRL_VERIFY +to look for the CRL in the configured trust store file or path (see .Xr crl 1 ) . +The accepted values for +.Ev SSL_CRL_VERIFY +are: +.Bl -tag -width ".Ar present" +.It Ar leaf +Verify the leaf certificate only. +If the CRL is not present, the verification fails. +.It Ar chain +Verify the full certificate chain. +If any CRL is not present, the verification fails. +.It Ar present +Verify the full certificate chain, but only use the currently present +CRLs as opposed to requiring all of them. +This allows to verify certificates that do not have a CRL distribution +point set, but will also verify certificates which do have a publicly +available CRL that was not provided to the trust store. +A message will be printed to +.Va stderr +to acknowledge which certficate CRL was not found and therefore not +verified. +.El .Pp Peer verification can be disabled by setting the environment variable .Ev SSL_NO_VERIFY_PEER .