mirror of https://github.com/dahall/Vanara.git
Completed unit testing and fixes for SafePSID and SafePSIDArray
parent
d95600ecf0
commit
0c798f899f
|
@ -63,6 +63,10 @@ namespace Vanara.PInvoke
|
|||
/// <value><c>true</c> if this instance is a valid SID; otherwise, <c>false</c>.</value>
|
||||
public bool IsValidSid => IsValidSid(this);
|
||||
|
||||
/// <summary>Gets the length, in bytes, of the SID.</summary>
|
||||
/// <value>The SID length, in bytes.</value>
|
||||
public int Length => IsValidSid ? GetLengthSid(this) : 0;
|
||||
|
||||
/// <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>
|
||||
/// <returns>A <see cref="SafePSID"/> instance.</returns>
|
||||
|
@ -151,7 +155,7 @@ namespace Vanara.PInvoke
|
|||
/// <summary>Indicates whether the current object is equal to another object of the same type.</summary>
|
||||
/// <param name="other">An object to compare with this object.</param>
|
||||
/// <returns>true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.</returns>
|
||||
public bool Equals(SafePSID other) => EqualSid(this, other);
|
||||
public bool Equals(SafePSID other) => other != null && (ReferenceEquals(this, other) || EqualSid(this, other));
|
||||
|
||||
/// <summary>Indicates whether the current object is equal to another object of the same type.</summary>
|
||||
/// <param name="other">An object to compare with this object.</param>
|
||||
|
@ -214,14 +218,22 @@ namespace Vanara.PInvoke
|
|||
|
||||
/// <summary>Initializes a new instance of the <see cref="SafePSIDArray"/> class and assigns an existing handle.</summary>
|
||||
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
|
||||
/// <param name="count">The count of PSID array values pointed to by <paramref name="preexistingHandle"/>.</param>
|
||||
/// <param name="ownsHandle">
|
||||
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).
|
||||
/// <see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not
|
||||
/// recommended). If <see langword="true"/>, the individually allocated values for each PSID will also be released.
|
||||
/// </param>
|
||||
public SafePSIDArray(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
|
||||
public SafePSIDArray(IntPtr preexistingHandle, int count, bool ownsHandle = true) : base(preexistingHandle, ownsHandle)
|
||||
{
|
||||
if (ownsHandle)
|
||||
Count = count;
|
||||
else
|
||||
items = new List<SafePSID>(handle.ToIEnum<IntPtr>(count).Select(p => new SafePSID(p)));
|
||||
}
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="SafePSIDArray"/> class.</summary>
|
||||
/// <param name="pSIDs">A list of <see cref="SafePSID"/> instances.</param>
|
||||
public SafePSIDArray(IEnumerable<SafePSID> pSIDs) : this(pSIDs.Select(p => (PSID)p))
|
||||
public SafePSIDArray(IEnumerable<SafePSID> pSIDs) : this(pSIDs?.Select(p => (PSID)p))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -229,8 +241,9 @@ namespace Vanara.PInvoke
|
|||
/// <param name="pSIDs">A list of <see cref="SafePSID"/> instances.</param>
|
||||
public SafePSIDArray(IEnumerable<PSID> pSIDs) : base()
|
||||
{
|
||||
if (pSIDs is null) throw new ArgumentNullException(nameof(pSIDs));
|
||||
items = pSIDs.Select(p => new SafePSID(p)).ToList();
|
||||
SetHandle(items.Cast<IntPtr>().MarshalToPtr(i => LocalAlloc(LMEM.LPTR, i).DangerousGetHandle(), out _));
|
||||
SetHandle(items.Select(p => (IntPtr)p).MarshalToPtr(i => LocalAlloc(LMEM.LPTR, i).DangerousGetHandle(), out _));
|
||||
}
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="SafePSIDArray"/> class.</summary>
|
||||
|
@ -243,8 +256,13 @@ namespace Vanara.PInvoke
|
|||
get => items?.Count ?? throw new InvalidOperationException("The length must be set before using this function.");
|
||||
set
|
||||
{
|
||||
if (items != null) throw new InvalidOperationException("The length can only be set once.");
|
||||
items = new List<SafePSID>(handle.ToIEnum<IntPtr>(value).Select(p => new SafePSID(p)));
|
||||
if (items != null) throw new InvalidOperationException("The length can only be set for partially initialized arrays.");
|
||||
items = new List<SafePSID>();
|
||||
foreach (var psid in handle.ToIEnum<IntPtr>(value))
|
||||
{
|
||||
items.Add(new SafePSID(psid));
|
||||
LocalFree(psid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,88 @@
|
|||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
using Vanara.InteropServices;
|
||||
using Vanara.Extensions;
|
||||
using static Vanara.PInvoke.AdvApi32;
|
||||
|
||||
namespace Vanara.PInvoke.Tests
|
||||
{
|
||||
public static class UtilExt
|
||||
{
|
||||
public static byte[] GetBytes(this SecurityIdentifier si)
|
||||
{
|
||||
if (si == null) return new byte[0];
|
||||
var sidLen = si.BinaryLength;
|
||||
var bytes = new byte[sidLen];
|
||||
si.GetBinaryForm(bytes, 0);
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixture()]
|
||||
public class PSIDTests
|
||||
{
|
||||
public static SafePSID GetCurrentSid() => new SafePSID(WindowsIdentity.GetCurrent().User.GetBytes());
|
||||
|
||||
[Test()]
|
||||
public void CloneTest()
|
||||
{
|
||||
var sid = GetCurrentSid();
|
||||
var sid2 = sid.Clone();
|
||||
Assert.That(sid2.IsValidSid);
|
||||
Assert.That(sid, Is.EqualTo(sid2));
|
||||
}
|
||||
|
||||
[Test()]
|
||||
public void CopyTest()
|
||||
{
|
||||
var sid = GetCurrentSid();
|
||||
Assert.That(!sid.IsInvalid);
|
||||
Assert.That(sid.IsValidSid);
|
||||
Assert.That(sid.ToString(), Does.StartWith("S-1-5"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EqualsTest()
|
||||
{
|
||||
var ssid = new SafePSID("S-1-1-0");
|
||||
var esid = SafePSID.Everyone;
|
||||
var mesid = SafePSID.Current;
|
||||
Assert.That(ssid == esid, Is.True);
|
||||
Assert.That(ssid != mesid, Is.True);
|
||||
Assert.That(ssid.Equals(null), Is.False);
|
||||
Assert.That(ssid == null, Is.False);
|
||||
Assert.That(ssid.Equals((PSID)esid), Is.True);
|
||||
Assert.That(ssid.Equals((IntPtr)esid), Is.True);
|
||||
Assert.That(ssid.Equals((object)esid), Is.True);
|
||||
Assert.That(ssid.Equals((object)(PSID)esid), Is.True);
|
||||
Assert.That(ssid.Equals((object)(IntPtr)esid), Is.True);
|
||||
Assert.That(ssid.Equals((object)54), Is.False);
|
||||
}
|
||||
|
||||
[Test()]
|
||||
public void GetBinaryForm()
|
||||
{
|
||||
var sid = new SafePSID("S-1-1-0");
|
||||
Assert.That(sid.GetBinaryForm(), Is.EquivalentTo(new SecurityIdentifier(WellKnownSidType.WorldSid, null).GetBytes()));
|
||||
}
|
||||
|
||||
[Test()]
|
||||
public void InitTest()
|
||||
{
|
||||
var sid = GetCurrentSid();
|
||||
var sidStr = sid.ToString();
|
||||
Assert.That(sidStr, Does.StartWith("S-1-5-"));
|
||||
var ssid = sid.ToString().Substring(6).Split('-').Select(int.Parse).ToArray();
|
||||
var i = ssid[0];
|
||||
var dest = new int[ssid.Length - 1];
|
||||
Array.Copy(ssid, 1, dest, 0, ssid.Length - 1);
|
||||
var sid2 = SafePSID.Init(KnownSIDAuthority.SECURITY_NT_AUTHORITY, i, dest);
|
||||
Assert.That(sid2.IsValidSid);
|
||||
Assert.That(sid, Is.EqualTo(sid2));
|
||||
}
|
||||
|
||||
[Test()]
|
||||
public void PSIDTest()
|
||||
{
|
||||
|
@ -38,65 +111,69 @@ namespace Vanara.PInvoke.Tests
|
|||
Assert.That(sid.Equals(sid3), Is.False);
|
||||
}
|
||||
|
||||
[Test()]
|
||||
public void CopyTest()
|
||||
{
|
||||
var sid = GetCurrentSid();
|
||||
Assert.That(!sid.IsInvalid);
|
||||
Assert.That(sid.IsValidSid);
|
||||
Assert.That(sid.ToString(), Does.StartWith("S-1-5"));
|
||||
}
|
||||
|
||||
public static SafePSID GetCurrentSid() => new SafePSID(WindowsIdentity.GetCurrent().User.GetBytes());
|
||||
|
||||
[Test()]
|
||||
public void InitTest()
|
||||
{
|
||||
var sid = GetCurrentSid();
|
||||
var sidStr = sid.ToString();
|
||||
Assert.That(sidStr, Does.StartWith("S-1-5-"));
|
||||
var ssid = sid.ToString().Substring(6).Split('-').Select(int.Parse).ToArray();
|
||||
var i = ssid[0];
|
||||
var dest = new int[ssid.Length - 1];
|
||||
Array.Copy(ssid, 1, dest, 0, ssid.Length - 1);
|
||||
var sid2 = SafePSID.Init(KnownSIDAuthority.SECURITY_NT_AUTHORITY, i, dest);
|
||||
Assert.That(sid2.IsValidSid);
|
||||
Assert.That(sid, Is.EqualTo(sid2));
|
||||
}
|
||||
|
||||
[Test()]
|
||||
public void CloneTest()
|
||||
{
|
||||
var sid = GetCurrentSid();
|
||||
var sid2 = sid.Clone();
|
||||
Assert.That(sid2.IsValidSid);
|
||||
Assert.That(sid, Is.EqualTo(sid2));
|
||||
}
|
||||
|
||||
[Test()]
|
||||
public void GetBinaryForm()
|
||||
{
|
||||
var sid = new SafePSID("S-1-1-0");
|
||||
Assert.That(sid.GetBinaryForm(), Is.EquivalentTo(new SecurityIdentifier(WellKnownSidType.WorldSid, null).GetBytes()));
|
||||
}
|
||||
|
||||
[Test()]
|
||||
public void ToStringTest()
|
||||
{
|
||||
var sid = SafePSID.Init(KnownSIDAuthority.SECURITY_WORLD_SID_AUTHORITY, KnownSIDRelativeID.SECURITY_WORLD_RID);
|
||||
Assert.That(sid.ToString(), Is.EqualTo("S-1-1-0"));
|
||||
}
|
||||
}
|
||||
|
||||
public static class UtilExt
|
||||
{
|
||||
public static byte[] GetBytes(this SecurityIdentifier si)
|
||||
[Test]
|
||||
public void SafePSIDArrayCtorTest()
|
||||
{
|
||||
if (si == null) return new byte[0];
|
||||
var sidLen = si.BinaryLength;
|
||||
var bytes = new byte[sidLen];
|
||||
si.GetBinaryForm(bytes, 0);
|
||||
return bytes;
|
||||
var sids = new[] { SafePSID.Current, SafePSID.Everyone };
|
||||
SafePSIDArray safeArr = null;
|
||||
Assert.That(() => safeArr = new SafePSIDArray((SafePSID[])null), Throws.ArgumentNullException);
|
||||
Assert.That(() => safeArr = new SafePSIDArray(new SafePSID[0]), Throws.Nothing);
|
||||
Assert.That(safeArr.Count, Is.Zero);
|
||||
Assert.That(() => safeArr = new SafePSIDArray(sids), Throws.Nothing);
|
||||
Assert.That(safeArr.Count, Is.EqualTo(sids.Length));
|
||||
Assert.That(() => safeArr = new SafePSIDArray(Array.ConvertAll(sids, s => (PSID)s)), Throws.Nothing);
|
||||
Assert.That(safeArr.Count, Is.EqualTo(sids.Length));
|
||||
Assert.That(EqualSid(safeArr[0], SafePSID.Current), Is.True);
|
||||
Assert.That(EqualSid(safeArr[1], SafePSID.Everyone), Is.True);
|
||||
Assert.That(() => safeArr[2], Throws.Exception);
|
||||
Assert.That(safeArr, Is.EquivalentTo(sids));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SafePSIDArrayCtorTest2()
|
||||
{
|
||||
// Build in-memory SID array
|
||||
var sids = new[] { SafePSID.Current, SafePSID.Everyone };
|
||||
|
||||
SafePSIDArray safeArr = null;
|
||||
Assert.That(() => safeArr = new SafePSIDArray(IntPtr.Zero, 0), Throws.Nothing);
|
||||
Assert.That(safeArr.Count, Is.Zero);
|
||||
|
||||
// Unowned
|
||||
var ptr = Build();
|
||||
Assert.That(() => safeArr = new SafePSIDArray(ptr, sids.Length, false), Throws.Nothing);
|
||||
Assert.That(safeArr.Count, Is.EqualTo(sids.Length));
|
||||
foreach (var psid in ptr.ToIEnum<IntPtr>(sids.Length))
|
||||
Kernel32.LocalFree(psid);
|
||||
Kernel32.LocalFree(ptr);
|
||||
safeArr.Dispose();
|
||||
|
||||
// Owned
|
||||
ptr = Build();
|
||||
Assert.That(() => safeArr = new SafePSIDArray(ptr, sids.Length, true), Throws.Nothing);
|
||||
Assert.That(safeArr.Count, Is.EqualTo(sids.Length));
|
||||
safeArr.Dispose();
|
||||
|
||||
IntPtr Build()
|
||||
{
|
||||
var len = sids.Length * IntPtr.Size + sids.Sum(p => p.Length);
|
||||
var mem = Kernel32.LocalAlloc(Kernel32.LMEM.LPTR, sids.Length * IntPtr.Size);
|
||||
for (var i = 0; i < sids.Length; i++)
|
||||
{
|
||||
var sid = sids[i];
|
||||
var psid = Kernel32.LocalAlloc(Kernel32.LMEM.LPTR, sid.Length);
|
||||
Marshal.Copy(sid.GetBinaryForm(), 0, (IntPtr)psid, sid.Length);
|
||||
Marshal.WriteIntPtr((IntPtr)mem, i * IntPtr.Size, (IntPtr)psid);
|
||||
}
|
||||
return (IntPtr)mem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue