dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.91k stars 4.64k forks source link

[API Proposal]: SO_PEERCRED support for Unix Domain Sockets #71207

Open sakno opened 2 years ago

sakno commented 2 years ago

Background and motivation

I would like to verify remote peer connecting to my application through Unix Domain Socket. Linux and FreeBSD allow to do that using SO_PEERCRED (or LOCAL_PEERCRED on FreeBSD) socket option via getsockopt native function. This function needs to be called on accepted socket by server side.

API Proposal

namespace System.Net.Sockets;

public enum SocketOptionName
{
   PeerCredentials = 65535, // on Linux, SOPEERCRED is equal to 17, but historically the enum follows WinSock constants
}

The returned data can be represented as ValueTuple<uint, uint, uint> to match the original ucred structure.

The option must be requested on accepted socket with SocketOptionLevel.Socket value. On Windows, GetSocketOption returns null.

API Usage

using var listener = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
listener.Bind(new UnixDomainSocketEndPoint("/path/to/endpoint.sock"));
listener.Listen();

using var client = await listener.AcceptAsync(CancellationToken.None);
var credentials = ((uint pid, uint uid, uint gid))client.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.PeerCredentials);

Alternative Designs

We can keep SocketOptionName enum untouched and introduce static method in UnixDomainSocketEndPoint class:

public sealed class UnixDomainSocketEndPoint
{
    [CLSCompliant(false)]
    public static bool TryGetPeerCredentials(Socket socket, out uint processId, out uint userId, out uint groupId);
}

On unsupported platforms, the method returns false.

Risks

I don't see any.

ghost commented 2 years ago

Tagging subscribers to this area: @dotnet/ncl See info in area-owners.md if you want to be subscribed.

Issue Details
### Background and motivation I would like to verify remote peer connecting to my application through Unix Domain Socket. Linux and FreeBSD allow to do that using `SO_PEERCRED` (or `LOCAL_PEERCRED` on FreeBSD) socket option via `getsockopt` native function. This function needs to be called on accepted socket by server side. ### API Proposal ```csharp namespace System.Net.Sockets; public enum SocketOptionName { PeerCredentials = 65535, // in Linux, SOPEERCRED is equal to 17, but historically the enum follows WinSock constants } ``` The returned data can be represented as `ValueTuple` to match the original [ucred](https://github.com/torvalds/linux/blob/master/include/linux/socket.h#L173) structure. The option must be requested on accepted socket with `SocketOptionLevel.Socket` value. On Windows, `GetSocketOption` returns **null**. ### API Usage ```csharp using var listener = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Unspecified); listener.Bind(new UnixDomainSocketEndPoint("/path/to/endpoint.sock")); listener.Listen(); using var client = await listener.AcceptAsync(CancellationToken.None); var credentials = ((uint pid, uint uid, uint gid))client.GetSocketOption(SocketOptionLevel.Socket, SocketOptionName.PeerCredentials); ``` ### Alternative Designs We can keep `SocketOptionName` enum untouched and introduce static method in `UnixDomainSocketEndPoint` class: ```csharp public sealed class UnixDomainSocketEndPoint { [CLSCompliant(false)] public static bool TryGetPeerCredentials(Socket socket, out uint processId, out uint userId, out uint groupId); } ``` On unsupported platforms, the method returns **false**. ### Risks I don't see any.
Author: sakno
Assignees: -
Labels: `api-suggestion`, `area-System.Net.Sockets`, `untriaged`
Milestone: -
antonfirsov commented 2 years ago

@sakno have you tried using GetRawSocketOption for your scenario?

I'm not sure if it's a good idea to implement a seemingly xplat socket option that is not supported by all platforms in reality.

ghost commented 2 years ago

This issue has been marked needs-author-action and may be missing some important information.

sakno commented 2 years ago

@antonfirsov , I'll try! Thanks for advice. Anyway, I don't see any problem with some API which is not supported on all platforms. .NET has a lot of such API.

sakno commented 2 years ago

GetRawSocketOption works as expected! On FreeBSD, xucred differs from Linux version: https://cgit.freebsd.org/src/tree/sys/sys/ucred.h

Feel free to close this issue.

antonfirsov commented 2 years ago

Happy to hear it works for you!

We have a couple of similar feature requests (like #1476 or #36170), so maybe we can keep this one open too, so people who are interested can upvote/comment.

On the other hand, it's very unlikely that we will address these in the near future, so it would also make sense to close all of them to shorten our backlog.

karelz commented 2 years ago

Triage: Given we have a few similar issues open in Future, let's keep this one as well. We can decide on it later.