2009-05-26 14 views
0

これで1週間戦った後、私のコードでは常に失敗する理由はどこにもありませんでしたが、他の例では失敗しました。コンパイル中の私のコードは、私が知っている正しいログイン情報を持っているユーザーにはログインしません。それが失敗するところには次の行があります:LogonUserでMC++でエラーが発生しました

トークンがゼロであり、ユーザートークンに設定されていないため、ここでは失敗します。ここに私の完全なコードは次のとおりです。

今、マイクロソフトからこのわずかに変更された例を使用して
#ifndef UNCAPI_H 
#define UNCAPI_H 

#include <windows.h> 

#pragma once 
using namespace System; 
using namespace System::Runtime::InteropServices; 
using namespace System::Security::Principal; 
using namespace System::Security::Permissions; 

namespace UNCAPI 
{ 
public ref class UNCAccess 
{ 
public: 
    //bool Logon(String ^_srUsername, String ^_srDomain, String ^_srPassword); 
    [PermissionSetAttribute(SecurityAction::Demand, Name = "FullTrust")] 
    bool Logon(String ^_srUsername, String ^_srDomain, String ^_srPassword) 
    { 
     bool bSuccess = false; 
     token = IntPtr(0); 
     bSuccess = LogonUser(_srUsername, _srDomain, _srPassword, 8, 0, &tokenHandle); 

     if(bSuccess) 
     { 
      wi = gcnew WindowsIdentity(token); 
      wic = wi->Impersonate();     
     } 

     return bSuccess; 
    } 

    void UNCAccess::Logoff() 
    { 
     if (wic != nullptr) 
     { 
      wic->Undo(); 
     } 

     CloseHandle((int*)token.ToPointer());   
    } 
private: 
    [DllImport("advapi32.dll", SetLastError=true)]//[DllImport("advapi32.DLL", EntryPoint="LogonUserW", SetLastError=true, CharSet=CharSet::Unicode, ExactSpelling=true, CallingConvention=CallingConvention::StdCall)] 
    bool static LogonUser(String ^lpszUsername, String ^lpszDomain, String ^lpszPassword, int dwLogonType, int dwLogonProvider, IntPtr *phToken); 

    [DllImport("KERNEL32.DLL", EntryPoint="CloseHandle", SetLastError=true, CharSet=CharSet::Unicode, ExactSpelling=true, CallingConvention=CallingConvention::StdCall)] 
    bool static CloseHandle(int *handle); 
    IntPtr token; 
    WindowsIdentity ^wi; 
    WindowsImpersonationContext ^wic; 
};// End of Class UNCAccess 
}// End of Name Space 

#endif UNCAPI_H 

私は、ログインしてトークンを取得することができました:

#using <mscorlib.dll> 
#using <System.dll> 
using namespace System; 
using namespace System::Runtime::InteropServices; 
using namespace System::Security::Principal; 
using namespace System::Security::Permissions; 

[assembly:SecurityPermissionAttribute(SecurityAction::RequestMinimum, UnmanagedCode=true)] 
[assembly:PermissionSetAttribute(SecurityAction::RequestMinimum, Name = "FullTrust")]; 


[DllImport("advapi32.dll", SetLastError=true)] 
bool LogonUser(String^ lpszUsername, String^ lpszDomain, String^ lpszPassword, int dwLogonType, int dwLogonProvider, IntPtr* phToken); 

[DllImport("kernel32.dll", CharSet=System::Runtime::InteropServices::CharSet::Auto)] 
int FormatMessage(int dwFlags, IntPtr* lpSource, int dwMessageId, int dwLanguageId, String^ lpBuffer, int nSize, IntPtr *Arguments); 

[DllImport("kernel32.dll", CharSet=CharSet::Auto)] 
bool CloseHandle(IntPtr handle); 

[DllImport("advapi32.dll", CharSet=CharSet::Auto, SetLastError=true)] 
bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, IntPtr* DuplicateTokenHandle); 


// GetErrorMessage formats and returns an error message 
// corresponding to the input errorCode. 
String^ GetErrorMessage(int errorCode) 
{ 
    int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100; 
    int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200; 
    int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000; 

    //int errorCode = 0x5; //ERROR_ACCESS_DENIED 
    //throw new System.ComponentModel.Win32Exception(errorCode); 

    int messageSize = 255; 
    String^ lpMsgBuf = ""; 
    int dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; 

    IntPtr ptrlpSource = IntPtr::Zero; 
    IntPtr prtArguments = IntPtr::Zero; 

    int retVal = FormatMessage(dwFlags, &ptrlpSource, errorCode, 0, lpMsgBuf, messageSize, &prtArguments); 
    if (0 == retVal) 
    { 
     throw gcnew Exception(String::Format("Failed to format message for error code {0}. ", errorCode)); 
    } 

    return lpMsgBuf; 
} 

