tlsschannel.cpp

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

Generated by  doxygen 1.6.2