support for ssl-upstream (works from unbound-control).

git-svn-id: file:///svn/unbound/trunk@2532 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2011-11-01 09:26:58 +00:00
parent 03c34b695f
commit 115c36a94e
4 changed files with 63 additions and 13 deletions

View file

@ -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 31 October 2011: Wouter
- dns over ssl support, ssl-service-pem and ssl-service-key files - dns over ssl support, ssl-service-pem and ssl-service-key files
can be given and then TCP queries are serviced wrapped in SSL. can be given and then TCP queries are serviced wrapped in SSL.

View file

@ -58,6 +58,7 @@
#include "util/net_help.h" #include "util/net_help.h"
#include "util/random.h" #include "util/random.h"
#include "util/fptr_wlist.h" #include "util/fptr_wlist.h"
#include <openssl/ssl.h>
#ifdef HAVE_NETDB_H #ifdef HAVE_NETDB_H
#include <netdb.h> #include <netdb.h>
@ -237,6 +238,18 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
return 0; 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->pkt = NULL;
w->next_waiting = (void*)pend; w->next_waiting = (void*)pend;
pend->id = LDNS_ID_WIRE(pkt); pend->id = LDNS_ID_WIRE(pkt);
@ -280,6 +293,11 @@ static void
decomission_pending_tcp(struct outside_network* outnet, decomission_pending_tcp(struct outside_network* outnet,
struct pending_tcp* pend) 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); comm_point_close(pend->c);
pend->next_free = outnet->tcp_free; pend->next_free = outnet->tcp_free;
outnet->tcp_free = pend; outnet->tcp_free = pend;

View file

@ -709,6 +709,18 @@ static long win_bio_cb(BIO *b, int oper, const char* ATTR_UNUSED(argp),
/* return original return value */ /* return original return value */
return retvalue; 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 #endif
void void
@ -736,17 +748,14 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg)
return; return;
if(c->ssl) { if(c->ssl) {
c_hdl->ssl = incoming_ssl_fd(c->ssl, new_fd); 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; return;
}
c_hdl->ssl_shake_state = comm_ssl_shake_read; c_hdl->ssl_shake_state = comm_ssl_shake_read;
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
/* set them both just in case, but usually they are the same BIO */ comm_point_tcp_win_bio_cb(c_hdl, c_hdl->ssl);
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));
#endif #endif
} }
@ -862,7 +871,7 @@ ssl_handshake(struct comm_point* c)
} }
} }
/* this is where peer verification could take place */ /* 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); c->repinfo.addrlen);
/* setup listen rw correctly */ /* setup listen rw correctly */
@ -1037,6 +1046,15 @@ ssl_handle_write(struct comm_point* c)
return 1; 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. /** Handle tcp reading callback.
* @param fd: file descriptor of socket. * @param fd: file descriptor of socket.
* @param c: comm point to read from into buffer. * @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; ssize_t r;
log_assert(c->type == comm_tcp || c->type == comm_local); log_assert(c->type == comm_tcp || c->type == comm_local);
if(c->ssl)
return ssl_handle_it(c);
if(!c->tcp_is_reading) if(!c->tcp_is_reading)
return 0; return 0;
if(c->ssl)
return ssl_handle_read(c);
log_assert(fd != -1); log_assert(fd != -1);
if(c->tcp_byte_count < sizeof(uint16_t)) { 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; ssize_t r;
log_assert(c->type == comm_tcp); log_assert(c->type == comm_tcp);
if(c->tcp_is_reading) if(c->tcp_is_reading && !c->ssl)
return 0; return 0;
log_assert(fd != -1); log_assert(fd != -1);
if(c->tcp_byte_count == 0 && c->tcp_check_nb_connect) { 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) if(c->ssl)
return ssl_handle_write(c); return ssl_handle_it(c);
if(c->tcp_byte_count < sizeof(uint16_t)) { if(c->tcp_byte_count < sizeof(uint16_t)) {
uint16_t len = htons(ldns_buffer_limit(c->buffer)); uint16_t len = htons(ldns_buffer_limit(c->buffer));

View file

@ -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); 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 */ #endif /* NET_EVENT_H */