]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
Flush sssd caches in addition to nscd caches 128/head
authorJakub Hrozek <jakub.hrozek@posteo.se>
Wed, 12 Sep 2018 12:22:11 +0000 (14:22 +0200)
committerJakub Hrozek <jakub.hrozek@posteo.se>
Thu, 13 Sep 2018 12:20:02 +0000 (14:20 +0200)
Some distributions, notably Fedora, have the following order of nsswitch
modules by default:
    passwd: sss files
    group:  sss files

The advantage of serving local users through SSSD is that the nss_sss
module has a fast mmapped-cache that speeds up NSS lookups compared to
accessing the disk an opening the files on each NSS request.

Traditionally, this has been done with the help of nscd, but using nscd
in parallel with sssd is cumbersome, as both SSSD and nscd use their own
independent caching, so using nscd in setups where sssd is also serving
users from some remote domain (LDAP, AD, ...) can result in a bit of
unpredictability.

More details about why Fedora chose to use sss before files can be found
on e.g.:
    https://fedoraproject.org//wiki/Changes/SSSDCacheForLocalUsers
or:
    https://docs.pagure.org/SSSD.sssd/design_pages/files_provider.html

Now, even though sssd watches the passwd and group files with the help
of inotify, there can still be a small window where someone requests a
user or a group, finds that it doesn't exist, adds the entry and checks
again. Without some support in shadow-utils that would explicitly drop
the sssd caches, the inotify watch can fire a little late, so a
combination of commands like this:
    getent passwd user || useradd user; getent passwd user
can result in the second getent passwd not finding the newly added user
as the racy behaviour might still return the cached negative hit from
the first getent passwd.

This patch more or less copies the already existing support that
shadow-utils had for dropping nscd caches, except using the "sss_cache"
tool that sssd ships.

25 files changed:
configure.ac
lib/Makefile.am
lib/commonio.c
lib/sssd.c [new file with mode: 0644]
lib/sssd.h [new file with mode: 0644]
src/chfn.c
src/chgpasswd.c
src/chpasswd.c
src/chsh.c
src/gpasswd.c
src/groupadd.c
src/groupdel.c
src/groupmod.c
src/grpck.c
src/grpconv.c
src/grpunconv.c
src/newusers.c
src/passwd.c
src/pwck.c
src/pwconv.c
src/pwunconv.c
src/useradd.c
src/userdel.c
src/usermod.c
src/vipw.c

index 41068a5d5b0555702d7e54f744a7630110d7e1a9..10ad70cfb572c21121ff94ee1e6fc4a469f031d9 100644 (file)
@@ -280,6 +280,9 @@ AC_ARG_WITH(sha-crypt,
 AC_ARG_WITH(nscd,
        [AC_HELP_STRING([--with-nscd], [enable support for nscd @<:@default=yes@:>@])],
        [with_nscd=$withval], [with_nscd=yes])
+AC_ARG_WITH(sssd,
+       [AC_HELP_STRING([--with-sssd], [enable support for flushing sssd caches @<:@default=yes@:>@])],
+       [with_sssd=$withval], [with_sssd=yes])
 AC_ARG_WITH(group-name-max-length,
        [AC_HELP_STRING([--with-group-name-max-length], [set max group name length @<:@default=16@:>@])],
        [with_group_name_max_length=$withval], [with_group_name_max_length=yes])
@@ -304,6 +307,12 @@ if test "$with_nscd" = "yes"; then
                      [AC_MSG_ERROR([posix_spawn is needed for nscd support])])
 fi
 
+if test "$with_sssd" = "yes"; then
+       AC_CHECK_FUNC(posix_spawn,
+                     [AC_DEFINE(USE_SSSD, 1, [Define to support flushing of sssd caches])],
+                     [AC_MSG_ERROR([posix_spawn is needed for sssd support])])
+fi
+
 dnl Check for some functions in libc first, only if not found check for
 dnl other libraries.  This should prevent linking libnsl if not really
 dnl needed (Linux glibc, Irix), but still link it if needed (Solaris).
@@ -679,5 +688,6 @@ echo "      shadow group support:           $enable_shadowgrp"
 echo " S/Key support:                  $with_skey"
 echo " SHA passwords encryption:       $with_sha_crypt"
 echo " nscd support:                   $with_nscd"
+echo " sssd support:                   $with_sssd"
 echo " subordinate IDs support:        $enable_subids"
 echo
