* 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.
This commit is contained in:
		| @@ -1,3 +1,75 @@ | ||||
| 2005-03-23  Corinna Vinschen  <corinna@vinschen.de> | ||||
|  | ||||
| 	* 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. | ||||
|  | ||||
| 2005-03-23  Christopher Faylor  <cgf@timesys.com> | ||||
|  | ||||
| 	* include/ctype.h: Always define macros when inside cygwin. | ||||
|   | ||||
| @@ -363,7 +363,6 @@ class fhandler_socket: public fhandler_base | ||||
|   int addr_family; | ||||
|   int type; | ||||
|   int connect_secret[4]; | ||||
|   HANDLE secret_event; | ||||
|  | ||||
|   pid_t     sec_pid; | ||||
|   __uid32_t sec_uid; | ||||
| @@ -371,14 +370,19 @@ class fhandler_socket: public fhandler_base | ||||
|   pid_t     sec_peer_pid; | ||||
|   __uid32_t sec_peer_uid; | ||||
|   __gid32_t sec_peer_gid; | ||||
|   void eid_setblocking (bool &, bool &); | ||||
|   void eid_unsetblocking (bool, bool); | ||||
|   bool eid_recv (void); | ||||
|   bool eid_send (void); | ||||
|   void eid_accept (void); | ||||
|   void eid_connect (void); | ||||
|   void af_local_set_secret (char *); | ||||
|   void af_local_setblocking (bool &, bool &); | ||||
|   void af_local_unsetblocking (bool, bool); | ||||
|   void af_local_set_cred (void); | ||||
|   void af_local_copy (fhandler_socket *); | ||||
|   bool af_local_recv_secret (void); | ||||
|   bool af_local_send_secret (void); | ||||
|   bool af_local_recv_cred (void); | ||||
|   bool af_local_send_cred (void); | ||||
|   int af_local_accept (void); | ||||
|  public: | ||||
|   void set_socketpair_eids (void); | ||||
|   int af_local_connect (void); | ||||
|   void af_local_set_sockpair_cred (void); | ||||
|  | ||||
|  private: | ||||
|   struct _WSAPROTOCOL_INFOA *prot_info_ptr; | ||||
| @@ -459,18 +463,6 @@ class fhandler_socket: public fhandler_base | ||||
|   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 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))); | ||||
|   | ||||
| @@ -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"); | ||||
|   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); | ||||
| } | ||||
|   /* This keeps the test out of select. */ | ||||
|   if (get_addr_family () != AF_LOCAL || get_socket_type () != SOCK_STREAM) | ||||
|     return 0; | ||||
|  | ||||
| void | ||||
| fhandler_socket::eid_accept (void) | ||||
| { | ||||
|   debug_printf ("eid_accept called"); | ||||
|   debug_printf ("af_local_connect 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); | ||||
| } | ||||
|  | ||||
| char * | ||||
| fhandler_socket::get_proc_fd_name (char *buf) | ||||
|   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 ()) | ||||
|     { | ||||
|   __small_sprintf (buf, "socket:[%d]", get_socket ()); | ||||
|   return buf; | ||||
|       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; | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_socket::open (int flags, mode_t mode) | ||||
| fhandler_socket::af_local_accept (void) | ||||
| { | ||||
|   set_errno (ENXIO); | ||||
|   debug_printf ("af_local_accept called"); | ||||
|   bool 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; | ||||
| } | ||||
|  | ||||
| void | ||||
| fhandler_socket::set_connect_secret () | ||||
| fhandler_socket::af_local_set_cred (void) | ||||
| { | ||||
|   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; | ||||
| } | ||||
|  | ||||
| void | ||||
| fhandler_socket::af_local_copy (fhandler_socket *sock) | ||||
| { | ||||
|   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::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) | ||||
|       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 ()) | ||||
| 	{ | ||||
| 	  /* 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 (); | ||||
| 	  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); | ||||
|   | ||||
| @@ -790,6 +790,7 @@ cygwin_getsockopt (int fd, int level, int optname, void *optval, int *optlen) | ||||
| 	{ | ||||
| 	  int *e = (int *) optval; | ||||
|  | ||||
| 	  debug_printf ("WinSock SO_ERROR = %d", *e); | ||||
| 	  *e = find_winsock_errno (*e); | ||||
| 	} | ||||
|  | ||||
| @@ -2162,7 +2163,7 @@ socketpair (int family, int type, int protocol, int *sb) | ||||
| 	((fhandler_socket *) sb0)->set_socket_type (type); | ||||
| 	((fhandler_socket *) sb0)->connect_state (connected); | ||||
| 	if (family == AF_LOCAL && type == SOCK_STREAM) | ||||
| 	  ((fhandler_socket *) sb0)->set_socketpair_eids (); | ||||
| 	  ((fhandler_socket *) sb0)->af_local_set_sockpair_cred (); | ||||
|  | ||||
| 	cygheap_fdnew sb1 (sb0, false); | ||||
|  | ||||
| @@ -2173,7 +2174,7 @@ socketpair (int family, int type, int protocol, int *sb) | ||||
| 	    ((fhandler_socket *) sb1)->set_socket_type (type); | ||||
| 	    ((fhandler_socket *) sb1)->connect_state (connected); | ||||
| 	    if (family == AF_LOCAL && type == SOCK_STREAM) | ||||
| 	      ((fhandler_socket *) sb1)->set_socketpair_eids (); | ||||
| 	      ((fhandler_socket *) sb1)->af_local_set_sockpair_cred (); | ||||
|  | ||||
| 	    sb[0] = sb0; | ||||
| 	    sb[1] = sb1; | ||||
|   | ||||
| @@ -352,14 +352,8 @@ set_bits (select_record *me, fd_set *readfds, fd_set *writefds, | ||||
| 	{ | ||||
| 	  UNIX_FD_SET (me->fd, writefds); | ||||
| 	  if ((sock = me->fh->is_socket ())) | ||||
| 	    { | ||||
| 	      /* 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); | ||||
| 	} | ||||
| 	} | ||||
|       if (me->except_selected) | ||||
| 	UNIX_FD_SET (me->fd, exceptfds); | ||||
|       ready++; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user