]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Update from main branch.
authorUlrich Drepper <drepper@redhat.com>
Mon, 27 Sep 1999 00:17:10 +0000 (00:17 +0000)
committerUlrich Drepper <drepper@redhat.com>
Mon, 27 Sep 1999 00:17:10 +0000 (00:17 +0000)
nscd/Makefile
nscd/cache.c
nscd/grpcache.c
nscd/hstcache.c
nscd/nscd.h
nscd/nscd_nischeck.c [new file with mode: 0644]
nscd/pwdcache.c

index d915aa70f4a803a5ca84e86e2d4b6dbbcf677451..b37f77781e37efba9ef7e22e839e89fecb659189 100644 (file)
@@ -31,10 +31,10 @@ nscd-modules := nscd connections pwdcache getpwnam_r getpwuid_r grpcache \
 
 ifeq ($(have-thread-library),yes)
 
-others := nscd
-install-sbin := nscd
+others := nscd nscd_nischeck
+install-sbin := nscd nscd_nischeck
 
-extra-objs := $(nscd-modules:=.o)
+extra-objs := $(nscd-modules:=.o) nscd_nischeck.o
 
 endif
 
@@ -44,15 +44,18 @@ otherlibs += $(nssobjdir)/libnss_files.a $(resolvobjdir)/libnss_dns.a \
 endif
 
 distribute := nscd.h nscd-client.h dbg_log.h \
-             $(nscd-modules:=.c) TODO nscd.conf nscd.init \
+             $(nscd-modules:=.c) nscd_nischeck.c TODO nscd.conf nscd.init \
              nscd_proto.h
 
 include ../Rules
 
 $(objpfx)nscd: $(nscd-modules:%=$(objpfx)%.o)
+$(objpfx)nscd_nischeck: $(objpfx)nscd_nischeck.o
 
 ifeq ($(build-shared),yes)
 $(objpfx)nscd: $(shared-thread-library) $(common-objpfx)nis/libnsl.so
+$(objpfx)nscd_nischeck: $(common-objpfx)nis/libnsl.so
 else
 $(objpfx)nscd: $(static-thread-library) $(common-objpfx)nis/libnsl.a
+$(objpfx)nscd_nischeck: $(common-objpfx)nis/libnsl.a
 endif
index e57c8686d23f2ac389d93636dcb19b38fac33b43..61fb7703c2884d75337bb952f6fd7f6d6452f03e 100644 (file)
@@ -23,6 +23,7 @@
 #include <limits.h>
 #include <stdlib.h>
 #include <string.h>
+#include <libintl.h>
 #include <arpa/inet.h>
 #include <rpcsvc/nis.h>
 #include <sys/param.h>
@@ -38,7 +39,8 @@
 
    This function must be called with the read-lock held.  */
 struct hashentry *
