Skip to content

Instantly share code, notes, and snippets.

@hiboma
Created February 29, 2012 14:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save hiboma/1941172 to your computer and use it in GitHub Desktop.
Save hiboma/1941172 to your computer and use it in GitHub Desktop.
SOL_SOCKET, SO_PEERCRED in ruby
#!/usr/bin/env ruby
require 'socket'
include Socket::Constants
UNIXServer.open("\0(abstract socket)") {|server|
clinet = UNIXSocket.new("\0(abstract socket)")
clinet.setsockopt(SOL_SOCKET, SO_PASSCRED, 1)
sock = server.accept
opt = sock.getsockopt(SOL_SOCKET, SO_PEERCRED)
pid, euid, egid = opt.unpack("i3")
printf "pid: %d, euid: %d, egid: %s\n", pid, euid, egid
}
@hiboma
Copy link
Author

hiboma commented Feb 29, 2012

unpack使わないで pid,euid,egid 取る方法あんのかな。rubyのソース見たけど分からん

http://rxr.whitequark.org/mri/source/ext/socket/option.c#603

@hiboma
Copy link
Author

hiboma commented Feb 29, 2012

1.9.3 オプション名をシンボルで指定できる

#!/usr/bin/env ruby

require 'socket'

UNIXServer.open("\0(abstract sock)") {|server|

  clinet = UNIXSocket.new("\0(abstract sock)")
  clinet.setsockopt(:SOCKET, :PASSCRED, 1)

  sock = server.accept
  opt  = sock.getsockopt(:SOCKET, :PEERCRED)

  pid, euid, egid = opt.unpack("i3")
  printf "pid: %d, euid: %d, egid: %s\n", pid, euid, egid
}

@hiboma
Copy link
Author

hiboma commented Feb 29, 2012

from lxc-0.7.5

int lxc_af_unix_send_credential(int fd, void *data, size_t size)
{
        struct msghdr msg = { 0 };
        struct iovec iov;
        struct cmsghdr *cmsg;
        struct ucred cred = {
                .pid = getpid(),
                .uid = getuid(),
                .gid = getgid(),
        };
        char cmsgbuf[CMSG_SPACE(sizeof(cred))];
        char buf[1];

        msg.msg_control = cmsgbuf;
        msg.msg_controllen = sizeof(cmsgbuf);

        cmsg = CMSG_FIRSTHDR(&msg);
        cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
        cmsg->cmsg_level = SOL_SOCKET;
        cmsg->cmsg_type = SCM_CREDENTIALS;
        memcpy(CMSG_DATA(cmsg), &cred, sizeof(cred));

        msg.msg_name = NULL;
        msg.msg_namelen = 0;

        iov.iov_base = data ? data : buf;
        iov.iov_len = data ? size : sizeof(buf);
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;

        return sendmsg(fd, &msg, 0);
}
int lxc_af_unix_rcv_credential(int fd, void *data, size_t size)
{
        struct msghdr msg = { 0 };
        struct iovec iov;
        struct cmsghdr *cmsg;
        struct ucred cred;
        char cmsgbuf[CMSG_SPACE(sizeof(cred))];
        char buf[1];
        int ret;

        msg.msg_name = NULL;
        msg.msg_namelen = 0;
        msg.msg_control = cmsgbuf;
        msg.msg_controllen = sizeof(cmsgbuf);

        iov.iov_base = data ? data : buf;
        iov.iov_len = data ? size : sizeof(buf);
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;

        ret = recvmsg(fd, &msg, 0);
        if (ret <= 0)
                goto out;

        cmsg = CMSG_FIRSTHDR(&msg);

        if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)) &&
            cmsg->cmsg_level == SOL_SOCKET &&
            cmsg->cmsg_type == SCM_CREDENTIALS) {
                memcpy(&cred, CMSG_DATA(cmsg), sizeof(cred));
                if (cred.uid && (cred.uid != getuid() || cred.gid != getgid())) {
                        INFO("message denied for '%d/%d'", cred.uid, cred.gid);
                        return -EACCES;
                }
        }
out:
        return ret;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment