From 5d550262911f376e55323690a9c7fe269273002e Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sun, 4 May 2008 00:32:57 +0000 Subject: [PATCH] Added support for SO_PEERCRED for Unix sockets. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25305 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../network/protocols/unix/UnixEndpoint.cpp | 31 +++++++++++++++++-- .../network/protocols/unix/UnixEndpoint.h | 6 ++-- .../kernel/network/protocols/unix/unix.cpp | 11 +++++++ 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/add-ons/kernel/network/protocols/unix/UnixEndpoint.cpp b/src/add-ons/kernel/network/protocols/unix/UnixEndpoint.cpp index 98ff9554cd..bfb229606d 100644 --- a/src/add-ons/kernel/network/protocols/unix/UnixEndpoint.cpp +++ b/src/add-ons/kernel/network/protocols/unix/UnixEndpoint.cpp @@ -254,6 +254,10 @@ UnixEndpoint::Listen(int backlog) _UnsetReceiveFifo(); + fCredentials.pid = getpid(); + fCredentials.uid = geteuid(); + fCredentials.gid = getegid(); + fState = UNIX_ENDPOINT_LISTENING; RETURN_ERROR(B_OK); @@ -352,7 +356,7 @@ UnixEndpoint::Connect(const struct sockaddr *_address) UnixEndpointLocker connectedLocker(connectedEndpoint); - connectedEndpoint->_Spawn(this, peerFifo); + connectedEndpoint->_Spawn(this, listeningEndpoint, peerFifo); // update our attributes _UnsetReceiveFifo(); @@ -362,6 +366,10 @@ UnixEndpoint::Connect(const struct sockaddr *_address) fPeerEndpoint->AddReference(); fReceiveFifo = fifo; + fCredentials.pid = getpid(); + fCredentials.uid = geteuid(); + fCredentials.gid = getegid(); + fifoDeleter.Detach(); peerFifoDeleter.Detach(); @@ -650,6 +658,22 @@ UnixEndpoint::SetReceiveBufferSize(size_t size) } +status_t +UnixEndpoint::GetPeerCredentials(ucred* credentials) +{ + UnixEndpointLocker locker(this); + UnixEndpointLocker peerLocker; + + status_t error = _LockConnectedEndpoints(locker, peerLocker); + if (error != B_OK) + RETURN_ERROR(error); + + *credentials = fPeerEndpoint->fCredentials; + + return B_OK; +} + + status_t UnixEndpoint::Shutdown(int direction) { @@ -710,7 +734,8 @@ UnixEndpoint::Shutdown(int direction) void -UnixEndpoint::_Spawn(UnixEndpoint* connectingEndpoint, UnixFifo* fifo) +UnixEndpoint::_Spawn(UnixEndpoint* connectingEndpoint, + UnixEndpoint* listeningEndpoint, UnixFifo* fifo) { ProtocolSocket::Open(); @@ -722,6 +747,8 @@ UnixEndpoint::_Spawn(UnixEndpoint* connectingEndpoint, UnixFifo* fifo) PeerAddress().SetTo(&connectingEndpoint->socket->address); + fCredentials = listeningEndpoint->fCredentials; + fState = UNIX_ENDPOINT_CONNECTED; } diff --git a/src/add-ons/kernel/network/protocols/unix/UnixEndpoint.h b/src/add-ons/kernel/network/protocols/unix/UnixEndpoint.h index 90d08580ad..3749676b6b 100644 --- a/src/add-ons/kernel/network/protocols/unix/UnixEndpoint.h +++ b/src/add-ons/kernel/network/protocols/unix/UnixEndpoint.h @@ -76,6 +76,7 @@ public: ssize_t Receivable(); status_t SetReceiveBufferSize(size_t size); + status_t GetPeerCredentials(ucred* credentials); status_t Shutdown(int direction); @@ -95,7 +96,8 @@ public: } private: - void _Spawn(UnixEndpoint* connectingEndpoint, UnixFifo* fifo); + void _Spawn(UnixEndpoint* connectingEndpoint, + UnixEndpoint* listeningEndpoint, UnixFifo* fifo); void _Disconnect(); status_t _LockConnectedEndpoints(UnixEndpointLocker& locker, UnixEndpointLocker& peerLocker); @@ -115,8 +117,8 @@ private: UnixFifo* fReceiveFifo; unix_endpoint_state fState; sem_id fAcceptSemaphore; + ucred fCredentials; bool fIsChild; }; - #endif // UNIX_ENDPOINT_H diff --git a/src/add-ons/kernel/network/protocols/unix/unix.cpp b/src/add-ons/kernel/network/protocols/unix/unix.cpp index 954bd3c3d3..ddbeb40f14 100644 --- a/src/add-ons/kernel/network/protocols/unix/unix.cpp +++ b/src/add-ons/kernel/network/protocols/unix/unix.cpp @@ -132,6 +132,17 @@ status_t unix_getsockopt(net_protocol *protocol, int level, int option, void *value, int *_length) { + UnixEndpoint* endpoint = (UnixEndpoint*)protocol; + + if (level == SOL_SOCKET && option == SO_PEERCRED) { + if (*_length < (int)sizeof(ucred)) + return B_BAD_VALUE; + + *_length = sizeof(ucred); + + return endpoint->GetPeerCredentials((ucred*)value); + } + return gSocketModule->get_option(protocol->socket, level, option, value, _length); }