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>2014-10-11 22:28:04 +0400
committerCorinna Vinschen <corinna@vinschen.de>2014-10-11 22:28:04 +0400
commit697b9afe00c21df9fc74c748ea35113b4b37c4b4 (patch)
treefd3a5755a6880643d192ebb7043dd501dedd1505 /winsup/cygwin
parenta85ab1d48243778e745b8f04b3eb67b8c13a64ad (diff)
Add setsockopt(sd, SOL_SOCKET, SO_PEERCRED, NULL, 0) to disable
initial handshake on AF_LOCAL sockets. * fhandler.h (class fhandler_socket): Add no_getpeereid status flag. (fhandler_socket::af_local_set_no_getpeereid): New prototype. * fhandler_socket.cc (fhandler_socket::af_local_connect): Skip handshake if no_getpeereid is set. Add debug output. (fhandler_socket::af_local_accept): Likewise. (fhandler_socket::af_local_set_no_getpeereid): New function. (fhandler_socket::af_local_copy): Copy no_getpeereid. (fhandler_socket::getpeereid): Fail if no_getpeereid is set. * net.cc (cygwin_setsockopt): Add SO_PEERCRED for AF_LOCAL/SOCK_STREAM sockets. Add comment to explain why we need it. * include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump.
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/ChangeLog16
-rw-r--r--winsup/cygwin/fhandler.h5
-rw-r--r--winsup/cygwin/fhandler_socket.cc35
-rw-r--r--winsup/cygwin/include/cygwin/version.h3
-rw-r--r--winsup/cygwin/net.cc19
5 files changed, 74 insertions, 4 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index ce4102ca9..b9e11747c 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,19 @@
+2014-10-11 Christian Franke <franke@computer.org>
+
+ Add setsockopt(sd, SOL_SOCKET, SO_PEERCRED, NULL, 0) to disable
+ initial handshake on AF_LOCAL sockets.
+ * fhandler.h (class fhandler_socket): Add no_getpeereid status flag.
+ (fhandler_socket::af_local_set_no_getpeereid): New prototype.
+ * fhandler_socket.cc (fhandler_socket::af_local_connect): Skip handshake
+ if no_getpeereid is set. Add debug output.
+ (fhandler_socket::af_local_accept): Likewise.
+ (fhandler_socket::af_local_set_no_getpeereid): New function.
+ (fhandler_socket::af_local_copy): Copy no_getpeereid.
+ (fhandler_socket::getpeereid): Fail if no_getpeereid is set.
+ * net.cc (cygwin_setsockopt): Add SO_PEERCRED for AF_LOCAL/SOCK_STREAM
+ sockets. Add comment to explain why we need it.
+ * include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump.
+
2014-10-11 Corinna Vinschen <corinna@vinschen.de>
* fhandler_socket.cc (fhandler_socket::af_local_connect): Drop outdated
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index cf4de0746..aff8d85e0 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -504,6 +504,7 @@ class fhandler_socket: public fhandler_base
int af_local_accept ();
public:
int af_local_connect ();
+ int af_local_set_no_getpeereid ();
void af_local_set_sockpair_cred ();
private:
@@ -531,10 +532,11 @@ class fhandler_socket: public fhandler_base
unsigned saw_shutdown_write : 1; /* Socket saw a SHUT_WR */
unsigned saw_reuseaddr : 1; /* Socket saw SO_REUSEADDR call */
unsigned connect_state : 3;
+ unsigned no_getpeereid : 1;
public:
status_flags () :
async_io (0), saw_shutdown_read (0), saw_shutdown_write (0),
- connect_state (unconnected)
+ connect_state (unconnected), no_getpeereid (0)
{}
} status;
@@ -556,6 +558,7 @@ class fhandler_socket: public fhandler_base
IMPLEMENT_STATUS_FLAG (bool, saw_shutdown_write)
IMPLEMENT_STATUS_FLAG (bool, saw_reuseaddr)
IMPLEMENT_STATUS_FLAG (conn_state, connect_state)
+ IMPLEMENT_STATUS_FLAG (bool, no_getpeereid)
int bind (const struct sockaddr *name, int namelen);
int connect (const struct sockaddr *name, int namelen);
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index e2750ea72..ff150448e 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -401,7 +401,10 @@ fhandler_socket::af_local_connect ()
if (get_addr_family () != AF_LOCAL || get_socket_type () != SOCK_STREAM)
return 0;
- debug_printf ("af_local_connect called");
+ debug_printf ("af_local_connect called, no_getpeereid=%d", no_getpeereid ());
+ if (no_getpeereid ())
+ return 0;
+
connect_state (connect_credxchg);
af_local_setblocking (orig_async_io, orig_is_nonblocking);
if (!af_local_send_secret () || !af_local_recv_secret ()
@@ -421,7 +424,10 @@ fhandler_socket::af_local_accept ()
{
bool orig_async_io, orig_is_nonblocking;
- debug_printf ("af_local_accept called");
+ debug_printf ("af_local_accept called, no_getpeereid=%d", no_getpeereid ());
+ if (no_getpeereid ())
+ return 0;
+
connect_state (connect_credxchg);
af_local_setblocking (orig_async_io, orig_is_nonblocking);
if (!af_local_recv_secret () || !af_local_send_secret ()
@@ -437,6 +443,25 @@ fhandler_socket::af_local_accept ()
return 0;
}
+int
+fhandler_socket::af_local_set_no_getpeereid ()
+{
+ if (get_addr_family () != AF_LOCAL || get_socket_type () != SOCK_STREAM)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ if (connect_state () != unconnected)
+ {
+ set_errno (EALREADY);
+ return -1;
+ }
+
+ debug_printf ("no_getpeereid set");
+ no_getpeereid (true);
+ return 0;
+}
+
void
fhandler_socket::af_local_set_cred ()
{
@@ -461,6 +486,7 @@ fhandler_socket::af_local_copy (fhandler_socket *sock)
sock->sec_peer_pid = sec_peer_pid;
sock->sec_peer_uid = sec_peer_uid;
sock->sec_peer_gid = sec_peer_gid;
+ sock->no_getpeereid (no_getpeereid ());
}
void
@@ -2303,6 +2329,11 @@ fhandler_socket::getpeereid (pid_t *pid, uid_t *euid, gid_t *egid)
set_errno (EINVAL);
return -1;
}
+ if (no_getpeereid ())
+ {
+ set_errno (ENOTSUP);
+ return -1;
+ }
if (connect_state () != connected)
{
set_errno (ENOTCONN);
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index a5c482da9..66fad063a 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -452,12 +452,13 @@ details. */
CW_GETENT, CW_ENDENT, CW_GETNSSSEP, CW_GETPWSID, CW_GETGRSID,
CW_CYGNAME_FROM_WINNAME.
276: Export ffsl, ffsll.
+ 277: Add setsockopt(SO_PEERCRED).
*/
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 276
+#define CYGWIN_VERSION_API_MINOR 277
/* 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 b6c0f7257..a01dbedf1 100644
--- a/winsup/cygwin/net.cc
+++ b/winsup/cygwin/net.cc
@@ -810,6 +810,25 @@ cygwin_setsockopt (int fd, int level, int optname, const void *optval,
fhandler_socket *fh = get (fd);
if (!fh)
__leave;
+
+ /* Switch off the AF_LOCAL handshake and thus SO_PEERCRED handling
+ for AF_LOCAL/SOCK_STREAM sockets. This allows to handle special
+ situations in which connect is called before a listening socket
+ accepts connections.
+ FIXME: In the long run we should find a more generic solution which
+ doesn't require a blocking handshake in accept/connect to exchange
+ SO_PEERCRED credentials. */
+ if (level == SOL_SOCKET && optname == SO_PEERCRED)
+ {
+ if (optval || optlen
+ || fh->get_addr_family () != AF_LOCAL
+ || fh->get_socket_type () != SOCK_STREAM)
+ set_errno (EINVAL);
+ else
+ res = fh->af_local_set_no_getpeereid ();
+ __leave;
+ }
+
/* Old applications still use the old WinSock1 IPPROTO_IP values. */
if (level == IPPROTO_IP && CYGWIN_VERSION_CHECK_FOR_USING_WINSOCK1_VALUES)
optname = convert_ws1_ip_optname (optname);