gloox  1.0.16
tlsschannel.cpp
1 /*
2  * Copyright (c) 2007-2015 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 
19 namespace 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
std::list< std::string > StringList
Definition: gloox.h:1244
virtual void handleEncryptedData(const TLSBase *base, const std::string &data)=0
virtual bool handshake()
bool chain
Definition: gloox.h:987
std::string cipher
Definition: gloox.h:995
virtual int decrypt(const std::string &data)
virtual void setCACerts(const StringList &cacerts)
std::string issuer
Definition: gloox.h:988
std::string server
Definition: gloox.h:989
virtual ~SChannel()
Definition: tlsschannel.cpp:27
std::string mac
Definition: gloox.h:996
SChannel(TLSHandler *th, const std::string &server)
Definition: tlsschannel.cpp:21
virtual bool hasChannelBinding() const
The namespace for the gloox library.
Definition: adhoc.cpp:27
int date_from
Definition: gloox.h:990
virtual void setClientCert(const std::string &clientKey, const std::string &clientCerts)
std::string protocol
Definition: gloox.h:994
virtual bool encrypt(const std::string &data)
Definition: tlsschannel.cpp:34
virtual void cleanup()
An abstract base class for TLS implementations.
Definition: tlsbase.h:31
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.
Definition: tlshandler.h:34
const std::string EmptyString
Definition: gloox.cpp:123
virtual void handleHandshakeResult(const TLSBase *base, bool success, CertInfo &certinfo)=0