OSDN Git Service

* cygwin.din (getpeereid): Export.
authorcorinna <corinna>
Wed, 23 Feb 2005 17:39:44 +0000 (17:39 +0000)
committercorinna <corinna>
Wed, 23 Feb 2005 17:39:44 +0000 (17:39 +0000)
* 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.

winsup/cygwin/ChangeLog
winsup/cygwin/cygwin.din
winsup/cygwin/fhandler.h
winsup/cygwin/fhandler_socket.cc
winsup/cygwin/include/asm/socket.h
winsup/cygwin/include/cygwin/socket.h
winsup/cygwin/include/cygwin/version.h
winsup/cygwin/net.cc

index a02fb4e..4e77c59 100644 (file)
@@ -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.
 
index dd8e5a8..594f114 100644 (file)
@@ -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
index 3199351..d3250d1 100644 (file)
@@ -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);
index 9f0b39f..b5b4847 100644 (file)
@@ -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;
+}
index b1392ce..ed06219 100644 (file)
@@ -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.
index 67e1345..f6dc113 100644 (file)
@@ -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       */
index 10cf2ba..11db44c 100644 (file)
@@ -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
index 33356d1..98e121c 100644 (file)
@@ -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)