summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2007-09-28 18:12:22 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:31:03 -0500
commit58a9621904f0334d8f5a1f34e2dfd95409e7c68d (patch)
tree86518455fe29c58cc3747de1c2a89832b8e0c7bb /source3
parent5335a5d0c4b41bb1c518fa9966cd75cbf4643e7a (diff)
downloadsamba-58a9621904f0334d8f5a1f34e2dfd95409e7c68d.tar.gz
samba-58a9621904f0334d8f5a1f34e2dfd95409e7c68d.tar.bz2
samba-58a9621904f0334d8f5a1f34e2dfd95409e7c68d.zip
r25406: Make the Linux nss client code thread-safe.
Fix originally inspired from code from boyang <yyyeer.bo@gmail.com>. Jeremy. (This used to be commit cc19c0ace43a3613f6290fa4bc4f68c964563743)
Diffstat (limited to 'source3')
-rw-r--r--source3/Makefile.in2
-rw-r--r--source3/configure.in6
-rw-r--r--source3/nsswitch/winbind_nss_linux.c193
3 files changed, 187 insertions, 14 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index ffb5d93d50..9de9ea2b78 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -1489,7 +1489,7 @@ bin/winbindd@EXEEXT@: $(BINARY_PREREQS) $(WINBINDD_OBJ) @BUILD_POPT@
@WINBIND_NSS@: $(BINARY_PREREQS) $(WINBIND_NSS_OBJ)
@echo "Linking $@"
@$(SHLD) $(WINBIND_NSS_LDSHFLAGS) -o $@ $(WINBIND_NSS_OBJ) \
- @WINBIND_NSS_EXTRA_LIBS@ @SONAMEFLAG@`basename $@`@NSSSONAMEVERSIONSUFFIX@
+ @WINBIND_NSS_EXTRA_LIBS@ @WINBIND_NSS_PTHREAD@ @SONAMEFLAG@`basename $@`@NSSSONAMEVERSIONSUFFIX@
@WINBIND_WINS_NSS@: $(BINARY_PREREQS) $(WINBIND_WINS_NSS_OBJ)
@echo "Linking $@"
diff --git a/source3/configure.in b/source3/configure.in
index 1aa3478919..df4d040b0f 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -991,7 +991,7 @@ LIBS="${LIBS} ${LIBDL}"
AC_CHECK_HEADERS(aio.h arpa/inet.h sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h rpc/nettype.h)
AC_CHECK_HEADERS(unistd.h utime.h grp.h sys/id.h memory.h alloca.h)
-AC_CHECK_HEADERS(limits.h float.h)
+AC_CHECK_HEADERS(limits.h float.h pthread.h)
AC_CHECK_HEADERS(rpc/rpc.h rpcsvc/nis.h rpcsvc/ypclnt.h)
AC_CHECK_HEADERS(sys/param.h ctype.h sys/wait.h sys/resource.h sys/ioctl.h sys/ipc.h sys/prctl.h)
AC_CHECK_HEADERS(sys/mman.h sys/filio.h sys/priv.h sys/shm.h string.h strings.h stdlib.h sys/socket.h)
@@ -5984,6 +5984,7 @@ WINBIND_NSS="nsswitch/libnss_winbind.$SHLIBEXT"
WINBIND_WINS_NSS="nsswitch/libnss_wins.$SHLIBEXT"
WINBIND_NSS_LDSHFLAGS=$LDSHFLAGS
NSSSONAMEVERSIONSUFFIX=""
+WINBIND_NSS_PTHREAD=""
case "$host_os" in
linux*-gnu* | gnu* | k*bsd*-gnu)
@@ -6047,6 +6048,9 @@ case "$host_os" in
;;
esac
+AC_CHECK_LIB(pthread, pthread_mutex_lock, [WINBIND_NSS_PTHREAD="-lpthread"
+ AC_DEFINE(HAVE_PTHREAD, 1, [whether pthread exists])])
+AC_SUBST(WINBIND_NSS_PTHREAD)
AC_SUBST(WINBIND_NSS)
AC_SUBST(WINBIND_WINS_NSS)
AC_SUBST(WINBIND_NSS_LDSHFLAGS)
diff --git a/source3/nsswitch/winbind_nss_linux.c b/source3/nsswitch/winbind_nss_linux.c
index ac53979ced..6de419da5a 100644
--- a/source3/nsswitch/winbind_nss_linux.c
+++ b/source3/nsswitch/winbind_nss_linux.c
@@ -21,6 +21,14 @@
#include "winbind_client.h"
+#if HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
+#if HAVE_PTHREAD
+static pthread_mutex_t winbind_nss_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
/* Maximum number of users to pass back over the unix domain socket
per call. This is not a static limit on the total number of users
or groups returned in total. */
@@ -332,6 +340,10 @@ _nss_winbind_setpwent(void)
fprintf(stderr, "[%5d]: setpwent\n", getpid());
#endif
+#if HAVE_PTHREAD
+ pthread_mutex_lock(&winbind_nss_mutex);
+#endif
+
if (num_pw_cache > 0) {
ndx_pw_cache = num_pw_cache = 0;
winbindd_free_response(&getpwent_response);
@@ -342,6 +354,10 @@ _nss_winbind_setpwent(void)
fprintf(stderr, "[%5d]: setpwent returns %s (%d)\n", getpid(),
nss_err_str(ret), ret);
#endif
+
+#if HAVE_PTHREAD
+ pthread_mutex_unlock(&winbind_nss_mutex);
+#endif
return ret;
}
@@ -355,6 +371,10 @@ _nss_winbind_endpwent(void)
fprintf(stderr, "[%5d]: endpwent\n", getpid());
#endif
+#if HAVE_PTHREAD
+ pthread_mutex_lock(&winbind_nss_mutex);
+#endif
+
if (num_pw_cache > 0) {
ndx_pw_cache = num_pw_cache = 0;
winbindd_free_response(&getpwent_response);
@@ -365,6 +385,11 @@ _nss_winbind_endpwent(void)
fprintf(stderr, "[%5d]: endpwent returns %s (%d)\n", getpid(),
nss_err_str(ret), ret);
#endif
+
+#if HAVE_PTHREAD
+ pthread_mutex_unlock(&winbind_nss_mutex);
+#endif
+
return ret;
}
@@ -382,6 +407,10 @@ _nss_winbind_getpwent_r(struct passwd *result, char *buffer,
fprintf(stderr, "[%5d]: getpwent\n", getpid());
#endif
+#if HAVE_PTHREAD
+ pthread_mutex_lock(&winbind_nss_mutex);
+#endif
+
/* Return an entry from the cache if we have one, or if we are
called again because we exceeded our static buffer. */
@@ -452,6 +481,10 @@ _nss_winbind_getpwent_r(struct passwd *result, char *buffer,
fprintf(stderr, "[%5d]: getpwent returns %s (%d)\n", getpid(),
nss_err_str(ret), ret);
#endif
+
+#if HAVE_PTHREAD
+ pthread_mutex_unlock(&winbind_nss_mutex);
+#endif
return ret;
}
@@ -464,14 +497,18 @@ _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, char *buffer,
NSS_STATUS ret;
static struct winbindd_response response;
struct winbindd_request request;
- static int keep_response=0;
+ static int keep_response;
#ifdef DEBUG_NSS
- fprintf(stderr, "[%5d]: getpwuid %d\n", getpid(), (unsigned int)uid);
+ fprintf(stderr, "[%5d]: getpwuid_r %d\n", getpid(), (unsigned int)uid);
+#endif
+
+#if HAVE_PTHREAD
+ pthread_mutex_lock(&winbind_nss_mutex);
#endif
/* If our static buffer needs to be expanded we are called again */
- if (!keep_response) {
+ if (!keep_response || uid != response.data.pw.pw_uid) {
/* Call for the first time */
@@ -500,7 +537,6 @@ _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, char *buffer,
ret = fill_pwent(result, &response.data.pw, &buffer, &buflen);
if (ret == NSS_STATUS_TRYAGAIN) {
- keep_response = true;
*errnop = errno = ERANGE;
goto done;
}
@@ -510,12 +546,18 @@ _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, char *buffer,
}
winbindd_free_response(&response);
+
done:
#ifdef DEBUG_NSS
fprintf(stderr, "[%5d]: getpwuid %d returns %s (%d)\n", getpid(),
(unsigned int)uid, nss_err_str(ret), ret);
#endif
+
+#if HAVE_PTHREAD
+ pthread_mutex_unlock(&winbind_nss_mutex);
+#endif
+
return ret;
}
@@ -530,12 +572,16 @@ _nss_winbind_getpwnam_r(const char *name, struct passwd *result, char *buffer,
static int keep_response;
#ifdef DEBUG_NSS
- fprintf(stderr, "[%5d]: getpwnam %s\n", getpid(), name);
+ fprintf(stderr, "[%5d]: getpwnam_r %s\n", getpid(), name);
+#endif
+
+#if HAVE_PTHREAD
+ pthread_mutex_lock(&winbind_nss_mutex);
#endif
/* If our static buffer needs to be expanded we are called again */
- if (!keep_response) {
+ if (!keep_response || strcmp(name,response.data.pw.pw_name) != 0) {
/* Call for the first time */
@@ -582,6 +628,11 @@ _nss_winbind_getpwnam_r(const char *name, struct passwd *result, char *buffer,
fprintf(stderr, "[%5d]: getpwnam %s returns %s (%d)\n", getpid(),
name, nss_err_str(ret), ret);
#endif
+
+#if HAVE_PTHREAD
+ pthread_mutex_unlock(&winbind_nss_mutex);
+#endif
+
return ret;
}
@@ -604,6 +655,10 @@ _nss_winbind_setgrent(void)
fprintf(stderr, "[%5d]: setgrent\n", getpid());
#endif
+#if HAVE_PTHREAD
+ pthread_mutex_lock(&winbind_nss_mutex);
+#endif
+
if (num_gr_cache > 0) {
ndx_gr_cache = num_gr_cache = 0;
winbindd_free_response(&getgrent_response);
@@ -614,6 +669,11 @@ _nss_winbind_setgrent(void)
fprintf(stderr, "[%5d]: setgrent returns %s (%d)\n", getpid(),
nss_err_str(ret), ret);
#endif
+
+#if HAVE_PTHREAD
+ pthread_mutex_unlock(&winbind_nss_mutex);
+#endif
+
return ret;
}
@@ -627,6 +687,10 @@ _nss_winbind_endgrent(void)
fprintf(stderr, "[%5d]: endgrent\n", getpid());
#endif
+#if HAVE_PTHREAD
+ pthread_mutex_lock(&winbind_nss_mutex);
+#endif
+
if (num_gr_cache > 0) {
ndx_gr_cache = num_gr_cache = 0;
winbindd_free_response(&getgrent_response);
@@ -637,6 +701,11 @@ _nss_winbind_endgrent(void)
fprintf(stderr, "[%5d]: endgrent returns %s (%d)\n", getpid(),
nss_err_str(ret), ret);
#endif
+
+#if HAVE_PTHREAD
+ pthread_mutex_unlock(&winbind_nss_mutex);
+#endif
+
return ret;
}
@@ -656,6 +725,10 @@ winbind_getgrent(enum winbindd_cmd cmd,
fprintf(stderr, "[%5d]: getgrent\n", getpid());
#endif
+#if HAVE_PTHREAD
+ pthread_mutex_lock(&winbind_nss_mutex);
+#endif
+
/* Return an entry from the cache if we have one, or if we are
called again because we exceeded our static buffer. */
@@ -735,6 +808,11 @@ winbind_getgrent(enum winbindd_cmd cmd,
fprintf(stderr, "[%5d]: getgrent returns %s (%d)\n", getpid(),
nss_err_str(ret), ret);
#endif
+
+#if HAVE_PTHREAD
+ pthread_mutex_unlock(&winbind_nss_mutex);
+#endif
+
return ret;
}
@@ -769,9 +847,14 @@ _nss_winbind_getgrnam_r(const char *name,
fprintf(stderr, "[%5d]: getgrnam %s\n", getpid(), name);
#endif
+#if HAVE_PTHREAD
+ pthread_mutex_lock(&winbind_nss_mutex);
+#endif
+
/* If our static buffer needs to be expanded we are called again */
-
- if (!keep_response) {
+ /* Or if the stored response group name differs from the request. */
+
+ if (!keep_response || strcmp(name,response.data.gr.gr_name) != 0) {
/* Call for the first time */
@@ -798,13 +881,13 @@ _nss_winbind_getgrnam_r(const char *name,
}
} else {
-
+
/* We've been called again */
-
+
ret = fill_grent(result, &response.data.gr,
(char *)response.extra_data.data, &buffer,
&buflen);
-
+
if (ret == NSS_STATUS_TRYAGAIN) {
keep_response = true;
*errnop = errno = ERANGE;
@@ -821,6 +904,11 @@ _nss_winbind_getgrnam_r(const char *name,
fprintf(stderr, "[%5d]: getgrnam %s returns %s (%d)\n", getpid(),
name, nss_err_str(ret), ret);
#endif
+
+#if HAVE_PTHREAD
+ pthread_mutex_unlock(&winbind_nss_mutex);
+#endif
+
return ret;
}
@@ -840,9 +928,14 @@ _nss_winbind_getgrgid_r(gid_t gid,
fprintf(stderr, "[%5d]: getgrgid %d\n", getpid(), gid);
#endif
+#if HAVE_PTHREAD
+ pthread_mutex_lock(&winbind_nss_mutex);
+#endif
+
/* If our static buffer needs to be expanded we are called again */
+ /* Or if the stored response group name differs from the request. */
- if (!keep_response) {
+ if (!keep_response || gid != response.data.gr.gr_gid) {
/* Call for the first time */
@@ -890,6 +983,10 @@ _nss_winbind_getgrgid_r(gid_t gid,
fprintf(stderr, "[%5d]: getgrgid %d returns %s (%d)\n", getpid(),
(unsigned int)gid, nss_err_str(ret), ret);
#endif
+
+#if HAVE_PTHREAD
+ pthread_mutex_unlock(&winbind_nss_mutex);
+#endif
return ret;
}
@@ -910,6 +1007,10 @@ _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start,
user, group);
#endif
+#if HAVE_PTHREAD
+ pthread_mutex_lock(&winbind_nss_mutex);
+#endif
+
ZERO_STRUCT(request);
ZERO_STRUCT(response);
@@ -990,6 +1091,11 @@ _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start,
fprintf(stderr, "[%5d]: initgroups %s returns %s (%d)\n", getpid(),
user, nss_err_str(ret), ret);
#endif
+
+#if HAVE_PTHREAD
+ pthread_mutex_unlock(&winbind_nss_mutex);
+#endif
+
return ret;
}
@@ -1008,6 +1114,10 @@ _nss_winbind_getusersids(const char *user_sid, char **group_sids,
fprintf(stderr, "[%5d]: getusersids %s\n", getpid(), user_sid);
#endif
+#if HAVE_PTHREAD
+ pthread_mutex_lock(&winbind_nss_mutex);
+#endif
+
ZERO_STRUCT(request);
ZERO_STRUCT(response);
@@ -1033,6 +1143,11 @@ _nss_winbind_getusersids(const char *user_sid, char **group_sids,
done:
winbindd_free_response(&response);
+
+#if HAVE_PTHREAD
+ pthread_mutex_unlock(&winbind_nss_mutex);
+#endif
+
return ret;
}
@@ -1050,6 +1165,10 @@ _nss_winbind_nametosid(const char *name, char **sid, char *buffer,
fprintf(stderr, "[%5d]: nametosid %s\n", getpid(), name);
#endif
+#if HAVE_PTHREAD
+ pthread_mutex_lock(&winbind_nss_mutex);
+#endif
+
ZERO_STRUCT(response);
ZERO_STRUCT(request);
@@ -1075,6 +1194,11 @@ _nss_winbind_nametosid(const char *name, char **sid, char *buffer,
failed:
winbindd_free_response(&response);
+
+#if HAVE_PTHREAD
+ pthread_mutex_unlock(&winbind_nss_mutex);
+#endif
+
return ret;
}
@@ -1093,6 +1217,10 @@ _nss_winbind_sidtoname(const char *sid, char **name, char *buffer,
fprintf(stderr, "[%5d]: sidtoname %s\n", getpid(), sid);
#endif
+#if HAVE_PTHREAD
+ pthread_mutex_lock(&winbind_nss_mutex);
+#endif
+
ZERO_STRUCT(response);
ZERO_STRUCT(request);
@@ -1139,6 +1267,11 @@ _nss_winbind_sidtoname(const char *sid, char **name, char *buffer,
failed:
winbindd_free_response(&response);
+
+#if HAVE_PTHREAD
+ pthread_mutex_unlock(&winbind_nss_mutex);
+#endif
+
return ret;
}
@@ -1154,6 +1287,10 @@ _nss_winbind_sidtouid(const char *sid, uid_t *uid, int *errnop)
fprintf(stderr, "[%5d]: sidtouid %s\n", getpid(), sid);
#endif
+#if HAVE_PTHREAD
+ pthread_mutex_lock(&winbind_nss_mutex);
+#endif
+
ZERO_STRUCT(request);
ZERO_STRUCT(response);
@@ -1169,6 +1306,11 @@ _nss_winbind_sidtouid(const char *sid, uid_t *uid, int *errnop)
*uid = response.data.uid;
failed:
+
+#if HAVE_PTHREAD
+ pthread_mutex_unlock(&winbind_nss_mutex);
+#endif
+
return ret;
}
@@ -1184,6 +1326,10 @@ _nss_winbind_sidtogid(const char *sid, gid_t *gid, int *errnop)
fprintf(stderr, "[%5d]: sidtogid %s\n", getpid(), sid);
#endif
+#if HAVE_PTHREAD
+ pthread_mutex_lock(&winbind_nss_mutex);
+#endif
+
ZERO_STRUCT(request);
ZERO_STRUCT(response);
@@ -1199,6 +1345,11 @@ _nss_winbind_sidtogid(const char *sid, gid_t *gid, int *errnop)
*gid = response.data.gid;
failed:
+
+#if HAVE_PTHREAD
+ pthread_mutex_lock(&winbind_nss_mutex);
+#endif
+
return ret;
}
@@ -1215,6 +1366,10 @@ _nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer,
fprintf(stderr, "[%5u]: uidtosid %u\n", (unsigned int)getpid(), (unsigned int)uid);
#endif
+#if HAVE_PTHREAD
+ pthread_mutex_lock(&winbind_nss_mutex);
+#endif
+
ZERO_STRUCT(response);
ZERO_STRUCT(request);
@@ -1238,6 +1393,11 @@ _nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer,
failed:
winbindd_free_response(&response);
+
+#if HAVE_PTHREAD
+ pthread_mutex_unlock(&winbind_nss_mutex);
+#endif
+
return ret;
}
@@ -1254,6 +1414,10 @@ _nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer,
fprintf(stderr, "[%5u]: gidtosid %u\n", (unsigned int)getpid(), (unsigned int)gid);
#endif
+#if HAVE_PTHREAD
+ pthread_mutex_lock(&winbind_nss_mutex);
+#endif
+
ZERO_STRUCT(response);
ZERO_STRUCT(request);
@@ -1277,5 +1441,10 @@ _nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer,
failed:
winbindd_free_response(&response);
+
+#if HAVE_PTHREAD
+ pthread_mutex_unlock(&winbind_nss_mutex);
+#endif
+
return ret;
}