Cleaned and extended Vanara.Security to support `ActiveDirectoryExtension` on all platforms

pull/211/head
dahall 2020-12-18 17:51:35 -07:00
parent 9f65b87ab7
commit 9245c5b90e
4 changed files with 40 additions and 96 deletions

View File

@ -144,7 +144,7 @@ namespace Vanara.Security.AccessControl
/// <returns>An array of <see cref="SecurityIdentifier"/> objects representing all accounts with the specified privilege.</returns>
public IEnumerable<SecurityIdentifier> EnumerateAccountsWithRight(string privilege)
{
var ret = LsaEnumerateAccountsWithUserRight(Handle, privilege, out var buffer, out var count);
NTStatus ret = LsaEnumerateAccountsWithUserRight(Handle, privilege, out SafeLsaMemoryHandle buffer, out var count);
if (ret == NTStatus.STATUS_NO_MORE_ENTRIES)
return new SecurityIdentifier[0];
ThrowIfLsaError(ret);
@ -185,11 +185,11 @@ namespace Vanara.Security.AccessControl
{
if (names == null || names.Length == 0)
throw new ArgumentException(@"At least one user name must be supplied.", nameof(names));
var ret = LsaLookupNames2(Handle, localOnly ? LsaLookupNamesFlags.LSA_LOOKUP_ISOLATED_AS_LOCAL : 0, (uint)names.Length, names, out var domains, out var sids);
NTStatus ret = LsaLookupNames2(Handle, localOnly ? LsaLookupNamesFlags.LSA_LOOKUP_ISOLATED_AS_LOCAL : 0, (uint)names.Length, names, out SafeLsaMemoryHandle domains, out SafeLsaMemoryHandle sids);
if (ret != NTStatus.STATUS_SUCCESS && ret != NTStatus.STATUS_SOME_NOT_MAPPED)
ThrowIfLsaError(ret);
var d = domains.DangerousGetHandle().ToStructure<LSA_REFERENCED_DOMAIN_LIST>().DomainList.ToArray();
var ts = sids.DangerousGetHandle().ToIEnum<LSA_TRANSLATED_SID2>(names.Length).ToArray();
LSA_TRUST_INFORMATION[] d = domains.DangerousGetHandle().ToStructure<LSA_REFERENCED_DOMAIN_LIST>().DomainList.ToArray();
LSA_TRANSLATED_SID2[] ts = sids.DangerousGetHandle().ToIEnum<LSA_TRANSLATED_SID2>(names.Length).ToArray();
var retVal = new SystemAccountInfo[names.Length];
for (var i = 0; i < names.Length; i++)
retVal[i] = new SystemAccountInfo(names[i], ts[i].Use, IsValidSid(ts[i].Use) ? new SecurityIdentifier((IntPtr)ts[i].Sid) : null, ts[i].DomainIndex, d);
@ -206,14 +206,14 @@ namespace Vanara.Security.AccessControl
{
if (sids == null || sids.Length == 0)
throw new ArgumentException(@"At least one SecurityIdentifier must be supplied.", nameof(sids));
var opts = (preferInternetNames ? LsaLookupSidsFlags.LSA_LOOKUP_PREFER_INTERNET_NAMES : 0) |
LsaLookupSidsFlags opts = (preferInternetNames ? LsaLookupSidsFlags.LSA_LOOKUP_PREFER_INTERNET_NAMES : 0) |
(disallowConnectedAccts ? LsaLookupSidsFlags.LSA_LOOKUP_DISALLOW_CONNECTED_ACCOUNT_INTERNET_SID : 0);
var psids = sids.Select(s => new PinnedSid(s));
var ret = LsaLookupSids2(Handle, opts, (uint)sids.Length, psids.Select(s => s.PSID).ToArray(), out var domains, out var names);
IEnumerable<PinnedSid> psids = sids.Select(s => new PinnedSid(s));
NTStatus ret = LsaLookupSids2(Handle, opts, (uint)sids.Length, psids.Select(s => s.PSID).ToArray(), out SafeLsaMemoryHandle domains, out SafeLsaMemoryHandle names);
if (ret != NTStatus.STATUS_SUCCESS && ret != NTStatus.STATUS_SOME_NOT_MAPPED)
ThrowIfLsaError(ret);
var d = domains.DangerousGetHandle().ToStructure<LSA_REFERENCED_DOMAIN_LIST>().DomainList.ToArray();
var tn = names.DangerousGetHandle().ToIEnum<LSA_TRANSLATED_NAME>(sids.Length).ToArray();
LSA_TRUST_INFORMATION[] d = domains.DangerousGetHandle().ToStructure<LSA_REFERENCED_DOMAIN_LIST>().DomainList.ToArray();
LSA_TRANSLATED_NAME[] tn = names.DangerousGetHandle().ToIEnum<LSA_TRANSLATED_NAME>(sids.Length).ToArray();
var retVal = new SystemAccountInfo[sids.Length];
for (var i = 0; i < sids.Length; i++)
retVal[i] = new SystemAccountInfo(tn[i].Name.ToString(), tn[i].Use, sids[i], tn[i].DomainIndex, d);
@ -224,7 +224,7 @@ namespace Vanara.Security.AccessControl
/// <returns>An enumeration of CAPIDs.</returns>
public IEnumerable<SecurityIdentifier> GetAvailableCAPIDs()
{
ThrowIfLsaError(LsaGetAppliedCAPIDs(svr, out var capIdArray, out var capCount));
ThrowIfLsaError(LsaGetAppliedCAPIDs(svr, out SafeLsaMemoryHandle capIdArray, out var capCount));
return capCount == 0 || capIdArray.IsInvalid ? new SecurityIdentifier[0] : capIdArray.DangerousGetHandle().ToIEnum<IntPtr>((int)capCount).Select(p => new SecurityIdentifier(p));
}
@ -250,7 +250,7 @@ namespace Vanara.Security.AccessControl
private static void SetSystemAccess(SafeLSA_HANDLE hAcct, AccountLogonRights rights)
{
var cur = GetSystemAccess(hAcct);
AccountLogonRights cur = GetSystemAccess(hAcct);
ThrowIfLsaError(LsaSetSystemAccessAccount(hAcct, (int)(cur | rights)));
}
@ -260,8 +260,8 @@ namespace Vanara.Security.AccessControl
private SafeLSA_HANDLE GetAccount(string accountName, LsaAccountAccessMask mask = LsaAccountAccessMask.ACCOUNT_VIEW)
{
var sid = GetSid(accountName);
var res = LsaNtStatusToWinError(LsaOpenAccount(Handle, sid, mask, out var hAcct));
PSID sid = GetSid(accountName);
Win32Error res = LsaNtStatusToWinError(LsaOpenAccount(Handle, sid, mask, out SafeLSA_HANDLE hAcct));
if (res == Win32Error.ERROR_FILE_NOT_FOUND)
ThrowIfLsaError(LsaCreateAccount(Handle, sid, mask, out hAcct));
else
@ -285,7 +285,7 @@ namespace Vanara.Security.AccessControl
private PSID GetSid(string accountName)
{
int sidSize = 0, nameSize = 0;
LookupAccountName(svr, accountName, SafePSID.Null, ref sidSize, null, ref nameSize, out var accountType);
LookupAccountName(svr, accountName, SafePSID.Null, ref sidSize, null, ref nameSize, out SID_NAME_USE accountType);
var domainName = new System.Text.StringBuilder(nameSize);
var sid = new SafePSID(sidSize);
if (!LookupAccountName(string.Empty, accountName, sid, ref sidSize, domainName, ref nameSize, out accountType))
@ -311,8 +311,9 @@ namespace Vanara.Security.AccessControl
ctrl = parent;
if (!string.IsNullOrEmpty(userName))
{
user = userName;
}
else
{
using var identity = WindowsIdentity.GetCurrent();
@ -369,8 +370,9 @@ namespace Vanara.Security.AccessControl
ctrl = parent;
if (!string.IsNullOrEmpty(userName))
{
user = userName;
}
else
{
using var identity = WindowsIdentity.GetCurrent();
@ -393,7 +395,7 @@ namespace Vanara.Security.AccessControl
get => (Rights & right) == right;
set
{
var hAcct = ctrl.GetAccount(user, LsaAccountAccessMask.ACCOUNT_VIEW | LsaAccountAccessMask.ACCOUNT_ADJUST_SYSTEM_ACCESS);
SafeLSA_HANDLE hAcct = ctrl.GetAccount(user, LsaAccountAccessMask.ACCOUNT_VIEW | LsaAccountAccessMask.ACCOUNT_ADJUST_SYSTEM_ACCESS);
EnumFlagIndexer<AccountLogonRights> cur = GetSystemAccess(hAcct);
if (cur[right] == value) return;
cur[right] = value;

View File

@ -1,5 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Principal;
using static Vanara.PInvoke.AdvApi32;
namespace Vanara.Security
{
@ -20,7 +24,7 @@ namespace Vanara.Security
{
var acct = new NTAccount(id.Name);
var si = (SecurityIdentifier) acct.Translate(typeof(SecurityIdentifier));
var si = (SecurityIdentifier)acct.Translate(typeof(SecurityIdentifier));
return si.IsWellKnown(WellKnownSidType.LocalSystemSid) || si.IsWellKnown(WellKnownSidType.NetworkServiceSid) || si.IsWellKnown(WellKnownSidType.LocalServiceSid) || si.IsWellKnown(WellKnownSidType.ServiceSid);
}
@ -28,14 +32,15 @@ namespace Vanara.Security
return false;
}
/// <summary>Runs the specified function as the impersonated Windows identity.</summary>
/// <param name="identity">The impersonated identity under which to run the function.</param>
/// <param name="func">The System.Func to run.</param>
public static void Run(this WindowsIdentity identity, Action func)
{
if (identity is null)
{
func();
}
else
{
#if NETFRAMEWORK
@ -91,75 +96,5 @@ namespace Vanara.Security
catch { }
return null;
}
/*private static bool LookupAccountSid(string computerName, IntPtr sid, out string accountName, out string domainName, out SID_NAME_USE use)
{
int anLen = 0x100;
int dnLen = 0x100;
StringBuilder acctName = new StringBuilder(anLen);
StringBuilder domName = new StringBuilder(dnLen);
if (LookupAccountSid(computerName, sid, acctName, ref anLen, domName, ref dnLen, out use))
{
accountName = acctName.ToString().TrimEnd('$');
domainName = domName.ToString();
return true;
}
accountName = domainName = null;
return false;
}
private static bool FindUserFromSid(IntPtr incomingSid, string computerName, ref string userName)
{
SID_NAME_USE use;
string acctName, domainName;
if (!LookupAccountSid(computerName, incomingSid, out acctName, out domainName, out use))
throw new Win32Exception();
bool flag = use == SID_NAME_USE.SidTypeUser;
if (userName == null)
return flag;
if (!string.IsNullOrEmpty(domainName))
domainName = computerName;
userName = string.Format("{0}\\{1}", domainName, acctName);
return flag;
}
private static string FormattedUserNameFromSid(IntPtr incomingSid, string computerName)
{
string userName = string.Empty;
FindUserFromSid(incomingSid, computerName, ref userName);
if (!string.IsNullOrEmpty(userName))
{
SecurityIdentifier identifier = new SecurityIdentifier(incomingSid);
string[] strArray = userName.Split(new char[] { '\\' });
if (strArray.Length != 2)
{
return userName;
}
string str2 = strArray[1];
if ((identifier.IsWellKnown(WellKnownSidType.NetworkServiceSid) || identifier.IsWellKnown(WellKnownSidType.AnonymousSid)) || ((identifier.IsWellKnown(WellKnownSidType.LocalSystemSid) || identifier.IsWellKnown(WellKnownSidType.LocalServiceSid)) || identifier.IsWellKnown(WellKnownSidType.LocalSid)))
{
return str2;
}
if (string.Compare(strArray[0], computerName, StringComparison.CurrentCultureIgnoreCase) == 0)
{
userName = str2;
}
}
return userName;
}
private static string FormattedUserNameFromStringSid(string incomingSid, string computerName)
{
string str = string.Empty;
IntPtr zero = IntPtr.Zero;
if (!ConvertStringSidToSid(incomingSid, ref zero))
{
throw new Win32Exception();
}
str = FormattedUserNameFromSid(zero, computerName);
Marshal.FreeHGlobal(zero);
return str;
}*/
}
}

View File

@ -1,5 +1,4 @@
#if (NET20 || NET35 || NET40 || NET45)
using System;
using System;
using System.Linq;
using System.DirectoryServices.ActiveDirectory;
using Vanara.Extensions.Reflection;
@ -45,5 +44,4 @@ namespace Vanara.Extensions
return new SafeDsHandle(hDc);
}
}
}
#endif
}

View File

@ -17,9 +17,18 @@ AccountLogonRights, DesiredAccess, SystemPrivilege
</PackageReleaseNotes>
</PropertyGroup>
<ItemGroup Condition=" $(TargetFramework.StartsWith('net2')) Or $(TargetFramework.StartsWith('net3')) Or $(TargetFramework.StartsWith('net4')) ">
<Reference Include="System.DirectoryServices" />
</ItemGroup>
<Choose>
<When Condition=" $(TargetFramework.StartsWith('net2')) Or $(TargetFramework.StartsWith('net3')) Or $(TargetFramework.StartsWith('net4')) ">
<ItemGroup>
<Reference Include="System.DirectoryServices" />
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<PackageReference Include="System.DirectoryServices" Version="5.0.0" />
</ItemGroup>
</Otherwise>
</Choose>
<ItemGroup>
<ProjectReference Include="..\Core\Vanara.Core.csproj" />
<ProjectReference Include="..\PInvoke\NTDSApi\Vanara.PInvoke.NTDSApi.csproj" />