Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2005-02-23 20:39:46 +0300
committerCorinna Vinschen <corinna@vinschen.de>2005-02-23 20:39:46 +0300
commitc8b404bf5c8c5268ef9a288d8c59b7e3ea935e8b (patch)
tree619b38b52fa65a469b1d8ca788b9a834a15768c9
parent81d0376064d861df4d70f1263ec627af96486443 (diff)
* 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.
-rw-r--r--winsup/cygwin/ChangeLog22
-rw-r--r--winsup/cygwin/cygwin.din1
-rw-r--r--winsup/cygwin/fhandler.h11
-rw-r--r--winsup/cygwin/fhandler_socket.cc102
-rw-r--r--winsup/cygwin/include/asm/socket.h1
-rw-r--r--winsup/cygwin/include/cygwin/socket.h6
-rw-r--r--winsup/cygwin/include/cygwin/version.h4
-rw-r--r--winsup/cygwin/net.cc17
8 files changed, 159 insertions, 5 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index a02fb4e33..4e77c597e 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,27 @@
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>
+
* include/sys/statvfs.h (ST_RDONLY): Define.
(ST_NOSUID): Define.
diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
index dd8e5a8c4..594f114e7 100644
--- a/winsup/cygwin/cygwin.din
+++ b/winsup/cygwin/cygwin.din
@@ -307,6 +307,7 @@ gethostbyaddr = cygwin_gethostbyaddr SIGFE
gethostbyname = cygwin_gethostbyname SIGFE
_gethostname = cygwin_gethostname SIGFE
gethostname = cygwin_gethostname SIGFE
+getpeereid SIGFE
getpeername = cygwin_getpeername SIGFE
getprogname NOSIGFE
getprotobyname = cygwin_getprotobyname SIGFE
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 3199351ce..d3250d1b2 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -355,6 +355,16 @@ class fhandler_socket: public fhandler_base
int type;
int connect_secret [4];
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;
char *sun_path;
struct status_flags
@@ -395,6 +405,7 @@ class fhandler_socket: public fhandler_base
int accept (struct sockaddr *peer, int *len);
int getsockname (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);
ssize_t readv (const struct iovec *, int iovcnt, ssize_t tot = -1);
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index 9f0b39f53..b5b4847ec 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -53,6 +53,13 @@ secret_event_name (char *buf, short port, int *secret_ptr)
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 */
static int
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_base (),
+ sec_pipe (INVALID_HANDLE_VALUE),
sun_path (NULL),
status ()
{
@@ -620,6 +628,22 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen)
set_errno (ECONNREFUSED);
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 ();
@@ -638,7 +662,26 @@ fhandler_socket::listen (int backlog)
if (res)
set_winsock_errno ();
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;
}
@@ -648,6 +691,8 @@ fhandler_socket::accept (struct sockaddr *peer, int *len)
int res = -1;
bool secret_check_failed = 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. */
struct sockaddr_in peer_dummy;
@@ -700,6 +745,23 @@ fhandler_socket::accept (struct sockaddr *peer, int *len)
set_errno (ECONNABORTED);
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)
@@ -709,10 +771,18 @@ fhandler_socket::accept (struct sockaddr *peer, int *len)
cygheap_fdnew res_fd;
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_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);
res = res_fd;
}
@@ -1322,6 +1392,10 @@ fhandler_socket::close ()
setsockopt (get_socket (), SOL_SOCKET, SO_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)
{
if (WSAGetLastError () != WSAEWOULDBLOCK)
@@ -1539,3 +1613,25 @@ fhandler_socket::set_sun_path (const char *path)
{
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;
+}
diff --git a/winsup/cygwin/include/asm/socket.h b/winsup/cygwin/include/asm/socket.h
index b1392ce22..ed062190c 100644
--- a/winsup/cygwin/include/asm/socket.h
+++ b/winsup/cygwin/include/asm/socket.h
@@ -54,6 +54,7 @@ details. */
#define SO_LINGER 0x0080 /* linger on close if data present */
#define SO_OOBINLINE 0x0100 /* leave received OOB data in line */
#define SO_DONTLINGER (u_int)(~SO_LINGER)
+#define SO_PEERCRED 0x0200 /* same as getpeereid */
/*
* Additional options.
diff --git a/winsup/cygwin/include/cygwin/socket.h b/winsup/cygwin/include/cygwin/socket.h
index 67e1345f2..f6dc11353 100644
--- a/winsup/cygwin/include/cygwin/socket.h
+++ b/winsup/cygwin/include/cygwin/socket.h
@@ -25,6 +25,12 @@ struct sockaddr {
#include <cygwin/uio.h> /* iovec support */
#include <sys/types.h>
+struct ucred {
+ pid_t pid;
+ __uid32_t uid;
+ __gid32_t gid;
+};
+
struct linger {
unsigned short l_onoff; /* Linger active */
unsigned short l_linger; /* How long to linger for */
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index 10cf2ba2d..11db44cc0 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -248,13 +248,13 @@ details. */
118: Export getpriority, setpriority.
119: Export fdatasync.
120: Export basename, dirname.
- 121: Export statvfs, fstatvfs.
+ 122: Export statvfs, fstatvfs.
*/
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#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
shared memory regions. It is incremented when incompatible
diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc
index 33356d13e..98e121c5a 100644
--- a/winsup/cygwin/net.cc
+++ b/winsup/cygwin/net.cc
@@ -780,6 +780,8 @@ cygwin_getsockopt (int fd, int level, int optname, void *optval, int *optlen)
case SO_ERROR:
name = "SO_ERROR";
break;
+ case SO_PEERCRED:
+ name = "SO_PEERCRED";
}
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)))
|| !fh)
res = -1;
+ else if (optname == SO_PEERCRED)
+ {
+ struct ucred *cred = (struct ucred *) optval;
+ res = fh->getpeereid (&cred->pid, &cred->uid, &cred->gid);
+ }
else
{
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;
}
+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? */
extern "C" int
cygwin_connect (int fd, const struct sockaddr *name, int namelen)