mirror of
https://github.com/rkd77/elinks.git
synced 2024-12-04 14:46:47 -05:00
1040: Blacklist servers that support SSL3 but not TLS1.
It seems GnuTLS is not as good at negotiating a supported protocol as OpenSSL is. ELinks tries to work around that by retrying with a different protocol if the SSL library reports an error. However, ELinks must not automatically retry POST requests where some data may have already reached the server; POST is not a safe method in HTTP. So instead, collect the name of the TLS-incapable server in a blacklist when ELinks e.g. loads an HTML form from it; the actual POST can then immediately use the protocol that worked. It's a bit ugly that src/network/socket.c now uses protocol/http/blacklist.h. It might be better to move the blacklist files out of the http directory, and perhaps merge them with the BitTorrent blacklisting code.
This commit is contained in:
parent
5ef63a5d01
commit
a83ff1f565
2
NEWS
2
NEWS
@ -21,6 +21,8 @@ includes the changes listed under "ELinks 0.11.4.GIT now" below.
|
||||
JS_CallFunction, which can crash if given a closure.
|
||||
* critical bug 1031: Use the same JSRuntime for both user SMJS and
|
||||
scripts on web pages, to work around SpiderMonkey bug 378918.
|
||||
* bug 1040: Blacklist servers that don't support TLS. This reduces
|
||||
SSL errors especially in HTTP POST requests using GnuTLS.
|
||||
* minor bug 951: SpiderMonkey scripting objects used to prevent ELinks
|
||||
from removing files from the memory cache
|
||||
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "network/ssl/socket.h"
|
||||
#include "osdep/osdep.h"
|
||||
#include "osdep/getifaddrs.h"
|
||||
#include "protocol/http/blacklist.h"
|
||||
#include "protocol/protocol.h"
|
||||
#include "protocol/uri.h"
|
||||
#include "util/error.h"
|
||||
@ -65,6 +66,7 @@ struct connect_info {
|
||||
void *dnsquery; /* Pointer to DNS query info. */
|
||||
int port; /* Which port to bind to. */
|
||||
int ip_family; /* If non-zero, force to IP version. */
|
||||
struct uri *uri; /* For updating the blacklist. */
|
||||
};
|
||||
|
||||
|
||||
@ -104,6 +106,7 @@ init_connection_info(struct uri *uri, struct socket *socket,
|
||||
connect_info->ip_family = uri->ip_family;
|
||||
connect_info->triedno = -1;
|
||||
connect_info->addr = NULL;
|
||||
connect_info->uri = get_uri_reference(uri);
|
||||
|
||||
return connect_info;
|
||||
}
|
||||
@ -118,6 +121,7 @@ done_connection_info(struct socket *socket)
|
||||
if (connect_info->dnsquery) kill_dns_request(&connect_info->dnsquery);
|
||||
|
||||
mem_free_if(connect_info->addr);
|
||||
done_uri(connect_info->uri);
|
||||
mem_free_set(&socket->connect_info, NULL);
|
||||
}
|
||||
|
||||
@ -258,6 +262,11 @@ make_connection(struct socket *socket, struct uri *uri,
|
||||
/* XXX: Keep here and not in init_connection_info() to make
|
||||
* complete_connect_socket() work from the HTTP implementation. */
|
||||
socket->need_ssl = get_protocol_need_ssl(uri->protocol);
|
||||
if (!socket->set_no_tls) {
|
||||
enum blacklist_flags flags = get_blacklist_flags(uri);
|
||||
socket->no_tls = ((flags & SERVER_BLACKLIST_NO_TLS) != 0);
|
||||
socket->set_no_tls = 1;
|
||||
}
|
||||
|
||||
debug_transfer_log("\nCONNECTION: ", -1);
|
||||
debug_transfer_log(host, -1);
|
||||
@ -425,6 +434,20 @@ complete_connect_socket(struct socket *socket, struct uri *uri,
|
||||
{
|
||||
struct connect_info *connect_info = socket->connect_info;
|
||||
|
||||
if (connect_info && connect_info->uri) {
|
||||
/* Remember whether the server supported TLS or not.
|
||||
* Then the next request can immediately use the right
|
||||
* protocol. This is important for HTTP POST requests
|
||||
* because it is not safe to silently retry them. The
|
||||
* uri parameter is normally NULL here so don't use it. */
|
||||
if (socket->no_tls)
|
||||
add_blacklist_entry(connect_info->uri,
|
||||
SERVER_BLACKLIST_NO_TLS);
|
||||
else
|
||||
del_blacklist_entry(connect_info->uri,
|
||||
SERVER_BLACKLIST_NO_TLS);
|
||||
}
|
||||
|
||||
/* This is a special case used by the HTTP implementation to acquire an
|
||||
* SSL link for handling CONNECT requests. */
|
||||
if (!connect_info) {
|
||||
|
@ -97,6 +97,7 @@ struct socket {
|
||||
unsigned int protocol_family:1; /* EL_PF_INET, EL_PF_INET6 */
|
||||
unsigned int need_ssl:1; /* If the socket needs SSL support */
|
||||
unsigned int no_tls:1; /* Internal SSL flag. */
|
||||
unsigned int set_no_tls:1; /* Was the blacklist checked yet? */
|
||||
unsigned int duplex:1; /* Allow simultaneous reads & writes. */
|
||||
};
|
||||
|
||||
|
@ -107,7 +107,7 @@ ssl_want_read(struct socket *socket)
|
||||
break;
|
||||
|
||||
default:
|
||||
socket->no_tls = 1;
|
||||
socket->no_tls = !socket->no_tls;
|
||||
socket->ops->retry(socket, S_SSL_ERROR);
|
||||
}
|
||||
}
|
||||
@ -189,7 +189,7 @@ ssl_connect(struct socket *socket)
|
||||
default:
|
||||
if (ret != SSL_ERROR_NONE) {
|
||||
/* DBG("sslerr %s", gnutls_strerror(ret)); */
|
||||
socket->no_tls = 1;
|
||||
socket->no_tls = !socket->no_tls;
|
||||
}
|
||||
|
||||
connect_socket(socket, S_SSL_ERROR);
|
||||
|
@ -8,6 +8,7 @@ enum blacklist_flags {
|
||||
SERVER_BLACKLIST_NONE = 0,
|
||||
SERVER_BLACKLIST_HTTP10 = 1,
|
||||
SERVER_BLACKLIST_NO_CHARSET = 2,
|
||||
SERVER_BLACKLIST_NO_TLS = 4,
|
||||
};
|
||||
|
||||
void add_blacklist_entry(struct uri *, enum blacklist_flags);
|
||||
|
Loading…
Reference in New Issue
Block a user