diff options
author | Daniel Stenberg <daniel@haxx.se> | 2020-09-28 14:02:27 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2020-09-29 07:50:07 +0200 |
commit | edfb6168e9d3c7d3b0befc6977c2256c095a6690 (patch) | |
tree | 1617aa4616228e1bc70accb7f14dac9817ba8d20 | |
parent | 82d66f15825b2a088ba9302e2917e0548b1fe75f (diff) | |
download | curl-edfb6168e9d3c7d3b0befc6977c2256c095a6690.tar.gz |
libssh2: handle the SSH protocols done over HTTPS proxy
Reported-by: Robin Douine
Fixes #4295
Closes #6021
-rw-r--r-- | lib/vssh/libssh2.c | 91 |
1 files changed, 83 insertions, 8 deletions
diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c index c90d6367f..d983cc9a9 100644 --- a/lib/vssh/libssh2.c +++ b/lib/vssh/libssh2.c @@ -3039,6 +3039,42 @@ static CURLcode ssh_setup_connection(struct connectdata *conn) static Curl_recv scp_recv, sftp_recv; static Curl_send scp_send, sftp_send; +static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer, + size_t length, int flags, void **abstract) +{ + struct connectdata *conn = (struct connectdata *)*abstract; + ssize_t nread; + CURLcode result; + (void)flags; + + result = Curl_read(conn, sock, buffer, length, &nread); + if(result == CURLE_AGAIN) + return -EAGAIN; /* magic return code for libssh2 */ + else if(result) + return -1; /* generic error */ + if(conn->data->set.verbose) + Curl_debug(conn->data, CURLINFO_DATA_IN, (char *)buffer, (size_t)nread); + return nread; +} + +static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer, + size_t length, int flags, void **abstract) +{ + struct connectdata *conn = (struct connectdata *)*abstract; + ssize_t nwrite; + CURLcode result; + (void)flags; + + result = Curl_write(conn, sock, buffer, length, &nwrite); + if(result == CURLE_AGAIN) + return -EAGAIN; /* magic return code for libssh2 */ + else if(result) + return -1; /* error */ + if(conn->data->set.verbose) + Curl_debug(conn->data, CURLINFO_DATA_OUT, (char *)buffer, (size_t)nwrite); + return nwrite; +} + /* * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to * do protocol-specific actions at connect-time. @@ -3060,14 +3096,6 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done) function to make the re-use checks properly be able to check this bit. */ connkeep(conn, "SSH default"); - if(conn->handler->protocol & CURLPROTO_SCP) { - conn->recv[FIRSTSOCKET] = scp_recv; - conn->send[FIRSTSOCKET] = scp_send; - } - else { - conn->recv[FIRSTSOCKET] = sftp_recv; - conn->send[FIRSTSOCKET] = sftp_send; - } ssh = &conn->proto.sshc; #ifdef CURL_LIBSSH2_DEBUG @@ -3088,6 +3116,53 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done) return CURLE_FAILED_INIT; } + if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) { + /* + * This crazy union dance is here to avoid assigning a void pointer a + * function pointer as it is invalid C. The problem is of course that + * libssh2 has such an API... + */ + union receive { + void *recvp; + ssize_t (*recvptr)(libssh2_socket_t, void *, size_t, int, void **); + }; + union transfer { + void *sendp; + ssize_t (*sendptr)(libssh2_socket_t, const void *, size_t, int, void **); + }; + union receive sshrecv; + union transfer sshsend; + + sshrecv.recvptr = ssh_tls_recv; + sshsend.sendptr = ssh_tls_send; + + infof(data, "Uses HTTPS proxy!\n"); + /* + Setup libssh2 callbacks to make it read/write TLS from the socket. + + ssize_t + recvcb(libssh2_socket_t sock, void *buffer, size_t length, + int flags, void **abstract); + + ssize_t + sendcb(libssh2_socket_t sock, const void *buffer, size_t length, + int flags, void **abstract); + + */ + libssh2_session_callback_set(ssh->ssh_session, + LIBSSH2_CALLBACK_RECV, sshrecv.recvp); + libssh2_session_callback_set(ssh->ssh_session, + LIBSSH2_CALLBACK_SEND, sshsend.sendp); + } + else if(conn->handler->protocol & CURLPROTO_SCP) { + conn->recv[FIRSTSOCKET] = scp_recv; + conn->send[FIRSTSOCKET] = scp_send; + } + else { + conn->recv[FIRSTSOCKET] = sftp_recv; + conn->send[FIRSTSOCKET] = sftp_send; + } + if(data->set.ssh_compression) { #if LIBSSH2_VERSION_NUM >= 0x010208 if(libssh2_session_flag(ssh->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0) |