aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2005-03-23 17:27:18 +0000
committerCorinna Vinschen <corinna@vinschen.de>2005-03-23 17:27:18 +0000
commita6099ff810747d2830edebc836202ff8dae1ead7 (patch)
tree3c79a17be098abb709311e8893488d2c3c116d33
parentbc3f9e29d0baa7d8ad07567a7780473c0fd3edcc (diff)
downloadnewlib-a6099ff810747d2830edebc836202ff8dae1ead7.zip
newlib-a6099ff810747d2830edebc836202ff8dae1ead7.tar.gz
newlib-a6099ff810747d2830edebc836202ff8dae1ead7.tar.bz2
* fhandler.h (fhandler_socket::eid_connect): Make private.
(fhandler_socket::set_connect_secret): Ditto. (fhandler_socket::get_connect_secret): Ditto. (fhandler_socket::create_secret_event): Ditto. Remove secret argument. (fhandler_socket::check_peer_secret_event): Ditto. (fhandler_socket::signal_secret_event): Make private. (fhandler_socket::close_secret_event): Ditto. (fhandler_socket::sec_event_accept): New private method. (fhandler_socket::sec_event_connect): Ditto. (fhandler_socket::af_local_connect): New public method. * fhandler_socket.cc: Use 'struct sockaddr' and 'struct sockaddr_in' rather than just 'sockaddr' and 'sockaddr_in' throughout. (fhandler_socket::eid_connect): Drop AF_LOCAL/SOCK_STREAM test. (fhandler_socket::create_secret_event): Remove secret argument. Always use connect_secret instead. (fhandler_socket::check_peer_secret_event): Ditto. (fhandler_socket::sec_event_connect): New method, combining entire secret event handshake on connect side. (fhandler_socket::af_local_connect): New method, combining secret event handshake and eid credential transaction on connect side, to be called from select. (fhandler_socket::sec_event_accept): New method, combining entire secret event handshake on accept side. (fhandler_socket::connect): Drop secret, use connect_secret instead. Move entire secret event handshake to sec_event_connect. (fhandler_socket::accept): Move entire secret event handshake to sec_event_accept. * select.cc (set_bits): Just call af_local_connect here.
-rw-r--r--winsup/cygwin/ChangeLog31
-rw-r--r--winsup/cygwin/fhandler.h13
-rw-r--r--winsup/cygwin/fhandler_socket.cc152
-rw-r--r--winsup/cygwin/select.cc15
4 files changed, 135 insertions, 76 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index ad38fde..f10a698 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,34 @@
+2005-03-23 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler.h (fhandler_socket::eid_connect): Make private.
+ (fhandler_socket::set_connect_secret): Ditto.
+ (fhandler_socket::get_connect_secret): Ditto.
+ (fhandler_socket::create_secret_event): Ditto. Remove secret argument.
+ (fhandler_socket::check_peer_secret_event): Ditto.
+ (fhandler_socket::signal_secret_event): Make private.
+ (fhandler_socket::close_secret_event): Ditto.
+ (fhandler_socket::sec_event_accept): New private method.
+ (fhandler_socket::sec_event_connect): Ditto.
+ (fhandler_socket::af_local_connect): New public method.
+ * fhandler_socket.cc: Use 'struct sockaddr' and 'struct sockaddr_in'
+ rather than just 'sockaddr' and 'sockaddr_in' throughout.
+ (fhandler_socket::eid_connect): Drop AF_LOCAL/SOCK_STREAM test.
+ (fhandler_socket::create_secret_event): Remove secret argument.
+ Always use connect_secret instead.
+ (fhandler_socket::check_peer_secret_event): Ditto.
+ (fhandler_socket::sec_event_connect): New method, combining entire
+ secret event handshake on connect side.
+ (fhandler_socket::af_local_connect): New method, combining secret
+ event handshake and eid credential transaction on connect side, to
+ be called from select.
+ (fhandler_socket::sec_event_accept): New method, combining entire
+ secret event handshake on accept side.
+ (fhandler_socket::connect): Drop secret, use connect_secret instead.
+ Move entire secret event handshake to sec_event_connect.
+ (fhandler_socket::accept): Move entire secret event handshake to
+ sec_event_accept.
+ * select.cc (set_bits): Just call af_local_connect here.
+
2005-03-23 Christopher Faylor <cgf@timesys.com>
* include/cygwin/version.h: Change coment for most recent API version
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 1ca95d3..2f14246 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -376,8 +376,8 @@ class fhandler_socket: public fhandler_base
bool eid_recv (void);
bool eid_send (void);
void eid_accept (void);
- public:
void eid_connect (void);
+ public:
void set_socketpair_eids (void);
private:
@@ -458,12 +458,19 @@ class fhandler_socket: public fhandler_base
int get_socket_type () {return type;}
void set_sun_path (const char *path);
char *get_sun_path () {return sun_path;}
+
+ private:
void set_connect_secret ();
void get_connect_secret (char*);
- HANDLE create_secret_event (int *secret = NULL);
- int check_peer_secret_event (struct sockaddr_in *peer, int *secret = NULL);
+ HANDLE create_secret_event ();
+ int check_peer_secret_event (struct sockaddr_in *peer);
void signal_secret_event ();
void close_secret_event ();
+ int sec_event_accept (int, struct sockaddr_in *);
+ int sec_event_connect (struct sockaddr_in *peer);
+ public:
+ int af_local_connect (void);
+
int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2)));
int __stdcall fchmod (mode_t mode) __attribute__ ((regparm (1)));
int __stdcall fchown (__uid32_t uid, __gid32_t gid) __attribute__ ((regparm (2)));
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index e7194df..d2892e2 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -65,7 +65,7 @@ get_inet_addr (const struct sockaddr *in, int inlen,
if (in->sa_family == AF_INET)
{
- *out = * (sockaddr_in *)in;
+ *out = * (struct sockaddr_in *)in;
*outlen = inlen;
return 1;
}
@@ -100,7 +100,7 @@ get_inet_addr (const struct sockaddr *in, int inlen,
memset (buf, 0, sizeof buf);
if (ReadFile (fh, buf, 128, &len, 0))
{
- sockaddr_in sin;
+ struct sockaddr_in sin;
sin.sin_family = AF_INET;
sscanf (buf + strlen (SOCKET_COOKIE), "%hu %08x-%08x-%08x-%08x",
&sin.sin_port,
@@ -238,10 +238,6 @@ fhandler_socket::eid_send (void)
void
fhandler_socket::eid_connect (void)
{
- /* This test allows to keep select.cc clean from boring implementation
- details. */
- if (get_addr_family () != AF_LOCAL || get_socket_type () != SOCK_STREAM)
- return;
debug_printf ("eid_connect called");
bool orig_async_io, orig_is_nonblocking;
eid_setblocking (orig_async_io, orig_is_nonblocking);
@@ -306,7 +302,7 @@ fhandler_socket::get_connect_secret (char* buf)
}
HANDLE
-fhandler_socket::create_secret_event (int* secret)
+fhandler_socket::create_secret_event ()
{
struct sockaddr_in sin;
int sin_len = sizeof (sin);
@@ -321,7 +317,7 @@ fhandler_socket::create_secret_event (int* secret)
}
char event_name[CYG_MAX_PATH];
- secret_event_name (event_name, sin.sin_port, secret ?: connect_secret);
+ secret_event_name (event_name, sin.sin_port, connect_secret);
secret_event = CreateEvent (&sec_all, FALSE, FALSE, event_name);
if (!secret_event)
@@ -354,12 +350,12 @@ fhandler_socket::close_secret_event ()
}
int
-fhandler_socket::check_peer_secret_event (struct sockaddr_in* peer, int* secret)
+fhandler_socket::check_peer_secret_event (struct sockaddr_in *peer)
{
char event_name[CYG_MAX_PATH];
- secret_event_name (event_name, peer->sin_port, secret ?: connect_secret);
+ 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");
@@ -377,6 +373,78 @@ fhandler_socket::check_peer_secret_event (struct sockaddr_in* peer, int* secret)
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)
{
@@ -687,16 +755,14 @@ int
fhandler_socket::connect (const struct sockaddr *name, int namelen)
{
int res = -1;
- bool secret_check_failed = false;
bool in_progress = false;
- sockaddr_in sin;
- int secret [4];
+ struct sockaddr_in sin;
DWORD err;
- if (!get_inet_addr (name, namelen, &sin, &namelen, secret))
+ if (!get_inet_addr (name, namelen, &sin, &namelen, connect_secret))
return -1;
- res = ::connect (get_socket (), (sockaddr *) &sin, namelen);
+ res = ::connect (get_socket (), (struct sockaddr *) &sin, namelen);
if (!res)
err = 0;
@@ -723,34 +789,6 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen)
if (get_addr_family () == AF_LOCAL && get_socket_type () == SOCK_STREAM)
{
- if (!res || in_progress)
- {
- if (!create_secret_event (secret))
- {
- secret_check_failed = true;
- }
- else if (in_progress)
- signal_secret_event ();
- }
-
- if (!secret_check_failed && !res)
- {
- if (!check_peer_secret_event (&sin, secret))
- {
- debug_printf ("accept from unauthorized server");
- secret_check_failed = true;
- }
- }
-
- if (secret_check_failed)
- {
- close_secret_event ();
- if (res)
- closesocket (res);
- set_errno (ECONNREFUSED);
- res = -1;
- }
-
/* Prepare eid credential transaction. */
sec_pid = getpid ();
sec_uid = geteuid32 ();
@@ -760,6 +798,9 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen)
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,
@@ -803,7 +844,6 @@ int
fhandler_socket::accept (struct sockaddr *peer, int *len)
{
int res = -1;
- bool secret_check_failed = false;
/* Allows NULL peer and len parameters. */
struct sockaddr_in peer_dummy;
@@ -827,27 +867,7 @@ fhandler_socket::accept (struct sockaddr *peer, int *len)
if ((SOCKET) res != INVALID_SOCKET && get_addr_family () == AF_LOCAL
&& get_socket_type () == SOCK_STREAM)
- {
- if (!create_secret_event ())
- secret_check_failed = true;
-
- if (!secret_check_failed)
- {
- if (!check_peer_secret_event ((struct sockaddr_in*) peer))
- {
- debug_printf ("connect from unauthorized client");
- secret_check_failed = true;
- }
- }
-
- if (secret_check_failed)
- {
- close_secret_event ();
- closesocket (res);
- set_errno (ECONNABORTED);
- return -1;
- }
- }
+ res = sec_event_accept (res, (struct sockaddr_in *) peer);
if ((SOCKET) res == INVALID_SOCKET)
set_winsock_errno ();
@@ -1256,7 +1276,7 @@ int
fhandler_socket::sendto (const void *ptr, size_t len, int flags,
const struct sockaddr *to, int tolen)
{
- sockaddr_in sin;
+ struct sockaddr_in sin;
if (to && !get_inet_addr (to, tolen, &sin, &tolen))
return SOCKET_ERROR;
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index 8b77d2a..a884ea1 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -338,11 +338,10 @@ set_bits (select_record *me, fd_set *readfds, fd_set *writefds,
UNIX_FD_SET (me->fd, writefds);
if (me->except_on_write && (sock = me->fh->is_socket ()))
{
- /* eid credential transaction on successful non-blocking connect.
- Since the read bit indicates an error, don't start transaction
- if it's set. */
- if (!me->read_ready && sock->connect_state () == connect_pending)
- sock->eid_connect ();
+ /* Special AF_LOCAL handling. */
+ if (!me->read_ready && sock->connect_state () == connect_pending
+ && sock->af_local_connect () && me->read_selected)
+ UNIX_FD_SET (me->fd, readfds);
sock->connect_state (connected);
}
ready++;
@@ -354,8 +353,10 @@ set_bits (select_record *me, fd_set *readfds, fd_set *writefds,
UNIX_FD_SET (me->fd, writefds);
if ((sock = me->fh->is_socket ()))
{
- if (!me->read_ready && sock->connect_state () == connect_pending)
- sock->eid_connect ();
+ /* Special AF_LOCAL handling. */
+ if (!me->read_ready && sock->connect_state () == connect_pending
+ && sock->af_local_connect () && me->read_selected)
+ UNIX_FD_SET (me->fd, readfds);
sock->connect_state (connected);
}
}