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 */
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 */
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);
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.*/
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);
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*)
#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,
(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
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_NGTCP2
char* sid_ctx = "unbound server";
#ifndef HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_SERVER_CONTEXT
SSL_QUIC_METHOD* quic_method;
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 |
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);
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. */
SSL_CTX_set_quic_method(ctx, doq_socket->quic_method);
#endif
return ctx;
+#else /* HAVE_NGTCP2 */
+ (void)key; (void)pem; (void)verifypem;
+ return NULL;
+#endif /* HAVE_NGTCP2 */
}
/** Get the ngtcp2_conn from ssl userdata of type ngtcp2_conn_ref */
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)
* @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.
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);
/**
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);
/** 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);
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)
{
}
#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))
{
*/
void listen_sslctx_setup_2(void* ctxt);
-/**
+/**
* create SSL listen context
* @param key: private key file.
* @param pem: public key cert.
/** create new doq server socket structure */
static struct doq_server_socket*
doq_server_socket_create(struct doq_table* table, struct ub_randstate* rnd,
- const char* ssl_service_key, const char* ssl_service_pem,
- struct comm_point* c, struct comm_base* base, struct config_file* cfg)
+ const void* quic_sslctx, struct comm_point* c, struct comm_base* base,
+ struct config_file* cfg)
{
size_t doq_buffer_size = 4096; /* bytes buffer size, for one packet. */
struct doq_server_socket* doq_socket;
doq_socket->table = table;
doq_socket->rnd = rnd;
doq_socket->validate_addr = 1;
- if(ssl_service_key == NULL || ssl_service_key[0]==0) {
- log_err("doq server socket create: no tls-service-key");
- free(doq_socket);
- return NULL;
- }
- if(ssl_service_pem == NULL || ssl_service_pem[0]==0) {
- log_err("doq server socket create: no tls-service-pem");
- free(doq_socket);
- return NULL;
- }
- doq_socket->ssl_service_key = strdup(ssl_service_key);
- if(!doq_socket->ssl_service_key) {
- free(doq_socket);
- return NULL;
- }
- doq_socket->ssl_service_pem = strdup(ssl_service_pem);
- if(!doq_socket->ssl_service_pem) {
- free(doq_socket->ssl_service_key);
- free(doq_socket);
- return NULL;
- }
- doq_socket->ssl_verify_pem = NULL;
/* the doq_socket has its own copy of the static secret, as
* well as other config values, so that they do not need table.lock */
doq_socket->static_secret_len = table->static_secret_len;
doq_socket->static_secret = memdup(table->static_secret,
table->static_secret_len);
if(!doq_socket->static_secret) {
- free(doq_socket->ssl_service_key);
- free(doq_socket->ssl_service_pem);
- free(doq_socket->ssl_verify_pem);
- free(doq_socket);
- return NULL;
- }
- if(!doq_socket_setup_ctx(doq_socket)) {
- free(doq_socket->ssl_service_key);
- free(doq_socket->ssl_service_pem);
- free(doq_socket->ssl_verify_pem);
- free(doq_socket->static_secret);
free(doq_socket);
return NULL;
}
+ doq_socket->ctx = (SSL_CTX*)quic_sslctx;
doq_socket->idle_timeout = table->idle_timeout;
doq_socket->sv_scidlen = table->sv_scidlen;
doq_socket->cp = c;
doq_socket->pkt_buf = sldns_buffer_new(doq_buffer_size);
if(!doq_socket->pkt_buf) {
- free(doq_socket->ssl_service_key);
- free(doq_socket->ssl_service_pem);
- free(doq_socket->ssl_verify_pem);
free(doq_socket->static_secret);
- SSL_CTX_free(doq_socket->ctx);
free(doq_socket);
return NULL;
}
doq_socket->blocked_pkt = sldns_buffer_new(
sldns_buffer_capacity(doq_socket->pkt_buf));
if(!doq_socket->pkt_buf) {
- free(doq_socket->ssl_service_key);
- free(doq_socket->ssl_service_pem);
- free(doq_socket->ssl_verify_pem);
free(doq_socket->static_secret);
- SSL_CTX_free(doq_socket->ctx);
sldns_buffer_free(doq_socket->pkt_buf);
free(doq_socket);
return NULL;
doq_socket->blocked_paddr = calloc(1,
sizeof(*doq_socket->blocked_paddr));
if(!doq_socket->blocked_paddr) {
- free(doq_socket->ssl_service_key);
- free(doq_socket->ssl_service_pem);
- free(doq_socket->ssl_verify_pem);
free(doq_socket->static_secret);
- SSL_CTX_free(doq_socket->ctx);
sldns_buffer_free(doq_socket->pkt_buf);
sldns_buffer_free(doq_socket->blocked_pkt);
free(doq_socket);
}
doq_socket->timer = comm_timer_create(base, doq_timer_cb, doq_socket);
if(!doq_socket->timer) {
- free(doq_socket->ssl_service_key);
- free(doq_socket->ssl_service_pem);
- free(doq_socket->ssl_verify_pem);
free(doq_socket->static_secret);
- SSL_CTX_free(doq_socket->ctx);
sldns_buffer_free(doq_socket->pkt_buf);
sldns_buffer_free(doq_socket->blocked_pkt);
free(doq_socket->blocked_paddr);
if(!doq_socket)
return;
free(doq_socket->static_secret);
- SSL_CTX_free(doq_socket->ctx);
#ifndef HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_SERVER_CONTEXT
free(doq_socket->quic_method);
#endif
- free(doq_socket->ssl_service_key);
- free(doq_socket->ssl_service_pem);
- free(doq_socket->ssl_verify_pem);
sldns_buffer_free(doq_socket->pkt_buf);
sldns_buffer_free(doq_socket->blocked_pkt);
free(doq_socket->blocked_paddr);
comm_point_create_doq(struct comm_base *base, int fd, sldns_buffer* buffer,
comm_point_callback_type* callback, void* callback_arg,
struct unbound_socket* socket, struct doq_table* table,
- struct ub_randstate* rnd, const char* ssl_service_key,
- const char* ssl_service_pem, struct config_file* cfg)
+ struct ub_randstate* rnd, const void* quic_sslctx,
+ struct config_file* cfg)
{
#ifdef HAVE_NGTCP2
struct comm_point* c = (struct comm_point*)calloc(1,
c->dnscrypt = 0;
c->dnscrypt_buffer = NULL;
#endif
-#ifdef HAVE_NGTCP2
- c->doq_socket = doq_server_socket_create(table, rnd, ssl_service_key,
- ssl_service_pem, c, base, cfg);
+ c->doq_socket = doq_server_socket_create(table, rnd, quic_sslctx, c,
+ base, cfg);
if(!c->doq_socket) {
log_err("could not create doq comm_point");
comm_point_delete(c);
return NULL;
}
-#endif
c->inuse = 0;
c->callback = callback;
c->cb_arg = callback_arg;
(void)socket;
(void)rnd;
(void)table;
- (void)ssl_service_key;
- (void)ssl_service_pem;
+ (void)quic_sslctx;
(void)cfg;
sock_close(fd);
return NULL;
* @param socket: and opened socket properties will be passed to your callback function.
* @param table: the doq connection table for the host.
* @param rnd: random generator to use.
- * @param ssl_service_key: the ssl service key file.
- * @param ssl_service_pem: the ssl service pem file.
+ * @param quic_sslctx: the quic ssl context.
* @param cfg: config file struct.
* @return: returns the allocated communication point. NULL on error.
* Sets timeout to NULL. Turns off TCP options.
int fd, struct sldns_buffer* buffer,
comm_point_callback_type* callback, void* callback_arg,
struct unbound_socket* socket, struct doq_table* table,
- struct ub_randstate* rnd, const char* ssl_service_key,
- const char* ssl_service_pem, struct config_file* cfg);
+ struct ub_randstate* rnd, const void* quic_sslctx,
+ struct config_file* cfg);
/**
* Create a TCP listener comm point. Calls malloc.
struct ub_randstate* rnd;
/** if address validation is enabled */
uint8_t validate_addr;
- /** the ssl service key file */
- char* ssl_service_key;
- /** the ssl service pem file */
- char* ssl_service_pem;
- /** the ssl verify pem file */
- char* ssl_verify_pem;
/** the server scid length */
int sv_scidlen;
/** the idle timeout in nanoseconds */
if(!(daemon->listen_sslctx = listen_sslctx_create(
cfg->ssl_service_key, cfg->ssl_service_pem, NULL)))
fatal_exit("could not set up listen 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)))