2009-08-10 4 views
2

도메인에 가입되어 있지 않은 컴퓨터에서 사용자의 Windows 자격 증명의 유효성을 검사하려고합니다. SSPI API를 사용하여이 작업을 수행 할 수 있어야하는 것처럼 보이지만 제대로 작동하지 못했습니다.다른 도메인의 Windows 사용자 자격 증명 유효성 검사

내가 시도한 코드가 포함되어 있습니다 (간략하게하기 위해 리소스 정리가 생략되었습니다). ' beesly

(I :
도메인 control.dundermifflin.com : 던더 미 플린
사용자 : jim_halpert
패스

도메인 컨트롤러 :이 정보의 중요한 조각이다 m-air 네트워크에서 테스트하기 때문에 실제 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를 사용할 수 있습니다.

작동 할 수있는 또 다른 방법은 비 도메인 시스템에 도달하려는 도메인에 대해 알리는 것입니다. 이 작업은 ksetup 도구를 사용하여 수행 할 수 있습니다. 보유하고있는 도메인에 대한 KDC 호스트 이름을 구성 할 수 있습니다./AddKdc 옵션을보십시오. 그러면 Kerberos는 제공된 영역 (일명 도메인)에 대해 KDC 요청에 제공된 호스트 이름으로 이동해야 함을 알 수 있습니다.

이 정보가 도움이되기를 바랍니다.

+0

확실히 도움이됩니다. SSPI는 요구 사항이 아니므로 KB 180548을 읽는 방법과 같이 보입니다. 서비스와 인증을 받으려면 소켓을 열어야합니까? – thudbang

+1

서비스에 따라 다릅니다. SSPI에서 생성 된 BLOB를 서버 측과 교환해야하므로 서비스가 사용하는 전송에 따라 다릅니다. LDAP를 사용하도록 제안한 이유는 LDAP API를 사용하고 SSP로 협상을 선택하면 일부 세부 정보와 SSPI를 올바르게 호출하는지 여부를 신경 쓰지 않아도된다는 것입니다. ksetup 구성을 시도하고 예제를 다시 시험해 보는 것이 좋습니다. 또한 SEC_I_CONTINUE_NEEDED 인 경우 코드가 InitializeSecurityContext/AcceptSecurityContext 주위를 반복해야합니다. 작동하는지 알려주세요. – Nasko

관련 문제