From 115c36a94e0b4593ccba9c6d9d8952d6a0454ac0 Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Tue, 1 Nov 2011 09:26:58 +0000 Subject: [PATCH] support for ssl-upstream (works from unbound-control). git-svn-id: file:///svn/unbound/trunk@2532 be551aaa-1e26-0410-a405-d3ace91eadb9 --- doc/Changelog | 4 ++++ services/outside_network.c | 18 ++++++++++++++++ util/netevent.c | 44 +++++++++++++++++++++++++++----------- util/netevent.h | 10 +++++++++ 4 files changed, 63 insertions(+), 13 deletions(-) diff --git a/doc/Changelog b/doc/Changelog index 17920c717..8045d4bcf 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,7 @@ +1 November 2011: Wouter + - dns over ssl support as a client, ssl-upstream yes turns it on. + It performs an SSL transaction for every DNS query (250 msec). + 31 October 2011: Wouter - dns over ssl support, ssl-service-pem and ssl-service-key files can be given and then TCP queries are serviced wrapped in SSL. diff --git a/services/outside_network.c b/services/outside_network.c index 3a41554c7..3366b9ed6 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -58,6 +58,7 @@ #include "util/net_help.h" #include "util/random.h" #include "util/fptr_wlist.h" +#include #ifdef HAVE_NETDB_H #include @@ -237,6 +238,18 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len) return 0; } } + if(w->outnet->sslctx) { + pend->c->ssl = outgoing_ssl_fd(w->outnet->sslctx, s); + if(!pend->c->ssl) { + pend->c->fd = s; + comm_point_close(pend->c); + return 0; + } +#ifdef USE_WINSOCK + comm_point_tcp_win_bio_cb(pend->c, pend->c->ssl); +#endif + pend->c->ssl_shake_state = comm_ssl_shake_write; + } w->pkt = NULL; w->next_waiting = (void*)pend; pend->id = LDNS_ID_WIRE(pkt); @@ -280,6 +293,11 @@ static void decomission_pending_tcp(struct outside_network* outnet, struct pending_tcp* pend) { + if(pend->c->ssl) { + SSL_shutdown(pend->c->ssl); + SSL_free(pend->c->ssl); + pend->c->ssl = NULL; + } comm_point_close(pend->c); pend->next_free = outnet->tcp_free; outnet->tcp_free = pend; diff --git a/util/netevent.c b/util/netevent.c index 328679948..a6bdbcaff 100644 --- a/util/netevent.c +++ b/util/netevent.c @@ -709,6 +709,18 @@ static long win_bio_cb(BIO *b, int oper, const char* ATTR_UNUSED(argp), /* return original return value */ return retvalue; } + +/** set win bio callbacks for nonblocking operations */ +void +comm_point_tcp_win_bio_cb(struct comm_point* c, void* thessl) +{ + SSL* ssl = (SSL*)thessl; + /* set them both just in case, but usually they are the same BIO */ + BIO_set_callback(SSL_get_rbio(ssl), &win_bio_cb); + BIO_set_callback_arg(SSL_get_rbio(ssl), (char*)comm_point_internal(c)); + BIO_set_callback(SSL_get_wbio(ssl), &win_bio_cb); + BIO_set_callback_arg(SSL_get_wbio(ssl), (char*)comm_point_internal(c)); +} #endif void @@ -736,17 +748,14 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg) return; if(c->ssl) { c_hdl->ssl = incoming_ssl_fd(c->ssl, new_fd); - if(!c_hdl->ssl) + if(!c_hdl->ssl) { + c_hdl->fd = new_fd; + comm_point_close(c_hdl); return; + } c_hdl->ssl_shake_state = comm_ssl_shake_read; #ifdef USE_WINSOCK - /* set them both just in case, but usually they are the same BIO */ - BIO_set_callback(SSL_get_rbio(c_hdl->ssl), &win_bio_cb); - BIO_set_callback_arg(SSL_get_rbio(c_hdl->ssl), - (char*)comm_point_internal(c_hdl)); - BIO_set_callback(SSL_get_wbio(c_hdl->ssl), &win_bio_cb); - BIO_set_callback_arg(SSL_get_wbio(c_hdl->ssl), - (char*)comm_point_internal(c_hdl)); + comm_point_tcp_win_bio_cb(c_hdl, c_hdl->ssl); #endif } @@ -862,7 +871,7 @@ ssl_handshake(struct comm_point* c) } } /* this is where peer verification could take place */ - log_addr(VERB_ALGO, "SSL connection from", &c->repinfo.addr, + log_addr(VERB_ALGO, "SSL DNS connection", &c->repinfo.addr, c->repinfo.addrlen); /* setup listen rw correctly */ @@ -1037,6 +1046,15 @@ ssl_handle_write(struct comm_point* c) return 1; } +/** handle ssl tcp connection with dns contents */ +static int +ssl_handle_it(struct comm_point* c) +{ + if(c->tcp_is_reading) + return ssl_handle_read(c); + return ssl_handle_write(c); +} + /** Handle tcp reading callback. * @param fd: file descriptor of socket. * @param c: comm point to read from into buffer. @@ -1048,10 +1066,10 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok) { ssize_t r; log_assert(c->type == comm_tcp || c->type == comm_local); + if(c->ssl) + return ssl_handle_it(c); if(!c->tcp_is_reading) return 0; - if(c->ssl) - return ssl_handle_read(c); log_assert(fd != -1); if(c->tcp_byte_count < sizeof(uint16_t)) { @@ -1148,7 +1166,7 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c) { ssize_t r; log_assert(c->type == comm_tcp); - if(c->tcp_is_reading) + if(c->tcp_is_reading && !c->ssl) return 0; log_assert(fd != -1); if(c->tcp_byte_count == 0 && c->tcp_check_nb_connect) { @@ -1191,7 +1209,7 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c) } } if(c->ssl) - return ssl_handle_write(c); + return ssl_handle_it(c); if(c->tcp_byte_count < sizeof(uint16_t)) { uint16_t len = htons(ldns_buffer_limit(c->buffer)); diff --git a/util/netevent.h b/util/netevent.h index 5425eebc6..ade37cdae 100644 --- a/util/netevent.h +++ b/util/netevent.h @@ -636,4 +636,14 @@ void comm_point_local_handle_callback(int fd, short event, void* arg); */ void comm_point_raw_handle_callback(int fd, short event, void* arg); +#ifdef USE_WINSOCK +/** + * Callback for openssl BIO to on windows detect WSAEWOULDBLOCK and notify + * the winsock_event of this for proper TCP nonblocking implementation. + * @param c: comm_point, fd must be set its struct event is registered. + * @param ssl: openssl SSL, fd must be set so it has a bio. + */ +void comm_point_tcp_win_bio_cb(struct comm_point* c, void* ssl); +#endif + #endif /* NET_EVENT_H */ -- 2.47.2