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