Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create the SSL_CTX for QUIC before chroot and privilege drop #1187

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions daemon/daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -956,6 +956,9 @@ daemon_delete(struct daemon* daemon)
listen_sslctx_delete_ticket_keys();
SSL_CTX_free((SSL_CTX*)daemon->listen_sslctx);
SSL_CTX_free((SSL_CTX*)daemon->connect_sslctx);
#endif
#ifdef HAVE_NGTCP2
SSL_CTX_free((SSL_CTX*)daemon->quic_sslctx);
#endif
free(daemon);
/* lex cleanup */
Expand Down
2 changes: 2 additions & 0 deletions daemon/daemon.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ struct daemon {
struct daemon_remote* rc;
/** ssl context for listening to dnstcp over ssl, and connecting ssl */
void* listen_sslctx, *connect_sslctx;
/** ssl context for listening to quic */
void* quic_sslctx;
/** num threads allocated */
int num;
/** num threads allocated in the previous config or 0 at first */
Expand Down
13 changes: 10 additions & 3 deletions daemon/unbound.c
Original file line number Diff line number Diff line change
Expand Up @@ -494,8 +494,9 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
fatal_exit("could not set up remote-control");
if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
if(!(daemon->listen_sslctx = listen_sslctx_create(
cfg->ssl_service_key, cfg->ssl_service_pem, NULL)))
cfg->ssl_service_key, cfg->ssl_service_pem, NULL))) {
fatal_exit("could not set up listen SSL_CTX");
}
if(cfg->tls_ciphers && cfg->tls_ciphers[0]) {
if (!SSL_CTX_set_cipher_list(daemon->listen_sslctx, cfg->tls_ciphers)) {
fatal_exit("failed to set tls-cipher %s", cfg->tls_ciphers);
Expand All @@ -507,18 +508,24 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
fatal_exit("failed to set tls-ciphersuites %s", cfg->tls_ciphersuites);
}
}
#endif
#endif /* HAVE_SSL_CTX_SET_CIPHERSUITES */
if(cfg->tls_session_ticket_keys.first &&
cfg->tls_session_ticket_keys.first->str[0] != 0) {
if(!listen_sslctx_setup_ticket_keys(daemon->listen_sslctx, cfg->tls_session_ticket_keys.first)) {
fatal_exit("could not set session ticket SSL_CTX");
}
}
#ifdef HAVE_NGTCP2
if(!(daemon->quic_sslctx = quic_sslctx_create(
cfg->ssl_service_key, cfg->ssl_service_pem, NULL))) {
fatal_exit("could not set up quic SSL_CTX");
}
#endif /* HAVE_NGTCP2 */
}
if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL,
cfg->tls_cert_bundle, cfg->tls_win_cert)))
fatal_exit("could not set up connect SSL_CTX");
#endif
#endif /* HAVE_SSL */

