diff options
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | nscd/cache.c | 10 | ||||
-rw-r--r-- | nscd/connections.c | 61 | ||||
-rw-r--r-- | nscd/grpcache.c | 38 | ||||
-rw-r--r-- | nscd/hstcache.c | 80 | ||||
-rw-r--r-- | nscd/nscd.c | 21 | ||||
-rw-r--r-- | nscd/nscd.h | 29 | ||||
-rw-r--r-- | nscd/pwdcache.c | 40 |
8 files changed, 225 insertions, 67 deletions
diff --git a/ChangeLog b/ChangeLog index d68fa422d5..04cda7fb2e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +1999-06-11 Thorsten Kukuk <kukuk@suse.de> + + * nscd/nscd.c: Add -S options for separate caching of data for + every user. So one user couldn't see the data another user + has gotten with his credentials. + * nscd/nscd.h: Add new prototypes. + * nscd/cache.c: Compare owner of cache entry if in secure mode. + * nscd/connections.c: Check on shutdown if caller really was root. + In secure mode get uid of caller. + * nscd/grpcache.c: Add support for new secure group mode. + * nscd/hstcache.c: Add support for new secure hosts mode. + * nscd/pwdcache.c: Add support for new secure passwd mode. + 1999-06-11 Ulrich Drepper <drepper@cygnus.com> * resolv/nss_dns/dns-host.c (getanswer_r): Correctly track usage diff --git a/nscd/cache.c b/nscd/cache.c index e57c8686d2..0071c11524 100644 --- a/nscd/cache.c +++ b/nscd/cache.c @@ -38,7 +38,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 +48,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 +77,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 +89,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; diff --git a/nscd/connections.c b/nscd/connections.c index ca139fbddf..3f05d685ef 100644 --- a/nscd/connections.c +++ b/nscd/connections.c @@ -195,7 +195,7 @@ close_sockets (void) /* Handle new request. */ static void -handle_request (int fd, request_header *req, void *key) +handle_request (int fd, request_header *req, void *key, uid_t uid) { if (debug_level > 0) dbg_log (_("handle_request: request received (Version = %d)"), @@ -251,7 +251,7 @@ cannot handle old request version %d; current version is %d"), /* See whether we can handle it from the cache. */ cached = (struct hashentry *) cache_search (req->type, key, req->key_len, - db); + db, uid); if (cached != NULL) { /* Hurray it's in the cache. */ @@ -279,35 +279,35 @@ cannot handle old request version %d; current version is %d"), switch (req->type) { case GETPWBYNAME: - addpwbyname (&dbs[serv2db[req->type]], fd, req, key); + addpwbyname (&dbs[serv2db[req->type]], fd, req, key, uid); break; case GETPWBYUID: - addpwbyuid (&dbs[serv2db[req->type]], fd, req, key); + addpwbyuid (&dbs[serv2db[req->type]], fd, req, key, uid); break; case GETGRBYNAME: - addgrbyname (&dbs[serv2db[req->type]], fd, req, key); + addgrbyname (&dbs[serv2db[req->type]], fd, req, key, uid); break; case GETGRBYGID: - addgrbygid (&dbs[serv2db[req->type]], fd, req, key); + addgrbygid (&dbs[serv2db[req->type]], fd, req, key, uid); break; case GETHOSTBYNAME: - addhstbyname (&dbs[serv2db[req->type]], fd, req, key); + addhstbyname (&dbs[serv2db[req->type]], fd, req, key, uid); break; case GETHOSTBYNAMEv6: - addhstbynamev6 (&dbs[serv2db[req->type]], fd, req, key); + addhstbynamev6 (&dbs[serv2db[req->type]], fd, req, key, uid); break; case GETHOSTBYADDR: - addhstbyaddr (&dbs[serv2db[req->type]], fd, req, key); + addhstbyaddr (&dbs[serv2db[req->type]], fd, req, key, uid); break; case GETHOSTBYADDRv6: - addhstbyaddrv6 (&dbs[serv2db[req->type]], fd, req, key); + addhstbyaddrv6 (&dbs[serv2db[req->type]], fd, req, key, uid); break; case GETSTAT: @@ -315,7 +315,24 @@ cannot handle old request version %d; current version is %d"), break; case SHUTDOWN: - termination_handler (0); + /* Accept shutdown only from root */ + if (secure_in_use && uid == 0) + termination_handler (0); + else + { + struct ucred caller; + int optlen = sizeof (caller); + + if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &caller, &optlen) < 0) + { + char buf[256]; + + dbg_log (_("error getting callers id: %s"), + strerror_r (errno, buf, sizeof (buf))); + } + else if (caller.uid == 0) + termination_handler (0); + } break; default: @@ -362,6 +379,7 @@ nscd_run (void *p) int fd = accept (conn.fd, NULL, NULL); request_header req; char buf[256]; + uid_t uid = 0; if (fd < 0) { @@ -380,6 +398,25 @@ nscd_run (void *p) continue; } + if (secure_in_use) + { + struct ucred caller; + int optlen = sizeof (caller); + + if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, + &caller, &optlen) < 0) + { + dbg_log (_("error getting callers id: %s"), + strerror_r (errno, buf, sizeof (buf))); + close (fd); + continue; + } + + if (req.type < GETPWBYNAME || req.type >= LASTREQ + || secure[serv2db[req.type]]) + uid = caller.uid; + } + /* It should not be possible to crash the nscd with a silly request (i.e., a terribly large key. We limit the size to 1kb. */ @@ -404,7 +441,7 @@ nscd_run (void *p) } /* Phew, we got all the data, now process it. */ - handle_request (fd, &req, keybuf); + handle_request (fd, &req, keybuf, uid); /* We are done. */ close (fd); diff --git a/nscd/grpcache.c b/nscd/grpcache.c index 1c6b1aff3f..d8848f3e00 100644 --- a/nscd/grpcache.c +++ b/nscd/grpcache.c @@ -77,7 +77,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 +105,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, &iov_notfound, - sizeof (notfound), (void *) -1, 0, t, db); + sizeof (notfound), (void *) -1, 0, t, db, owner); pthread_rwlock_unlock (&db->lock); } @@ -177,9 +177,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 +194,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 +205,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 +224,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 +244,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 +263,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); } diff --git a/nscd/hstcache.c b/nscd/hstcache.c index 15459752bb..6fceecfc56 100644 --- a/nscd/hstcache.c +++ b/nscd/hstcache.c @@ -88,7 +88,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 +116,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, &iov_notfound, - sizeof (notfound), (void *) -1, 0, t, db); + sizeof (notfound), (void *) -1, 0, t, db, owner); pthread_rwlock_unlock (&db->lock); } @@ -227,10 +227,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 +239,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 +248,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 +257,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 +282,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 +293,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 +314,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 +333,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 +342,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 +358,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 +377,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 +387,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 +403,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 +422,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 +431,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 +447,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); } diff --git a/nscd/nscd.c b/nscd/nscd.c index b2e5843a91..af5ce42be8 100644 --- a/nscd/nscd.c +++ b/nscd/nscd.c @@ -1,6 +1,6 @@ /* 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 @@ -58,10 +58,13 @@ typedef struct thread_info_t thread_info; -int do_shutdown = 0; -int disabled_passwd = 0; -int disabled_group = 0; +int do_shutdown; +int disabled_passwd; +int disabled_group; int go_background = 1; + +int secure[lastdb]; +int secure_in_use; static const char *conffile = _PATH_NSCDCONF; static int check_pid (const char *file); @@ -81,6 +84,7 @@ static const struct argp_option options[] = { "nthreads", 't', N_("NUMBER"), 0, N_("Start NUMBER threads") }, { "shutdown", 'K', NULL, 0, N_("Shut the server down") }, { "statistic", 'g', NULL, 0, N_("Print current configuration statistic") }, + { "secure", 'S', N_("TABLE,yes"), 0, N_("Use separate cache for each user")}, { NULL, 0, NULL, 0, NULL } }; @@ -208,6 +212,15 @@ parse_opt (int key, char *arg, struct argp_state *state) nthreads = atol (arg); break; + case 'S': + if (strcmp (arg, "passwd,yes") == 0) + secure_in_use = secure[pwddb] = 1; + else if (strcmp (arg, "group,yes") == 0) + secure_in_use = secure[grpdb] = 1; + else if (strcmp (arg, "hosts,yes") == 0) + secure_in_use = secure[hstdb] = 1; + break; + default: return ARGP_ERR_UNKNOWN; } diff --git a/nscd/nscd.h b/nscd/nscd.h index 9177235911..36fd1b3002 100644 --- a/nscd/nscd.h +++ b/nscd/nscd.h @@ -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/pwdcache.c b/nscd/pwdcache.c index 5bf89a75ba..a66cf4fe3d 100644 --- a/nscd/pwdcache.c +++ b/nscd/pwdcache.c @@ -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. @@ -84,7 +84,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 +112,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, &iov_notfound, - sizeof (notfound), (void *) -1, 0, t, db); + sizeof (notfound), (void *) -1, 0, t, db, owner); pthread_rwlock_unlock (&db->lock); } @@ -175,9 +175,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 +192,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 +203,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 +222,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 +242,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 +261,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); } |