summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-02-08 12:53:55 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-02-08 12:53:55 +0000
commit411e9997d2062d7d871f8a4ffe810c8261be4b36 (patch)
tree2a9094e24862a7cc918abdad0d47ad07b2cf0ea9
parentc79dac1c3ec4477af4e8a115942c80cfc414f648 (diff)
* ext/socket/extconf.rb: check struct cmsgcred.
* ext/socket/ancdata.c (anc_inspect_passcred_credentials): add "(ucred)". (anc_inspect_socket_creds): show struct cmsgcred too, for FreeBSD. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22129 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog8
-rw-r--r--ext/socket/ancdata.c72
-rw-r--r--ext/socket/extconf.rb1
-rw-r--r--test/socket/test_unix.rb45
4 files changed, 97 insertions, 29 deletions
diff --git a/ChangeLog b/ChangeLog
index 681ed5d5e4..956de742ba 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+Sun Feb 8 21:47:50 2009 Tanaka Akira <akr@fsij.org>
+
+ * ext/socket/extconf.rb: check struct cmsgcred.
+
+ * ext/socket/ancdata.c (anc_inspect_passcred_credentials): add
+ "(ucred)".
+ (anc_inspect_socket_creds): show struct cmsgcred too, for FreeBSD.
+
Sun Feb 8 21:05:35 2009 Tanaka Akira <akr@fsij.org>
* lib/drb/extservm.rb (DRb::ExtServManager#invoke_service_command):
diff --git a/ext/socket/ancdata.c b/ext/socket/ancdata.c
index c2606fb366..63d6491a05 100644
--- a/ext/socket/ancdata.c
+++ b/ext/socket/ancdata.c
@@ -385,6 +385,7 @@ anc_inspect_passcred_credentials(int level, int type, VALUE data, VALUE ret)
struct ucred cred;
memcpy(&cred, RSTRING_PTR(data), sizeof(struct ucred));
rb_str_catf(ret, " pid=%u uid=%u gid=%u", cred.pid, cred.uid, cred.gid);
+ rb_str_cat2(ret, " (ucred)");
return 0;
}
else {
@@ -393,38 +394,71 @@ anc_inspect_passcred_credentials(int level, int type, VALUE data, VALUE ret)
}
#endif
-#if defined(SCM_CREDS) && defined(HAVE_TYPE_STRUCT_SOCKCRED) /* NetBSD */
+#if defined(SCM_CREDS)
#define INSPECT_SCM_CREDS
static int
anc_inspect_socket_creds(int level, int type, VALUE data, VALUE ret)
{
int i;
- if (level == SOL_SOCKET && type == SCM_CREDS &&
- RSTRING_LEN(data) >= SOCKCREDSIZE(0)) {
- struct sockcred cred0, *cred;
- memcpy(&cred0, RSTRING_PTR(data), SOCKCREDSIZE(0));
- if (RSTRING_LEN(data) != SOCKCREDSIZE(cred0.sc_ngroups)) {
- return -1;
- }
- cred = (struct sockcred *)ALLOCA_N(char, SOCKCREDSIZE(cred0.sc_ngroups));
- memcpy(cred, RSTRING_PTR(data), SOCKCREDSIZE(cred0.sc_ngroups));
- rb_str_catf(ret, " uid=%u", cred->sc_uid);
- rb_str_catf(ret, " euid=%u", cred->sc_euid);
- rb_str_catf(ret, " gid=%u", cred->sc_gid);
- rb_str_catf(ret, " egid=%u", cred->sc_egid);
- if (cred0.sc_ngroups) {
+ if (level != SOL_SOCKET && type != SCM_CREDS)
+ return -1;
+
+ /*
+ * FreeBSD has struct cmsgcred and struct sockcred.
+ * They use both SOL_SOCKET/SCM_CREDS in the ancillary message.
+ * They are not ambiguous from the view of the caller
+ * because struct sockcred is sent if and only if the caller sets LOCAL_CREDS socket option.
+ * But inspect method doesn't know it.
+ * So they are ambiguous from the view of inspect.
+ * This function distinguish them by the size of the ancillary message.
+ * This heuristics works well except when sc_ngroups == CMGROUP_MAX.
+ */
+
+#if defined(HAVE_TYPE_STRUCT_CMSGCRED) /* FreeBSD */
+ if (RSTRING_LEN(data) == sizeof(struct cmsgcred)) {
+ struct cmsgcred cred;
+ memcpy(&cred, RSTRING_PTR(data), sizeof(struct cmsgcred));
+ rb_str_catf(ret, " pid=%u", cred.cmcred_pid);
+ rb_str_catf(ret, " uid=%u", cred.cmcred_uid);
+ rb_str_catf(ret, " euid=%u", cred.cmcred_euid);
+ rb_str_catf(ret, " gid=%u", cred.cmcred_gid);
+ if (cred.cmcred_ngroups) {
char *sep = "=";
rb_str_cat2(ret, " groups");
- for (i = 0; i < cred0.sc_ngroups; i++) {
- rb_str_catf(ret, "%s%u", sep, cred->sc_groups[i]);
+ for (i = 0; i < cred.cmcred_ngroups; i++) {
+ rb_str_catf(ret, "%s%u", sep, cred.cmcred_groups[i]);
sep = ",";
}
}
+ rb_str_cat2(ret, " (cmsgcred)");
return 0;
}
- else {
- return -1;
+#endif
+#if defined(HAVE_TYPE_STRUCT_SOCKCRED) /* FreeBSD, NetBSD */
+ if (RSTRING_LEN(data) >= SOCKCREDSIZE(0)) {
+ struct sockcred cred0, *cred;
+ memcpy(&cred0, RSTRING_PTR(data), SOCKCREDSIZE(0));
+ if (RSTRING_LEN(data) == SOCKCREDSIZE(cred0.sc_ngroups)) {
+ cred = (struct sockcred *)ALLOCA_N(char, SOCKCREDSIZE(cred0.sc_ngroups));
+ memcpy(cred, RSTRING_PTR(data), SOCKCREDSIZE(cred0.sc_ngroups));
+ rb_str_catf(ret, " uid=%u", cred->sc_uid);
+ rb_str_catf(ret, " euid=%u", cred->sc_euid);
+ rb_str_catf(ret, " gid=%u", cred->sc_gid);
+ rb_str_catf(ret, " egid=%u", cred->sc_egid);
+ if (cred0.sc_ngroups) {
+ char *sep = "=";
+ rb_str_cat2(ret, " groups");
+ for (i = 0; i < cred0.sc_ngroups; i++) {
+ rb_str_catf(ret, "%s%u", sep, cred->sc_groups[i]);
+ sep = ",";
+ }
+ }
+ rb_str_cat2(ret, " (sockcred)");
+ return 0;
+ }
}
+#endif
+ return -1;
}
#endif
diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb
index ad36112926..c7d07d0a4d 100644
--- a/ext/socket/extconf.rb
+++ b/ext/socket/extconf.rb
@@ -309,6 +309,7 @@ have_type("struct in6_pktinfo", headers) {|src|
}
have_type("struct sockcred", headers)
+have_type("struct cmsgcred", headers)
$distcleanfiles << "constants.h" << "constdefs.*"
diff --git a/test/socket/test_unix.rb b/test/socket/test_unix.rb
index d31999bfd4..31d60e3ff3 100644
--- a/test/socket/test_unix.rb
+++ b/test/socket/test_unix.rb
@@ -296,7 +296,7 @@ class TestUNIXSocket < Test::Unit::TestCase
}
end
- def test_cred_linux
+ def test_cred_ucred
return if /linux/ !~ RUBY_PLATFORM
Dir.mktmpdir {|d|
sockpath = "#{d}/sock"
@@ -306,15 +306,17 @@ class TestUNIXSocket < Test::Unit::TestCase
s.setsockopt(:SOCKET, :PASSCRED, 1)
c.print "a"
msg, cliend_ai, rflags, cred = s.recvmsg
+ inspect = cred.inspect
assert_equal("a", msg)
- assert_match(/ pid=#{$$} /, cred.inspect)
- assert_match(/ uid=#{Process.uid} /, cred.inspect)
- assert_match(/ gid=#{Process.gid}>/, cred.inspect)
+ assert_match(/ pid=#{$$} /, inspect)
+ assert_match(/ uid=#{Process.uid} /, inspect)
+ assert_match(/ gid=#{Process.gid}>/, inspect)
+ assert_match(/ \(ucred\)/, inspect)
}
end
- def test_cred_netbsd
- return if /netbsd/ !~ RUBY_PLATFORM
+ def test_cred_sockcred
+ return if /netbsd|freebsd/ !~ RUBY_PLATFORM
Dir.mktmpdir {|d|
sockpath = "#{d}/sock"
serv = Socket.unix_server_socket(sockpath)
@@ -324,10 +326,33 @@ class TestUNIXSocket < Test::Unit::TestCase
c.print "a"
msg, cliend_ai, rflags, cred = s.recvmsg
assert_equal("a", msg)
- assert_match(/ uid=#{Process.uid} /, cred.inspect)
- assert_match(/ euid=#{Process.euid} /, cred.inspect)
- assert_match(/ gid=#{Process.gid} /, cred.inspect)
- assert_match(/ egid=#{Process.egid} /, cred.inspect)
+ inspect = cred.inspect
+ p inspect
+ assert_match(/ uid=#{Process.uid} /, inspect)
+ assert_match(/ euid=#{Process.euid} /, inspect)
+ assert_match(/ gid=#{Process.gid} /, inspect)
+ assert_match(/ egid=#{Process.egid} /, inspect)
+ assert_match(/ \(sockcred\)/, inspect)
+ }
+ end
+
+ def test_cred_cmsgcred
+ return if /freebsd/ !~ RUBY_PLATFORM
+ Dir.mktmpdir {|d|
+ sockpath = "#{d}/sock"
+ serv = Socket.unix_server_socket(sockpath)
+ c = Socket.unix(sockpath)
+ s, = serv.accept
+ c.sendmsg("a", 0, nil, [:SOCKET, Socket::SCM_CREDS, ""])
+ msg, cliend_ai, rflags, cred = s.recvmsg
+ assert_equal("a", msg)
+ inspect = cred.inspect
+ p inspect
+ assert_match(/ pid=#{$$} /, inspect)
+ assert_match(/ uid=#{Process.uid} /, inspect)
+ assert_match(/ euid=#{Process.euid} /, inspect)
+ assert_match(/ gid=#{Process.gid} /, inspect)
+ assert_match(/ \(cmsgcred\)/, inspect)
}
end