diff --git a/include/types/protocols.h b/include/types/protocols.h index 2c68e8866..6ff447651 100644 --- a/include/types/protocols.h +++ b/include/types/protocols.h @@ -24,6 +24,8 @@ #include #include +#include +#include #include #include @@ -60,6 +62,13 @@ struct listener { void (*handler)(struct task *t, struct timeval *next); /* protocol handler */ struct timeval *timeout; /* pointer to client-side timeout */ void *private; /* any private data which may be used by accept() */ + union { /* protocol-dependant access restrictions */ + struct { /* UNIX socket permissions */ + uid_t uid; /* -1 to leave unchanged */ + gid_t gid; /* -1 to leave unchanged */ + mode_t mode; /* 0 to leave unchanged */ + } ux; + } perm; }; /* This structure contains all information needed to easily handle a protocol. diff --git a/src/proto_uxst.c b/src/proto_uxst.c index 192037669..e23d1d4f1 100644 --- a/src/proto_uxst.c +++ b/src/proto_uxst.c @@ -59,10 +59,13 @@ #endif /* This function creates a named PF_UNIX stream socket at address . Note - * that the path cannot be NULL nor empty. + * that the path cannot be NULL nor empty. and different of -1 will + * be used to change the socket owner. If is not 0, it will be used to + * restrict access to the socket. While it is known not to be portable on every + * OS, it's still useful where it works. * It returns the assigned file descriptor, or -1 in the event of an error. */ -static int create_uxst_socket(const char *path) +static int create_uxst_socket(const char *path, uid_t uid, gid_t gid, mode_t mode) { char tempname[MAXPATHLEN]; char backname[MAXPATHLEN]; @@ -132,6 +135,12 @@ static int create_uxst_socket(const char *path) goto err_unlink_temp; } + if (((uid != -1 || gid != -1) && (chown(tempname, uid, gid) == -1)) || + (mode != 0 && chmod(tempname, mode) == -1)) { + Alert("cannot change UNIX socket ownership. Aborting.\n"); + goto err_unlink_temp; + } + if (listen(sock, 0) < 0) { Alert("cannot listen to socket for UNIX listener. Aborting.\n"); goto err_unlink_temp; @@ -217,7 +226,10 @@ static int uxst_bind_listeners(struct protocol *proto) if (listener->state != LI_INIT) continue; /* already started */ - fd = create_uxst_socket(((struct sockaddr_un *)&listener->addr)->sun_path); + fd = create_uxst_socket(((struct sockaddr_un *)&listener->addr)->sun_path, + listener->perm.ux.uid, + listener->perm.ux.gid, + listener->perm.ux.mode); if (fd == -1) { err |= ERR_FATAL; continue;