diff options
Diffstat (limited to 'Utilities/cmcurl/lib/vtls/rustls.c')
-rw-r--r-- | Utilities/cmcurl/lib/vtls/rustls.c | 163 |
1 files changed, 99 insertions, 64 deletions
diff --git a/Utilities/cmcurl/lib/vtls/rustls.c b/Utilities/cmcurl/lib/vtls/rustls.c index 77a49f1..27f4ec8 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 */ |