gloox  1.0
tlsschannel.cpp
1 /*
2  * Copyright (c) 2007-2009 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 
468  void SChannel::setCACerts( const StringList& /*cacerts*/ ) {}
469 
470  void SChannel::setClientCert( const std::string& /*clientKey*/, const std::string& /*clientCerts*/ ) {}
471 
472  void SChannel::setSizes()
473  {
474  if( QueryContextAttributes( &m_context, SECPKG_ATTR_STREAM_SIZES, &m_sizes ) == SEC_E_OK )
475  {
476  //std::cout << "set_sizes success\n";
477  }
478  else
479  {
480  //std::cout << "set_sizes no success\n";
481  cleanup();
482  m_handler->handleHandshakeResult( this, false, m_certInfo );
483  }
484  }
485 
486  int SChannel::filetime2int( FILETIME t )
487  {
488  SYSTEMTIME stUTC;
489  FileTimeToSystemTime(&t, &stUTC);
490  std::tm ts;
491  ts.tm_year = stUTC.wYear - 1900;
492  ts.tm_mon = stUTC.wMonth - 1;
493  ts.tm_mday = stUTC.wDay;
494  ts.tm_hour = stUTC.wHour;
495  ts.tm_min = stUTC.wMinute;
496  ts.tm_sec = stUTC.wSecond;
497 
498  time_t unixtime;
499  if ( (unixtime = mktime(&ts)) == -1 )
500  unixtime = 0;
501  return (int)unixtime;
502  }
503 
504  void SChannel::validateCert()
505  {
506  bool valid = false;
507  HTTPSPolicyCallbackData policyHTTPS;
508  CERT_CHAIN_POLICY_PARA policyParameter;
509  CERT_CHAIN_POLICY_STATUS policyStatus;
510 
511  PCCERT_CONTEXT remoteCertContext = NULL;
512  PCCERT_CHAIN_CONTEXT chainContext = NULL;
513  CERT_CHAIN_PARA chainParameter;
514  PSTR serverName = const_cast<char*>( m_server.c_str() );
515 
516  PWSTR uServerName = NULL;
517  DWORD csizeServerName;
518 
519  LPSTR Usages[] = {
520  szOID_PKIX_KP_SERVER_AUTH,
521  szOID_SERVER_GATED_CRYPTO,
522  szOID_SGC_NETSCAPE
523  };
524  DWORD cUsages = sizeof( Usages ) / sizeof( LPSTR );
525 
526  do
527  {
528  // Get server's certificate.
529  if( QueryContextAttributes( &m_context, SECPKG_ATTR_REMOTE_CERT_CONTEXT,
530  (PVOID)&remoteCertContext ) != SEC_E_OK )
531  {
532  //printf("Error querying remote certificate\n");
533  // !!! THROW SOME ERROR
534  break;
535  }
536 
537  // unicode conversation
538  // calculating unicode server name size
539  csizeServerName = MultiByteToWideChar( CP_ACP, 0, serverName, -1, NULL, 0 );
540  uServerName = reinterpret_cast<WCHAR *>( LocalAlloc( LMEM_FIXED,
541  csizeServerName * sizeof( WCHAR ) ) );
542  if( uServerName == NULL )
543  {
544  //printf("SEC_E_INSUFFICIENT_MEMORY ~ Not enough memory!!!\n");
545  break;
546  }
547 
548  // convert into unicode
549  csizeServerName = MultiByteToWideChar( CP_ACP, 0, serverName, -1, uServerName, csizeServerName );
550  if( csizeServerName == 0 )
551  {
552  //printf("SEC_E_WRONG_PRINCIPAL\n");
553  break;
554  }
555 
556  // create the chain
557  ZeroMemory( &chainParameter, sizeof( chainParameter ) );
558  chainParameter.cbSize = sizeof( chainParameter );
559  chainParameter.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
560  chainParameter.RequestedUsage.Usage.cUsageIdentifier = cUsages;
561  chainParameter.RequestedUsage.Usage.rgpszUsageIdentifier = Usages;
562 
563  if( !CertGetCertificateChain( NULL, remoteCertContext, NULL, remoteCertContext->hCertStore,
564  &chainParameter, 0, NULL, &chainContext ) )
565  {
566 // DWORD status = GetLastError();
567 // printf("Error 0x%x returned by CertGetCertificateChain!!!\n", status);
568  break;
569  }
570 
571  // validate the chain
572  ZeroMemory( &policyHTTPS, sizeof( HTTPSPolicyCallbackData ) );
573  policyHTTPS.cbStruct = sizeof( HTTPSPolicyCallbackData );
574  policyHTTPS.dwAuthType = AUTHTYPE_SERVER;
575  policyHTTPS.fdwChecks = 0;
576  policyHTTPS.pwszServerName = uServerName;
577 
578  memset( &policyParameter, 0, sizeof( policyParameter ) );
579  policyParameter.cbSize = sizeof( policyParameter );
580  policyParameter.pvExtraPolicyPara = &policyHTTPS;
581 
582  memset( &policyStatus, 0, sizeof( policyStatus ) );
583  policyStatus.cbSize = sizeof( policyStatus );
584 
585  if( !CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_SSL, chainContext, &policyParameter,
586  &policyStatus ) )
587  {
588 // DWORD status = GetLastError();
589 // printf("Error 0x%x returned by CertVerifyCertificateChainPolicy!!!\n", status);
590  break;
591  }
592 
593  if( policyStatus.dwError )
594  {
595  //printf("Trust Error!!!}n");
596  break;
597  }
598  valid = true;
599  }
600  while( false );
601  // cleanup
602  if( chainContext ) CertFreeCertificateChain( chainContext );
603  m_certInfo.chain = valid;
604  }
605 
606  void SChannel::connectionInfos()
607  {
608  SecPkgContext_ConnectionInfo conn_info;
609 
610  memset( &conn_info, 0, sizeof( conn_info ) );
611 
612  if( QueryContextAttributes( &m_context, SECPKG_ATTR_CONNECTION_INFO, &conn_info ) == SEC_E_OK )
613  {
614  switch( conn_info.dwProtocol )
615  {
616  case SP_PROT_TLS1_CLIENT:
617  m_certInfo.protocol = "TLSv1";
618  break;
619  case SP_PROT_SSL3_CLIENT:
620  m_certInfo.protocol = "SSLv3";
621  break;
622  default:
623  m_certInfo.protocol = "unknown";
624  }
625 
626  switch( conn_info.aiCipher )
627  {
628  case CALG_3DES:
629  m_certInfo.cipher = "3DES";
630  break;
631  case CALG_AES_128:
632  m_certInfo.cipher = "AES_128";
633  break;
634  case CALG_AES_256:
635  m_certInfo.cipher = "AES_256";
636  break;
637  case CALG_DES:
638  m_certInfo.cipher = "DES";
639  break;
640  case CALG_RC2:
641  m_certInfo.cipher = "RC2";
642  break;
643  case CALG_RC4:
644  m_certInfo.cipher = "RC4";
645  break;
646  default:
647  m_certInfo.cipher = EmptyString;
648  }
649 
650  switch( conn_info.aiHash )
651  {
652  case CALG_MD5:
653  m_certInfo.mac = "MD5";
654  break;
655  case CALG_SHA:
656  m_certInfo.mac = "SHA";
657  break;
658  default:
659  m_certInfo.mac = EmptyString;
660  }
661  }
662  }
663 
664  void SChannel::certData()
665  {
666  PCCERT_CONTEXT remoteCertContext = NULL;
667  CHAR certString[1000];
668 
669  // getting server's certificate
670  if( QueryContextAttributes( &m_context, SECPKG_ATTR_REMOTE_CERT_CONTEXT,
671  (PVOID)&remoteCertContext ) != SEC_E_OK )
672  {
673  return;
674  }
675 
676  // setting certificat's lifespan
677  m_certInfo.date_from = filetime2int( remoteCertContext->pCertInfo->NotBefore );
678  m_certInfo.date_to = filetime2int( remoteCertContext->pCertInfo->NotAfter );
679 
680  if( !CertNameToStrA( remoteCertContext->dwCertEncodingType,
681  &remoteCertContext->pCertInfo->Subject,
682  CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
683  certString, sizeof( certString ) ) )
684  {
685  return;
686  }
687  m_certInfo.server = certString;
688 
689  if( !CertNameToStrA( remoteCertContext->dwCertEncodingType,
690  &remoteCertContext->pCertInfo->Issuer,
691  CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
692  certString, sizeof( certString ) ) )
693  {
694  return;
695  }
696  m_certInfo.issuer = certString;
697  }
698 
699  void SChannel::setCertinfos()
700  {
701  validateCert();
702  connectionInfos();
703  certData();
704  }
705 
706 #if 0
707  void SChannel::print_error( int errorcode, const char* place )
708  {
709  printf( "Win error at %s.\n", place );
710  switch( errorcode )
711  {
712  case SEC_E_OK:
713  printf( "\tValue:\tSEC_E_OK\n" );
714  printf( "\tDesc:\tNot really an error. Everything is fine.\n" );
715  break;
716  case SEC_E_INSUFFICIENT_MEMORY:
717  printf( "\tValue:\tSEC_E_INSUFFICIENT_MEMORY\n" );
718  printf( "\tDesc:\tThere is not enough memory available to complete the requested action.\n" );
719  break;
720  case SEC_E_INTERNAL_ERROR:
721  printf( "\tValue:\tSEC_E_INTERNAL_ERROR\n" );
722  printf( "\tDesc:\tAn error occurred that did not map to an SSPI error code.\n" );
723  break;
724  case SEC_E_NO_CREDENTIALS:
725  printf( "\tValue:\tSEC_E_NO_CREDENTIALS\n" );
726  printf( "\tDesc:\tNo credentials are available in the security package.\n" );
727  break;
728  case SEC_E_NOT_OWNER:
729  printf( "\tValue:\tSEC_E_NOT_OWNER\n" );
730  printf( "\tDesc:\tThe caller of the function does not have the necessary credentials.\n" );
731  break;
732  case SEC_E_SECPKG_NOT_FOUND:
733  printf( "\tValue:\tSEC_E_SECPKG_NOT_FOUND\n" );
734  printf( "\tDesc:\tThe requested security package does not exist. \n" );
735  break;
736  case SEC_E_UNKNOWN_CREDENTIALS:
737  printf( "\tValue:\tSEC_E_UNKNOWN_CREDENTIALS\n" );
738  printf( "\tDesc:\tThe credentials supplied to the package were not recognized.\n" );
739  break;
740  case SEC_E_INCOMPLETE_MESSAGE:
741  printf( "\tValue:\tSEC_E_INCOMPLETE_MESSAGE\n" );
742  printf( "\tDesc:\tData for the whole message was not read from the wire.\n" );
743  break;
744  case SEC_E_INVALID_HANDLE:
745  printf( "\tValue:\tSEC_E_INVALID_HANDLE\n" );
746  printf( "\tDesc:\tThe handle passed to the function is invalid.\n" );
747  break;
748  case SEC_E_INVALID_TOKEN:
749  printf( "\tValue:\tSEC_E_INVALID_TOKEN\n" );
750  printf( "\tDesc:\tThe error is due to a malformed input token, such as a token "
751  "corrupted in transit...\n" );
752  break;
753  case SEC_E_LOGON_DENIED:
754  printf( "\tValue:\tSEC_E_LOGON_DENIED\n" );
755  printf( "\tDesc:\tThe logon failed.\n" );
756  break;
757  case SEC_E_NO_AUTHENTICATING_AUTHORITY:
758  printf( "\tValue:\tSEC_E_NO_AUTHENTICATING_AUTHORITY\n" );
759  printf( "\tDesc:\tNo authority could be contacted for authentication...\n" );
760  break;
761  case SEC_E_TARGET_UNKNOWN:
762  printf( "\tValue:\tSEC_E_TARGET_UNKNOWN\n" );
763  printf( "\tDesc:\tThe target was not recognized.\n" );
764  break;
765  case SEC_E_UNSUPPORTED_FUNCTION:
766  printf( "\tValue:\tSEC_E_UNSUPPORTED_FUNCTION\n" );
767  printf( "\tDesc:\tAn invalid context attribute flag (ISC_REQ_DELEGATE or "
768  "ISC_REQ_PROMPT_FOR_CREDS)...\n" );
769  break;
770  case SEC_E_WRONG_PRINCIPAL:
771  printf( "\tValue:\tSEC_E_WRONG_PRINCIPAL\n" );
772  printf( "\tDesc:\tThe principal that received the authentication request "
773  "is not the same as the...\n" );
774  break;
775  case SEC_I_COMPLETE_AND_CONTINUE:
776  printf( "\tValue:\tSEC_I_COMPLETE_AND_CONTINUE\n" );
777  printf( "\tDesc:\tThe client must call CompleteAuthToken and then pass the output...\n" );
778  break;
779  case SEC_I_COMPLETE_NEEDED:
780  printf( "\tValue:\tSEC_I_COMPLETE_NEEDED\n" );
781  printf( "\tDesc:\tThe client must finish building the message and then "
782  "call the CompleteAuthToken function.\n" );
783  break;
784  case SEC_I_CONTINUE_NEEDED:
785  printf( "\tValue:\tSEC_I_CONTINUE_NEEDED\n" );
786  printf( "\tDesc:\tThe client must send the output token to the server "
787  "and wait for a return token...\n" );
788  break;
789  case SEC_I_INCOMPLETE_CREDENTIALS:
790  printf( "\tValue:\tSEC_I_INCOMPLETE_CREDENTIALS\n" );
791  printf( "\tDesc:\tThe server has requested client authentication, "
792  "and the supplied credentials either...\n" );
793  break;
794  default:
795  printf( "\tValue:\t%d\n", errorcode );
796  printf( "\tDesc:\tUnknown error code.\n" );
797  }
798  }
799 #endif
800 
801 }
802 
803 #endif // HAVE_WINTLS