进行模拟后无法获取访问控制,出现错误

Posted

技术标签:

【中文标题】进行模拟后无法获取访问控制,出现错误【英文标题】:Can't GetAccessControl After Doing Impersonation, Get Error 【发布时间】:2014-02-17 22:28:42 【问题描述】:

我需要能够使用具有更高权限的帐户更改文件的访问权限。这是我的模拟代码:

    const int LOGON32_LOGON_INTERACTIVE = 2;
    const int LOGON32_PROVIDER_DEFAULT = 0;

    public Impersonation(string domain, string username, string password)
    
        var ok = LogonUser(username, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out this._handle);
        if (!ok)
        
            var errorCode = Marshal.GetLastWin32Error();
            throw new ApplicationException(string.Format("Could not impersonate the elevated user.  LogonUser returned error code 0.", errorCode));
        

        this._context = WindowsIdentity.Impersonate(this._handle.DangerousGetHandle());
    

    public void Dispose()
    
        this._context.Dispose();
        this._handle.Dispose();
    

    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);

    public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
    
        private SafeTokenHandle()
            : base(true)  

        [DllImport("kernel32.dll")]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [SuppressUnmanagedCodeSecurity]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool CloseHandle(IntPtr handle);

        protected override bool ReleaseHandle()
        
            return CloseHandle(handle);
        
    

这是使用模拟的 sn-p:

using (new Impersonation("domain", "username", "pswd"))

  FileInfo fi = new FileInfo(@"file name");
  FileSecurity fs = fi.GetAccessControl();

这是我尝试执行 GetAccessControl 时得到的结果。任何帮助将不胜感激。

System.InvalidOperationException: Method failed with unexpected error code 3.
   at System.Security.AccessControl.NativeObjectSecurity.CreateInternal(Resource
Type resourceType, Boolean isContainer, String name, SafeHandle handle, AccessCo
ntrolSections includeSections, Boolean createByName, ExceptionFromErrorCode exce
ptionFromErrorCode, Object exceptionContext)
  at System.Security.AccessControl.FileSystemSecurity..ctor(Boolean isContainer
, String name, AccessControlSections includeSections, Boolean isDirectory)
at System.Security.AccessControl.FileSecurity..ctor(String fileName, AccessCo
ntrolSections includeSections)
at System.IO.FileInfo.GetAccessControl()
at ImpersonationDemo.Main(String[] args) in c:\Users\david.ohara\Documents\Vi
sual Studio 2013\Projects\SecTest\SecTest\Program.cs:line 84

【问题讨论】:

【参考方案1】:

我以前做过,但它是在 VB.net 中而不是 C# 中,但代码可能会对你有所帮助,因为这肯定有效:

在伪代码中是:

LogonUserA(userName, domain, password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, token)
DuplicateToken(token, 2, tokenDuplicate)
_windowsIdentity = New WindowsIdentity(tokenDuplicate)
_impersonationContext = _windowsIdentity.Impersonate()
 System.Threading.Thread.CurrentPrincipal = New System.Security.Principal.WindowsPrincipal(_windowsIdentity)

这是一个完整的类。它位于 VB.Net 中,因此您需要将其转换为 C#:

Option Strict On
#Region "Imports"
Imports System.Security.Principal
Imports System.Runtime.InteropServices
Imports System
Imports System.Net
Imports System.Net.Security
Imports System.Security
Imports System.Security.Cryptography.X509Certificates
Imports System.Text
Imports System.IO
Imports System.Security.Cryptography
#End Region

Public Class ABCSecurity

#Region "Members"
    Private Shared _impersonationContext As WindowsImpersonationContext
    Private Shared _windowsIdentity As WindowsIdentity
#End Region

#Region "Win32 APIs"

    Private Shared LOGON32_LOGON_INTERACTIVE As Integer = 2
    Private Shared LOGON32_PROVIDER_DEFAULT As Integer = 0
    Private Shared LOGON32_LOGON_BATCH As Integer = 4
    Private Shared LOGON32_LOGON_NETWORK As Integer = 3


    Private Declare Function LogonUserA Lib "advapi32.dll" (ByVal lpszUsername As String, _
                            ByVal lpszDomain As String, _
                            ByVal lpszPassword As String, _
                            ByVal dwLogonType As Integer, _
                            ByVal dwLogonProvider As Integer, _
                            ByRef phToken As IntPtr) As Integer

    Private Declare Function DuplicateToken Lib "advapi32.dll" ( _
                            ByVal ExistingTokenHandle As IntPtr, _
                            ByVal ImpersonationLevel As Integer, _
                            ByRef DuplicateTokenHandle As IntPtr) As Integer

    Private Declare Function RevertToSelf Lib "advapi32.dll" () As Integer
    Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Long

    <DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
   Public Shared Function GetShortPathName(ByVal longPath As String, <MarshalAs(UnmanagedType.LPTStr)> ByVal ShortPath As StringBuilder, <MarshalAs(UnmanagedType.U4)> ByVal bufferSize As Integer) As Integer
    End Function

    Public Const FORMAT_MESSAGE_FROM_SYSTEM As Integer = &H1000


    <DllImport("Kernel32.dll")> _
    Public Shared Function FormatMessage(ByVal flags As Integer, ByVal [source] As IntPtr, ByVal messageId As Integer, ByVal languageId As Integer, ByVal buffer As StringBuilder, ByVal size As Integer, ByVal arguments As IntPtr) As Integer
    End Function
