private static NetworkCredential UnpackAuthenticationBuffer([NotNull] SafeNativeMemory outCredBuffer) { Contract.Requires(outCredBuffer != null); const int maxLen = 100; var usernameBuf = new StringBuilder(maxLen); var passwordBuf = new StringBuilder(maxLen); var domainBuf = new StringBuilder(maxLen); var maxUserLen = maxLen; var maxDomainLen = maxLen; var maxPasswordLen = maxLen; if (!NativeMethods.CredUnPackAuthenticationBuffer(1, outCredBuffer.DangerousGetHandle(), outCredBuffer.Size, usernameBuf, ref maxUserLen, domainBuf, ref maxDomainLen, passwordBuf, ref maxPasswordLen)) { return(null); } return(new NetworkCredential() { UserName = usernameBuf.ToString(), Password = passwordBuf.ToString(), Domain = domainBuf.ToString() }); }
/// <summary> /// The function gets the elevation information of the current process. It /// dictates whether the process is elevated or not. Token elevation is only /// available on Windows Vista and newer operating systems, thus /// IsProcessElevated throws a C++ exception if it is called on systems prior /// to Windows Vista. It is not appropriate to use this function to determine /// whether a process is run as administartor. /// </summary> /// <returns> /// Returns true if the process is elevated. Returns false if it is not. /// </returns> /// <exception cref="System.ComponentModel.Win32Exception"> /// When any native Windows API call fails, the function throws a Win32Exception /// with the last error code. /// </exception> /// <remarks> /// TOKEN_INFORMATION_CLASS provides TokenElevationType to check the elevation /// type (TokenElevationTypeDefault / TokenElevationTypeLimited / /// TokenElevationTypeFull) of the process. It is different from TokenElevation /// in that, when UAC is turned off, elevation type always returns /// TokenElevationTypeDefault even though the process is elevated (Integrity /// Level == High). In other words, it is not safe to say if the process is /// elevated based on elevation type. Instead, we should use TokenElevation. /// </remarks> public static bool IsProcessElevated() { // Open the access token of the current process with TOKEN_QUERY. if (!NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle, TOKEN_QUERY, out var phToken)) { throw new Win32Exception(); } using var hToken = new SafeTokenHandle(phToken); // Allocate a buffer for the elevation information. using var pTokenElevation = new SafeNativeMemory <TOKEN_ELEVATION>(); // Retrieve token elevation information. if (!NativeMethods.GetTokenInformation(hToken, TOKEN_INFORMATION_CLASS.TokenElevation, pTokenElevation)) { // When the process is run on operating systems prior to Windows // Vista, GetTokenInformation returns false with the error code // ERROR_INVALID_PARAMETER because TokenElevation is not supported // on those operating systems. if ((Marshal.GetLastWin32Error() & 0xFFFF) == ERROR_INVALID_PARAMETER) { // => so on XP we are always "Elevated"! return(true); } throw new Win32Exception(); } // Marshal the TOKEN_ELEVATION struct from native to .NET object. var elevation = (TOKEN_ELEVATION)pTokenElevation; // TOKEN_ELEVATION.TokenIsElevated is a non-zero value if the token // has elevated privileges; otherwise, a zero value. return(elevation.TokenIsElevated != 0); }
private static NetworkCredential PromptForCredential([NotNull] IWin32Window parent, [CanBeNull] string caption, [CanBeNull] string message, int authenticationError, [NotNull] SafeNativeMemory inCredBuffer) { Contract.Requires(parent != null); Contract.Requires(inCredBuffer != null); var save = true; uint authPackage = 0; var credui = new CREDUI_INFO { cbSize = Marshal.SizeOf(typeof(CREDUI_INFO)), pszCaptionText = caption, pszMessageText = message, hwndParent = parent.Handle }; if (0 != NativeMethods.CredUIPromptForWindowsCredentials(ref credui, authenticationError, ref authPackage, inCredBuffer.DangerousGetHandle(), inCredBuffer.Size, out var outCredBufferPtr, out int outCredSize, ref save, 0)) { return(null); } using (var outCredBuffer = new SafeNativeMemory(outCredBufferPtr, outCredSize)) { return(UnpackAuthenticationBuffer(outCredBuffer)); } }
/// <summary> /// The function checks whether the object associated with the access token belongs /// to a user account that is a member of the local Administrators group, even if /// it currently is not elevated. /// </summary> /// <param name="userToken">The user token.</param> /// <returns> /// Returns true if the object associated with the access token belongs to user /// account that is a member of the local Administrators group. Returns false /// if the token does not. /// </returns> /// <exception cref="Win32Exception"> /// </exception> /// <exception cref="System.ComponentModel.Win32Exception">When any native Windows API call fails, the function throws a Win32Exception with the last error code.</exception> public static bool IsUserInAdminGroup(SafeTokenHandle userToken) { // Determine whether system is running Windows Vista or later operating // systems (major version >= 6) because they support linked tokens, but // previous versions (major version < 6) do not. var version = Environment.OSVersion.Version; if ((version != null) && (version.Major >= 6)) { // Running Windows Vista or later (major version >= 6). // Determine token type: limited, elevated, or default. // Allocate a buffer for the elevation type information. using var pElevationType = new SafeNativeMemory(sizeof(TOKEN_ELEVATION_TYPE)); // Retrieve token elevation type information. if (!NativeMethods.GetTokenInformation(userToken, TOKEN_INFORMATION_CLASS.TokenElevationType, pElevationType)) { throw new Win32Exception(); } // Marshal the TOKEN_ELEVATION_TYPE enum from native to .NET. var elevType = pElevationType.ReadInt32().ToEnum <TOKEN_ELEVATION_TYPE>(); // If limited, get the linked elevated token for further check. if (elevType == TOKEN_ELEVATION_TYPE.TokenElevationTypeLimited) { // Allocate a buffer for the linked token. using var pLinkedToken = new SafeNativeMemory(IntPtr.Size); // Get the linked token. if (!NativeMethods.GetTokenInformation(userToken, TOKEN_INFORMATION_CLASS.TokenLinkedToken, pLinkedToken)) { throw new Win32Exception(); } // Marshal the linked token value from native to .NET. var hLinkedToken = pLinkedToken.ReadIntPtr(); using var linkedToken = new SafeTokenHandle(hLinkedToken); return(IsAdministrator(linkedToken)); } } // CheckTokenMembership requires an impersonation token. If we just got // a linked token, it already is an impersonation token. If we did not // get a linked token, duplicate the original into an impersonation // token for CheckTokenMembership. if (!NativeMethods.DuplicateToken(userToken, SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, out var phTokenToCheck)) { throw new Win32Exception(); } using var hTokenToCheck = new SafeTokenHandle(phTokenToCheck); // Check if the token to be checked contains admin SID. return(IsAdministrator(hTokenToCheck)); }
public static int GetProcessIntegrityLevel() { // Open the access token of the current process with TOKEN_QUERY. if (!NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle, TOKEN_QUERY, out var phToken)) { throw new Win32Exception(); } using (var hToken = new SafeTokenHandle(phToken)) { // Then we must query the size of the integrity level information // associated with the token. Note that we expect GetTokenInformation // to return false with the ERROR_INSUFFICIENT_BUFFER error code // because we've given it a null buffer. On exit cbTokenIntegrityLevel will tell // the size of the group information. if (!NativeMethods.GetTokenInformation(hToken, TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, IntPtr.Zero, 0, out var cbTokenIntegrityLevel)) { var error = Marshal.GetLastWin32Error(); if (error != ERROR_INSUFFICIENT_BUFFER) { // When the process is run on operating systems prior to // Windows Vista, GetTokenInformation returns false with the // ERROR_INVALID_PARAMETER error code because // TokenIntegrityLevel is not supported on those OS's. throw new Win32Exception(error); } } // Now we allocate a buffer for the integrity level information. using (var pTokenIntegrityLevel = new SafeNativeMemory <TOKEN_MANDATORY_LABEL>(cbTokenIntegrityLevel)) { // Now we ask for the integrity level information again. This may fail // if an administrator has added this account to an additional group // between our first call to GetTokenInformation and this one. if (!NativeMethods.GetTokenInformation(hToken, TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, pTokenIntegrityLevel)) { throw new Win32Exception(); } // Marshal the TOKEN_MANDATORY_LABEL struct from native to .NET object. var tokenIntegrityLevel = (TOKEN_MANDATORY_LABEL)pTokenIntegrityLevel; // Integrity Level SIDs are in the form of S-1-16-0xXXXX. (e.g. // S-1-16-0x1000 stands for low integrity level SID). There is one // and only one sub-authority. var pIntegrityLevel = NativeMethods.GetSidSubAuthority(tokenIntegrityLevel.Label.Sid, 0); return(Marshal.ReadInt32(pIntegrityLevel)); } } }
private static SafeNativeMemory PackAuthenticationBuffer([CanBeNull] NetworkCredential?credential) { var userName = credential?.UserName; if (string.IsNullOrEmpty(userName)) { return(new SafeNativeMemory()); } var inCredSize = 0; NativeMethods.CredPackAuthenticationBuffer(0, userName, string.Empty, IntPtr.Zero, ref inCredSize); var buffer = new SafeNativeMemory(inCredSize); NativeMethods.CredPackAuthenticationBuffer(0, userName, string.Empty, buffer.DangerousGetHandle(), ref inCredSize); return(buffer); }
private static NetworkCredential?PromptForCredential(IntPtr parentHandle, string?caption, string?message, int authenticationError, SafeNativeMemory inCredBuffer) { var save = true; uint authPackage = 0; var credui = new CREDUI_INFO { cbSize = Marshal.SizeOf(typeof(CREDUI_INFO)), pszCaptionText = caption, pszMessageText = message, hwndParent = parentHandle }; if (0 != NativeMethods.CredUIPromptForWindowsCredentials(ref credui, authenticationError, ref authPackage, inCredBuffer.DangerousGetHandle(), inCredBuffer.Size, out var outCredBufferPtr, out int outCredSize, ref save, 0)) { return(null); } using var outCredBuffer = new SafeNativeMemory(outCredBufferPtr, outCredSize); return(UnpackAuthenticationBuffer(outCredBuffer)); }
private static NetworkCredential PromptForCredential([NotNull] IWin32Window parent, string caption, string message, int authenticationError, [NotNull] SafeNativeMemory inCredBuffer) { Contract.Requires(parent != null); Contract.Requires(inCredBuffer != null); var save = true; uint authPackage = 0; IntPtr outCredBufferPtr; int outCredSize; var credui = new CREDUI_INFO { cbSize = Marshal.SizeOf(typeof(CREDUI_INFO)), pszCaptionText = caption, pszMessageText = message, hwndParent = parent.Handle }; if (0 != NativeMethods.CredUIPromptForWindowsCredentials(ref credui, authenticationError, ref authPackage, inCredBuffer.DangerousGetHandle(), inCredBuffer.Size, out outCredBufferPtr, out outCredSize, ref save, 0)) return null; using (var outCredBuffer = new SafeNativeMemory(outCredBufferPtr, outCredSize)) { return UnpackAuthenticationBuffer(outCredBuffer); } }
private static SafeNativeMemory PackAuthenticationBuffer(NetworkCredential credential) { var userName = credential.Maybe().Return(c => c.UserName); if (string.IsNullOrEmpty(userName)) return new SafeNativeMemory(); var inCredSize = 0; NativeMethods.CredPackAuthenticationBuffer(0, userName, string.Empty, IntPtr.Zero, ref inCredSize); var buffer = new SafeNativeMemory(inCredSize); NativeMethods.CredPackAuthenticationBuffer(0, userName, string.Empty, buffer.DangerousGetHandle(), ref inCredSize); return buffer; }
public static int GetProcessIntegrityLevel() { IntPtr phToken; // Open the access token of the current process with TOKEN_QUERY. if (!NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle, TOKEN_QUERY, out phToken)) { throw new Win32Exception(); } using (var hToken = new SafeTokenHandle(phToken)) { // Then we must query the size of the integrity level information // associated with the token. Note that we expect GetTokenInformation // to return false with the ERROR_INSUFFICIENT_BUFFER error code // because we've given it a null buffer. On exit cbTokenIntegrityLevel will tell // the size of the group information. int cbTokenIntegrityLevel; if (!NativeMethods.GetTokenInformation(hToken, TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, IntPtr.Zero, 0, out cbTokenIntegrityLevel)) { var error = Marshal.GetLastWin32Error(); if (error != ERROR_INSUFFICIENT_BUFFER) { // When the process is run on operating systems prior to // Windows Vista, GetTokenInformation returns false with the // ERROR_INVALID_PARAMETER error code because // TokenIntegrityLevel is not supported on those OS's. throw new Win32Exception(error); } } // Now we allocate a buffer for the integrity level information. using (var pTokenIntegrityLevel = new SafeNativeMemory<TOKEN_MANDATORY_LABEL>(cbTokenIntegrityLevel)) { // Now we ask for the integrity level information again. This may fail // if an administrator has added this account to an additional group // between our first call to GetTokenInformation and this one. if (!NativeMethods.GetTokenInformation(hToken, TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, pTokenIntegrityLevel)) { throw new Win32Exception(); } // Marshal the TOKEN_MANDATORY_LABEL struct from native to .NET object. var tokenIntegrityLevel = (TOKEN_MANDATORY_LABEL)pTokenIntegrityLevel; // Integrity Level SIDs are in the form of S-1-16-0xXXXX. (e.g. // S-1-16-0x1000 stands for low integrity level SID). There is one // and only one sub-authority. var pIntegrityLevel = NativeMethods.GetSidSubAuthority(tokenIntegrityLevel.Label.Sid, 0); return Marshal.ReadInt32(pIntegrityLevel); } } }
public static bool IsProcessElevated() { IntPtr phToken; // Open the access token of the current process with TOKEN_QUERY. if (!NativeMethods.OpenProcessToken(Process.GetCurrentProcess().Handle, TOKEN_QUERY, out phToken)) { throw new Win32Exception(); } using (var hToken = new SafeTokenHandle(phToken)) { // Allocate a buffer for the elevation information. using (var pTokenElevation = new SafeNativeMemory<TOKEN_ELEVATION>()) { // Retrieve token elevation information. if (!NativeMethods.GetTokenInformation(hToken, TOKEN_INFORMATION_CLASS.TokenElevation, pTokenElevation)) { // When the process is run on operating systems prior to Windows // Vista, GetTokenInformation returns false with the error code // ERROR_INVALID_PARAMETER because TokenElevation is not supported // on those operating systems. if ((Marshal.GetLastWin32Error() & 0xFFFF) == ERROR_INVALID_PARAMETER) { // => so on XP we are always "Elevated"! return true; } throw new Win32Exception(); } // Marshal the TOKEN_ELEVATION struct from native to .NET object. var elevation = (TOKEN_ELEVATION)pTokenElevation; // TOKEN_ELEVATION.TokenIsElevated is a non-zero value if the token // has elevated privileges; otherwise, a zero value. return (elevation.TokenIsElevated != 0); } } }
/// <summary> /// The function checks whether the object associated with the access token belongs /// to a user account that is a member of the local Administrators group, even if /// it currently is not elevated. /// </summary> /// <param name="userToken">The user token.</param> /// <returns> /// Returns true if the object associated with the access token belongs to user /// account that is a member of the local Administrators group. Returns false /// if the token does not. /// </returns> /// <exception cref="Win32Exception"> /// </exception> /// <exception cref="System.ComponentModel.Win32Exception">When any native Windows API call fails, the function throws a Win32Exception with the last error code.</exception> public static bool IsUserInAdminGroup([NotNull] SafeTokenHandle userToken) { Contract.Requires(userToken != null); // Determine whether system is running Windows Vista or later operating // systems (major version >= 6) because they support linked tokens, but // previous versions (major version < 6) do not. var version = Environment.OSVersion.Version; if ((version != null) && (version.Major >= 6)) { // Running Windows Vista or later (major version >= 6). // Determine token type: limited, elevated, or default. // Allocate a buffer for the elevation type information. using (var pElevationType = new SafeNativeMemory(sizeof(TOKEN_ELEVATION_TYPE))) { // Retrieve token elevation type information. if (!NativeMethods.GetTokenInformation(userToken, TOKEN_INFORMATION_CLASS.TokenElevationType, pElevationType)) { throw new Win32Exception(); } // Marshal the TOKEN_ELEVATION_TYPE enum from native to .NET. var elevType = pElevationType.ReadInt32().ToEnum<TOKEN_ELEVATION_TYPE>(); // If limited, get the linked elevated token for further check. if (elevType == TOKEN_ELEVATION_TYPE.TokenElevationTypeLimited) { // Allocate a buffer for the linked token. using (var pLinkedToken = new SafeNativeMemory(IntPtr.Size)) { // Get the linked token. if (!NativeMethods.GetTokenInformation(userToken, TOKEN_INFORMATION_CLASS.TokenLinkedToken, pLinkedToken)) { throw new Win32Exception(); } // Marshal the linked token value from native to .NET. var hLinkedToken = pLinkedToken.ReadIntPtr(); using (var linkedToken = new SafeTokenHandle(hLinkedToken)) { return IsAdministrator(linkedToken); } } } } } // CheckTokenMembership requires an impersonation token. If we just got // a linked token, it already is an impersonation token. If we did not // get a linked token, duplicate the original into an impersonation // token for CheckTokenMembership. IntPtr phTokenToCheck; if (!NativeMethods.DuplicateToken(userToken, SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, out phTokenToCheck)) { throw new Win32Exception(); } using (var hTokenToCheck = new SafeTokenHandle(phTokenToCheck)) { // Check if the token to be checked contains admin SID. return IsAdministrator(hTokenToCheck); } }
public static bool GetTokenInformation([NotNull] SafeTokenHandle hToken, TOKEN_INFORMATION_CLASS tokenInfoClass, [NotNull] SafeNativeMemory pTokenInfo) { Contract.Requires(hToken != null); Contract.Requires(pTokenInfo != null); return(GetTokenInformation(hToken, tokenInfoClass, pTokenInfo.DangerousGetHandle(), pTokenInfo.Size, out _)); }
public static bool GetTokenInformation(SafeTokenHandle hToken, TOKEN_INFORMATION_CLASS tokenInfoClass, SafeNativeMemory pTokenInfo) { return(GetTokenInformation(hToken, tokenInfoClass, pTokenInfo.DangerousGetHandle(), pTokenInfo.Size, out _)); }