Commit aea54018 authored by Dave Reisner's avatar Dave Reisner

Implement SocketUser= and SocketGroup= for [Socket]

Since we already allow defining the mode of AF_UNIX sockets and FIFO, it
makes sense to also allow specific user/group ownership of the socket
file for restricting access.
parent edca2e23
......@@ -357,6 +357,30 @@
0666.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>SocketUser=</varname></term>
<listitem><para>If listening on a file system
socket or FIFO, this option specifies the
user owner of the created socket. When
defining this, keep in mind that name
switch services for user name lookups may
not be available. It is advisable to use a
numeric UID for this
setting.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>SocketGroup=</varname></term>
<listitem><para>If listening on a file system
socket or FIFO, this option specifies the
group owner of the created socket. When
defining this, keep in mind that name
switch services for group name lookups may
not be available. It is advisable to use a
numeric GID for this
setting.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>Accept=</varname></term>
<listitem><para>Takes a boolean
......
......@@ -43,6 +43,8 @@
" <property name=\"BindToDevice\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
" <property name=\"SocketMode\" type=\"u\" access=\"read\"/>\n" \
" <property name=\"SocketUser\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"SocketGroup\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"Accept\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"KeepAlive\" type=\"b\" access=\"read\"/>\n" \
" <property name=\"Priority\" type=\"i\" access=\"read\"/>\n" \
......@@ -109,6 +111,8 @@ static const BusProperty bus_socket_properties[] = {
{ "BindToDevice", bus_property_append_string, "s", offsetof(Socket, bind_to_device), true },
{ "DirectoryMode", bus_property_append_mode, "u", offsetof(Socket, directory_mode) },
{ "SocketMode", bus_property_append_mode, "u", offsetof(Socket, socket_mode) },
{ "SocketUser", bus_property_append_string, "s", offsetof(Socket, socket_user), true },
{ "SocketGroup", bus_property_append_string, "s", offsetof(Socket, socket_group), true },
{ "Accept", bus_property_append_bool, "b", offsetof(Socket, accept) },
{ "KeepAlive", bus_property_append_bool, "b", offsetof(Socket, keep_alive) },
{ "Priority", bus_property_append_int, "i", offsetof(Socket, priority) },
......
......@@ -189,6 +189,8 @@ Socket.ExecStopPost, config_parse_exec, SOCKET_EXEC
Socket.TimeoutSec, config_parse_usec, 0, offsetof(Socket, timeout_usec)
Socket.DirectoryMode, config_parse_mode, 0, offsetof(Socket, directory_mode)
Socket.SocketMode, config_parse_mode, 0, offsetof(Socket, socket_mode)
Socket.SocketUser, config_parse_string, 0, offsetof(Socket, socket_user)
Socket.SocketGroup, config_parse_string, 0, offsetof(Socket, socket_group)
Socket.Accept, config_parse_bool, 0, offsetof(Socket, accept)
Socket.MaxConnections, config_parse_unsigned, 0, offsetof(Socket, max_connections)
Socket.KeepAlive, config_parse_bool, 0, offsetof(Socket, keep_alive)
......
......@@ -136,6 +136,12 @@ static void socket_done(Unit *u) {
free(s->smack_ip_in);
free(s->smack_ip_out);
free(s->socket_user);
s->socket_user = NULL;
free(s->socket_group);
s->socket_group = NULL;
unit_unwatch_timer(u, &s->timer_watch);
}
......@@ -449,6 +455,16 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
prefix, yes_no(s->pass_sec),
prefix, strna(s->tcp_congestion));
if (s->socket_user)
fprintf(f,
"SocketUser: %s\n",
s->socket_user);
if (s->socket_group)
fprintf(f,
"SocketGroup: %s\n",
s->socket_group);
if (s->control_pid > 0)
fprintf(f,
"%sControl PID: %lu\n",
......@@ -692,6 +708,9 @@ static void socket_close_fds(Socket *s) {
}
static void socket_apply_socket_options(Socket *s, int fd) {
uid_t uid = 0;
gid_t gid = 0;
assert(s);
assert(fd >= 0);
......@@ -775,6 +794,21 @@ static void socket_apply_socket_options(Socket *s, int fd) {
if (s->smack_ip_out)
if (fsetxattr(fd, "security.SMACK64IPOUT", s->smack_ip_out, strlen(s->smack_ip_out), 0) < 0)
log_error("fsetxattr(\"security.SMACK64IPOUT\"): %m");
if (s->socket_user &&
get_user_creds((const char **)&s->socket_user, &uid,
NULL, NULL, NULL) < 0) {
log_warning("failed to lookup user: %s", s->socket_user);
}
if (s->socket_group &&
get_group_creds((const char **)&s->socket_group, &gid) < 0) {
log_warning("failed to lookup group: %s", s->socket_group);
}
if ((uid != 0 || gid != 0) && fchown(fd, uid, gid) < 0) {
log_warning("failed to change ownership of socket");
}
}
static void socket_apply_fifo_options(Socket *s, int fd) {
......@@ -794,11 +828,15 @@ static int fifo_address_create(
const char *path,
mode_t directory_mode,
mode_t socket_mode,
const char *socket_user,
const char *socket_group,
int *_fd) {
int fd = -1, r = 0;
struct stat st;
mode_t old_mask;
uid_t uid = 0;
gid_t gid = 0;
assert(path);
assert(_fd);
......@@ -823,7 +861,8 @@ static int fifo_address_create(
goto fail;
}
if ((fd = open(path, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW)) < 0) {
fd = open(path, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW);
if (fd < 0) {
r = -errno;
goto fail;
}
......@@ -835,15 +874,35 @@ static int fifo_address_create(
goto fail;
}
if (socket_user &&
get_user_creds(&socket_user, &uid, NULL, NULL, NULL) < 0) {
r = -errno;
log_error("failed to lookup user: %s", socket_user);
goto fail;
}
if (socket_group &&
get_group_creds(&socket_group, &gid) < 0) {
r = -errno;
log_error("failed to lookup group: %s", socket_group);
goto fail;
}
if (!S_ISFIFO(st.st_mode) ||
(st.st_mode & 0777) != (socket_mode & ~old_mask) ||
st.st_uid != getuid() ||
st.st_gid != getgid()) {
st.st_uid != uid ||
st.st_gid != gid) {
r = -EEXIST;
goto fail;
}
if ((uid != 0 || gid != 0) && fchown(fd, uid, gid) < 0) {
r = -errno;
log_error("failed to changed ownership of FIFO: %s", path);
goto fail;
}
*_fd = fd;
return 0;
......@@ -1013,6 +1072,8 @@ static int socket_open_fds(Socket *s) {
p->path,
s->directory_mode,
s->socket_mode,
s->socket_user,
s->socket_group,
&p->fd)) < 0)
goto rollback;
......
......@@ -118,6 +118,8 @@ struct Socket {
mode_t directory_mode;
mode_t socket_mode;
char *socket_user;
char *socket_group;
SocketResult result;
......
......@@ -52,6 +52,7 @@ int socket_address_listen(
int *ret) {
int r, fd, one;
assert(a);
assert(ret);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment