summaryrefslogtreecommitdiff
path: root/source3/nsswitch
diff options
context:
space:
mode:
Diffstat (limited to 'source3/nsswitch')
-rw-r--r--source3/nsswitch/wb_common.c73
-rw-r--r--source3/nsswitch/winbindd.c30
-rw-r--r--source3/nsswitch/winbindd.h2
-rw-r--r--source3/nsswitch/winbindd_misc.c17
-rw-r--r--source3/nsswitch/winbindd_nss.h5
-rw-r--r--source3/nsswitch/winbindd_pam.c13
-rw-r--r--source3/nsswitch/winbindd_util.c24
7 files changed, 131 insertions, 33 deletions
diff --git a/source3/nsswitch/wb_common.c b/source3/nsswitch/wb_common.c
index 89c751a4ef..ac1ccb217e 100644
--- a/source3/nsswitch/wb_common.c
+++ b/source3/nsswitch/wb_common.c
@@ -131,27 +131,16 @@ static int make_safe_fd(int fd)
/* Connect to winbindd socket */
-int winbind_open_pipe_sock(void)
+static int winbind_named_pipe_sock(const char *dir)
{
-#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) {
+ if (lstat(dir, &st) == -1) {
return -1;
}
@@ -162,13 +151,13 @@ int winbind_open_pipe_sock(void)
/* Connect to socket */
- strncpy(path, WINBINDD_SOCKET_DIR, sizeof(path) - 1);
+ strncpy(path, dir, sizeof(path) - 1);
path[sizeof(path) - 1] = '\0';
- strncat(path, "/", sizeof(path) - 1);
+ strncat(path, "/", sizeof(path) - 1 - strlen(path));
path[sizeof(path) - 1] = '\0';
- strncat(path, WINBINDD_SOCKET_NAME, sizeof(path) - 1);
+ strncat(path, WINBINDD_SOCKET_NAME, sizeof(path) - 1 - strlen(path));
path[sizeof(path) - 1] = '\0';
ZERO_STRUCT(sunaddr);
@@ -196,16 +185,60 @@ int winbind_open_pipe_sock(void)
return -1;
}
- if ((winbindd_fd = make_safe_fd( fd)) == -1) {
- return winbindd_fd;
+ if ((fd = make_safe_fd( fd)) == -1) {
+ return fd;
}
- if (connect(winbindd_fd, (struct sockaddr *)&sunaddr,
+ if (connect(fd, (struct sockaddr *)&sunaddr,
sizeof(sunaddr)) == -1) {
- close_sock();
+ 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;
+ }
+ }
+
return winbindd_fd;
#else
return -1;
diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c
index 35fef6e361..3b91f2d6af 100644
--- a/source3/nsswitch/winbindd.c
+++ b/source3/nsswitch/winbindd.c
@@ -265,6 +265,7 @@ static struct dispatch_table dispatch_table[] = {
{ WINBINDD_INTERFACE_VERSION, winbindd_interface_version, "INTERFACE_VERSION" },
{ WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" },
{ WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" },
+ { WINBINDD_PRIV_PIPE_DIR, winbindd_priv_pipe_dir, "WINBINDD_PRIV_PIPE_DIR" },
/* WINS functions */
@@ -311,7 +312,7 @@ static void process_request(struct winbindd_cli_state *state)
/* Process a new connection by adding it to the client connection list */
-static void new_connection(int listen_sock)
+static void new_connection(int listen_sock, BOOL privilaged)
{
struct sockaddr_un sunaddr;
struct winbindd_cli_state *state;
@@ -342,6 +343,8 @@ static void new_connection(int listen_sock)
state->last_access = time(NULL);
+ state->privilaged = privilaged;
+
/* Add to connection list */
winbindd_add_client(state);
@@ -553,7 +556,7 @@ static void process_loop(void)
while (1) {
struct winbindd_cli_state *state;
fd_set r_fds, w_fds;
- int maxfd, listen_sock, selret;
+ int maxfd, listen_sock, listen_priv_sock, selret;
struct timeval timeout;
/* Handle messages */
@@ -572,17 +575,19 @@ static void process_loop(void)
/* Initialise fd lists for select() */
listen_sock = open_winbindd_socket();
+ listen_priv_sock = open_winbindd_priv_socket();
- if (listen_sock == -1) {
+ if (listen_sock == -1 || listen_priv_sock == -1) {
perror("open_winbind_socket");
exit(1);
}
- maxfd = listen_sock;
+ maxfd = MAX(listen_sock, listen_priv_sock);
FD_ZERO(&r_fds);
FD_ZERO(&w_fds);
FD_SET(listen_sock, &r_fds);
+ FD_SET(listen_priv_sock, &r_fds);
timeout.tv_sec = WINBINDD_ESTABLISH_LOOP;
timeout.tv_usec = 0;
@@ -659,7 +664,22 @@ static void process_loop(void)
break;
}
}
- new_connection(listen_sock);
+ /* new, non-privilaged connection */
+ new_connection(listen_sock, False);
+ }
+
+ if (FD_ISSET(listen_priv_sock, &r_fds)) {
+ while (winbindd_num_clients() > WINBINDD_MAX_SIMULTANEOUS_CLIENTS - 1) {
+ DEBUG(5,("winbindd: Exceeding %d client connections, removing idle connection.\n",
+ WINBINDD_MAX_SIMULTANEOUS_CLIENTS));
+ if (!remove_idle_client()) {
+ DEBUG(0,("winbindd: Exceeding %d client connections, no idle connection found\n",
+ WINBINDD_MAX_SIMULTANEOUS_CLIENTS));
+ break;
+ }
+ }
+ /* new, privilaged connection */
+ new_connection(listen_priv_sock, True);
}
/* Process activity on client connections */
diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h
index cc7cdc5297..f6b0e73543 100644
--- a/source3/nsswitch/winbindd.h
+++ b/source3/nsswitch/winbindd.h
@@ -42,6 +42,8 @@ struct winbindd_cli_state {
BOOL finished; /* Can delete from list */
BOOL write_extra_data; /* Write extra_data field */
time_t last_access; /* Time of last access (read or write) */
+ BOOL privilaged; /* Is the client 'privilaged' */
+
struct winbindd_request request; /* Request from client */
struct winbindd_response response; /* Respose to client */
struct getent_state *getpwent_state; /* State for getpwent() */
diff --git a/source3/nsswitch/winbindd_misc.c b/source3/nsswitch/winbindd_misc.c
index 0b283812b2..3b44d029c0 100644
--- a/source3/nsswitch/winbindd_misc.c
+++ b/source3/nsswitch/winbindd_misc.c
@@ -233,3 +233,20 @@ enum winbindd_result winbindd_netbios_name(struct winbindd_cli_state *state)
return WINBINDD_OK;
}
+
+/* What's my name again? */
+
+enum winbindd_result winbindd_priv_pipe_dir(struct winbindd_cli_state *state)
+{
+
+ DEBUG(3, ("[%5d]: request location of privilaged pipe\n", state->pid));
+
+ state->response.extra_data = strdup(get_winbind_priv_pipe_dir());
+ if (!state->response.extra_data)
+ return WINBINDD_ERROR;
+
+ /* must add one to length to copy the 0 for string termination */
+ state->response.length += strlen((char *)state->response.extra_data) + 1;
+
+ return WINBINDD_OK;
+}
diff --git a/source3/nsswitch/winbindd_nss.h b/source3/nsswitch/winbindd_nss.h
index 2c87a77100..88f4a11f87 100644
--- a/source3/nsswitch/winbindd_nss.h
+++ b/source3/nsswitch/winbindd_nss.h
@@ -30,7 +30,7 @@
#define WINBINDD_SOCKET_NAME "pipe" /* Name of PF_UNIX socket */
#define WINBINDD_SOCKET_DIR "/tmp/.winbindd" /* Name of PF_UNIX dir */
-
+#define WINBINDD_PRIV_SOCKET_SUBDIR "winbindd_privilaged" /* name of subdirectory of lp_lockdir() to hold the 'privilaged' pipe */
#define WINBINDD_DOMAIN_ENV "WINBINDD_DOMAIN" /* Environment variables */
#define WINBINDD_DONT_ENV "_NO_WINBINDD"
@@ -105,6 +105,9 @@ enum winbindd_cmd {
WINBINDD_NETBIOS_NAME, /* The netbios name of the server */
/* Placeholder for end of cmd list */
+ /* find the location of our privilaged pipe */
+ WINBINDD_PRIV_PIPE_DIR,
+
WINBINDD_NUM_CMDS
};
diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c
index e24afbabd6..d408a8b3ae 100644
--- a/source3/nsswitch/winbindd_pam.c
+++ b/source3/nsswitch/winbindd_pam.c
@@ -174,6 +174,12 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
DATA_BLOB lm_resp, nt_resp;
+ if (!state->privilaged) {
+ DEBUG(2, ("winbindd_pam_auth_crap: non-privilaged access denied!\n"));
+ result = NT_STATUS_ACCESS_DENIED;
+ goto done;
+ }
+
/* Ensure null termination */
state->request.data.auth_crap.user[sizeof(state->request.data.auth_crap.user)-1]='\0';
@@ -272,19 +278,12 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
result = append_info3_as_ndr(mem_ctx, state, &info3);
}
-#if 0
- /* we don't currently do this stuff right */
- /* Doing an assert in a daemon is going to be a pretty bad
- idea. - tpot */
if (state->request.data.auth_crap.flags & WINBIND_PAM_NTKEY) {
- SMB_ASSERT(sizeof(state->response.data.auth.nt_session_key) == sizeof(info3.user_sess_key));
memcpy(state->response.data.auth.nt_session_key, info3.user_sess_key, sizeof(state->response.data.auth.nt_session_key) /* 16 */);
}
if (state->request.data.auth_crap.flags & WINBIND_PAM_LMKEY) {
- SMB_ASSERT(sizeof(state->response.data.auth.nt_session_key) <= sizeof(info3.user_sess_key));
memcpy(state->response.data.auth.first_8_lm_hash, info3.padding, sizeof(state->response.data.auth.nt_session_key) /* 16 */);
}
-#endif
}
done:
diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c
index 99b94eac47..262d862b8a 100644
--- a/source3/nsswitch/winbindd_util.c
+++ b/source3/nsswitch/winbindd_util.c
@@ -444,9 +444,15 @@ void fill_domain_username(fstring name, const char *domain, const char *user)
* Winbindd socket accessor functions
*/
+char *get_winbind_priv_pipe_dir(void)
+{
+ return lock_path(WINBINDD_PRIV_SOCKET_SUBDIR);
+}
+
/* Open the winbindd socket */
static int _winbindd_socket = -1;
+static int _winbindd_priv_socket = -1;
int open_winbindd_socket(void)
{
@@ -460,6 +466,18 @@ int open_winbindd_socket(void)
return _winbindd_socket;
}
+int open_winbindd_priv_socket(void)
+{
+ if (_winbindd_priv_socket == -1) {
+ _winbindd_priv_socket = create_pipe_sock(
+ get_winbind_priv_pipe_dir(), WINBINDD_SOCKET_NAME, 0750);
+ DEBUG(10, ("open_winbindd_priv_socket: opened socket fd %d\n",
+ _winbindd_priv_socket));
+ }
+
+ return _winbindd_priv_socket;
+}
+
/* Close the winbindd socket */
void close_winbindd_socket(void)
@@ -470,6 +488,12 @@ void close_winbindd_socket(void)
close(_winbindd_socket);
_winbindd_socket = -1;
}
+ if (_winbindd_priv_socket != -1) {
+ DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n",
+ _winbindd_priv_socket));
+ close(_winbindd_priv_socket);
+ _winbindd_priv_socket = -1;
+ }
}
/*