mirror of
https://github.com/samba-team/samba.git
synced 2025-12-23 00:23:53 +03:00
Winbind client-side cleanups.
The global winbind file descriptor can cause havoc in some situations - particulary when it becomes 0, 1 or 2. This patch (based on some very nice work by Hannes Schmidt <mail@schmidt-net.via.t-online.de>) starts to recitfy the problem by ensuring that the close-on-exec flag is set, and that we move above 3 in the file descriptor table. I've also decided that the PAM module can close it's pipe handle on every request - this isn't performance-critical code. The next step is to do the same for nss_winbind. (But things like getent() might get in our way there). This also cleans up some function prototypes, puts them in just one place. Andrew Bartlett
This commit is contained in:
@@ -762,6 +762,8 @@ extern int errno;
|
||||
|
||||
#include "mangle.h"
|
||||
|
||||
#include "nsswitch/winbind_client.h"
|
||||
|
||||
/*
|
||||
* Type for wide character dirent structure.
|
||||
* Only d_name is defined by POSIX.
|
||||
|
||||
@@ -1623,8 +1623,6 @@ struct unix_error_map {
|
||||
|
||||
#define SAFE_NETBIOS_CHARS ". -_"
|
||||
|
||||
#include "nsswitch/winbindd_nss.h"
|
||||
|
||||
/* generic iconv conversion structure */
|
||||
typedef struct {
|
||||
size_t (*direct)(void *cd, char **inbuf, size_t *inbytesleft,
|
||||
|
||||
@@ -11,11 +11,6 @@
|
||||
|
||||
#include "pam_winbind.h"
|
||||
|
||||
/* prototypes from common.c */
|
||||
void init_request(struct winbindd_request *req,int rq_type);
|
||||
int write_sock(void *buffer, int count);
|
||||
int read_reply(struct winbindd_response *response);
|
||||
|
||||
/* data tokens */
|
||||
|
||||
#define MAX_PASSWD_TRIES 3
|
||||
@@ -99,24 +94,30 @@ static int _make_remark(pam_handle_t * pamh, int type, const char *text)
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int winbind_request(enum winbindd_cmd req_type,
|
||||
static int pam_winbind_request(enum winbindd_cmd req_type,
|
||||
struct winbindd_request *request,
|
||||
struct winbindd_response *response)
|
||||
{
|
||||
|
||||
/* Fill in request and send down pipe */
|
||||
init_request(request, req_type);
|
||||
|
||||
if (write_sock(request, sizeof(*request)) == -1) {
|
||||
_pam_log(LOG_ERR, "write to socket failed!");
|
||||
close_sock();
|
||||
return PAM_SERVICE_ERR;
|
||||
}
|
||||
|
||||
/* Wait for reply */
|
||||
if (read_reply(response) == -1) {
|
||||
_pam_log(LOG_ERR, "read from socket failed!");
|
||||
close_sock();
|
||||
return PAM_SERVICE_ERR;
|
||||
}
|
||||
|
||||
/* We are done with the socket - close it and avoid mischeif */
|
||||
close_sock();
|
||||
|
||||
/* Copy reply data from socket */
|
||||
if (response->result != WINBINDD_OK) {
|
||||
if (response->data.auth.pam_error != PAM_SUCCESS) {
|
||||
@@ -148,7 +149,7 @@ static int winbind_auth_request(const char *user, const char *pass, int ctrl)
|
||||
strncpy(request.data.auth.pass, pass,
|
||||
sizeof(request.data.auth.pass)-1);
|
||||
|
||||
retval = winbind_request(WINBINDD_PAM_AUTH, &request, &response);
|
||||
retval = pam_winbind_request(WINBINDD_PAM_AUTH, &request, &response);
|
||||
|
||||
switch (retval) {
|
||||
case PAM_AUTH_ERR:
|
||||
@@ -217,7 +218,7 @@ static int winbind_chauthtok_request(const char *user, const char *oldpass,
|
||||
request.data.chauthtok.newpass[0] = '\0';
|
||||
}
|
||||
|
||||
return winbind_request(WINBINDD_PAM_CHAUTHTOK, &request, &response);
|
||||
return pam_winbind_request(WINBINDD_PAM_CHAUTHTOK, &request, &response);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -90,5 +90,4 @@ do { \
|
||||
#define on(x, y) (x & y)
|
||||
#define off(x, y) (!(x & y))
|
||||
|
||||
#include "winbind_nss_config.h"
|
||||
#include "winbindd_nss.h"
|
||||
#include "winbind_client.h"
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
Copyright (C) Tim Potter 2000
|
||||
Copyright (C) Andrew Tridgell 2000
|
||||
Copyright (C) Andrew Bartlett 2002
|
||||
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
@@ -75,7 +77,7 @@ void init_response(struct winbindd_response *response)
|
||||
|
||||
/* Close established socket */
|
||||
|
||||
static void close_sock(void)
|
||||
void close_sock(void)
|
||||
{
|
||||
if (winbindd_fd != -1) {
|
||||
close(winbindd_fd);
|
||||
@@ -83,6 +85,64 @@ static void close_sock(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure socket handle isn't stdin, stdout or stderr */
|
||||
#define RECURSION_LIMIT 3
|
||||
|
||||
static int make_nonstd_fd_internals(int fd, int limit /* Recursion limiter */)
|
||||
{
|
||||
int new_fd;
|
||||
if (fd >= 0 && fd <= 2) {
|
||||
#ifdef F_DUPFD
|
||||
if ((new_fd = fcntl(fd, F_DUPFD, 3)) == -1) {
|
||||
return -1;
|
||||
}
|
||||
/* Parinoia */
|
||||
if (new_fd < 3) {
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
return new_fd;
|
||||
#else
|
||||
if (limit <= 0)
|
||||
return -1;
|
||||
|
||||
new_fd = dup(fd);
|
||||
if (new_fd == -1)
|
||||
return -1;
|
||||
|
||||
/* use the program stack to hold our list of FDs to close */
|
||||
new_fd = make_nonstd_fd_internals(new_fd, limit - 1);
|
||||
close(fd);
|
||||
return new_fd;
|
||||
#endif
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int make_safe_fd(int fd)
|
||||
{
|
||||
int result, flags;
|
||||
int new_fd = make_nonstd_fd_internals(fd, RECURSION_LIMIT);
|
||||
if (new_fd == -1) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
/* Socket should be closed on exec() */
|
||||
|
||||
#ifdef FD_CLOEXEC
|
||||
result = flags = fcntl(new_fd, F_GETFD, 0);
|
||||
if (flags >= 0) {
|
||||
flags |= FD_CLOEXEC;
|
||||
result = fcntl( new_fd, F_SETFD, flags );
|
||||
}
|
||||
if (result < 0) {
|
||||
close(new_fd);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return new_fd;
|
||||
}
|
||||
|
||||
/* Connect to winbindd socket */
|
||||
|
||||
int winbind_open_pipe_sock(void)
|
||||
@@ -91,6 +151,7 @@ int winbind_open_pipe_sock(void)
|
||||
static pid_t our_pid;
|
||||
struct stat st;
|
||||
pstring path;
|
||||
int fd;
|
||||
|
||||
if (our_pid != getpid()) {
|
||||
close_sock();
|
||||
@@ -144,10 +205,14 @@ int winbind_open_pipe_sock(void)
|
||||
|
||||
/* Connect to socket */
|
||||
|
||||
if ((winbindd_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
|
||||
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((winbindd_fd = make_safe_fd( fd)) == -1) {
|
||||
return winbindd_fd;
|
||||
}
|
||||
|
||||
if (connect(winbindd_fd, (struct sockaddr *)&sunaddr,
|
||||
sizeof(sunaddr)) == -1) {
|
||||
close_sock();
|
||||
|
||||
@@ -28,11 +28,7 @@
|
||||
#undef DBGC_CLASS
|
||||
#define DBGC_CLASS DBGC_WINBIND
|
||||
|
||||
/* Prototypes from common.h */
|
||||
|
||||
NSS_STATUS winbindd_request(int req_type,
|
||||
struct winbindd_request *request,
|
||||
struct winbindd_response *response);
|
||||
extern int winbindd_fd;
|
||||
|
||||
static char winbind_separator(void)
|
||||
{
|
||||
@@ -613,8 +609,8 @@ static BOOL wbinfo_ping(void)
|
||||
|
||||
/* Display response */
|
||||
|
||||
d_printf("'ping' to winbindd %s\n",
|
||||
(result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
|
||||
d_printf("'ping' to winbindd %s on fd %d\n",
|
||||
(result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed", winbindd_fd);
|
||||
|
||||
return result == NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -21,8 +21,7 @@
|
||||
Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "winbind_nss_config.h"
|
||||
#include "winbindd_nss.h"
|
||||
#include "winbind_client.h"
|
||||
|
||||
#ifdef HAVE_NS_API_H
|
||||
#undef VOLATILE
|
||||
@@ -37,17 +36,6 @@
|
||||
|
||||
extern int winbindd_fd;
|
||||
|
||||
void init_request(struct winbindd_request *req,int rq_type);
|
||||
NSS_STATUS winbindd_send_request(int req_type,
|
||||
struct winbindd_request *request);
|
||||
NSS_STATUS winbindd_get_response(struct winbindd_response *response);
|
||||
NSS_STATUS winbindd_request(int req_type,
|
||||
struct winbindd_request *request,
|
||||
struct winbindd_response *response);
|
||||
int winbind_open_pipe_sock(void);
|
||||
int write_sock(void *buffer, int count);
|
||||
int read_reply(struct winbindd_response *response);
|
||||
void free_response(struct winbindd_response *response);
|
||||
|
||||
#ifdef HAVE_NS_API_H
|
||||
/* IRIX version */
|
||||
|
||||
@@ -62,6 +62,14 @@
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#else
|
||||
#ifdef HAVE_SYS_FCNTL_H
|
||||
#include <sys/fcntl.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
Reference in New Issue
Block a user