krb5 commit: Add underpinnings of UNIX domain socket support
ghudson at mit.edu
ghudson at mit.edu
Wed Dec 11 17:02:51 EST 2024
https://github.com/krb5/krb5/commit/a575589ef525fb139cafa0de1a05382845f0afbd
commit a575589ef525fb139cafa0de1a05382845f0afbd
Author: Andreas Schneider <asn at samba.org>
Date: Tue Jul 9 11:32:34 2024 +0200
Add underpinnings of UNIX domain socket support
Add sa2sun() and ss2sun() helpers to socket-utils.h. Add UNIX domain
socket support to sa_socklen() and print_addr(). Expand buffers for
printing addresses to 128 bytes to accomodate the maximum UNIX domain
socket path length.
Add loop_add_unix_socket() to net-server.c, primarily using the
existing TCP support (renamed to "stream").
As there is no standard Kerberos address type for UNIX domain sockets,
add basic directional address support. Add a definition for
ADDRTYPE_DIRECTIONAL in krb5.h. Add private constant krb5_address
objects to libkrb5 for initiator and acceptor directional addresses.
Use directional addresses for the KRB-SAFE/KRB-PRIV source address in
the kprop and password change protocols when the transport is not IPv4
or IPv6.
krb5_address objects are used for auditing purposes in the KDC audit
and KDB pluggable interfaces. Add a local-use address type
ADDRTYPE_UNIXSOCK for use in these cases. Add a flag to
k5_sockaddr_to_address() to indicate whether this address type can be
used. Add UNIX domains socket conversion support to the test audit
plugin module.
[ghudson at mit.edu: combined several commits; used directional addresses
for KRB-SAFE/KRB-PRIV; reduced duplication in net-server.c support;
wrote commit message. Also based on work by Alexander Bokovoy.]
ticket: 9155
doc/appdev/refs/macros/index.rst | 2 +
src/include/k5-int.h | 12 ++-
src/include/krb5/krb5.hin | 9 +++
src/include/net-server.h | 1 +
src/include/port-sockets.h | 1 +
src/include/socket-utils.h | 14 ++++
src/kadmin/server/schpw.c | 6 +-
src/kdc/dispatch.c | 2 +-
src/kdc/kdc_audit.c | 2 +-
src/kdc/kdc_log.c | 8 +-
src/kdc/kdc_util.c | 2 +-
src/kprop/kprop.c | 4 +-
src/kprop/kpropd.c | 4 +-
src/lib/apputils/net-server.c | 169 +++++++++++++++++++++++++++++----------
src/lib/krb5/libkrb5.exports | 2 +
src/lib/krb5/os/addr.c | 21 ++++-
src/lib/krb5/os/changepw.c | 6 ++
src/plugins/audit/j_dict.h | 1 +
src/plugins/audit/kdc_j_encode.c | 11 +++
19 files changed, 216 insertions(+), 61 deletions(-)
diff --git a/doc/appdev/refs/macros/index.rst b/doc/appdev/refs/macros/index.rst
index 645b59f02..c1bda5c6c 100644
--- a/doc/appdev/refs/macros/index.rst
+++ b/doc/appdev/refs/macros/index.rst
@@ -9,6 +9,7 @@ Public
ADDRTYPE_ADDRPORT.rst
ADDRTYPE_CHAOS.rst
+ ADDRTYPE_DIRECTIONAL.rst
ADDRTYPE_DDP.rst
ADDRTYPE_INET.rst
ADDRTYPE_INET6.rst
@@ -17,6 +18,7 @@ Public
ADDRTYPE_IS_LOCAL.rst
ADDRTYPE_NETBIOS.rst
ADDRTYPE_XNS.rst
+ ADDRTYPE_UNIXSOCK.rst
AD_TYPE_EXTERNAL.rst
AD_TYPE_FIELD_TYPE_MASK.rst
AD_TYPE_REGISTERED.rst
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
index 12eb114a4..ec9e320e1 100644
--- a/src/include/k5-int.h
+++ b/src/include/k5-int.h
@@ -2409,13 +2409,19 @@ krb5_error_code
k5_hmac_md5(const krb5_data *key, const krb5_crypto_iov *data, size_t num_data,
krb5_data *output);
+/* Address objects for initiator and acceptor directional addresses. */
+extern const krb5_address k5_addr_directional_init;
+extern const krb5_address k5_addr_directional_accept;
+
/*
* Translate sa to a krb5_address, putting the result in *out with contents
- * aliased from *sa. Return KRB5_PROG_ATYPE_NOSUPP if sa is not an IPv4 or
- * IPv6 address.
+ * aliased from *sa. If local_use is true, translate UNIX domain socket names
+ * to ADDRTYPE_UNIXSOCK; otherwise do not handle them. Return
+ * KRB5_PROG_ATYPE_NOSUPP if sa cannot be converted.
*/
krb5_error_code
-k5_sockaddr_to_address(const struct sockaddr *sa, krb5_address *out);
+k5_sockaddr_to_address(const struct sockaddr *sa, krb5_boolean local_use,
+ krb5_address *out);
/* Place a printable representation of sa (without port) into buf. */
void
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
index c6998adc5..b5d295f33 100644
--- a/src/include/krb5/krb5.hin
+++ b/src/include/krb5/krb5.hin
@@ -322,6 +322,7 @@ typedef struct _krb5_address {
/* per Kerberos v5 protocol spec */
#define ADDRTYPE_INET 0x0002
+#define ADDRTYPE_DIRECTIONAL 0x0003
#define ADDRTYPE_CHAOS 0x0005
#define ADDRTYPE_XNS 0x0006
#define ADDRTYPE_ISO 0x0007
@@ -332,6 +333,14 @@ typedef struct _krb5_address {
#define ADDRTYPE_ADDRPORT 0x0100
#define ADDRTYPE_IPPORT 0x0101
+/*
+ * Negative values for the host address type are reserved for local use. Do
+ * not use these types in Kerberos protocol elements.
+ */
+
+/* The contents field contains a UNIX domain socket path. */
+#define ADDRTYPE_UNIXSOCK (0x8000 | 0x0001)
+
/* macros to determine if a type is a local type */
#define ADDRTYPE_IS_LOCAL(addrtype) (addrtype & 0x8000)
diff --git a/src/include/net-server.h b/src/include/net-server.h
index 14fc23a43..8ac3ff26f 100644
--- a/src/include/net-server.h
+++ b/src/include/net-server.h
@@ -59,6 +59,7 @@ krb5_error_code loop_add_rpc_service(int default_port, const char *addresses,
u_long prognum, u_long versnum,
void (*dispatchfn)(struct svc_req *,
SVCXPRT *));
+krb5_error_code loop_add_unix_socket(const char *socket_paths);
krb5_error_code loop_setup_network(verto_ctx *ctx, void *handle,
const char *progname,
diff --git a/src/include/port-sockets.h b/src/include/port-sockets.h
index 228e4cf05..459cd8667 100644
--- a/src/include/port-sockets.h
+++ b/src/include/port-sockets.h
@@ -157,6 +157,7 @@ typedef int socklen_t;
#include <sys/types.h>
#include <netinet/in.h> /* For struct sockaddr_in and in_addr */
+#include <sys/un.h> /* For struct sockaddr_un */
#include <arpa/inet.h> /* For inet_ntoa */
#include <netdb.h>
#include <string.h> /* For memset */
diff --git a/src/include/socket-utils.h b/src/include/socket-utils.h
index d379b37e1..177662c87 100644
--- a/src/include/socket-utils.h
+++ b/src/include/socket-utils.h
@@ -90,6 +90,16 @@ static inline struct sockaddr_in6 *ss2sin6 (struct sockaddr_storage *ss)
{
return (struct sockaddr_in6 *) ss;
}
+#ifndef _WIN32
+static inline const struct sockaddr_un *sa2sun(const struct sockaddr *sa)
+{
+ return (const struct sockaddr_un *)(void *)sa;
+}
+static inline struct sockaddr_un *ss2sun(struct sockaddr_storage *ss)
+{
+ return (struct sockaddr_un *)ss;
+}
+#endif
/* Set the IPv4 or IPv6 port on sa to port. Do nothing if sa is not an
* Internet socket. */
@@ -141,6 +151,10 @@ sa_socklen(const struct sockaddr *sa)
return sizeof(struct sockaddr_in6);
else if (sa->sa_family == AF_INET)
return sizeof(struct sockaddr_in);
+#ifndef _WIN32
+ else if (sa->sa_family == AF_UNIX)
+ return sizeof(struct sockaddr_un);
+#endif
else
abort();
}
diff --git a/src/kadmin/server/schpw.c b/src/kadmin/server/schpw.c
index d366c050a..5b73a3d8d 100644
--- a/src/kadmin/server/schpw.c
+++ b/src/kadmin/server/schpw.c
@@ -40,7 +40,7 @@ process_chpw_request(krb5_context context, void *server_handle, char *realm,
const char *errmsg = NULL;
size_t clen;
char *cdots;
- char addrbuf[100];
+ char addrbuf[128];
*rep = empty_data();
@@ -286,8 +286,8 @@ chpwfail:
cipher = empty_data();
if (ap_rep.length) {
- if (k5_sockaddr_to_address(local_addr, &laddr) != 0)
- abort();
+ if (k5_sockaddr_to_address(local_addr, FALSE, &laddr) != 0)
+ laddr = k5_addr_directional_accept;
ret = krb5_auth_con_setaddrs(context, auth_context, &laddr, NULL);
if (ret) {
numresult = KRB5_KPASSWD_HARDERROR;
diff --git a/src/kdc/dispatch.c b/src/kdc/dispatch.c
index 13d17b6d3..46b1c8b44 100644
--- a/src/kdc/dispatch.c
+++ b/src/kdc/dispatch.c
@@ -116,7 +116,7 @@ dispatch(void *cb, const struct sockaddr *local_addr,
if (kdc_check_lookaside(kdc_err_context, pkt, &response)) {
/* a hit! */
const char *name = 0;
- char buf[46];
+ char buf[128];
k5_print_addr(remote_addr, buf, sizeof(buf));
if (name == 0)
diff --git a/src/kdc/kdc_audit.c b/src/kdc/kdc_audit.c
index a5e022489..9ce8263d2 100644
--- a/src/kdc/kdc_audit.c
+++ b/src/kdc/kdc_audit.c
@@ -188,7 +188,7 @@ kau_init_kdc_req(krb5_context context,
if (state == NULL)
return ret;
- ret = k5_sockaddr_to_address(from, &addr);
+ ret = k5_sockaddr_to_address(from, TRUE, &addr);
if (ret)
addr = unknown_addr;
ret = krb5_copy_addr(context, &addr, &state->cl_addr);
diff --git a/src/kdc/kdc_log.c b/src/kdc/kdc_log.c
index 6278d645a..0291362d4 100644
--- a/src/kdc/kdc_log.c
+++ b/src/kdc/kdc_log.c
@@ -63,7 +63,7 @@ log_as_req(krb5_context context,
krb5_timestamp authtime,
const char *status, krb5_error_code errcode, const char *emsg)
{
- char fromstring[70];
+ char fromstring[128];
char *ktypestr = NULL;
const char *cname2 = cname ? cname : "<unknown client>";
const char *sname2 = sname ? sname : "<unknown server>";
@@ -88,8 +88,8 @@ log_as_req(krb5_context context,
ktypestr ? ktypestr : "", fromstring, status, cname2,
sname2, emsg ? ", " : "", emsg ? emsg : "");
}
- (void)k5_sockaddr_to_address(local_addr, &laddr);
- (void)k5_sockaddr_to_address(remote_addr, &raddr);
+ (void)k5_sockaddr_to_address(local_addr, TRUE, &laddr);
+ (void)k5_sockaddr_to_address(remote_addr, TRUE, &raddr);
krb5_db_audit_as_req(context, request, &laddr, &raddr, client, server,
authtime, errcode);
@@ -123,7 +123,7 @@ log_tgs_req(krb5_context ctx, const struct sockaddr *from,
const char *status, krb5_error_code errcode, const char *emsg)
{
char *ktypestr = NULL, *rep_etypestr = NULL;
- char fromstring[70];
+ char fromstring[128];
char *cname = NULL, *sname = NULL, *altcname = NULL;
char *logcname = NULL, *logsname = NULL, *logaltcname = NULL;
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
index b7249c083..6f88afa2d 100644
--- a/src/kdc/kdc_util.c
+++ b/src/kdc/kdc_util.c
@@ -194,7 +194,7 @@ kdc_process_tgs_req(kdc_realm_t *realm, krb5_kdc_req *request,
/* If from_addr isn't IPv4 or IPv6, fake up an address that won't be
* matched if the ticket has an address list. */
- retval = k5_sockaddr_to_address(from, &from_addr);
+ retval = k5_sockaddr_to_address(from, FALSE, &from_addr);
if (retval)
from_addr = nomatch_addr;
retval = krb5_auth_con_setaddrs(context, auth_context, NULL, &from_addr);
diff --git a/src/kprop/kprop.c b/src/kprop/kprop.c
index cb5c5267a..5adf430ac 100644
--- a/src/kprop/kprop.c
+++ b/src/kprop/kprop.c
@@ -269,8 +269,8 @@ open_connection(krb5_context context, char *host, int *fd_out)
com_err(progname, errno, _("while getting local socket address"));
exit(1);
}
- if (k5_sockaddr_to_address(ss2sa(&my_sin), &addr) != 0)
- abort();
+ if (k5_sockaddr_to_address(ss2sa(&my_sin), FALSE, &addr) != 0)
+ addr = k5_addr_directional_init;
retval = krb5_copy_addr(context, &addr, &sender_addr);
if (retval) {
com_err(progname, retval, _("while converting local address"));
diff --git a/src/kprop/kpropd.c b/src/kprop/kpropd.c
index d6deb4738..4b3675264 100644
--- a/src/kprop/kpropd.c
+++ b/src/kprop/kpropd.c
@@ -1199,8 +1199,8 @@ kerberos_authenticate(krb5_context context, int fd, krb5_principal *clientp,
exit(1);
}
- if (k5_sockaddr_to_address(ss2sa(my_sin), &addr) != 0)
- abort();
+ if (k5_sockaddr_to_address(ss2sa(my_sin), FALSE, &addr) != 0)
+ addr = k5_addr_directional_accept;
retval = krb5_copy_addr(context, &addr, &receiver_addr);
if (retval) {
com_err(progname, retval, _("while converting local address"));
diff --git a/src/lib/apputils/net-server.c b/src/lib/apputils/net-server.c
index 3713b5026..6fa8a97e0 100644
--- a/src/lib/apputils/net-server.c
+++ b/src/lib/apputils/net-server.c
@@ -39,6 +39,7 @@
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
+#include <sys/un.h>
#ifdef HAVE_SYS_SOCKIO_H
/* for SIOCGIFCONF, etc. */
#include <sys/sockio.h>
@@ -67,8 +68,8 @@
/* XXX */
#define KDC5_NONET (-1779992062L)
-static int tcp_or_rpc_data_counter;
-static int max_tcp_or_rpc_data_connections = 45;
+static int stream_data_counter;
+static int max_stream_data_connections = 45;
static int
setreuseaddr(int sock, int value)
@@ -97,17 +98,29 @@ setv6only(int sock, int value)
/* KDC data. */
enum conn_type {
- CONN_UDP, CONN_TCP_LISTENER, CONN_TCP, CONN_RPC_LISTENER, CONN_RPC
+ CONN_UDP, CONN_TCP_LISTENER, CONN_TCP, CONN_RPC_LISTENER, CONN_RPC,
+ CONN_UNIXSOCK_LISTENER, CONN_UNIXSOCK
+};
+
+static const char *const conn_type_names[] = {
+ [CONN_UDP] = "UDP",
+ [CONN_TCP_LISTENER] = "TCP listener",
+ [CONN_TCP] = "TCP",
+ [CONN_RPC_LISTENER] = "RPC listener",
+ [CONN_RPC] = "RPC",
+ [CONN_UNIXSOCK_LISTENER] = "UNIX domain socket listener",
+ [CONN_UNIXSOCK] = "UNIX domain socket"
};
enum bind_type {
- UDP, TCP, RPC
+ UDP, TCP, RPC, UNX
};
static const char *const bind_type_names[] = {
[UDP] = "UDP",
[TCP] = "TCP",
[RPC] = "RPC",
+ [UNX] = "UNIXSOCK",
};
/* Per-connection info. */
@@ -119,7 +132,7 @@ struct connection {
/* Connection fields (TCP or RPC) */
struct sockaddr_storage addr_s;
socklen_t addrlen;
- char addrbuf[56];
+ char addrbuf[128];
/* Incoming data (TCP) */
size_t bufsiz;
@@ -262,10 +275,10 @@ loop_setup_signals(verto_ctx *ctx, void *handle, void (*reset)(void *))
*
* Arguments:
* - address
- * A string for the address (or hostname). Pass NULL to use the wildcard
- * address. The address is parsed with k5_parse_host_string().
+ * An address string, hostname, or UNIX socket path.
+ * Pass NULL to use the wildcard address for IP sockets.
* - port
- * What port the socket should be set to.
+ * What port the socket should be set to (for IPv4 or IPv6).
* - type
* bind_type for the socket.
* - rpc_data
@@ -371,6 +384,19 @@ loop_add_addresses(const char *addresses, int default_port,
/* Loop through each address in the string and add it to the loop. */
addr = strtok_r(addresses_copy, ADDRESSES_DELIM, &saveptr);
for (; addr != NULL; addr = strtok_r(NULL, ADDRESSES_DELIM, &saveptr)) {
+ if (type == UNX) {
+ /* Skip non-pathnames when binding UNIX domain sockets. */
+ if (*addr != '/')
+ continue;
+ ret = loop_add_address(addr, 0, type, rpc_data);
+ if (ret)
+ goto cleanup;
+ continue;
+ } else if (*addr == '/') {
+ /* Skip pathnames when not binding UNIX domain sockets. */
+ continue;
+ }
+
/* Parse the host string. */
ret = k5_parse_host_string(addr, default_port, &host, &port);
if (ret)
@@ -416,6 +442,16 @@ loop_add_rpc_service(int default_port, const char *addresses, u_long prognum,
return loop_add_addresses(addresses, default_port, RPC, &svc);
}
+krb5_error_code
+loop_add_unix_socket(const char *socket_paths)
+{
+ /* There is no wildcard or default UNIX domain socket. */
+ if (socket_paths == NULL)
+ return 0;
+
+ return loop_add_addresses(socket_paths, 0, UNX, NULL);
+}
+
#define USE_AF AF_INET
#define USE_TYPE SOCK_DGRAM
#define USE_PROTO 0
@@ -484,7 +520,8 @@ free_socket(verto_ctx *ctx, verto_ev *ev)
}
/* Fall through. */
case CONN_TCP:
- tcp_or_rpc_data_counter--;
+ case CONN_UNIXSOCK:
+ stream_data_counter--;
break;
default:
break;
@@ -548,9 +585,9 @@ add_fd(int sock, enum conn_type conntype, verto_ev_flag flags, void *handle,
}
static void process_packet(verto_ctx *ctx, verto_ev *ev);
-static void accept_tcp_connection(verto_ctx *ctx, verto_ev *ev);
-static void process_tcp_connection_read(verto_ctx *ctx, verto_ev *ev);
-static void process_tcp_connection_write(verto_ctx *ctx, verto_ev *ev);
+static void accept_stream_connection(verto_ctx *ctx, verto_ev *ev);
+static void process_stream_connection_read(verto_ctx *ctx, verto_ev *ev);
+static void process_stream_connection_write(verto_ctx *ctx, verto_ev *ev);
static void accept_rpc_connection(verto_ctx *ctx, verto_ev *ev);
static void process_rpc_connection(verto_ctx *ctx, verto_ev *ev);
@@ -568,6 +605,8 @@ create_server_socket(struct sockaddr *addr, int type, const char *prog,
*fd_out = -1;
+ if (addr->sa_family == AF_UNIX)
+ (void)unlink(sa2sun(addr)->sun_path);
sock = socket(addr->sa_family, type, 0);
if (sock == -1) {
e = errno;
@@ -641,7 +680,8 @@ static const int bind_socktypes[] =
{
[UDP] = SOCK_DGRAM,
[TCP] = SOCK_STREAM,
- [RPC] = SOCK_STREAM
+ [RPC] = SOCK_STREAM,
+ [UNX] = SOCK_STREAM
};
/* An enum map containing conn_type (for struct connection) for each
@@ -650,7 +690,8 @@ static const enum conn_type bind_conn_types[] =
{
[UDP] = CONN_UDP,
[TCP] = CONN_TCP_LISTENER,
- [RPC] = CONN_RPC_LISTENER
+ [RPC] = CONN_RPC_LISTENER,
+ [UNX] = CONN_UNIXSOCK_LISTENER
};
/*
@@ -668,7 +709,7 @@ static const enum conn_type bind_conn_types[] =
static krb5_error_code
setup_socket(struct bind_address *ba, struct sockaddr *sock_address,
void *handle, const char *prog, verto_ctx *ctx,
- int tcp_listen_backlog, verto_callback vcb, enum conn_type ctype)
+ int listen_backlog, verto_callback vcb, enum conn_type ctype)
{
krb5_error_code ret;
struct connection *conn;
@@ -687,16 +728,17 @@ setup_socket(struct bind_address *ba, struct sockaddr *sock_address,
if (ret)
goto cleanup;
- /* Listen for backlogged connections on TCP sockets. (For RPC sockets this
- * will be done by svc_register().) */
- if (ba->type == TCP && listen(sock, tcp_listen_backlog) != 0) {
+ /* Listen for backlogged connections on stream sockets. (For RPC sockets
+ * this will be done by svc_register().) */
+ if ((ba->type == TCP || ba->type == UNX) &&
+ listen(sock, listen_backlog) != 0) {
ret = errno;
com_err(prog, errno, _("Cannot listen on %s server socket on %s"),
bind_type_names[ba->type], addrbuf);
goto cleanup;
}
- /* Set non-blocking I/O for UDP and TCP listener sockets. */
+ /* Set non-blocking I/O for non-RPC listener sockets. */
if (ba->type != RPC && setnbio(sock) != 0) {
ret = errno;
com_err(prog, errno,
@@ -780,18 +822,20 @@ cleanup:
*/
static krb5_error_code
setup_addresses(verto_ctx *ctx, void *handle, const char *prog,
- int tcp_listen_backlog)
+ int listen_backlog)
{
/* An bind_type enum map for the verto callback functions. */
static verto_callback *const verto_callbacks[] = {
[UDP] = &process_packet,
- [TCP] = &accept_tcp_connection,
- [RPC] = &accept_rpc_connection
+ [TCP] = &accept_stream_connection,
+ [RPC] = &accept_rpc_connection,
+ [UNX] = &accept_stream_connection
};
krb5_error_code ret = 0;
size_t i;
int err, bound_any;
struct bind_address addr;
+ struct sockaddr_un sun;
struct addrinfo hints, *ai_list = NULL, *ai = NULL;
verto_callback vcb;
char addrbuf[128];
@@ -816,6 +860,28 @@ setup_addresses(verto_ctx *ctx, void *handle, const char *prog,
addr = bind_addresses.data[i];
hints.ai_socktype = bind_socktypes[addr.type];
+ if (addr.type == UNX) {
+ sun.sun_family = AF_UNIX;
+ if (strlcpy(sun.sun_path, addr.address, sizeof(sun.sun_path)) >=
+ sizeof(sun.sun_path)) {
+ ret = ENAMETOOLONG;
+ krb5_klog_syslog(LOG_ERR,
+ _("UNIX domain socket path too long: %s"),
+ addr.address);
+ goto cleanup;
+ }
+ ret = setup_socket(&addr, (struct sockaddr *)&sun, handle, prog,
+ ctx, listen_backlog, verto_callbacks[addr.type],
+ bind_conn_types[addr.type]);
+ if (ret) {
+ krb5_klog_syslog(LOG_ERR,
+ _("Failed setting up a UNIX socket (for %s)"),
+ addr.address);
+ goto cleanup;
+ }
+ continue;
+ }
+
/* Call getaddrinfo, using a dummy port value. */
err = getaddrinfo(addr.address, "0", &hints, &ai_list);
if (err) {
@@ -846,7 +912,7 @@ setup_addresses(verto_ctx *ctx, void *handle, const char *prog,
sa_setport(ai->ai_addr, addr.port);
ret = setup_socket(&addr, ai->ai_addr, handle, prog, ctx,
- tcp_listen_backlog, verto_callbacks[addr.type],
+ listen_backlog, verto_callbacks[addr.type],
bind_conn_types[addr.type]);
if (ret) {
k5_print_addr(ai->ai_addr, addrbuf, sizeof(addrbuf));
@@ -876,7 +942,7 @@ cleanup:
krb5_error_code
loop_setup_network(verto_ctx *ctx, void *handle, const char *prog,
- int tcp_listen_backlog)
+ int listen_backlog)
{
krb5_error_code ret;
verto_ev *ev;
@@ -892,7 +958,7 @@ loop_setup_network(verto_ctx *ctx, void *handle, const char *prog,
events.n = 0;
krb5_klog_syslog(LOG_INFO, _("setting up network..."));
- ret = setup_addresses(ctx, handle, prog, tcp_listen_backlog);
+ ret = setup_addresses(ctx, handle, prog, listen_backlog);
if (ret) {
com_err(prog, ret, _("Error setting up network"));
exit(1);
@@ -1015,7 +1081,7 @@ process_packet(verto_ctx *ctx, verto_ev *ev)
}
static int
-kill_lru_tcp_or_rpc_connection(void *handle, verto_ev *newev)
+kill_lru_stream_connection(void *handle, verto_ev *newev)
{
struct connection *c = NULL, *oldest_c = NULL;
verto_ev *ev, *oldest_ev = NULL;
@@ -1030,7 +1096,8 @@ kill_lru_tcp_or_rpc_connection(void *handle, verto_ev *newev)
c = verto_get_private(ev);
if (!c)
continue;
- if (c->type != CONN_TCP && c->type != CONN_RPC)
+ if (c->type != CONN_TCP && c->type != CONN_RPC &&
+ c->type != CONN_UNIXSOCK)
continue;
if (oldest_c == NULL
|| oldest_c->start_time > c->start_time) {
@@ -1040,7 +1107,7 @@ kill_lru_tcp_or_rpc_connection(void *handle, verto_ev *newev)
}
if (oldest_c != NULL) {
krb5_klog_syslog(LOG_INFO, _("dropping %s fd %d from %s"),
- oldest_c->type == CONN_RPC ? "rpc" : "tcp",
+ conn_type_names[oldest_c->type],
verto_get_fd(oldest_ev), oldest_c->addrbuf);
if (oldest_c->type == CONN_RPC)
oldest_c->rpc_force_close = 1;
@@ -1050,12 +1117,13 @@ kill_lru_tcp_or_rpc_connection(void *handle, verto_ev *newev)
}
static void
-accept_tcp_connection(verto_ctx *ctx, verto_ev *ev)
+accept_stream_connection(verto_ctx *ctx, verto_ev *ev)
{
int s;
struct sockaddr_storage addr;
socklen_t addrlen = sizeof(addr);
struct connection *newconn, *conn;
+ enum conn_type ctype;
verto_ev_flag flags;
verto_ev *newev;
@@ -1070,16 +1138,31 @@ accept_tcp_connection(verto_ctx *ctx, verto_ev *ev)
return;
}
#endif
- setnbio(s), setnolinger(s), setkeepalive(s);
+ setnbio(s);
+ setnolinger(s);
+ if (addr.ss_family != AF_UNIX)
+ setkeepalive(s);
flags = VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_PERSIST;
- if (add_fd(s, CONN_TCP, flags, conn->handle, conn->prog, ctx,
- process_tcp_connection_read, &newev) != 0) {
+ ctype = (conn->type == CONN_TCP_LISTENER) ? CONN_TCP : CONN_UNIXSOCK;
+ if (add_fd(s, ctype, flags, conn->handle, conn->prog, ctx,
+ process_stream_connection_read, &newev) != 0) {
close(s);
return;
}
newconn = verto_get_private(newev);
+ if (addr.ss_family == AF_UNIX) {
+ /* accept() doesn't fill in sun_path as the client socket isn't bound.
+ * For logging purposes we will use the target address. */
+ addrlen = sizeof(addr);
+ if (getsockname(s, ss2sa(&addr), &addrlen) < 0) {
+ com_err(conn->prog, errno, _("Failed to get address for %d"), s);
+ close(s);
+ return;
+ }
+ }
+
k5_print_addr_port(ss2sa(&addr), newconn->addrbuf,
sizeof(newconn->addrbuf));
newconn->addr_s = addr;
@@ -1088,8 +1171,8 @@ accept_tcp_connection(verto_ctx *ctx, verto_ev *ev)
newconn->buffer = malloc(newconn->bufsiz);
newconn->start_time = time(0);
- if (++tcp_or_rpc_data_counter > max_tcp_or_rpc_data_connections)
- kill_lru_tcp_or_rpc_connection(conn->handle, newev);
+ if (++stream_data_counter > max_stream_data_connections)
+ kill_lru_stream_connection(conn->handle, newev);
if (newconn->buffer == 0) {
com_err(conn->prog, errno,
@@ -1112,7 +1195,7 @@ struct tcp_dispatch_state {
};
static void
-process_tcp_response(void *arg, krb5_error_code code, krb5_data *response)
+process_stream_response(void *arg, krb5_error_code code, krb5_data *response)
{
struct tcp_dispatch_state *state = arg;
verto_ev *ev;
@@ -1132,14 +1215,14 @@ process_tcp_response(void *arg, krb5_error_code code, krb5_data *response)
state->conn->sgnum = 2;
ev = make_event(state->ctx, VERTO_EV_FLAG_IO_WRITE | VERTO_EV_FLAG_PERSIST,
- process_tcp_connection_write, state->sock, state->conn);
+ process_stream_connection_write, state->sock, state->conn);
if (ev) {
free(state);
return;
}
kill_tcp_connection:
- tcp_or_rpc_data_counter--;
+ stream_data_counter--;
free_connection(state->conn);
close(state->sock);
free(state);
@@ -1166,7 +1249,7 @@ prepare_for_dispatch(verto_ctx *ctx, verto_ev *ev)
}
static void
-process_tcp_connection_read(verto_ctx *ctx, verto_ev *ev)
+process_stream_connection_read(verto_ctx *ctx, verto_ev *ev)
{
struct tcp_dispatch_state *state = NULL;
struct connection *conn = NULL;
@@ -1219,7 +1302,7 @@ process_tcp_connection_read(verto_ctx *ctx, verto_ev *ev)
krb5_free_data(get_context(conn->handle), response);
goto kill_tcp_connection;
}
- process_tcp_response(state, 0, response);
+ process_stream_response(state, 0, response);
}
}
} else {
@@ -1253,7 +1336,7 @@ process_tcp_connection_read(verto_ctx *ctx, verto_ev *ev)
}
dispatch(state->conn->handle, ss2sa(&state->local_saddr),
ss2sa(&conn->addr_s), &state->request, 1, ctx,
- process_tcp_response, state);
+ process_stream_response, state);
}
return;
@@ -1263,7 +1346,7 @@ kill_tcp_connection:
}
static void
-process_tcp_connection_write(verto_ctx *ctx, verto_ev *ev)
+process_stream_connection_write(verto_ctx *ctx, verto_ev *ev)
{
struct connection *conn;
SOCKET_WRITEV_TEMP tmp;
@@ -1377,8 +1460,8 @@ accept_rpc_connection(verto_ctx *ctx, verto_ev *ev)
newconn->addrlen = addrlen;
newconn->start_time = time(0);
- if (++tcp_or_rpc_data_counter > max_tcp_or_rpc_data_connections)
- kill_lru_tcp_or_rpc_connection(newconn->handle, newev);
+ if (++stream_data_counter > max_stream_data_connections)
+ kill_lru_stream_connection(newconn->handle, newev);
}
}
diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports
index 63bc7a86c..1e7076d3c 100644
--- a/src/lib/krb5/libkrb5.exports
+++ b/src/lib/krb5/libkrb5.exports
@@ -119,6 +119,8 @@ initialize_prof_error_table
k5_add_empty_pa_data
k5_add_pa_data_element
k5_add_pa_data_from_data
+k5_addr_directional_accept
+k5_addr_directional_init
k5_alloc_pa_data
k5_authind_decode
k5_build_conf_principals
diff --git a/src/lib/krb5/os/addr.c b/src/lib/krb5/os/addr.c
index 1d8ae7501..e351ef800 100644
--- a/src/lib/krb5/os/addr.c
+++ b/src/lib/krb5/os/addr.c
@@ -33,8 +33,16 @@
#include "k5-int.h"
#include "socket-utils.h"
+const krb5_address k5_addr_directional_init = {
+ KV5M_ADDRESS, ADDRTYPE_DIRECTIONAL, 4, (uint8_t *)"\x00\x00\x00\x00"
+};
+const krb5_address k5_addr_directional_accept = {
+ KV5M_ADDRESS, ADDRTYPE_DIRECTIONAL, 4, (uint8_t *)"\x00\x00\x00\x01"
+};
+
krb5_error_code
-k5_sockaddr_to_address(const struct sockaddr *sa, krb5_address *out)
+k5_sockaddr_to_address(const struct sockaddr *sa, krb5_boolean local_use,
+ krb5_address *out)
{
if (sa->sa_family == AF_INET) {
const struct sockaddr_in *sin = sa2sin(sa);
@@ -52,6 +60,13 @@ k5_sockaddr_to_address(const struct sockaddr *sa, krb5_address *out)
out->length = sizeof(sin6->sin6_addr);
out->contents = (uint8_t *)&sin6->sin6_addr;
}
+#ifndef _WIN32
+ } else if (sa->sa_family == AF_UNIX && local_use) {
+ const struct sockaddr_un *sun = sa2sun(sa);
+ out->addrtype = ADDRTYPE_UNIXSOCK;
+ out->length = strlen(sun->sun_path);
+ out->contents = (uint8_t *)sun->sun_path;
+#endif
} else {
return KRB5_PROG_ATYPE_NOSUPP;
}
@@ -66,6 +81,10 @@ k5_print_addr(const struct sockaddr *sa, char *buf, size_t len)
if (getnameinfo(sa, sa_socklen(sa), buf, len, NULL, 0,
NI_NUMERICHOST | NI_NUMERICSERV) != 0)
strlcpy(buf, "<unknown>", len);
+#ifndef _WIN32
+ } else if (sa->sa_family == AF_UNIX) {
+ strlcpy(buf, sa2sun(sa)->sun_path, len);
+#endif
} else {
strlcpy(buf, "<unknown>", len);
}
diff --git a/src/lib/krb5/os/changepw.c b/src/lib/krb5/os/changepw.c
index bc132bc33..d32a12b63 100644
--- a/src/lib/krb5/os/changepw.c
+++ b/src/lib/krb5/os/changepw.c
@@ -143,6 +143,12 @@ kpasswd_sendto_msg_callback(SOCKET fd, void *data, krb5_data *message)
local_kaddr.addrtype = ADDRTYPE_INET6;
local_kaddr.length = sizeof(ss2sin6(&local_addr)->sin6_addr);
local_kaddr.contents = (krb5_octet *) &ss2sin6(&local_addr)->sin6_addr;
+#ifndef _WIN32
+ } else if (local_addr.ss_family == AF_UNIX) {
+ /* There is no standard way to represent UNIX domain sockets. Assume
+ * that the receiver will accept a directional address. */
+ local_kaddr = k5_addr_directional_init;
+#endif
} else {
code = krb5_os_localaddr(ctx->context, &addrs);
if (code)
diff --git a/src/plugins/audit/j_dict.h b/src/plugins/audit/j_dict.h
index 65962e331..fd93ceb04 100644
--- a/src/plugins/audit/j_dict.h
+++ b/src/plugins/audit/j_dict.h
@@ -45,6 +45,7 @@
#define AU_FROMADDR "fromaddr"
#define AU_TYPE "type" /* used by fromaddr */
#define AU_IP "ip" /* used by fromaddr */
+#define AU_PATH "path" /* used by fromaddr */
#define AU_SESS_ETYPE "sess_etype"
#define AU_SRV_ETYPE "srv_etype"
#define AU_REP_ETYPE "rep_etype"
diff --git a/src/plugins/audit/kdc_j_encode.c b/src/plugins/audit/kdc_j_encode.c
index 0df258d76..31f308067 100755
--- a/src/plugins/audit/kdc_j_encode.c
+++ b/src/plugins/audit/kdc_j_encode.c
@@ -630,6 +630,17 @@ addr_to_obj(krb5_address *a, k5_json_object obj)
ret = k5_json_object_set(obj, AU_IP, arr);
if (ret)
goto error;
+ } else if (a->addrtype == ADDRTYPE_UNIXSOCK) {
+ k5_json_string str = NULL;
+
+ ret = k5_json_string_create_len(a->contents, a->length, &str);
+ if (ret)
+ return ret;
+
+ ret = k5_json_object_set(obj, AU_PATH, str);
+ k5_json_release(str);
+ if (ret)
+ goto error;
}
error:
More information about the cvs-krb5
mailing list