mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-12-22 12:12:35 +03:00
Downgrade TLS version support if it turns out the server can't cope with TLSv1.1.
This commit is contained in:
parent
d0d3d31e97
commit
3dff750ae2
@ -85,7 +85,7 @@ static bool fetch_rsrc_can_fetch(const nsurl *url)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void *fetch_rsrc_setup(struct fetch *parent_fetch, nsurl *url,
|
static void *fetch_rsrc_setup(struct fetch *parent_fetch, nsurl *url,
|
||||||
bool only_2xx, const char *post_urlenc,
|
bool only_2xx, bool downgrade_tls, const char *post_urlenc,
|
||||||
const struct fetch_multipart_data *post_multipart,
|
const struct fetch_multipart_data *post_multipart,
|
||||||
const char **headers)
|
const char **headers)
|
||||||
{
|
{
|
||||||
|
@ -235,7 +235,8 @@ struct fetch * fetch_start(nsurl *url, nsurl *referer,
|
|||||||
fetch_callback callback,
|
fetch_callback callback,
|
||||||
void *p, bool only_2xx, const char *post_urlenc,
|
void *p, bool only_2xx, const char *post_urlenc,
|
||||||
const struct fetch_multipart_data *post_multipart,
|
const struct fetch_multipart_data *post_multipart,
|
||||||
bool verifiable, const char *headers[])
|
bool verifiable, bool downgrade_tls,
|
||||||
|
const char *headers[])
|
||||||
{
|
{
|
||||||
struct fetch *fetch;
|
struct fetch *fetch;
|
||||||
scheme_fetcher *fetcher = fetchers;
|
scheme_fetcher *fetcher = fetchers;
|
||||||
@ -321,8 +322,9 @@ struct fetch * fetch_start(nsurl *url, nsurl *referer,
|
|||||||
|
|
||||||
/* Got a scheme fetcher, try and set up the fetch */
|
/* Got a scheme fetcher, try and set up the fetch */
|
||||||
fetch->fetcher_handle = fetch->ops->setup_fetch(fetch, url,
|
fetch->fetcher_handle = fetch->ops->setup_fetch(fetch, url,
|
||||||
only_2xx, post_urlenc,
|
only_2xx, downgrade_tls,
|
||||||
post_multipart, headers);
|
post_urlenc, post_multipart,
|
||||||
|
headers);
|
||||||
|
|
||||||
if (fetch->fetcher_handle == NULL)
|
if (fetch->fetcher_handle == NULL)
|
||||||
goto failed;
|
goto failed;
|
||||||
|
@ -43,7 +43,8 @@ typedef enum {
|
|||||||
FETCH_REDIRECT,
|
FETCH_REDIRECT,
|
||||||
FETCH_NOTMODIFIED,
|
FETCH_NOTMODIFIED,
|
||||||
FETCH_AUTH,
|
FETCH_AUTH,
|
||||||
FETCH_CERT_ERR
|
FETCH_CERT_ERR,
|
||||||
|
FETCH_SSL_ERR
|
||||||
} fetch_msg_type;
|
} fetch_msg_type;
|
||||||
|
|
||||||
typedef struct fetch_msg {
|
typedef struct fetch_msg {
|
||||||
@ -103,7 +104,7 @@ struct fetch * fetch_start(nsurl *url, nsurl *referer,
|
|||||||
fetch_callback callback,
|
fetch_callback callback,
|
||||||
void *p, bool only_2xx, const char *post_urlenc,
|
void *p, bool only_2xx, const char *post_urlenc,
|
||||||
const struct fetch_multipart_data *post_multipart,
|
const struct fetch_multipart_data *post_multipart,
|
||||||
bool verifiable,
|
bool verifiable, bool downgrade_tls,
|
||||||
const char *headers[]);
|
const char *headers[]);
|
||||||
void fetch_abort(struct fetch *f);
|
void fetch_abort(struct fetch *f);
|
||||||
void fetch_poll(void);
|
void fetch_poll(void);
|
||||||
@ -123,17 +124,17 @@ struct fetch_multipart_data *fetch_multipart_data_clone(
|
|||||||
|
|
||||||
/* API for fetchers themselves */
|
/* API for fetchers themselves */
|
||||||
|
|
||||||
typedef bool (*fetcher_initialise)(lwc_string *);
|
typedef bool (*fetcher_initialise)(lwc_string *scheme);
|
||||||
typedef bool (*fetcher_can_fetch)(const nsurl *);
|
typedef bool (*fetcher_can_fetch)(const nsurl *url);
|
||||||
typedef void* (*fetcher_setup_fetch)(struct fetch *, nsurl *,
|
typedef void *(*fetcher_setup_fetch)(struct fetch *parent_fetch, nsurl *url,
|
||||||
bool, const char *,
|
bool only_2xx, bool downgrade_tls, const char *post_urlenc,
|
||||||
const struct fetch_multipart_data *,
|
const struct fetch_multipart_data *post_multipart,
|
||||||
const char **);
|
const char **headers);
|
||||||
typedef bool (*fetcher_start_fetch)(void *);
|
typedef bool (*fetcher_start_fetch)(void *fetch);
|
||||||
typedef void (*fetcher_abort_fetch)(void *);
|
typedef void (*fetcher_abort_fetch)(void *fetch);
|
||||||
typedef void (*fetcher_free_fetch)(void *);
|
typedef void (*fetcher_free_fetch)(void *fetch);
|
||||||
typedef void (*fetcher_poll_fetcher)(lwc_string *);
|
typedef void (*fetcher_poll_fetcher)(lwc_string *scheme);
|
||||||
typedef void (*fetcher_finalise)(lwc_string *);
|
typedef void (*fetcher_finalise)(lwc_string *scheme);
|
||||||
|
|
||||||
/** Register a fetcher for a scheme
|
/** Register a fetcher for a scheme
|
||||||
*
|
*
|
||||||
|
@ -729,6 +729,7 @@ static void *
|
|||||||
fetch_about_setup(struct fetch *fetchh,
|
fetch_about_setup(struct fetch *fetchh,
|
||||||
nsurl *url,
|
nsurl *url,
|
||||||
bool only_2xx,
|
bool only_2xx,
|
||||||
|
bool downgrade_tls,
|
||||||
const char *post_urlenc,
|
const char *post_urlenc,
|
||||||
const struct fetch_multipart_data *post_multipart,
|
const struct fetch_multipart_data *post_multipart,
|
||||||
const char **headers)
|
const char **headers)
|
||||||
|
@ -77,6 +77,7 @@ struct curl_fetch_info {
|
|||||||
bool abort; /**< Abort requested. */
|
bool abort; /**< Abort requested. */
|
||||||
bool stopped; /**< Download stopped on purpose. */
|
bool stopped; /**< Download stopped on purpose. */
|
||||||
bool only_2xx; /**< Only HTTP 2xx responses acceptable. */
|
bool only_2xx; /**< Only HTTP 2xx responses acceptable. */
|
||||||
|
bool downgrade_tls; /**< Downgrade to TLS <= 1.0 */
|
||||||
nsurl *url; /**< URL of this fetch. */
|
nsurl *url; /**< URL of this fetch. */
|
||||||
lwc_string *host; /**< The hostname of this fetch. */
|
lwc_string *host; /**< The hostname of this fetch. */
|
||||||
struct curl_slist *headers; /**< List of request headers. */
|
struct curl_slist *headers; /**< List of request headers. */
|
||||||
@ -114,7 +115,7 @@ static bool fetch_curl_initialise(lwc_string *scheme);
|
|||||||
static void fetch_curl_finalise(lwc_string *scheme);
|
static void fetch_curl_finalise(lwc_string *scheme);
|
||||||
static bool fetch_curl_can_fetch(const nsurl *url);
|
static bool fetch_curl_can_fetch(const nsurl *url);
|
||||||
static void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
|
static void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
|
||||||
bool only_2xx, const char *post_urlenc,
|
bool only_2xx, bool downgrade_tls, const char *post_urlenc,
|
||||||
const struct fetch_multipart_data *post_multipart,
|
const struct fetch_multipart_data *post_multipart,
|
||||||
const char **headers);
|
const char **headers);
|
||||||
static bool fetch_curl_start(void *vfetch);
|
static bool fetch_curl_start(void *vfetch);
|
||||||
@ -348,7 +349,7 @@ bool fetch_curl_can_fetch(const nsurl *url)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
|
void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
|
||||||
bool only_2xx, const char *post_urlenc,
|
bool only_2xx, bool downgrade_tls, const char *post_urlenc,
|
||||||
const struct fetch_multipart_data *post_multipart,
|
const struct fetch_multipart_data *post_multipart,
|
||||||
const char **headers)
|
const char **headers)
|
||||||
{
|
{
|
||||||
@ -370,6 +371,7 @@ void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
|
|||||||
fetch->abort = false;
|
fetch->abort = false;
|
||||||
fetch->stopped = false;
|
fetch->stopped = false;
|
||||||
fetch->only_2xx = only_2xx;
|
fetch->only_2xx = only_2xx;
|
||||||
|
fetch->downgrade_tls = downgrade_tls;
|
||||||
fetch->headers = NULL;
|
fetch->headers = NULL;
|
||||||
fetch->url = nsurl_ref(url);
|
fetch->url = nsurl_ref(url);
|
||||||
fetch->host = nsurl_get_component(url, NSURL_HOST);
|
fetch->host = nsurl_get_component(url, NSURL_HOST);
|
||||||
@ -665,14 +667,28 @@ fetch_curl_set_options(struct curl_fetch_info *f)
|
|||||||
CURLcode
|
CURLcode
|
||||||
fetch_curl_sslctxfun(CURL *curl_handle, void *_sslctx, void *parm)
|
fetch_curl_sslctxfun(CURL *curl_handle, void *_sslctx, void *parm)
|
||||||
{
|
{
|
||||||
|
struct curl_fetch_info *f = (struct curl_fetch_info *) parm;
|
||||||
SSL_CTX *sslctx = _sslctx;
|
SSL_CTX *sslctx = _sslctx;
|
||||||
|
long options = SSL_OP_ALL;
|
||||||
|
|
||||||
SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, fetch_curl_verify_callback);
|
SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, fetch_curl_verify_callback);
|
||||||
SSL_CTX_set_cert_verify_callback(sslctx, fetch_curl_cert_verify_callback,
|
SSL_CTX_set_cert_verify_callback(sslctx, fetch_curl_cert_verify_callback,
|
||||||
parm);
|
parm);
|
||||||
|
|
||||||
|
if (f->downgrade_tls) {
|
||||||
|
#ifdef SSL_OP_NO_TLSv1_1
|
||||||
|
/* Disable TLS1.1, if the server can't cope with it */
|
||||||
|
options |= SSL_OP_NO_TLSv1_1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef SSL_OP_NO_TLSv1_2
|
#ifdef SSL_OP_NO_TLSv1_2
|
||||||
/* Disable TLS1.2, as it causes some servers to stall. */
|
/* Disable TLS1.2, as it causes some servers to stall. */
|
||||||
SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_2);
|
options |= SSL_OP_NO_TLSv1_2;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
SSL_CTX_set_options(sslctx, options);
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -851,17 +867,16 @@ void fetch_curl_done(CURL *curl_handle, CURLcode result)
|
|||||||
else {
|
else {
|
||||||
finished = true;
|
finished = true;
|
||||||
}
|
}
|
||||||
} else if (result == CURLE_WRITE_ERROR && f->stopped)
|
} else if (result == CURLE_WRITE_ERROR && f->stopped) {
|
||||||
/* CURLE_WRITE_ERROR occurs when fetch_curl_data
|
/* CURLE_WRITE_ERROR occurs when fetch_curl_data
|
||||||
* returns 0, which we use to abort intentionally */
|
* returns 0, which we use to abort intentionally */
|
||||||
;
|
;
|
||||||
else if (result == CURLE_SSL_PEER_CERTIFICATE ||
|
} else if (result == CURLE_SSL_PEER_CERTIFICATE ||
|
||||||
result == CURLE_SSL_CACERT) {
|
result == CURLE_SSL_CACERT) {
|
||||||
memcpy(certs, f->cert_data, sizeof(certs));
|
memcpy(certs, f->cert_data, sizeof(certs));
|
||||||
memset(f->cert_data, 0, sizeof(f->cert_data));
|
memset(f->cert_data, 0, sizeof(f->cert_data));
|
||||||
cert = true;
|
cert = true;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
LOG(("Unknown cURL response code %d", result));
|
LOG(("Unknown cURL response code %d", result));
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
@ -955,8 +970,12 @@ void fetch_curl_done(CURL *curl_handle, CURLcode result)
|
|||||||
msg.data.cert_err.num_certs = i;
|
msg.data.cert_err.num_certs = i;
|
||||||
fetch_send_callback(&msg, f->fetch_handle);
|
fetch_send_callback(&msg, f->fetch_handle);
|
||||||
} else if (error) {
|
} else if (error) {
|
||||||
msg.type = FETCH_ERROR;
|
if (result != CURLE_SSL_CONNECT_ERROR) {
|
||||||
msg.data.error = fetch_error_buffer;
|
msg.type = FETCH_ERROR;
|
||||||
|
msg.data.error = fetch_error_buffer;
|
||||||
|
} else {
|
||||||
|
msg.type = FETCH_SSL_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
fetch_send_callback(&msg, f->fetch_handle);
|
fetch_send_callback(&msg, f->fetch_handle);
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ static bool fetch_data_can_fetch(const nsurl *url)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void *fetch_data_setup(struct fetch *parent_fetch, nsurl *url,
|
static void *fetch_data_setup(struct fetch *parent_fetch, nsurl *url,
|
||||||
bool only_2xx, const char *post_urlenc,
|
bool only_2xx, bool downgrade_tls, const char *post_urlenc,
|
||||||
const struct fetch_multipart_data *post_multipart,
|
const struct fetch_multipart_data *post_multipart,
|
||||||
const char **headers)
|
const char **headers)
|
||||||
{
|
{
|
||||||
|
@ -128,6 +128,7 @@ static void *
|
|||||||
fetch_file_setup(struct fetch *fetchh,
|
fetch_file_setup(struct fetch *fetchh,
|
||||||
nsurl *url,
|
nsurl *url,
|
||||||
bool only_2xx,
|
bool only_2xx,
|
||||||
|
bool downgrade_tls,
|
||||||
const char *post_urlenc,
|
const char *post_urlenc,
|
||||||
const struct fetch_multipart_data *post_multipart,
|
const struct fetch_multipart_data *post_multipart,
|
||||||
const char **headers)
|
const char **headers)
|
||||||
|
@ -231,6 +231,7 @@ static void *
|
|||||||
fetch_resource_setup(struct fetch *fetchh,
|
fetch_resource_setup(struct fetch *fetchh,
|
||||||
nsurl *url,
|
nsurl *url,
|
||||||
bool only_2xx,
|
bool only_2xx,
|
||||||
|
bool downgrade_tls,
|
||||||
const char *post_urlenc,
|
const char *post_urlenc,
|
||||||
const struct fetch_multipart_data *post_multipart,
|
const struct fetch_multipart_data *post_multipart,
|
||||||
const char **headers)
|
const char **headers)
|
||||||
|
@ -84,6 +84,8 @@ typedef struct {
|
|||||||
|
|
||||||
bool tried_with_auth; /**< Whether we've tried with auth */
|
bool tried_with_auth; /**< Whether we've tried with auth */
|
||||||
|
|
||||||
|
bool tried_with_tls_downgrade; /**< Whether we've tried TLS <= 1.0 */
|
||||||
|
|
||||||
bool outstanding_query; /**< Waiting for a query response */
|
bool outstanding_query; /**< Waiting for a query response */
|
||||||
} llcache_fetch_ctx;
|
} llcache_fetch_ctx;
|
||||||
|
|
||||||
@ -711,6 +713,7 @@ static nserror llcache_object_refetch(llcache_object *object)
|
|||||||
object->fetch.flags & LLCACHE_RETRIEVE_NO_ERROR_PAGES,
|
object->fetch.flags & LLCACHE_RETRIEVE_NO_ERROR_PAGES,
|
||||||
urlenc, multipart,
|
urlenc, multipart,
|
||||||
object->fetch.flags & LLCACHE_RETRIEVE_VERIFIABLE,
|
object->fetch.flags & LLCACHE_RETRIEVE_VERIFIABLE,
|
||||||
|
object->fetch.tried_with_tls_downgrade,
|
||||||
(const char **) headers);
|
(const char **) headers);
|
||||||
|
|
||||||
/* Clean up cache-control headers */
|
/* Clean up cache-control headers */
|
||||||
@ -1543,6 +1546,45 @@ static nserror llcache_fetch_cert_error(llcache_object *object,
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a TLS connection setup failure
|
||||||
|
*
|
||||||
|
* \param object Object being fetched
|
||||||
|
* \return NSERROR_OK on success, appropriate error otherwise
|
||||||
|
*/
|
||||||
|
static nserror llcache_fetch_ssl_error(llcache_object *object)
|
||||||
|
{
|
||||||
|
nserror error = NSERROR_OK;
|
||||||
|
|
||||||
|
/* Fetch has been stopped, and destroyed. Invalidate object's pointer */
|
||||||
|
object->fetch.fetch = NULL;
|
||||||
|
|
||||||
|
/* Invalidate cache-control data */
|
||||||
|
llcache_invalidate_cache_control_data(object);
|
||||||
|
|
||||||
|
if (object->fetch.tried_with_tls_downgrade == true) {
|
||||||
|
/* Have already tried to downgrade, so give up */
|
||||||
|
llcache_event event;
|
||||||
|
|
||||||
|
/* Mark object complete */
|
||||||
|
object->fetch.state = LLCACHE_FETCH_COMPLETE;
|
||||||
|
|
||||||
|
/* Inform client(s) that object fetch failed */
|
||||||
|
event.type = LLCACHE_EVENT_ERROR;
|
||||||
|
/** \todo More appropriate error message */
|
||||||
|
event.data.msg = messages_get("FetchFailed");
|
||||||
|
|
||||||
|
error = llcache_send_event_to_users(object, &event);
|
||||||
|
} else {
|
||||||
|
/* Flag that we've tried to downgrade, so that if the
|
||||||
|
* fetch fails again, we give up */
|
||||||
|
object->fetch.tried_with_tls_downgrade = true;
|
||||||
|
error = llcache_object_refetch(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for fetch events
|
* Handler for fetch events
|
||||||
*
|
*
|
||||||
@ -1705,6 +1747,17 @@ static void llcache_fetch_callback(const fetch_msg *msg, void *p)
|
|||||||
msg->data.cert_err.certs,
|
msg->data.cert_err.certs,
|
||||||
msg->data.cert_err.num_certs);
|
msg->data.cert_err.num_certs);
|
||||||
break;
|
break;
|
||||||
|
case FETCH_SSL_ERR:
|
||||||
|
/* TLS connection setup failed */
|
||||||
|
|
||||||
|
/* Release candidate, if any */
|
||||||
|
if (object->candidate != NULL) {
|
||||||
|
object->candidate->candidate_count--;
|
||||||
|
object->candidate = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = llcache_fetch_ssl_error(object);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deal with any errors reported by event handlers */
|
/* Deal with any errors reported by event handlers */
|
||||||
|
Loading…
Reference in New Issue
Block a user