summaryrefslogtreecommitdiff
path: root/libs/libcurl/src/vtls/bearssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libcurl/src/vtls/bearssl.c')
-rw-r--r--libs/libcurl/src/vtls/bearssl.c90
1 files changed, 57 insertions, 33 deletions
diff --git a/libs/libcurl/src/vtls/bearssl.c b/libs/libcurl/src/vtls/bearssl.c
index f5f6ad3756..fdbb4f648a 100644
--- a/libs/libcurl/src/vtls/bearssl.c
+++ b/libs/libcurl/src/vtls/bearssl.c
@@ -63,6 +63,7 @@ struct bearssl_ssl_backend_data {
bool active;
/* size of pending write, yet to be flushed */
size_t pending_write;
+ BIT(sent_shutdown);
};
struct cafile_parser {
@@ -327,7 +328,7 @@ static unsigned x509_end_chain(const br_x509_class **ctx)
struct x509_context *x509 = (struct x509_context *)ctx;
if(!x509->verifypeer) {
- return br_x509_decoder_last_error(&x509->decoder);
+ return (unsigned)br_x509_decoder_last_error(&x509->decoder);
}
return x509->minimal.vtable->end_chain(&x509->minimal.vtable);
@@ -583,7 +584,7 @@ static CURLcode bearssl_connect_step1(struct Curl_cfilter *cf,
backend->x509.verifyhost = verifyhost;
br_ssl_engine_set_x509(&backend->ctx.eng, &backend->x509.vtable);
- if(ssl_config->primary.sessionid) {
+ if(ssl_config->primary.cache_session) {
void *session;
CURL_TRC_CF(data, cf, "connect_step1, check session cache");
@@ -722,6 +723,8 @@ static CURLcode bearssl_run_until(struct Curl_cfilter *cf,
ret = Curl_conn_cf_send(cf->next, data, (char *)buf, len, &result);
CURL_TRC_CF(data, cf, "ssl_send(len=%zu) -> %zd, %d", len, ret, result);
if(ret <= 0) {
+ if(result == CURLE_AGAIN)
+ connssl->io_need |= CURL_SSL_IO_NEED_SEND;
return result;
}
br_ssl_engine_sendrec_ack(&backend->ctx.eng, ret);
@@ -735,6 +738,8 @@ static CURLcode bearssl_run_until(struct Curl_cfilter *cf,
return CURLE_RECV_ERROR;
}
if(ret <= 0) {
+ if(result == CURLE_AGAIN)
+ connssl->io_need |= CURL_SSL_IO_NEED_RECV;
return result;
}
br_ssl_engine_recvrec_ack(&backend->ctx.eng, ret);
@@ -813,9 +818,7 @@ static CURLcode bearssl_connect_step3(struct Curl_cfilter *cf,
proto? strlen(proto) : 0);
}
- if(ssl_config->primary.sessionid) {
- bool incache;
- void *oldsession;
+ if(ssl_config->primary.cache_session) {
br_ssl_session_parameters *session;
session = malloc(sizeof(*session));
@@ -823,13 +826,8 @@ static CURLcode bearssl_connect_step3(struct Curl_cfilter *cf,
return CURLE_OUT_OF_MEMORY;
br_ssl_engine_get_session_parameters(&backend->ctx.eng, session);
Curl_ssl_sessionid_lock(data);
- incache = !(Curl_ssl_getsessionid(cf, data, &connssl->peer,
- &oldsession, NULL));
- if(incache)
- Curl_ssl_delsessionid(data, oldsession);
-
- ret = Curl_ssl_addsessionid(cf, data, &connssl->peer, session, 0,
- bearssl_session_free);
+ ret = Curl_ssl_set_sessionid(cf, data, &connssl->peer, session, 0,
+ bearssl_session_free);
Curl_ssl_sessionid_unlock(data);
if(ret)
return ret;
@@ -925,9 +923,7 @@ static CURLcode bearssl_connect_common(struct Curl_cfilter *cf,
return ret;
}
- while(ssl_connect_2 == connssl->connecting_state ||
- ssl_connect_2_reading == connssl->connecting_state ||
- ssl_connect_2_writing == connssl->connecting_state) {
+ while(ssl_connect_2 == connssl->connecting_state) {
/* check allowed time left */
timeout_ms = Curl_timeleft(data, NULL, TRUE);
@@ -937,14 +933,13 @@ static CURLcode bearssl_connect_common(struct Curl_cfilter *cf,
return CURLE_OPERATION_TIMEDOUT;
}
- /* if ssl is expecting something, check if it's available. */
- if(ssl_connect_2_reading == connssl->connecting_state ||
- ssl_connect_2_writing == connssl->connecting_state) {
+ /* if ssl is expecting something, check if it is available. */
+ if(connssl->io_need) {
- curl_socket_t writefd = ssl_connect_2_writing ==
- connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
- curl_socket_t readfd = ssl_connect_2_reading ==
- connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
+ curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND)?
+ sockfd:CURL_SOCKET_BAD;
+ curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV)?
+ sockfd:CURL_SOCKET_BAD;
CURL_TRC_CF(data, cf, "connect_common, check socket");
what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
@@ -975,11 +970,9 @@ static CURLcode bearssl_connect_common(struct Curl_cfilter *cf,
* before step2 has completed while ensuring that a client using select()
* or epoll() will always have a valid fdset to wait on.
*/
+ connssl->io_need = CURL_SSL_IO_NEED_NONE;
ret = bearssl_connect_step2(cf, data);
- if(ret || (nonblocking &&
- (ssl_connect_2 == connssl->connecting_state ||
- ssl_connect_2_reading == connssl->connecting_state ||
- ssl_connect_2_writing == connssl->connecting_state)))
+ if(ret || (nonblocking && (ssl_connect_2 == connssl->connecting_state)))
return ret;
}
@@ -1070,20 +1063,52 @@ static void *bearssl_get_internals(struct ssl_connect_data *connssl,
return &backend->ctx;
}
-static void bearssl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
+static CURLcode bearssl_shutdown(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ bool send_shutdown, bool *done)
{
struct ssl_connect_data *connssl = cf->ctx;
struct bearssl_ssl_backend_data *backend =
(struct bearssl_ssl_backend_data *)connssl->backend;
- size_t i;
+ CURLcode result;
DEBUGASSERT(backend);
+ if(!backend->active || cf->shutdown) {
+ *done = TRUE;
+ return CURLE_OK;
+ }
- if(backend->active) {
- backend->active = FALSE;
+ *done = FALSE;
+ if(!backend->sent_shutdown) {
+ (void)send_shutdown; /* unknown how to suppress our close notify */
br_ssl_engine_close(&backend->ctx.eng);
- (void)bearssl_run_until(cf, data, BR_SSL_CLOSED);
+ backend->sent_shutdown = TRUE;
+ }
+
+ result = bearssl_run_until(cf, data, BR_SSL_CLOSED);
+ if(result == CURLE_OK) {
+ *done = TRUE;
}
+ else if(result == CURLE_AGAIN)
+ result = CURLE_OK;
+ else
+ CURL_TRC_CF(data, cf, "shutdown error: %d", result);
+
+ cf->shutdown = (result || *done);
+ return result;
+}
+
+static void bearssl_close(struct Curl_cfilter *cf, struct Curl_easy *data)
+{
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct bearssl_ssl_backend_data *backend =
+ (struct bearssl_ssl_backend_data *)connssl->backend;
+ size_t i;
+
+ (void)data;
+ DEBUGASSERT(backend);
+
+ backend->active = FALSE;
if(backend->anchors) {
for(i = 0; i < backend->anchors_len; ++i)
free(backend->anchors[i].dn.data);
@@ -1113,7 +1138,7 @@ const struct Curl_ssl Curl_ssl_bearssl = {
Curl_none_cleanup, /* cleanup */
bearssl_version, /* version */
Curl_none_check_cxn, /* check_cxn */
- Curl_none_shutdown, /* shutdown */
+ bearssl_shutdown, /* shutdown */
bearssl_data_pending, /* data_pending */
bearssl_random, /* random */
Curl_none_cert_status_request, /* cert_status_request */
@@ -1130,7 +1155,6 @@ const struct Curl_ssl Curl_ssl_bearssl = {
bearssl_sha256sum, /* sha256sum */
NULL, /* associate_connection */
NULL, /* disassociate_connection */
- NULL, /* free_multi_ssl_backend_data */
bearssl_recv, /* recv decrypted data */
bearssl_send, /* send data to encrypt */
};