/* init syslog (as root) if needed, before daemonize, otherwise
* a fork error could not be printed since daemonize closed stderr.*/
Expand Down
4 changes: 2 additions & 2 deletions daemon/worker.c
Original file line number Diff line number Diff line change
Expand Up @@ -2174,9 +2174,9 @@ worker_init(struct worker* worker, struct config_file *cfg,
cfg->harden_large_queries, cfg->http_max_streams,
cfg->http_endpoint, cfg->http_notls_downstream,
worker->daemon->tcl, worker->daemon->listen_sslctx,
worker->daemon->quic_sslctx,
dtenv, worker->daemon->doq_table, worker->env.rnd,
cfg->ssl_service_key, cfg->ssl_service_pem, cfg,
worker_handle_request, worker);
cfg, worker_handle_request, worker);
if(!worker->front) {
log_err("could not create listening sockets");
worker_delete(worker);
Expand Down
71 changes: 35 additions & 36 deletions services/listen_dnsport.c
Original file line number Diff line number Diff line change
Expand Up @@ -1523,9 +1523,9 @@ listen_create(struct comm_base* base, struct listen_port* ports,
size_t bufsize, int tcp_accept_count, int tcp_idle_timeout,
int harden_large_queries, uint32_t http_max_streams,
char* http_endpoint, int http_notls, struct tcl_list* tcp_conn_limit,
void* sslctx, struct dt_env* dtenv, struct doq_table* doq_table,
struct ub_randstate* rnd, const char* ssl_service_key,
const char* ssl_service_pem, struct config_file* cfg,
void* sslctx, void* quic_sslctx, struct dt_env* dtenv,
struct doq_table* doq_table,
struct ub_randstate* rnd,struct config_file* cfg,
comm_point_callback_type* cb, void *cb_arg)
{
struct listen_dnsport* front = (struct listen_dnsport*)
Expand Down Expand Up @@ -1558,8 +1558,7 @@ listen_create(struct comm_base* base, struct listen_port* ports,
#endif
cp = comm_point_create_doq(base, ports->fd,
front->udp_buff, cb, cb_arg, ports->socket,
doq_table, rnd, ssl_service_key,
ssl_service_pem, cfg);
doq_table, rnd, quic_sslctx, cfg);
} else if(ports->ftype == listen_type_tcp ||
ports->ftype == listen_type_tcp_dnscrypt) {
cp = comm_point_create_tcp(base, ports->fd,
Expand Down Expand Up @@ -1620,10 +1619,13 @@ listen_create(struct comm_base* base, struct listen_port* ports,
(ports->ftype == listen_type_udpancil) ||
(ports->ftype == listen_type_tcp_dnscrypt) ||
(ports->ftype == listen_type_udp_dnscrypt) ||
(ports->ftype == listen_type_udpancil_dnscrypt))
(ports->ftype == listen_type_udpancil_dnscrypt)) {
cp->ssl = NULL;
else
} else if(ports->ftype == listen_type_doq) {
cp->ssl = quic_sslctx;
} else {
cp->ssl = sslctx;
}
cp->dtenv = dtenv;
cp->do_not_close = 1;
#ifdef USE_DNSCRYPT
Expand Down Expand Up @@ -4598,10 +4600,9 @@ doq_alpn_select_cb(SSL* ATTR_UNUSED(ssl), const unsigned char** out,
return SSL_TLSEXT_ERR_ALERT_FATAL;
}

/** create new tls session for server doq connection */
static SSL_CTX*
doq_ctx_server_setup(struct doq_server_socket* doq_socket)
void* quic_sslctx_create(char* key, char* pem, char* verifypem)
{
#ifdef HAVE_NGHTTP2
char* sid_ctx = "unbound server";
#ifndef HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_SERVER_CONTEXT
SSL_QUIC_METHOD* quic_method;
Expand All @@ -4611,6 +4612,16 @@ doq_ctx_server_setup(struct doq_server_socket* doq_socket)
log_crypto_err("Could not SSL_CTX_new");
return NULL;
}
if(!key || key[0] == 0) {
log_err("doq: error, no tls-service-key file specified");
SSL_CTX_free(ctx);
return NULL;
}
if(!pem || pem[0] == 0) {
log_err("doq: error, no tls-service-pem file specified");
SSL_CTX_free(ctx);
return NULL;
}
SSL_CTX_set_options(ctx,
(SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
SSL_OP_SINGLE_ECDH_USE |
Expand All @@ -4623,43 +4634,37 @@ doq_ctx_server_setup(struct doq_server_socket* doq_socket)
SSL_CTX_set_alpn_select_cb(ctx, doq_alpn_select_cb, NULL);
#endif
SSL_CTX_set_default_verify_paths(ctx);
if(!SSL_CTX_use_certificate_chain_file(ctx,
doq_socket->ssl_service_pem)) {
log_err("doq: error for cert file: %s",
doq_socket->ssl_service_pem);
if(!SSL_CTX_use_certificate_chain_file(ctx, pem)) {
log_err("doq: error for cert file: %s", pem);
log_crypto_err("doq: error in "
"SSL_CTX_use_certificate_chain_file");
SSL_CTX_free(ctx);
return NULL;
}
if(!SSL_CTX_use_PrivateKey_file(ctx, doq_socket->ssl_service_key,
SSL_FILETYPE_PEM)) {
log_err("doq: error for private key file: %s",
doq_socket->ssl_service_key);
if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)) {
log_err("doq: error for private key file: %s", key);
log_crypto_err("doq: error in SSL_CTX_use_PrivateKey_file");
SSL_CTX_free(ctx);
return NULL;
}
if(!SSL_CTX_check_private_key(ctx)) {
log_err("doq: error for key file: %s",
doq_socket->ssl_service_key);
log_err("doq: error for key file: %s", key);
log_crypto_err("doq: error in SSL_CTX_check_private_key");
SSL_CTX_free(ctx);
return NULL;
}
SSL_CTX_set_session_id_context(ctx, (void*)sid_ctx, strlen(sid_ctx));
if(doq_socket->ssl_verify_pem && doq_socket->ssl_verify_pem[0]) {
if(!SSL_CTX_load_verify_locations(ctx,
doq_socket->ssl_verify_pem, NULL)) {
if(verifypem && verifypem[0]) {
if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) {
log_err("doq: error for verify pem file: %s",
doq_socket->ssl_verify_pem);
verifypem);
log_crypto_err("doq: error in "
"SSL_CTX_load_verify_locations");
SSL_CTX_free(ctx);
return NULL;
}
SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(
doq_socket->ssl_verify_pem));
verifypem));
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|
SSL_VERIFY_CLIENT_ONCE|
SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
Expand All @@ -4672,7 +4677,7 @@ doq_ctx_server_setup(struct doq_server_socket* doq_socket)
SSL_CTX_free(ctx);
return NULL;
}
#else
#else /* HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_SERVER_CONTEXT */
/* The quic_method needs to remain valid during the SSL_CTX
* lifetime, so we allocate it. It is freed with the
* doq_server_socket. */
Expand All @@ -4690,6 +4695,10 @@ doq_ctx_server_setup(struct doq_server_socket* doq_socket)
SSL_CTX_set_quic_method(ctx, doq_socket->quic_method);
#endif
return ctx;
#else /* HAVE_NGHTTP2 */
(void)key; (void)pem; (void)verifypem;
return NULL;
#endif /* HAVE_NGHTTP2 */
}

