1
0
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:
Kalle Olavi Niemitalo 2008-07-27 01:24:36 +03:00 committed by Kalle Olavi Niemitalo
parent 5ef63a5d01
commit a83ff1f565
5 changed files with 29 additions and 2 deletions

2
NEWS
View File

@ -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. JS_CallFunction, which can crash if given a closure.
* critical bug 1031: Use the same JSRuntime for both user SMJS and * critical bug 1031: Use the same JSRuntime for both user SMJS and
scripts on web pages, to work around SpiderMonkey bug 378918. 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 * minor bug 951: SpiderMonkey scripting objects used to prevent ELinks
from removing files from the memory cache from removing files from the memory cache

View File

@ -49,6 +49,7 @@
#include "network/ssl/socket.h" #include "network/ssl/socket.h"
#include "osdep/osdep.h" #include "osdep/osdep.h"
#include "osdep/getifaddrs.h" #include "osdep/getifaddrs.h"
#include "protocol/http/blacklist.h"
#include "protocol/protocol.h" #include "protocol/protocol.h"
#include "protocol/uri.h" #include "protocol/uri.h"
#include "util/error.h" #include "util/error.h"
@ -65,6 +66,7 @@ struct connect_info {
void *dnsquery; /* Pointer to DNS query info. */ void *dnsquery; /* Pointer to DNS query info. */
int port; /* Which port to bind to. */ int port; /* Which port to bind to. */
int ip_family; /* If non-zero, force to IP version. */ 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->ip_family = uri->ip_family;
connect_info->triedno = -1; connect_info->triedno = -1;
connect_info->addr = NULL; connect_info->addr = NULL;
connect_info->uri = get_uri_reference(uri);
return connect_info; return connect_info;
} }
@ -118,6 +121,7 @@ done_connection_info(struct socket *socket)
if (connect_info->dnsquery) kill_dns_request(&connect_info->dnsquery); if (connect_info->dnsquery) kill_dns_request(&connect_info->dnsquery);
mem_free_if(connect_info->addr); mem_free_if(connect_info->addr);
done_uri(connect_info->uri);
mem_free_set(&socket->connect_info, NULL); 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 /* XXX: Keep here and not in init_connection_info() to make
* complete_connect_socket() work from the HTTP implementation. */ * complete_connect_socket() work from the HTTP implementation. */
socket->need_ssl = get_protocol_need_ssl(uri->protocol); 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("\nCONNECTION: ", -1);
debug_transfer_log(host, -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; 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 /* This is a special case used by the HTTP implementation to acquire an
* SSL link for handling CONNECT requests. */ * SSL link for handling CONNECT requests. */
if (!connect_info) { if (!connect_info) {

View File

@ -97,6 +97,7 @@ struct socket {
unsigned int protocol_family:1; /* EL_PF_INET, EL_PF_INET6 */ unsigned int protocol_family:1; /* EL_PF_INET, EL_PF_INET6 */
unsigned int need_ssl:1; /* If the socket needs SSL support */ unsigned int need_ssl:1; /* If the socket needs SSL support */
unsigned int no_tls:1; /* Internal SSL flag. */ 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. */ unsigned int duplex:1; /* Allow simultaneous reads & writes. */
}; };

View File

@ -107,7 +107,7 @@ ssl_want_read(struct socket *socket)
break; break;
default: default:
socket->no_tls = 1; socket->no_tls = !socket->no_tls;
socket->ops->retry(socket, S_SSL_ERROR); socket->ops->retry(socket, S_SSL_ERROR);
} }
} }
@ -189,7 +189,7 @@ ssl_connect(struct socket *socket)
default: default:
if (ret != SSL_ERROR_NONE) { if (ret != SSL_ERROR_NONE) {
/* DBG("sslerr %s", gnutls_strerror(ret)); */ /* DBG("sslerr %s", gnutls_strerror(ret)); */
socket->no_tls = 1; socket->no_tls = !socket->no_tls;
} }
connect_socket(socket, S_SSL_ERROR); connect_socket(socket, S_SSL_ERROR);

View File

@ -8,6 +8,7 @@ enum blacklist_flags {
SERVER_BLACKLIST_NONE = 0, SERVER_BLACKLIST_NONE = 0,
SERVER_BLACKLIST_HTTP10 = 1, SERVER_BLACKLIST_HTTP10 = 1,
SERVER_BLACKLIST_NO_CHARSET = 2, SERVER_BLACKLIST_NO_CHARSET = 2,
SERVER_BLACKLIST_NO_TLS = 4,
}; };
void add_blacklist_entry(struct uri *, enum blacklist_flags); void add_blacklist_entry(struct uri *, enum blacklist_flags);