* 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
This commit is contained in:
akr 2009-02-08 12:53:55 +00:00
parent c79dac1c3e
commit 411e9997d2
4 changed files with 97 additions and 29 deletions

View File

@ -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):

View File

@ -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

View File

@ -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.*"

View File

@ -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