Use AI_NUMERICSERV if block_dns, and use local getaddrinfo to audit.

This change has two parts:

1. Provide our own local implementation of numeric-only getaddrinfo
   in auditdns.c used to audit for DNS leaks, rather than deferring
   to dlsym(RTLD_NEXT, "getaddrinfo"), in terms of inet_pton.

   To keep review and implementation simple, this is limited to
   AI_NUMERICHOST _and_ AI_NUMERICSERV -- this requires that we
   arrange to pass AI_NUMERICSERV in callers too.

2. Wherever we implement block_dns, set AI_NUMERICSERV in addition to
   AI_NUMERICHOST as needed by the new auditdns.c getaddrinfo.

   (In principle this might also avoid other network leaks -- POSIX
   guarantees no name resolution service will be invoked, and gives
   NIS+ as an example.)

   One tiny semantic change to avoid tripping over the auditor:
   kadmin(8) now uses the string "749" rather than the string
   "kerberos-adm".  (Currently we don't audit kadmin(8) for DNS leaks
   but let's avoid leaving a rake to step on.)  Every other caller I
   found is already guaranteed to pass a numeric service rather than
   named service to getaddrinfo.

fix https://github.com/heimdal/heimdal/issues/1212
This commit is contained in:
Taylor R Campbell
2024-01-09 04:23:24 +00:00
committed by Nico Williams
parent 1d8f4347bb
commit e75e549252
11 changed files with 305 additions and 22 deletions

View File

@@ -574,7 +574,7 @@ kadm_connect(kadm5_client_context *ctx)
if (krb5_config_get_bool(context, NULL, "libdefaults", "block_dns",
NULL)) {
hints.ai_flags &= ~AI_CANONNAME;
hints.ai_flags |= AI_NUMERICHOST;
hints.ai_flags |= AI_NUMERICHOST|AI_NUMERICSERV;
}
error = getaddrinfo(hostname, portstr, &hints, &ai);
if (error) {

View File

@@ -73,7 +73,7 @@ connect_to_master (krb5_context context, const char *master,
if (krb5_config_get_bool(context, NULL, "libdefaults", "block_dns",
NULL)) {
hints.ai_flags &= ~AI_CANONNAME;
hints.ai_flags |= AI_NUMERICHOST;
hints.ai_flags |= AI_NUMERICHOST|AI_NUMERICSERV;
}
error = getaddrinfo(master, port_str, &hints, &ai);
if (error) {

View File

@@ -2720,7 +2720,7 @@ kadm5_log_signal_socket_info(krb5_context context,
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_NUMERICHOST;
hints.ai_flags = AI_NUMERICHOST|AI_NUMERICSERV;
if (server_end)
hints.ai_flags |= AI_PASSIVE;
hints.ai_family = AF_INET;

View File

@@ -1213,7 +1213,7 @@ krb5_parse_address(krb5_context context,
if (krb5_config_get_bool(context, NULL, "libdefaults", "block_dns",
NULL)) {
hint.ai_flags &= ~AI_CANONNAME;
hint.ai_flags |= AI_NUMERICHOST;
hint.ai_flags |= AI_NUMERICHOST|AI_NUMERICSERV;
}
error = getaddrinfo (string, NULL, &hint, &ai);
if (error) {

View File

@@ -353,7 +353,7 @@ get_addresses(krb5_context context,
if (krb5_config_get_bool(context, NULL, "libdefaults", "block_dns",
NULL)) {
hints.ai_flags &= ~AI_CANONNAME;
hints.ai_flags |= AI_NUMERICHOST;
hints.ai_flags |= AI_NUMERICHOST|AI_NUMERICSERV;
}
eai = getaddrinfo(hostname, NULL, &hints, &ai);
if (eai) {

View File

@@ -433,7 +433,7 @@ krb5_krbhst_get_addrinfo(krb5_context context, krb5_krbhst_info *host,
if (krb5_config_get_bool(context, NULL, "libdefaults", "block_dns",
NULL)) {
hints.ai_flags &= ~AI_CANONNAME;
hints.ai_flags |= AI_NUMERICHOST;
hints.ai_flags |= AI_NUMERICHOST|AI_NUMERICSERV;
}
ret = getaddrinfo(host->hostname, portstr, &hints, &host->ai);
if (ret) {
@@ -558,7 +558,7 @@ fallback_get_hosts(krb5_context context, struct krb5_krbhst_data *kd,
if (krb5_config_get_bool(context, NULL, "libdefaults", "block_dns",
NULL)) {
hints.ai_flags &= ~AI_CANONNAME;
hints.ai_flags |= AI_NUMERICHOST;
hints.ai_flags |= AI_NUMERICHOST|AI_NUMERICSERV;
}
ret = getaddrinfo(host, portstr, &hints, &ai);
if (ret) {

View File

@@ -860,7 +860,7 @@ submit_request(krb5_context context, krb5_sendto_ctx ctx, krb5_krbhst_info *hi)
if (krb5_config_get_bool(context, NULL, "libdefaults", "block_dns",
NULL)) {
hints.ai_flags &= ~AI_CANONNAME;
hints.ai_flags |= AI_NUMERICHOST;
hints.ai_flags |= AI_NUMERICHOST|AI_NUMERICSERV;
}
ret = getaddrinfo(proxy, portstr, &hints, &ai);
free(proxy2);

View File

@@ -205,7 +205,7 @@ check_host(krb5_context context, const char *path, char *data)
if (krb5_config_get_bool(context, NULL, "libdefaults", "block_dns",
NULL)) {
hints.ai_flags &= ~AI_CANONNAME;
hints.ai_flags |= AI_NUMERICHOST;
hints.ai_flags |= AI_NUMERICHOST|AI_NUMERICSERV;
}
ret = getaddrinfo(hostname, service, &hints, &ai);
if (ret == EAI_SERVICE && !isdigit((unsigned char)service[0])) {

View File

@@ -49,7 +49,7 @@ get_address(int flags, struct addrinfo ** ret)
memset(&ai, 0, sizeof(ai));
ai.ai_flags = flags | AI_NUMERICHOST;
ai.ai_flags = flags | AI_NUMERICHOST | AI_NUMERICSERV;
ai.ai_family = AF_INET;
ai.ai_socktype = SOCK_STREAM;
ai.ai_protocol = PF_UNSPEC;