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

source/include/includes.h
source/include/smb.h
source/nsswitch/pam_winbind.c
source/nsswitch/pam_winbind.h
source/nsswitch/wb_common.c
source/nsswitch/wbinfo.c
source/nsswitch/winbind_nss.c
source/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>