summaryrefslogtreecommitdiff
path: root/source3/lib
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2001-03-17 03:36:38 +0000
committerJeremy Allison <jra@samba.org>2001-03-17 03:36:38 +0000
commit0dfc30cf87ab3b5746701034150e3a6400857148 (patch)
treecd4243ccb69598cbfb80d27a6fa4e7274f5cdbaa /source3/lib
parent70c812e6aee0fa9b10b660f4051cc5460c023917 (diff)
downloadsamba-0dfc30cf87ab3b5746701034150e3a6400857148.tar.gz
samba-0dfc30cf87ab3b5746701034150e3a6400857148.tar.bz2
samba-0dfc30cf87ab3b5746701034150e3a6400857148.zip
lib/system.c (Finally) fixed all insure errors in password caching code. We can't
stop libc routines from calling getpwXXX functions, so caching a pointer to them is impossible. This new code now makes two copies of the returned struct passwd struct - one used as a cache, one returned to allow the caller to modify. When doing a lookup we compare against the cached copy. Code is now easier to understand also. smbd/posix_acls.c: If we move the head of the linked list, remember to pass a reference to that pointer..... Jeremy. (This used to be commit af364b93d92f70aa52195c46d3cc516830752609)
Diffstat (limited to 'source3/lib')
-rw-r--r--source3/lib/system.c109
1 files changed, 53 insertions, 56 deletions
diff --git a/source3/lib/system.c b/source3/lib/system.c
index 5557aa8735..526113dcf7 100644
--- a/source3/lib/system.c
+++ b/source3/lib/system.c
@@ -580,49 +580,61 @@ int sys_setgroups(int setlen, gid_t *gidset)
Helper function for getpwnam/getpwuid wrappers.
****************************************************************************/
+struct saved_pw {
+ fstring pw_name;
+ fstring pw_passwd;
+ struct passwd pass;
+};
+
+static struct saved_pw pw_mod; /* This is the structure returned - can be modified. */
+static struct saved_pw pw_cache; /* This is the structure saved - used to check cache. */
+
+static int num_lookups; /* Counter so we don't always use cache. */
+#ifndef PW_RET_CACHE_MAX_LOOKUPS
+#define PW_RET_CACHE_MAX_LOOKUPS 100
+#endif
+
static struct passwd *setup_pwret(struct passwd *pass)
{
- static fstring pw_name;
- static fstring pw_passwd;
- static struct passwd pw_ret;
-
- if (pass == NULL)
+ if (pass == NULL) {
+ /* Clear the caches. */
+ memset(&pw_cache, '\0', sizeof(struct saved_pw));
+ memset(&pw_mod, '\0', sizeof(struct saved_pw));
+ num_lookups = 0;
return NULL;
+ }
/* this gets the uid, gid and null pointers */
- memcpy((char *)&pw_ret, pass, sizeof(struct passwd));
- if (pass->pw_name)
- {
- pw_ret.pw_name = pw_name;
- fstrcpy(pw_ret.pw_name, pass->pw_name);
- }
+ memcpy((char *)&pw_mod.pass, pass, sizeof(struct passwd));
+ fstrcpy(pw_mod.pw_name, pass->pw_name);
+ pw_mod.pass.pw_name = pw_mod.pw_name;
+ fstrcpy(pw_mod.pw_passwd, pass->pw_passwd);
+ pw_mod.pass.pw_passwd = pw_mod.pw_passwd;
- if (pass->pw_passwd)
- {
- pw_ret.pw_passwd = pw_passwd;
- fstrcpy(pw_ret.pw_passwd, pass->pw_passwd);
- }
- return &pw_ret;
-}
+ if (pass != &pw_cache.pass) {
-/* static pointer to be used for caching the last
- getpw[nam|uid]() call. Patch by "Richard Bollinger"
- <rabollinger@home.com> */
+ /* If it's a cache miss we must also refill the cache. */
-/*
- * This next static pointer is used to cache the results
- * from the real getpwXX calls. It is never returned to
- * the caller, only the output from calling setup_pwret with
- * this is returned. JRA.
- */
+ memcpy((char *)&pw_cache.pass, pass, sizeof(struct passwd));
+ fstrcpy(pw_cache.pw_name, pass->pw_name);
+ pw_cache.pass.pw_name = pw_cache.pw_name;
+ fstrcpy(pw_cache.pw_passwd, pass->pw_passwd);
+ pw_cache.pass.pw_passwd = pw_cache.pw_passwd;
-static struct passwd *sv_pw_ret; /* implicitly initialized to NULL */
-static int num_lookups; /* Counter so we don't always use cache. */
-#ifndef PW_RET_CACHE_MAX_LOOKUPS
-#define PW_RET_CACHE_MAX_LOOKUPS 100
-#endif
+ num_lookups = 1;
+
+ } else {
+
+ /* Cache hit. */
+
+ num_lookups++;
+ num_lookups = (num_lookups % PW_RET_CACHE_MAX_LOOKUPS);
+ }
+
+ return &pw_mod.pass;
+}
/**************************************************************************
Wrappers for setpwent(), getpwent() and endpwent()
@@ -630,19 +642,18 @@ static int num_lookups; /* Counter so we don't always use cache. */
void sys_setpwent(void)
{
- sv_pw_ret = NULL;
+ setup_pwret(NULL); /* Clear cache. */
setpwent();
}
struct passwd *sys_getpwent(void)
{
- sv_pw_ret = getpwent();
- return setup_pwret(sv_pw_ret);
+ return setup_pwret(getpwent());
}
void sys_endpwent(void)
{
- sv_pw_ret = NULL;
+ setup_pwret(NULL); /* Clear cache. */
endpwent();
}
@@ -656,22 +667,15 @@ struct passwd *sys_getpwnam(const char *name)
return NULL;
/* check for a cache hit first */
- if (num_lookups && sv_pw_ret && !strcmp(name, sv_pw_ret->pw_name))
- {
+ if (num_lookups && pw_cache.pass.pw_name && !strcmp(name, pw_cache.pass.pw_name)) {
DEBUG(2,("getpwnam(%s) avoided - using cached results\n",name));
- num_lookups++;
- num_lookups = (num_lookups % PW_RET_CACHE_MAX_LOOKUPS);
- return setup_pwret(sv_pw_ret);
+ return setup_pwret(&pw_cache.pass);
}
/* no cache hit--use old lookup instead */
DEBUG(2,("getpwnam(%s) called\n",name));
- num_lookups = 1;
-
- sv_pw_ret = getpwnam(name);
-
- return setup_pwret(sv_pw_ret);
+ return setup_pwret(getpwnam(name));
}
/**************************************************************************
@@ -680,21 +684,14 @@ struct passwd *sys_getpwnam(const char *name)
struct passwd *sys_getpwuid(uid_t uid)
{
- if (num_lookups && sv_pw_ret && (uid == sv_pw_ret->pw_uid))
- {
+ if (num_lookups && pw_cache.pass.pw_name && (uid == pw_cache.pass.pw_uid)) {
DEBUG(2,("getpwuid(%d) avoided - using cached results\n",uid));
- num_lookups++;
- num_lookups = (num_lookups % PW_RET_CACHE_MAX_LOOKUPS);
- return setup_pwret(sv_pw_ret);
+ return setup_pwret(&pw_cache.pass);
}
DEBUG(2,("getpwuid(%d) called\n",uid));
- num_lookups = 1;
-
- sv_pw_ret = getpwuid(uid);
-
- return setup_pwret(sv_pw_ret);
+ return setup_pwret(getpwuid(uid));
}
/**************************************************************************