From: Jakub Hrozek Date: Wed, 12 Sep 2018 12:22:11 +0000 (+0200) Subject: Flush sssd caches in addition to nscd caches X-Git-Tag: 4.7~30^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F128%2Fhead;p=thirdparty%2Fshadow.git Flush sssd caches in addition to nscd caches 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. --- diff --git a/configure.ac b/configure.ac index 41068a5d5..10ad70cfb 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/lib/Makefile.am b/lib/Makefile.am index 6db86cd62..fd634542c 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -30,6 +30,8 @@ libshadow_la_SOURCES = \ lockpw.c \ nscd.c \ nscd.h \ + sssd.c \ + sssd.h \ pam_defs.h \ port.c \ port.h \ diff --git a/lib/commonio.c b/lib/commonio.c index d06b8e7dc..96f2d5f7e 100644 --- a/lib/commonio.c +++ b/lib/commonio.c @@ -45,6 +45,7 @@ #include #include #include "nscd.h" +#include "sssd.h" #ifdef WITH_TCB #include #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 index 000000000..80e49e55f --- /dev/null +++ b/lib/sssd.c @@ -0,0 +1,75 @@ +/* Author: Peter Vrabec */ + +#include +#ifdef USE_SSSD + +#include +#include +#include +#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 index 000000000..00ff2a8a3 --- /dev/null +++ b/lib/sssd.h @@ -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 + diff --git a/src/chfn.c b/src/chfn.c index 18aa3de7b..0725e1c71 100644 --- a/src/chfn.c +++ b/src/chfn.c @@ -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); diff --git a/src/chgpasswd.c b/src/chgpasswd.c index 13203a46d..e5f2eb7e8 100644 --- a/src/chgpasswd.c +++ b/src/chgpasswd.c @@ -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); } diff --git a/src/chpasswd.c b/src/chpasswd.c index 918b27ee9..49e79cdb6 100644 --- a/src/chpasswd.c +++ b/src/chpasswd.c @@ -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); } diff --git a/src/chsh.c b/src/chsh.c index c89708b92..910e3dd4c 100644 --- a/src/chsh.c +++ b/src/chsh.c @@ -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); diff --git a/src/gpasswd.c b/src/gpasswd.c index c4a492b10..4d75af96e 100644 --- a/src/gpasswd.c +++ b/src/gpasswd.c @@ -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); } diff --git a/src/groupadd.c b/src/groupadd.c index b57006c50..2dd8eec9e 100644 --- a/src/groupadd.c +++ b/src/groupadd.c @@ -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; } diff --git a/src/groupdel.c b/src/groupdel.c index 70bed010a..f941a84ad 100644 --- a/src/groupdel.c +++ b/src/groupdel.c @@ -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; } diff --git a/src/groupmod.c b/src/groupmod.c index b293b98f6..1dca5fc9c 100644 --- a/src/groupmod.c +++ b/src/groupmod.c @@ -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; } diff --git a/src/grpck.c b/src/grpck.c index ea5d3b39e..6140b10df 100644 --- a/src/grpck.c +++ b/src/grpck.c @@ -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. diff --git a/src/grpconv.c b/src/grpconv.c index f95f49602..5e5eaaca3 100644 --- a/src/grpconv.c +++ b/src/grpconv.c @@ -48,6 +48,7 @@ #include #include #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; } diff --git a/src/grpunconv.c b/src/grpunconv.c index 253f06f51..e4105c265 100644 --- a/src/grpunconv.c +++ b/src/grpunconv.c @@ -48,6 +48,7 @@ #include #include #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; } diff --git a/src/newusers.c b/src/newusers.c index 8e4bef973..7c3bb1c2d 100644 --- a/src/newusers.c +++ b/src/newusers.c @@ -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; diff --git a/src/passwd.c b/src/passwd.c index 3af3e6517..5bea27657 100644 --- a/src/passwd.c +++ b/src/passwd.c @@ -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 (); diff --git a/src/pwck.c b/src/pwck.c index 05df68ece..0ffb711ef 100644 --- a/src/pwck.c +++ b/src/pwck.c @@ -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. diff --git a/src/pwconv.c b/src/pwconv.c index d6ee31a8f..9c69fa131 100644 --- a/src/pwconv.c +++ b/src/pwconv.c @@ -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; } diff --git a/src/pwunconv.c b/src/pwunconv.c index fabf02376..e11ea4941 100644 --- a/src/pwunconv.c +++ b/src/pwunconv.c @@ -42,6 +42,7 @@ #include #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; } diff --git a/src/useradd.c b/src/useradd.c index ca90f076a..b0c2224d6 100644 --- a/src/useradd.c +++ b/src/useradd.c @@ -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; } diff --git a/src/userdel.c b/src/userdel.c index c8de1d316..0715e4fe9 100644 --- a/src/userdel.c +++ b/src/userdel.c @@ -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); } diff --git a/src/usermod.c b/src/usermod.c index 7355ad311..fd9a98a63 100644 --- a/src/usermod.c +++ b/src/usermod.c @@ -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) { diff --git a/src/vipw.c b/src/vipw.c index 6d730f65a..2cfac6b48 100644 --- a/src/vipw.c +++ b/src/vipw.c @@ -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; }