In article <200607191340.25414.jfh / cise.ufl.edu>, "James F. Hranicky" <jfh / cise.ufl.edu> writes: > Are negative values allowed on Linux? AFAICT, if the credentials aren't > available on Linux, say when I check a TCPServer socket's credentials > after accepting a connection from another host, the system call returns > 0 but sets the uid & gid to -1: An example of negative UID is on NFS: "nobody" is -2. [RFC 1094] > +if have_macro("SO_PEERCRED", "sys/socket.h") > + $defs << "-DHAVE_SO_PEERCRED " > +end Uselessly complex. Just use #if defined(SO_PEERCRED) in socket.c. > +/* > + * Document-method: peer_cred > + * call-seq: socket.peer_cred => hash > + * hash[:uid] => ruid || euid > + * hash[:gid] => rgid || egid > + * hash[:ruid] => ruid > + * hash[:euid] => euid > + * hash[:rgid] => rgid > + * hash[:egid] => egid > + * } unmatched closing curly brace? > static VALUE > +bsock_peer_cred(sock) > + VALUE sock; > +{ > + char buf[1024]; > + socklen_t len = sizeof buf; It seems that buf is not used. > +#if defined(HAVE_GETPEERUCRED) > + ucred_t *creds; > +#elif defined(HAVE_SO_PEERCRED) > + struct ucred creds; > +#elif defined(HAVE_GETPEEREID) > + int euid, egid; > +#else > + rb_raise(rb_eSocket, "peer_cred not implemented on this platform"); There is rb_notimplement(). See other usages of rb_notimplement(). > + kuid = rb_str_intern(rb_str_new2("uid")); > + kgid = rb_str_intern(rb_str_new2("gid")); > + kruid = rb_str_intern(rb_str_new2("ruid")); > + krgid = rb_str_intern(rb_str_new2("rgid")); > + keuid = rb_str_intern(rb_str_new2("euid")); > + kegid = rb_str_intern(rb_str_new2("egid")); rb_str_new2 and rb_str_intern is too complex here. Use ID2SYM(rb_intern("uid")), etc. > + ahash = rb_hash_new(); > + > + rb_hash_aset(ahash, kuid, Qnil); > + rb_hash_aset(ahash, kgid, Qnil); > + rb_hash_aset(ahash, kruid, Qnil); > + rb_hash_aset(ahash, krgid, Qnil); > + rb_hash_aset(ahash, keuid, Qnil); > + rb_hash_aset(ahash, kegid, Qnil); I think the hash entries which OS doesn't provides are useless. % ./ruby -v -rsocket -e ' File.unlink("/tmp/s") rescue nil serv = UNIXServer.new("/tmp/s") sock = UNIXSocket.new("/tmp/s") s = serv.accept p s.peer_cred ' ruby 1.8.5 (2006-07-21) [i686-linux] {:egid=>1000, :rgid=>nil, :uid=>1000, :gid=>1000, :euid=>1000, :ruid=>nil} I think :rgid=>nil and :ruid=>nil should be removed as follows. {:egid=>1000, :uid=>1000, :gid=>1000, :euid=>1000} > +#if defined(HAVE_GETPEERUCRED) > + if ((creds = malloc(ucred_size())) == NULL) > + rb_sys_fail("malloc"); Why memory allocation? > + if (getpeerucred(fileno(fptr->f), &creds) < 0) > + rb_sys_fail("getpeerucred(2)"); It seems getpeerucred allocates memory. http://docs.sun.com/app/docs/doc/816-5168/6mbb3hrcl?l=ja&a=view > + rb_hash_aset(ahash, kuid, INT2FIX(creds.uid)); > + rb_hash_aset(ahash, kgid, INT2FIX(creds.gid)); > + rb_hash_aset(ahash, keuid, INT2FIX(creds.uid)); > + rb_hash_aset(ahash, kegid, INT2FIX(creds.gid)); I'd like to replace kuid by ID2SYM(rb_intern("uid")), to avoid variables and unused variable initialization. > + if ((hashval = rb_hash_aref(ahash, kuid)) == Qnil) > + rb_raise(rb_eSocket, "Invalid credentials: uid is nil"); > + > + if ((hashval = rb_hash_aref(ahash, kgid)) == Qnil) > + rb_raise(rb_eSocket, "Invalid credentials: gid is nil"); It seems a defensive programming. > + rb_define_method(rb_cBasicSocket, "peer_cred", bsock_peer_cred, 0); Of course, the last possible problem is the method name. I'm not sure that matz accept peer_cred. -- Tanaka Akira