#End Region

#Region "Shared Properties"
    Public Shared ReadOnly Property CurrentlyLoggedOnUser() As String
        Get
            If IsImpersonating Then
                Return _windowsIdentity.Name
            Else
                Return System.Threading.Thread.CurrentPrincipal.Identity.Name
            End If
        End Get
    End Property

    Private Shared _isImpersonating As Boolean = False
    Public Shared ReadOnly Property IsImpersonating() As Boolean
        Get
            Return _isImpersonating
        End Get
    End Property
#End Region

#Region "Shared Methods"

    Public Shared Function impersonateValidUser(ByVal userName As String, _
    ByVal domain As String, ByVal password As String) As Boolean

        Dim token As IntPtr = IntPtr.Zero
        Dim tokenDuplicate As IntPtr = IntPtr.Zero
        Dim returnValue As Boolean = False

        If RevertToSelf() <> 0 Then
            If LogonUserA(userName, domain, password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, token) <> 0 Then
                If DuplicateToken(token, 2, tokenDuplicate) <> 0 Then
                    _windowsIdentity = New WindowsIdentity(tokenDuplicate)
                    _impersonationContext = _windowsIdentity.Impersonate()
                    If Not _impersonationContext Is Nothing Then
                        returnValue = True
                        _isImpersonating = True
                        System.Threading.Thread.CurrentPrincipal = New System.Security.Principal.WindowsPrincipal(_windowsIdentity) '_impersonationContext
                    Else
                        returnValue = False
                        _isImpersonating = False
                        My.User.InitializeWithWindowsUser()
                    End If
                End If
            Else
                'there was an error
                returnValue = False
                _isImpersonating = False

                Dim errorNumber As Integer = Marshal.GetLastWin32Error()
                If errorNumber = 1326 Then
                    Throw New Exception("Windows DomainAccount Authentication Failed ")
                Else
                    Dim sbFormatMessage As New StringBuilder(1024)
                    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, IntPtr.Zero, errorNumber, 0, sbFormatMessage, sbFormatMessage.Capacity, IntPtr.Zero)
                    Throw New Exception("Error occured. GetLastError returns " & System.Runtime.InteropServices.Marshal.GetLastWin32Error.ToString & System.Environment.NewLine & _
                    sbFormatMessage.ToString())
                End If

                returnValue = False
                _isImpersonating = False
                My.User.InitializeWithWindowsUser()
            End If
        End If

        If Not tokenDuplicate.Equals(IntPtr.Zero) Then
            CloseHandle(tokenDuplicate)
        End If

        If Not token.Equals(IntPtr.Zero) Then
            CloseHandle(token)
        End If

        Return returnValue
    End Function

    Public Shared Sub undoImpersonation()
        If _impersonationContext IsNot Nothing Then
            _impersonationContext.Undo()
            _impersonationContext = Nothing
            _isImpersonating = False
            My.User.InitializeWithWindowsUser()
        End If
    End Sub

#End Region

End Class

【讨论】:

谢谢。我试试看。 我用这段代码构建了一个 VB.NET 解决方案。我得到与上面完全相同的错误。 我解决了这个问题。我在 GetAccessControl 中使用 X:filename。使用实际的服务器路径修复它。猜猜没有关于模拟的映射。 @David,我很好奇。请你解释一下 X:filename 是什么意思? X:是一个映射驱动器吗?此外,如果您发布自己问题的答案,您可以自己接受,其他人可能会从您的发现中受益。【参考方案2】:

我解决了这个问题。我在 GetAccessControl 中使用 X:filename。使用实际的服务器路径修复它。猜猜没有模拟上的映射

【讨论】:

以上是关于进行模拟后无法获取访问控制,出现错误的主要内容,如果未能解决你的问题,请参考以下文章

SQL 访问控制错误:权限不足,无法对架构“INFORMATION_SCHEMA”进行操作

一天一坑系列无法访问Controller:SpringBoot项目启动后,请求无法进入控制器Controller中(可以进入服务,但是无法访问控制器)

由于访问控制检查,ios Safari XMLHttpRequest 无法加载

雪花:SQL 访问控制错误:权限不足,无法对架构进行操作

添加 Access-Control-Allow-Origin 后,仍然出现“请求的资源上没有“访问控制允许来源”标头”错误:*

如何绕过访问控制允许来源?