Mercurial > dovecot > core-2.2
changeset 16276:d594ce839da3
net_getunixcred() support for NetBSD <v5.0. Fixed also building with other NetBSDs.
Patch by Emmanuel Dreyfus
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 11 Apr 2013 13:15:39 +0300 |
parents | e33ec9eb166e |
children | c802c0b960e2 |
files | src/lib/net.c |
diffstat | 1 files changed, 63 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib/net.c Thu Apr 11 13:13:14 2013 +0300 +++ b/src/lib/net.c Thu Apr 11 13:15:39 2013 +0300 @@ -38,6 +38,10 @@ # define SIZEOF_SOCKADDR(so) (sizeof(so.sin)) #endif +#if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && !defined(HAVE_GETPEERUCRED) && defined(MSG_WAITALL) && defined(LOCAL_CREDS) +# define NEEDS_LOCAL_CREDS 1 +#endif + bool net_ip_compare(const struct ip_addr *ip1, const struct ip_addr *ip2) { return net_ip_cmp(ip1, ip2) == 0; @@ -303,6 +307,16 @@ return -1; } +#ifdef NEEDS_LOCAL_CREDS + { + int on = 1; + if (setsockopt(fd, 0, LOCAL_CREDS, &on, sizeof on)) { + i_error("setsockopt(LOCAL_CREDS) failed: %m"); + return -1; + } + } +#endif + return fd; } @@ -458,6 +472,16 @@ return -1; } +#ifdef NEEDS_LOCAL_CREDS + { + int on = 1; + if (setsockopt(fd, 0, LOCAL_CREDS, &on, sizeof on)) { + i_error("setsockopt(LOCAL_CREDS) failed: %m"); + return -1; + } + } +#endif + /* bind */ if (bind(fd, &sa.sa, sizeof(sa)) < 0) { if (errno != EADDRINUSE) @@ -721,7 +745,7 @@ struct unpcbid ucred; socklen_t len = sizeof(ucred); - if (getsockopt(s, 0, LOCAL_PEEREID, &ucred, &len) < 0) { + if (getsockopt(fd, 0, LOCAL_PEEREID, &ucred, &len) < 0) { i_error("getsockopt(LOCAL_PEEREID) failed: %m"); return -1; } @@ -776,6 +800,44 @@ return -1; } return 0; +#elif NEEDS_LOCAL_CREDS + /* NetBSD < 5 */ + int i, n, on; + struct iovec iov; + struct msghdr msg; + struct { + struct cmsghdr ch; + char buf[110]; + } cdata; + struct sockcred *sc; + + iov.iov_base = (char *)&on; + iov.iov_len = 1; + + sc = (struct sockcred *)cdata.buf; + sc->sc_uid = sc->sc_euid = sc->sc_gid = sc->sc_egid = -1; + memset(&cdata.ch, 0, sizeof cdata.ch); + + memset(&msg, 0, sizeof msg); + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = &cdata; + msg.msg_controllen = sizeof(cdata.ch) + sizeof(cdata.buf); + + for (i = 0; i < 10; i++) { + n = recvmsg(fd, &msg, MSG_WAITALL | MSG_PEEK); + if (n >= 0 || errno != EAGAIN) + break; + usleep(100); + } + if (n < 0) { + i_error("recvmsg() failed: %m"); + return -1; + } + cred_r->uid = sc->sc_euid; + cred_r->gid = sc->sc_egid; + return 0; #else errno = EINVAL; return -1;