index 6db86cd628aafad8977645028ada61abafd4a20b..fd634542c8c14d267a9e4ad1a804093969db7c5d 100644 (file)
@@ -30,6 +30,8 @@ libshadow_la_SOURCES = \
        lockpw.c \
        nscd.c \
        nscd.h \
+       sssd.c \
+       sssd.h \
        pam_defs.h \
        port.c \
        port.h \
index d06b8e7dc94e1a5a0ed9eae6a5660e561238f509..96f2d5f7ec41b8b4a0edb0e13fc803303252de9f 100644 (file)
@@ -45,6 +45,7 @@
 #include <stdio.h>
 #include <signal.h>
 #include "nscd.h"
+#include "sssd.h"
 #ifdef WITH_TCB
 #include <tcb.h>
 #endif                         /* WITH_TCB */
@@ -485,6 +486,7 @@ static void dec_lock_count (void)
                        if (nscd_need_reload) {
                                nscd_flush_cache ("passwd");
                                nscd_flush_cache ("group");
+                               sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP);
                                nscd_need_reload = false;
                        }
 #ifdef HAVE_LCKPWDF
diff --git a/lib/sssd.c b/lib/sssd.c
new file mode 100644 (file)
index 0000000..80e49e5
--- /dev/null
@@ -0,0 +1,75 @@
+/* Author: Peter Vrabec <pvrabec@redhat.com> */
+
+#include <config.h>
+#ifdef USE_SSSD
+
+#include <stdio.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include "exitcodes.h"
+#include "defines.h"
+#include "prototypes.h"
+#include "sssd.h"
+
+#define MSG_SSSD_FLUSH_CACHE_FAILED "%s: Failed to flush the sssd cache.\n"
+
+int sssd_flush_cache (int dbflags)
+{
+       int status, code, rv;
+       const char *cmd = "/usr/sbin/sss_cache";
+       char *sss_cache_args = NULL;
+       const char *spawnedArgs[] = {"sss_cache", NULL, NULL};
+       const char *spawnedEnv[] = {NULL};
+       int i = 0;
+
+       sss_cache_args = malloc(4);
+       if (sss_cache_args == NULL) {
+           return -1;
+       }
+
+       sss_cache_args[i++] = '-';
+       if (dbflags & SSSD_DB_PASSWD) {
+               sss_cache_args[i++] = 'U';
+       }
+       if (dbflags & SSSD_DB_GROUP) {
+               sss_cache_args[i++] = 'G';
+       }
+       sss_cache_args[i++] = '\0';
+       if (i == 2) {
+               /* Neither passwd nor group, nothing to do */
+               free(sss_cache_args);
+               return 0;
+       }
+       spawnedArgs[1] = sss_cache_args;
+
+       rv = run_command (cmd, spawnedArgs, spawnedEnv, &status);
+       free(sss_cache_args);
+       if (rv != 0) {
+               /* run_command writes its own more detailed message. */
+               (void) fprintf (stderr, _(MSG_SSSD_FLUSH_CACHE_FAILED), Prog);
+               return -1;
+       }
+
+       code = WEXITSTATUS (status);
+       if (!WIFEXITED (status)) {
+               (void) fprintf (stderr,
+                               _("%s: sss_cache did not terminate normally (signal %d)\n"),
+                               Prog, WTERMSIG (status));
+               return -1;
+       } else if (code == E_CMD_NOTFOUND) {
+               /* sss_cache is not installed, or it is installed but uses an
+                  interpreter that is missing.  Probably the former. */
+               return 0;
+       } else if (code != 0) {
+               (void) fprintf (stderr, _("%s: sss_cache exited with status %d\n"),
+                               Prog, code);
+               (void) fprintf (stderr, _(MSG_SSSD_FLUSH_CACHE_FAILED), Prog);
+               return -1;
+       }
+
+       return 0;
+}
+#else                          /* USE_SSSD */
+extern int errno;              /* warning: ANSI C forbids an empty source file */
+#endif                         /* USE_SSSD */
+
diff --git a/lib/sssd.h b/lib/sssd.h
new file mode 100644 (file)
index 0000000..00ff2a8
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef _SSSD_H_
+#define _SSSD_H_
+
+#define SSSD_DB_PASSWD 0x001
+#define SSSD_DB_GROUP  0x002
+
+/*
+ * sssd_flush_cache - flush specified service buffer in sssd cache
+ */
+#ifdef USE_SSSD
+extern int sssd_flush_cache (int dbflags);
+#else
+#define sssd_flush_cache(service) (0)
+#endif
+
+#endif
+
index 18aa3de7b4d03a25090e26696eda4be6d26ba15d..0725e1c7124f3184a8cd091fa386e4d85ed94eb1 100644 (file)
@@ -47,6 +47,7 @@
 #include "defines.h"
 #include "getdef.h"
 #include "nscd.h"
