From 99aa79b48f24ff3cab28dece6fb1767ee6ba48f9 Mon Sep 17 00:00:00 2001 From: saradickinson Date: Sun, 7 Dec 2014 19:03:34 +0000 Subject: [PATCH 01/10] First pass at TLS implementation - needs work! --- spec/index.html | 6 +- src/const-info.c | 2 + src/context.c | 78 +++++- src/context.h | 2 + src/getdns/getdns.h.in | 6 +- src/request-internal.c | 1 + src/stub.c | 469 ++++++++++++++++++++++++++++++++---- src/test/getdns_query.c | 140 ++++++++--- src/test/tests_stub_async.c | 6 + src/test/tests_stub_sync.c | 6 + src/types-internal.h | 2 + 11 files changed, 634 insertions(+), 84 deletions(-) mode change 100644 => 100755 spec/index.html mode change 100644 => 100755 src/const-info.c mode change 100644 => 100755 src/getdns/getdns.h.in mode change 100644 => 100755 src/stub.c diff --git a/spec/index.html b/spec/index.html old mode 100644 new mode 100755 index 9e85490f..5b25f8e1 --- a/spec/index.html +++ b/spec/index.html @@ -2193,8 +2193,10 @@ getdns_context_set_dns_transport( The value is GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP, GETDNS_TRANSPORT_UDP_ONLY, -GETDNS_TRANSPORT_TCP_ONLY, or -GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN.

+GETDNS_TRANSPORT_TCP_ONLY, +GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN>, +GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN>, or +GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN>
getdns_return_t diff --git a/src/const-info.c b/src/const-info.c old mode 100644 new mode 100755 index d759765e..5c5a3d99 --- a/src/const-info.c +++ b/src/const-info.c @@ -39,6 +39,8 @@ static struct const_info consts_info[] = { { 541, "GETDNS_TRANSPORT_UDP_ONLY", GETDNS_TRANSPORT_UDP_ONLY_TEXT }, { 542, "GETDNS_TRANSPORT_TCP_ONLY", GETDNS_TRANSPORT_TCP_ONLY_TEXT }, { 543, "GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN", GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN_TEXT }, + { 544, "GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN", GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN_TEXT }, + { 545, "GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN", GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN_TEXT }, { 550, "GETDNS_APPEND_NAME_ALWAYS", GETDNS_APPEND_NAME_ALWAYS_TEXT }, { 551, "GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE", GETDNS_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE_TEXT }, { 552, "GETDNS_APPEND_NAME_ONLY_TO_MULTIPLE_LABEL_NAME_AFTER_FAILURE", GETDNS_APPEND_NAME_ONLY_TO_MULTIPLE_LABEL_NAME_AFTER_FAILURE_TEXT }, diff --git a/src/context.c b/src/context.c index b3c26c48..07c09c75 100644 --- a/src/context.c +++ b/src/context.c @@ -470,6 +470,24 @@ upstreams_resize(getdns_upstreams *upstreams, size_t size) return r; } +static void +upstreams_cleanup(getdns_upstreams *upstreams) +{ + if (!upstreams) + return; + for (int i = 0; i < (int)upstreams->count; i++) { + if (upstreams->upstreams[i].tls_obj != NULL) { + SSL_shutdown(upstreams->upstreams[i].tls_obj); + SSL_free(upstreams->upstreams[i].tls_obj); + upstreams->upstreams[i].tls_obj = NULL; + } + if (upstreams->upstreams[i].fd != -1) { + close(upstreams->upstreams[i].fd); + upstreams->upstreams[i].fd = -1; + } + } +} + static void upstreams_dereference(getdns_upstreams *upstreams) { @@ -541,6 +559,7 @@ upstream_init(getdns_upstream *upstream, /* For sharing a socket to this upstream with TCP */ upstream->fd = -1; + upstream->tls_obj = NULL; upstream->loop = NULL; (void) getdns_eventloop_event_init( &upstream->event, upstream, NULL, NULL, NULL); @@ -770,6 +789,7 @@ getdns_context_create_with_extended_memory_functions( result->edns_extended_rcode = 0; result->edns_version = 0; result->edns_do_bit = 0; + result-> tls_ctx = NULL; result->extension = &result->mini_event.loop; if ((r = getdns_mini_event_init(result, &result->mini_event))) @@ -876,6 +896,9 @@ getdns_context_destroy(struct getdns_context *context) GETDNS_FREE(context->my_mf, context->fchg_hosts->prevstat); GETDNS_FREE(context->my_mf, context->fchg_hosts); } + if (context->tls_ctx) { + SSL_CTX_free(context->tls_ctx); + } getdns_list_destroy(context->dns_root_servers); getdns_list_destroy(context->suffix); @@ -887,6 +910,7 @@ getdns_context_destroy(struct getdns_context *context) getdns_traverse_postorder(&context->local_hosts, destroy_local_host, context); + upstreams_cleanup(context->upstreams); upstreams_dereference(context->upstreams); GETDNS_FREE(context->my_mf, context); @@ -1114,13 +1138,25 @@ set_ub_dns_transport(struct getdns_context* context, set_ub_string_opt(context, "do-tcp:", "no"); break; case GETDNS_TRANSPORT_TCP_ONLY: - case GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN: + case GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN: set_ub_string_opt(context, "do-udp:", "no"); set_ub_string_opt(context, "do-tcp:", "yes"); break; - default: - /* TODO GETDNS_CONTEXT_TCP_ONLY_KEEP_CONNECTIONS_OPEN */ - return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; + case GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN: + case GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN: + /* TODO: Investigate why ssl-upstream in Unbound isn't working (error + that the SSL lib isn't init'ed but that is done in prep_for_res.*/ + /* Note: no fallback or pipelining available directly in unbound.*/ + set_ub_string_opt(context, "do-udp:", "no"); + set_ub_string_opt(context, "do-tcp:", "yes"); + //set_ub_string_opt(context, "ssl-upstream:", "yes"); + /* TODO: Specifying a different port to do TLS on in unbound is a bit + tricky as it involves modifying each fwd upstream defined on the + unbound ctx... And to support fallback this would have to be reset + from the stub code while trying to connect...*/ + break; + default: + return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; } return GETDNS_RETURN_GOOD; } @@ -1134,6 +1170,11 @@ getdns_context_set_dns_transport(struct getdns_context *context, getdns_transport_t value) { RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); + /* Note that the call below does not have any effect in unbound after the + ctx is finalised. So will not apply for recursive mode or stub + dnssec. + However the method returns success as otherwise the transport could not + be reset for stub mode..... */ + /* Also, not all transport options supported in libunbound yet*/ if (set_ub_dns_transport(context, value) != GETDNS_RETURN_GOOD) { return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; } @@ -1448,6 +1489,7 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context, freeaddrinfo(ai); } upstreams_dereference(context->upstreams); + /*Don't the existing upstreams need to be handled before overwritting here?*/ context->upstreams = upstreams; dispatch_updated(context, GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS); @@ -1756,6 +1798,34 @@ getdns_context_prepare_for_resolution(struct getdns_context *context, if (context->destroying) { return GETDNS_RETURN_BAD_CONTEXT; } + + /* Transport can in theory be set per query in stub mode so deal with it + here */ + printf("[TLS] preparing for resolution, checking transport type\n"); + if (context->resolution_type == GETDNS_RESOLUTION_STUB) { + switch (context->dns_transport) { + case GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN: + case GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN: + if (context->tls_ctx == NULL) { + /* Init the SSL library */ + SSL_library_init(); + /* Load error messages */ + SSL_load_error_strings(); + + /* Create client context, use TLS v1.2 only for now */ + SSL_CTX* tls_ctx = SSL_CTX_new(TLSv1_2_client_method()); + if(!tls_ctx) { + ERR_print_errors_fp(stderr); + return GETDNS_RETURN_BAD_CONTEXT; + } + context->tls_ctx = tls_ctx; + } + break; + default: + break; + } + } + if (context->resolution_type_set == context->resolution_type) /* already set and no config changes * have caused this to be bad. diff --git a/src/context.h b/src/context.h index bc30efb3..816c068b 100644 --- a/src/context.h +++ b/src/context.h @@ -83,6 +83,7 @@ typedef struct getdns_upstream { /* For sharing a TCP socket to this upstream */ int fd; + SSL* tls_obj; getdns_eventloop_event event; getdns_eventloop *loop; getdns_tcp_state tcp; @@ -133,6 +134,7 @@ struct getdns_context { uint8_t edns_version; uint8_t edns_do_bit; int edns_maximum_udp_payload_size; /* -1 is unset */ + SSL_CTX* tls_ctx; getdns_update_callback update_callback; getdns_update_callback2 update_callback2; diff --git a/src/getdns/getdns.h.in b/src/getdns/getdns.h.in old mode 100644 new mode 100755 index 4b0bf8aa..f69a2dfc --- a/src/getdns/getdns.h.in +++ b/src/getdns/getdns.h.in @@ -163,7 +163,9 @@ typedef enum getdns_transport_t { GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP = 540, GETDNS_TRANSPORT_UDP_ONLY = 541, GETDNS_TRANSPORT_TCP_ONLY = 542, - GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN = 543 + GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN = 543, + GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN = 544, + GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN = 545 } getdns_transport_t; /** @@ -174,6 +176,8 @@ typedef enum getdns_transport_t { #define GETDNS_TRANSPORT_UDP_ONLY_TEXT "See getdns_context_set_dns_transport()" #define GETDNS_TRANSPORT_TCP_ONLY_TEXT "See getdns_context_set_dns_transport()" #define GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN_TEXT "See getdns_context_set_dns_transport()" +#define GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN_TEXT "See getdns_context_set_dns_transport()" +#define GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN_TEXT "See getdns_context_set_dns_transport()" /** @} */ diff --git a/src/request-internal.c b/src/request-internal.c index 99e5c7d6..6709fde9 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -98,6 +98,7 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner, net_req->write_queue_tail = NULL; net_req->query_len = 0; net_req->response_len = 0; + net_req->tls_obj = NULL; net_req->wire_data_sz = wire_data_sz; if (max_query_sz) { diff --git a/src/stub.c b/src/stub.c old mode 100644 new mode 100755 index bb4277e9..2de8d028 --- a/src/stub.c +++ b/src/stub.c @@ -41,6 +41,8 @@ #include "util-internal.h" #include "general.h" +#define TLS_PORT 1021 + static time_t secret_rollover_time = 0; static uint32_t secret = 0; static uint32_t prev_secret = 0; @@ -318,6 +320,13 @@ upstream_erred(getdns_upstream *upstream) netreq->state = NET_REQ_FINISHED; priv_getdns_check_dns_req_complete(netreq->owner); } + // TODO[TLS]: When we get an error (which is probably a timeout) and are + // using to keep connections open should we leave the connection up here? + if (upstream->tls_obj) { + SSL_shutdown(upstream->tls_obj); + SSL_free(upstream->tls_obj); + upstream->tls_obj = NULL; + } close(upstream->fd); upstream->fd = -1; } @@ -498,6 +507,8 @@ stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf) uint8_t *buf; size_t buf_size; + fprintf(stderr, "[TLS] method: stub_tcp_read\n"); + if (!tcp->read_buf) { /* First time tcp read, create a buffer for reading */ if (!(tcp->read_buf = GETDNS_XMALLOC(*mf, uint8_t, 4096))) @@ -518,10 +529,11 @@ stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf) /* TODO: Try to reconnect */ return STUB_TCP_ERROR; } + fprintf(stderr, "[TLS] method: read %d TCP bytes \n", (int)read); tcp->to_read -= read; tcp->read_pos += read; - if (tcp->to_read > 0) + if ((int)tcp->to_read > 0) return STUB_TCP_AGAIN; read = tcp->read_pos - tcp->read_buf; @@ -563,13 +575,16 @@ stub_tcp_read_cb(void *userarg) &dnsreq->context->mf))) { case STUB_TCP_AGAIN: + fprintf(stderr, "[TLS] method: stub_tcp_read_cb -> tcp again\n"); return; case STUB_TCP_ERROR: + fprintf(stderr, "[TLS] method: stub_tcp_read_cb -> tcp error\n"); stub_erred(netreq); return; default: + fprintf(stderr, "[TLS] method: stub_tcp_read_cb -> All done. close fd %d\n", netreq->fd); GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); if (q != netreq->query_id) return; @@ -595,8 +610,200 @@ stub_tcp_read_cb(void *userarg) } } +/** wait for a socket to become ready */ +static int +sock_wait(int sockfd) +{ + int ret; + fd_set fds; + FD_ZERO(&fds); + FD_SET(FD_SET_T sockfd, &fds); + struct timeval timeout = {2, 0 }; + ret = select(sockfd+1, NULL, &fds, NULL, &timeout); + if(ret == 0) + /* timeout expired */ + return 0; + else if(ret == -1) + /* error */ + return 0; + return 1; +} + +static int +sock_connected(int sockfd) +{ + fprintf(stderr, "[TLS] connect in progress \n"); + /* wait(write) until connected or error */ + while(1) { + int error = 0; + socklen_t len = (socklen_t)sizeof(error); + + if(!sock_wait(sockfd)) { + close(sockfd); + return -1; + } + + /* check if there is a pending error for nonblocking connect */ + if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)&error, &len) < 0) { + error = errno; /* on solaris errno is error */ + } + if (error == EINPROGRESS || error == EWOULDBLOCK) + continue; /* try again */ + else if (error != 0) { + close(sockfd); + return -1; + } + /* connected */ + break; + } + return sockfd; +} + +/* The connection testing and handshake should be handled by integrating this + * with the event loop framework, but for now just implement a standalone + * handshake method.*/ +SSL* +do_tls_handshake(getdns_dns_req *dnsreq, getdns_upstream *upstream) +{ + /*Lets make sure the connection is up before we try a handshake*/ + if (errno == EINPROGRESS && sock_connected(upstream->fd) == -1) { + fprintf(stderr, "[TLS] connect failed \n"); + return NULL; + } + fprintf(stderr, "[TLS] connect done \n"); + + /* Create SSL instance */ + SSL* ssl = SSL_new(dnsreq->context->tls_ctx); + if(!ssl) { + return NULL; + } + /* Connect the SSL object with a file descriptor */ + if(!SSL_set_fd(ssl, upstream->fd)) { + SSL_free(ssl); + return NULL; + } + SSL_set_connect_state(ssl); + (void) SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); + + int r; + int want; + fd_set fds; + FD_ZERO(&fds); + FD_SET(upstream->fd, &fds); + struct timeval timeout = {dnsreq->context->timeout/1000, 0 }; + while ((r = SSL_do_handshake(ssl)) != 1) + { + want = SSL_get_error(ssl, r); + fprintf(stderr, "[TLS] in handshake loop %d, want is %d \n", r, want); + switch (want) { + case SSL_ERROR_WANT_READ: + if (select(upstream->fd + 1, &fds, NULL, NULL, &timeout) == 0) { + fprintf(stderr, "[TLS] ssl handshake timeout %d\n", want); + SSL_free(ssl); + return NULL; + } + break; + case SSL_ERROR_WANT_WRITE: + if (select(upstream->fd + 1, NULL, &fds, NULL, &timeout) == 0) { + fprintf(stderr, "[TLS] ssl handshake timeout %d\n", want); + SSL_free(ssl); + return NULL; + } + break; + default: + fprintf(stderr, "[TLS] got ssl error code %d\n", want); + SSL_free(ssl); + return NULL; + } + } + fprintf(stderr, "[TLS] got TLS connection\n"); + return ssl; +} + +static int +stub_tls_read(SSL* tls_obj, getdns_tcp_state *tcp, struct mem_funcs *mf) +{ + ssize_t read; + uint8_t *buf; + size_t buf_size; + + fprintf(stderr, "[TLS] method: stub_tls_read\n"); + + if (!tcp->read_buf) { + /* First time tls read, create a buffer for reading */ + if (!(tcp->read_buf = GETDNS_XMALLOC(*mf, uint8_t, 4096))) + return STUB_TCP_ERROR; + + tcp->read_buf_len = 4096; + tcp->read_pos = tcp->read_buf; + tcp->to_read = 2; /* Packet size */ + } + + ERR_clear_error(); + read = SSL_read(tls_obj, tcp->read_pos, tcp->to_read); + if (read <= 0) { + /* TODO[TLS]: Handle SSL_ERROR_WANT_WRITE which means handshake + renegotiation. Need to keep handshake state to do that.*/ + int want = SSL_get_error(tls_obj, read); + if (want == SSL_ERROR_WANT_READ) { + return STUB_TCP_AGAIN; /* read more later */ + } else + return STUB_TCP_ERROR; + } + fprintf(stderr, "[TLS] method: read %d TLS bytes \n", (int)read); + tcp->to_read -= read; + tcp->read_pos += read; + + if ((int)tcp->to_read > 0) + return STUB_TCP_AGAIN; + + read = tcp->read_pos - tcp->read_buf; + if (read == 2) { + /* Read the packet size short */ + tcp->to_read = gldns_read_uint16(tcp->read_buf); + fprintf(stderr, "[TLS] method: %d TLS bytes to read \n", (int)tcp->to_read); + + if (tcp->to_read < GLDNS_HEADER_SIZE) + return STUB_TCP_ERROR; + + /* Resize our buffer if needed */ + if (tcp->to_read > tcp->read_buf_len) { + buf_size = tcp->read_buf_len; + while (tcp->to_read > buf_size) + buf_size *= 2; + + if (!(buf = GETDNS_XREALLOC(*mf, + tcp->read_buf, uint8_t, buf_size))) + return STUB_TCP_ERROR; + + tcp->read_buf = buf; + tcp->read_buf_len = buf_size; + } + + /* Ready to start reading the packet */ + fprintf(stderr, "[TLS] method: resetting read_pos \n"); + tcp->read_pos = tcp->read_buf; + read = SSL_read(tls_obj, tcp->read_pos, tcp->to_read); + if (read <= 0) { + /* TODO[TLS]: Handle SSL_ERROR_WANT_WRITE which means handshake + renegotiation. Need to keep handshake state to do that.*/ + int want = SSL_get_error(tls_obj, read); + if (want == SSL_ERROR_WANT_READ) { + return STUB_TCP_AGAIN; /* read more later */ + } else + return STUB_TCP_ERROR; + } + tcp->to_read -= read; + tcp->read_pos += read; + if ((int)tcp->to_read > 0) + return STUB_TCP_AGAIN; + } + return GLDNS_ID_WIRE(tcp->read_buf); +} + static void netreq_upstream_read_cb(void *userarg); static void netreq_upstream_write_cb(void *userarg); +static void upstream_write_cb(void *userarg); static void upstream_read_cb(void *userarg) { @@ -607,9 +814,18 @@ upstream_read_cb(void *userarg) uint16_t query_id; intptr_t query_id_intptr; - switch ((q = stub_tcp_read(upstream->fd, &upstream->tcp, - &upstream->upstreams->mf))) { + fprintf(stderr, "[TLS] method: upstream_read_cb\n"); + + if (upstream->tls_obj) + q = stub_tls_read(upstream->tls_obj, &upstream->tcp, + &upstream->upstreams->mf); + else + q = stub_tcp_read(upstream->fd, &upstream->tcp, + &upstream->upstreams->mf); + + switch (q) { case STUB_TCP_AGAIN: + fprintf(stderr, "[TLS] method: upstream_read_cb -> STUB_TCP_AGAIN\n"); return; case STUB_TCP_ERROR: @@ -617,6 +833,8 @@ upstream_read_cb(void *userarg) return; default: + fprintf(stderr, "[TLS] method: upstream_read_cb -> processing reponse\n"); + /* Lookup netreq */ query_id = (uint16_t) q; query_id_intptr = (intptr_t) query_id; @@ -633,6 +851,7 @@ upstream_read_cb(void *userarg) netreq->response = upstream->tcp.read_buf; netreq->response_len = upstream->tcp.read_pos - upstream->tcp.read_buf; + netreq->tls_obj = upstream->tls_obj; upstream->tcp.read_buf = NULL; upstream->upstreams->current = 0; @@ -687,6 +906,7 @@ static int stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq) { getdns_dns_req *dnsreq = netreq->owner; + fprintf(stderr, "[TLS] method: stub_tcp_write\n"); size_t pkt_len = netreq->response - netreq->query; ssize_t written; @@ -705,9 +925,9 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq) * the write_queue) for that upstream. Register this netreq * by query_id in the process. */ - if (dnsreq->context->dns_transport != - GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN) - + if ((dnsreq->context->dns_transport == GETDNS_TRANSPORT_TCP_ONLY) || + (dnsreq->context->dns_transport == GETDNS_TRANSPORT_UDP_ONLY) || + (dnsreq->context->dns_transport == GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP)) query_id = arc4random(); else do { query_id = arc4random(); @@ -822,6 +1042,56 @@ stub_tcp_write_cb(void *userarg) } } +static int +stub_tls_write(SSL* tls_obj, getdns_tcp_state *tcp, getdns_network_req *netreq) +{ + fprintf(stderr, "[TLS] method: stub_tls_write\n"); + + size_t pkt_len = netreq->response - netreq->query; + ssize_t written; + uint16_t query_id; + intptr_t query_id_intptr; + + /* Do we have remaining data that we could not write before? */ + if (! tcp->write_buf) { + /* No, this is an initial write. Try to send + */ + + /* Find a unique query_id not already written (or in + * the write_queue) for that upstream. Register this netreq + * by query_id in the process. + */ + do { + query_id = ldns_get_random(); + query_id_intptr = (intptr_t)query_id; + netreq->node.key = (void *)query_id_intptr; + + } while (!getdns_rbtree_insert( + &netreq->upstream->netreq_by_query_id, &netreq->node)); + + GLDNS_ID_SET(netreq->query, query_id); + if (netreq->opt) + /* no limits on the max udp payload size with tcp */ + gldns_write_uint16(netreq->opt + 3, 65535); + + /* We have an initialized packet buffer. + * Lets see how much of it we can write */ + + // TODO[TLS]: Handle error cases, partial writes, renegotiation etc. + ERR_clear_error(); + written = SSL_write(tls_obj, netreq->query - 2, pkt_len + 2); + if (written <= 0) + return STUB_TCP_ERROR; + + /* We were able to write everything! Start reading. */ + return (int) query_id; + + } + + return STUB_TCP_ERROR; +} + + static void upstream_write_cb(void *userarg) { @@ -830,7 +1100,14 @@ upstream_write_cb(void *userarg) getdns_dns_req *dnsreq = netreq->owner; int q; - switch ((q = stub_tcp_write(upstream->fd, &upstream->tcp, netreq))) { + fprintf(stderr, "[TLS] method: upstream_write_cb for %s with class %d\n", dnsreq->name, (int)netreq->request_class); + + if (upstream->tls_obj) + q = stub_tls_write(upstream->tls_obj, &upstream->tcp, netreq); + else + q = stub_tcp_write(upstream->fd, &upstream->tcp, netreq); + + switch (q) { case STUB_TCP_AGAIN: return; @@ -902,18 +1179,110 @@ upstream_schedule_netreq(getdns_upstream *upstream, getdns_network_req *netreq) } } +static in_port_t +get_port(struct sockaddr_storage* addr) +{ + return ntohs(addr->ss_family == AF_INET + ? ((struct sockaddr_in *)addr)->sin_port + : ((struct sockaddr_in6*)addr)->sin6_port); +} + +void +set_port(struct sockaddr_storage* addr, in_port_t port) +{ + addr->ss_family == AF_INET + ? (((struct sockaddr_in *)addr)->sin_port = htons(port)) + : (((struct sockaddr_in6*)addr)->sin6_port = htons(port)); +} + +typedef enum getdns_base_transport { + NONE, + UDP, + TCP_SINGLE, + TCP, + TLS +} getdns_base_transport_t; + +getdns_transport_t +get_transport(getdns_transport_t transport, int level) { + if (!(level == 0 || level == 1)) return NONE; + switch (transport) { + case GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP: + if (level == 0) return UDP; + if (level == 1) return TCP; + case GETDNS_TRANSPORT_UDP_ONLY: + if (level == 0) return UDP; + if (level == 1) return NONE; + case GETDNS_TRANSPORT_TCP_ONLY: + if (level == 0) return TCP_SINGLE; + if (level == 1) return NONE; + case GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN: + if (level == 0) return TCP; + if (level == 1) return NONE; + case GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN: + if (level == 0) return TLS; + if (level == 1) return NONE; + case GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN: + if (level == 0) return TLS; + if (level == 1) return TCP; + default: + return NONE; + } +} + +int +tcp_connect (getdns_upstream *upstream, getdns_base_transport_t transport) { + + int fd =-1; + struct sockaddr_storage connect_addr; + struct sockaddr_storage* addr = &upstream->addr; + socklen_t addr_len = upstream->addr_len; + + /* TODO[TLS]: For now, override the port to a hardcoded value*/ + if (transport == TLS && (int)get_port(addr) != TLS_PORT) { + connect_addr = upstream->addr; + addr = &connect_addr; + set_port(addr, TLS_PORT); + fprintf(stderr, "[TLS] Forcing switch to port %d for TLS\n", TLS_PORT); + } + + if ((fd = socket(addr->ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) + return -1; + + getdns_sock_nonblock(fd); +#ifdef USE_TCP_FASTOPEN + /* Leave the connect to the later call to sendto() if using TCP*/ + if (transport == TCP || transport == TCP_SINGLE) + return fd; +#endif + if (connect(fd, (struct sockaddr *)addr, + addr_len) == -1) { + if (errno != EINPROGRESS) { + close(fd); + return -1; + } + } + return fd; +} + getdns_return_t priv_getdns_submit_stub_request(getdns_network_req *netreq) { getdns_dns_req *dnsreq = netreq->owner; getdns_upstream *upstream = pick_upstream(dnsreq); + fprintf(stderr, "[TLS] method: priv_getdns_submit_stub_request\n"); + if (!upstream) return GETDNS_RETURN_GENERIC_ERROR; - switch(dnsreq->context->dns_transport) { - case GETDNS_TRANSPORT_UDP_ONLY: - case GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP: + // Work out the primary and fallback transport options + getdns_base_transport_t transport = get_transport( + dnsreq->context->dns_transport,0); + getdns_base_transport_t fb_transport = get_transport( + dnsreq->context->dns_transport,1); + switch(transport) { + case UDP: if ((netreq->fd = socket( upstream->addr.ss_family, SOCK_DGRAM, IPPROTO_UDP)) == -1) @@ -929,23 +1298,10 @@ priv_getdns_submit_stub_request(getdns_network_req *netreq) return GETDNS_RETURN_GOOD; - case GETDNS_TRANSPORT_TCP_ONLY: + case TCP_SINGLE: - if ((netreq->fd = socket( - upstream->addr.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) + if ((netreq->fd = tcp_connect(upstream, transport)) == -1) return GETDNS_RETURN_GENERIC_ERROR; - - getdns_sock_nonblock(netreq->fd); -#ifdef USE_TCP_FASTOPEN - /* Leave the connect to the later call to sendto() */ -#else - if (connect(netreq->fd, (struct sockaddr *)&upstream->addr, - upstream->addr_len) == -1 && errno != EINPROGRESS) { - - close(netreq->fd); - return GETDNS_RETURN_GENERIC_ERROR; - } -#endif netreq->upstream = upstream; GETDNS_SCHEDULE_EVENT( @@ -955,37 +1311,58 @@ priv_getdns_submit_stub_request(getdns_network_req *netreq) return GETDNS_RETURN_GOOD; - case GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN: + case TCP: + case TLS: /* In coming comments, "global" means "context wide" */ /* Are we the first? (Is global socket initialized?) */ if (upstream->fd == -1) { - /* We are the first. Make global socket and connect. */ - if ((upstream->fd = socket(upstream->addr.ss_family, - SOCK_STREAM, IPPROTO_TCP)) == -1) - return GETDNS_RETURN_GENERIC_ERROR; - - getdns_sock_nonblock(upstream->fd); -#ifdef USE_TCP_FASTOPEN - /* Leave the connect to the later call to sendto() */ -#else - if (connect(upstream->fd, - (struct sockaddr *)&upstream->addr, - upstream->addr_len) == -1 && errno != EINPROGRESS){ + /* TODO[TLS]: We should remember on the context if we had to fallback + * for this upstream so when re-connecting from a dropped TCP + * connection we don't retry TLS. */ + int fallback = 0; - close(upstream->fd); - upstream->fd = -1; - return GETDNS_RETURN_GENERIC_ERROR; + /* We are the first. Make global socket and connect. */ + if ((upstream->fd = tcp_connect(upstream, transport)) == -1) { + //TODO: Hum, a reset doesn't make the connect fail... + if (fb_transport == NONE) + return GETDNS_RETURN_GENERIC_ERROR; + fprintf(stderr, "[TLS] Connect failed on fd... %d\n", upstream->fd); + if ((upstream->fd = tcp_connect(upstream, fb_transport)) == -1) + return GETDNS_RETURN_GENERIC_ERROR; + fallback = 1; + } + + /* Now do a handshake for TLS. Note waiting for this to succeed or + timeout blocks the scheduling of any messages for this upstream*/ + if (transport == TLS && (fallback == 0)) { + fprintf(stderr, "[TLS] Doing SSL handshake... %d\n", upstream->fd); + upstream->tls_obj = do_tls_handshake(dnsreq, upstream); + if (!upstream->tls_obj) { + if (fb_transport == NONE) + return GETDNS_RETURN_GENERIC_ERROR; + close(upstream->fd); + if ((upstream->fd = tcp_connect(upstream, fb_transport)) == -1) + return GETDNS_RETURN_GENERIC_ERROR; + } + } + } else { + /* Cater for the case of the user downgrading and existing TLS + connection to TCP for some reason...*/ + if (transport == TCP && upstream->tls_obj) { + SSL_shutdown(upstream->tls_obj); + SSL_free(upstream->tls_obj); + upstream->tls_obj = NULL; } -#endif - /* Attach to the global event loop - * so it can do it's own scheduling - */ - upstream->loop = dnsreq->context->extension; } netreq->upstream = upstream; + /* Attach to the global event loop + * so it can do it's own scheduling + */ + upstream->loop = dnsreq->context->extension; + /* We have a context wide socket. * Now schedule the write request. */ diff --git a/src/test/getdns_query.c b/src/test/getdns_query.c index 524a9a7c..3fc27ffe 100644 --- a/src/test/getdns_query.c +++ b/src/test/getdns_query.c @@ -29,9 +29,23 @@ #include #include #include +#include #include #include +static int quiet = 0; +static int batch_mode = 0; +static char *query_file = NULL; +static int json = 0; +static char *the_root = "."; +static char *name; +static getdns_context *context; +static getdns_dict *extensions; +static uint16_t request_type = GETDNS_RRTYPE_NS; +static int timeout, edns0_size; +static int async = 0, interactive = 0; +static enum { GENERAL, ADDRESS, HOSTNAME, SERVICE } calltype = GENERAL; + int get_rrtype(const char *t); getdns_dict * @@ -90,6 +104,7 @@ print_usage(FILE *out, const char *progname) fprintf(out, "\t-b \tSet edns0 max_udp_payload size\n"); fprintf(out, "\t-D\tSet edns0 do bit\n"); fprintf(out, "\t-d\tclear edns0 do bit\n"); + fprintf(out, "\t-F \tread the queries from the specified file\n"); fprintf(out, "\t-G\tgeneral lookup\n"); fprintf(out, "\t-H\thostname lookup. ( must be an IP address; is ignored)\n"); fprintf(out, "\t-h\tPrint this help\n"); @@ -104,29 +119,47 @@ print_usage(FILE *out, const char *progname) fprintf(out, "\t-t \tSet timeout in miliseconds\n"); fprintf(out, "\t-T\tSet transport to TCP only\n"); fprintf(out, "\t-O\tSet transport to TCP only keep connections open\n"); + fprintf(out, "\t-L\tSet transport to TLS only keep connections open\n"); + fprintf(out, "\t-E\tSet transport to TLS with TCP fallback only keep connections open\n"); fprintf(out, "\t-u\tSet transport to UDP with TCP fallback\n"); fprintf(out, "\t-U\tSet transport to UDP only\n"); + fprintf(out, "\t-B\tBatch mode. Schedule all messages before processing responses.\n"); + fprintf(out, "\t-q\tQuiet mode - don't print response\n"); + fprintf(out, "\t+sit[=cookie]\tSet edns cookie\n"); } void callback(getdns_context *context, getdns_callback_type_t callback_type, getdns_dict *response, void *userarg, getdns_transaction_t trans_id) { - getdns_dict **response_ptr = (getdns_dict **)userarg; + char *response_str; - if (response) - *response_ptr = response; + if (callback_type == GETDNS_CALLBACK_COMPLETE) { + /* This is a callback with data */; + if (!quiet) { + if (json) + response_str = getdns_print_json_dict( + response, json == 1); + else if ((response_str = getdns_pretty_print_dict(response))) { + fprintf(stdout, "ASYNC response:\n%s\n", response_str); + free(response_str); + } + } + fprintf(stderr, + "The callback with ID %llu was successfull.\n", + (unsigned long long)trans_id); + + } else if (callback_type == GETDNS_CALLBACK_CANCEL) + fprintf(stderr, + "The callback with ID %llu was cancelled. Exiting.\n", + (unsigned long long)trans_id); + else + fprintf(stderr, + "The callback got a callback_type of %d. Exiting.\n", + callback_type); + getdns_dict_destroy(response); + response = NULL; } -static char *the_root = "."; -static char *name; -static getdns_context *context; -static getdns_dict *extensions; -static uint16_t request_type = GETDNS_RRTYPE_NS; -static int timeout, edns0_size; -static int async = 0, interactive = 0; -static enum { GENERAL, ADDRESS, HOSTNAME, SERVICE } calltype = GENERAL; -static int json = 0; - #define CONTINUE ((getdns_return_t)-2) static getdns_return_t set_cookie(getdns_dict *exts, char *cookie) @@ -259,6 +292,15 @@ getdns_return_t parse_args(int argc, char **argv) case 'd': (void) getdns_context_set_edns_do_bit(context, 0); break; + case 'F': + if (c[1] != 0 || ++i >= argc || !*argv[i]) { + fprintf(stderr, "file name expected " + "after -F\n"); + return GETDNS_RETURN_GENERIC_ERROR; + } + query_file = argv[i]; + interactive = 1; + break; case 'G': calltype = GENERAL; break; @@ -282,6 +324,8 @@ getdns_return_t parse_args(int argc, char **argv) break; case 'p': json = 0; + case 'q': + quiet = 1; break; case 'r': getdns_context_set_resolution_type( @@ -319,6 +363,14 @@ getdns_return_t parse_args(int argc, char **argv) getdns_context_set_dns_transport(context, GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN); break; + case 'L': + getdns_context_set_dns_transport(context, + GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN); + break; + case 'E': + getdns_context_set_dns_transport(context, + GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN); + break; case 'u': getdns_context_set_dns_transport(context, GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP); @@ -327,6 +379,9 @@ getdns_return_t parse_args(int argc, char **argv) getdns_context_set_dns_transport(context, GETDNS_TRANSPORT_UDP_ONLY); break; + case 'B': + batch_mode = 1; + break; default: @@ -361,6 +416,7 @@ main(int argc, char **argv) char *response_str; getdns_return_t r; getdns_dict *address = NULL; + FILE *fp = NULL; name = the_root; if ((r = getdns_context_create(&context, 1))) { @@ -376,14 +432,28 @@ main(int argc, char **argv) if ((r = parse_args(argc, argv))) goto done_destroy_context; + if (query_file) { + fp = fopen(query_file, "rt"); + if (fp == NULL) { + fprintf(stderr, "Could not open query file: %s\n", query_file); + goto done_destroy_context; + } + } + /* Make the call */ do { char line[1024], *token, *linev[256]; int linec; if (interactive) { - fprintf(stdout, "> "); - if (!fgets(line, 1024, stdin) || !*line) - break; + if (!query_file) { + fprintf(stdout, "> "); + if (!fgets(line, 1024, stdin) || !*line) + break; + } else { + if (!fgets(line, 1024, fp) || !*line) + break; + fprintf(stdout,"Found query: %s", line); + } linev[0] = argv[0]; linec = 1; @@ -430,8 +500,8 @@ main(int argc, char **argv) } if (r) goto done_destroy_extensions; - - getdns_context_run(context); + if (!batch_mode) + getdns_context_run(context); } else { switch (calltype) { case GENERAL: @@ -456,22 +526,27 @@ main(int argc, char **argv) } if (r) goto done_destroy_extensions; - } - if (json) - response_str = getdns_print_json_dict( - response, json == 1); - else - response_str = getdns_pretty_print_dict(response); - - if (response_str) { - fprintf(stdout, "%s\n", response_str); - free(response_str); - } else { - r = GETDNS_RETURN_MEMORY_ERROR; - fprintf(stderr, "Could not print response\n"); + if (!quiet) { + if (json) + response_str = getdns_print_json_dict( + response, json == 1); + else if ((response_str = getdns_pretty_print_dict(response))) { + fprintf(stdout, "SYNC response:\n%s\n", response_str); + free(response_str); + } else { + r = GETDNS_RETURN_MEMORY_ERROR; + fprintf(stderr, "Could not print response\n"); + } + } else if (r == GETDNS_RETURN_GOOD) + fprintf(stdout, "Response code was: GOOD\n"); + else if (interactive) + fprintf(stderr, "An error occurred: %d\n", r); } } while (interactive); + if (batch_mode) + getdns_context_run(context); + /* Clean up */ done_destroy_extensions: getdns_dict_destroy(extensions); @@ -479,6 +554,9 @@ done_destroy_context: if (response) getdns_dict_destroy(response); getdns_context_destroy(context); + if (fp) + fclose(fp); + if (r == CONTINUE) return 0; if (r) diff --git a/src/test/tests_stub_async.c b/src/test/tests_stub_async.c index 4c6e0b4a..fb0baf63 100644 --- a/src/test/tests_stub_async.c +++ b/src/test/tests_stub_async.c @@ -44,6 +44,8 @@ #define TRANSPORT_UDP "udp" #define TRANSPORT_TCP "tcp" #define TRANSPORT_PIPELINE "pipeline" +#define TRANSPORT_TLS_KEEPOPEN "tls" +#define TRANSPORT_TLS_TCP_KEEPOPEN "dns-over-tls" #define RESOLUTION_STUB "stub" #define RESOLUTION_REC "rec" @@ -98,6 +100,10 @@ main(int argc, char** argv) getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TCP_ONLY); else if (strncmp(transport, TRANSPORT_PIPELINE, 8) == 0) getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN); + else if (strncmp(transport, TRANSPORT_TLS_KEEPOPEN, 3) == 0) + getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN); + else if (strncmp(transport, TRANSPORT_TLS_TCP_KEEPOPEN, 12) == 0) + getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN); else if (strncmp(transport, TRANSPORT_UDP, 3) != 0) { fprintf(stderr, "Invalid transport %s, must be one of udp, tcp or pipeline\n", transport); exit(EXIT_FAILURE); diff --git a/src/test/tests_stub_sync.c b/src/test/tests_stub_sync.c index 4b04d5fb..496fb7ab 100644 --- a/src/test/tests_stub_sync.c +++ b/src/test/tests_stub_sync.c @@ -41,6 +41,8 @@ #define TRANSPORT_UDP "udp" #define TRANSPORT_TCP "tcp" #define TRANSPORT_PIPELINE "pipeline" +#define TRANSPORT_TLS_KEEPOPEN "tls" +#define TRANSPORT_TLS_TCP_KEEPOPEN "dns-over-tls" #define RESOLUTION_STUB "stub" #define RESOLUTION_REC "rec" @@ -82,6 +84,10 @@ main(int argc, char** argv) getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TCP_ONLY); else if (strncmp(transport, TRANSPORT_PIPELINE, 8) == 0) getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN); + else if (strncmp(transport, TRANSPORT_TLS_KEEPOPEN, 3) == 0) + getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN); + else if (strncmp(transport, TRANSPORT_TLS_TCP_KEEPOPEN, 12) == 0) + getdns_context_set_dns_transport(this_context, GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN); else if (strncmp(transport, TRANSPORT_UDP, 3) != 0) { fprintf(stderr, "Invalid transport %s, must be one of udp, tcp or pipeline\n", transport); exit(EXIT_FAILURE); diff --git a/src/types-internal.h b/src/types-internal.h index 81141bcc..b961729e 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -37,6 +37,7 @@ #define TYPES_INTERNAL_H_ #include +#include #include "getdns/getdns.h" #include "getdns/getdns_extra.h" #include "util/rbtree.h" @@ -211,6 +212,7 @@ typedef struct getdns_network_req uint8_t *opt; /* offset of OPT RR in query */ size_t response_len; uint8_t *response; + SSL* tls_obj; size_t wire_data_sz; uint8_t wire_data[]; From 99c1973faeb2df7f770d341e67e2221ad0f8deef Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Thu, 16 Apr 2015 18:01:17 +0100 Subject: [PATCH 02/10] Cleanup of TLS code --- src/context.c | 27 +++++++++------------ src/request-internal.c | 1 - src/stub.c | 54 +++++++----------------------------------- src/types-internal.h | 1 - 4 files changed, 20 insertions(+), 63 deletions(-) diff --git a/src/context.c b/src/context.c index 07c09c75..961ea8f9 100644 --- a/src/context.c +++ b/src/context.c @@ -1145,15 +1145,15 @@ set_ub_dns_transport(struct getdns_context* context, case GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN: case GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN: /* TODO: Investigate why ssl-upstream in Unbound isn't working (error - that the SSL lib isn't init'ed but that is done in prep_for_res.*/ - /* Note: no fallback or pipelining available directly in unbound.*/ + * that the SSL lib isn't init'ed but that is done in prep_for_res. + * Note: no fallback or pipelining available directly in unbound.*/ set_ub_string_opt(context, "do-udp:", "no"); set_ub_string_opt(context, "do-tcp:", "yes"); - //set_ub_string_opt(context, "ssl-upstream:", "yes"); + /* set_ub_string_opt(context, "ssl-upstream:", "yes");*/ /* TODO: Specifying a different port to do TLS on in unbound is a bit - tricky as it involves modifying each fwd upstream defined on the - unbound ctx... And to support fallback this would have to be reset - from the stub code while trying to connect...*/ + * tricky as it involves modifying each fwd upstream defined on the + * unbound ctx... And to support fallback this would have to be reset + * from the stub code while trying to connect...*/ break; default: return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; @@ -1171,10 +1171,10 @@ getdns_context_set_dns_transport(struct getdns_context *context, { RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER); /* Note that the call below does not have any effect in unbound after the - ctx is finalised. So will not apply for recursive mode or stub + dnssec. - However the method returns success as otherwise the transport could not - be reset for stub mode..... */ - /* Also, not all transport options supported in libunbound yet*/ + * ctx is finalised. So will not apply for recursive mode or stub + dnssec. + * However the method returns success as otherwise the transport could not + * be reset for stub mode..... + * Also, not all transport options supported in libunbound yet */ if (set_ub_dns_transport(context, value) != GETDNS_RETURN_GOOD) { return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; } @@ -1799,9 +1799,7 @@ getdns_context_prepare_for_resolution(struct getdns_context *context, return GETDNS_RETURN_BAD_CONTEXT; } - /* Transport can in theory be set per query in stub mode so deal with it - here */ - printf("[TLS] preparing for resolution, checking transport type\n"); + /* Transport can in theory be set per query in stub mode */ if (context->resolution_type == GETDNS_RESOLUTION_STUB) { switch (context->dns_transport) { case GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN: @@ -1809,13 +1807,10 @@ getdns_context_prepare_for_resolution(struct getdns_context *context, if (context->tls_ctx == NULL) { /* Init the SSL library */ SSL_library_init(); - /* Load error messages */ - SSL_load_error_strings(); /* Create client context, use TLS v1.2 only for now */ SSL_CTX* tls_ctx = SSL_CTX_new(TLSv1_2_client_method()); if(!tls_ctx) { - ERR_print_errors_fp(stderr); return GETDNS_RETURN_BAD_CONTEXT; } context->tls_ctx = tls_ctx; diff --git a/src/request-internal.c b/src/request-internal.c index 6709fde9..99e5c7d6 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -98,7 +98,6 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner, net_req->write_queue_tail = NULL; net_req->query_len = 0; net_req->response_len = 0; - net_req->tls_obj = NULL; net_req->wire_data_sz = wire_data_sz; if (max_query_sz) { diff --git a/src/stub.c b/src/stub.c index 2de8d028..0d8610c4 100755 --- a/src/stub.c +++ b/src/stub.c @@ -320,8 +320,8 @@ upstream_erred(getdns_upstream *upstream) netreq->state = NET_REQ_FINISHED; priv_getdns_check_dns_req_complete(netreq->owner); } - // TODO[TLS]: When we get an error (which is probably a timeout) and are - // using to keep connections open should we leave the connection up here? + /* TODO[TLS]: When we get an error (which is probably a timeout) and are + * using to keep connections open should we leave the connection up here? */ if (upstream->tls_obj) { SSL_shutdown(upstream->tls_obj); SSL_free(upstream->tls_obj); @@ -507,8 +507,6 @@ stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf) uint8_t *buf; size_t buf_size; - fprintf(stderr, "[TLS] method: stub_tcp_read\n"); - if (!tcp->read_buf) { /* First time tcp read, create a buffer for reading */ if (!(tcp->read_buf = GETDNS_XMALLOC(*mf, uint8_t, 4096))) @@ -529,7 +527,6 @@ stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf) /* TODO: Try to reconnect */ return STUB_TCP_ERROR; } - fprintf(stderr, "[TLS] method: read %d TCP bytes \n", (int)read); tcp->to_read -= read; tcp->read_pos += read; @@ -575,16 +572,13 @@ stub_tcp_read_cb(void *userarg) &dnsreq->context->mf))) { case STUB_TCP_AGAIN: - fprintf(stderr, "[TLS] method: stub_tcp_read_cb -> tcp again\n"); return; case STUB_TCP_ERROR: - fprintf(stderr, "[TLS] method: stub_tcp_read_cb -> tcp error\n"); stub_erred(netreq); return; default: - fprintf(stderr, "[TLS] method: stub_tcp_read_cb -> All done. close fd %d\n", netreq->fd); GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event); if (q != netreq->query_id) return; @@ -618,7 +612,8 @@ sock_wait(int sockfd) fd_set fds; FD_ZERO(&fds); FD_SET(FD_SET_T sockfd, &fds); - struct timeval timeout = {2, 0 }; + /*TODO[TLS]: Pick up this timeout from the context*/ + struct timeval timeout = {5, 0 }; ret = select(sockfd+1, NULL, &fds, NULL, &timeout); if(ret == 0) /* timeout expired */ @@ -632,7 +627,6 @@ sock_wait(int sockfd) static int sock_connected(int sockfd) { - fprintf(stderr, "[TLS] connect in progress \n"); /* wait(write) until connected or error */ while(1) { int error = 0; @@ -667,10 +661,8 @@ do_tls_handshake(getdns_dns_req *dnsreq, getdns_upstream *upstream) { /*Lets make sure the connection is up before we try a handshake*/ if (errno == EINPROGRESS && sock_connected(upstream->fd) == -1) { - fprintf(stderr, "[TLS] connect failed \n"); return NULL; } - fprintf(stderr, "[TLS] connect done \n"); /* Create SSL instance */ SSL* ssl = SSL_new(dnsreq->context->tls_ctx); @@ -694,29 +686,24 @@ do_tls_handshake(getdns_dns_req *dnsreq, getdns_upstream *upstream) while ((r = SSL_do_handshake(ssl)) != 1) { want = SSL_get_error(ssl, r); - fprintf(stderr, "[TLS] in handshake loop %d, want is %d \n", r, want); switch (want) { case SSL_ERROR_WANT_READ: if (select(upstream->fd + 1, &fds, NULL, NULL, &timeout) == 0) { - fprintf(stderr, "[TLS] ssl handshake timeout %d\n", want); SSL_free(ssl); return NULL; } break; case SSL_ERROR_WANT_WRITE: if (select(upstream->fd + 1, NULL, &fds, NULL, &timeout) == 0) { - fprintf(stderr, "[TLS] ssl handshake timeout %d\n", want); SSL_free(ssl); return NULL; } break; default: - fprintf(stderr, "[TLS] got ssl error code %d\n", want); SSL_free(ssl); return NULL; } } - fprintf(stderr, "[TLS] got TLS connection\n"); return ssl; } @@ -727,8 +714,6 @@ stub_tls_read(SSL* tls_obj, getdns_tcp_state *tcp, struct mem_funcs *mf) uint8_t *buf; size_t buf_size; - fprintf(stderr, "[TLS] method: stub_tls_read\n"); - if (!tcp->read_buf) { /* First time tls read, create a buffer for reading */ if (!(tcp->read_buf = GETDNS_XMALLOC(*mf, uint8_t, 4096))) @@ -750,7 +735,6 @@ stub_tls_read(SSL* tls_obj, getdns_tcp_state *tcp, struct mem_funcs *mf) } else return STUB_TCP_ERROR; } - fprintf(stderr, "[TLS] method: read %d TLS bytes \n", (int)read); tcp->to_read -= read; tcp->read_pos += read; @@ -761,7 +745,6 @@ stub_tls_read(SSL* tls_obj, getdns_tcp_state *tcp, struct mem_funcs *mf) if (read == 2) { /* Read the packet size short */ tcp->to_read = gldns_read_uint16(tcp->read_buf); - fprintf(stderr, "[TLS] method: %d TLS bytes to read \n", (int)tcp->to_read); if (tcp->to_read < GLDNS_HEADER_SIZE) return STUB_TCP_ERROR; @@ -781,7 +764,6 @@ stub_tls_read(SSL* tls_obj, getdns_tcp_state *tcp, struct mem_funcs *mf) } /* Ready to start reading the packet */ - fprintf(stderr, "[TLS] method: resetting read_pos \n"); tcp->read_pos = tcp->read_buf; read = SSL_read(tls_obj, tcp->read_pos, tcp->to_read); if (read <= 0) { @@ -803,7 +785,6 @@ stub_tls_read(SSL* tls_obj, getdns_tcp_state *tcp, struct mem_funcs *mf) static void netreq_upstream_read_cb(void *userarg); static void netreq_upstream_write_cb(void *userarg); -static void upstream_write_cb(void *userarg); static void upstream_read_cb(void *userarg) { @@ -814,8 +795,6 @@ upstream_read_cb(void *userarg) uint16_t query_id; intptr_t query_id_intptr; - fprintf(stderr, "[TLS] method: upstream_read_cb\n"); - if (upstream->tls_obj) q = stub_tls_read(upstream->tls_obj, &upstream->tcp, &upstream->upstreams->mf); @@ -825,7 +804,6 @@ upstream_read_cb(void *userarg) switch (q) { case STUB_TCP_AGAIN: - fprintf(stderr, "[TLS] method: upstream_read_cb -> STUB_TCP_AGAIN\n"); return; case STUB_TCP_ERROR: @@ -833,7 +811,6 @@ upstream_read_cb(void *userarg) return; default: - fprintf(stderr, "[TLS] method: upstream_read_cb -> processing reponse\n"); /* Lookup netreq */ query_id = (uint16_t) q; @@ -851,7 +828,6 @@ upstream_read_cb(void *userarg) netreq->response = upstream->tcp.read_buf; netreq->response_len = upstream->tcp.read_pos - upstream->tcp.read_buf; - netreq->tls_obj = upstream->tls_obj; upstream->tcp.read_buf = NULL; upstream->upstreams->current = 0; @@ -906,7 +882,6 @@ static int stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq) { getdns_dns_req *dnsreq = netreq->owner; - fprintf(stderr, "[TLS] method: stub_tcp_write\n"); size_t pkt_len = netreq->response - netreq->query; ssize_t written; @@ -1045,8 +1020,6 @@ stub_tcp_write_cb(void *userarg) static int stub_tls_write(SSL* tls_obj, getdns_tcp_state *tcp, getdns_network_req *netreq) { - fprintf(stderr, "[TLS] method: stub_tls_write\n"); - size_t pkt_len = netreq->response - netreq->query; ssize_t written; uint16_t query_id; @@ -1100,8 +1073,6 @@ upstream_write_cb(void *userarg) getdns_dns_req *dnsreq = netreq->owner; int q; - fprintf(stderr, "[TLS] method: upstream_write_cb for %s with class %d\n", dnsreq->name, (int)netreq->request_class); - if (upstream->tls_obj) q = stub_tls_write(upstream->tls_obj, &upstream->tcp, netreq); else @@ -1243,7 +1214,6 @@ tcp_connect (getdns_upstream *upstream, getdns_base_transport_t transport) { connect_addr = upstream->addr; addr = &connect_addr; set_port(addr, TLS_PORT); - fprintf(stderr, "[TLS] Forcing switch to port %d for TLS\n", TLS_PORT); } if ((fd = socket(addr->ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) @@ -1271,8 +1241,6 @@ priv_getdns_submit_stub_request(getdns_network_req *netreq) getdns_dns_req *dnsreq = netreq->owner; getdns_upstream *upstream = pick_upstream(dnsreq); - fprintf(stderr, "[TLS] method: priv_getdns_submit_stub_request\n"); - if (!upstream) return GETDNS_RETURN_GENERIC_ERROR; @@ -1325,19 +1293,16 @@ priv_getdns_submit_stub_request(getdns_network_req *netreq) /* We are the first. Make global socket and connect. */ if ((upstream->fd = tcp_connect(upstream, transport)) == -1) { - //TODO: Hum, a reset doesn't make the connect fail... if (fb_transport == NONE) return GETDNS_RETURN_GENERIC_ERROR; - fprintf(stderr, "[TLS] Connect failed on fd... %d\n", upstream->fd); if ((upstream->fd = tcp_connect(upstream, fb_transport)) == -1) return GETDNS_RETURN_GENERIC_ERROR; fallback = 1; } /* Now do a handshake for TLS. Note waiting for this to succeed or - timeout blocks the scheduling of any messages for this upstream*/ + * timeout blocks the scheduling of any messages for this upstream*/ if (transport == TLS && (fallback == 0)) { - fprintf(stderr, "[TLS] Doing SSL handshake... %d\n", upstream->fd); upstream->tls_obj = do_tls_handshake(dnsreq, upstream); if (!upstream->tls_obj) { if (fb_transport == NONE) @@ -1347,6 +1312,10 @@ priv_getdns_submit_stub_request(getdns_network_req *netreq) return GETDNS_RETURN_GENERIC_ERROR; } } + /* Attach to the global event loop + * so it can do it's own scheduling + */ + upstream->loop = dnsreq->context->extension; } else { /* Cater for the case of the user downgrading and existing TLS connection to TCP for some reason...*/ @@ -1358,11 +1327,6 @@ priv_getdns_submit_stub_request(getdns_network_req *netreq) } netreq->upstream = upstream; - /* Attach to the global event loop - * so it can do it's own scheduling - */ - upstream->loop = dnsreq->context->extension; - /* We have a context wide socket. * Now schedule the write request. */ diff --git a/src/types-internal.h b/src/types-internal.h index b961729e..6e4001e6 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -212,7 +212,6 @@ typedef struct getdns_network_req uint8_t *opt; /* offset of OPT RR in query */ size_t response_len; uint8_t *response; - SSL* tls_obj; size_t wire_data_sz; uint8_t wire_data[]; From ab4fb8d9e9bf42f6feafaccf271c4a36b2d5efed Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Fri, 17 Apr 2015 15:50:08 +0100 Subject: [PATCH 03/10] Enable GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN for libunbound. Should only be used in stub mode. GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN still just does TCP. Also some tidy up of new transport types. --- src/context.c | 68 ++++++++++++++++++++++++++++++++++++------------ src/context.h | 11 ++++++++ src/stub.c | 71 +++++++++++++-------------------------------------- 3 files changed, 80 insertions(+), 70 deletions(-) diff --git a/src/context.c b/src/context.c index 961ea8f9..77fe07df 100644 --- a/src/context.c +++ b/src/context.c @@ -521,7 +521,8 @@ upstream_scope_id(getdns_upstream *upstream) } static void -upstream_ntop_buf(getdns_upstream *upstream, char *buf, size_t len) +upstream_ntop_buf(getdns_upstream *upstream, getdns_transport_t transport, + char *buf, size_t len) { /* Also possible but prints scope_id by name (nor parsed by unbound) * @@ -533,9 +534,14 @@ upstream_ntop_buf(getdns_upstream *upstream, char *buf, size_t len) if (upstream_scope_id(upstream)) (void) snprintf(buf + strlen(buf), len - strlen(buf), "%%%d", (int)*upstream_scope_id(upstream)); - if (upstream_port(upstream) != 53 && upstream_port(upstream) != 0) + if (transport == GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN) (void) snprintf(buf + strlen(buf), len - strlen(buf), - "@%d", (int)upstream_port(upstream)); + "@%d", GETDNS_TLS_PORT); + else { + if (upstream_port(upstream) != 53 && upstream_port(upstream) != 0) + (void) snprintf(buf + strlen(buf), len - strlen(buf), + "@%d", (int)upstream_port(upstream)); + } } static int @@ -809,6 +815,9 @@ getdns_context_create_with_extended_memory_functions( result->return_dnssec_status = GETDNS_EXTENSION_FALSE; /* unbound context is initialized here */ + /* Unbound needs SSL to be init'ed this early when TLS is used. However we + * don't know that till later so we will have to do this every time. */ + SSL_library_init(); result->unbound_ctx = NULL; if ((r = rebuild_ub_ctx(result))) goto error; @@ -1125,6 +1134,33 @@ getdns_context_set_namespaces(struct getdns_context *context, return GETDNS_RETURN_GOOD; } /* getdns_context_set_namespaces */ +getdns_transport_t +priv_get_transport(getdns_transport_t transport, int level) { + if (!(level == 0 || level == 1)) return GETDNS_TRANSPORT_NONE; + switch (transport) { + case GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP: + if (level == 0) return GETDNS_TRANSPORT_UDP; + if (level == 1) return GETDNS_TRANSPORT_TCP; + case GETDNS_TRANSPORT_UDP_ONLY: + if (level == 0) return GETDNS_TRANSPORT_UDP; + if (level == 1) return GETDNS_TRANSPORT_NONE; + case GETDNS_TRANSPORT_TCP_ONLY: + if (level == 0) return GETDNS_TRANSPORT_TCP_SINGLE; + if (level == 1) return GETDNS_TRANSPORT_NONE; + case GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN: + if (level == 0) return GETDNS_TRANSPORT_TCP; + if (level == 1) return GETDNS_TRANSPORT_NONE; + case GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN: + if (level == 0) return GETDNS_TRANSPORT_TLS; + if (level == 1) return GETDNS_TRANSPORT_NONE; + case GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN: + if (level == 0) return GETDNS_TRANSPORT_TLS; + if (level == 1) return GETDNS_TRANSPORT_TCP; + default: + return GETDNS_TRANSPORT_NONE; + } +} + static getdns_return_t set_ub_dns_transport(struct getdns_context* context, getdns_transport_t value) { @@ -1138,22 +1174,22 @@ set_ub_dns_transport(struct getdns_context* context, set_ub_string_opt(context, "do-tcp:", "no"); break; case GETDNS_TRANSPORT_TCP_ONLY: + /* Note: no pipelining available directly in unbound.*/ case GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN: set_ub_string_opt(context, "do-udp:", "no"); set_ub_string_opt(context, "do-tcp:", "yes"); break; case GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN: + /* Hum. If used in recursive mode this will try TLS on port 53... + * So we need to fix or document that or delay setting it until + * resolution.*/ + set_ub_string_opt(context, "ssl-upstream:", "yes"); + /* Fall through*/ case GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN: - /* TODO: Investigate why ssl-upstream in Unbound isn't working (error - * that the SSL lib isn't init'ed but that is done in prep_for_res. - * Note: no fallback or pipelining available directly in unbound.*/ + /* Note: no fallback to TCP available directly in unbound, so we just + * use TCP for now to make sure the messages are sent. */ set_ub_string_opt(context, "do-udp:", "no"); set_ub_string_opt(context, "do-tcp:", "yes"); - /* set_ub_string_opt(context, "ssl-upstream:", "yes");*/ - /* TODO: Specifying a different port to do TLS on in unbound is a bit - * tricky as it involves modifying each fwd upstream defined on the - * unbound ctx... And to support fallback this would have to be reset - * from the stub code while trying to connect...*/ break; default: return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; @@ -1695,17 +1731,18 @@ getdns_cancel_callback(getdns_context *context, } /* getdns_cancel_callback */ static getdns_return_t -ub_setup_stub(struct ub_ctx *ctx, getdns_upstreams *upstreams) +ub_setup_stub(struct ub_ctx *ctx, struct getdns_context *context) { getdns_return_t r = GETDNS_RETURN_GOOD; size_t i; getdns_upstream *upstream; char addr[1024]; + getdns_upstreams *upstreams = context->upstreams; (void) ub_ctx_set_fwd(ctx, NULL); for (i = 0; i < upstreams->count; i++) { upstream = &upstreams->upstreams[i]; - upstream_ntop_buf(upstream, addr, 1024); + upstream_ntop_buf(upstream, context->dns_transport, addr, 1024); ub_ctx_set_fwd(ctx, addr); } @@ -1777,7 +1814,7 @@ priv_getdns_ns_dns_setup(struct getdns_context *context) case GETDNS_RESOLUTION_STUB: if (!context->upstreams || !context->upstreams->count) return GETDNS_RETURN_GENERIC_ERROR; - return ub_setup_stub(context->unbound_ctx, context->upstreams); + return ub_setup_stub(context->unbound_ctx, context); case GETDNS_RESOLUTION_RECURSING: /* TODO: use the root servers via root hints file */ @@ -1805,9 +1842,6 @@ getdns_context_prepare_for_resolution(struct getdns_context *context, case GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN: case GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN: if (context->tls_ctx == NULL) { - /* Init the SSL library */ - SSL_library_init(); - /* Create client context, use TLS v1.2 only for now */ SSL_CTX* tls_ctx = SSL_CTX_new(TLSv1_2_client_method()); if(!tls_ctx) { diff --git a/src/context.h b/src/context.h index 816c068b..a9b23317 100644 --- a/src/context.h +++ b/src/context.h @@ -49,6 +49,7 @@ struct ub_ctx; #define GETDNS_FN_RESOLVCONF "/etc/resolv.conf" #define GETDNS_FN_HOSTS "/etc/hosts" +#define GETDNS_TLS_PORT 1021 enum filechgs { GETDNS_FCHG_ERRORS = -1 , GETDNS_FCHG_NOERROR = 0 @@ -71,6 +72,14 @@ struct filechg { struct stat *prevstat; }; +typedef enum getdns_base_transport { + GETDNS_TRANSPORT_NONE, + GETDNS_TRANSPORT_UDP, + GETDNS_TRANSPORT_TCP_SINGLE, + GETDNS_TRANSPORT_TCP, + GETDNS_TRANSPORT_TLS +} getdns_base_transport_t; + typedef struct getdns_upstream { struct getdns_upstreams *upstreams; @@ -222,4 +231,6 @@ int filechg_check(struct getdns_context *context, struct filechg *fchg); void priv_getdns_context_ub_read_cb(void *userarg); +getdns_transport_t priv_get_transport(getdns_transport_t transport, int level); + #endif /* _GETDNS_CONTEXT_H_ */ diff --git a/src/stub.c b/src/stub.c index 0d8610c4..72c00faf 100755 --- a/src/stub.c +++ b/src/stub.c @@ -41,8 +41,6 @@ #include "util-internal.h" #include "general.h" -#define TLS_PORT 1021 - static time_t secret_rollover_time = 0; static uint32_t secret = 0; static uint32_t prev_secret = 0; @@ -656,7 +654,7 @@ sock_connected(int sockfd) /* The connection testing and handshake should be handled by integrating this * with the event loop framework, but for now just implement a standalone * handshake method.*/ -SSL* +static SSL* do_tls_handshake(getdns_dns_req *dnsreq, getdns_upstream *upstream) { /*Lets make sure the connection is up before we try a handshake*/ @@ -1158,7 +1156,7 @@ get_port(struct sockaddr_storage* addr) : ((struct sockaddr_in6*)addr)->sin6_port); } -void +static void set_port(struct sockaddr_storage* addr, in_port_t port) { addr->ss_family == AF_INET @@ -1166,42 +1164,7 @@ set_port(struct sockaddr_storage* addr, in_port_t port) : (((struct sockaddr_in6*)addr)->sin6_port = htons(port)); } -typedef enum getdns_base_transport { - NONE, - UDP, - TCP_SINGLE, - TCP, - TLS -} getdns_base_transport_t; - -getdns_transport_t -get_transport(getdns_transport_t transport, int level) { - if (!(level == 0 || level == 1)) return NONE; - switch (transport) { - case GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP: - if (level == 0) return UDP; - if (level == 1) return TCP; - case GETDNS_TRANSPORT_UDP_ONLY: - if (level == 0) return UDP; - if (level == 1) return NONE; - case GETDNS_TRANSPORT_TCP_ONLY: - if (level == 0) return TCP_SINGLE; - if (level == 1) return NONE; - case GETDNS_TRANSPORT_TCP_ONLY_KEEP_CONNECTIONS_OPEN: - if (level == 0) return TCP; - if (level == 1) return NONE; - case GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN: - if (level == 0) return TLS; - if (level == 1) return NONE; - case GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN: - if (level == 0) return TLS; - if (level == 1) return TCP; - default: - return NONE; - } -} - -int +static int tcp_connect (getdns_upstream *upstream, getdns_base_transport_t transport) { int fd =-1; @@ -1210,10 +1173,11 @@ tcp_connect (getdns_upstream *upstream, getdns_base_transport_t transport) { socklen_t addr_len = upstream->addr_len; /* TODO[TLS]: For now, override the port to a hardcoded value*/ - if (transport == TLS && (int)get_port(addr) != TLS_PORT) { + if (transport == GETDNS_TRANSPORT_TLS && + (int)get_port(addr) != GETDNS_TLS_PORT) { connect_addr = upstream->addr; addr = &connect_addr; - set_port(addr, TLS_PORT); + set_port(addr, GETDNS_TLS_PORT); } if ((fd = socket(addr->ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) @@ -1222,7 +1186,8 @@ tcp_connect (getdns_upstream *upstream, getdns_base_transport_t transport) { getdns_sock_nonblock(fd); #ifdef USE_TCP_FASTOPEN /* Leave the connect to the later call to sendto() if using TCP*/ - if (transport == TCP || transport == TCP_SINGLE) + if (transport == GETDNS_TRANSPORT_TCP || + transport == GETDNS_TRANSPORT_TCP_SINGLE) return fd; #endif if (connect(fd, (struct sockaddr *)addr, @@ -1245,12 +1210,12 @@ priv_getdns_submit_stub_request(getdns_network_req *netreq) return GETDNS_RETURN_GENERIC_ERROR; // Work out the primary and fallback transport options - getdns_base_transport_t transport = get_transport( + getdns_base_transport_t transport = priv_get_transport( dnsreq->context->dns_transport,0); - getdns_base_transport_t fb_transport = get_transport( + getdns_base_transport_t fb_transport = priv_get_transport( dnsreq->context->dns_transport,1); switch(transport) { - case UDP: + case GETDNS_TRANSPORT_UDP: if ((netreq->fd = socket( upstream->addr.ss_family, SOCK_DGRAM, IPPROTO_UDP)) == -1) @@ -1266,7 +1231,7 @@ priv_getdns_submit_stub_request(getdns_network_req *netreq) return GETDNS_RETURN_GOOD; - case TCP_SINGLE: + case GETDNS_TRANSPORT_TCP_SINGLE: if ((netreq->fd = tcp_connect(upstream, transport)) == -1) return GETDNS_RETURN_GENERIC_ERROR; @@ -1279,8 +1244,8 @@ priv_getdns_submit_stub_request(getdns_network_req *netreq) return GETDNS_RETURN_GOOD; - case TCP: - case TLS: + case GETDNS_TRANSPORT_TCP: + case GETDNS_TRANSPORT_TLS: /* In coming comments, "global" means "context wide" */ @@ -1293,7 +1258,7 @@ priv_getdns_submit_stub_request(getdns_network_req *netreq) /* We are the first. Make global socket and connect. */ if ((upstream->fd = tcp_connect(upstream, transport)) == -1) { - if (fb_transport == NONE) + if (fb_transport == GETDNS_TRANSPORT_NONE) return GETDNS_RETURN_GENERIC_ERROR; if ((upstream->fd = tcp_connect(upstream, fb_transport)) == -1) return GETDNS_RETURN_GENERIC_ERROR; @@ -1302,10 +1267,10 @@ priv_getdns_submit_stub_request(getdns_network_req *netreq) /* Now do a handshake for TLS. Note waiting for this to succeed or * timeout blocks the scheduling of any messages for this upstream*/ - if (transport == TLS && (fallback == 0)) { + if (transport == GETDNS_TRANSPORT_TLS && (fallback == 0)) { upstream->tls_obj = do_tls_handshake(dnsreq, upstream); if (!upstream->tls_obj) { - if (fb_transport == NONE) + if (fb_transport == GETDNS_TRANSPORT_NONE) return GETDNS_RETURN_GENERIC_ERROR; close(upstream->fd); if ((upstream->fd = tcp_connect(upstream, fb_transport)) == -1) @@ -1319,7 +1284,7 @@ priv_getdns_submit_stub_request(getdns_network_req *netreq) } else { /* Cater for the case of the user downgrading and existing TLS connection to TCP for some reason...*/ - if (transport == TCP && upstream->tls_obj) { + if (transport == GETDNS_TRANSPORT_TCP && upstream->tls_obj) { SSL_shutdown(upstream->tls_obj); SSL_free(upstream->tls_obj); upstream->tls_obj = NULL; From 6c7ffc4e4ecbffbe148fea6e1b7d2cdf75d49104 Mon Sep 17 00:00:00 2001 From: Sara Dickinson Date: Fri, 17 Apr 2015 18:38:13 +0100 Subject: [PATCH 04/10] 1) Fix enum mapping error. 2) Also add detection of TLS 1.2 in openssl during configure and warn that it if not available then TLS will not be available. Using TLS_ONLY in stub mode will then error with BAD_CONTEXT. TLS/TCP will fallback to TCP. 3) Explicitly disallow use of TLS_ONLY in RECURSIVE mode since it isn't supported yet. TLS/TCP will fallback to TCP. 4) Fix for MAC OS X build where openssl not linked correctly --- m4/acx_openssl.m4 | 6 ++++-- src/context.c | 17 ++++++++++++----- src/context.h | 2 +- src/stub.c | 6 ++++-- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/m4/acx_openssl.m4 b/m4/acx_openssl.m4 index 68e40f38..87507dce 100644 --- a/m4/acx_openssl.m4 +++ b/m4/acx_openssl.m4 @@ -48,8 +48,8 @@ AC_DEFUN([ACX_SSL_CHECKS], [ fi AC_MSG_CHECKING([for HMAC_CTX_init in -lcrypto]) - LIBS="$LIBS -lcrypto" - LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto" + LIBS="$LIBS -lcrypto -lssl" + LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto -lssl" AC_TRY_LINK(, [ int HMAC_CTX_init(void); (void)HMAC_CTX_init(); @@ -105,6 +105,8 @@ AC_DEFUN([ACX_SSL_CHECKS], [ AC_CHECK_HEADERS([openssl/ssl.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([openssl/err.h],,, [AC_INCLUDES_DEFAULT]) AC_CHECK_HEADERS([openssl/rand.h],,, [AC_INCLUDES_DEFAULT]) +AC_CHECK_LIB(ssl, TLSv1_2_client_method,AC_DEFINE([HAVE_LIBTLS1_2], [1], + [Define if you have libssl with tls 1.2]),[AC_MSG_WARN([Cannot find TLSv1_2_client_method in libssl library. TLS will not be available.])]) ])dnl End of ACX_SSL_CHECKS dnl Check for SSL, where SSL is mandatory diff --git a/src/context.c b/src/context.c index 77fe07df..1c6caddd 100644 --- a/src/context.c +++ b/src/context.c @@ -1134,8 +1134,8 @@ getdns_context_set_namespaces(struct getdns_context *context, return GETDNS_RETURN_GOOD; } /* getdns_context_set_namespaces */ -getdns_transport_t -priv_get_transport(getdns_transport_t transport, int level) { +getdns_base_transport_t +priv_get_base_transport(getdns_transport_t transport, int level) { if (!(level == 0 || level == 1)) return GETDNS_TRANSPORT_NONE; switch (transport) { case GETDNS_TRANSPORT_UDP_FIRST_AND_FALL_BACK_TO_TCP: @@ -1837,23 +1837,30 @@ getdns_context_prepare_for_resolution(struct getdns_context *context, } /* Transport can in theory be set per query in stub mode */ + /* TODO: move this transport logic to a separate functions*/ if (context->resolution_type == GETDNS_RESOLUTION_STUB) { switch (context->dns_transport) { case GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN: case GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN: if (context->tls_ctx == NULL) { +#ifdef HAVE_LIBTLS1_2 /* Create client context, use TLS v1.2 only for now */ - SSL_CTX* tls_ctx = SSL_CTX_new(TLSv1_2_client_method()); - if(!tls_ctx) { + context->tls_ctx = SSL_CTX_new(TLSv1_2_client_method()); +#endif + if(!context->tls_ctx && context->dns_transport == + GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN) { return GETDNS_RETURN_BAD_CONTEXT; } - context->tls_ctx = tls_ctx; } break; default: break; } } + /* Block use of TLS ONLY in recursive mode as it won't work */ + if (context->resolution_type == GETDNS_RESOLUTION_RECURSING + && context->dns_transport == GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN) + return GETDNS_RETURN_BAD_CONTEXT; if (context->resolution_type_set == context->resolution_type) /* already set and no config changes diff --git a/src/context.h b/src/context.h index a9b23317..569d42c5 100644 --- a/src/context.h +++ b/src/context.h @@ -231,6 +231,6 @@ int filechg_check(struct getdns_context *context, struct filechg *fchg); void priv_getdns_context_ub_read_cb(void *userarg); -getdns_transport_t priv_get_transport(getdns_transport_t transport, int level); +getdns_base_transport_t priv_get_base_transport(getdns_transport_t transport, int level); #endif /* _GETDNS_CONTEXT_H_ */ diff --git a/src/stub.c b/src/stub.c index 72c00faf..0914aa57 100755 --- a/src/stub.c +++ b/src/stub.c @@ -663,6 +663,8 @@ do_tls_handshake(getdns_dns_req *dnsreq, getdns_upstream *upstream) } /* Create SSL instance */ + if (dnsreq->context->tls_ctx == NULL) + return NULL; SSL* ssl = SSL_new(dnsreq->context->tls_ctx); if(!ssl) { return NULL; @@ -1210,9 +1212,9 @@ priv_getdns_submit_stub_request(getdns_network_req *netreq) return GETDNS_RETURN_GENERIC_ERROR; // Work out the primary and fallback transport options - getdns_base_transport_t transport = priv_get_transport( + getdns_base_transport_t transport = priv_get_base_transport( dnsreq->context->dns_transport,0); - getdns_base_transport_t fb_transport = priv_get_transport( + getdns_base_transport_t fb_transport = priv_get_base_transport( dnsreq->context->dns_transport,1); switch(transport) { case GETDNS_TRANSPORT_UDP: From b26f09d1aac102c2334eb694be2776c91f8d2286 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sat, 18 Apr 2015 09:35:46 +0200 Subject: [PATCH 05/10] autoreconf -if # For convenience... --- configure | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- src/config.h.in | 3 +++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/configure b/configure index f404ad66..5c7c0b18 100755 --- a/configure +++ b/configure @@ -11333,8 +11333,8 @@ $as_echo "found in $ssldir" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for HMAC_CTX_init in -lcrypto" >&5 $as_echo_n "checking for HMAC_CTX_init in -lcrypto... " >&6; } - LIBS="$LIBS -lcrypto" - LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto" + LIBS="$LIBS -lcrypto -lssl" + LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto -lssl" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -11543,6 +11543,51 @@ fi done +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for TLSv1_2_client_method in -lssl" >&5 +$as_echo_n "checking for TLSv1_2_client_method in -lssl... " >&6; } +if ${ac_cv_lib_ssl_TLSv1_2_client_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lssl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char TLSv1_2_client_method (); +int +main () +{ +return TLSv1_2_client_method (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ssl_TLSv1_2_client_method=yes +else + ac_cv_lib_ssl_TLSv1_2_client_method=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_TLSv1_2_client_method" >&5 +$as_echo "$ac_cv_lib_ssl_TLSv1_2_client_method" >&6; } +if test "x$ac_cv_lib_ssl_TLSv1_2_client_method" = xyes; then : + +$as_echo "#define HAVE_LIBTLS1_2 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find TLSv1_2_client_method in libssl library. TLS will not be available." >&5 +$as_echo "$as_me: WARNING: Cannot find TLSv1_2_client_method in libssl library. TLS will not be available." >&2;} +fi + diff --git a/src/config.h.in b/src/config.h.in index c6d368fd..1c458b61 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -84,6 +84,9 @@ /* Define to 1 if you have the `ldns' library (-lldns). */ #undef HAVE_LIBLDNS +/* Define if you have libssl with tls 1.2 */ +#undef HAVE_LIBTLS1_2 + /* Define to 1 if you have the `unbound' library (-lunbound). */ #undef HAVE_LIBUNBOUND From 84c5b67ee0f3ee575f64091c325a97e2b6a76986 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sat, 18 Apr 2015 09:53:50 +0200 Subject: [PATCH 06/10] Re-enable printing of json with getdns_query --- src/test/getdns_query.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/test/getdns_query.c b/src/test/getdns_query.c index 3fc27ffe..abe21529 100644 --- a/src/test/getdns_query.c +++ b/src/test/getdns_query.c @@ -125,7 +125,6 @@ print_usage(FILE *out, const char *progname) fprintf(out, "\t-U\tSet transport to UDP only\n"); fprintf(out, "\t-B\tBatch mode. Schedule all messages before processing responses.\n"); fprintf(out, "\t-q\tQuiet mode - don't print response\n"); - fprintf(out, "\t+sit[=cookie]\tSet edns cookie\n"); } void callback(getdns_context *context, getdns_callback_type_t callback_type, @@ -135,14 +134,12 @@ void callback(getdns_context *context, getdns_callback_type_t callback_type, if (callback_type == GETDNS_CALLBACK_COMPLETE) { /* This is a callback with data */; - if (!quiet) { - if (json) - response_str = getdns_print_json_dict( - response, json == 1); - else if ((response_str = getdns_pretty_print_dict(response))) { - fprintf(stdout, "ASYNC response:\n%s\n", response_str); - free(response_str); - } + if (!quiet && (response_str = json ? + getdns_print_json_dict(response, json == 1) + : getdns_pretty_print_dict(response))) { + + fprintf(stdout, "ASYNC response:\n%s\n", response_str); + free(response_str); } fprintf(stderr, "The callback with ID %llu was successfull.\n", @@ -156,6 +153,7 @@ void callback(getdns_context *context, getdns_callback_type_t callback_type, fprintf(stderr, "The callback got a callback_type of %d. Exiting.\n", callback_type); + getdns_dict_destroy(response); response = NULL; } @@ -527,15 +525,17 @@ main(int argc, char **argv) if (r) goto done_destroy_extensions; if (!quiet) { - if (json) - response_str = getdns_print_json_dict( - response, json == 1); - else if ((response_str = getdns_pretty_print_dict(response))) { - fprintf(stdout, "SYNC response:\n%s\n", response_str); + if ((response_str = json ? + getdns_print_json_dict(response, json == 1) + : getdns_pretty_print_dict(response))) { + + fprintf( stdout, "SYNC response:\n%s\n" + , response_str); free(response_str); } else { r = GETDNS_RETURN_MEMORY_ERROR; - fprintf(stderr, "Could not print response\n"); + fprintf( stderr + , "Could not print response\n"); } } else if (r == GETDNS_RETURN_GOOD) fprintf(stdout, "Response code was: GOOD\n"); From 0ba6af352394fc6df8393ea7c9519ba148767311 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sat, 18 Apr 2015 22:17:28 +0200 Subject: [PATCH 07/10] upstreams_cleanup from upstreams_dereference --- src/context.c | 77 ++++++++++++++++++------------------------ src/context.h | 2 ++ src/request-internal.c | 3 +- 3 files changed, 36 insertions(+), 46 deletions(-) diff --git a/src/context.c b/src/context.c index 1c6caddd..45e4b472 100644 --- a/src/context.c +++ b/src/context.c @@ -470,29 +470,22 @@ upstreams_resize(getdns_upstreams *upstreams, size_t size) return r; } -static void -upstreams_cleanup(getdns_upstreams *upstreams) +void +priv_getdns_upstreams_dereference(getdns_upstreams *upstreams) { - if (!upstreams) - return; - for (int i = 0; i < (int)upstreams->count; i++) { - if (upstreams->upstreams[i].tls_obj != NULL) { - SSL_shutdown(upstreams->upstreams[i].tls_obj); - SSL_free(upstreams->upstreams[i].tls_obj); - upstreams->upstreams[i].tls_obj = NULL; - } - if (upstreams->upstreams[i].fd != -1) { - close(upstreams->upstreams[i].fd); - upstreams->upstreams[i].fd = -1; - } - } -} + size_t i; -static void -upstreams_dereference(getdns_upstreams *upstreams) -{ - if (upstreams && --upstreams->referenced == 0) + if (upstreams && --upstreams->referenced == 0) { + for (i = 0; i < upstreams->count; i++) { + if (upstreams->upstreams[i].tls_obj != NULL) { + SSL_shutdown(upstreams->upstreams[i].tls_obj); + SSL_free(upstreams->upstreams[i].tls_obj); + } + if (upstreams->upstreams[i].fd != -1) + close(upstreams->upstreams[i].fd); + } GETDNS_FREE(upstreams->mf, upstreams); + } } static uint8_t* @@ -537,11 +530,9 @@ upstream_ntop_buf(getdns_upstream *upstream, getdns_transport_t transport, if (transport == GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN) (void) snprintf(buf + strlen(buf), len - strlen(buf), "@%d", GETDNS_TLS_PORT); - else { - if (upstream_port(upstream) != 53 && upstream_port(upstream) != 0) - (void) snprintf(buf + strlen(buf), len - strlen(buf), - "@%d", (int)upstream_port(upstream)); - } + else if (upstream_port(upstream) != 53 && upstream_port(upstream) != 0) + (void) snprintf(buf + strlen(buf), len - strlen(buf), + "@%d", (int)upstream_port(upstream)); } static int @@ -919,8 +910,7 @@ getdns_context_destroy(struct getdns_context *context) getdns_traverse_postorder(&context->local_hosts, destroy_local_host, context); - upstreams_cleanup(context->upstreams); - upstreams_dereference(context->upstreams); + priv_getdns_upstreams_dereference(context->upstreams); GETDNS_FREE(context->my_mf, context); } /* getdns_context_destroy */ @@ -1524,8 +1514,7 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context, upstreams->count++; freeaddrinfo(ai); } - upstreams_dereference(context->upstreams); - /*Don't the existing upstreams need to be handled before overwritting here?*/ + priv_getdns_upstreams_dereference(context->upstreams); context->upstreams = upstreams; dispatch_updated(context, GETDNS_CONTEXT_CODE_UPSTREAM_RECURSIVE_SERVERS); @@ -1535,7 +1524,7 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context, invalid_parameter: r = GETDNS_RETURN_INVALID_PARAMETER; error: - upstreams_dereference(upstreams); + priv_getdns_upstreams_dereference(upstreams); return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; } /* getdns_context_set_upstream_recursive_servers */ @@ -1731,14 +1720,14 @@ getdns_cancel_callback(getdns_context *context, } /* getdns_cancel_callback */ static getdns_return_t -ub_setup_stub(struct ub_ctx *ctx, struct getdns_context *context) +ub_setup_stub(struct ub_ctx *ctx, getdns_context *context) { getdns_return_t r = GETDNS_RETURN_GOOD; size_t i; getdns_upstream *upstream; char addr[1024]; - getdns_upstreams *upstreams = context->upstreams; + (void) ub_ctx_set_fwd(ctx, NULL); for (i = 0; i < upstreams->count; i++) { upstream = &upstreams->upstreams[i]; @@ -1840,21 +1829,21 @@ getdns_context_prepare_for_resolution(struct getdns_context *context, /* TODO: move this transport logic to a separate functions*/ if (context->resolution_type == GETDNS_RESOLUTION_STUB) { switch (context->dns_transport) { - case GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN: - case GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN: - if (context->tls_ctx == NULL) { + case GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN: + case GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN: + if (context->tls_ctx == NULL) { #ifdef HAVE_LIBTLS1_2 - /* Create client context, use TLS v1.2 only for now */ - context->tls_ctx = SSL_CTX_new(TLSv1_2_client_method()); + /* Create client context, use TLS v1.2 only for now */ + context->tls_ctx = SSL_CTX_new(TLSv1_2_client_method()); #endif - if(!context->tls_ctx && context->dns_transport == - GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN) { - return GETDNS_RETURN_BAD_CONTEXT; - } + if(!context->tls_ctx && context->dns_transport == + GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN) { + return GETDNS_RETURN_BAD_CONTEXT; } - break; - default: - break; + } + break; + default: + break; } } /* Block use of TLS ONLY in recursive mode as it won't work */ diff --git a/src/context.h b/src/context.h index 569d42c5..12a2c263 100644 --- a/src/context.h +++ b/src/context.h @@ -233,4 +233,6 @@ void priv_getdns_context_ub_read_cb(void *userarg); getdns_base_transport_t priv_get_base_transport(getdns_transport_t transport, int level); +void priv_getdns_upstreams_dereference(getdns_upstreams *upstreams); + #endif /* _GETDNS_CONTEXT_H_ */ diff --git a/src/request-internal.c b/src/request-internal.c index 99e5c7d6..0889b3fc 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -177,8 +177,7 @@ dns_req_free(getdns_dns_req * req) return; } - if (req->upstreams && --req->upstreams->referenced == 0) - GETDNS_FREE(req->upstreams->mf, req->upstreams); + priv_getdns_upstreams_dereference(req->upstreams); /* cleanup network requests */ for (net_req = req->netreqs; *net_req; net_req++) From 2a6fc74314afc361ea37a3755e23ec827a29e9e3 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sat, 18 Apr 2015 22:30:56 +0200 Subject: [PATCH 08/10] netinet/in.h and openssl/ssl.h from config.h --- configure.ac | 4 ++++ src/config.h.in | 4 ++++ src/types-internal.h | 2 -- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 141633c2..74d0f527 100755 --- a/configure.ac +++ b/configure.ac @@ -741,6 +741,10 @@ unsigned char *SHA512(void* data, unsigned int data_len, unsigned char *digest); #include #endif +#ifdef HAVE_OPENSSL_SSL_H +#include +#endif + #ifdef HAVE_ATTR_FORMAT # define ATTR_FORMAT(archetype, string_index, first_to_check) \ __attribute__ ((format (archetype, string_index, first_to_check))) diff --git a/src/config.h.in b/src/config.h.in index 1c458b61..c6e67fae 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -323,6 +323,10 @@ unsigned char *SHA512(void* data, unsigned int data_len, unsigned char *digest); #include #endif +#ifdef HAVE_OPENSSL_SSL_H +#include +#endif + #ifdef HAVE_ATTR_FORMAT # define ATTR_FORMAT(archetype, string_index, first_to_check) \ __attribute__ ((format (archetype, string_index, first_to_check))) diff --git a/src/types-internal.h b/src/types-internal.h index 6e4001e6..5220d599 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -36,8 +36,6 @@ #ifndef TYPES_INTERNAL_H_ #define TYPES_INTERNAL_H_ -#include -#include #include "getdns/getdns.h" #include "getdns/getdns_extra.h" #include "util/rbtree.h" From 034150cb42ec671a91152ec42b13a58155ed0578 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sun, 19 Apr 2015 21:36:24 +0200 Subject: [PATCH 09/10] Bump version & update ChangeLog for 0.1.8 release --- ChangeLog | 5 +++++ configure | 23 ++++++++++++----------- configure.ac | 5 +++-- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4b3802f1..53a43bb4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +* 2015-04-19: Version 0.1.8 + * The GETDNS_TRANSPORT_TLS_ONLY_KEEP_CONNECTIONS_OPEN and + GETDNS_TRANSPORT_TLS_FIRST_AND_FALL_BACK_TO_TCP_KEEP_CONNECTIONS_OPEN + DNS over TLS transport options. + * 2015-04-08: Version 0.1.7 * Individual getter functions for context settings * Fix: --with-current-date function to make build deterministically diff --git a/configure b/configure index 5c7c0b18..acb71ec3 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for getdns 0.1.7. +# Generated by GNU Autoconf 2.69 for getdns 0.1.8. # # Report bugs to . # @@ -590,8 +590,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='getdns' PACKAGE_TARNAME='getdns' -PACKAGE_VERSION='0.1.7' -PACKAGE_STRING='getdns 0.1.7' +PACKAGE_VERSION='0.1.8' +PACKAGE_STRING='getdns 0.1.8' PACKAGE_BUGREPORT='stub-resolver@verisignlabs.com' PACKAGE_URL='http://getdnsapi.net' @@ -1323,7 +1323,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures getdns 0.1.7 to adapt to many kinds of systems. +\`configure' configures getdns 0.1.8 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1388,7 +1388,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of getdns 0.1.7:";; + short | recursive ) echo "Configuration of getdns 0.1.8:";; esac cat <<\_ACEOF @@ -1519,7 +1519,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -getdns configure 0.1.7 +getdns configure 0.1.8 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2008,7 +2008,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by getdns $as_me 0.1.7, which was +It was created by getdns $as_me 0.1.8, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2367,7 +2367,7 @@ else CURRENT_DATE="`date -u +%Y-%m-%dT%H:%M:%SZ`" fi -GETDNS_COMPILATION_COMMENT="getdns 0.1.7 configured on $CURRENT_DATE for the January 2015 version of the API" +GETDNS_COMPILATION_COMMENT="getdns 0.1.8 configured on $CURRENT_DATE for the January 2015 version of the API" # Library version # --------------- @@ -2388,8 +2388,9 @@ GETDNS_COMPILATION_COMMENT="getdns 0.1.7 configured on $CURRENT_DATE for the Jan # getdns-0.1.5 had libversion 1:0:0 # getdns-0.1.6 had libversion 1:1:0 # getdns-0.1.7 will have libversion 1:2:1 +# getdns-0.1.8 will have libversion 1:3:2 # -GETDNS_LIBVERSION=1:2:1 +GETDNS_LIBVERSION=1:3:2 @@ -14322,7 +14323,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by getdns $as_me 0.1.7, which was +This file was extended by getdns $as_me 0.1.8, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -14389,7 +14390,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -getdns config.status 0.1.7 +getdns config.status 0.1.8 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 74d0f527..c7dcf349 100755 --- a/configure.ac +++ b/configure.ac @@ -31,7 +31,7 @@ AC_PREREQ([2.56]) -AC_INIT([getdns], [0.1.7], [stub-resolver@verisignlabs.com], [], [http://getdnsapi.net]) +AC_INIT([getdns], [0.1.8], [stub-resolver@verisignlabs.com], [], [http://getdnsapi.net]) AC_SUBST(RELEASE_CANDIDATE, []) # Set current date from system if not set @@ -61,8 +61,9 @@ GETDNS_COMPILATION_COMMENT="AC_PACKAGE_STRING configured on $CURRENT_DATE for th # getdns-0.1.5 had libversion 1:0:0 # getdns-0.1.6 had libversion 1:1:0 # getdns-0.1.7 will have libversion 1:2:1 +# getdns-0.1.8 will have libversion 1:3:2 # -GETDNS_LIBVERSION=1:2:1 +GETDNS_LIBVERSION=1:3:2 AC_SUBST(GETDNS_COMPILATION_COMMENT) AC_SUBST(GETDNS_LIBVERSION) From 6d4c0afdebd124925458136688a9c1244eafdc8a Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Sun, 19 Apr 2015 22:07:11 +0200 Subject: [PATCH 10/10] Correct library version bump Also the mistake in the last version --- configure | 6 +++--- configure.ac | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/configure b/configure index acb71ec3..490c4ac9 100755 --- a/configure +++ b/configure @@ -2387,10 +2387,10 @@ GETDNS_COMPILATION_COMMENT="getdns 0.1.8 configured on $CURRENT_DATE for the Jan # getdns-0.1.4 had libversion 0:0:0 # getdns-0.1.5 had libversion 1:0:0 # getdns-0.1.6 had libversion 1:1:0 -# getdns-0.1.7 will have libversion 1:2:1 -# getdns-0.1.8 will have libversion 1:3:2 +# getdns-0.1.7 had libversion 1:2:1 +# getdns-0.1.8 will have libversion 1:3:0 # -GETDNS_LIBVERSION=1:3:2 +GETDNS_LIBVERSION=1:3:0 diff --git a/configure.ac b/configure.ac index c7dcf349..6e98e01f 100755 --- a/configure.ac +++ b/configure.ac @@ -60,10 +60,10 @@ GETDNS_COMPILATION_COMMENT="AC_PACKAGE_STRING configured on $CURRENT_DATE for th # getdns-0.1.4 had libversion 0:0:0 # getdns-0.1.5 had libversion 1:0:0 # getdns-0.1.6 had libversion 1:1:0 -# getdns-0.1.7 will have libversion 1:2:1 -# getdns-0.1.8 will have libversion 1:3:2 +# getdns-0.1.7 had libversion 1:2:1 +# getdns-0.1.8 will have libversion 1:3:0 # -GETDNS_LIBVERSION=1:3:2 +GETDNS_LIBVERSION=1:3:0 AC_SUBST(GETDNS_COMPILATION_COMMENT) AC_SUBST(GETDNS_LIBVERSION)