From ef2e26c91b80556af033d3335e55f5dfa6fff31d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 13 Aug 2003 01:53:07 +0000 Subject: first public release of samba4 code (This used to be commit b0510b5428b3461aeb9bbe3cc95f62fc73e2b97f) --- source4/nsswitch/wb_common.c | 433 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 433 insertions(+) create mode 100644 source4/nsswitch/wb_common.c (limited to 'source4/nsswitch/wb_common.c') diff --git a/source4/nsswitch/wb_common.c b/source4/nsswitch/wb_common.c new file mode 100644 index 0000000000..89c751a4ef --- /dev/null +++ b/source4/nsswitch/wb_common.c @@ -0,0 +1,433 @@ +/* + Unix SMB/CIFS implementation. + + winbind client common code + + 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 + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "winbind_client.h" + +/* Global variables. These are effectively the client state information */ + +int winbindd_fd = -1; /* fd for winbindd socket */ + +/* Free a response structure */ + +void free_response(struct winbindd_response *response) +{ + /* Free any allocated extra_data */ + + if (response) + SAFE_FREE(response->extra_data); +} + +/* Initialise a request structure */ + +void init_request(struct winbindd_request *request, int request_type) +{ + request->length = sizeof(struct winbindd_request); + + request->cmd = (enum winbindd_cmd)request_type; + request->pid = getpid(); + +} + +/* Initialise a response structure */ + +void init_response(struct winbindd_response *response) +{ + /* Initialise return value */ + + response->result = WINBINDD_ERROR; +} + +/* Close established socket */ + +void close_sock(void) +{ + if (winbindd_fd != -1) { + close(winbindd_fd); + winbindd_fd = -1; + } +} + +/* 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) { + close(new_fd); + 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) +{ +#ifdef HAVE_UNIXSOCKET + struct sockaddr_un sunaddr; + static pid_t our_pid; + struct stat st; + pstring path; + int fd; + + if (our_pid != getpid()) { + close_sock(); + our_pid = getpid(); + } + + if (winbindd_fd != -1) { + return winbindd_fd; + } + + /* Check permissions on unix socket directory */ + + if (lstat(WINBINDD_SOCKET_DIR, &st) == -1) { + return -1; + } + + if (!S_ISDIR(st.st_mode) || + (st.st_uid != 0 && st.st_uid != geteuid())) { + return -1; + } + + /* Connect to socket */ + + strncpy(path, WINBINDD_SOCKET_DIR, sizeof(path) - 1); + path[sizeof(path) - 1] = '\0'; + + strncat(path, "/", sizeof(path) - 1); + path[sizeof(path) - 1] = '\0'; + + strncat(path, WINBINDD_SOCKET_NAME, sizeof(path) - 1); + path[sizeof(path) - 1] = '\0'; + + ZERO_STRUCT(sunaddr); + sunaddr.sun_family = AF_UNIX; + strncpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path) - 1); + + /* If socket file doesn't exist, don't bother trying to connect + with retry. This is an attempt to make the system usable when + the winbindd daemon is not running. */ + + if (lstat(path, &st) == -1) { + return -1; + } + + /* Check permissions on unix socket file */ + + if (!S_ISSOCK(st.st_mode) || + (st.st_uid != 0 && st.st_uid != geteuid())) { + return -1; + } + + /* Connect to socket */ + + 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) { + close_sock(); + return -1; + } + + return winbindd_fd; +#else + return -1; +#endif /* HAVE_UNIXSOCKET */ +} + +/* Write data to winbindd socket */ + +int write_sock(void *buffer, int count) +{ + int result, nwritten; + + /* Open connection to winbind daemon */ + + restart: + + if (winbind_open_pipe_sock() == -1) { + return -1; + } + + /* Write data to socket */ + + nwritten = 0; + + while(nwritten < count) { + struct timeval tv; + fd_set r_fds; + + /* Catch pipe close on other end by checking if a read() + call would not block by calling select(). */ + + FD_ZERO(&r_fds); + FD_SET(winbindd_fd, &r_fds); + ZERO_STRUCT(tv); + + if (select(winbindd_fd + 1, &r_fds, NULL, NULL, &tv) == -1) { + close_sock(); + return -1; /* Select error */ + } + + /* Write should be OK if fd not available for reading */ + + if (!FD_ISSET(winbindd_fd, &r_fds)) { + + /* Do the write */ + + result = write(winbindd_fd, + (char *)buffer + nwritten, + count - nwritten); + + if ((result == -1) || (result == 0)) { + + /* Write failed */ + + close_sock(); + return -1; + } + + nwritten += result; + + } else { + + /* Pipe has closed on remote end */ + + close_sock(); + goto restart; + } + } + + return nwritten; +} + +/* Read data from winbindd socket */ + +static int read_sock(void *buffer, int count) +{ + int result = 0, nread = 0; + + /* Read data from socket */ + + while(nread < count) { + + result = read(winbindd_fd, (char *)buffer + nread, + count - nread); + + if ((result == -1) || (result == 0)) { + + /* Read failed. I think the only useful thing we + can do here is just return -1 and fail since the + transaction has failed half way through. */ + + close_sock(); + return -1; + } + + nread += result; + } + + return result; +} + +/* Read reply */ + +int read_reply(struct winbindd_response *response) +{ + int result1, result2 = 0; + + if (!response) { + return -1; + } + + /* Read fixed length response */ + + if ((result1 = read_sock(response, sizeof(struct winbindd_response))) + == -1) { + + return -1; + } + + /* We actually send the pointer value of the extra_data field from + the server. This has no meaning in the client's address space + so we clear it out. */ + + response->extra_data = NULL; + + /* Read variable length response */ + + if (response->length > sizeof(struct winbindd_response)) { + int extra_data_len = response->length - + sizeof(struct winbindd_response); + + /* Mallocate memory for extra data */ + + if (!(response->extra_data = malloc(extra_data_len))) { + return -1; + } + + if ((result2 = read_sock(response->extra_data, extra_data_len)) + == -1) { + free_response(response); + return -1; + } + } + + /* Return total amount of data read */ + + return result1 + result2; +} + +/* + * send simple types of requests + */ + +NSS_STATUS winbindd_send_request(int req_type, struct winbindd_request *request) +{ + struct winbindd_request lrequest; + + /* Check for our tricky environment variable */ + + if (getenv(WINBINDD_DONT_ENV)) { + return NSS_STATUS_NOTFOUND; + } + + if (!request) { + ZERO_STRUCT(lrequest); + request = &lrequest; + } + + /* Fill in request and send down pipe */ + + init_request(request, req_type); + + if (write_sock(request, sizeof(*request)) == -1) { + return NSS_STATUS_UNAVAIL; + } + + return NSS_STATUS_SUCCESS; +} + +/* + * Get results from winbindd request + */ + +NSS_STATUS winbindd_get_response(struct winbindd_response *response) +{ + struct winbindd_response lresponse; + + if (!response) { + ZERO_STRUCT(lresponse); + response = &lresponse; + } + + init_response(response); + + /* Wait for reply */ + if (read_reply(response) == -1) { + return NSS_STATUS_UNAVAIL; + } + + /* Throw away extra data if client didn't request it */ + if (response == &lresponse) { + free_response(response); + } + + /* Copy reply data from socket */ + if (response->result != WINBINDD_OK) { + return NSS_STATUS_NOTFOUND; + } + + return NSS_STATUS_SUCCESS; +} + +/* Handle simple types of requests */ + +NSS_STATUS winbindd_request(int req_type, + struct winbindd_request *request, + struct winbindd_response *response) +{ + NSS_STATUS status; + + status = winbindd_send_request(req_type, request); + if (status != NSS_STATUS_SUCCESS) + return(status); + return winbindd_get_response(response); +} -- cgit From 7fb1be73734915e027f86aca9ba62b86c56ca787 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 24 May 2004 17:41:47 +0000 Subject: r853: remove a real big bunch of unused code I really think that this is needed to get a better overview of what is currently used Also this stuff is really out of date so if we really ever need some of this stuff back, a 'svn copy' from the SAMBA_3_0 branch should be no big problem... metze (This used to be commit 972598d511c64f29bdc849fe58c9c82fbcf6a4a2) --- source4/nsswitch/wb_common.c | 433 ------------------------------------------- 1 file changed, 433 deletions(-) delete mode 100644 source4/nsswitch/wb_common.c (limited to 'source4/nsswitch/wb_common.c') diff --git a/source4/nsswitch/wb_common.c b/source4/nsswitch/wb_common.c deleted file mode 100644 index 89c751a4ef..0000000000 --- a/source4/nsswitch/wb_common.c +++ /dev/null @@ -1,433 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - winbind client common code - - 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 - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -#include "winbind_client.h" - -/* Global variables. These are effectively the client state information */ - -int winbindd_fd = -1; /* fd for winbindd socket */ - -/* Free a response structure */ - -void free_response(struct winbindd_response *response) -{ - /* Free any allocated extra_data */ - - if (response) - SAFE_FREE(response->extra_data); -} - -/* Initialise a request structure */ - -void init_request(struct winbindd_request *request, int request_type) -{ - request->length = sizeof(struct winbindd_request); - - request->cmd = (enum winbindd_cmd)request_type; - request->pid = getpid(); - -} - -/* Initialise a response structure */ - -void init_response(struct winbindd_response *response) -{ - /* Initialise return value */ - - response->result = WINBINDD_ERROR; -} - -/* Close established socket */ - -void close_sock(void) -{ - if (winbindd_fd != -1) { - close(winbindd_fd); - winbindd_fd = -1; - } -} - -/* 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) { - close(new_fd); - 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) -{ -#ifdef HAVE_UNIXSOCKET - struct sockaddr_un sunaddr; - static pid_t our_pid; - struct stat st; - pstring path; - int fd; - - if (our_pid != getpid()) { - close_sock(); - our_pid = getpid(); - } - - if (winbindd_fd != -1) { - return winbindd_fd; - } - - /* Check permissions on unix socket directory */ - - if (lstat(WINBINDD_SOCKET_DIR, &st) == -1) { - return -1; - } - - if (!S_ISDIR(st.st_mode) || - (st.st_uid != 0 && st.st_uid != geteuid())) { - return -1; - } - - /* Connect to socket */ - - strncpy(path, WINBINDD_SOCKET_DIR, sizeof(path) - 1); - path[sizeof(path) - 1] = '\0'; - - strncat(path, "/", sizeof(path) - 1); - path[sizeof(path) - 1] = '\0'; - - strncat(path, WINBINDD_SOCKET_NAME, sizeof(path) - 1); - path[sizeof(path) - 1] = '\0'; - - ZERO_STRUCT(sunaddr); - sunaddr.sun_family = AF_UNIX; - strncpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path) - 1); - - /* If socket file doesn't exist, don't bother trying to connect - with retry. This is an attempt to make the system usable when - the winbindd daemon is not running. */ - - if (lstat(path, &st) == -1) { - return -1; - } - - /* Check permissions on unix socket file */ - - if (!S_ISSOCK(st.st_mode) || - (st.st_uid != 0 && st.st_uid != geteuid())) { - return -1; - } - - /* Connect to socket */ - - 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) { - close_sock(); - return -1; - } - - return winbindd_fd; -#else - return -1; -#endif /* HAVE_UNIXSOCKET */ -} - -/* Write data to winbindd socket */ - -int write_sock(void *buffer, int count) -{ - int result, nwritten; - - /* Open connection to winbind daemon */ - - restart: - - if (winbind_open_pipe_sock() == -1) { - return -1; - } - - /* Write data to socket */ - - nwritten = 0; - - while(nwritten < count) { - struct timeval tv; - fd_set r_fds; - - /* Catch pipe close on other end by checking if a read() - call would not block by calling select(). */ - - FD_ZERO(&r_fds); - FD_SET(winbindd_fd, &r_fds); - ZERO_STRUCT(tv); - - if (select(winbindd_fd + 1, &r_fds, NULL, NULL, &tv) == -1) { - close_sock(); - return -1; /* Select error */ - } - - /* Write should be OK if fd not available for reading */ - - if (!FD_ISSET(winbindd_fd, &r_fds)) { - - /* Do the write */ - - result = write(winbindd_fd, - (char *)buffer + nwritten, - count - nwritten); - - if ((result == -1) || (result == 0)) { - - /* Write failed */ - - close_sock(); - return -1; - } - - nwritten += result; - - } else { - - /* Pipe has closed on remote end */ - - close_sock(); - goto restart; - } - } - - return nwritten; -} - -/* Read data from winbindd socket */ - -static int read_sock(void *buffer, int count) -{ - int result = 0, nread = 0; - - /* Read data from socket */ - - while(nread < count) { - - result = read(winbindd_fd, (char *)buffer + nread, - count - nread); - - if ((result == -1) || (result == 0)) { - - /* Read failed. I think the only useful thing we - can do here is just return -1 and fail since the - transaction has failed half way through. */ - - close_sock(); - return -1; - } - - nread += result; - } - - return result; -} - -/* Read reply */ - -int read_reply(struct winbindd_response *response) -{ - int result1, result2 = 0; - - if (!response) { - return -1; - } - - /* Read fixed length response */ - - if ((result1 = read_sock(response, sizeof(struct winbindd_response))) - == -1) { - - return -1; - } - - /* We actually send the pointer value of the extra_data field from - the server. This has no meaning in the client's address space - so we clear it out. */ - - response->extra_data = NULL; - - /* Read variable length response */ - - if (response->length > sizeof(struct winbindd_response)) { - int extra_data_len = response->length - - sizeof(struct winbindd_response); - - /* Mallocate memory for extra data */ - - if (!(response->extra_data = malloc(extra_data_len))) { - return -1; - } - - if ((result2 = read_sock(response->extra_data, extra_data_len)) - == -1) { - free_response(response); - return -1; - } - } - - /* Return total amount of data read */ - - return result1 + result2; -} - -/* - * send simple types of requests - */ - -NSS_STATUS winbindd_send_request(int req_type, struct winbindd_request *request) -{ - struct winbindd_request lrequest; - - /* Check for our tricky environment variable */ - - if (getenv(WINBINDD_DONT_ENV)) { - return NSS_STATUS_NOTFOUND; - } - - if (!request) { - ZERO_STRUCT(lrequest); - request = &lrequest; - } - - /* Fill in request and send down pipe */ - - init_request(request, req_type); - - if (write_sock(request, sizeof(*request)) == -1) { - return NSS_STATUS_UNAVAIL; - } - - return NSS_STATUS_SUCCESS; -} - -/* - * Get results from winbindd request - */ - -NSS_STATUS winbindd_get_response(struct winbindd_response *response) -{ - struct winbindd_response lresponse; - - if (!response) { - ZERO_STRUCT(lresponse); - response = &lresponse; - } - - init_response(response); - - /* Wait for reply */ - if (read_reply(response) == -1) { - return NSS_STATUS_UNAVAIL; - } - - /* Throw away extra data if client didn't request it */ - if (response == &lresponse) { - free_response(response); - } - - /* Copy reply data from socket */ - if (response->result != WINBINDD_OK) { - return NSS_STATUS_NOTFOUND; - } - - return NSS_STATUS_SUCCESS; -} - -/* Handle simple types of requests */ - -NSS_STATUS winbindd_request(int req_type, - struct winbindd_request *request, - struct winbindd_response *response) -{ - NSS_STATUS status; - - status = winbindd_send_request(req_type, request); - if (status != NSS_STATUS_SUCCESS) - return(status); - return winbindd_get_response(response); -} -- cgit From 4298624589e2b44d88d703fe7cc0e73957c7652e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 24 Oct 2004 23:54:00 +0000 Subject: r3170: Add winbind client support back into Samba4. This is to allow auth_winbind to work, and to therefore use the new ntlm_auth and GENSEC in an otherwise Samba3 setup. I'm not quite sure what fun-and games my svn cp caused as I merged this from samba_3_0, but anyway... Andrew Bartlett (This used to be commit 5925b94a59da406d7e6b8cc695c99ba112fdfcd6) --- source4/nsswitch/wb_common.c | 612 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 612 insertions(+) create mode 100644 source4/nsswitch/wb_common.c (limited to 'source4/nsswitch/wb_common.c') diff --git a/source4/nsswitch/wb_common.c b/source4/nsswitch/wb_common.c new file mode 100644 index 0000000000..2f112e8695 --- /dev/null +++ b/source4/nsswitch/wb_common.c @@ -0,0 +1,612 @@ +/* + Unix SMB/CIFS implementation. + + winbind client common code + + 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 + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "includes.h" + +/* Global variables. These are effectively the client state information */ + +int winbindd_fd = -1; /* fd for winbindd socket */ + +/* Free a response structure */ + +void free_response(struct winbindd_response *response) +{ + /* Free any allocated extra_data */ + + if (response) + SAFE_FREE(response->extra_data); +} + +/* Initialise a request structure */ + +void init_request(struct winbindd_request *request, int request_type) +{ + request->length = sizeof(struct winbindd_request); + + request->cmd = (enum winbindd_cmd)request_type; + request->pid = getpid(); + +} + +/* Initialise a response structure */ + +void init_response(struct winbindd_response *response) +{ + /* Initialise return value */ + + response->result = WINBINDD_ERROR; +} + +/* Close established socket */ + +void close_sock(void) +{ + if (winbindd_fd != -1) { + close(winbindd_fd); + winbindd_fd = -1; + } +} + +#define CONNECT_TIMEOUT 30 +#define WRITE_TIMEOUT CONNECT_TIMEOUT +#define READ_TIMEOUT CONNECT_TIMEOUT + +/* 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; + } + /* Paranoia */ + if (new_fd < 3) { + close(new_fd); + 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; +} + +/**************************************************************************** + Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available, + else + if SYSV use O_NDELAY + if BSD use FNDELAY + Set close on exec also. +****************************************************************************/ + +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 nonblocking. */ +#ifdef O_NONBLOCK +#define FLAG_TO_SET O_NONBLOCK +#else +#ifdef SYSV +#define FLAG_TO_SET O_NDELAY +#else /* BSD */ +#define FLAG_TO_SET FNDELAY +#endif +#endif + + if ((flags = fcntl(new_fd, F_GETFL)) == -1) { + close(new_fd); + return -1; + } + + flags |= FLAG_TO_SET; + if (fcntl(new_fd, F_SETFL, flags) == -1) { + close(new_fd); + return -1; + } + +#undef FLAG_TO_SET + + /* 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 */ + +static int winbind_named_pipe_sock(const char *dir) +{ + struct sockaddr_un sunaddr; + struct stat st; + pstring path; + int fd; + int wait_time; + int slept; + + /* Check permissions on unix socket directory */ + + if (lstat(dir, &st) == -1) { + return -1; + } + + if (!S_ISDIR(st.st_mode) || + (st.st_uid != 0 && st.st_uid != geteuid())) { + return -1; + } + + /* Connect to socket */ + + snprintf(path, sizeof(path), "%s%s", dir, "/" WINBINDD_SOCKET_NAME); + + ZERO_STRUCT(sunaddr); + sunaddr.sun_family = AF_UNIX; + strncpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path) - 1); + + /* If socket file doesn't exist, don't bother trying to connect + with retry. This is an attempt to make the system usable when + the winbindd daemon is not running. */ + + if (lstat(path, &st) == -1) { + return -1; + } + + /* Check permissions on unix socket file */ + + if (!S_ISSOCK(st.st_mode) || + (st.st_uid != 0 && st.st_uid != geteuid())) { + return -1; + } + + /* Connect to socket */ + + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + return -1; + } + + /* Set socket non-blocking and close on exec. */ + + if ((fd = make_safe_fd( fd)) == -1) { + return fd; + } + + for (wait_time = 0; connect(fd, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1; + wait_time += slept) { + struct timeval tv; + fd_set w_fds; + int ret; + int connect_errno = 0, errnosize; + + if (wait_time >= CONNECT_TIMEOUT) + goto error_out; + + switch (errno) { + case EINPROGRESS: + FD_ZERO(&w_fds); + FD_SET(fd, &w_fds); + tv.tv_sec = CONNECT_TIMEOUT - wait_time; + tv.tv_usec = 0; + + ret = select(fd + 1, NULL, &w_fds, NULL, &tv); + + if (ret > 0) { + errnosize = sizeof(connect_errno); + + ret = getsockopt(fd, SOL_SOCKET, + SO_ERROR, &connect_errno, &errnosize); + + if (ret >= 0 && connect_errno == 0) { + /* Connect succeed */ + goto out; + } + } + + slept = CONNECT_TIMEOUT; + break; + case EAGAIN: + slept = rand() % 3 + 1; + sleep(slept); + break; + default: + goto error_out; + } + + } + + out: + + return fd; + + error_out: + + close(fd); + return -1; + + if (connect(fd, (struct sockaddr *)&sunaddr, + sizeof(sunaddr)) == -1) { + close(fd); + return -1; + } + + return fd; +} + +/* Connect to winbindd socket */ + +int winbind_open_pipe_sock(void) +{ +#ifdef HAVE_UNIXSOCKET + static pid_t our_pid; + struct winbindd_request request; + struct winbindd_response response; + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + if (our_pid != getpid()) { + close_sock(); + our_pid = getpid(); + } + + if (winbindd_fd != -1) { + return winbindd_fd; + } + + if ((winbindd_fd = winbind_named_pipe_sock(WINBINDD_SOCKET_DIR)) == -1) { + return -1; + } + + /* version-check the socket */ + + if ((winbindd_request(WINBINDD_INTERFACE_VERSION, &request, &response) != NSS_STATUS_SUCCESS) || (response.data.interface_version != WINBIND_INTERFACE_VERSION)) { + close_sock(); + return -1; + } + + /* try and get priv pipe */ + + if (winbindd_request(WINBINDD_PRIV_PIPE_DIR, &request, &response) == NSS_STATUS_SUCCESS) { + int fd; + if ((fd = winbind_named_pipe_sock(response.extra_data)) != -1) { + close(winbindd_fd); + winbindd_fd = fd; + } + } + + SAFE_FREE(response.extra_data); + + return winbindd_fd; +#else + return -1; +#endif /* HAVE_UNIXSOCKET */ +} + +/* Write data to winbindd socket */ + +int write_sock(void *buffer, int count) +{ + int result, nwritten; + + /* Open connection to winbind daemon */ + + restart: + + if (winbind_open_pipe_sock() == -1) { + return -1; + } + + /* Write data to socket */ + + nwritten = 0; + + while(nwritten < count) { + struct timeval tv; + fd_set r_fds; + + /* Catch pipe close on other end by checking if a read() + call would not block by calling select(). */ + + FD_ZERO(&r_fds); + FD_SET(winbindd_fd, &r_fds); + ZERO_STRUCT(tv); + + if (select(winbindd_fd + 1, &r_fds, NULL, NULL, &tv) == -1) { + close_sock(); + return -1; /* Select error */ + } + + /* Write should be OK if fd not available for reading */ + + if (!FD_ISSET(winbindd_fd, &r_fds)) { + + /* Do the write */ + + result = write(winbindd_fd, + (char *)buffer + nwritten, + count - nwritten); + + if ((result == -1) || (result == 0)) { + + /* Write failed */ + + close_sock(); + return -1; + } + + nwritten += result; + + } else { + + /* Pipe has closed on remote end */ + + close_sock(); + goto restart; + } + } + + return nwritten; +} + +/* Read data from winbindd socket */ + +static int read_sock(void *buffer, int count) +{ + int result = 0, nread = 0; + int total_time = 0, selret; + + /* Read data from socket */ + while(nread < count) { + struct timeval tv; + fd_set r_fds; + + /* Catch pipe close on other end by checking if a read() + call would not block by calling select(). */ + + FD_ZERO(&r_fds); + FD_SET(winbindd_fd, &r_fds); + ZERO_STRUCT(tv); + /* Wait for 5 seconds for a reply. May need to parameterise this... */ + tv.tv_sec = 5; + + if ((selret = select(winbindd_fd + 1, &r_fds, NULL, NULL, &tv)) == -1) { + close_sock(); + return -1; /* Select error */ + } + + if (selret == 0) { + /* Not ready for read yet... */ + if (total_time >= 30) { + /* Timeout */ + close_sock(); + return -1; + } + total_time += 5; + continue; + } + + if (FD_ISSET(winbindd_fd, &r_fds)) { + + /* Do the Read */ + + result = read(winbindd_fd, (char *)buffer + nread, + count - nread); + + if ((result == -1) || (result == 0)) { + + /* Read failed. I think the only useful thing we + can do here is just return -1 and fail since the + transaction has failed half way through. */ + + close_sock(); + return -1; + } + + nread += result; + + } + } + + return result; +} + +/* Read reply */ + +int read_reply(struct winbindd_response *response) +{ + int result1, result2 = 0; + + if (!response) { + return -1; + } + + /* Read fixed length response */ + + if ((result1 = read_sock(response, sizeof(struct winbindd_response))) + == -1) { + + return -1; + } + + /* We actually send the pointer value of the extra_data field from + the server. This has no meaning in the client's address space + so we clear it out. */ + + response->extra_data = NULL; + + /* Read variable length response */ + + if (response->length > sizeof(struct winbindd_response)) { + int extra_data_len = response->length - + sizeof(struct winbindd_response); + + /* Mallocate memory for extra data */ + + if (!(response->extra_data = malloc(extra_data_len))) { + return -1; + } + + if ((result2 = read_sock(response->extra_data, extra_data_len)) + == -1) { + free_response(response); + return -1; + } + } + + /* Return total amount of data read */ + + return result1 + result2; +} + +/* + * send simple types of requests + */ + +NSS_STATUS winbindd_send_request(int req_type, struct winbindd_request *request) +{ + struct winbindd_request lrequest; + char *env; + int value; + + /* Check for our tricky environment variable */ + + if ( (env = getenv(WINBINDD_DONT_ENV)) != NULL ) { + value = atoi(env); + if ( value == 1 ) + return NSS_STATUS_NOTFOUND; + } + + if (!request) { + ZERO_STRUCT(lrequest); + request = &lrequest; + } + + /* Fill in request and send down pipe */ + + init_request(request, req_type); + + if (write_sock(request, sizeof(*request)) == -1) { + return NSS_STATUS_UNAVAIL; + } + + return NSS_STATUS_SUCCESS; +} + +/* + * Get results from winbindd request + */ + +NSS_STATUS winbindd_get_response(struct winbindd_response *response) +{ + struct winbindd_response lresponse; + + if (!response) { + ZERO_STRUCT(lresponse); + response = &lresponse; + } + + init_response(response); + + /* Wait for reply */ + if (read_reply(response) == -1) { + return NSS_STATUS_UNAVAIL; + } + + /* Throw away extra data if client didn't request it */ + if (response == &lresponse) { + free_response(response); + } + + /* Copy reply data from socket */ + if (response->result != WINBINDD_OK) { + return NSS_STATUS_NOTFOUND; + } + + return NSS_STATUS_SUCCESS; +} + +/* Handle simple types of requests */ + +NSS_STATUS winbindd_request(int req_type, + struct winbindd_request *request, + struct winbindd_response *response) +{ + NSS_STATUS status; + + status = winbindd_send_request(req_type, request); + if (status != NSS_STATUS_SUCCESS) + return(status); + return winbindd_get_response(response); +} + +/************************************************************************* + A couple of simple functions to disable winbindd lookups and re- + enable them + ************************************************************************/ + +/* Use putenv() instead of setenv() in these functions as not all + environments have the latter. */ + +BOOL winbind_off( void ) +{ + static char *s = WINBINDD_DONT_ENV "=1"; + + return putenv(s) != -1; +} + +BOOL winbind_on( void ) +{ + static char *s = WINBINDD_DONT_ENV "=0"; + + return putenv(s) != -1; +} -- cgit From a6ae640313a47ac2950c0948e4385fa934a5ef09 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 28 Oct 2004 13:19:39 +0000 Subject: r3323: more warning reductions (This used to be commit 5921587ec26e4892efc678421277e4969417d7f5) --- source4/nsswitch/wb_common.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'source4/nsswitch/wb_common.c') diff --git a/source4/nsswitch/wb_common.c b/source4/nsswitch/wb_common.c index 2f112e8695..a26e430db4 100644 --- a/source4/nsswitch/wb_common.c +++ b/source4/nsswitch/wb_common.c @@ -599,14 +599,22 @@ NSS_STATUS winbindd_request(int req_type, BOOL winbind_off( void ) { - static char *s = WINBINDD_DONT_ENV "=1"; - +#if HAVE_SETENV + setenv(WINBINDD_DONT_ENV, "1", 1); + return True; +#else + static const char *s = WINBINDD_DONT_ENV "=1"; return putenv(s) != -1; +#endif } BOOL winbind_on( void ) { - static char *s = WINBINDD_DONT_ENV "=0"; - +#if HAVE_SETENV + setenv(WINBINDD_DONT_ENV, "0", 1); + return True; +#else + static const char *s = WINBINDD_DONT_ENV "=0"; return putenv(s) != -1; +#endif } -- cgit From e82aad1ce39a6b7a2e51b9e2cb494d74ec70e158 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 10 Feb 2005 05:09:35 +0000 Subject: r5298: - got rid of pstring.h from includes.h. This at least makes it a bit less likely that anyone will use pstring for new code - got rid of winbind_client.h from includes.h. This one triggered a huge change, as winbind_client.h was including system/filesys.h and defining the old uint32 and uint16 types, as well as its own pstring and fstring. (This used to be commit 9db6c79e902ec538108d6b7d3324039aabe1704f) --- source4/nsswitch/wb_common.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/nsswitch/wb_common.c') diff --git a/source4/nsswitch/wb_common.c b/source4/nsswitch/wb_common.c index a26e430db4..d7b4614f35 100644 --- a/source4/nsswitch/wb_common.c +++ b/source4/nsswitch/wb_common.c @@ -25,6 +25,7 @@ */ #include "includes.h" +#include "nsswitch/winbind_client.h" /* Global variables. These are effectively the client state information */ -- cgit From b1ad4a27cb7f7a0169c4f6a3756462912a9fa8e6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 21 Sep 2005 14:41:29 +0000 Subject: r10390: Remove fstring, pstring and uint32_t from winbindd_nss.h. Volker (This used to be commit 3dc7e67dc5e5844523e9768081123c622e61c7e9) --- source4/nsswitch/wb_common.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source4/nsswitch/wb_common.c') diff --git a/source4/nsswitch/wb_common.c b/source4/nsswitch/wb_common.c index d7b4614f35..97f8232524 100644 --- a/source4/nsswitch/wb_common.c +++ b/source4/nsswitch/wb_common.c @@ -172,7 +172,7 @@ static int winbind_named_pipe_sock(const char *dir) { struct sockaddr_un sunaddr; struct stat st; - pstring path; + char *path; int fd; int wait_time; int slept; @@ -190,8 +190,7 @@ static int winbind_named_pipe_sock(const char *dir) /* Connect to socket */ - snprintf(path, sizeof(path), "%s%s", dir, "/" WINBINDD_SOCKET_NAME); - + asprintf(&path, "%s%s", dir, "/" WINBINDD_SOCKET_NAME); ZERO_STRUCT(sunaddr); sunaddr.sun_family = AF_UNIX; strncpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path) - 1); @@ -201,8 +200,11 @@ static int winbind_named_pipe_sock(const char *dir) the winbindd daemon is not running. */ if (lstat(path, &st) == -1) { + SAFE_FREE(path); return -1; } + + SAFE_FREE(path); /* Check permissions on unix socket file */ -- cgit From e5671ad531c7efe72836cfe48604fb90a8fa53a9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 12 Oct 2005 20:20:20 +0000 Subject: r10934: Fix a gcc 4 warning (This used to be commit 317edeb546ef03507812e5a0fa1fb331073f55c1) --- source4/nsswitch/wb_common.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/nsswitch/wb_common.c') diff --git a/source4/nsswitch/wb_common.c b/source4/nsswitch/wb_common.c index 97f8232524..98eeb279f8 100644 --- a/source4/nsswitch/wb_common.c +++ b/source4/nsswitch/wb_common.c @@ -230,7 +230,8 @@ static int winbind_named_pipe_sock(const char *dir) struct timeval tv; fd_set w_fds; int ret; - int connect_errno = 0, errnosize; + int connect_errno = 0; + socklen_t errnosize; if (wait_time >= CONNECT_TIMEOUT) goto error_out; -- cgit From 7f38e8644bf875fd68edc79158a2edf9f9f0a607 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 24 Aug 2006 12:13:41 +0000 Subject: r17794: ifdef out unused macros metze (This used to be commit 6968136621dc75532a19c910bf559aa37b7e41bd) --- source4/nsswitch/wb_common.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/nsswitch/wb_common.c') diff --git a/source4/nsswitch/wb_common.c b/source4/nsswitch/wb_common.c index 98eeb279f8..f829b55f2a 100644 --- a/source4/nsswitch/wb_common.c +++ b/source4/nsswitch/wb_common.c @@ -72,8 +72,10 @@ void close_sock(void) } #define CONNECT_TIMEOUT 30 +#if 0 /* unused */ #define WRITE_TIMEOUT CONNECT_TIMEOUT #define READ_TIMEOUT CONNECT_TIMEOUT +#endif /* Make sure socket handle isn't stdin, stdout or stderr */ #define RECURSION_LIMIT 3 -- cgit From 2cd4e0264ff2a852c657049ac27b13d8d5d27fc3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 7 Sep 2006 11:48:53 +0000 Subject: r18218: setenv() is guaranteed by libreplace also, putenv() cannot take a const char * (This used to be commit 03c9f9dc3668d43983e0e6d7b87d9d3bbf8869f0) --- source4/nsswitch/wb_common.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'source4/nsswitch/wb_common.c') diff --git a/source4/nsswitch/wb_common.c b/source4/nsswitch/wb_common.c index f829b55f2a..e8c317b598 100644 --- a/source4/nsswitch/wb_common.c +++ b/source4/nsswitch/wb_common.c @@ -600,27 +600,14 @@ NSS_STATUS winbindd_request(int req_type, enable them ************************************************************************/ -/* Use putenv() instead of setenv() in these functions as not all - environments have the latter. */ - BOOL winbind_off( void ) { -#if HAVE_SETENV setenv(WINBINDD_DONT_ENV, "1", 1); return True; -#else - static const char *s = WINBINDD_DONT_ENV "=1"; - return putenv(s) != -1; -#endif } BOOL winbind_on( void ) { -#if HAVE_SETENV setenv(WINBINDD_DONT_ENV, "0", 1); return True; -#else - static const char *s = WINBINDD_DONT_ENV "=0"; - return putenv(s) != -1; -#endif } -- cgit From 3fb4bd1c06a081f8f010ecfe66a9e18ed8413d66 Mon Sep 17 00:00:00 2001 From: Kai Blin Date: Sat, 2 Jun 2007 11:38:27 +0000 Subject: r23311: Updating the samba4 winbind protocol to version 18. nsswitch/winbindd_nss.h is just copied from SAMBA_3_0. nsswitch/winbind_nss_config.h is copied from SAMBA_3_0, too, but I had to drop some of the defines to make things build again. Kai (This used to be commit 553b7e146f52975b45941ba850140e312a280513) --- source4/nsswitch/wb_common.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source4/nsswitch/wb_common.c') diff --git a/source4/nsswitch/wb_common.c b/source4/nsswitch/wb_common.c index e8c317b598..51f9deb5b0 100644 --- a/source4/nsswitch/wb_common.c +++ b/source4/nsswitch/wb_common.c @@ -38,7 +38,7 @@ void free_response(struct winbindd_response *response) /* Free any allocated extra_data */ if (response) - SAFE_FREE(response->extra_data); + SAFE_FREE(response->extra_data.data); } /* Initialise a request structure */ @@ -324,13 +324,13 @@ int winbind_open_pipe_sock(void) if (winbindd_request(WINBINDD_PRIV_PIPE_DIR, &request, &response) == NSS_STATUS_SUCCESS) { int fd; - if ((fd = winbind_named_pipe_sock(response.extra_data)) != -1) { + if ((fd = winbind_named_pipe_sock(response.extra_data.data)) != -1) { close(winbindd_fd); winbindd_fd = fd; } } - SAFE_FREE(response.extra_data); + SAFE_FREE(response.extra_data.data); return winbindd_fd; #else @@ -488,7 +488,7 @@ int read_reply(struct winbindd_response *response) the server. This has no meaning in the client's address space so we clear it out. */ - response->extra_data = NULL; + response->extra_data.data = NULL; /* Read variable length response */ @@ -498,11 +498,11 @@ int read_reply(struct winbindd_response *response) /* Mallocate memory for extra data */ - if (!(response->extra_data = malloc(extra_data_len))) { + if (!(response->extra_data.data = malloc(extra_data_len))) { return -1; } - if ((result2 = read_sock(response->extra_data, extra_data_len)) + if ((result2 = read_sock(response->extra_data.data, extra_data_len)) == -1) { free_response(response); return -1; -- cgit From 95f930d8751f1bcdd7ca9ef23c59b182c1315891 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 02:31:50 +0000 Subject: r23794: convert more code from LGPLv2+ to LGPLv3+ (This used to be commit 9d37f1ec070ddcfd49dfe351e76cc08fa0d9b41c) --- source4/nsswitch/wb_common.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'source4/nsswitch/wb_common.c') diff --git a/source4/nsswitch/wb_common.c b/source4/nsswitch/wb_common.c index 51f9deb5b0..3ecfc50b9b 100644 --- a/source4/nsswitch/wb_common.c +++ b/source4/nsswitch/wb_common.c @@ -11,17 +11,15 @@ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. + version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. + You should have received a copy of the GNU Library General Public License + along with this program. If not, see . */ #include "includes.h" -- cgit From b8875bee5f0c5385ba02646c7a8b2380fdfabb7a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 04:04:46 +0000 Subject: r23800: LGPL is now called GNU Lesser General Public License not GNU Library General Public License (This used to be commit 01e3fe7533b5670236c026ec3c6cc1e25655fbc3) --- source4/nsswitch/wb_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/nsswitch/wb_common.c') diff --git a/source4/nsswitch/wb_common.c b/source4/nsswitch/wb_common.c index 3ecfc50b9b..b368483141 100644 --- a/source4/nsswitch/wb_common.c +++ b/source4/nsswitch/wb_common.c @@ -9,7 +9,7 @@ This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public + modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. @@ -18,7 +18,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. - You should have received a copy of the GNU Library General Public License + You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ -- cgit From 40dbe572e5884d123377608f83dbe4bc3054565e Mon Sep 17 00:00:00 2001 From: Kai Blin Date: Sun, 15 Jul 2007 07:51:31 +0000 Subject: r23876: Prepare to run nsstest from make test, just not add it to tests_all.sh yet. (This used to be commit f45ae8a878c3d34ea2e4e1c7770e57cd96fa845b) --- source4/nsswitch/wb_common.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'source4/nsswitch/wb_common.c') diff --git a/source4/nsswitch/wb_common.c b/source4/nsswitch/wb_common.c index b368483141..7c17c32937 100644 --- a/source4/nsswitch/wb_common.c +++ b/source4/nsswitch/wb_common.c @@ -295,6 +295,7 @@ int winbind_open_pipe_sock(void) static pid_t our_pid; struct winbindd_request request; struct winbindd_response response; + const char *winbindd_socket_dir_env; ZERO_STRUCT(request); ZERO_STRUCT(response); @@ -307,7 +308,21 @@ int winbind_open_pipe_sock(void) return winbindd_fd; } - if ((winbindd_fd = winbind_named_pipe_sock(WINBINDD_SOCKET_DIR)) == -1) { +#ifdef DEVELOPER + winbindd_socket_dir_env = getenv(WINBINDD_SOCKET_DIR_ENV); + + if (!winbindd_socket_dir_env) + { + winbindd_socket_dir_env = WINBINDD_SOCKET_DIR; + } +#else + winbindd_socket_dir_env = WINBINDD_SOCKET_DIR; +#endif + + winbindd_fd = winbind_named_pipe_sock(winbindd_socket_dir_env); + + if (winbindd_fd == -1) + { return -1; } -- cgit From 9b1cdd45ebaf70fd6160d4805931c5ee31dddcde Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 9 Aug 2007 08:08:09 +0000 Subject: r24285: A number of machines on the build farm fail because while they use SOCKET_WRAPPER, they don't compile with --enable-developer. As such the winbind tests fail. We need to ensure that on production systems we never have SOCKET_WRAPPER set, or this could be a security issue. Andrew Bartlett (This used to be commit eccc2d11da86661cb2086a6f5ce970571d744ec9) --- source4/nsswitch/wb_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/nsswitch/wb_common.c') diff --git a/source4/nsswitch/wb_common.c b/source4/nsswitch/wb_common.c index 7c17c32937..e2b84e9f69 100644 --- a/source4/nsswitch/wb_common.c +++ b/source4/nsswitch/wb_common.c @@ -308,7 +308,7 @@ int winbind_open_pipe_sock(void) return winbindd_fd; } -#ifdef DEVELOPER +#ifdef SOCKET_WRAPPER winbindd_socket_dir_env = getenv(WINBINDD_SOCKET_DIR_ENV); if (!winbindd_socket_dir_env) -- cgit From 32ce9de932c3f08b728bd9c743c70d702dc68a88 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Wed, 22 Aug 2007 13:51:44 +0000 Subject: r24629: Make read_sock return the total number of bytes read instead of the number of bytes read in the last of possibly several read calls. This was noted by Metze. Michael (This used to be commit 37363307c6cbe28f1ca7135ca501d8c0dcd4c6d7) --- source4/nsswitch/wb_common.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/nsswitch/wb_common.c') diff --git a/source4/nsswitch/wb_common.c b/source4/nsswitch/wb_common.c index e2b84e9f69..e8ea31db0f 100644 --- a/source4/nsswitch/wb_common.c +++ b/source4/nsswitch/wb_common.c @@ -421,7 +421,7 @@ int write_sock(void *buffer, int count) static int read_sock(void *buffer, int count) { - int result = 0, nread = 0; + int nread = 0; int total_time = 0, selret; /* Read data from socket */ @@ -458,7 +458,7 @@ static int read_sock(void *buffer, int count) /* Do the Read */ - result = read(winbindd_fd, (char *)buffer + nread, + int result = read(winbindd_fd, (char *)buffer + nread, count - nread); if ((result == -1) || (result == 0)) { @@ -476,7 +476,7 @@ static int read_sock(void *buffer, int count) } } - return result; + return nread; } /* Read reply */ -- cgit From 7e297ecfa4db2c7ab720a63c7764bc0e20f8058c Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 9 Sep 2007 19:34:30 +0000 Subject: r25047: Fix more warnings. (This used to be commit 69de86d2d2e49439760fbc61901eb87fb7fc5d55) --- source4/nsswitch/wb_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/nsswitch/wb_common.c') diff --git a/source4/nsswitch/wb_common.c b/source4/nsswitch/wb_common.c index e8ea31db0f..101659380c 100644 --- a/source4/nsswitch/wb_common.c +++ b/source4/nsswitch/wb_common.c @@ -613,13 +613,13 @@ NSS_STATUS winbindd_request(int req_type, enable them ************************************************************************/ -BOOL winbind_off( void ) +bool winbind_off( void ) { setenv(WINBINDD_DONT_ENV, "1", 1); return True; } -BOOL winbind_on( void ) +bool winbind_on( void ) { setenv(WINBINDD_DONT_ENV, "0", 1); return True; -- cgit From 540caf7ea691874436ddfaf440f4b0714e592dce Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 15 Sep 2007 20:09:29 +0000 Subject: r25181: sync winbind client code with samba3 NOTE: wbinfo.c isn't fully merged here metze (This used to be commit eee5327dc2f79c052c2db0ca89f23cc9d2ce355d) --- source4/nsswitch/wb_common.c | 242 ++++++++++++++++++++++++++++--------------- 1 file changed, 160 insertions(+), 82 deletions(-) (limited to 'source4/nsswitch/wb_common.c') diff --git a/source4/nsswitch/wb_common.c b/source4/nsswitch/wb_common.c index 101659380c..2ae85dcb1e 100644 --- a/source4/nsswitch/wb_common.c +++ b/source4/nsswitch/wb_common.c @@ -22,16 +22,16 @@ along with this program. If not, see . */ -#include "includes.h" -#include "nsswitch/winbind_client.h" +#include "winbind_client.h" /* Global variables. These are effectively the client state information */ int winbindd_fd = -1; /* fd for winbindd socket */ +static int is_privileged = 0; /* Free a response structure */ -void free_response(struct winbindd_response *response) +void winbindd_free_response(struct winbindd_response *response) { /* Free any allocated extra_data */ @@ -41,7 +41,7 @@ void free_response(struct winbindd_response *response) /* Initialise a request structure */ -void init_request(struct winbindd_request *request, int request_type) +void winbindd_init_request(struct winbindd_request *request, int request_type) { request->length = sizeof(struct winbindd_request); @@ -52,7 +52,7 @@ void init_request(struct winbindd_request *request, int request_type) /* Initialise a response structure */ -void init_response(struct winbindd_response *response) +static void init_response(struct winbindd_response *response) { /* Initialise return value */ @@ -61,7 +61,7 @@ void init_response(struct winbindd_response *response) /* Close established socket */ -void close_sock(void) +void winbind_close_sock(void) { if (winbindd_fd != -1) { close(winbindd_fd); @@ -70,10 +70,6 @@ void close_sock(void) } #define CONNECT_TIMEOUT 30 -#if 0 /* unused */ -#define WRITE_TIMEOUT CONNECT_TIMEOUT -#define READ_TIMEOUT CONNECT_TIMEOUT -#endif /* Make sure socket handle isn't stdin, stdout or stderr */ #define RECURSION_LIMIT 3 @@ -172,7 +168,7 @@ static int winbind_named_pipe_sock(const char *dir) { struct sockaddr_un sunaddr; struct stat st; - char *path; + pstring path; int fd; int wait_time; int slept; @@ -189,8 +185,16 @@ static int winbind_named_pipe_sock(const char *dir) } /* Connect to socket */ - - asprintf(&path, "%s%s", dir, "/" WINBINDD_SOCKET_NAME); + + strncpy(path, dir, sizeof(path) - 1); + path[sizeof(path) - 1] = '\0'; + + strncat(path, "/", sizeof(path) - 1 - strlen(path)); + path[sizeof(path) - 1] = '\0'; + + strncat(path, WINBINDD_SOCKET_NAME, sizeof(path) - 1 - strlen(path)); + path[sizeof(path) - 1] = '\0'; + ZERO_STRUCT(sunaddr); sunaddr.sun_family = AF_UNIX; strncpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path) - 1); @@ -200,11 +204,8 @@ static int winbind_named_pipe_sock(const char *dir) the winbindd daemon is not running. */ if (lstat(path, &st) == -1) { - SAFE_FREE(path); return -1; } - - SAFE_FREE(path); /* Check permissions on unix socket file */ @@ -277,72 +278,80 @@ static int winbind_named_pipe_sock(const char *dir) close(fd); return -1; +} - if (connect(fd, (struct sockaddr *)&sunaddr, - sizeof(sunaddr)) == -1) { - close(fd); - return -1; +static const char *winbindd_socket_dir(void) +{ +#ifdef SOCKET_WRAPPER + const char *env_dir; + + env_dir = getenv(WINBINDD_SOCKET_DIR_ENVVAR); + if (env_dir) { + return env_dir; } - - return fd; +#endif + + return WINBINDD_SOCKET_DIR; } /* Connect to winbindd socket */ -int winbind_open_pipe_sock(void) +static int winbind_open_pipe_sock(int recursing, int need_priv) { #ifdef HAVE_UNIXSOCKET static pid_t our_pid; struct winbindd_request request; struct winbindd_response response; - const char *winbindd_socket_dir_env; ZERO_STRUCT(request); ZERO_STRUCT(response); if (our_pid != getpid()) { - close_sock(); + winbind_close_sock(); our_pid = getpid(); } + + if ((need_priv != 0) && (is_privileged == 0)) { + winbind_close_sock(); + } if (winbindd_fd != -1) { return winbindd_fd; } -#ifdef SOCKET_WRAPPER - winbindd_socket_dir_env = getenv(WINBINDD_SOCKET_DIR_ENV); - - if (!winbindd_socket_dir_env) - { - winbindd_socket_dir_env = WINBINDD_SOCKET_DIR; + if (recursing) { + return -1; } -#else - winbindd_socket_dir_env = WINBINDD_SOCKET_DIR; -#endif - - winbindd_fd = winbind_named_pipe_sock(winbindd_socket_dir_env); - if (winbindd_fd == -1) - { + if ((winbindd_fd = winbind_named_pipe_sock(winbindd_socket_dir())) == -1) { return -1; } + is_privileged = 0; + /* version-check the socket */ - if ((winbindd_request(WINBINDD_INTERFACE_VERSION, &request, &response) != NSS_STATUS_SUCCESS) || (response.data.interface_version != WINBIND_INTERFACE_VERSION)) { - close_sock(); + request.wb_flags = WBFLAG_RECURSE; + if ((winbindd_request_response(WINBINDD_INTERFACE_VERSION, &request, &response) != NSS_STATUS_SUCCESS) || (response.data.interface_version != WINBIND_INTERFACE_VERSION)) { + winbind_close_sock(); return -1; } /* try and get priv pipe */ - if (winbindd_request(WINBINDD_PRIV_PIPE_DIR, &request, &response) == NSS_STATUS_SUCCESS) { + request.wb_flags = WBFLAG_RECURSE; + if (winbindd_request_response(WINBINDD_PRIV_PIPE_DIR, &request, &response) == NSS_STATUS_SUCCESS) { int fd; - if ((fd = winbind_named_pipe_sock(response.extra_data.data)) != -1) { + if ((fd = winbind_named_pipe_sock((char *)response.extra_data.data)) != -1) { close(winbindd_fd); winbindd_fd = fd; + is_privileged = 1; } } + if ((need_priv != 0) && (is_privileged == 0)) { + return -1; + } + SAFE_FREE(response.extra_data.data); return winbindd_fd; @@ -353,7 +362,7 @@ int winbind_open_pipe_sock(void) /* Write data to winbindd socket */ -int write_sock(void *buffer, int count) +int winbind_write_sock(void *buffer, int count, int recursing, int need_priv) { int result, nwritten; @@ -361,7 +370,7 @@ int write_sock(void *buffer, int count) restart: - if (winbind_open_pipe_sock() == -1) { + if (winbind_open_pipe_sock(recursing, need_priv) == -1) { return -1; } @@ -381,7 +390,7 @@ int write_sock(void *buffer, int count) ZERO_STRUCT(tv); if (select(winbindd_fd + 1, &r_fds, NULL, NULL, &tv) == -1) { - close_sock(); + winbind_close_sock(); return -1; /* Select error */ } @@ -399,7 +408,7 @@ int write_sock(void *buffer, int count) /* Write failed */ - close_sock(); + winbind_close_sock(); return -1; } @@ -409,7 +418,7 @@ int write_sock(void *buffer, int count) /* Pipe has closed on remote end */ - close_sock(); + winbind_close_sock(); goto restart; } } @@ -419,11 +428,15 @@ int write_sock(void *buffer, int count) /* Read data from winbindd socket */ -static int read_sock(void *buffer, int count) +int winbind_read_sock(void *buffer, int count) { int nread = 0; int total_time = 0, selret; + if (winbindd_fd == -1) { + return -1; + } + /* Read data from socket */ while(nread < count) { struct timeval tv; @@ -439,7 +452,7 @@ static int read_sock(void *buffer, int count) tv.tv_sec = 5; if ((selret = select(winbindd_fd + 1, &r_fds, NULL, NULL, &tv)) == -1) { - close_sock(); + winbind_close_sock(); return -1; /* Select error */ } @@ -447,7 +460,7 @@ static int read_sock(void *buffer, int count) /* Not ready for read yet... */ if (total_time >= 30) { /* Timeout */ - close_sock(); + winbind_close_sock(); return -1; } total_time += 5; @@ -467,7 +480,7 @@ static int read_sock(void *buffer, int count) can do here is just return -1 and fail since the transaction has failed half way through. */ - close_sock(); + winbind_close_sock(); return -1; } @@ -481,7 +494,7 @@ static int read_sock(void *buffer, int count) /* Read reply */ -int read_reply(struct winbindd_response *response) +int winbindd_read_reply(struct winbindd_response *response) { int result1, result2 = 0; @@ -491,9 +504,9 @@ int read_reply(struct winbindd_response *response) /* Read fixed length response */ - if ((result1 = read_sock(response, sizeof(struct winbindd_response))) - == -1) { - + result1 = winbind_read_sock(response, + sizeof(struct winbindd_response)); + if (result1 == -1) { return -1; } @@ -515,9 +528,10 @@ int read_reply(struct winbindd_response *response) return -1; } - if ((result2 = read_sock(response->extra_data.data, extra_data_len)) - == -1) { - free_response(response); + result2 = winbind_read_sock(response->extra_data.data, + extra_data_len); + if (result2 == -1) { + winbindd_free_response(response); return -1; } } @@ -527,22 +541,31 @@ int read_reply(struct winbindd_response *response) return result1 + result2; } +bool winbind_env_set(void) +{ + char *env; + + if ((env=getenv(WINBINDD_DONT_ENV)) != NULL) { + if(strcmp(env, "1") == 0) { + return true; + } + } + return false; +} + /* * send simple types of requests */ -NSS_STATUS winbindd_send_request(int req_type, struct winbindd_request *request) +NSS_STATUS winbindd_send_request(int req_type, int need_priv, + struct winbindd_request *request) { struct winbindd_request lrequest; - char *env; - int value; - + /* Check for our tricky environment variable */ - if ( (env = getenv(WINBINDD_DONT_ENV)) != NULL ) { - value = atoi(env); - if ( value == 1 ) - return NSS_STATUS_NOTFOUND; + if (winbind_env_set()) { + return NSS_STATUS_NOTFOUND; } if (!request) { @@ -552,9 +575,19 @@ NSS_STATUS winbindd_send_request(int req_type, struct winbindd_request *request) /* Fill in request and send down pipe */ - init_request(request, req_type); + winbindd_init_request(request, req_type); - if (write_sock(request, sizeof(*request)) == -1) { + if (winbind_write_sock(request, sizeof(*request), + request->wb_flags & WBFLAG_RECURSE, + need_priv) == -1) { + return NSS_STATUS_UNAVAIL; + } + + if ((request->extra_len != 0) && + (winbind_write_sock(request->extra_data.data, + request->extra_len, + request->wb_flags & WBFLAG_RECURSE, + need_priv) == -1)) { return NSS_STATUS_UNAVAIL; } @@ -577,13 +610,13 @@ NSS_STATUS winbindd_get_response(struct winbindd_response *response) init_response(response); /* Wait for reply */ - if (read_reply(response) == -1) { + if (winbindd_read_reply(response) == -1) { return NSS_STATUS_UNAVAIL; } /* Throw away extra data if client didn't request it */ if (response == &lresponse) { - free_response(response); + winbindd_free_response(response); } /* Copy reply data from socket */ @@ -596,16 +629,40 @@ NSS_STATUS winbindd_get_response(struct winbindd_response *response) /* Handle simple types of requests */ -NSS_STATUS winbindd_request(int req_type, +NSS_STATUS winbindd_request_response(int req_type, struct winbindd_request *request, struct winbindd_response *response) { - NSS_STATUS status; + NSS_STATUS status = NSS_STATUS_UNAVAIL; + int count = 0; - status = winbindd_send_request(req_type, request); - if (status != NSS_STATUS_SUCCESS) - return(status); - return winbindd_get_response(response); + while ((status == NSS_STATUS_UNAVAIL) && (count < 10)) { + status = winbindd_send_request(req_type, 0, request); + if (status != NSS_STATUS_SUCCESS) + return(status); + status = winbindd_get_response(response); + count += 1; + } + + return status; +} + +NSS_STATUS winbindd_priv_request_response(int req_type, + struct winbindd_request *request, + struct winbindd_response *response) +{ + NSS_STATUS status = NSS_STATUS_UNAVAIL; + int count = 0; + + while ((status == NSS_STATUS_UNAVAIL) && (count < 10)) { + status = winbindd_send_request(req_type, 1, request); + if (status != NSS_STATUS_SUCCESS) + return(status); + status = winbindd_get_response(response); + count += 1; + } + + return status; } /************************************************************************* @@ -613,14 +670,35 @@ NSS_STATUS winbindd_request(int req_type, enable them ************************************************************************/ -bool winbind_off( void ) +bool winbind_off(void) { - setenv(WINBINDD_DONT_ENV, "1", 1); - return True; + return setenv(WINBINDD_DONT_ENV, "1", 1) != -1; } -bool winbind_on( void ) +bool winbind_on(void) { - setenv(WINBINDD_DONT_ENV, "0", 1); - return True; + return setenv(WINBINDD_DONT_ENV, "0", 1) != -1; +} + +/************************************************************************* + ************************************************************************/ + +const char *nss_err_str(NSS_STATUS ret) +{ + switch (ret) { + case NSS_STATUS_TRYAGAIN: + return "NSS_STATUS_TRYAGAIN"; + case NSS_STATUS_SUCCESS: + return "NSS_STATUS_SUCCESS"; + case NSS_STATUS_NOTFOUND: + return "NSS_STATUS_NOTFOUND"; + case NSS_STATUS_UNAVAIL: + return "NSS_STATUS_UNAVAIL"; +#ifdef NSS_STATUS_RETURN + case NSS_STATUS_RETURN: + return "NSS_STATUS_RETURN"; +#endif + default: + return "UNKNOWN RETURN CODE!!!!!!!"; + } } -- cgit