1717#include <openssl/provider.h>
1818#include <openssl/store.h>
1919#include <openssl/core_names.h>
20+ #include <openssl/http.h>
21+ #include <openssl/pem.h>
2022#include <secutils/credentials/credentials.h>
2123#include <secutils/credentials/store.h>
2224#include <secutils/credentials/cert.h>
@@ -638,25 +640,133 @@ EVP_PKEY *FILES_load_pubkey_ex(OPTIONAL OSSL_LIB_CTX *libctx, OPTIONAL const cha
638640 return pkey ;
639641}
640642
643+ static BIO * bio_to_mem_bio (BIO * in , size_t max_len )
644+ {
645+ char buf [4096 ];
646+ size_t total = 0 ;
647+
648+ if (in == NULL )
649+ return NULL ;
650+
651+ BIO * mem = BIO_new (BIO_s_mem ());
652+ if (mem == NULL )
653+ return NULL ;
654+
655+ for (;;) {
656+ int n = BIO_read (in , buf , sizeof (buf ));
657+ if (n == 0 )
658+ break ; /* EOF */
659+
660+ if (n > 0 ) {
661+ if (max_len != 0 && total + (size_t )n > max_len ) {
662+ BIO_free (mem );
663+ return NULL ;
664+ }
665+
666+ if (BIO_write (mem , buf , n ) != n ) {
667+ BIO_free (mem );
668+ return NULL ;
669+ }
670+
671+ total += (size_t )n ;
672+ continue ;
673+ }
674+
675+ if (BIO_should_retry (in ))
676+ continue ;
677+
678+ BIO_free (mem );
679+ return NULL ;
680+ }
681+
682+ return mem ;
683+ }
684+
685+ static bool contains_str (const char * buf , size_t len , const char * str )
686+ {
687+ size_t nlen = strlen (str );
688+ if (nlen == 0 || len < nlen )
689+ return false;
690+
691+ const char * max = buf + len - nlen ;
692+ while (buf <= max )
693+ if (memcmp (buf ++ , str , nlen ) == 0 )
694+ return true;
695+ return false;
696+ }
697+
698+ static BIO * http_get_mem (const char * uri , int timeout , const char * str , bool * found , const char * desc )
699+ {
700+ * found = false;
701+ if (CONN_IS_HTTPS (uri )) {
702+ LOG (FL_ERR , "Loading %s over HTTPS is unsupported; uri=%s" , desc , uri );
703+ return NULL ;
704+ }
705+ BIO * res = OSSL_HTTP_get (uri , NULL /* proxy */ , NULL /* no_proxy */ ,
706+ NULL /* bio */ , NULL /* rbio */ , NULL /* cb */ , NULL /* arg */ ,
707+ 0 /* buf_size */ , NULL /* headers */ ,
708+ NULL /* expected_ct */ , 0 /* expect_asn1 */ ,
709+ 100000 /* max_resp_len */ , timeout );
710+ if (res == NULL ) {
711+ LOG (FL_ERR , "Unable to download %s from %s\n" , desc , uri );
712+ return NULL ;
713+ }
714+ if (str == NULL )
715+ return res ;
716+
717+ BIO * mem = bio_to_mem_bio (res , 0 );
718+ BIO_free (res );
719+ if (mem == NULL ) {
720+ LOG (FL_ERR , "Error reading %s data received from %s" , desc , uri );
721+ return NULL ;
722+ }
723+
724+ char * data = NULL ;
725+ long len = BIO_get_mem_data (mem , & data );
726+ if (len <= 0 || data == NULL ) {
727+ LOG (FL_ERR , "Error peeking at %s data received from %s" , desc , uri );
728+ BIO_free (mem );
729+ return NULL ;
730+ }
731+
732+ * found = contains_str (data , (size_t )len , str );
733+ return mem ;
734+ }
735+
641736X509 * FILES_load_cert_ex (OPTIONAL OSSL_LIB_CTX * libctx , OPTIONAL const char * propq ,
642737 OPTIONAL const char * uri , file_format_t format , bool maybe_stdin ,
643- OPTIONAL const char * source , OPTIONAL const char * desc ,
738+ int timeout , OPTIONAL const char * source , OPTIONAL const char * desc ,
644739 int type_CA , OPTIONAL const X509_VERIFY_PARAM * vpm )
645740{
646741 char * pass ;
647- X509 * cert ;
742+ X509 * cert = NULL ;
648743
649744 if (desc == NULL )
650745 desc = "certificate" ;
651746 LOG (FL_DEBUG , "Loading %s from %s" , desc , uri != NULL ? uri : "<stdin>" );
652- pass = FILES_get_pass (source , desc );
653- (void )load_key_certs_crls (libctx , propq , uri , format , maybe_stdin , pass , desc , false,
654- NULL , NULL , NULL , & cert , NULL , 1 , NULL , NULL , 0 );
655- UTIL_cleanse_free (pass );
747+ if (CONN_IS_HTTP (uri ) || CONN_IS_HTTPS (uri )) {
748+ bool is_pem ;
749+ BIO * mem = http_get_mem (uri , timeout , "-----BEGIN CERTIFICATE-----" , & is_pem , desc );
750+ if (mem != NULL ) {
751+ cert = is_pem ? PEM_read_bio_X509 (mem , NULL , NULL , NULL ) : d2i_X509_bio (mem , NULL );
752+ BIO_free (mem );
753+ if (cert == NULL )
754+ LOG (FL_ERR , "Unable to decode %s from %s" , desc , uri );
755+ }
756+ } else {
757+ pass = FILES_get_pass (source , desc );
758+ (void )load_key_certs_crls (libctx , propq , uri , format , maybe_stdin , pass , desc , false,
759+ NULL , NULL , NULL , & cert , NULL , 1 , NULL , NULL , 0 );
760+ UTIL_cleanse_free (pass );
761+ }
656762 if (!CERT_check (uri , cert , type_CA , vpm ) && vpm != NULL ) {
657763 X509_free (cert );
658764 cert = NULL ;
659765 }
766+ if (cert == NULL ) {
767+ ERR_print_errors (bio_err );
768+ LOG (FL_ERR , "Unable to load %s from %s\n" , desc , uri != NULL ? uri : "<stdin>" );
769+ }
660770 return cert ;
661771}
662772
@@ -692,26 +802,20 @@ bool FILES_load_certs_ex(OPTIONAL OSSL_LIB_CTX *libctx, OPTIONAL const char *pro
692802
693803 if (desc == NULL )
694804 desc = "certs" ;
695- LOG (FL_DEBUG , "Loading %s from %s" , desc , srcs );
805+ if (!CONN_IS_HTTP (srcs )) /* well, this suppresses output also if only part of the srcs is HTTP-based */
806+ LOG (FL_DEBUG , "Loading %s from %s" , desc , srcs );
696807 pass = FILES_get_pass (source , desc );
697808
698809 if (names == NULL || (all_crts = sk_X509_new_null ()) == NULL )
699810 goto oom ;
700811 for (src = UTIL_first_item (names ); src != NULL ; src = next ) {
701812 next = UTIL_next_item (src ); /* must do this here to split string */
702813
703- if (CONN_IS_HTTPS (src )) {
704- LOG (FL_ERR , "Loading %s over HTTPS is unsupported; uri=%s\n" , desc , src );
705- goto err ;
706- }
707-
708- if (CONN_IS_HTTP (src )) {
709- crt = X509_load_http (src , NULL , NULL , timeout );
710- if (crt == NULL ) {
711- ERR_print_errors (bio_err );
712- LOG (FL_ERR , "Unable to load %s from %s\n" , desc , src );
814+ if (CONN_IS_HTTP (src ) || CONN_IS_HTTPS (src )) {
815+ crt = FILES_load_cert_ex (libctx , propq , src , format , false,
816+ timeout , NULL , desc , type_CA , vpm );
817+ if (crt == NULL )
713818 goto err ;
714- }
715819 goto handle_crt ;
716820 } else {
717821 if (!load_key_certs_crls (libctx , propq , src ,
@@ -793,26 +897,27 @@ X509_CRL *FILES_load_crl_ex(OPTIONAL OSSL_LIB_CTX *libctx, OPTIONAL const char *
793897 if (desc == NULL )
794898 desc = "CRL" ;
795899 LOG (FL_DEBUG , "Loading %s from %s" , desc , uri != NULL ? uri : "<stdin>" );
796- if (CONN_IS_HTTPS (uri )) {
797- LOG (FL_ERR , "Loading %s over HTTPS is unsupported; uri=%s\n" , desc , uri );
798- } else if (CONN_IS_HTTP (uri )) { /* TODO maybe also support PEM format */
799- #if 1
800- crl = CONN_load_crl_http (uri , timeout , 0 , desc );
801- #else
802- crl = X509_CRL_load_http (uri , NULL , NULL , timeout );
803- if (crl == NULL ) {
804- ERR_print_errors (bio_err );
805- LOG (FL_ERR , "Unable to load %s from %s\n" , desc , uri != NULL ? uri : "<stdin>" );
900+ if (CONN_IS_HTTP (uri ) || CONN_IS_HTTPS (uri )) {
901+ bool is_pem ;
902+ BIO * mem = http_get_mem (uri , timeout , "-----BEGIN X509 CRL-----" , & is_pem , desc );
903+ if (mem != NULL ) {
904+ crl = is_pem ? PEM_read_bio_X509_CRL (mem , NULL , NULL , NULL ) : d2i_X509_CRL_bio (mem , NULL );
905+ BIO_free (mem );
906+ if (crl == NULL )
907+ LOG (FL_ERR , "Unable to decode %s from %s" , desc , uri );
806908 }
807- #endif
808909 } else {
809910 (void )load_key_certs_crls (libctx , propq ,
810911 uri , format , maybe_stdin , NULL , desc , false,
811912 NULL , NULL , NULL , NULL , NULL , 0 , & crl , NULL , 1 );
812913 }
813914 if (!CRL_check (uri , crl , vpm ) && vpm != NULL ) {
814915 X509_CRL_free (crl );
815- return NULL ;
916+ crl = NULL ;
917+ }
918+ if (crl == NULL ) {
919+ ERR_print_errors (bio_err );
920+ LOG (FL_ERR , "Unable to load %s from %s\n" , desc , uri != NULL ? uri : "<stdin>" );
816921 }
817922 return crl ;
818923}
@@ -828,20 +933,18 @@ STACK_OF(X509_CRL) *FILES_load_crls_ex(OPTIONAL OSSL_LIB_CTX *libctx, OPTIONAL c
828933
829934 if (desc == NULL )
830935 desc = "CRLs" ;
831- LOG (FL_DEBUG , "Loading %s from %s" , desc , srcs );
936+ if (!CONN_IS_HTTP (srcs )) /* well, this suppresses output also if only part of the srcs is HTTP-based */
937+ LOG (FL_DEBUG , "Loading %s from %s" , desc , srcs );
832938
833939 if (names == NULL || (all_crls = sk_X509_CRL_new_null ()) == NULL )
834940 goto oom ;
835941 for (src = UTIL_first_item (names ); src != NULL ; src = next ) {
836942 next = UTIL_next_item (src ); /* must do this here to split string */
837943
838- if (CONN_IS_HTTPS (src )) {
839- LOG (FL_ERR , "Loading %s over HTTPS is unsupported; uri=%s\n" , desc , src );
840- goto err ;
841- }
842944
843- if (CONN_IS_HTTP (src )) {
844- if ((crl = CONN_load_crl_http (src , timeout , 0 , desc )) == NULL )
945+ if (CONN_IS_HTTP (src ) || CONN_IS_HTTPS (src )) {
946+ if ((crl = FILES_load_crl_ex (libctx , propq , src , format , false,
947+ timeout , desc , vpm )) == NULL )
845948 goto err ;
846949 goto handle_crl ;
847950 } else {
0 commit comments