summaryrefslogtreecommitdiff
path: root/source3/nsswitch
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2003-03-24 09:54:13 +0000
committerAndrew Bartlett <abartlet@samba.org>2003-03-24 09:54:13 +0000
commit53beee9e5675a59c67d9ecfbaec50dca4ac01750 (patch)
treeb4ca6d9d3055c941bab8da23d70abf3e9eae4260 /source3/nsswitch
parent7d4bfa0eda4f79f55950d4089e636eecc37975f6 (diff)
downloadsamba-53beee9e5675a59c67d9ecfbaec50dca4ac01750.tar.gz
samba-53beee9e5675a59c67d9ecfbaec50dca4ac01750.tar.bz2
samba-53beee9e5675a59c67d9ecfbaec50dca4ac01750.zip
(merge from HEAD)
NTLM Authentication: - Add a 'privileged' mode to Winbindd. This is achieved by means of a directory under lockdir, that the admin can change the group access for. - This mode is now required to access with 'CRAP' authentication feature. - This *will* break the current SQUID helper, so I've fixed up our ntlm_auth replacement: - Update our NTLMSSP code to cope with 'datagram' mode, where we don't get a challenge. - Use this to make our ntlm_auth utility suitable for use in current Squid 2.5 servers. - Tested - works for Win2k clients, but not Win9X at present. NTLMSSP updates are needed. - Now uses fgets(), not x_fgets() to cope with Squid environment (I think somthing to do with non-blocking stdin). - Add much more robust connection code to wb_common.c - it will not connect to a server of a different protocol version, and it will automatically try and reconnect to the 'privileged' pipe if possible. - This could help with 'privileged' idmap operations etc in future. - Add a generic HEX encode routine to util_str.c, - fix a small line of dodgy C in StrnCpy_fn() - Correctly pull our 'session key' out of the info3 from th the DC. This is used in both the auth code, and in for export over the winbind pipe to ntlm_auth. - Given the user's challenge/response and access to the privileged pipe, allow external access to the 'session key'. To be used for MSCHAPv2 integration. Andrew Bartlett (This used to be commit ec071ca3dcbd3881dc08e6a8d7ac2ff0bcd57664)
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;
+ }
}
/*