13 #include "tlsschannelbase.h"
23 :
TLSBase( th, server ), m_cleanedup( true ), m_haveCredentialsHandle( false ),
24 m_store( 0 ), m_cert( 0 )
40 memset( &m_tlsCred, 0,
sizeof( SCHANNEL_CRED ) );
41 m_tlsCred.dwVersion = SCHANNEL_CRED_VERSION;
42 m_tlsCred.grbitEnabledProtocols = SP_PROT_TLS1_SERVER;
44 if( !m_subject.empty() )
46 m_store = CertOpenSystemStore( 0,
"MY" );
50 int length = MultiByteToWideChar( CP_UTF8, 0, m_subject.c_str(), m_subject.length(), 0, 0 );
51 LPWSTR wsubject =
new WCHAR[length+1];
52 wsubject[length] = L
'\0';
53 length = MultiByteToWideChar( CP_UTF8, 0, m_subject.c_str(), m_subject.length(), wsubject, length );
54 m_cert = CertFindCertificateInStore( m_store, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
55 0, CERT_FIND_SUBJECT_STR, wsubject, 0 );
63 m_tlsCred.paCred = &m_cert;
71 if( !m_handler || !m_valid )
75 size_t currentPos = 0;
76 const size_t inputSize = data.size();
79 SecBufferDesc buffer_desc;
80 DWORD cbIoBufferLength = m_sizes.cbHeader + m_sizes.cbMaximumMessage + m_sizes.cbTrailer;
82 PBYTE e_iobuffer =
static_cast<PBYTE
>( LocalAlloc( LMEM_FIXED, cbIoBufferLength ) );
92 PBYTE e_message = e_iobuffer + m_sizes.cbHeader;
95 const size_t size = ( ( inputSize - currentPos ) > m_sizes.cbMaximumMessage )
96 ? m_sizes.cbMaximumMessage
97 : ( inputSize - currentPos );
98 memcpy( e_message, data.data() + currentPos, size );
102 buffer[0].pvBuffer = e_iobuffer;
103 buffer[0].cbBuffer = m_sizes.cbHeader;
104 buffer[0].BufferType = SECBUFFER_STREAM_HEADER;
106 buffer[1].pvBuffer = e_message;
107 buffer[1].cbBuffer = size;
108 buffer[1].BufferType = SECBUFFER_DATA;
110 buffer[2].pvBuffer =
static_cast<char*
>( buffer[1].pvBuffer ) + buffer[1].cbBuffer;
111 buffer[2].cbBuffer = m_sizes.cbTrailer;
112 buffer[2].BufferType = SECBUFFER_STREAM_TRAILER;
114 buffer[3].BufferType = SECBUFFER_EMPTY;
116 buffer_desc.ulVersion = SECBUFFER_VERSION;
117 buffer_desc.cBuffers = 4;
118 buffer_desc.pBuffers = buffer;
120 SECURITY_STATUS e_status = EncryptMessage( &m_context, 0, &buffer_desc, 0 );
121 if( SUCCEEDED( e_status ) )
123 std::string encrypted( reinterpret_cast<const char*>( e_iobuffer ),
124 buffer[0].cbBuffer + buffer[1].cbBuffer + buffer[2].cbBuffer );
129 LocalFree( e_iobuffer );
137 while( currentPos < inputSize - 1 );
139 LocalFree( e_iobuffer );
146 if( !m_handler || !m_valid )
161 SecBufferDesc buffer_desc;
162 DWORD cbIoBufferLength = m_sizes.cbHeader + m_sizes.cbMaximumMessage + m_sizes.cbTrailer;
163 bool wantNewBufferSize =
false;
165 PBYTE e_iobuffer =
static_cast<PBYTE
>( LocalAlloc( LMEM_FIXED, cbIoBufferLength ) );
174 SECURITY_STATUS e_status;
178 if( wantNewBufferSize )
181 e_iobuffer =
static_cast<PBYTE
>( LocalReAlloc( e_iobuffer, cbIoBufferLength, 0 ) );
182 wantNewBufferSize =
false;
186 memcpy( e_iobuffer, m_buffer.data(), m_buffer.size() >
187 cbIoBufferLength ? cbIoBufferLength : m_buffer.size() );
189 buffer[0].pvBuffer = e_iobuffer;
190 buffer[0].cbBuffer =
static_cast<unsigned long>( m_buffer.size() > cbIoBufferLength
193 buffer[0].BufferType = SECBUFFER_DATA;
194 buffer[1].cbBuffer = buffer[2].cbBuffer = buffer[3].cbBuffer = 0;
195 buffer[1].BufferType = buffer[2].BufferType = buffer[3].BufferType = SECBUFFER_EMPTY;
197 buffer_desc.ulVersion = SECBUFFER_VERSION;
198 buffer_desc.cBuffers = 4;
199 buffer_desc.pBuffers = buffer;
201 unsigned long processed_data = buffer[0].cbBuffer;
203 e_status = DecryptMessage( &m_context, &buffer_desc, 0, 0 );
211 SecBuffer* pDataBuffer = 0;
212 SecBuffer* pExtraBuffer = 0;
213 for(
int i = 1; i < 4; i++ )
215 if( !pDataBuffer && buffer[i].BufferType == SECBUFFER_DATA )
217 pDataBuffer = &buffer[i];
220 if( !pExtraBuffer && buffer[i].BufferType == SECBUFFER_EXTRA )
222 pExtraBuffer = &buffer[i];
225 if( e_status == SEC_E_OK )
227 std::string decrypted( reinterpret_cast<const char*>( pDataBuffer->pvBuffer ),
228 pDataBuffer->cbBuffer );
234 m_buffer.erase( 0, processed_data - pExtraBuffer->cbBuffer );
240 m_buffer.erase( 0, processed_data );
243 cbIoBufferLength = m_sizes.cbHeader + m_sizes.cbMaximumMessage + m_sizes.cbTrailer;
244 wantNewBufferSize =
true;
246 else if( e_status == SEC_E_INCOMPLETE_MESSAGE )
248 if( cbIoBufferLength < 200000 && m_buffer.size() > cbIoBufferLength )
250 cbIoBufferLength += 1000;
251 wantNewBufferSize =
true;
255 cbIoBufferLength = m_sizes.cbHeader + m_sizes.cbMaximumMessage + m_sizes.cbTrailer;
256 wantNewBufferSize =
true;
270 while( m_buffer.size() != 0 );
271 LocalFree( e_iobuffer );
288 DeleteSecurityContext( &m_context );
289 FreeCredentialsHandle( &m_credHandle );
297 void SChannelBase::setSizes()
299 if( QueryContextAttributes( &m_context, SECPKG_ATTR_STREAM_SIZES, &m_sizes ) != SEC_E_OK )
306 int SChannelBase::filetime2int( FILETIME t )
309 FileTimeToSystemTime( &t, &stUTC );
311 ts.tm_year = stUTC.wYear - 1900;
312 ts.tm_mon = stUTC.wMonth - 1;
313 ts.tm_mday = stUTC.wDay;
314 ts.tm_hour = stUTC.wHour;
315 ts.tm_min = stUTC.wMinute;
316 ts.tm_sec = stUTC.wSecond;
319 if ( ( unixtime = mktime( &ts ) ) == -1 )
321 return (
int)unixtime;
324 void SChannelBase::validateCert()
327 HTTPSPolicyCallbackData policyHTTPS;
328 CERT_CHAIN_POLICY_PARA policyParameter;
329 CERT_CHAIN_POLICY_STATUS policyStatus;
331 PCCERT_CONTEXT remoteCertContext = 0;
332 PCCERT_CHAIN_CONTEXT chainContext = 0;
333 CERT_CHAIN_PARA chainParameter;
334 PSTR serverName =
const_cast<char*
>( m_server.c_str() );
336 PWSTR uServerName = 0;
337 DWORD csizeServerName;
340 szOID_PKIX_KP_SERVER_AUTH,
341 szOID_SERVER_GATED_CRYPTO,
344 DWORD cUsages =
sizeof( Usages ) /
sizeof( LPSTR );
349 if( QueryContextAttributes( &m_context, SECPKG_ATTR_REMOTE_CERT_CONTEXT,
350 (PVOID)&remoteCertContext ) != SEC_E_OK )
359 csizeServerName = MultiByteToWideChar( CP_ACP, 0, serverName, -1, 0, 0 );
360 uServerName =
reinterpret_cast<WCHAR *
>( LocalAlloc( LMEM_FIXED,
361 csizeServerName *
sizeof( WCHAR ) ) );
369 csizeServerName = MultiByteToWideChar( CP_ACP, 0, serverName, -1, uServerName, csizeServerName );
370 if( !csizeServerName )
377 ZeroMemory( &chainParameter,
sizeof( chainParameter ) );
378 chainParameter.cbSize =
sizeof( chainParameter );
379 chainParameter.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
380 chainParameter.RequestedUsage.Usage.cUsageIdentifier = cUsages;
381 chainParameter.RequestedUsage.Usage.rgpszUsageIdentifier = Usages;
383 if( !CertGetCertificateChain( 0, remoteCertContext, 0, remoteCertContext->hCertStore,
384 &chainParameter, 0, 0, &chainContext ) )
392 ZeroMemory( &policyHTTPS,
sizeof( HTTPSPolicyCallbackData ) );
393 policyHTTPS.cbStruct =
sizeof( HTTPSPolicyCallbackData );
394 policyHTTPS.dwAuthType = AUTHTYPE_SERVER;
395 policyHTTPS.fdwChecks = 0;
396 policyHTTPS.pwszServerName = uServerName;
398 memset( &policyParameter, 0,
sizeof( policyParameter ) );
399 policyParameter.cbSize =
sizeof( policyParameter );
400 policyParameter.pvExtraPolicyPara = &policyHTTPS;
402 memset( &policyStatus, 0,
sizeof( policyStatus ) );
403 policyStatus.cbSize =
sizeof( policyStatus );
405 if( !CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_SSL, chainContext, &policyParameter,
413 if( policyStatus.dwError )
422 if( chainContext ) CertFreeCertificateChain( chainContext );
423 m_certInfo.
chain = valid;
426 void SChannelBase::connectionInfos()
428 SecPkgContext_ConnectionInfo conn_info;
430 memset( &conn_info, 0,
sizeof( conn_info ) );
432 if( QueryContextAttributes( &m_context, SECPKG_ATTR_CONNECTION_INFO, &conn_info ) == SEC_E_OK )
434 switch( conn_info.dwProtocol )
436 case SP_PROT_TLS1_CLIENT:
437 case SP_PROT_TLS1_SERVER:
440 case SP_PROT_SSL3_CLIENT:
441 case SP_PROT_SSL3_SERVER:
448 switch( conn_info.aiCipher )
451 m_certInfo.
cipher =
"3DES";
454 m_certInfo.
cipher =
"AES_128";
457 m_certInfo.
cipher =
"AES_256";
460 m_certInfo.
cipher =
"DES";
463 m_certInfo.
cipher =
"RC2";
466 m_certInfo.
cipher =
"RC4";
472 switch( conn_info.aiHash )
475 m_certInfo.
mac =
"MD5";
478 m_certInfo.
mac =
"SHA";
486 void SChannelBase::certData()
488 PCCERT_CONTEXT remoteCertContext = 0;
489 CHAR certString[1000];
493 if( QueryContextAttributes( &m_context, SECPKG_ATTR_REMOTE_CERT_CONTEXT,
494 (PVOID)&remoteCertContext ) != SEC_E_OK )
501 m_certInfo.
date_from = filetime2int( remoteCertContext->pCertInfo->NotBefore );
505 m_certInfo.
date_to = filetime2int( remoteCertContext->pCertInfo->NotAfter );
506 if( m_certInfo.
date_to < time( 0 ) )
509 if( !CertNameToStrA( remoteCertContext->dwCertEncodingType,
510 &remoteCertContext->pCertInfo->Subject,
511 CERT_NAME_STR_NO_PLUS_FLAG,
512 certString,
sizeof( certString ) ) )
517 m_certInfo.
server = certString;
519 if( certString != m_server )
522 if( !CertNameToStrA( remoteCertContext->dwCertEncodingType,
523 &remoteCertContext->pCertInfo->Issuer,
524 CERT_NAME_STR_NO_PLUS_FLAG,
525 certString,
sizeof( certString ) ) )
530 m_certInfo.
issuer = certString;
533 void SChannelBase::setCertinfos()
541 void SChannelBase::print_error(
int errorcode,
const char* place )
543 if( errorcode != SEC_E_OK )
544 printf(
"Win error at %s.\n", place );
551 case SEC_E_MESSAGE_ALTERED:
552 printf(
"\tValue:\tSEC_E_MESSAGE_ALTERED\n" );
553 printf(
"\tDesc:\tThe message has been altered.\n" );
555 case SEC_E_INSUFFICIENT_MEMORY:
556 printf(
"\tValue:\tSEC_E_INSUFFICIENT_MEMORY\n" );
557 printf(
"\tDesc:\tThere is not enough memory available to complete the requested action.\n" );
559 case SEC_E_INTERNAL_ERROR:
560 printf(
"\tValue:\tSEC_E_INTERNAL_ERROR\n" );
561 printf(
"\tDesc:\tAn error occurred that did not map to an SSPI error code.\n" );
563 case SEC_E_NO_CREDENTIALS:
564 printf(
"\tValue:\tSEC_E_NO_CREDENTIALS\n" );
565 printf(
"\tDesc:\tNo credentials are available in the security package.\n" );
567 case SEC_E_NOT_OWNER:
568 printf(
"\tValue:\tSEC_E_NOT_OWNER\n" );
569 printf(
"\tDesc:\tThe caller of the function does not have the necessary credentials.\n" );
571 case SEC_E_SECPKG_NOT_FOUND:
572 printf(
"\tValue:\tSEC_E_SECPKG_NOT_FOUND\n" );
573 printf(
"\tDesc:\tThe requested security package does not exist. \n" );
575 case SEC_E_UNKNOWN_CREDENTIALS:
576 printf(
"\tValue:\tSEC_E_UNKNOWN_CREDENTIALS\n" );
577 printf(
"\tDesc:\tThe credentials supplied to the package were not recognized.\n" );
579 case SEC_E_INCOMPLETE_MESSAGE:
580 printf(
"\tValue:\tSEC_E_INCOMPLETE_MESSAGE\n" );
581 printf(
"\tDesc:\tData for the whole message was not read from the wire.\n" );
583 case SEC_E_INVALID_HANDLE:
584 printf(
"\tValue:\tSEC_E_INVALID_HANDLE\n" );
585 printf(
"\tDesc:\tThe handle passed to the function is invalid.\n" );
587 case SEC_E_INVALID_TOKEN:
588 printf(
"\tValue:\tSEC_E_INVALID_TOKEN\n" );
589 printf(
"\tDesc:\tThe error is due to a malformed input token, such as a token "
590 "corrupted in transit...\n" );
592 case SEC_E_LOGON_DENIED:
593 printf(
"\tValue:\tSEC_E_LOGON_DENIED\n" );
594 printf(
"\tDesc:\tThe logon failed.\n" );
596 case SEC_E_NO_AUTHENTICATING_AUTHORITY:
597 printf(
"\tValue:\tSEC_E_NO_AUTHENTICATING_AUTHORITY\n" );
598 printf(
"\tDesc:\tNo authority could be contacted for authentication...\n" );
600 case SEC_E_TARGET_UNKNOWN:
601 printf(
"\tValue:\tSEC_E_TARGET_UNKNOWN\n" );
602 printf(
"\tDesc:\tThe target was not recognized.\n" );
604 case SEC_I_CONTEXT_EXPIRED:
605 printf(
"\tValue:\tSEC_E_CONTEXT_EXPIRED\n" );
606 printf(
"\tDesc:\tThe message sender has finished using the connection and has initiated "
609 case SEC_E_UNSUPPORTED_FUNCTION:
610 printf(
"\tValue:\tSEC_E_UNSUPPORTED_FUNCTION\n" );
611 printf(
"\tDesc:\tAn invalid context attribute flag (ISC_REQ_DELEGATE or "
612 "ISC_REQ_PROMPT_FOR_CREDS)...\n" );
614 case SEC_E_WRONG_PRINCIPAL:
615 printf(
"\tValue:\tSEC_E_WRONG_PRINCIPAL\n" );
616 printf(
"\tDesc:\tThe principal that received the authentication request "
617 "is not the same as the...\n" );
619 case SEC_E_OUT_OF_SEQUENCE:
620 printf(
"\tValue:\tSEC_E_OUT_OF_SEQUENCE\n" );
621 printf(
"\tDesc:\tThe message was not received in the correct sequence.\n" );
623 case SEC_I_COMPLETE_AND_CONTINUE:
624 printf(
"\tValue:\tSEC_I_COMPLETE_AND_CONTINUE\n" );
625 printf(
"\tDesc:\tThe client must call CompleteAuthToken and then pass the output...\n" );
627 case SEC_I_COMPLETE_NEEDED:
628 printf(
"\tValue:\tSEC_I_COMPLETE_NEEDED\n" );
629 printf(
"\tDesc:\tThe client must finish building the message and then "
630 "call the CompleteAuthToken function.\n" );
632 case SEC_I_RENEGOTIATE:
633 printf(
"\tValue:\tSEC_I_RENEGOTIATE\n" );
634 printf(
"\tDesc:\tThe remote party requires a new handshake sequence or the "
635 "application has just initiated a shutdown.\n" );
637 case SEC_I_CONTINUE_NEEDED:
638 printf(
"\tValue:\tSEC_I_CONTINUE_NEEDED\n" );
639 printf(
"\tDesc:\tThe client must send the output token to the server "
640 "and wait for a return token...\n" );
642 case SEC_I_INCOMPLETE_CREDENTIALS:
643 printf(
"\tValue:\tSEC_I_INCOMPLETE_CREDENTIALS\n" );
644 printf(
"\tDesc:\tThe server has requested client authentication, "
645 "and the supplied credentials either...\n" );
648 printf(
"\tValue:\t%d\n", errorcode );
649 printf(
"\tDesc:\tUnknown error code.\n" );
656 #endif // HAVE_WINTLS