]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
nss: add new "nss-systemd" NSS module for mapping dynamic users
authorLennart Poettering <lennart@poettering.net>
Thu, 14 Jul 2016 17:19:49 +0000 (19:19 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 22 Jul 2016 13:53:45 +0000 (15:53 +0200)
With this NSS module all dynamic service users will be resolvable via NSS like
any real user.

Makefile-man.am
Makefile.am
README
man/nss-myhostname.xml
man/nss-mymachines.xml
man/nss-resolve.xml
man/nss-systemd.xml [new file with mode: 0644]
src/core/execute.c
src/nss-systemd/Makefile [new symlink]
src/nss-systemd/nss-systemd.c [new file with mode: 0644]
src/nss-systemd/nss-systemd.sym [new file with mode: 0644]

index 8ab733360dd46e3cbbb6939c321474b31598409e..3ac1906a4a03ecc994477c8bea552ecb3c80fb05 100644 (file)
@@ -23,6 +23,7 @@ MANPAGES += \
        man/localtime.5 \
        man/machine-id.5 \
        man/machine-info.5 \
+       man/nss-systemd.8 \
        man/os-release.5 \
        man/sd-bus-errors.3 \
        man/sd-bus.3 \
@@ -255,6 +256,7 @@ MANPAGES_ALIAS += \
        man/SD_WARNING.3 \
        man/init.1 \
        man/journald.conf.d.5 \
+       man/libnss_systemd.so.2.8 \
        man/poweroff.8 \
        man/reboot.8 \
        man/sd_bus_creds_get_audit_login_uid.3 \
@@ -587,6 +589,7 @@ man/SD_NOTICE.3: man/sd-daemon.3
 man/SD_WARNING.3: man/sd-daemon.3
 man/init.1: man/systemd.1
 man/journald.conf.d.5: man/journald.conf.5
+man/libnss_systemd.so.2.8: man/nss-systemd.8
 man/poweroff.8: man/halt.8
 man/reboot.8: man/halt.8
 man/sd_bus_creds_get_audit_login_uid.3: man/sd_bus_creds_get_pid.3
@@ -1071,6 +1074,9 @@ man/init.html: man/systemd.html
 man/journald.conf.d.html: man/journald.conf.html
        $(html-alias)
 
+man/libnss_systemd.so.2.html: man/nss-systemd.html
+       $(html-alias)
+
 man/poweroff.html: man/halt.html
        $(html-alias)
 
@@ -2519,6 +2525,7 @@ EXTRA_DIST += \
        man/nss-myhostname.xml \
        man/nss-mymachines.xml \
        man/nss-resolve.xml \
+       man/nss-systemd.xml \
        man/os-release.xml \
        man/pam_systemd.xml \
        man/resolved.conf.xml \
index 3d5ce1e2c319bba1678d04fb819982dc22945fc9..a4241122d5388c04b8cee2047b9f099296e50000 100644 (file)
@@ -5001,6 +5001,27 @@ test_nss_LDADD = \
 manual_tests += \
        test-nss
 
+# ------------------------------------------------------------------------------
+libnss_systemd_la_SOURCES = \
+       src/nss-systemd/nss-systemd.sym \
+       src/nss-systemd/nss-systemd.c
+
+libnss_systemd_la_LDFLAGS = \
+       $(AM_LDFLAGS) \
+       -module \
+       -export-dynamic \
+       -avoid-version \
+       -shared \
+       -shrext .so.2 \
+       -Wl,--version-script=$(top_srcdir)/src/nss-systemd/nss-systemd.sym
+
+libnss_systemd_la_LIBADD = \
+       libsystemd-internal.la \
+       libbasic.la
+
+lib_LTLIBRARIES += \
+       libnss_systemd.la
+
 # ------------------------------------------------------------------------------
 if HAVE_MYHOSTNAME
 libnss_myhostname_la_SOURCES = \
diff --git a/README b/README
index ca8993cb1282e22fcb1c0fcecaa4f1cc6adc3f63..19c15a70b07638a624a6361c1f0b7afc8b310482 100644 (file)
--- a/README
+++ b/README
@@ -201,7 +201,7 @@ USERS AND GROUPS:
         "systemd-coredump" system user and group to exist.
 
 NSS:
-        systemd ships with three NSS modules:
+        systemd ships with four glibc NSS modules:
 
         nss-myhostname resolves the local hostname to locally
         configured IP addresses, as well as "localhost" to
@@ -210,15 +210,22 @@ NSS:
         nss-resolve enables DNS resolution via the systemd-resolved
         DNS/LLMNR caching stub resolver "systemd-resolved".
 
-        nss-mymachines enables resolution of all local containers
-        registered with machined to their respective IP addresses.
+        nss-mymachines enables resolution of all local containers registered
+        with machined to their respective IP addresses. It also maps UID/GIDs
+        ranges used by containers to useful names.
 
-        To make use of these NSS modules, please add them to the
-        "hosts: " line in /etc/nsswitch.conf. The "resolve" module
-        should replace the glibc "dns" module in this file.
+        nss-systemd enables resolution of all dynamically allocated service
+        users. (See the DynamicUser= setting in unit files.)
 
-        The three modules should be used in the following order:
+        To make use of these NSS modules, please add them to the "hosts:",
+        "passwd:" and "group:" lines in /etc/nsswitch.conf. The "resolve"
+        module should replace the glibc "dns" module in this file (and don't
+        worry, it chain-loads the "dns" module if it can't talk to resolved).
 
+        The four modules should be used in the following order:
+
+                passwd: compat mymachines systemd
+                group: compat mymachines systemd
                 hosts: files mymachines resolve myhostname
 
 SYSV INIT.D SCRIPTS:
index a920ec334f06207efe4f1e081e1b48dc046f3f79..b1daaba02b01ee0665fa19ea2f58756d9c436836 100644 (file)
     <para>Here is an example <filename>/etc/nsswitch.conf</filename> file that enables
     <command>nss-myhostname</command> correctly:</para>
 
-<programlisting>passwd:         compat mymachines
-group:          compat mymachines
+<programlisting>passwd:         compat mymachines systemd
+group:          compat mymachines systemd
 shadow:         compat
 
 hosts:          files mymachines resolve <command>myhostname</command>
@@ -138,6 +138,7 @@ netgroup:       nis</programlisting>
     <title>See Also</title>
     <para>
       <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>nss-systemd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>nss-resolve</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>nss-mymachines</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry project='man-pages'><refentrytitle>nsswitch.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
index ec047449bf99ede0b34951ba10253139ab1bfaca..a70119e25619732829da9d8809ba1cbfd10f6c92 100644 (file)
@@ -82,8 +82,8 @@
     <para>Here is an example <filename>/etc/nsswitch.conf</filename> file that enables
     <command>nss-mymachines</command> correctly:</para>
 
-    <programlisting>passwd:         compat <command>mymachines</command>
-group:          compat <command>mymachines</command>
+    <programlisting>passwd:         compat <command>mymachines</command> systemd
+group:          compat <command>mymachines</command> systemd
 shadow:         compat
 
 hosts:          files <command>mymachines</command> resolve myhostname
@@ -103,6 +103,7 @@ netgroup:       nis</programlisting>
     <para>
       <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>nss-systemd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>nss-resolve</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>nss-myhostname</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry project='man-pages'><refentrytitle>nsswitch.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
index d9e56453e8e2f71894280e415ec3693a4d2a5c0a..e6cc1d982af3f150825280f5fe3229aa1aeebf98 100644 (file)
@@ -81,8 +81,8 @@
     <para>Here is an example <filename>/etc/nsswitch.conf</filename> file that enables <command>nss-resolve</command>
     correctly:</para>
 
-<programlisting>passwd:         compat mymachines
-group:          compat mymachines
+<programlisting>passwd:         compat mymachines systemd
+group:          compat mymachines systemd
 shadow:         compat
 
 hosts:          files mymachines <command>resolve</command> myhostname
@@ -102,8 +102,9 @@ netgroup:       nis</programlisting>
     <para>
       <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd-resolved</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>nss-mymachines</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>nss-systemd</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>nss-myhostname</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>nss-mymachines</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry project='man-pages'><refentrytitle>nsswitch.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
     </para>
   </refsect1>
diff --git a/man/nss-systemd.xml b/man/nss-systemd.xml
new file mode 100644 (file)
index 0000000..4228372
--- /dev/null
@@ -0,0 +1,107 @@
+<?xml version='1.0'?> <!--*-nxml-*-->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+  "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<!--
+  This file is part of systemd.
+
+  Copyright 2016 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<refentry id="nss-systemd">
+
+  <refentryinfo>
+    <title>nss-systemd</title>
+    <productname>systemd</productname>
+
+    <authorgroup>
+      <author>
+        <contrib>Developer</contrib>
+        <firstname>Lennart</firstname>
+        <surname>Poettering</surname>
+        <email>lennart@poettering.net</email>
+      </author>
+    </authorgroup>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>nss-systemd</refentrytitle>
+    <manvolnum>8</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>nss-systemd</refname>
+    <refname>libnss_systemd.so.2</refname>
+    <refpurpose>Provide UNIX user and group name resolution for dynamic users and groups.</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <para><filename>libnss_systemd.so.2</filename></para>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para><command>nss-systemd</command> is a plug-in module for the GNU Name Service Switch (NSS) functionality of the
+    GNU C Library (<command>glibc</command>), providing UNIX user and group name resolution for dynamic users and
+    groups allocated through the <varname>DynamicUser=</varname> option in systemd unit files. See
+    <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for details on
+    this option.</para>
+
+    <para>To activate the NSS module, add <literal>systemd</literal> to the lines starting with
+    <literal>passwd:</literal> and <literal>group:</literal> in <filename>/etc/nsswitch.conf</filename>.</para>
+
+    <para>It is recommended to place <literal>systemd</literal> after the <literal>files</literal> or
+    <literal>compat</literal> entry of the <filename>/etc/nsswitch.conf</filename> lines so that
+    <filename>/etc/passwd</filename> and <filename>/etc/group</filename> based mappings take precedence.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Example</title>
+
+    <para>Here is an example <filename>/etc/nsswitch.conf</filename> file that enables
+    <command>nss-systemd</command> correctly:</para>
+
+    <programlisting>passwd:         compat mymachines <command>systemd</command>
+group:          compat mymachines <command>systemd</command>
+shadow:         compat
+
+hosts:          files mymachines resolve myhostname
+networks:       files
+
+protocols:      db files
+services:       db files
+ethers:         db files
+rpc:            db files
+
+netgroup:       nis</programlisting>
+
+  </refsect1>
+
+  <refsect1>
+    <title>See Also</title>
+    <para>
+      <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>nss-resolve</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>nss-myhostname</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>nss-mymachines</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>nsswitch.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
+      <citerefentry project='man-pages'><refentrytitle>getent</refentrytitle><manvolnum>1</manvolnum></citerefentry>
+    </para>
+  </refsect1>
+
+</refentry>
index c186f2a7059d9afb9e35745ca5506c3d4808f8ae..26e9cd5339ede7353870995045c93a7ce5ddad2d 100644 (file)
@@ -1670,6 +1670,12 @@ static int exec_child(
 
         if (context->dynamic_user && dcreds) {
 
+                /* Make sure we bypass our own NSS module for any NSS checks */
+                if (putenv((char*) "SYSTEMD_NSS_DYNAMIC_BYPASS=1") != 0) {
+                        *exit_status = EXIT_USER;
+                        return -errno;
+                }
+
                 r = dynamic_creds_realize(dcreds, &uid, &gid);
                 if (r < 0) {
                         *exit_status = EXIT_USER;
diff --git a/src/nss-systemd/Makefile b/src/nss-systemd/Makefile
new file mode 120000 (symlink)
index 0000000..d0b0e8e
--- /dev/null
@@ -0,0 +1 @@
+../Makefile
\ No newline at end of file
diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c
new file mode 100644 (file)
index 0000000..e7a4393
--- /dev/null
@@ -0,0 +1,332 @@
+/***
+  This file is part of systemd.
+
+  Copyright 2016 Lennart Poettering
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <nss.h>
+
+#include "sd-bus.h"
+
+#include "bus-common-errors.h"
+#include "env-util.h"
+#include "macro.h"
+#include "nss-util.h"
+#include "signal-util.h"
+#include "user-util.h"
+#include "util.h"
+
+NSS_GETPW_PROTOTYPES(systemd);
+NSS_GETGR_PROTOTYPES(systemd);
+
+enum nss_status _nss_systemd_getpwnam_r(
+                const char *name,
+                struct passwd *pwd,
+                char *buffer, size_t buflen,
+                int *errnop) {
+
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+        uint32_t translated;
+        size_t l;
+        int r;
+
+        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
+        assert(name);
+        assert(pwd);
+
+        /* Make sure that we don't go in circles when allocating a dynamic UID by checking our own database */
+        if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0)
+                goto not_found;
+
+        r = sd_bus_open_system(&bus);
+        if (r < 0)
+                goto fail;
+
+        r = sd_bus_call_method(bus,
+                               "org.freedesktop.systemd1",
+                               "/org/freedesktop/systemd1",
+                               "org.freedesktop.systemd1.Manager",
+                               "LookupDynamicUserByName",
+                               &error,
+                               &reply,
+                               "s",
+                               name);
+        if (r < 0) {
+                if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER))
+                        goto not_found;
+
+                goto fail;
+        }
+
+        r = sd_bus_message_read(reply, "u", &translated);
+        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 = (uid_t) translated;
+        pwd->pw_gid = (uid_t) translated;
+        pwd->pw_gecos = (char*) "Dynamic User";
+        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_systemd_getpwuid_r(
+                uid_t uid,
+                struct passwd *pwd,
+                char *buffer, size_t buflen,
+                int *errnop) {
+
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+        const char *translated;
+        size_t l;
+        int r;
+
+        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
+        if (!uid_is_valid(uid)) {
+                r = -EINVAL;
+                goto fail;
+        }
+
+        if (uid <= SYSTEM_UID_MAX)
+                goto not_found;
+
+        if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0)
+                goto not_found;
+
+        r = sd_bus_open_system(&bus);
+        if (r < 0)
+                goto fail;
+
+        r = sd_bus_call_method(bus,
+                               "org.freedesktop.systemd1",
+                               "/org/freedesktop/systemd1",
+                               "org.freedesktop.systemd1.Manager",
+                               "LookupDynamicUserByUID",
+                               &error,
+                               &reply,
+                               "u",
+                               (uint32_t) uid);
+        if (r < 0) {
+                if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER))
+                        goto not_found;
+
+                goto fail;
+        }
+
+        r = sd_bus_message_read(reply, "s", &translated);
+        if (r < 0)
+                goto fail;
+
+        l = strlen(translated) + 1;
+        if (buflen < l) {
+                *errnop = ENOMEM;
+                return NSS_STATUS_TRYAGAIN;
+        }
+
+        memcpy(buffer, translated, l);
+
+        pwd->pw_name = buffer;
+        pwd->pw_uid = uid;
+        pwd->pw_gid = uid;
+        pwd->pw_gecos = (char*) "Dynamic User";
+        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_systemd_getgrnam_r(
+                const char *name,
+                struct group *gr,
+                char *buffer, size_t buflen,
+                int *errnop) {
+
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+        uint32_t translated;
+        size_t l;
+        int r;
+
+        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
+        assert(name);
+        assert(gr);
+
+        if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0)
+                goto not_found;
+
+        r = sd_bus_open_system(&bus);
+        if (r < 0)
+                goto fail;
+
+        r = sd_bus_call_method(bus,
+                               "org.freedesktop.systemd1",
+                               "/org/freedesktop/systemd1",
+                               "org.freedesktop.systemd1.Manager",
+                               "LookupDynamicUserByName",
+                               &error,
+                               &reply,
+                               "s",
+                               name);
+        if (r < 0) {
+                if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER))
+                        goto not_found;
+
+                goto fail;
+        }
+
+        r = sd_bus_message_read(reply, "u", &translated);
+        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_t) translated;
+        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_systemd_getgrgid_r(
+                gid_t gid,
+                struct group *gr,
+                char *buffer, size_t buflen,
+                int *errnop) {
+
+        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
+        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
+        const char *translated;
+        size_t l;
+        int r;
+
+        BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
+
+        if (!gid_is_valid(gid)) {
+                r = -EINVAL;
+                goto fail;
+        }
+
+        if (gid <= SYSTEM_GID_MAX)
+                goto not_found;
+
+        if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0)
+                goto not_found;
+
+        r = sd_bus_open_system(&bus);
+        if (r < 0)
+                goto fail;
+
+        r = sd_bus_call_method(bus,
+                               "org.freedesktop.systemd1",
+                               "/org/freedesktop/systemd1",
+                               "org.freedesktop.systemd1.Manager",
+                               "LookupDynamicUserByUID",
+                               &error,
+                               &reply,
+                               "u",
+                               (uint32_t) gid);
+        if (r < 0) {
+                if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_DYNAMIC_USER))
+                        goto not_found;
+
+                goto fail;
+        }
+
+        r = sd_bus_message_read(reply, "s", &translated);
+        if (r < 0)
+                goto fail;
+
+        l = sizeof(char*) + strlen(translated) + 1;
+        if (buflen < l) {
+                *errnop = ENOMEM;
+                return NSS_STATUS_TRYAGAIN;
+        }
+
+        memzero(buffer, sizeof(char*));
+        strcpy(buffer + sizeof(char*), translated);
+
+        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;
+}
diff --git a/src/nss-systemd/nss-systemd.sym b/src/nss-systemd/nss-systemd.sym
new file mode 100644 (file)
index 0000000..9550787
--- /dev/null
@@ -0,0 +1,17 @@
+/***
+  This file is part of systemd.
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+***/
+
+{
+global:
+        _nss_systemd_getpwnam_r;
+        _nss_systemd_getpwuid_r;
+        _nss_systemd_getgrnam_r;
+        _nss_systemd_getgrgid_r;
+local: *;
+};