summaryrefslogtreecommitdiff
path: root/Utilities/cmcurl/lib/vtls/rustls.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmcurl/lib/vtls/rustls.c')
-rw-r--r--Utilities/cmcurl/lib/vtls/rustls.c163
1 files changed, 99 insertions, 64 deletions
diff --git a/Utilities/cmcurl/lib/vtls/rustls.c b/Utilities/cmcurl/lib/vtls/rustls.c
index 77a49f1ab4..27f4ec8d8c 100644
--- a/Utilities/cmcurl/lib/vtls/rustls.c
+++ b/Utilities/cmcurl/lib/vtls/rustls.c
@@ -35,6 +35,7 @@
#include "urldata.h"
#include "sendf.h"
#include "vtls.h"
+#include "vtls_int.h"
#include "select.h"
#include "strerror.h"
#include "multiif.h"
@@ -63,43 +64,64 @@ static CURLcode map_error(rustls_result r)
}
static bool
-cr_data_pending(const struct connectdata *conn, int sockindex)
+cr_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data)
{
- const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
- struct ssl_backend_data *backend = connssl->backend;
- DEBUGASSERT(backend);
- return backend->data_pending;
+ struct ssl_connect_data *ctx = cf->ctx;
+
+ (void)data;
+ DEBUGASSERT(ctx && ctx->backend);
+ return ctx->backend->data_pending;
}
static CURLcode
-cr_connect(struct Curl_easy *data UNUSED_PARAM,
- struct connectdata *conn UNUSED_PARAM,
- int sockindex UNUSED_PARAM)
+cr_connect(struct Curl_cfilter *cf UNUSED_PARAM,
+ struct Curl_easy *data UNUSED_PARAM)
{
infof(data, "rustls_connect: unimplemented");
return CURLE_SSL_CONNECT_ERROR;
}
+struct io_ctx {
+ struct Curl_cfilter *cf;
+ struct Curl_easy *data;
+};
+
static int
read_cb(void *userdata, uint8_t *buf, uintptr_t len, uintptr_t *out_n)
{
- ssize_t n = sread(*(int *)userdata, buf, len);
- if(n < 0) {
- return SOCKERRNO;
+ struct io_ctx *io_ctx = userdata;
+ CURLcode result;
+ int ret = 0;
+ ssize_t nread = Curl_conn_cf_recv(io_ctx->cf->next, io_ctx->data,
+ (char *)buf, len, &result);
+ if(nread < 0) {
+ nread = 0;
+ if(CURLE_AGAIN == result)
+ ret = EAGAIN;
+ else
+ ret = EINVAL;
}
- *out_n = n;
- return 0;
+ *out_n = (int)nread;
+ return ret;
}
static int
write_cb(void *userdata, const uint8_t *buf, uintptr_t len, uintptr_t *out_n)
{
- ssize_t n = swrite(*(int *)userdata, buf, len);
- if(n < 0) {
- return SOCKERRNO;
+ struct io_ctx *io_ctx = userdata;
+ CURLcode result;
+ int ret = 0;
+ ssize_t nwritten = Curl_conn_cf_send(io_ctx->cf->next, io_ctx->data,
+ (const char *)buf, len, &result);
+ if(nwritten < 0) {
+ nwritten = 0;
+ if(CURLE_AGAIN == result)
+ ret = EAGAIN;
+ else
+ ret = EINVAL;
}
- *out_n = n;
- return 0;
+ *out_n = (int)nwritten;
+ return ret;
}
/*
@@ -115,13 +137,13 @@ write_cb(void *userdata, const uint8_t *buf, uintptr_t len, uintptr_t *out_n)
* output buffer.
*/
static ssize_t
-cr_recv(struct Curl_easy *data, int sockindex,
+cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
char *plainbuf, size_t plainlen, CURLcode *err)
{
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *const connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *const connssl = cf->ctx;
struct ssl_backend_data *const backend = connssl->backend;
struct rustls_connection *rconn = NULL;
+ struct io_ctx io_ctx;
size_t n = 0;
size_t tls_bytes_read = 0;
@@ -133,10 +155,13 @@ cr_recv(struct Curl_easy *data, int sockindex,
DEBUGASSERT(backend);
rconn = backend->conn;
- io_error = rustls_connection_read_tls(rconn, read_cb,
- &conn->sock[sockindex], &tls_bytes_read);
+ io_ctx.cf = cf;
+ io_ctx.data = data;
+
+ io_error = rustls_connection_read_tls(rconn, read_cb, &io_ctx,
+ &tls_bytes_read);
if(io_error == EAGAIN || io_error == EWOULDBLOCK) {
- infof(data, "sread: EAGAIN or EWOULDBLOCK");
+ infof(data, CFMSG(cf, "cr_recv: EAGAIN or EWOULDBLOCK"));
}
else if(io_error) {
char buffer[STRERROR_LEN];
@@ -146,7 +171,7 @@ cr_recv(struct Curl_easy *data, int sockindex,
return -1;
}
- infof(data, "cr_recv read %ld bytes from the network", tls_bytes_read);
+ infof(data, CFMSG(cf, "cr_recv: read %ld TLS bytes"), tls_bytes_read);
rresult = rustls_connection_process_new_packets(rconn);
if(rresult != RUSTLS_RESULT_OK) {
@@ -164,7 +189,8 @@ cr_recv(struct Curl_easy *data, int sockindex,
plainlen - plain_bytes_copied,
&n);
if(rresult == RUSTLS_RESULT_PLAINTEXT_EMPTY) {
- infof(data, "cr_recv got PLAINTEXT_EMPTY. will try again later.");
+ infof(data, CFMSG(cf, "cr_recv: got PLAINTEXT_EMPTY. "
+ "will try again later."));
backend->data_pending = FALSE;
break;
}
@@ -181,7 +207,7 @@ cr_recv(struct Curl_easy *data, int sockindex,
break;
}
else {
- infof(data, "cr_recv copied out %ld bytes of plaintext", n);
+ infof(data, CFMSG(cf, "cr_recv: got %ld plain bytes"), n);
plain_bytes_copied += n;
}
}
@@ -216,13 +242,13 @@ cr_recv(struct Curl_easy *data, int sockindex,
* It will only drain rustls' plaintext output buffer into the socket.
*/
static ssize_t
-cr_send(struct Curl_easy *data, int sockindex,
+cr_send(struct Curl_cfilter *cf, struct Curl_easy *data,
const void *plainbuf, size_t plainlen, CURLcode *err)
{
- struct connectdata *conn = data->conn;
- struct ssl_connect_data *const connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *const connssl = cf->ctx;
struct ssl_backend_data *const backend = connssl->backend;
struct rustls_connection *rconn = NULL;
+ struct io_ctx io_ctx;
size_t plainwritten = 0;
size_t tlswritten = 0;
size_t tlswritten_total = 0;
@@ -232,7 +258,7 @@ cr_send(struct Curl_easy *data, int sockindex,
DEBUGASSERT(backend);
rconn = backend->conn;
- infof(data, "cr_send %ld bytes of plaintext", plainlen);
+ infof(data, CFMSG(cf, "cr_send: %ld plain bytes"), plainlen);
if(plainlen > 0) {
rresult = rustls_connection_write(rconn, plainbuf, plainlen,
@@ -249,11 +275,15 @@ cr_send(struct Curl_easy *data, int sockindex,
}
}
+ io_ctx.cf = cf;
+ io_ctx.data = data;
+
while(rustls_connection_wants_write(rconn)) {
- io_error = rustls_connection_write_tls(rconn, write_cb,
- &conn->sock[sockindex], &tlswritten);
+ io_error = rustls_connection_write_tls(rconn, write_cb, &io_ctx,
+ &tlswritten);
if(io_error == EAGAIN || io_error == EWOULDBLOCK) {
- infof(data, "swrite: EAGAIN after %ld bytes", tlswritten_total);
+ infof(data, CFMSG(cf, "cr_send: EAGAIN after %ld bytes"),
+ tlswritten_total);
*err = CURLE_AGAIN;
return -1;
}
@@ -269,7 +299,7 @@ cr_send(struct Curl_easy *data, int sockindex,
*err = CURLE_WRITE_ERROR;
return -1;
}
- infof(data, "cr_send wrote %ld bytes to network", tlswritten);
+ infof(data, CFMSG(cf, "cr_send: wrote %ld TLS bytes"), tlswritten);
tlswritten_total += tlswritten;
}
@@ -302,18 +332,20 @@ cr_hostname_is_ip(const char *hostname)
}
static CURLcode
-cr_init_backend(struct Curl_easy *data, struct connectdata *conn,
+cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data,
struct ssl_backend_data *const backend)
{
+ struct ssl_connect_data *connssl = cf->ctx;
+ struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
struct rustls_connection *rconn = NULL;
struct rustls_client_config_builder *config_builder = NULL;
struct rustls_root_cert_store *roots = NULL;
- const struct curl_blob *ca_info_blob = SSL_CONN_CONFIG(ca_info_blob);
+ const struct curl_blob *ca_info_blob = 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 bool verifypeer = SSL_CONN_CONFIG(verifypeer);
- const char *hostname = conn->host.name;
+ (ca_info_blob ? NULL : conn_config->CAfile);
+ const bool verifypeer = conn_config->verifypeer;
+ const char *hostname = connssl->hostname;
char errorbuf[256];
size_t errorlen;
int result;
@@ -400,7 +432,7 @@ cr_init_backend(struct Curl_easy *data, struct connectdata *conn,
}
static void
-cr_set_negotiated_alpn(struct Curl_easy *data, struct connectdata *conn,
+cr_set_negotiated_alpn(struct Curl_cfilter *cf, struct Curl_easy *data,
const struct rustls_connection *rconn)
{
const uint8_t *protocol = NULL;
@@ -415,29 +447,29 @@ cr_set_negotiated_alpn(struct Curl_easy *data, struct connectdata *conn,
#ifdef USE_HTTP2
if(len == ALPN_H2_LENGTH && 0 == memcmp(ALPN_H2, protocol, len)) {
infof(data, VTLS_INFOF_ALPN_ACCEPTED_1STR, ALPN_H2);
- conn->alpn = CURL_HTTP_VERSION_2;
+ cf->conn->alpn = CURL_HTTP_VERSION_2;
}
else
#endif
if(len == ALPN_HTTP_1_1_LENGTH &&
0 == memcmp(ALPN_HTTP_1_1, protocol, len)) {
infof(data, VTLS_INFOF_ALPN_ACCEPTED_1STR, ALPN_HTTP_1_1);
- conn->alpn = CURL_HTTP_VERSION_1_1;
+ cf->conn->alpn = CURL_HTTP_VERSION_1_1;
}
else {
infof(data, "ALPN, negotiated an unrecognized protocol");
}
- Curl_multiuse_state(data, conn->alpn == CURL_HTTP_VERSION_2 ?
+ Curl_multiuse_state(data, cf->conn->alpn == CURL_HTTP_VERSION_2 ?
BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
}
static CURLcode
-cr_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
- int sockindex, bool *done)
+cr_connect_nonblocking(struct Curl_cfilter *cf,
+ struct Curl_easy *data, bool *done)
{
- struct ssl_connect_data *const connssl = &conn->ssl[sockindex];
- curl_socket_t sockfd = conn->sock[sockindex];
+ struct ssl_connect_data *const connssl = cf->ctx;
+ curl_socket_t sockfd = cf->conn->sock[cf->sockindex];
struct ssl_backend_data *const backend = connssl->backend;
struct rustls_connection *rconn = NULL;
CURLcode tmperr = CURLE_OK;
@@ -451,7 +483,7 @@ cr_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
DEBUGASSERT(backend);
if(ssl_connection_none == connssl->state) {
- result = cr_init_backend(data, conn, connssl->backend);
+ result = cr_init_backend(cf, data, connssl->backend);
if(result != CURLE_OK) {
return result;
}
@@ -471,10 +503,8 @@ cr_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
/* Done with the handshake. Set up callbacks to send/receive data. */
connssl->state = ssl_connection_complete;
- cr_set_negotiated_alpn(data, conn, rconn);
+ cr_set_negotiated_alpn(cf, data, rconn);
- conn->recv[sockindex] = cr_recv;
- conn->send[sockindex] = cr_send;
*done = TRUE;
return CURLE_OK;
}
@@ -502,7 +532,7 @@ cr_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
if(wants_write) {
infof(data, "rustls_connection wants us to write_tls.");
- cr_send(data, sockindex, NULL, 0, &tmperr);
+ cr_send(cf, data, NULL, 0, &tmperr);
if(tmperr == CURLE_AGAIN) {
infof(data, "writing would block");
/* fall through */
@@ -515,7 +545,7 @@ cr_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
if(wants_read) {
infof(data, "rustls_connection wants us to read_tls.");
- cr_recv(data, sockindex, NULL, 0, &tmperr);
+ cr_recv(cf, data, NULL, 0, &tmperr);
if(tmperr == CURLE_AGAIN) {
infof(data, "reading would block");
/* fall through */
@@ -539,13 +569,15 @@ cr_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
/* returns a bitmap of flags for this connection's first socket indicating
whether we want to read or write */
static int
-cr_getsock(struct connectdata *conn, curl_socket_t *socks)
+cr_get_select_socks(struct Curl_cfilter *cf, struct Curl_easy *data,
+ curl_socket_t *socks)
{
- struct ssl_connect_data *const connssl = &conn->ssl[FIRSTSOCKET];
- curl_socket_t sockfd = conn->sock[FIRSTSOCKET];
+ struct ssl_connect_data *const connssl = cf->ctx;
+ curl_socket_t sockfd = cf->conn->sock[cf->sockindex];
struct ssl_backend_data *const backend = connssl->backend;
struct rustls_connection *rconn = NULL;
+ (void)data;
DEBUGASSERT(backend);
rconn = backend->conn;
@@ -571,10 +603,9 @@ cr_get_internals(struct ssl_connect_data *connssl,
}
static void
-cr_close(struct Curl_easy *data, struct connectdata *conn,
- int sockindex)
+cr_close(struct Curl_cfilter *cf, struct Curl_easy *data)
{
- struct ssl_connect_data *connssl = &conn->ssl[sockindex];
+ struct ssl_connect_data *connssl = cf->ctx;
struct ssl_backend_data *backend = connssl->backend;
CURLcode tmperr = CURLE_OK;
ssize_t n = 0;
@@ -583,7 +614,7 @@ cr_close(struct Curl_easy *data, struct connectdata *conn,
if(backend->conn) {
rustls_connection_send_close_notify(backend->conn);
- n = cr_send(data, sockindex, NULL, 0, &tmperr);
+ n = cr_send(cf, data, NULL, 0, &tmperr);
if(n < 0) {
failf(data, "error sending close notify: %d", tmperr);
}
@@ -606,7 +637,8 @@ static size_t cr_version(char *buffer, size_t size)
const struct Curl_ssl Curl_ssl_rustls = {
{ CURLSSLBACKEND_RUSTLS, "rustls" },
SSLSUPP_CAINFO_BLOB | /* supports */
- SSLSUPP_TLS13_CIPHERSUITES,
+ SSLSUPP_TLS13_CIPHERSUITES |
+ SSLSUPP_HTTPS_PROXY,
sizeof(struct ssl_backend_data),
Curl_none_init, /* init */
@@ -619,7 +651,7 @@ const struct Curl_ssl Curl_ssl_rustls = {
Curl_none_cert_status_request, /* cert_status_request */
cr_connect, /* connect */
cr_connect_nonblocking, /* connect_nonblocking */
- cr_getsock, /* cr_getsock */
+ cr_get_select_socks, /* get_select_socks */
cr_get_internals, /* get_internals */
cr_close, /* close_one */
Curl_none_close_all, /* close_all */
@@ -630,7 +662,10 @@ const struct Curl_ssl Curl_ssl_rustls = {
Curl_none_false_start, /* false_start */
NULL, /* sha256sum */
NULL, /* associate_connection */
- NULL /* disassociate_connection */
+ NULL, /* disassociate_connection */
+ NULL, /* free_multi_ssl_backend_data */
+ cr_recv, /* recv decrypted data */
+ cr_send, /* send data to encrypt */
};
#endif /* USE_RUSTLS */