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,
|
||||
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 char **headers)
|
||||
{
|
||||
|
@ -235,7 +235,8 @@ struct fetch * fetch_start(nsurl *url, nsurl *referer,
|
||||
fetch_callback callback,
|
||||
void *p, bool only_2xx, const char *post_urlenc,
|
||||
const struct fetch_multipart_data *post_multipart,
|
||||
bool verifiable, const char *headers[])
|
||||
bool verifiable, bool downgrade_tls,
|
||||
const char *headers[])
|
||||
{
|
||||
struct fetch *fetch;
|
||||
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 */
|
||||
fetch->fetcher_handle = fetch->ops->setup_fetch(fetch, url,
|
||||
only_2xx, post_urlenc,
|
||||
post_multipart, headers);
|
||||
only_2xx, downgrade_tls,
|
||||
post_urlenc, post_multipart,
|
||||
headers);
|
||||
|
||||
if (fetch->fetcher_handle == NULL)
|
||||
goto failed;
|
||||
|
@ -43,7 +43,8 @@ typedef enum {
|
||||
FETCH_REDIRECT,
|
||||
FETCH_NOTMODIFIED,
|
||||
FETCH_AUTH,
|
||||
FETCH_CERT_ERR
|
||||
FETCH_CERT_ERR,
|
||||
FETCH_SSL_ERR
|
||||
} fetch_msg_type;
|
||||
|
||||
typedef struct fetch_msg {
|
||||
@ -103,7 +104,7 @@ struct fetch * fetch_start(nsurl *url, nsurl *referer,
|
||||
fetch_callback callback,
|
||||
void *p, bool only_2xx, const char *post_urlenc,
|
||||
const struct fetch_multipart_data *post_multipart,
|
||||
bool verifiable,
|
||||
bool verifiable, bool downgrade_tls,
|
||||
const char *headers[]);
|
||||
void fetch_abort(struct fetch *f);
|
||||
void fetch_poll(void);
|
||||
@ -123,17 +124,17 @@ struct fetch_multipart_data *fetch_multipart_data_clone(
|
||||
|
||||
/* API for fetchers themselves */
|
||||
|
||||
typedef bool (*fetcher_initialise)(lwc_string *);
|
||||
typedef bool (*fetcher_can_fetch)(const nsurl *);
|
||||
typedef void* (*fetcher_setup_fetch)(struct fetch *, nsurl *,
|
||||
bool, const char *,
|
||||
const struct fetch_multipart_data *,
|
||||
const char **);
|
||||
typedef bool (*fetcher_start_fetch)(void *);
|
||||
typedef void (*fetcher_abort_fetch)(void *);
|
||||
typedef void (*fetcher_free_fetch)(void *);
|
||||
typedef void (*fetcher_poll_fetcher)(lwc_string *);
|
||||
typedef void (*fetcher_finalise)(lwc_string *);
|
||||
typedef bool (*fetcher_initialise)(lwc_string *scheme);
|
||||
typedef bool (*fetcher_can_fetch)(const nsurl *url);
|
||||
typedef void *(*fetcher_setup_fetch)(struct fetch *parent_fetch, nsurl *url,
|
||||
bool only_2xx, bool downgrade_tls, const char *post_urlenc,
|
||||
const struct fetch_multipart_data *post_multipart,
|
||||
const char **headers);
|
||||
typedef bool (*fetcher_start_fetch)(void *fetch);
|
||||
typedef void (*fetcher_abort_fetch)(void *fetch);
|
||||
typedef void (*fetcher_free_fetch)(void *fetch);
|
||||
typedef void (*fetcher_poll_fetcher)(lwc_string *scheme);
|
||||
typedef void (*fetcher_finalise)(lwc_string *scheme);
|
||||
|
||||
/** Register a fetcher for a scheme
|
||||
*
|
||||
|
@ -729,6 +729,7 @@ static void *
|
||||
fetch_about_setup(struct fetch *fetchh,
|
||||
nsurl *url,
|
||||
bool only_2xx,
|
||||
bool downgrade_tls,
|
||||
const char *post_urlenc,
|
||||
const struct fetch_multipart_data *post_multipart,
|
||||
const char **headers)
|
||||
|
@ -77,6 +77,7 @@ struct curl_fetch_info {
|
||||
bool abort; /**< Abort requested. */
|
||||
bool stopped; /**< Download stopped on purpose. */
|
||||
bool only_2xx; /**< Only HTTP 2xx responses acceptable. */
|
||||
bool downgrade_tls; /**< Downgrade to TLS <= 1.0 */
|
||||
nsurl *url; /**< URL of this fetch. */
|
||||
lwc_string *host; /**< The hostname of this fetch. */
|
||||
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 bool fetch_curl_can_fetch(const 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 char **headers);
|
||||
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,
|
||||
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 char **headers)
|
||||
{
|
||||
@ -370,6 +371,7 @@ void * fetch_curl_setup(struct fetch *parent_fetch, nsurl *url,
|
||||
fetch->abort = false;
|
||||
fetch->stopped = false;
|
||||
fetch->only_2xx = only_2xx;
|
||||
fetch->downgrade_tls = downgrade_tls;
|
||||
fetch->headers = NULL;
|
||||
fetch->url = nsurl_ref(url);
|
||||
fetch->host = nsurl_get_component(url, NSURL_HOST);
|
||||
@ -665,14 +667,28 @@ fetch_curl_set_options(struct curl_fetch_info *f)
|
||||
CURLcode
|
||||
fetch_curl_sslctxfun(CURL *curl_handle, void *_sslctx, void *parm)
|
||||
{
|
||||
struct curl_fetch_info *f = (struct curl_fetch_info *) parm;
|
||||
SSL_CTX *sslctx = _sslctx;
|
||||
long options = SSL_OP_ALL;
|
||||
|
||||
SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER, fetch_curl_verify_callback);
|
||||
SSL_CTX_set_cert_verify_callback(sslctx, fetch_curl_cert_verify_callback,
|
||||
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
|
||||
/* 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
|
||||
|
||||
SSL_CTX_set_options(sslctx, options);
|
||||
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
@ -851,17 +867,16 @@ void fetch_curl_done(CURL *curl_handle, CURLcode result)
|
||||
else {
|
||||
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
|
||||
* 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) {
|
||||
memcpy(certs, f->cert_data, sizeof(certs));
|
||||
memset(f->cert_data, 0, sizeof(f->cert_data));
|
||||
cert = true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
LOG(("Unknown cURL response code %d", result));
|
||||
error = true;
|
||||
}
|
||||
@ -955,8 +970,12 @@ void fetch_curl_done(CURL *curl_handle, CURLcode result)
|
||||
msg.data.cert_err.num_certs = i;
|
||||
fetch_send_callback(&msg, f->fetch_handle);
|
||||
} else if (error) {
|
||||
msg.type = FETCH_ERROR;
|
||||
msg.data.error = fetch_error_buffer;
|
||||
if (result != CURLE_SSL_CONNECT_ERROR) {
|
||||
msg.type = FETCH_ERROR;
|
||||
msg.data.error = fetch_error_buffer;
|
||||
} else {
|
||||
msg.type = FETCH_SSL_ERR;
|
||||
}
|
||||
|
||||
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,
|
||||
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 char **headers)
|
||||
{
|
||||
|
@ -128,6 +128,7 @@ static void *
|
||||
fetch_file_setup(struct fetch *fetchh,
|
||||
nsurl *url,
|
||||
bool only_2xx,
|
||||
bool downgrade_tls,
|
||||
const char *post_urlenc,
|
||||
const struct fetch_multipart_data *post_multipart,
|
||||
const char **headers)
|
||||
|
@ -231,6 +231,7 @@ static void *
|
||||
fetch_resource_setup(struct fetch *fetchh,
|
||||
nsurl *url,
|
||||
bool only_2xx,
|
||||
bool downgrade_tls,
|
||||
const char *post_urlenc,
|
||||
const struct fetch_multipart_data *post_multipart,
|
||||
const char **headers)
|
||||
|
@ -84,6 +84,8 @@ typedef struct {
|
||||
|
||||
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 */
|
||||
} llcache_fetch_ctx;
|
||||
|
||||
@ -711,6 +713,7 @@ static nserror llcache_object_refetch(llcache_object *object)
|
||||
object->fetch.flags & LLCACHE_RETRIEVE_NO_ERROR_PAGES,
|
||||
urlenc, multipart,
|
||||
object->fetch.flags & LLCACHE_RETRIEVE_VERIFIABLE,
|
||||
object->fetch.tried_with_tls_downgrade,
|
||||
(const char **) headers);
|
||||
|
||||
/* Clean up cache-control headers */
|
||||
@ -1543,6 +1546,45 @@ static nserror llcache_fetch_cert_error(llcache_object *object,
|
||||
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
|
||||
*
|
||||
@ -1705,6 +1747,17 @@ static void llcache_fetch_callback(const fetch_msg *msg, void *p)
|
||||
msg->data.cert_err.certs,
|
||||
msg->data.cert_err.num_certs);
|
||||
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 */
|
||||
|
Loading…
Reference in New Issue
Block a user