From 38b78f59a08b11dc7c551dfe279df58203f2e2da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Witold=20Kr=C4=99cicki?= Date: Thu, 1 Oct 2020 13:18:47 +0200 Subject: [PATCH] Add DoT support to bind Parse the configuration of tls objects into SSL_CTX* objects. Listen on DoT if 'tls' option is setup in listen-on directive. Use DoT/DoH ports for DoT/DoH. --- bin/named/config.c | 26 ++++--- bin/named/include/named/config.h | 3 +- bin/named/include/named/globals.h | 3 +- bin/named/main.c | 16 ++-- bin/named/named.conf.rst | 1 + bin/named/server.c | 123 +++++++++++++++++++++--------- doc/misc/options | 1 + doc/misc/options.active | 1 + doc/misc/options.grammar.rst | 1 + lib/isc/netmgr/tcpdns.c | 1 + lib/isccfg/namedconf.c | 1 + lib/ns/Makefile.am | 6 +- lib/ns/include/ns/listenlist.h | 6 +- lib/ns/interfacemgr.c | 57 ++++++++++++-- lib/ns/listenlist.c | 19 ++++- 15 files changed, 199 insertions(+), 66 deletions(-) diff --git a/bin/named/config.c b/bin/named/config.c index 39a67eee12..c19a889768 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -93,6 +93,7 @@ options {\n\ nta-recheck 300;\n\ # pid-file \"" NAMED_LOCALSTATEDIR "/run/named/named.pid\"; \n\ port 53;\n\ + dot-port 853;\n\ prefetch 2 9;\n\ recursing-file \"named.recursing\";\n\ recursive-clients 1000;\n\ @@ -497,7 +498,7 @@ named_config_getiplist(const cfg_obj_t *config, const cfg_obj_t *list, } else if (defport != 0) { port = defport; } else { - result = named_config_getport(config, &port); + result = named_config_getport(config, "port", &port); if (result != ISC_R_SUCCESS) { return (result); } @@ -644,7 +645,7 @@ named_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list, /* * Get system defaults. */ - result = named_config_getport(config, &port); + result = named_config_getport(config, "port", &port); if (result != ISC_R_SUCCESS) { goto cleanup; } @@ -925,7 +926,8 @@ cleanup: } isc_result_t -named_config_getport(const cfg_obj_t *config, in_port_t *portp) { +named_config_getport(const cfg_obj_t *config, const char *type, + in_port_t *portp) { const cfg_obj_t *maps[3]; const cfg_obj_t *options = NULL; const cfg_obj_t *portobj = NULL; @@ -940,7 +942,7 @@ named_config_getport(const cfg_obj_t *config, in_port_t *portp) { maps[i++] = named_g_defaults; maps[i] = NULL; - result = named_config_get(maps, "port", &portobj); + result = named_config_get(maps, type, &portobj); INSIST(result == ISC_R_SUCCESS); if (cfg_obj_asuint32(portobj) >= UINT16_MAX) { cfg_obj_log(portobj, named_g_lctx, ISC_LOG_ERROR, @@ -980,13 +982,15 @@ named_config_getdscp(const cfg_obj_t *config, isc_dscp_t *dscpp) { struct keyalgorithms { const char *str; - enum { hmacnone, - hmacmd5, - hmacsha1, - hmacsha224, - hmacsha256, - hmacsha384, - hmacsha512 } hmac; + enum { + hmacnone, + hmacmd5, + hmacsha1, + hmacsha224, + hmacsha256, + hmacsha384, + hmacsha512 + } hmac; unsigned int type; uint16_t size; } algorithms[] = { { "hmac-md5", hmacmd5, DST_ALG_HMACMD5, 128 }, diff --git a/bin/named/include/named/config.h b/bin/named/include/named/config.h index 06a414164a..7e005a29a1 100644 --- a/bin/named/include/named/config.h +++ b/bin/named/include/named/config.h @@ -67,7 +67,8 @@ named_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list, isc_mem_t *mctx, dns_ipkeylist_t *ipkl); isc_result_t -named_config_getport(const cfg_obj_t *config, in_port_t *portp); +named_config_getport(const cfg_obj_t *config, const char *type, + in_port_t *portp); isc_result_t named_config_getkeyalgorithm(const char *str, const dns_name_t **name, diff --git a/bin/named/include/named/globals.h b/bin/named/include/named/globals.h index 78e30dbc0f..4c0569dfdf 100644 --- a/bin/named/include/named/globals.h +++ b/bin/named/include/named/globals.h @@ -72,6 +72,7 @@ EXTERN const char *named_g_srcid INIT(PACKAGE_SRCID); EXTERN const char *named_g_configargs INIT(PACKAGE_CONFIGARGS); EXTERN const char *named_g_builder INIT(PACKAGE_BUILDER); EXTERN in_port_t named_g_port INIT(0); +EXTERN in_port_t named_g_dot_port INIT(0); EXTERN isc_dscp_t named_g_dscp INIT(-1); EXTERN named_server_t *named_g_server INIT(NULL); @@ -128,7 +129,7 @@ EXTERN bool named_g_forcelock INIT(false); #if NAMED_RUN_PID_DIR EXTERN const char *named_g_defaultpidfile INIT(NAMED_LOCALSTATEDIR "/run/named/" "named.pid"); -#else /* if NAMED_RUN_PID_DIR */ +#else /* if NAMED_RUN_PID_DIR */ EXTERN const char *named_g_defaultpidfile INIT(NAMED_LOCALSTATEDIR "/run/" "named.pid"); #endif /* if NAMED_RUN_PID_DIR */ diff --git a/bin/named/main.c b/bin/named/main.c index 443263d7f4..13fbba9927 100644 --- a/bin/named/main.c +++ b/bin/named/main.c @@ -232,7 +232,7 @@ assertion_failed(const char *file, int line, isc_assertiontype_t type, NAMED_LOGMODULE_MAIN, ISC_LOG_CRITICAL, "%s", strs[i]); } -#else /* HAVE_BACKTRACE_SYMBOLS */ +#else /* HAVE_BACKTRACE_SYMBOLS */ for (int i = 0; i < nframes; i++) { isc_log_write( named_g_lctx, NAMED_LOGCATEGORY_GENERAL, @@ -521,8 +521,8 @@ printversion(bool verbose) { printf("linked to OpenSSL version: %s\n", OpenSSL_version(OPENSSL_VERSION)); -#else /* if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= \ - * 0x10100000L */ +#else /* if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= \ + * 0x10100000L */ printf("linked to OpenSSL version: %s\n", SSLeay_version(SSLEAY_VERSION)); #endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */ @@ -789,11 +789,13 @@ parse_command_line(int argc, char *argv[]) { break; case 'p': port = parse_int(isc_commandline_argument, "port"); - if (port < 1 || port > 65535) { + if (port < 1 || port > 64735) { named_main_earlyfatal("port '%s' out of range", isc_commandline_argument); } named_g_port = port; + /* XXXWPK have a separate option for that. */ + named_g_dot_port = port + 800; break; case 's': /* XXXRTH temporary syntax */ @@ -887,7 +889,7 @@ create_managers(void) { named_g_cpus, named_g_cpus == 1 ? "" : "s"); #ifdef WIN32 named_g_udpdisp = 1; -#else /* ifdef WIN32 */ +#else /* ifdef WIN32 */ if (named_g_udpdisp == 0) { named_g_udpdisp = named_g_cpus_detected; } @@ -1107,8 +1109,8 @@ setup(void) { NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, "linked to OpenSSL version: %s", OpenSSL_version(OPENSSL_VERSION)); -#else /* if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= \ - * 0x10100000L */ +#else /* if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= \ + * 0x10100000L */ isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_MAIN, ISC_LOG_NOTICE, "linked to OpenSSL version: %s", diff --git a/bin/named/named.conf.rst b/bin/named/named.conf.rst index 68d1d8eee1..34caff2e35 100644 --- a/bin/named/named.conf.rst +++ b/bin/named/named.conf.rst @@ -231,6 +231,7 @@ OPTIONS size ) ] [ versions ( unlimited | integer ) ] [ suffix ( increment | timestamp ) ]; dnstap-version ( quoted_string | none ); + dot-port integer; dscp integer; dual-stack-servers [ port integer ] { ( quoted_string [ port integer ] [ dscp integer ] | ipv4_address [ port diff --git a/bin/named/server.c b/bin/named/server.c index af3ea26442..dbdb6332c1 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -465,7 +465,7 @@ nzd_close(MDB_txn **txnp, bool commit); static isc_result_t nzd_count(dns_view_t *view, int *countp); -#else /* ifdef HAVE_LMDB */ +#else /* ifdef HAVE_LMDB */ static isc_result_t nzf_append(dns_view_t *view, const cfg_obj_t *zconfig); #endif /* ifdef HAVE_LMDB */ @@ -674,11 +674,13 @@ ta_fromconfig(const cfg_obj_t *key, bool *initialp, const char **namestrp, dns_name_t *name = NULL; isc_buffer_t namebuf; const char *atstr = NULL; - enum { INIT_DNSKEY, - STATIC_DNSKEY, - INIT_DS, - STATIC_DS, - TRUSTED } anchortype; + enum { + INIT_DNSKEY, + STATIC_DNSKEY, + INIT_DS, + STATIC_DS, + TRUSTED + } anchortype; REQUIRE(namestrp != NULL && *namestrp == NULL); REQUIRE(ds != NULL); @@ -1388,7 +1390,7 @@ configure_order(dns_order_t *order, const cfg_obj_t *ent) { if (!strcasecmp(str, "fixed")) { #if DNS_RDATASET_FIXED mode = DNS_RDATASETATTR_FIXEDORDER; -#else /* if DNS_RDATASET_FIXED */ +#else /* if DNS_RDATASET_FIXED */ mode = DNS_RDATASETATTR_CYCLIC; #endif /* DNS_RDATASET_FIXED */ } else if (!strcasecmp(str, "random")) { @@ -2475,7 +2477,7 @@ configure_rpz(dns_view_t *view, const cfg_obj_t **maps, " without `./configure --enable-dnsrps`"); return (ISC_R_FAILURE); } -#else /* ifndef USE_DNSRPS */ +#else /* ifndef USE_DNSRPS */ if (dnsrps_enabled) { if (librpz == NULL) { cfg_obj_log(rpz_obj, named_g_lctx, DNS_RPZ_ERROR_LEVEL, @@ -3962,7 +3964,7 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config, /* * Set the view's port number for outgoing queries. */ - CHECKM(named_config_getport(config, &port), "port"); + CHECKM(named_config_getport(config, "port", &port), "port"); dns_view_setdstport(view, port); /* @@ -5762,7 +5764,7 @@ configure_alternates(const cfg_obj_t *config, dns_view_t *view, /* * Determine which port to send requests to. */ - CHECKM(named_config_getport(config, &port), "port"); + CHECKM(named_config_getport(config, "port", &port), "port"); if (alternates != NULL) { portobj = cfg_tuple_get(alternates, "port"); @@ -5850,7 +5852,7 @@ configure_forward(const cfg_obj_t *config, dns_view_t *view, /* * Determine which port to send forwarded requests to. */ - CHECKM(named_config_getport(config, &port), "port"); + CHECKM(named_config_getport(config, "port", &port), "port"); if (forwarders != NULL) { portobj = cfg_tuple_get(forwarders, "port"); @@ -6735,7 +6737,8 @@ add_listenelt(isc_mem_t *mctx, ns_listenlist_t *list, isc_sockaddr_t *addr, } result = ns_listenelt_create(mctx, isc_sockaddr_getport(addr), - dscp, src_acl, &lelt); + dscp, src_acl, false, NULL, NULL, + &lelt); if (result != ISC_R_SUCCESS) { goto clean; } @@ -6822,8 +6825,7 @@ adjust_interfaces(named_server_t *server, isc_mem_t *mctx) { for (view = ISC_LIST_HEAD(server->viewlist); view != NULL && view != zoneview; view = ISC_LIST_NEXT(view, link)) - { - } + {} if (view == NULL) { continue; } @@ -7752,7 +7754,7 @@ setup_newzones(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig, return (ISC_R_FAILURE); } } -#else /* ifdef HAVE_LMDB */ +#else /* ifdef HAVE_LMDB */ UNUSED(obj); #endif /* HAVE_LMDB */ @@ -8799,7 +8801,8 @@ load_configuration(const char *filename, named_server_t *server, if (named_g_port != 0) { listen_port = named_g_port; } else { - CHECKM(named_config_getport(config, &listen_port), "port"); + CHECKM(named_config_getport(config, "port", &listen_port), + "port"); } /* @@ -9774,7 +9777,7 @@ run_server(isc_task_t *task, isc_event_t *event) { #if defined(HAVE_GEOIP2) geoip = named_g_geoip; -#else /* if defined(HAVE_GEOIP2) */ +#else /* if defined(HAVE_GEOIP2) */ geoip = NULL; #endif /* if defined(HAVE_GEOIP2) */ @@ -10860,20 +10863,67 @@ ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, cfg_aclconfctx_t *actx, isc_mem_t *mctx, uint16_t family, ns_listenelt_t **target) { isc_result_t result; - const cfg_obj_t *portobj, *dscpobj; + const cfg_obj_t *tlsobj, *portobj, *dscpobj; in_port_t port; isc_dscp_t dscp = -1; + const char *key = NULL, *cert = NULL; + bool tls = false; ns_listenelt_t *delt = NULL; REQUIRE(target != NULL && *target == NULL); + /* XXXWPK TODO be more verbose on failures. */ + tlsobj = cfg_tuple_get(listener, "tls"); + if (tlsobj != NULL && cfg_obj_isstring(tlsobj)) { + const cfg_obj_t *tlsconfigs = NULL; + const cfg_listelt_t *element; + (void)cfg_map_get(config, "tls", &tlsconfigs); + for (element = cfg_list_first(tlsconfigs); element != NULL; + element = cfg_list_next(element)) + { + cfg_obj_t *tconfig = cfg_listelt_value(element); + const cfg_obj_t *name = cfg_map_getname(tconfig); + if (!strcmp(cfg_obj_asstring(name), + cfg_obj_asstring(tlsobj))) { + tls = true; + const cfg_obj_t *keyo = NULL, *certo = NULL; + (void)cfg_map_get(tconfig, "key-file", &keyo); + if (keyo == NULL) { + return (ISC_R_FAILURE); + } + (void)cfg_map_get(tconfig, "cert-file", &certo); + if (certo == NULL) { + return (ISC_R_FAILURE); + } + key = cfg_obj_asstring(keyo); + cert = cfg_obj_asstring(certo); + break; + } + } + if (!tls) { + return (ISC_R_FAILURE); + } + } portobj = cfg_tuple_get(listener, "port"); if (!cfg_obj_isuint32(portobj)) { - if (named_g_port != 0) { - port = named_g_port; + if (tls) { + if (named_g_dot_port != 0) { + port = named_g_dot_port; + } else { + result = named_config_getport( + config, "dot-port", &port); + if (result != ISC_R_SUCCESS) { + return (result); + } + } } else { - result = named_config_getport(config, &port); - if (result != ISC_R_SUCCESS) { - return (result); + if (named_g_port != 0) { + port = named_g_port; + } else { + result = named_config_getport(config, "port", + &port); + if (result != ISC_R_SUCCESS) { + return (result); + } } } } else { @@ -10899,7 +10949,8 @@ ns_listenelt_fromconfig(const cfg_obj_t *listener, const cfg_obj_t *config, dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj); } - result = ns_listenelt_create(mctx, port, dscp, NULL, &delt); + result = ns_listenelt_create(mctx, port, dscp, NULL, tls, key, cert, + &delt); if (result != ISC_R_SUCCESS) { return (result); } @@ -13330,7 +13381,7 @@ do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, #ifndef HAVE_LMDB FILE *fp = NULL; bool cleanup_config = false; -#else /* HAVE_LMDB */ +#else /* HAVE_LMDB */ MDB_txn *txn = NULL; MDB_dbi dbi; @@ -13371,7 +13422,7 @@ do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, (void)isc_stdio_close(fp); fp = NULL; -#else /* HAVE_LMDB */ +#else /* HAVE_LMDB */ /* Make sure we can open the NZD database */ result = nzd_writable(view); if (result != ISC_R_SUCCESS) { @@ -13469,7 +13520,7 @@ do_addzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, /* Save the new zone configuration into the NZD */ CHECK(nzd_open(view, 0, &txn, &dbi)); CHECK(nzd_save(&txn, dbi, zone, zoneobj)); -#else /* ifdef HAVE_LMDB */ +#else /* ifdef HAVE_LMDB */ /* Append the zone configuration to the NZF */ result = nzf_append(view, zoneobj); #endif /* HAVE_LMDB */ @@ -13485,7 +13536,7 @@ cleanup: cfg->nzf_config, name, NULL); RUNTIME_CHECK(tresult == ISC_R_SUCCESS); } -#else /* HAVE_LMDB */ +#else /* HAVE_LMDB */ if (txn != NULL) { (void)nzd_close(&txn, false); } @@ -13510,7 +13561,7 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, #ifndef HAVE_LMDB FILE *fp = NULL; cfg_obj_t *z; -#else /* HAVE_LMDB */ +#else /* HAVE_LMDB */ MDB_txn *txn = NULL; MDB_dbi dbi; LOCK(&view->new_zone_lock); @@ -13558,7 +13609,7 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, } (void)isc_stdio_close(fp); fp = NULL; -#else /* HAVE_LMDB */ +#else /* HAVE_LMDB */ /* Make sure we can open the NZD database */ result = nzd_writable(view); if (result != ISC_R_SUCCESS) { @@ -13679,7 +13730,7 @@ do_modzone(named_server_t *server, ns_cfgctx_t *cfg, dns_view_t *view, #ifdef HAVE_LMDB CHECK(nzd_open(view, 0, &txn, &dbi)); CHECK(nzd_save(&txn, dbi, zone, zoneobj)); -#else /* ifdef HAVE_LMDB */ +#else /* ifdef HAVE_LMDB */ result = nzf_append(view, zoneobj); if (result != ISC_R_SUCCESS) { TCHECK(putstr(text, "\nNew zone config not saved: ")); @@ -13707,7 +13758,7 @@ cleanup: if (fp != NULL) { (void)isc_stdio_close(fp); } -#else /* HAVE_LMDB */ +#else /* HAVE_LMDB */ if (txn != NULL) { (void)nzd_close(&txn, false); } @@ -13752,7 +13803,7 @@ named_server_changezone(named_server_t *server, char *command, /* Are we accepting new zones in this view? */ #ifdef HAVE_LMDB if (view->new_zone_db == NULL) -#else /* ifdef HAVE_LMDB */ +#else /* ifdef HAVE_LMDB */ if (view->new_zone_file == NULL) #endif /* HAVE_LMDB */ { @@ -13898,7 +13949,7 @@ rmzone(isc_task_t *task, isc_event_t *event) { (void)nzd_close(&txn, false); } UNLOCK(&view->new_zone_lock); -#else /* ifdef HAVE_LMDB */ +#else /* ifdef HAVE_LMDB */ result = delete_zoneconf(view, cfg->add_parser, cfg->nzf_config, dns_zone_getorigin(zone), nzf_writeconf); @@ -14267,7 +14318,7 @@ named_server_showzone(named_server_t *server, isc_lex_t *lex, zconfig = find_name_in_list_from_map(cfg->nzf_config, "zone", zonename, redirect); } -#else /* HAVE_LMDB */ +#else /* HAVE_LMDB */ if (zconfig == NULL) { const cfg_obj_t *zlist = NULL; CHECK(get_newzone_config(view, zonename, &nzconfig)); @@ -15935,7 +15986,7 @@ named_server_dnstap(named_server_t *server, isc_lex_t *lex, result = dns_dt_reopen(server->dtenv, backups); return (result); -#else /* ifdef HAVE_DNSTAP */ +#else /* ifdef HAVE_DNSTAP */ UNUSED(server); UNUSED(lex); UNUSED(text); diff --git a/doc/misc/options b/doc/misc/options index 1f3daa904a..6d92b380de 100644 --- a/doc/misc/options +++ b/doc/misc/options @@ -173,6 +173,7 @@ options { ) ] [ versions ( unlimited | ) ] [ suffix ( increment | timestamp ) ]; dnstap-version ( | none ); + dot-port ; dscp ; dual-stack-servers [ port ] { ( [ port ] [ dscp ] | [ port diff --git a/doc/misc/options.active b/doc/misc/options.active index 6da3e4ee7a..76f4c546b8 100644 --- a/doc/misc/options.active +++ b/doc/misc/options.active @@ -159,6 +159,7 @@ options { ) ] [ versions ( unlimited | ) ] [ suffix ( increment | timestamp ) ]; dnstap-version ( | none ); + dot-port ; dscp ; dual-stack-servers [ port ] { ( [ port ] [ dscp ] | [ port diff --git a/doc/misc/options.grammar.rst b/doc/misc/options.grammar.rst index 9fef7669d3..2360354c3e 100644 --- a/doc/misc/options.grammar.rst +++ b/doc/misc/options.grammar.rst @@ -89,6 +89,7 @@ ) ] [ versions ( unlimited | ) ] [ suffix ( increment | timestamp ) ]; dnstap-version ( | none ); + dot-port ; dscp ; dual-stack-servers [ port ] { ( [ port ] [ dscp ] | [ port diff --git a/lib/isc/netmgr/tcpdns.c b/lib/isc/netmgr/tcpdns.c index 8004124a85..422e26d2b5 100644 --- a/lib/isc/netmgr/tcpdns.c +++ b/lib/isc/netmgr/tcpdns.c @@ -471,6 +471,7 @@ isc__nm_async_tcpdnsstop(isc__networker_t *worker, isc__netievent_t *ev0) { break; default: INSIST(0); + ISC_UNREACHABLE(); } isc__nmsocket_detach(&sock->outer); } diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index b4eed89a11..ebd0d19520 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -1201,6 +1201,7 @@ static cfg_clausedef_t options_clauses[] = { { "notify-rate", &cfg_type_uint32, 0 }, { "pid-file", &cfg_type_qstringornone, 0 }, { "port", &cfg_type_uint32, 0 }, + { "dot-port", &cfg_type_uint32, 0 }, { "querylog", &cfg_type_boolean, 0 }, { "random-device", &cfg_type_qstringornone, 0 }, { "recursing-file", &cfg_type_qstring, 0 }, diff --git a/lib/ns/Makefile.am b/lib/ns/Makefile.am index 5c93b2e85b..d430493aef 100644 --- a/lib/ns/Makefile.am +++ b/lib/ns/Makefile.am @@ -44,12 +44,14 @@ libns_la_CPPFLAGS = \ $(LIBDNS_CFLAGS) \ $(LIBISC_CFLAGS) \ $(LIBNS_CFLAGS) \ - $(LIBUV_CFLAGS) + $(LIBUV_CFLAGS) \ + $(OPENSSL_CFLAGS) libns_la_LIBADD = \ $(LIBDNS_LIBS) \ $(LIBISC_LIBS) \ - $(LIBUV_LIBS) + $(LIBUV_LIBS) \ + $(OPENSSL_LIBS) libns_la_LDFLAGS = \ $(AM_LDFLAGS) \ diff --git a/lib/ns/include/ns/listenlist.h b/lib/ns/include/ns/listenlist.h index 22a6af0d5b..d3ced20034 100644 --- a/lib/ns/include/ns/listenlist.h +++ b/lib/ns/include/ns/listenlist.h @@ -31,6 +31,8 @@ #include +#include + /*** *** Types ***/ @@ -43,6 +45,7 @@ struct ns_listenelt { in_port_t port; isc_dscp_t dscp; /* -1 = not set, 0..63 */ dns_acl_t *acl; + SSL_CTX * sslctx; ISC_LINK(ns_listenelt_t) link; }; @@ -58,7 +61,8 @@ struct ns_listenlist { isc_result_t ns_listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp, - dns_acl_t *acl, ns_listenelt_t **target); + dns_acl_t *acl, bool tls, const char *key, const char *cert, + ns_listenelt_t **target); /*%< * Create a listen-on list element. */ diff --git a/lib/ns/interfacemgr.c b/lib/ns/interfacemgr.c index 193e7e62cb..ae8c1c2406 100644 --- a/lib/ns/interfacemgr.c +++ b/lib/ns/interfacemgr.c @@ -502,10 +502,48 @@ ns_interface_listentcp(ns_interface_t *ifp) { return (result); } +/* + * XXXWPK we should probably pass a complete object with key, cert, and other + * TLS related options. + */ +static isc_result_t +ns_interface_listentls(ns_interface_t *ifp, SSL_CTX *sslctx) { + isc_result_t result; + SSL_CTX *ctx = NULL; + + result = isc_nm_listentlsdns( + ifp->mgr->nm, (isc_nmiface_t *)&ifp->addr, ns__client_request, + ifp, ns__client_tcpconn, ifp, sizeof(ns_client_t), + ifp->mgr->backlog, &ifp->mgr->sctx->tcpquota, sslctx, + &ifp->tcplistensocket); + + if (result != ISC_R_SUCCESS) { + isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, + "creating TLS socket: %s", + isc_result_totext(result)); + SSL_CTX_free(ctx); + return (result); + } + + /* + * We call this now to update the tcp-highwater statistic: + * this is necessary because we are adding to the TCP quota just + * by listening. + */ + result = ns__client_tcpconn(NULL, ISC_R_SUCCESS, ifp); + if (result != ISC_R_SUCCESS) { + isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, + "updating TCP stats: %s", + isc_result_totext(result)); + } + + return (result); +} + static isc_result_t ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, const char *name, ns_interface_t **ifpret, bool accept_tcp, - isc_dscp_t dscp, bool *addr_in_use) { + ns_listenelt_t *elt, bool *addr_in_use) { isc_result_t result; ns_interface_t *ifp = NULL; REQUIRE(ifpret != NULL && *ifpret == NULL); @@ -516,7 +554,16 @@ ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, return (result); } - ifp->dscp = dscp; + ifp->dscp = elt->dscp; + + if (elt->sslctx != NULL) { + result = ns_interface_listentls(ifp, elt->sslctx); + if (result != ISC_R_SUCCESS) { + goto cleanup_interface; + } + *ifpret = ifp; + return (result); + } result = ns_interface_listenudp(ifp); if (result != ISC_R_SUCCESS) { @@ -865,7 +912,7 @@ do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, bool verbose) { le->port); result = ns_interface_setup(mgr, &listen_addr, "", &ifp, true, - le->dscp, NULL); + le, NULL); if (result == ISC_R_SUCCESS) { ifp->flags |= NS_INTERFACEFLAG_ANYADDR; } else { @@ -1087,8 +1134,8 @@ do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, bool verbose) { result = ns_interface_setup( mgr, &listen_sockaddr, interface.name, - &ifp, (adjusting) ? false : true, - le->dscp, &addr_in_use); + &ifp, (adjusting) ? false : true, le, + &addr_in_use); tried_listening = true; if (!addr_in_use) { diff --git a/lib/ns/listenlist.c b/lib/ns/listenlist.c index cf23b3f617..50e71023d6 100644 --- a/lib/ns/listenlist.c +++ b/lib/ns/listenlist.c @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -25,8 +26,10 @@ destroy(ns_listenlist_t *list); isc_result_t ns_listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp, - dns_acl_t *acl, ns_listenelt_t **target) { + dns_acl_t *acl, bool tls, const char *key, const char *cert, + ns_listenelt_t **target) { ns_listenelt_t *elt = NULL; + isc_result_t result = ISC_R_SUCCESS; REQUIRE(target != NULL && *target == NULL); elt = isc_mem_get(mctx, sizeof(*elt)); elt->mctx = mctx; @@ -34,6 +37,13 @@ ns_listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp, elt->port = port; elt->dscp = dscp; elt->acl = acl; + elt->sslctx = NULL; + if (tls) { + result = isc_nm_tls_create_server_ctx(key, cert, &elt->sslctx); + if (result != ISC_R_SUCCESS) { + return (result); + } + } *target = elt; return (ISC_R_SUCCESS); } @@ -43,6 +53,10 @@ ns_listenelt_destroy(ns_listenelt_t *elt) { if (elt->acl != NULL) { dns_acl_detach(&elt->acl); } + if (elt->sslctx != NULL) { + SSL_CTX_free(elt->sslctx); + elt->sslctx = NULL; + } isc_mem_put(elt->mctx, elt, sizeof(*elt)); } @@ -104,7 +118,8 @@ ns_listenlist_default(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp, goto cleanup; } - result = ns_listenelt_create(mctx, port, dscp, acl, &elt); + result = ns_listenelt_create(mctx, port, dscp, acl, false, NULL, NULL, + &elt); if (result != ISC_R_SUCCESS) { goto cleanup_acl; }