Skip to content

Commit 3581ecb

Browse files
committed
darwin: Use LOCAL_PEERCRED instead of SO_PEERCRED
While LOCAL_PEERCRED is somewhat similar to SO_PEERCRED, we unfortunately don't have access to the PID of the remote peer. This is something we actually need to properly distinguish the remote peer by giving it an IP address with the PID encoded, otherwise we'd end up with duplicate IPs. On the other hand, using random IP addresses also is not a very good solution here, since we actually *want* to have the same IP for the same process. Right now the UID and GID fields are not used at all on Darwin, but we really need to figure out a way to properly assign fake IP addresses. Signed-off-by: aszlig <[email protected]>
1 parent 3790608 commit 3581ecb

File tree

3 files changed

+50
-5
lines changed

3 files changed

+50
-5
lines changed

src/sockaddr.cc

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,23 @@ bool SockAddr::set_host(const SockAddr &other)
114114
return false;
115115
}
116116

117-
bool SockAddr::set_host(const ucred &peercred)
117+
#if defined(SO_PEERCRED)
118+
#define PEERCRED_TYPE ucred
119+
#define PEERCRED_PID peercred.pid
120+
#define PEERCRED_GID peercred.gid
121+
#define PEERCRED_UID peercred.uid
122+
#else
123+
#define PEERCRED_TYPE xucred
124+
#define PEERCRED_PID peercred.cr_pid
125+
#define PEERCRED_GID peercred.cr_gid
126+
#define PEERCRED_UID peercred.cr_uid
127+
#endif
128+
129+
bool SockAddr::set_host(const PEERCRED_TYPE &peercred)
118130
{
119131
if (this->is_inet4()) {
120132
this->cast4()->sin_addr.s_addr =
121-
htonl(static_cast<uint32_t>(peercred.pid));
133+
htonl(static_cast<uint32_t>(PEERCRED_PID));
122134
return true;
123135
}
124136

@@ -128,12 +140,15 @@ bool SockAddr::set_host(const ucred &peercred)
128140
addr->sin6_addr.s6_addr[1] = 0x80;
129141
addr->sin6_addr.s6_addr[2] = 0x00;
130142
addr->sin6_addr.s6_addr[3] = 0x00;
131-
uint32_t part = htonl(static_cast<uint32_t>(peercred.uid));
143+
uint32_t part = htonl(static_cast<uint32_t>(PEERCRED_UID));
132144
memcpy(addr->sin6_addr.s6_addr + 4, &part, 4);
133-
part = htonl(static_cast<uint32_t>(peercred.gid));
145+
// XXX!
146+
#if defined(SO_PEERCRED)
147+
part = htonl(static_cast<uint32_t>(PEERCRED_GID));
134148
memcpy(addr->sin6_addr.s6_addr + 8, &part, 4);
135-
part = htonl(static_cast<uint32_t>(peercred.pid));
149+
part = htonl(static_cast<uint32_t>(PEERCRED_PID));
136150
memcpy(addr->sin6_addr.s6_addr + 12, &part, 4);
151+
#endif
137152
return true;
138153
}
139154

src/sockaddr.hh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
#include <sys/socket.h>
1414
#include <sys/un.h>
1515

16+
#if defined(__APPLE__)
17+
#include <sys/ucred.h>
18+
#endif
19+
1620
struct sockaddr_in6;
1721
struct sockaddr_in;
1822

@@ -27,7 +31,11 @@ struct SockAddr
2731

2832
std::optional<std::string> get_host(void) const;
2933
bool set_host(const std::string&);
34+
#if defined(SO_PEERCRED)
3035
bool set_host(const ucred&);
36+
#else
37+
bool set_host(const xucred&);
38+
#endif
3139
bool set_host(const SockAddr&);
3240

3341
bool set_random_host(void);

src/socket.cc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
#include <stdint.h>
1616
#include <unistd.h>
1717

18+
#if defined(__APPLE__)
19+
#include <sys/ucred.h>
20+
#endif
21+
1822
std::optional<Socket::Ptr> Socket::find(int fd)
1923
{
2024
using itype = decltype(Socket::registry)::const_iterator;
@@ -272,10 +276,19 @@ bool Socket::create_binding(const SockAddr &addr)
272276
if (!local.set_host(addr))
273277
return false;
274278
} else {
279+
#if defined(SO_PEERCRED)
275280
ucred local_cred;
276281
local_cred.uid = getuid();
277282
local_cred.gid = getgid();
278283
local_cred.pid = getpid();
284+
#else
285+
xucred local_cred;
286+
local_cred.cr_uid = getuid();
287+
/* XXX!
288+
local_cred.cr_gid = getgid();
289+
local_cred.cr_pid = getpid();
290+
*/
291+
#endif
279292

280293
// Our local sockaddr, which we only need if we didn't have a
281294
// bind() before our connect.
@@ -460,11 +473,20 @@ int Socket::accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
460473
} else {
461474
// We use SO_PEERCRED to get uid, gid and pid in order to generate
462475
// unique IP addresses.
476+
#if defined(SO_PEERCRED)
463477
ucred peercred;
464478
socklen_t len = sizeof peercred;
465479

466480
if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &peercred, &len) == -1)
467481
return -1;
482+
#else
483+
xucred peercred;
484+
socklen_t len = sizeof peercred;
485+
486+
if (getsockopt(sockfd, SOL_LOCAL, LOCAL_PEERCRED, &peercred,
487+
&len) == -1)
488+
return -1;
489+
#endif
468490

469491
if (!peer.set_host(peercred)) {
470492
errno = EINVAL;

0 commit comments

Comments
 (0)