summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVolker Lendecke <vlendec@samba.org>2007-03-19 21:04:56 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:18:42 -0500
commit3fdef9433a9e08064b32e34a16ce62a60ce144fb (patch)
treec035739e6b8a7c4b57d937fe25961b9e469b4b60
parent7c09cfd0806d24e89f4dc9714a9efe09758e6f12 (diff)
downloadsamba-3fdef9433a9e08064b32e34a16ce62a60ce144fb.tar.gz
samba-3fdef9433a9e08064b32e34a16ce62a60ce144fb.tar.xz
samba-3fdef9433a9e08064b32e34a16ce62a60ce144fb.zip
r21878: Fix a bug with smbd serving a windows terminal server: If winbind decides smbd
to be idle it might happen that smbd needs to do a winbind operation (for example sid2name) as non-root. This then fails to get the privileged pipe. When later on on the same connection another authentication request comes in, we try to do the CRAP auth via the non-privileged pipe. This adds a winbindd_priv_request_response() request that kills the existing winbind pipe connection if it's not privileged. Volker (This used to be commit e5741e27c4c22702c9f8b07877641fecc7eef39c)
-rw-r--r--source3/auth/auth_winbind.c3
-rw-r--r--source3/nsswitch/pam_winbind.c2
-rw-r--r--source3/nsswitch/wb_common.c47
-rw-r--r--source3/nsswitch/winbind_client.h7
-rw-r--r--source3/nsswitch/winbind_nss_irix.c2
5 files changed, 49 insertions, 12 deletions
diff --git a/source3/auth/auth_winbind.c b/source3/auth/auth_winbind.c
index fa56757950d..f06f83f4065 100644
--- a/source3/auth/auth_winbind.c
+++ b/source3/auth/auth_winbind.c
@@ -108,7 +108,8 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
/* we are contacting the privileged pipe */
become_root();
- result = winbindd_request_response(WINBINDD_PAM_AUTH_CRAP, &request, &response);
+ result = winbindd_priv_request_response(WINBINDD_PAM_AUTH_CRAP,
+ &request, &response);
unbecome_root();
if ( result == NSS_STATUS_UNAVAIL ) {
diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c
index e16f44dff50..66f9a093144 100644
--- a/source3/nsswitch/pam_winbind.c
+++ b/source3/nsswitch/pam_winbind.c
@@ -436,7 +436,7 @@ static int pam_winbind_request(pam_handle_t * pamh, int ctrl,
/* Fill in request and send down pipe */
init_request(request, req_type);
- if (write_sock(request, sizeof(*request), 0) == -1) {
+ if (write_sock(request, sizeof(*request), 0, 1) == -1) {
_pam_log(pamh, ctrl, LOG_ERR, "pam_winbind_request: write to socket failed!");
close_sock();
return PAM_SERVICE_ERR;
diff --git a/source3/nsswitch/wb_common.c b/source3/nsswitch/wb_common.c
index 05d2a660e73..fb84373aa63 100644
--- a/source3/nsswitch/wb_common.c
+++ b/source3/nsswitch/wb_common.c
@@ -33,6 +33,7 @@ BOOL winbind_on( void );
/* 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 */
@@ -287,7 +288,7 @@ static int winbind_named_pipe_sock(const char *dir)
/* Connect to winbindd socket */
-static int winbind_open_pipe_sock(int recursing)
+static int winbind_open_pipe_sock(int recursing, int need_priv)
{
#ifdef HAVE_UNIXSOCKET
static pid_t our_pid;
@@ -300,6 +301,10 @@ static int winbind_open_pipe_sock(int recursing)
close_sock();
our_pid = getpid();
}
+
+ if ((need_priv != 0) && (is_privileged == 0)) {
+ close_sock();
+ }
if (winbindd_fd != -1) {
return winbindd_fd;
@@ -313,6 +318,8 @@ static int winbind_open_pipe_sock(int recursing)
return -1;
}
+ is_privileged = 0;
+
/* version-check the socket */
request.flags = WBFLAG_RECURSE;
@@ -329,9 +336,14 @@ static int winbind_open_pipe_sock(int recursing)
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;
@@ -342,7 +354,7 @@ static int winbind_open_pipe_sock(int recursing)
/* Write data to winbindd socket */
-int write_sock(void *buffer, int count, int recursing)
+int write_sock(void *buffer, int count, int recursing, int need_priv)
{
int result, nwritten;
@@ -350,7 +362,7 @@ int write_sock(void *buffer, int count, int recursing)
restart:
- if (winbind_open_pipe_sock(recursing) == -1) {
+ if (winbind_open_pipe_sock(recursing, need_priv) == -1) {
return -1;
}
@@ -536,7 +548,8 @@ BOOL winbind_env_set( void )
* 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;
@@ -555,12 +568,14 @@ NSS_STATUS winbindd_send_request(int req_type, struct winbindd_request *request)
init_request(request, req_type);
- if (write_sock(request, sizeof(*request), request->flags & WBFLAG_RECURSE) == -1) {
+ if (write_sock(request, sizeof(*request),
+ request->flags & WBFLAG_RECURSE, need_priv) == -1) {
return NSS_STATUS_UNAVAIL;
}
if ((request->extra_len != 0) &&
- (write_sock(request->extra_data.data, request->extra_len, request->flags & WBFLAG_RECURSE) == -1)) {
+ (write_sock(request->extra_data.data, request->extra_len,
+ request->flags & WBFLAG_RECURSE, need_priv) == -1)) {
return NSS_STATUS_UNAVAIL;
}
@@ -610,7 +625,25 @@ NSS_STATUS winbindd_request_response(int req_type,
int count = 0;
while ((status == NSS_STATUS_UNAVAIL) && (count < 10)) {
- status = winbindd_send_request(req_type, request);
+ 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);
diff --git a/source3/nsswitch/winbind_client.h b/source3/nsswitch/winbind_client.h
index 1d3d379af00..d80aff37fa1 100644
--- a/source3/nsswitch/winbind_client.h
+++ b/source3/nsswitch/winbind_client.h
@@ -2,13 +2,16 @@
#include "winbindd_nss.h"
void init_request(struct winbindd_request *req,int rq_type);
-NSS_STATUS winbindd_send_request(int req_type,
+NSS_STATUS winbindd_send_request(int req_type, int need_priv,
struct winbindd_request *request);
NSS_STATUS winbindd_get_response(struct winbindd_response *response);
NSS_STATUS winbindd_request_response(int req_type,
struct winbindd_request *request,
struct winbindd_response *response);
-int write_sock(void *buffer, int count, int recursing);
+NSS_STATUS winbindd_priv_request_response(int req_type,
+ struct winbindd_request *request,
+ struct winbindd_response *response);
+int write_sock(void *buffer, int count, int recursing, int need_priv);
int read_reply(struct winbindd_response *response);
void close_sock(void);
void free_response(struct winbindd_response *response);
diff --git a/source3/nsswitch/winbind_nss_irix.c b/source3/nsswitch/winbind_nss_irix.c
index 2fbf3e0df82..5c6679f0442 100644
--- a/source3/nsswitch/winbind_nss_irix.c
+++ b/source3/nsswitch/winbind_nss_irix.c
@@ -454,7 +454,7 @@ send_next_request(nsd_file_t *rq, struct winbindd_request *request)
nsd_logprintf(NSD_LOG_MIN,
"send_next_request (winbind) %d, timeout = %d sec\n",
rq->f_cmd_data, timeout);
- status = winbindd_send_request((int)rq->f_cmd_data,request);
+ status = winbindd_send_request((int)rq->f_cmd_data,request,0);
SAFE_FREE(request);
if (status != NSS_STATUS_SUCCESS) {