From 81e2b60d65f57d1642bcc028310455a9e174b0b2 Mon Sep 17 00:00:00 2001 From: sakno Date: Sat, 13 Jan 2024 21:26:25 +0200 Subject: [PATCH] Added support of username --- .../ApplicationMaintenanceInterfaceHost.cs | 7 +-- .../Principal/LinuxUdsPeerIdentity.cs | 56 +++++++++++++++++-- ...ommandLineMaintenanceInterfaceHostTests.cs | 7 ++- 3 files changed, 56 insertions(+), 14 deletions(-) diff --git a/src/DotNext.MaintenanceServices/Maintenance/ApplicationMaintenanceInterfaceHost.cs b/src/DotNext.MaintenanceServices/Maintenance/ApplicationMaintenanceInterfaceHost.cs index abf9fe51b3..249200d797 100644 --- a/src/DotNext.MaintenanceServices/Maintenance/ApplicationMaintenanceInterfaceHost.cs +++ b/src/DotNext.MaintenanceServices/Maintenance/ApplicationMaintenanceInterfaceHost.cs @@ -143,12 +143,7 @@ private static IIdentity GetRemotePeerIdentity(Socket socket) { if (OperatingSystem.IsLinux() && socket.TryGetCredentials(out var processId, out var userId, out var groupId)) { - return new LinuxUdsPeerIdentity() - { - ProcessId = processId, - UserId = userId, - GroupId = groupId, - }; + return new LinuxUdsPeerIdentity(processId, userId, groupId); } return AnonymousPrincipal.Instance; diff --git a/src/DotNext.MaintenanceServices/Security/Principal/LinuxUdsPeerIdentity.cs b/src/DotNext.MaintenanceServices/Security/Principal/LinuxUdsPeerIdentity.cs index 50c0536bd4..1290ca4745 100644 --- a/src/DotNext.MaintenanceServices/Security/Principal/LinuxUdsPeerIdentity.cs +++ b/src/DotNext.MaintenanceServices/Security/Principal/LinuxUdsPeerIdentity.cs @@ -1,5 +1,7 @@ using System.Runtime.Versioning; using System.Security.Principal; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; namespace DotNext.Security.Principal; @@ -12,11 +14,35 @@ namespace DotNext.Security.Principal; [CLSCompliant(false)] public sealed record class LinuxUdsPeerIdentity : IIdentity { + private static readonly Getpwuid? GetpwuidFunction; + + static LinuxUdsPeerIdentity() + { + var getpwuid = NativeLibrary.GetExport(NativeLibrary.GetMainProgramHandle(), "getpwuid"); + GetpwuidFunction = getpwuid is not 0 + ? Marshal.GetDelegateForFunctionPointer(getpwuid) + : null; + } + [SupportedOSPlatform("linux")] - internal LinuxUdsPeerIdentity() + internal LinuxUdsPeerIdentity(uint pid, uint uid, uint gid) { if (!OperatingSystem.IsLinux()) throw new PlatformNotSupportedException(); + + ProcessId = pid; + UserId = uid; + GroupId = gid; + + if (GetpwuidFunction is not null) + { + ref var passwd = ref GetpwuidFunction(uid); + if (!Unsafe.IsNullRef(ref passwd)) + { + Name = Marshal.PtrToStringAnsi(passwd.Name); + DisplayName = Marshal.PtrToStringAnsi(passwd.UserInfo); + } + } } /// @@ -27,21 +53,41 @@ internal LinuxUdsPeerIdentity() /// /// Gets calling process ID. /// - public uint ProcessId { get; internal init; } + public uint ProcessId { get; } /// /// Gets user ID of the process identified by . /// - public uint UserId { get; internal init; } + public uint UserId { get; } /// /// Gets group ID of the process identified by . /// - public uint GroupId { get; internal init; } + public uint GroupId { get; } /// string? IIdentity.AuthenticationType => "ucred"; /// - string? IIdentity.Name => null; + public string? Name { get; } + + /// + /// Gets user information, if available. + /// + public string? DisplayName { get; } + + [StructLayout(LayoutKind.Sequential)] + private readonly struct Passwd + { + internal readonly nint Name; + internal readonly nint Password; + internal readonly uint UserId; + internal readonly uint GroupId; + internal readonly nint UserInfo; + internal readonly nint HomeDirectory; + internal readonly nint Shell; + } + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate ref Passwd Getpwuid(uint userId); } \ No newline at end of file diff --git a/src/DotNext.Tests/Maintenance/CommandLine/CommandLineMaintenanceInterfaceHostTests.cs b/src/DotNext.Tests/Maintenance/CommandLine/CommandLineMaintenanceInterfaceHostTests.cs index 15720d1519..e19ffda56f 100644 --- a/src/DotNext.Tests/Maintenance/CommandLine/CommandLineMaintenanceInterfaceHostTests.cs +++ b/src/DotNext.Tests/Maintenance/CommandLine/CommandLineMaintenanceInterfaceHostTests.cs @@ -56,7 +56,7 @@ public static async Task DefaultCommandsAsync(string request, string response) await host.StopAsync(); } - [PlatformSpecificFact("linux")] + [Fact] public static async Task UdsEndpointAuthentication() { var unixDomainSocketPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); @@ -71,8 +71,9 @@ public static async Task UdsEndpointAuthentication() command.SetHandler(static session => { True(session.Identity.IsAuthenticated); - IsType(session.Identity); - session.ResponseWriter.Write(((LinuxUdsPeerIdentity)session.Identity).ProcessId); + var identity = IsType(session.Identity); + Equal(Environment.UserName, identity.Name); + session.ResponseWriter.Write(identity.ProcessId); }, DefaultBindings.Session); });