Fix STARTTLS fallback.

This commit is contained in:
Sara Dickinson 2015-04-30 14:52:16 +01:00
parent 7905eda8b7
commit 450a3bc6ff
3 changed files with 21 additions and 15 deletions

View File

@ -75,8 +75,8 @@ getdns_port_array[GETDNS_BASE_TRANSPORT_MAX] = {
GETDNS_PORT_ZERO, GETDNS_PORT_ZERO,
GETDNS_PORT_ZERO, GETDNS_PORT_ZERO,
GETDNS_PORT_TCP, GETDNS_PORT_TCP,
GETDNS_PORT_TLS, GETDNS_PORT_TCP,
GETDNS_PORT_TCP GETDNS_PORT_TLS
}; };
char* char*
@ -85,8 +85,8 @@ getdns_port_str_array[] = {
GETDNS_STR_PORT_ZERO, GETDNS_STR_PORT_ZERO,
GETDNS_STR_PORT_ZERO, GETDNS_STR_PORT_ZERO,
GETDNS_STR_PORT_TCP, GETDNS_STR_PORT_TCP,
GETDNS_STR_PORT_TLS, GETDNS_STR_PORT_TCP,
GETDNS_STR_PORT_TCP GETDNS_STR_PORT_TLS
}; };
/* Private functions */ /* Private functions */
@ -1792,10 +1792,10 @@ ub_setup_stub(struct ub_ctx *ctx, getdns_context *context)
(void) ub_ctx_set_fwd(ctx, NULL); (void) ub_ctx_set_fwd(ctx, NULL);
for (i = 0; i < upstreams->count; i++) { for (i = 0; i < upstreams->count; i++) {
upstream = &upstreams->upstreams[i]; upstream = &upstreams->upstreams[i];
/*[TLS]: Use only the TLS subset of upstreams when only TLS is used. /*[TLS]: Use only the TLS subset of upstreams when TLS is the only thing
* All other cases must currently fallback to TCP for libunbound. */ * used. All other cases must currently fallback to TCP for libunbound.*/
if (context->dns_base_transports[0] == GETDNS_BASE_TRANSPORT_TLS && if (context->dns_base_transports[0] == GETDNS_BASE_TRANSPORT_TLS &&
context->dns_base_transports[0] == GETDNS_BASE_TRANSPORT_NONE && context->dns_base_transports[1] == GETDNS_BASE_TRANSPORT_NONE &&
upstream_port(upstream) != GETDNS_PORT_TLS) upstream_port(upstream) != GETDNS_PORT_TLS)
continue; continue;
else if (upstream_port(upstream) != GETDNS_PORT_TCP) else if (upstream_port(upstream) != GETDNS_PORT_TCP)

View File

@ -594,14 +594,22 @@ stub_udp_write_cb(void *userarg)
stub_udp_read_cb, NULL, stub_timeout_cb)); stub_udp_read_cb, NULL, stub_timeout_cb));
} }
/* TODO[TLS]: Optimise to re-use TCP (or failed STARTTLS) where possible.*/
static int static int
transport_valid(struct getdns_upstream *upstream, getdns_base_transport_t transport) { transport_valid(struct getdns_upstream *upstream, getdns_base_transport_t transport) {
/* For single shot transports, use any upstream. */
if (transport == GETDNS_BASE_TRANSPORT_UDP || if (transport == GETDNS_BASE_TRANSPORT_UDP ||
transport == GETDNS_BASE_TRANSPORT_TCP_SINGLE) transport == GETDNS_BASE_TRANSPORT_TCP_SINGLE)
return 1; return 1;
/* Allow TCP messages to be sent on a STARTTLS upstream that hasn't upgraded
* to avoid opening a new connection if one is aleady open. */
if (transport == GETDNS_BASE_TRANSPORT_TCP &&
upstream->dns_base_transport == GETDNS_BASE_TRANSPORT_STARTTLS &&
upstream->tls_hs_state == GETDNS_HS_FAILED)
return 1;
/* Otherwise, transport must match */
if (upstream->dns_base_transport != transport) if (upstream->dns_base_transport != transport)
return 0; return 0;
/* But don't use if upgrade failed for (START)TLS*/
if ((transport == GETDNS_BASE_TRANSPORT_TLS || if ((transport == GETDNS_BASE_TRANSPORT_TLS ||
transport == GETDNS_BASE_TRANSPORT_STARTTLS) transport == GETDNS_BASE_TRANSPORT_STARTTLS)
&& upstream->tls_hs_state == GETDNS_HS_FAILED) && upstream->tls_hs_state == GETDNS_HS_FAILED)
@ -1433,11 +1441,9 @@ connect_to_upstream(getdns_upstream *upstream, getdns_base_transport_t transport
upstream->fd = fd; upstream->fd = fd;
break; break;
case GETDNS_BASE_TRANSPORT_STARTTLS: case GETDNS_BASE_TRANSPORT_STARTTLS:
/* Use existing if available. May be either negotiating or doing TLS */ /* Use existing if available. Let the fallback code handle it if STARTTLS
if (upstream->fd != 1 && * isn't availble. */
(upstream->starttls_req != NULL) || if (upstream->fd != -1)
(upstream->starttls_req == NULL &&
tls_handshake_active(upstream->tls_hs_state)))
return upstream->fd; return upstream->fd;
fd = tcp_connect(upstream, transport); fd = tcp_connect(upstream, transport);
if (fd == -1) return -1; if (fd == -1) return -1;

View File

@ -169,9 +169,9 @@ typedef enum getdns_base_transport {
GETDNS_BASE_TRANSPORT_NONE = 0, GETDNS_BASE_TRANSPORT_NONE = 0,
GETDNS_BASE_TRANSPORT_UDP, GETDNS_BASE_TRANSPORT_UDP,
GETDNS_BASE_TRANSPORT_TCP_SINGLE, /* To be removed? */ GETDNS_BASE_TRANSPORT_TCP_SINGLE, /* To be removed? */
GETDNS_BASE_TRANSPORT_STARTTLS, /* Define before TCP to allow fallback when scheduling*/
GETDNS_BASE_TRANSPORT_TCP, GETDNS_BASE_TRANSPORT_TCP,
GETDNS_BASE_TRANSPORT_TLS, GETDNS_BASE_TRANSPORT_TLS,
GETDNS_BASE_TRANSPORT_STARTTLS,
GETDNS_BASE_TRANSPORT_MAX GETDNS_BASE_TRANSPORT_MAX
} getdns_base_transport_t; } getdns_base_transport_t;