2009-08-10 17 views
2

ドメインに参加していないコンピュータでユーザーのWindows資格情報を検証しようとしています。これはSSPI APIの使用が可能になるはずですが、動作させることができませんでした。異なるドメインのWindowsユーザー資格情報の検証

私が試していたコードが含まれています(簡潔さのためにリソースのクリーンアップが省略されています)。 「 beesly

(I:
ドメイン control.dundermifflin.com: DUNDERMIFFLIN
ユーザー: jim_halpert
パス

ドメインコントローラ:これらは、重要な情報です実際のdundermifflin.comとのDNS競合はありません。

私が得るエラーはSEC_E_LOGON_DENIEDです。私はそのユーザーと他のアプリケーションでログオンできるので、ユーザー名とパスワードが正しいと確信しています。誰かが私を正しい方向に向けることができますか?

#include <Windows.h> 
#define SECURITY_WIN32 
#include <Security.h> 
#include <crtdbg.h> 

#pragma comment(lib, "Secur32.lib") 

int main() 
{ 
    SEC_CHAR* principal = "HOST/control.dundermifflin.com"; 
    SEC_CHAR* spn  = NULL; 

    SEC_CHAR* domain = "DUNDERMIFFLIN"; 
    SEC_CHAR* user = "jim_halpert"; 
    SEC_CHAR* pass = "beesly"; 

    ///////////////////////////////////////////// 
    // Fill out the authentication information // 
    ///////////////////////////////////////////// 

    SEC_WINNT_AUTH_IDENTITY auth; 
    auth.Domain   = reinterpret_cast<unsigned char*>(domain); 
    auth.DomainLength = strlen(domain); 
    auth.User   = reinterpret_cast<unsigned char*>(user); 
    auth.UserLength  = strlen(user); 
    auth.Password  = reinterpret_cast<unsigned char*>(pass); 
    auth.PasswordLength = strlen(pass); 
    auth.Flags   = SEC_WINNT_AUTH_IDENTITY_ANSI; 

    //////////////////////////////////////////// 
    // Allocate the client and server buffers // 
    //////////////////////////////////////////// 

    char clientOutBufferData[8192]; 
    char serverOutBufferData[8192]; 

    SecBuffer  clientOutBuffer; 
    SecBufferDesc clientOutBufferDesc; 

    SecBuffer  serverOutBuffer; 
    SecBufferDesc serverOutBufferDesc; 

    /////////////////////////////////////////// 
    // Get the client and server credentials // 
    /////////////////////////////////////////// 

    CredHandle clientCredentials; 
    CredHandle serverCredentials; 

    SECURITY_STATUS status; 

    status = ::AcquireCredentialsHandle(principal, 
             "Negotiate", 
             SECPKG_CRED_OUTBOUND, 
             NULL, 
             &auth, 
             NULL, 
             NULL, 
             &clientCredentials, 
             NULL); 

    _ASSERT(status == SEC_E_OK); 

    status = ::AcquireCredentialsHandle(principal, 
             "Negotiate", 
             SECPKG_CRED_INBOUND, 
             NULL, 
             NULL, 
             NULL, 
             NULL, 
             &serverCredentials, 
             NULL); 

    _ASSERT(status == SEC_E_OK); 

    ////////////////////////////////////// 
    // Initialize the security contexts // 
    ////////////////////////////////////// 

    CtxtHandle clientContext = {}; 
    unsigned long clientContextAttr = 0; 

    CtxtHandle serverContext = {}; 
    unsigned long serverContextAttr = 0; 

    ///////////////////////////// 
    // Clear the client buffer // 
    ///////////////////////////// 

    clientOutBuffer.BufferType = SECBUFFER_TOKEN; 
    clientOutBuffer.cbBuffer = sizeof clientOutBufferData; 
    clientOutBuffer.pvBuffer = clientOutBufferData; 

    clientOutBufferDesc.cBuffers = 1; 
    clientOutBufferDesc.pBuffers = &clientOutBuffer; 
    clientOutBufferDesc.ulVersion = SECBUFFER_VERSION; 

    /////////////////////////////////// 
    // Initialize the client context // 
    /////////////////////////////////// 

    status = InitializeSecurityContext(&clientCredentials, 
             NULL, 
             spn, 
             0, 
             0, 
             SECURITY_NATIVE_DREP, 
             NULL, 
             0, 
             &clientContext, 
             &clientOutBufferDesc, 
             &clientContextAttr, 
             NULL); 

    _ASSERT(status == SEC_I_CONTINUE_NEEDED); 

    ///////////////////////////// 
    // Clear the server buffer // 
    ///////////////////////////// 

    serverOutBuffer.BufferType = SECBUFFER_TOKEN; 
    serverOutBuffer.cbBuffer = sizeof serverOutBufferData; 
    serverOutBuffer.pvBuffer = serverOutBufferData; 

    serverOutBufferDesc.cBuffers = 1; 
    serverOutBufferDesc.pBuffers = &serverOutBuffer; 
    serverOutBufferDesc.ulVersion = SECBUFFER_VERSION; 

    ////////////////////////////////////////////////////// 
    // Accept the client security context on the server // 
    ////////////////////////////////////////////////////// 

    status = AcceptSecurityContext(&serverCredentials, 
            NULL, 
            &clientOutBufferDesc, 
            0, 
            SECURITY_NATIVE_DREP, 
            &serverContext, 
            &serverOutBufferDesc, 
            &serverContextAttr, 
            NULL); 

    _ASSERT(status == SEC_I_CONTINUE_NEEDED); 

    ///////////////////////////// 
    // Clear the client buffer // 
    ///////////////////////////// 

    clientOutBuffer.BufferType = SECBUFFER_TOKEN; 
    clientOutBuffer.cbBuffer = sizeof clientOutBufferData; 
    clientOutBuffer.pvBuffer = clientOutBufferData; 

    clientOutBufferDesc.cBuffers = 1; 
    clientOutBufferDesc.pBuffers = &clientOutBuffer; 
    clientOutBufferDesc.ulVersion = SECBUFFER_VERSION; 

    /////////////////////////////////////// 
    // Give the client the server buffer // 
    /////////////////////////////////////// 

    status = InitializeSecurityContext(&clientCredentials, 
             &clientContext, 
             spn, 
             0, 
             0, 
             SECURITY_NATIVE_DREP, 
             &serverOutBufferDesc, 
             0, 
             &clientContext, 
             &clientOutBufferDesc, 
             &clientContextAttr, 
             NULL); 

    _ASSERT(status == SEC_E_OK); 

    ////////////////////////////////////////////////////// 
    // Accept the client security context on the server // 
    ////////////////////////////////////////////////////// 

    status = AcceptSecurityContext(&serverCredentials, 
            &serverContext, 
            &clientOutBufferDesc, 
            0, 
            SECURITY_NATIVE_DREP, 
            &serverContext, 
            &serverOutBufferDesc, 
            &serverContextAttr, 
            NULL); 

    _ASSERT(status == SEC_E_LOGON_DENIED); 
} 
+0

セキュリティホールのユーザ名パス...ビットを編集したい場合があります; –

答えて

2

あなたはcontrol.dundermifflin.comドメインについて知らない同じマシンにいるので、これはうまくいかないでしょう。

ユーザー名とパスワードを確認する場合、最も簡単な方法は、実際のドメイン内のマシンに対して認証することです。これは "net use \ dc \ netlogon/u:username password"と同じくらい簡単ですが、SSPIで行う必要があるかどうかは言及していません。そうであれば、認証するDC上のサービスを見つける必要があります。たとえば、LDAPを使用できます。

もう1つの方法は、ドメイン以外のマシンに到達しようとしているドメインについて伝えることです。これは、ksetupツールを使用して行うことができます。あなたが持っているドメインのKDCホスト名を設定することができます。/AddKdcオプションを見てください。これによりKerberosは、指定された領域(別名ドメイン)に対して、KDC要求のために提供されたホスト名に移動する必要があることを認識します。

こちらがお役に立てば幸いです。

+0

これは間違いなく役立ちます。 SSPIは必須ではありませんが、KB 180548を読んでいるような感じです。 サービスで認証するには、ソケットを開く必要がありますか? – thudbang

+1

サービスによって異なります。 SSPIによって生成されたブロブをサーバー側と交換する必要があるため、サービスが使用しているトランスポートによって異なります。私がLDAPを使用するように提案したのは、LDAP APIを使用してSSPとしてネゴシエートを選択した場合、SSPIを正しく呼び出すかどうか、いくつかの詳細について心配する必要はないということです。 ksetupの設定を試して、この例をもう一度試してみることをお勧めします。また、SEC_I_CONTINUE_NEEDEDの場合は、コードがInitializeSecurityContext/AcceptSecurityContextの周りをループしている必要があります。 問題が解決するかどうか教えてください。 – Nasko

関連する問題