gloox 1.0.24
tlsschannel.cpp
1/*
2 * Copyright (c) 2007-2019 by Jakob Schröter <js@camaya.net>
3 * This file is part of the gloox library. http://camaya.net/gloox
4 *
5 * This software is distributed under a license. The full license
6 * agreement can be found in the file LICENSE in this distribution.
7 * This software may not be copied, modified, sold or distributed
8 * other than expressed in the named license agreement.
9 *
10 * This software is distributed without any warranty.
11 */
12
13#include "tlsschannel.h"
14
15#ifdef HAVE_WINTLS
16
17#include <stdio.h> // just for debugging output
18
19namespace gloox
20{
21 SChannel::SChannel( TLSHandler* th, const std::string& server )
22 : TLSBase( th, server ), m_cleanedup( true )
23 {
24 //printf(">> SChannel::SChannel()\n");
25 }
26
28 {
29 m_handler = 0;
30 cleanup();
31 //printf(">> SChannel::~SChannel()\n");
32 }
33
34 bool SChannel::encrypt( const std::string& data )
35 {
36 if( !m_handler )
37 return false;
38
39 //printf(">> SChannel::encrypt()\n");
40 std::string data_copy = data;
41
42 SecBuffer buffer[4];
43 SecBufferDesc buffer_desc;
44 DWORD cbIoBufferLength = m_sizes.cbHeader + m_sizes.cbMaximumMessage + m_sizes.cbTrailer;
45
46 PBYTE e_iobuffer = static_cast<PBYTE>( malloc( cbIoBufferLength ) );
47
48 if( e_iobuffer == NULL )
49 {
50 //printf("**** Out of memory (2)\n");
51 cleanup();
52 if( !m_secure )
53 m_handler->handleHandshakeResult( this, false, m_certInfo );
54 return false;
55 }
56 PBYTE e_message = e_iobuffer + m_sizes.cbHeader;
57 do
58 {
59 const size_t size = ( data_copy.size() > m_sizes.cbMaximumMessage )
60 ? m_sizes.cbMaximumMessage
61 : data_copy.size();
62 memcpy( e_message, data_copy.data(), size );
63 if( data_copy.size() > m_sizes.cbMaximumMessage )
64 data_copy.erase( 0, m_sizes.cbMaximumMessage );
65 else
66 data_copy = EmptyString;
67
68 buffer[0].pvBuffer = e_iobuffer;
69 buffer[0].cbBuffer = m_sizes.cbHeader;
70 buffer[0].BufferType = SECBUFFER_STREAM_HEADER;
71
72 buffer[1].pvBuffer = e_message;
73 buffer[1].cbBuffer = size;
74 buffer[1].BufferType = SECBUFFER_DATA;
75
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;
79
80 buffer[3].BufferType = SECBUFFER_EMPTY;
81
82 buffer_desc.ulVersion = SECBUFFER_VERSION;
83 buffer_desc.cBuffers = 4;
84 buffer_desc.pBuffers = buffer;
85
86 SECURITY_STATUS e_status = EncryptMessage( &m_context, 0, &buffer_desc, 0 );
87 if( SUCCEEDED( e_status ) )
88 {
89 std::string encrypted( reinterpret_cast<const char*>(e_iobuffer),
90 buffer[0].cbBuffer + buffer[1].cbBuffer + buffer[2].cbBuffer );
91 m_handler->handleEncryptedData( this, encrypted );
92 //if (data_copy.size() <= m_sizes.cbMaximumMessage) data_copy = EmptyString;
93 }
94 else
95 {
96 free( e_iobuffer );
97 e_iobuffer = 0;
98 if( !m_secure )
99 m_handler->handleHandshakeResult( this, false, m_certInfo );
100 cleanup();
101 return false;
102 }
103 }
104 while( data_copy.size() > 0 );
105 free( e_iobuffer );
106 e_iobuffer = 0;
107 return true;
108 }
109
110 int SChannel::decrypt( const std::string& data )
111 {
112
113 if( !m_handler )
114 return 0;
115
116 //printf(">> SChannel::decrypt()\n");
117 if( m_secure )
118 {
119 m_buffer += data;
120
121 SecBuffer buffer[4];
122 SecBufferDesc buffer_desc;
123 DWORD cbIoBufferLength = m_sizes.cbHeader + m_sizes.cbMaximumMessage + m_sizes.cbTrailer;
124 bool wantNewBufferSize = false;
125
126 PBYTE e_iobuffer = static_cast<PBYTE>( malloc( cbIoBufferLength ) );
127 if( e_iobuffer == NULL )
128 {
129 //printf("**** Out of memory (2)\n");
130 cleanup();
131 if( !m_secure )
132 m_handler->handleHandshakeResult( this, false, m_certInfo );
133 return 0;
134 }
135 SECURITY_STATUS e_status;
136
137 do
138 {
139 if( wantNewBufferSize )
140 {
141 void* tmp = realloc( e_iobuffer, cbIoBufferLength );
142 if( tmp )
143 {
144 e_iobuffer = static_cast<PBYTE>( tmp );
145 wantNewBufferSize = false;
146 }
147 else
148 {
149 //printf("**** Out of memory (2)\n");
150 cleanup();
151 m_handler->handleHandshakeResult( this, false, m_certInfo );
152 return 0;
153 }
154 }
155
156 // copy data chunk from tmp string into encryption memory buffer
157 memcpy( e_iobuffer, m_buffer.data(), m_buffer.size() >
158 cbIoBufferLength ? cbIoBufferLength : m_buffer.size() );
159
160 buffer[0].pvBuffer = e_iobuffer;
161 buffer[0].cbBuffer = static_cast<unsigned long>( m_buffer.size() > cbIoBufferLength
162 ? cbIoBufferLength
163 : m_buffer.size() );
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;
167
168 buffer_desc.ulVersion = SECBUFFER_VERSION;
169 buffer_desc.cBuffers = 4;
170 buffer_desc.pBuffers = buffer;
171
172 unsigned long processed_data = buffer[0].cbBuffer;
173 e_status = DecryptMessage( &m_context, &buffer_desc, 0, 0 );
174
175 // print_error(e_status, "decrypt() ~ DecryptMessage()");
176 // for (int n=0; n<4; n++)
177 // printf("buffer[%d].cbBuffer: %d \t%d\n", n, buffer[n].cbBuffer, buffer[n].BufferType);
178
179 // Locate data and (optional) extra buffers.
180 SecBuffer* pDataBuffer = NULL;
181 SecBuffer* pExtraBuffer = NULL;
182 for( int i = 1; i < 4; i++ )
183 {
184 if( pDataBuffer == NULL && buffer[i].BufferType == SECBUFFER_DATA )
185 {
186 pDataBuffer = &buffer[i];
187 //printf("buffer[%d].BufferType = SECBUFFER_DATA\n",i);
188 }
189 if( pExtraBuffer == NULL && buffer[i].BufferType == SECBUFFER_EXTRA )
190 {
191 pExtraBuffer = &buffer[i];
192 }
193 }
194 if( e_status == SEC_E_OK )
195 {
196 std::string decrypted( reinterpret_cast<const char*>( pDataBuffer->pvBuffer ),
197 pDataBuffer->cbBuffer );
198 m_handler->handleDecryptedData( this, decrypted );
199 if( pExtraBuffer == NULL )
200 {
201 m_buffer.erase( 0, processed_data );
202 }
203 else
204 {
205 //std::cout << "m_buffer.size() = " << pExtraBuffer->cbBuffer << std::endl;
206 m_buffer.erase( 0, processed_data - pExtraBuffer->cbBuffer );
207 //std::cout << "m_buffer.size() = " << m_buffer.size() << std::endl;
208
209 cbIoBufferLength = m_sizes.cbHeader + m_sizes.cbMaximumMessage + m_sizes.cbTrailer;
210 wantNewBufferSize = true;
211 }
212 }
213 else if( e_status == SEC_E_INCOMPLETE_MESSAGE )
214 {
215 if( cbIoBufferLength < 200000 && m_buffer.size() > cbIoBufferLength )
216 {
217 cbIoBufferLength += 1000;
218 wantNewBufferSize = true;
219 }
220 else
221 {
222 cbIoBufferLength = m_sizes.cbHeader + m_sizes.cbMaximumMessage + m_sizes.cbTrailer;
223 wantNewBufferSize = true;
224 break;
225 }
226 }
227 else
228 {
229 //std::cout << "decrypt !!!ERROR!!!\n";
230 if( !m_secure )
231 m_handler->handleHandshakeResult( this, false, m_certInfo );
232 cleanup();
233 break;
234 }
235 }
236 while( m_buffer.size() != 0 );
237 free( e_iobuffer );
238 }
239 else
240 {
241 handshakeStage( data );
242 }
243 //printf("<< SChannel::decrypt()\n");
244 return 0;
245 }
246
248 {
249 if( !m_mutex.trylock() )
250 return;
251
252 m_buffer = "";
253 if( !m_cleanedup )
254 {
255 m_valid = false;
256 m_secure = false;
257 m_cleanedup = true;
258 DeleteSecurityContext( &m_context );
259 FreeCredentialsHandle( &m_credHandle );
260 }
261
262 m_mutex.unlock();
263 }
264
266 {
267 if( !m_handler )
268 return false;
269
270 //printf(">> SChannel::handshake()\n");
271 SECURITY_STATUS error;
272 ULONG return_flags;
273 TimeStamp t;
274 SecBuffer obuf[1];
275 SecBufferDesc obufs;
276 SCHANNEL_CRED tlscred;
277 ULONG request = ISC_REQ_ALLOCATE_MEMORY
278 | ISC_REQ_CONFIDENTIALITY
279 | ISC_REQ_EXTENDED_ERROR
280 | ISC_REQ_INTEGRITY
281 | ISC_REQ_REPLAY_DETECT
282 | ISC_REQ_SEQUENCE_DETECT
283 | ISC_REQ_STREAM
284 | ISC_REQ_MANUAL_CRED_VALIDATION;
285
286 /* initialize TLS credential */
287 memset( &tlscred, 0, sizeof( SCHANNEL_CRED ) );
288 tlscred.dwVersion = SCHANNEL_CRED_VERSION;
289 tlscred.grbitEnabledProtocols = SP_PROT_TLS1;
290 /* acquire credentials */
291 error = AcquireCredentialsHandle( 0,
292 UNISP_NAME,
293 SECPKG_CRED_OUTBOUND,
294 0,
295 &tlscred,
296 0,
297 0,
298 &m_credHandle,
299 &t );
300 //print_error(error, "handshake() ~ AcquireCredentialsHandle()");
301 if( error != SEC_E_OK )
302 {
303 cleanup();
304 m_handler->handleHandshakeResult( this, false, m_certInfo );
305 return false;
306 }
307 else
308 {
309 /* initialize buffers */
310 obuf[0].cbBuffer = 0;
311 obuf[0].pvBuffer = 0;
312 obuf[0].BufferType = SECBUFFER_TOKEN;
313 /* initialize buffer descriptors */
314 obufs.ulVersion = SECBUFFER_VERSION;
315 obufs.cBuffers = 1;
316 obufs.pBuffers = obuf;
317 /* negotiate security */
318 SEC_CHAR* hname = const_cast<char*>( m_server.c_str() );
319
320 error = InitializeSecurityContextA( &m_credHandle,
321 0,
322 hname,
323 request,
324 0,
325 SECURITY_NETWORK_DREP,
326 0,
327 0,
328 &m_context,
329 &obufs,
330 &return_flags,
331 NULL );
332 //print_error(error, "handshake() ~ InitializeSecurityContext()");
333
334 if( error == SEC_I_CONTINUE_NEEDED )
335 {
336 m_cleanedup = false;
337 //std::cout << "obuf[1].cbBuffer: " << obuf[0].cbBuffer << "\n";
338 std::string senddata( static_cast<char*>(obuf[0].pvBuffer), obuf[0].cbBuffer );
339 FreeContextBuffer( obuf[0].pvBuffer );
340 m_handler->handleEncryptedData( this, senddata );
341 return true;
342 }
343 else
344 {
345 cleanup();
346 m_handler->handleHandshakeResult( this, false, m_certInfo );
347 return false;
348 }
349 }
350 }
351
352 void SChannel::handshakeStage( const std::string& data )
353 {
354 //printf(" >> handshake_stage\n");
355 m_buffer += data;
356
357 SECURITY_STATUS error;
358 ULONG a;
359 TimeStamp t;
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
365 | ISC_REQ_INTEGRITY
366 | ISC_REQ_REPLAY_DETECT
367 | ISC_REQ_SEQUENCE_DETECT
368 | ISC_REQ_STREAM
369 | ISC_REQ_MANUAL_CRED_VALIDATION;
370
371 SEC_CHAR* hname = const_cast<char*>( m_server.c_str() );
372
373 do
374 {
375 /* initialize buffers */
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() ) );
378 //std::cout << "Size: " << m_buffer.size() << "\n";
379 ibuf[1].cbBuffer = 0;
380 ibuf[1].pvBuffer = 0;
381 obuf[0].cbBuffer = 0;
382 obuf[0].pvBuffer = 0;
383
384 ibuf[0].BufferType = SECBUFFER_TOKEN;
385 ibuf[1].BufferType = SECBUFFER_EMPTY;
386 obuf[0].BufferType = SECBUFFER_EMPTY;
387 /* initialize buffer descriptors */
388 ibufs.ulVersion = obufs.ulVersion = SECBUFFER_VERSION;
389 ibufs.cBuffers = 2;
390 obufs.cBuffers = 1;
391 ibufs.pBuffers = ibuf;
392 obufs.pBuffers = obuf;
393
394 /*
395 * std::cout << "obuf[0].cbBuffer: " << obuf[0].cbBuffer << "\t" << obuf[0].BufferType << "\n";
396 * std::cout << "ibuf[0].cbBuffer: " << ibuf[0].cbBuffer << "\t" << ibuf[0].BufferType << "\n";
397 * std::cout << "ibuf[1].cbBuffer: " << ibuf[1].cbBuffer << "\t" << ibuf[1].BufferType << "\n";
398 */
399
400 /* negotiate security */
401 error = InitializeSecurityContextA( &m_credHandle,
402 &m_context,
403 hname,
404 request,
405 0,
406 0,
407 &ibufs,
408 0,
409 0,
410 &obufs,
411 &a,
412 &t );
413 //print_error(error, "handshake() ~ InitializeSecurityContext()");
414 if( error == SEC_E_OK )
415 {
416 // EXTRA STUFF??
417 if( ibuf[1].BufferType == SECBUFFER_EXTRA )
418 {
419 m_buffer.erase( 0, m_buffer.size() - ibuf[1].cbBuffer );
420 }
421 else
422 {
423 m_buffer = EmptyString;
424 }
425 setSizes();
426 setCertinfos();
427
428 m_secure = true;
429 m_handler->handleHandshakeResult( this, true, m_certInfo );
430 break;
431 }
432 else if( error == SEC_I_CONTINUE_NEEDED )
433 {
434 /*
435 * std::cout << "obuf[0].cbBuffer: " << obuf[0].cbBuffer << "\t" << obuf[0].BufferType << "\n";
436 * std::cout << "ibuf[0].cbBuffer: " << ibuf[0].cbBuffer << "\t" << ibuf[0].BufferType << "\n";
437 * std::cout << "ibuf[1].cbBuffer: " << ibuf[1].cbBuffer << "\t" << ibuf[1].BufferType << "\n";
438 */
439
440 // STUFF TO SEND??
441 if( obuf[0].cbBuffer != 0 && obuf[0].pvBuffer != NULL )
442 {
443 std::string senddata( static_cast<char*>(obuf[0].pvBuffer), obuf[0].cbBuffer );
444 FreeContextBuffer( obuf[0].pvBuffer );
445 m_handler->handleEncryptedData( this, senddata );
446 }
447 // EXTRA STUFF??
448 if( ibuf[1].BufferType == SECBUFFER_EXTRA )
449 {
450 m_buffer.erase( 0, m_buffer.size() - ibuf[1].cbBuffer );
451 // Call again if we aren't sending anything (otherwise the server will not send anything back
452 // and this function won't get called again to finish the processing). This is needed for
453 // NT4.0 which does not seem to process the entire buffer the first time around
454 if( obuf[0].cbBuffer == 0 )
455 handshakeStage( EmptyString );
456 }
457 else
458 {
459 m_buffer = EmptyString;
460 }
461 return;
462 }
463 else if( error == SEC_I_INCOMPLETE_CREDENTIALS )
464 {
465 handshakeStage( EmptyString );
466 }
467 else if( error == SEC_E_INCOMPLETE_MESSAGE )
468 {
469 break;
470 }
471 else
472 {
473 cleanup();
474 m_handler->handleHandshakeResult( this, false, m_certInfo );
475 break;
476 }
477 }
478 while( true );
479 }
480
482 {
483#ifdef HAVE_WINTLS_CHANNEL_BINDING
484 return true;
485#else
486 return false;
487#endif
488 }
489
490 const std::string SChannel::channelBinding() const
491 {
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 )
495 {
496 return std::string( buf->Bindings[buf->Bindings.dwApplicationDataOffset], buf->Bindings.cbApplicationDataLength );
497 }
498#endif
499 return EmptyString;
500 }
501
502 void SChannel::setCACerts( const StringList& /*cacerts*/ ) {}
503
504 void SChannel::setClientCert( const std::string& /*clientKey*/, const std::string& /*clientCerts*/ ) {}
505
506 void SChannel::setSizes()
507 {
508 if( QueryContextAttributes( &m_context, SECPKG_ATTR_STREAM_SIZES, &m_sizes ) == SEC_E_OK )
509 {
510 //std::cout << "set_sizes success\n";
511 }
512 else
513 {
514 //std::cout << "set_sizes no success\n";
515 cleanup();
516 m_handler->handleHandshakeResult( this, false, m_certInfo );
517 }
518 }
519
520 int SChannel::filetime2int( FILETIME t )
521 {
522 SYSTEMTIME stUTC;
523 FileTimeToSystemTime(&t, &stUTC);
524 std::tm ts;
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;
531
532 time_t unixtime;
533 if ( (unixtime = mktime(&ts)) == -1 )
534 unixtime = 0;
535 return (int)unixtime;
536 }
537
538 void SChannel::validateCert()
539 {
540 bool valid = false;
541 HTTPSPolicyCallbackData policyHTTPS;
542 CERT_CHAIN_POLICY_PARA policyParameter;
543 CERT_CHAIN_POLICY_STATUS policyStatus;
544
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() );
549
550 PWSTR uServerName = NULL;
551 DWORD csizeServerName;
552
553 LPSTR Usages[] = {
554 szOID_PKIX_KP_SERVER_AUTH,
555 szOID_SERVER_GATED_CRYPTO,
556 szOID_SGC_NETSCAPE
557 };
558 DWORD cUsages = sizeof( Usages ) / sizeof( LPSTR );
559
560 do
561 {
562 // Get server's certificate.
563 if( QueryContextAttributes( &m_context, SECPKG_ATTR_REMOTE_CERT_CONTEXT,
564 (PVOID)&remoteCertContext ) != SEC_E_OK )
565 {
566 //printf("Error querying remote certificate\n");
567 // !!! THROW SOME ERROR
568 break;
569 }
570
571 // unicode conversation
572 // calculating unicode server name size
573 csizeServerName = MultiByteToWideChar( CP_ACP, 0, serverName, -1, NULL, 0 );
574 uServerName = reinterpret_cast<WCHAR *>( malloc( csizeServerName * sizeof( WCHAR ) ) );
575 if( uServerName == NULL )
576 {
577 //printf("SEC_E_INSUFFICIENT_MEMORY ~ Not enough memory!!!\n");
578 break;
579 }
580
581 // convert into unicode
582 csizeServerName = MultiByteToWideChar( CP_ACP, 0, serverName, -1, uServerName, csizeServerName );
583 if( csizeServerName == 0 )
584 {
585 //printf("SEC_E_WRONG_PRINCIPAL\n");
586 break;
587 }
588
589 // create the chain
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;
595
596 if( !CertGetCertificateChain( NULL, remoteCertContext, NULL, remoteCertContext->hCertStore,
597 &chainParameter, 0, NULL, &chainContext ) )
598 {
599// DWORD status = GetLastError();
600// printf("Error 0x%x returned by CertGetCertificateChain!!!\n", status);
601 break;
602 }
603
604 // validate the chain
605 ZeroMemory( &policyHTTPS, sizeof( HTTPSPolicyCallbackData ) );
606 policyHTTPS.cbStruct = sizeof( HTTPSPolicyCallbackData );
607 policyHTTPS.dwAuthType = AUTHTYPE_SERVER;
608 policyHTTPS.fdwChecks = 0;
609 policyHTTPS.pwszServerName = uServerName;
610
611 memset( &policyParameter, 0, sizeof( policyParameter ) );
612 policyParameter.cbSize = sizeof( policyParameter );
613 policyParameter.pvExtraPolicyPara = &policyHTTPS;
614
615 memset( &policyStatus, 0, sizeof( policyStatus ) );
616 policyStatus.cbSize = sizeof( policyStatus );
617
618 if( !CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_SSL, chainContext, &policyParameter,
619 &policyStatus ) )
620 {
621// DWORD status = GetLastError();
622// printf("Error 0x%x returned by CertVerifyCertificateChainPolicy!!!\n", status);
623 break;
624 }
625
626 if( policyStatus.dwError )
627 {
628 //printf("Trust Error!!!}n");
629 break;
630 }
631 valid = true;
632 }
633 while( false );
634 // cleanup
635 if( chainContext )
636 CertFreeCertificateChain( chainContext );
637 if( uServerName != 0 )
638 free( uServerName );
639 m_certInfo.chain = valid;
640 }
641
642 void SChannel::connectionInfos()
643 {
644 SecPkgContext_ConnectionInfo conn_info;
645
646 memset( &conn_info, 0, sizeof( conn_info ) );
647
648 if( QueryContextAttributes( &m_context, SECPKG_ATTR_CONNECTION_INFO, &conn_info ) == SEC_E_OK )
649 {
650 switch( conn_info.dwProtocol )
651 {
652 case SP_PROT_TLS1_CLIENT:
653 m_certInfo.protocol = "TLSv1";
654 break;
655 case SP_PROT_SSL3_CLIENT:
656 m_certInfo.protocol = "SSLv3";
657 break;
658 default:
659 m_certInfo.protocol = "unknown";
660 }
661
662 switch( conn_info.aiCipher )
663 {
664 case CALG_3DES:
665 m_certInfo.cipher = "3DES";
666 break;
667 case CALG_AES_128:
668 m_certInfo.cipher = "AES_128";
669 break;
670 case CALG_AES_256:
671 m_certInfo.cipher = "AES_256";
672 break;
673 case CALG_DES:
674 m_certInfo.cipher = "DES";
675 break;
676 case CALG_RC2:
677 m_certInfo.cipher = "RC2";
678 break;
679 case CALG_RC4:
680 m_certInfo.cipher = "RC4";
681 break;
682 default:
683 m_certInfo.cipher = EmptyString;
684 }
685
686 switch( conn_info.aiHash )
687 {
688 case CALG_MD5:
689 m_certInfo.mac = "MD5";
690 break;
691 case CALG_SHA:
692 m_certInfo.mac = "SHA";
693 break;
694 default:
695 m_certInfo.mac = EmptyString;
696 }
697 }
698 }
699
700 void SChannel::certData()
701 {
702 PCCERT_CONTEXT remoteCertContext = NULL;
703 CHAR certString[1000];
704
705 // getting server's certificate
706 if( QueryContextAttributes( &m_context, SECPKG_ATTR_REMOTE_CERT_CONTEXT,
707 (PVOID)&remoteCertContext ) != SEC_E_OK )
708 {
709 return;
710 }
711
712 // setting certificat's lifespan
713 m_certInfo.date_from = filetime2int( remoteCertContext->pCertInfo->NotBefore );
714 m_certInfo.date_to = filetime2int( remoteCertContext->pCertInfo->NotAfter );
715
716 if( !CertNameToStrA( remoteCertContext->dwCertEncodingType,
717 &remoteCertContext->pCertInfo->Subject,
718 CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
719 certString, sizeof( certString ) ) )
720 {
721 return;
722 }
723 m_certInfo.server = certString;
724
725 if( !CertNameToStrA( remoteCertContext->dwCertEncodingType,
726 &remoteCertContext->pCertInfo->Issuer,
727 CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
728 certString, sizeof( certString ) ) )
729 {
730 return;
731 }
732 m_certInfo.issuer = certString;
733 }
734
735 void SChannel::setCertinfos()
736 {
737 validateCert();
738 connectionInfos();
739 certData();
740 }
741
742#if 0
743 void SChannel::print_error( int errorcode, const char* place )
744 {
745 printf( "Win error at %s.\n", place );
746 switch( errorcode )
747 {
748 case SEC_E_OK:
749 printf( "\tValue:\tSEC_E_OK\n" );
750 printf( "\tDesc:\tNot really an error. Everything is fine.\n" );
751 break;
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" );
755 break;
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" );
759 break;
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" );
763 break;
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" );
767 break;
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" );
771 break;
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" );
775 break;
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" );
779 break;
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" );
783 break;
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" );
788 break;
789 case SEC_E_LOGON_DENIED:
790 printf( "\tValue:\tSEC_E_LOGON_DENIED\n" );
791 printf( "\tDesc:\tThe logon failed.\n" );
792 break;
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" );
796 break;
797 case SEC_E_TARGET_UNKNOWN:
798 printf( "\tValue:\tSEC_E_TARGET_UNKNOWN\n" );
799 printf( "\tDesc:\tThe target was not recognized.\n" );
800 break;
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" );
805 break;
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" );
810 break;
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" );
814 break;
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" );
819 break;
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" );
824 break;
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" );
829 break;
830 default:
831 printf( "\tValue:\t%d\n", errorcode );
832 printf( "\tDesc:\tUnknown error code.\n" );
833 }
834 }
835#endif
836
837}
838
839#endif // HAVE_WINTLS
virtual bool encrypt(const std::string &data)
Definition: tlsschannel.cpp:34
virtual ~SChannel()
Definition: tlsschannel.cpp:27
virtual void setCACerts(const StringList &cacerts)
virtual bool handshake()
virtual void cleanup()
virtual void setClientCert(const std::string &clientKey, const std::string &clientCerts)
SChannel(TLSHandler *th, const std::string &server)
Definition: tlsschannel.cpp:21
virtual const std::string channelBinding() const
virtual bool hasChannelBinding() const
virtual int decrypt(const std::string &data)
An abstract base class for TLS implementations.
Definition: tlsbase.h:32
An interface that allows for interacting with TLS implementations derived from TLSBase.
Definition: tlshandler.h:35
virtual void handleDecryptedData(const TLSBase *base, const std::string &data)=0
virtual void handleEncryptedData(const TLSBase *base, const std::string &data)=0
virtual void handleHandshakeResult(const TLSBase *base, bool success, CertInfo &certinfo)=0
The namespace for the gloox library.
Definition: adhoc.cpp:28
std::list< std::string > StringList
Definition: gloox.h:1251
const std::string EmptyString
Definition: gloox.cpp:124
std::string cipher
Definition: gloox.h:1002
bool chain
Definition: gloox.h:992
std::string server
Definition: gloox.h:994
std::string mac
Definition: gloox.h:1003
int date_from
Definition: gloox.h:995
std::string protocol
Definition: gloox.h:1001
std::string issuer
Definition: gloox.h:993