2017-11-22 16 views
0

SSPIを使用して安全な接続を作成するためのコードを実装しました。私はSMTP経由でメールを送信するためにそれを使用します。 smtp.gmail.comと私が試したいくつかの他のサーバーでうまく動作します。しかし、smtp.live.comでは動作しません。 InitializeSecurityContext()の2回目の呼び出しで私はSEC_I_INCOMPLETE_CREDENTIALSを返します。私が理解するように、これはクライアント証明書を提供する必要があることを意味します。しかし、これは公の無料メールサーバです。どのようなクライアント証明書が必要ですか?あるいは、間違ったパラメータやフラグを使用していますか?InitializeSecurityContext(Schannel)が予期せずSEC_I_INCOMPLETE_CREDENTIALSを返します

私はsmtp.live.com:587に接続します。最初は接続が暗号化されず、プレーンテキストです。まず、EHLOコマンドを送信した後、STARTTLSコマンドを送信します。その後、私はここで

以下のコードを使用してSSLハンドシェイクを実行するコードです:

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サービスを表示します。 – RbMm

+0

@RbMmポート587 – CITBL

答えて

0

は自分の質問に答えます。私はWiresharkでトラフィックを捕捉しました。はい、smtp.live.comは、TLSハンドシェイク中にクライアント証明書を要求します。しかし、ハンドシェイクを続行するには空の(長さゼロの)証明書を送るだけで十分です。これを行うには、SEC_I_INCOMPLETE_CREDENTIALSを取得した直後に、同じパラメータでInitializeSecurityContext()を再度呼び出します。つまり、SEC_I_INCOMPLETE_CREDENTIALSを取得した後、私はハンドシェイクループを続行しますが、次の1つの繰り返しの入力バッファの受信をスキップします。私がSEC_I_INCOMPLETE_CREDENTIALSをもう一度得ると、私のクライアントが証明書による認証をサポートしていないので、私はエラーで終了します。 (実際には、SEC_I_INCOMPLETE_CREDENTIALSを2回取得することが可能かどうかわかりません)

関連する問題