[#7978] Patch for Unix socket peer credentials — "James F. Hranicky" <jfh@...>

This patch adds support for getting the uid and gid of the peer

27 messages 2006/06/09
[#8004] Re: Patch for Unix socket peer credentials — Tanaka Akira <akr@...17n.org> 2006/06/16

In article <200606091528.30171.jfh@cise.ufl.edu>,

[#8005] Re: Patch for Unix socket peer credentials — "James F. Hranicky" <jfh@...> 2006/06/16

On Friday 16 June 2006 11:51, Tanaka Akira wrote:

[#8010] Re: Patch for Unix socket peer credentials — Tanaka Akira <akr@...17n.org> 2006/06/17

In article <200606161327.35948.jfh@cise.ufl.edu>,

[#8191] Re: Patch for Unix socket peer credentials — "James F. Hranicky" <jfh@...> 2006/07/10

On Saturday 17 June 2006 06:27, Tanaka Akira wrote:

[#8193] Re: Patch for Unix socket peer credentials — Tanaka Akira <akr@...> 2006/07/11

In article <200607101352.16804.jfh@cise.ufl.edu>,

[#8212] Re: Patch for Unix socket peer credentials — "James F. Hranicky" <jfh@...> 2006/07/13

On Tuesday 11 July 2006 00:10, Tanaka Akira wrote:

[#8217] Re: Patch for Unix socket peer credentials — nobu@... 2006/07/14

Hi,

[#8257] Re: Patch for Unix socket peer credentials — "James F. Hranicky" <jfh@...> 2006/07/18

On Thursday 13 July 2006 22:48, nobu@ruby-lang.org wrote:

[#8258] Re: Patch for Unix socket peer credentials — Eric Hodel <drbrain@...7.net> 2006/07/18

On Jul 18, 2006, at 12:27 PM, James F. Hranicky wrote:

[#8073] 1.8.5p1 build failure on Solaris 10 — "Daniel Berger" <Daniel.Berger@...>

Solaris 10

23 messages 2006/06/27
[#8074] Re: 1.8.5p1 build failure on Solaris 10 — Yukihiro Matsumoto <matz@...> 2006/06/28

Hi,

[#8078] Re: 1.8.5p1 build failure on Solaris 10 — "Daniel Berger" <Daniel.Berger@...> 2006/06/28

Yukihiro Matsumoto wrote:

[#8079] Re: 1.8.5p1 build failure on Solaris 10 — ts <decoux@...> 2006/06/28

>>>>> "D" == Daniel Berger <Daniel.Berger@qwest.com> writes:

[#8096] Re: 1.8.5p1 build failure on Solaris 10 — ville.mattila@... 2006/06/29

ts <decoux@moulon.inra.fr> wrote on 28.06.2006 17:37:00:

Patch for Unix socket peer credentials

From: "James F. Hranicky" <jfh@...>
Date: 2006-06-09 19:28:36 UTC
List: ruby-core #7978
This patch adds support for getting the uid and gid of the peer
socket connected to a Unix domain socket.

The patch is really just a suggestion, as you can't necessarily get the
same kinds of information across platforms. Unless I'm mistaken this is
what you can get for the following platforms:

	FreeBSD, OSX (getpeereid)   : euid, egid
	Linux        (getsockopt)   : pid, uid, gid
	Solaris 10   (getpeerucred) : uid, euid, gid, egid, pid and more

The patch adds checks to extconf.rb for the getpeereid and getpeerucred
functions and a check for the SO_PEERCRED macro. If none of these are
found calls to the peer_uid and peer_gid method raise an error. 

Questions and comments welcome, and I'm open to suggestions for
changes/improvements.

Jim

Attachments (1)

ruby-sock-cred.patch (4.7 KB, text/x-diff)
diff -ru ruby-1.8.4/ext/socket/extconf.rb ruby-1.8.4.mod/ext/socket/extconf.rb
--- ruby-1.8.4/ext/socket/extconf.rb	2005-07-19 15:04:46.000000000 -0400
+++ ruby-1.8.4.mod/ext/socket/extconf.rb	2006-06-09 12:04:47.518827000 -0400
@@ -251,6 +251,21 @@
 EOS
 end
 
+if have_library("c", "getpeerucred")
+  $defs << "-DHAVE_GETPEERUCRED "
+else
+   puts "no getpeerucred"
+end
+
+if have_library("c", "getpeereid")
+  $defs << "-DHAVE_GETPEEREID "
+end
+
+if have_macro("SO_PEERCRED", "sys/socket.h")
+  $defs <<  "-DHAVE_SO_PEERCRED "
+end
+
+
 case with_config("lookup-order-hack", "UNSPEC")
 when "INET"
   $defs << "-DLOOKUP_ORDER_HACK_INET"
diff -ru ruby-1.8.4/ext/socket/socket.c ruby-1.8.4.mod/ext/socket/socket.c
--- ruby-1.8.4/ext/socket/socket.c	2005-11-28 04:56:45.000000000 -0500
+++ ruby-1.8.4.mod/ext/socket/socket.c	2006-06-09 14:33:45.199625000 -0400
@@ -71,6 +71,13 @@
 #endif
 #include "sockport.h"
 
+#if defined(HAVE_GETPEERUCRED)
+#include <ucred.h>
+#elif defined(HAVE_GETPEEREID)
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
 #if defined(__vms)
 #include <tcp.h>
 #endif
@@ -1916,6 +1923,142 @@
         addr.sun_path[0] = '\0';
     return unixaddr(&addr);
 }
+
+/*
+ * Document-method: peer_uid
+ * call-seq: socket.peer_uid => int
+ *
+ * Returns the uid of the peer socket for Unix domain stream sockets
+ *
+ * === Example
+ * # Client example
+ *   require 'socket'
+ *   s = UNIXSocket.new("/path/to/socket")
+ *   puts "Peer uid is #{s.peer_uid}"
+ *
+ * # Server example
+ *   require 'socket'
+ *   s = UNIXServer.new("/path/to/socket")
+ *   ns = s.accept
+ *   puts "Peer uid is #{ns.peer_uid}"
+ *
+ */
+ 
+static VALUE
+unix_peer_uid(sock)
+    VALUE sock;
+{
+    char buf[1024];
+    socklen_t len = sizeof buf;
+    OpenFile *fptr;
+    int uid;
+
+#if defined(HAVE_GETPEERUCRED)
+    ucred_t *creds;
+#elif defined(HAVE_SO_PEERCRED)
+    struct ucred creds;
+#elif defined(HAVE_GETPEEREID)
+    int gid;
+#else
+    rb_raise(rb_eSocket, "UNIXSocket::uid not implemented on this platform");
+#endif
+
+    GetOpenFile(sock, fptr);
+
+#if defined(HAVE_GETPEERUCRED)
+    if ((creds = malloc(ucred_size())) < 0)
+        rb_sys_fail("malloc");
+
+    if (getpeerucred(fileno(fptr->f), &creds) < 0)
+        rb_sys_fail("getpeerucred(2)");
+
+    uid = ucred_getruid(creds);
+    ucred_free(creds);
+
+    return INT2FIX(uid);
+
+#elif defined(HAVE_SO_PEERCRED)
+
+    if (getsockopt(fileno(fptr->f), SOL_SOCKET, SO_PEERCRED, &creds, &len) < 0)
+        rb_sys_fail("getsockopt");
+
+    return INT2FIX(creds.uid);
+
+#elif defined(HAVE_GETPEEREID)
+    if (getpeereid(fileno(fptr->f), &uid, &gid) < 0)
+        rb_sys_fail("getpeereid");
+
+    return INT2FIX(uid);
+#endif
+}
+    
+/*
+ * Document-method: peer_gid
+ * call-seq: socket.peer_gid => int
+ *
+ * Returns the gid of the peer socket for Unix domain stream sockets
+ *
+ * === Example
+ * # Client example
+ *   require 'socket'
+ *   s = UNIXSocket.new("/path/to/socket")
+ *   puts "Peer gid is #{s.peer_gid}"
+ *
+ * # Server example
+ *   require 'socket'
+ *   s = UNIXServer.new("/path/to/socket")
+ *   ns = s.accept
+ *   puts "Peer gid is #{ns.peer_gid}"
+ *
+ */
+
+static VALUE
+unix_peer_gid(sock)
+    VALUE sock;
+{
+    char buf[1024];
+    socklen_t len = sizeof buf;
+    OpenFile *fptr;
+    int gid;
+
+#if defined(HAVE_GETPEERUCRED)
+    ucred_t *creds;
+#elif defined(HAVE_SO_PEERCRED)
+    struct ucred creds;
+#elif defined(HAVE_GETPEEREID)
+    int uid;
+#else
+    rb_raise(rb_eSocket, "UNIXSocket::gid not implemented on this platform");
+#endif
+
+    GetOpenFile(sock, fptr);
+
+#if defined(HAVE_GETPEERUCRED)
+    if ((creds = malloc(ucred_size())) < 0)
+        rb_sys_fail("malloc");
+
+    if (getpeerucred(fileno(fptr->f), &creds) < 0)
+        rb_sys_fail("getpeerucred(2)");
+
+    gid = ucred_getrgid(creds);
+    ucred_free(creds);
+
+    return INT2FIX(gid);
+
+#elif defined(HAVE_SO_PEERCRED)
+
+    if (getsockopt(fileno(fptr->f), SOL_SOCKET, SO_PEERCRED, &creds, &len) < 0)
+        rb_sys_fail("getsockopt");
+
+    return INT2FIX(creds.gid);
+
+#elif defined(HAVE_GETPEEREID)
+    if (getpeereid(fileno(fptr->f), &uid, &gid) < 0)
+        rb_sys_fail("getpeereid");
+
+    return INT2FIX(gid);
+#endif
+}
 #endif
 
 static void
@@ -3199,6 +3342,8 @@
     rb_define_method(rb_cUNIXSocket, "recvfrom", unix_recvfrom, -1);
     rb_define_method(rb_cUNIXSocket, "send_io", unix_send_io, 1);
     rb_define_method(rb_cUNIXSocket, "recv_io", unix_recv_io, -1);
+    rb_define_method(rb_cUNIXSocket, "peer_uid", unix_peer_uid, 0);
+    rb_define_method(rb_cUNIXSocket, "peer_gid", unix_peer_gid, 0);
     rb_define_singleton_method(rb_cUNIXSocket, "socketpair", unix_s_socketpair, -1);
     rb_define_singleton_method(rb_cUNIXSocket, "pair", unix_s_socketpair, -1);
 

In This Thread

Prev Next