You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ansible/test/support/windows-integration/plugins/modules/win_whoami.ps1

838 lines
31 KiB
PowerShell

#!powershell
# Copyright: (c) 2017, Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#Requires -Module Ansible.ModuleUtils.Legacy
#Requires -Module Ansible.ModuleUtils.CamelConversion
$ErrorActionPreference = "Stop"
$params = Parse-Args $args -supports_check_mode $true
$_remote_tmp = Get-AnsibleParam $params "_ansible_remote_tmp" -type "path" -default $env:TMP
$session_util = @'
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text;
namespace Ansible
{
public class SessionInfo
{
// SECURITY_LOGON_SESSION_DATA
public UInt64 LogonId { get; internal set; }
public Sid Account { get; internal set; }
public string LoginDomain { get; internal set; }
public string AuthenticationPackage { get; internal set; }
public SECURITY_LOGON_TYPE LogonType { get; internal set; }
public string LoginTime { get; internal set; }
public string LogonServer { get; internal set; }
public string DnsDomainName { get; internal set; }
public string Upn { get; internal set; }
public ArrayList UserFlags { get; internal set; }
// TOKEN_STATISTICS
public SECURITY_IMPERSONATION_LEVEL ImpersonationLevel { get; internal set; }
public TOKEN_TYPE TokenType { get; internal set; }
// TOKEN_GROUPS
public ArrayList Groups { get; internal set; }
public ArrayList Rights { get; internal set; }
// TOKEN_MANDATORY_LABEL
public Sid Label { get; internal set; }
// TOKEN_PRIVILEGES
public Hashtable Privileges { get; internal set; }
}
public class Win32Exception : System.ComponentModel.Win32Exception
{
private string _msg;
public Win32Exception(string message) : this(Marshal.GetLastWin32Error(), message) { }
public Win32Exception(int errorCode, string message) : base(errorCode)
{
_msg = String.Format("{0} ({1}, Win32ErrorCode {2})", message, base.Message, errorCode);
}
public override string Message { get { return _msg; } }
public static explicit operator Win32Exception(string message) { return new Win32Exception(message); }
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct LSA_UNICODE_STRING
{
public UInt16 Length;
public UInt16 MaximumLength;
public IntPtr buffer;
}
[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
public UInt32 LowPart;
public Int32 HighPart;
}
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_LOGON_SESSION_DATA
{
public UInt32 Size;
public LUID LogonId;
public LSA_UNICODE_STRING Username;
public LSA_UNICODE_STRING LoginDomain;
public LSA_UNICODE_STRING AuthenticationPackage;
public SECURITY_LOGON_TYPE LogonType;
public UInt32 Session;
public IntPtr Sid;
public UInt64 LoginTime;
public LSA_UNICODE_STRING LogonServer;
public LSA_UNICODE_STRING DnsDomainName;
public LSA_UNICODE_STRING Upn;
public UInt32 UserFlags;
public LSA_LAST_INTER_LOGON_INFO LastLogonInfo;
public LSA_UNICODE_STRING LogonScript;
public LSA_UNICODE_STRING ProfilePath;
public LSA_UNICODE_STRING HomeDirectory;
public LSA_UNICODE_STRING HomeDirectoryDrive;
public UInt64 LogoffTime;
public UInt64 KickOffTime;
public UInt64 PasswordLastSet;
public UInt64 PasswordCanChange;
public UInt64 PasswordMustChange;
}
[StructLayout(LayoutKind.Sequential)]
public struct LSA_LAST_INTER_LOGON_INFO
{
public UInt64 LastSuccessfulLogon;
public UInt64 LastFailedLogon;
public UInt32 FailedAttemptCountSinceLastSuccessfulLogon;
}
public enum TOKEN_TYPE
{
TokenPrimary = 1,
TokenImpersonation
}
public enum SECURITY_IMPERSONATION_LEVEL
{
SecurityAnonymous,
SecurityIdentification,
SecurityImpersonation,
SecurityDelegation
}
public enum SECURITY_LOGON_TYPE
{
System = 0, // Used only by the Sytem account
Interactive = 2,
Network,
Batch,
Service,
Proxy,
Unlock,
NetworkCleartext,
NewCredentials,
RemoteInteractive,
CachedInteractive,
CachedRemoteInteractive,
CachedUnlock
}
[Flags]
public enum TokenGroupAttributes : uint
{
SE_GROUP_ENABLED = 0x00000004,
SE_GROUP_ENABLED_BY_DEFAULT = 0x00000002,
SE_GROUP_INTEGRITY = 0x00000020,
SE_GROUP_INTEGRITY_ENABLED = 0x00000040,
SE_GROUP_LOGON_ID = 0xC0000000,
SE_GROUP_MANDATORY = 0x00000001,
SE_GROUP_OWNER = 0x00000008,
SE_GROUP_RESOURCE = 0x20000000,
SE_GROUP_USE_FOR_DENY_ONLY = 0x00000010,
}
[Flags]
public enum UserFlags : uint
{
LOGON_OPTIMIZED = 0x4000,
LOGON_WINLOGON = 0x8000,
LOGON_PKINIT = 0x10000,
LOGON_NOT_OPTMIZED = 0x20000,
}
[StructLayout(LayoutKind.Sequential)]
public struct SID_AND_ATTRIBUTES
{
public IntPtr Sid;
public UInt32 Attributes;
}
[StructLayout(LayoutKind.Sequential)]
public struct LUID_AND_ATTRIBUTES
{
public LUID Luid;
public UInt32 Attributes;
}
[StructLayout(LayoutKind.Sequential)]
public struct TOKEN_GROUPS
{
public UInt32 GroupCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public SID_AND_ATTRIBUTES[] Groups;
}
[StructLayout(LayoutKind.Sequential)]
public struct TOKEN_MANDATORY_LABEL
{
public SID_AND_ATTRIBUTES Label;
}
[StructLayout(LayoutKind.Sequential)]
public struct TOKEN_STATISTICS
{
public LUID TokenId;
public LUID AuthenticationId;
public UInt64 ExpirationTime;
public TOKEN_TYPE TokenType;
public SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
public UInt32 DynamicCharged;
public UInt32 DynamicAvailable;
public UInt32 GroupCount;
public UInt32 PrivilegeCount;
public LUID ModifiedId;
}
[StructLayout(LayoutKind.Sequential)]
public struct TOKEN_PRIVILEGES
{
public UInt32 PrivilegeCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public LUID_AND_ATTRIBUTES[] Privileges;
}
public class AccessToken : IDisposable
{
public enum TOKEN_INFORMATION_CLASS
{
TokenUser = 1,
TokenGroups,
TokenPrivileges,
TokenOwner,
TokenPrimaryGroup,
TokenDefaultDacl,
TokenSource,
TokenType,
TokenImpersonationLevel,
TokenStatistics,
TokenRestrictedSids,
TokenSessionId,
TokenGroupsAndPrivileges,
TokenSessionReference,
TokenSandBoxInert,
TokenAuditPolicy,
TokenOrigin,
TokenElevationType,
TokenLinkedToken,
TokenElevation,
TokenHasRestrictions,
TokenAccessInformation,
TokenVirtualizationAllowed,
TokenVirtualizationEnabled,
TokenIntegrityLevel,
TokenUIAccess,
TokenMandatoryPolicy,
TokenLogonSid,
TokenIsAppContainer,
TokenCapabilities,
TokenAppContainerSid,
TokenAppContainerNumber,
TokenUserClaimAttributes,
TokenDeviceClaimAttributes,
TokenRestrictedUserClaimAttributes,
TokenRestrictedDeviceClaimAttributes,
TokenDeviceGroups,
TokenRestrictedDeviceGroups,
TokenSecurityAttributes,
TokenIsRestricted,
MaxTokenInfoClass
}
public IntPtr hToken = IntPtr.Zero;
[DllImport("kernel32.dll")]
private static extern IntPtr GetCurrentProcess();
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool OpenProcessToken(
IntPtr ProcessHandle,
TokenAccessLevels DesiredAccess,
out IntPtr TokenHandle);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool GetTokenInformation(
IntPtr TokenHandle,
TOKEN_INFORMATION_CLASS TokenInformationClass,
IntPtr TokenInformation,
UInt32 TokenInformationLength,
out UInt32 ReturnLength);
public AccessToken(TokenAccessLevels tokenAccessLevels)
{
IntPtr currentProcess = GetCurrentProcess();
if (!OpenProcessToken(currentProcess, tokenAccessLevels, out hToken))
throw new Win32Exception("OpenProcessToken() for current process failed");
}
public IntPtr GetTokenInformation<T>(out T tokenInformation, TOKEN_INFORMATION_CLASS tokenClass)
{
UInt32 tokenLength = 0;
GetTokenInformation(hToken, tokenClass, IntPtr.Zero, 0, out tokenLength);
IntPtr infoPtr = Marshal.AllocHGlobal((int)tokenLength);
if (!GetTokenInformation(hToken, tokenClass, infoPtr, tokenLength, out tokenLength))
throw new Win32Exception(String.Format("GetTokenInformation() data for {0} failed", tokenClass.ToString()));
tokenInformation = (T)Marshal.PtrToStructure(infoPtr, typeof(T));
return infoPtr;
}
public void Dispose()
{
GC.SuppressFinalize(this);
}
~AccessToken() { Dispose(); }
}
public class LsaHandle : IDisposable
{
[Flags]
public enum DesiredAccess : uint
{
POLICY_VIEW_LOCAL_INFORMATION = 0x00000001,
POLICY_VIEW_AUDIT_INFORMATION = 0x00000002,
POLICY_GET_PRIVATE_INFORMATION = 0x00000004,
POLICY_TRUST_ADMIN = 0x00000008,
POLICY_CREATE_ACCOUNT = 0x00000010,
POLICY_CREATE_SECRET = 0x00000020,
POLICY_CREATE_PRIVILEGE = 0x00000040,
POLICY_SET_DEFAULT_QUOTA_LIMITS = 0x00000080,
POLICY_SET_AUDIT_REQUIREMENTS = 0x00000100,
POLICY_AUDIT_LOG_ADMIN = 0x00000200,
POLICY_SERVER_ADMIN = 0x00000400,
POLICY_LOOKUP_NAMES = 0x00000800,
POLICY_NOTIFICATION = 0x00001000
}
public IntPtr handle = IntPtr.Zero;
[DllImport("advapi32.dll", SetLastError = true)]
private static extern uint LsaOpenPolicy(
LSA_UNICODE_STRING[] SystemName,
ref LSA_OBJECT_ATTRIBUTES ObjectAttributes,
DesiredAccess AccessMask,
out IntPtr PolicyHandle);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern uint LsaClose(
IntPtr ObjectHandle);
[DllImport("advapi32.dll", SetLastError = false)]
private static extern int LsaNtStatusToWinError(
uint Status);
[StructLayout(LayoutKind.Sequential)]
public struct LSA_OBJECT_ATTRIBUTES
{
public int Length;
public IntPtr RootDirectory;
public IntPtr ObjectName;
public int Attributes;
public IntPtr SecurityDescriptor;
public IntPtr SecurityQualityOfService;
}
public LsaHandle(DesiredAccess desiredAccess)
{
LSA_OBJECT_ATTRIBUTES lsaAttr;
lsaAttr.RootDirectory = IntPtr.Zero;
lsaAttr.ObjectName = IntPtr.Zero;
lsaAttr.Attributes = 0;
lsaAttr.SecurityDescriptor = IntPtr.Zero;
lsaAttr.SecurityQualityOfService = IntPtr.Zero;
lsaAttr.Length = Marshal.SizeOf(typeof(LSA_OBJECT_ATTRIBUTES));
LSA_UNICODE_STRING[] system = new LSA_UNICODE_STRING[1];
system[0].buffer = IntPtr.Zero;
uint res = LsaOpenPolicy(system, ref lsaAttr, desiredAccess, out handle);
if (res != 0)
throw new Win32Exception(LsaNtStatusToWinError(res), "LsaOpenPolicy() failed");
}
public void Dispose()
{
if (handle != IntPtr.Zero)
{
LsaClose(handle);
handle = IntPtr.Zero;
}
GC.SuppressFinalize(this);
}
~LsaHandle() { Dispose(); }
}
public class Sid
{
public string SidString { get; internal set; }
public string DomainName { get; internal set; }
public string AccountName { get; internal set; }
public SID_NAME_USE SidType { get; internal set; }
public enum SID_NAME_USE
{
SidTypeUser = 1,
SidTypeGroup,
SidTypeDomain,
SidTypeAlias,
SidTypeWellKnownGroup,
SidTypeDeletedAccount,
SidTypeInvalid,
SidTypeUnknown,
SidTypeComputer,
SidTypeLabel,
SidTypeLogon,
}
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool LookupAccountSid(
string lpSystemName,
[MarshalAs(UnmanagedType.LPArray)]
byte[] Sid,
StringBuilder lpName,
ref UInt32 cchName,
StringBuilder ReferencedDomainName,
ref UInt32 cchReferencedDomainName,
out SID_NAME_USE peUse);
public Sid(IntPtr sidPtr)
{
SecurityIdentifier sid;
try
{
sid = new SecurityIdentifier(sidPtr);
}
catch (Exception e)
{
throw new ArgumentException(String.Format("Failed to cast IntPtr to SecurityIdentifier: {0}", e));
}
SetSidInfo(sid);
}
public Sid(SecurityIdentifier sid)
{
SetSidInfo(sid);
}
public override string ToString()
{
return SidString;
}
private void SetSidInfo(SecurityIdentifier sid)
{
byte[] sidBytes = new byte[sid.BinaryLength];
sid.GetBinaryForm(sidBytes, 0);
StringBuilder lpName = new StringBuilder();
UInt32 cchName = 0;
StringBuilder referencedDomainName = new StringBuilder();
UInt32 cchReferencedDomainName = 0;
SID_NAME_USE peUse;
LookupAccountSid(null, sidBytes, lpName, ref cchName, referencedDomainName, ref cchReferencedDomainName, out peUse);
lpName.EnsureCapacity((int)cchName);
referencedDomainName.EnsureCapacity((int)cchReferencedDomainName);
SidString = sid.ToString();
if (!LookupAccountSid(null, sidBytes, lpName, ref cchName, referencedDomainName, ref cchReferencedDomainName, out peUse))
{
int lastError = Marshal.GetLastWin32Error();
if (lastError != 1332 && lastError != 1789) // Fails to lookup Logon Sid
{
throw new Win32Exception(lastError, String.Format("LookupAccountSid() failed for SID: {0} {1}", sid.ToString(), lastError));
}
else if (SidString.StartsWith("S-1-5-5-"))
{
AccountName = String.Format("LogonSessionId_{0}", SidString.Substring(8));
DomainName = "NT AUTHORITY";
SidType = SID_NAME_USE.SidTypeLogon;
}
else
{
AccountName = null;
DomainName = null;
SidType = SID_NAME_USE.SidTypeUnknown;
}
}
else
{
AccountName = lpName.ToString();
DomainName = referencedDomainName.ToString();
SidType = peUse;
}
}
}
public class SessionUtil
{
[DllImport("secur32.dll", SetLastError = false)]
private static extern uint LsaFreeReturnBuffer(
IntPtr Buffer);
[DllImport("secur32.dll", SetLastError = false)]
private static extern uint LsaEnumerateLogonSessions(
out UInt64 LogonSessionCount,
out IntPtr LogonSessionList);
[DllImport("secur32.dll", SetLastError = false)]
private static extern uint LsaGetLogonSessionData(
IntPtr LogonId,
out IntPtr ppLogonSessionData);
[DllImport("advapi32.dll", SetLastError = false)]
private static extern int LsaNtStatusToWinError(
uint Status);
[DllImport("advapi32", SetLastError = true)]
private static extern uint LsaEnumerateAccountRights(
IntPtr PolicyHandle,
IntPtr AccountSid,
out IntPtr UserRights,
out UInt64 CountOfRights);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool LookupPrivilegeName(
string lpSystemName,
ref LUID lpLuid,
StringBuilder lpName,
ref UInt32 cchName);
private const UInt32 SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001;
private const UInt32 SE_PRIVILEGE_ENABLED = 0x00000002;
private const UInt32 STATUS_OBJECT_NAME_NOT_FOUND = 0xC0000034;
private const UInt32 STATUS_ACCESS_DENIED = 0xC0000022;
public static SessionInfo GetSessionInfo()
{
AccessToken accessToken = new AccessToken(TokenAccessLevels.Query);
// Get Privileges
Hashtable privilegeInfo = new Hashtable();
TOKEN_PRIVILEGES privileges;
IntPtr privilegesPtr = accessToken.GetTokenInformation(out privileges, AccessToken.TOKEN_INFORMATION_CLASS.TokenPrivileges);
LUID_AND_ATTRIBUTES[] luidAndAttributes = new LUID_AND_ATTRIBUTES[privileges.PrivilegeCount];
try
{
PtrToStructureArray(luidAndAttributes, privilegesPtr.ToInt64() + Marshal.SizeOf(privileges.PrivilegeCount));
}
finally
{
Marshal.FreeHGlobal(privilegesPtr);
}
foreach (LUID_AND_ATTRIBUTES luidAndAttribute in luidAndAttributes)
{
LUID privLuid = luidAndAttribute.Luid;
UInt32 privNameLen = 0;
StringBuilder privName = new StringBuilder();
LookupPrivilegeName(null, ref privLuid, null, ref privNameLen);
privName.EnsureCapacity((int)(privNameLen + 1));
if (!LookupPrivilegeName(null, ref privLuid, privName, ref privNameLen))
throw new Win32Exception("LookupPrivilegeName() failed");
string state = "disabled";
if ((luidAndAttribute.Attributes & SE_PRIVILEGE_ENABLED) == SE_PRIVILEGE_ENABLED)
state = "enabled";
if ((luidAndAttribute.Attributes & SE_PRIVILEGE_ENABLED_BY_DEFAULT) == SE_PRIVILEGE_ENABLED_BY_DEFAULT)
state = "enabled-by-default";
privilegeInfo.Add(privName.ToString(), state);
}
// Get Current Process LogonSID, User Rights and Groups
ArrayList userRights = new ArrayList();
ArrayList userGroups = new ArrayList();
TOKEN_GROUPS groups;
IntPtr groupsPtr = accessToken.GetTokenInformation(out groups, AccessToken.TOKEN_INFORMATION_CLASS.TokenGroups);
SID_AND_ATTRIBUTES[] sidAndAttributes = new SID_AND_ATTRIBUTES[groups.GroupCount];
LsaHandle lsaHandle = null;
// We can only get rights if we are an admin
if (new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator))
lsaHandle = new LsaHandle(LsaHandle.DesiredAccess.POLICY_LOOKUP_NAMES);
try
{
PtrToStructureArray(sidAndAttributes, groupsPtr.ToInt64() + IntPtr.Size);
foreach (SID_AND_ATTRIBUTES sidAndAttribute in sidAndAttributes)
{
TokenGroupAttributes attributes = (TokenGroupAttributes)sidAndAttribute.Attributes;
if (attributes.HasFlag(TokenGroupAttributes.SE_GROUP_ENABLED) && lsaHandle != null)
{
ArrayList rights = GetAccountRights(lsaHandle.handle, sidAndAttribute.Sid);
foreach (string right in rights)
{
// Includes both Privileges and Account Rights, only add the ones with Logon in the name
// https://msdn.microsoft.com/en-us/library/windows/desktop/bb545671(v=vs.85).aspx
if (!userRights.Contains(right) && right.Contains("Logon"))
userRights.Add(right);
}
}
// Do not include the Logon SID in the groups category
if (!attributes.HasFlag(TokenGroupAttributes.SE_GROUP_LOGON_ID))
{
Hashtable groupInfo = new Hashtable();
Sid group = new Sid(sidAndAttribute.Sid);
ArrayList groupAttributes = new ArrayList();
foreach (TokenGroupAttributes attribute in Enum.GetValues(typeof(TokenGroupAttributes)))
{
if (attributes.HasFlag(attribute))
{
string attributeName = attribute.ToString().Substring(9);
attributeName = attributeName.Replace('_', ' ');
attributeName = attributeName.First().ToString().ToUpper() + attributeName.Substring(1).ToLower();
groupAttributes.Add(attributeName);
}
}
// Using snake_case here as I can't generically convert all dict keys in PS (see Privileges)
groupInfo.Add("sid", group.SidString);
groupInfo.Add("domain_name", group.DomainName);
groupInfo.Add("account_name", group.AccountName);
groupInfo.Add("type", group.SidType);
groupInfo.Add("attributes", groupAttributes);
userGroups.Add(groupInfo);
}
}
}
finally
{
Marshal.FreeHGlobal(groupsPtr);
if (lsaHandle != null)
lsaHandle.Dispose();
}
// Get Integrity Level
Sid integritySid = null;
TOKEN_MANDATORY_LABEL mandatoryLabel;
IntPtr mandatoryLabelPtr = accessToken.GetTokenInformation(out mandatoryLabel, AccessToken.TOKEN_INFORMATION_CLASS.TokenIntegrityLevel);
Marshal.FreeHGlobal(mandatoryLabelPtr);
integritySid = new Sid(mandatoryLabel.Label.Sid);
// Get Token Statistics
TOKEN_STATISTICS tokenStats;
IntPtr tokenStatsPtr = accessToken.GetTokenInformation(out tokenStats, AccessToken.TOKEN_INFORMATION_CLASS.TokenStatistics);
Marshal.FreeHGlobal(tokenStatsPtr);
SessionInfo sessionInfo = GetSessionDataForLogonSession(tokenStats.AuthenticationId);
sessionInfo.Groups = userGroups;
sessionInfo.Label = integritySid;
sessionInfo.ImpersonationLevel = tokenStats.ImpersonationLevel;
sessionInfo.TokenType = tokenStats.TokenType;
sessionInfo.Privileges = privilegeInfo;
sessionInfo.Rights = userRights;
return sessionInfo;
}
private static ArrayList GetAccountRights(IntPtr lsaHandle, IntPtr sid)
{
UInt32 res;
ArrayList rights = new ArrayList();
IntPtr userRightsPointer = IntPtr.Zero;
UInt64 countOfRights = 0;
res = LsaEnumerateAccountRights(lsaHandle, sid, out userRightsPointer, out countOfRights);
if (res != 0 && res != STATUS_OBJECT_NAME_NOT_FOUND)
throw new Win32Exception(LsaNtStatusToWinError(res), "LsaEnumerateAccountRights() failed");
else if (res != STATUS_OBJECT_NAME_NOT_FOUND)
{
LSA_UNICODE_STRING[] userRights = new LSA_UNICODE_STRING[countOfRights];
PtrToStructureArray(userRights, userRightsPointer.ToInt64());
rights = new ArrayList();
foreach (LSA_UNICODE_STRING right in userRights)
rights.Add(Marshal.PtrToStringUni(right.buffer));
}
return rights;
}
private static SessionInfo GetSessionDataForLogonSession(LUID logonSession)
{
uint res;
UInt64 count = 0;
IntPtr luidPtr = IntPtr.Zero;
SessionInfo sessionInfo = null;
UInt64 processDataId = ConvertLuidToUint(logonSession);
res = LsaEnumerateLogonSessions(out count, out luidPtr);
if (res != 0)
throw new Win32Exception(LsaNtStatusToWinError(res), "LsaEnumerateLogonSessions() failed");
Int64 luidAddr = luidPtr.ToInt64();
try
{
for (UInt64 i = 0; i < count; i++)
{
IntPtr dataPointer = IntPtr.Zero;
res = LsaGetLogonSessionData(luidPtr, out dataPointer);
if (res == STATUS_ACCESS_DENIED) // Non admins won't be able to get info for session's that are not their own
{
luidPtr = new IntPtr(luidPtr.ToInt64() + Marshal.SizeOf(typeof(LUID)));
continue;
}
else if (res != 0)
throw new Win32Exception(LsaNtStatusToWinError(res), String.Format("LsaGetLogonSessionData() failed {0}", res));
SECURITY_LOGON_SESSION_DATA sessionData = (SECURITY_LOGON_SESSION_DATA)Marshal.PtrToStructure(dataPointer, typeof(SECURITY_LOGON_SESSION_DATA));
UInt64 sessionDataid = ConvertLuidToUint(sessionData.LogonId);
if (sessionDataid == processDataId)
{
ArrayList userFlags = new ArrayList();
UserFlags flags = (UserFlags)sessionData.UserFlags;
foreach (UserFlags flag in Enum.GetValues(typeof(UserFlags)))
{
if (flags.HasFlag(flag))
{
string flagName = flag.ToString().Substring(6);
flagName = flagName.Replace('_', ' ');
flagName = flagName.First().ToString().ToUpper() + flagName.Substring(1).ToLower();
userFlags.Add(flagName);
}
}
sessionInfo = new SessionInfo()
{
AuthenticationPackage = Marshal.PtrToStringUni(sessionData.AuthenticationPackage.buffer),
DnsDomainName = Marshal.PtrToStringUni(sessionData.DnsDomainName.buffer),
LoginDomain = Marshal.PtrToStringUni(sessionData.LoginDomain.buffer),
LoginTime = ConvertIntegerToDateString(sessionData.LoginTime),
LogonId = ConvertLuidToUint(sessionData.LogonId),
LogonServer = Marshal.PtrToStringUni(sessionData.LogonServer.buffer),
LogonType = sessionData.LogonType,
Upn = Marshal.PtrToStringUni(sessionData.Upn.buffer),
UserFlags = userFlags,
Account = new Sid(sessionData.Sid)
};
break;
}
luidPtr = new IntPtr(luidPtr.ToInt64() + Marshal.SizeOf(typeof(LUID)));
}
}
finally
{
LsaFreeReturnBuffer(new IntPtr(luidAddr));
}
if (sessionInfo == null)
throw new Exception(String.Format("Could not find the data for logon session {0}", processDataId));
return sessionInfo;
}
private static string ConvertIntegerToDateString(UInt64 time)
{
if (time == 0)
return null;
if (time > (UInt64)DateTime.MaxValue.ToFileTime())
return null;
DateTime dateTime = DateTime.FromFileTime((long)time);
return dateTime.ToString("o");
}
private static UInt64 ConvertLuidToUint(LUID luid)
{
UInt32 low = luid.LowPart;
UInt64 high = (UInt64)luid.HighPart;
high = high << 32;
UInt64 uintValue = (high | (UInt64)low);
return uintValue;
}
private static void PtrToStructureArray<T>(T[] array, Int64 pointerAddress)
{
Int64 pointerOffset = pointerAddress;
for (int i = 0; i < array.Length; i++, pointerOffset += Marshal.SizeOf(typeof(T)))
array[i] = (T)Marshal.PtrToStructure(new IntPtr(pointerOffset), typeof(T));
}
public static IEnumerable<T> GetValues<T>()
{
return Enum.GetValues(typeof(T)).Cast<T>();
}
}
}
'@
$original_tmp = $env:TMP
$env:TMP = $_remote_tmp
Add-Type -TypeDefinition $session_util
$env:TMP = $original_tmp
$session_info = [Ansible.SessionUtil]::GetSessionInfo()
Function Convert-Value($value) {
$new_value = $value
if ($value -is [System.Collections.ArrayList]) {
$new_value = [System.Collections.ArrayList]@()
foreach ($list_value in $value) {
$new_list_value = Convert-Value -value $list_value
[void]$new_value.Add($new_list_value)
}
} elseif ($value -is [Hashtable]) {
$new_value = @{}
foreach ($entry in $value.GetEnumerator()) {
$entry_value = Convert-Value -value $entry.Value
# manually convert Sid type entry to remove the SidType prefix
if ($entry.Name -eq "type") {
$entry_value = $entry_value.Replace("SidType", "")
}
$new_value[$entry.Name] = $entry_value
}
} elseif ($value -is [Ansible.Sid]) {
$new_value = @{
sid = $value.SidString
account_name = $value.AccountName
domain_name = $value.DomainName
type = $value.SidType.ToString().Replace("SidType", "")
}
} elseif ($value -is [Enum]) {
$new_value = $value.ToString()
}
return ,$new_value
}
$result = @{
changed = $false
}
$properties = [type][Ansible.SessionInfo]
foreach ($property in $properties.DeclaredProperties) {
$property_name = $property.Name
$property_value = $session_info.$property_name
$snake_name = Convert-StringToSnakeCase -string $property_name
$result.$snake_name = Convert-Value -value $property_value
}
Exit-Json -obj $result