summaryrefslogtreecommitdiff
path: root/source3/nsswitch/wb_common.c
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2002-09-07 05:41:23 +0000
committerAndrew Bartlett <abartlet@samba.org>2002-09-07 05:41:23 +0000
commit885f4f9379b48e74de132d6e6c24f11e8b06ce26 (patch)
tree295d933dd14a3a0d0a79fb86da5a30589ee1a7dd /source3/nsswitch/wb_common.c
parentec4f2af04a09a50e87a95c0ad494a581b0364f03 (diff)
downloadsamba-885f4f9379b48e74de132d6e6c24f11e8b06ce26.tar.gz
samba-885f4f9379b48e74de132d6e6c24f11e8b06ce26.tar.bz2
samba-885f4f9379b48e74de132d6e6c24f11e8b06ce26.zip
Winbind client-side cleanups.
The global winbind file descriptor can cause havoc in some situations - particulary when it becomes 0, 1 or 2. This patch (based on some very nice work by Hannes Schmidt <mail@schmidt-net.via.t-online.de>) starts to recitfy the problem by ensuring that the close-on-exec flag is set, and that we move above 3 in the file descriptor table. I've also decided that the PAM module can close it's pipe handle on every request - this isn't performance-critical code. The next step is to do the same for nss_winbind. (But things like getent() might get in our way there). This also cleans up some function prototypes, puts them in just one place. Andrew Bartlett (This used to be commit 442eb39657b98f67cd229ed3110b63aae8bf4e3c)
Diffstat (limited to 'source3/nsswitch/wb_common.c')
-rw-r--r--source3/nsswitch/wb_common.c73
1 files changed, 69 insertions, 4 deletions
diff --git a/source3/nsswitch/wb_common.c b/source3/nsswitch/wb_common.c
index 9bc9faafb5..0d1be4d5d1 100644
--- a/source3/nsswitch/wb_common.c
+++ b/source3/nsswitch/wb_common.c
@@ -5,6 +5,8 @@
Copyright (C) Tim Potter 2000
Copyright (C) Andrew Tridgell 2000
+ Copyright (C) Andrew Bartlett 2002
+
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -75,7 +77,7 @@ void init_response(struct winbindd_response *response)
/* Close established socket */
-static void close_sock(void)
+void close_sock(void)
{
if (winbindd_fd != -1) {
close(winbindd_fd);
@@ -83,6 +85,64 @@ static void close_sock(void)
}
}
+/* Make sure socket handle isn't stdin, stdout or stderr */
+#define RECURSION_LIMIT 3
+
+static int make_nonstd_fd_internals(int fd, int limit /* Recursion limiter */)
+{
+ int new_fd;
+ if (fd >= 0 && fd <= 2) {
+#ifdef F_DUPFD
+ if ((new_fd = fcntl(fd, F_DUPFD, 3)) == -1) {
+ return -1;
+ }
+ /* Parinoia */
+ if (new_fd < 3) {
+ return -1;
+ }
+ close(fd);
+ return new_fd;
+#else
+ if (limit <= 0)
+ return -1;
+
+ new_fd = dup(fd);
+ if (new_fd == -1)
+ return -1;
+
+ /* use the program stack to hold our list of FDs to close */
+ new_fd = make_nonstd_fd_internals(new_fd, limit - 1);
+ close(fd);
+ return new_fd;
+#endif
+ }
+ return fd;
+}
+
+static int make_safe_fd(int fd)
+{
+ int result, flags;
+ int new_fd = make_nonstd_fd_internals(fd, RECURSION_LIMIT);
+ if (new_fd == -1) {
+ close(fd);
+ return -1;
+ }
+ /* Socket should be closed on exec() */
+
+#ifdef FD_CLOEXEC
+ result = flags = fcntl(new_fd, F_GETFD, 0);
+ if (flags >= 0) {
+ flags |= FD_CLOEXEC;
+ result = fcntl( new_fd, F_SETFD, flags );
+ }
+ if (result < 0) {
+ close(new_fd);
+ return -1;
+ }
+#endif
+ return new_fd;
+}
+
/* Connect to winbindd socket */
int winbind_open_pipe_sock(void)
@@ -91,6 +151,7 @@ int winbind_open_pipe_sock(void)
static pid_t our_pid;
struct stat st;
pstring path;
+ int fd;
if (our_pid != getpid()) {
close_sock();
@@ -144,9 +205,13 @@ int winbind_open_pipe_sock(void)
/* Connect to socket */
- if ((winbindd_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+ if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
return -1;
}
+
+ if ((winbindd_fd = make_safe_fd( fd)) == -1) {
+ return winbindd_fd;
+ }
if (connect(winbindd_fd, (struct sockaddr *)&sunaddr,
sizeof(sunaddr)) == -1) {
@@ -366,8 +431,8 @@ NSS_STATUS winbindd_get_response(struct winbindd_response *response)
/* Handle simple types of requests */
NSS_STATUS winbindd_request(int req_type,
- struct winbindd_request *request,
- struct winbindd_response *response)
+ struct winbindd_request *request,
+ struct winbindd_response *response)
{
NSS_STATUS status;