/** Get the ngtcp2_conn from ssl userdata of type ngtcp2_conn_ref */
Expand Down Expand Up @@ -4720,16 +4729,6 @@ doq_ssl_server_setup(SSL_CTX* ctx, struct doq_conn* conn)
return ssl;
}

/** setup the doq_socket server tls context */
int
doq_socket_setup_ctx(struct doq_server_socket* doq_socket)
{
doq_socket->ctx = doq_ctx_server_setup(doq_socket);
if(!doq_socket->ctx)
return 0;
return 1;
}

int
doq_conn_setup(struct doq_conn* conn, uint8_t* scid, size_t scidlen,
uint8_t* ocid, size_t ocidlen, const uint8_t* token, size_t tokenlen)
Expand Down
21 changes: 13 additions & 8 deletions services/listen_dnsport.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,10 @@ int resolve_interface_names(char** ifs, int num_ifs,
* @param http_notls: no TLS for http downstream
* @param tcp_conn_limit: TCP connection limit info.
* @param sslctx: nonNULL if ssl context.
* @param quic_sslctx: nonNULL if quic ssl context.
* @param dtenv: nonNULL if dnstap enabled.
* @param doq_table: the doq connection table, with shared information.
* @param rnd: random state.
* @param ssl_service_key: the SSL service key file.
* @param ssl_service_pem: the SSL service pem file.
* @param cfg: config file struct.
* @param cb: callback function when a request arrives. It is passed
* the packet and user argument. Return true to send a reply.
Expand All @@ -211,9 +210,9 @@ listen_create(struct comm_base* base, struct listen_port* ports,
size_t bufsize, int tcp_accept_count, int tcp_idle_timeout,
int harden_large_queries, uint32_t http_max_streams,
char* http_endpoint, int http_notls, struct tcl_list* tcp_conn_limit,
void* sslctx, struct dt_env* dtenv, struct doq_table* doq_table,
struct ub_randstate* rnd, const char* ssl_service_key,
const char* ssl_service_pem, struct config_file* cfg,
void* sslctx, void* quic_sslctx, struct dt_env* dtenv,
struct doq_table* doq_table,
struct ub_randstate* rnd,struct config_file* cfg,
comm_point_callback_type* cb, void *cb_arg);

/**
Expand Down Expand Up @@ -512,6 +511,15 @@ struct doq_table {
size_t current_size;
};

/**
* create SSL context for QUIC
* @param key: private key file.
* @param pem: public key cert.
* @param verifypem: if nonNULL, verifylocation file.
* return SSL_CTX* or NULL on failure (logged).
*/
void* quic_sslctx_create(char* key, char* pem, char* verifypem);

/** create doq table */
struct doq_table* doq_table_create(struct config_file* cfg,
struct ub_randstate* rnd);
Expand Down Expand Up @@ -712,9 +720,6 @@ int doq_timer_cmp(const void* key1, const void* key2);
/** compare function of doq_stream */
int doq_stream_cmp(const void* key1, const void* key2);

/** setup the doq_socket server tls context */
int doq_socket_setup_ctx(struct doq_server_socket* doq_socket);

/** setup the doq connection callbacks, and settings. */
int doq_conn_setup(struct doq_conn* conn, uint8_t* scid, size_t scidlen,
uint8_t* ocid, size_t ocidlen, const uint8_t* token, size_t tokenlen);
Expand Down
5 changes: 2 additions & 3 deletions testcode/fake_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -938,11 +938,10 @@ listen_create(struct comm_base* base, struct listen_port* ATTR_UNUSED(ports),
char* ATTR_UNUSED(http_endpoint),
int ATTR_UNUSED(http_notls),
struct tcl_list* ATTR_UNUSED(tcp_conn_limit),
void* ATTR_UNUSED(sslctx), struct dt_env* ATTR_UNUSED(dtenv),
void* ATTR_UNUSED(sslctx), void* ATTR_UNUSED(quic_ssl),
struct dt_env* ATTR_UNUSED(dtenv),
struct doq_table* ATTR_UNUSED(table),
struct ub_randstate* ATTR_UNUSED(rnd),
const char* ATTR_UNUSED(ssl_service_key),
const char* ATTR_UNUSED(ssl_service_pem),
struct config_file* ATTR_UNUSED(cfg),
comm_point_callback_type* cb, void *cb_arg)
{
Expand Down
6 changes: 6 additions & 0 deletions testcode/testbound.c
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,12 @@ void listen_desetup_locks(void)
}

#ifdef HAVE_NGTCP2
void* quic_sslctx_create(char* ATTR_UNUSED(key), char* ATTR_UNUSED(pem),
char* ATTR_UNUSED(verifypem))
{
return NULL;
}

void comm_point_doq_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(event),
void* ATTR_UNUSED(arg))
{
Expand Down
2 changes: 1 addition & 1 deletion util/net_help.h
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ int listen_sslctx_setup(void* ctxt);
*/
void listen_sslctx_setup_2(void* ctxt);

/**
/**
* create SSL listen context
* @param key: private key file.
* @param pem: public key cert.
Expand Down
Loading