Commit 1e0a8b9d authored by Daniel Kahn Gillmor's avatar Daniel Kahn Gillmor Committed by Ondřej Surý

listen using TLS on specific sockets

kresd has --tls/-t by analogy with --addr/-a where the daemon opens
the socket itself.

This changeset adds equivalent functionality for inherited sockets:
--tlsfd/-T by analogy with --fd/-Sa
parent 0c78ff54
......@@ -333,7 +333,7 @@ int tcp_bind_tls(uv_tcp_t *handle, struct sockaddr *addr)
return _tcp_bind(handle, addr, tls_accept);
}
int tcp_bindfd(uv_tcp_t *handle, int fd)
static int _tcp_bindfd(uv_tcp_t *handle, int fd, uv_connection_cb connection)
{
if (!handle) {
return kr_error(EINVAL);
......@@ -344,13 +344,23 @@ int tcp_bindfd(uv_tcp_t *handle, int fd)
return ret;
}
ret = uv_listen((uv_stream_t *)handle, 16, tcp_accept);
ret = uv_listen((uv_stream_t *)handle, 16, connection);
if (ret != 0) {
return ret;
}
return tcp_bind_finalize((uv_handle_t *)handle);
}
int tcp_bindfd(uv_tcp_t *handle, int fd)
{
return _tcp_bindfd(handle, fd, tcp_accept);
}
int tcp_bindfd_tls(uv_tcp_t *handle, int fd)
{
return _tcp_bindfd(handle, fd, tls_accept);
}
void io_create(uv_loop_t *loop, uv_handle_t *handle, int type)
{
if (type == SOCK_DGRAM) {
......
......@@ -44,6 +44,7 @@ int udp_bindfd(uv_udp_t *handle, int fd);
int tcp_bind(uv_tcp_t *handle, struct sockaddr *addr);
int tcp_bind_tls(uv_tcp_t *handle, struct sockaddr *addr);
int tcp_bindfd(uv_tcp_t *handle, int fd);
int tcp_bindfd_tls(uv_tcp_t *handle, int fd);
void io_create(uv_loop_t *loop, uv_handle_t *handle, int type);
void io_deinit(uv_handle_t *handle);
......
......@@ -278,6 +278,7 @@ static void help(int argc, char *argv[])
" -a, --addr=[addr] Server address (default: localhost#53).\n"
" -t, --tls=[addr] Server address for TLS (default: off).\n"
" -S, --fd=[fd] Listen on given fd (handed out by supervisor).\n"
" -T, --tlsfd=[fd] Listen using TLS on given fd (handed out by supervisor).\n"
" -c, --config=[path] Config file path (relative to [rundir]) (default: config).\n"
" -k, --keyfile=[path] File containing trust anchors (DS or DNSKEY).\n"
" -f, --forks=N Start N forks sharing the configuration.\n"
......@@ -388,6 +389,8 @@ int main(int argc, char **argv)
array_init(tls_set);
array_t(int) fd_set;
array_init(fd_set);
array_t(int) tls_fd_set;
array_init(tls_fd_set);
char *keyfile = NULL;
const char *config = NULL;
char *keyfile_buf = NULL;
......@@ -399,6 +402,7 @@ int main(int argc, char **argv)
{"addr", required_argument, 0, 'a'},
{"tls", required_argument, 0, 't'},
{"fd", required_argument, 0, 'S'},
{"tlsfd", required_argument, 0, 'T'},
{"config", required_argument, 0, 'c'},
{"keyfile",required_argument, 0, 'k'},
{"forks",required_argument, 0, 'f'},
......@@ -408,7 +412,7 @@ int main(int argc, char **argv)
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
while ((c = getopt_long(argc, argv, "a:t:S:c:f:k:vqVh", opts, &li)) != -1) {
while ((c = getopt_long(argc, argv, "a:t:S:T:c:f:k:vqVh", opts, &li)) != -1) {
switch (c)
{
case 'a':
......@@ -420,6 +424,9 @@ int main(int argc, char **argv)
case 'S':
array_push(fd_set, atoi(optarg));
break;
case 'T':
array_push(tls_fd_set, atoi(optarg));
break;
case 'c':
config = optarg;
break;
......@@ -523,7 +530,7 @@ int main(int argc, char **argv)
* sockets etc. before forking, but at the same time can't touch it before
* forking otherwise it crashes, so it's a chicken and egg problem.
* Disabling until https://github.com/libuv/libuv/pull/846 is done. */
if (forks > 1 && fd_set.len == 0) {
if (forks > 1 && fd_set.len == 0 && tls_fd_set.len == 0) {
kr_log_error("[system] forking >1 workers supported only on Linux 3.9+ or with supervisor\n");
return EXIT_FAILURE;
}
......@@ -559,13 +566,22 @@ int main(int argc, char **argv)
}
/* Bind to passed fds and run */
for (size_t i = 0; i < fd_set.len; ++i) {
ret = network_listen_fd(&engine.net, fd_set.at[i]);
ret = network_listen_fd(&engine.net, fd_set.at[i], false);
if (ret != 0) {
kr_log_error("[system] listen on fd=%d %s\n", fd_set.at[i], kr_strerror(ret));
ret = EXIT_FAILURE;
break;
}
}
/* Do the same for TLS */
for (size_t i = 0; i < tls_fd_set.len; ++i) {
ret = network_listen_fd(&engine.net, tls_fd_set.at[i], true);
if (ret != 0) {
kr_log_error("[system] TLS listen on fd=%d %s\n", tls_fd_set.at[i], kr_strerror(ret));
ret = EXIT_FAILURE;
break;
}
}
/* Bind to sockets and run */
if (ret == 0) {
for (size_t i = 0; i < addr_set.len; ++i) {
......
......@@ -170,9 +170,14 @@ static int open_endpoint(struct network *net, struct endpoint *ep, struct sockad
}
/** Open fd as endpoint. */
static int open_endpoint_fd(struct network *net, struct endpoint *ep, int fd, int sock_type)
static int open_endpoint_fd(struct network *net, struct endpoint *ep, int fd, int sock_type, bool use_tls)
{
int ret = kr_ok();
if (sock_type == SOCK_DGRAM) {
if (use_tls) {
/* we do not support TLS over UDP */
return kr_error(EBADF);
}
if (ep->udp) {
return kr_error(EEXIST);
}
......@@ -181,7 +186,7 @@ static int open_endpoint_fd(struct network *net, struct endpoint *ep, int fd, in
return kr_error(ENOMEM);
}
uv_udp_init(net->loop, ep->udp);
int ret = udp_bindfd(ep->udp, fd);
ret = udp_bindfd(ep->udp, fd);
if (ret != 0) {
close_handle((uv_handle_t *)ep->udp, false);
return ret;
......@@ -198,7 +203,12 @@ static int open_endpoint_fd(struct network *net, struct endpoint *ep, int fd, in
return kr_error(ENOMEM);
}
uv_tcp_init(net->loop, ep->tcp);
int ret = tcp_bindfd(ep->tcp, fd);
if (use_tls) {
ret = tcp_bindfd_tls(ep->tcp, fd);
ep->flags |= NET_TLS;
} else {
ret = tcp_bindfd(ep->tcp, fd);
}
if (ret != 0) {
close_handle((uv_handle_t *)ep->tcp, false);
return ret;
......@@ -225,7 +235,7 @@ static endpoint_array_t *network_get(struct network *net, const char *addr, uint
return NULL;
}
int network_listen_fd(struct network *net, int fd)
int network_listen_fd(struct network *net, int fd, bool use_tls)
{
/* Extract local address and socket type. */
int sock_type = SOCK_DGRAM;
......@@ -270,7 +280,7 @@ int network_listen_fd(struct network *net, int fd)
struct endpoint *ep = ep_array->at[index];
assert(ep != NULL);
/* Create a libuv struct for this socket. */
return open_endpoint_fd(net, ep, fd, sock_type);
return open_endpoint_fd(net, ep, fd, sock_type, use_tls);
}
int network_listen(struct network *net, const char *addr, uint16_t port, uint32_t flags)
......
......@@ -17,6 +17,7 @@
#pragma once
#include <uv.h>
#include <stdbool.h>
#include "lib/generic/array.h"
#include "lib/generic/map.h"
......@@ -48,7 +49,7 @@ struct network {
void network_init(struct network *net, uv_loop_t *loop);
void network_deinit(struct network *net);
int network_listen_fd(struct network *net, int fd);
int network_listen_fd(struct network *net, int fd, bool use_tls);
int network_listen(struct network *net, const char *addr, uint16_t port, uint32_t flags);
int network_close(struct network *net, const char *addr, uint16_t port);
int network_set_tls_cert(struct network *net, const char *cert);
......
......@@ -105,6 +105,10 @@ times to listen on more addresses.
Listen on given file descriptor(s), passed by supervisor.
Option may be passed multiple times to listen on more file descriptors.
.TP
.B \-T\fI fd\fR, \-\-tlsfd=\fI<fd>
Listen using TLS on given file descriptor(s), passed by supervisor.
Option may be passed multiple times to listen on more file descriptors.
.TP
.B \-k\fI keyfile\fR, \fB\-\-keyfile=\fI<keyfile>
Use given for keeping root trust anchors. If the file doesn't exist, it will be
automatically boostrapped from IANA and warning for you will be issued to check it
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment