diff options
Diffstat (limited to 'source3/nsswitch')
-rw-r--r-- | source3/nsswitch/wb_common.c | 73 | ||||
-rw-r--r-- | source3/nsswitch/winbindd.c | 30 | ||||
-rw-r--r-- | source3/nsswitch/winbindd.h | 2 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_misc.c | 17 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_nss.h | 5 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_pam.c | 13 | ||||
-rw-r--r-- | source3/nsswitch/winbindd_util.c | 24 |
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; + } } /* |