2014-05-14 22 views
3

是否有一系列標誌允許LogonUser在計算機未連接到網絡時(但所有帳戶本地已存在)都能返回可用於模擬本地用戶的令牌。Win32 API LogonUser離線訪問本地帳戶

我有域帳戶執行的應用程序

MYDOMAIN \ FooUser

,我試圖讓一個模擬令牌

MYLAPTOP \ TestUser用戶

然後我讀了一系列文字文件夾中的所有文件都可以通過FooUser讀取,但有些文件具有拒絕讀取權限TestUser

如果我登錄到Windows並從TestUser運行應用程序,權限映射正確並且文件上的權限被拒絕。如果我已連接到我的域並從FooUser運行應用程序,我也可以模擬TestUser,文件權限再次正確地拒絕訪問(使用LOGON32_LOGON_INTERACTIVE)。

的問題時,我的以太網電纜被拔掉,我嘗試調用LogonUserTestUser,我預計我會能夠以某種方式驗證本地憑據......發生在本地?

使用LOGON32_LOGON_INTERACTIVE

  • TestUser返回錯誤輸入憑據指示FooUser返回錯誤,表示「沒有登錄服務器可用」(有道理「錯誤的用戶名或密碼」
  • 輸入憑據,我不抱怨...除了我沒有連接到我的域名時,我是如何在第一個登錄Windows的?)

使用LOGON32_LOGON_NEW_CREDENTIALS

  • 進入亂碼憑證返回似乎有相同的訪問權限FooUser
using System; 
using System.ComponentModel; 
using System.Runtime.InteropServices; 
using System.Security; 
using System.Security.Principal; 
using Common.NativeMethods.Enumerations; 

namespace Common.NativeMethods 
{ 
    public static class AdvApi32 
    { 
     // http://www.pinvoke.net/default.aspx/advapi32.logonuser 
     // http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.securestringtoglobalallocunicode(v=vs.100).aspx 

     // PInvoke into the Win32 API to provide access to the 
     // LogonUser and CloseHandle functions. 
     [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
     internal static extern bool LogonUser(
      IntPtr username, 
      IntPtr domain, 
      IntPtr password, 
      LogonType logonType, 
      LogonProvider logonProvider, 
      ref IntPtr token 
     ); 

     public static WindowsIdentity LogonUser(SecureString p_userName, SecureString p_password, SecureString p_domainName) 
     { 
      IntPtr UserAccountToken = IntPtr.Zero; 

      IntPtr UserNamePointer = IntPtr.Zero; 
      IntPtr PasswordPointer = IntPtr.Zero; 
      IntPtr DomainNamePointer = IntPtr.Zero; 

      try 
      { 
       // Marshal the SecureString to unmanaged memory. 
       UserNamePointer = Marshal.SecureStringToGlobalAllocUnicode(p_password); 
       PasswordPointer = Marshal.SecureStringToGlobalAllocUnicode(p_userName); 
       DomainNamePointer = Marshal.SecureStringToGlobalAllocUnicode(p_domainName); 

       // Call LogonUser, passing the unmanaged (and decrypted) copy of the SecureString password. 
       bool ReturnValue = 
        AdvApi32 
         .LogonUser(
          UserNamePointer, 
          DomainNamePointer, 
          PasswordPointer, 
          LogonType.LOGON32_LOGON_INTERACTIVE, //.LOGON32_LOGON_NEW_CREDENTIALS, 
          LogonProvider.LOGON32_PROVIDER_DEFAULT, //.LOGON32_PROVIDER_WINNT50, 
          ref UserAccountToken); 

       // Get the Last win32 Error and throw an exception. 
       if (!ReturnValue && UserAccountToken == IntPtr.Zero) 
       { 
        int error = Marshal.GetLastWin32Error(); 

        throw 
         new Win32Exception(error); 
       } 

       // The token that is passed to the following constructor must 
       // be a primary token in order to use it for impersonation. 
       return 
        new WindowsIdentity(UserAccountToken); 
      } 
      finally 
      { 
       // Zero-out and free the unmanaged string reference. 
       Marshal.ZeroFreeGlobalAllocUnicode(UserNamePointer); 
       Marshal.ZeroFreeGlobalAllocUnicode(PasswordPointer); 
       Marshal.ZeroFreeGlobalAllocUnicode(DomainNamePointer); 

       // Close the token handle. 
       Kernel32.CloseHandle(UserAccountToken); 
      } 
     } 
    } 
} 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Runtime.InteropServices; 
using System.Runtime.ConstrainedExecution; 
using System.Security; 

namespace Common.NativeMethods 
{ 
    // http://msdn.microsoft.com/en-us/library/system.security.principal.windowsimpersonationcontext%28v=vs.100%29.aspx 

    public static class Kernel32 
    { 
     [DllImport("kernel32.dll", CharSet = CharSet.Auto)] 
     [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
     [SuppressUnmanagedCodeSecurity] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     internal extern static bool CloseHandle(IntPtr handle); 
    } 
} 
+1

你想說的LogonUser失敗試圖獲得當地「TestUser用戶」帳戶的用戶令牌時,並認爲這是你的問題? – elgonzo

+0

不完全。它在我連接到我的公司域網絡時起作用,但當我離線時不起作用。請注意,這是一個WinForms應用程序。我想知道是否有某種方式可以訪問緩存的憑證......因爲我顯然可以在我的筆記本電腦上登錄到「FooUser」或「TestUser」,而無需連接到公司網絡。當我沒有連接時,我無法找到「模擬」用戶(但更重要的是'TestUser')的方法。 – HodlDwon

+1

當模擬TestUser時,你如何獲得TestUser的令牌?更具體地說,調用LogonUser時域和用戶參數是什麼?你有沒有嘗試過 」。」作爲TestUser的(本地)域名? – elgonzo

回答

0

哎呀令牌......我犯了一個錯字,當我重構。 LogonUser工作得很好,當沒有連接到域;如果你至少指向正確的參數。

UserNamePointer = Marshal.SecureStringToGlobalAllocUnicode(p_password); 
PasswordPointer = Marshal.SecureStringToGlobalAllocUnicode(p_userName); 

固定

UserNamePointer = Marshal.SecureStringToGlobalAllocUnicode(p_userName); 
PasswordPointer = Marshal.SecureStringToGlobalAllocUnicode(p_password);