2017-11-22 26 views
0

SSPI를 사용하여 보안 연결을 만들기위한 코드를 구현했습니다. SMTP를 통해 메일을 보내는 데 사용합니다. 그것은 smtp.gmail.com와 내가 그것을 시도한 다른 서버들과 잘 동작한다. 하지만 smtp.live.com에서는 작동하지 않습니다. InitializeSecurityContext()의 두 번째 전화는 SEC_I_INCOMPLETE_CREDENTIALS입니다. 이것이 클라이언트 인증서를 제공해야 함을 의미하는 것으로 알고 있습니다. 그러나 이것은 공용 무료 메일 서버입니다. 어떤 클라이언트 인증서가 필요할 수 있습니까 ?? 아니면 잘못된 매개 변수 나 플래그를 사용합니까?InitializeSecurityContext (Schannel)가 예기치 않게 SEC_I_INCOMPLETE_CREDENTIALS를 반환합니다.

smtp.live.com:587에 연결 초기에는 암호화되지 않은 일반 텍스트로 연결됩니다. 먼저 EHLO 명령을 보낸 다음 STARTTLS 명령을 보냅니다.

SCHANNEL_CRED schCred; 
memset(&schCred,0,sizeof(schCred)); 
schCred.dwVersion=SCHANNEL_CRED_VERSION; // == 4 
schCred.dwFlags=SCH_CRED_NO_DEFAULT_CREDS; 

// acquire credentials 
SECURITY_STATUS status= 
    AcquireCredentialsHandle(NULL,UNISP_NAME,SECPKG_CRED_OUTBOUND,NULL, 
       &schCred,NULL,NULL,&Creds,NULL); 

// then I create a context 
const DWORD dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT | 
       ISC_REQ_REPLAY_DETECT  | 
       ISC_REQ_CONFIDENTIALITY | 
       ISC_RET_EXTENDED_ERROR | 
       ISC_REQ_ALLOCATE_MEMORY | 
       ISC_REQ_STREAM; 

SECURITY_STATUS scRet = 
      InitializeSecurityContextW(&Creds, NULL, targetName, dwSSPIFlags, 
       0, 0 , NULL, 0, &Context,&outBuffer, &dwSSPIOutFlags, &tsExpiry); 

// scRet==SEC_I_CONTINUE_NEEDED 

SendOutBuffer(outBuffers); 
ReceiveInputBuffers(inBuffers); 

// Then I call InitializeSecurityContext for the second time 
scRet = InitializeSecurityContext(&Creds, &Context, NULL, dwSSPIFlags, 
       0, 0, &inBuffer, 0, NULL, &outBuffer, &dwSSPIOutFlags, &tsExpiry); 


if((SEC_E_OK == scRet || SEC_I_CONTINUE_NEEDED == scRet || 
FAILED(scRet) && (dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR)) 
    && BufferNotEmpty(outBuffers)) {   

    SendOutBuffer(outBuffers);     
} 

if(SEC_I_INCOMPLETE_CREDENTIALS == scRet) {     
// This is where I am when connecting to smtp.live.com 
} 
+0

SECPKG_ATTR_ISSUER_LIST_EX와 함께 QueryContextAttributes (Schannel) 함수를 호출하여 서버가 허용 할 CA를 확인해 보았습니다. 그런 다음 시스템의 인증서를 검토하여 그 중 하나가 일치하는지 확인할 수 있습니다. (여기서 다른 클라이언트를 사용하여 문제가있는 서버에 연결하는 데 성공했다고 가정하고 있습니다. – SoronelHaetir

+0

* smtp.live.com *에 연결하는 포트는? 995에서 ssl pop3 서비스를 볼 수 있으며 여기에 모두 25 번으로 표시됩니다. – RbMm

+0

@RbMm 포트 587 – CITBL

답변

0

내 자신의 질문에 대답 : 그 후 나는 여기

아래의 코드를 사용하여 SSL 핸드 셰이크를 수행하는 코드입니다. 나는 Wireshark로 트래픽을 포착했고, 그렇습니다. smtp.live.com은 TLS 핸드 셰이크 중에 클라이언트 인증서를 요구합니다. 그러나 핸드 셰이크를 진행하려면 빈 (길이가 0 인) 인증서를 보내면 충분합니다. 이렇게하려면 SEC_I_INCOMPLETE_CREDENTIALS을 얻은 직후 동일한 매개 변수를 사용하여 InitializeSecurityContext()으로 다시 전화하면됩니다. 다시 말하면, SEC_I_INCOMPLETE_CREDENTIALS을 얻은 후에 나는 핸드 셰이크 루프를 계속하지만 다음 반복을위한 입력 버퍼의 수신을 건너 뜁니다. 두 번째로 SEC_I_INCOMPLETE_CREDENTIALS이 표시되면 내 클라이언트가 인증서로 인증을 지원하지 않기 때문에 오류가 발생합니다. (실제로는 SEC_I_INCOMPLETE_CREDENTIALS을 두 번 가져올 수 있는지 확실하지 않습니다.)