2011-09-30 25 views
11

を偽装するとき、私は私のコードでユーザーを偽装するために、次の方法のようなものを使用しています:別のクラスにおいて現在のユーザ名を取得

How do you do Impersonation in .NET?

、私はMYDOMAIN」のような現在のユーザを(見つける必要があり\ moose ")、私が現在別のユーザーに偽装しているかどうかはわかりません。

誰かに偽装している場合、どのようにユーザー名を取得しますか?

System.Environment.UserNameおよびSystem.Security.Principal.WindowsIdentity.GetCurrent()。名前は、どちらも現在の偽装ユーザーではなく、元のユーザーを返します。

詳細:

私は、ユーザーが通常にアクセスできませんnetowrk共有にいくつかのファイルにアクセスできるように、私はこの偽装をしています。

LOGON32_LOGON_INTERACTIVEのログオンタイプを使用すると、新しいユーザーが表示されますが、ネットワーク共有にアクセスできません。 LOGON32_LOGON_NEW_CREDENTIALS(値9)のログオンタイプを使用すると、ネットワーク共有にアクセスできますが、Environment.UserNameに新しいユーザーが表示されません。

+2

偽装されたユーザーを返す必要があります。あなたは、あなたが現在のユーザーを調べるメソッド呼び出しで偽装されていることを絶対に確信していますか? – mellamokb

+0

私は偽装されたユーザーを使って、ログオンしたユーザーがアクセスできないディレクトリにアクセスすることをテストしました。私はディレクトリにアクセスすることができますが、どちらの方法でも元のユーザーが返されます。なりすましをやめると、アクセスが拒否され、ディレクトリにアクセスしようとするため、正しく偽装されていることがわかります。 – Moose

+0

詳細を追加しました。問題の原因となっているログオンタイプと思われます。 – Moose

答えて

18

編集開始: 質問に答える私の最初の試みはあまり明確ではありませんでした。

まず、私はあなたが(偽装クラス内)のLogonUserのログオンタイプとしてLOGON32_LOGON_NEW_CREDENTIALSまたはLOGON32_LOGON_INTERACTIVEを使用した場合の特性WindowsIdentity.GetCurrent().Nameは を返します。何を指摘したいと思います。だから、私は 別の試みを開始したいと思います機能:

LOGON32_LOGON_INTERACTIVE LOGON32_LOGON_NEW_CREDENTIALSを使用して

// Assuming this code runs under USER_B 

using (var imp = new Impersonation("treyresearch", "USER_A", "SecurePwd", LOGON32_LOGON_INTERACTIVE)) 
{ 
    // Now, we run under USER_A 
    Console.Out.WriteLine(WindowsIdentity.GetCurrent().Name); // Will return USER_A 
} 
  • を使用して

    1. // Assuming this codes runs under USER_B 
      
      using (var imp = new Impersonation("treyresearch", "USER_A", "SecurePwd", LOGON32_LOGON_NEW_CREDENTIALS)) 
      { 
          Console.Out.WriteLine(WindowsIdentity.GetCurrent().Name); // Will return USER_B 
      } 
      

    、あなたの質問に記載されており、LogonUser機能のためのMSDNの説明と一致しているので、これは動作です。 LOGON32_LOGON_NEW_CREDENTIALSの場合、作成されたユーザートークンは、現在のユーザートークンの単なるクローンに過ぎません。これは、作成されたユーザーセッションが、呼び出しスレッドと同じ識別子を持つことを意味します。 LogonUser関数に渡された資格情報は、アウトバウンドネットワーク接続にのみ使用されます。

    第二には、私はLOGON32_LOGON_INTERACTIVELOGON32_LOGON_NEW_CREDENTIALSとの記述の違いが明確になる2つの状況を指摘してみましょう:computer_A、computer_B

  • 2人のユーザー:USER_A(computer_A上のローカル管理者)

    • 二つのドメインは、コンピューターに参加しました、user_B(Bの標準ユーザー権限のみ)
    • computer_B上で1つのネットワーク共有(mynetworkshare、user_Bは共有にアクセスする権限を持っています)。
    • computer_Aの1つのローカルフォルダ(user_Aのみがこのフォルダへの書き込み権限を持っています)。

    (user_Aのアカウントで)computer_Aでプログラムを実行します。 user_Bを偽装します(LOGON32_LOGON_INTERACTIVEを使用)。次に、computer_Bのネットワーク共有に接続し、ファイルをローカルフォルダにコピーしようとします(user_Aにのみこのフォルダへの書き込み権限があります)。次に、アクセスが拒否されたというエラーメッセージが表示されます。ファイル操作は、ローカルフォルダに対するアクセス許可を持たないuser_Bのアクセス許可で行われるためです。

    上記と同じです。しかし、現在はLOGON32_LOGON_NEW_CREDENTIALSを使用してuser_Bを偽装しています。ネットワークドライブに接続し、ネットワークドライブからローカルフォルダにファイルをコピーします。この場合、ファイル操作はuser_Aの許可で行われるため、操作は成功します。

    のEND EDIT

    希望、このことができます。

  • +0

    これは役に立ちます。残念ながら、私に必要なネットワーク共有にアクセスできる唯一の方法は、LOGON32_LOGON_NEW_CREDENTIALSを使用することですが、私は誰であるかわかりません。だから、私はこの特定のケースで偽装を使わないようにする必要があります。とにかくそれは本当の解決策だと思います。 LogonUser()に渡されたLogon型の違いに関する最も詳細な情報があるので、これを答えとしてマークしています。 – Moose

    +0

    @Mose:あなたが知っている必要があるかどうか偽装している場合は、次のstackoverflowの質問/回答を見てください:http://stackoverflow.com/questions/3973982/how-to-tell-if-current- thread-is-impersonating – Hans

    +0

    私はちょうどユーザーの身元を取得する方法を知る必要があり、これは私が探していたものを正確に与えました。驚くばかり! –

    5

    例によると、http://msdn.microsoft.com/en-us/library/chf6fbt4.aspxによると、偽装中に現在の身元が変更されます。コードが偽装されたコードブロック内にあることは確かですか?

    +0

    はい、テストされました。まだ運がありません。私は偽装権を取得していることは分かっていますが、元のユーザーを引き返しています。 – Moose

    1

    QueryCredentialsAttributesをご覧ください。

    +0

    GetTokenInformationを意味しますか? LogonUserから返された偽装トークンHANDLEが指定されている場合、CredHandleをQueryCredentialAttributesに供給することさえ可能かどうかは不明です。 –

    2

    私はそれをしないヘルパークラスを書いた:

    public static class ImpersonationUtils 
    { 
        private const int SW_SHOW = 5; 
        private const int TOKEN_QUERY = 0x0008; 
        private const int TOKEN_DUPLICATE = 0x0002; 
        private const int TOKEN_ASSIGN_PRIMARY = 0x0001; 
        private const int STARTF_USESHOWWINDOW = 0x00000001; 
        private const int STARTF_FORCEONFEEDBACK = 0x00000040; 
        private const int CREATE_UNICODE_ENVIRONMENT = 0x00000400; 
        private const int TOKEN_IMPERSONATE = 0x0004; 
        private const int TOKEN_QUERY_SOURCE = 0x0010; 
        private const int TOKEN_ADJUST_PRIVILEGES = 0x0020; 
        private const int TOKEN_ADJUST_GROUPS = 0x0040; 
        private const int TOKEN_ADJUST_DEFAULT = 0x0080; 
        private const int TOKEN_ADJUST_SESSIONID = 0x0100; 
        private const int STANDARD_RIGHTS_REQUIRED = 0x000F0000; 
        private const int TOKEN_ALL_ACCESS = 
         STANDARD_RIGHTS_REQUIRED | 
         TOKEN_ASSIGN_PRIMARY | 
         TOKEN_DUPLICATE | 
         TOKEN_IMPERSONATE | 
         TOKEN_QUERY | 
         TOKEN_QUERY_SOURCE | 
         TOKEN_ADJUST_PRIVILEGES | 
         TOKEN_ADJUST_GROUPS | 
         TOKEN_ADJUST_DEFAULT | 
         TOKEN_ADJUST_SESSIONID; 
    
        [StructLayout(LayoutKind.Sequential)] 
        private struct PROCESS_INFORMATION 
        { 
         public IntPtr hProcess; 
         public IntPtr hThread; 
         public int dwProcessId; 
         public int dwThreadId; 
        } 
    
        [StructLayout(LayoutKind.Sequential)] 
        private struct SECURITY_ATTRIBUTES 
        { 
         public int nLength; 
         public IntPtr lpSecurityDescriptor; 
         public bool bInheritHandle; 
        } 
    
        [StructLayout(LayoutKind.Sequential)] 
        private struct STARTUPINFO 
        { 
         public int cb; 
         public string lpReserved; 
         public string lpDesktop; 
         public string lpTitle; 
         public int dwX; 
         public int dwY; 
         public int dwXSize; 
         public int dwYSize; 
         public int dwXCountChars; 
         public int dwYCountChars; 
         public int dwFillAttribute; 
         public int dwFlags; 
         public short wShowWindow; 
         public short cbReserved2; 
         public IntPtr lpReserved2; 
         public IntPtr hStdInput; 
         public IntPtr hStdOutput; 
         public IntPtr hStdError; 
        } 
    
        private enum SECURITY_IMPERSONATION_LEVEL 
        { 
         SecurityAnonymous, 
         SecurityIdentification, 
         SecurityImpersonation, 
         SecurityDelegation 
        } 
    
        private enum TOKEN_TYPE 
        { 
         TokenPrimary = 1, 
         TokenImpersonation 
        } 
    
        [DllImport("advapi32.dll", SetLastError = true)] 
        private static extern bool CreateProcessAsUser(
         IntPtr hToken, 
         string lpApplicationName, 
         string lpCommandLine, 
         ref SECURITY_ATTRIBUTES lpProcessAttributes, 
         ref SECURITY_ATTRIBUTES lpThreadAttributes, 
         bool bInheritHandles, 
         int dwCreationFlags, 
         IntPtr lpEnvironment, 
         string lpCurrentDirectory, 
         ref STARTUPINFO lpStartupInfo, 
         out PROCESS_INFORMATION lpProcessInformation); 
    
        [DllImport("advapi32.dll", SetLastError = true)] 
        private static extern bool DuplicateTokenEx(
         IntPtr hExistingToken, 
         int dwDesiredAccess, 
         ref SECURITY_ATTRIBUTES lpThreadAttributes, 
         int ImpersonationLevel, 
         int dwTokenType, 
         ref IntPtr phNewToken); 
    
        [DllImport("advapi32.dll", SetLastError = true)] 
        private static extern bool OpenProcessToken(
         IntPtr ProcessHandle, 
         int DesiredAccess, 
         ref IntPtr TokenHandle); 
    
        [DllImport("userenv.dll", SetLastError = true)] 
        private static extern bool CreateEnvironmentBlock(
          ref IntPtr lpEnvironment, 
          IntPtr hToken, 
          bool bInherit); 
    
        [DllImport("userenv.dll", SetLastError = true)] 
        private static extern bool DestroyEnvironmentBlock(
          IntPtr lpEnvironment); 
    
        [DllImport("kernel32.dll", SetLastError = true)] 
        private static extern bool CloseHandle(
         IntPtr hObject); 
    
        private static void LaunchProcessAsUser(string cmdLine, IntPtr token, IntPtr envBlock, int sessionId) 
        { 
         var pi = new PROCESS_INFORMATION(); 
         var saProcess = new SECURITY_ATTRIBUTES(); 
         var saThread = new SECURITY_ATTRIBUTES(); 
         saProcess.nLength = Marshal.SizeOf(saProcess); 
         saThread.nLength = Marshal.SizeOf(saThread); 
    
         var si = new STARTUPINFO(); 
         si.cb = Marshal.SizeOf(si); 
         si.lpDesktop = @"WinSta0\Default"; 
         si.dwFlags = STARTF_USESHOWWINDOW | STARTF_FORCEONFEEDBACK; 
         si.wShowWindow = SW_SHOW; 
    
         if (!CreateProcessAsUser(
          token, 
          null, 
          cmdLine, 
          ref saProcess, 
          ref saThread, 
          false, 
          CREATE_UNICODE_ENVIRONMENT, 
          envBlock, 
          null, 
          ref si, 
          out pi)) 
         { 
          throw new Win32Exception(Marshal.GetLastWin32Error(), "CreateProcessAsUser failed"); 
         } 
        } 
    
        private static IDisposable Impersonate(IntPtr token) 
        { 
         var identity = new WindowsIdentity(token); 
         return identity.Impersonate(); 
        } 
    
        private static IntPtr GetPrimaryToken(Process process) 
        { 
         var token = IntPtr.Zero; 
         var primaryToken = IntPtr.Zero; 
    
         if (OpenProcessToken(process.Handle, TOKEN_DUPLICATE, ref token)) 
         { 
          var sa = new SECURITY_ATTRIBUTES(); 
          sa.nLength = Marshal.SizeOf(sa); 
    
          if (!DuplicateTokenEx(
           token, 
           TOKEN_ALL_ACCESS, 
           ref sa, 
           (int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, 
           (int)TOKEN_TYPE.TokenPrimary, 
           ref primaryToken)) 
          { 
           throw new Win32Exception(Marshal.GetLastWin32Error(), "DuplicateTokenEx failed"); 
          } 
    
          CloseHandle(token); 
         } 
         else 
         { 
          throw new Win32Exception(Marshal.GetLastWin32Error(), "OpenProcessToken failed"); 
         } 
    
         return primaryToken; 
        } 
    
        private static IntPtr GetEnvironmentBlock(IntPtr token) 
        { 
         var envBlock = IntPtr.Zero; 
         if (!CreateEnvironmentBlock(ref envBlock, token, false)) 
         { 
          throw new Win32Exception(Marshal.GetLastWin32Error(), "CreateEnvironmentBlock failed"); 
         } 
         return envBlock; 
        } 
    
        public static void LaunchAsCurrentUser(string cmdLine) 
        { 
         var process = Process.GetProcessesByName("explorer").FirstOrDefault(); 
         if (process != null) 
         { 
          var token = GetPrimaryToken(process); 
          if (token != IntPtr.Zero) 
          { 
           var envBlock = GetEnvironmentBlock(token); 
           if (envBlock != IntPtr.Zero) 
           { 
            LaunchProcessAsUser(cmdLine, token, envBlock, process.SessionId); 
            if (!DestroyEnvironmentBlock(envBlock)) 
            { 
             throw new Win32Exception(Marshal.GetLastWin32Error(), "DestroyEnvironmentBlock failed"); 
            } 
           } 
    
           CloseHandle(token); 
          } 
         } 
        } 
    
        public static IDisposable ImpersonateCurrentUser() 
        { 
         var process = Process.GetProcessesByName("explorer").FirstOrDefault(); 
         if (process != null) 
         { 
          var token = GetPrimaryToken(process); 
          if (token != IntPtr.Zero) 
          { 
           return Impersonate(token); 
          } 
         } 
    
         throw new Exception("Could not find explorer.exe"); 
        } 
    } 
    

    あなたはそのようにそれを使用することができます:あなたがここに見つけることができます

    ImpersonationUtils.LaunchAsCurrentUser("notepad"); 
    
    using (ImpersonationUtils.ImpersonateCurrentUser()) 
    { 
    
    } 
    

    詳しい説明と例:

    Impersonating CurrentUser from SYSTEM

    関連する問題