13 #include "tlsschannel.h"
22 :
TLSBase( th, server ), m_cleanedup( true )
40 std::string data_copy = data;
43 SecBufferDesc buffer_desc;
44 DWORD cbIoBufferLength = m_sizes.cbHeader + m_sizes.cbMaximumMessage + m_sizes.cbTrailer;
46 PBYTE e_iobuffer =
static_cast<PBYTE
>( malloc( cbIoBufferLength ) );
48 if( e_iobuffer == NULL )
56 PBYTE e_message = e_iobuffer + m_sizes.cbHeader;
59 const size_t size = ( data_copy.size() > m_sizes.cbMaximumMessage )
60 ? m_sizes.cbMaximumMessage
62 memcpy( e_message, data_copy.data(), size );
63 if( data_copy.size() > m_sizes.cbMaximumMessage )
64 data_copy.erase( 0, m_sizes.cbMaximumMessage );
68 buffer[0].pvBuffer = e_iobuffer;
69 buffer[0].cbBuffer = m_sizes.cbHeader;
70 buffer[0].BufferType = SECBUFFER_STREAM_HEADER;
72 buffer[1].pvBuffer = e_message;
73 buffer[1].cbBuffer = size;
74 buffer[1].BufferType = SECBUFFER_DATA;
76 buffer[2].pvBuffer =
static_cast<char*
>(buffer[1].pvBuffer) + buffer[1].cbBuffer;
77 buffer[2].cbBuffer = m_sizes.cbTrailer;
78 buffer[2].BufferType = SECBUFFER_STREAM_TRAILER;
80 buffer[3].BufferType = SECBUFFER_EMPTY;
82 buffer_desc.ulVersion = SECBUFFER_VERSION;
83 buffer_desc.cBuffers = 4;
84 buffer_desc.pBuffers = buffer;
86 SECURITY_STATUS e_status = EncryptMessage( &m_context, 0, &buffer_desc, 0 );
87 if( SUCCEEDED( e_status ) )
89 std::string encrypted( reinterpret_cast<const char*>(e_iobuffer),
90 buffer[0].cbBuffer + buffer[1].cbBuffer + buffer[2].cbBuffer );
104 while( data_copy.size() > 0 );
122 SecBufferDesc buffer_desc;
123 DWORD cbIoBufferLength = m_sizes.cbHeader + m_sizes.cbMaximumMessage + m_sizes.cbTrailer;
124 bool wantNewBufferSize =
false;
126 PBYTE e_iobuffer =
static_cast<PBYTE
>( malloc( cbIoBufferLength ) );
127 if( e_iobuffer == NULL )
135 SECURITY_STATUS e_status;
139 if( wantNewBufferSize )
141 void* tmp = realloc( e_iobuffer, cbIoBufferLength );
144 e_iobuffer =
static_cast<PBYTE
>( tmp );
145 wantNewBufferSize =
false;
157 memcpy( e_iobuffer, m_buffer.data(), m_buffer.size() >
158 cbIoBufferLength ? cbIoBufferLength : m_buffer.size() );
160 buffer[0].pvBuffer = e_iobuffer;
161 buffer[0].cbBuffer =
static_cast<unsigned long>( m_buffer.size() > cbIoBufferLength
164 buffer[0].BufferType = SECBUFFER_DATA;
165 buffer[1].cbBuffer = buffer[2].cbBuffer = buffer[3].cbBuffer = 0;
166 buffer[1].BufferType = buffer[2].BufferType = buffer[3].BufferType = SECBUFFER_EMPTY;
168 buffer_desc.ulVersion = SECBUFFER_VERSION;
169 buffer_desc.cBuffers = 4;
170 buffer_desc.pBuffers = buffer;
172 unsigned long processed_data = buffer[0].cbBuffer;
173 e_status = DecryptMessage( &m_context, &buffer_desc, 0, 0 );
180 SecBuffer* pDataBuffer = NULL;
181 SecBuffer* pExtraBuffer = NULL;
182 for(
int i = 1; i < 4; i++ )
184 if( pDataBuffer == NULL && buffer[i].BufferType == SECBUFFER_DATA )
186 pDataBuffer = &buffer[i];
189 if( pExtraBuffer == NULL && buffer[i].BufferType == SECBUFFER_EXTRA )
191 pExtraBuffer = &buffer[i];
194 if( e_status == SEC_E_OK )
196 std::string decrypted( reinterpret_cast<const char*>( pDataBuffer->pvBuffer ),
197 pDataBuffer->cbBuffer );
199 if( pExtraBuffer == NULL )
201 m_buffer.erase( 0, processed_data );
206 m_buffer.erase( 0, processed_data - pExtraBuffer->cbBuffer );
209 cbIoBufferLength = m_sizes.cbHeader + m_sizes.cbMaximumMessage + m_sizes.cbTrailer;
210 wantNewBufferSize =
true;
213 else if( e_status == SEC_E_INCOMPLETE_MESSAGE )
215 if( cbIoBufferLength < 200000 && m_buffer.size() > cbIoBufferLength )
217 cbIoBufferLength += 1000;
218 wantNewBufferSize =
true;
222 cbIoBufferLength = m_sizes.cbHeader + m_sizes.cbMaximumMessage + m_sizes.cbTrailer;
223 wantNewBufferSize =
true;
236 while( m_buffer.size() != 0 );
241 handshakeStage( data );
258 DeleteSecurityContext( &m_context );
259 FreeCredentialsHandle( &m_credHandle );
271 SECURITY_STATUS error;
276 SCHANNEL_CRED tlscred;
277 ULONG request = ISC_REQ_ALLOCATE_MEMORY
278 | ISC_REQ_CONFIDENTIALITY
279 | ISC_REQ_EXTENDED_ERROR
281 | ISC_REQ_REPLAY_DETECT
282 | ISC_REQ_SEQUENCE_DETECT
284 | ISC_REQ_MANUAL_CRED_VALIDATION;
287 memset( &tlscred, 0,
sizeof( SCHANNEL_CRED ) );
288 tlscred.dwVersion = SCHANNEL_CRED_VERSION;
289 tlscred.grbitEnabledProtocols = SP_PROT_TLS1;
291 error = AcquireCredentialsHandle( 0,
293 SECPKG_CRED_OUTBOUND,
301 if( error != SEC_E_OK )
310 obuf[0].cbBuffer = 0;
311 obuf[0].pvBuffer = 0;
312 obuf[0].BufferType = SECBUFFER_TOKEN;
314 obufs.ulVersion = SECBUFFER_VERSION;
316 obufs.pBuffers = obuf;
318 SEC_CHAR* hname =
const_cast<char*
>( m_server.c_str() );
320 error = InitializeSecurityContextA( &m_credHandle,
325 SECURITY_NETWORK_DREP,
334 if( error == SEC_I_CONTINUE_NEEDED )
338 std::string senddata( static_cast<char*>(obuf[0].pvBuffer), obuf[0].cbBuffer );
339 FreeContextBuffer( obuf[0].pvBuffer );
352 void SChannel::handshakeStage(
const std::string& data )
357 SECURITY_STATUS error;
360 SecBuffer ibuf[2], obuf[1];
361 SecBufferDesc ibufs, obufs;
362 ULONG request = ISC_REQ_ALLOCATE_MEMORY
363 | ISC_REQ_CONFIDENTIALITY
364 | ISC_REQ_EXTENDED_ERROR
366 | ISC_REQ_REPLAY_DETECT
367 | ISC_REQ_SEQUENCE_DETECT
369 | ISC_REQ_MANUAL_CRED_VALIDATION;
371 SEC_CHAR* hname =
const_cast<char*
>( m_server.c_str() );
376 ibuf[0].cbBuffer =
static_cast<unsigned long>( m_buffer.size() );
377 ibuf[0].pvBuffer =
static_cast<void*
>(
const_cast<char*
>( m_buffer.c_str() ) );
379 ibuf[1].cbBuffer = 0;
380 ibuf[1].pvBuffer = 0;
381 obuf[0].cbBuffer = 0;
382 obuf[0].pvBuffer = 0;
384 ibuf[0].BufferType = SECBUFFER_TOKEN;
385 ibuf[1].BufferType = SECBUFFER_EMPTY;
386 obuf[0].BufferType = SECBUFFER_EMPTY;
388 ibufs.ulVersion = obufs.ulVersion = SECBUFFER_VERSION;
391 ibufs.pBuffers = ibuf;
392 obufs.pBuffers = obuf;
401 error = InitializeSecurityContextA( &m_credHandle,
414 if( error == SEC_E_OK )
417 if( ibuf[1].BufferType == SECBUFFER_EXTRA )
419 m_buffer.erase( 0, m_buffer.size() - ibuf[1].cbBuffer );
432 else if( error == SEC_I_CONTINUE_NEEDED )
441 if( obuf[0].cbBuffer != 0 && obuf[0].pvBuffer != NULL )
443 std::string senddata( static_cast<char*>(obuf[0].pvBuffer), obuf[0].cbBuffer );
444 FreeContextBuffer( obuf[0].pvBuffer );
448 if( ibuf[1].BufferType == SECBUFFER_EXTRA )
450 m_buffer.erase( 0, m_buffer.size() - ibuf[1].cbBuffer );
454 if( obuf[0].cbBuffer == 0 )
463 else if( error == SEC_I_INCOMPLETE_CREDENTIALS )
467 else if( error == SEC_E_INCOMPLETE_MESSAGE )
483 #ifdef HAVE_WINTLS_CHANNEL_BINDING
492 #ifdef HAVE_WINTLS_CHANNEL_BINDING // see ../config.h.win if the following doesn't compile
493 SecPkgContext_Bindings buf;
494 if( QueryContextAttributes( &m_context, SECPKG_ATTR_UNIQUE_BINDINGS, &buf ) == SEC_E_OK )
496 return std::string( buf->Bindings[buf->Bindings.dwApplicationDataOffset], buf->Bindings.cbApplicationDataLength );
506 void SChannel::setSizes()
508 if( QueryContextAttributes( &m_context, SECPKG_ATTR_STREAM_SIZES, &m_sizes ) == SEC_E_OK )
520 int SChannel::filetime2int( FILETIME t )
523 FileTimeToSystemTime(&t, &stUTC);
525 ts.tm_year = stUTC.wYear - 1900;
526 ts.tm_mon = stUTC.wMonth - 1;
527 ts.tm_mday = stUTC.wDay;
528 ts.tm_hour = stUTC.wHour;
529 ts.tm_min = stUTC.wMinute;
530 ts.tm_sec = stUTC.wSecond;
533 if ( (unixtime = mktime(&ts)) == -1 )
535 return (
int)unixtime;
538 void SChannel::validateCert()
541 HTTPSPolicyCallbackData policyHTTPS;
542 CERT_CHAIN_POLICY_PARA policyParameter;
543 CERT_CHAIN_POLICY_STATUS policyStatus;
545 PCCERT_CONTEXT remoteCertContext = NULL;
546 PCCERT_CHAIN_CONTEXT chainContext = NULL;
547 CERT_CHAIN_PARA chainParameter;
548 PSTR serverName =
const_cast<char*
>( m_server.c_str() );
550 PWSTR uServerName = NULL;
551 DWORD csizeServerName;
554 szOID_PKIX_KP_SERVER_AUTH,
555 szOID_SERVER_GATED_CRYPTO,
558 DWORD cUsages =
sizeof( Usages ) /
sizeof( LPSTR );
563 if( QueryContextAttributes( &m_context, SECPKG_ATTR_REMOTE_CERT_CONTEXT,
564 (PVOID)&remoteCertContext ) != SEC_E_OK )
573 csizeServerName = MultiByteToWideChar( CP_ACP, 0, serverName, -1, NULL, 0 );
574 uServerName =
reinterpret_cast<WCHAR *
>( malloc( csizeServerName *
sizeof( WCHAR ) ) );
575 if( uServerName == NULL )
582 csizeServerName = MultiByteToWideChar( CP_ACP, 0, serverName, -1, uServerName, csizeServerName );
583 if( csizeServerName == 0 )
590 ZeroMemory( &chainParameter,
sizeof( chainParameter ) );
591 chainParameter.cbSize =
sizeof( chainParameter );
592 chainParameter.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
593 chainParameter.RequestedUsage.Usage.cUsageIdentifier = cUsages;
594 chainParameter.RequestedUsage.Usage.rgpszUsageIdentifier = Usages;
596 if( !CertGetCertificateChain( NULL, remoteCertContext, NULL, remoteCertContext->hCertStore,
597 &chainParameter, 0, NULL, &chainContext ) )
605 ZeroMemory( &policyHTTPS,
sizeof( HTTPSPolicyCallbackData ) );
606 policyHTTPS.cbStruct =
sizeof( HTTPSPolicyCallbackData );
607 policyHTTPS.dwAuthType = AUTHTYPE_SERVER;
608 policyHTTPS.fdwChecks = 0;
609 policyHTTPS.pwszServerName = uServerName;
611 memset( &policyParameter, 0,
sizeof( policyParameter ) );
612 policyParameter.cbSize =
sizeof( policyParameter );
613 policyParameter.pvExtraPolicyPara = &policyHTTPS;
615 memset( &policyStatus, 0,
sizeof( policyStatus ) );
616 policyStatus.cbSize =
sizeof( policyStatus );
618 if( !CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_SSL, chainContext, &policyParameter,
626 if( policyStatus.dwError )
636 CertFreeCertificateChain( chainContext );
637 if( uServerName != 0 )
639 m_certInfo.
chain = valid;
642 void SChannel::connectionInfos()
644 SecPkgContext_ConnectionInfo conn_info;
646 memset( &conn_info, 0,
sizeof( conn_info ) );
648 if( QueryContextAttributes( &m_context, SECPKG_ATTR_CONNECTION_INFO, &conn_info ) == SEC_E_OK )
650 switch( conn_info.dwProtocol )
652 case SP_PROT_TLS1_CLIENT:
655 case SP_PROT_SSL3_CLIENT:
662 switch( conn_info.aiCipher )
665 m_certInfo.
cipher =
"3DES";
668 m_certInfo.
cipher =
"AES_128";
671 m_certInfo.
cipher =
"AES_256";
674 m_certInfo.
cipher =
"DES";
677 m_certInfo.
cipher =
"RC2";
680 m_certInfo.
cipher =
"RC4";
686 switch( conn_info.aiHash )
689 m_certInfo.
mac =
"MD5";
692 m_certInfo.
mac =
"SHA";
700 void SChannel::certData()
702 PCCERT_CONTEXT remoteCertContext = NULL;
703 CHAR certString[1000];
706 if( QueryContextAttributes( &m_context, SECPKG_ATTR_REMOTE_CERT_CONTEXT,
707 (PVOID)&remoteCertContext ) != SEC_E_OK )
713 m_certInfo.
date_from = filetime2int( remoteCertContext->pCertInfo->NotBefore );
714 m_certInfo.
date_to = filetime2int( remoteCertContext->pCertInfo->NotAfter );
716 if( !CertNameToStrA( remoteCertContext->dwCertEncodingType,
717 &remoteCertContext->pCertInfo->Subject,
718 CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
719 certString,
sizeof( certString ) ) )
723 m_certInfo.
server = certString;
725 if( !CertNameToStrA( remoteCertContext->dwCertEncodingType,
726 &remoteCertContext->pCertInfo->Issuer,
727 CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
728 certString,
sizeof( certString ) ) )
732 m_certInfo.
issuer = certString;
735 void SChannel::setCertinfos()
743 void SChannel::print_error(
int errorcode,
const char* place )
745 printf(
"Win error at %s.\n", place );
749 printf(
"\tValue:\tSEC_E_OK\n" );
750 printf(
"\tDesc:\tNot really an error. Everything is fine.\n" );
752 case SEC_E_INSUFFICIENT_MEMORY:
753 printf(
"\tValue:\tSEC_E_INSUFFICIENT_MEMORY\n" );
754 printf(
"\tDesc:\tThere is not enough memory available to complete the requested action.\n" );
756 case SEC_E_INTERNAL_ERROR:
757 printf(
"\tValue:\tSEC_E_INTERNAL_ERROR\n" );
758 printf(
"\tDesc:\tAn error occurred that did not map to an SSPI error code.\n" );
760 case SEC_E_NO_CREDENTIALS:
761 printf(
"\tValue:\tSEC_E_NO_CREDENTIALS\n" );
762 printf(
"\tDesc:\tNo credentials are available in the security package.\n" );
764 case SEC_E_NOT_OWNER:
765 printf(
"\tValue:\tSEC_E_NOT_OWNER\n" );
766 printf(
"\tDesc:\tThe caller of the function does not have the necessary credentials.\n" );
768 case SEC_E_SECPKG_NOT_FOUND:
769 printf(
"\tValue:\tSEC_E_SECPKG_NOT_FOUND\n" );
770 printf(
"\tDesc:\tThe requested security package does not exist. \n" );
772 case SEC_E_UNKNOWN_CREDENTIALS:
773 printf(
"\tValue:\tSEC_E_UNKNOWN_CREDENTIALS\n" );
774 printf(
"\tDesc:\tThe credentials supplied to the package were not recognized.\n" );
776 case SEC_E_INCOMPLETE_MESSAGE:
777 printf(
"\tValue:\tSEC_E_INCOMPLETE_MESSAGE\n" );
778 printf(
"\tDesc:\tData for the whole message was not read from the wire.\n" );
780 case SEC_E_INVALID_HANDLE:
781 printf(
"\tValue:\tSEC_E_INVALID_HANDLE\n" );
782 printf(
"\tDesc:\tThe handle passed to the function is invalid.\n" );
784 case SEC_E_INVALID_TOKEN:
785 printf(
"\tValue:\tSEC_E_INVALID_TOKEN\n" );
786 printf(
"\tDesc:\tThe error is due to a malformed input token, such as a token "
787 "corrupted in transit...\n" );
789 case SEC_E_LOGON_DENIED:
790 printf(
"\tValue:\tSEC_E_LOGON_DENIED\n" );
791 printf(
"\tDesc:\tThe logon failed.\n" );
793 case SEC_E_NO_AUTHENTICATING_AUTHORITY:
794 printf(
"\tValue:\tSEC_E_NO_AUTHENTICATING_AUTHORITY\n" );
795 printf(
"\tDesc:\tNo authority could be contacted for authentication...\n" );
797 case SEC_E_TARGET_UNKNOWN:
798 printf(
"\tValue:\tSEC_E_TARGET_UNKNOWN\n" );
799 printf(
"\tDesc:\tThe target was not recognized.\n" );
801 case SEC_E_UNSUPPORTED_FUNCTION:
802 printf(
"\tValue:\tSEC_E_UNSUPPORTED_FUNCTION\n" );
803 printf(
"\tDesc:\tAn invalid context attribute flag (ISC_REQ_DELEGATE or "
804 "ISC_REQ_PROMPT_FOR_CREDS)...\n" );
806 case SEC_E_WRONG_PRINCIPAL:
807 printf(
"\tValue:\tSEC_E_WRONG_PRINCIPAL\n" );
808 printf(
"\tDesc:\tThe principal that received the authentication request "
809 "is not the same as the...\n" );
811 case SEC_I_COMPLETE_AND_CONTINUE:
812 printf(
"\tValue:\tSEC_I_COMPLETE_AND_CONTINUE\n" );
813 printf(
"\tDesc:\tThe client must call CompleteAuthToken and then pass the output...\n" );
815 case SEC_I_COMPLETE_NEEDED:
816 printf(
"\tValue:\tSEC_I_COMPLETE_NEEDED\n" );
817 printf(
"\tDesc:\tThe client must finish building the message and then "
818 "call the CompleteAuthToken function.\n" );
820 case SEC_I_CONTINUE_NEEDED:
821 printf(
"\tValue:\tSEC_I_CONTINUE_NEEDED\n" );
822 printf(
"\tDesc:\tThe client must send the output token to the server "
823 "and wait for a return token...\n" );
825 case SEC_I_INCOMPLETE_CREDENTIALS:
826 printf(
"\tValue:\tSEC_I_INCOMPLETE_CREDENTIALS\n" );
827 printf(
"\tDesc:\tThe server has requested client authentication, "
828 "and the supplied credentials either...\n" );
831 printf(
"\tValue:\t%d\n", errorcode );
832 printf(
"\tDesc:\tUnknown error code.\n" );
839 #endif // HAVE_WINTLS
std::list< std::string > StringList
virtual void handleEncryptedData(const TLSBase *base, const std::string &data)=0
virtual int decrypt(const std::string &data)
virtual void setCACerts(const StringList &cacerts)
SChannel(TLSHandler *th, const std::string &server)
virtual bool hasChannelBinding() const
The namespace for the gloox library.
virtual void setClientCert(const std::string &clientKey, const std::string &clientCerts)
virtual bool encrypt(const std::string &data)
An abstract base class for TLS implementations.
virtual const std::string channelBinding() const
virtual void handleDecryptedData(const TLSBase *base, const std::string &data)=0
An interface that allows for interacting with TLS implementations derived from TLSBase.
const std::string EmptyString
virtual void handleHandshakeResult(const TLSBase *base, bool success, CertInfo &certinfo)=0