Winbind client-side cleanups.
authorAndrew Bartlett <abartlet@samba.org>
Sat, 7 Sep 2002 05:41:23 +0000 (05:41 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Sat, 7 Sep 2002 05:41:23 +0000 (05:41 +0000)
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)

source3/include/includes.h
source3/include/smb.h
source3/nsswitch/pam_winbind.c
source3/nsswitch/pam_winbind.h
source3/nsswitch/wb_common.c
source3/nsswitch/wbinfo.c
source3/nsswitch/winbind_nss.c
source3/nsswitch/winbind_nss_config.h

index dacac356e3d79b38d2abb9d167574e077d3c3383..eaa0d25239c1bc42d75ba0a2cac8f82feb56dcd4 100644 (file)
@@ -762,6 +762,8 @@ extern int errno;
 
 #include "mangle.h"
 
+#include "nsswitch/winbind_client.h"
+
 /*
  * Type for wide character dirent structure.
  * Only d_name is defined by POSIX.
index 2ee2f0cb7245e294ec0b542ece131afc6f4e10d2..a1b3faa3436f539184c8c1869defa922ecf6055f 100644 (file)
@@ -1623,8 +1623,6 @@ struct unix_error_map {
 
 #define SAFE_NETBIOS_CHARS ". -_"
 
-#include "nsswitch/winbindd_nss.h"
-
 /* generic iconv conversion structure */
 typedef struct {
        size_t (*direct)(void *cd, char **inbuf, size_t *inbytesleft,
index 29ceca4e79ef877e2aede66a4a70af7ffef3fb01..f95caefb4cd409fd63ba20666ff5f7ca06939f64 100644 (file)
 
 #include "pam_winbind.h"
 
-/* prototypes from common.c */
-void init_request(struct winbindd_request *req,int rq_type);
-int write_sock(void *buffer, int count);
-int read_reply(struct winbindd_response *response);
-
 /* data tokens */
 
 #define MAX_PASSWD_TRIES       3
@@ -99,24 +94,30 @@ static int _make_remark(pam_handle_t * pamh, int type, const char *text)
        return retval;
 }
 
-static int winbind_request(enum winbindd_cmd req_type,
-                           struct winbindd_request *request,
-                           struct winbindd_response *response)
+static int pam_winbind_request(enum winbindd_cmd req_type,
+                              struct winbindd_request *request,
+                              struct winbindd_response *response)
 {
+
        /* Fill in request and send down pipe */
        init_request(request, req_type);
        
        if (write_sock(request, sizeof(*request)) == -1) {
                _pam_log(LOG_ERR, "write to socket failed!");
+               close_sock();
                return PAM_SERVICE_ERR;
        }
        
        /* Wait for reply */
        if (read_reply(response) == -1) {
                _pam_log(LOG_ERR, "read from socket failed!");
+               close_sock();
                return PAM_SERVICE_ERR;
        }
 
+       /* We are done with the socket - close it and avoid mischeif */
+       close_sock();
+
        /* Copy reply data from socket */
        if (response->result != WINBINDD_OK) {
                if (response->data.auth.pam_error != PAM_SUCCESS) {
@@ -148,7 +149,7 @@ static int winbind_auth_request(const char *user, const char *pass, int ctrl)
        strncpy(request.data.auth.pass, pass, 
                 sizeof(request.data.auth.pass)-1);
        
-        retval = winbind_request(WINBINDD_PAM_AUTH, &request, &response);
+        retval = pam_winbind_request(WINBINDD_PAM_AUTH, &request, &response);
 
        switch (retval) {
        case PAM_AUTH_ERR:
@@ -217,7 +218,7 @@ static int winbind_chauthtok_request(const char *user, const char *oldpass,
             request.data.chauthtok.newpass[0] = '\0';
         }
        
-        return winbind_request(WINBINDD_PAM_CHAUTHTOK, &request, &response);
+        return pam_winbind_request(WINBINDD_PAM_CHAUTHTOK, &request, &response);
 }
 
 /*
index 9897249e164101a19c78304785c87c4f045d8739..fae635d8067fde692d967a415c1db1d4056cf08a 100644 (file)
@@ -90,5 +90,4 @@ do {                             \
 #define on(x, y) (x & y)
 #define off(x, y) (!(x & y))
 
-#include "winbind_nss_config.h"
-#include "winbindd_nss.h"
+#include "winbind_client.h"
index 9bc9faafb50e62794c6e71f8f43605e763843662..0d1be4d5d1f6311b250d44930c7ad962d118f6fe 100644 (file)
@@ -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;
 
index d7d70b9e52e29a2b2ba58bbd1a21dcf545df7586..a0fdd033d795acae3bf1769b38182a9b34ffbabc 100644 (file)
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
 
-/* Prototypes from common.h */
-
-NSS_STATUS winbindd_request(int req_type, 
-                           struct winbindd_request *request,
-                           struct winbindd_response *response);
+extern int winbindd_fd;
 
 static char winbind_separator(void)
 {
@@ -608,13 +604,13 @@ static BOOL wbinfo_set_auth_user(char *username)
 static BOOL wbinfo_ping(void)
 {
         NSS_STATUS result;
-       
+
        result = winbindd_request(WINBINDD_PING, NULL, NULL);
 
        /* Display response */
 
-        d_printf("'ping' to winbindd %s\n", 
-               (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
+        d_printf("'ping' to winbindd %s on fd %d\n", 
+               (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed", winbindd_fd);
 
         return result == NSS_STATUS_SUCCESS;
 }
index 594b5fbadb29fad20028def2850c033b6a7399ca..0b4c0ce1d087786d97dc4b6f6a7378ff1b29a544 100644 (file)
@@ -21,8 +21,7 @@
    Boston, MA  02111-1307, USA.   
 */
 
-#include "winbind_nss_config.h"
-#include "winbindd_nss.h"
+#include "winbind_client.h"
 
 #ifdef HAVE_NS_API_H
 #undef VOLATILE
 
 extern int winbindd_fd;
 
-void init_request(struct winbindd_request *req,int rq_type);
-NSS_STATUS winbindd_send_request(int req_type,
-                                struct winbindd_request *request);
-NSS_STATUS winbindd_get_response(struct winbindd_response *response);
-NSS_STATUS winbindd_request(int req_type, 
-                                struct winbindd_request *request,
-                                struct winbindd_response *response);
-int winbind_open_pipe_sock(void);
-int write_sock(void *buffer, int count);
-int read_reply(struct winbindd_response *response);
-void free_response(struct winbindd_response *response);
 
 #ifdef HAVE_NS_API_H
 /* IRIX version */
index 00cd5c12e4798dc08131cb3de47d8d92cc318c71..d9a9b8aaaefe07a250b89cc79070febc212940ef 100644 (file)
 #include <string.h>
 #endif
 
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#else
+#ifdef HAVE_SYS_FCNTL_H
+#include <sys/fcntl.h>
+#endif
+#endif
+
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <errno.h>