tlsschannel.cpp

00001 /*
00002  * Copyright (c) 2007-2008 by Jakob Schroeter <js@camaya.net>
00003  * This file is part of the gloox library. http://camaya.net/gloox
00004  *
00005  * This software is distributed under a license. The full license
00006  * agreement can be found in the file LICENSE in this distribution.
00007  * This software may not be copied, modified, sold or distributed
00008  * other than expressed in the named license agreement.
00009  *
00010  * This software is distributed without any warranty.
00011  */
00012 
00013 #include "tlsschannel.h"
00014 
00015 #ifdef HAVE_WINTLS
00016 
00017 #include <stdio.h> // just for debugging output
00018 #include <iostream>
00019 
00020 namespace gloox
00021 {
00022   SChannel::SChannel( TLSHandler* th, const std::string& server )
00023     : TLSBase( th, server ), m_cleanedup( true )
00024   {
00025     //printf(">> SChannel::SChannel()\n");
00026   }
00027 
00028   SChannel::~SChannel()
00029   {
00030     m_handler = 0;
00031     cleanup();
00032     //printf(">> SChannel::~SChannel()\n");
00033   }
00034 
00035   bool SChannel::encrypt( const std::string& data )
00036   {
00037     if( !m_handler )
00038       return false;
00039 
00040     //printf(">> SChannel::encrypt()\n");
00041     std::string data_copy = data;
00042 
00043     SecBuffer buffer[4];
00044     SecBufferDesc buffer_desc;
00045     DWORD cbIoBufferLength = m_sizes.cbHeader + m_sizes.cbMaximumMessage + m_sizes.cbTrailer;
00046 
00047     PBYTE e_iobuffer = static_cast<PBYTE>( LocalAlloc( LMEM_FIXED, cbIoBufferLength ) );
00048 
00049     if( e_iobuffer == NULL )
00050     {
00051       //printf("**** Out of memory (2)\n");
00052       cleanup();
00053       if( !m_secure )
00054         m_handler->handleHandshakeResult( this, false, m_certInfo );
00055       return false;
00056     }
00057     PBYTE e_message = e_iobuffer + m_sizes.cbHeader;
00058     do
00059     {
00060       const int size = data_copy.size() > m_sizes.cbMaximumMessage
00061                                   ? m_sizes.cbMaximumMessage
00062                                   : data_copy.size();
00063       memcpy( e_message, data_copy.data(), size );
00064       if( data_copy.size() > m_sizes.cbMaximumMessage )
00065         data_copy.erase( 0, m_sizes.cbMaximumMessage );
00066       else
00067         data_copy = "";
00068 
00069       buffer[0].pvBuffer     = e_iobuffer;
00070       buffer[0].cbBuffer     = m_sizes.cbHeader;
00071       buffer[0].BufferType   = SECBUFFER_STREAM_HEADER;
00072 
00073       buffer[1].pvBuffer     = e_message;
00074       buffer[1].cbBuffer     = size;
00075       buffer[1].BufferType   = SECBUFFER_DATA;
00076 
00077       buffer[2].pvBuffer     = static_cast<char*>(buffer[1].pvBuffer) + buffer[1].cbBuffer;
00078       buffer[2].cbBuffer     = m_sizes.cbTrailer;
00079       buffer[2].BufferType   = SECBUFFER_STREAM_TRAILER;
00080 
00081       buffer[3].BufferType   = SECBUFFER_EMPTY;
00082 
00083       buffer_desc.ulVersion       = SECBUFFER_VERSION;
00084       buffer_desc.cBuffers        = 4;
00085       buffer_desc.pBuffers        = buffer;
00086 
00087       SECURITY_STATUS e_status = EncryptMessage( &m_context, 0, &buffer_desc, 0 );
00088       if( SUCCEEDED( e_status ) )
00089       {
00090         std::string encrypted( reinterpret_cast<const char*>(e_iobuffer),
00091                                buffer[0].cbBuffer + buffer[1].cbBuffer + buffer[2].cbBuffer );
00092         m_handler->handleEncryptedData( this, encrypted );
00093         //if (data_copy.size() <= m_sizes.cbMaximumMessage) data_copy = "";
00094       }
00095       else
00096       {
00097         LocalFree( e_iobuffer );
00098         cleanup();
00099         if( !m_secure )
00100           m_handler->handleHandshakeResult( this, false, m_certInfo );
00101         return false;
00102       }
00103     }
00104     while( data_copy.size() > 0 );
00105     LocalFree( e_iobuffer );
00106     return true;
00107   }
00108 
00109   int SChannel::decrypt( const std::string& data )
00110   {
00111 
00112     if( !m_handler )
00113       return 0;
00114 
00115     //printf(">> SChannel::decrypt()\n");
00116     if( m_secure )
00117     {
00118       m_buffer += data;
00119 
00120       SecBuffer buffer[4];
00121       SecBufferDesc buffer_desc;
00122       DWORD cbIoBufferLength = m_sizes.cbHeader + m_sizes.cbMaximumMessage + m_sizes.cbTrailer;
00123 
00124       PBYTE e_iobuffer = static_cast<PBYTE>( LocalAlloc( LMEM_FIXED, cbIoBufferLength ) );
00125       if( e_iobuffer == NULL )
00126       {
00127         //printf("**** Out of memory (2)\n");
00128         cleanup();
00129         if( !m_secure )
00130           m_handler->handleHandshakeResult( this, false, m_certInfo );
00131         return 0;
00132       }
00133       SECURITY_STATUS e_status;
00134 
00135       // copy data chunk from tmp string into encryption memory buffer
00136       do
00137       {
00138         memcpy( e_iobuffer, m_buffer.data(), m_buffer.size() >
00139                cbIoBufferLength ? cbIoBufferLength : m_buffer.size() );
00140 
00141         buffer[0].pvBuffer     = e_iobuffer;
00142         buffer[0].cbBuffer     = m_buffer.size() > cbIoBufferLength ? cbIoBufferLength : m_buffer.size();
00143         buffer[0].BufferType   = SECBUFFER_DATA;
00144         buffer[1].cbBuffer = buffer[2].cbBuffer = buffer[3].cbBuffer = 0;
00145         buffer[1].BufferType = buffer[2].BufferType = buffer[3].BufferType  = SECBUFFER_EMPTY;
00146 
00147         buffer_desc.ulVersion       = SECBUFFER_VERSION;
00148         buffer_desc.cBuffers        = 4;
00149         buffer_desc.pBuffers        = buffer;
00150 
00151         unsigned long processed_data = buffer[0].cbBuffer;
00152         e_status = DecryptMessage( &m_context, &buffer_desc, 0, 0 );
00153 
00154         // print_error(e_status, "decrypt() ~ DecryptMessage()");
00155         // for (int n=0; n<4; n++)
00156         //     printf("buffer[%d].cbBuffer: %d   \t%d\n", n, buffer[n].cbBuffer, buffer[n].BufferType);
00157 
00158         // Locate data and (optional) extra buffers.
00159         SecBuffer* pDataBuffer  = NULL;
00160         SecBuffer* pExtraBuffer = NULL;
00161         for( int i = 1; i < 4; i++ )
00162         {
00163           if( pDataBuffer == NULL && buffer[i].BufferType == SECBUFFER_DATA )
00164           {
00165             pDataBuffer = &buffer[i];
00166             //printf("buffer[%d].BufferType = SECBUFFER_DATA\n",i);
00167           }
00168           if( pExtraBuffer == NULL && buffer[i].BufferType == SECBUFFER_EXTRA )
00169           {
00170             pExtraBuffer = &buffer[i];
00171           }
00172         }
00173         if( e_status == SEC_E_OK )
00174         {
00175           std::string decrypted( reinterpret_cast<const char*>( pDataBuffer->pvBuffer ),
00176                                  pDataBuffer->cbBuffer );
00177           m_handler->handleDecryptedData( this, decrypted );
00178           if( pExtraBuffer == NULL )
00179           {
00180             m_buffer.erase( 0, processed_data );
00181           }
00182           else
00183           {
00184             //std::cout << "m_buffer.size() = " << pExtraBuffer->cbBuffer << std::endl;
00185             m_buffer.erase( 0, m_buffer.size() - pExtraBuffer->cbBuffer );
00186             //std::cout << "m_buffer.size() = " << m_buffer.size() << std::endl;
00187           }
00188         }
00189         else if( e_status == SEC_E_INCOMPLETE_MESSAGE )
00190         {
00191           break;
00192         }
00193         else
00194         {
00195           //std::cout << "decrypt !!!ERROR!!!\n";
00196           cleanup();
00197           if( !m_secure )
00198             m_handler->handleHandshakeResult( this, false, m_certInfo );
00199           break;
00200         }
00201       }
00202       while( m_buffer.size() != 0 );
00203       LocalFree( e_iobuffer );
00204     }
00205     else
00206     {
00207       handshakeStage( data );
00208     }
00209     //printf("<< SChannel::decrypt()\n");
00210     return 0;
00211   }
00212 
00213   void SChannel::cleanup()
00214   {
00215     m_buffer = "";
00216     if( !m_cleanedup )
00217     {
00218       m_valid = false;
00219       m_secure = false;
00220       m_cleanedup = true;
00221       DeleteSecurityContext( &m_context );
00222       FreeCredentialsHandle( &m_credHandle );
00223     }
00224   }
00225 
00226   bool SChannel::handshake()
00227   {
00228     if( !m_handler )
00229       return false;
00230 
00231     //printf(">> SChannel::handshake()\n");
00232     SECURITY_STATUS error;
00233     ULONG return_flags;
00234     TimeStamp t;
00235     SecBuffer obuf[1];
00236     SecBufferDesc obufs;
00237     SCHANNEL_CRED tlscred;
00238     ULONG request = ISC_REQ_ALLOCATE_MEMORY
00239                     | ISC_REQ_CONFIDENTIALITY
00240                     | ISC_REQ_EXTENDED_ERROR
00241                     | ISC_REQ_INTEGRITY
00242                     | ISC_REQ_REPLAY_DETECT
00243                     | ISC_REQ_SEQUENCE_DETECT
00244                     | ISC_REQ_STREAM
00245                     | ISC_REQ_MANUAL_CRED_VALIDATION;
00246 
00247     /* initialize TLS credential */
00248     memset( &tlscred, 0, sizeof( SCHANNEL_CRED ) );
00249     tlscred.dwVersion = SCHANNEL_CRED_VERSION;
00250     tlscred.grbitEnabledProtocols = SP_PROT_TLS1;
00251     /* acquire credentials */
00252     error = AcquireCredentialsHandle( 0,
00253                                       UNISP_NAME,
00254                                       SECPKG_CRED_OUTBOUND,
00255                                       0,
00256                                       &tlscred,
00257                                       0,
00258                                       0,
00259                                       &m_credHandle,
00260                                       &t );
00261     //print_error(error, "handshake() ~ AcquireCredentialsHandle()");
00262     if( error != SEC_E_OK )
00263     {
00264       cleanup();
00265       m_handler->handleHandshakeResult( this, false, m_certInfo );
00266       return false;
00267     }
00268     else
00269     {
00270       /* initialize buffers */
00271       obuf[0].cbBuffer = 0;
00272       obuf[0].pvBuffer = 0;
00273       obuf[0].BufferType = SECBUFFER_TOKEN;
00274       /* initialize buffer descriptors */
00275       obufs.ulVersion = SECBUFFER_VERSION;
00276       obufs.cBuffers = 1;
00277       obufs.pBuffers = obuf;
00278       /* negotiate security */
00279       SEC_CHAR* hname = const_cast<char*>( m_server.c_str() );
00280 
00281       error = InitializeSecurityContext( &m_credHandle,
00282                                          0,
00283                                          hname,
00284                                          request,
00285                                          0,
00286                                          SECURITY_NETWORK_DREP,
00287                                          0,
00288                                          0,
00289                                          &m_context,
00290                                          &obufs,
00291                                          &return_flags,
00292                                          NULL );
00293       //print_error(error, "handshake() ~ InitializeSecurityContext()");
00294 
00295       if( error == SEC_I_CONTINUE_NEEDED )
00296       {
00297         m_cleanedup = false;
00298         //std::cout << "obuf[1].cbBuffer: " << obuf[0].cbBuffer << "\n";
00299         std::string senddata( static_cast<char*>(obuf[0].pvBuffer), obuf[0].cbBuffer );
00300         FreeContextBuffer( obuf[0].pvBuffer );
00301         m_handler->handleEncryptedData( this, senddata );
00302         return true;
00303       }
00304       else
00305       {
00306         cleanup();
00307         m_handler->handleHandshakeResult( this, false, m_certInfo );
00308         return false;
00309       }
00310     }
00311     return true;
00312   }
00313 
00314   void SChannel::handshakeStage( const std::string& data )
00315   {
00316     //printf(" >> handshake_stage\n");
00317     m_buffer += data;
00318 
00319     SECURITY_STATUS error;
00320     ULONG a;
00321     TimeStamp t;
00322     SecBuffer ibuf[2], obuf[1];
00323     SecBufferDesc ibufs, obufs;
00324     ULONG request = ISC_REQ_ALLOCATE_MEMORY
00325                     | ISC_REQ_CONFIDENTIALITY
00326                     | ISC_REQ_EXTENDED_ERROR
00327                     | ISC_REQ_INTEGRITY
00328                     | ISC_REQ_REPLAY_DETECT
00329                     | ISC_REQ_SEQUENCE_DETECT
00330                     | ISC_REQ_STREAM
00331                     | ISC_REQ_MANUAL_CRED_VALIDATION;
00332 
00333     SEC_CHAR* hname = const_cast<char*>( m_server.c_str() );
00334 
00335     do
00336     {
00337       /* initialize buffers */
00338       ibuf[0].cbBuffer = m_buffer.size();
00339       ibuf[0].pvBuffer = static_cast<void*>( const_cast<char*>( m_buffer.c_str() ) );
00340       //std::cout << "Size: " << m_buffer.size() << "\n";
00341       ibuf[1].cbBuffer = 0;
00342       ibuf[1].pvBuffer = 0;
00343       obuf[0].cbBuffer = 0;
00344       obuf[0].pvBuffer = 0;
00345 
00346       ibuf[0].BufferType = SECBUFFER_TOKEN;
00347       ibuf[1].BufferType = SECBUFFER_EMPTY;
00348       obuf[0].BufferType = SECBUFFER_EMPTY;
00349       /* initialize buffer descriptors */
00350       ibufs.ulVersion = obufs.ulVersion = SECBUFFER_VERSION;
00351       ibufs.cBuffers = 2;
00352       obufs.cBuffers = 1;
00353       ibufs.pBuffers = ibuf;
00354       obufs.pBuffers = obuf;
00355 
00356       /*
00357        * std::cout << "obuf[0].cbBuffer: " << obuf[0].cbBuffer << "\t" << obuf[0].BufferType << "\n";
00358        * std::cout << "ibuf[0].cbBuffer: " << ibuf[0].cbBuffer << "\t" << ibuf[0].BufferType << "\n";
00359        * std::cout << "ibuf[1].cbBuffer: " << ibuf[1].cbBuffer << "\t" << ibuf[1].BufferType << "\n";
00360        */
00361 
00362       /* negotiate security */
00363       error = InitializeSecurityContext( &m_credHandle,
00364                                          &m_context,
00365                                          hname,
00366                                          request,
00367                                          0,
00368                                          0,
00369                                          &ibufs,
00370                                          0,
00371                                          0,
00372                                          &obufs,
00373                                          &a,
00374                                          &t );
00375       //print_error(error, "handshake() ~ InitializeSecurityContext()");
00376       if( error == SEC_E_OK )
00377       {
00378         // EXTRA STUFF??
00379         if( ibuf[1].BufferType == SECBUFFER_EXTRA )
00380         {
00381           m_buffer.erase( 0, m_buffer.size() - ibuf[1].cbBuffer );
00382         }
00383         else
00384         {
00385           m_buffer = "";
00386         }
00387         setSizes();
00388         setCertinfos();
00389 
00390         m_secure = true;
00391         m_handler->handleHandshakeResult( this, true, m_certInfo );
00392         break;
00393       }
00394       else if( error == SEC_I_CONTINUE_NEEDED )
00395       {
00396         /*
00397          * std::cout << "obuf[0].cbBuffer: " << obuf[0].cbBuffer << "\t" << obuf[0].BufferType << "\n";
00398          * std::cout << "ibuf[0].cbBuffer: " << ibuf[0].cbBuffer << "\t" << ibuf[0].BufferType << "\n";
00399          * std::cout << "ibuf[1].cbBuffer: " << ibuf[1].cbBuffer << "\t" << ibuf[1].BufferType << "\n";
00400          */
00401 
00402         // STUFF TO SEND??
00403         if( obuf[0].cbBuffer != 0 && obuf[0].pvBuffer != NULL )
00404         {
00405           std::string senddata( static_cast<char*>(obuf[0].pvBuffer), obuf[0].cbBuffer );
00406           FreeContextBuffer( obuf[0].pvBuffer );
00407           m_handler->handleEncryptedData( this, senddata );
00408         }
00409         // EXTRA STUFF??
00410         if( ibuf[1].BufferType == SECBUFFER_EXTRA )
00411         {
00412           m_buffer.erase( 0, m_buffer.size() - ibuf[1].cbBuffer );
00413         }
00414         else
00415         {
00416           m_buffer = "";
00417         }
00418         return;
00419       }
00420       else if( error == SEC_I_INCOMPLETE_CREDENTIALS )
00421       {
00422         handshakeStage( "" );
00423       }
00424       else if( error == SEC_E_INCOMPLETE_MESSAGE )
00425       {
00426         break;
00427       }
00428       else
00429       {
00430         cleanup();
00431         m_handler->handleHandshakeResult( this, false, m_certInfo );
00432         break;
00433       }
00434     }
00435     while( true );
00436   }
00437 
00438   void SChannel::setCACerts( const StringList& cacerts ) {}
00439 
00440   void SChannel::setClientCert( const std::string& clientKey, const std::string& clientCerts ) {}
00441 
00442   void SChannel::setSizes()
00443   {
00444     if( QueryContextAttributes( &m_context, SECPKG_ATTR_STREAM_SIZES, &m_sizes ) == SEC_E_OK )
00445     {
00446       //std::cout << "set_sizes success\n";
00447     }
00448     else
00449     {
00450       //std::cout << "set_sizes no success\n";
00451       cleanup();
00452       m_handler->handleHandshakeResult( this, false, m_certInfo );
00453     }
00454   }
00455 
00456   int SChannel::filetime2int( FILETIME t )
00457   {
00458     SYSTEMTIME stUTC;
00459     FileTimeToSystemTime(&t, &stUTC);
00460     std::tm ts;
00461     ts.tm_year = stUTC.wYear - 1900;
00462     ts.tm_mon = stUTC.wMonth - 1;
00463     ts.tm_mday = stUTC.wDay;
00464     ts.tm_hour = stUTC.wHour;
00465     ts.tm_min = stUTC.wMinute;
00466     ts.tm_sec = stUTC.wSecond;
00467 
00468     int unixtime;
00469     if ( (unixtime = mktime(&ts)) == -1 )
00470       unixtime = 0;
00471     return unixtime;
00472   }
00473 
00474   void SChannel::validateCert()
00475   {
00476     bool valid = false;
00477     HTTPSPolicyCallbackData policyHTTPS;
00478     CERT_CHAIN_POLICY_PARA policyParameter;
00479     CERT_CHAIN_POLICY_STATUS policyStatus;
00480 
00481     PCCERT_CONTEXT remoteCertContext = NULL;
00482     PCCERT_CHAIN_CONTEXT chainContext = NULL;
00483     CERT_CHAIN_PARA chainParameter;
00484     PSTR serverName = const_cast<char*>( m_server.c_str() );
00485 
00486     PWSTR uServerName = NULL;
00487     DWORD csizeServerName;
00488 
00489     LPSTR Usages[] = {
00490       szOID_PKIX_KP_SERVER_AUTH,
00491       szOID_SERVER_GATED_CRYPTO,
00492       szOID_SGC_NETSCAPE
00493     };
00494     DWORD cUsages = sizeof( Usages ) / sizeof( LPSTR );
00495 
00496     do
00497     {
00498       // Get server's certificate.
00499       if( QueryContextAttributes( &m_context, SECPKG_ATTR_REMOTE_CERT_CONTEXT,
00500                                   (PVOID)&remoteCertContext ) != SEC_E_OK )
00501       {
00502         //printf("Error querying remote certificate\n");
00503         // !!! THROW SOME ERROR
00504         break;
00505       }
00506 
00507       // unicode conversation
00508       // calculating unicode server name size
00509       csizeServerName = MultiByteToWideChar( CP_ACP, 0, serverName, -1, NULL, 0 );
00510       uServerName = reinterpret_cast<WCHAR *>( LocalAlloc( LMEM_FIXED,
00511                                                              csizeServerName * sizeof( WCHAR ) ) );
00512       if( uServerName == NULL )
00513       {
00514         //printf("SEC_E_INSUFFICIENT_MEMORY ~ Not enough memory!!!\n");
00515         break;
00516       }
00517 
00518       // convert into unicode
00519       csizeServerName = MultiByteToWideChar( CP_ACP, 0, serverName, -1, uServerName, csizeServerName );
00520       if( csizeServerName == 0 )
00521       {
00522         //printf("SEC_E_WRONG_PRINCIPAL\n");
00523         break;
00524       }
00525 
00526       // create the chain
00527       ZeroMemory( &chainParameter, sizeof( chainParameter ) );
00528       chainParameter.cbSize = sizeof( chainParameter );
00529       chainParameter.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
00530       chainParameter.RequestedUsage.Usage.cUsageIdentifier     = cUsages;
00531       chainParameter.RequestedUsage.Usage.rgpszUsageIdentifier = Usages;
00532 
00533       if( !CertGetCertificateChain( NULL, remoteCertContext, NULL, remoteCertContext->hCertStore,
00534                                     &chainParameter, 0, NULL, &chainContext ) )
00535       {
00536         DWORD status = GetLastError();
00537         //printf("Error 0x%x returned by CertGetCertificateChain!!!\n", status);
00538         break;
00539       }
00540 
00541       // validate the chain
00542       ZeroMemory( &policyHTTPS, sizeof( HTTPSPolicyCallbackData ) );
00543       policyHTTPS.cbStruct           = sizeof( HTTPSPolicyCallbackData );
00544       policyHTTPS.dwAuthType         = AUTHTYPE_SERVER;
00545       policyHTTPS.fdwChecks          = 0;
00546       policyHTTPS.pwszServerName     = uServerName;
00547 
00548       memset( &policyParameter, 0, sizeof( policyParameter ) );
00549       policyParameter.cbSize            = sizeof( policyParameter );
00550       policyParameter.pvExtraPolicyPara = &policyHTTPS;
00551 
00552       memset( &policyStatus, 0, sizeof( policyStatus ) );
00553       policyStatus.cbSize = sizeof( policyStatus );
00554 
00555       if( !CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_SSL, chainContext, &policyParameter,
00556                                              &policyStatus ) )
00557       {
00558         DWORD status = GetLastError();
00559         //printf("Error 0x%x returned by CertVerifyCertificateChainPolicy!!!\n", status);
00560         break;
00561       }
00562 
00563       if( policyStatus.dwError )
00564       {
00565         //printf("Trust Error!!!}n");
00566         break;
00567       }
00568       valid = true;
00569     }
00570     while( false );
00571     // cleanup
00572     if( chainContext ) CertFreeCertificateChain( chainContext );
00573     m_certInfo.chain = valid;
00574   }
00575 
00576   void SChannel::connectionInfos()
00577   {
00578     SecPkgContext_ConnectionInfo conn_info;
00579 
00580     memset( &conn_info, 0, sizeof( conn_info ) );
00581 
00582     if( QueryContextAttributes( &m_context, SECPKG_ATTR_CONNECTION_INFO, &conn_info ) == SEC_E_OK )
00583     {
00584       switch( conn_info.dwProtocol )
00585       {
00586         case SP_PROT_TLS1_CLIENT:
00587           m_certInfo.protocol = "TLSv1";
00588           break;
00589         case SP_PROT_SSL3_CLIENT:
00590           m_certInfo.protocol = "SSLv3";
00591           break;
00592         default:
00593           m_certInfo.protocol = "unknown";
00594       }
00595 
00596       switch( conn_info.aiCipher )
00597       {
00598         case CALG_3DES:
00599           m_certInfo.cipher = "3DES";
00600           break;
00601         case CALG_AES_128:
00602           m_certInfo.cipher = "AES_128";
00603           break;
00604         case CALG_AES_256:
00605           m_certInfo.cipher = "AES_256";
00606           break;
00607         case CALG_DES:
00608           m_certInfo.cipher = "DES";
00609           break;
00610         case CALG_RC2:
00611           m_certInfo.cipher = "RC2";
00612           break;
00613         case CALG_RC4:
00614           m_certInfo.cipher = "RC4";
00615           break;
00616         default:
00617           m_certInfo.cipher = "";
00618       }
00619 
00620       switch( conn_info.aiHash )
00621       {
00622         case CALG_MD5:
00623           m_certInfo.mac = "MD5";
00624           break;
00625         case CALG_SHA:
00626           m_certInfo.mac = "SHA";
00627           break;
00628         default:
00629           m_certInfo.mac = "";
00630       }
00631     }
00632   }
00633 
00634   void SChannel::certData()
00635   {
00636     PCCERT_CONTEXT remoteCertContext = NULL;
00637     CHAR certString[1000];
00638 
00639     // getting server's certificate
00640     if( QueryContextAttributes( &m_context, SECPKG_ATTR_REMOTE_CERT_CONTEXT,
00641                                 (PVOID)&remoteCertContext ) != SEC_E_OK )
00642     {
00643       return;
00644     }
00645 
00646     // setting certificat's lifespan
00647     m_certInfo.date_from = filetime2int( remoteCertContext->pCertInfo->NotBefore );
00648     m_certInfo.date_to = filetime2int( remoteCertContext->pCertInfo->NotAfter );
00649 
00650     if( !CertNameToStr( remoteCertContext->dwCertEncodingType,
00651                         &remoteCertContext->pCertInfo->Subject,
00652                         CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
00653                         certString, sizeof( certString ) ) )
00654     {
00655       return;
00656     }
00657     m_certInfo.server = certString;
00658 
00659     if( !CertNameToStr( remoteCertContext->dwCertEncodingType,
00660                        &remoteCertContext->pCertInfo->Issuer,
00661                        CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
00662                        certString, sizeof( certString ) ) )
00663     {
00664       return;
00665     }
00666     m_certInfo.issuer = certString;
00667   }
00668 
00669   void SChannel::setCertinfos()
00670   {
00671     validateCert();
00672     connectionInfos();
00673     certData();
00674   }
00675 
00676 #if 0
00677   void SChannel::print_error( int errorcode, const char* place )
00678   {
00679     printf( "Win error at %s.\n", place );
00680     switch( errorcode )
00681     {
00682       case SEC_E_OK:
00683         printf( "\tValue:\tSEC_E_OK\n" );
00684         printf( "\tDesc:\tNot really an error. Everything is fine.\n" );
00685         break;
00686       case SEC_E_INSUFFICIENT_MEMORY:
00687         printf( "\tValue:\tSEC_E_INSUFFICIENT_MEMORY\n" );
00688         printf( "\tDesc:\tThere is not enough memory available to complete the requested action.\n" );
00689         break;
00690       case SEC_E_INTERNAL_ERROR:
00691         printf( "\tValue:\tSEC_E_INTERNAL_ERROR\n" );
00692         printf( "\tDesc:\tAn error occurred that did not map to an SSPI error code.\n" );
00693         break;
00694       case SEC_E_NO_CREDENTIALS:
00695         printf( "\tValue:\tSEC_E_NO_CREDENTIALS\n" );
00696         printf( "\tDesc:\tNo credentials are available in the security package.\n" );
00697         break;
00698       case SEC_E_NOT_OWNER:
00699         printf( "\tValue:\tSEC_E_NOT_OWNER\n" );
00700         printf( "\tDesc:\tThe caller of the function does not have the necessary credentials.\n" );
00701         break;
00702       case SEC_E_SECPKG_NOT_FOUND:
00703         printf( "\tValue:\tSEC_E_SECPKG_NOT_FOUND\n" );
00704         printf( "\tDesc:\tThe requested security package does not exist. \n" );
00705         break;
00706       case SEC_E_UNKNOWN_CREDENTIALS:
00707         printf( "\tValue:\tSEC_E_UNKNOWN_CREDENTIALS\n" );
00708         printf( "\tDesc:\tThe credentials supplied to the package were not recognized.\n" );
00709         break;
00710       case SEC_E_INCOMPLETE_MESSAGE:
00711         printf( "\tValue:\tSEC_E_INCOMPLETE_MESSAGE\n" );
00712         printf( "\tDesc:\tData for the whole message was not read from the wire.\n" );
00713         break;
00714       case SEC_E_INVALID_HANDLE:
00715         printf( "\tValue:\tSEC_E_INVALID_HANDLE\n" );
00716         printf( "\tDesc:\tThe handle passed to the function is invalid.\n" );
00717         break;
00718       case SEC_E_INVALID_TOKEN:
00719         printf( "\tValue:\tSEC_E_INVALID_TOKEN\n" );
00720         printf( "\tDesc:\tThe error is due to a malformed input token, such as a token "
00721                 "corrupted in transit...\n" );
00722         break;
00723       case SEC_E_LOGON_DENIED:
00724         printf( "\tValue:\tSEC_E_LOGON_DENIED\n" );
00725         printf( "\tDesc:\tThe logon failed.\n" );
00726         break;
00727       case SEC_E_NO_AUTHENTICATING_AUTHORITY:
00728         printf( "\tValue:\tSEC_E_NO_AUTHENTICATING_AUTHORITY\n" );
00729         printf( "\tDesc:\tNo authority could be contacted for authentication...\n" );
00730         break;
00731       case SEC_E_TARGET_UNKNOWN:
00732         printf( "\tValue:\tSEC_E_TARGET_UNKNOWN\n" );
00733         printf( "\tDesc:\tThe target was not recognized.\n" );
00734         break;
00735       case SEC_E_UNSUPPORTED_FUNCTION:
00736         printf( "\tValue:\tSEC_E_UNSUPPORTED_FUNCTION\n" );
00737         printf( "\tDesc:\tAn invalid context attribute flag (ISC_REQ_DELEGATE or "
00738                 "ISC_REQ_PROMPT_FOR_CREDS)...\n" );
00739         break;
00740       case SEC_E_WRONG_PRINCIPAL:
00741         printf( "\tValue:\tSEC_E_WRONG_PRINCIPAL\n" );
00742         printf( "\tDesc:\tThe principal that received the authentication request "
00743                 "is not the same as the...\n" );
00744         break;
00745       case SEC_I_COMPLETE_AND_CONTINUE:
00746         printf( "\tValue:\tSEC_I_COMPLETE_AND_CONTINUE\n" );
00747         printf( "\tDesc:\tThe client must call CompleteAuthToken and then pass the output...\n" );
00748         break;
00749       case SEC_I_COMPLETE_NEEDED:
00750         printf( "\tValue:\tSEC_I_COMPLETE_NEEDED\n" );
00751         printf( "\tDesc:\tThe client must finish building the message and then "
00752                 "call the CompleteAuthToken function.\n" );
00753         break;
00754       case SEC_I_CONTINUE_NEEDED:
00755         printf( "\tValue:\tSEC_I_CONTINUE_NEEDED\n" );
00756         printf( "\tDesc:\tThe client must send the output token to the server "
00757                 "and wait for a return token...\n" );
00758         break;
00759       case SEC_I_INCOMPLETE_CREDENTIALS:
00760         printf( "\tValue:\tSEC_I_INCOMPLETE_CREDENTIALS\n" );
00761         printf( "\tDesc:\tThe server has requested client authentication, "
00762                 "and the supplied credentials either...\n" );
00763         break;
00764       default:
00765         printf( "\tValue:\t%d\n", errorcode );
00766         printf( "\tDesc:\tUnknown error code.\n" );
00767     }
00768   }
00769 #endif
00770 
00771 }
00772 
00773 #endif // HAVE_WINTLS

Generated on Fri Oct 10 15:26:12 2008 for gloox by  doxygen 1.5.6