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 "mangle.h"
|
||||||
|
|
||||||
|
#include "nsswitch/winbind_client.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Type for wide character dirent structure.
|
* Type for wide character dirent structure.
|
||||||
* Only d_name is defined by POSIX.
|
* Only d_name is defined by POSIX.
|
||||||
|
|||||||
@@ -1623,8 +1623,6 @@ struct unix_error_map {
|
|||||||
|
|
||||||
#define SAFE_NETBIOS_CHARS ". -_"
|
#define SAFE_NETBIOS_CHARS ". -_"
|
||||||
|
|
||||||
#include "nsswitch/winbindd_nss.h"
|
|
||||||
|
|
||||||
/* generic iconv conversion structure */
|
/* generic iconv conversion structure */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t (*direct)(void *cd, char **inbuf, size_t *inbytesleft,
|
size_t (*direct)(void *cd, char **inbuf, size_t *inbytesleft,
|
||||||
|
|||||||
@@ -11,11 +11,6 @@
|
|||||||
|
|
||||||
#include "pam_winbind.h"
|
#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 */
|
/* data tokens */
|
||||||
|
|
||||||
#define MAX_PASSWD_TRIES 3
|
#define MAX_PASSWD_TRIES 3
|
||||||
@@ -99,24 +94,30 @@ static int _make_remark(pam_handle_t * pamh, int type, const char *text)
|
|||||||
return retval;
|
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_request *request,
|
||||||
struct winbindd_response *response)
|
struct winbindd_response *response)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Fill in request and send down pipe */
|
/* Fill in request and send down pipe */
|
||||||
init_request(request, req_type);
|
init_request(request, req_type);
|
||||||
|
|
||||||
if (write_sock(request, sizeof(*request)) == -1) {
|
if (write_sock(request, sizeof(*request)) == -1) {
|
||||||
_pam_log(LOG_ERR, "write to socket failed!");
|
_pam_log(LOG_ERR, "write to socket failed!");
|
||||||
|
close_sock();
|
||||||
return PAM_SERVICE_ERR;
|
return PAM_SERVICE_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for reply */
|
/* Wait for reply */
|
||||||
if (read_reply(response) == -1) {
|
if (read_reply(response) == -1) {
|
||||||
_pam_log(LOG_ERR, "read from socket failed!");
|
_pam_log(LOG_ERR, "read from socket failed!");
|
||||||
|
close_sock();
|
||||||
return PAM_SERVICE_ERR;
|
return PAM_SERVICE_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We are done with the socket - close it and avoid mischeif */
|
||||||
|
close_sock();
|
||||||
|
|
||||||
/* Copy reply data from socket */
|
/* Copy reply data from socket */
|
||||||
if (response->result != WINBINDD_OK) {
|
if (response->result != WINBINDD_OK) {
|
||||||
if (response->data.auth.pam_error != PAM_SUCCESS) {
|
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,
|
strncpy(request.data.auth.pass, pass,
|
||||||
sizeof(request.data.auth.pass)-1);
|
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) {
|
switch (retval) {
|
||||||
case PAM_AUTH_ERR:
|
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';
|
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 on(x, y) (x & y)
|
||||||
#define off(x, y) (!(x & y))
|
#define off(x, y) (!(x & y))
|
||||||
|
|
||||||
#include "winbind_nss_config.h"
|
#include "winbind_client.h"
|
||||||
#include "winbindd_nss.h"
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
Copyright (C) Tim Potter 2000
|
Copyright (C) Tim Potter 2000
|
||||||
Copyright (C) Andrew Tridgell 2000
|
Copyright (C) Andrew Tridgell 2000
|
||||||
|
Copyright (C) Andrew Bartlett 2002
|
||||||
|
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Library General Public
|
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 */
|
/* Close established socket */
|
||||||
|
|
||||||
static void close_sock(void)
|
void close_sock(void)
|
||||||
{
|
{
|
||||||
if (winbindd_fd != -1) {
|
if (winbindd_fd != -1) {
|
||||||
close(winbindd_fd);
|
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 */
|
/* Connect to winbindd socket */
|
||||||
|
|
||||||
int winbind_open_pipe_sock(void)
|
int winbind_open_pipe_sock(void)
|
||||||
@@ -91,6 +151,7 @@ int winbind_open_pipe_sock(void)
|
|||||||
static pid_t our_pid;
|
static pid_t our_pid;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
pstring path;
|
pstring path;
|
||||||
|
int fd;
|
||||||
|
|
||||||
if (our_pid != getpid()) {
|
if (our_pid != getpid()) {
|
||||||
close_sock();
|
close_sock();
|
||||||
@@ -144,9 +205,13 @@ int winbind_open_pipe_sock(void)
|
|||||||
|
|
||||||
/* Connect to socket */
|
/* Connect to socket */
|
||||||
|
|
||||||
if ((winbindd_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
|
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((winbindd_fd = make_safe_fd( fd)) == -1) {
|
||||||
|
return winbindd_fd;
|
||||||
|
}
|
||||||
|
|
||||||
if (connect(winbindd_fd, (struct sockaddr *)&sunaddr,
|
if (connect(winbindd_fd, (struct sockaddr *)&sunaddr,
|
||||||
sizeof(sunaddr)) == -1) {
|
sizeof(sunaddr)) == -1) {
|
||||||
@@ -366,8 +431,8 @@ NSS_STATUS winbindd_get_response(struct winbindd_response *response)
|
|||||||
/* Handle simple types of requests */
|
/* Handle simple types of requests */
|
||||||
|
|
||||||
NSS_STATUS winbindd_request(int req_type,
|
NSS_STATUS winbindd_request(int req_type,
|
||||||
struct winbindd_request *request,
|
struct winbindd_request *request,
|
||||||
struct winbindd_response *response)
|
struct winbindd_response *response)
|
||||||
{
|
{
|
||||||
NSS_STATUS status;
|
NSS_STATUS status;
|
||||||
|
|
||||||
|
|||||||
@@ -28,11 +28,7 @@
|
|||||||
#undef DBGC_CLASS
|
#undef DBGC_CLASS
|
||||||
#define DBGC_CLASS DBGC_WINBIND
|
#define DBGC_CLASS DBGC_WINBIND
|
||||||
|
|
||||||
/* Prototypes from common.h */
|
extern int winbindd_fd;
|
||||||
|
|
||||||
NSS_STATUS winbindd_request(int req_type,
|
|
||||||
struct winbindd_request *request,
|
|
||||||
struct winbindd_response *response);
|
|
||||||
|
|
||||||
static char winbind_separator(void)
|
static char winbind_separator(void)
|
||||||
{
|
{
|
||||||
@@ -608,13 +604,13 @@ static BOOL wbinfo_set_auth_user(char *username)
|
|||||||
static BOOL wbinfo_ping(void)
|
static BOOL wbinfo_ping(void)
|
||||||
{
|
{
|
||||||
NSS_STATUS result;
|
NSS_STATUS result;
|
||||||
|
|
||||||
result = winbindd_request(WINBINDD_PING, NULL, NULL);
|
result = winbindd_request(WINBINDD_PING, NULL, NULL);
|
||||||
|
|
||||||
/* Display response */
|
/* Display response */
|
||||||
|
|
||||||
d_printf("'ping' to winbindd %s\n",
|
d_printf("'ping' to winbindd %s on fd %d\n",
|
||||||
(result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
|
(result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed", winbindd_fd);
|
||||||
|
|
||||||
return result == NSS_STATUS_SUCCESS;
|
return result == NSS_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,7 @@
|
|||||||
Boston, MA 02111-1307, USA.
|
Boston, MA 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "winbind_nss_config.h"
|
#include "winbind_client.h"
|
||||||
#include "winbindd_nss.h"
|
|
||||||
|
|
||||||
#ifdef HAVE_NS_API_H
|
#ifdef HAVE_NS_API_H
|
||||||
#undef VOLATILE
|
#undef VOLATILE
|
||||||
@@ -37,17 +36,6 @@
|
|||||||
|
|
||||||
extern int winbindd_fd;
|
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
|
#ifdef HAVE_NS_API_H
|
||||||
/* IRIX version */
|
/* IRIX version */
|
||||||
|
|||||||
@@ -62,6 +62,14 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#endif
|
#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/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|||||||
Reference in New Issue
Block a user