add support for authentication using SCM_CREDENTIALS

git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@596 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
Lennart Poettering 2006-02-24 15:12:42 +00:00
parent a1f5573313
commit 3f264b2c4a
12 changed files with 343 additions and 92 deletions

View file

@ -27,12 +27,14 @@
#include <assert.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include "winsock.h"
#include <polypcore/util.h>
#include <polypcore/socket-util.h>
#include <polypcore/xmalloc.h>
#include <polypcore/log.h>
#include "iochannel.h"
@ -242,6 +244,134 @@ ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l) {
return r;
}
#ifdef SCM_CREDENTIALS
int pa_iochannel_creds_supported(pa_iochannel *io) {
struct sockaddr_un sa;
socklen_t l;
assert(io);
assert(io->ifd >= 0);
assert(io->ofd == io->ifd);
l = sizeof(sa);
if (getsockname(io->ifd, (struct sockaddr*) &sa, &l) < 0)
return 0;
return sa.sun_family == AF_UNIX;
}
int pa_iochannel_creds_enable(pa_iochannel *io) {
int t = 1;
assert(io);
assert(io->ifd >= 0);
if (setsockopt(io->ifd, SOL_SOCKET, SO_PASSCRED, &t, sizeof(t)) < 0) {
pa_log_error("setsockopt(SOL_SOCKET, SO_PASSCRED): %s", strerror(errno));
return -1;
}
return 0;
}
ssize_t pa_iochannel_write_with_creds(pa_iochannel*io, const void*data, size_t l) {
ssize_t r;
struct msghdr mh;
struct iovec iov;
uint8_t cmsg_data[CMSG_SPACE(sizeof(struct ucred))];
struct ucred *ucred;
struct cmsghdr *cmsg;
assert(io);
assert(data);
assert(l);
assert(io->ofd >= 0);
memset(&iov, 0, sizeof(iov));
iov.iov_base = (void*) data;
iov.iov_len = l;
memset(cmsg_data, 0, sizeof(cmsg_data));
cmsg = (struct cmsghdr*) cmsg_data;
cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_CREDENTIALS;
ucred = (struct ucred*) CMSG_DATA(cmsg);
ucred->pid = getpid();
ucred->uid = getuid();
ucred->gid = getgid();
memset(&mh, 0, sizeof(mh));
mh.msg_name = NULL;
mh.msg_namelen = 0;
mh.msg_iov = &iov;
mh.msg_iovlen = 1;
mh.msg_control = cmsg_data;
mh.msg_controllen = sizeof(cmsg_data);
mh.msg_flags = 0;
if ((r = sendmsg(io->ofd, &mh, MSG_NOSIGNAL)) >= 0) {
io->writable = 0;
enable_mainloop_sources(io);
}
return r;
}
ssize_t pa_iochannel_read_with_creds(pa_iochannel*io, void*data, size_t l, struct ucred *ucred, int *creds_valid) {
ssize_t r;
struct msghdr mh;
struct iovec iov;
uint8_t cmsg_data[CMSG_SPACE(sizeof(struct ucred))];
assert(io);
assert(data);
assert(l);
assert(io->ifd >= 0);
assert(ucred);
assert(creds_valid);
memset(&iov, 0, sizeof(iov));
iov.iov_base = data;
iov.iov_len = l;
memset(cmsg_data, 0, sizeof(cmsg_data));
memset(&mh, 0, sizeof(mh));
mh.msg_name = NULL;
mh.msg_namelen = 0;
mh.msg_iov = &iov;
mh.msg_iovlen = 1;
mh.msg_control = cmsg_data;
mh.msg_controllen = sizeof(cmsg_data);
mh.msg_flags = 0;
if ((r = recvmsg(io->ifd, &mh, MSG_NOSIGNAL)) >= 0) {
struct cmsghdr *cmsg;
*creds_valid = 0;
for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) {
assert(cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)));
memcpy(ucred, CMSG_DATA(cmsg), sizeof(struct ucred));
*creds_valid = 1;
break;
}
}
io->readable = 0;
enable_mainloop_sources(io);
}
return r;
}
#endif
void pa_iochannel_set_callback(pa_iochannel*io, pa_iochannel_cb_t _callback, void *userdata) {
assert(io);