+#include "sssd.h"
 #ifdef USE_PAM
 #include "pam_defs.h"
 #endif
@@ -746,6 +747,7 @@ int main (int argc, char **argv)
        SYSLOG ((LOG_INFO, "changed user '%s' information", user));
 
        nscd_flush_cache ("passwd");
+       sssd_flush_cache (SSSD_DB_PASSWD);
 
        closelog ();
        exit (E_SUCCESS);
index 13203a46d7f3bf4805a8b5a4e3e2b63a804efdfa..e5f2eb7e86077931772cb5a07d1a77e1077427d2 100644 (file)
@@ -46,6 +46,7 @@
 #endif                         /* ACCT_TOOLS_SETUID */
 #include "defines.h"
 #include "nscd.h"
+#include "sssd.h"
 #include "prototypes.h"
 #include "groupio.h"
 #ifdef SHADOWGRP
@@ -581,6 +582,7 @@ int main (int argc, char **argv)
        close_files ();
 
        nscd_flush_cache ("group");
+       sssd_flush_cache (SSSD_DB_GROUP);
 
        return (0);
 }
index 918b27ee95743be68ab9169b1b248d05a65dab64..49e79cdb6260ff1636d217d568e87747f0f0e5c9 100644 (file)
@@ -44,6 +44,7 @@
 #endif                         /* USE_PAM */
 #include "defines.h"
 #include "nscd.h"
+#include "sssd.h"
 #include "getdef.h"
 #include "prototypes.h"
 #include "pwio.h"
@@ -624,6 +625,7 @@ int main (int argc, char **argv)
        }
 
        nscd_flush_cache ("passwd");
+       sssd_flush_cache (SSSD_DB_PASSWD);
 
        return (0);
 }
index c89708b9222017ff23c2a1871db3d2b7b36a4899..910e3dd4cd0de2c15baf0c6f048b589c6a91d3d4 100644 (file)
@@ -46,6 +46,7 @@
 #include "defines.h"
 #include "getdef.h"
 #include "nscd.h"
+#include "sssd.h"
 #include "prototypes.h"
 #include "pwauth.h"
 #include "pwio.h"
@@ -557,6 +558,7 @@ int main (int argc, char **argv)
        SYSLOG ((LOG_INFO, "changed user '%s' shell to '%s'", user, loginsh));
 
        nscd_flush_cache ("passwd");
+       sssd_flush_cache (SSSD_DB_PASSWD);
 
        closelog ();
        exit (E_SUCCESS);
index c4a492b105ec46d9cc46c1ad029e50a60c684fa5..4d75af96e4dbef43be4f6721280728d57928e752 100644 (file)
@@ -45,6 +45,7 @@
 #include "defines.h"
 #include "groupio.h"
 #include "nscd.h"
+#include "sssd.h"
 #include "prototypes.h"
 #ifdef SHADOWGRP
 #include "sgroupio.h"
@@ -1201,6 +1202,7 @@ int main (int argc, char **argv)
        close_files ();
 
        nscd_flush_cache ("group");
+       sssd_flush_cache (SSSD_DB_GROUP);
 
        exit (E_SUCCESS);
 }
index b57006c5068933e5af5551f472ad01f5f2070950..2dd8eec9e4eff8c204e8c9ccf79a10de393d0ba6 100644 (file)
@@ -51,6 +51,7 @@
 #include "getdef.h"
 #include "groupio.h"
 #include "nscd.h"
+#include "sssd.h"
 #include "prototypes.h"
 #ifdef SHADOWGRP
 #include "sgroupio.h"
@@ -625,6 +626,7 @@ int main (int argc, char **argv)
        close_files ();
 
        nscd_flush_cache ("group");
+       sssd_flush_cache (SSSD_DB_GROUP);
 
        return E_SUCCESS;
 }
index 70bed010ac2b0b9437d6f7599d8d3eac1884b846..f941a84ad43d8add2161b76a741f66631bcf1282 100644 (file)
@@ -49,6 +49,7 @@
 #include "defines.h"
 #include "groupio.h"
 #include "nscd.h"
+#include "sssd.h"
 #include "prototypes.h"
 #ifdef SHADOWGRP
 #include "sgroupio.h"
@@ -492,6 +493,7 @@ int main (int argc, char **argv)
        close_files ();
 
        nscd_flush_cache ("group");
+       sssd_flush_cache (SSSD_DB_GROUP);
 
        return E_SUCCESS;
 }
index b293b98f61bd2b116fefebaa813057421864583f..1dca5fc9c22bbddb57dd71c4b276947cb861d657 100644 (file)
@@ -51,6 +51,7 @@
 #include "groupio.h"
 #include "pwio.h"
 #include "nscd.h"
+#include "sssd.h"
 #include "prototypes.h"
 #ifdef SHADOWGRP
 #include "sgroupio.h"
@@ -877,6 +878,7 @@ int main (int argc, char **argv)
        close_files ();
 
        nscd_flush_cache ("group");
+       sssd_flush_cache (SSSD_DB_GROUP);
 
        return E_SUCCESS;
 }
index ea5d3b39eb034a52fcbd49f86a7b40740e0c60de..6140b10dff865bce4af6bb597ebd0b05b72a33b2 100644 (file)
@@ -45,6 +45,7 @@
 #include "defines.h"
 #include "groupio.h"
 #include "nscd.h"
+#include "sssd.h"
 #include "prototypes.h"
 
 #ifdef SHADOWGRP
@@ -870,6 +871,7 @@ int main (int argc, char **argv)
        close_files (changed);
 
        nscd_flush_cache ("group");
+       sssd_flush_cache (SSSD_DB_GROUP);
 
        /*
         * Tell the user what we did and exit.
index f95f4960255fe9a86079f9db15afba209b39edc3..5e5eaaca384045861192fe8f8ea20819b7bf25a7 100644 (file)
@@ -48,6 +48,7 @@
 #include <unistd.h>
 #include <getopt.h>
 #include "nscd.h"
+#include "sssd.h"
 #include "prototypes.h"
 /*@-exitarg@*/
 #include "exitcodes.h"
@@ -273,6 +274,7 @@ int main (int argc, char **argv)
        }
 
        nscd_flush_cache ("group");
+       sssd_flush_cache (SSSD_DB_GROUP);
 
        return 0;
 }
index 253f06f51f136e2227ef4995c9c9ac05eeb99d2a..e4105c2654ece54dbeca26069776a4e6d37a4c34 100644 (file)
@@ -48,6 +48,7 @@
 #include <grp.h>
 #include <getopt.h>
 #include "nscd.h"
+#include "sssd.h"
 #include "prototypes.h"
 /*@-exitarg@*/
 #include "exitcodes.h"
@@ -236,6 +237,7 @@ int main (int argc, char **argv)
        }
 
        nscd_flush_cache ("group");
+       sssd_flush_cache (SSSD_DB_GROUP);
 
        return 0;
 }
index 8e4bef9734bfc59244c39fc1622f94c79cd0d903..7c3bb1c2d65e1dcb5bd1a26178f7001d1a842e1f 100644 (file)
@@ -62,6 +62,7 @@
 #include "getdef.h"
 #include "groupio.h"
 #include "nscd.h"
+#include "sssd.h"
 #include "pwio.h"
 #include "sgroupio.h"
 #include "shadowio.h"
@@ -1233,6 +1234,7 @@ int main (int argc, char **argv)
 
        nscd_flush_cache ("passwd");
        nscd_flush_cache ("group");
+       sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP);
 
 #ifdef USE_PAM
        unsigned int i;
index 3af3e65173231aa52c506653375bdae9eef7021c..5bea2765742fa91e02edbc409056226168256288 100644 (file)
@@ -51,6 +51,7 @@
 #include "defines.h"
 #include "getdef.h"
 #include "nscd.h"
+#include "sssd.h"
 #include "prototypes.h"
 #include "pwauth.h"
 #include "pwio.h"
@@ -1150,6 +1151,7 @@ int main (int argc, char **argv)
 
        nscd_flush_cache ("passwd");
        nscd_flush_cache ("group");
+       sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP);
 
        SYSLOG ((LOG_INFO, "password for '%s' changed by '%s'", name, myname));
        closelog ();
