gloox  1.0.9
tlsschannel.cpp
1 /*
2  * Copyright (c) 2007-2013 by Jakob Schroeter <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>( LocalAlloc( LMEM_FIXED, 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  LocalFree( e_iobuffer );
97  if( !m_secure )
98  m_handler->handleHandshakeResult( this, false, m_certInfo );
99  cleanup();
100  return false;
101  }
102  }
103  while( data_copy.size() > 0 );
104  LocalFree( e_iobuffer );
105  return true;
106  }
107 
108  int SChannel::decrypt( const std::string& data )
109  {
110 
111  if( !m_handler )
112  return 0;
113 
114  //printf(">> SChannel::decrypt()\n");
115  if( m_secure )
116  {
117  m_buffer += data;
118 
119  SecBuffer buffer[4];
120  SecBufferDesc buffer_desc;
121  DWORD cbIoBufferLength = m_sizes.cbHeader + m_sizes.cbMaximumMessage + m_sizes.cbTrailer;
122  bool wantNewBufferSize = false;
123 
124  PBYTE e_iobuffer = static_cast<PBYTE>( LocalAlloc( LMEM_FIXED, cbIoBufferLength ) );
125  if( e_iobuffer == NULL )
126  {
127  //printf("**** Out of memory (2)\n");
128  cleanup();
129  if( !m_secure )
130  m_handler->handleHandshakeResult( this, false, m_certInfo );
131  return 0;
132  }
133  SECURITY_STATUS e_status;
134 
135  do
136  {
137  if( wantNewBufferSize )
138  {
139  e_iobuffer = static_cast<PBYTE>( LocalReAlloc( e_iobuffer, cbIoBufferLength, 0 ) );
140  wantNewBufferSize = false;
141  }
142 
143  // copy data chunk from tmp string into encryption memory buffer
144  memcpy( e_iobuffer, m_buffer.data(), m_buffer.size() >
145  cbIoBufferLength ? cbIoBufferLength : m_buffer.size() );
146 
147  buffer[0].pvBuffer = e_iobuffer;
148  buffer[0].cbBuffer = static_cast<unsigned long>( m_buffer.size() > cbIoBufferLength
149  ? cbIoBufferLength
150  : m_buffer.size() );
151  buffer[0].BufferType = SECBUFFER_DATA;
152  buffer[1].cbBuffer = buffer[2].cbBuffer = buffer[3].cbBuffer = 0;
153  buffer[1].BufferType = buffer[2].BufferType = buffer[3].BufferType = SECBUFFER_EMPTY;
154 
155  buffer_desc.ulVersion = SECBUFFER_VERSION;
156  buffer_desc.cBuffers = 4;
157  buffer_desc.pBuffers = buffer;
158 
159  unsigned long processed_data = buffer[0].cbBuffer;
160  e_status = DecryptMessage( &m_context, &buffer_desc, 0, 0 );
161 
162  // print_error(e_status, "decrypt() ~ DecryptMessage()");
163  // for (int n=0; n<4; n++)
164  // printf("buffer[%d].cbBuffer: %d \t%d\n", n, buffer[n].cbBuffer, buffer[n].BufferType);
165 
166  // Locate data and (optional) extra buffers.
167  SecBuffer* pDataBuffer = NULL;
168  SecBuffer* pExtraBuffer = NULL;
169  for( int i = 1; i < 4; i++ )
170  {
171  if( pDataBuffer == NULL && buffer[i].BufferType == SECBUFFER_DATA )
172  {
173  pDataBuffer = &buffer[i];
174  //printf("buffer[%d].BufferType = SECBUFFER_DATA\n",i);
175  }
176  if( pExtraBuffer == NULL && buffer[i].BufferType == SECBUFFER_EXTRA )
177  {
178  pExtraBuffer = &buffer[i];
179  }
180  }
181  if( e_status == SEC_E_OK )
182  {
183  std::string decrypted( reinterpret_cast<const char*>( pDataBuffer->pvBuffer ),
184  pDataBuffer->cbBuffer );
185  m_handler->handleDecryptedData( this, decrypted );
186  if( pExtraBuffer == NULL )
187  {
188  m_buffer.erase( 0, processed_data );
189  }
190  else
191  {
192  //std::cout << "m_buffer.size() = " << pExtraBuffer->cbBuffer << std::endl;
193  m_buffer.erase( 0, processed_data - pExtraBuffer->cbBuffer );
194  //std::cout << "m_buffer.size() = " << m_buffer.size() << std::endl;
195 
196  cbIoBufferLength = m_sizes.cbHeader + m_sizes.cbMaximumMessage + m_sizes.cbTrailer;
197  wantNewBufferSize = true;
198  }
199  }
200  else if( e_status == SEC_E_INCOMPLETE_MESSAGE )
201  {
202  if( cbIoBufferLength < 200000 && m_buffer.size() > cbIoBufferLength )
203  {
204  cbIoBufferLength += 1000;
205  wantNewBufferSize = true;
206  }
207  else
208  {
209  cbIoBufferLength = m_sizes.cbHeader + m_sizes.cbMaximumMessage + m_sizes.cbTrailer;
210  wantNewBufferSize = true;
211  break;
212  }
213  }
214  else
215  {
216  //std::cout << "decrypt !!!ERROR!!!\n";
217  if( !m_secure )
218  m_handler->handleHandshakeResult( this, false, m_certInfo );
219  cleanup();
220  break;
221  }
222  }
223  while( m_buffer.size() != 0 );
224  LocalFree( e_iobuffer );
225  }
226  else
227  {
228  handshakeStage( data );
229  }
230  //printf("<< SChannel::decrypt()\n");
231  return 0;
232  }
233 
235  {
236  if( !m_mutex.trylock() )
237  return;
238 
239  m_buffer = "";
240  if( !m_cleanedup )
241  {
242  m_valid = false;
243  m_secure = false;
244  m_cleanedup = true;
245  DeleteSecurityContext( &m_context );
246  FreeCredentialsHandle( &m_credHandle );
247  }
248 
249  m_mutex.unlock();
250  }
251 
253  {
254  if( !m_handler )
255  return false;
256 
257  //printf(">> SChannel::handshake()\n");
258  SECURITY_STATUS error;
259  ULONG return_flags;
260  TimeStamp t;
261  SecBuffer obuf[1];
262  SecBufferDesc obufs;
263  SCHANNEL_CRED tlscred;
264  ULONG request = ISC_REQ_ALLOCATE_MEMORY
265  | ISC_REQ_CONFIDENTIALITY
266  | ISC_REQ_EXTENDED_ERROR
267  | ISC_REQ_INTEGRITY
268  | ISC_REQ_REPLAY_DETECT
269  | ISC_REQ_SEQUENCE_DETECT
270  | ISC_REQ_STREAM
271  | ISC_REQ_MANUAL_CRED_VALIDATION;
272 
273  /* initialize TLS credential */
274  memset( &tlscred, 0, sizeof( SCHANNEL_CRED ) );
275  tlscred.dwVersion = SCHANNEL_CRED_VERSION;
276  tlscred.grbitEnabledProtocols = SP_PROT_TLS1;
277  /* acquire credentials */
278  error = AcquireCredentialsHandle( 0,
279  UNISP_NAME,
280  SECPKG_CRED_OUTBOUND,
281  0,
282  &tlscred,
283  0,
284  0,
285  &m_credHandle,
286  &t );
287  //print_error(error, "handshake() ~ AcquireCredentialsHandle()");
288  if( error != SEC_E_OK )
289  {
290  cleanup();
291  m_handler->handleHandshakeResult( this, false, m_certInfo );
292  return false;
293  }
294  else
295  {
296  /* initialize buffers */
297  obuf[0].cbBuffer = 0;
298  obuf[0].pvBuffer = 0;
299  obuf[0].BufferType = SECBUFFER_TOKEN;
300  /* initialize buffer descriptors */
301  obufs.ulVersion = SECBUFFER_VERSION;
302  obufs.cBuffers = 1;
303  obufs.pBuffers = obuf;
304  /* negotiate security */
305  SEC_CHAR* hname = const_cast<char*>( m_server.c_str() );
306 
307  error = InitializeSecurityContextA( &m_credHandle,
308  0,
309  hname,
310  request,
311  0,
312  SECURITY_NETWORK_DREP,
313  0,
314  0,
315  &m_context,
316  &obufs,
317  &return_flags,
318  NULL );
319  //print_error(error, "handshake() ~ InitializeSecurityContext()");
320 
321  if( error == SEC_I_CONTINUE_NEEDED )
322  {
323  m_cleanedup = false;
324  //std::cout << "obuf[1].cbBuffer: " << obuf[0].cbBuffer << "\n";
325  std::string senddata( static_cast<char*>(obuf[0].pvBuffer), obuf[0].cbBuffer );
326  FreeContextBuffer( obuf[0].pvBuffer );
327  m_handler->handleEncryptedData( this, senddata );
328  return true;
329  }
330  else
331  {
332  cleanup();
333  m_handler->handleHandshakeResult( this, false, m_certInfo );
334  return false;
335  }
336  }
337  }
338 
339  void SChannel::handshakeStage( const std::string& data )
340  {
341  //printf(" >> handshake_stage\n");
342  m_buffer += data;
343 
344  SECURITY_STATUS error;
345  ULONG a;
346  TimeStamp t;
347  SecBuffer ibuf[2], obuf[1];
348  SecBufferDesc ibufs, obufs;
349  ULONG request = ISC_REQ_ALLOCATE_MEMORY
350  | ISC_REQ_CONFIDENTIALITY
351  | ISC_REQ_EXTENDED_ERROR
352  | ISC_REQ_INTEGRITY
353  | ISC_REQ_REPLAY_DETECT
354  | ISC_REQ_SEQUENCE_DETECT
355  | ISC_REQ_STREAM
356  | ISC_REQ_MANUAL_CRED_VALIDATION;
357 
358  SEC_CHAR* hname = const_cast<char*>( m_server.c_str() );
359 
360  do
361  {
362  /* initialize buffers */
363  ibuf[0].cbBuffer = static_cast<unsigned long>( m_buffer.size() );
364  ibuf[0].pvBuffer = static_cast<void*>( const_cast<char*>( m_buffer.c_str() ) );
365  //std::cout << "Size: " << m_buffer.size() << "\n";
366  ibuf[1].cbBuffer = 0;
367  ibuf[1].pvBuffer = 0;
368  obuf[0].cbBuffer = 0;
369  obuf[0].pvBuffer = 0;
370 
371  ibuf[0].BufferType = SECBUFFER_TOKEN;
372  ibuf[1].BufferType = SECBUFFER_EMPTY;
373  obuf[0].BufferType = SECBUFFER_EMPTY;
374  /* initialize buffer descriptors */
375  ibufs.ulVersion = obufs.ulVersion = SECBUFFER_VERSION;
376  ibufs.cBuffers = 2;
377  obufs.cBuffers = 1;
378  ibufs.pBuffers = ibuf;
379  obufs.pBuffers = obuf;
380 
381  /*
382  * std::cout << "obuf[0].cbBuffer: " << obuf[0].cbBuffer << "\t" << obuf[0].BufferType << "\n";
383  * std::cout << "ibuf[0].cbBuffer: " << ibuf[0].cbBuffer << "\t" << ibuf[0].BufferType << "\n";
384  * std::cout << "ibuf[1].cbBuffer: " << ibuf[1].cbBuffer << "\t" << ibuf[1].BufferType << "\n";
385  */
386 
387  /* negotiate security */
388  error = InitializeSecurityContextA( &m_credHandle,
389  &m_context,
390  hname,
391  request,
392  0,
393  0,
394  &ibufs,
395  0,
396  0,
397  &obufs,
398  &a,
399  &t );
400  //print_error(error, "handshake() ~ InitializeSecurityContext()");
401  if( error == SEC_E_OK )
402  {
403  // EXTRA STUFF??
404  if( ibuf[1].BufferType == SECBUFFER_EXTRA )
405  {
406  m_buffer.erase( 0, m_buffer.size() - ibuf[1].cbBuffer );
407  }
408  else
409  {
410  m_buffer = EmptyString;
411  }
412  setSizes();
413  setCertinfos();
414 
415  m_secure = true;
416  m_handler->handleHandshakeResult( this, true, m_certInfo );
417  break;
418  }
419  else if( error == SEC_I_CONTINUE_NEEDED )
420  {
421  /*
422  * std::cout << "obuf[0].cbBuffer: " << obuf[0].cbBuffer << "\t" << obuf[0].BufferType << "\n";
423  * std::cout << "ibuf[0].cbBuffer: " << ibuf[0].cbBuffer << "\t" << ibuf[0].BufferType << "\n";
424  * std::cout << "ibuf[1].cbBuffer: " << ibuf[1].cbBuffer << "\t" << ibuf[1].BufferType << "\n";
425  */
426 
427  // STUFF TO SEND??
428  if( obuf[0].cbBuffer != 0 && obuf[0].pvBuffer != NULL )
429  {
430  std::string senddata( static_cast<char*>(obuf[0].pvBuffer), obuf[0].cbBuffer );
431  FreeContextBuffer( obuf[0].pvBuffer );
432  m_handler->handleEncryptedData( this, senddata );
433  }
434  // EXTRA STUFF??
435  if( ibuf[1].BufferType == SECBUFFER_EXTRA )
436  {
437  m_buffer.erase( 0, m_buffer.size() - ibuf[1].cbBuffer );
438  // Call again if we aren't sending anything (otherwise the server will not send anything back
439  // and this function won't get called again to finish the processing). This is needed for
440  // NT4.0 which does not seem to process the entire buffer the first time around
441  if( obuf[0].cbBuffer == 0 )
442  handshakeStage( EmptyString );
443  }
444  else
445  {
446  m_buffer = EmptyString;
447  }
448  return;
449  }
450  else if( error == SEC_I_INCOMPLETE_CREDENTIALS )
451  {
452  handshakeStage( EmptyString );
453  }
454  else if( error == SEC_E_INCOMPLETE_MESSAGE )
455  {
456  break;
457  }
458  else
459  {
460  cleanup();
461  m_handler->handleHandshakeResult( this, false, m_certInfo );
462  break;
463  }
464  }
465  while( true );
466  }
467 
469  {
470 #ifdef HAVE_WINTLS_CHANNEL_BINDING
471  return true;
472 #else
473  return false;
474 #endif
475  }
476 
477  const std::string SChannel::channelBinding() const
478  {
479 #ifdef HAVE_WINTLS_CHANNEL_BINDING // see ../config.h.win if the following doesn't compile
480  SecPkgContext_Bindings buf;
481  if( QueryContextAttributes( &m_context, SECPKG_ATTR_UNIQUE_BINDINGS, &buf ) == SEC_E_OK )
482  {
483  return std::string( buf->Bindings[buf->Bindings.dwApplicationDataOffset], buf->Bindings.cbApplicationDataLength );
484  }
485 #endif
486  return EmptyString;
487  }
488 
489  void SChannel::setCACerts( const StringList& /*cacerts*/ ) {}
490 
491  void SChannel::setClientCert( const std::string& /*clientKey*/, const std::string& /*clientCerts*/ ) {}
492 
493  void SChannel::setSizes()
494  {
495  if( QueryContextAttributes( &m_context, SECPKG_ATTR_STREAM_SIZES, &m_sizes ) == SEC_E_OK )
496  {
497  //std::cout << "set_sizes success\n";
498  }
499  else
500  {
501  //std::cout << "set_sizes no success\n";
502  cleanup();
503  m_handler->handleHandshakeResult( this, false, m_certInfo );
504  }
505  }
506 
507  int SChannel::filetime2int( FILETIME t )
508  {
509  SYSTEMTIME stUTC;
510  FileTimeToSystemTime(&t, &stUTC);
511  std::tm ts;
512  ts.tm_year = stUTC.wYear - 1900;
513  ts.tm_mon = stUTC.wMonth - 1;
514  ts.tm_mday = stUTC.wDay;
515  ts.tm_hour = stUTC.wHour;
516  ts.tm_min = stUTC.wMinute;
517  ts.tm_sec = stUTC.wSecond;
518 
519  time_t unixtime;
520  if ( (unixtime = mktime(&ts)) == -1 )
521  unixtime = 0;
522  return (int)unixtime;
523  }
524 
525  void SChannel::validateCert()
526  {
527  bool valid = false;
528  HTTPSPolicyCallbackData policyHTTPS;
529  CERT_CHAIN_POLICY_PARA policyParameter;
530  CERT_CHAIN_POLICY_STATUS policyStatus;
531 
532  PCCERT_CONTEXT remoteCertContext = NULL;
533  PCCERT_CHAIN_CONTEXT chainContext = NULL;
534  CERT_CHAIN_PARA chainParameter;
535  PSTR serverName = const_cast<char*>( m_server.c_str() );
536 
537  PWSTR uServerName = NULL;
538  DWORD csizeServerName;
539 
540  LPSTR Usages[] = {
541  szOID_PKIX_KP_SERVER_AUTH,
542  szOID_SERVER_GATED_CRYPTO,
543  szOID_SGC_NETSCAPE
544  };
545  DWORD cUsages = sizeof( Usages ) / sizeof( LPSTR );
546 
547  do
548  {
549  // Get server's certificate.
550  if( QueryContextAttributes( &m_context, SECPKG_ATTR_REMOTE_CERT_CONTEXT,
551  (PVOID)&remoteCertContext ) != SEC_E_OK )
552  {
553  //printf("Error querying remote certificate\n");
554  // !!! THROW SOME ERROR
555  break;
556  }
557 
558  // unicode conversation
559  // calculating unicode server name size
560  csizeServerName = MultiByteToWideChar( CP_ACP, 0, serverName, -1, NULL, 0 );
561  uServerName = reinterpret_cast<WCHAR *>( LocalAlloc( LMEM_FIXED,
562  csizeServerName * sizeof( WCHAR ) ) );
563  if( uServerName == NULL )
564  {
565  //printf("SEC_E_INSUFFICIENT_MEMORY ~ Not enough memory!!!\n");
566  break;
567  }
568 
569  // convert into unicode
570  csizeServerName = MultiByteToWideChar( CP_ACP, 0, serverName, -1, uServerName, csizeServerName );
571  if( csizeServerName == 0 )
572  {
573  //printf("SEC_E_WRONG_PRINCIPAL\n");
574  break;
575  }
576 
577  // create the chain
578  ZeroMemory( &chainParameter, sizeof( chainParameter ) );
579  chainParameter.cbSize = sizeof( chainParameter );
580  chainParameter.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
581  chainParameter.RequestedUsage.Usage.cUsageIdentifier = cUsages;
582  chainParameter.RequestedUsage.Usage.rgpszUsageIdentifier = Usages;
583 
584  if( !CertGetCertificateChain( NULL, remoteCertContext, NULL, remoteCertContext->hCertStore,
585  &chainParameter, 0, NULL, &chainContext ) )
586  {
587 // DWORD status = GetLastError();
588 // printf("Error 0x%x returned by CertGetCertificateChain!!!\n", status);
589  break;
590  }
591 
592  // validate the chain
593  ZeroMemory( &policyHTTPS, sizeof( HTTPSPolicyCallbackData ) );
594  policyHTTPS.cbStruct = sizeof( HTTPSPolicyCallbackData );
595  policyHTTPS.dwAuthType = AUTHTYPE_SERVER;
596  policyHTTPS.fdwChecks = 0;
597  policyHTTPS.pwszServerName = uServerName;
598 
599  memset( &policyParameter, 0, sizeof( policyParameter ) );
600  policyParameter.cbSize = sizeof( policyParameter );
601  policyParameter.pvExtraPolicyPara = &policyHTTPS;
602 
603  memset( &policyStatus, 0, sizeof( policyStatus ) );
604  policyStatus.cbSize = sizeof( policyStatus );
605 
606  if( !CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_SSL, chainContext, &policyParameter,
607  &policyStatus ) )
608  {
609 // DWORD status = GetLastError();
610 // printf("Error 0x%x returned by CertVerifyCertificateChainPolicy!!!\n", status);
611  break;
612  }
613 
614  if( policyStatus.dwError )
615  {
616  //printf("Trust Error!!!}n");
617  break;
618  }
619  valid = true;
620  }
621  while( false );
622  // cleanup
623  if( chainContext ) CertFreeCertificateChain( chainContext );
624  m_certInfo.chain = valid;
625  }
626 
627  void SChannel::connectionInfos()
628  {
629  SecPkgContext_ConnectionInfo conn_info;
630 
631  memset( &conn_info, 0, sizeof( conn_info ) );
632 
633  if( QueryContextAttributes( &m_context, SECPKG_ATTR_CONNECTION_INFO, &conn_info ) == SEC_E_OK )
634  {
635  switch( conn_info.dwProtocol )
636  {
637  case SP_PROT_TLS1_CLIENT:
638  m_certInfo.protocol = "TLSv1";
639  break;
640  case SP_PROT_SSL3_CLIENT:
641  m_certInfo.protocol = "SSLv3";
642  break;
643  default:
644  m_certInfo.protocol = "unknown";
645  }
646 
647  switch( conn_info.aiCipher )
648  {
649  case CALG_3DES:
650  m_certInfo.cipher = "3DES";
651  break;
652  case CALG_AES_128:
653  m_certInfo.cipher = "AES_128";
654  break;
655  case CALG_AES_256:
656  m_certInfo.cipher = "AES_256";
657  break;
658  case CALG_DES:
659  m_certInfo.cipher = "DES";
660  break;
661  case CALG_RC2:
662  m_certInfo.cipher = "RC2";
663  break;
664  case CALG_RC4:
665  m_certInfo.cipher = "RC4";
666  break;
667  default:
668  m_certInfo.cipher = EmptyString;
669  }
670 
671  switch( conn_info.aiHash )
672  {
673  case CALG_MD5:
674  m_certInfo.mac = "MD5";
675  break;
676  case CALG_SHA:
677  m_certInfo.mac = "SHA";
678  break;
679  default:
680  m_certInfo.mac = EmptyString;
681  }
682  }
683  }
684 
685  void SChannel::certData()
686  {
687  PCCERT_CONTEXT remoteCertContext = NULL;
688  CHAR certString[1000];
689 
690  // getting server's certificate
691  if( QueryContextAttributes( &m_context, SECPKG_ATTR_REMOTE_CERT_CONTEXT,
692  (PVOID)&remoteCertContext ) != SEC_E_OK )
693  {
694  return;
695  }
696 
697  // setting certificat's lifespan
698  m_certInfo.date_from = filetime2int( remoteCertContext->pCertInfo->NotBefore );
699  m_certInfo.date_to = filetime2int( remoteCertContext->pCertInfo->NotAfter );
700 
701  if( !CertNameToStrA( remoteCertContext->dwCertEncodingType,
702  &remoteCertContext->pCertInfo->Subject,
703  CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
704  certString, sizeof( certString ) ) )
705  {
706  return;
707  }
708  m_certInfo.server = certString;
709 
710  if( !CertNameToStrA( remoteCertContext->dwCertEncodingType,
711  &remoteCertContext->pCertInfo->Issuer,
712  CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
713  certString, sizeof( certString ) ) )
714  {
715  return;
716  }
717  m_certInfo.issuer = certString;
718  }
719 
720  void SChannel::setCertinfos()
721  {
722  validateCert();
723  connectionInfos();
724  certData();
725  }
726 
727 #if 0
728  void SChannel::print_error( int errorcode, const char* place )
729  {
730  printf( "Win error at %s.\n", place );
731  switch( errorcode )
732  {
733  case SEC_E_OK:
734  printf( "\tValue:\tSEC_E_OK\n" );
735  printf( "\tDesc:\tNot really an error. Everything is fine.\n" );
736  break;
737  case SEC_E_INSUFFICIENT_MEMORY:
738  printf( "\tValue:\tSEC_E_INSUFFICIENT_MEMORY\n" );
739  printf( "\tDesc:\tThere is not enough memory available to complete the requested action.\n" );
740  break;
741  case SEC_E_INTERNAL_ERROR:
742  printf( "\tValue:\tSEC_E_INTERNAL_ERROR\n" );
743  printf( "\tDesc:\tAn error occurred that did not map to an SSPI error code.\n" );
744  break;
745  case SEC_E_NO_CREDENTIALS:
746  printf( "\tValue:\tSEC_E_NO_CREDENTIALS\n" );
747  printf( "\tDesc:\tNo credentials are available in the security package.\n" );
748  break;
749  case SEC_E_NOT_OWNER:
750  printf( "\tValue:\tSEC_E_NOT_OWNER\n" );
751  printf( "\tDesc:\tThe caller of the function does not have the necessary credentials.\n" );
752  break;
753  case SEC_E_SECPKG_NOT_FOUND:
754  printf( "\tValue:\tSEC_E_SECPKG_NOT_FOUND\n" );
755  printf( "\tDesc:\tThe requested security package does not exist. \n" );
756  break;
757  case SEC_E_UNKNOWN_CREDENTIALS:
758  printf( "\tValue:\tSEC_E_UNKNOWN_CREDENTIALS\n" );
759  printf( "\tDesc:\tThe credentials supplied to the package were not recognized.\n" );
760  break;
761  case SEC_E_INCOMPLETE_MESSAGE:
762  printf( "\tValue:\tSEC_E_INCOMPLETE_MESSAGE\n" );
763  printf( "\tDesc:\tData for the whole message was not read from the wire.\n" );
764  break;
765  case SEC_E_INVALID_HANDLE:
766  printf( "\tValue:\tSEC_E_INVALID_HANDLE\n" );
767  printf( "\tDesc:\tThe handle passed to the function is invalid.\n" );
768  break;
769  case SEC_E_INVALID_TOKEN:
770  printf( "\tValue:\tSEC_E_INVALID_TOKEN\n" );
771  printf( "\tDesc:\tThe error is due to a malformed input token, such as a token "
772  "corrupted in transit...\n" );
773  break;
774  case SEC_E_LOGON_DENIED:
775  printf( "\tValue:\tSEC_E_LOGON_DENIED\n" );
776  printf( "\tDesc:\tThe logon failed.\n" );
777  break;
778  case SEC_E_NO_AUTHENTICATING_AUTHORITY:
779  printf( "\tValue:\tSEC_E_NO_AUTHENTICATING_AUTHORITY\n" );
780  printf( "\tDesc:\tNo authority could be contacted for authentication...\n" );
781  break;
782  case SEC_E_TARGET_UNKNOWN:
783  printf( "\tValue:\tSEC_E_TARGET_UNKNOWN\n" );
784  printf( "\tDesc:\tThe target was not recognized.\n" );
785  break;
786  case SEC_E_UNSUPPORTED_FUNCTION:
787  printf( "\tValue:\tSEC_E_UNSUPPORTED_FUNCTION\n" );
788  printf( "\tDesc:\tAn invalid context attribute flag (ISC_REQ_DELEGATE or "
789  "ISC_REQ_PROMPT_FOR_CREDS)...\n" );
790  break;
791  case SEC_E_WRONG_PRINCIPAL:
792  printf( "\tValue:\tSEC_E_WRONG_PRINCIPAL\n" );
793  printf( "\tDesc:\tThe principal that received the authentication request "
794  "is not the same as the...\n" );
795  break;
796  case SEC_I_COMPLETE_AND_CONTINUE:
797  printf( "\tValue:\tSEC_I_COMPLETE_AND_CONTINUE\n" );
798  printf( "\tDesc:\tThe client must call CompleteAuthToken and then pass the output...\n" );
799  break;
800  case SEC_I_COMPLETE_NEEDED:
801  printf( "\tValue:\tSEC_I_COMPLETE_NEEDED\n" );
802  printf( "\tDesc:\tThe client must finish building the message and then "
803  "call the CompleteAuthToken function.\n" );
804  break;
805  case SEC_I_CONTINUE_NEEDED:
806  printf( "\tValue:\tSEC_I_CONTINUE_NEEDED\n" );
807  printf( "\tDesc:\tThe client must send the output token to the server "
808  "and wait for a return token...\n" );
809  break;
810  case SEC_I_INCOMPLETE_CREDENTIALS:
811  printf( "\tValue:\tSEC_I_INCOMPLETE_CREDENTIALS\n" );
812  printf( "\tDesc:\tThe server has requested client authentication, "
813  "and the supplied credentials either...\n" );
814  break;
815  default:
816  printf( "\tValue:\t%d\n", errorcode );
817  printf( "\tDesc:\tUnknown error code.\n" );
818  }
819  }
820 #endif
821 
822 }
823 
824 #endif // HAVE_WINTLS