summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/nsswitch/winbind_nss.c310
1 files changed, 199 insertions, 111 deletions
diff --git a/source/nsswitch/winbind_nss.c b/source/nsswitch/winbind_nss.c
index 4495ae5df54..40c8eb9d889 100644
--- a/source/nsswitch/winbind_nss.c
+++ b/source/nsswitch/winbind_nss.c
@@ -1,6 +1,7 @@
/*
Unix SMB/Netbios implementation.
Version 2.0
+
Windows NT Domain nsswitch module
Copyright (C) Tim Potter 2000
@@ -21,69 +22,130 @@
*/
-#include <stdio.h>
-#include <sys/socket.h>
-#include <sys/un.h>
+#include "includes.h"
#include <nss.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include "includes.h"
+/*
+ * Utility and helper functions
+ */
+
+#ifdef strcpy
+#undef strcpy /* I think I know what I'm doing here (-: */
+#endif
/* Connect to winbindd socket */
-int connect_sock(void)
+static int open_root_pipe_sock(void)
{
- int sock, result;
+ static int established_socket = -1;
struct sockaddr_un sunaddr;
- fd_set writefd;
- struct timeval timeout;
+ static pid_t our_pid;
struct stat st;
+ fstring path;
+
+ if (our_pid != getpid()) {
+ if (established_socket != -1) close(established_socket);
+ established_socket = -1;
+ our_pid = getpid();
+ }
+
+ if (established_socket != -1) {
+ return established_socket;
+ }
/* Check permissions on unix socket file and directory */
- if (lstat(WINBINDD_SOCKET_DIR, &st) < 0) {
+ if (lstat(WINBINDD_SOCKET_DIR, &st) == -1) {
return -1;
}
- if (!S_ISDIR(st.st_mode) || (st.st_uid != 0) ||
- ((st.st_mode & 0777) != 0755)) {
+ if (!S_ISDIR(st.st_mode) || (st.st_uid != 0)) {
+ return -1;
+ }
+
+ /* Create socket */
+
+ if ((established_socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
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, WINBINDD_SOCKET_DIR "/" WINBINDD_SOCKET_NAME,
- sizeof(sunaddr.sun_path));
+ strncpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path) - 1);
- if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+ if (connect(established_socket, (struct sockaddr *)&sunaddr,
+ sizeof(sunaddr)) == -1) {
+ close(established_socket);
+ established_socket = -1;
return -1;
}
- /* Attempt to connect. Use select as the connect() call can block
- for a long time if the winbindd is suspended (e.g in gdb). */
+ return established_socket;
+}
- if (fcntl(sock, F_SETFL, O_NONBLOCK | fcntl(sock, F_GETFL)) < 0) {
- return -1;
- }
+/* Write data to winbindd socket with timeout */
- FD_ZERO(&writefd);
- FD_SET(sock, &writefd);
- timeout.tv_sec = WINBINDD_TIMEOUT_SEC;
- timeout.tv_usec = 0;
-
- if ((result = select(sock + 1, NULL, &writefd, NULL,
- &timeout)) <= 0) {
- return -1;
+int write_sock(int sock, void *buffer, int count)
+{
+ int result, nwritten;
+
+ /* Write data to socket */
+
+ nwritten = 0;
+
+ while(nwritten < count) {
+
+ result = write(sock, (char *)buffer + nwritten, count - nwritten);
+
+ if ((result == -1) || (result == 0)) {
+
+ /* Write failed */
+
+ return result;
+ }
+
+ nwritten += result;
}
+
+ return nwritten;
+}
- if (connect(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
- return -1;
+/* Read data from winbindd socket with timeout */
+
+int read_sock(int sock, void *buffer, int count)
+{
+ int result, nread;
+
+ /* Read data from socket */
+
+ nread = 0;
+
+ while(nread < count) {
+
+ result = read(sock, (char *)buffer + nread, count - nread);
+
+ if ((result == -1) || (result == 0)) {
+
+ /* Read failed */
+
+ return result;
+ }
+
+ nread += result;
}
- return sock;
+ return nread;
}
/* Allocate some space from the nss static buffer. The buffer and buflen
@@ -110,6 +172,56 @@ static char *get_static(char **buffer, int *buflen, int len)
return result;
}
+/* I've copied the strtok() replacement function next_token() from
+ lib/util_str.c as I really don't want to have to link in any other
+ objects if I can possibly avoid it. */
+
+#ifdef strchr /* Aargh! This points at multibyte_strchr(). )-: */
+#undef strchr
+#endif
+
+static char *last_ptr = NULL;
+
+BOOL next_token(char **ptr, char *buff, char *sep, size_t bufsize)
+{
+ char *s;
+ BOOL quoted;
+ size_t len=1;
+
+ if (!ptr) ptr = &last_ptr;
+ if (!ptr) return(False);
+
+ s = *ptr;
+
+ /* default to simple separators */
+ if (!sep) sep = " \t\n\r";
+
+ /* find the first non sep char */
+ while(*s && strchr(sep,*s)) s++;
+
+ /* nothing left? */
+ if (! *s) return(False);
+
+ /* copy over the token */
+ for (quoted = False;
+ len < bufsize && *s && (quoted || !strchr(sep,*s));
+ s++) {
+
+ if (*s == '\"') {
+ quoted = !quoted;
+ } else {
+ len++;
+ *buff++ = *s;
+ }
+ }
+
+ *ptr = (*s) ? s+1 : s;
+ *buff = 0;
+ last_ptr = *ptr;
+
+ return(True);
+}
+
/* Fill a pwent structure from a winbindd_response structure. We use
the static data passed to us by libc to put strings and stuff in.
Return errno = ERANGE and NSS_STATUS_TRYAGAIN if we run out of
@@ -132,7 +244,7 @@ static int fill_pwent(struct passwd *result,
return NSS_STATUS_TRYAGAIN;
}
- fstrcpy(result->pw_name, pw->pw_name);
+ strcpy(result->pw_name, pw->pw_name);
/* Password */
@@ -145,7 +257,7 @@ static int fill_pwent(struct passwd *result,
return NSS_STATUS_TRYAGAIN;
}
- fstrcpy(result->pw_passwd, pw->pw_passwd);
+ strcpy(result->pw_passwd, pw->pw_passwd);
/* [ug]id */
@@ -163,7 +275,7 @@ static int fill_pwent(struct passwd *result,
return NSS_STATUS_TRYAGAIN;
}
- fstrcpy(result->pw_gecos, pw->pw_gecos);
+ strcpy(result->pw_gecos, pw->pw_gecos);
/* Home directory */
@@ -176,7 +288,7 @@ static int fill_pwent(struct passwd *result,
return NSS_STATUS_TRYAGAIN;
}
- fstrcpy(result->pw_dir, pw->pw_dir);
+ strcpy(result->pw_dir, pw->pw_dir);
/* Logon shell */
@@ -189,7 +301,7 @@ static int fill_pwent(struct passwd *result,
return NSS_STATUS_TRYAGAIN;
}
- fstrcpy(result->pw_shell, pw->pw_shell);
+ strcpy(result->pw_shell, pw->pw_shell);
return NSS_STATUS_SUCCESS;
}
@@ -204,7 +316,8 @@ static int fill_grent(struct group *result,
char **buffer, int *buflen, int *errnop)
{
struct winbindd_gr *gr = &response->data.gr;
- char *name;
+ fstring name;
+ char *mem;
int i;
/* Group name */
@@ -218,7 +331,7 @@ static int fill_grent(struct group *result,
return NSS_STATUS_TRYAGAIN;
}
- fstrcpy(result->gr_name, gr->gr_name);
+ strcpy(result->gr_name, gr->gr_name);
/* Password */
@@ -231,7 +344,7 @@ static int fill_grent(struct group *result,
return NSS_STATUS_TRYAGAIN;
}
- fstrcpy(result->gr_passwd, gr->gr_passwd);
+ strcpy(result->gr_passwd, gr->gr_passwd);
/* gid */
@@ -266,20 +379,22 @@ static int fill_grent(struct group *result,
i = 0;
- for(name = strtok(gr->gr_mem, ","); name; name = strtok(NULL, ",")) {
+ mem = gr->gr_mem;
+ while(next_token(&mem, name, ",", sizeof(fstring))) {
+
/* Allocate space for member */
-
+
if (((result->gr_mem)[i] =
get_static(buffer, buflen, strlen(name) + 1)) == NULL) {
-
+
/* Out of memory */
-
+
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
-
- fstrcpy((result->gr_mem)[i], name);
+
+ strcpy((result->gr_mem)[i], name);
i++;
}
@@ -303,30 +418,26 @@ _nss_ntdom_setpwent(void)
struct winbindd_response response;
int sock, result;
- /* Connect to agent socket */
-
- if ((sock = connect_sock()) < 0) {
+ if ((sock = open_root_pipe_sock()) == -1) {
return NSS_STATUS_UNAVAIL;
}
/* Fill in request and send down pipe */
request.cmd = WINBINDD_SETPWENT;
- request.pid = getpid();
- if ((result = write_sock(sock, &request, sizeof(request))) < 0) {
+ if ((result = write_sock(sock, &request, sizeof(request))) == -1) {
+ close(sock);
return NSS_STATUS_UNAVAIL;
}
/* Wait for reply */
- if (read_sock(sock, &response, sizeof(response)) < 0) {
+ if (read_sock(sock, &response, sizeof(response)) == -1) {
close(sock);
return NSS_STATUS_UNAVAIL;
}
- close(sock);
-
/* Copy reply data from socket */
if (response.result != WINBINDD_OK) {
@@ -347,28 +458,25 @@ _nss_ntdom_endpwent(void)
/* Connect to agent socket */
- if ((sock = connect_sock()) < 0) {
+ if ((sock = open_root_pipe_sock()) == -1) {
return NSS_STATUS_UNAVAIL;
}
/* Fill in request and send down pipe */
request.cmd = WINBINDD_ENDPWENT;
- request.pid = getpid();
- if (write_sock(sock, &request, sizeof(request)) < 0) {
+ if (write_sock(sock, &request, sizeof(request)) == -1) {
return NSS_STATUS_UNAVAIL;
}
/* Wait for reply */
- if (read_sock(sock, &response, sizeof(response)) < 0) {
+ if (read_sock(sock, &response, sizeof(response)) == -1) {
close(sock);
return NSS_STATUS_UNAVAIL;
}
- close(sock);
-
/* Copy reply data from socket */
if (response.result != WINBINDD_OK) {
@@ -390,28 +498,26 @@ _nss_ntdom_getpwent_r(struct passwd *result, char *buffer,
/* Connect to agent socket */
- if ((sock = connect_sock()) < 0) {
+ if ((sock = open_root_pipe_sock()) == -1) {
return NSS_STATUS_UNAVAIL;
}
/* Fill in request and send down pipe */
request.cmd = WINBINDD_GETPWENT;
- request.pid = getpid();
- if (write_sock(sock, &request, sizeof(request)) < 0) {
+ if (write_sock(sock, &request, sizeof(request)) == -1) {
+ close(sock);
return NSS_STATUS_UNAVAIL;
}
/* Wait for reply */
- if (read_sock(sock, &response, sizeof(response)) < 0) {
+ if (read_sock(sock, &response, sizeof(response)) == -1) {
close(sock);
return NSS_STATUS_UNAVAIL;
}
- close(sock);
-
/* Copy reply data from socket */
if (response.result != WINBINDD_OK) {
@@ -434,29 +540,26 @@ _nss_ntdom_getpwuid_r(uid_t uid, struct passwd *result, char *buffer,
/* Connect to agent socket */
- if ((sock = connect_sock()) < 0) {
+ if ((sock = open_root_pipe_sock()) == -1) {
return NSS_STATUS_UNAVAIL;
}
/* Fill in request and send down pipe */
request.cmd = WINBINDD_GETPWNAM_FROM_UID;
- request.pid = getpid();
request.data.uid = uid;
- if (write_sock(sock, &request, sizeof(request)) < 0) {
+ if (write_sock(sock, &request, sizeof(request)) == -1) {
return NSS_STATUS_UNAVAIL;
}
/* Wait for reply */
- if (read_sock(sock, &response, sizeof(response)) < 0) {
+ if (read_sock(sock, &response, sizeof(response)) == -1) {
close(sock);
return NSS_STATUS_UNAVAIL;
}
- close(sock);
-
/* Copy reply data from socket */
if (response.result != WINBINDD_OK) {
@@ -481,28 +584,27 @@ _nss_ntdom_getpwnam_r(const char *name, struct passwd *result, char *buffer,
/* Connect to agent socket */
- if ((sock = connect_sock()) < 0) {
+ if ((sock = open_root_pipe_sock()) == -1) {
return NSS_STATUS_UNAVAIL;
}
/* Fill in request and send down pipe */
request.cmd = WINBINDD_GETPWNAM_FROM_USER;
- request.pid = getpid();
- fstrcpy(request.data.username, name);
- if (write_sock(sock, &request, sizeof(request)) < 0) {
+ strncpy(request.data.username, name, sizeof(request.data.username) - 1);
+ request.data.username[sizeof(request.data.username) - 1] = '\0';
+
+ if (write_sock(sock, &request, sizeof(request)) == -1) {
return NSS_STATUS_UNAVAIL;
}
/* Wait for reply */
- if (read_sock(sock, &response, sizeof(response)) < 0) {
+ if (read_sock(sock, &response, sizeof(response)) == -1) {
return NSS_STATUS_UNAVAIL;
}
- close(sock);
-
/* Copy reply data from socket */
if (response.result != WINBINDD_OK) {
@@ -529,28 +631,25 @@ _nss_ntdom_setgrent(void)
/* Connect to agent socket */
- if ((sock = connect_sock()) < 0) {
+ if ((sock = open_root_pipe_sock()) == -1) {
return NSS_STATUS_UNAVAIL;
}
/* Fill in request and send down pipe */
request.cmd = WINBINDD_SETGRENT;
- request.pid = getpid();
- if ((result = write_sock(sock, &request, sizeof(request))) < 0) {
+ if ((result = write_sock(sock, &request, sizeof(request))) == -1) {
return NSS_STATUS_UNAVAIL;
}
/* Wait for reply */
- if (read_sock(sock, &response, sizeof(response)) < 0) {
+ if (read_sock(sock, &response, sizeof(response)) == -1) {
close(sock);
return NSS_STATUS_UNAVAIL;
}
- close(sock);
-
/* Copy reply data from socket */
if (response.result != WINBINDD_OK) {
@@ -571,28 +670,25 @@ _nss_ntdom_endgrent(void)
/* Connect to agent socket */
- if ((sock = connect_sock()) < 0) {
+ if ((sock = open_root_pipe_sock()) == -1) {
return NSS_STATUS_UNAVAIL;
}
/* Fill in request and send down pipe */
request.cmd = WINBINDD_ENDGRENT;
- request.pid = getpid();
- if (write_sock(sock, &request, sizeof(request)) < 0) {
+ if (write_sock(sock, &request, sizeof(request)) == -1) {
return NSS_STATUS_UNAVAIL;
}
/* Wait for reply */
- if (read_sock(sock, &response, sizeof(response)) < 0) {
+ if (read_sock(sock, &response, sizeof(response)) == -1) {
close(sock);
return NSS_STATUS_UNAVAIL;
}
- close(sock);
-
/* Copy reply data from socket */
if (response.result != WINBINDD_OK) {
@@ -614,28 +710,25 @@ _nss_ntdom_getgrent_r(struct group *result,
/* Connect to agent socket */
- if ((sock = connect_sock()) < 0) {
+ if ((sock = open_root_pipe_sock()) == -1) {
return NSS_STATUS_UNAVAIL;
}
/* Fill in request and send down pipe */
request.cmd = WINBINDD_GETGRENT;
- request.pid = getpid();
- if (write_sock(sock, &request, sizeof(request)) < 0) {
+ if (write_sock(sock, &request, sizeof(request)) == -1) {
return NSS_STATUS_UNAVAIL;
}
/* Wait for reply */
- if (read_sock(sock, &response, sizeof(response)) < 0) {
+ if (read_sock(sock, &response, sizeof(response)) == -1) {
close(sock);
return NSS_STATUS_UNAVAIL;
}
- close(sock);
-
/* Copy reply data from socket */
if (response.result == WINBINDD_OK) {
@@ -658,30 +751,28 @@ _nss_ntdom_getgrnam_r(const char *name,
/* Connect to agent socket */
- if ((sock = connect_sock()) < 0) {
+ if ((sock = open_root_pipe_sock()) == -1) {
return NSS_STATUS_UNAVAIL;
}
/* Fill in request and send down pipe */
request.cmd = WINBINDD_GETGRNAM_FROM_GROUP;
- request.pid = getpid();
- fstrcpy(request.data.groupname, name);
+ strncpy(request.data.groupname, name, sizeof(request.data.groupname));
+ request.data.groupname[sizeof(request.data.groupname) - 1] = '\0';
- if (write_sock(sock, &request, sizeof(request)) < 0) {
+ if (write_sock(sock, &request, sizeof(request)) == -1) {
return NSS_STATUS_UNAVAIL;
}
/* Wait for reply */
- if (read_sock(sock, &response, sizeof(response)) < 0) {
+ if (read_sock(sock, &response, sizeof(response)) == -1) {
close(sock);
return NSS_STATUS_UNAVAIL;
}
- close(sock);
-
/* Copy reply data from socket */
if (response.result != WINBINDD_OK) {
@@ -704,29 +795,26 @@ _nss_ntdom_getgrgid_r(gid_t gid,
/* Connect to agent socket */
- if ((sock = connect_sock()) < 0) {
+ if ((sock = open_root_pipe_sock()) == -1) {
return NSS_STATUS_UNAVAIL;
}
/* Fill in request and send down pipe */
request.cmd = WINBINDD_GETGRNAM_FROM_GID;
- request.pid = getpid();
request.data.gid = gid;
- if (write_sock(sock, &request, sizeof(request)) < 0) {
+ if (write_sock(sock, &request, sizeof(request)) == -1) {
return NSS_STATUS_UNAVAIL;
}
/* Wait for reply */
- if (read_sock(sock, &response, sizeof(response)) < 0) {
+ if (read_sock(sock, &response, sizeof(response)) == -1) {
close(sock);
return NSS_STATUS_UNAVAIL;
}
- close(sock);
-
/* Copy reply data from socket */
if (response.result != WINBINDD_OK) {