diff options
Diffstat (limited to 'Utilities/cmcurl/lib/vtls/bearssl.c')
-rw-r--r-- | Utilities/cmcurl/lib/vtls/bearssl.c | 142 |
1 files changed, 97 insertions, 45 deletions
diff --git a/Utilities/cmcurl/lib/vtls/bearssl.c b/Utilities/cmcurl/lib/vtls/bearssl.c index 7f72971..e87649e 100644 --- a/Utilities/cmcurl/lib/vtls/bearssl.c +++ b/Utilities/cmcurl/lib/vtls/bearssl.c @@ -68,6 +68,14 @@ struct cafile_parser { size_t dn_len; }; +#define CAFILE_SOURCE_PATH 1 +#define CAFILE_SOURCE_BLOB 2 +struct cafile_source { + const int type; + const char * const data; + const size_t len; +}; + static void append_dn(void *ctx, const void *buf, size_t len) { struct cafile_parser *ca = ctx; @@ -90,7 +98,8 @@ static void x509_push(void *ctx, const void *buf, size_t len) br_x509_decoder_push(&ca->xc, buf, len); } -static CURLcode load_cafile(const char *path, br_x509_trust_anchor **anchors, +static CURLcode load_cafile(struct cafile_source *source, + br_x509_trust_anchor **anchors, size_t *anchors_len) { struct cafile_parser ca; @@ -100,13 +109,22 @@ static CURLcode load_cafile(const char *path, br_x509_trust_anchor **anchors, br_x509_trust_anchor *new_anchors; size_t new_anchors_len; br_x509_pkey *pkey; - FILE *fp; - unsigned char buf[BUFSIZ], *p; + FILE *fp = 0; + unsigned char buf[BUFSIZ]; + const unsigned char *p; const char *name; size_t n, i, pushed; - fp = fopen(path, "rb"); - if(!fp) + DEBUGASSERT(source->type == CAFILE_SOURCE_PATH + || source->type == CAFILE_SOURCE_BLOB); + + if(source->type == CAFILE_SOURCE_PATH) { + fp = fopen(source->data, "rb"); + if(!fp) + return CURLE_SSL_CACERT_BADFILE; + } + + if(source->type == CAFILE_SOURCE_BLOB && source->len > (size_t)INT_MAX) return CURLE_SSL_CACERT_BADFILE; ca.err = CURLE_OK; @@ -115,11 +133,17 @@ static CURLcode load_cafile(const char *path, br_x509_trust_anchor **anchors, ca.anchors_len = 0; br_pem_decoder_init(&pc); br_pem_decoder_setdest(&pc, x509_push, &ca); - for(;;) { - n = fread(buf, 1, sizeof(buf), fp); - if(n == 0) - break; - p = buf; + do { + if(source->type == CAFILE_SOURCE_PATH) { + n = fread(buf, 1, sizeof(buf), fp); + if(n == 0) + break; + p = buf; + } + else if(source->type == CAFILE_SOURCE_BLOB) { + n = source->len; + p = (unsigned char *) source->data; + } while(n) { pushed = br_pem_decoder_push(&pc, p, n); if(ca.err) @@ -211,12 +235,13 @@ static CURLcode load_cafile(const char *path, br_x509_trust_anchor **anchors, goto fail; } } - } - if(ferror(fp)) + } while(source->type != CAFILE_SOURCE_BLOB); + if(fp && ferror(fp)) ca.err = CURLE_READ_ERROR; fail: - fclose(fp); + if(fp) + fclose(fp); if(ca.err == CURLE_OK) { *anchors = ca.anchors; *anchors_len = ca.anchors_len; @@ -299,8 +324,11 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data, { struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_backend_data *backend = connssl->backend; - const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); - const char * const hostname = SSL_HOST_NAME(); + const struct curl_blob *ca_info_blob = SSL_CONN_CONFIG(ca_info_blob); + const char * const ssl_cafile = + /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */ + (ca_info_blob ? NULL : SSL_CONN_CONFIG(CAfile)); + const char *hostname = SSL_HOST_NAME(); const bool verifypeer = SSL_CONN_CONFIG(verifypeer); const bool verifyhost = SSL_CONN_CONFIG(verifyhost); CURLcode ret; @@ -340,8 +368,30 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data, return CURLE_SSL_CONNECT_ERROR; } + if(ca_info_blob) { + struct cafile_source source = { + CAFILE_SOURCE_BLOB, + ca_info_blob->data, + ca_info_blob->len, + }; + ret = load_cafile(&source, &backend->anchors, &backend->anchors_len); + if(ret != CURLE_OK) { + if(verifypeer) { + failf(data, "error importing CA certificate blob"); + return ret; + } + /* Only warn if no certificate verification is required. */ + infof(data, "error importing CA certificate blob, continuing anyway"); + } + } + if(ssl_cafile) { - ret = load_cafile(ssl_cafile, &backend->anchors, &backend->anchors_len); + struct cafile_source source = { + CAFILE_SOURCE_PATH, + ssl_cafile, + 0, + }; + ret = load_cafile(&source, &backend->anchors, &backend->anchors_len); if(ret != CURLE_OK) { if(verifypeer) { failf(data, "error setting certificate verify locations." @@ -349,7 +399,7 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data, return ret; } infof(data, "error setting certificate verify locations," - " continuing anyway:\n"); + " continuing anyway:"); } } @@ -373,7 +423,7 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data, if(!Curl_ssl_getsessionid(data, conn, SSL_IS_PROXY() ? TRUE : FALSE, &session, NULL, sockindex)) { br_ssl_engine_set_session_parameters(&backend->ctx.eng, session); - infof(data, "BearSSL: re-using session ID\n"); + infof(data, "BearSSL: re-using session ID"); } Curl_ssl_sessionid_unlock(data); } @@ -392,12 +442,12 @@ static CURLcode bearssl_connect_step1(struct Curl_easy *data, #endif ) { backend->protocols[cur++] = ALPN_H2; - infof(data, "ALPN, offering %s\n", ALPN_H2); + infof(data, "ALPN, offering %s", ALPN_H2); } #endif backend->protocols[cur++] = ALPN_HTTP_1_1; - infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1); + infof(data, "ALPN, offering %s", ALPN_HTTP_1_1); br_ssl_engine_set_protocol_names(&backend->ctx.eng, backend->protocols, cur); @@ -538,7 +588,7 @@ static CURLcode bearssl_connect_step3(struct Curl_easy *data, protocol = br_ssl_engine_get_selected_protocol(&backend->ctx.eng); if(protocol) { - infof(data, "ALPN, server accepted to use %s\n", protocol); + infof(data, "ALPN, server accepted to use %s", protocol); #ifdef USE_HTTP2 if(!strcmp(protocol, ALPN_H2)) @@ -548,12 +598,12 @@ static CURLcode bearssl_connect_step3(struct Curl_easy *data, if(!strcmp(protocol, ALPN_HTTP_1_1)) conn->negnpn = CURL_HTTP_VERSION_1_1; else - infof(data, "ALPN, unrecognized protocol %s\n", protocol); + infof(data, "ALPN, unrecognized protocol %s", protocol); Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ? BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE); } else - infof(data, "ALPN, server did not agree to a protocol\n"); + infof(data, "ALPN, server did not agree to a protocol"); } if(SSL_SET_OPTION(primary.sessionid)) { @@ -840,30 +890,32 @@ static CURLcode bearssl_sha256sum(const unsigned char *input, } const struct Curl_ssl Curl_ssl_bearssl = { - { CURLSSLBACKEND_BEARSSL, "bearssl" }, - 0, + { CURLSSLBACKEND_BEARSSL, "bearssl" }, /* info */ + SSLSUPP_CAINFO_BLOB, sizeof(struct ssl_backend_data), - Curl_none_init, - Curl_none_cleanup, - bearssl_version, - Curl_none_check_cxn, - Curl_none_shutdown, - bearssl_data_pending, - bearssl_random, - Curl_none_cert_status_request, - bearssl_connect, - bearssl_connect_nonblocking, - Curl_ssl_getsock, - bearssl_get_internals, - bearssl_close, - Curl_none_close_all, - bearssl_session_free, - Curl_none_set_engine, - Curl_none_set_engine_default, - Curl_none_engines_list, - Curl_none_false_start, - bearssl_sha256sum + Curl_none_init, /* init */ + Curl_none_cleanup, /* cleanup */ + bearssl_version, /* version */ + Curl_none_check_cxn, /* check_cxn */ + Curl_none_shutdown, /* shutdown */ + bearssl_data_pending, /* data_pending */ + bearssl_random, /* random */ + Curl_none_cert_status_request, /* cert_status_request */ + bearssl_connect, /* connect */ + bearssl_connect_nonblocking, /* connect_nonblocking */ + Curl_ssl_getsock, /* getsock */ + bearssl_get_internals, /* get_internals */ + bearssl_close, /* close_one */ + Curl_none_close_all, /* close_all */ + bearssl_session_free, /* session_free */ + Curl_none_set_engine, /* set_engine */ + Curl_none_set_engine_default, /* set_engine_default */ + Curl_none_engines_list, /* engines_list */ + Curl_none_false_start, /* false_start */ + bearssl_sha256sum, /* sha256sum */ + NULL, /* associate_connection */ + NULL /* disassociate_connection */ }; #endif /* USE_BEARSSL */ |