-cache_search (int type, void *key, size_t len, struct database *table)
+cache_search (int type, void *key, size_t len, struct database *table,
+             uid_t owner)
 {
   unsigned long int hash = __nis_hash (key, len) % table->module;
   struct hashentry *work;
@@ -47,8 +49,8 @@ cache_search (int type, void *key, size_t len, struct database *table)
 
   while (work != NULL)
     {
-      if (type == work->type
-         && len == work->len && memcmp (key, work->key, len) == 0)
+      if (type == work->type && len == work->len
+         && memcmp (key, work->key, len) == 0 && work->owner == owner)
        {
          /* We found the entry.  Increment the appropriate counter.  */
          if (work->data == (void *) -1)
@@ -76,7 +78,7 @@ cache_search (int type, void *key, size_t len, struct database *table)
    the readlock reduces the chance of conflicts.  */
 void
 cache_add (int type, void *key, size_t len, const void *packet, size_t total,
-          void *data, int last, time_t t, struct database *table)
+          void *data, int last, time_t t, struct database *table, uid_t owner)
 {
   unsigned long int hash = __nis_hash (key, len) % table->module;
   struct hashentry *newp;
@@ -88,6 +90,7 @@ cache_add (int type, void *key, size_t len, const void *packet, size_t total,
   newp->type = type;
   newp->len = len;
   newp->key = key;
+  newp->owner = owner;
   newp->data = data;
   newp->timeout = t;
   newp->packet = packet;
index 7e2c4b15c071e166ba9f2867a6c623e1298c7cec..7a591c81aec07cd21bcd66dc604d40678c405b99 100644 (file)
@@ -26,6 +26,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <libintl.h>
 
 #include "nscd.h"
 #include "dbg_log.h"
@@ -77,7 +78,7 @@ struct groupdata
 
 static void
 cache_addgr (struct database *db, int fd, request_header *req, void *key,
-            struct group *grp)
+            struct group *grp, uid_t owner)
 {
   ssize_t total;
   ssize_t written;
@@ -105,7 +106,7 @@ cache_addgr (struct database *db, int fd, request_header *req, void *key,
       pthread_rwlock_rdlock (&db->lock);
 
       cache_add (req->type, copy, req->key_len, &notfound,
-                sizeof (notfound), (void *) -1, 0, t, db);
+                sizeof (notfound), (void *) -1, 0, t, db, owner);
 
       pthread_rwlock_unlock (&db->lock);
     }
@@ -177,9 +178,9 @@ cache_addgr (struct database *db, int fd, request_header *req, void *key,
 
       /* We have to add the value for both, byname and byuid.  */
       cache_add (GETGRBYNAME, gr_name, gr_name_len, data,
-                total, data, 0, t, db);
+                total, data, 0, t, db, owner);
 
-      cache_add (GETGRBYGID, cp, n, data, total, data, 1, t, db);
+      cache_add (GETGRBYGID, cp, n, data, total, data, 1, t, db, owner);
 
       pthread_rwlock_unlock (&db->lock);
     }
@@ -194,7 +195,8 @@ cache_addgr (struct database *db, int fd, request_header *req, void *key,
 
 
 void
-addgrbyname (struct database *db, int fd, request_header *req, void *key)
+addgrbyname (struct database *db, int fd, request_header *req,
+            void *key, uid_t uid)
 {
   /* Search for the entry matching the key.  Please note that we don't
      look again in the table whether the dataset is now available.  We
@@ -204,10 +206,17 @@ addgrbyname (struct database *db, int fd, request_header *req, void *key)
   char *buffer = alloca (buflen);
   struct group resultbuf;
   struct group *grp;
+  uid_t oldeuid = 0;
 
   if (debug_level > 0)
     dbg_log (_("Haven't found \"%s\" in group cache!"), key);
 
+  if (secure[grpdb])
+    {
+      oldeuid = geteuid ();
+      seteuid (uid);
+    }
+
   while (__getgrnam_r (key, &resultbuf, buffer, buflen, &grp) != 0
         && errno == ERANGE)
     {
@@ -216,12 +225,16 @@ addgrbyname (struct database *db, int fd, request_header *req, void *key)
       buffer = alloca (buflen);
     }
 
-  cache_addgr (db, fd, req, key, grp);
+  if (secure[grpdb])
+    seteuid (oldeuid);
+
+  cache_addgr (db, fd, req, key, grp, uid);
 }
 
 
 void
-addgrbygid (struct database *db, int fd, request_header *req, void *key)
+addgrbygid (struct database *db, int fd, request_header *req,
+           void *key, uid_t uid)
 {
   /* Search for the entry matching the key.  Please note that we don't
      look again in the table whether the dataset is now available.  We
@@ -232,10 +245,17 @@ addgrbygid (struct database *db, int fd, request_header *req, void *key)
   struct group resultbuf;
   struct group *grp;
   gid_t gid = atol (key);
+  uid_t oldeuid = 0;
 
   if (debug_level > 0)
     dbg_log (_("Haven't found \"%d\" in group cache!"), gid);
 
+  if (secure[grpdb])
+    {
+      oldeuid = geteuid ();
+      seteuid (uid);
+    }
+
   while (__getgrgid_r (gid, &resultbuf, buffer, buflen, &grp) != 0
         && errno == ERANGE)
     {
@@ -244,5 +264,8 @@ addgrbygid (struct database *db, int fd, request_header *req, void *key)
       buffer = alloca (buflen);
     }
 
-  cache_addgr (db, fd, req, key, grp);
+  if (secure[grpdb])
+    seteuid (oldeuid);
+
+  cache_addgr (db, fd, req, key, grp, uid);
 }
index 6365b06b9addee55425665818b06325fe9b37cf4..b8a80af340016d87c3fdab6582b9805b7ad66c1f 100644 (file)
@@ -28,6 +28,7 @@
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
+#include <libintl.h>
 #include <arpa/inet.h>
 
 #include "nscd.h"
@@ -88,7 +89,7 @@ struct hostdata
 
 static void
 cache_addhst (struct database *db, int fd, request_header *req, void *key,
-             struct hostent *hst)
+             struct hostent *hst, uid_t owner)
 {
   ssize_t total;
   ssize_t written;
@@ -116,7 +117,7 @@ cache_addhst (struct database *db, int fd, request_header *req, void *key,
       pthread_rwlock_rdlock (&db->lock);
 
       cache_add (req->type, copy, req->key_len, &notfound,
-                sizeof (notfound), (void *) -1, 0, t, db);
+                sizeof (notfound), (void *) -1, 0, t, db, owner);
 
       pthread_rwlock_unlock (&db->lock);
     }
@@ -227,10 +228,10 @@ cache_addhst (struct database *db, int fd, request_header *req, void *key,
        {
          if (addr_list_type == GETHOSTBYADDR)
            cache_add (GETHOSTBYNAME, aliases, h_aliases_len[cnt], data, total,
-                      data, 0, t, db);
+                      data, 0, t, db, owner);
 
          cache_add (GETHOSTBYNAMEv6, aliases, h_aliases_len[cnt], data, total,
-                    data, 0, t, db);
+                    data, 0, t, db, owner);
 
          aliases += h_aliases_len[cnt];
        }
@@ -239,7 +240,7 @@ cache_addhst (struct database *db, int fd, request_header *req, void *key,
       for (cnt = 0; cnt < h_addr_list_cnt; ++cnt)
        {
          cache_add (addr_list_type, addresses, hst->h_length, data, total,
-                    data, 0, t, db);
+                    data, 0, t, db, owner);
          addresses += hst->h_length;
        }
 
@@ -248,7 +249,7 @@ cache_addhst (struct database *db, int fd, request_header *req, void *key,
        for (cnt = 0; cnt < h_addr_list_cnt; ++cnt)
          {
            cache_add (GETHOSTBYADDRv6, addresses, IN6ADDRSZ, data, total,
-                      data, 0, t, db);
+                      data, 0, t, db, owner);
            addresses += IN6ADDRSZ;
          }
 
@@ -257,17 +258,17 @@ cache_addhst (struct database *db, int fd, request_header *req, void *key,
        {
          if (addr_list_type == GETHOSTBYADDR)
            cache_add (GETHOSTBYNAME, key_copy, req->key_len, data, total,
-                      data, 0, t, db);
+                      data, 0, t, db, owner);
          cache_add (GETHOSTBYNAMEv6, key_copy, req->key_len, data,
-                    total, data, 0, t, db);
+                    total, data, 0, t, db, owner);
        }
 
       /* And finally the name.  We mark this as the last entry.  */
       if (addr_list_type == GETHOSTBYADDR)
        cache_add (GETHOSTBYNAME, data->strdata, h_name_len, data, total, data,
-                  0, t, db);
+                  0, t, db, owner);
       cache_add (GETHOSTBYNAMEv6, data->strdata, h_name_len, data,
-                total, data, 1, t, db);
+                total, data, 1, t, db, owner);
 
       pthread_rwlock_unlock (&db->lock);
     }
@@ -282,7 +283,8 @@ cache_addhst (struct database *db, int fd, request_header *req, void *key,
 
 
 void
-addhstbyname (struct database *db, int fd, request_header *req, void *key)
+addhstbyname (struct database *db, int fd, request_header *req,
+             void *key, uid_t uid)
 {
   /* Search for the entry matching the key.  Please note that we don't
      look again in the table whether the dataset is now available.  We
@@ -292,10 +294,17 @@ addhstbyname (struct database *db, int fd, request_header *req, void *key)
   char *buffer = alloca (buflen);
   struct hostent resultbuf;
   struct hostent *hst;
+  uid_t oldeuid = 0;
 
   if (debug_level > 0)
     dbg_log (_("Haven't found \"%s\" in hosts cache!"), key);
 
+  if (secure[hstdb])
+    {
+      oldeuid = geteuid ();
+      seteuid (uid);
+    }
+
   while (__gethostbyname2_r (key, AF_INET, &resultbuf, buffer, buflen,
                             &hst, &h_errno) != 0
         && h_errno == NETDB_INTERNAL
@@ -306,12 +315,16 @@ addhstbyname (struct database *db, int fd, request_header *req, void *key)
       buffer = alloca (buflen);
     }
 
-  cache_addhst (db, fd, req, key, hst);
+  if (secure[hstdb])
+    seteuid (uid);
+
+  cache_addhst (db, fd, req, key, hst, uid);
 }
 
 
 void
-addhstbyaddr (struct database *db, int fd, request_header *req, void *key)
+addhstbyaddr (struct database *db, int fd, request_header *req,
+             void *key, uid_t uid)
 {
   /* Search for the entry matching the key.  Please note that we don't
      look again in the table whether the dataset is now available.  We
@@ -321,6 +334,7 @@ addhstbyaddr (struct database *db, int fd, request_header *req, void *key)
   char *buffer = alloca (buflen);
   struct hostent resultbuf;
   struct hostent *hst;
+  uid_t oldeuid = 0;
 
   if (debug_level > 0)
     {
@@ -329,6 +343,12 @@ addhstbyaddr (struct database *db, int fd, request_header *req, void *key)
               inet_ntop (AF_INET, key, buf, sizeof (buf)));
     }
 
+  if (secure[hstdb])
+    {
+      oldeuid = geteuid ();
+      seteuid (uid);
+    }
+
   while (__gethostbyaddr_r (key, INADDRSZ, AF_INET, &resultbuf, buffer,
                            buflen, &hst, &h_errno) != 0
         && h_errno == NETDB_INTERNAL
@@ -339,12 +359,16 @@ addhstbyaddr (struct database *db, int fd, request_header *req, void *key)
       buffer = alloca (buflen);
     }
 
-  cache_addhst (db, fd, req, key, hst);
+  if (secure[hstdb])
+    seteuid (oldeuid);
+
+  cache_addhst (db, fd, req, key, hst, uid);
 }
 
 
 void
-addhstbynamev6 (struct database *db, int fd, request_header *req, void *key)
+addhstbynamev6 (struct database *db, int fd, request_header *req,
+               void *key, uid_t uid)
 {
   /* Search for the entry matching the key.  Please note that we don't
      look again in the table whether the dataset is now available.  We
@@ -354,6 +378,7 @@ addhstbynamev6 (struct database *db, int fd, request_header *req, void *key)
   char *buffer = alloca (buflen);
   struct hostent resultbuf;
   struct hostent *hst;
+  uid_t oldeuid = 0;
 
   if (debug_level > 0)
     {
@@ -363,6 +388,12 @@ addhstbynamev6 (struct database *db, int fd, request_header *req, void *key)
               inet_ntop (AF_INET6, key, buf, sizeof (buf)));
     }
 
+  if (secure[hstdb])
+    {
+      oldeuid = geteuid ();
+      seteuid (uid);
+    }
+
   while (__gethostbyname2_r (key, AF_INET6, &resultbuf, buffer, buflen,
                             &hst, &h_errno) != 0
         && h_errno == NETDB_INTERNAL
@@ -373,12 +404,16 @@ addhstbynamev6 (struct database *db, int fd, request_header *req, void *key)
       buffer = alloca (buflen);
     }
 
-  cache_addhst (db, fd, req, key, hst);
+  if (secure[hstdb])
+    seteuid (oldeuid);
+
+  cache_addhst (db, fd, req, key, hst, uid);
 }
 
 
 void
-addhstbyaddrv6 (struct database *db, int fd, request_header *req, void *key)
+addhstbyaddrv6 (struct database *db, int fd, request_header *req,
+               void *key, uid_t uid)
 {
   /* Search for the entry matching the key.  Please note that we don't
      look again in the table whether the dataset is now available.  We
@@ -388,6 +423,7 @@ addhstbyaddrv6 (struct database *db, int fd, request_header *req, void *key)
   char *buffer = alloca (buflen);
   struct hostent resultbuf;
   struct hostent *hst;
+  uid_t oldeuid = 0;
 
   if (debug_level > 0)
     {
@@ -396,6 +432,12 @@ addhstbyaddrv6 (struct database *db, int fd, request_header *req, void *key)
               inet_ntop (AF_INET6, key, buf, sizeof (buf)));
     }
 
+  if (secure[hstdb])
+    {
+      oldeuid = geteuid ();
+      seteuid (uid);
+    }
+
   while (__gethostbyaddr_r (key, IN6ADDRSZ, AF_INET6, &resultbuf,
                            buffer, buflen, &hst, &h_errno) != 0
         && h_errno == NETDB_INTERNAL
@@ -406,5 +448,8 @@ addhstbyaddrv6 (struct database *db, int fd, request_header *req, void *key)
       buffer = alloca (buflen);
     }
 
-  cache_addhst (db, fd, req, key, hst);
+  if (secure[hstdb])
+    seteuid (oldeuid);
+
+  cache_addhst (db, fd, req, key, hst, uid);
 }
index 9177235911f9544c282ab3fa1b7a9881e613a955..36fd1b300295d975a5c99726d42778205d637af7 100644 (file)
@@ -1,6 +1,6 @@
-/* Copyright (c) 1998 Free Software Foundation, Inc.
+/* Copyright (c) 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
-   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1998.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public License as
@@ -46,6 +46,7 @@ struct hashentry
   request_type type;           /* Which type of dataset.  */
   size_t len;                  /* Length of key.  */
   void *key;                   /* Pointer to key.  */
+  uid_t owner;                  /* If secure table, this is the owner.  */
   struct hashentry *next;      /* Next entry in this hash bucket list.  */
   time_t timeout;              /* Time when this entry becomes invalid.  */
   ssize_t total;               /* Number of bytes in PACKET.  */
@@ -91,6 +92,9 @@ extern const struct iovec hst_iov_disabled;
 /* Number of threads to run.  */
 extern int nthreads;
 
+/* Tables for which we cache data with uid */
+extern int secure[lastdb];
+extern int secure_in_use; /* Is one of the above 1 ? */
 
 /* Prototypes for global functions.  */
 
@@ -112,33 +116,34 @@ extern int receive_print_stats (void);
 
 /* cache.c */
 extern struct hashentry *cache_search (int type, void *key, size_t len,
-                                      struct database *table);
+                                      struct database *table, uid_t owner);
 extern void cache_add (int type, void *key, size_t len,
                       const void *packet, size_t iovtotal, void *data,
-                      int last, time_t t, struct database *table);
+                      int last, time_t t, struct database *table,
+                      uid_t owner);
 extern void prune_cache (struct database *table, time_t now);
 
 /* pwdcache.c */
 extern void addpwbyname (struct database *db, int fd, request_header *req,
-                        void *key);
+                        void *key, uid_t uid);
 extern void addpwbyuid (struct database *db, int fd, request_header *req,
-                       void *key);
+                       void *key, uid_t uid);
 
 /* grpcache.c */
 extern void addgrbyname (struct database *db, int fd, request_header *req,
-                        void *key);
+                        void *key, uid_t uid);
 extern void addgrbygid (struct database *db, int fd, request_header *req,
-                       void *key);
+                       void *key, uid_t uid);
 
 /* hstcache.c */
 extern void addhstbyname (struct database *db, int fd, request_header *req,
-                         void *key);
+                         void *key, uid_t uid);
 extern void addhstbyaddr (struct database *db, int fd, request_header *req,
-                         void *key);
+                         void *key, uid_t uid);
 extern void addhstbynamev6 (struct database *db, int fd, request_header *req,
-                           void *key);
+                           void *key, uid_t uid);
 extern void addhstbyaddrv6 (struct database *db, int fd, request_header *req,
-                           void *key);
+                           void *key, uid_t uid);
 
 
 #endif /* nscd.h */
