Skip to content

Commit

Permalink
Flush sssd caches in addition to nscd caches
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jhrozek committed Sep 13, 2018
1 parent 6bf2d74 commit 4aaf05d
Show file tree
Hide file tree
Showing 25 changed files with 146 additions and 0 deletions.
10 changes: 10 additions & 0 deletions configure.ac
Expand Up @@ -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])
Expand All @@ -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).
Expand Down Expand Up @@ -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
2 changes: 2 additions & 0 deletions lib/Makefile.am
Expand Up @@ -30,6 +30,8 @@ libshadow_la_SOURCES = \
lockpw.c \
nscd.c \
nscd.h \
sssd.c \
sssd.h \
pam_defs.h \
port.c \
port.h \
Expand Down
2 changes: 2 additions & 0 deletions lib/commonio.c
Expand Up @@ -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 */
Expand Down Expand Up @@ -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
Expand Down
75 changes: 75 additions & 0 deletions lib/sssd.c
@@ -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 */

17 changes: 17 additions & 0 deletions 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

2 changes: 2 additions & 0 deletions src/chfn.c
Expand Up @@ -47,6 +47,7 @@
#include "defines.h"
#include "getdef.h"
#include "nscd.h"
#include "sssd.h"
#ifdef USE_PAM
#include "pam_defs.h"
#endif
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions src/chgpasswd.c
Expand Up @@ -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
Expand Down Expand Up @@ -581,6 +582,7 @@ int main (int argc, char **argv)
close_files ();

nscd_flush_cache ("group");
sssd_flush_cache (SSSD_DB_GROUP);

return (0);
}
Expand Down
2 changes: 2 additions & 0 deletions src/chpasswd.c
Expand Up @@ -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"
Expand Down Expand Up @@ -624,6 +625,7 @@ int main (int argc, char **argv)
}

nscd_flush_cache ("passwd");
sssd_flush_cache (SSSD_DB_PASSWD);

return (0);
}
Expand Down
2 changes: 2 additions & 0 deletions src/chsh.c
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions src/gpasswd.c
Expand Up @@ -45,6 +45,7 @@
#include "defines.h"
#include "groupio.h"
#include "nscd.h"
#include "sssd.h"
#include "prototypes.h"
#ifdef SHADOWGRP
#include "sgroupio.h"
Expand Down Expand Up @@ -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);
}
Expand Down
2 changes: 2 additions & 0 deletions src/groupadd.c
Expand Up @@ -51,6 +51,7 @@
#include "getdef.h"
#include "groupio.h"
#include "nscd.h"
#include "sssd.h"
#include "prototypes.h"
#ifdef SHADOWGRP
#include "sgroupio.h"
Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 2 additions & 0 deletions src/groupdel.c
Expand Up @@ -49,6 +49,7 @@
#include "defines.h"
#include "groupio.h"
#include "nscd.h"
#include "sssd.h"
#include "prototypes.h"
#ifdef SHADOWGRP
#include "sgroupio.h"
Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 2 additions & 0 deletions src/groupmod.c
Expand Up @@ -51,6 +51,7 @@
#include "groupio.h"
#include "pwio.h"
#include "nscd.h"
#include "sssd.h"
#include "prototypes.h"
#ifdef SHADOWGRP
#include "sgroupio.h"
Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 2 additions & 0 deletions src/grpck.c
Expand Up @@ -45,6 +45,7 @@
#include "defines.h"
#include "groupio.h"
#include "nscd.h"
#include "sssd.h"
#include "prototypes.h"

#ifdef SHADOWGRP
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 2 additions & 0 deletions src/grpconv.c
Expand Up @@ -48,6 +48,7 @@
#include <unistd.h>
#include <getopt.h>
#include "nscd.h"
#include "sssd.h"
#include "prototypes.h"
/*@-exitarg@*/
#include "exitcodes.h"
Expand Down Expand Up @@ -273,6 +274,7 @@ int main (int argc, char **argv)
}

nscd_flush_cache ("group");
sssd_flush_cache (SSSD_DB_GROUP);

return 0;
}
Expand Down
2 changes: 2 additions & 0 deletions src/grpunconv.c
Expand Up @@ -48,6 +48,7 @@
#include <grp.h>
#include <getopt.h>
#include "nscd.h"
#include "sssd.h"
#include "prototypes.h"
/*@-exitarg@*/
#include "exitcodes.h"
Expand Down Expand Up @@ -236,6 +237,7 @@ int main (int argc, char **argv)
}

nscd_flush_cache ("group");
sssd_flush_cache (SSSD_DB_GROUP);

return 0;
}
Expand Down
2 changes: 2 additions & 0 deletions src/newusers.c
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions src/passwd.c
Expand Up @@ -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"
Expand Down Expand Up @@ -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 ();
Expand Down
2 changes: 2 additions & 0 deletions src/pwck.c
Expand Up @@ -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 */
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 2 additions & 0 deletions src/pwconv.c
Expand Up @@ -72,6 +72,7 @@
#include "pwio.h"
#include "shadowio.h"
#include "nscd.h"
#include "sssd.h"

/*
* exit status values
Expand Down Expand Up @@ -328,6 +329,7 @@ int main (int argc, char **argv)
}

nscd_flush_cache ("passwd");
sssd_flush_cache (SSSD_DB_PASSWD);

return E_SUCCESS;
}
Expand Down

0 comments on commit 4aaf05d

Please sign in to comment.