Mercurial > dovecot > core-2.2
changeset 16158:52efc1740e15
lib-http: Prepare for TLS SNI support.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 04 Apr 2013 17:34:23 +0300 |
parents | c040fa0fcfdf |
children | f4bac0352464 |
files | src/lib-http/http-client-connection.c src/lib-http/http-client-host.c src/lib-http/http-client-peer.c src/lib-http/http-client-private.h |
diffstat | 4 files changed, 31 insertions(+), 45 deletions(-) [+] |
line wrap: on
line diff
--- 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);
--- 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;
--- 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; }
--- 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);