diff --git a/nscd/nscd_nischeck.c b/nscd/nscd_nischeck.c
new file mode 100644 (file)
index 0000000..087386a
--- /dev/null
@@ -0,0 +1,96 @@
+/* Copyright (c) 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@suse.de>, 1999.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA. */
+
+/* nscd_nischeck: Check, if everybody has read permissions for NIS+ table.
+   Return value:
+    0: Everybody can read the NIS+ table
+    1: Only authenticated users could read the NIS+ table */
+
+#include <argp.h>
+#include <error.h>
+#include <stdlib.h>
+#include <libintl.h>
+#include <locale.h>
+#include <rpcsvc/nis.h>
+
+/* Get libc version number.  */
+#include <version.h>
+
+#define PACKAGE _libc_intl_domainname
+
+/* Name and version of program.  */
+static void print_version (FILE *stream, struct argp_state *state);
+void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
+
+/* Data structure to communicate with argp functions.  */
+static struct argp argp =
+{
+  NULL, NULL, NULL, NULL,
+};
+
+int
+main (int argc, char **argv)
+{
+  int remaining;
+  nis_result *res;
+  char *tablename, *cp;
+
+  /* Set locale via LC_ALL.  */
+  setlocale (LC_ALL, "");
+  /* Set the text message domain.  */
+  textdomain (PACKAGE);
+
+  /* Parse and process arguments.  */
+  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
+
+  if (remaining + 1 != argc)
+    {
+      error (0, 0, gettext ("wrong number of arguments"));
+      argp_help (&argp, stdout, ARGP_HELP_SEE, program_invocation_short_name);
+      exit (EXIT_FAILURE);
+    }
+
+  tablename = alloca (strlen (argv[1]) + 10);
+  cp = stpcpy (tablename, argv[1]);
+  strcpy (cp, ".org_dir");
+
+  res = nis_lookup (tablename, EXPAND_NAME|FOLLOW_LINKS);
+
+  if (res == NULL ||
+      (res->status != NIS_SUCCESS && res->status != NIS_S_SUCCESS))
+    return 0;
+
+  if (NIS_NOBODY(NIS_RES_OBJECT(res)->zo_access, NIS_READ_ACC))
+    return 0;
+  else
+    return 1;
+}
+
+/* Print the version information.  */
+static void
+print_version (FILE *stream, struct argp_state *state)
+{
+  fprintf (stream, "nscd_nischeck (GNU %s) %s\n", PACKAGE, VERSION);
+  fprintf (stream, gettext ("\
+Copyright (C) %s Free Software Foundation, Inc.\n\
+This is free software; see the source for copying conditions.  There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
+"), "1999");
+  fprintf (stream, gettext ("Written by %s.\n"), "Thorsten Kukuk");
+}
index 86f5c310eeccef79d1cf053944ce8e05140a280f..2e54a773ff53017a4169e5c543b2345bd249f8ef 100644 (file)
@@ -1,5 +1,5 @@
 /* Cache handling for passwd lookup.
-   Copyright (C) 1998 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -27,6 +27,7 @@
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
+#include <libintl.h>
 
 #include "nscd.h"
 #include "dbg_log.h"
@@ -84,7 +85,7 @@ struct passwddata
 
 static void
 cache_addpw (struct database *db, int fd, request_header *req, void *key,
-            struct passwd *pwd)
+            struct passwd *pwd, uid_t owner)
 {
   ssize_t total;
   ssize_t written;
@@ -112,7 +113,7 @@ cache_addpw (struct database *db, int fd, request_header *req, void *key,
       pthread_rwlock_rdlock (&db->lock);
 
       cache_add (req->type, copy, req->key_len, &notfound,
-                sizeof (notfound), (void *) -1, 0, t, db);
+                sizeof (notfound), (void *) -1, 0, t, db, owner);
 
       pthread_rwlock_unlock (&db->lock);
     }
@@ -175,9 +176,9 @@ cache_addpw (struct database *db, int fd, request_header *req, void *key,
 
       /* We have to add the value for both, byname and byuid.  */
       cache_add (GETPWBYNAME, data->strdata, pw_name_len, data,
-                total, data, 0, t, db);
+                total, data, 0, t, db, owner);
 
-      cache_add (GETPWBYUID, cp, n, data, total, data, 1, t, db);
+      cache_add (GETPWBYUID, cp, n, data, total, data, 1, t, db, owner);
 
       pthread_rwlock_unlock (&db->lock);
     }
