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-03-24 17:04:06 +0300
committerCorinna Vinschen <corinna@vinschen.de>2005-03-24 17:04:06 +0300
commitb832c4cf214e3932d50de622dead4133845fc47e (patch)
tree0d0fb934d925ecdd67407491e91ebd92ceb425ef /winsup/cygwin/fhandler_socket.cc
parentbc47d398b27f09cbb044dc40e4e9425fb33be7a9 (diff)
* fhandler.h (fhandler_socket::secret_event): Remove.
(fhandler_socket::af_local_set_secret): New function combining former set_connect_secret and get_connect_secret into one function. (fhandler_socket::af_local_setblocking): Rename from eid_setblocking. (fhandler_socket::af_local_unsetblocking): Rename from eid_unsetblocking. (fhandler_socket::af_local_set_cred): New method. (fhandler_socket::af_local_copy): New method. (fhandler_socket::af_local_recv_secret): New method. (fhandler_socket::af_local_send_secret): New method. (fhandler_socket::af_local_recv_cred): Rename from eid_recv. (fhandler_socket::af_local_send_cred): Rename from eid_send. (fhandler_socket::af_local_accept): New method. (fhandler_socket::af_local_set_sockpair_cred): Rename from set_socketpair_eids. (fhandler_socket::eid_accept): Remove. (fhandler_socket::eid_connect): Remove. (fhandler_socket::set_connect_secret): Remove. (fhandler_socket::get_connect_secret): Remove. (fhandler_socket::create_secret_event): Remove. (fhandler_socket::check_peer_secret_event): Remove. (fhandler_socket::signal_secret_event): Remove. (fhandler_socket::close_secret_event): Remove. (fhandler_socket::sec_event_accept): Remove. (fhandler_socket::sec_event_connect): Remove. * fhandler_socket.cc (secret_event_name): Remove. (fhandler_socket::af_local_set_sockpair_cred): Rename from set_socketpair_eids. (fhandler_socket::af_local_setblocking): Rename from eid_setblocking. (fhandler_socket::af_local_unsetblocking): Rename from eid_unsetblocking. (fhandler_socket::af_local_recv_secret): New function to receive AF_LOCAL connect secret over socket itself. (fhandler_socket::af_local_send_secret): New function to send AF_LOCAL connect secret over socket itself. (fhandler_socket::af_local_recv_cred): Rename from eid_recv. (fhandler_socket::af_local_send_cred): Rename from eid_send. (fhandler_socket::eid_connect): Remove. (fhandler_socket::af_local_connect): Take over connect side handling of AF_LOCAL secret and credential handshake. (fhandler_socket::eid_accept): Remove. (fhandler_socket::af_local_accept): New method, take over accept side handling of AF_LOCAL secret and credential handshake. (fhandler_socket::af_local_set_cred): New method, set eid credentials to start values. (fhandler_socket::af_local_copy): New method, copy secret and credentials to another socket. (fhandler_socket::af_local_set_secret): New function combining former set_connect_secret and get_connect_secret into one function. (fhandler_socket::create_secret_event): Remove. (fhandler_socket::signal_secret_event): Remove. (fhandler_socket::close_secret_event): Remove. (fhandler_socket::check_peer_secret_event): Remove. (fhandler_socket::sec_event_connect): Remove. (fhandler_socket::sec_event_accept): Remove. (fhandler_socket::fixup_after_fork): Drop secret_event handling. (fhandler_socket::bind): Call af_local_set_secret. (fhandler_socket::connect): Call af_local_set_cred and af_local_connect. (fhandler_socket::listen): Call af_local_set_cred. (fhandler_socket::accept): Call af_local_copy and af_local_accept on accepted socket. (fhandler_socket::close): Don't call close_secret_event. (fhandler_socket::set_close_on_exec): Don't set secret_event inheritance. * net.cc (cygwin_getsockopt): Add debug output. (socketpair): Call af_local_set_sockpair_cred instead of set_socketpair_eids. * select.cc (set_bits): Drop AF_LOCAL special handling in case of except bit set.
Diffstat (limited to 'winsup/cygwin/fhandler_socket.cc')
-rw-r--r--winsup/cygwin/fhandler_socket.cc373
1 files changed, 140 insertions, 233 deletions
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index d2892e2df..8e7443e1d 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -45,16 +45,6 @@ int sscanf (const char *, const char *, ...);
fhandler_dev_random* entropy_source;
-static void
-secret_event_name (char *buf, short port, int *secret_ptr)
-{
- __small_sprintf (buf, "%scygwin.local_socket.secret.%d.%08x-%08x-%08x-%08x",
- wincap.has_terminal_services () ? "Global\\" : "",
- port,
- secret_ptr [0], secret_ptr [1],
- secret_ptr [2], secret_ptr [3]);
-}
-
/* cygwin internal: map sockaddr into internet domain address */
static int
get_inet_addr (const struct sockaddr *in, int inlen,
@@ -150,8 +140,22 @@ fhandler_socket::~fhandler_socket ()
cfree (sun_path);
}
+char *
+fhandler_socket::get_proc_fd_name (char *buf)
+{
+ __small_sprintf (buf, "socket:[%d]", get_socket ());
+ return buf;
+}
+
+int
+fhandler_socket::open (int flags, mode_t mode)
+{
+ set_errno (ENXIO);
+ return 0;
+}
+
void
-fhandler_socket::set_socketpair_eids (void)
+fhandler_socket::af_local_set_sockpair_cred (void)
{
sec_pid = sec_peer_pid = getpid ();
sec_uid = sec_peer_uid = geteuid32 ();
@@ -159,7 +163,7 @@ fhandler_socket::set_socketpair_eids (void)
}
void
-fhandler_socket::eid_setblocking (bool &async, bool &nonblocking)
+fhandler_socket::af_local_setblocking (bool &async, bool &nonblocking)
{
async = async_io ();
nonblocking = is_nonblocking ();
@@ -172,7 +176,7 @@ fhandler_socket::eid_setblocking (bool &async, bool &nonblocking)
}
void
-fhandler_socket::eid_unsetblocking (bool async, bool nonblocking)
+fhandler_socket::af_local_unsetblocking (bool async, bool nonblocking)
{
if (nonblocking)
{
@@ -188,7 +192,55 @@ fhandler_socket::eid_unsetblocking (bool async, bool nonblocking)
}
bool
-fhandler_socket::eid_recv (void)
+fhandler_socket::af_local_recv_secret (void)
+{
+ int out[4] = { 0, 0, 0, 0 };
+ int rest = sizeof out;
+ char *ptr = (char *) out;
+ while (rest > 0)
+ {
+ int ret = recvfrom (ptr, rest, 0, NULL, NULL);
+ if (ret <= 0)
+ break;
+ rest -= ret;
+ ptr += ret;
+ }
+ if (rest == 0)
+ {
+ debug_printf ("Received af_local secret: %08x-%08x-%08x-%08x",
+ out[0], out[1], out[2], out[3]);
+ if (out[0] != connect_secret[0] || out[1] != connect_secret[1]
+ || out[2] != connect_secret[2] || out[3] != connect_secret[3])
+ {
+ debug_printf ("Receiving af_local secret mismatch");
+ return false;
+ }
+ }
+ else
+ debug_printf ("Receiving af_local secret failed");
+ return rest == 0;
+}
+
+bool
+fhandler_socket::af_local_send_secret (void)
+{
+ int rest = sizeof connect_secret;
+ char *ptr = (char *) connect_secret;
+ while (rest > 0)
+ {
+ int ret = sendto (ptr, rest, 0, NULL, 0);
+ if (ret <= 0)
+ break;
+ rest -= ret;
+ ptr += ret;
+ }
+ debug_printf ("Sending af_local secret %s", rest == 0 ? "succeeded"
+ : "failed");
+ return rest == 0;
+}
+
+bool
+fhandler_socket::af_local_recv_cred (void)
{
struct ucred out = { (pid_t) 0, (__uid32_t) -1, (__gid32_t) -1 };
int rest = sizeof out;
@@ -215,7 +267,7 @@ fhandler_socket::eid_recv (void)
}
bool
-fhandler_socket::eid_send (void)
+fhandler_socket::af_local_send_cred (void)
{
struct ucred in = { sec_pid, sec_uid, sec_gid };
int rest = sizeof in;
@@ -235,42 +287,75 @@ fhandler_socket::eid_send (void)
return rest == 0;
}
-void
-fhandler_socket::eid_connect (void)
+int
+fhandler_socket::af_local_connect (void)
{
- debug_printf ("eid_connect called");
+ /* This keeps the test out of select. */
+ if (get_addr_family () != AF_LOCAL || get_socket_type () != SOCK_STREAM)
+ return 0;
+
+ debug_printf ("af_local_connect called");
bool orig_async_io, orig_is_nonblocking;
- eid_setblocking (orig_async_io, orig_is_nonblocking);
- eid_send () && eid_recv ();
- eid_unsetblocking (orig_async_io, orig_is_nonblocking);
+ af_local_setblocking (orig_async_io, orig_is_nonblocking);
+ if (!af_local_send_secret () || !af_local_recv_secret ()
+ || !af_local_send_cred () || !af_local_recv_cred ())
+ {
+ debug_printf ("accept from unauthorized server");
+ ::shutdown (get_socket (), SD_BOTH);
+ WSASetLastError (WSAECONNREFUSED);
+ return -1;
+ }
+ af_local_unsetblocking (orig_async_io, orig_is_nonblocking);
+ return 0;
}
-void
-fhandler_socket::eid_accept (void)
+int
+fhandler_socket::af_local_accept (void)
{
- debug_printf ("eid_accept called");
+ debug_printf ("af_local_accept called");
bool orig_async_io, orig_is_nonblocking;
- eid_setblocking (orig_async_io, orig_is_nonblocking);
- eid_recv () && eid_send ();
- eid_unsetblocking (orig_async_io, orig_is_nonblocking);
+ af_local_setblocking (orig_async_io, orig_is_nonblocking);
+ if (!af_local_recv_secret () || !af_local_send_secret ()
+ || !af_local_recv_cred () || !af_local_send_cred ())
+ {
+ debug_printf ("connect from unauthorized client");
+ ::shutdown (get_socket (), SD_BOTH);
+ ::closesocket (get_socket ());
+ WSASetLastError (WSAECONNABORTED);
+ return -1;
+ }
+ af_local_unsetblocking (orig_async_io, orig_is_nonblocking);
+ return 0;
}
-char *
-fhandler_socket::get_proc_fd_name (char *buf)
+void
+fhandler_socket::af_local_set_cred (void)
{
- __small_sprintf (buf, "socket:[%d]", get_socket ());
- return buf;
+ sec_pid = getpid ();
+ sec_uid = geteuid32 ();
+ sec_gid = getegid32 ();
+ sec_peer_pid = (pid_t) 0;
+ sec_peer_uid = (__uid32_t) -1;
+ sec_peer_gid = (__gid32_t) -1;
}
-int
-fhandler_socket::open (int flags, mode_t mode)
+void
+fhandler_socket::af_local_copy (fhandler_socket *sock)
{
- set_errno (ENXIO);
- return 0;
+ sock->connect_secret[0] = connect_secret[0];
+ sock->connect_secret[1] = connect_secret[1];
+ sock->connect_secret[2] = connect_secret[2];
+ sock->connect_secret[3] = connect_secret[3];
+ sock->sec_pid = sec_pid;
+ sock->sec_uid = sec_uid;
+ sock->sec_gid = sec_gid;
+ sock->sec_peer_pid = sec_peer_pid;
+ sock->sec_peer_uid = sec_peer_uid;
+ sock->sec_peer_gid = sec_peer_gid;
}
void
-fhandler_socket::set_connect_secret ()
+fhandler_socket::af_local_set_secret (char *buf)
{
if (!entropy_source)
{
@@ -291,160 +376,11 @@ fhandler_socket::set_connect_secret ()
if (len != sizeof (connect_secret))
bzero ((char*) connect_secret, sizeof (connect_secret));
}
-}
-
-void
-fhandler_socket::get_connect_secret (char* buf)
-{
__small_sprintf (buf, "%08x-%08x-%08x-%08x",
connect_secret [0], connect_secret [1],
connect_secret [2], connect_secret [3]);
}
-HANDLE
-fhandler_socket::create_secret_event ()
-{
- struct sockaddr_in sin;
- int sin_len = sizeof (sin);
-
- if (secret_event)
- return secret_event;
-
- if (::getsockname (get_socket (), (struct sockaddr*) &sin, &sin_len))
- {
- debug_printf ("error getting local socket name (%d)", WSAGetLastError ());
- return NULL;
- }
-
- char event_name[CYG_MAX_PATH];
- secret_event_name (event_name, sin.sin_port, connect_secret);
- secret_event = CreateEvent (&sec_all, FALSE, FALSE, event_name);
-
- if (!secret_event)
- debug_printf("create event %E");
- else if (close_on_exec ())
- /* Event allows inheritance, but handle will not be inherited */
- set_no_inheritance (secret_event, 1);
-
- return secret_event;
-}
-
-void
-fhandler_socket::signal_secret_event ()
-{
- if (!secret_event)
- debug_printf ("no secret event?");
- else
- {
- SetEvent (secret_event);
- debug_printf ("signaled secret_event");
- }
-}
-
-void
-fhandler_socket::close_secret_event ()
-{
- if (secret_event)
- CloseHandle (secret_event);
- secret_event = NULL;
-}
-
-int
-fhandler_socket::check_peer_secret_event (struct sockaddr_in *peer)
-{
-
- char event_name[CYG_MAX_PATH];
-
- secret_event_name (event_name, peer->sin_port, connect_secret);
- HANDLE ev = CreateEvent (&sec_all_nih, FALSE, FALSE, event_name);
- if (!ev)
- debug_printf("create event %E");
-
- signal_secret_event ();
-
- if (ev)
- {
- DWORD rc = WaitForSingleObject (ev, 10000);
- debug_printf ("WFSO rc=%d", rc);
- CloseHandle (ev);
- return (rc == WAIT_OBJECT_0 ? 1 : 0);
- }
- else
- return 0;
-}
-
-int
-fhandler_socket::sec_event_connect (struct sockaddr_in *peer)
-{
- bool secret_check_failed = false;
- struct sockaddr_in sin;
- int siz = sizeof sin;
-
- debug_printf ("sec_event_connect called");
- if (!peer)
- {
- if (::getpeername (get_socket (), (struct sockaddr *) &sin, &siz))
- goto err;
- peer = &sin;
- }
- if (!create_secret_event ())
- secret_check_failed = true;
- if (!secret_check_failed && !check_peer_secret_event (peer))
- {
- debug_printf ("accept from unauthorized server");
- secret_check_failed = true;
- }
- if (!secret_check_failed)
- return 0;
-
-err:
- close_secret_event ();
- closesocket (get_socket ());
- WSASetLastError (WSAECONNREFUSED);
- set_winsock_errno ();
- return -1;
-}
-
-/* Called from select(). It combines the secret event handshake and
- the eid credential transaction into one call. This keeps implementation
- details from select. */
-int
-fhandler_socket::af_local_connect (void)
-{
- if (get_addr_family () != AF_LOCAL || get_socket_type () != SOCK_STREAM)
- return 0;
- int ret = sec_event_connect (NULL);
- if (!ret)
- eid_connect ();
- return ret;
-}
-
-int
-fhandler_socket::sec_event_accept (int sock, struct sockaddr_in *peer)
-{
- bool secret_check_failed = false;
-
- debug_printf ("sec_event_accept called");
-
- if (!create_secret_event ())
- secret_check_failed = true;
-
- if (!secret_check_failed
- && !check_peer_secret_event (peer))
- {
- debug_printf ("connect from unauthorized client");
- secret_check_failed = true;
- }
- if (secret_check_failed)
- {
- close_secret_event ();
- closesocket (sock);
- set_errno (ECONNABORTED);
- return -1;
- }
- return sock;
-}
-
void
fhandler_socket::fixup_before_fork_exec (DWORD win_proc_id)
{
@@ -493,9 +429,6 @@ fhandler_socket::fixup_after_fork (HANDLE parent)
debug_printf ("WSASocket went fine new_sock %p, old_sock %p", new_sock, get_io_handle ());
set_io_handle ((HANDLE) new_sock);
}
-
- if (secret_event)
- fork_fixup (parent, secret_event, "secret_event");
}
void
@@ -722,11 +655,9 @@ fhandler_socket::bind (const struct sockaddr *name, int namelen)
__seterrno ();
}
- set_connect_secret ();
-
char buf[sizeof (SOCKET_COOKIE) + 80];
__small_sprintf (buf, "%s%u ", SOCKET_COOKIE, sin.sin_port);
- get_connect_secret (strchr (buf, '\0'));
+ af_local_set_secret (strchr (buf, '\0'));
DWORD blen = strlen (buf) + 1;
if (!WriteFile (fh, buf, blen, &blen, 0))
{
@@ -789,23 +720,13 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen)
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) 0;
- sec_peer_uid = (__uid32_t) -1;
- sec_peer_gid = (__gid32_t) -1;
-
- if (!res)
- res = sec_event_connect (&sin);
-
- if (!res)
- {
- /* eid credential transaction. If connect is in progress,
- we're deferring the eid transaction to the successful select,
- see select.cc, function set_bits(). */
- eid_connect ();
+ af_local_set_cred (); /* Don't move into af_local_connect since
+ af_local_connect is called from select,
+ possibly running under another identity. */
+ if (!res && af_local_connect ())
+ {
+ set_winsock_errno ();
+ return -1;
}
}
@@ -826,15 +747,7 @@ fhandler_socket::listen (int backlog)
else
{
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) 0;
- sec_peer_uid = (__uid32_t) -1;
- sec_peer_gid = (__gid32_t) -1;
- }
+ af_local_set_cred ();
connect_state (connected);
}
return res;
@@ -865,11 +778,7 @@ fhandler_socket::accept (struct sockaddr *peer, int *len)
res = ::accept (get_socket (), peer, len);
- if ((SOCKET) res != INVALID_SOCKET && get_addr_family () == AF_LOCAL
- && get_socket_type () == SOCK_STREAM)
- res = sec_event_accept (res, (struct sockaddr_in *) peer);
-
- if ((SOCKET) res == INVALID_SOCKET)
+ if (res == (int) INVALID_SOCKET)
set_winsock_errno ();
else
{
@@ -889,13 +798,14 @@ fhandler_socket::accept (struct sockaddr *peer, int *len)
/* Don't forget to copy credentials from accepting
socket to accepted socket and start transaction
on accepted socket! */
- sock->sec_pid = sec_pid;
- sock->sec_uid = sec_uid;
- sock->sec_gid = sec_gid;
- sock->sec_peer_pid = sec_peer_pid;
- sock->sec_peer_uid = sec_peer_uid;
- sock->sec_peer_gid = sec_peer_gid;
- sock->eid_accept ();
+ af_local_copy (sock);
+ res = sock->af_local_accept ();
+ if (res == -1)
+ {
+ res_fd.release ();
+ set_winsock_errno ();
+ goto out;
+ }
}
}
sock->connect_state (connected);
@@ -908,6 +818,7 @@ fhandler_socket::accept (struct sockaddr *peer, int *len)
}
}
+out:
debug_printf ("res %d", res);
return res;
}
@@ -1524,8 +1435,6 @@ fhandler_socket::close ()
WSASetLastError (0);
}
- close_secret_event ();
-
debug_printf ("%d = fhandler_socket::close()", res);
return res;
}
@@ -1709,8 +1618,6 @@ fhandler_socket::fcntl (int cmd, void *arg)
void
fhandler_socket::set_close_on_exec (bool val)
{
- if (secret_event)
- set_no_inheritance (secret_event, val);
if (!winsock2_active) /* < Winsock 2.0 */
set_no_inheritance (get_handle (), val);
close_on_exec (val);