// Test harness. 
// If you incorporate this code into a DLL, be sure to demand FullTrust. 
[PermissionSetAttribute(SecurityAction::Demand, Name = "FullTrust")] 
int main() 
{  
    IntPtr tokenHandle = IntPtr(0); 
    IntPtr dupeTokenHandle = IntPtr(0); 
    try 
    { 
     String^ userName; 
     String^ domainName; 

     // Get the user token for the specified user, domain, and password using the 
     // unmanaged LogonUser method. 
     // The local machine name can be used for the domain name to impersonate a user on this machine. 
     Console::Write("Enter the name of the domain on which to log on: "); 
     domainName = Console::ReadLine(); 

     Console::Write("Enter the login of a user on {0} that you wish to impersonate: ", domainName); 
     userName = Console::ReadLine(); 

     Console::Write("Enter the password for {0}: ", userName); 

     const int LOGON32_PROVIDER_DEFAULT = 0; 
     //This parameter causes LogonUser to create a primary token. 
     const int LOGON32_LOGON_INTERACTIVE = 2; 
     const int SecurityImpersonation = 2; 

     tokenHandle = IntPtr::Zero; 
     dupeTokenHandle = IntPtr::Zero; 

     // Call LogonUser to obtain a handle to an access token. 
     bool returnValue = LogonUser(userName, domainName, Console::ReadLine(), 
     LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, 
     &tokenHandle); 

     Console::WriteLine("LogonUser called."); 

     if (false == returnValue) 
     { 
      int ret = Marshal::GetLastWin32Error(); 
      Console::WriteLine("LogonUser failed with error code : {0}", ret); 
      Console::WriteLine("\nError: [{0}] {1}\n", ret, GetErrorMessage(ret)); 
      int errorCode = 0x5; //ERROR_ACCESS_DENIED 
      throw gcnew System::ComponentModel::Win32Exception(errorCode); 
     } 

     Console::WriteLine("Did LogonUser Succeed? {0}", (returnValue?"Yes":"No")); 
     Console::WriteLine("Value of Windows NT token: {0}", tokenHandle); 

     // Check the identity. 
     Console::WriteLine("Before impersonation: {0}", WindowsIdentity::GetCurrent()->Name); 

     bool retVal = DuplicateToken(tokenHandle, SecurityImpersonation, &dupeTokenHandle); 
     if (false == retVal) 
     { 
      CloseHandle(tokenHandle); 
      Console::WriteLine("Exception thrown in trying to duplicate token.");   
      return -1; 
     } 

     // The token that is passed to the following constructor must 
     // be a primary token in order to use it for impersonation. 
     WindowsIdentity^ newId = gcnew WindowsIdentity(dupeTokenHandle); 
     WindowsImpersonationContext^ impersonatedUser = newId->Impersonate(); 

     // Check the identity. 
     Console::WriteLine("After impersonation: {0}", WindowsIdentity::GetCurrent()->Name); 

     // Stop impersonating the user. 
     impersonatedUser->Undo(); 

     // Check the identity. 
     Console::WriteLine("After Undo: {0}", WindowsIdentity::GetCurrent()->Name); 

     // Free the tokens. 
     if (tokenHandle != IntPtr::Zero) 
      CloseHandle(tokenHandle); 
     if (dupeTokenHandle != IntPtr::Zero) 
      CloseHandle(dupeTokenHandle); 
    } 
    catch(Exception^ ex) 
    { 
     Console::WriteLine("Exception occurred. {0}", ex->Message); 
    } 

Console::ReadLine(); 
}// end of function 

なぜMicrosoftのコードは私が失敗した場合は、成功する必要がありますか?

答えて

1

「なぜ私のコードは失敗するのですか?」

あなたのコードは、この行で何か違う:-)

を行いますので:

bool returnValue = LogonUser(userName, domainName, Console::ReadLine(), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, 
    &tokenHandle); 

'tokenHandle' の参照渡しが、あなたのバージョンであることに注意してください:

bSuccess = LogonUser(_srUsername, _srDomain, _srPassword, 8, 0, (IntPtr*)token.ToPointer()); 

あなたはではありません。は 'token'を参照渡しであるため、ローカル参照は更新されません。そのため、それを渡すときにはまだゼロですe WindowsIdentity。

+0

これも以前私が思っていたことです。これが私の現在のコードではその方法ですが、悲しいことにこれも失敗します。上記のコードを変更して、その変更が反映されるようにしました。 –

+0

編集したコードがどのように動作するかはわかりません - refでtokenHandleを渡していますが、他の場所では使用していません! –

0

私は答えはLogonUser関数を記述したMSDNの記事であることを考える:


LOGON32_LOGON_NETWORKログオンタイプが最速であるが、それは次の制限があります、

機能が偽装トークンを返します。プライマリトークンではありません。このトークンは、CreateProcessAsUser関数で直接使用することはできません。ただし、DuplicateTokenEx関数を呼び出して、トークンをプライマリトークンに変換し、CreateProcessAsUserで使用することができます。


関連する問題