From 2bdb80165c2e095b169c59ef18607b30f8758ec7 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Wed, 14 Jan 2015 22:36:38 +0100 Subject: [PATCH] frontend: Make peer detection more flexible. It's now a property of a listener implementation. Moved the unixsock implementation over from frontend/connection to frontend/sock. --- src/frontend/connection.c | 52 +--------------------------------- src/frontend/sock.c | 59 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 52 deletions(-) diff --git a/src/frontend/connection.c b/src/frontend/connection.c index c35d2d2..700c84a 100644 --- a/src/frontend/connection.c +++ b/src/frontend/connection.c @@ -47,19 +47,6 @@ #include #include -#include -#include -#include - -#ifdef HAVE_UCRED_H -# include -#endif -#ifdef HAVE_SYS_UCRED_H -# include -#endif - -#include - #include /* @@ -77,36 +64,6 @@ static bool conn_ctx_key_initialized = 0; #define CONN_FD_PREFIX "conn#" #define CONN_FD_PLACEHOLDER "XXXXXXX" -/* XXX: only supports UNIX sockets so far */ -static char * -peer(int sockfd) -{ - uid_t uid; - - struct passwd pw_entry; - struct passwd *result = NULL; - char buf[1024]; - -#ifdef SO_PEERCRED - struct ucred cred; - socklen_t len = sizeof(cred); - - if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cred, &len) - || (len != sizeof(cred))) - return NULL; - uid = cred.uid; -#else /* SO_PEERCRED */ - errno = ENOSYS; - return NULL; -#endif - - memset(&pw_entry, 0, sizeof(pw_entry)); - if (getpwuid_r(uid, &pw_entry, buf, sizeof(buf), &result) - || (! result)) - return NULL; - return strdup(result->pw_name); -} /* peer */ - static ssize_t conn_read(sdb_conn_t *conn, size_t len) { @@ -181,14 +138,7 @@ connection_init(sdb_object_t *obj, va_list ap) return -1; } - conn->username = peer(conn->fd); - if (! conn->username) { - char buf[1024]; - sdb_log(SDB_LOG_ERR, "frontend: Failed to retrieve peer for " - "connection conn#%i: %s", conn->fd, - sdb_strerror(errno, buf, sizeof(buf))); - return -1; - } + conn->username = NULL; conn->ready = 0; sdb_log(SDB_LOG_DEBUG, "frontend: Accepted connection on fd=%i", diff --git a/src/frontend/sock.c b/src/frontend/sock.c index 860fb8e..2def8da 100644 --- a/src/frontend/sock.c +++ b/src/frontend/sock.c @@ -53,10 +53,19 @@ #include #include #include +#include #include -#include +#ifdef HAVE_UCRED_H +# include +#endif +#ifdef HAVE_SYS_UCRED_H +# include +#endif + +#include +#include #include /* @@ -69,6 +78,7 @@ typedef struct { int sock_fd; int (*accept)(sdb_conn_t *); + int (*peer)(sdb_conn_t *); } listener_t; typedef struct { @@ -94,6 +104,46 @@ struct sdb_fe_socket { * connection management functions */ +static int +unixsock_peer(sdb_conn_t *conn) +{ + uid_t uid; + + struct passwd pw_entry; + struct passwd *result = NULL; + char buf[1024]; + +#ifdef SO_PEERCRED + struct ucred cred; + socklen_t len = sizeof(cred); + + if (getsockopt(conn->fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) + || (len != sizeof(cred))) { + char errbuf[1024]; + sdb_log(SDB_LOG_ERR, "frontend: Failed to determine peer for " + "connection conn#%i: %s", conn->fd, + sdb_strerror(errno, errbuf, sizeof(errbuf))); + return -1; + } + uid = cred.uid; +#else /* SO_PEERCRED */ + sdb_log(SDB_LOG_ERR, "frontend: Failed to determine peer for " + "connection conn#%i: operation not supported", conn->fd); + return -1; +#endif + + memset(&pw_entry, 0, sizeof(pw_entry)); + if (getpwuid_r(uid, &pw_entry, buf, sizeof(buf), &result) || (! result) + || (! (conn->username = strdup(result->pw_name)))) { + char errbuf[1024]; + sdb_log(SDB_LOG_ERR, "frontend: Failed to determine peer for " + "connection conn#%i: %s", conn->fd, + sdb_strerror(errno, errbuf, sizeof(errbuf))); + return -1; + } + return 0; +} /* unixsock_peer */ + static int open_unixsock(listener_t *listener) { @@ -147,6 +197,8 @@ open_unixsock(listener_t *listener) listener->address, sdb_strerror(errno, buf, sizeof(buf))); return -1; } + + listener->peer = unixsock_peer; return 0; } /* open_unixsock */ @@ -397,6 +449,11 @@ connection_accept(sdb_fe_socket_t *sock, listener_t *listener) sdb_object_deref(obj); return -1; } + if (listener->peer && listener->peer(CONN(obj))) { + /* peer() is expected to log an error */ + sdb_object_deref(obj); + return -1; + } status = sdb_llist_append(sock->open_connections, obj); if (status) -- 2.30.2