@@ -192,7 +193,8 @@ cache_addpw (struct database *db, int fd, request_header *req, void *key,
 
 
 void
-addpwbyname (struct database *db, int fd, request_header *req, void *key)
+addpwbyname (struct database *db, int fd, request_header *req,
+            void *key, uid_t c_uid)
 {
   /* Search for the entry matching the key.  Please note that we don't
      look again in the table whether the dataset is now available.  We
@@ -202,10 +204,17 @@ addpwbyname (struct database *db, int fd, request_header *req, void *key)
   char *buffer = alloca (buflen);
   struct passwd resultbuf;
   struct passwd *pwd;
+  uid_t oldeuid;
 
   if (debug_level > 0)
     dbg_log (_("Haven't found \"%s\" in password cache!"), key);
 
+  if (secure[pwddb])
+    {
+      oldeuid = geteuid ();
+      seteuid (c_uid);
+    }
+
   while (__getpwnam_r (key, &resultbuf, buffer, buflen, &pwd) != 0
         && errno == ERANGE)
     {
@@ -214,12 +223,16 @@ addpwbyname (struct database *db, int fd, request_header *req, void *key)
       buffer = alloca (buflen);
     }
 
-  cache_addpw (db, fd, req, key, pwd);
+  if (secure[pwddb])
+    seteuid (c_uid);
+
+  cache_addpw (db, fd, req, key, pwd, c_uid);
 }
 
 
 void
-addpwbyuid (struct database *db, int fd, request_header *req, void *key)
+addpwbyuid (struct database *db, int fd, request_header *req,
+           void *key, uid_t c_uid)
 {
   /* Search for the entry matching the key.  Please note that we don't
      look again in the table whether the dataset is now available.  We
@@ -230,10 +243,17 @@ addpwbyuid (struct database *db, int fd, request_header *req, void *key)
   struct passwd resultbuf;
   struct passwd *pwd;
   uid_t uid = atol (key);
+  uid_t oldeuid = 0;
 
   if (debug_level > 0)
     dbg_log (_("Haven't found \"%d\" in password cache!"), uid);
 
+  if (secure[pwddb])
+    {
+      oldeuid = geteuid ();
+      seteuid (c_uid);
+    }
+
   while (__getpwuid_r (uid, &resultbuf, buffer, buflen, &pwd) != 0
         && errno == ERANGE)
     {
@@ -242,5 +262,8 @@ addpwbyuid (struct database *db, int fd, request_header *req, void *key)
       buffer = alloca (buflen);
     }
 
-  cache_addpw (db, fd, req, key, pwd);
+  if (secure[pwddb])
+    seteuid (oldeuid);
+
+  cache_addpw (db, fd, req, key, pwd, c_uid);
 }