mirror of https://github.com/dahall/Vanara.git
Added DebuggerDisplay attribute and property. Added factory method to create known capability SID. Added PSID extension methods to mimic some found in SafePSID.
parent
fd5fb45297
commit
18b02b1c77
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using Vanara.Extensions;
|
using Vanara.Extensions;
|
||||||
|
@ -13,6 +14,7 @@ namespace Vanara.PInvoke
|
||||||
{
|
{
|
||||||
/// <summary>Class representation of the native SID structure.</summary>
|
/// <summary>Class representation of the native SID structure.</summary>
|
||||||
/// <seealso cref="SafeHGlobalHandle"/>
|
/// <seealso cref="SafeHGlobalHandle"/>
|
||||||
|
[DebuggerDisplay("{DebugString}")]
|
||||||
public class SafePSID : SafeMemoryHandle<LocalMemoryMethods>, IEquatable<SafePSID>, IEquatable<PSID>, IEquatable<IntPtr>, ICloneable, ISecurityObject
|
public class SafePSID : SafeMemoryHandle<LocalMemoryMethods>, IEquatable<SafePSID>, IEquatable<PSID>, IEquatable<IntPtr>, ICloneable, ISecurityObject
|
||||||
{
|
{
|
||||||
/// <summary>Equivalent to a NULL pointer to a SID.</summary>
|
/// <summary>Equivalent to a NULL pointer to a SID.</summary>
|
||||||
|
@ -67,6 +69,27 @@ namespace Vanara.PInvoke
|
||||||
/// <value>The SID length, in bytes.</value>
|
/// <value>The SID length, in bytes.</value>
|
||||||
public int Length => IsValidSid ? GetLengthSid(this) : 0;
|
public int Length => IsValidSid ? GetLengthSid(this) : 0;
|
||||||
|
|
||||||
|
/// <summary>Gets the string used to display in the debugger.</summary>
|
||||||
|
internal string DebugString
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (IsInvalid || IsClosed) return "NULL";
|
||||||
|
if (!IsValidSid) return "Invalid";
|
||||||
|
var d = ToString("D");
|
||||||
|
var n = ToString("P");
|
||||||
|
return d == n ? $"({d})" : $"{n} ({d})";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Creates a SID for predefined capability.</summary>
|
||||||
|
/// <param name="KnownSIDCapability">
|
||||||
|
/// Member of the KnownSIDCapability enumeration that specifies which capability the SID will identify.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>A <see cref="SafePSID"/> instance.</returns>
|
||||||
|
public static SafePSID CreateCapability(KnownSIDCapability capability) =>
|
||||||
|
Init(KnownSIDAuthority.SECURITY_APP_PACKAGE_AUTHORITY, KnownSIDRelativeID.SECURITY_CAPABILITY_BASE_RID, (int)capability);
|
||||||
|
|
||||||
/// <summary>Copies the specified SID from a memory pointer to a <see cref="SafePSID"/> instance.</summary>
|
/// <summary>Copies the specified SID from a memory pointer to a <see cref="SafePSID"/> instance.</summary>
|
||||||
/// <param name="psid">The SID pointer. This value remains the responsibility of the caller to release.</param>
|
/// <param name="psid">The SID pointer. This value remains the responsibility of the caller to release.</param>
|
||||||
/// <returns>A <see cref="SafePSID"/> instance.</returns>
|
/// <returns>A <see cref="SafePSID"/> instance.</returns>
|
||||||
|
@ -191,9 +214,46 @@ namespace Vanara.PInvoke
|
||||||
|
|
||||||
/// <summary>Returns a <see cref="string"/> that represents this instance.</summary>
|
/// <summary>Returns a <see cref="string"/> that represents this instance.</summary>
|
||||||
/// <returns>A <see cref="string"/> that represents this instance.</returns>
|
/// <returns>A <see cref="string"/> that represents this instance.</returns>
|
||||||
public override string ToString()
|
public override string ToString() => ToString(null);
|
||||||
|
|
||||||
|
/// <summary>Converts the value of this security identifier (SID) to its equivalent string representation according to the provided format specifier.</summary>
|
||||||
|
/// <param name="format">
|
||||||
|
/// A single format specifier that indicates how to format the value of this security identifier (SID). The format parameter can be
|
||||||
|
/// "B", "D", "N", or "P". If format is null or an empty string (""), "D" is used.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>The value of this security identifier (SID), in the specified format.</returns>
|
||||||
|
/// <exception cref="ArgumentException">SID value is not a valid SID. - pSid</exception>
|
||||||
|
/// <exception cref="FormatException">The value of format is not null, an empty string (""), "B", "D", "N", or "P".</exception>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>The following table shows the accepted format specifiers for the format parameter.</para>
|
||||||
|
/// <list type="table">
|
||||||
|
/// <item>
|
||||||
|
/// <description>Specifier</description>
|
||||||
|
/// <description>Format of return value</description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <description>"B"</description>
|
||||||
|
/// <description>
|
||||||
|
/// <para>Binary hex dump representation of the SID.</para>
|
||||||
|
/// </description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <description>"D"</description>
|
||||||
|
/// <description>SDDL representation of the SID.</description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <description>"N"</description>
|
||||||
|
/// <description>The NT4 style name (domain\username) corresponding to the SID.</description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <description>"P"</description>
|
||||||
|
/// <description>The internet style name (UPN) corresponding to the SID.</description>
|
||||||
|
/// </item>
|
||||||
|
/// </list>
|
||||||
|
/// </remarks>
|
||||||
|
public string ToString(string format)
|
||||||
{
|
{
|
||||||
try { return ConvertSidToStringSid(this); }
|
try { return ((PSID)handle).ToString(format); }
|
||||||
catch { return !IsInvalid && !IsClosed ? "Invalid" : "0"; }
|
catch { return !IsInvalid && !IsClosed ? "Invalid" : "0"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,4 +355,113 @@ namespace Vanara.PInvoke
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Extension methods for PSID instances.</summary>
|
||||||
|
public static class PSIDExtensions
|
||||||
|
{
|
||||||
|
/// <summary>Determines equality of two PSID instances.</summary>
|
||||||
|
/// <param name="psid1">The first PSID.</param>
|
||||||
|
/// <param name="psid2">The second PSID.</param>
|
||||||
|
/// <returns><see langword="true"/> if the SID structures are equal; <see langword="false"/> otherwise.</returns>
|
||||||
|
public static bool Equals(this PSID psid1, PSID psid2) => AdvApi32.EqualSid(psid1, psid2);
|
||||||
|
|
||||||
|
/// <summary>Gets the binary form of the SID structure.</summary>
|
||||||
|
/// <param name="pSid">The SID structure pointer.</param>
|
||||||
|
/// <returns>The binary form (byte array) of the SID structure.</returns>
|
||||||
|
public static byte[] GetBinaryForm(this PSID pSid) => pSid.IsValidSid() ? ((IntPtr)pSid).ToArray<byte>(pSid.Length()) : (new byte[0]);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validates a security identifier (SID) by verifying that the revision number is within a known range, and that the number of
|
||||||
|
/// subauthorities is less than the maximum.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pSid">A pointer to the SID structure to validate. This parameter cannot be NULL.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// If the SID structure is valid, the return value is <see langword="true"/>. If the SID structure is not valid, the return value is <see langword="false"/>.
|
||||||
|
/// </returns>
|
||||||
|
public static bool IsValidSid(this PSID pSid) => AdvApi32.IsValidSid(pSid);
|
||||||
|
|
||||||
|
/// <summary>Returns the length, in bytes, of a valid security identifier (SID).</summary>
|
||||||
|
/// <param name="pSid">A pointer to the SID structure whose length is returned. The structure is assumed to be valid.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// If the SID structure is valid, the return value is the length, in bytes, of the SID structure. If the SID structure is not valid,
|
||||||
|
/// the return value is 0.
|
||||||
|
/// </returns>
|
||||||
|
public static int Length(this PSID pSid) => AdvApi32.IsValidSid(pSid) ? AdvApi32.GetLengthSid(pSid) : 0;
|
||||||
|
|
||||||
|
/// <summary>Converts the value of a security identifier (SID) to its equivalent string representation according to the provided format specifier.</summary>
|
||||||
|
/// <param name="pSid">A pointer to a valid SID structure.</param>
|
||||||
|
/// <param name="format">
|
||||||
|
/// A single format specifier that indicates how to format the value of this security identifier (SID). The format parameter can be
|
||||||
|
/// "B", "D", "N", or "P". If format is null or an empty string (""), "D" is used.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>The value of this security identifier (SID), in the specified format.</returns>
|
||||||
|
/// <exception cref="ArgumentException">SID value is not a valid SID. - pSid</exception>
|
||||||
|
/// <exception cref="FormatException">The value of format is not null, an empty string (""), "B", "D", "N", or "P".</exception>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>The following table shows the accepted format specifiers for the format parameter.</para>
|
||||||
|
/// <list type="table">
|
||||||
|
/// <item>
|
||||||
|
/// <description>Specifier</description>
|
||||||
|
/// <description>Format of return value</description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <description>"B"</description>
|
||||||
|
/// <description>
|
||||||
|
/// <para>Binary hex dump representation of the SID.</para>
|
||||||
|
/// </description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <description>"D"</description>
|
||||||
|
/// <description>SDDL representation of the SID.</description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <description>"N"</description>
|
||||||
|
/// <description>The NT4 style name (domain\username) corresponding to the SID.</description>
|
||||||
|
/// </item>
|
||||||
|
/// <item>
|
||||||
|
/// <description>"P"</description>
|
||||||
|
/// <description>The internet style name (UPN) corresponding to the SID.</description>
|
||||||
|
/// </item>
|
||||||
|
/// </list>
|
||||||
|
/// </remarks>
|
||||||
|
public static string ToString(this PSID pSid, string format)
|
||||||
|
{
|
||||||
|
if (!pSid.IsValidSid())
|
||||||
|
throw new ArgumentException("SID value is not a valid SID.", nameof(pSid));
|
||||||
|
switch (format)
|
||||||
|
{
|
||||||
|
case "B":
|
||||||
|
var len = pSid.Length();
|
||||||
|
return pSid.GetBinaryForm().ToHexDumpString(len, len, 0).Trim(' ', '\r', '\n');
|
||||||
|
|
||||||
|
case "D":
|
||||||
|
case null:
|
||||||
|
case "":
|
||||||
|
return AdvApi32.ConvertSidToStringSid(pSid);
|
||||||
|
|
||||||
|
case "N":
|
||||||
|
case "P":
|
||||||
|
using (var hPol = AdvApi32.LsaOpenPolicy(AdvApi32.LsaPolicyRights.POLICY_ALL_ACCESS))
|
||||||
|
{
|
||||||
|
var flag = format == "P" ? AdvApi32.LsaLookupSidsFlags.LSA_LOOKUP_PREFER_INTERNET_NAMES : 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
AdvApi32.LsaLookupSids2(hPol, flag, 1, new[] { pSid }, out var memDoms, out var memNames).ThrowIfFailed();
|
||||||
|
memDoms.Dispose();
|
||||||
|
using (memNames)
|
||||||
|
{
|
||||||
|
return memNames.ToStructure<AdvApi32.LSA_TRANSLATED_NAME>().Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
goto case "D";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new FormatException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue