1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-12-04 14:46:47 -05:00

1024: Use RFC 3546 server_name TLS extension

For both GnuTLS and OpenSSL.  Not tested with nss-compat-openssl.
This commit is contained in:
Kalle Olavi Niemitalo 2011-05-02 14:41:40 +03:00 committed by Kalle Olavi Niemitalo
parent 5d0e4e2452
commit 6c84978cf5
3 changed files with 53 additions and 8 deletions

View File

@ -181,12 +181,28 @@ int
ssl_connect(struct socket *socket)
{
int ret;
unsigned char *server_name;
struct connection *conn = socket->conn;
if (init_ssl_connection(socket) == S_SSL_ERROR) {
/* TODO: Recode server_name to UTF-8. */
server_name = get_uri_string(conn->proxied_uri, URI_HOST);
if (!server_name) {
socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
return -1;
}
/* RFC 3546 says literal IPv4 and IPv6 addresses are not allowed. */
if (is_ip_address(server_name, strlen(server_name)))
mem_free_set(&server_name, NULL);
if (init_ssl_connection(socket, server_name) == S_SSL_ERROR) {
mem_free_if(server_name);
socket->ops->done(socket, connection_state(S_SSL_ERROR));
return -1;
}
mem_free_if(server_name);
if (socket->no_tls)
ssl_set_no_tls(socket);

View File

@ -249,13 +249,26 @@ struct module ssl_module = struct_module(
);
int
init_ssl_connection(struct socket *socket)
init_ssl_connection(struct socket *socket,
const unsigned char *server_name)
{
#ifdef USE_OPENSSL
socket->ssl = SSL_new(context);
if (!socket->ssl) return S_SSL_ERROR;
/* If the server name is known, pass it to OpenSSL.
*
* The return value of SSL_set_tlsext_host_name is not
* documented. The source shows that it returns 1 if
* successful; on error, it calls SSLerr and returns 0. */
if (server_name
&& !SSL_set_tlsext_host_name(socket->ssl, server_name)) {
SSL_free(socket->ssl);
socket->ssl = NULL;
return S_SSL_ERROR;
}
#elif defined(CONFIG_GNUTLS)
/* const unsigned char server_name[] = "localhost"; */
ssl_t *state = mem_alloc(sizeof(ssl_t));
if (!state) return S_SSL_ERROR;
@ -294,11 +307,17 @@ init_ssl_connection(struct socket *socket)
/* gnutls_handshake_set_private_extensions(*state, 1); */
gnutls_cipher_set_priority(*state, cipher_priority);
gnutls_kx_set_priority(*state, kx_priority);
/* gnutls_certificate_type_set_priority(*state, cert_type_priority);
gnutls_server_name_set(*state, GNUTLS_NAME_DNS, server_name,
sizeof(server_name) - 1); */
/* gnutls_certificate_type_set_priority(*state, cert_type_priority); */
#endif
if (server_name
&& gnutls_server_name_set(*state, GNUTLS_NAME_DNS, server_name,
strlen(server_name))) {
gnutls_deinit(*state);
mem_free(state);
return S_SSL_ERROR;
}
socket->ssl = state;
#endif

View File

@ -11,8 +11,18 @@ struct socket;
extern struct module ssl_module;
/* Initializes the SSL connection data. Returns S_OK on success and S_SSL_ERROR
* on failure. */
int init_ssl_connection(struct socket *socket);
* on failure.
*
* server_name is the DNS name of the server (in UTF-8), or NULL if
* ELinks knows only the IP address. ELinks reports that name to the
* server so that the server can choose the correct certificate if it
* has multiple virtual hosts on the same IP address. See RFC 3546
* section 3.1.
*
* server_name does not affect how ELinks verifies the certificate
* after the server has returned it. */
int init_ssl_connection(struct socket *socket,
const unsigned char *server_name);
/* Releases the SSL connection data */
void done_ssl_connection(struct socket *socket);