简体   繁体   English

模拟后无法GetAccessControl,获取错误

[英]Can't GetAccessControl After Doing Impersonation, Get Error

I need to be able to change a file's access rights using an acct with higher privs. 我需要能够使用具有较高privs的acct来更改文件的访问权限。 Here's my impersonate code: 这是我的模拟代码:

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

Here's a snippet of using the impersonate: 这是使用模拟的摘要:

using (new Impersonation("domain", "username", "pswd"))
{
  FileInfo fi = new FileInfo(@"file name");
  FileSecurity fs = fi.GetAccessControl();
}

Here's what I'm getting when I try to do the GetAccessControl. 这就是我尝试执行GetAccessControl时得到的。 Any help would be greatly appreciated. 任何帮助将不胜感激。

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

I've done this before but it's in VB.net not C#, the code might help you though since this definitely worked: 我之前已经做过,但是它在VB.net中而不是C#中,但是代码可以为您提供帮助,因为这肯定可以工作:

In Psuedo Code it is: 在伪代码中,它是:

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)

Here's a complete class which does it. 这是一个完整的课程。 It's in VB.Net so you'll need to convert it to C#: 它在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

I solved this. 我解决了 I was using X:filename in the GetAccessControl. 我在GetAccessControl中使用X:filename。 Using the actual server path fixed it. 使用实际的服务器路径修复它。 Guerss there is no mapping on an impersonation Guerss上没有模拟的映射

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM