mirror of
https://github.com/systemd/systemd.git
synced 2025-01-10 05:18:17 +03:00
nss-mymachines: map userns users of containers to real user names
Given a container "foo", that maps user id $UID to container user, using user namespaces, this NSS module extenstion will now map the $UID to a name "vu-foo-$TUID" for the translated UID $UID. Similar, userns groups are mapped to "vg-foo-$TGID" for translated GIDs of $GID. This simple change should make userns users more discoverable. Also, given that many tools like "adduser" check NSS before allocating a UID, should lower the chance of UID range conflicts between tools.
This commit is contained in:
parent
43694a8cc7
commit
c01ff965b4
@ -59,21 +59,26 @@
|
|||||||
<para><command>nss-mymachines</command> is a plugin for the GNU
|
<para><command>nss-mymachines</command> is a plugin for the GNU
|
||||||
Name Service Switch (NSS) functionality of the GNU C Library
|
Name Service Switch (NSS) functionality of the GNU C Library
|
||||||
(<command>glibc</command>) providing hostname resolution for
|
(<command>glibc</command>) providing hostname resolution for
|
||||||
containers running locally, that are registered with
|
container names of containers running locally, that are registered
|
||||||
|
with
|
||||||
<citerefentry><refentrytitle>systemd-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
|
<citerefentry><refentrytitle>systemd-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
|
||||||
The container names are resolved to IP addresses of the specific
|
The container names are resolved to the IP addresses of the
|
||||||
container, ordered by their scope.</para>
|
specific container, ordered by their scope.</para>
|
||||||
|
|
||||||
|
<para>The module also resolves user IDs used by containers to user
|
||||||
|
names indicating the container name, and back.</para>
|
||||||
|
|
||||||
<para>To activate the NSS modules, <literal>mymachines</literal>
|
<para>To activate the NSS modules, <literal>mymachines</literal>
|
||||||
has to be added to the line starting with
|
has to be added to the lines starting with
|
||||||
<literal>hosts:</literal> in
|
<literal>hosts:</literal>, <literal>passwd:</literal> and
|
||||||
|
<literal>group:</literal> in
|
||||||
<filename>/etc/nsswitch.conf</filename>.</para>
|
<filename>/etc/nsswitch.conf</filename>.</para>
|
||||||
|
|
||||||
<para>It is recommended to place <literal>mymachines</literal>
|
<para>It is recommended to place <literal>mymachines</literal>
|
||||||
near the end of the <filename>nsswitch.conf</filename> line to
|
near the end of the <filename>nsswitch.conf</filename> lines to
|
||||||
make sure that this mapping is only used as fallback, and any DNS
|
make sure that its mappings are only used as fallback, and any
|
||||||
or <filename>/etc/hosts</filename> based mapping takes
|
other mappings, such as DNS or <filename>/etc/hosts</filename>
|
||||||
precedence.</para>
|
based mappings take precedence.</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
@ -82,17 +87,17 @@
|
|||||||
<para>Here's an example <filename>/etc/nsswitch.conf</filename>
|
<para>Here's an example <filename>/etc/nsswitch.conf</filename>
|
||||||
file, that enables <command>mymachines</command> correctly:</para>
|
file, that enables <command>mymachines</command> correctly:</para>
|
||||||
|
|
||||||
<programlisting>passwd: compat
|
<programlisting>passwd: compat <command>mymachines</command>
|
||||||
group: compat
|
group: compat <command>mymachines</command>
|
||||||
shadow: compat
|
shadow: compat
|
||||||
|
|
||||||
hosts: files dns <command>mymachines</command> myhostname
|
hosts: files dns <command>mymachines</command> myhostname
|
||||||
networks: files
|
networks: files
|
||||||
|
|
||||||
protocols: db files
|
protocols: db files
|
||||||
services: db files
|
services: db files
|
||||||
ethers: db files
|
ethers: db files
|
||||||
rpc: db files
|
rpc: db files
|
||||||
|
|
||||||
netgroup: nis</programlisting>
|
netgroup: nis</programlisting>
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#define _printf_(a,b) __attribute__ ((format (printf, a, b)))
|
#define _printf_(a,b) __attribute__ ((format (printf, a, b)))
|
||||||
#define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__)))
|
#define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__)))
|
||||||
@ -461,6 +462,18 @@ do { \
|
|||||||
#define GID_INVALID ((gid_t) -1)
|
#define GID_INVALID ((gid_t) -1)
|
||||||
#define MODE_INVALID ((mode_t) -1)
|
#define MODE_INVALID ((mode_t) -1)
|
||||||
|
|
||||||
|
static inline bool UID_IS_INVALID(uid_t uid) {
|
||||||
|
/* We consider both the old 16bit -1 user and the newer 32bit
|
||||||
|
* -1 user invalid, since they are or used to be incompatible
|
||||||
|
* with syscalls such as setresuid() or chown(). */
|
||||||
|
|
||||||
|
return uid == (uid_t) ((uint32_t) -1) || uid == (uid_t) ((uint16_t) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool GID_IS_INVALID(gid_t gid) {
|
||||||
|
return gid == (gid_t) ((uint32_t) -1) || gid == (gid_t) ((uint16_t) -1);
|
||||||
|
}
|
||||||
|
|
||||||
#define DEFINE_TRIVIAL_CLEANUP_FUNC(type, func) \
|
#define DEFINE_TRIVIAL_CLEANUP_FUNC(type, func) \
|
||||||
static inline void func##p(type *p) { \
|
static inline void func##p(type *p) { \
|
||||||
if (*p) \
|
if (*p) \
|
||||||
|
@ -46,6 +46,8 @@
|
|||||||
#define BUS_ERROR_NO_MACHINE_FOR_PID "org.freedesktop.machine1.NoMachineForPID"
|
#define BUS_ERROR_NO_MACHINE_FOR_PID "org.freedesktop.machine1.NoMachineForPID"
|
||||||
#define BUS_ERROR_MACHINE_EXISTS "org.freedesktop.machine1.MachineExists"
|
#define BUS_ERROR_MACHINE_EXISTS "org.freedesktop.machine1.MachineExists"
|
||||||
#define BUS_ERROR_NO_PRIVATE_NETWORKING "org.freedesktop.machine1.NoPrivateNetworking"
|
#define BUS_ERROR_NO_PRIVATE_NETWORKING "org.freedesktop.machine1.NoPrivateNetworking"
|
||||||
|
#define BUS_ERROR_NO_SUCH_USER_MAPPING "org.freedesktop.machine1.NoSuchUserMapping"
|
||||||
|
#define BUS_ERROR_NO_SUCH_GROUP_MAPPING "org.freedesktop.machine1.NoSuchGroupMapping"
|
||||||
|
|
||||||
#define BUS_ERROR_NO_SUCH_SESSION "org.freedesktop.login1.NoSuchSession"
|
#define BUS_ERROR_NO_SUCH_SESSION "org.freedesktop.login1.NoSuchSession"
|
||||||
#define BUS_ERROR_NO_SESSION_FOR_PID "org.freedesktop.login1.NoSessionForPID"
|
#define BUS_ERROR_NO_SESSION_FOR_PID "org.freedesktop.login1.NoSessionForPID"
|
||||||
|
@ -31,12 +31,13 @@
|
|||||||
#include "bus-common-errors.h"
|
#include "bus-common-errors.h"
|
||||||
#include "cgroup-util.h"
|
#include "cgroup-util.h"
|
||||||
#include "btrfs-util.h"
|
#include "btrfs-util.h"
|
||||||
|
#include "formats-util.h"
|
||||||
|
#include "process-util.h"
|
||||||
#include "machine-image.h"
|
#include "machine-image.h"
|
||||||
#include "machine-pool.h"
|
#include "machine-pool.h"
|
||||||
#include "image-dbus.h"
|
#include "image-dbus.h"
|
||||||
#include "machined.h"
|
#include "machined.h"
|
||||||
#include "machine-dbus.h"
|
#include "machine-dbus.h"
|
||||||
#include "formats-util.h"
|
|
||||||
|
|
||||||
static int property_get_pool_path(
|
static int property_get_pool_path(
|
||||||
sd_bus *bus,
|
sd_bus *bus,
|
||||||
@ -840,6 +841,230 @@ static int method_set_image_limit(sd_bus_message *message, void *userdata, sd_bu
|
|||||||
return bus_image_method_set_limit(message, i, error);
|
return bus_image_method_set_limit(message, i, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int method_map_from_machine_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||||
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
|
Manager *m = userdata;
|
||||||
|
const char *name, *p;
|
||||||
|
Machine *machine;
|
||||||
|
uint32_t uid;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = sd_bus_message_read(message, "su", &name, &uid);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (UID_IS_INVALID(uid))
|
||||||
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
|
||||||
|
|
||||||
|
machine = hashmap_get(m->machines, name);
|
||||||
|
if (!machine)
|
||||||
|
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
|
||||||
|
|
||||||
|
p = procfs_file_alloca(machine->leader, "uid_map");
|
||||||
|
f = fopen(p, "re");
|
||||||
|
if (!f)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
uid_t uid_base, uid_shift, uid_range, converted;
|
||||||
|
int k;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT, &uid_base, &uid_shift, &uid_range);
|
||||||
|
if (k < 0 && feof(f))
|
||||||
|
break;
|
||||||
|
if (k != 3) {
|
||||||
|
if (ferror(f) && errno != 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uid < uid_base || uid >= uid_base + uid_range)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
converted = uid - uid_base + uid_shift;
|
||||||
|
if (UID_IS_INVALID(converted))
|
||||||
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
|
||||||
|
|
||||||
|
return sd_bus_reply_method_return(message, "u", (uint32_t) converted);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "Machine '%s' has no matching user mappings.", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int method_map_to_machine_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||||
|
Manager *m = userdata;
|
||||||
|
Machine *machine;
|
||||||
|
uid_t uid;
|
||||||
|
Iterator i;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = sd_bus_message_read(message, "u", &uid);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if (UID_IS_INVALID(uid))
|
||||||
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
|
||||||
|
if (uid < 0x10000)
|
||||||
|
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "User " UID_FMT " belongs to host UID range", uid);
|
||||||
|
|
||||||
|
HASHMAP_FOREACH(machine, m->machines, i) {
|
||||||
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
|
char p[strlen("/proc//uid_map") + DECIMAL_STR_MAX(pid_t) + 1];
|
||||||
|
|
||||||
|
xsprintf(p, "/proc/" UID_FMT "/uid_map", machine->leader);
|
||||||
|
f = fopen(p, "re");
|
||||||
|
if (!f) {
|
||||||
|
log_warning_errno(errno, "Failed top open %s, ignoring,", p);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
_cleanup_free_ char *o = NULL;
|
||||||
|
uid_t uid_base, uid_shift, uid_range, converted;
|
||||||
|
int k;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT, &uid_base, &uid_shift, &uid_range);
|
||||||
|
if (k < 0 && feof(f))
|
||||||
|
break;
|
||||||
|
if (k != 3) {
|
||||||
|
if (ferror(f) && errno != 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uid < uid_shift || uid >= uid_shift + uid_range)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
converted = (uid - uid_shift + uid_base);
|
||||||
|
if (UID_IS_INVALID(converted))
|
||||||
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
|
||||||
|
|
||||||
|
o = machine_bus_path(machine);
|
||||||
|
if (!o)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
return sd_bus_reply_method_return(message, "sou", machine->name, o, (uint32_t) converted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "No matching user mapping for " UID_FMT ".", uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int method_map_from_machine_group(sd_bus_message *message, void *groupdata, sd_bus_error *error) {
|
||||||
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
|
Manager *m = groupdata;
|
||||||
|
const char *name, *p;
|
||||||
|
Machine *machine;
|
||||||
|
uint32_t gid;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = sd_bus_message_read(message, "su", &name, &gid);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (GID_IS_INVALID(gid))
|
||||||
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
|
||||||
|
|
||||||
|
machine = hashmap_get(m->machines, name);
|
||||||
|
if (!machine)
|
||||||
|
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_MACHINE, "No machine '%s' known", name);
|
||||||
|
|
||||||
|
p = procfs_file_alloca(machine->leader, "gid_map");
|
||||||
|
f = fopen(p, "re");
|
||||||
|
if (!f)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
gid_t gid_base, gid_shift, gid_range, converted;
|
||||||
|
int k;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
k = fscanf(f, GID_FMT " " GID_FMT " " GID_FMT, &gid_base, &gid_shift, &gid_range);
|
||||||
|
if (k < 0 && feof(f))
|
||||||
|
break;
|
||||||
|
if (k != 3) {
|
||||||
|
if (ferror(f) && errno != 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gid < gid_base || gid >= gid_base + gid_range)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
converted = gid - gid_base + gid_shift;
|
||||||
|
if (GID_IS_INVALID(converted))
|
||||||
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
|
||||||
|
|
||||||
|
return sd_bus_reply_method_return(message, "u", (uint32_t) converted);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "Machine '%s' has no matching group mappings.", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int method_map_to_machine_group(sd_bus_message *message, void *groupdata, sd_bus_error *error) {
|
||||||
|
Manager *m = groupdata;
|
||||||
|
Machine *machine;
|
||||||
|
gid_t gid;
|
||||||
|
Iterator i;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = sd_bus_message_read(message, "u", &gid);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if (GID_IS_INVALID(gid))
|
||||||
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
|
||||||
|
if (gid < 0x10000)
|
||||||
|
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "Group " GID_FMT " belongs to host GID range", gid);
|
||||||
|
|
||||||
|
HASHMAP_FOREACH(machine, m->machines, i) {
|
||||||
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
|
char p[strlen("/proc//gid_map") + DECIMAL_STR_MAX(pid_t) + 1];
|
||||||
|
|
||||||
|
xsprintf(p, "/proc/" GID_FMT "/gid_map", machine->leader);
|
||||||
|
f = fopen(p, "re");
|
||||||
|
if (!f) {
|
||||||
|
log_warning_errno(errno, "Failed top open %s, ignoring,", p);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
_cleanup_free_ char *o = NULL;
|
||||||
|
gid_t gid_base, gid_shift, gid_range, converted;
|
||||||
|
int k;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
k = fscanf(f, GID_FMT " " GID_FMT " " GID_FMT, &gid_base, &gid_shift, &gid_range);
|
||||||
|
if (k < 0 && feof(f))
|
||||||
|
break;
|
||||||
|
if (k != 3) {
|
||||||
|
if (ferror(f) && errno != 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gid < gid_shift || gid >= gid_shift + gid_range)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
converted = (gid - gid_shift + gid_base);
|
||||||
|
if (GID_IS_INVALID(converted))
|
||||||
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
|
||||||
|
|
||||||
|
o = machine_bus_path(machine);
|
||||||
|
if (!o)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
return sd_bus_reply_method_return(message, "sou", machine->name, o, (uint32_t) converted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "No matching group mapping for " GID_FMT ".", gid);
|
||||||
|
}
|
||||||
|
|
||||||
const sd_bus_vtable manager_vtable[] = {
|
const sd_bus_vtable manager_vtable[] = {
|
||||||
SD_BUS_VTABLE_START(0),
|
SD_BUS_VTABLE_START(0),
|
||||||
SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path, 0, 0),
|
SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path, 0, 0),
|
||||||
@ -869,6 +1094,10 @@ const sd_bus_vtable manager_vtable[] = {
|
|||||||
SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL, method_mark_image_read_only, SD_BUS_VTABLE_UNPRIVILEGED),
|
SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL, method_mark_image_read_only, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
SD_BUS_METHOD("SetPoolLimit", "t", NULL, method_set_pool_limit, SD_BUS_VTABLE_UNPRIVILEGED),
|
SD_BUS_METHOD("SetPoolLimit", "t", NULL, method_set_pool_limit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
SD_BUS_METHOD("SetImageLimit", "st", NULL, method_set_image_limit, SD_BUS_VTABLE_UNPRIVILEGED),
|
SD_BUS_METHOD("SetImageLimit", "st", NULL, method_set_image_limit, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
|
SD_BUS_METHOD("MapFromMachineUser", "su", "u", method_map_from_machine_user, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
|
SD_BUS_METHOD("MapToMachineUser", "u", "sou", method_map_to_machine_user, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
|
SD_BUS_METHOD("MapFromMachineGroup", "su", "u", method_map_from_machine_group, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
|
SD_BUS_METHOD("MapToMachineGroup", "u", "sou", method_map_to_machine_group, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||||
SD_BUS_SIGNAL("MachineNew", "so", 0),
|
SD_BUS_SIGNAL("MachineNew", "so", 0),
|
||||||
SD_BUS_SIGNAL("MachineRemoved", "so", 0),
|
SD_BUS_SIGNAL("MachineRemoved", "so", 0),
|
||||||
SD_BUS_VTABLE_END
|
SD_BUS_VTABLE_END
|
||||||
|
@ -112,6 +112,22 @@
|
|||||||
send_interface="org.freedesktop.machine1.Manager"
|
send_interface="org.freedesktop.machine1.Manager"
|
||||||
send_member="SetImageLimit"/>
|
send_member="SetImageLimit"/>
|
||||||
|
|
||||||
|
<allow send_destination="org.freedesktop.machine1"
|
||||||
|
send_interface="org.freedesktop.machine1.Manager"
|
||||||
|
send_member="MapFromMachineUser"/>
|
||||||
|
|
||||||
|
<allow send_destination="org.freedesktop.machine1"
|
||||||
|
send_interface="org.freedesktop.machine1.Manager"
|
||||||
|
send_member="MapToMachineUser"/>
|
||||||
|
|
||||||
|
<allow send_destination="org.freedesktop.machine1"
|
||||||
|
send_interface="org.freedesktop.machine1.Manager"
|
||||||
|
send_member="MapFromMachineGroup"/>
|
||||||
|
|
||||||
|
<allow send_destination="org.freedesktop.machine1"
|
||||||
|
send_interface="org.freedesktop.machine1.Manager"
|
||||||
|
send_member="MapToMachineGroup"/>
|
||||||
|
|
||||||
<allow send_destination="org.freedesktop.machine1"
|
<allow send_destination="org.freedesktop.machine1"
|
||||||
send_interface="org.freedesktop.machine1.Machine"
|
send_interface="org.freedesktop.machine1.Machine"
|
||||||
send_member="GetAddresses"/>
|
send_member="GetAddresses"/>
|
||||||
|
@ -28,9 +28,12 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "nss-util.h"
|
#include "nss-util.h"
|
||||||
#include "bus-util.h"
|
#include "bus-util.h"
|
||||||
|
#include "bus-common-errors.h"
|
||||||
#include "in-addr-util.h"
|
#include "in-addr-util.h"
|
||||||
|
|
||||||
NSS_GETHOSTBYNAME_PROTOTYPES(mymachines);
|
NSS_GETHOSTBYNAME_PROTOTYPES(mymachines);
|
||||||
|
NSS_GETPW_PROTOTYPES(mymachines);
|
||||||
|
NSS_GETGR_PROTOTYPES(mymachines);
|
||||||
|
|
||||||
static int count_addresses(sd_bus_message *m, int af, unsigned *ret) {
|
static int count_addresses(sd_bus_message *m, int af, unsigned *ret) {
|
||||||
unsigned c = 0;
|
unsigned c = 0;
|
||||||
@ -380,4 +383,319 @@ fail:
|
|||||||
return NSS_STATUS_UNAVAIL;
|
return NSS_STATUS_UNAVAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSS_GETHOSTBYNAME_FALLBACKS(mymachines)
|
NSS_GETHOSTBYNAME_FALLBACKS(mymachines);
|
||||||
|
|
||||||
|
enum nss_status _nss_mymachines_getpwnam_r(
|
||||||
|
const char *name,
|
||||||
|
struct passwd *pwd,
|
||||||
|
char *buffer, size_t buflen,
|
||||||
|
int *errnop) {
|
||||||
|
|
||||||
|
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||||
|
_cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
|
||||||
|
_cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
|
||||||
|
const char *p, *e, *machine;
|
||||||
|
uint32_t mapped;
|
||||||
|
uid_t uid;
|
||||||
|
size_t l;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(name);
|
||||||
|
assert(pwd);
|
||||||
|
|
||||||
|
p = startswith(name, "vu-");
|
||||||
|
if (!p)
|
||||||
|
goto not_found;
|
||||||
|
|
||||||
|
e = strrchr(p, '-');
|
||||||
|
if (!e || e == p)
|
||||||
|
goto not_found;
|
||||||
|
|
||||||
|
r = parse_uid(e + 1, &uid);
|
||||||
|
if (r < 0)
|
||||||
|
goto not_found;
|
||||||
|
|
||||||
|
machine = strndupa(p, e - p);
|
||||||
|
if (!machine_name_is_valid(machine))
|
||||||
|
goto not_found;
|
||||||
|
|
||||||
|
r = sd_bus_open_system(&bus);
|
||||||
|
if (r < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
r = sd_bus_call_method(bus,
|
||||||
|
"org.freedesktop.machine1",
|
||||||
|
"/org/freedesktop/machine1",
|
||||||
|
"org.freedesktop.machine1.Manager",
|
||||||
|
"MapFromMachineUser",
|
||||||
|
&error,
|
||||||
|
&reply,
|
||||||
|
"su",
|
||||||
|
machine, (uint32_t) uid);
|
||||||
|
if (r < 0) {
|
||||||
|
if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_USER_MAPPING))
|
||||||
|
goto not_found;
|
||||||
|
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sd_bus_message_read(reply, "u", &mapped);
|
||||||
|
if (r < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
l = strlen(name);
|
||||||
|
if (buflen < l+1) {
|
||||||
|
*errnop = ENOMEM;
|
||||||
|
return NSS_STATUS_TRYAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer, name, l+1);
|
||||||
|
|
||||||
|
pwd->pw_name = buffer;
|
||||||
|
pwd->pw_uid = mapped;
|
||||||
|
pwd->pw_gid = 65534; /* nobody */
|
||||||
|
pwd->pw_gecos = buffer;
|
||||||
|
pwd->pw_passwd = (char*) "*"; /* locked */
|
||||||
|
pwd->pw_dir = (char*) "/";
|
||||||
|
pwd->pw_shell = (char*) "/sbin/nologin";
|
||||||
|
|
||||||
|
*errnop = 0;
|
||||||
|
return NSS_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
not_found:
|
||||||
|
*errnop = 0;
|
||||||
|
return NSS_STATUS_NOTFOUND;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
*errnop = -r;
|
||||||
|
return NSS_STATUS_UNAVAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum nss_status _nss_mymachines_getpwuid_r(
|
||||||
|
uid_t uid,
|
||||||
|
struct passwd *pwd,
|
||||||
|
char *buffer, size_t buflen,
|
||||||
|
int *errnop) {
|
||||||
|
|
||||||
|
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||||
|
_cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
|
||||||
|
_cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
|
||||||
|
const char *machine, *object;
|
||||||
|
uint32_t mapped;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (UID_IS_INVALID(uid)) {
|
||||||
|
r = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We consider all uids < 65536 host uids */
|
||||||
|
if (uid < 0x10000)
|
||||||
|
goto not_found;
|
||||||
|
|
||||||
|
r = sd_bus_open_system(&bus);
|
||||||
|
if (r < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
r = sd_bus_call_method(bus,
|
||||||
|
"org.freedesktop.machine1",
|
||||||
|
"/org/freedesktop/machine1",
|
||||||
|
"org.freedesktop.machine1.Manager",
|
||||||
|
"MapToMachineUser",
|
||||||
|
&error,
|
||||||
|
&reply,
|
||||||
|
"u",
|
||||||
|
(uint32_t) uid);
|
||||||
|
if (r < 0) {
|
||||||
|
if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_USER_MAPPING))
|
||||||
|
goto not_found;
|
||||||
|
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sd_bus_message_read(reply, "sou", &machine, &object, &mapped);
|
||||||
|
if (r < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (snprintf(buffer, buflen, "vu-%s-" UID_FMT, machine, (uid_t) mapped) >= (int) buflen) {
|
||||||
|
*errnop = ENOMEM;
|
||||||
|
return NSS_STATUS_TRYAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
pwd->pw_name = buffer;
|
||||||
|
pwd->pw_uid = uid;
|
||||||
|
pwd->pw_gid = 65534; /* nobody */
|
||||||
|
pwd->pw_gecos = buffer;
|
||||||
|
pwd->pw_passwd = (char*) "*"; /* locked */
|
||||||
|
pwd->pw_dir = (char*) "/";
|
||||||
|
pwd->pw_shell = (char*) "/sbin/nologin";
|
||||||
|
|
||||||
|
*errnop = 0;
|
||||||
|
return NSS_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
not_found:
|
||||||
|
*errnop = 0;
|
||||||
|
return NSS_STATUS_NOTFOUND;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
*errnop = -r;
|
||||||
|
return NSS_STATUS_UNAVAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum nss_status _nss_mymachines_getgrnam_r(
|
||||||
|
const char *name,
|
||||||
|
struct group *gr,
|
||||||
|
char *buffer, size_t buflen,
|
||||||
|
int *errnop) {
|
||||||
|
|
||||||
|
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||||
|
_cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
|
||||||
|
_cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
|
||||||
|
const char *p, *e, *machine;
|
||||||
|
uint32_t mapped;
|
||||||
|
uid_t gid;
|
||||||
|
size_t l;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(name);
|
||||||
|
assert(gr);
|
||||||
|
|
||||||
|
p = startswith(name, "vg-");
|
||||||
|
if (!p)
|
||||||
|
goto not_found;
|
||||||
|
|
||||||
|
e = strrchr(p, '-');
|
||||||
|
if (!e || e == p)
|
||||||
|
goto not_found;
|
||||||
|
|
||||||
|
r = parse_gid(e + 1, &gid);
|
||||||
|
if (r < 0)
|
||||||
|
goto not_found;
|
||||||
|
|
||||||
|
machine = strndupa(p, e - p);
|
||||||
|
if (!machine_name_is_valid(machine))
|
||||||
|
goto not_found;
|
||||||
|
|
||||||
|
r = sd_bus_open_system(&bus);
|
||||||
|
if (r < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
r = sd_bus_call_method(bus,
|
||||||
|
"org.freedesktop.machine1",
|
||||||
|
"/org/freedesktop/machine1",
|
||||||
|
"org.freedesktop.machine1.Manager",
|
||||||
|
"MapFromMachineGroup",
|
||||||
|
&error,
|
||||||
|
&reply,
|
||||||
|
"su",
|
||||||
|
machine, (uint32_t) gid);
|
||||||
|
if (r < 0) {
|
||||||
|
if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_GROUP_MAPPING))
|
||||||
|
goto not_found;
|
||||||
|
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sd_bus_message_read(reply, "u", &mapped);
|
||||||
|
if (r < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
l = sizeof(char*) + strlen(name) + 1;
|
||||||
|
if (buflen < l) {
|
||||||
|
*errnop = ENOMEM;
|
||||||
|
return NSS_STATUS_TRYAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
memzero(buffer, sizeof(char*));
|
||||||
|
strcpy(buffer + sizeof(char*), name);
|
||||||
|
|
||||||
|
gr->gr_name = buffer + sizeof(char*);
|
||||||
|
gr->gr_gid = gid;
|
||||||
|
gr->gr_passwd = (char*) "*"; /* locked */
|
||||||
|
gr->gr_mem = (char**) buffer;
|
||||||
|
|
||||||
|
*errnop = 0;
|
||||||
|
return NSS_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
not_found:
|
||||||
|
*errnop = 0;
|
||||||
|
return NSS_STATUS_NOTFOUND;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
*errnop = -r;
|
||||||
|
return NSS_STATUS_UNAVAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum nss_status _nss_mymachines_getgrgid_r(
|
||||||
|
gid_t gid,
|
||||||
|
struct group *gr,
|
||||||
|
char *buffer, size_t buflen,
|
||||||
|
int *errnop) {
|
||||||
|
|
||||||
|
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||||
|
_cleanup_bus_message_unref_ sd_bus_message* reply = NULL;
|
||||||
|
_cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
|
||||||
|
const char *machine, *object;
|
||||||
|
uint32_t mapped;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (GID_IS_INVALID(gid)) {
|
||||||
|
r = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We consider all gids < 65536 host gids */
|
||||||
|
if (gid < 0x10000)
|
||||||
|
goto not_found;
|
||||||
|
|
||||||
|
r = sd_bus_open_system(&bus);
|
||||||
|
if (r < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
r = sd_bus_call_method(bus,
|
||||||
|
"org.freedesktop.machine1",
|
||||||
|
"/org/freedesktop/machine1",
|
||||||
|
"org.freedesktop.machine1.Manager",
|
||||||
|
"MapToMachineGroup",
|
||||||
|
&error,
|
||||||
|
&reply,
|
||||||
|
"u",
|
||||||
|
(uint32_t) gid);
|
||||||
|
if (r < 0) {
|
||||||
|
if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_GROUP_MAPPING))
|
||||||
|
goto not_found;
|
||||||
|
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sd_bus_message_read(reply, "sou", &machine, &object, &mapped);
|
||||||
|
if (r < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (buflen < sizeof(char*) + 1) {
|
||||||
|
*errnop = ENOMEM;
|
||||||
|
return NSS_STATUS_TRYAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
memzero(buffer, sizeof(char*));
|
||||||
|
if (snprintf(buffer + sizeof(char*), buflen - sizeof(char*), "vg-%s-" GID_FMT, machine, (gid_t) mapped) >= (int) buflen) {
|
||||||
|
*errnop = ENOMEM;
|
||||||
|
return NSS_STATUS_TRYAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
gr->gr_name = buffer + sizeof(char*);
|
||||||
|
gr->gr_gid = gid;
|
||||||
|
gr->gr_passwd = (char*) "*"; /* locked */
|
||||||
|
gr->gr_mem = (char**) buffer;
|
||||||
|
|
||||||
|
*errnop = 0;
|
||||||
|
return NSS_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
not_found:
|
||||||
|
*errnop = 0;
|
||||||
|
return NSS_STATUS_NOTFOUND;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
*errnop = -r;
|
||||||
|
return NSS_STATUS_UNAVAIL;
|
||||||
|
}
|
||||||
|
@ -13,5 +13,9 @@ global:
|
|||||||
_nss_mymachines_gethostbyname2_r;
|
_nss_mymachines_gethostbyname2_r;
|
||||||
_nss_mymachines_gethostbyname3_r;
|
_nss_mymachines_gethostbyname3_r;
|
||||||
_nss_mymachines_gethostbyname4_r;
|
_nss_mymachines_gethostbyname4_r;
|
||||||
|
_nss_mymachines_getpwnam_r;
|
||||||
|
_nss_mymachines_getpwuid_r;
|
||||||
|
_nss_mymachines_getgrnam_r;
|
||||||
|
_nss_mymachines_getgrgid_r;
|
||||||
local: *;
|
local: *;
|
||||||
};
|
};
|
||||||
|
@ -24,6 +24,9 @@
|
|||||||
#include <nss.h>
|
#include <nss.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <resolv.h>
|
#include <resolv.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <grp.h>
|
||||||
|
|
||||||
|
|
||||||
#define NSS_GETHOSTBYNAME_PROTOTYPES(module) \
|
#define NSS_GETHOSTBYNAME_PROTOTYPES(module) \
|
||||||
enum nss_status _nss_##module##_gethostbyname4_r( \
|
enum nss_status _nss_##module##_gethostbyname4_r( \
|
||||||
@ -109,7 +112,8 @@ enum nss_status _nss_##module##_gethostbyname_r( \
|
|||||||
NULL, \
|
NULL, \
|
||||||
NULL); \
|
NULL); \
|
||||||
return ret; \
|
return ret; \
|
||||||
}
|
} \
|
||||||
|
struct __useless_struct_to_allow_trailing_semicolon__
|
||||||
|
|
||||||
#define NSS_GETHOSTBYADDR_FALLBACKS(module) \
|
#define NSS_GETHOSTBYADDR_FALLBACKS(module) \
|
||||||
enum nss_status _nss_##module##_gethostbyaddr_r( \
|
enum nss_status _nss_##module##_gethostbyaddr_r( \
|
||||||
@ -125,4 +129,29 @@ enum nss_status _nss_##module##_gethostbyaddr_r( \
|
|||||||
buffer, buflen, \
|
buffer, buflen, \
|
||||||
errnop, h_errnop, \
|
errnop, h_errnop, \
|
||||||
NULL); \
|
NULL); \
|
||||||
}
|
} \
|
||||||
|
struct __useless_struct_to_allow_trailing_semicolon__
|
||||||
|
|
||||||
|
#define NSS_GETPW_PROTOTYPES(module) \
|
||||||
|
enum nss_status _nss_##module##_getpwnam_r( \
|
||||||
|
const char *name, \
|
||||||
|
struct passwd *pwd, \
|
||||||
|
char *buffer, size_t buflen, \
|
||||||
|
int *errnop) _public_; \
|
||||||
|
enum nss_status _nss_mymachines_getpwuid_r( \
|
||||||
|
uid_t uid, \
|
||||||
|
struct passwd *pwd, \
|
||||||
|
char *buffer, size_t buflen, \
|
||||||
|
int *errnop) _public_
|
||||||
|
|
||||||
|
#define NSS_GETGR_PROTOTYPES(module) \
|
||||||
|
enum nss_status _nss_##module##_getgrnam_r( \
|
||||||
|
const char *name, \
|
||||||
|
struct group *gr, \
|
||||||
|
char *buffer, size_t buflen, \
|
||||||
|
int *errnop) _public_; \
|
||||||
|
enum nss_status _nss_##module##_getgrgid_r( \
|
||||||
|
gid_t gid, \
|
||||||
|
struct group *gr, \
|
||||||
|
char *buffer, size_t buflen, \
|
||||||
|
int *errnop) _public_
|
||||||
|
Loading…
Reference in New Issue
Block a user