From 961370d49f68a6e53358ccbb789e4521538bdfb5 Mon Sep 17 00:00:00 2001 From: Nicolas Williams Date: Thu, 22 Jan 2026 20:57:07 -0600 Subject: [PATCH] krb5: Add support for "Directional" host address type Currently the Directional host address type is pretty useless, since it's only useful in application protocols that a) use KRB-PRIV/KRB-SAFE messages (so: not GSS-API applications), and b) state in their specs to use Directional, or otherwise provide for negotiation of host address types. There are no such protocols that we care about except -since we control it- iprop. But even for iprop it'd be better to switch to GSS-API. --- lib/krb5/addr_families.c | 67 ++++++++++++++++++++++++++++++++++++++++ lib/krb5/krb5.h | 11 ++++--- 2 files changed, 73 insertions(+), 5 deletions(-) diff --git a/lib/krb5/addr_families.c b/lib/krb5/addr_families.c index d8de39a3f..b39cc22a3 100644 --- a/lib/krb5/addr_families.c +++ b/lib/krb5/addr_families.c @@ -734,6 +734,56 @@ addrport_print_addr (const krb5_address *addr, char *str, size_t len) return ret_len; } +/* + * RFC 4120 section 7.1 "Directional" address type (type 3). + * + * Used in KRB-SAFE, KRB-PRIV, and KRB-CRED s-address/r-address fields when + * the actual network addresses aren't available (e.g., behind NAT). + * + * The address data is a 4-byte value in network byte order: + * 0 = sender + * 1 = recipient + */ + +static int +directional_print_addr(const krb5_address *addr, char *str, size_t len) +{ + unsigned long value; + + if (addr->address.length == 4) { + _krb5_get_int(addr->address.data, &value, 4); + if (value == 0) + return snprintf(str, len, "DIRECTIONAL:client"); + if (value == 1) + return snprintf(str, len, "DIRECTIONAL:server"); + return snprintf(str, len, "DIRECTIONAL:", value); + } + return snprintf(str, len, "DIRECTIONAL:"); +} + +static int +directional_parse_addr(krb5_context context, const char *address, + krb5_address *addr) +{ + unsigned long value; + unsigned char buf[4]; + + if (strncasecmp(address, "DIRECTIONAL:", 12) != 0) + return -1; + address += 12; + + if (strcasecmp(address, "client") == 0) + value = 0; + else if (strcasecmp(address, "server") == 0) + value = 1; + else + return -1; + + addr->addr_type = KRB5_ADDRESS_DIRECTIONAL; + _krb5_put_int(buf, value, 4); + return krb5_data_copy(&addr->address, buf, 4); +} + static const struct addr_operations at[] = { { AF_INET, KRB5_ADDRESS_INET, sizeof(struct sockaddr_in), @@ -807,6 +857,23 @@ static const struct addr_operations at[] = { NULL, NULL, NULL + }, + { + KRB5_ADDRESS_DIRECTIONAL, KRB5_ADDRESS_DIRECTIONAL, 0, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + directional_print_addr, + directional_parse_addr, + NULL, + NULL, + NULL, + NULL } }; diff --git a/lib/krb5/krb5.h b/lib/krb5/krb5.h index 593d1a366..6c9fb0881 100644 --- a/lib/krb5/krb5.h +++ b/lib/krb5/krb5.h @@ -333,11 +333,12 @@ typedef struct krb5_preauthdata { }krb5_preauthdata; typedef enum krb5_address_type { - KRB5_ADDRESS_INET = 2, - KRB5_ADDRESS_NETBIOS = 20, - KRB5_ADDRESS_INET6 = 24, - KRB5_ADDRESS_ADDRPORT = 256, - KRB5_ADDRESS_IPPORT = 257 + KRB5_ADDRESS_INET = 2, + KRB5_ADDRESS_DIRECTIONAL = 3, + KRB5_ADDRESS_NETBIOS = 20, + KRB5_ADDRESS_INET6 = 24, + KRB5_ADDRESS_ADDRPORT = 256, + KRB5_ADDRESS_IPPORT = 257 } krb5_address_type; enum {