* cygwin.din (getpeereid): Export.
* fhandler.h (class fhandler_socket): Add pipe and id members to exchange eid credentials for AF_LOCAL sockets. (eid_pipe_name): Declare new method. (getpeereid): Ditto. * fhandler_socket.cc (fhandler_socket::eid_pipe_name): New method. (fhandler_socket::fhandler_socket): Initialize sec_pipe. (fhandler_socket::connect): Exchange eid credentials with accepting socket process. (fhandler_socket::listen): Prepare eid credential transaction. (fhandler_socket::accept): Exchange eid credentials with connecting socket process. (fhandler_socket::close): Close eid credentials pipe if open. (fhandler_socket::getpeereid): New method. * net.cc (cygwin_getsockopt): Add SO_PEERCRED handling. (getpeereid): New function. * include/asm/socket.h (SO_PEERCRED): Define. * include/cygwin/socket.h (struct ucred): Define new type. * include/cygwin/version.h: Bump API minor version.
This commit is contained in:
parent
81d0376064
commit
c8b404bf5c
|
@ -1,3 +1,25 @@
|
||||||
|
2005-02-23 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* cygwin.din (getpeereid): Export.
|
||||||
|
* fhandler.h (class fhandler_socket): Add pipe and id members to
|
||||||
|
exchange eid credentials for AF_LOCAL sockets.
|
||||||
|
(eid_pipe_name): Declare new method.
|
||||||
|
(getpeereid): Ditto.
|
||||||
|
* fhandler_socket.cc (fhandler_socket::eid_pipe_name): New method.
|
||||||
|
(fhandler_socket::fhandler_socket): Initialize sec_pipe.
|
||||||
|
(fhandler_socket::connect): Exchange eid credentials with accepting
|
||||||
|
socket process.
|
||||||
|
(fhandler_socket::listen): Prepare eid credential transaction.
|
||||||
|
(fhandler_socket::accept): Exchange eid credentials with connecting
|
||||||
|
socket process.
|
||||||
|
(fhandler_socket::close): Close eid credentials pipe if open.
|
||||||
|
(fhandler_socket::getpeereid): New method.
|
||||||
|
* net.cc (cygwin_getsockopt): Add SO_PEERCRED handling.
|
||||||
|
(getpeereid): New function.
|
||||||
|
* include/asm/socket.h (SO_PEERCRED): Define.
|
||||||
|
* include/cygwin/socket.h (struct ucred): Define new type.
|
||||||
|
* include/cygwin/version.h: Bump API minor version.
|
||||||
|
|
||||||
2005-02-23 Corinna Vinschen <corinna@vinschen.de>
|
2005-02-23 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* include/sys/statvfs.h (ST_RDONLY): Define.
|
* include/sys/statvfs.h (ST_RDONLY): Define.
|
||||||
|
|
|
@ -307,6 +307,7 @@ gethostbyaddr = cygwin_gethostbyaddr SIGFE
|
||||||
gethostbyname = cygwin_gethostbyname SIGFE
|
gethostbyname = cygwin_gethostbyname SIGFE
|
||||||
_gethostname = cygwin_gethostname SIGFE
|
_gethostname = cygwin_gethostname SIGFE
|
||||||
gethostname = cygwin_gethostname SIGFE
|
gethostname = cygwin_gethostname SIGFE
|
||||||
|
getpeereid SIGFE
|
||||||
getpeername = cygwin_getpeername SIGFE
|
getpeername = cygwin_getpeername SIGFE
|
||||||
getprogname NOSIGFE
|
getprogname NOSIGFE
|
||||||
getprotobyname = cygwin_getprotobyname SIGFE
|
getprotobyname = cygwin_getprotobyname SIGFE
|
||||||
|
|
|
@ -355,6 +355,16 @@ class fhandler_socket: public fhandler_base
|
||||||
int type;
|
int type;
|
||||||
int connect_secret [4];
|
int connect_secret [4];
|
||||||
HANDLE secret_event;
|
HANDLE secret_event;
|
||||||
|
|
||||||
|
HANDLE sec_pipe;
|
||||||
|
pid_t sec_pid;
|
||||||
|
__uid32_t sec_uid;
|
||||||
|
__gid32_t sec_gid;
|
||||||
|
pid_t sec_peer_pid;
|
||||||
|
__uid32_t sec_peer_uid;
|
||||||
|
__gid32_t sec_peer_gid;
|
||||||
|
char *eid_pipe_name (char *buf);
|
||||||
|
|
||||||
struct _WSAPROTOCOL_INFOA *prot_info_ptr;
|
struct _WSAPROTOCOL_INFOA *prot_info_ptr;
|
||||||
char *sun_path;
|
char *sun_path;
|
||||||
struct status_flags
|
struct status_flags
|
||||||
|
@ -395,6 +405,7 @@ class fhandler_socket: public fhandler_base
|
||||||
int accept (struct sockaddr *peer, int *len);
|
int accept (struct sockaddr *peer, int *len);
|
||||||
int getsockname (struct sockaddr *name, int *namelen);
|
int getsockname (struct sockaddr *name, int *namelen);
|
||||||
int getpeername (struct sockaddr *name, int *namelen);
|
int getpeername (struct sockaddr *name, int *namelen);
|
||||||
|
int getpeereid (pid_t *pid, __uid32_t *euid, __gid32_t *egid);
|
||||||
|
|
||||||
int open (int flags, mode_t mode = 0);
|
int open (int flags, mode_t mode = 0);
|
||||||
ssize_t readv (const struct iovec *, int iovcnt, ssize_t tot = -1);
|
ssize_t readv (const struct iovec *, int iovcnt, ssize_t tot = -1);
|
||||||
|
|
|
@ -53,6 +53,13 @@ secret_event_name (char *buf, short port, int *secret_ptr)
|
||||||
secret_ptr [2], secret_ptr [3]);
|
secret_ptr [2], secret_ptr [3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
fhandler_socket::eid_pipe_name (char *buf)
|
||||||
|
{
|
||||||
|
__small_sprintf (buf, "\\\\.\\pipe\\cygwin-unix-$s", get_sun_path ());
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
/* cygwin internal: map sockaddr into internet domain address */
|
/* cygwin internal: map sockaddr into internet domain address */
|
||||||
static int
|
static int
|
||||||
get_inet_addr (const struct sockaddr *in, int inlen,
|
get_inet_addr (const struct sockaddr *in, int inlen,
|
||||||
|
@ -124,6 +131,7 @@ get_inet_addr (const struct sockaddr *in, int inlen,
|
||||||
|
|
||||||
fhandler_socket::fhandler_socket () :
|
fhandler_socket::fhandler_socket () :
|
||||||
fhandler_base (),
|
fhandler_base (),
|
||||||
|
sec_pipe (INVALID_HANDLE_VALUE),
|
||||||
sun_path (NULL),
|
sun_path (NULL),
|
||||||
status ()
|
status ()
|
||||||
{
|
{
|
||||||
|
@ -620,6 +628,22 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen)
|
||||||
set_errno (ECONNREFUSED);
|
set_errno (ECONNREFUSED);
|
||||||
res = -1;
|
res = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* eid credential transaction. */
|
||||||
|
struct ucred in = { getpid (), geteuid32 (), getegid32 () };
|
||||||
|
struct ucred out = { (pid_t) -1, (__uid32_t) -1, (__gid32_t) -1 };
|
||||||
|
DWORD bytes = 0;
|
||||||
|
if (CallNamedPipe(eid_pipe_name ((char *) alloca (CYG_MAX_PATH + 1)),
|
||||||
|
&in, sizeof in, &out, sizeof out, &bytes, 1000))
|
||||||
|
{
|
||||||
|
debug_printf ("Received eid credentials: pid: %d, uid: %d, gid: %d",
|
||||||
|
out.pid, out.uid, out.gid);
|
||||||
|
sec_peer_pid = out.pid;
|
||||||
|
sec_peer_uid = out.uid;
|
||||||
|
sec_peer_gid = out.gid;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
debug_printf ("Receiving eid credentials failed: %E");
|
||||||
}
|
}
|
||||||
|
|
||||||
err = WSAGetLastError ();
|
err = WSAGetLastError ();
|
||||||
|
@ -638,7 +662,26 @@ fhandler_socket::listen (int backlog)
|
||||||
if (res)
|
if (res)
|
||||||
set_winsock_errno ();
|
set_winsock_errno ();
|
||||||
else
|
else
|
||||||
connect_state (connected);
|
{
|
||||||
|
if (get_addr_family () == AF_LOCAL && get_socket_type () == SOCK_STREAM)
|
||||||
|
{
|
||||||
|
/* Prepare eid credential transaction. */
|
||||||
|
sec_pid = getpid ();
|
||||||
|
sec_uid = geteuid32 ();
|
||||||
|
sec_gid = getegid32 ();
|
||||||
|
sec_peer_pid = (pid_t) -1;
|
||||||
|
sec_peer_uid = (__uid32_t) -1;
|
||||||
|
sec_peer_gid = (__gid32_t) -1;
|
||||||
|
sec_pipe =
|
||||||
|
CreateNamedPipe (eid_pipe_name ((char *) alloca (CYG_MAX_PATH + 1)),
|
||||||
|
PIPE_ACCESS_DUPLEX,
|
||||||
|
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
|
||||||
|
1, sizeof (struct ucred), sizeof (struct ucred),
|
||||||
|
1000, &sec_all);
|
||||||
|
debug_printf ("sec_pipe: %x", sec_pipe);
|
||||||
|
}
|
||||||
|
connect_state (connected);
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -648,6 +691,8 @@ fhandler_socket::accept (struct sockaddr *peer, int *len)
|
||||||
int res = -1;
|
int res = -1;
|
||||||
bool secret_check_failed = false;
|
bool secret_check_failed = false;
|
||||||
bool in_progress = false;
|
bool in_progress = false;
|
||||||
|
struct ucred in = { sec_pid, sec_uid, sec_gid };
|
||||||
|
struct ucred out = { (pid_t) -1, (__uid32_t) -1, (__gid32_t) -1 };
|
||||||
|
|
||||||
/* Allows NULL peer and len parameters. */
|
/* Allows NULL peer and len parameters. */
|
||||||
struct sockaddr_in peer_dummy;
|
struct sockaddr_in peer_dummy;
|
||||||
|
@ -700,6 +745,23 @@ fhandler_socket::accept (struct sockaddr *peer, int *len)
|
||||||
set_errno (ECONNABORTED);
|
set_errno (ECONNABORTED);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* eid credential transaction. */
|
||||||
|
DWORD bytes = 0;
|
||||||
|
bool ret = ConnectNamedPipe (sec_pipe, NULL);
|
||||||
|
if (ret || GetLastError () == ERROR_PIPE_CONNECTED)
|
||||||
|
{
|
||||||
|
if (!ReadFile (sec_pipe, &out, sizeof out, &bytes, NULL))
|
||||||
|
debug_printf ("Receiving eid credentials failed: %E");
|
||||||
|
else
|
||||||
|
debug_printf ("Received eid credentials: pid: %d, uid: %d, gid: %d",
|
||||||
|
out.pid, out.uid, out.gid);
|
||||||
|
if (!WriteFile (sec_pipe, &in, sizeof in, &bytes, NULL))
|
||||||
|
debug_printf ("Sending eid credentials failed: %E");
|
||||||
|
DisconnectNamedPipe (sec_pipe);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
debug_printf ("Connecting the eid credential pipe failed: %E");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((SOCKET) res == INVALID_SOCKET)
|
if ((SOCKET) res == INVALID_SOCKET)
|
||||||
|
@ -709,10 +771,18 @@ fhandler_socket::accept (struct sockaddr *peer, int *len)
|
||||||
cygheap_fdnew res_fd;
|
cygheap_fdnew res_fd;
|
||||||
if (res_fd >= 0 && fdsock (res_fd, &dev (), res))
|
if (res_fd >= 0 && fdsock (res_fd, &dev (), res))
|
||||||
{
|
{
|
||||||
if (get_addr_family () == AF_LOCAL)
|
|
||||||
((fhandler_socket *) res_fd)->set_sun_path (get_sun_path ());
|
|
||||||
((fhandler_socket *) res_fd)->set_addr_family (get_addr_family ());
|
((fhandler_socket *) res_fd)->set_addr_family (get_addr_family ());
|
||||||
((fhandler_socket *) res_fd)->set_socket_type (get_socket_type ());
|
((fhandler_socket *) res_fd)->set_socket_type (get_socket_type ());
|
||||||
|
if (get_addr_family () == AF_LOCAL)
|
||||||
|
{
|
||||||
|
((fhandler_socket *) res_fd)->set_sun_path (get_sun_path ());
|
||||||
|
if (get_socket_type () == SOCK_STREAM)
|
||||||
|
{
|
||||||
|
((fhandler_socket *) res_fd)->sec_peer_pid = out.pid;
|
||||||
|
((fhandler_socket *) res_fd)->sec_peer_uid = out.uid;
|
||||||
|
((fhandler_socket *) res_fd)->sec_peer_gid = out.gid;
|
||||||
|
}
|
||||||
|
}
|
||||||
((fhandler_socket *) res_fd)->connect_state (connected);
|
((fhandler_socket *) res_fd)->connect_state (connected);
|
||||||
res = res_fd;
|
res = res_fd;
|
||||||
}
|
}
|
||||||
|
@ -1322,6 +1392,10 @@ fhandler_socket::close ()
|
||||||
setsockopt (get_socket (), SOL_SOCKET, SO_LINGER,
|
setsockopt (get_socket (), SOL_SOCKET, SO_LINGER,
|
||||||
(const char *)&linger, sizeof linger);
|
(const char *)&linger, sizeof linger);
|
||||||
|
|
||||||
|
/* Close eid credentials pipe handle. */
|
||||||
|
if (sec_pipe != INVALID_HANDLE_VALUE)
|
||||||
|
CloseHandle (sec_pipe);
|
||||||
|
|
||||||
while ((res = closesocket (get_socket ())) != 0)
|
while ((res = closesocket (get_socket ())) != 0)
|
||||||
{
|
{
|
||||||
if (WSAGetLastError () != WSAEWOULDBLOCK)
|
if (WSAGetLastError () != WSAEWOULDBLOCK)
|
||||||
|
@ -1539,3 +1613,25 @@ fhandler_socket::set_sun_path (const char *path)
|
||||||
{
|
{
|
||||||
sun_path = path ? cstrdup (path) : NULL;
|
sun_path = path ? cstrdup (path) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
fhandler_socket::getpeereid (pid_t *pid, __uid32_t *euid, __gid32_t *egid)
|
||||||
|
{
|
||||||
|
if (get_addr_family () == AF_LOCAL && get_socket_type () == SOCK_STREAM)
|
||||||
|
{
|
||||||
|
if (connect_state () == connected && sec_peer_pid != (pid_t) -1)
|
||||||
|
{
|
||||||
|
if (!check_null_invalid_struct (pid))
|
||||||
|
*pid = sec_peer_pid;
|
||||||
|
if (!check_null_invalid_struct (euid))
|
||||||
|
*euid = sec_peer_uid;
|
||||||
|
if (!check_null_invalid_struct (egid))
|
||||||
|
*egid = sec_peer_gid;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
set_errno (ENOTCONN);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
set_errno (EINVAL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@ details. */
|
||||||
#define SO_LINGER 0x0080 /* linger on close if data present */
|
#define SO_LINGER 0x0080 /* linger on close if data present */
|
||||||
#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */
|
#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */
|
||||||
#define SO_DONTLINGER (u_int)(~SO_LINGER)
|
#define SO_DONTLINGER (u_int)(~SO_LINGER)
|
||||||
|
#define SO_PEERCRED 0x0200 /* same as getpeereid */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Additional options.
|
* Additional options.
|
||||||
|
|
|
@ -25,6 +25,12 @@ struct sockaddr {
|
||||||
#include <cygwin/uio.h> /* iovec support */
|
#include <cygwin/uio.h> /* iovec support */
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
struct ucred {
|
||||||
|
pid_t pid;
|
||||||
|
__uid32_t uid;
|
||||||
|
__gid32_t gid;
|
||||||
|
};
|
||||||
|
|
||||||
struct linger {
|
struct linger {
|
||||||
unsigned short l_onoff; /* Linger active */
|
unsigned short l_onoff; /* Linger active */
|
||||||
unsigned short l_linger; /* How long to linger for */
|
unsigned short l_linger; /* How long to linger for */
|
||||||
|
|
|
@ -248,13 +248,13 @@ details. */
|
||||||
118: Export getpriority, setpriority.
|
118: Export getpriority, setpriority.
|
||||||
119: Export fdatasync.
|
119: Export fdatasync.
|
||||||
120: Export basename, dirname.
|
120: Export basename, dirname.
|
||||||
121: Export statvfs, fstatvfs.
|
122: Export statvfs, fstatvfs.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
|
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
|
||||||
|
|
||||||
#define CYGWIN_VERSION_API_MAJOR 0
|
#define CYGWIN_VERSION_API_MAJOR 0
|
||||||
#define CYGWIN_VERSION_API_MINOR 121
|
#define CYGWIN_VERSION_API_MINOR 122
|
||||||
|
|
||||||
/* There is also a compatibity version number associated with the
|
/* There is also a compatibity version number associated with the
|
||||||
shared memory regions. It is incremented when incompatible
|
shared memory regions. It is incremented when incompatible
|
||||||
|
|
|
@ -780,6 +780,8 @@ cygwin_getsockopt (int fd, int level, int optname, void *optval, int *optlen)
|
||||||
case SO_ERROR:
|
case SO_ERROR:
|
||||||
name = "SO_ERROR";
|
name = "SO_ERROR";
|
||||||
break;
|
break;
|
||||||
|
case SO_PEERCRED:
|
||||||
|
name = "SO_PEERCRED";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((optval
|
if ((optval
|
||||||
|
@ -787,6 +789,11 @@ cygwin_getsockopt (int fd, int level, int optname, void *optval, int *optlen)
|
||||||
|| __check_null_invalid_struct_errno (optval, (unsigned) *optlen)))
|
|| __check_null_invalid_struct_errno (optval, (unsigned) *optlen)))
|
||||||
|| !fh)
|
|| !fh)
|
||||||
res = -1;
|
res = -1;
|
||||||
|
else if (optname == SO_PEERCRED)
|
||||||
|
{
|
||||||
|
struct ucred *cred = (struct ucred *) optval;
|
||||||
|
res = fh->getpeereid (&cred->pid, &cred->uid, &cred->gid);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
res = getsockopt (fh->get_socket (), level, optname, (char *) optval,
|
res = getsockopt (fh->get_socket (), level, optname, (char *) optval,
|
||||||
|
@ -808,6 +815,16 @@ cygwin_getsockopt (int fd, int level, int optname, void *optval, int *optlen)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
getpeereid (int fd, __uid32_t *euid, __gid32_t *egid)
|
||||||
|
{
|
||||||
|
sig_dispatch_pending ();
|
||||||
|
fhandler_socket *fh = get (fd);
|
||||||
|
if (fh)
|
||||||
|
return fh->getpeereid (NULL, euid, egid);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* exported as connect: standards? */
|
/* exported as connect: standards? */
|
||||||
extern "C" int
|
extern "C" int
|
||||||
cygwin_connect (int fd, const struct sockaddr *name, int namelen)
|
cygwin_connect (int fd, const struct sockaddr *name, int namelen)
|
||||||
|
|
Loading…
Reference in New Issue