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



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

    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);
        }
    }

下面是使用模拟的代码片段:

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:Usersdavid.oharaDocumentsVi
sual Studio 2013ProjectsSecTestSecTestProgram.cs:line 84

我以前做过这个,但它是用 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

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

相关内容

最新更新