index 05df68ece8c679d9edb0688fa3661d4c4d2cfcc5..0ffb711efb13d7021b42d9671fd5fd0dc8ad85fa 100644 (file)
@@ -48,6 +48,7 @@
 #include "shadowio.h"
 #include "getdef.h"
 #include "nscd.h"
+#include "sssd.h"
 #ifdef WITH_TCB
 #include "tcbfuncs.h"
 #endif                         /* WITH_TCB */
@@ -877,6 +878,7 @@ int main (int argc, char **argv)
        close_files (changed);
 
        nscd_flush_cache ("passwd");
+       sssd_flush_cache (SSSD_DB_PASSWD);
 
        /*
         * Tell the user what we did and exit.
index d6ee31a8febab0d1015d1bbb771fa0f5c6591137..9c69fa131d8e34a3a1c7069a22e22e0cd31ecf53 100644 (file)
@@ -72,6 +72,7 @@
 #include "pwio.h"
 #include "shadowio.h"
 #include "nscd.h"
+#include "sssd.h"
 
 /*
  * exit status values
@@ -328,6 +329,7 @@ int main (int argc, char **argv)
        }
 
        nscd_flush_cache ("passwd");
+       sssd_flush_cache (SSSD_DB_PASSWD);
 
        return E_SUCCESS;
 }
index fabf02376389323f4164506baf279e66aaed59df..e11ea4941e795a97f8d84c33dfd129b7a9cf773d 100644 (file)
@@ -42,6 +42,7 @@
 #include <getopt.h>
 #include "defines.h"
 #include "nscd.h"
+#include "sssd.h"
 #include "prototypes.h"
 #include "pwio.h"
 #include "shadowio.h"
@@ -250,6 +251,7 @@ int main (int argc, char **argv)
        }
 
        nscd_flush_cache ("passwd");
+       sssd_flush_cache (SSSD_DB_PASSWD);
 
        return 0;
 }
index ca90f076ab2f1e26de24b218a84b66a923e14fd8..b0c2224d69b0beb6611ddf0d6c6a02e9bd7a0acd 100644 (file)
@@ -60,6 +60,7 @@
 #include "getdef.h"
 #include "groupio.h"
 #include "nscd.h"
+#include "sssd.h"
 #include "prototypes.h"
 #include "pwauth.h"
 #include "pwio.h"
@@ -2425,6 +2426,7 @@ int main (int argc, char **argv)
 
        nscd_flush_cache ("passwd");
        nscd_flush_cache ("group");
+       sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP);
 
        return E_SUCCESS;
 }
index c8de1d316876e4f7d6e4f65bcdf85ead50fdb8ca..0715e4fe9043542221037f9d96252051cb49902f 100644 (file)
@@ -53,6 +53,7 @@
 #include "getdef.h"
 #include "groupio.h"
 #include "nscd.h"
+#include "sssd.h"
 #include "prototypes.h"
 #include "pwauth.h"
 #include "pwio.h"
@@ -1328,6 +1329,7 @@ int main (int argc, char **argv)
 
        nscd_flush_cache ("passwd");
        nscd_flush_cache ("group");
+       sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP);
 
        return ((0 != errors) ? E_HOMEDIR : E_SUCCESS);
 }
index 7355ad31103dd0f38101e0adecad866cbe81e69f..fd9a98a63a912fbae5a927e7614a28dcafa8e608 100644 (file)
@@ -57,6 +57,7 @@
 #include "getdef.h"
 #include "groupio.h"
 #include "nscd.h"
+#include "sssd.h"
 #include "prototypes.h"
 #include "pwauth.h"
 #include "pwio.h"
@@ -2255,6 +2256,7 @@ int main (int argc, char **argv)
 
        nscd_flush_cache ("passwd");
        nscd_flush_cache ("group");
+       sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP);
 
 #ifdef WITH_SELINUX
        if (Zflg) {
index 6d730f65a3c9f8056e72709b496ffa5c92c21a73..2cfac6b4810e05321647ec3e42211bbe036882c6 100644 (file)
@@ -42,6 +42,7 @@
 #include "defines.h"
 #include "groupio.h"
 #include "nscd.h"
+#include "sssd.h"
 #include "prototypes.h"
 #include "pwio.h"
 #include "sgroupio.h"
@@ -556,6 +557,7 @@ int main (int argc, char **argv)
 
        nscd_flush_cache ("passwd");
        nscd_flush_cache ("group");
+       sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP);
 
        return E_SUCCESS;
 }