summaryrefslogtreecommitdiffstats
path: root/Utilities/cmcurl/lib/vtls/bearssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmcurl/lib/vtls/bearssl.c')
-rw-r--r--Utilities/cmcurl/lib/vtls/bearssl.c142
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 */