gloox 1.0
|
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