mirror of https://github.com/getdnsapi/getdns.git
Add ability to verify server certificate using hostname for TLS/STARTTLS
NOTE: This implementation will only work for OpenSSL v1.0.2 and later. Doing it for earlier versions is totally insane: https://wiki.openssl.org/index.php/Hostname_validation
This commit is contained in:
parent
8beace7036
commit
cb1dff1ac7
|
@ -605,6 +605,7 @@ upstream_init(getdns_upstream *upstream,
|
|||
upstream->starttls_req = NULL;
|
||||
upstream->transport = GETDNS_TRANSPORT_TCP;
|
||||
upstream->tls_hs_state = GETDNS_HS_NONE;
|
||||
upstream->tls_auth_name[0] = '\0';
|
||||
upstream->tcp.write_error = 0;
|
||||
upstream->loop = NULL;
|
||||
(void) getdns_eventloop_event_init(
|
||||
|
@ -1216,6 +1217,8 @@ getdns_set_base_dns_transports(
|
|||
if (!context || transport_count == 0 || transports == NULL)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
/* TODO: restrict the use of each transport to once ->
|
||||
sane list and correct max size for array*/
|
||||
for(i=0; i<transport_count; i++)
|
||||
{
|
||||
if( transports[i] != GETDNS_TRANSPORT_UDP
|
||||
|
@ -1662,6 +1665,7 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
|
|||
getdns_dict *dict;
|
||||
getdns_bindata *address_type;
|
||||
getdns_bindata *address_data;
|
||||
getdns_bindata *tls_auth_name;
|
||||
struct sockaddr_storage addr;
|
||||
|
||||
getdns_bindata *scope_id;
|
||||
|
@ -1735,6 +1739,16 @@ getdns_context_set_upstream_recursive_servers(struct getdns_context *context,
|
|||
upstream->addr.ss_family = addr.ss_family;
|
||||
upstream_init(upstream, upstreams, ai);
|
||||
upstream->transport = getdns_upstream_transports[j];
|
||||
if (getdns_upstream_transports[j] == GETDNS_TRANSPORT_TLS) {
|
||||
if ((r = getdns_dict_get_bindata(
|
||||
dict, "tls_auth_name", &tls_auth_name)) == GETDNS_RETURN_GOOD) {
|
||||
/*TODO: VALIDATE THIS STRING!*/
|
||||
memcpy(upstream->tls_auth_name,
|
||||
(char *)tls_auth_name->data,
|
||||
tls_auth_name->size);
|
||||
upstream->tls_auth_name[tls_auth_name->size] = '\0';
|
||||
}
|
||||
}
|
||||
upstreams->count++;
|
||||
freeaddrinfo(ai);
|
||||
}
|
||||
|
@ -2130,11 +2144,14 @@ getdns_context_prepare_for_resolution(struct getdns_context *context,
|
|||
#endif
|
||||
if(context->tls_ctx == NULL)
|
||||
return GETDNS_RETURN_BAD_CONTEXT;
|
||||
SSL_CTX_set_verify(context->tls_ctx, SSL_VERIFY_PEER, NULL);
|
||||
if (!SSL_CTX_set_default_verify_paths(context->tls_ctx))
|
||||
return GETDNS_RETURN_BAD_CONTEXT;
|
||||
}
|
||||
}
|
||||
/* Block use of STARTTLS/TLS ONLY in recursive mode as it won't work */
|
||||
/* Note: If TLS is used in recursive mode this will try TLS on port
|
||||
* 53 so it is blocked here. So is STARTTLS only at the moment. */
|
||||
* 53 so it is blocked here. So is 'STARTTLS only' at the moment. */
|
||||
if (context->resolution_type == GETDNS_RESOLUTION_RECURSING &&
|
||||
context->dns_transport_count == 1 &&
|
||||
(context->dns_transports[0] == GETDNS_TRANSPORT_TLS ||
|
||||
|
|
|
@ -101,6 +101,7 @@ typedef struct getdns_upstream {
|
|||
getdns_eventloop_event event;
|
||||
getdns_eventloop *loop;
|
||||
getdns_tcp_state tcp;
|
||||
char tls_auth_name[256];
|
||||
|
||||
/* Pipelining of TCP network requests */
|
||||
getdns_network_req *write_queue;
|
||||
|
|
14
src/stub.c
14
src/stub.c
|
@ -32,6 +32,7 @@
|
|||
*/
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/x509v3.h>
|
||||
#include "config.h"
|
||||
#include <fcntl.h>
|
||||
#include "stub.h"
|
||||
|
@ -822,12 +823,14 @@ tls_failed(getdns_upstream *upstream)
|
|||
}
|
||||
|
||||
static SSL*
|
||||
tls_create_object(getdns_context *context, int fd)
|
||||
tls_create_object(getdns_context *context, int fd, const char* auth_name)
|
||||
{
|
||||
/* Create SSL instance */
|
||||
if (context->tls_ctx == NULL)
|
||||
return NULL;
|
||||
SSL* ssl = SSL_new(context->tls_ctx);
|
||||
X509_VERIFY_PARAM *param;
|
||||
|
||||
if(!ssl)
|
||||
return NULL;
|
||||
/* Connect the SSL object with a file descriptor */
|
||||
|
@ -835,6 +838,10 @@ tls_create_object(getdns_context *context, int fd)
|
|||
SSL_free(ssl);
|
||||
return NULL;
|
||||
}
|
||||
SSL_set_tlsext_host_name(ssl, auth_name);
|
||||
param = SSL_get0_param(ssl);
|
||||
X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
|
||||
X509_VERIFY_PARAM_set1_host(param, auth_name, 0);
|
||||
SSL_set_connect_state(ssl);
|
||||
(void) SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);
|
||||
return ssl;
|
||||
|
@ -1302,7 +1309,8 @@ upstream_read_cb(void *userarg)
|
|||
dnsreq = netreq->owner;
|
||||
if (is_starttls_response(netreq)) {
|
||||
upstream->tls_obj = tls_create_object(dnsreq->context,
|
||||
upstream->fd);
|
||||
upstream->fd,
|
||||
upstream->tls_auth_name);
|
||||
if (upstream->tls_obj == NULL)
|
||||
upstream->tls_hs_state = GETDNS_HS_FAILED;
|
||||
upstream->tls_hs_state = GETDNS_HS_WRITE;
|
||||
|
@ -1542,7 +1550,7 @@ upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport,
|
|||
return upstream->fd;
|
||||
fd = tcp_connect(upstream, transport);
|
||||
if (fd == -1) return -1;
|
||||
upstream->tls_obj = tls_create_object(dnsreq->context, fd);
|
||||
upstream->tls_obj = tls_create_object(dnsreq->context, fd, upstream->tls_auth_name);
|
||||
if (upstream->tls_obj == NULL) {
|
||||
close(fd);
|
||||
return -1;
|
||||
|
|
|
@ -55,6 +55,7 @@ ipaddr_dict(getdns_context *context, char *ipstr)
|
|||
char *s = strchr(ipstr, '%'), *scope_id_str = "";
|
||||
char *p = strchr(ipstr, '@'), *portstr = "";
|
||||
char *t = strchr(ipstr, '#'), *tls_portstr = "";
|
||||
char *n = strchr(ipstr, '~'), *tls_namestr = "";
|
||||
uint8_t buf[sizeof(struct in6_addr)];
|
||||
getdns_bindata addr;
|
||||
|
||||
|
@ -73,6 +74,10 @@ ipaddr_dict(getdns_context *context, char *ipstr)
|
|||
*t = 0;
|
||||
tls_portstr = t + 1;
|
||||
}
|
||||
if (n) {
|
||||
*n = 0;
|
||||
tls_namestr = n + 1;
|
||||
}
|
||||
if (strchr(ipstr, ':')) {
|
||||
getdns_dict_util_set_string(r, "address_type", "IPv6");
|
||||
addr.size = 16;
|
||||
|
@ -93,6 +98,9 @@ ipaddr_dict(getdns_context *context, char *ipstr)
|
|||
getdns_dict_set_int(r, "port", (int32_t)atoi(portstr));
|
||||
if (*tls_portstr)
|
||||
getdns_dict_set_int(r, "tls_port", (int32_t)atoi(tls_portstr));
|
||||
if (*tls_namestr) {
|
||||
getdns_dict_util_set_string(r, "tls_auth_name", tls_namestr);
|
||||
}
|
||||
if (*scope_id_str)
|
||||
getdns_dict_util_set_string(r, "scope_id", scope_id_str);
|
||||
|
||||
|
|
Loading…
Reference in New Issue