dovecot-2.2: lib-http: Prepare for TLS SNI support.

dovecot at dovecot.org dovecot at dovecot.org
Thu Apr 4 17:39:29 EEST 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/52efc1740e15
changeset: 16158:52efc1740e15
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Apr 04 17:34:23 2013 +0300
description:
lib-http: Prepare for TLS SNI support.

diffstat:

 src/lib-http/http-client-connection.c |  15 +++++----------
 src/lib-http/http-client-host.c       |  31 ++++++++++++++++++-------------
 src/lib-http/http-client-peer.c       |  24 ++++++------------------
 src/lib-http/http-client-private.h    |   6 ++----
 4 files changed, 31 insertions(+), 45 deletions(-)

diffs (253 lines):

diff -r c040fa0fcfdf -r 52efc1740e15 src/lib-http/http-client-connection.c
--- a/src/lib-http/http-client-connection.c	Thu Apr 04 16:53:08 2013 +0300
+++ b/src/lib-http/http-client-connection.c	Thu Apr 04 17:34:23 2013 +0300
@@ -640,6 +640,7 @@
 http_client_connection_ssl_handshaked(const char **error_r, void *context)
 {
 	struct http_client_connection *conn = context;
+	const char *host = conn->peer->addr.https_name;
 
 	if (conn->client->set.ssl_allow_invalid_cert) {
 		/* skip certificate checks */
@@ -651,16 +652,10 @@
 		else
 			*error_r = "Received invalid SSL certificate";
 		return -1;
+	} else if (ssl_iostream_cert_match_name(conn->ssl_iostream, host) == 0) {
+		http_client_connection_debug(conn, "SSL handshake successful");
+		return 0;
 	} else {
-		const char *host = http_client_peer_get_hostname(conn->peer);
-
-		i_assert(host != NULL);
-
-		if (ssl_iostream_cert_match_name(conn->ssl_iostream, host) == 0) {
-			http_client_connection_debug(conn, "SSL handshake successful");
-			return 0;
-		}
-
 		*error_r = t_strdup_printf(
 			"SSL certificate doesn't match expected host name %s", host);
 		return -1;
@@ -720,7 +715,7 @@
 			"connect(%s) failed: %m", _conn->name));
 	} else {
 		http_client_connection_debug(conn, "Connected");
-		if (conn->peer->addr.ssl) {
+		if (conn->peer->addr.https_name != NULL) {
 			if (http_client_connection_ssl_init(conn, &error) < 0) {
 				http_client_peer_connection_failure(conn->peer, error);
 				http_client_connection_unref(&conn);
diff -r c040fa0fcfdf -r 52efc1740e15 src/lib-http/http-client-host.c
--- a/src/lib-http/http-client-host.c	Thu Apr 04 16:53:08 2013 +0300
+++ b/src/lib-http/http-client-host.c	Thu Apr 04 17:34:23 2013 +0300
@@ -43,12 +43,13 @@
 
 static struct http_client_host_port *
 http_client_host_port_find(struct http_client_host *host,
-	unsigned int port, bool ssl)
+	unsigned int port, const char *https_name)
 {
 	struct http_client_host_port *hport;
 
 	array_foreach_modifiable(&host->ports, hport) {
-		if (hport->port == port && hport->ssl == ssl)
+		if (hport->port == port &&
+		    null_strcmp(hport->https_name, https_name) == 0)
 			return hport;
 	}
 
@@ -57,15 +58,15 @@
 
 static struct http_client_host_port *
 http_client_host_port_init(struct http_client_host *host,
-	unsigned int port, bool ssl)
+	unsigned int port, const char *https_name)
 {
 	struct http_client_host_port *hport;
 
-	hport = http_client_host_port_find(host, port, ssl);
+	hport = http_client_host_port_find(host, port, https_name);
 	if (hport == NULL) {
 		hport = array_append_space(&host->ports);
 		hport->port = port;
-		hport->ssl = ssl;
+		hport->https_name = i_strdup(https_name);
 		hport->ips_connect_idx = 0;
 		i_array_init(&hport->request_queue, 16);
 	}
@@ -89,6 +90,7 @@
 {
 	http_client_host_port_error
 		(hport, HTTP_CLIENT_REQUEST_ERROR_ABORTED, "Aborted");
+	i_free(hport->https_name);
 	array_free(&hport->request_queue);
 }
 
@@ -121,10 +123,11 @@
 
 	addr.ip = host->ips[hport->ips_connect_idx];
 	addr.port = hport->port;
-	addr.ssl = hport->ssl;
+	addr.https_name = hport->https_name;
 
-	http_client_host_debug(host, "Setting up connection to %s:%u (ssl=%s)",
-		net_ip2addr(&addr.ip), addr.port, (addr.ssl ? "yes" : "no"));
+	http_client_host_debug(host, "Setting up connection to %s:%u%s",
+		net_ip2addr(&addr.ip), addr.port, addr.https_name == NULL ? "" :
+		t_strdup_printf(" (SSL=%s)", addr.https_name));
 
 	peer = http_client_peer_get(host->client, &addr);
 	http_client_peer_add_host(peer, host);
@@ -138,7 +141,7 @@
 	http_client_host_debug(host, "Failed to connect to %s:%u: %s",
 		net_ip2addr(&addr->ip), addr->port, reason);
 
-	hport = http_client_host_port_find(host, addr->port, addr->ssl);
+	hport = http_client_host_port_find(host, addr->port, addr->https_name);
 	if (hport == NULL)
 		return;
 
@@ -275,6 +278,7 @@
 	struct http_client_request *req)
 {
 	struct http_client_host_port *hport;
+	const char *https_name = req->ssl ? req->hostname : NULL;
 	const char *error;
 
 	req->host = host;
@@ -288,7 +292,7 @@
 	}
 
 	/* add request to host (grouped by tcp port) */
-	hport = http_client_host_port_init(host, req->port, req->ssl);
+	hport = http_client_host_port_init(host, req->port, https_name);
 	if (req->urgent)
 		array_insert(&hport->request_queue, 0, &req, 1);
 	else
@@ -314,7 +318,7 @@
 	struct http_client_request *req;
 	unsigned int i, count;
 
-	hport = http_client_host_port_find(host, addr->port, addr->ssl);
+	hport = http_client_host_port_find(host, addr->port, addr->https_name);
 	if (hport == NULL)
 		return NULL;
 
@@ -348,7 +352,7 @@
 
 	*num_urgent_r = 0;
 
-	hport = http_client_host_port_find(host, addr->port, addr->ssl);
+	hport = http_client_host_port_find(host, addr->port, addr->https_name);
 	if (hport == NULL)
 		return 0;
 
@@ -362,8 +366,9 @@
 	struct http_client_request *req)
 {
 	struct http_client_host_port *hport;
+	const char *https_name = req->ssl ? req->hostname : NULL;
 
-	hport = http_client_host_port_find(host, req->port, req->ssl);
+	hport = http_client_host_port_find(host, req->port, https_name);
 	if (hport == NULL)
 		return;
 
diff -r c040fa0fcfdf -r 52efc1740e15 src/lib-http/http-client-peer.c
--- a/src/lib-http/http-client-peer.c	Thu Apr 04 16:53:08 2013 +0300
+++ b/src/lib-http/http-client-peer.c	Thu Apr 04 17:34:23 2013 +0300
@@ -43,7 +43,8 @@
 unsigned int http_client_peer_addr_hash
 (const struct http_client_peer_addr *peer)
 {
-	return net_ip_hash(&peer->ip) + peer->port + peer->ssl;
+	return net_ip_hash(&peer->ip) + peer->port +
+		str_hash(peer->https_name);
 }
 
 int http_client_peer_addr_cmp
@@ -56,28 +57,13 @@
 		return ret;
 	if (peer1->port != peer2->port)
 		return (peer1->port > peer2->port ? 1 : -1);
-	if (peer1->ssl != peer2->ssl)
-		return (peer1->ssl > peer2->ssl ? 1 : -1);
-	return 0;
+	return null_strcmp(peer1->https_name, peer2->https_name);
 }
 
 /*
  * Peer
  */
 
-const char *
-http_client_peer_get_hostname(struct http_client_peer *peer)
-{
-	struct http_client_host *const *host;
-
-	if (array_count(&peer->hosts) == 0)
-		return NULL;
-
-	/* just return name of initial host */
-	host = array_idx(&peer->hosts, 1);
-	return (*host)->name;
-}
-
 static void
 http_client_peer_connect(struct http_client_peer *peer, unsigned int count)
 {
@@ -182,11 +168,12 @@
 {
 	struct http_client_peer *peer;
 
-	i_assert(!addr->ssl || client->ssl_ctx != NULL);
+	i_assert(addr->https_name == NULL || client->ssl_ctx != NULL);
 
 	peer = i_new(struct http_client_peer, 1);
 	peer->client = client;
 	peer->addr = *addr;
+	peer->addr.https_name = i_strdup(addr->https_name);
 	i_array_init(&peer->hosts, 16);
 	i_array_init(&peer->conns, 16);
 
@@ -227,6 +214,7 @@
 		(peer->client->peers, (const struct http_client_peer_addr *)&peer->addr);
 	DLLIST_REMOVE(&peer->client->peers_list, peer);
 
+	i_free(peer->addr.https_name);
 	i_free(peer);
 	*_peer = NULL;
 }
diff -r c040fa0fcfdf -r 52efc1740e15 src/lib-http/http-client-private.h
--- a/src/lib-http/http-client-private.h	Thu Apr 04 16:53:08 2013 +0300
+++ b/src/lib-http/http-client-private.h	Thu Apr 04 17:34:23 2013 +0300
@@ -79,7 +79,7 @@
 	/* requests pending in queue to be picked up by connections */
 	ARRAY_TYPE(http_client_request) request_queue;
 
-	unsigned int ssl:1;
+	char *https_name;
 };
 
 struct http_client_host {
@@ -103,9 +103,9 @@
 };
 
 struct http_client_peer_addr {
+	char *https_name; /* TLS SNI */
 	struct ip_addr ip;
 	unsigned int port;
-	unsigned int ssl:1;              /* https */
 };
 
 struct http_client_peer {
@@ -220,8 +220,6 @@
 	(const struct http_client_peer_addr *peer1,
 		const struct http_client_peer_addr *peer2) ATTR_PURE;
 
-const char *
-	http_client_peer_get_hostname(struct http_client_peer *peer);
 struct http_client_peer *
 	http_client_peer_get(struct http_client *client,
 		const struct http_client_peer_addr *addr);


More information about the dovecot-cvs mailing list