LogonUserメソッドとWindowsIdentityクラスのImpersonateメソッドを組み合わせることで
ログインしているユーザとは別のユーザとしてプログラムを実行させることができる(ユーザの偽装)
手順としては以下のようになる
1.LogonUserメソッドで別ユーザのトークンを取得
2.WindowsIdentityクラスのImpersonateメソッドで1で取得したトークンを用いて別ユーザに偽装
3.偽装したユーザで任意の処理を実行
4.WindowsIdentityクラスのUndoメソッドで元のユーザに戻る
サンプルプログラムは以下の通り
Module1.vb
Imports System Imports System.Runtime.InteropServices Imports System.Security.Principal Imports System.Security.Permissions Imports Microsoft.VisualBasic <Assembly: SecurityPermissionAttribute(SecurityAction.RequestMinimum, UnmanagedCode:=True), _ Assembly: PermissionSetAttribute(SecurityAction.RequestMinimum, Name:="FullTrust")> Module Module1 Public Class ImpersonationDemo '必要なAPIの定義 Private Declare Auto Function LogonUser 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 Boolean <DllImport("kernel32.dll")> _ Public Shared Function FormatMessage(ByVal dwFlags As Integer, ByRef lpSource As IntPtr, _ ByVal dwMessageId As Integer, ByVal dwLanguageId As Integer, ByRef lpBuffer As [String], _ ByVal nSize As Integer, ByRef Arguments As IntPtr) As Integer End Function Public Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Boolean Public Declare Auto Function DuplicateToken Lib "advapi32.dll" (ByVal ExistingTokenHandle As IntPtr, _ ByVal SECURITY_IMPERSONATION_LEVEL As Integer, _ ByRef DuplicateTokenHandle As IntPtr) As Boolean '---メイン処理--- <PermissionSetAttribute(SecurityAction.Demand, Name:="FullTrust")> _ Public Overloads Shared Sub Main(ByVal args() As String) Dim tokenHandle As New IntPtr(0) Dim dupeTokenHandle As New IntPtr(0) Try Dim userName, domainName, password As String '★偽装するユーザID、パスワードを定義 domainName = "" 'ドメインに所属していないならドメインは不要 userName = "GisouTest" 'ユーザ password = "GisouTest" 'パスワード Const LOGON32_PROVIDER_DEFAULT As Integer = 0 Const LOGON32_LOGON_INTERACTIVE As Integer = 2 tokenHandle = IntPtr.Zero '■指定したユーザ情報でトークンを発行 Dim returnValue As Boolean = LogonUser(userName, domainName, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, tokenHandle) Console.WriteLine("LogonUser called.") '■トークンが発行できたか確認 If False = returnValue Then Dim ret As Integer = Marshal.GetLastWin32Error() Console.WriteLine("LogonUser failed with error code : {0}", ret) Throw New System.ComponentModel.Win32Exception(ret) Return End If Dim success As String If returnValue Then success = "Yes" Else success = "No" Console.WriteLine(("Did LogonUser succeed? " + success)) Console.WriteLine(("Value of Windows NT token: " + tokenHandle.ToString())) ' 現在のユーザの確認1 Console.WriteLine(("Before impersonation: " + WindowsIdentity.GetCurrent().Name)) '■発行したトークンで別ユーザに偽装 Dim newId As New WindowsIdentity(tokenHandle) Dim impersonatedUser As WindowsImpersonationContext = newId.Impersonate() '■偽装したユーザでファイルアクセス(偽装されたかのテスト) Call GetDirTest() ' 現在のユーザの確認2 Console.WriteLine(("After impersonation: " + WindowsIdentity.GetCurrent().Name)) '■ユーザの偽装をやめる impersonatedUser.Undo() ' 現在のユーザの確認3 Console.WriteLine(("After Undo: " + WindowsIdentity.GetCurrent().Name)) ' Free the tokens. If Not System.IntPtr.op_Equality(tokenHandle, IntPtr.Zero) Then CloseHandle(tokenHandle) End If Catch ex As Exception Console.WriteLine(("例外 →" + ex.Message)) End Try End Sub 'Main End Class 'Class1 Private Sub GetDirTest() '★IPアドレス Const SERVER_IP As String = "127.0.0.1" '★フォルダのパス(アクセス権のないフォルダだと例外が発生するのでそれでテストする) Const SERVER_DIRECTORY As String = "D:\Gisou\GisouTest\" 'フォルダにアクセス Dim serverPath As String = System.IO.Path.Combine(SERVER_IP, SERVER_DIRECTORY) 'サーバのディレクトリ内を走査 For Each serverFilePath As String In System.IO.Directory.GetFiles(serverPath) 'ファイル名を取得 Dim fileName As String = System.IO.Path.GetFileName(serverFilePath) Console.WriteLine("fileName→ " + fileName) Next End Sub End Module
このサンプルプログラムでは別ユーザに偽装したのちフォルダのアクセスを行っている
フォルダへのアクセス権を設定することで偽装できたかの確認ができる
(★の箇所を適当に書き換えること)
なお、LogonUserではローカルコンピュータにしかログオンできない
別のコンピュータへログインしたい場合は別の仕組みが必要
参考:LogonUserメソッドについて
http://msdn.microsoft.com/ja-jp/library/cc447468.aspx
動作確認環境:Windows XP sp3,Visual Stadio 2005