tlsschannel.cpp

00001 /*
00002  * Copyright (c) 2007 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     if( !m_cleanedup )
00216     {
00217       m_valid = false;
00218       m_secure = false;
00219       DeleteSecurityContext( &m_context );
00220       FreeCredentialsHandle( &m_credHandle );
00221     }
00222   }
00223 
00224   bool SChannel::handshake()
00225   {
00226     if( !m_handler )
00227       return false;
00228 
00229     //printf(">> SChannel::handshake()\n");
00230     SECURITY_STATUS error;
00231     ULONG return_flags;
00232     TimeStamp t;
00233     SecBuffer obuf[1];
00234     SecBufferDesc obufs;
00235     SCHANNEL_CRED tlscred;
00236     ULONG request = ISC_REQ_ALLOCATE_MEMORY
00237                     | ISC_REQ_CONFIDENTIALITY
00238                     | ISC_REQ_EXTENDED_ERROR
00239                     | ISC_REQ_INTEGRITY
00240                     | ISC_REQ_REPLAY_DETECT
00241                     | ISC_REQ_SEQUENCE_DETECT
00242                     | ISC_REQ_STREAM
00243                     | ISC_REQ_MANUAL_CRED_VALIDATION;
00244 
00245     /* initialize TLS credential */
00246     memset( &tlscred, 0, sizeof( SCHANNEL_CRED ) );
00247     tlscred.dwVersion = SCHANNEL_CRED_VERSION;
00248     tlscred.grbitEnabledProtocols = SP_PROT_TLS1;
00249     /* acquire credentials */
00250     error = AcquireCredentialsHandle( 0,
00251                                       UNISP_NAME,
00252                                       SECPKG_CRED_OUTBOUND,
00253                                       0,
00254                                       &tlscred,
00255                                       0,
00256                                       0,
00257                                       &m_credHandle,
00258                                       &t );
00259     //print_error(error, "handshake() ~ AcquireCredentialsHandle()");
00260     if( error != SEC_E_OK )
00261     {
00262       cleanup();
00263       m_handler->handleHandshakeResult( this, false, m_certInfo );
00264       return false;
00265     }
00266     else
00267     {
00268       /* initialize buffers */
00269       obuf[0].cbBuffer = 0;
00270       obuf[0].pvBuffer = 0;
00271       obuf[0].BufferType = SECBUFFER_TOKEN;
00272       /* initialize buffer descriptors */
00273       obufs.ulVersion = SECBUFFER_VERSION;
00274       obufs.cBuffers = 1;
00275       obufs.pBuffers = obuf;
00276       /* negotiate security */
00277       SEC_CHAR* hname = const_cast<char*>( m_server.c_str() );
00278 
00279       error = InitializeSecurityContext( &m_credHandle,
00280                                          0,
00281                                          hname,
00282                                          request,
00283                                          0,
00284                                          SECURITY_NETWORK_DREP,
00285                                          0,
00286                                          0,
00287                                          &m_context,
00288                                          &obufs,
00289                                          &return_flags,
00290                                          NULL );
00291       //print_error(error, "handshake() ~ InitializeSecurityContext()");
00292 
00293       if( error == SEC_I_CONTINUE_NEEDED )
00294       {
00295         m_cleanedup = false;
00296         //std::cout << "obuf[1].cbBuffer: " << obuf[0].cbBuffer << "\n";
00297         std::string senddata( static_cast<char*>(obuf[0].pvBuffer), obuf[0].cbBuffer );
00298         FreeContextBuffer( obuf[0].pvBuffer );
00299         m_handler->handleEncryptedData( this, senddata );
00300         return true;
00301       }
00302       else
00303       {
00304         cleanup();
00305         m_handler->handleHandshakeResult( this, false, m_certInfo );
00306         return false;
00307       }
00308     }
00309     return true;
00310   }
00311 
00312   void SChannel::handshakeStage( const std::string& data )
00313   {
00314     //printf(" >> handshake_stage\n");
00315     m_buffer += data;
00316 
00317     SECURITY_STATUS error;
00318     ULONG a;
00319     TimeStamp t;
00320     SecBuffer ibuf[2], obuf[1];
00321     SecBufferDesc ibufs, obufs;
00322     ULONG request = ISC_REQ_ALLOCATE_MEMORY
00323                     | ISC_REQ_CONFIDENTIALITY
00324                     | ISC_REQ_EXTENDED_ERROR
00325                     | ISC_REQ_INTEGRITY
00326                     | ISC_REQ_REPLAY_DETECT
00327                     | ISC_REQ_SEQUENCE_DETECT
00328                     | ISC_REQ_STREAM
00329                     | ISC_REQ_MANUAL_CRED_VALIDATION;
00330 
00331     SEC_CHAR* hname = const_cast<char*>( m_server.c_str() );
00332 
00333     do
00334     {
00335       /* initialize buffers */
00336       ibuf[0].cbBuffer = m_buffer.size();
00337       ibuf[0].pvBuffer = static_cast<void*>( const_cast<char*>( m_buffer.c_str() ) );
00338       //std::cout << "Size: " << m_buffer.size() << "\n";
00339       ibuf[1].cbBuffer = 0;
00340       ibuf[1].pvBuffer = 0;
00341       obuf[0].cbBuffer = 0;
00342       obuf[0].pvBuffer = 0;
00343 
00344       ibuf[0].BufferType = SECBUFFER_TOKEN;
00345       ibuf[1].BufferType = SECBUFFER_EMPTY;
00346       obuf[0].BufferType = SECBUFFER_EMPTY;
00347       /* initialize buffer descriptors */
00348       ibufs.ulVersion = obufs.ulVersion = SECBUFFER_VERSION;
00349       ibufs.cBuffers = 2;
00350       obufs.cBuffers = 1;
00351       ibufs.pBuffers = ibuf;
00352       obufs.pBuffers = obuf;
00353 
00354       /*
00355        * std::cout << "obuf[0].cbBuffer: " << obuf[0].cbBuffer << "\t" << obuf[0].BufferType << "\n";
00356        * std::cout << "ibuf[0].cbBuffer: " << ibuf[0].cbBuffer << "\t" << ibuf[0].BufferType << "\n";
00357        * std::cout << "ibuf[1].cbBuffer: " << ibuf[1].cbBuffer << "\t" << ibuf[1].BufferType << "\n";
00358        */
00359 
00360       /* negotiate security */
00361       error = InitializeSecurityContext( &m_credHandle,
00362                                          &m_context,
00363                                          hname,
00364                                          request,
00365                                          0,
00366                                          0,
00367                                          &ibufs,
00368                                          0,
00369                                          0,
00370                                          &obufs,
00371                                          &a,
00372                                          &t );
00373       //print_error(error, "handshake() ~ InitializeSecurityContext()");
00374       if( error == SEC_E_OK )
00375       {
00376         // EXTRA STUFF??
00377         if( ibuf[1].BufferType == SECBUFFER_EXTRA )
00378         {
00379           m_buffer.erase( 0, m_buffer.size() - ibuf[1].cbBuffer );
00380         }
00381         else
00382         {
00383           m_buffer = "";
00384         }
00385         setSizes();
00386         setCertinfos();
00387 
00388         m_secure = true;
00389         m_handler->handleHandshakeResult( this, true, m_certInfo );
00390         break;
00391       }
00392       else if( error == SEC_I_CONTINUE_NEEDED )
00393       {
00394         /*
00395          * std::cout << "obuf[0].cbBuffer: " << obuf[0].cbBuffer << "\t" << obuf[0].BufferType << "\n";
00396          * std::cout << "ibuf[0].cbBuffer: " << ibuf[0].cbBuffer << "\t" << ibuf[0].BufferType << "\n";
00397          * std::cout << "ibuf[1].cbBuffer: " << ibuf[1].cbBuffer << "\t" << ibuf[1].BufferType << "\n";
00398          */
00399 
00400         // STUFF TO SEND??
00401         if( obuf[0].cbBuffer != 0 && obuf[0].pvBuffer != NULL )
00402         {
00403           std::string senddata( static_cast<char*>(obuf[0].pvBuffer), obuf[0].cbBuffer );
00404           FreeContextBuffer( obuf[0].pvBuffer );
00405           m_handler->handleEncryptedData( this, senddata );
00406         }
00407         // EXTRA STUFF??
00408         if( ibuf[1].BufferType == SECBUFFER_EXTRA )
00409         {
00410           m_buffer.erase( 0, m_buffer.size() - ibuf[1].cbBuffer );
00411         }
00412         else
00413         {
00414           m_buffer = "";
00415         }
00416         return;
00417       }
00418       else if( error == SEC_I_INCOMPLETE_CREDENTIALS )
00419       {
00420         handshakeStage( "" );
00421       }
00422       else if( error == SEC_E_INCOMPLETE_MESSAGE )
00423       {
00424         break;
00425       }
00426       else
00427       {
00428         cleanup();
00429         m_handler->handleHandshakeResult( this, false, m_certInfo );
00430         break;
00431       }
00432     }
00433     while( true );
00434   }
00435 
00436   void SChannel::setCACerts( const StringList& cacerts ) {}
00437 
00438   void SChannel::setClientCert( const std::string& clientKey, const std::string& clientCerts ) {}
00439 
00440   void SChannel::setSizes()
00441   {
00442     if( QueryContextAttributes( &m_context, SECPKG_ATTR_STREAM_SIZES, &m_sizes ) == SEC_E_OK )
00443     {
00444       //std::cout << "set_sizes success\n";
00445     }
00446     else
00447     {
00448       //std::cout << "set_sizes no success\n";
00449       cleanup();
00450       m_handler->handleHandshakeResult( this, false, m_certInfo );
00451     }
00452   }
00453 
00454   int SChannel::filetime2int( FILETIME t )
00455   {
00456     SYSTEMTIME stUTC;
00457     FileTimeToSystemTime(&t, &stUTC);
00458     std::tm ts;
00459     ts.tm_year = stUTC.wYear - 1900;
00460     ts.tm_mon = stUTC.wMonth - 1;
00461     ts.tm_mday = stUTC.wDay;
00462     ts.tm_hour = stUTC.wHour;
00463     ts.tm_min = stUTC.wMinute;
00464     ts.tm_sec = stUTC.wSecond;
00465 
00466     int unixtime;
00467     if ( (unixtime = mktime(&ts)) == -1 )
00468       unixtime = 0;
00469     return unixtime;
00470   }
00471 
00472   void SChannel::validateCert()
00473   {
00474     bool valid = false;
00475     HTTPSPolicyCallbackData policyHTTPS;
00476     CERT_CHAIN_POLICY_PARA policyParameter;
00477     CERT_CHAIN_POLICY_STATUS policyStatus;
00478 
00479     PCCERT_CONTEXT remoteCertContext = NULL;
00480     PCCERT_CHAIN_CONTEXT chainContext = NULL;
00481     CERT_CHAIN_PARA chainParameter;
00482     PSTR serverName = const_cast<char*>( m_server.c_str() );
00483 
00484     PWSTR uServerName = NULL;
00485     DWORD csizeServerName;
00486 
00487     LPSTR Usages[] = {
00488       szOID_PKIX_KP_SERVER_AUTH,
00489       szOID_SERVER_GATED_CRYPTO,
00490       szOID_SGC_NETSCAPE
00491     };
00492     DWORD cUsages = sizeof( Usages ) / sizeof( LPSTR );
00493 
00494     do
00495     {
00496       // Get server's certificate.
00497       if( QueryContextAttributes( &m_context, SECPKG_ATTR_REMOTE_CERT_CONTEXT,
00498                                   (PVOID)&remoteCertContext ) != SEC_E_OK )
00499       {
00500         //printf("Error querying remote certificate\n");
00501         // !!! THROW SOME ERROR
00502         break;
00503       }
00504 
00505       // unicode conversation
00506       // calculating unicode server name size
00507       csizeServerName = MultiByteToWideChar( CP_ACP, 0, serverName, -1, NULL, 0 );
00508       uServerName = reinterpret_cast<WCHAR *>( LocalAlloc( LMEM_FIXED,
00509                                                              csizeServerName * sizeof( WCHAR ) ) );
00510       if( uServerName == NULL )
00511       {
00512         //printf("SEC_E_INSUFFICIENT_MEMORY ~ Not enough memory!!!\n");
00513         break;
00514       }
00515 
00516       // convert into unicode
00517       csizeServerName = MultiByteToWideChar( CP_ACP, 0, serverName, -1, uServerName, csizeServerName );
00518       if( csizeServerName == 0 )
00519       {
00520         //printf("SEC_E_WRONG_PRINCIPAL\n");
00521         break;
00522       }
00523 
00524       // create the chain
00525       ZeroMemory( &chainParameter, sizeof( chainParameter ) );
00526       chainParameter.cbSize = sizeof( chainParameter );
00527       chainParameter.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;
00528       chainParameter.RequestedUsage.Usage.cUsageIdentifier     = cUsages;
00529       chainParameter.RequestedUsage.Usage.rgpszUsageIdentifier = Usages;
00530 
00531       if( !CertGetCertificateChain( NULL, remoteCertContext, NULL, remoteCertContext->hCertStore,
00532                                     &chainParameter, 0, NULL, &chainContext ) )
00533       {
00534         DWORD status = GetLastError();
00535         //printf("Error 0x%x returned by CertGetCertificateChain!!!\n", status);
00536         break;
00537       }
00538 
00539       // validate the chain
00540       ZeroMemory( &policyHTTPS, sizeof( HTTPSPolicyCallbackData ) );
00541       policyHTTPS.cbStruct           = sizeof( HTTPSPolicyCallbackData );
00542       policyHTTPS.dwAuthType         = AUTHTYPE_SERVER;
00543       policyHTTPS.fdwChecks          = 0;
00544       policyHTTPS.pwszServerName     = uServerName;
00545 
00546       memset( &policyParameter, 0, sizeof( policyParameter ) );
00547       policyParameter.cbSize            = sizeof( policyParameter );
00548       policyParameter.pvExtraPolicyPara = &policyHTTPS;
00549 
00550       memset( &policyStatus, 0, sizeof( policyStatus ) );
00551       policyStatus.cbSize = sizeof( policyStatus );
00552 
00553       if( !CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_SSL, chainContext, &policyParameter,
00554                                              &policyStatus ) )
00555       {
00556         DWORD status = GetLastError();
00557         //printf("Error 0x%x returned by CertVerifyCertificateChainPolicy!!!\n", status);
00558         break;
00559       }
00560 
00561       if( policyStatus.dwError )
00562       {
00563         //printf("Trust Error!!!}n");
00564         break;
00565       }
00566       valid = true;
00567     }
00568     while( false );
00569     // cleanup
00570     if( chainContext ) CertFreeCertificateChain( chainContext );
00571     m_certInfo.chain = valid;
00572   }
00573 
00574   void SChannel::connectionInfos()
00575   {
00576     SecPkgContext_ConnectionInfo conn_info;
00577 
00578     memset( &conn_info, 0, sizeof( conn_info ) );
00579 
00580     if( QueryContextAttributes( &m_context, SECPKG_ATTR_CONNECTION_INFO, &conn_info ) == SEC_E_OK )
00581     {
00582       switch( conn_info.dwProtocol )
00583       {
00584         case SP_PROT_TLS1_CLIENT:
00585           m_certInfo.protocol = "TLSv1";
00586           break;
00587         case SP_PROT_SSL3_CLIENT:
00588           m_certInfo.protocol = "SSLv3";
00589           break;
00590         default:
00591           m_certInfo.protocol = "unknown";
00592       }
00593 
00594       switch( conn_info.aiCipher )
00595       {
00596         case CALG_3DES:
00597           m_certInfo.cipher = "3DES";
00598           break;
00599         case CALG_AES_128:
00600           m_certInfo.cipher = "AES_128";
00601           break;
00602         case CALG_AES_256:
00603           m_certInfo.cipher = "AES_256";
00604           break;
00605         case CALG_DES:
00606           m_certInfo.cipher = "DES";
00607           break;
00608         case CALG_RC2:
00609           m_certInfo.cipher = "RC2";
00610           break;
00611         case CALG_RC4:
00612           m_certInfo.cipher = "RC4";
00613           break;
00614         default:
00615           m_certInfo.cipher = "";
00616       }
00617 
00618       switch( conn_info.aiHash )
00619       {
00620         case CALG_MD5:
00621           m_certInfo.mac = "MD5";
00622           break;
00623         case CALG_SHA:
00624           m_certInfo.mac = "SHA";
00625           break;
00626         default:
00627           m_certInfo.mac = "";
00628       }
00629     }
00630   }
00631 
00632   void SChannel::certData()
00633   {
00634     PCCERT_CONTEXT remoteCertContext = NULL;
00635     CHAR certString[1000];
00636 
00637     // getting server's certificate
00638     if( QueryContextAttributes( &m_context, SECPKG_ATTR_REMOTE_CERT_CONTEXT,
00639                                 (PVOID)&remoteCertContext ) != SEC_E_OK )
00640     {
00641       return;
00642     }
00643 
00644     // setting certificat's lifespan
00645     m_certInfo.date_from = filetime2int( remoteCertContext->pCertInfo->NotBefore );
00646     m_certInfo.date_to = filetime2int( remoteCertContext->pCertInfo->NotAfter );
00647 
00648     if( !CertNameToStr( remoteCertContext->dwCertEncodingType,
00649                         &remoteCertContext->pCertInfo->Subject,
00650                         CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
00651                         certString, sizeof( certString ) ) )
00652     {
00653       return;
00654     }
00655     m_certInfo.server = certString;
00656 
00657     if( !CertNameToStr( remoteCertContext->dwCertEncodingType,
00658                        &remoteCertContext->pCertInfo->Issuer,
00659                        CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG,
00660                        certString, sizeof( certString ) ) )
00661     {
00662       return;
00663     }
00664     m_certInfo.issuer = certString;
00665   }
00666 
00667   void SChannel::setCertinfos()
00668   {
00669     validateCert();
00670     connectionInfos();
00671     certData();
00672   }
00673 
00674 #if 0
00675   void SChannel::print_error( int errorcode, const char* place )
00676   {
00677     printf( "Win error at %s.\n", place );
00678     switch( errorcode )
00679     {
00680       case SEC_E_OK:
00681         printf( "\tValue:\tSEC_E_OK\n" );
00682         printf( "\tDesc:\tNot really an error. Everything is fine.\n" );
00683         break;
00684       case SEC_E_INSUFFICIENT_MEMORY:
00685         printf( "\tValue:\tSEC_E_INSUFFICIENT_MEMORY\n" );
00686         printf( "\tDesc:\tThere is not enough memory available to complete the requested action.\n" );
00687         break;
00688       case SEC_E_INTERNAL_ERROR:
00689         printf( "\tValue:\tSEC_E_INTERNAL_ERROR\n" );
00690         printf( "\tDesc:\tAn error occurred that did not map to an SSPI error code.\n" );
00691         break;
00692       case SEC_E_NO_CREDENTIALS:
00693         printf( "\tValue:\tSEC_E_NO_CREDENTIALS\n" );
00694         printf( "\tDesc:\tNo credentials are available in the security package.\n" );
00695         break;
00696       case SEC_E_NOT_OWNER:
00697         printf( "\tValue:\tSEC_E_NOT_OWNER\n" );
00698         printf( "\tDesc:\tThe caller of the function does not have the necessary credentials.\n" );
00699         break;
00700       case SEC_E_SECPKG_NOT_FOUND:
00701         printf( "\tValue:\tSEC_E_SECPKG_NOT_FOUND\n" );
00702         printf( "\tDesc:\tThe requested security package does not exist. \n" );
00703         break;
00704       case SEC_E_UNKNOWN_CREDENTIALS:
00705         printf( "\tValue:\tSEC_E_UNKNOWN_CREDENTIALS\n" );
00706         printf( "\tDesc:\tThe credentials supplied to the package were not recognized.\n" );
00707         break;
00708       case SEC_E_INCOMPLETE_MESSAGE:
00709         printf( "\tValue:\tSEC_E_INCOMPLETE_MESSAGE\n" );
00710         printf( "\tDesc:\tData for the whole message was not read from the wire.\n" );
00711         break;
00712       case SEC_E_INVALID_HANDLE:
00713         printf( "\tValue:\tSEC_E_INVALID_HANDLE\n" );
00714         printf( "\tDesc:\tThe handle passed to the function is invalid.\n" );
00715         break;
00716       case SEC_E_INVALID_TOKEN:
00717         printf( "\tValue:\tSEC_E_INVALID_TOKEN\n" );
00718         printf( "\tDesc:\tThe error is due to a malformed input token, such as a token "
00719                 "corrupted in transit...\n" );
00720         break;
00721       case SEC_E_LOGON_DENIED:
00722         printf( "\tValue:\tSEC_E_LOGON_DENIED\n" );
00723         printf( "\tDesc:\tThe logon failed.\n" );
00724         break;
00725       case SEC_E_NO_AUTHENTICATING_AUTHORITY:
00726         printf( "\tValue:\tSEC_E_NO_AUTHENTICATING_AUTHORITY\n" );
00727         printf( "\tDesc:\tNo authority could be contacted for authentication...\n" );
00728         break;
00729       case SEC_E_TARGET_UNKNOWN:
00730         printf( "\tValue:\tSEC_E_TARGET_UNKNOWN\n" );
00731         printf( "\tDesc:\tThe target was not recognized.\n" );
00732         break;
00733       case SEC_E_UNSUPPORTED_FUNCTION:
00734         printf( "\tValue:\tSEC_E_UNSUPPORTED_FUNCTION\n" );
00735         printf( "\tDesc:\tAn invalid context attribute flag (ISC_REQ_DELEGATE or "
00736                 "ISC_REQ_PROMPT_FOR_CREDS)...\n" );
00737         break;
00738       case SEC_E_WRONG_PRINCIPAL:
00739         printf( "\tValue:\tSEC_E_WRONG_PRINCIPAL\n" );
00740         printf( "\tDesc:\tThe principal that received the authentication request "
00741                 "is not the same as the...\n" );
00742         break;
00743       case SEC_I_COMPLETE_AND_CONTINUE:
00744         printf( "\tValue:\tSEC_I_COMPLETE_AND_CONTINUE\n" );
00745         printf( "\tDesc:\tThe client must call CompleteAuthToken and then pass the output...\n" );
00746         break;
00747       case SEC_I_COMPLETE_NEEDED:
00748         printf( "\tValue:\tSEC_I_COMPLETE_NEEDED\n" );
00749         printf( "\tDesc:\tThe client must finish building the message and then "
00750                 "call the CompleteAuthToken function.\n" );
00751         break;
00752       case SEC_I_CONTINUE_NEEDED:
00753         printf( "\tValue:\tSEC_I_CONTINUE_NEEDED\n" );
00754         printf( "\tDesc:\tThe client must send the output token to the server "
00755                 "and wait for a return token...\n" );
00756         break;
00757       case SEC_I_INCOMPLETE_CREDENTIALS:
00758         printf( "\tValue:\tSEC_I_INCOMPLETE_CREDENTIALS\n" );
00759         printf( "\tDesc:\tThe server has requested client authentication, "
00760                 "and the supplied credentials either...\n" );
00761         break;
00762       default:
00763         printf( "\tValue:\t%d\n", errorcode );
00764         printf( "\tDesc:\tUnknown error code.\n" );
00765     }
00766   }
00767 #endif
00768 
00769 }
00770 
00771 #endif // HAVE_WINTLS

Generated on Sat Nov 10 08:50:27 2007 for gloox by  doxygen 1.5.3-20071008