Пример #1
0
        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()
            });
        }
Пример #2
0
        /// <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);
        }
Пример #3
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));
            }
        }
Пример #4
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(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));
        }
Пример #5
0
        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));
                }
            }
        }
Пример #6
0
        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);
        }
Пример #7
0
        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));
        }
Пример #8
0
        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);
            }
        }
Пример #9
0
        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;
        }
Пример #10
0
        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);
                }
            }
        }
Пример #11
0
        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);
                }
            }
        }
Пример #12
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);
            }
        }
Пример #13
0
            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 _));
            }
Пример #14
0
 public static bool GetTokenInformation(SafeTokenHandle hToken, TOKEN_INFORMATION_CLASS tokenInfoClass, SafeNativeMemory pTokenInfo)
 {
     return(GetTokenInformation(hToken, tokenInfoClass, pTokenInfo.DangerousGetHandle(), pTokenInfo.Size, out _));
 }