diff options
author | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2009-02-08 12:53:55 +0000 |
---|---|---|
committer | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2009-02-08 12:53:55 +0000 |
commit | 411e9997d2062d7d871f8a4ffe810c8261be4b36 (patch) | |
tree | 2a9094e24862a7cc918abdad0d47ad07b2cf0ea9 | |
parent | c79dac1c3ec4477af4e8a115942c80cfc414f648 (diff) | |
download | ruby-411e9997d2062d7d871f8a4ffe810c8261be4b36.tar.gz |
* 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-- | ChangeLog | 8 | ||||
-rw-r--r-- | ext/socket/ancdata.c | 72 | ||||
-rw-r--r-- | ext/socket/extconf.rb | 1 | ||||
-rw-r--r-- | test/socket/test_unix.rb | 45 |
4 files changed, 97 insertions, 29 deletions
@@ -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 |