#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/un.h>
#include <common/config.h>
#include <common/mini-clist.h>
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.
#endif
/* This function creates a named PF_UNIX stream socket at address <path>. Note
- * that the path cannot be NULL nor empty.
+ * that the path cannot be NULL nor empty. <uid> and <gid> different of -1 will
+ * be used to change the socket owner. If <mode> 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];
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;
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;