summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthur de Jong <arthur@arthurdejong.org>2013-07-26 14:26:55 +0200
committerArthur de Jong <arthur@arthurdejong.org>2013-07-26 14:26:55 +0200
commit6054499f9a9952593ccadc83182e01d39ff62f12 (patch)
tree74b61921f9bcbf780863060971a2bf280a9fd5c3
parentd2e2e400e79c94c2e60f21ec61811dfe948924cc (diff)
Allow invalidating the nfsidmap cache
This introduces an nfsidmap value for nscd_invalidate which will cause the nfsidmap -c command to be run.
-rw-r--r--man/nslcd.conf.5.xml16
-rw-r--r--nslcd/attmap.c3
-rw-r--r--nslcd/cfg.c1
-rw-r--r--nslcd/cfg.h1
-rw-r--r--nslcd/nscd.c24
-rw-r--r--pynslcd/cfg.py2
-rw-r--r--pynslcd/nscd.py32
7 files changed, 54 insertions, 25 deletions
diff --git a/man/nslcd.conf.5.xml b/man/nslcd.conf.5.xml
index 87d21f8..9435e3a 100644
--- a/man/nslcd.conf.5.xml
+++ b/man/nslcd.conf.5.xml
@@ -825,13 +825,21 @@
<para>
If this option is set, on start-up and whenever a connection to the
<acronym>LDAP</acronym> server is re-established after an error
+ the specified cache is flushed.
+ </para>
+ <para>
+ If <replaceable>DB</replaceable> is one of the nsswitch maps,
<command>nscd</command> is contacted to flush it's cache for the
- configured databases.
+ specified database.
+ </para>
+ <para> <!-- since 0.9.1 -->
+ If <replaceable>DB</replaceable> is <literal>nfsidmap</literal>,
+ <command>nfsidmap</command> to contacted to clear it's cache.
</para>
<para>
- Using this option ensures that <command>nscd</command> is not
- caching absence of users that were not available if the LDAP server
- was unavailable.
+ Using this option ensures that external caches are cleared of
+ information (typically the absence of users) while the
+ <acronym>LDAP</acronym> server was unavailable.
</para>
</listitem>
</varlistentry>
diff --git a/nslcd/attmap.c b/nslcd/attmap.c
index 2480096..08130fa 100644
--- a/nslcd/attmap.c
+++ b/nslcd/attmap.c
@@ -57,6 +57,7 @@ const char **base_get_var(enum ldap_map_selector map)
case LM_RPC: return rpc_bases;
case LM_SERVICES: return service_bases;
case LM_SHADOW: return shadow_bases;
+ case LM_NFSIDMAP:
case LM_NONE:
default: return NULL;
}
@@ -90,6 +91,7 @@ int *scope_get_var(enum ldap_map_selector map)
case LM_RPC: return &rpc_scope;
case LM_SERVICES: return &service_scope;
case LM_SHADOW: return &shadow_scope;
+ case LM_NFSIDMAP:
case LM_NONE:
default: return NULL;
}
@@ -123,6 +125,7 @@ const char **filter_get_var(enum ldap_map_selector map)
case LM_RPC: return &rpc_filter;
case LM_SERVICES: return &service_filter;
case LM_SHADOW: return &shadow_filter;
+ case LM_NFSIDMAP:
case LM_NONE:
default: return NULL;
}
diff --git a/nslcd/cfg.c b/nslcd/cfg.c
index 056b6e2..381ddec 100644
--- a/nslcd/cfg.c
+++ b/nslcd/cfg.c
@@ -527,6 +527,7 @@ static const char *print_map(enum ldap_map_selector map)
case LM_RPC: return "rpc";
case LM_SERVICES: return "services";
case LM_SHADOW: return "shadow";
+ case LM_NFSIDMAP: return "nfsidmap";
case LM_NONE:
default: return "???";
}
diff --git a/nslcd/cfg.h b/nslcd/cfg.h
index bd53560..4ec31ff 100644
--- a/nslcd/cfg.h
+++ b/nslcd/cfg.h
@@ -67,6 +67,7 @@ enum ldap_map_selector {
LM_RPC,
LM_SERVICES,
LM_SHADOW,
+ LM_NFSIDMAP, /* only used for cache invalidation */
LM_NONE
};
diff --git a/nslcd/nscd.c b/nslcd/nscd.c
index da58c2e..14a976c 100644
--- a/nslcd/nscd.c
+++ b/nslcd/nscd.c
@@ -55,6 +55,7 @@ static const char *map2name(enum ldap_map_selector map)
case LM_RPC: return "rpc";
case LM_SERVICES: return "services";
case LM_SHADOW: return "shadow";
+ case LM_NFSIDMAP: return "nfsidmap";
case LM_NONE:
default: return NULL;
}
@@ -65,7 +66,7 @@ static void exec_invalidate(const char *db)
{
pid_t cpid;
int i, status;
- char *argv[] = { "nscd", "-i", NULL, NULL };
+ char *argv[4];
#ifdef HAVE_EXECVPE
char *newenviron[] = { NULL };
#endif
@@ -82,12 +83,25 @@ static void exec_invalidate(const char *db)
i = 32;
for (; i >= 0; i--)
close(i);
+ /* build command line */
+ if (strcmp(db, "nfsidmap") == 0)
+ {
+ argv[0] = "nfsidmap";
+ argv[1] = "-c";
+ argv[2] = NULL;
+ }
+ else
+ {
+ argv[0] = "nscd";
+ argv[1] = "-i";
+ argv[2] = (char *)db;
+ argv[3] = NULL;
+ }
/* execute command */
- argv[2] = (char *)db;
#ifdef HAVE_EXECVPE
- execvpe("nscd", argv, newenviron);
+ execvpe(argv[0], argv, newenviron);
#else
- execvp("nscd", argv);
+ execvp(argv[0], argv);
#endif
/* if we are here there has been an error */
/* we can't log since we don't have any useful file descriptors */
@@ -137,7 +151,7 @@ static void nscd_handle_requests(int fd)
const char *db;
log_log(LOG_DEBUG, "nscd_invalidator: starting");
/* set up environment */
- chdir("/");
+ (void)chdir("/");
putenv("PATH=/usr/sbin:/usr/bin:/sbin:/bin");
/* handle incoming requests */
while (1)
diff --git a/pynslcd/cfg.py b/pynslcd/cfg.py
index a9f1d89..516eeb7 100644
--- a/pynslcd/cfg.py
+++ b/pynslcd/cfg.py
@@ -317,7 +317,7 @@ def read(filename):
if m:
dbs = re.split('[ ,]+', m.group('value').lower())
for db in dbs:
- if db not in maps:
+ if db not in maps.keys() + ['nfsidmap']:
raise ParseError(filename, lineno, 'map %s unknown' % db)
nscd_invalidate.update(dbs)
continue
diff --git a/pynslcd/nscd.py b/pynslcd/nscd.py
index acee9a9..1cc05cf 100644
--- a/pynslcd/nscd.py
+++ b/pynslcd/nscd.py
@@ -34,31 +34,31 @@ signalfd = None
_db_to_char = dict(
aliases='A', ethers='E', group='G', hosts='H', netgroup='U',
networks='N', passwd='P', protocols='L', rpc='R', services='V',
- shadow='S',
+ shadow='S', nfsidmap='F',
)
_char_to_db = dict((reversed(item) for item in _db_to_char.items()))
-def exec_invalidate(db):
- logging.debug('nscd_invalidator: nscd -i %s', db)
+def exec_invalidate(*args):
+ cmd = ' '.join(args)
+ logging.debug('nscd_invalidator: %s', cmd)
try:
- p = subprocess.Popen(['nscd', '-i', db],
- bufsize=4096, close_fds=True,
+ p = subprocess.Popen(args, bufsize=4096, close_fds=True,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output, ignored = p.communicate()
if output:
output = ': %s' % output[:1024].strip()
if p.returncode == 0:
- logging.debug('nscd_invalidator: nscd -i %s (pid %d) success%s',
- db, p.pid, output)
+ logging.debug('nscd_invalidator: %s (pid %d) success%s',
+ cmd, p.pid, output)
elif p.returncode > 0:
- logging.debug('nscd_invalidator: nscd -i %s (pid %d) failed (%d)%s',
- db, p.pid, p.returncode, output)
+ logging.debug('nscd_invalidator: %s (pid %d) failed (%d)%s',
+ cmd, p.pid, p.returncode, output)
else: # p.returncode < 0
- logging.error('nscd_invalidator: nscd -i %s (pid %d) killed by signal %d%s',
- db, p.pid, -p.returncode, output)
+ logging.error('nscd_invalidator: %s (pid %d) killed by signal %d%s',
+ cmd, p.pid, -p.returncode, output)
except:
- logging.warn('nscd_invalidator: nscd -i %s failed', db, exc_info=True)
+ logging.warn('nscd_invalidator: %s failed', cmd, exc_info=True)
def loop(fd):
@@ -76,8 +76,10 @@ def loop(fd):
if db == '':
break # close process down
db = _char_to_db.get(db, None)
- if db:
- exec_invalidate(db)
+ if db == 'nfsidmap':
+ exec_invalidate('nfsidmap', '-c')
+ else if db:
+ exec_invalidate('nscd', '-i', db)
def start_invalidator():
@@ -107,4 +109,4 @@ def invalidate(db=None):
try:
os.write(signalfd, db)
except:
- logging.warn('nscd_invalidator: nscd -i %s failed', db, exc_info=True)
+ logging.warn('requesting invalidation (%s) failed', db, exc_info=True)