mirror of
https://github.com/curl/curl.git
synced 2026-07-28 01:33:11 +03:00
lib: connection filters (cfilter) addition to curl:
- general construct/destroy in connectdata - default implementations of callback functions - connect: cfilters for connect and accept - socks: cfilter for socks proxying - http_proxy: cfilter for http proxy tunneling - vtls: cfilters for primary and proxy ssl - change in general handling of data/conn - Curl_cfilter_setup() sets up filter chain based on data settings, if none are installed by the protocol handler setup - Curl_cfilter_connect() boot straps filters into `connected` status, used by handlers and multi to reach further stages - Curl_cfilter_is_connected() to check if a conn is connected, e.g. all filters have done their work - Curl_cfilter_get_select_socks() gets the sockets and READ/WRITE indicators for multi select to work - Curl_cfilter_data_pending() asks filters if the have incoming data pending for recv - Curl_cfilter_recv()/Curl_cfilter_send are the general callbacks installed in conn->recv/conn->send for io handling - Curl_cfilter_attach_data()/Curl_cfilter_detach_data() inform filters and addition/removal of a `data` from their connection - adding vtl functions to prevent use of Curl_ssl globals directly in other parts of the code. Reviewed-by: Daniel Stenberg Closes #9855
This commit is contained in:
parent
89ee5cfb38
commit
dafdb20a26
49 changed files with 3325 additions and 1969 deletions
|
|
@ -74,6 +74,7 @@ LIB_VTLS_HFILES = \
|
|||
vtls/schannel.h \
|
||||
vtls/sectransp.h \
|
||||
vtls/vtls.h \
|
||||
vtls/vtls_int.h \
|
||||
vtls/wolfssl.h \
|
||||
vtls/x509asn1.h
|
||||
|
||||
|
|
@ -105,6 +106,7 @@ LIB_CFILES = \
|
|||
base64.c \
|
||||
bufref.c \
|
||||
c-hyper.c \
|
||||
cfilters.c \
|
||||
conncache.c \
|
||||
connect.c \
|
||||
content_encoding.c \
|
||||
|
|
@ -227,6 +229,7 @@ LIB_HFILES = \
|
|||
asyn.h \
|
||||
bufref.h \
|
||||
c-hyper.h \
|
||||
cfilters.h \
|
||||
conncache.h \
|
||||
connect.h \
|
||||
content_encoding.h \
|
||||
|
|
|
|||
435
lib/cfilters.c
Normal file
435
lib/cfilters.c
Normal file
|
|
@ -0,0 +1,435 @@
|
|||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
#include "curl_setup.h"
|
||||
|
||||
#include "urldata.h"
|
||||
#include "strerror.h"
|
||||
#include "cfilters.h"
|
||||
#include "connect.h"
|
||||
#include "url.h" /* for Curl_safefree() */
|
||||
#include "sendf.h"
|
||||
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
|
||||
#include "multiif.h"
|
||||
#include "progress.h"
|
||||
#include "warnless.h"
|
||||
#include "http_proxy.h"
|
||||
#include "socks.h"
|
||||
#include "vtls/vtls.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
#ifndef ARRAYSIZE
|
||||
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
||||
#endif
|
||||
|
||||
#ifdef DEBUGBUILD
|
||||
static void cf_debug(struct Curl_easy *data, const char *fname,
|
||||
struct connectdata *conn, int index, CURLcode result)
|
||||
{
|
||||
struct Curl_cfilter *cf;
|
||||
char chain[128];
|
||||
size_t offset = 0, len;
|
||||
|
||||
for(cf = conn->cfilter[index]; cf; cf = cf->next) {
|
||||
len = strlen(cf->cft->name);
|
||||
if(offset + len + 2 > sizeof(chain))
|
||||
break;
|
||||
if(offset) {
|
||||
chain[offset++] = '.';
|
||||
}
|
||||
strcpy(chain + offset, cf->cft->name);
|
||||
offset += len;
|
||||
}
|
||||
chain[offset] = 0;
|
||||
infof(data, "%s(handle=%p, cfilter%d=[%s]) -> %d",
|
||||
fname, data, index, chain, result);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void Curl_cf_def_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
{
|
||||
(void)cf;
|
||||
(void)data;
|
||||
}
|
||||
|
||||
CURLcode Curl_cf_def_setup(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
const struct Curl_dns_entry *remotehost)
|
||||
{
|
||||
DEBUGASSERT(cf->next);
|
||||
return cf->next->cft->setup(cf->next, data, remotehost);
|
||||
}
|
||||
|
||||
void Curl_cf_def_attach_data(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
(void)cf;
|
||||
(void)data;
|
||||
}
|
||||
|
||||
void Curl_cf_def_detach_data(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
(void)cf;
|
||||
(void)data;
|
||||
}
|
||||
|
||||
void Curl_cf_def_close(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
{
|
||||
DEBUGASSERT(cf->next);
|
||||
cf->connected = FALSE;
|
||||
cf->next->cft->close(cf->next, data);
|
||||
}
|
||||
|
||||
CURLcode Curl_cf_def_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
{
|
||||
DEBUGASSERT(cf->next);
|
||||
return cf->next->cft->connect(cf->next, data, blocking, done);
|
||||
}
|
||||
|
||||
int Curl_cf_def_get_select_socks(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
curl_socket_t *socks)
|
||||
{
|
||||
DEBUGASSERT(cf->next);
|
||||
return cf->next->cft->get_select_socks(cf->next, data, socks);
|
||||
}
|
||||
|
||||
bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
|
||||
const struct Curl_easy *data)
|
||||
{
|
||||
DEBUGASSERT(cf->next);
|
||||
return cf->next->cft->has_data_pending(cf->next, data);
|
||||
}
|
||||
|
||||
ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
const void *buf, size_t len, CURLcode *err)
|
||||
{
|
||||
DEBUGASSERT(cf->next);
|
||||
return cf->next->cft->do_send(cf->next, data, buf, len, err);
|
||||
}
|
||||
|
||||
ssize_t Curl_cf_def_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
char *buf, size_t len, CURLcode *err)
|
||||
{
|
||||
DEBUGASSERT(cf->next);
|
||||
return cf->next->cft->do_recv(cf->next, data, buf, len, err);
|
||||
}
|
||||
|
||||
void Curl_cfilter_destroy(struct Curl_easy *data,
|
||||
struct connectdata *conn, int index)
|
||||
{
|
||||
struct Curl_cfilter *cfn, *cf = conn->cfilter[index];
|
||||
|
||||
if(cf) {
|
||||
DEBUGF(infof(data, "Curl_cfilter_destroy(handle=%p, connection=%ld, "
|
||||
"index=%d)", data, conn->connection_id, index));
|
||||
conn->cfilter[index] = NULL;
|
||||
while(cf) {
|
||||
cfn = cf->next;
|
||||
cf->cft->destroy(cf, data);
|
||||
free(cf);
|
||||
cf = cfn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Curl_cfilter_close(struct Curl_easy *data,
|
||||
struct connectdata *conn, int index)
|
||||
{
|
||||
struct Curl_cfilter *cf;
|
||||
|
||||
DEBUGASSERT(conn);
|
||||
/* it is valid to call that without filters being present */
|
||||
cf = conn->cfilter[index];
|
||||
if(cf) {
|
||||
DEBUGF(infof(data, "Curl_cfilter_close(handle=%p, index=%d)",
|
||||
data, index));
|
||||
cf->cft->close(cf, data);
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t Curl_cfilter_recv(struct Curl_easy *data, int num, char *buf,
|
||||
size_t len, CURLcode *code)
|
||||
{
|
||||
struct Curl_cfilter *cf;
|
||||
ssize_t nread;
|
||||
|
||||
DEBUGASSERT(data);
|
||||
DEBUGASSERT(data->conn);
|
||||
cf = data->conn->cfilter[num];
|
||||
while(cf && !cf->connected) {
|
||||
cf = cf->next;
|
||||
}
|
||||
if(cf) {
|
||||
nread = cf->cft->do_recv(cf, data, buf, len, code);
|
||||
/* DEBUGF(infof(data, "Curl_cfilter_recv(handle=%p, index=%d)"
|
||||
"-> %ld, err=%d", data, num, nread, *code));*/
|
||||
return nread;
|
||||
}
|
||||
failf(data, "no filter connected, conn=%ld, sockindex=%d",
|
||||
data->conn->connection_id, num);
|
||||
*code = CURLE_FAILED_INIT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssize_t Curl_cfilter_send(struct Curl_easy *data, int num,
|
||||
const void *mem, size_t len, CURLcode *code)
|
||||
{
|
||||
struct Curl_cfilter *cf;
|
||||
ssize_t nwritten;
|
||||
|
||||
DEBUGASSERT(data);
|
||||
DEBUGASSERT(data->conn);
|
||||
cf = data->conn->cfilter[num];
|
||||
while(cf && !cf->connected) {
|
||||
cf = cf->next;
|
||||
}
|
||||
if(cf) {
|
||||
nwritten = cf->cft->do_send(cf, data, mem, len, code);
|
||||
/* DEBUGF(infof(data, "Curl_cfilter_send(handle=%p, index=%d, len=%ld)"
|
||||
" -> %ld, err=%d", data, num, len, nwritten, *code));*/
|
||||
return nwritten;
|
||||
}
|
||||
failf(data, "no filter connected, conn=%ld, sockindex=%d",
|
||||
data->conn->connection_id, num);
|
||||
*code = CURLE_FAILED_INIT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
CURLcode Curl_cfilter_create(struct Curl_cfilter **pcf,
|
||||
struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex,
|
||||
const struct Curl_cftype *cft,
|
||||
void *ctx)
|
||||
{
|
||||
struct Curl_cfilter *cf;
|
||||
CURLcode result = CURLE_OUT_OF_MEMORY;
|
||||
|
||||
(void)data;
|
||||
(void)conn;
|
||||
DEBUGASSERT(cft);
|
||||
cf = calloc(sizeof(*cf), 1);
|
||||
if(!cf)
|
||||
goto out;
|
||||
|
||||
cf->cft = cft;
|
||||
cf->conn = conn;
|
||||
cf->sockindex = sockindex;
|
||||
cf->ctx = ctx;
|
||||
result = CURLE_OK;
|
||||
out:
|
||||
*pcf = cf;
|
||||
return result;
|
||||
}
|
||||
|
||||
void Curl_cfilter_add(struct Curl_easy *data, struct connectdata *conn,
|
||||
int index, struct Curl_cfilter *cf)
|
||||
{
|
||||
(void)data;
|
||||
DEBUGF(infof(data, "Curl_cfilter_add(conn=%ld, index=%d, filter=%s)",
|
||||
conn->connection_id, index, cf->cft->name));
|
||||
|
||||
cf->next = conn->cfilter[index];
|
||||
cf->conn = conn;
|
||||
cf->sockindex = index;
|
||||
conn->cfilter[index] = cf;
|
||||
}
|
||||
|
||||
CURLcode Curl_cfilter_setup(struct Curl_easy *data,
|
||||
struct connectdata *conn, int sockindex,
|
||||
const struct Curl_dns_entry *remotehost,
|
||||
int ssl_mode)
|
||||
{
|
||||
struct Curl_cfilter *cf;
|
||||
CURLcode result;
|
||||
|
||||
DEBUGASSERT(data);
|
||||
/* If no filter is set, we have the "default" setup of connection filters.
|
||||
* The filter chain from botton to top will be:
|
||||
* - SOCKET socket filter for outgoing connection to remotehost
|
||||
* if http_proxy tunneling is engaged:
|
||||
* - SSL if proxytype is CURLPROXY_HTTPS
|
||||
* - HTTP_PROXY_TUNNEL
|
||||
* otherwise, if socks_proxy is engaged:
|
||||
* - SOCKS_PROXY_TUNNEL
|
||||
* - SSL if conn->handler has PROTOPT_SSL
|
||||
*/
|
||||
if(!conn->cfilter[sockindex]) {
|
||||
DEBUGF(infof(data, "Curl_cfilter_setup(conn #%ld, index=%d)",
|
||||
conn->connection_id, sockindex));
|
||||
result = Curl_cfilter_socket_set(data, conn, sockindex);
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
if(conn->bits.socksproxy) {
|
||||
result = Curl_cfilter_socks_proxy_add(data, conn, sockindex);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(conn->bits.httpproxy) {
|
||||
#ifdef USE_SSL
|
||||
if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
|
||||
result = Curl_cfilter_ssl_proxy_add(data, conn, sockindex);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
#endif /* USE_SSL */
|
||||
|
||||
#if !defined(CURL_DISABLE_HTTP)
|
||||
if(conn->bits.tunnel_proxy) {
|
||||
result = Curl_cfilter_http_proxy_add(data, conn, sockindex);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
#endif /* !CURL_DISABLE_HTTP */
|
||||
}
|
||||
#endif /* !CURL_DISABLE_PROXY */
|
||||
|
||||
#ifdef USE_SSL
|
||||
if(ssl_mode == CURL_CF_SSL_ENABLE
|
||||
|| (ssl_mode != CURL_CF_SSL_DISABLE
|
||||
&& conn->handler->flags & PROTOPT_SSL)) {
|
||||
result = Curl_cfilter_ssl_add(data, conn, sockindex);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
#else
|
||||
(void)ssl_mode;
|
||||
#endif /* USE_SSL */
|
||||
}
|
||||
DEBUGASSERT(conn->cfilter[sockindex]);
|
||||
cf = data->conn->cfilter[sockindex];
|
||||
result = cf->cft->setup(cf, data, remotehost);
|
||||
out:
|
||||
DEBUGF(cf_debug(data, "Curl_cfilter_setup", conn, sockindex, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
CURLcode Curl_cfilter_connect(struct Curl_easy *data,
|
||||
struct connectdata *conn, int sockindex,
|
||||
bool blocking, bool *done)
|
||||
{
|
||||
struct Curl_cfilter *cf;
|
||||
CURLcode result;
|
||||
|
||||
DEBUGASSERT(data);
|
||||
|
||||
cf = conn->cfilter[sockindex];
|
||||
DEBUGASSERT(cf);
|
||||
result = cf->cft->connect(cf, data, blocking, done);
|
||||
|
||||
DEBUGF(infof(data, "Curl_cfilter_connect(handle=%p, index=%d, block=%d) "
|
||||
"-> %d, done=%d", data, sockindex, blocking, result, *done));
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Curl_cfilter_is_connected(struct Curl_easy *data,
|
||||
struct connectdata *conn, int sockindex)
|
||||
{
|
||||
struct Curl_cfilter *cf;
|
||||
|
||||
(void)data;
|
||||
cf = conn->cfilter[sockindex];
|
||||
return cf && cf->connected;
|
||||
}
|
||||
|
||||
bool Curl_cfilter_data_pending(const struct Curl_easy *data,
|
||||
struct connectdata *conn, int sockindex)
|
||||
{
|
||||
struct Curl_cfilter *cf;
|
||||
|
||||
DEBUGASSERT(data);
|
||||
cf = conn->cfilter[sockindex];
|
||||
while(cf && !cf->connected) {
|
||||
cf = cf->next;
|
||||
}
|
||||
if(cf) {
|
||||
return cf->cft->has_data_pending(cf, data);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int Curl_cfilter_get_select_socks(struct Curl_easy *data,
|
||||
struct connectdata *conn, int sockindex,
|
||||
curl_socket_t *socks)
|
||||
{
|
||||
struct Curl_cfilter *cf;
|
||||
|
||||
DEBUGASSERT(data);
|
||||
cf = conn->cfilter[sockindex];
|
||||
if(cf) {
|
||||
return cf->cft->get_select_socks(cf, data, socks);
|
||||
}
|
||||
return GETSOCK_BLANK;
|
||||
}
|
||||
|
||||
void Curl_cfilter_attach_data(struct connectdata *conn,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
size_t i;
|
||||
struct Curl_cfilter *cf;
|
||||
|
||||
for(i = 0; i < ARRAYSIZE(conn->cfilter); ++i) {
|
||||
cf = conn->cfilter[i];
|
||||
if(cf) {
|
||||
DEBUGF(infof(data, "Curl_cfilter_attach(handle=%p, connection=%ld, "
|
||||
"index=%d)", data, conn->connection_id, i));
|
||||
while(cf) {
|
||||
cf->cft->attach_data(cf, data);
|
||||
cf = cf->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Curl_cfilter_detach_data(struct connectdata *conn,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
size_t i;
|
||||
struct Curl_cfilter *cf;
|
||||
|
||||
for(i = 0; i < ARRAYSIZE(conn->cfilter); ++i) {
|
||||
cf = conn->cfilter[i];
|
||||
if(cf) {
|
||||
DEBUGF(infof(data, "Curl_cfilter_detach(handle=%p, connection=%ld, "
|
||||
"index=%d)", data, conn->connection_id, i));
|
||||
while(cf) {
|
||||
cf->cft->detach_data(cf, data);
|
||||
cf = cf->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
206
lib/cfilters.h
Normal file
206
lib/cfilters.h
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
#ifndef HEADER_CURL_CFILTERS_H
|
||||
#define HEADER_CURL_CFILTERS_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
struct Curl_cfilter;
|
||||
struct Curl_easy;
|
||||
|
||||
/* Destroy a filter instance. Implementations MUST NOT chain calls to cf->next.
|
||||
*/
|
||||
typedef void Curl_cf_destroy(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data);
|
||||
|
||||
/* Setup the connection for `data`, using destination `remotehost`.
|
||||
*/
|
||||
typedef CURLcode Curl_cf_setup(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
const struct Curl_dns_entry *remotehost);
|
||||
typedef void Curl_cf_close(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data);
|
||||
|
||||
typedef CURLcode Curl_cf_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done);
|
||||
|
||||
/* Filters may return sockets and fdset flags they are waiting for.
|
||||
* The passes array has room for up to MAX_SOCKSPEREASYHANDLE sockets.
|
||||
* @return read/write fdset for index in socks
|
||||
* or GETSOCK_BLANK when nothing to wait on
|
||||
*/
|
||||
typedef int Curl_cf_get_select_socks(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
curl_socket_t *socks);
|
||||
|
||||
typedef bool Curl_cf_data_pending(struct Curl_cfilter *cf,
|
||||
const struct Curl_easy *data);
|
||||
|
||||
typedef ssize_t Curl_cf_send(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data, /* transfer */
|
||||
const void *buf, /* data to write */
|
||||
size_t len, /* max amount to write */
|
||||
CURLcode *err); /* error to return */
|
||||
|
||||
typedef ssize_t Curl_cf_recv(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data, /* transfer */
|
||||
char *buf, /* store data here */
|
||||
size_t len, /* max amount to read */
|
||||
CURLcode *err); /* error to return */
|
||||
|
||||
typedef void Curl_cf_attach_data(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data);
|
||||
typedef void Curl_cf_detach_data(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data);
|
||||
|
||||
/**
|
||||
* The easy handle `data` is being detached (no longer served)
|
||||
* by connection `conn`. All filters are informed to release any resources
|
||||
* related to `data`.
|
||||
* Note: there may be several `data` attached to a connection at the same
|
||||
* time.
|
||||
*/
|
||||
void Curl_cfilter_detach(struct connectdata *conn, struct Curl_easy *data);
|
||||
|
||||
/* A connection filter type, e.g. specific implementation. */
|
||||
struct Curl_cftype {
|
||||
const char *name; /* name of the filter type */
|
||||
Curl_cf_destroy *destroy; /* destroy resources held */
|
||||
Curl_cf_attach_data *attach_data; /* data is being handled here */
|
||||
Curl_cf_detach_data *detach_data; /* data is no longer handled here */
|
||||
Curl_cf_setup *setup; /* setup for a connection */
|
||||
Curl_cf_close *close; /* close conn */
|
||||
Curl_cf_connect *connect; /* establish connection */
|
||||
Curl_cf_get_select_socks *get_select_socks;/* sockets to select on */
|
||||
Curl_cf_data_pending *has_data_pending;/* conn has data pending */
|
||||
Curl_cf_send *do_send; /* send data */
|
||||
Curl_cf_recv *do_recv; /* receive data */
|
||||
};
|
||||
|
||||
/* A connection filter instance, e.g. registered at a connection */
|
||||
struct Curl_cfilter {
|
||||
const struct Curl_cftype *cft; /* the type providing implementation */
|
||||
struct Curl_cfilter *next; /* next filter in chain */
|
||||
void *ctx; /* filter type specific settings */
|
||||
struct connectdata *conn; /* the connection this filter belongs to */
|
||||
int sockindex; /* TODO: like to get rid off this */
|
||||
BIT(connected); /* != 0 iff this filter is connected */
|
||||
};
|
||||
|
||||
/* Default implementations for the type functions, implementing nop. */
|
||||
void Curl_cf_def_destroy(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data);
|
||||
|
||||
/* Default implementations for the type functions, implementing pass-through
|
||||
* the filter chain. */
|
||||
CURLcode Curl_cf_def_setup(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
const struct Curl_dns_entry *remotehost);
|
||||
void Curl_cf_def_close(struct Curl_cfilter *cf, struct Curl_easy *data);
|
||||
CURLcode Curl_cf_def_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done);
|
||||
int Curl_cf_def_get_select_socks(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
curl_socket_t *socks);
|
||||
bool Curl_cf_def_data_pending(struct Curl_cfilter *cf,
|
||||
const struct Curl_easy *data);
|
||||
ssize_t Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
const void *buf, size_t len, CURLcode *err);
|
||||
ssize_t Curl_cf_def_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
char *buf, size_t len, CURLcode *err);
|
||||
void Curl_cf_def_attach_data(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data);
|
||||
void Curl_cf_def_detach_data(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data);
|
||||
|
||||
|
||||
CURLcode Curl_cfilter_create(struct Curl_cfilter **pcf,
|
||||
struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex,
|
||||
const struct Curl_cftype *cft,
|
||||
void *ctx);
|
||||
|
||||
void Curl_cfilter_destroy(struct Curl_easy *data,
|
||||
struct connectdata *conn, int index);
|
||||
|
||||
void Curl_cfilter_add(struct Curl_easy *data,
|
||||
struct connectdata *conn, int index,
|
||||
struct Curl_cfilter *cf);
|
||||
|
||||
|
||||
#define CURL_CF_SSL_DEFAULT -1
|
||||
#define CURL_CF_SSL_DISABLE 0
|
||||
#define CURL_CF_SSL_ENABLE 1
|
||||
|
||||
CURLcode Curl_cfilter_setup(struct Curl_easy *data,
|
||||
struct connectdata *conn, int sockindex,
|
||||
const struct Curl_dns_entry *remotehost,
|
||||
int ssl_mode);
|
||||
CURLcode Curl_cfilter_connect(struct Curl_easy *data,
|
||||
struct connectdata *conn, int sockindex,
|
||||
bool blocking, bool *done);
|
||||
bool Curl_cfilter_is_connected(struct Curl_easy *data,
|
||||
struct connectdata *conn, int sockindex);
|
||||
|
||||
void Curl_cfilter_close(struct Curl_easy *data,
|
||||
struct connectdata *conn, int index);
|
||||
|
||||
bool Curl_cfilter_data_pending(const struct Curl_easy *data,
|
||||
struct connectdata *conn, int sockindex);
|
||||
|
||||
/**
|
||||
* Get any select fd flags and the socket filters might be waiting for.
|
||||
*/
|
||||
int Curl_cfilter_get_select_socks(struct Curl_easy *data,
|
||||
struct connectdata *conn, int sockindex,
|
||||
curl_socket_t *socks);
|
||||
|
||||
/* Helper function to migrate conn->recv, conn->send callback to filters */
|
||||
ssize_t Curl_cfilter_recv(struct Curl_easy *data, int num, char *buf,
|
||||
size_t len, CURLcode *code);
|
||||
ssize_t Curl_cfilter_send(struct Curl_easy *data, int num,
|
||||
const void *mem, size_t len, CURLcode *code);
|
||||
|
||||
/**
|
||||
* The easy handle `data` is being attached (served) by connection `conn`.
|
||||
* All filters are informed to adapt to handling `data`.
|
||||
* Note: there may be several `data` attached to a connection at the same
|
||||
* time.
|
||||
*/
|
||||
void Curl_cfilter_attach_data(struct connectdata *conn,
|
||||
struct Curl_easy *data);
|
||||
|
||||
/**
|
||||
* The easy handle `data` is being detached (no longer served)
|
||||
* by connection `conn`. All filters are informed to release any resources
|
||||
* related to `data`.
|
||||
* Note: there may be several `data` attached to a connection at the same
|
||||
* time.
|
||||
*/
|
||||
void Curl_cfilter_detach_data(struct connectdata *conn,
|
||||
struct Curl_easy *data);
|
||||
|
||||
#endif /* HEADER_CURL_CFILTERS_H */
|
||||
440
lib/connect.c
440
lib/connect.c
|
|
@ -64,6 +64,7 @@
|
|||
#include "sendf.h"
|
||||
#include "if2ip.h"
|
||||
#include "strerror.h"
|
||||
#include "cfilters.h"
|
||||
#include "connect.h"
|
||||
#include "select.h"
|
||||
#include "url.h" /* for Curl_safefree() */
|
||||
|
|
@ -79,7 +80,6 @@
|
|||
#include "share.h"
|
||||
#include "version_win32.h"
|
||||
#include "quic.h"
|
||||
#include "socks.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
|
|
@ -237,10 +237,9 @@ timediff_t Curl_timeleft(struct Curl_easy *data,
|
|||
return timeout_ms;
|
||||
}
|
||||
|
||||
static CURLcode bindlocal(struct Curl_easy *data,
|
||||
static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn,
|
||||
curl_socket_t sockfd, int af, unsigned int scope)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
struct Curl_sockaddr_storage sa;
|
||||
struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */
|
||||
curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */
|
||||
|
|
@ -776,95 +775,25 @@ void Curl_updateconninfo(struct Curl_easy *data, struct connectdata *conn,
|
|||
Curl_persistconninfo(data, conn, local_ip, local_port);
|
||||
}
|
||||
|
||||
/* After a TCP connection to the proxy has been verified, this function does
|
||||
the next magic steps. If 'done' isn't set TRUE, it is not done yet and
|
||||
must be called again.
|
||||
|
||||
Note: this function's sub-functions call failf()
|
||||
|
||||
*/
|
||||
static CURLcode connect_SOCKS(struct Curl_easy *data, int sockindex,
|
||||
bool *done)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
CURLproxycode pxresult = CURLPX_OK;
|
||||
struct connectdata *conn = data->conn;
|
||||
if(conn->bits.socksproxy) {
|
||||
/* for the secondary socket (FTP), use the "connect to host"
|
||||
* but ignore the "connect to port" (use the secondary port)
|
||||
*/
|
||||
const char * const host =
|
||||
conn->bits.httpproxy ?
|
||||
conn->http_proxy.host.name :
|
||||
conn->bits.conn_to_host ?
|
||||
conn->conn_to_host.name :
|
||||
sockindex == SECONDARYSOCKET ?
|
||||
conn->secondaryhostname : conn->host.name;
|
||||
const int port =
|
||||
conn->bits.httpproxy ? (int)conn->http_proxy.port :
|
||||
sockindex == SECONDARYSOCKET ? conn->secondary_port :
|
||||
conn->bits.conn_to_port ? conn->conn_to_port :
|
||||
conn->remote_port;
|
||||
switch(conn->socks_proxy.proxytype) {
|
||||
case CURLPROXY_SOCKS5:
|
||||
case CURLPROXY_SOCKS5_HOSTNAME:
|
||||
pxresult = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd,
|
||||
host, port, sockindex, data, done);
|
||||
break;
|
||||
|
||||
case CURLPROXY_SOCKS4:
|
||||
case CURLPROXY_SOCKS4A:
|
||||
pxresult = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex,
|
||||
data, done);
|
||||
break;
|
||||
|
||||
default:
|
||||
failf(data, "unknown proxytype option given");
|
||||
result = CURLE_COULDNT_CONNECT;
|
||||
} /* switch proxytype */
|
||||
if(pxresult) {
|
||||
result = CURLE_PROXY;
|
||||
data->info.pxcode = pxresult;
|
||||
}
|
||||
}
|
||||
else
|
||||
#else
|
||||
(void)data;
|
||||
(void)sockindex;
|
||||
#endif /* CURL_DISABLE_PROXY */
|
||||
*done = TRUE; /* no SOCKS proxy, so consider us connected */
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* post_SOCKS() is called after a successful connect to the peer, which
|
||||
* *could* be a SOCKS proxy
|
||||
* post_connect() is called after a successful connect to the peer
|
||||
*/
|
||||
static void post_SOCKS(struct Curl_easy *data,
|
||||
static void post_connect(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex,
|
||||
bool *connected)
|
||||
int sockindex)
|
||||
{
|
||||
conn->bits.tcpconnect[sockindex] = TRUE;
|
||||
|
||||
*connected = TRUE;
|
||||
if(sockindex == FIRSTSOCKET)
|
||||
Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
|
||||
Curl_updateconninfo(data, conn, conn->sock[sockindex]);
|
||||
Curl_verboseconnect(data, conn);
|
||||
data->info.numconnects++; /* to track the number of connections made */
|
||||
}
|
||||
|
||||
/*
|
||||
* Curl_is_connected() checks if the socket has connected.
|
||||
* is_connected() checks if the socket has connected.
|
||||
*/
|
||||
|
||||
CURLcode Curl_is_connected(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex,
|
||||
bool *connected)
|
||||
static CURLcode is_connected(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex,
|
||||
bool *connected)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
timediff_t allow;
|
||||
|
|
@ -877,22 +806,14 @@ CURLcode Curl_is_connected(struct Curl_easy *data,
|
|||
|
||||
*connected = FALSE; /* a very negative world view is best */
|
||||
|
||||
if(conn->bits.tcpconnect[sockindex]) {
|
||||
/* we are connected already! */
|
||||
*connected = TRUE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
now = Curl_now();
|
||||
|
||||
if(SOCKS_STATE(conn->cnnct.state)) {
|
||||
/* still doing SOCKS */
|
||||
result = connect_SOCKS(data, sockindex, connected);
|
||||
if(!result && *connected)
|
||||
post_SOCKS(data, conn, sockindex, connected);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Check if any of the conn->tempsock we use for establishing connections
|
||||
* succeeded and, if so, close any ongoing other ones.
|
||||
* Transfer the successful conn->tempsock to conn->sock[sockindex]
|
||||
* and set conn->tempsock to CURL_SOCKET_BAD.
|
||||
* If transport is QUIC, we need to shutdown the ongoing 'other'
|
||||
* connect attempts in a QUIC appropriate way. */
|
||||
for(i = 0; i<2; i++) {
|
||||
const int other = i ^ 1;
|
||||
if(conn->tempsock[i] == CURL_SOCKET_BAD)
|
||||
|
|
@ -906,7 +827,7 @@ CURLcode Curl_is_connected(struct Curl_easy *data,
|
|||
conn->sock[sockindex] = conn->tempsock[i];
|
||||
conn->ip_addr = conn->tempaddr[i];
|
||||
conn->tempsock[i] = CURL_SOCKET_BAD;
|
||||
post_SOCKS(data, conn, sockindex, connected);
|
||||
post_connect(data, conn, sockindex);
|
||||
connkeep(conn, "HTTP/3 default");
|
||||
if(conn->tempsock[other] != CURL_SOCKET_BAD)
|
||||
Curl_quic_disconnect(data, conn, other);
|
||||
|
|
@ -968,14 +889,7 @@ CURLcode Curl_is_connected(struct Curl_easy *data,
|
|||
conn->tempsock[other] = CURL_SOCKET_BAD;
|
||||
}
|
||||
|
||||
/* see if we need to kick off any SOCKS proxy magic once we
|
||||
connected */
|
||||
result = connect_SOCKS(data, sockindex, connected);
|
||||
if(result || !*connected)
|
||||
return result;
|
||||
|
||||
post_SOCKS(data, conn, sockindex, connected);
|
||||
|
||||
*connected = TRUE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
}
|
||||
|
|
@ -1266,7 +1180,7 @@ static CURLcode singleipconnect(struct Curl_easy *data,
|
|||
|| addr.family == AF_INET6
|
||||
#endif
|
||||
) {
|
||||
result = bindlocal(data, sockfd, addr.family,
|
||||
result = bindlocal(data, conn, sockfd, addr.family,
|
||||
Curl_ipv6_scope(&addr.sa_addr));
|
||||
if(result) {
|
||||
Curl_closesocket(data, conn, sockfd); /* close socket and bail out */
|
||||
|
|
@ -1529,7 +1443,7 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
|
|||
bool Curl_connalive(struct connectdata *conn)
|
||||
{
|
||||
/* First determine if ssl */
|
||||
if(conn->ssl[FIRSTSOCKET].use) {
|
||||
if(Curl_ssl_use(conn, FIRSTSOCKET)) {
|
||||
/* use the SSL context */
|
||||
if(!Curl_ssl_check_cxn(conn))
|
||||
return false; /* FIN received */
|
||||
|
|
@ -1558,6 +1472,8 @@ bool Curl_connalive(struct connectdata *conn)
|
|||
int Curl_closesocket(struct Curl_easy *data, struct connectdata *conn,
|
||||
curl_socket_t sock)
|
||||
{
|
||||
DEBUGF(infof(data, "Curl_closesocket(conn #%ld, sock=%d), fclosesocket=%d",
|
||||
conn->connection_id, (int)sock, conn->fclosesocket));
|
||||
if(conn && conn->fclosesocket) {
|
||||
if((sock == conn->sock[SECONDARYSOCKET]) && conn->bits.sock_accepted)
|
||||
/* if this socket matches the second socket, and that was created with
|
||||
|
|
@ -1720,15 +1636,313 @@ void Curl_conncontrol(struct connectdata *conn,
|
|||
}
|
||||
|
||||
/* Data received can be cached at various levels, so check them all here. */
|
||||
bool Curl_conn_data_pending(struct connectdata *conn, int sockindex)
|
||||
bool Curl_conn_data_pending(struct Curl_easy *data, int sockindex)
|
||||
{
|
||||
return Curl_recv_has_postponed_data(data->conn, sockindex)
|
||||
||Curl_cfilter_data_pending(data, data->conn, sockindex);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
SCFST_INIT,
|
||||
SCFST_WAITING,
|
||||
SCFST_DONE
|
||||
} cf_connect_state;
|
||||
|
||||
struct socket_cf_ctx {
|
||||
const struct Curl_dns_entry *remotehost;
|
||||
cf_connect_state state;
|
||||
};
|
||||
|
||||
static int socket_cf_get_select_socks(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
curl_socket_t *socks)
|
||||
{
|
||||
struct connectdata *conn = cf->conn;
|
||||
int i, s, rc = GETSOCK_BLANK;
|
||||
|
||||
(void)data;
|
||||
if(cf->connected) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
for(i = s = 0; i<2; i++) {
|
||||
if(conn->tempsock[i] != CURL_SOCKET_BAD) {
|
||||
socks[s] = conn->tempsock[i];
|
||||
rc |= GETSOCK_WRITESOCK(s);
|
||||
#ifdef ENABLE_QUIC
|
||||
if(conn->transport == TRNSPRT_QUIC)
|
||||
/* when connecting QUIC, we want to read the socket too */
|
||||
rc |= GETSOCK_READSOCK(s);
|
||||
#endif
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static CURLcode socket_cf_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
{
|
||||
struct connectdata *conn = cf->conn;
|
||||
int sockindex = cf->sockindex;
|
||||
struct socket_cf_ctx *ctx = cf->ctx;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
if(cf->connected) {
|
||||
*done = TRUE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
(void)blocking;
|
||||
DEBUGASSERT(ctx);
|
||||
*done = FALSE;
|
||||
switch(ctx->state) {
|
||||
case SCFST_INIT:
|
||||
DEBUGASSERT(CURL_SOCKET_BAD == conn->sock[sockindex]);
|
||||
DEBUGASSERT(!cf->connected);
|
||||
result = Curl_connecthost(data, conn, ctx->remotehost);
|
||||
if(!result)
|
||||
ctx->state = SCFST_WAITING;
|
||||
DEBUGF(infof(data, "socket_cf_connect(handle=%p, index=%d) -> "
|
||||
"connecthost() -> %d, done=%d",
|
||||
data, sockindex, result, *done));
|
||||
break;
|
||||
case SCFST_WAITING:
|
||||
result = is_connected(data, conn, sockindex, done);
|
||||
if(!result && *done) {
|
||||
Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
|
||||
if(Curl_ssl_use(conn, FIRSTSOCKET) ||
|
||||
(conn->handler->protocol & PROTO_FAMILY_SSH))
|
||||
Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
|
||||
post_connect(data, conn, sockindex);
|
||||
ctx->state = SCFST_DONE;
|
||||
cf->connected = TRUE;
|
||||
}
|
||||
DEBUGF(infof(data, "socket_cf_connect(handle=%p, index=%d) -> "
|
||||
"is_connected() -> %d, done=%d",
|
||||
data, sockindex, result, *done));
|
||||
break;
|
||||
case SCFST_DONE:
|
||||
*done = TRUE;
|
||||
DEBUGF(infof(data, "socket_cf_connect(handle=%p, index=%d) -> "
|
||||
"already connected-> %d, done=%d",
|
||||
data, sockindex, result, *done));
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode socket_cf_setup(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
const struct Curl_dns_entry *remotehost)
|
||||
{
|
||||
struct socket_cf_ctx *ctx = cf->ctx;
|
||||
bool done;
|
||||
|
||||
DEBUGASSERT(ctx);
|
||||
if(ctx->remotehost != remotehost) {
|
||||
if(ctx->remotehost) {
|
||||
/* switching dns entry? TODO: reset? */
|
||||
}
|
||||
ctx->remotehost = remotehost;
|
||||
}
|
||||
/* we start connecting right on setup */
|
||||
DEBUGF(infof(data, "socket_cf_setup(handle=%p, remotehost=%s)",
|
||||
data, cf->conn->hostname_resolve));
|
||||
return socket_cf_connect(cf, data, FALSE, &done);
|
||||
}
|
||||
|
||||
static void socket_cf_close(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
int sockindex = cf->sockindex;
|
||||
struct socket_cf_ctx *ctx = cf->ctx;
|
||||
|
||||
DEBUGASSERT(ctx);
|
||||
/* close possibly still open sockets */
|
||||
if(CURL_SOCKET_BAD != cf->conn->sock[sockindex]) {
|
||||
Curl_closesocket(data, cf->conn, cf->conn->sock[sockindex]);
|
||||
cf->conn->sock[sockindex] = CURL_SOCKET_BAD;
|
||||
}
|
||||
if(CURL_SOCKET_BAD != cf->conn->tempsock[sockindex]) {
|
||||
Curl_closesocket(data, cf->conn, cf->conn->tempsock[sockindex]);
|
||||
cf->conn->tempsock[sockindex] = CURL_SOCKET_BAD;
|
||||
}
|
||||
cf->connected = FALSE;
|
||||
ctx->state = SCFST_INIT;
|
||||
}
|
||||
|
||||
static bool socket_cf_data_pending(struct Curl_cfilter *cf,
|
||||
const struct Curl_easy *data)
|
||||
{
|
||||
int readable;
|
||||
DEBUGASSERT(conn);
|
||||
(void)data;
|
||||
DEBUGASSERT(cf);
|
||||
|
||||
if(Curl_ssl_data_pending(conn, sockindex) ||
|
||||
Curl_recv_has_postponed_data(conn, sockindex))
|
||||
return true;
|
||||
|
||||
readable = SOCKET_READABLE(conn->sock[sockindex], 0);
|
||||
readable = SOCKET_READABLE(cf->conn->sock[cf->sockindex], 0);
|
||||
return (readable > 0 && (readable & CURL_CSELECT_IN));
|
||||
}
|
||||
|
||||
static ssize_t socket_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
const void *buf, size_t len, CURLcode *err)
|
||||
{
|
||||
ssize_t nwritten;
|
||||
nwritten = Curl_send_plain(data, cf->sockindex, buf, len, err);
|
||||
/* DEBUGF(infof(data, "socket_cf_send(handle=%p, index=%d, len=%ld)"
|
||||
"-> %ld, code=%d", data, cf->sockindex, len, nwritten, *err));*/
|
||||
return nwritten;
|
||||
}
|
||||
|
||||
static ssize_t socket_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
char *buf, size_t len, CURLcode *err)
|
||||
{
|
||||
ssize_t nread;
|
||||
nread = Curl_recv_plain(data, cf->sockindex, buf, len, err);
|
||||
/* DEBUGF(infof(data, "socket_cf_recv(handle=%p, index=%d) -> %ld",
|
||||
data, cf->sockindex, nread));*/
|
||||
return nread;
|
||||
}
|
||||
|
||||
static void socket_cf_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
{
|
||||
struct socket_cf_ctx *state = cf->ctx;
|
||||
|
||||
(void)data;
|
||||
DEBUGF(infof(data, "socket_cf_destroy(conn #%ld, index=%d",
|
||||
cf->conn->connection_id, cf->sockindex));
|
||||
if(cf->connected) {
|
||||
socket_cf_close(cf, data);
|
||||
}
|
||||
/* release any resources held in state */
|
||||
Curl_safefree(state);
|
||||
}
|
||||
|
||||
static const struct Curl_cftype cft_socket = {
|
||||
"SOCKET",
|
||||
socket_cf_destroy,
|
||||
Curl_cf_def_attach_data,
|
||||
Curl_cf_def_detach_data,
|
||||
socket_cf_setup,
|
||||
socket_cf_close,
|
||||
socket_cf_connect,
|
||||
socket_cf_get_select_socks,
|
||||
socket_cf_data_pending,
|
||||
socket_cf_send,
|
||||
socket_cf_recv,
|
||||
};
|
||||
|
||||
CURLcode Curl_cfilter_socket_set(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex)
|
||||
{
|
||||
CURLcode result;
|
||||
struct Curl_cfilter *cf = NULL;
|
||||
struct socket_cf_ctx *scf_ctx = NULL;
|
||||
|
||||
/* Need to be first */
|
||||
DEBUGASSERT(!conn->cfilter[sockindex]);
|
||||
scf_ctx = calloc(sizeof(*scf_ctx), 1);
|
||||
if(!scf_ctx) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
result = Curl_cfilter_create(&cf, data, conn, sockindex,
|
||||
&cft_socket, scf_ctx);
|
||||
if(result)
|
||||
goto out;
|
||||
Curl_cfilter_add(data, conn, sockindex, cf);
|
||||
|
||||
out:
|
||||
if(result) {
|
||||
Curl_safefree(cf);
|
||||
Curl_safefree(scf_ctx);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode socket_accept_cf_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
{
|
||||
/* we start accepted, if we ever close, we cannot go on */
|
||||
(void)data;
|
||||
(void)blocking;
|
||||
if(cf->connected) {
|
||||
*done = TRUE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
|
||||
static CURLcode socket_accept_cf_setup(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
const struct Curl_dns_entry *remotehost)
|
||||
{
|
||||
/* we start accepted, if we ever close, we cannot go on */
|
||||
(void)data;
|
||||
(void)remotehost;
|
||||
if(cf->connected) {
|
||||
return CURLE_OK;
|
||||
}
|
||||
return CURLE_FAILED_INIT;
|
||||
}
|
||||
|
||||
static const struct Curl_cftype cft_socket_accept = {
|
||||
"SOCKET-ACCEPT",
|
||||
socket_cf_destroy,
|
||||
Curl_cf_def_attach_data,
|
||||
Curl_cf_def_detach_data,
|
||||
socket_accept_cf_setup,
|
||||
socket_cf_close,
|
||||
socket_accept_cf_connect,
|
||||
Curl_cf_def_get_select_socks,
|
||||
socket_cf_data_pending,
|
||||
socket_cf_send,
|
||||
socket_cf_recv,
|
||||
};
|
||||
|
||||
CURLcode Curl_cfilter_socket_accepted_set(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex, curl_socket_t *s)
|
||||
{
|
||||
CURLcode result;
|
||||
struct Curl_cfilter *cf = NULL;
|
||||
struct socket_cf_ctx *scf_ctx = NULL;
|
||||
|
||||
cf = conn->cfilter[sockindex];
|
||||
if(cf && cf->cft == &cft_socket_accept) {
|
||||
/* already an accept filter installed, just replace the socket */
|
||||
scf_ctx = cf->ctx;
|
||||
result = CURLE_OK;
|
||||
}
|
||||
else {
|
||||
/* replace any existing */
|
||||
Curl_cfilter_destroy(data, conn, sockindex);
|
||||
scf_ctx = calloc(sizeof(*scf_ctx), 1);
|
||||
if(!scf_ctx) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
result = Curl_cfilter_create(&cf, data, conn, sockindex,
|
||||
&cft_socket_accept, scf_ctx);
|
||||
if(result)
|
||||
goto out;
|
||||
Curl_cfilter_add(data, conn, sockindex, cf);
|
||||
}
|
||||
|
||||
/* close any existing socket and replace */
|
||||
Curl_closesocket(data, conn, conn->sock[sockindex]);
|
||||
conn->sock[sockindex] = *s;
|
||||
conn->bits.sock_accepted = TRUE;
|
||||
cf->connected = TRUE;
|
||||
scf_ctx->state = SCFST_DONE;
|
||||
|
||||
out:
|
||||
if(result) {
|
||||
Curl_safefree(cf);
|
||||
Curl_safefree(scf_ctx);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,11 +29,6 @@
|
|||
#include "sockaddr.h"
|
||||
#include "timeval.h"
|
||||
|
||||
CURLcode Curl_is_connected(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex,
|
||||
bool *connected);
|
||||
|
||||
CURLcode Curl_connecthost(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
const struct Curl_dns_entry *host);
|
||||
|
|
@ -153,6 +148,14 @@ void Curl_conncontrol(struct connectdata *conn,
|
|||
#define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP)
|
||||
#endif
|
||||
|
||||
bool Curl_conn_data_pending(struct connectdata *conn, int sockindex);
|
||||
bool Curl_conn_data_pending(struct Curl_easy *data, int sockindex);
|
||||
|
||||
CURLcode Curl_cfilter_socket_set(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex);
|
||||
|
||||
CURLcode Curl_cfilter_socket_accepted_set(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex, curl_socket_t *s);
|
||||
|
||||
#endif /* HEADER_CURL_CONNECT_H */
|
||||
|
|
|
|||
15
lib/file.c
15
lib/file.c
|
|
@ -150,9 +150,19 @@ static CURLcode file_connect(struct Curl_easy *data, bool *done)
|
|||
char *actual_path;
|
||||
#endif
|
||||
size_t real_path_len;
|
||||
CURLcode result;
|
||||
|
||||
CURLcode result = Curl_urldecode(data->state.up.path, 0, &real_path,
|
||||
&real_path_len, REJECT_ZERO);
|
||||
if(file->path) {
|
||||
/* already connected.
|
||||
* the handler->connect_it() is normally only called once, but
|
||||
* FILE does a special check on setting up the connection which
|
||||
* calls this explicitly. */
|
||||
*done = TRUE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
result = Curl_urldecode(data->state.up.path, 0, &real_path,
|
||||
&real_path_len, REJECT_ZERO);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
|
|
@ -226,6 +236,7 @@ static CURLcode file_connect(struct Curl_easy *data, bool *done)
|
|||
file->path = real_path;
|
||||
#endif
|
||||
#endif
|
||||
Curl_safefree(file->freepath);
|
||||
file->freepath = real_path; /* free this when done */
|
||||
|
||||
file->fd = fd;
|
||||
|
|
|
|||
202
lib/ftp.c
202
lib/ftp.c
|
|
@ -65,6 +65,7 @@
|
|||
#include "strtoofft.h"
|
||||
#include "strcase.h"
|
||||
#include "vtls/vtls.h"
|
||||
#include "cfilters.h"
|
||||
#include "connect.h"
|
||||
#include "strerror.h"
|
||||
#include "inet_ntop.h"
|
||||
|
|
@ -218,14 +219,8 @@ const struct Curl_handler Curl_handler_ftps = {
|
|||
static void close_secondarysocket(struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET]) {
|
||||
Curl_closesocket(data, conn, conn->sock[SECONDARYSOCKET]);
|
||||
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
|
||||
}
|
||||
conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
conn->bits.proxy_ssl_connected[SECONDARYSOCKET] = FALSE;
|
||||
#endif
|
||||
Curl_cfilter_close(data, conn, SECONDARYSOCKET);
|
||||
Curl_cfilter_destroy(data, conn, SECONDARYSOCKET);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -277,13 +272,13 @@ static CURLcode AcceptServerConnect(struct Curl_easy *data)
|
|||
struct sockaddr_in add;
|
||||
#endif
|
||||
curl_socklen_t size = (curl_socklen_t) sizeof(add);
|
||||
CURLcode result;
|
||||
|
||||
if(0 == getsockname(sock, (struct sockaddr *) &add, &size)) {
|
||||
size = sizeof(add);
|
||||
|
||||
s = accept(sock, (struct sockaddr *) &add, &size);
|
||||
}
|
||||
Curl_closesocket(data, conn, sock); /* close the first socket */
|
||||
|
||||
if(CURL_SOCKET_BAD == s) {
|
||||
failf(data, "Error accept()ing server connect");
|
||||
|
|
@ -294,9 +289,11 @@ static CURLcode AcceptServerConnect(struct Curl_easy *data)
|
|||
not needing DO_MORE anymore */
|
||||
conn->bits.do_more = FALSE;
|
||||
|
||||
conn->sock[SECONDARYSOCKET] = s;
|
||||
(void)curlx_nonblock(s, TRUE); /* enable non-blocking */
|
||||
conn->bits.sock_accepted = TRUE;
|
||||
/* Replace any filter on SECONDARY with one listeing on this socket */
|
||||
result = Curl_cfilter_socket_accepted_set(data, conn, SECONDARYSOCKET, &s);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(data->set.fsockopt) {
|
||||
int error = 0;
|
||||
|
|
@ -440,15 +437,13 @@ static CURLcode InitiateTransfer(struct Curl_easy *data)
|
|||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct connectdata *conn = data->conn;
|
||||
bool connected;
|
||||
|
||||
if(conn->bits.ftp_use_data_ssl) {
|
||||
/* since we only have a plaintext TCP connection here, we must now
|
||||
* do the TLS stuff */
|
||||
infof(data, "Doing the SSL/TLS handshake on the data stream");
|
||||
result = Curl_ssl_connect(data, conn, SECONDARYSOCKET);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
DEBUGF(infof(data, "ftp InitiateTransfer()"));
|
||||
result = Curl_cfilter_connect(data, conn, SECONDARYSOCKET,
|
||||
TRUE, &connected);
|
||||
if(result || !connected)
|
||||
return result;
|
||||
|
||||
if(conn->proto.ftpc.state_saved == FTP_STOR) {
|
||||
/* When we know we're uploading a specified file, we can get the file
|
||||
|
|
@ -496,22 +491,23 @@ static CURLcode AllowServerConnect(struct Curl_easy *data, bool *connected)
|
|||
if(timeout_ms < 0) {
|
||||
/* if a timeout was already reached, bail out */
|
||||
failf(data, "Accept timeout occurred while waiting server connect");
|
||||
return CURLE_FTP_ACCEPT_TIMEOUT;
|
||||
result = CURLE_FTP_ACCEPT_TIMEOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* see if the connection request is already here */
|
||||
result = ReceivedServerConnect(data, connected);
|
||||
if(result)
|
||||
return result;
|
||||
goto out;
|
||||
|
||||
if(*connected) {
|
||||
result = AcceptServerConnect(data);
|
||||
if(result)
|
||||
return result;
|
||||
goto out;
|
||||
|
||||
result = InitiateTransfer(data);
|
||||
if(result)
|
||||
return result;
|
||||
goto out;
|
||||
}
|
||||
else {
|
||||
/* Add timeout to multi handle and break out of the loop */
|
||||
|
|
@ -520,6 +516,8 @@ static CURLcode AllowServerConnect(struct Curl_easy *data, bool *connected)
|
|||
EXPIRE_FTP_ACCEPT);
|
||||
}
|
||||
|
||||
out:
|
||||
DEBUGF(infof(data, "ftp AllowServerConnect() -> %d", result));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -671,7 +669,7 @@ CURLcode Curl_GetFTPResponse(struct Curl_easy *data,
|
|||
* wait for more data anyway.
|
||||
*/
|
||||
}
|
||||
else if(!Curl_conn_data_pending(conn, FIRSTSOCKET)) {
|
||||
else if(!Curl_conn_data_pending(data, FIRSTSOCKET)) {
|
||||
switch(SOCKET_READABLE(sockfd, interval_ms)) {
|
||||
case -1: /* select() error, stop reading */
|
||||
failf(data, "FTP response aborted due to select/poll error: %d",
|
||||
|
|
@ -820,8 +818,10 @@ static int ftp_domore_getsock(struct Curl_easy *data,
|
|||
* handle ordinary commands.
|
||||
*/
|
||||
|
||||
if(SOCKS_STATE(conn->cnnct.state))
|
||||
return Curl_SOCKS_getsock(conn, socks, SECONDARYSOCKET);
|
||||
DEBUGF(infof(data, "ftp_domore_getsock()"));
|
||||
if(conn->cfilter[SECONDARYSOCKET]
|
||||
&& !Curl_cfilter_is_connected(data, conn, SECONDARYSOCKET))
|
||||
return Curl_cfilter_get_select_socks(data, conn, SECONDARYSOCKET, socks);
|
||||
|
||||
if(FTP_STOP == ftpc->state) {
|
||||
int bits = GETSOCK_READSOCK(0);
|
||||
|
|
@ -916,7 +916,7 @@ typedef enum {
|
|||
static CURLcode ftp_state_use_port(struct Curl_easy *data,
|
||||
ftpport fcmd) /* start with this */
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
CURLcode result = CURLE_FTP_PORT_FAILED;
|
||||
struct connectdata *conn = data->conn;
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
curl_socket_t portsock = CURL_SOCKET_BAD;
|
||||
|
|
@ -965,8 +965,10 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
|
|||
char *port_sep = NULL;
|
||||
|
||||
addr = calloc(addrlen + 1, 1);
|
||||
if(!addr)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
if(!addr) {
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_IPV6
|
||||
if(*string_ftpport == '[') {
|
||||
|
|
@ -1026,7 +1028,6 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
|
|||
if(port_min > port_max)
|
||||
port_min = port_max = 0;
|
||||
|
||||
|
||||
if(*addr != '\0') {
|
||||
/* attempt to get the address of the given interface name */
|
||||
switch(Curl_if2ip(conn->ip_addr->ai_family,
|
||||
|
|
@ -1040,7 +1041,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
|
|||
host = addr;
|
||||
break;
|
||||
case IF2IP_AF_NOT_SUPPORTED:
|
||||
return CURLE_FTP_PORT_FAILED;
|
||||
goto out;
|
||||
case IF2IP_FOUND:
|
||||
host = hbuf; /* use the hbuf for host name */
|
||||
}
|
||||
|
|
@ -1058,8 +1059,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
|
|||
if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
|
||||
failf(data, "getsockname() failed: %s",
|
||||
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
|
||||
free(addr);
|
||||
return CURLE_FTP_PORT_FAILED;
|
||||
goto out;
|
||||
}
|
||||
switch(sa->sa_family) {
|
||||
#ifdef ENABLE_IPV6
|
||||
|
|
@ -1071,8 +1071,9 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
|
|||
r = Curl_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, sizeof(hbuf));
|
||||
break;
|
||||
}
|
||||
if(!r)
|
||||
return CURLE_FTP_PORT_FAILED;
|
||||
if(!r) {
|
||||
goto out;
|
||||
}
|
||||
host = hbuf; /* use this host name */
|
||||
possibly_non_local = FALSE; /* we know it is local now */
|
||||
}
|
||||
|
|
@ -1092,11 +1093,9 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
|
|||
|
||||
if(!res) {
|
||||
failf(data, "failed to resolve the address provided to PORT: %s", host);
|
||||
free(addr);
|
||||
return CURLE_FTP_PORT_FAILED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
free(addr);
|
||||
host = NULL;
|
||||
|
||||
/* step 2, create a socket for the requested address */
|
||||
|
|
@ -1104,8 +1103,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
|
|||
portsock = CURL_SOCKET_BAD;
|
||||
error = 0;
|
||||
for(ai = res; ai; ai = ai->ai_next) {
|
||||
result = Curl_socket(data, ai, NULL, &portsock);
|
||||
if(result) {
|
||||
if(Curl_socket(data, ai, NULL, &portsock)) {
|
||||
error = SOCKERRNO;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1114,8 +1112,9 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
|
|||
if(!ai) {
|
||||
failf(data, "socket failure: %s",
|
||||
Curl_strerror(error, buffer, sizeof(buffer)));
|
||||
return CURLE_FTP_PORT_FAILED;
|
||||
goto out;
|
||||
}
|
||||
DEBUGF(infof(data, "ftp_state_use_port(), opened socket"));
|
||||
|
||||
/* step 3, bind to a suitable local address */
|
||||
|
||||
|
|
@ -1144,8 +1143,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
|
|||
if(getsockname(conn->sock[FIRSTSOCKET], sa, &sslen)) {
|
||||
failf(data, "getsockname() failed: %s",
|
||||
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
|
||||
Curl_closesocket(data, conn, portsock);
|
||||
return CURLE_FTP_PORT_FAILED;
|
||||
goto out;
|
||||
}
|
||||
port = port_min;
|
||||
possibly_non_local = FALSE; /* don't try this again */
|
||||
|
|
@ -1154,8 +1152,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
|
|||
if(error != EADDRINUSE && error != EACCES) {
|
||||
failf(data, "bind(port=%hu) failed: %s", port,
|
||||
Curl_strerror(error, buffer, sizeof(buffer)));
|
||||
Curl_closesocket(data, conn, portsock);
|
||||
return CURLE_FTP_PORT_FAILED;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -1167,8 +1164,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
|
|||
/* maybe all ports were in use already */
|
||||
if(port > port_max) {
|
||||
failf(data, "bind() failed, we ran out of ports");
|
||||
Curl_closesocket(data, conn, portsock);
|
||||
return CURLE_FTP_PORT_FAILED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* get the name again after the bind() so that we can extract the
|
||||
|
|
@ -1177,18 +1173,18 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
|
|||
if(getsockname(portsock, sa, &sslen)) {
|
||||
failf(data, "getsockname() failed: %s",
|
||||
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
|
||||
Curl_closesocket(data, conn, portsock);
|
||||
return CURLE_FTP_PORT_FAILED;
|
||||
goto out;
|
||||
}
|
||||
DEBUGF(infof(data, "ftp_state_use_port(), socket bound to port %d", port));
|
||||
|
||||
/* step 4, listen on the socket */
|
||||
|
||||
if(listen(portsock, 1)) {
|
||||
failf(data, "socket failure: %s",
|
||||
Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
|
||||
Curl_closesocket(data, conn, portsock);
|
||||
return CURLE_FTP_PORT_FAILED;
|
||||
goto out;
|
||||
}
|
||||
DEBUGF(infof(data, "ftp_state_use_port(), listening on %d", port));
|
||||
|
||||
/* step 5, send the proper FTP command */
|
||||
|
||||
|
|
@ -1241,12 +1237,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
|
|||
if(result) {
|
||||
failf(data, "Failure sending EPRT command: %s",
|
||||
curl_easy_strerror(result));
|
||||
Curl_closesocket(data, conn, portsock);
|
||||
/* don't retry using PORT */
|
||||
ftpc->count1 = PORT;
|
||||
/* bail out */
|
||||
state(data, FTP_STOP);
|
||||
return result;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -1272,10 +1263,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
|
|||
if(result) {
|
||||
failf(data, "Failure sending PORT command: %s",
|
||||
curl_easy_strerror(result));
|
||||
Curl_closesocket(data, conn, portsock);
|
||||
/* bail out */
|
||||
state(data, FTP_STOP);
|
||||
return result;
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -1284,23 +1272,21 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
|
|||
/* store which command was sent */
|
||||
ftpc->count1 = fcmd;
|
||||
|
||||
close_secondarysocket(data, conn);
|
||||
|
||||
/* we set the secondary socket variable to this for now, it is only so that
|
||||
the cleanup function will close it in case we fail before the true
|
||||
secondary stuff is made */
|
||||
conn->sock[SECONDARYSOCKET] = portsock;
|
||||
|
||||
/* this tcpconnect assignment below is a hackish work-around to make the
|
||||
multi interface with active FTP work - as it will not wait for a
|
||||
(passive) connect in Curl_is_connected().
|
||||
|
||||
The *proper* fix is to make sure that the active connection from the
|
||||
server is done in a non-blocking way. Currently, it is still BLOCKING.
|
||||
*/
|
||||
conn->bits.tcpconnect[SECONDARYSOCKET] = TRUE;
|
||||
|
||||
/* Replace any filter on SECONDARY with one listeing on this socket */
|
||||
result = Curl_cfilter_socket_accepted_set(data, conn, SECONDARYSOCKET,
|
||||
&portsock);
|
||||
if(result)
|
||||
goto out;
|
||||
portsock = CURL_SOCKET_BAD; /* now held in filter */
|
||||
state(data, FTP_PORT);
|
||||
|
||||
out:
|
||||
if(result) {
|
||||
state(data, FTP_STOP);
|
||||
}
|
||||
if(portsock != CURL_SOCKET_BAD)
|
||||
Curl_closesocket(data, conn, portsock);
|
||||
free(addr);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -1803,6 +1789,8 @@ static CURLcode ftp_epsv_disable(struct Curl_easy *data,
|
|||
infof(data, "Failed EPSV attempt. Disabling EPSV");
|
||||
/* disable it for next transfer */
|
||||
conn->bits.ftp_use_epsv = FALSE;
|
||||
Curl_cfilter_close(data, conn, SECONDARYSOCKET);
|
||||
Curl_cfilter_destroy(data, conn, SECONDARYSOCKET);
|
||||
data->state.errorbuf = FALSE; /* allow error message to get
|
||||
rewritten */
|
||||
result = Curl_pp_sendf(data, &conn->proto.ftpc.pp, "%s", "PASV");
|
||||
|
|
@ -1992,8 +1980,9 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data,
|
|||
}
|
||||
}
|
||||
|
||||
conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE;
|
||||
result = Curl_connecthost(data, conn, addr);
|
||||
result = Curl_cfilter_setup(data, conn, SECONDARYSOCKET, addr,
|
||||
conn->bits.ftp_use_data_ssl?
|
||||
CURL_CF_SSL_ENABLE : CURL_CF_SSL_DISABLE);
|
||||
|
||||
if(result) {
|
||||
Curl_resolv_unlock(data, addr); /* we're done using this address */
|
||||
|
|
@ -2209,6 +2198,7 @@ static CURLcode ftp_state_retr(struct Curl_easy *data,
|
|||
struct connectdata *conn = data->conn;
|
||||
struct ftp_conn *ftpc = &conn->proto.ftpc;
|
||||
|
||||
DEBUGF(infof(data, "ftp_state_retr()"));
|
||||
if(data->set.max_filesize && (filesize > data->set.max_filesize)) {
|
||||
failf(data, "Maximum file size exceeded");
|
||||
return CURLE_FILESIZE_EXCEEDED;
|
||||
|
|
@ -2755,8 +2745,9 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
|
|||
*/
|
||||
|
||||
if((ftpcode == 234) || (ftpcode == 334)) {
|
||||
/* Curl_ssl_connect is BLOCKING */
|
||||
result = Curl_ssl_connect(data, conn, FIRSTSOCKET);
|
||||
/* this was BLOCKING, keep it so for now */
|
||||
bool done;
|
||||
result = Curl_cfilter_connect(data, conn, FIRSTSOCKET, TRUE, &done);
|
||||
if(!result) {
|
||||
conn->bits.ftp_use_data_ssl = FALSE; /* clear-text data */
|
||||
conn->bits.ftp_use_control_ssl = TRUE; /* SSL on control */
|
||||
|
|
@ -3166,7 +3157,7 @@ static CURLcode ftp_connect(struct Curl_easy *data,
|
|||
|
||||
if(conn->handler->flags & PROTOPT_SSL) {
|
||||
/* BLOCKING */
|
||||
result = Curl_ssl_connect(data, conn, FIRSTSOCKET);
|
||||
result = Curl_cfilter_connect(data, conn, FIRSTSOCKET, TRUE, done);
|
||||
if(result)
|
||||
return result;
|
||||
conn->bits.ftp_use_control_ssl = TRUE;
|
||||
|
|
@ -3309,14 +3300,6 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status,
|
|||
}
|
||||
}
|
||||
|
||||
if(conn->ssl[SECONDARYSOCKET].use) {
|
||||
/* The secondary socket is using SSL so we must close down that part
|
||||
first before we close the socket for real */
|
||||
Curl_ssl_close(data, conn, SECONDARYSOCKET);
|
||||
|
||||
/* Note that we keep "use" set to TRUE since that (next) connection is
|
||||
still requested to use SSL */
|
||||
}
|
||||
close_secondarysocket(data, conn);
|
||||
}
|
||||
|
||||
|
|
@ -3571,22 +3554,10 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
|
|||
struct FTP *ftp = NULL;
|
||||
|
||||
/* if the second connection isn't done yet, wait for it */
|
||||
if(!conn->bits.tcpconnect[SECONDARYSOCKET]) {
|
||||
if(Curl_connect_ongoing(conn)) {
|
||||
/* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
|
||||
aren't used so we blank their arguments. */
|
||||
result = Curl_proxyCONNECT(data, SECONDARYSOCKET, NULL, 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
result = Curl_is_connected(data, conn, SECONDARYSOCKET, &connected);
|
||||
|
||||
/* Ready to do more? */
|
||||
if(connected) {
|
||||
DEBUGF(infof(data, "DO-MORE connected phase starts"));
|
||||
}
|
||||
else {
|
||||
if(conn->cfilter[SECONDARYSOCKET]) {
|
||||
result = Curl_cfilter_connect(data, conn, SECONDARYSOCKET,
|
||||
FALSE, &connected);
|
||||
if(result || !connected) {
|
||||
if(result && (ftpc->count1 == 0)) {
|
||||
*completep = -1; /* go back to DOING please */
|
||||
/* this is a EPSV connect failing, try PASV instead */
|
||||
|
|
@ -3596,19 +3567,6 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
result = Curl_proxy_connect(data, SECONDARYSOCKET);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(CONNECT_SECONDARYSOCKET_PROXY_SSL())
|
||||
return result;
|
||||
|
||||
if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
|
||||
Curl_connect_ongoing(conn))
|
||||
return result;
|
||||
#endif
|
||||
|
||||
/* Curl_proxy_connect might have moved the protocol state */
|
||||
ftp = data->req.p.ftp;
|
||||
|
||||
|
|
@ -3738,7 +3696,6 @@ CURLcode ftp_perform(struct Curl_easy *data,
|
|||
{
|
||||
/* this is FTP and no proxy */
|
||||
CURLcode result = CURLE_OK;
|
||||
struct connectdata *conn = data->conn;
|
||||
|
||||
DEBUGF(infof(data, "DO phase starts"));
|
||||
|
||||
|
|
@ -3758,7 +3715,7 @@ CURLcode ftp_perform(struct Curl_easy *data,
|
|||
/* run the state-machine */
|
||||
result = ftp_multi_statemach(data, dophase_done);
|
||||
|
||||
*connected = conn->bits.tcpconnect[SECONDARYSOCKET];
|
||||
*connected = Curl_cfilter_is_connected(data, data->conn, SECONDARYSOCKET);
|
||||
|
||||
infof(data, "ftp_perform ends with SECONDARY: %d", *connected);
|
||||
|
||||
|
|
@ -4374,6 +4331,7 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data,
|
|||
{
|
||||
char *type;
|
||||
struct FTP *ftp;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
data->req.p.ftp = ftp = calloc(sizeof(struct FTP), 1);
|
||||
if(!ftp)
|
||||
|
|
@ -4415,7 +4373,7 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data,
|
|||
ftp->downloadsize = 0;
|
||||
conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
|
||||
|
||||
return CURLE_OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* CURL_DISABLE_FTP */
|
||||
|
|
|
|||
|
|
@ -533,13 +533,7 @@ static CURLcode getinfo_slist(struct Curl_easy *data, CURLINFO info,
|
|||
|
||||
#ifdef USE_SSL
|
||||
if(conn && tsi->backend != CURLSSLBACKEND_NONE) {
|
||||
unsigned int i;
|
||||
for(i = 0; i < (sizeof(conn->ssl) / sizeof(conn->ssl[0])); ++i) {
|
||||
if(conn->ssl[i].use) {
|
||||
tsi->internals = Curl_ssl->get_internals(&conn->ssl[i], info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
tsi->internals = Curl_ssl_get_internals(data, FIRSTSOCKET, info, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <curl/curl.h>
|
||||
#include "transfer.h"
|
||||
#include "sendf.h"
|
||||
#include "cfilters.h"
|
||||
#include "connect.h"
|
||||
#include "progress.h"
|
||||
#include "gopher.h"
|
||||
|
|
@ -117,7 +118,9 @@ static CURLcode gopher_connect(struct Curl_easy *data, bool *done)
|
|||
static CURLcode gopher_connecting(struct Curl_easy *data, bool *done)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
CURLcode result = Curl_ssl_connect(data, conn, FIRSTSOCKET);
|
||||
CURLcode result;
|
||||
|
||||
result = Curl_cfilter_connect(data, conn, FIRSTSOCKET, TRUE, done);
|
||||
if(result)
|
||||
connclose(conn, "Failed TLS connection");
|
||||
*done = TRUE;
|
||||
|
|
|
|||
77
lib/http.c
77
lib/http.c
|
|
@ -80,6 +80,7 @@
|
|||
#include "http_proxy.h"
|
||||
#include "warnless.h"
|
||||
#include "http2.h"
|
||||
#include "cfilters.h"
|
||||
#include "connect.h"
|
||||
#include "strdup.h"
|
||||
#include "altsvc.h"
|
||||
|
|
@ -105,14 +106,6 @@ static bool http_should_fail(struct Curl_easy *data);
|
|||
static CURLcode add_haproxy_protocol_header(struct Curl_easy *data);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSL
|
||||
static CURLcode https_connecting(struct Curl_easy *data, bool *done);
|
||||
static int https_getsock(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
curl_socket_t *socks);
|
||||
#else
|
||||
#define https_connecting(x,y) CURLE_COULDNT_CONNECT
|
||||
#endif
|
||||
static CURLcode http_setup_conn(struct Curl_easy *data,
|
||||
struct connectdata *conn);
|
||||
#ifdef USE_WEBSOCKETS
|
||||
|
|
@ -184,9 +177,9 @@ const struct Curl_handler Curl_handler_https = {
|
|||
Curl_http_done, /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
Curl_http_connect, /* connect_it */
|
||||
https_connecting, /* connecting */
|
||||
NULL, /* connecting */
|
||||
ZERO_NULL, /* doing */
|
||||
https_getsock, /* proto_getsock */
|
||||
NULL, /* proto_getsock */
|
||||
http_getsock_do, /* doing_getsock */
|
||||
ZERO_NULL, /* domore_getsock */
|
||||
ZERO_NULL, /* perform_getsock */
|
||||
|
|
@ -209,9 +202,9 @@ const struct Curl_handler Curl_handler_wss = {
|
|||
Curl_http_done, /* done */
|
||||
ZERO_NULL, /* do_more */
|
||||
Curl_http_connect, /* connect_it */
|
||||
https_connecting, /* connecting */
|
||||
NULL, /* connecting */
|
||||
ZERO_NULL, /* doing */
|
||||
https_getsock, /* proto_getsock */
|
||||
NULL, /* proto_getsock */
|
||||
http_getsock_do, /* doing_getsock */
|
||||
ZERO_NULL, /* domore_getsock */
|
||||
ZERO_NULL, /* perform_getsock */
|
||||
|
|
@ -1555,23 +1548,11 @@ CURLcode Curl_http_connect(struct Curl_easy *data, bool *done)
|
|||
function to make the re-use checks properly be able to check this bit. */
|
||||
connkeep(conn, "HTTP default");
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
/* the CONNECT procedure might not have been completed */
|
||||
result = Curl_proxy_connect(data, FIRSTSOCKET);
|
||||
if(result)
|
||||
result = Curl_cfilter_connect(data, conn, FIRSTSOCKET, FALSE, done);
|
||||
if(result || !*done)
|
||||
return result;
|
||||
|
||||
if(conn->bits.proxy_connect_closed)
|
||||
/* this is not an error, just part of the connection negotiation */
|
||||
return CURLE_OK;
|
||||
|
||||
if(CONNECT_FIRSTSOCKET_PROXY_SSL())
|
||||
return CURLE_OK; /* wait for HTTPS proxy SSL initialization to complete */
|
||||
|
||||
if(Curl_connect_ongoing(conn))
|
||||
/* nothing else to do except wait right now - we're not done here. */
|
||||
return CURLE_OK;
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
if(data->set.haproxyprotocol && !data->state.is_haproxy_hdr_sent) {
|
||||
/* add HAProxy PROXY protocol header */
|
||||
result = add_haproxy_protocol_header(data);
|
||||
|
|
@ -1583,15 +1564,6 @@ CURLcode Curl_http_connect(struct Curl_easy *data, bool *done)
|
|||
}
|
||||
#endif
|
||||
|
||||
if(conn->given->flags & PROTOPT_SSL) {
|
||||
/* perform SSL initialization */
|
||||
result = https_connecting(data, done);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
else
|
||||
*done = TRUE;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
|
@ -1644,39 +1616,6 @@ static CURLcode add_haproxy_protocol_header(struct Curl_easy *data)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSL
|
||||
static CURLcode https_connecting(struct Curl_easy *data, bool *done)
|
||||
{
|
||||
CURLcode result;
|
||||
struct connectdata *conn = data->conn;
|
||||
DEBUGASSERT((data) && (data->conn->handler->flags & PROTOPT_SSL));
|
||||
|
||||
#ifdef ENABLE_QUIC
|
||||
if(conn->transport == TRNSPRT_QUIC) {
|
||||
*done = TRUE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* perform SSL initialization for this socket */
|
||||
result = Curl_ssl_connect_nonblocking(data, conn, FALSE, FIRSTSOCKET, done);
|
||||
if(result)
|
||||
connclose(conn, "Failed HTTPS connection");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int https_getsock(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
curl_socket_t *socks)
|
||||
{
|
||||
(void)data;
|
||||
if(conn->handler->flags & PROTOPT_SSL)
|
||||
return Curl_ssl->getsock(conn, socks);
|
||||
return GETSOCK_BLANK;
|
||||
}
|
||||
#endif /* USE_SSL */
|
||||
|
||||
/*
|
||||
* Curl_http_done() gets called after a single HTTP request has been
|
||||
* performed.
|
||||
|
|
|
|||
1868
lib/http_proxy.c
1868
lib/http_proxy.c
File diff suppressed because it is too large
Load diff
|
|
@ -28,54 +28,14 @@
|
|||
#include "urldata.h"
|
||||
|
||||
#if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP)
|
||||
/* ftp can use this as well */
|
||||
CURLcode Curl_proxyCONNECT(struct Curl_easy *data,
|
||||
int tunnelsocket,
|
||||
const char *hostname, int remote_port);
|
||||
|
||||
/* Default proxy timeout in milliseconds */
|
||||
#define PROXY_TIMEOUT (3600*1000)
|
||||
|
||||
CURLcode Curl_proxy_connect(struct Curl_easy *data, int sockindex);
|
||||
CURLcode Curl_cfilter_http_proxy_add(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex);
|
||||
|
||||
bool Curl_connect_complete(struct connectdata *conn);
|
||||
bool Curl_connect_ongoing(struct connectdata *conn);
|
||||
int Curl_connect_getsock(struct connectdata *conn);
|
||||
void Curl_connect_done(struct Curl_easy *data);
|
||||
|
||||
#else
|
||||
#define Curl_proxyCONNECT(x,y,z,w) CURLE_NOT_BUILT_IN
|
||||
#define Curl_proxy_connect(x,y) CURLE_OK
|
||||
#define Curl_connect_complete(x) CURLE_OK
|
||||
#define Curl_connect_ongoing(x) FALSE
|
||||
#define Curl_connect_getsock(x) 0
|
||||
#define Curl_connect_done(x)
|
||||
#endif
|
||||
|
||||
void Curl_connect_free(struct Curl_easy *data);
|
||||
|
||||
/* struct for HTTP CONNECT state data */
|
||||
struct http_connect_state {
|
||||
struct HTTP http_proxy;
|
||||
struct HTTP *prot_save;
|
||||
struct dynbuf rcvbuf;
|
||||
struct dynbuf req;
|
||||
size_t nsend;
|
||||
size_t headerlines;
|
||||
enum keeponval {
|
||||
KEEPON_DONE,
|
||||
KEEPON_CONNECT,
|
||||
KEEPON_IGNORE
|
||||
} keepon;
|
||||
curl_off_t cl; /* size of content to read and ignore */
|
||||
enum {
|
||||
TUNNEL_INIT, /* init/default/no tunnel state */
|
||||
TUNNEL_CONNECT, /* CONNECT has been sent off */
|
||||
TUNNEL_COMPLETE, /* CONNECT response received completely */
|
||||
TUNNEL_EXIT
|
||||
} tunnel_state;
|
||||
BIT(chunked_encoding);
|
||||
BIT(close_connection);
|
||||
};
|
||||
|
||||
#endif /* HEADER_CURL_HTTP_PROXY_H */
|
||||
|
|
|
|||
22
lib/imap.c
22
lib/imap.c
|
|
@ -75,6 +75,7 @@
|
|||
#include "strtoofft.h"
|
||||
#include "strcase.h"
|
||||
#include "vtls/vtls.h"
|
||||
#include "cfilters.h"
|
||||
#include "connect.h"
|
||||
#include "select.h"
|
||||
#include "multiif.h"
|
||||
|
|
@ -478,9 +479,16 @@ static CURLcode imap_perform_upgrade_tls(struct Curl_easy *data,
|
|||
{
|
||||
/* Start the SSL connection */
|
||||
struct imap_conn *imapc = &conn->proto.imapc;
|
||||
CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
|
||||
FIRSTSOCKET, &imapc->ssldone);
|
||||
CURLcode result;
|
||||
|
||||
if(!Curl_cfilter_ssl_added(data, conn, FIRSTSOCKET)) {
|
||||
result = Curl_cfilter_ssl_add(data, conn, FIRSTSOCKET);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = Curl_cfilter_connect(data, conn, FIRSTSOCKET,
|
||||
FALSE, &imapc->ssldone);
|
||||
if(!result) {
|
||||
if(imapc->state != IMAP_UPGRADETLS)
|
||||
state(data, IMAP_UPGRADETLS);
|
||||
|
|
@ -490,7 +498,7 @@ static CURLcode imap_perform_upgrade_tls(struct Curl_easy *data,
|
|||
result = imap_perform_capability(data, conn);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -950,7 +958,7 @@ static CURLcode imap_state_capability_resp(struct Curl_easy *data,
|
|||
line += wordlen;
|
||||
}
|
||||
}
|
||||
else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
|
||||
else if(data->set.use_ssl && !Curl_ssl_use(conn, FIRSTSOCKET)) {
|
||||
/* PREAUTH is not compatible with STARTTLS. */
|
||||
if(imapcode == IMAP_RESP_OK && imapc->tls_supported && !imapc->preauth) {
|
||||
/* Switch to TLS connection now */
|
||||
|
|
@ -1384,8 +1392,8 @@ static CURLcode imap_multi_statemach(struct Curl_easy *data, bool *done)
|
|||
struct imap_conn *imapc = &conn->proto.imapc;
|
||||
|
||||
if((conn->handler->flags & PROTOPT_SSL) && !imapc->ssldone) {
|
||||
result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
|
||||
FIRSTSOCKET, &imapc->ssldone);
|
||||
result = Curl_cfilter_connect(data, conn, FIRSTSOCKET,
|
||||
FALSE, &imapc->ssldone);
|
||||
if(result || !imapc->ssldone)
|
||||
return result;
|
||||
}
|
||||
|
|
@ -1602,7 +1610,7 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected,
|
|||
/* Run the state-machine */
|
||||
result = imap_multi_statemach(data, dophase_done);
|
||||
|
||||
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
|
||||
*connected = Curl_cfilter_is_connected(data, conn, FIRSTSOCKET);
|
||||
|
||||
if(*dophase_done)
|
||||
DEBUGF(infof(data, "DO phase is complete"));
|
||||
|
|
|
|||
146
lib/multi.c
146
lib/multi.c
|
|
@ -29,6 +29,7 @@
|
|||
#include "urldata.h"
|
||||
#include "transfer.h"
|
||||
#include "url.h"
|
||||
#include "cfilters.h"
|
||||
#include "connect.h"
|
||||
#include "progress.h"
|
||||
#include "easyif.h"
|
||||
|
|
@ -160,7 +161,7 @@ static void mstate(struct Curl_easy *data, CURLMstate state
|
|||
NULL, /* TUNNELING */
|
||||
NULL, /* PROTOCONNECT */
|
||||
NULL, /* PROTOCONNECTING */
|
||||
Curl_connect_free, /* DO */
|
||||
NULL, /* DO */
|
||||
NULL, /* DOING */
|
||||
NULL, /* DOING_MORE */
|
||||
before_perform, /* DID */
|
||||
|
|
@ -709,6 +710,11 @@ static CURLcode multi_done(struct Curl_easy *data,
|
|||
#endif
|
||||
) || conn->bits.close
|
||||
|| (premature && !(conn->handler->flags & PROTOPT_STREAM))) {
|
||||
DEBUGF(infof(data, "multi_done, not re-using connection=%ld, forbid=%d"
|
||||
", close=%d, premature=%d, stream=%d",
|
||||
conn->connection_id,
|
||||
data->set.reuse_forbid, conn->bits.close, premature,
|
||||
(conn->handler->flags & PROTOPT_STREAM)));
|
||||
connclose(conn, "disconnecting");
|
||||
Curl_conncache_remove_conn(data, conn, FALSE);
|
||||
CONNCACHE_UNLOCK(data);
|
||||
|
|
@ -948,9 +954,8 @@ void Curl_detach_connection(struct Curl_easy *data)
|
|||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
if(conn) {
|
||||
Curl_connect_done(data); /* if mid-CONNECT, shut it down */
|
||||
Curl_cfilter_detach_data(conn, data);
|
||||
Curl_llist_remove(&conn->easyq, &data->conn_queue, NULL);
|
||||
Curl_ssl_detach_conn(data, conn);
|
||||
}
|
||||
data->conn = NULL;
|
||||
}
|
||||
|
|
@ -968,53 +973,9 @@ void Curl_attach_connection(struct Curl_easy *data,
|
|||
data->conn = conn;
|
||||
Curl_llist_insert_next(&conn->easyq, conn->easyq.tail, data,
|
||||
&data->conn_queue);
|
||||
Curl_cfilter_attach_data(conn, data);
|
||||
if(conn->handler->attach)
|
||||
conn->handler->attach(data, conn);
|
||||
Curl_ssl_associate_conn(data, conn);
|
||||
}
|
||||
|
||||
static int waitconnect_getsock(struct connectdata *conn,
|
||||
curl_socket_t *sock)
|
||||
{
|
||||
int i;
|
||||
int s = 0;
|
||||
int rc = 0;
|
||||
|
||||
#ifdef USE_SSL
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
if(CONNECT_FIRSTSOCKET_PROXY_SSL())
|
||||
return Curl_ssl->getsock(conn, sock);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if(SOCKS_STATE(conn->cnnct.state))
|
||||
return Curl_SOCKS_getsock(conn, sock, FIRSTSOCKET);
|
||||
|
||||
for(i = 0; i<2; i++) {
|
||||
if(conn->tempsock[i] != CURL_SOCKET_BAD) {
|
||||
sock[s] = conn->tempsock[i];
|
||||
rc |= GETSOCK_WRITESOCK(s);
|
||||
#ifdef ENABLE_QUIC
|
||||
if(conn->transport == TRNSPRT_QUIC)
|
||||
/* when connecting QUIC, we want to read the socket too */
|
||||
rc |= GETSOCK_READSOCK(s);
|
||||
#endif
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int waitproxyconnect_getsock(struct connectdata *conn,
|
||||
curl_socket_t *sock)
|
||||
{
|
||||
sock[0] = conn->sock[FIRSTSOCKET];
|
||||
|
||||
if(conn->connect_state)
|
||||
return Curl_connect_getsock(conn);
|
||||
|
||||
return GETSOCK_WRITESOCK(0);
|
||||
}
|
||||
|
||||
static int domore_getsock(struct Curl_easy *data,
|
||||
|
|
@ -1076,10 +1037,8 @@ static int multi_getsock(struct Curl_easy *data,
|
|||
return doing_getsock(data, conn, socks);
|
||||
|
||||
case MSTATE_TUNNELING:
|
||||
return waitproxyconnect_getsock(conn, socks);
|
||||
|
||||
case MSTATE_CONNECTING:
|
||||
return waitconnect_getsock(conn, socks);
|
||||
return Curl_cfilter_get_select_socks(data, conn, FIRSTSOCKET, socks);
|
||||
|
||||
case MSTATE_DOING_MORE:
|
||||
return domore_getsock(data, conn, socks);
|
||||
|
|
@ -1737,7 +1696,8 @@ static CURLcode protocol_connect(struct Curl_easy *data,
|
|||
|
||||
*protocol_done = FALSE;
|
||||
|
||||
if(conn->bits.tcpconnect[FIRSTSOCKET] && conn->bits.protoconnstart) {
|
||||
if(Curl_cfilter_is_connected(data, conn, FIRSTSOCKET)
|
||||
&& conn->bits.protoconnstart) {
|
||||
/* We already are connected, get back. This may happen when the connect
|
||||
worked fine in the first call, like when we connect to a local server
|
||||
or proxy. Note that we don't know if the protocol is actually done.
|
||||
|
|
@ -1751,21 +1711,6 @@ static CURLcode protocol_connect(struct Curl_easy *data,
|
|||
}
|
||||
|
||||
if(!conn->bits.protoconnstart) {
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
result = Curl_proxy_connect(data, FIRSTSOCKET);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
if(CONNECT_FIRSTSOCKET_PROXY_SSL())
|
||||
/* wait for HTTPS proxy SSL initialization to complete */
|
||||
return CURLE_OK;
|
||||
|
||||
if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
|
||||
Curl_connect_ongoing(conn))
|
||||
/* when using an HTTP tunnel proxy, await complete tunnel establishment
|
||||
before proceeding further. Return CURLE_OK so we'll be called again */
|
||||
return CURLE_OK;
|
||||
#endif
|
||||
if(conn->handler->connect_it) {
|
||||
/* is there a protocol-specific connect() procedure? */
|
||||
|
||||
|
|
@ -1901,7 +1846,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||
if(data->set.connecttimeout)
|
||||
Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT);
|
||||
|
||||
result = Curl_connect(data, &async, &protocol_connected);
|
||||
result = Curl_connect(data, &async, &connected);
|
||||
if(CURLE_NO_CONNECTION_AVAILABLE == result) {
|
||||
/* There was no connection available. We will go to the pending
|
||||
state and wait for an available connection. */
|
||||
|
|
@ -1929,15 +1874,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||
WAITDO or DO! */
|
||||
rc = CURLM_CALL_MULTI_PERFORM;
|
||||
|
||||
if(protocol_connected)
|
||||
multistate(data, MSTATE_DO);
|
||||
if(connected)
|
||||
multistate(data, MSTATE_PROTOCONNECT);
|
||||
else {
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
if(Curl_connect_ongoing(data->conn))
|
||||
multistate(data, MSTATE_TUNNELING);
|
||||
else
|
||||
#endif
|
||||
multistate(data, MSTATE_CONNECTING);
|
||||
multistate(data, MSTATE_CONNECTING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1989,7 +1929,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||
if(dns) {
|
||||
/* Perform the next step in the connection phase, and then move on
|
||||
to the WAITCONNECT state */
|
||||
result = Curl_once_resolved(data, &protocol_connected);
|
||||
result = Curl_once_resolved(data, &connected);
|
||||
|
||||
if(result)
|
||||
/* if Curl_once_resolved() returns failure, the connection struct
|
||||
|
|
@ -1998,15 +1938,10 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||
else {
|
||||
/* call again please so that we get the next socket setup */
|
||||
rc = CURLM_CALL_MULTI_PERFORM;
|
||||
if(protocol_connected)
|
||||
multistate(data, MSTATE_DO);
|
||||
if(connected)
|
||||
multistate(data, MSTATE_PROTOCONNECT);
|
||||
else {
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
if(Curl_connect_ongoing(data->conn))
|
||||
multistate(data, MSTATE_TUNNELING);
|
||||
else
|
||||
#endif
|
||||
multistate(data, MSTATE_CONNECTING);
|
||||
multistate(data, MSTATE_CONNECTING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2035,16 +1970,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||
else
|
||||
#endif
|
||||
if(!result) {
|
||||
if(
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
(data->conn->http_proxy.proxytype != CURLPROXY_HTTPS ||
|
||||
data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) &&
|
||||
#endif
|
||||
Curl_connect_complete(data->conn)) {
|
||||
rc = CURLM_CALL_MULTI_PERFORM;
|
||||
/* initiate protocol connect phase */
|
||||
multistate(data, MSTATE_PROTOCONNECT);
|
||||
}
|
||||
rc = CURLM_CALL_MULTI_PERFORM;
|
||||
/* initiate protocol connect phase */
|
||||
multistate(data, MSTATE_PROTOCONNECT);
|
||||
}
|
||||
else
|
||||
stream_error = TRUE;
|
||||
|
|
@ -2054,27 +1982,11 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||
case MSTATE_CONNECTING:
|
||||
/* awaiting a completion of an asynch TCP connect */
|
||||
DEBUGASSERT(data->conn);
|
||||
result = Curl_is_connected(data, data->conn, FIRSTSOCKET, &connected);
|
||||
result = Curl_cfilter_connect(data, data->conn, FIRSTSOCKET,
|
||||
FALSE, &connected);
|
||||
if(connected && !result) {
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
if(
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
(data->conn->http_proxy.proxytype == CURLPROXY_HTTPS &&
|
||||
!data->conn->bits.proxy_ssl_connected[FIRSTSOCKET]) ||
|
||||
#endif
|
||||
Curl_connect_ongoing(data->conn)) {
|
||||
multistate(data, MSTATE_TUNNELING);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
rc = CURLM_CALL_MULTI_PERFORM;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
multistate(data,
|
||||
data->conn->bits.tunnel_proxy?
|
||||
MSTATE_TUNNELING : MSTATE_PROTOCONNECT);
|
||||
#else
|
||||
multistate(data, MSTATE_PROTOCONNECT);
|
||||
#endif
|
||||
}
|
||||
else if(result) {
|
||||
/* failure detected */
|
||||
|
|
@ -2086,6 +1998,14 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
|
|||
break;
|
||||
|
||||
case MSTATE_PROTOCONNECT:
|
||||
if(data->conn->bits.reuse) {
|
||||
/* ftp seems to hang when protoconnect on reused connection
|
||||
* since we handle PROTOCONNECT in general inside the filers, it
|
||||
* seems wrong to restart this on a reused connection. */
|
||||
multistate(data, MSTATE_DO);
|
||||
rc = CURLM_CALL_MULTI_PERFORM;
|
||||
break;
|
||||
}
|
||||
result = protocol_connect(data, &protocol_connected);
|
||||
if(!result && !protocol_connected)
|
||||
/* switch to waiting state */
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
#include "transfer.h"
|
||||
#include "curl_ldap.h"
|
||||
#include "curl_base64.h"
|
||||
#include "cfilters.h"
|
||||
#include "connect.h"
|
||||
#include "curl_sasl.h"
|
||||
#include "strcase.h"
|
||||
|
|
@ -500,8 +501,7 @@ static CURLcode oldap_ssl_connect(struct Curl_easy *data, ldapstate newstate)
|
|||
struct ldapconninfo *li = conn->proto.ldapc;
|
||||
bool ssldone = 0;
|
||||
|
||||
result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
|
||||
FIRSTSOCKET, &ssldone);
|
||||
result = Curl_cfilter_connect(data, FIRSTSOCKET, FALSE, &ssldone);
|
||||
if(!result) {
|
||||
state(data, newstate);
|
||||
|
||||
|
|
@ -1153,7 +1153,7 @@ ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg)
|
|||
(void)arg;
|
||||
if(opt == LBER_SB_OPT_DATA_READY) {
|
||||
struct Curl_easy *data = sbiod->sbiod_pvt;
|
||||
return Curl_ssl_data_pending(data->conn, FIRSTSOCKET);
|
||||
return Curl_cfilter_data_pending(data->conn, FIRSTSOCKET);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "curl_setup.h"
|
||||
|
||||
#include "urldata.h"
|
||||
#include "cfilters.h"
|
||||
#include "sendf.h"
|
||||
#include "select.h"
|
||||
#include "progress.h"
|
||||
|
|
@ -102,12 +103,12 @@ CURLcode Curl_pp_statemach(struct Curl_easy *data,
|
|||
else
|
||||
interval_ms = 0; /* immediate */
|
||||
|
||||
if(Curl_ssl_data_pending(conn, FIRSTSOCKET))
|
||||
if(Curl_cfilter_data_pending(data, conn, FIRSTSOCKET))
|
||||
rc = 1;
|
||||
else if(Curl_pp_moredata(pp))
|
||||
/* We are receiving and there is data in the cache so just read it */
|
||||
rc = 1;
|
||||
else if(!pp->sendleft && Curl_ssl_data_pending(conn, FIRSTSOCKET))
|
||||
else if(!pp->sendleft && Curl_cfilter_data_pending(data, conn, FIRSTSOCKET))
|
||||
/* We are receiving and there is data ready in the SSL library */
|
||||
rc = 1;
|
||||
else
|
||||
|
|
|
|||
25
lib/pop3.c
25
lib/pop3.c
|
|
@ -76,6 +76,7 @@
|
|||
#include "strtoofft.h"
|
||||
#include "strcase.h"
|
||||
#include "vtls/vtls.h"
|
||||
#include "cfilters.h"
|
||||
#include "connect.h"
|
||||
#include "select.h"
|
||||
#include "multiif.h"
|
||||
|
|
@ -373,9 +374,16 @@ static CURLcode pop3_perform_upgrade_tls(struct Curl_easy *data,
|
|||
{
|
||||
/* Start the SSL connection */
|
||||
struct pop3_conn *pop3c = &conn->proto.pop3c;
|
||||
CURLcode result =
|
||||
Curl_ssl_connect_nonblocking(data, conn, FALSE, FIRSTSOCKET,
|
||||
&pop3c->ssldone);
|
||||
CURLcode result;
|
||||
|
||||
if(!Curl_cfilter_ssl_added(data, conn, FIRSTSOCKET)) {
|
||||
result = Curl_cfilter_ssl_add(data, conn, FIRSTSOCKET);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = Curl_cfilter_connect(data, conn, FIRSTSOCKET,
|
||||
FALSE, &pop3c->ssldone);
|
||||
|
||||
if(!result) {
|
||||
if(pop3c->state != POP3_UPGRADETLS)
|
||||
|
|
@ -386,7 +394,7 @@ static CURLcode pop3_perform_upgrade_tls(struct Curl_easy *data,
|
|||
result = pop3_perform_capa(data, conn);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -767,7 +775,7 @@ static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code,
|
|||
if(pop3code != '+')
|
||||
pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
|
||||
|
||||
if(!data->set.use_ssl || conn->ssl[FIRSTSOCKET].use)
|
||||
if(!data->set.use_ssl || Curl_ssl_use(conn, FIRSTSOCKET))
|
||||
result = pop3_perform_authentication(data, conn);
|
||||
else if(pop3code == '+' && pop3c->tls_supported)
|
||||
/* Switch to TLS connection now */
|
||||
|
|
@ -1054,8 +1062,8 @@ static CURLcode pop3_multi_statemach(struct Curl_easy *data, bool *done)
|
|||
struct pop3_conn *pop3c = &conn->proto.pop3c;
|
||||
|
||||
if((conn->handler->flags & PROTOPT_SSL) && !pop3c->ssldone) {
|
||||
result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
|
||||
FIRSTSOCKET, &pop3c->ssldone);
|
||||
result = Curl_cfilter_connect(data, conn, FIRSTSOCKET,
|
||||
FALSE, &pop3c->ssldone);
|
||||
if(result || !pop3c->ssldone)
|
||||
return result;
|
||||
}
|
||||
|
|
@ -1192,7 +1200,6 @@ static CURLcode pop3_perform(struct Curl_easy *data, bool *connected,
|
|||
{
|
||||
/* This is POP3 and no proxy */
|
||||
CURLcode result = CURLE_OK;
|
||||
struct connectdata *conn = data->conn;
|
||||
struct POP3 *pop3 = data->req.p.pop3;
|
||||
|
||||
DEBUGF(infof(data, "DO phase starts"));
|
||||
|
|
@ -1211,7 +1218,7 @@ static CURLcode pop3_perform(struct Curl_easy *data, bool *connected,
|
|||
|
||||
/* Run the state-machine */
|
||||
result = pop3_multi_statemach(data, dophase_done);
|
||||
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
|
||||
*connected = Curl_cfilter_is_connected(data, data->conn, FIRSTSOCKET);
|
||||
|
||||
if(*dophase_done)
|
||||
DEBUGF(infof(data, "DO phase is complete"));
|
||||
|
|
|
|||
|
|
@ -27,10 +27,14 @@
|
|||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include "vtls/vtls.h"
|
||||
#include "sendf.h"
|
||||
#include "timeval.h"
|
||||
#include "rand.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
|
|
|
|||
12
lib/sendf.c
12
lib/sendf.c
|
|
@ -38,6 +38,7 @@
|
|||
|
||||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "cfilters.h"
|
||||
#include "connect.h"
|
||||
#include "vtls/vtls.h"
|
||||
#include "vssh/ssh.h"
|
||||
|
|
@ -159,7 +160,7 @@ static CURLcode pre_receive_plain(struct Curl_easy *data,
|
|||
performed before every send() if any incoming data is
|
||||
available. However, skip this, if buffer is already full. */
|
||||
if((conn->handler->protocol&PROTO_FAMILY_HTTP) != 0 &&
|
||||
conn->recv[num] == Curl_recv_plain &&
|
||||
conn->recv[num] == Curl_cfilter_recv &&
|
||||
(!psnd->buffer || bytestorecv)) {
|
||||
const int readymask = Curl_socket_check(sockfd, CURL_SOCKET_BAD,
|
||||
CURL_SOCKET_BAD, 0);
|
||||
|
|
@ -718,11 +719,14 @@ CURLcode Curl_read(struct Curl_easy *data, /* transfer */
|
|||
|
||||
nread = conn->recv[num](data, num, buffertofill, bytesfromsocket, &result);
|
||||
if(nread < 0)
|
||||
return result;
|
||||
goto out;
|
||||
|
||||
*n += nread;
|
||||
|
||||
return CURLE_OK;
|
||||
result = CURLE_OK;
|
||||
out:
|
||||
/* DEBUGF(infof(data, "Curl_read(handle=%p) -> %d, nread=%ld",
|
||||
data, result, nread)); */
|
||||
return result;
|
||||
}
|
||||
|
||||
/* return 0 on success */
|
||||
|
|
|
|||
24
lib/setopt.c
24
lib/setopt.c
|
|
@ -229,7 +229,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
|||
break;
|
||||
#endif
|
||||
case CURLOPT_TLS13_CIPHERS:
|
||||
if(Curl_ssl_tls13_ciphersuites()) {
|
||||
if(Curl_ssl_supports(data, SSLSUPP_TLS13_CIPHERSUITES)) {
|
||||
/* set preferred list of TLS 1.3 cipher suites */
|
||||
result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST],
|
||||
va_arg(param, char *));
|
||||
|
|
@ -239,7 +239,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
|||
break;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
case CURLOPT_PROXY_TLS13_CIPHERS:
|
||||
if(Curl_ssl_tls13_ciphersuites()) {
|
||||
if(Curl_ssl_supports(data, SSLSUPP_TLS13_CIPHERSUITES)) {
|
||||
/* set preferred list of TLS 1.3 cipher suites for proxy */
|
||||
result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_PROXY],
|
||||
va_arg(param, char *));
|
||||
|
|
@ -2001,7 +2001,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
|||
* Set a SSL_CTX callback
|
||||
*/
|
||||
#ifdef USE_SSL
|
||||
if(Curl_ssl->supports & SSLSUPP_SSL_CTX)
|
||||
if(Curl_ssl_supports(data, SSLSUPP_SSL_CTX))
|
||||
data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
|
||||
else
|
||||
#endif
|
||||
|
|
@ -2012,7 +2012,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
|||
* Set a SSL_CTX callback parameter pointer
|
||||
*/
|
||||
#ifdef USE_SSL
|
||||
if(Curl_ssl->supports & SSLSUPP_SSL_CTX)
|
||||
if(Curl_ssl_supports(data, SSLSUPP_SSL_CTX))
|
||||
data->set.ssl.fsslctxp = va_arg(param, void *);
|
||||
else
|
||||
#endif
|
||||
|
|
@ -2022,7 +2022,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
|||
/*
|
||||
* Enable TLS false start.
|
||||
*/
|
||||
if(!Curl_ssl_false_start()) {
|
||||
if(!Curl_ssl_false_start(data)) {
|
||||
result = CURLE_NOT_BUILT_IN;
|
||||
break;
|
||||
}
|
||||
|
|
@ -2031,7 +2031,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
|||
break;
|
||||
case CURLOPT_CERTINFO:
|
||||
#ifdef USE_SSL
|
||||
if(Curl_ssl->supports & SSLSUPP_CERTINFO)
|
||||
if(Curl_ssl_supports(data, SSLSUPP_CERTINFO))
|
||||
data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
|
||||
else
|
||||
#endif
|
||||
|
|
@ -2043,7 +2043,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
|||
* Specify file name of the public key in DER format.
|
||||
*/
|
||||
#ifdef USE_SSL
|
||||
if(Curl_ssl->supports & SSLSUPP_PINNEDPUBKEY)
|
||||
if(Curl_ssl_supports(data, SSLSUPP_PINNEDPUBKEY))
|
||||
result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY],
|
||||
va_arg(param, char *));
|
||||
else
|
||||
|
|
@ -2057,7 +2057,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
|||
* Specify file name of the public key in DER format.
|
||||
*/
|
||||
#ifdef USE_SSL
|
||||
if(Curl_ssl->supports & SSLSUPP_PINNEDPUBKEY)
|
||||
if(Curl_ssl_supports(data, SSLSUPP_PINNEDPUBKEY))
|
||||
result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
|
||||
va_arg(param, char *));
|
||||
else
|
||||
|
|
@ -2078,7 +2078,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
|||
* Specify entire PEM of the CA certificate
|
||||
*/
|
||||
#ifdef USE_SSL
|
||||
if(Curl_ssl->supports & SSLSUPP_CAINFO_BLOB)
|
||||
if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB))
|
||||
result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO],
|
||||
va_arg(param, struct curl_blob *));
|
||||
else
|
||||
|
|
@ -2101,7 +2101,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
|||
* Specify entire PEM of the CA certificate
|
||||
*/
|
||||
#ifdef USE_SSL
|
||||
if(Curl_ssl->supports & SSLSUPP_CAINFO_BLOB)
|
||||
if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB))
|
||||
result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO_PROXY],
|
||||
va_arg(param, struct curl_blob *));
|
||||
else
|
||||
|
|
@ -2115,7 +2115,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
|||
* certificates which have been prepared using openssl c_rehash utility.
|
||||
*/
|
||||
#ifdef USE_SSL
|
||||
if(Curl_ssl->supports & SSLSUPP_CA_PATH)
|
||||
if(Curl_ssl_supports(data, SSLSUPP_CA_PATH))
|
||||
/* This does not work on windows. */
|
||||
result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH],
|
||||
va_arg(param, char *));
|
||||
|
|
@ -2130,7 +2130,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
|
|||
* CA certificates which have been prepared using openssl c_rehash utility.
|
||||
*/
|
||||
#ifdef USE_SSL
|
||||
if(Curl_ssl->supports & SSLSUPP_CA_PATH)
|
||||
if(Curl_ssl_supports(data, SSLSUPP_CA_PATH))
|
||||
/* This does not work on windows. */
|
||||
result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
|
||||
va_arg(param, char *));
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "multiif.h"
|
||||
#include "cfilters.h"
|
||||
#include "connect.h"
|
||||
#include "progress.h"
|
||||
#include "transfer.h"
|
||||
|
|
@ -666,8 +667,8 @@ static CURLcode smb_connection_state(struct Curl_easy *data, bool *done)
|
|||
#ifdef USE_SSL
|
||||
if((conn->handler->flags & PROTOPT_SSL)) {
|
||||
bool ssl_done = FALSE;
|
||||
result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
|
||||
FIRSTSOCKET, &ssl_done);
|
||||
result = Curl_cfilter_connect(data, conn, FIRSTSOCKET,
|
||||
FALSE, &ssl_done);
|
||||
if(result && result != CURLE_AGAIN)
|
||||
return result;
|
||||
if(!ssl_done)
|
||||
|
|
|
|||
26
lib/smtp.c
26
lib/smtp.c
|
|
@ -79,6 +79,7 @@
|
|||
#include "strtoofft.h"
|
||||
#include "strcase.h"
|
||||
#include "vtls/vtls.h"
|
||||
#include "cfilters.h"
|
||||
#include "connect.h"
|
||||
#include "select.h"
|
||||
#include "multiif.h"
|
||||
|
|
@ -400,10 +401,16 @@ static CURLcode smtp_perform_upgrade_tls(struct Curl_easy *data)
|
|||
/* Start the SSL connection */
|
||||
struct connectdata *conn = data->conn;
|
||||
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
||||
CURLcode result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
|
||||
FIRSTSOCKET,
|
||||
&smtpc->ssldone);
|
||||
CURLcode result;
|
||||
|
||||
if(!Curl_cfilter_ssl_added(data, conn, FIRSTSOCKET)) {
|
||||
result = Curl_cfilter_ssl_add(data, conn, FIRSTSOCKET);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = Curl_cfilter_connect(data, conn, FIRSTSOCKET,
|
||||
FALSE, &smtpc->ssldone);
|
||||
if(!result) {
|
||||
if(smtpc->state != SMTP_UPGRADETLS)
|
||||
state(data, SMTP_UPGRADETLS);
|
||||
|
|
@ -413,7 +420,7 @@ static CURLcode smtp_perform_upgrade_tls(struct Curl_easy *data)
|
|||
result = smtp_perform_ehlo(data);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -888,7 +895,7 @@ static CURLcode smtp_state_ehlo_resp(struct Curl_easy *data,
|
|||
(void)instate; /* no use for this yet */
|
||||
|
||||
if(smtpcode/100 != 2 && smtpcode != 1) {
|
||||
if(data->set.use_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use)
|
||||
if(data->set.use_ssl <= CURLUSESSL_TRY || Curl_ssl_use(conn, FIRSTSOCKET))
|
||||
result = smtp_perform_helo(data, conn);
|
||||
else {
|
||||
failf(data, "Remote access denied: %d", smtpcode);
|
||||
|
|
@ -953,7 +960,7 @@ static CURLcode smtp_state_ehlo_resp(struct Curl_easy *data,
|
|||
}
|
||||
|
||||
if(smtpcode != 1) {
|
||||
if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
|
||||
if(data->set.use_ssl && !Curl_ssl_use(conn, FIRSTSOCKET)) {
|
||||
/* We don't have a SSL/TLS connection yet, but SSL is requested */
|
||||
if(smtpc->tls_supported)
|
||||
/* Switch to TLS connection now */
|
||||
|
|
@ -1285,8 +1292,8 @@ static CURLcode smtp_multi_statemach(struct Curl_easy *data, bool *done)
|
|||
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
||||
|
||||
if((conn->handler->flags & PROTOPT_SSL) && !smtpc->ssldone) {
|
||||
result = Curl_ssl_connect_nonblocking(data, conn, FALSE,
|
||||
FIRSTSOCKET, &smtpc->ssldone);
|
||||
result = Curl_cfilter_connect(data, conn, FIRSTSOCKET,
|
||||
FALSE, &smtpc->ssldone);
|
||||
if(result || !smtpc->ssldone)
|
||||
return result;
|
||||
}
|
||||
|
|
@ -1479,7 +1486,6 @@ static CURLcode smtp_perform(struct Curl_easy *data, bool *connected,
|
|||
{
|
||||
/* This is SMTP and no proxy */
|
||||
CURLcode result = CURLE_OK;
|
||||
struct connectdata *conn = data->conn;
|
||||
struct SMTP *smtp = data->req.p.smtp;
|
||||
|
||||
DEBUGF(infof(data, "DO phase starts"));
|
||||
|
|
@ -1519,7 +1525,7 @@ static CURLcode smtp_perform(struct Curl_easy *data, bool *connected,
|
|||
/* Run the state-machine */
|
||||
result = smtp_multi_statemach(data, dophase_done);
|
||||
|
||||
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
|
||||
*connected = Curl_cfilter_is_connected(data, data->conn, FIRSTSOCKET);
|
||||
|
||||
if(*dophase_done)
|
||||
DEBUGF(infof(data, "DO phase is complete"));
|
||||
|
|
|
|||
417
lib/socks.c
417
lib/socks.c
|
|
@ -36,17 +36,52 @@
|
|||
#include "urldata.h"
|
||||
#include "sendf.h"
|
||||
#include "select.h"
|
||||
#include "cfilters.h"
|
||||
#include "connect.h"
|
||||
#include "timeval.h"
|
||||
#include "socks.h"
|
||||
#include "multiif.h" /* for getsock macros */
|
||||
#include "inet_pton.h"
|
||||
#include "url.h"
|
||||
|
||||
/* The last 3 #include files should be in this order */
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
/* for the (SOCKS) connect state machine */
|
||||
enum connect_t {
|
||||
CONNECT_INIT,
|
||||
CONNECT_SOCKS_INIT, /* 1 */
|
||||
CONNECT_SOCKS_SEND, /* 2 waiting to send more first data */
|
||||
CONNECT_SOCKS_READ_INIT, /* 3 set up read */
|
||||
CONNECT_SOCKS_READ, /* 4 read server response */
|
||||
CONNECT_GSSAPI_INIT, /* 5 */
|
||||
CONNECT_AUTH_INIT, /* 6 setup outgoing auth buffer */
|
||||
CONNECT_AUTH_SEND, /* 7 send auth */
|
||||
CONNECT_AUTH_READ, /* 8 read auth response */
|
||||
CONNECT_REQ_INIT, /* 9 init SOCKS "request" */
|
||||
CONNECT_RESOLVING, /* 10 */
|
||||
CONNECT_RESOLVED, /* 11 */
|
||||
CONNECT_RESOLVE_REMOTE, /* 12 */
|
||||
CONNECT_REQ_SEND, /* 13 */
|
||||
CONNECT_REQ_SENDING, /* 14 */
|
||||
CONNECT_REQ_READ, /* 15 */
|
||||
CONNECT_REQ_READ_MORE, /* 16 */
|
||||
CONNECT_DONE /* 17 connected fine to the remote or the SOCKS proxy */
|
||||
};
|
||||
|
||||
struct socks_state {
|
||||
enum connect_t state;
|
||||
ssize_t outstanding; /* send this many bytes more */
|
||||
unsigned char *outp; /* send from this pointer */
|
||||
|
||||
const char *hostname;
|
||||
int remote_port;
|
||||
const char *proxy_user;
|
||||
const char *proxy_password;
|
||||
};
|
||||
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
/*
|
||||
* Helper read-from-socket functions. Does the same as Curl_read() but it
|
||||
|
|
@ -104,21 +139,20 @@ int Curl_blockread_all(struct Curl_easy *data, /* transfer */
|
|||
|
||||
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
|
||||
#define DEBUG_AND_VERBOSE
|
||||
#define sxstate(x,y) socksstate(x,y, __LINE__)
|
||||
#define sxstate(x,d,y) socksstate(x,d,y, __LINE__)
|
||||
#else
|
||||
#define sxstate(x,y) socksstate(x,y)
|
||||
#define sxstate(x,d,y) socksstate(x,d,y)
|
||||
#endif
|
||||
|
||||
/* always use this function to change state, to make debugging easier */
|
||||
static void socksstate(struct Curl_easy *data,
|
||||
static void socksstate(struct socks_state *sx, struct Curl_easy *data,
|
||||
enum connect_t state
|
||||
#ifdef DEBUG_AND_VERBOSE
|
||||
, int lineno
|
||||
#endif
|
||||
)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
enum connect_t oldstate = conn->cnnct.state;
|
||||
enum connect_t oldstate = sx->state;
|
||||
#ifdef DEBUG_AND_VERBOSE
|
||||
/* synced with the state list in urldata.h */
|
||||
static const char * const statename[] = {
|
||||
|
|
@ -143,40 +177,21 @@ static void socksstate(struct Curl_easy *data,
|
|||
};
|
||||
#endif
|
||||
|
||||
(void)data;
|
||||
if(oldstate == state)
|
||||
/* don't bother when the new state is the same as the old state */
|
||||
return;
|
||||
|
||||
conn->cnnct.state = state;
|
||||
sx->state = state;
|
||||
|
||||
#ifdef DEBUG_AND_VERBOSE
|
||||
infof(data,
|
||||
"SXSTATE: %s => %s conn %p; line %d",
|
||||
statename[oldstate], statename[conn->cnnct.state], conn,
|
||||
"SXSTATE: %s => %s; line %d",
|
||||
statename[oldstate], statename[sx->state],
|
||||
lineno);
|
||||
#endif
|
||||
}
|
||||
|
||||
int Curl_SOCKS_getsock(struct connectdata *conn, curl_socket_t *sock,
|
||||
int sockindex)
|
||||
{
|
||||
int rc = 0;
|
||||
sock[0] = conn->sock[sockindex];
|
||||
switch(conn->cnnct.state) {
|
||||
case CONNECT_RESOLVING:
|
||||
case CONNECT_SOCKS_READ:
|
||||
case CONNECT_AUTH_READ:
|
||||
case CONNECT_REQ_READ:
|
||||
case CONNECT_REQ_READ_MORE:
|
||||
rc = GETSOCK_READSOCK(0);
|
||||
break;
|
||||
default:
|
||||
rc = GETSOCK_WRITESOCK(0);
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function logs in to a SOCKS4 proxy and sends the specifics to the final
|
||||
* destination server.
|
||||
|
|
@ -188,20 +203,16 @@ int Curl_SOCKS_getsock(struct connectdata *conn, curl_socket_t *sock,
|
|||
* Set protocol4a=true for "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)"
|
||||
* Nonsupport "Identification Protocol (RFC1413)"
|
||||
*/
|
||||
CURLproxycode Curl_SOCKS4(const char *proxy_user,
|
||||
const char *hostname,
|
||||
int remote_port,
|
||||
int sockindex,
|
||||
struct Curl_easy *data,
|
||||
bool *done)
|
||||
static CURLproxycode do_SOCKS4(struct Curl_cfilter *cf,
|
||||
struct socks_state *sx,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
struct connectdata *conn = cf->conn;
|
||||
const bool protocol4a =
|
||||
(conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A) ? TRUE : FALSE;
|
||||
unsigned char *socksreq = (unsigned char *)data->state.buffer;
|
||||
CURLcode result;
|
||||
curl_socket_t sockfd = conn->sock[sockindex];
|
||||
struct connstate *sx = &conn->cnnct;
|
||||
curl_socket_t sockfd = conn->sock[cf->sockindex];
|
||||
struct Curl_dns_entry *dns = NULL;
|
||||
ssize_t actualread;
|
||||
ssize_t written;
|
||||
|
|
@ -209,18 +220,16 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
|
|||
/* make sure that the buffer is at least 600 bytes */
|
||||
DEBUGASSERT(READBUFFER_MIN >= 600);
|
||||
|
||||
if(!SOCKS_STATE(sx->state) && !*done)
|
||||
sxstate(data, CONNECT_SOCKS_INIT);
|
||||
|
||||
switch(sx->state) {
|
||||
case CONNECT_SOCKS_INIT:
|
||||
/* SOCKS4 can only do IPv4, insist! */
|
||||
conn->ip_version = CURL_IPRESOLVE_V4;
|
||||
if(conn->bits.httpproxy)
|
||||
infof(data, "SOCKS4%s: connecting to HTTP proxy %s port %d",
|
||||
protocol4a ? "a" : "", hostname, remote_port);
|
||||
protocol4a ? "a" : "", sx->hostname, sx->remote_port);
|
||||
|
||||
infof(data, "SOCKS4 communication to %s:%d", hostname, remote_port);
|
||||
infof(data, "SOCKS4 communication to %s:%d",
|
||||
sx->hostname, sx->remote_port);
|
||||
|
||||
/*
|
||||
* Compose socks4 request
|
||||
|
|
@ -235,40 +244,40 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
|
|||
|
||||
socksreq[0] = 4; /* version (SOCKS4) */
|
||||
socksreq[1] = 1; /* connect */
|
||||
socksreq[2] = (unsigned char)((remote_port >> 8) & 0xff); /* PORT MSB */
|
||||
socksreq[3] = (unsigned char)(remote_port & 0xff); /* PORT LSB */
|
||||
socksreq[2] = (unsigned char)((sx->remote_port >> 8) & 0xff); /* MSB */
|
||||
socksreq[3] = (unsigned char)(sx->remote_port & 0xff); /* LSB */
|
||||
|
||||
/* DNS resolve only for SOCKS4, not SOCKS4a */
|
||||
if(!protocol4a) {
|
||||
enum resolve_t rc =
|
||||
Curl_resolv(data, hostname, remote_port, FALSE, &dns);
|
||||
Curl_resolv(data, sx->hostname, sx->remote_port, FALSE, &dns);
|
||||
|
||||
if(rc == CURLRESOLV_ERROR)
|
||||
return CURLPX_RESOLVE_HOST;
|
||||
else if(rc == CURLRESOLV_PENDING) {
|
||||
sxstate(data, CONNECT_RESOLVING);
|
||||
infof(data, "SOCKS4 non-blocking resolve of %s", hostname);
|
||||
sxstate(sx, data, CONNECT_RESOLVING);
|
||||
infof(data, "SOCKS4 non-blocking resolve of %s", sx->hostname);
|
||||
return CURLPX_OK;
|
||||
}
|
||||
sxstate(data, CONNECT_RESOLVED);
|
||||
sxstate(sx, data, CONNECT_RESOLVED);
|
||||
goto CONNECT_RESOLVED;
|
||||
}
|
||||
|
||||
/* socks4a doesn't resolve anything locally */
|
||||
sxstate(data, CONNECT_REQ_INIT);
|
||||
sxstate(sx, data, CONNECT_REQ_INIT);
|
||||
goto CONNECT_REQ_INIT;
|
||||
|
||||
case CONNECT_RESOLVING:
|
||||
/* check if we have the name resolved by now */
|
||||
dns = Curl_fetch_addr(data, hostname, (int)conn->port);
|
||||
dns = Curl_fetch_addr(data, sx->hostname, (int)conn->port);
|
||||
|
||||
if(dns) {
|
||||
#ifdef CURLRES_ASYNCH
|
||||
data->state.async.dns = dns;
|
||||
data->state.async.done = TRUE;
|
||||
#endif
|
||||
infof(data, "Hostname '%s' was found", hostname);
|
||||
sxstate(data, CONNECT_RESOLVED);
|
||||
infof(data, "Hostname '%s' was found", sx->hostname);
|
||||
sxstate(sx, data, CONNECT_RESOLVED);
|
||||
}
|
||||
else {
|
||||
result = Curl_resolv_check(data, &dns);
|
||||
|
|
@ -309,11 +318,11 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
|
|||
Curl_resolv_unlock(data, dns); /* not used anymore from now on */
|
||||
}
|
||||
else
|
||||
failf(data, "SOCKS4 connection to %s not supported", hostname);
|
||||
failf(data, "SOCKS4 connection to %s not supported", sx->hostname);
|
||||
}
|
||||
else
|
||||
failf(data, "Failed to resolve \"%s\" for SOCKS4 connect.",
|
||||
hostname);
|
||||
sx->hostname);
|
||||
|
||||
if(!hp)
|
||||
return CURLPX_RESOLVE_HOST;
|
||||
|
|
@ -325,14 +334,14 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
|
|||
* This is currently not supporting "Identification Protocol (RFC1413)".
|
||||
*/
|
||||
socksreq[8] = 0; /* ensure empty userid is NUL-terminated */
|
||||
if(proxy_user) {
|
||||
size_t plen = strlen(proxy_user);
|
||||
if(sx->proxy_user) {
|
||||
size_t plen = strlen(sx->proxy_user);
|
||||
if(plen >= (size_t)data->set.buffer_size - 8) {
|
||||
failf(data, "Too long SOCKS proxy user name, can't use");
|
||||
return CURLPX_LONG_USER;
|
||||
}
|
||||
/* copy the proxy name WITH trailing zero */
|
||||
memcpy(socksreq + 8, proxy_user, plen + 1);
|
||||
memcpy(socksreq + 8, sx->proxy_user, plen + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -350,9 +359,9 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
|
|||
socksreq[6] = 0;
|
||||
socksreq[7] = 1;
|
||||
/* append hostname */
|
||||
hostnamelen = strlen(hostname) + 1; /* length including NUL */
|
||||
hostnamelen = strlen(sx->hostname) + 1; /* length including NUL */
|
||||
if(hostnamelen <= 255)
|
||||
strcpy((char *)socksreq + packetsize, hostname);
|
||||
strcpy((char *)socksreq + packetsize, sx->hostname);
|
||||
else {
|
||||
failf(data, "SOCKS4: too long host name");
|
||||
return CURLPX_LONG_HOSTNAME;
|
||||
|
|
@ -361,7 +370,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
|
|||
}
|
||||
sx->outp = socksreq;
|
||||
sx->outstanding = packetsize;
|
||||
sxstate(data, CONNECT_REQ_SENDING);
|
||||
sxstate(sx, data, CONNECT_REQ_SENDING);
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case CONNECT_REQ_SENDING:
|
||||
|
|
@ -382,7 +391,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
|
|||
/* done sending! */
|
||||
sx->outstanding = 8; /* receive data size */
|
||||
sx->outp = socksreq;
|
||||
sxstate(data, CONNECT_SOCKS_READ);
|
||||
sxstate(sx, data, CONNECT_SOCKS_READ);
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case CONNECT_SOCKS_READ:
|
||||
|
|
@ -405,7 +414,7 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
|
|||
sx->outp += actualread;
|
||||
return CURLPX_OK;
|
||||
}
|
||||
sxstate(data, CONNECT_DONE);
|
||||
sxstate(sx, data, CONNECT_DONE);
|
||||
break;
|
||||
default: /* lots of unused states in SOCKS4 */
|
||||
break;
|
||||
|
|
@ -478,7 +487,6 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
|
|||
return CURLPX_UNKNOWN_FAIL;
|
||||
}
|
||||
|
||||
*done = TRUE;
|
||||
return CURLPX_OK; /* Proxy was successful! */
|
||||
}
|
||||
|
||||
|
|
@ -486,13 +494,9 @@ CURLproxycode Curl_SOCKS4(const char *proxy_user,
|
|||
* This function logs in to a SOCKS5 proxy and sends the specifics to the final
|
||||
* destination server.
|
||||
*/
|
||||
CURLproxycode Curl_SOCKS5(const char *proxy_user,
|
||||
const char *proxy_password,
|
||||
const char *hostname,
|
||||
int remote_port,
|
||||
int sockindex,
|
||||
struct Curl_easy *data,
|
||||
bool *done)
|
||||
static CURLproxycode do_SOCKS5(struct Curl_cfilter *cf,
|
||||
struct socks_state *sx,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
/*
|
||||
According to the RFC1928, section "6. Replies". This is what a SOCK5
|
||||
|
|
@ -510,31 +514,27 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
|
|||
o REP Reply field:
|
||||
o X'00' succeeded
|
||||
*/
|
||||
struct connectdata *conn = data->conn;
|
||||
struct connectdata *conn = cf->conn;
|
||||
unsigned char *socksreq = (unsigned char *)data->state.buffer;
|
||||
char dest[256] = "unknown"; /* printable hostname:port */
|
||||
int idx;
|
||||
ssize_t actualread;
|
||||
ssize_t written;
|
||||
CURLcode result;
|
||||
curl_socket_t sockfd = conn->sock[sockindex];
|
||||
curl_socket_t sockfd = conn->sock[cf->sockindex];
|
||||
bool socks5_resolve_local =
|
||||
(conn->socks_proxy.proxytype == CURLPROXY_SOCKS5) ? TRUE : FALSE;
|
||||
const size_t hostname_len = strlen(hostname);
|
||||
const size_t hostname_len = strlen(sx->hostname);
|
||||
ssize_t len = 0;
|
||||
const unsigned long auth = data->set.socks5auth;
|
||||
bool allow_gssapi = FALSE;
|
||||
struct connstate *sx = &conn->cnnct;
|
||||
struct Curl_dns_entry *dns = NULL;
|
||||
|
||||
if(!SOCKS_STATE(sx->state) && !*done)
|
||||
sxstate(data, CONNECT_SOCKS_INIT);
|
||||
|
||||
switch(sx->state) {
|
||||
case CONNECT_SOCKS_INIT:
|
||||
if(conn->bits.httpproxy)
|
||||
infof(data, "SOCKS5: connecting to HTTP proxy %s port %d",
|
||||
hostname, remote_port);
|
||||
sx->hostname, sx->remote_port);
|
||||
|
||||
/* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
|
||||
if(!socks5_resolve_local && hostname_len > 255) {
|
||||
|
|
@ -549,7 +549,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
|
|||
auth);
|
||||
if(!(auth & CURLAUTH_BASIC))
|
||||
/* disable username/password auth */
|
||||
proxy_user = NULL;
|
||||
sx->proxy_user = NULL;
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
if(auth & CURLAUTH_GSSAPI)
|
||||
allow_gssapi = TRUE;
|
||||
|
|
@ -561,7 +561,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
|
|||
socksreq[idx++] = 0; /* no authentication */
|
||||
if(allow_gssapi)
|
||||
socksreq[idx++] = 1; /* GSS-API */
|
||||
if(proxy_user)
|
||||
if(sx->proxy_user)
|
||||
socksreq[idx++] = 2; /* username/password */
|
||||
/* write the number of authentication methods */
|
||||
socksreq[1] = (unsigned char) (idx - 2);
|
||||
|
|
@ -572,12 +572,12 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
|
|||
return CURLPX_SEND_CONNECT;
|
||||
}
|
||||
if(written != idx) {
|
||||
sxstate(data, CONNECT_SOCKS_SEND);
|
||||
sxstate(sx, data, CONNECT_SOCKS_SEND);
|
||||
sx->outstanding = idx - written;
|
||||
sx->outp = &socksreq[written];
|
||||
return CURLPX_OK;
|
||||
}
|
||||
sxstate(data, CONNECT_SOCKS_READ);
|
||||
sxstate(sx, data, CONNECT_SOCKS_READ);
|
||||
goto CONNECT_SOCKS_READ_INIT;
|
||||
case CONNECT_SOCKS_SEND:
|
||||
result = Curl_write_plain(data, sockfd, (char *)sx->outp,
|
||||
|
|
@ -622,18 +622,18 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
|
|||
}
|
||||
else if(socksreq[1] == 0) {
|
||||
/* DONE! No authentication needed. Send request. */
|
||||
sxstate(data, CONNECT_REQ_INIT);
|
||||
sxstate(sx, data, CONNECT_REQ_INIT);
|
||||
goto CONNECT_REQ_INIT;
|
||||
}
|
||||
else if(socksreq[1] == 2) {
|
||||
/* regular name + password authentication */
|
||||
sxstate(data, CONNECT_AUTH_INIT);
|
||||
sxstate(sx, data, CONNECT_AUTH_INIT);
|
||||
goto CONNECT_AUTH_INIT;
|
||||
}
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
else if(allow_gssapi && (socksreq[1] == 1)) {
|
||||
sxstate(data, CONNECT_GSSAPI_INIT);
|
||||
result = Curl_SOCKS5_gssapi_negotiate(sockindex, data);
|
||||
sxstate(sx, data, CONNECT_GSSAPI_INIT);
|
||||
result = Curl_SOCKS5_gssapi_negotiate(cf->sockindex, data);
|
||||
if(result) {
|
||||
failf(data, "Unable to negotiate SOCKS5 GSS-API context.");
|
||||
return CURLPX_GSSAPI;
|
||||
|
|
@ -668,9 +668,9 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
|
|||
case CONNECT_AUTH_INIT: {
|
||||
/* Needs user name and password */
|
||||
size_t proxy_user_len, proxy_password_len;
|
||||
if(proxy_user && proxy_password) {
|
||||
proxy_user_len = strlen(proxy_user);
|
||||
proxy_password_len = strlen(proxy_password);
|
||||
if(sx->proxy_user && sx->proxy_password) {
|
||||
proxy_user_len = strlen(sx->proxy_user);
|
||||
proxy_password_len = strlen(sx->proxy_password);
|
||||
}
|
||||
else {
|
||||
proxy_user_len = 0;
|
||||
|
|
@ -687,26 +687,26 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
|
|||
len = 0;
|
||||
socksreq[len++] = 1; /* username/pw subnegotiation version */
|
||||
socksreq[len++] = (unsigned char) proxy_user_len;
|
||||
if(proxy_user && proxy_user_len) {
|
||||
if(sx->proxy_user && proxy_user_len) {
|
||||
/* the length must fit in a single byte */
|
||||
if(proxy_user_len >= 255) {
|
||||
failf(data, "Excessive user name length for proxy auth");
|
||||
return CURLPX_LONG_USER;
|
||||
}
|
||||
memcpy(socksreq + len, proxy_user, proxy_user_len);
|
||||
memcpy(socksreq + len, sx->proxy_user, proxy_user_len);
|
||||
}
|
||||
len += proxy_user_len;
|
||||
socksreq[len++] = (unsigned char) proxy_password_len;
|
||||
if(proxy_password && proxy_password_len) {
|
||||
if(sx->proxy_password && proxy_password_len) {
|
||||
/* the length must fit in a single byte */
|
||||
if(proxy_password_len > 255) {
|
||||
failf(data, "Excessive password length for proxy auth");
|
||||
return CURLPX_LONG_PASSWD;
|
||||
}
|
||||
memcpy(socksreq + len, proxy_password, proxy_password_len);
|
||||
memcpy(socksreq + len, sx->proxy_password, proxy_password_len);
|
||||
}
|
||||
len += proxy_password_len;
|
||||
sxstate(data, CONNECT_AUTH_SEND);
|
||||
sxstate(sx, data, CONNECT_AUTH_SEND);
|
||||
sx->outstanding = len;
|
||||
sx->outp = socksreq;
|
||||
}
|
||||
|
|
@ -726,7 +726,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
|
|||
}
|
||||
sx->outp = socksreq;
|
||||
sx->outstanding = 2;
|
||||
sxstate(data, CONNECT_AUTH_READ);
|
||||
sxstate(sx, data, CONNECT_AUTH_READ);
|
||||
/* FALLTHROUGH */
|
||||
case CONNECT_AUTH_READ:
|
||||
result = Curl_read_plain(sockfd, (char *)sx->outp,
|
||||
|
|
@ -754,36 +754,36 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
|
|||
}
|
||||
|
||||
/* Everything is good so far, user was authenticated! */
|
||||
sxstate(data, CONNECT_REQ_INIT);
|
||||
sxstate(sx, data, CONNECT_REQ_INIT);
|
||||
/* FALLTHROUGH */
|
||||
CONNECT_REQ_INIT:
|
||||
case CONNECT_REQ_INIT:
|
||||
if(socks5_resolve_local) {
|
||||
enum resolve_t rc = Curl_resolv(data, hostname, remote_port,
|
||||
enum resolve_t rc = Curl_resolv(data, sx->hostname, sx->remote_port,
|
||||
FALSE, &dns);
|
||||
|
||||
if(rc == CURLRESOLV_ERROR)
|
||||
return CURLPX_RESOLVE_HOST;
|
||||
|
||||
if(rc == CURLRESOLV_PENDING) {
|
||||
sxstate(data, CONNECT_RESOLVING);
|
||||
sxstate(sx, data, CONNECT_RESOLVING);
|
||||
return CURLPX_OK;
|
||||
}
|
||||
sxstate(data, CONNECT_RESOLVED);
|
||||
sxstate(sx, data, CONNECT_RESOLVED);
|
||||
goto CONNECT_RESOLVED;
|
||||
}
|
||||
goto CONNECT_RESOLVE_REMOTE;
|
||||
|
||||
case CONNECT_RESOLVING:
|
||||
/* check if we have the name resolved by now */
|
||||
dns = Curl_fetch_addr(data, hostname, remote_port);
|
||||
dns = Curl_fetch_addr(data, sx->hostname, sx->remote_port);
|
||||
|
||||
if(dns) {
|
||||
#ifdef CURLRES_ASYNCH
|
||||
data->state.async.dns = dns;
|
||||
data->state.async.done = TRUE;
|
||||
#endif
|
||||
infof(data, "SOCKS5: hostname '%s' found", hostname);
|
||||
infof(data, "SOCKS5: hostname '%s' found", sx->hostname);
|
||||
}
|
||||
|
||||
if(!dns) {
|
||||
|
|
@ -803,13 +803,13 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
|
|||
hp = dns->addr;
|
||||
if(!hp) {
|
||||
failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.",
|
||||
hostname);
|
||||
sx->hostname);
|
||||
return CURLPX_RESOLVE_HOST;
|
||||
}
|
||||
|
||||
Curl_printable_address(hp, dest, sizeof(dest));
|
||||
destlen = strlen(dest);
|
||||
msnprintf(dest + destlen, sizeof(dest) - destlen, ":%d", remote_port);
|
||||
msnprintf(dest + destlen, sizeof(dest) - destlen, ":%d", sx->remote_port);
|
||||
|
||||
len = 0;
|
||||
socksreq[len++] = 5; /* version (SOCKS5) */
|
||||
|
|
@ -866,7 +866,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
|
|||
#ifdef ENABLE_IPV6
|
||||
if(conn->bits.ipv6_ip) {
|
||||
char ip6[16];
|
||||
if(1 != Curl_inet_pton(AF_INET6, hostname, ip6))
|
||||
if(1 != Curl_inet_pton(AF_INET6, sx->hostname, ip6))
|
||||
return CURLPX_BAD_ADDRESS_TYPE;
|
||||
socksreq[len++] = 4;
|
||||
memcpy(&socksreq[len], ip6, sizeof(ip6));
|
||||
|
|
@ -874,7 +874,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
|
|||
}
|
||||
else
|
||||
#endif
|
||||
if(1 == Curl_inet_pton(AF_INET, hostname, ip4)) {
|
||||
if(1 == Curl_inet_pton(AF_INET, sx->hostname, ip4)) {
|
||||
socksreq[len++] = 1;
|
||||
memcpy(&socksreq[len], ip4, sizeof(ip4));
|
||||
len += sizeof(ip4);
|
||||
|
|
@ -882,20 +882,20 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
|
|||
else {
|
||||
socksreq[len++] = 3;
|
||||
socksreq[len++] = (char) hostname_len; /* one byte address length */
|
||||
memcpy(&socksreq[len], hostname, hostname_len); /* address w/o NULL */
|
||||
memcpy(&socksreq[len], sx->hostname, hostname_len); /* w/o NULL */
|
||||
len += hostname_len;
|
||||
}
|
||||
infof(data, "SOCKS5 connect to %s:%d (remotely resolved)",
|
||||
hostname, remote_port);
|
||||
sx->hostname, sx->remote_port);
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
|
||||
CONNECT_REQ_SEND:
|
||||
case CONNECT_REQ_SEND:
|
||||
/* PORT MSB */
|
||||
socksreq[len++] = (unsigned char)((remote_port >> 8) & 0xff);
|
||||
socksreq[len++] = (unsigned char)((sx->remote_port >> 8) & 0xff);
|
||||
/* PORT LSB */
|
||||
socksreq[len++] = (unsigned char)(remote_port & 0xff);
|
||||
socksreq[len++] = (unsigned char)(sx->remote_port & 0xff);
|
||||
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
if(conn->socks5_gssapi_enctype) {
|
||||
|
|
@ -905,7 +905,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
|
|||
#endif
|
||||
sx->outp = socksreq;
|
||||
sx->outstanding = len;
|
||||
sxstate(data, CONNECT_REQ_SENDING);
|
||||
sxstate(sx, data, CONNECT_REQ_SENDING);
|
||||
/* FALLTHROUGH */
|
||||
case CONNECT_REQ_SENDING:
|
||||
result = Curl_write_plain(data, sockfd, (char *)sx->outp,
|
||||
|
|
@ -928,7 +928,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
|
|||
#endif
|
||||
sx->outstanding = 10; /* minimum packet size is 10 */
|
||||
sx->outp = socksreq;
|
||||
sxstate(data, CONNECT_REQ_READ);
|
||||
sxstate(sx, data, CONNECT_REQ_READ);
|
||||
/* FALLTHROUGH */
|
||||
case CONNECT_REQ_READ:
|
||||
result = Curl_read_plain(sockfd, (char *)sx->outp,
|
||||
|
|
@ -958,7 +958,7 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
|
|||
CURLproxycode rc = CURLPX_REPLY_UNASSIGNED;
|
||||
int code = socksreq[1];
|
||||
failf(data, "Can't complete SOCKS5 connection to %s. (%d)",
|
||||
hostname, (unsigned char)socksreq[1]);
|
||||
sx->hostname, (unsigned char)socksreq[1]);
|
||||
if(code < 9) {
|
||||
/* RFC 1928 section 6 lists: */
|
||||
static const CURLproxycode lookup[] = {
|
||||
|
|
@ -1019,10 +1019,10 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
|
|||
if(len > 10) {
|
||||
sx->outstanding = len - 10; /* get the rest */
|
||||
sx->outp = &socksreq[10];
|
||||
sxstate(data, CONNECT_REQ_READ_MORE);
|
||||
sxstate(sx, data, CONNECT_REQ_READ_MORE);
|
||||
}
|
||||
else {
|
||||
sxstate(data, CONNECT_DONE);
|
||||
sxstate(sx, data, CONNECT_DONE);
|
||||
break;
|
||||
}
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
|
|
@ -1047,12 +1047,197 @@ CURLproxycode Curl_SOCKS5(const char *proxy_user,
|
|||
sx->outp += actualread;
|
||||
return CURLPX_OK;
|
||||
}
|
||||
sxstate(data, CONNECT_DONE);
|
||||
sxstate(sx, data, CONNECT_DONE);
|
||||
}
|
||||
infof(data, "SOCKS5 request granted.");
|
||||
|
||||
*done = TRUE;
|
||||
return CURLPX_OK; /* Proxy was successful! */
|
||||
}
|
||||
|
||||
static CURLcode connect_SOCKS(struct Curl_cfilter *cf,
|
||||
struct socks_state *sxstate,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
CURLproxycode pxresult = CURLPX_OK;
|
||||
struct connectdata *conn = cf->conn;
|
||||
|
||||
switch(conn->socks_proxy.proxytype) {
|
||||
case CURLPROXY_SOCKS5:
|
||||
case CURLPROXY_SOCKS5_HOSTNAME:
|
||||
pxresult = do_SOCKS5(cf, sxstate, data);
|
||||
break;
|
||||
|
||||
case CURLPROXY_SOCKS4:
|
||||
case CURLPROXY_SOCKS4A:
|
||||
pxresult = do_SOCKS4(cf, sxstate, data);
|
||||
break;
|
||||
|
||||
default:
|
||||
failf(data, "unknown proxytype option given");
|
||||
result = CURLE_COULDNT_CONNECT;
|
||||
} /* switch proxytype */
|
||||
if(pxresult) {
|
||||
result = CURLE_PROXY;
|
||||
data->info.pxcode = pxresult;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void socks_proxy_cf_free(struct Curl_cfilter *cf)
|
||||
{
|
||||
struct socks_state *sxstate = cf->ctx;
|
||||
if(sxstate) {
|
||||
free(sxstate);
|
||||
cf->ctx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* After a TCP connection to the proxy has been verified, this function does
|
||||
the next magic steps. If 'done' isn't set TRUE, it is not done yet and
|
||||
must be called again.
|
||||
|
||||
Note: this function's sub-functions call failf()
|
||||
|
||||
*/
|
||||
static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
{
|
||||
CURLcode result;
|
||||
struct connectdata *conn = cf->conn;
|
||||
int sockindex = cf->sockindex;
|
||||
struct socks_state *sx = cf->ctx;
|
||||
|
||||
if(cf->connected) {
|
||||
*done = TRUE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
result = cf->next->cft->connect(cf->next, data, blocking, done);
|
||||
if(result || !*done)
|
||||
return result;
|
||||
|
||||
if(!sx) {
|
||||
sx = calloc(sizeof(*sx), 1);
|
||||
if(!sx)
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
cf->ctx = sx;
|
||||
}
|
||||
|
||||
if(sx->state == CONNECT_INIT) {
|
||||
/* for the secondary socket (FTP), use the "connect to host"
|
||||
* but ignore the "connect to port" (use the secondary port)
|
||||
*/
|
||||
sxstate(sx, data, CONNECT_SOCKS_INIT);
|
||||
sx->hostname =
|
||||
conn->bits.httpproxy ?
|
||||
conn->http_proxy.host.name :
|
||||
conn->bits.conn_to_host ?
|
||||
conn->conn_to_host.name :
|
||||
sockindex == SECONDARYSOCKET ?
|
||||
conn->secondaryhostname : conn->host.name;
|
||||
sx->remote_port =
|
||||
conn->bits.httpproxy ? (int)conn->http_proxy.port :
|
||||
sockindex == SECONDARYSOCKET ? conn->secondary_port :
|
||||
conn->bits.conn_to_port ? conn->conn_to_port :
|
||||
conn->remote_port;
|
||||
sx->proxy_user = conn->socks_proxy.user;
|
||||
sx->proxy_password = conn->socks_proxy.passwd;
|
||||
}
|
||||
|
||||
result = connect_SOCKS(cf, sx, data);
|
||||
if(!result && sx->state == CONNECT_DONE) {
|
||||
cf->connected = TRUE;
|
||||
Curl_updateconninfo(data, conn, conn->sock[cf->sockindex]);
|
||||
Curl_verboseconnect(data, conn);
|
||||
socks_proxy_cf_free(cf);
|
||||
}
|
||||
|
||||
*done = cf->connected;
|
||||
return result;
|
||||
}
|
||||
|
||||
static int socks_cf_get_select_socks(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
curl_socket_t *socks)
|
||||
{
|
||||
struct socks_state *sx = cf->ctx;
|
||||
int fds;
|
||||
|
||||
fds = cf->next->cft->get_select_socks(cf->next, data, socks);
|
||||
if(!fds && cf->next->connected && !cf->connected && sx) {
|
||||
/* If we are not connected, the filter below is and has nothing
|
||||
* to wait on, we determine what to wait for. */
|
||||
socks[0] = cf->conn->sock[cf->sockindex];
|
||||
switch(sx->state) {
|
||||
case CONNECT_RESOLVING:
|
||||
case CONNECT_SOCKS_READ:
|
||||
case CONNECT_AUTH_READ:
|
||||
case CONNECT_REQ_READ:
|
||||
case CONNECT_REQ_READ_MORE:
|
||||
fds = GETSOCK_READSOCK(0);
|
||||
break;
|
||||
default:
|
||||
fds = GETSOCK_WRITESOCK(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return fds;
|
||||
}
|
||||
|
||||
static void socks_proxy_cf_close(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
|
||||
DEBUGASSERT(cf->next);
|
||||
cf->connected = FALSE;
|
||||
socks_proxy_cf_free(cf);
|
||||
cf->next->cft->close(cf->next, data);
|
||||
}
|
||||
|
||||
static void socks_proxy_cf_destroy(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
(void)data;
|
||||
socks_proxy_cf_free(cf);
|
||||
}
|
||||
|
||||
static void socks_proxy_cf_detach_data(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
(void)data;
|
||||
socks_proxy_cf_free(cf);
|
||||
}
|
||||
|
||||
|
||||
static const struct Curl_cftype cft_socks_proxy = {
|
||||
"SOCKS-PROXYY",
|
||||
socks_proxy_cf_destroy,
|
||||
Curl_cf_def_attach_data,
|
||||
socks_proxy_cf_detach_data,
|
||||
Curl_cf_def_setup,
|
||||
socks_proxy_cf_close,
|
||||
socks_proxy_cf_connect,
|
||||
socks_cf_get_select_socks,
|
||||
Curl_cf_def_data_pending,
|
||||
Curl_cf_def_send,
|
||||
Curl_cf_def_recv,
|
||||
};
|
||||
|
||||
CURLcode Curl_cfilter_socks_proxy_add(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex)
|
||||
{
|
||||
struct Curl_cfilter *cf;
|
||||
CURLcode result;
|
||||
|
||||
result = Curl_cfilter_create(&cf, data, conn, sockindex,
|
||||
&cft_socks_proxy, NULL);
|
||||
if(!result)
|
||||
Curl_cfilter_add(data, conn, sockindex, cf);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* CURL_DISABLE_PROXY */
|
||||
|
|
|
|||
30
lib/socks.h
30
lib/socks.h
|
|
@ -43,32 +43,6 @@ int Curl_blockread_all(struct Curl_easy *data,
|
|||
ssize_t buffersize,
|
||||
ssize_t *n);
|
||||
|
||||
int Curl_SOCKS_getsock(struct connectdata *conn,
|
||||
curl_socket_t *sock,
|
||||
int sockindex);
|
||||
/*
|
||||
* This function logs in to a SOCKS4(a) proxy and sends the specifics to the
|
||||
* final destination server.
|
||||
*/
|
||||
CURLproxycode Curl_SOCKS4(const char *proxy_name,
|
||||
const char *hostname,
|
||||
int remote_port,
|
||||
int sockindex,
|
||||
struct Curl_easy *data,
|
||||
bool *done);
|
||||
|
||||
/*
|
||||
* This function logs in to a SOCKS5 proxy and sends the specifics to the
|
||||
* final destination server.
|
||||
*/
|
||||
CURLproxycode Curl_SOCKS5(const char *proxy_name,
|
||||
const char *proxy_password,
|
||||
const char *hostname,
|
||||
int remote_port,
|
||||
int sockindex,
|
||||
struct Curl_easy *data,
|
||||
bool *done);
|
||||
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
/*
|
||||
* This function handles the SOCKS5 GSS-API negotiation and initialization
|
||||
|
|
@ -77,6 +51,10 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
|
|||
struct Curl_easy *data);
|
||||
#endif
|
||||
|
||||
CURLcode Curl_cfilter_socks_proxy_add(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex);
|
||||
|
||||
#endif /* CURL_DISABLE_PROXY */
|
||||
|
||||
#endif /* HEADER_CURL_SOCKS_H */
|
||||
|
|
|
|||
|
|
@ -1491,6 +1491,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
|
|||
}
|
||||
|
||||
while(keepon) {
|
||||
DEBUGF(infof(data, "telnet_do(handle=%p), poll %d fds", data, poll_cnt));
|
||||
switch(Curl_poll(pfd, poll_cnt, interval_ms)) {
|
||||
case -1: /* error, stop reading */
|
||||
keepon = FALSE;
|
||||
|
|
@ -1509,6 +1510,14 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done)
|
|||
/* returned not-zero, this an error */
|
||||
if(result) {
|
||||
keepon = FALSE;
|
||||
/* TODO: in test 1452, macOS sees a ECONNRESET sometimes?
|
||||
* Is this the telnet test server not shutting down the socket
|
||||
* in a clean way? Seems to be timing related, happens more
|
||||
* on slow debug build */
|
||||
if(data->state.os_errno == ECONNRESET) {
|
||||
DEBUGF(infof(data, "telnet_do(handle=%p), unexpected ECONNRESET"
|
||||
" on recv", data));
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* returned zero but actually received 0 or less here,
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@
|
|||
|
||||
#include "content_encoding.h"
|
||||
#include "hostip.h"
|
||||
#include "cfilters.h"
|
||||
#include "transfer.h"
|
||||
#include "sendf.h"
|
||||
#include "speedcheck.h"
|
||||
|
|
@ -454,7 +455,7 @@ static int data_pending(const struct Curl_easy *data)
|
|||
#endif
|
||||
|
||||
if(conn->handler->protocol&PROTO_FAMILY_FTP)
|
||||
return Curl_ssl_data_pending(conn, SECONDARYSOCKET);
|
||||
return Curl_cfilter_data_pending(data, conn, SECONDARYSOCKET);
|
||||
|
||||
/* in the case of libssh2, we can never be really sure that we have emptied
|
||||
its internal buffers so we MUST always try until we get EAGAIN back */
|
||||
|
|
@ -469,7 +470,7 @@ static int data_pending(const struct Curl_easy *data)
|
|||
a workaround, we return nonzero here to call http2_recv. */
|
||||
((conn->handler->protocol&PROTO_FAMILY_HTTP) && conn->httpversion >= 20) ||
|
||||
#endif
|
||||
Curl_ssl_data_pending(conn, FIRSTSOCKET);
|
||||
Curl_cfilter_data_pending(data, conn, FIRSTSOCKET);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -569,11 +570,13 @@ static CURLcode readwrite_data(struct Curl_easy *data,
|
|||
result = Curl_read(data, conn->sockfd, buf, bytestoread, &nread);
|
||||
|
||||
/* read would've blocked */
|
||||
if(CURLE_AGAIN == result)
|
||||
if(CURLE_AGAIN == result) {
|
||||
result = CURLE_OK;
|
||||
break; /* get out of loop */
|
||||
}
|
||||
|
||||
if(result>0)
|
||||
return result;
|
||||
goto out;
|
||||
}
|
||||
else {
|
||||
/* read nothing but since we wanted nothing we consider this an OK
|
||||
|
|
@ -619,7 +622,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
|
|||
if(conn->handler->readwrite) {
|
||||
result = conn->handler->readwrite(data, conn, &nread, &readmore);
|
||||
if(result)
|
||||
return result;
|
||||
goto out;
|
||||
if(readmore)
|
||||
break;
|
||||
}
|
||||
|
|
@ -632,13 +635,13 @@ static CURLcode readwrite_data(struct Curl_easy *data,
|
|||
bool stop_reading = FALSE;
|
||||
result = Curl_http_readwrite_headers(data, conn, &nread, &stop_reading);
|
||||
if(result)
|
||||
return result;
|
||||
goto out;
|
||||
|
||||
if(conn->handler->readwrite &&
|
||||
(k->maxdownload <= 0 && nread > 0)) {
|
||||
result = conn->handler->readwrite(data, conn, &nread, &readmore);
|
||||
if(result)
|
||||
return result;
|
||||
goto out;
|
||||
if(readmore)
|
||||
break;
|
||||
}
|
||||
|
|
@ -669,7 +672,8 @@ static CURLcode readwrite_data(struct Curl_easy *data,
|
|||
/* data arrives although we want none, bail out */
|
||||
streamclose(conn, "ignoring body");
|
||||
*done = TRUE;
|
||||
return CURLE_WEIRD_SERVER_REPLY;
|
||||
result = CURLE_WEIRD_SERVER_REPLY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_HTTP
|
||||
|
|
@ -680,7 +684,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
|
|||
/* HTTP-only checks */
|
||||
result = Curl_http_firstwrite(data, conn, done);
|
||||
if(result || *done)
|
||||
return result;
|
||||
goto out;
|
||||
}
|
||||
} /* this is the first time we write a body part */
|
||||
#endif /* CURL_DISABLE_HTTP */
|
||||
|
|
@ -717,10 +721,12 @@ static CURLcode readwrite_data(struct Curl_easy *data,
|
|||
if(CHUNKE_OK < res) {
|
||||
if(CHUNKE_PASSTHRU_ERROR == res) {
|
||||
failf(data, "Failed reading the chunked-encoded stream");
|
||||
return extra;
|
||||
result = extra;
|
||||
goto out;
|
||||
}
|
||||
failf(data, "%s in chunked-encoding", Curl_chunked_strerror(res));
|
||||
return CURLE_RECV_ERROR;
|
||||
result = CURLE_RECV_ERROR;
|
||||
goto out;
|
||||
}
|
||||
if(CHUNKE_STOP == res) {
|
||||
/* we're done reading chunks! */
|
||||
|
|
@ -796,7 +802,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
|
|||
(size_t)k->maxdownload);
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
goto out;
|
||||
}
|
||||
if(k->badheader < HEADER_ALLBAD) {
|
||||
/* This switch handles various content encodings. If there's an
|
||||
|
|
@ -821,7 +827,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
|
|||
k->badheader = HEADER_NORMAL; /* taken care of now */
|
||||
|
||||
if(result)
|
||||
return result;
|
||||
goto out;
|
||||
}
|
||||
|
||||
} /* if(!header and data to read) */
|
||||
|
|
@ -839,7 +845,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
|
|||
|
||||
result = conn->handler->readwrite(data, conn, &nread, &readmore);
|
||||
if(result)
|
||||
return result;
|
||||
goto out;
|
||||
|
||||
if(readmore)
|
||||
k->keepon |= KEEP_RECV; /* we're not done reading */
|
||||
|
|
@ -874,7 +880,9 @@ static CURLcode readwrite_data(struct Curl_easy *data,
|
|||
k->keepon &= ~KEEP_SEND; /* no writing anymore either */
|
||||
}
|
||||
|
||||
return CURLE_OK;
|
||||
out:
|
||||
DEBUGF(infof(data, "readwrite_data(handle=%p) -> %d", data, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
CURLcode Curl_done_sending(struct Curl_easy *data,
|
||||
|
|
@ -1201,14 +1209,15 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
|||
|
||||
if(select_res == CURL_CSELECT_ERR) {
|
||||
failf(data, "select/poll returned error");
|
||||
return CURLE_SEND_ERROR;
|
||||
result = CURLE_SEND_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef USE_HYPER
|
||||
if(conn->datastream) {
|
||||
result = conn->datastream(data, conn, &didwhat, done, select_res);
|
||||
if(result || *done)
|
||||
return result;
|
||||
goto out;
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
|
|
@ -1218,7 +1227,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
|||
if((k->keepon & KEEP_RECV) && (select_res & CURL_CSELECT_IN)) {
|
||||
result = readwrite_data(data, conn, k, &didwhat, done, comeback);
|
||||
if(result || *done)
|
||||
return result;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* If we still have writing to do, we check if we have a writable socket. */
|
||||
|
|
@ -1227,7 +1236,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
|||
|
||||
result = readwrite_upload(data, conn, &didwhat);
|
||||
if(result)
|
||||
return result;
|
||||
goto out;
|
||||
}
|
||||
#ifdef USE_HYPER
|
||||
}
|
||||
|
|
@ -1264,7 +1273,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
|||
if(conn->transport == TRNSPRT_QUIC) {
|
||||
result = Curl_quic_idle(data);
|
||||
if(result)
|
||||
return result;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1274,7 +1283,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
|||
else
|
||||
result = Curl_speedcheck(data, k->now);
|
||||
if(result)
|
||||
return result;
|
||||
goto out;
|
||||
|
||||
if(k->keepon) {
|
||||
if(0 > Curl_timeleft(data, &k->now, FALSE)) {
|
||||
|
|
@ -1291,7 +1300,8 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
|||
Curl_timediff(k->now, data->progress.t_startsingle),
|
||||
k->bytecount);
|
||||
}
|
||||
return CURLE_OPERATION_TIMEDOUT;
|
||||
result = CURLE_OPERATION_TIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -1312,7 +1322,8 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
|||
!k->newurl) {
|
||||
failf(data, "transfer closed with %" CURL_FORMAT_CURL_OFF_T
|
||||
" bytes remaining to read", k->size - k->bytecount);
|
||||
return CURLE_PARTIAL_FILE;
|
||||
result = CURLE_PARTIAL_FILE;
|
||||
goto out;
|
||||
}
|
||||
if(!(data->set.opt_no_body) && k->chunk &&
|
||||
(conn->chunk.state != CHUNK_STOP)) {
|
||||
|
|
@ -1326,17 +1337,22 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
|||
*
|
||||
*/
|
||||
failf(data, "transfer closed with outstanding read data remaining");
|
||||
return CURLE_PARTIAL_FILE;
|
||||
result = CURLE_PARTIAL_FILE;
|
||||
goto out;
|
||||
}
|
||||
if(Curl_pgrsUpdate(data)) {
|
||||
result = CURLE_ABORTED_BY_CALLBACK;
|
||||
goto out;
|
||||
}
|
||||
if(Curl_pgrsUpdate(data))
|
||||
return CURLE_ABORTED_BY_CALLBACK;
|
||||
}
|
||||
|
||||
/* Now update the "done" boolean we return */
|
||||
*done = (0 == (k->keepon&(KEEP_RECV|KEEP_SEND|
|
||||
KEEP_RECV_PAUSE|KEEP_SEND_PAUSE))) ? TRUE : FALSE;
|
||||
|
||||
return CURLE_OK;
|
||||
result = CURLE_OK;
|
||||
out:
|
||||
DEBUGF(infof(data, "Curl_readwrite(handle=%p) -> %d", data, result));
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
192
lib/url.c
192
lib/url.c
|
|
@ -107,6 +107,7 @@ bool Curl_win32_idn_to_ascii(const char *in, char **out);
|
|||
#include "system_win32.h"
|
||||
#include "hsts.h"
|
||||
#include "noproxy.h"
|
||||
#include "cfilters.h"
|
||||
|
||||
/* And now for the protocols */
|
||||
#include "ftp.h"
|
||||
|
|
@ -140,7 +141,11 @@ bool Curl_win32_idn_to_ascii(const char *in, char **out);
|
|||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
static void conn_free(struct connectdata *conn);
|
||||
#ifndef ARRAYSIZE
|
||||
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
|
||||
#endif
|
||||
|
||||
static void conn_free(struct Curl_easy *data, struct connectdata *conn);
|
||||
|
||||
/* Some parts of the code (e.g. chunked encoding) assume this buffer has at
|
||||
* more than just a few bytes to play with. Don't let it become too small or
|
||||
|
|
@ -756,28 +761,20 @@ static void conn_shutdown(struct Curl_easy *data, struct connectdata *conn)
|
|||
/* possible left-overs from the async name resolvers */
|
||||
Curl_resolver_cancel(data);
|
||||
|
||||
/* close the SSL stuff before we close any sockets since they will/may
|
||||
write to the sockets */
|
||||
Curl_ssl_close(data, conn, FIRSTSOCKET);
|
||||
#ifndef CURL_DISABLE_FTP
|
||||
Curl_ssl_close(data, conn, SECONDARYSOCKET);
|
||||
#endif
|
||||
|
||||
/* close possibly still open sockets */
|
||||
if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
|
||||
Curl_closesocket(data, conn, conn->sock[SECONDARYSOCKET]);
|
||||
if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
|
||||
Curl_closesocket(data, conn, conn->sock[FIRSTSOCKET]);
|
||||
if(CURL_SOCKET_BAD != conn->tempsock[0])
|
||||
Curl_closesocket(data, conn, conn->tempsock[0]);
|
||||
if(CURL_SOCKET_BAD != conn->tempsock[1])
|
||||
Curl_closesocket(data, conn, conn->tempsock[1]);
|
||||
Curl_cfilter_close(data, conn, SECONDARYSOCKET);
|
||||
Curl_cfilter_close(data, conn, FIRSTSOCKET);
|
||||
}
|
||||
|
||||
static void conn_free(struct connectdata *conn)
|
||||
static void conn_free(struct Curl_easy *data, struct connectdata *conn)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
DEBUGASSERT(conn);
|
||||
|
||||
for(i = 0; i < ARRAYSIZE(conn->cfilter); ++i) {
|
||||
Curl_cfilter_destroy(data, conn, (int)i);
|
||||
}
|
||||
|
||||
Curl_free_idnconverted_hostname(&conn->host);
|
||||
Curl_free_idnconverted_hostname(&conn->conn_to_host);
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
|
|
@ -801,7 +798,6 @@ static void conn_free(struct connectdata *conn)
|
|||
Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */
|
||||
Curl_safefree(conn->hostname_resolve);
|
||||
Curl_safefree(conn->secondaryhostname);
|
||||
Curl_safefree(conn->connect_state);
|
||||
|
||||
conn_reset_all_postponed_data(conn);
|
||||
Curl_llist_destroy(&conn->easyq, NULL);
|
||||
|
|
@ -847,6 +843,8 @@ void Curl_disconnect(struct Curl_easy *data,
|
|||
/* the transfer must be detached from the connection */
|
||||
DEBUGASSERT(!data->conn);
|
||||
|
||||
DEBUGF(infof(data, "Curl_disconnect(conn #%ld, dead=%d)",
|
||||
conn->connection_id, dead_connection));
|
||||
/*
|
||||
* If this connection isn't marked to force-close, leave it open if there
|
||||
* are other users of it
|
||||
|
|
@ -884,7 +882,7 @@ void Curl_disconnect(struct Curl_easy *data,
|
|||
/* detach it again */
|
||||
Curl_detach_connection(data);
|
||||
|
||||
conn_free(conn);
|
||||
conn_free(data, conn);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1687,7 +1685,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
|
|||
Note that these backend pointers can be swapped by vtls (eg ssl backend
|
||||
data becomes proxy backend data). */
|
||||
{
|
||||
size_t onesize = Curl_ssl->sizeof_ssl_backend_data;
|
||||
size_t onesize = Curl_ssl_get_backend_data_size(data);
|
||||
size_t totalsize = onesize;
|
||||
char *ssl;
|
||||
|
||||
|
|
@ -2435,7 +2433,7 @@ static CURLcode parse_proxy(struct Curl_easy *data,
|
|||
}
|
||||
|
||||
#ifdef USE_SSL
|
||||
if(!(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY))
|
||||
if(!Curl_ssl_supports(data, SSLSUPP_HTTPS_PROXY))
|
||||
#endif
|
||||
if(proxytype == CURLPROXY_HTTPS) {
|
||||
failf(data, "Unsupported proxy \'%s\', libcurl is built without the "
|
||||
|
|
@ -3529,13 +3527,13 @@ static CURLcode resolve_server(struct Curl_easy *data,
|
|||
}
|
||||
|
||||
/*
|
||||
* Cleanup the connection just allocated before we can move along and use the
|
||||
* previously existing one. All relevant data is copied over and old_conn is
|
||||
* ready for freeing once this function returns.
|
||||
* Cleanup the connection `temp`, just allocated for `data`, before using the
|
||||
* previously `existing` one for `data`. All relevant info is copied over
|
||||
* and `temp` is freed.
|
||||
*/
|
||||
static void reuse_conn(struct Curl_easy *data,
|
||||
struct connectdata *old_conn,
|
||||
struct connectdata *conn)
|
||||
struct connectdata *temp,
|
||||
struct connectdata *existing)
|
||||
{
|
||||
/* 'local_ip' and 'local_port' get filled with local's numerical
|
||||
ip address and port number whenever an outgoing connection is
|
||||
|
|
@ -3543,66 +3541,66 @@ static void reuse_conn(struct Curl_easy *data,
|
|||
char local_ip[MAX_IPADR_LEN] = "";
|
||||
int local_port = -1;
|
||||
|
||||
/* get the user+password information from the old_conn struct since it may
|
||||
/* get the user+password information from the temp struct since it may
|
||||
* be new for this request even when we re-use an existing connection */
|
||||
if(old_conn->user) {
|
||||
if(temp->user) {
|
||||
/* use the new user name and password though */
|
||||
Curl_safefree(conn->user);
|
||||
Curl_safefree(conn->passwd);
|
||||
conn->user = old_conn->user;
|
||||
conn->passwd = old_conn->passwd;
|
||||
old_conn->user = NULL;
|
||||
old_conn->passwd = NULL;
|
||||
Curl_safefree(existing->user);
|
||||
Curl_safefree(existing->passwd);
|
||||
existing->user = temp->user;
|
||||
existing->passwd = temp->passwd;
|
||||
temp->user = NULL;
|
||||
temp->passwd = NULL;
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
|
||||
if(conn->bits.proxy_user_passwd) {
|
||||
existing->bits.proxy_user_passwd = temp->bits.proxy_user_passwd;
|
||||
if(existing->bits.proxy_user_passwd) {
|
||||
/* use the new proxy user name and proxy password though */
|
||||
Curl_safefree(conn->http_proxy.user);
|
||||
Curl_safefree(conn->socks_proxy.user);
|
||||
Curl_safefree(conn->http_proxy.passwd);
|
||||
Curl_safefree(conn->socks_proxy.passwd);
|
||||
conn->http_proxy.user = old_conn->http_proxy.user;
|
||||
conn->socks_proxy.user = old_conn->socks_proxy.user;
|
||||
conn->http_proxy.passwd = old_conn->http_proxy.passwd;
|
||||
conn->socks_proxy.passwd = old_conn->socks_proxy.passwd;
|
||||
old_conn->http_proxy.user = NULL;
|
||||
old_conn->socks_proxy.user = NULL;
|
||||
old_conn->http_proxy.passwd = NULL;
|
||||
old_conn->socks_proxy.passwd = NULL;
|
||||
Curl_safefree(existing->http_proxy.user);
|
||||
Curl_safefree(existing->socks_proxy.user);
|
||||
Curl_safefree(existing->http_proxy.passwd);
|
||||
Curl_safefree(existing->socks_proxy.passwd);
|
||||
existing->http_proxy.user = temp->http_proxy.user;
|
||||
existing->socks_proxy.user = temp->socks_proxy.user;
|
||||
existing->http_proxy.passwd = temp->http_proxy.passwd;
|
||||
existing->socks_proxy.passwd = temp->socks_proxy.passwd;
|
||||
temp->http_proxy.user = NULL;
|
||||
temp->socks_proxy.user = NULL;
|
||||
temp->http_proxy.passwd = NULL;
|
||||
temp->socks_proxy.passwd = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
Curl_free_idnconverted_hostname(&conn->host);
|
||||
Curl_free_idnconverted_hostname(&conn->conn_to_host);
|
||||
Curl_safefree(conn->host.rawalloc);
|
||||
Curl_safefree(conn->conn_to_host.rawalloc);
|
||||
conn->host = old_conn->host;
|
||||
old_conn->host.rawalloc = NULL;
|
||||
old_conn->host.encalloc = NULL;
|
||||
conn->conn_to_host = old_conn->conn_to_host;
|
||||
old_conn->conn_to_host.rawalloc = NULL;
|
||||
conn->conn_to_port = old_conn->conn_to_port;
|
||||
conn->remote_port = old_conn->remote_port;
|
||||
Curl_safefree(conn->hostname_resolve);
|
||||
Curl_free_idnconverted_hostname(&existing->host);
|
||||
Curl_free_idnconverted_hostname(&existing->conn_to_host);
|
||||
Curl_safefree(existing->host.rawalloc);
|
||||
Curl_safefree(existing->conn_to_host.rawalloc);
|
||||
existing->host = temp->host;
|
||||
temp->host.rawalloc = NULL;
|
||||
temp->host.encalloc = NULL;
|
||||
existing->conn_to_host = temp->conn_to_host;
|
||||
temp->conn_to_host.rawalloc = NULL;
|
||||
existing->conn_to_port = temp->conn_to_port;
|
||||
existing->remote_port = temp->remote_port;
|
||||
Curl_safefree(existing->hostname_resolve);
|
||||
|
||||
conn->hostname_resolve = old_conn->hostname_resolve;
|
||||
old_conn->hostname_resolve = NULL;
|
||||
existing->hostname_resolve = temp->hostname_resolve;
|
||||
temp->hostname_resolve = NULL;
|
||||
|
||||
/* persist connection info in session handle */
|
||||
if(conn->transport == TRNSPRT_TCP) {
|
||||
Curl_conninfo_local(data, conn->sock[FIRSTSOCKET],
|
||||
if(existing->transport == TRNSPRT_TCP) {
|
||||
Curl_conninfo_local(data, existing->sock[FIRSTSOCKET],
|
||||
local_ip, &local_port);
|
||||
}
|
||||
Curl_persistconninfo(data, conn, local_ip, local_port);
|
||||
Curl_persistconninfo(data, existing, local_ip, local_port);
|
||||
|
||||
conn_reset_all_postponed_data(old_conn); /* free buffers */
|
||||
conn_reset_all_postponed_data(temp); /* free buffers */
|
||||
|
||||
/* re-use init */
|
||||
conn->bits.reuse = TRUE; /* yes, we're re-using here */
|
||||
existing->bits.reuse = TRUE; /* yes, we're re-using here */
|
||||
|
||||
conn_free(old_conn);
|
||||
conn_free(data, temp);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -3626,7 +3624,7 @@ static CURLcode create_conn(struct Curl_easy *data,
|
|||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct connectdata *conn;
|
||||
struct connectdata *conn_temp = NULL;
|
||||
struct connectdata *existing = NULL;
|
||||
bool reuse;
|
||||
bool connections_available = TRUE;
|
||||
bool force_reuse = FALSE;
|
||||
|
|
@ -3768,13 +3766,6 @@ static CURLcode create_conn(struct Curl_easy *data,
|
|||
if(result)
|
||||
goto out;
|
||||
|
||||
conn->recv[FIRSTSOCKET] = Curl_recv_plain;
|
||||
conn->send[FIRSTSOCKET] = Curl_send_plain;
|
||||
conn->recv[SECONDARYSOCKET] = Curl_recv_plain;
|
||||
conn->send[SECONDARYSOCKET] = Curl_send_plain;
|
||||
|
||||
conn->bits.tcp_fastopen = data->set.tcp_fastopen;
|
||||
|
||||
/***********************************************************************
|
||||
* file: is a special case in that it doesn't need a network connection
|
||||
***********************************************************************/
|
||||
|
|
@ -3789,8 +3780,6 @@ static CURLcode create_conn(struct Curl_easy *data,
|
|||
|
||||
/* Setup a "faked" transfer that'll do nothing */
|
||||
if(!result) {
|
||||
conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
|
||||
|
||||
Curl_attach_connection(data, conn);
|
||||
result = Curl_conncache_add_conn(data);
|
||||
if(result)
|
||||
|
|
@ -3816,6 +3805,13 @@ static CURLcode create_conn(struct Curl_easy *data,
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Setup filter for network connections */
|
||||
conn->recv[FIRSTSOCKET] = Curl_cfilter_recv;
|
||||
conn->send[FIRSTSOCKET] = Curl_cfilter_send;
|
||||
conn->recv[SECONDARYSOCKET] = Curl_cfilter_recv;
|
||||
conn->send[SECONDARYSOCKET] = Curl_cfilter_send;
|
||||
conn->bits.tcp_fastopen = data->set.tcp_fastopen;
|
||||
|
||||
/* Get a cloned copy of the SSL config situation stored in the
|
||||
connection struct. But to get this going nicely, we must first make
|
||||
sure that the strings in the master copy are pointing to the correct
|
||||
|
|
@ -3915,16 +3911,16 @@ static CURLcode create_conn(struct Curl_easy *data,
|
|||
data->set.connect_only)
|
||||
reuse = FALSE;
|
||||
else
|
||||
reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe);
|
||||
reuse = ConnectionExists(data, conn, &existing, &force_reuse, &waitpipe);
|
||||
|
||||
if(reuse) {
|
||||
/*
|
||||
* We already have a connection for this, we got the former connection in
|
||||
* the conn_temp variable and thus we need to cleanup the one we just
|
||||
* allocated before we can move along and use the previously existing one.
|
||||
* `existing` and thus we need to cleanup the one we just
|
||||
* allocated before we can move along and use `existing`.
|
||||
*/
|
||||
reuse_conn(data, conn, conn_temp);
|
||||
conn = conn_temp;
|
||||
reuse_conn(data, conn, existing);
|
||||
conn = existing;
|
||||
*in_connect = conn;
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
|
|
@ -3999,7 +3995,7 @@ static CURLcode create_conn(struct Curl_easy *data,
|
|||
if(!connections_available) {
|
||||
infof(data, "No connections available.");
|
||||
|
||||
conn_free(conn);
|
||||
conn_free(data, conn);
|
||||
*in_connect = NULL;
|
||||
|
||||
result = CURLE_NO_CONNECTION_AVAILABLE;
|
||||
|
|
@ -4082,7 +4078,6 @@ CURLcode Curl_setup_conn(struct Curl_easy *data,
|
|||
*protocol_done = TRUE;
|
||||
return result;
|
||||
}
|
||||
*protocol_done = FALSE; /* default to not done */
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
/* set proxy_connect_closed to false unconditionally already here since it
|
||||
|
|
@ -4099,26 +4094,11 @@ CURLcode Curl_setup_conn(struct Curl_easy *data,
|
|||
/* set start time here for timeout purposes in the connect procedure, it
|
||||
is later set again for the progress meter purpose */
|
||||
conn->now = Curl_now();
|
||||
|
||||
if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
|
||||
conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
|
||||
result = Curl_connecthost(data, conn, conn->dns_entry);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
|
||||
if(conn->ssl[FIRSTSOCKET].use ||
|
||||
(conn->handler->protocol & PROTO_FAMILY_SSH))
|
||||
Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
|
||||
conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
|
||||
*protocol_done = TRUE;
|
||||
Curl_updateconninfo(data, conn, conn->sock[FIRSTSOCKET]);
|
||||
Curl_verboseconnect(data, conn);
|
||||
}
|
||||
|
||||
conn->now = Curl_now(); /* time this *after* the connect is done, we set
|
||||
this here perhaps a second time */
|
||||
if(!conn->bits.reuse)
|
||||
result = Curl_cfilter_setup(data, conn, FIRSTSOCKET, conn->dns_entry,
|
||||
CURL_CF_SSL_DEFAULT);
|
||||
/* not sure we need this flag to be passed around any more */
|
||||
*protocol_done = FALSE;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
17
lib/url.h
17
lib/url.h
|
|
@ -64,21 +64,4 @@ void Curl_free_idnconverted_hostname(struct hostname *host);
|
|||
void Curl_verboseconnect(struct Curl_easy *data, struct connectdata *conn);
|
||||
#endif
|
||||
|
||||
#ifdef CURL_DISABLE_PROXY
|
||||
#define CONNECT_PROXY_SSL() FALSE
|
||||
#else
|
||||
|
||||
#define CONNECT_PROXY_SSL()\
|
||||
(conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\
|
||||
!conn->bits.proxy_ssl_connected[sockindex])
|
||||
|
||||
#define CONNECT_FIRSTSOCKET_PROXY_SSL()\
|
||||
(conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\
|
||||
!conn->bits.proxy_ssl_connected[FIRSTSOCKET])
|
||||
|
||||
#define CONNECT_SECONDARYSOCKET_PROXY_SSL()\
|
||||
(conn->http_proxy.proxytype == CURLPROXY_HTTPS &&\
|
||||
!conn->bits.proxy_ssl_connected[SECONDARYSOCKET])
|
||||
#endif /* !CURL_DISABLE_PROXY */
|
||||
|
||||
#endif /* HEADER_CURL_URL_H */
|
||||
|
|
|
|||
|
|
@ -477,8 +477,6 @@ struct negotiatedata {
|
|||
* Boolean values that concerns this connection.
|
||||
*/
|
||||
struct ConnectBits {
|
||||
bool tcpconnect[2]; /* the TCP layer (or similar) is connected, this is set
|
||||
the first time on the first connect function call */
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
bool proxy_ssl_connected[2]; /* TRUE when SSL initialization for HTTPS proxy
|
||||
is complete */
|
||||
|
|
@ -874,38 +872,6 @@ struct proxy_info {
|
|||
};
|
||||
|
||||
struct ldapconninfo;
|
||||
struct http_connect_state;
|
||||
|
||||
/* for the (SOCKS) connect state machine */
|
||||
enum connect_t {
|
||||
CONNECT_INIT,
|
||||
CONNECT_SOCKS_INIT, /* 1 */
|
||||
CONNECT_SOCKS_SEND, /* 2 waiting to send more first data */
|
||||
CONNECT_SOCKS_READ_INIT, /* 3 set up read */
|
||||
CONNECT_SOCKS_READ, /* 4 read server response */
|
||||
CONNECT_GSSAPI_INIT, /* 5 */
|
||||
CONNECT_AUTH_INIT, /* 6 setup outgoing auth buffer */
|
||||
CONNECT_AUTH_SEND, /* 7 send auth */
|
||||
CONNECT_AUTH_READ, /* 8 read auth response */
|
||||
CONNECT_REQ_INIT, /* 9 init SOCKS "request" */
|
||||
CONNECT_RESOLVING, /* 10 */
|
||||
CONNECT_RESOLVED, /* 11 */
|
||||
CONNECT_RESOLVE_REMOTE, /* 12 */
|
||||
CONNECT_REQ_SEND, /* 13 */
|
||||
CONNECT_REQ_SENDING, /* 14 */
|
||||
CONNECT_REQ_READ, /* 15 */
|
||||
CONNECT_REQ_READ_MORE, /* 16 */
|
||||
CONNECT_DONE /* 17 connected fine to the remote or the SOCKS proxy */
|
||||
};
|
||||
|
||||
#define SOCKS_STATE(x) (((x) >= CONNECT_SOCKS_INIT) && \
|
||||
((x) < CONNECT_DONE))
|
||||
|
||||
struct connstate {
|
||||
enum connect_t state;
|
||||
ssize_t outstanding; /* send this many bytes more */
|
||||
unsigned char *outp; /* send from this pointer */
|
||||
};
|
||||
|
||||
#define TRNSPRT_TCP 3
|
||||
#define TRNSPRT_UDP 4
|
||||
|
|
@ -917,7 +883,6 @@ struct connstate {
|
|||
* unique for an entire connection.
|
||||
*/
|
||||
struct connectdata {
|
||||
struct connstate cnnct;
|
||||
struct Curl_llist_element bundle_node; /* conncache */
|
||||
|
||||
/* chunk is for HTTP chunked encoding, but is in the general connectdata
|
||||
|
|
@ -986,6 +951,7 @@ struct connectdata {
|
|||
int tempfamily[2]; /* family used for the temp sockets */
|
||||
Curl_recv *recv[2];
|
||||
Curl_send *send[2];
|
||||
struct Curl_cfilter *cfilter[2]; /* connection filters */
|
||||
|
||||
#ifdef USE_RECV_BEFORE_SEND_WORKAROUND
|
||||
struct postponed_data postponed[2]; /* two buffers for two sockets */
|
||||
|
|
@ -1113,7 +1079,6 @@ struct connectdata {
|
|||
#endif
|
||||
} proto;
|
||||
|
||||
struct http_connect_state *connect_state; /* for HTTP CONNECT */
|
||||
struct connectbundle *bundle; /* The bundle we are member of */
|
||||
#ifdef USE_UNIX_SOCKETS
|
||||
char *unix_domain_socket;
|
||||
|
|
|
|||
|
|
@ -522,7 +522,7 @@ curl_version_info_data *curl_version_info(CURLversion stamp)
|
|||
Curl_ssl_version(ssl_buffer, sizeof(ssl_buffer));
|
||||
version_info.ssl_version = ssl_buffer;
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
if(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY)
|
||||
if(Curl_ssl_supports(NULL, SSLSUPP_HTTPS_PROXY))
|
||||
version_info.features |= CURL_VERSION_HTTPS_PROXY;
|
||||
else
|
||||
version_info.features &= ~CURL_VERSION_HTTPS_PROXY;
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@
|
|||
#include "strdup.h"
|
||||
#include "strcase.h"
|
||||
#include "vtls/vtls.h"
|
||||
#include "cfilters.h"
|
||||
#include "connect.h"
|
||||
#include "inet_ntop.h"
|
||||
#include "parsedate.h" /* for the week day and month names */
|
||||
|
|
@ -2323,7 +2324,6 @@ CURLcode scp_perform(struct Curl_easy *data,
|
|||
bool *connected, bool *dophase_done)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct connectdata *conn = data->conn;
|
||||
|
||||
DEBUGF(infof(data, "DO phase starts"));
|
||||
|
||||
|
|
@ -2334,7 +2334,7 @@ CURLcode scp_perform(struct Curl_easy *data,
|
|||
|
||||
result = myssh_multi_statemach(data, dophase_done);
|
||||
|
||||
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
|
||||
*connected = Curl_cfilter_is_connected(data, data->conn, FIRSTSOCKET);
|
||||
|
||||
if(*dophase_done) {
|
||||
DEBUGF(infof(data, "DO phase is complete"));
|
||||
|
|
@ -2504,7 +2504,6 @@ CURLcode sftp_perform(struct Curl_easy *data,
|
|||
bool *dophase_done)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct connectdata *conn = data->conn;
|
||||
|
||||
DEBUGF(infof(data, "DO phase starts"));
|
||||
|
||||
|
|
@ -2516,7 +2515,7 @@ CURLcode sftp_perform(struct Curl_easy *data,
|
|||
/* run the state-machine */
|
||||
result = myssh_multi_statemach(data, dophase_done);
|
||||
|
||||
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
|
||||
*connected = Curl_cfilter_is_connected(data, data->conn, FIRSTSOCKET);
|
||||
|
||||
if(*dophase_done) {
|
||||
DEBUGF(infof(data, "DO phase is complete"));
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@
|
|||
#include "strdup.h"
|
||||
#include "strcase.h"
|
||||
#include "vtls/vtls.h"
|
||||
#include "cfilters.h"
|
||||
#include "connect.h"
|
||||
#include "inet_ntop.h"
|
||||
#include "parsedate.h" /* for the week day and month names */
|
||||
|
|
@ -3374,7 +3375,6 @@ CURLcode scp_perform(struct Curl_easy *data,
|
|||
bool *dophase_done)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct connectdata *conn = data->conn;
|
||||
|
||||
DEBUGF(infof(data, "DO phase starts"));
|
||||
|
||||
|
|
@ -3386,7 +3386,7 @@ CURLcode scp_perform(struct Curl_easy *data,
|
|||
/* run the state-machine */
|
||||
result = ssh_multi_statemach(data, dophase_done);
|
||||
|
||||
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
|
||||
*connected = Curl_cfilter_is_connected(data, data->conn, FIRSTSOCKET);
|
||||
|
||||
if(*dophase_done) {
|
||||
DEBUGF(infof(data, "DO phase is complete"));
|
||||
|
|
@ -3575,7 +3575,7 @@ CURLcode sftp_perform(struct Curl_easy *data,
|
|||
/* run the state-machine */
|
||||
result = ssh_multi_statemach(data, dophase_done);
|
||||
|
||||
*connected = data->conn->bits.tcpconnect[FIRSTSOCKET];
|
||||
*connected = Curl_cfilter_is_connected(data, data->conn, FIRSTSOCKET);
|
||||
|
||||
if(*dophase_done) {
|
||||
DEBUGF(infof(data, "DO phase is complete"));
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include <wolfssh/ssh.h>
|
||||
#include <wolfssh/wolfsftp.h>
|
||||
#include "urldata.h"
|
||||
#include "cfilters.h"
|
||||
#include "connect.h"
|
||||
#include "sendf.h"
|
||||
#include "progress.h"
|
||||
|
|
@ -939,7 +940,6 @@ CURLcode wsftp_perform(struct Curl_easy *data,
|
|||
bool *dophase_done)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
struct connectdata *conn = data->conn;
|
||||
|
||||
DEBUGF(infof(data, "DO phase starts"));
|
||||
|
||||
|
|
@ -951,7 +951,7 @@ CURLcode wsftp_perform(struct Curl_easy *data,
|
|||
/* run the state-machine */
|
||||
result = wssh_multi_statemach(data, dophase_done);
|
||||
|
||||
*connected = conn->bits.tcpconnect[FIRSTSOCKET];
|
||||
*connected = Curl_cfilter_is_connected(data, data->conn, FIRSTSOCKET);
|
||||
|
||||
if(*dophase_done) {
|
||||
DEBUGF(infof(data, "DO phase is complete"));
|
||||
|
|
|
|||
|
|
@ -32,13 +32,17 @@
|
|||
#include "sendf.h"
|
||||
#include "inet_pton.h"
|
||||
#include "vtls.h"
|
||||
#include "vtls_int.h"
|
||||
#include "connect.h"
|
||||
#include "select.h"
|
||||
#include "multiif.h"
|
||||
#include "curl_printf.h"
|
||||
#include "curl_memory.h"
|
||||
#include "strcase.h"
|
||||
|
||||
/* The last #include files should be: */
|
||||
#include "curl_memory.h"
|
||||
#include "memdebug.h"
|
||||
|
||||
struct x509_context {
|
||||
const br_x509_class *vtable;
|
||||
br_x509_minimal_context minimal;
|
||||
|
|
@ -1069,8 +1073,6 @@ static CURLcode bearssl_connect_common(struct Curl_easy *data,
|
|||
|
||||
if(ssl_connect_done == connssl->connecting_state) {
|
||||
connssl->state = ssl_connection_complete;
|
||||
conn->recv[sockindex] = bearssl_recv;
|
||||
conn->send[sockindex] = bearssl_send;
|
||||
*done = TRUE;
|
||||
}
|
||||
else
|
||||
|
|
@ -1156,12 +1158,15 @@ static void bearssl_close(struct Curl_easy *data,
|
|||
DEBUGASSERT(backend);
|
||||
|
||||
if(backend->active) {
|
||||
backend->active = FALSE;
|
||||
br_ssl_engine_close(&backend->ctx.eng);
|
||||
(void)bearssl_run_until(data, conn, sockindex, BR_SSL_CLOSED);
|
||||
}
|
||||
for(i = 0; i < backend->anchors_len; ++i)
|
||||
free(backend->anchors[i].dn.data);
|
||||
free(backend->anchors);
|
||||
if(backend->anchors) {
|
||||
for(i = 0; i < backend->anchors_len; ++i)
|
||||
free(backend->anchors[i].dn.data);
|
||||
Curl_safefree(backend->anchors);
|
||||
}
|
||||
}
|
||||
|
||||
static void bearssl_session_free(void *ptr)
|
||||
|
|
@ -1209,7 +1214,9 @@ const struct Curl_ssl Curl_ssl_bearssl = {
|
|||
bearssl_sha256sum, /* sha256sum */
|
||||
NULL, /* associate_connection */
|
||||
NULL, /* disassociate_connection */
|
||||
NULL /* free_multi_ssl_backend_data */
|
||||
NULL, /* free_multi_ssl_backend_data */
|
||||
bearssl_recv, /* recv decrypted data */
|
||||
bearssl_send, /* send data to encrypt */
|
||||
};
|
||||
|
||||
#endif /* USE_BEARSSL */
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@
|
|||
#include "sendf.h"
|
||||
#include "gskit.h"
|
||||
#include "vtls.h"
|
||||
#include "vtls_int.h"
|
||||
#include "connect.h" /* for the connect timeout */
|
||||
#include "select.h"
|
||||
#include "strcase.h"
|
||||
|
|
@ -1146,8 +1147,6 @@ static CURLcode gskit_connect_common(struct Curl_easy *data,
|
|||
else if(connssl->connecting_state == ssl_connect_done) {
|
||||
connssl->state = ssl_connection_complete;
|
||||
connssl->connecting_state = ssl_connect_1;
|
||||
conn->recv[sockindex] = gskit_recv;
|
||||
conn->send[sockindex] = gskit_send;
|
||||
*done = TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -1324,7 +1323,9 @@ const struct Curl_ssl Curl_ssl_gskit = {
|
|||
NULL, /* sha256sum */
|
||||
NULL, /* associate_connection */
|
||||
NULL, /* disassociate_connection */
|
||||
NULL /* free_multi_ssl_backend_data */
|
||||
NULL, /* free_multi_ssl_backend_data */
|
||||
gskit_recv, /* recv decrypted data */
|
||||
gskit_send, /* send data to encrypt */
|
||||
};
|
||||
|
||||
#endif /* USE_GSKIT */
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#include "inet_pton.h"
|
||||
#include "gtls.h"
|
||||
#include "vtls.h"
|
||||
#include "vtls_int.h"
|
||||
#include "vauth/vauth.h"
|
||||
#include "parsedate.h"
|
||||
#include "connect.h" /* for the connect timeout */
|
||||
|
|
@ -1383,8 +1384,6 @@ gtls_connect_common(struct Curl_easy *data,
|
|||
rc = Curl_gtls_verifyserver(data, conn, session, sockindex);
|
||||
if(rc)
|
||||
return rc;
|
||||
conn->recv[sockindex] = gtls_recv;
|
||||
conn->send[sockindex] = gtls_send;
|
||||
}
|
||||
|
||||
*done = ssl_connect_1 == connssl->connecting_state;
|
||||
|
|
@ -1700,7 +1699,9 @@ const struct Curl_ssl Curl_ssl_gnutls = {
|
|||
gtls_sha256sum, /* sha256sum */
|
||||
NULL, /* associate_connection */
|
||||
NULL, /* disassociate_connection */
|
||||
NULL /* free_multi_ssl_backend_data */
|
||||
NULL, /* free_multi_ssl_backend_data */
|
||||
gtls_recv, /* recv decrypted data */
|
||||
gtls_send, /* send data to encrypt */
|
||||
};
|
||||
|
||||
#endif /* USE_GNUTLS */
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@
|
|||
#include "inet_pton.h"
|
||||
#include "mbedtls.h"
|
||||
#include "vtls.h"
|
||||
#include "vtls_int.h"
|
||||
#include "parsedate.h"
|
||||
#include "connect.h" /* for the connect timeout */
|
||||
#include "select.h"
|
||||
|
|
@ -675,9 +676,6 @@ mbed_connect_step2(struct Curl_easy *data, struct connectdata *conn,
|
|||
|
||||
DEBUGASSERT(backend);
|
||||
|
||||
conn->recv[sockindex] = mbed_recv;
|
||||
conn->send[sockindex] = mbed_send;
|
||||
|
||||
ret = mbedtls_ssl_handshake(&backend->ssl);
|
||||
|
||||
if(ret == MBEDTLS_ERR_SSL_WANT_READ) {
|
||||
|
|
@ -1147,8 +1145,6 @@ mbed_connect_common(struct Curl_easy *data,
|
|||
|
||||
if(ssl_connect_done == connssl->connecting_state) {
|
||||
connssl->state = ssl_connection_complete;
|
||||
conn->recv[sockindex] = mbed_recv;
|
||||
conn->send[sockindex] = mbed_send;
|
||||
*done = TRUE;
|
||||
}
|
||||
else
|
||||
|
|
@ -1268,7 +1264,9 @@ const struct Curl_ssl Curl_ssl_mbedtls = {
|
|||
mbedtls_sha256sum, /* sha256sum */
|
||||
NULL, /* associate_connection */
|
||||
NULL, /* disassociate_connection */
|
||||
NULL /* free_multi_ssl_backend_data */
|
||||
NULL, /* free_multi_ssl_backend_data */
|
||||
mbed_recv, /* recv decrypted data */
|
||||
mbed_send, /* send data to encrypt */
|
||||
};
|
||||
|
||||
#endif /* USE_MBEDTLS */
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include "strcase.h"
|
||||
#include "select.h"
|
||||
#include "vtls.h"
|
||||
#include "vtls_int.h"
|
||||
#include "llist.h"
|
||||
#include "multiif.h"
|
||||
#include "curl_printf.h"
|
||||
|
|
@ -2319,8 +2320,6 @@ static CURLcode nss_connect_common(struct Curl_easy *data,
|
|||
*done = TRUE;
|
||||
|
||||
connssl->state = ssl_connection_complete;
|
||||
conn->recv[sockindex] = nss_recv;
|
||||
conn->send[sockindex] = nss_send;
|
||||
|
||||
/* ssl_connect_done is never used outside, go back to the initial state */
|
||||
connssl->connecting_state = ssl_connect_1;
|
||||
|
|
@ -2531,7 +2530,9 @@ const struct Curl_ssl Curl_ssl_nss = {
|
|||
nss_sha256sum, /* sha256sum */
|
||||
NULL, /* associate_connection */
|
||||
NULL, /* disassociate_connection */
|
||||
NULL /* free_multi_ssl_backend_data */
|
||||
NULL, /* free_multi_ssl_backend_data */
|
||||
nss_recv, /* recv decrypted data */
|
||||
nss_send, /* send data to encrypt */
|
||||
};
|
||||
|
||||
#endif /* USE_NSS */
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@
|
|||
#include "slist.h"
|
||||
#include "select.h"
|
||||
#include "vtls.h"
|
||||
#include "vtls_int.h"
|
||||
#include "vauth/vauth.h"
|
||||
#include "keylog.h"
|
||||
#include "strcase.h"
|
||||
|
|
@ -4275,8 +4276,6 @@ static CURLcode ossl_connect_common(struct Curl_easy *data,
|
|||
|
||||
if(ssl_connect_done == connssl->connecting_state) {
|
||||
connssl->state = ssl_connection_complete;
|
||||
conn->recv[sockindex] = ossl_recv;
|
||||
conn->send[sockindex] = ossl_send;
|
||||
*done = TRUE;
|
||||
}
|
||||
else
|
||||
|
|
@ -4776,7 +4775,9 @@ const struct Curl_ssl Curl_ssl_openssl = {
|
|||
#endif
|
||||
ossl_associate_connection, /* associate_connection */
|
||||
ossl_disassociate_connection, /* disassociate_connection */
|
||||
ossl_free_multi_ssl_backend_data /* free_multi_ssl_backend_data */
|
||||
ossl_free_multi_ssl_backend_data, /* free_multi_ssl_backend_data */
|
||||
ossl_recv, /* recv decrypted data */
|
||||
ossl_send, /* send data to encrypt */
|
||||
};
|
||||
|
||||
#endif /* USE_OPENSSL */
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -473,8 +474,6 @@ cr_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
|
|||
|
||||
cr_set_negotiated_alpn(data, conn, rconn);
|
||||
|
||||
conn->recv[sockindex] = cr_recv;
|
||||
conn->send[sockindex] = cr_send;
|
||||
*done = TRUE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
|
@ -631,7 +630,9 @@ const struct Curl_ssl Curl_ssl_rustls = {
|
|||
NULL, /* sha256sum */
|
||||
NULL, /* associate_connection */
|
||||
NULL, /* disassociate_connection */
|
||||
NULL /* free_multi_ssl_backend_data */
|
||||
NULL, /* free_multi_ssl_backend_data */
|
||||
cr_recv, /* recv decrypted data */
|
||||
cr_send, /* send data to encrypt */
|
||||
};
|
||||
|
||||
#endif /* USE_RUSTLS */
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include "schannel.h"
|
||||
#include "vtls.h"
|
||||
#include "vtls_int.h"
|
||||
#include "strcase.h"
|
||||
#include "sendf.h"
|
||||
#include "connect.h" /* for the connect timeout */
|
||||
|
|
@ -1935,15 +1936,6 @@ schannel_connect_common(struct Curl_easy *data, struct connectdata *conn,
|
|||
|
||||
if(ssl_connect_done == connssl->connecting_state) {
|
||||
connssl->state = ssl_connection_complete;
|
||||
if(!connssl->backend->recv_renegotiating) {
|
||||
/* On renegotiation, we don't want to reset the existing recv/send
|
||||
* function pointers. They will have been set after the initial TLS
|
||||
* handshake was completed. If they were subsequently modified, as
|
||||
* is the case with HTTP/2, we don't want to override that change.
|
||||
*/
|
||||
conn->recv[sockindex] = schannel_recv;
|
||||
conn->send[sockindex] = schannel_send;
|
||||
}
|
||||
|
||||
#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS
|
||||
/* When SSPI is used in combination with Schannel
|
||||
|
|
@ -2810,7 +2802,9 @@ const struct Curl_ssl Curl_ssl_schannel = {
|
|||
schannel_sha256sum, /* sha256sum */
|
||||
NULL, /* associate_connection */
|
||||
NULL, /* disassociate_connection */
|
||||
NULL /* free_multi_ssl_backend_data */
|
||||
NULL, /* free_multi_ssl_backend_data */
|
||||
schannel_recv, /* recv decrypted data */
|
||||
schannel_send, /* send data to encrypt */
|
||||
};
|
||||
|
||||
#endif /* USE_SCHANNEL */
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#ifdef HAS_MANUAL_VERIFY_API
|
||||
|
||||
#include "vtls.h"
|
||||
#include "vtls_int.h"
|
||||
#include "sendf.h"
|
||||
#include "strerror.h"
|
||||
#include "curl_multibyte.h"
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@
|
|||
#include "connect.h"
|
||||
#include "select.h"
|
||||
#include "vtls.h"
|
||||
#include "vtls_int.h"
|
||||
#include "sectransp.h"
|
||||
#include "curl_printf.h"
|
||||
#include "strdup.h"
|
||||
|
|
@ -3134,8 +3135,6 @@ sectransp_connect_common(struct Curl_easy *data,
|
|||
|
||||
if(ssl_connect_done == connssl->connecting_state) {
|
||||
connssl->state = ssl_connection_complete;
|
||||
conn->recv[sockindex] = sectransp_recv;
|
||||
conn->send[sockindex] = sectransp_send;
|
||||
*done = TRUE;
|
||||
}
|
||||
else
|
||||
|
|
@ -3530,7 +3529,9 @@ const struct Curl_ssl Curl_ssl_sectransp = {
|
|||
sectransp_sha256sum, /* sha256sum */
|
||||
NULL, /* associate_connection */
|
||||
NULL, /* disassociate_connection */
|
||||
NULL /* free_multi_ssl_backend_data */
|
||||
NULL, /* free_multi_ssl_backend_data */
|
||||
sectransp_recv, /* recv decrypted data */
|
||||
sectransp_send, /* send data to encrypt */
|
||||
};
|
||||
|
||||
#ifdef __clang__
|
||||
|
|
|
|||
384
lib/vtls/vtls.c
384
lib/vtls/vtls.c
|
|
@ -51,8 +51,10 @@
|
|||
#endif
|
||||
|
||||
#include "urldata.h"
|
||||
#include "cfilters.h"
|
||||
|
||||
#include "vtls.h" /* generic SSL protos etc */
|
||||
#include "vtls_int.h"
|
||||
#include "slist.h"
|
||||
#include "sendf.h"
|
||||
#include "strcase.h"
|
||||
|
|
@ -295,6 +297,22 @@ static bool ssl_prefs_check(struct Curl_easy *data)
|
|||
static CURLcode
|
||||
ssl_connect_init_proxy(struct connectdata *conn, int sockindex)
|
||||
{
|
||||
/* TODO: curl has, so far, a limit of 2 SSL instances per
|
||||
* connection per sockindex. One for SSL to the origin server
|
||||
* and one for SSL to a proxy server.
|
||||
* - conn->ssl[sockindex]
|
||||
* - conn->ssl_proxy[sockindex]
|
||||
* Any SSL activity always happens on conn->ssl[sockindex], even
|
||||
* if it is to a proxy server. When the handshake is done,
|
||||
* conn->bits.proxy_ssl_connected[sockindex] = TRUE
|
||||
* is set, though conn->ssl_proxy[sockindex] is still empty.
|
||||
*
|
||||
* A new activity, on seeing this, will COPY the contents
|
||||
* of conn->ssl[sockindex] to conn->ssl_proxy[sockindex]
|
||||
* and NUL conn->ssl[sockindex] for a fresh start.
|
||||
*
|
||||
* This is what this function does.
|
||||
*/
|
||||
DEBUGASSERT(conn->bits.proxy_ssl_connected[sockindex]);
|
||||
if(ssl_connection_complete == conn->ssl[sockindex].state &&
|
||||
!conn->proxy_ssl[sockindex].use) {
|
||||
|
|
@ -319,9 +337,8 @@ ssl_connect_init_proxy(struct connectdata *conn, int sockindex)
|
|||
}
|
||||
#endif
|
||||
|
||||
CURLcode
|
||||
Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn,
|
||||
int sockindex)
|
||||
static CURLcode
|
||||
ssl_connect(struct Curl_easy *data, struct connectdata *conn, int sockindex)
|
||||
{
|
||||
CURLcode result;
|
||||
|
||||
|
|
@ -342,17 +359,19 @@ Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn,
|
|||
|
||||
result = Curl_ssl->connect_blocking(data, conn, sockindex);
|
||||
|
||||
if(!result)
|
||||
if(!result) {
|
||||
Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */
|
||||
DEBUGASSERT(conn->ssl[sockindex].state == ssl_connection_complete);
|
||||
}
|
||||
else
|
||||
conn->ssl[sockindex].use = FALSE;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CURLcode
|
||||
Curl_ssl_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
|
||||
bool isproxy, int sockindex, bool *done)
|
||||
static CURLcode
|
||||
ssl_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
|
||||
bool isproxy, int sockindex, bool *done)
|
||||
{
|
||||
CURLcode result;
|
||||
|
||||
|
|
@ -371,8 +390,11 @@ Curl_ssl_connect_nonblocking(struct Curl_easy *data, struct connectdata *conn,
|
|||
result = Curl_ssl->connect_nonblocking(data, conn, sockindex, done);
|
||||
if(result)
|
||||
conn->ssl[sockindex].use = FALSE;
|
||||
else if(*done && !isproxy)
|
||||
Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */
|
||||
else if(*done) {
|
||||
if(!isproxy)
|
||||
Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSL is connected */
|
||||
DEBUGASSERT(conn->ssl[sockindex].state == ssl_connection_complete);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -633,28 +655,6 @@ CURLcode Curl_ssl_addsessionid(struct Curl_easy *data,
|
|||
return CURLE_OK;
|
||||
}
|
||||
|
||||
void Curl_ssl_associate_conn(struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
if(Curl_ssl->associate_connection) {
|
||||
Curl_ssl->associate_connection(data, conn, FIRSTSOCKET);
|
||||
if((conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) &&
|
||||
conn->bits.sock_accepted)
|
||||
Curl_ssl->associate_connection(data, conn, SECONDARYSOCKET);
|
||||
}
|
||||
}
|
||||
|
||||
void Curl_ssl_detach_conn(struct Curl_easy *data,
|
||||
struct connectdata *conn)
|
||||
{
|
||||
if(Curl_ssl->disassociate_connection) {
|
||||
Curl_ssl->disassociate_connection(data, FIRSTSOCKET);
|
||||
if((conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD) &&
|
||||
conn->bits.sock_accepted)
|
||||
Curl_ssl->disassociate_connection(data, SECONDARYSOCKET);
|
||||
}
|
||||
}
|
||||
|
||||
void Curl_free_multi_ssl_backend_data(struct multi_ssl_backend_data *mbackend)
|
||||
{
|
||||
if(Curl_ssl->free_multi_ssl_backend_data && mbackend)
|
||||
|
|
@ -695,14 +695,6 @@ int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks)
|
|||
return GETSOCK_BLANK;
|
||||
}
|
||||
|
||||
void Curl_ssl_close(struct Curl_easy *data, struct connectdata *conn,
|
||||
int sockindex)
|
||||
{
|
||||
DEBUGASSERT((sockindex <= 1) && (sockindex >= -1));
|
||||
Curl_ssl->close_one(data, conn, sockindex);
|
||||
conn->ssl[sockindex].state = ssl_connection_none;
|
||||
}
|
||||
|
||||
CURLcode Curl_ssl_shutdown(struct Curl_easy *data, struct connectdata *conn,
|
||||
int sockindex)
|
||||
{
|
||||
|
|
@ -712,9 +704,6 @@ CURLcode Curl_ssl_shutdown(struct Curl_easy *data, struct connectdata *conn,
|
|||
conn->ssl[sockindex].use = FALSE; /* get back to ordinary socket usage */
|
||||
conn->ssl[sockindex].state = ssl_connection_none;
|
||||
|
||||
conn->recv[sockindex] = Curl_recv_plain;
|
||||
conn->send[sockindex] = Curl_send_plain;
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
|
@ -785,12 +774,6 @@ int Curl_ssl_check_cxn(struct connectdata *conn)
|
|||
return Curl_ssl->check_cxn(conn);
|
||||
}
|
||||
|
||||
bool Curl_ssl_data_pending(const struct connectdata *conn,
|
||||
int connindex)
|
||||
{
|
||||
return Curl_ssl->data_pending(conn, connindex);
|
||||
}
|
||||
|
||||
void Curl_ssl_free_certinfo(struct Curl_easy *data)
|
||||
{
|
||||
struct curl_certinfo *ci = &data->info.certs;
|
||||
|
|
@ -1144,19 +1127,12 @@ bool Curl_ssl_cert_status_request(void)
|
|||
/*
|
||||
* Check whether the SSL backend supports false start.
|
||||
*/
|
||||
bool Curl_ssl_false_start(void)
|
||||
bool Curl_ssl_false_start(struct Curl_easy *data)
|
||||
{
|
||||
(void)data;
|
||||
return Curl_ssl->false_start();
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether the SSL backend supports setting TLS 1.3 cipher suites
|
||||
*/
|
||||
bool Curl_ssl_tls13_ciphersuites(void)
|
||||
{
|
||||
return Curl_ssl->supports & SSLSUPP_TLS13_CIPHERSUITES;
|
||||
}
|
||||
|
||||
/*
|
||||
* Default implementations for unsupported functions.
|
||||
*/
|
||||
|
|
@ -1290,6 +1266,23 @@ static void multissl_close(struct Curl_easy *data, struct connectdata *conn,
|
|||
Curl_ssl->close_one(data, conn, sockindex);
|
||||
}
|
||||
|
||||
static ssize_t multissl_recv_plain(struct Curl_easy *data, int sockindex,
|
||||
char *buf, size_t len, CURLcode *code)
|
||||
{
|
||||
if(multissl_setup(NULL))
|
||||
return CURLE_FAILED_INIT;
|
||||
return Curl_ssl->recv_plain(data, sockindex, buf, len, code);
|
||||
}
|
||||
|
||||
static ssize_t multissl_send_plain(struct Curl_easy *data, int sockindex,
|
||||
const void *mem, size_t len,
|
||||
CURLcode *code)
|
||||
{
|
||||
if(multissl_setup(NULL))
|
||||
return CURLE_FAILED_INIT;
|
||||
return Curl_ssl->send_plain(data, sockindex, mem, len, code);
|
||||
}
|
||||
|
||||
static const struct Curl_ssl Curl_ssl_multi = {
|
||||
{ CURLSSLBACKEND_NONE, "multi" }, /* info */
|
||||
0, /* supports nothing */
|
||||
|
|
@ -1317,7 +1310,9 @@ static const struct Curl_ssl Curl_ssl_multi = {
|
|||
NULL, /* sha256sum */
|
||||
NULL, /* associate_connection */
|
||||
NULL, /* disassociate_connection */
|
||||
NULL /* free_multi_ssl_backend_data */
|
||||
NULL, /* free_multi_ssl_backend_data */
|
||||
multissl_recv_plain, /* recv decrypted data */
|
||||
multissl_send_plain, /* send data to encrypt */
|
||||
};
|
||||
|
||||
const struct Curl_ssl *Curl_ssl =
|
||||
|
|
@ -1505,3 +1500,276 @@ CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
|
|||
}
|
||||
|
||||
#endif /* !USE_SSL */
|
||||
|
||||
#ifdef USE_SSL
|
||||
|
||||
static void cf_close(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
{
|
||||
/* TODO: close_one closes BOTH conn->ssl AND conn->proxy_ssl for this
|
||||
* sockindex (if in use). Gladly, it is safe to call more than once. */
|
||||
Curl_ssl->close_one(data, cf->conn, cf->sockindex);
|
||||
cf->conn->ssl[cf->sockindex].state = ssl_connection_none;
|
||||
cf->conn->bits.proxy_ssl_connected[cf->sockindex] = FALSE;
|
||||
cf->connected = FALSE;
|
||||
}
|
||||
|
||||
static void ssl_cf_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
|
||||
{
|
||||
cf_close(cf, data);
|
||||
}
|
||||
|
||||
static CURLcode ssl_cf_setup(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
const struct Curl_dns_entry *remotehost)
|
||||
{
|
||||
CURLcode result;
|
||||
|
||||
result = cf->next->cft->setup(cf->next, data, remotehost);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
/* TODO our setup */
|
||||
return result;
|
||||
}
|
||||
|
||||
static void ssl_cf_close(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
cf_close(cf, data);
|
||||
cf->next->cft->close(cf->next, data);
|
||||
}
|
||||
|
||||
static CURLcode ssl_cf_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
{
|
||||
CURLcode result;
|
||||
|
||||
if(cf->connected) {
|
||||
*done = TRUE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
result = cf->next->cft->connect(cf->next, data, blocking, done);
|
||||
if(result || !*done)
|
||||
return result;
|
||||
|
||||
*done = FALSE;
|
||||
if(blocking) {
|
||||
result = ssl_connect(data, cf->conn, cf->sockindex);
|
||||
*done = (result == CURLE_OK);
|
||||
}
|
||||
else {
|
||||
result = ssl_connect_nonblocking(data, cf->conn, FALSE,
|
||||
cf->sockindex, done);
|
||||
}
|
||||
if (*done)
|
||||
cf->connected = TRUE;
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode ssl_proxy_cf_connect(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
bool blocking, bool *done)
|
||||
{
|
||||
CURLcode result;
|
||||
|
||||
if(cf->connected) {
|
||||
*done = TRUE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
result = ssl_cf_connect(cf, data, blocking, done);
|
||||
if(!result && *done) {
|
||||
cf->conn->bits.proxy_ssl_connected[cf->sockindex] = TRUE;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool ssl_cf_data_pending(struct Curl_cfilter *cf,
|
||||
const struct Curl_easy *data)
|
||||
{
|
||||
if(Curl_ssl->data_pending(cf->conn, cf->sockindex))
|
||||
return TRUE;
|
||||
return cf->next->cft->has_data_pending(cf->next, data);
|
||||
}
|
||||
|
||||
static ssize_t ssl_cf_send(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data, const void *buf, size_t len,
|
||||
CURLcode *err)
|
||||
{
|
||||
ssize_t nwritten;
|
||||
|
||||
*err = CURLE_OK;
|
||||
nwritten = Curl_ssl->send_plain(data, cf->sockindex, buf, len, err);
|
||||
DEBUGF(infof(data, "cf_ssl_send(handle=%p, len=%ld) -> %ld, code=%d",
|
||||
data, len, nwritten, *err));
|
||||
return nwritten;
|
||||
}
|
||||
|
||||
static ssize_t ssl_cf_recv(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data, char *buf, size_t len,
|
||||
CURLcode *err)
|
||||
{
|
||||
ssize_t nread;
|
||||
|
||||
*err = CURLE_OK;
|
||||
nread = Curl_ssl->recv_plain(data, cf->sockindex, buf, len, err);
|
||||
DEBUGF(infof(data, "cf_ssl_recv(handle=%p) -> %ld, code=%d",
|
||||
data, nread, *err));
|
||||
return nread;
|
||||
}
|
||||
|
||||
static int ssl_cf_get_select_socks(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
curl_socket_t *socks)
|
||||
{
|
||||
/* TODO, this needs to work for other than SOCKETFIRST filters
|
||||
* and also nested filters. Needs change of implementations.
|
||||
* What we really want to know if the SSL implementation wants
|
||||
* to READ or WRITE or needs nothing.
|
||||
*/
|
||||
(void)data;
|
||||
return Curl_ssl->getsock(cf->conn, socks);
|
||||
}
|
||||
|
||||
static void ssl_cf_def_attach_data(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
if(Curl_ssl->associate_connection) {
|
||||
Curl_ssl->associate_connection(data, cf->conn, cf->sockindex);
|
||||
}
|
||||
}
|
||||
|
||||
static void ssl_cf_def_detach_data(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
if(Curl_ssl->disassociate_connection) {
|
||||
Curl_ssl->disassociate_connection(data, cf->sockindex);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct Curl_cftype cft_ssl = {
|
||||
"SSL",
|
||||
ssl_cf_destroy,
|
||||
ssl_cf_def_attach_data,
|
||||
ssl_cf_def_detach_data,
|
||||
ssl_cf_setup,
|
||||
ssl_cf_close,
|
||||
ssl_cf_connect,
|
||||
ssl_cf_get_select_socks,
|
||||
ssl_cf_data_pending,
|
||||
ssl_cf_send,
|
||||
ssl_cf_recv,
|
||||
};
|
||||
|
||||
static const struct Curl_cftype cft_ssl_proxy = {
|
||||
"SSL-PROXY",
|
||||
ssl_cf_destroy,
|
||||
ssl_cf_def_attach_data,
|
||||
ssl_cf_def_detach_data,
|
||||
ssl_cf_setup,
|
||||
ssl_cf_close,
|
||||
ssl_proxy_cf_connect,
|
||||
ssl_cf_get_select_socks,
|
||||
ssl_cf_data_pending,
|
||||
ssl_cf_send,
|
||||
ssl_cf_recv,
|
||||
};
|
||||
|
||||
CURLcode Curl_cfilter_ssl_add(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex)
|
||||
{
|
||||
struct Curl_cfilter *cf;
|
||||
CURLcode result;
|
||||
|
||||
result = Curl_cfilter_create(&cf, data, conn, sockindex,
|
||||
&cft_ssl, NULL);
|
||||
if(!result)
|
||||
Curl_cfilter_add(data, conn, sockindex, cf);
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
CURLcode Curl_cfilter_ssl_proxy_add(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex)
|
||||
{
|
||||
struct Curl_cfilter *cf;
|
||||
CURLcode result;
|
||||
|
||||
result = Curl_cfilter_create(&cf, data, conn, sockindex,
|
||||
&cft_ssl_proxy, NULL);
|
||||
if(!result)
|
||||
Curl_cfilter_add(data, conn, sockindex, cf);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* !CURL_DISABLE_PROXY */
|
||||
|
||||
size_t Curl_ssl_get_backend_data_size(struct Curl_easy *data)
|
||||
{
|
||||
(void)data;
|
||||
return Curl_ssl->sizeof_ssl_backend_data;
|
||||
}
|
||||
|
||||
bool Curl_ssl_supports(struct Curl_easy *data, int option)
|
||||
{
|
||||
(void)data;
|
||||
return (Curl_ssl->supports & option)? TRUE : FALSE;
|
||||
}
|
||||
|
||||
void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
|
||||
CURLINFO info, int n)
|
||||
{
|
||||
struct connectdata *conn = data->conn;
|
||||
|
||||
#if 0
|
||||
struct Curl_cfilter *cf = conn? conn->cfilters[sockindex] : NULL;
|
||||
|
||||
for(; cf; cf = cf->next) {
|
||||
if(cf->cft == cft_ssl || cf->cft == cft_ssl_proxy) {
|
||||
if(n > 0) {
|
||||
--n;
|
||||
continue;
|
||||
}
|
||||
/* TODO: use cf->ctx instance once we have that */
|
||||
return Curl_ssl->get_internals(&data->conn->ssl[0], info);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if(conn) {
|
||||
size_t i;
|
||||
(void)n;
|
||||
(void)sockindex;
|
||||
for(i = 0; i < (sizeof(conn->ssl) / sizeof(conn->ssl[0])); ++i) {
|
||||
if(conn->ssl[i].use) {
|
||||
return Curl_ssl->get_internals(&conn->ssl[i], info);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool Curl_ssl_use(struct connectdata *conn, int sockindex)
|
||||
{
|
||||
return conn->ssl[sockindex].use;
|
||||
}
|
||||
|
||||
bool Curl_cfilter_ssl_added(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex)
|
||||
{
|
||||
struct Curl_cfilter *cf = conn? conn->cfilter[sockindex] : NULL;
|
||||
|
||||
(void)data;
|
||||
for(; cf; cf = cf->next) {
|
||||
if(cf->cft == &cft_ssl)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif /* USE_SSL */
|
||||
|
|
|
|||
169
lib/vtls/vtls.h
169
lib/vtls/vtls.h
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
struct connectdata;
|
||||
struct ssl_connect_data;
|
||||
struct ssl_primary_config;
|
||||
struct Curl_ssl_session;
|
||||
|
||||
#define SSLSUPP_CA_PATH (1<<0) /* supports CAPATH */
|
||||
#define SSLSUPP_CERTINFO (1<<1) /* supports CURLOPT_CERTINFO */
|
||||
|
|
@ -51,100 +53,9 @@ struct ssl_connect_data;
|
|||
backend */
|
||||
struct multi_ssl_backend_data;
|
||||
|
||||
struct Curl_ssl {
|
||||
/*
|
||||
* This *must* be the first entry to allow returning the list of available
|
||||
* backends in curl_global_sslset().
|
||||
*/
|
||||
curl_ssl_backend info;
|
||||
unsigned int supports; /* bitfield, see above */
|
||||
size_t sizeof_ssl_backend_data;
|
||||
|
||||
int (*init)(void);
|
||||
void (*cleanup)(void);
|
||||
|
||||
size_t (*version)(char *buffer, size_t size);
|
||||
int (*check_cxn)(struct connectdata *cxn);
|
||||
int (*shut_down)(struct Curl_easy *data, struct connectdata *conn,
|
||||
int sockindex);
|
||||
bool (*data_pending)(const struct connectdata *conn,
|
||||
int connindex);
|
||||
|
||||
/* return 0 if a find random is filled in */
|
||||
CURLcode (*random)(struct Curl_easy *data, unsigned char *entropy,
|
||||
size_t length);
|
||||
bool (*cert_status_request)(void);
|
||||
|
||||
CURLcode (*connect_blocking)(struct Curl_easy *data,
|
||||
struct connectdata *conn, int sockindex);
|
||||
CURLcode (*connect_nonblocking)(struct Curl_easy *data,
|
||||
struct connectdata *conn, int sockindex,
|
||||
bool *done);
|
||||
|
||||
/* If the SSL backend wants to read or write on this connection during a
|
||||
handshake, set socks[0] to the connection's FIRSTSOCKET, and return
|
||||
a bitmap indicating read or write with GETSOCK_WRITESOCK(0) or
|
||||
GETSOCK_READSOCK(0). Otherwise return GETSOCK_BLANK.
|
||||
Mandatory. */
|
||||
int (*getsock)(struct connectdata *conn, curl_socket_t *socks);
|
||||
|
||||
void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info);
|
||||
void (*close_one)(struct Curl_easy *data, struct connectdata *conn,
|
||||
int sockindex);
|
||||
void (*close_all)(struct Curl_easy *data);
|
||||
void (*session_free)(void *ptr);
|
||||
|
||||
CURLcode (*set_engine)(struct Curl_easy *data, const char *engine);
|
||||
CURLcode (*set_engine_default)(struct Curl_easy *data);
|
||||
struct curl_slist *(*engines_list)(struct Curl_easy *data);
|
||||
|
||||
bool (*false_start)(void);
|
||||
CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen,
|
||||
unsigned char *sha256sum, size_t sha256sumlen);
|
||||
|
||||
bool (*associate_connection)(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex);
|
||||
void (*disassociate_connection)(struct Curl_easy *data, int sockindex);
|
||||
|
||||
void (*free_multi_ssl_backend_data)(struct multi_ssl_backend_data *mbackend);
|
||||
};
|
||||
|
||||
#ifdef USE_SSL
|
||||
extern const struct Curl_ssl *Curl_ssl;
|
||||
#endif
|
||||
|
||||
int Curl_none_init(void);
|
||||
void Curl_none_cleanup(void);
|
||||
int Curl_none_shutdown(struct Curl_easy *data, struct connectdata *conn,
|
||||
int sockindex);
|
||||
int Curl_none_check_cxn(struct connectdata *conn);
|
||||
CURLcode Curl_none_random(struct Curl_easy *data, unsigned char *entropy,
|
||||
size_t length);
|
||||
void Curl_none_close_all(struct Curl_easy *data);
|
||||
void Curl_none_session_free(void *ptr);
|
||||
bool Curl_none_data_pending(const struct connectdata *conn, int connindex);
|
||||
bool Curl_none_cert_status_request(void);
|
||||
CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine);
|
||||
CURLcode Curl_none_set_engine_default(struct Curl_easy *data);
|
||||
struct curl_slist *Curl_none_engines_list(struct Curl_easy *data);
|
||||
bool Curl_none_false_start(void);
|
||||
bool Curl_ssl_tls13_ciphersuites(void);
|
||||
|
||||
CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name,
|
||||
const curl_ssl_backend ***avail);
|
||||
|
||||
#include "openssl.h" /* OpenSSL versions */
|
||||
#include "gtls.h" /* GnuTLS versions */
|
||||
#include "nssg.h" /* NSS versions */
|
||||
#include "gskit.h" /* Global Secure ToolKit versions */
|
||||
#include "wolfssl.h" /* wolfSSL versions */
|
||||
#include "schannel.h" /* Schannel SSPI version */
|
||||
#include "sectransp.h" /* SecureTransport (Darwin) version */
|
||||
#include "mbedtls.h" /* mbedTLS versions */
|
||||
#include "bearssl.h" /* BearSSL versions */
|
||||
#include "rustls.h" /* rustls versions */
|
||||
|
||||
#ifndef MAX_PINNED_PUBKEY_SIZE
|
||||
#define MAX_PINNED_PUBKEY_SIZE 1048576 /* 1MB */
|
||||
#endif
|
||||
|
|
@ -200,29 +111,15 @@ bool Curl_ssl_config_matches(struct ssl_primary_config *data,
|
|||
bool Curl_clone_primary_ssl_config(struct ssl_primary_config *source,
|
||||
struct ssl_primary_config *dest);
|
||||
void Curl_free_primary_ssl_config(struct ssl_primary_config *sslc);
|
||||
/* An implementation of the getsock field of Curl_ssl that relies
|
||||
on the ssl_connect_state enum. Asks for read or write depending
|
||||
on whether conn->state is ssl_connect_2_reading or
|
||||
ssl_connect_2_writing. */
|
||||
int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks);
|
||||
|
||||
curl_sslbackend Curl_ssl_backend(void);
|
||||
|
||||
#ifdef USE_SSL
|
||||
int Curl_ssl_init(void);
|
||||
void Curl_ssl_cleanup(void);
|
||||
CURLcode Curl_ssl_connect(struct Curl_easy *data, struct connectdata *conn,
|
||||
int sockindex);
|
||||
CURLcode Curl_ssl_connect_nonblocking(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
bool isproxy,
|
||||
int sockindex,
|
||||
bool *done);
|
||||
/* tell the SSL stuff to close down all open information regarding
|
||||
connections (and thus session ID caching etc) */
|
||||
void Curl_ssl_close_all(struct Curl_easy *data);
|
||||
void Curl_ssl_close(struct Curl_easy *data, struct connectdata *conn,
|
||||
int sockindex);
|
||||
CURLcode Curl_ssl_shutdown(struct Curl_easy *data, struct connectdata *conn,
|
||||
int sockindex);
|
||||
CURLcode Curl_ssl_set_engine(struct Curl_easy *data, const char *engine);
|
||||
|
|
@ -233,8 +130,6 @@ struct curl_slist *Curl_ssl_engines_list(struct Curl_easy *data);
|
|||
/* init the SSL session ID cache */
|
||||
CURLcode Curl_ssl_initsessions(struct Curl_easy *, size_t);
|
||||
void Curl_ssl_version(char *buffer, size_t size);
|
||||
bool Curl_ssl_data_pending(const struct connectdata *conn,
|
||||
int connindex);
|
||||
int Curl_ssl_check_cxn(struct connectdata *conn);
|
||||
|
||||
/* Certificate information list handling. */
|
||||
|
|
@ -310,43 +205,71 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data,
|
|||
|
||||
bool Curl_ssl_cert_status_request(void);
|
||||
|
||||
bool Curl_ssl_false_start(void);
|
||||
|
||||
void Curl_ssl_associate_conn(struct Curl_easy *data,
|
||||
struct connectdata *conn);
|
||||
void Curl_ssl_detach_conn(struct Curl_easy *data,
|
||||
struct connectdata *conn);
|
||||
bool Curl_ssl_false_start(struct Curl_easy *data);
|
||||
|
||||
void Curl_free_multi_ssl_backend_data(struct multi_ssl_backend_data *mbackend);
|
||||
|
||||
#define SSL_SHUTDOWN_TIMEOUT 10000 /* ms */
|
||||
|
||||
CURLcode Curl_cfilter_ssl_add(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex);
|
||||
|
||||
#ifndef CURL_DISABLE_PROXY
|
||||
CURLcode Curl_cfilter_ssl_proxy_add(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex);
|
||||
#endif /* !CURL_DISABLE_PROXY */
|
||||
|
||||
bool Curl_cfilter_ssl_added(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex);
|
||||
|
||||
/**
|
||||
* True iff the underlying SSL implementation supports the option.
|
||||
* Option is one of the defined SSLSUPP_* values.
|
||||
* `data` maybe NULL for the features of the default implementation.
|
||||
*/
|
||||
bool Curl_ssl_supports(struct Curl_easy *data, int ssl_option);
|
||||
|
||||
/**
|
||||
* Get the internal ssl instance (like OpenSSL's SSL*) from the filter
|
||||
* chain at `sockindex` of type specified by `info`.
|
||||
* For `n` == 0, the first active (top down) instance is returned.
|
||||
* 1 gives the second active, etc.
|
||||
* NULL is returned when no active SSL filter is present.
|
||||
*/
|
||||
void *Curl_ssl_get_internals(struct Curl_easy *data, int sockindex,
|
||||
CURLINFO info, int n);
|
||||
|
||||
size_t Curl_ssl_get_backend_data_size(struct Curl_easy *data);
|
||||
|
||||
bool Curl_ssl_use(struct connectdata *conn, int sockindex);
|
||||
|
||||
#else /* if not USE_SSL */
|
||||
|
||||
/* When SSL support is not present, just define away these function calls */
|
||||
#define Curl_ssl_init() 1
|
||||
#define Curl_ssl_cleanup() Curl_nop_stmt
|
||||
#define Curl_ssl_connect(x,y,z) CURLE_NOT_BUILT_IN
|
||||
#define Curl_ssl_close_all(x) Curl_nop_stmt
|
||||
#define Curl_ssl_close(x,y,z) Curl_nop_stmt
|
||||
#define Curl_ssl_shutdown(x,y,z) CURLE_NOT_BUILT_IN
|
||||
#define Curl_ssl_set_engine(x,y) CURLE_NOT_BUILT_IN
|
||||
#define Curl_ssl_set_engine_default(x) CURLE_NOT_BUILT_IN
|
||||
#define Curl_ssl_engines_list(x) NULL
|
||||
#define Curl_ssl_send(a,b,c,d,e) -1
|
||||
#define Curl_ssl_recv(a,b,c,d,e) -1
|
||||
#define Curl_ssl_initsessions(x,y) CURLE_OK
|
||||
#define Curl_ssl_data_pending(x,y) 0
|
||||
#define Curl_ssl_check_cxn(x) 0
|
||||
#define Curl_ssl_free_certinfo(x) Curl_nop_stmt
|
||||
#define Curl_ssl_connect_nonblocking(x,y,z,w,a) CURLE_NOT_BUILT_IN
|
||||
#define Curl_ssl_kill_session(x) Curl_nop_stmt
|
||||
#define Curl_ssl_random(x,y,z) ((void)x, CURLE_NOT_BUILT_IN)
|
||||
#define Curl_ssl_cert_status_request() FALSE
|
||||
#define Curl_ssl_false_start() FALSE
|
||||
#define Curl_ssl_tls13_ciphersuites() FALSE
|
||||
#define Curl_ssl_associate_conn(a,b) Curl_nop_stmt
|
||||
#define Curl_ssl_detach_conn(a,b) Curl_nop_stmt
|
||||
#define Curl_ssl_false_start(a) FALSE
|
||||
#define Curl_ssl_get_internals(a,b,c,d) NULL
|
||||
#define Curl_ssl_supports(a,b) FALSE
|
||||
#define Curl_ssl_get_backend_data_size(a) 0
|
||||
#define Curl_ssl_use(a,b) FALSE
|
||||
#define Curl_cfilter_ssl_added(a,b,c) FALSE
|
||||
#define Curl_cfilter_ssl_add(a,b,c) CURLE_NOT_BUILT_IN
|
||||
#define Curl_cfilter_ssl_proxy_add(a,b,c) CURLE_NOT_BUILT_IN
|
||||
#endif
|
||||
|
||||
#endif /* HEADER_CURL_VTLS_H */
|
||||
|
|
|
|||
127
lib/vtls/vtls_int.h
Normal file
127
lib/vtls/vtls_int.h
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
#ifndef HEADER_CURL_VTLS_INT_H
|
||||
#define HEADER_CURL_VTLS_INT_H
|
||||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
* are also available at https://curl.se/docs/copyright.html.
|
||||
*
|
||||
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||
* copies of the Software, and permit persons to whom the Software is
|
||||
* furnished to do so, under the terms of the COPYING file.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
#include "curl_setup.h"
|
||||
#include "urldata.h"
|
||||
|
||||
/* Definitions for SSL Implementations */
|
||||
|
||||
struct Curl_ssl {
|
||||
/*
|
||||
* This *must* be the first entry to allow returning the list of available
|
||||
* backends in curl_global_sslset().
|
||||
*/
|
||||
curl_ssl_backend info;
|
||||
unsigned int supports; /* bitfield, see above */
|
||||
size_t sizeof_ssl_backend_data;
|
||||
|
||||
int (*init)(void);
|
||||
void (*cleanup)(void);
|
||||
|
||||
size_t (*version)(char *buffer, size_t size);
|
||||
int (*check_cxn)(struct connectdata *cxn);
|
||||
int (*shut_down)(struct Curl_easy *data, struct connectdata *conn,
|
||||
int sockindex);
|
||||
bool (*data_pending)(const struct connectdata *conn,
|
||||
int connindex);
|
||||
|
||||
/* return 0 if a find random is filled in */
|
||||
CURLcode (*random)(struct Curl_easy *data, unsigned char *entropy,
|
||||
size_t length);
|
||||
bool (*cert_status_request)(void);
|
||||
|
||||
CURLcode (*connect_blocking)(struct Curl_easy *data,
|
||||
struct connectdata *conn, int sockindex);
|
||||
CURLcode (*connect_nonblocking)(struct Curl_easy *data,
|
||||
struct connectdata *conn, int sockindex,
|
||||
bool *done);
|
||||
|
||||
/* If the SSL backend wants to read or write on this connection during a
|
||||
handshake, set socks[0] to the connection's FIRSTSOCKET, and return
|
||||
a bitmap indicating read or write with GETSOCK_WRITESOCK(0) or
|
||||
GETSOCK_READSOCK(0). Otherwise return GETSOCK_BLANK.
|
||||
Mandatory. */
|
||||
int (*getsock)(struct connectdata *conn, curl_socket_t *socks);
|
||||
|
||||
void *(*get_internals)(struct ssl_connect_data *connssl, CURLINFO info);
|
||||
void (*close_one)(struct Curl_easy *data, struct connectdata *conn,
|
||||
int sockindex);
|
||||
void (*close_all)(struct Curl_easy *data);
|
||||
void (*session_free)(void *ptr);
|
||||
|
||||
CURLcode (*set_engine)(struct Curl_easy *data, const char *engine);
|
||||
CURLcode (*set_engine_default)(struct Curl_easy *data);
|
||||
struct curl_slist *(*engines_list)(struct Curl_easy *data);
|
||||
|
||||
bool (*false_start)(void);
|
||||
CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen,
|
||||
unsigned char *sha256sum, size_t sha256sumlen);
|
||||
|
||||
bool (*associate_connection)(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
int sockindex);
|
||||
void (*disassociate_connection)(struct Curl_easy *data, int sockindex);
|
||||
|
||||
void (*free_multi_ssl_backend_data)(struct multi_ssl_backend_data *mbackend);
|
||||
|
||||
ssize_t (*recv_plain)(struct Curl_easy *data, int sockindex, char *buf,
|
||||
size_t len, CURLcode *code);
|
||||
ssize_t (*send_plain)(struct Curl_easy *data, int sockindex,
|
||||
const void *mem, size_t len, CURLcode *code);
|
||||
|
||||
};
|
||||
|
||||
extern const struct Curl_ssl *Curl_ssl;
|
||||
|
||||
|
||||
int Curl_none_init(void);
|
||||
void Curl_none_cleanup(void);
|
||||
int Curl_none_shutdown(struct Curl_easy *data, struct connectdata *conn,
|
||||
int sockindex);
|
||||
int Curl_none_check_cxn(struct connectdata *conn);
|
||||
CURLcode Curl_none_random(struct Curl_easy *data, unsigned char *entropy,
|
||||
size_t length);
|
||||
void Curl_none_close_all(struct Curl_easy *data);
|
||||
void Curl_none_session_free(void *ptr);
|
||||
bool Curl_none_data_pending(const struct connectdata *conn, int connindex);
|
||||
bool Curl_none_cert_status_request(void);
|
||||
CURLcode Curl_none_set_engine(struct Curl_easy *data, const char *engine);
|
||||
CURLcode Curl_none_set_engine_default(struct Curl_easy *data);
|
||||
struct curl_slist *Curl_none_engines_list(struct Curl_easy *data);
|
||||
bool Curl_none_false_start(void);
|
||||
int Curl_ssl_getsock(struct connectdata *conn, curl_socket_t *socks);
|
||||
|
||||
#include "openssl.h" /* OpenSSL versions */
|
||||
#include "gtls.h" /* GnuTLS versions */
|
||||
#include "nssg.h" /* NSS versions */
|
||||
#include "gskit.h" /* Global Secure ToolKit versions */
|
||||
#include "wolfssl.h" /* wolfSSL versions */
|
||||
#include "schannel.h" /* Schannel SSPI version */
|
||||
#include "sectransp.h" /* SecureTransport (Darwin) version */
|
||||
#include "mbedtls.h" /* mbedTLS versions */
|
||||
#include "bearssl.h" /* BearSSL versions */
|
||||
#include "rustls.h" /* rustls versions */
|
||||
|
||||
#endif /* HEADER_CURL_VTLS_INT_H */
|
||||
|
|
@ -55,6 +55,7 @@
|
|||
#include "sendf.h"
|
||||
#include "inet_pton.h"
|
||||
#include "vtls.h"
|
||||
#include "vtls_int.h"
|
||||
#include "keylog.h"
|
||||
#include "parsedate.h"
|
||||
#include "connect.h" /* for the connect timeout */
|
||||
|
|
@ -606,9 +607,6 @@ wolfssl_connect_step2(struct Curl_easy *data, struct connectdata *conn,
|
|||
|
||||
ERR_clear_error();
|
||||
|
||||
conn->recv[sockindex] = wolfssl_recv;
|
||||
conn->send[sockindex] = wolfssl_send;
|
||||
|
||||
/* Enable RFC2818 checks */
|
||||
if(SSL_CONN_CONFIG(verifyhost)) {
|
||||
char *snihost = Curl_ssl_snihost(data, SSL_HOST_NAME(), NULL);
|
||||
|
|
@ -1135,8 +1133,6 @@ wolfssl_connect_common(struct Curl_easy *data,
|
|||
|
||||
if(ssl_connect_done == connssl->connecting_state) {
|
||||
connssl->state = ssl_connection_complete;
|
||||
conn->recv[sockindex] = wolfssl_recv;
|
||||
conn->send[sockindex] = wolfssl_send;
|
||||
*done = TRUE;
|
||||
}
|
||||
else
|
||||
|
|
@ -1242,7 +1238,9 @@ const struct Curl_ssl Curl_ssl_wolfssl = {
|
|||
wolfssl_sha256sum, /* sha256sum */
|
||||
NULL, /* associate_connection */
|
||||
NULL, /* disassociate_connection */
|
||||
NULL /* free_multi_ssl_backend_data */
|
||||
NULL, /* free_multi_ssl_backend_data */
|
||||
wolfssl_recv, /* recv decrypted data */
|
||||
wolfssl_send, /* send data to encrypt */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue