1 /* 2 * Copyright (c) 2007-2019 by Jakob Schröter <js@camaya.net> 3 * This file is part of the gloox library. http://camaya.net/gloox 4 * 5 * This software is distributed under a license. The full license 6 * agreement can be found in the file LICENSE in this distribution. 7 * This software may not be copied, modified, sold or distributed 8 * other than expressed in the named license agreement. 9 * 10 * This software is distributed without any warranty. 11 */ 12 13 #include "tlsschannel.h" 14 15 #ifdef HAVE_WINTLS 16 17 #include <stdio.h> // just for debugging output 18 19 namespace gloox 20 { SChannel(TLSHandler * th,const std::string & server)21 SChannel::SChannel( TLSHandler* th, const std::string& server ) 22 : TLSBase( th, server ), m_cleanedup( true ) 23 { 24 //printf(">> SChannel::SChannel()\n"); 25 } 26 ~SChannel()27 SChannel::~SChannel() 28 { 29 m_handler = 0; 30 cleanup(); 31 //printf(">> SChannel::~SChannel()\n"); 32 } 33 encrypt(const std::string & data)34 bool SChannel::encrypt( const std::string& data ) 35 { 36 if( !m_handler ) 37 return false; 38 39 //printf(">> SChannel::encrypt()\n"); 40 std::string data_copy = data; 41 42 SecBuffer buffer[4]; 43 SecBufferDesc buffer_desc; 44 DWORD cbIoBufferLength = m_sizes.cbHeader + m_sizes.cbMaximumMessage + m_sizes.cbTrailer; 45 46 PBYTE e_iobuffer = static_cast<PBYTE>( malloc( cbIoBufferLength ) ); 47 48 if( e_iobuffer == NULL ) 49 { 50 //printf("**** Out of memory (2)\n"); 51 cleanup(); 52 if( !m_secure ) 53 m_handler->handleHandshakeResult( this, false, m_certInfo ); 54 return false; 55 } 56 PBYTE e_message = e_iobuffer + m_sizes.cbHeader; 57 do 58 { 59 const size_t size = ( data_copy.size() > m_sizes.cbMaximumMessage ) 60 ? m_sizes.cbMaximumMessage 61 : data_copy.size(); 62 memcpy( e_message, data_copy.data(), size ); 63 if( data_copy.size() > m_sizes.cbMaximumMessage ) 64 data_copy.erase( 0, m_sizes.cbMaximumMessage ); 65 else 66 data_copy = EmptyString; 67 68 buffer[0].pvBuffer = e_iobuffer; 69 buffer[0].cbBuffer = m_sizes.cbHeader; 70 buffer[0].BufferType = SECBUFFER_STREAM_HEADER; 71 72 buffer[1].pvBuffer = e_message; 73 buffer[1].cbBuffer = size; 74 buffer[1].BufferType = SECBUFFER_DATA; 75 76 buffer[2].pvBuffer = static_cast<char*>(buffer[1].pvBuffer) + buffer[1].cbBuffer; 77 buffer[2].cbBuffer = m_sizes.cbTrailer; 78 buffer[2].BufferType = SECBUFFER_STREAM_TRAILER; 79 80 buffer[3].BufferType = SECBUFFER_EMPTY; 81 82 buffer_desc.ulVersion = SECBUFFER_VERSION; 83 buffer_desc.cBuffers = 4; 84 buffer_desc.pBuffers = buffer; 85 86 SECURITY_STATUS e_status = EncryptMessage( &m_context, 0, &buffer_desc, 0 ); 87 if( SUCCEEDED( e_status ) ) 88 { 89 std::string encrypted( reinterpret_cast<const char*>(e_iobuffer), 90 buffer[0].cbBuffer + buffer[1].cbBuffer + buffer[2].cbBuffer ); 91 m_handler->handleEncryptedData( this, encrypted ); 92 //if (data_copy.size() <= m_sizes.cbMaximumMessage) data_copy = EmptyString; 93 } 94 else 95 { 96 free( e_iobuffer ); 97 e_iobuffer = 0; 98 if( !m_secure ) 99 m_handler->handleHandshakeResult( this, false, m_certInfo ); 100 cleanup(); 101 return false; 102 } 103 } 104 while( data_copy.size() > 0 ); 105 free( e_iobuffer ); 106 e_iobuffer = 0; 107 return true; 108 } 109 decrypt(const std::string & data)110 int SChannel::decrypt( const std::string& data ) 111 { 112 113 if( !m_handler ) 114 return 0; 115 116 //printf(">> SChannel::decrypt()\n"); 117 if( m_secure ) 118 { 119 m_buffer += data; 120 121 SecBuffer buffer[4]; 122 SecBufferDesc buffer_desc; 123 DWORD cbIoBufferLength = m_sizes.cbHeader + m_sizes.cbMaximumMessage + m_sizes.cbTrailer; 124 bool wantNewBufferSize = false; 125 126 PBYTE e_iobuffer = static_cast<PBYTE>( malloc( cbIoBufferLength ) ); 127 if( e_iobuffer == NULL ) 128 { 129 //printf("**** Out of memory (2)\n"); 130 cleanup(); 131 if( !m_secure ) 132 m_handler->handleHandshakeResult( this, false, m_certInfo ); 133 return 0; 134 } 135 SECURITY_STATUS e_status; 136 137 do 138 { 139 if( wantNewBufferSize ) 140 { 141 void* tmp = realloc( e_iobuffer, cbIoBufferLength ); 142 if( tmp ) 143 { 144 e_iobuffer = static_cast<PBYTE>( tmp ); 145 wantNewBufferSize = false; 146 } 147 else 148 { 149 //printf("**** Out of memory (2)\n"); 150 cleanup(); 151 m_handler->handleHandshakeResult( this, false, m_certInfo ); 152 return 0; 153 } 154 } 155 156 // copy data chunk from tmp string into encryption memory buffer 157 memcpy( e_iobuffer, m_buffer.data(), m_buffer.size() > 158 cbIoBufferLength ? cbIoBufferLength : m_buffer.size() ); 159 160 buffer[0].pvBuffer = e_iobuffer; 161 buffer[0].cbBuffer = static_cast<unsigned long>( m_buffer.size() > cbIoBufferLength 162 ? cbIoBufferLength 163 : m_buffer.size() ); 164 buffer[0].BufferType = SECBUFFER_DATA; 165 buffer[1].cbBuffer = buffer[2].cbBuffer = buffer[3].cbBuffer = 0; 166 buffer[1].BufferType = buffer[2].BufferType = buffer[3].BufferType = SECBUFFER_EMPTY; 167 168 buffer_desc.ulVersion = SECBUFFER_VERSION; 169 buffer_desc.cBuffers = 4; 170 buffer_desc.pBuffers = buffer; 171 172 unsigned long processed_data = buffer[0].cbBuffer; 173 e_status = DecryptMessage( &m_context, &buffer_desc, 0, 0 ); 174 175 // print_error(e_status, "decrypt() ~ DecryptMessage()"); 176 // for (int n=0; n<4; n++) 177 // printf("buffer[%d].cbBuffer: %d \t%d\n", n, buffer[n].cbBuffer, buffer[n].BufferType); 178 179 // Locate data and (optional) extra buffers. 180 SecBuffer* pDataBuffer = NULL; 181 SecBuffer* pExtraBuffer = NULL; 182 for( int i = 1; i < 4; i++ ) 183 { 184 if( pDataBuffer == NULL && buffer[i].BufferType == SECBUFFER_DATA ) 185 { 186 pDataBuffer = &buffer[i]; 187 //printf("buffer[%d].BufferType = SECBUFFER_DATA\n",i); 188 } 189 if( pExtraBuffer == NULL && buffer[i].BufferType == SECBUFFER_EXTRA ) 190 { 191 pExtraBuffer = &buffer[i]; 192 } 193 } 194 if( e_status == SEC_E_OK ) 195 { 196 std::string decrypted( reinterpret_cast<const char*>( pDataBuffer->pvBuffer ), 197 pDataBuffer->cbBuffer ); 198 m_handler->handleDecryptedData( this, decrypted ); 199 if( pExtraBuffer == NULL ) 200 { 201 m_buffer.erase( 0, processed_data ); 202 } 203 else 204 { 205 //std::cout << "m_buffer.size() = " << pExtraBuffer->cbBuffer << std::endl; 206 m_buffer.erase( 0, processed_data - pExtraBuffer->cbBuffer ); 207 //std::cout << "m_buffer.size() = " << m_buffer.size() << std::endl; 208 209 cbIoBufferLength = m_sizes.cbHeader + m_sizes.cbMaximumMessage + m_sizes.cbTrailer; 210 wantNewBufferSize = true; 211 } 212 } 213 else if( e_status == SEC_E_INCOMPLETE_MESSAGE ) 214 { 215 if( cbIoBufferLength < 200000 && m_buffer.size() > cbIoBufferLength ) 216 { 217 cbIoBufferLength += 1000; 218 wantNewBufferSize = true; 219 } 220 else 221 { 222 cbIoBufferLength = m_sizes.cbHeader + m_sizes.cbMaximumMessage + m_sizes.cbTrailer; 223 wantNewBufferSize = true; 224 break; 225 } 226 } 227 else 228 { 229 //std::cout << "decrypt !!!ERROR!!!\n"; 230 if( !m_secure ) 231 m_handler->handleHandshakeResult( this, false, m_certInfo ); 232 cleanup(); 233 break; 234 } 235 } 236 while( m_buffer.size() != 0 ); 237 free( e_iobuffer ); 238 } 239 else 240 { 241 handshakeStage( data ); 242 } 243 //printf("<< SChannel::decrypt()\n"); 244 return 0; 245 } 246 cleanup()247 void SChannel::cleanup() 248 { 249 if( !m_mutex.trylock() ) 250 return; 251 252 m_buffer = ""; 253 if( !m_cleanedup ) 254 { 255 m_valid = false; 256 m_secure = false; 257 m_cleanedup = true; 258 DeleteSecurityContext( &m_context ); 259 FreeCredentialsHandle( &m_credHandle ); 260 } 261 262 m_mutex.unlock(); 263 } 264 handshake()265 bool SChannel::handshake() 266 { 267 if( !m_handler ) 268 return false; 269 270 //printf(">> SChannel::handshake()\n"); 271 SECURITY_STATUS error; 272 ULONG return_flags; 273 TimeStamp t; 274 SecBuffer obuf[1]; 275 SecBufferDesc obufs; 276 SCHANNEL_CRED tlscred; 277 ULONG request = ISC_REQ_ALLOCATE_MEMORY 278 | ISC_REQ_CONFIDENTIALITY 279 | ISC_REQ_EXTENDED_ERROR 280 | ISC_REQ_INTEGRITY 281 | ISC_REQ_REPLAY_DETECT 282 | ISC_REQ_SEQUENCE_DETECT 283 | ISC_REQ_STREAM 284 | ISC_REQ_MANUAL_CRED_VALIDATION; 285 286 /* initialize TLS credential */ 287 memset( &tlscred, 0, sizeof( SCHANNEL_CRED ) ); 288 tlscred.dwVersion = SCHANNEL_CRED_VERSION; 289 tlscred.grbitEnabledProtocols = SP_PROT_TLS1; 290 /* acquire credentials */ 291 error = AcquireCredentialsHandle( 0, 292 UNISP_NAME, 293 SECPKG_CRED_OUTBOUND, 294 0, 295 &tlscred, 296 0, 297 0, 298 &m_credHandle, 299 &t ); 300 //print_error(error, "handshake() ~ AcquireCredentialsHandle()"); 301 if( error != SEC_E_OK ) 302 { 303 cleanup(); 304 m_handler->handleHandshakeResult( this, false, m_certInfo ); 305 return false; 306 } 307 else 308 { 309 /* initialize buffers */ 310 obuf[0].cbBuffer = 0; 311 obuf[0].pvBuffer = 0; 312 obuf[0].BufferType = SECBUFFER_TOKEN; 313 /* initialize buffer descriptors */ 314 obufs.ulVersion = SECBUFFER_VERSION; 315 obufs.cBuffers = 1; 316 obufs.pBuffers = obuf; 317 /* negotiate security */ 318 SEC_CHAR* hname = const_cast<char*>( m_server.c_str() ); 319 320 error = InitializeSecurityContextA( &m_credHandle, 321 0, 322 hname, 323 request, 324 0, 325 SECURITY_NETWORK_DREP, 326 0, 327 0, 328 &m_context, 329 &obufs, 330 &return_flags, 331 NULL ); 332 //print_error(error, "handshake() ~ InitializeSecurityContext()"); 333 334 if( error == SEC_I_CONTINUE_NEEDED ) 335 { 336 m_cleanedup = false; 337 //std::cout << "obuf[1].cbBuffer: " << obuf[0].cbBuffer << "\n"; 338 std::string senddata( static_cast<char*>(obuf[0].pvBuffer), obuf[0].cbBuffer ); 339 FreeContextBuffer( obuf[0].pvBuffer ); 340 m_handler->handleEncryptedData( this, senddata ); 341 return true; 342 } 343 else 344 { 345 cleanup(); 346 m_handler->handleHandshakeResult( this, false, m_certInfo ); 347 return false; 348 } 349 } 350 } 351 handshakeStage(const std::string & data)352 void SChannel::handshakeStage( const std::string& data ) 353 { 354 //printf(" >> handshake_stage\n"); 355 m_buffer += data; 356 357 SECURITY_STATUS error; 358 ULONG a; 359 TimeStamp t; 360 SecBuffer ibuf[2], obuf[1]; 361 SecBufferDesc ibufs, obufs; 362 ULONG request = ISC_REQ_ALLOCATE_MEMORY 363 | ISC_REQ_CONFIDENTIALITY 364 | ISC_REQ_EXTENDED_ERROR 365 | ISC_REQ_INTEGRITY 366 | ISC_REQ_REPLAY_DETECT 367 | ISC_REQ_SEQUENCE_DETECT 368 | ISC_REQ_STREAM 369 | ISC_REQ_MANUAL_CRED_VALIDATION; 370 371 SEC_CHAR* hname = const_cast<char*>( m_server.c_str() ); 372 373 do 374 { 375 /* initialize buffers */ 376 ibuf[0].cbBuffer = static_cast<unsigned long>( m_buffer.size() ); 377 ibuf[0].pvBuffer = static_cast<void*>( const_cast<char*>( m_buffer.c_str() ) ); 378 //std::cout << "Size: " << m_buffer.size() << "\n"; 379 ibuf[1].cbBuffer = 0; 380 ibuf[1].pvBuffer = 0; 381 obuf[0].cbBuffer = 0; 382 obuf[0].pvBuffer = 0; 383 384 ibuf[0].BufferType = SECBUFFER_TOKEN; 385 ibuf[1].BufferType = SECBUFFER_EMPTY; 386 obuf[0].BufferType = SECBUFFER_EMPTY; 387 /* initialize buffer descriptors */ 388 ibufs.ulVersion = obufs.ulVersion = SECBUFFER_VERSION; 389 ibufs.cBuffers = 2; 390 obufs.cBuffers = 1; 391 ibufs.pBuffers = ibuf; 392 obufs.pBuffers = obuf; 393 394 /* 395 * std::cout << "obuf[0].cbBuffer: " << obuf[0].cbBuffer << "\t" << obuf[0].BufferType << "\n"; 396 * std::cout << "ibuf[0].cbBuffer: " << ibuf[0].cbBuffer << "\t" << ibuf[0].BufferType << "\n"; 397 * std::cout << "ibuf[1].cbBuffer: " << ibuf[1].cbBuffer << "\t" << ibuf[1].BufferType << "\n"; 398 */ 399 400 /* negotiate security */ 401 error = InitializeSecurityContextA( &m_credHandle, 402 &m_context, 403 hname, 404 request, 405 0, 406 0, 407 &ibufs, 408 0, 409 0, 410 &obufs, 411 &a, 412 &t ); 413 //print_error(error, "handshake() ~ InitializeSecurityContext()"); 414 if( error == SEC_E_OK ) 415 { 416 // EXTRA STUFF?? 417 if( ibuf[1].BufferType == SECBUFFER_EXTRA ) 418 { 419 m_buffer.erase( 0, m_buffer.size() - ibuf[1].cbBuffer ); 420 } 421 else 422 { 423 m_buffer = EmptyString; 424 } 425 setSizes(); 426 setCertinfos(); 427 428 m_secure = true; 429 m_handler->handleHandshakeResult( this, true, m_certInfo ); 430 break; 431 } 432 else if( error == SEC_I_CONTINUE_NEEDED ) 433 { 434 /* 435 * std::cout << "obuf[0].cbBuffer: " << obuf[0].cbBuffer << "\t" << obuf[0].BufferType << "\n"; 436 * std::cout << "ibuf[0].cbBuffer: " << ibuf[0].cbBuffer << "\t" << ibuf[0].BufferType << "\n"; 437 * std::cout << "ibuf[1].cbBuffer: " << ibuf[1].cbBuffer << "\t" << ibuf[1].BufferType << "\n"; 438 */ 439 440 // STUFF TO SEND?? 441 if( obuf[0].cbBuffer != 0 && obuf[0].pvBuffer != NULL ) 442 { 443 std::string senddata( static_cast<char*>(obuf[0].pvBuffer), obuf[0].cbBuffer ); 444 FreeContextBuffer( obuf[0].pvBuffer ); 445 m_handler->handleEncryptedData( this, senddata ); 446 } 447 // EXTRA STUFF?? 448 if( ibuf[1].BufferType == SECBUFFER_EXTRA ) 449 { 450 m_buffer.erase( 0, m_buffer.size() - ibuf[1].cbBuffer ); 451 // Call again if we aren't sending anything (otherwise the server will not send anything back 452 // and this function won't get called again to finish the processing). This is needed for 453 // NT4.0 which does not seem to process the entire buffer the first time around 454 if( obuf[0].cbBuffer == 0 ) 455 handshakeStage( EmptyString ); 456 } 457 else 458 { 459 m_buffer = EmptyString; 460 } 461 return; 462 } 463 else if( error == SEC_I_INCOMPLETE_CREDENTIALS ) 464 { 465 handshakeStage( EmptyString ); 466 } 467 else if( error == SEC_E_INCOMPLETE_MESSAGE ) 468 { 469 break; 470 } 471 else 472 { 473 cleanup(); 474 m_handler->handleHandshakeResult( this, false, m_certInfo ); 475 break; 476 } 477 } 478 while( true ); 479 } 480 hasChannelBinding() const481 bool SChannel::hasChannelBinding() const 482 { 483 #ifdef HAVE_WINTLS_CHANNEL_BINDING 484 return true; 485 #else 486 return false; 487 #endif 488 } 489 channelBinding() const490 const std::string SChannel::channelBinding() const 491 { 492 #ifdef HAVE_WINTLS_CHANNEL_BINDING // see ../config.h.win if the following doesn't compile 493 SecPkgContext_Bindings buf; 494 if( QueryContextAttributes( &m_context, SECPKG_ATTR_UNIQUE_BINDINGS, &buf ) == SEC_E_OK ) 495 { 496 return std::string( buf->Bindings[buf->Bindings.dwApplicationDataOffset], buf->Bindings.cbApplicationDataLength ); 497 } 498 #endif 499 return EmptyString; 500 } 501 setCACerts(const StringList &)502 void SChannel::setCACerts( const StringList& /*cacerts*/ ) {} 503 setClientCert(const std::string &,const std::string &)504 void SChannel::setClientCert( const std::string& /*clientKey*/, const std::string& /*clientCerts*/ ) {} 505 setSizes()506 void SChannel::setSizes() 507 { 508 if( QueryContextAttributes( &m_context, SECPKG_ATTR_STREAM_SIZES, &m_sizes ) == SEC_E_OK ) 509 { 510 //std::cout << "set_sizes success\n"; 511 } 512 else 513 { 514 //std::cout << "set_sizes no success\n"; 515 cleanup(); 516 m_handler->handleHandshakeResult( this, false, m_certInfo ); 517 } 518 } 519 filetime2int(FILETIME t)520 int SChannel::filetime2int( FILETIME t ) 521 { 522 SYSTEMTIME stUTC; 523 FileTimeToSystemTime(&t, &stUTC); 524 std::tm ts; 525 ts.tm_year = stUTC.wYear - 1900; 526 ts.tm_mon = stUTC.wMonth - 1; 527 ts.tm_mday = stUTC.wDay; 528 ts.tm_hour = stUTC.wHour; 529 ts.tm_min = stUTC.wMinute; 530 ts.tm_sec = stUTC.wSecond; 531 532 time_t unixtime; 533 if ( (unixtime = mktime(&ts)) == -1 ) 534 unixtime = 0; 535 return (int)unixtime; 536 } 537 validateCert()538 void SChannel::validateCert() 539 { 540 bool valid = false; 541 HTTPSPolicyCallbackData policyHTTPS; 542 CERT_CHAIN_POLICY_PARA policyParameter; 543 CERT_CHAIN_POLICY_STATUS policyStatus; 544 545 PCCERT_CONTEXT remoteCertContext = NULL; 546 PCCERT_CHAIN_CONTEXT chainContext = NULL; 547 CERT_CHAIN_PARA chainParameter; 548 PSTR serverName = const_cast<char*>( m_server.c_str() ); 549 550 PWSTR uServerName = NULL; 551 DWORD csizeServerName; 552 553 LPSTR Usages[] = { 554 szOID_PKIX_KP_SERVER_AUTH, 555 szOID_SERVER_GATED_CRYPTO, 556 szOID_SGC_NETSCAPE 557 }; 558 DWORD cUsages = sizeof( Usages ) / sizeof( LPSTR ); 559 560 do 561 { 562 // Get server's certificate. 563 if( QueryContextAttributes( &m_context, SECPKG_ATTR_REMOTE_CERT_CONTEXT, 564 (PVOID)&remoteCertContext ) != SEC_E_OK ) 565 { 566 //printf("Error querying remote certificate\n"); 567 // !!! THROW SOME ERROR 568 break; 569 } 570 571 // unicode conversation 572 // calculating unicode server name size 573 csizeServerName = MultiByteToWideChar( CP_ACP, 0, serverName, -1, NULL, 0 ); 574 uServerName = reinterpret_cast<WCHAR *>( malloc( csizeServerName * sizeof( WCHAR ) ) ); 575 if( uServerName == NULL ) 576 { 577 //printf("SEC_E_INSUFFICIENT_MEMORY ~ Not enough memory!!!\n"); 578 break; 579 } 580 581 // convert into unicode 582 csizeServerName = MultiByteToWideChar( CP_ACP, 0, serverName, -1, uServerName, csizeServerName ); 583 if( csizeServerName == 0 ) 584 { 585 //printf("SEC_E_WRONG_PRINCIPAL\n"); 586 break; 587 } 588 589 // create the chain 590 ZeroMemory( &chainParameter, sizeof( chainParameter ) ); 591 chainParameter.cbSize = sizeof( chainParameter ); 592 chainParameter.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR; 593 chainParameter.RequestedUsage.Usage.cUsageIdentifier = cUsages; 594 chainParameter.RequestedUsage.Usage.rgpszUsageIdentifier = Usages; 595 596 if( !CertGetCertificateChain( NULL, remoteCertContext, NULL, remoteCertContext->hCertStore, 597 &chainParameter, 0, NULL, &chainContext ) ) 598 { 599 // DWORD status = GetLastError(); 600 // printf("Error 0x%x returned by CertGetCertificateChain!!!\n", status); 601 break; 602 } 603 604 // validate the chain 605 ZeroMemory( &policyHTTPS, sizeof( HTTPSPolicyCallbackData ) ); 606 policyHTTPS.cbStruct = sizeof( HTTPSPolicyCallbackData ); 607 policyHTTPS.dwAuthType = AUTHTYPE_SERVER; 608 policyHTTPS.fdwChecks = 0; 609 policyHTTPS.pwszServerName = uServerName; 610 611 memset( &policyParameter, 0, sizeof( policyParameter ) ); 612 policyParameter.cbSize = sizeof( policyParameter ); 613 policyParameter.pvExtraPolicyPara = &policyHTTPS; 614 615 memset( &policyStatus, 0, sizeof( policyStatus ) ); 616 policyStatus.cbSize = sizeof( policyStatus ); 617 618 if( !CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_SSL, chainContext, &policyParameter, 619 &policyStatus ) ) 620 { 621 // DWORD status = GetLastError(); 622 // printf("Error 0x%x returned by CertVerifyCertificateChainPolicy!!!\n", status); 623 break; 624 } 625 626 if( policyStatus.dwError ) 627 { 628 //printf("Trust Error!!!}n"); 629 break; 630 } 631 valid = true; 632 } 633 while( false ); 634 // cleanup 635 if( chainContext ) 636 CertFreeCertificateChain( chainContext ); 637 if( uServerName != 0 ) 638 free( uServerName ); 639 m_certInfo.chain = valid; 640 } 641 connectionInfos()642 void SChannel::connectionInfos() 643 { 644 SecPkgContext_ConnectionInfo conn_info; 645 646 memset( &conn_info, 0, sizeof( conn_info ) ); 647 648 if( QueryContextAttributes( &m_context, SECPKG_ATTR_CONNECTION_INFO, &conn_info ) == SEC_E_OK ) 649 { 650 switch( conn_info.dwProtocol ) 651 { 652 case SP_PROT_TLS1_CLIENT: 653 m_certInfo.protocol = "TLSv1"; 654 break; 655 case SP_PROT_SSL3_CLIENT: 656 m_certInfo.protocol = "SSLv3"; 657 break; 658 default: 659 m_certInfo.protocol = "unknown"; 660 } 661 662 switch( conn_info.aiCipher ) 663 { 664 case CALG_3DES: 665 m_certInfo.cipher = "3DES"; 666 break; 667 case CALG_AES_128: 668 m_certInfo.cipher = "AES_128"; 669 break; 670 case CALG_AES_256: 671 m_certInfo.cipher = "AES_256"; 672 break; 673 case CALG_DES: 674 m_certInfo.cipher = "DES"; 675 break; 676 case CALG_RC2: 677 m_certInfo.cipher = "RC2"; 678 break; 679 case CALG_RC4: 680 m_certInfo.cipher = "RC4"; 681 break; 682 default: 683 m_certInfo.cipher = EmptyString; 684 } 685 686 switch( conn_info.aiHash ) 687 { 688 case CALG_MD5: 689 m_certInfo.mac = "MD5"; 690 break; 691 case CALG_SHA: 692 m_certInfo.mac = "SHA"; 693 break; 694 default: 695 m_certInfo.mac = EmptyString; 696 } 697 } 698 } 699 certData()700 void SChannel::certData() 701 { 702 PCCERT_CONTEXT remoteCertContext = NULL; 703 CHAR certString[1000]; 704 705 // getting server's certificate 706 if( QueryContextAttributes( &m_context, SECPKG_ATTR_REMOTE_CERT_CONTEXT, 707 (PVOID)&remoteCertContext ) != SEC_E_OK ) 708 { 709 return; 710 } 711 712 // setting certificat's lifespan 713 m_certInfo.date_from = filetime2int( remoteCertContext->pCertInfo->NotBefore ); 714 m_certInfo.date_to = filetime2int( remoteCertContext->pCertInfo->NotAfter ); 715 716 if( !CertNameToStrA( remoteCertContext->dwCertEncodingType, 717 &remoteCertContext->pCertInfo->Subject, 718 CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG, 719 certString, sizeof( certString ) ) ) 720 { 721 return; 722 } 723 m_certInfo.server = certString; 724 725 if( !CertNameToStrA( remoteCertContext->dwCertEncodingType, 726 &remoteCertContext->pCertInfo->Issuer, 727 CERT_X500_NAME_STR | CERT_NAME_STR_NO_PLUS_FLAG, 728 certString, sizeof( certString ) ) ) 729 { 730 return; 731 } 732 m_certInfo.issuer = certString; 733 } 734 setCertinfos()735 void SChannel::setCertinfos() 736 { 737 validateCert(); 738 connectionInfos(); 739 certData(); 740 } 741 742 #if 0 743 void SChannel::print_error( int errorcode, const char* place ) 744 { 745 printf( "Win error at %s.\n", place ); 746 switch( errorcode ) 747 { 748 case SEC_E_OK: 749 printf( "\tValue:\tSEC_E_OK\n" ); 750 printf( "\tDesc:\tNot really an error. Everything is fine.\n" ); 751 break; 752 case SEC_E_INSUFFICIENT_MEMORY: 753 printf( "\tValue:\tSEC_E_INSUFFICIENT_MEMORY\n" ); 754 printf( "\tDesc:\tThere is not enough memory available to complete the requested action.\n" ); 755 break; 756 case SEC_E_INTERNAL_ERROR: 757 printf( "\tValue:\tSEC_E_INTERNAL_ERROR\n" ); 758 printf( "\tDesc:\tAn error occurred that did not map to an SSPI error code.\n" ); 759 break; 760 case SEC_E_NO_CREDENTIALS: 761 printf( "\tValue:\tSEC_E_NO_CREDENTIALS\n" ); 762 printf( "\tDesc:\tNo credentials are available in the security package.\n" ); 763 break; 764 case SEC_E_NOT_OWNER: 765 printf( "\tValue:\tSEC_E_NOT_OWNER\n" ); 766 printf( "\tDesc:\tThe caller of the function does not have the necessary credentials.\n" ); 767 break; 768 case SEC_E_SECPKG_NOT_FOUND: 769 printf( "\tValue:\tSEC_E_SECPKG_NOT_FOUND\n" ); 770 printf( "\tDesc:\tThe requested security package does not exist. \n" ); 771 break; 772 case SEC_E_UNKNOWN_CREDENTIALS: 773 printf( "\tValue:\tSEC_E_UNKNOWN_CREDENTIALS\n" ); 774 printf( "\tDesc:\tThe credentials supplied to the package were not recognized.\n" ); 775 break; 776 case SEC_E_INCOMPLETE_MESSAGE: 777 printf( "\tValue:\tSEC_E_INCOMPLETE_MESSAGE\n" ); 778 printf( "\tDesc:\tData for the whole message was not read from the wire.\n" ); 779 break; 780 case SEC_E_INVALID_HANDLE: 781 printf( "\tValue:\tSEC_E_INVALID_HANDLE\n" ); 782 printf( "\tDesc:\tThe handle passed to the function is invalid.\n" ); 783 break; 784 case SEC_E_INVALID_TOKEN: 785 printf( "\tValue:\tSEC_E_INVALID_TOKEN\n" ); 786 printf( "\tDesc:\tThe error is due to a malformed input token, such as a token " 787 "corrupted in transit...\n" ); 788 break; 789 case SEC_E_LOGON_DENIED: 790 printf( "\tValue:\tSEC_E_LOGON_DENIED\n" ); 791 printf( "\tDesc:\tThe logon failed.\n" ); 792 break; 793 case SEC_E_NO_AUTHENTICATING_AUTHORITY: 794 printf( "\tValue:\tSEC_E_NO_AUTHENTICATING_AUTHORITY\n" ); 795 printf( "\tDesc:\tNo authority could be contacted for authentication...\n" ); 796 break; 797 case SEC_E_TARGET_UNKNOWN: 798 printf( "\tValue:\tSEC_E_TARGET_UNKNOWN\n" ); 799 printf( "\tDesc:\tThe target was not recognized.\n" ); 800 break; 801 case SEC_E_UNSUPPORTED_FUNCTION: 802 printf( "\tValue:\tSEC_E_UNSUPPORTED_FUNCTION\n" ); 803 printf( "\tDesc:\tAn invalid context attribute flag (ISC_REQ_DELEGATE or " 804 "ISC_REQ_PROMPT_FOR_CREDS)...\n" ); 805 break; 806 case SEC_E_WRONG_PRINCIPAL: 807 printf( "\tValue:\tSEC_E_WRONG_PRINCIPAL\n" ); 808 printf( "\tDesc:\tThe principal that received the authentication request " 809 "is not the same as the...\n" ); 810 break; 811 case SEC_I_COMPLETE_AND_CONTINUE: 812 printf( "\tValue:\tSEC_I_COMPLETE_AND_CONTINUE\n" ); 813 printf( "\tDesc:\tThe client must call CompleteAuthToken and then pass the output...\n" ); 814 break; 815 case SEC_I_COMPLETE_NEEDED: 816 printf( "\tValue:\tSEC_I_COMPLETE_NEEDED\n" ); 817 printf( "\tDesc:\tThe client must finish building the message and then " 818 "call the CompleteAuthToken function.\n" ); 819 break; 820 case SEC_I_CONTINUE_NEEDED: 821 printf( "\tValue:\tSEC_I_CONTINUE_NEEDED\n" ); 822 printf( "\tDesc:\tThe client must send the output token to the server " 823 "and wait for a return token...\n" ); 824 break; 825 case SEC_I_INCOMPLETE_CREDENTIALS: 826 printf( "\tValue:\tSEC_I_INCOMPLETE_CREDENTIALS\n" ); 827 printf( "\tDesc:\tThe server has requested client authentication, " 828 "and the supplied credentials either...\n" ); 829 break; 830 default: 831 printf( "\tValue:\t%d\n", errorcode ); 832 printf( "\tDesc:\tUnknown error code.\n" ); 833 } 834 } 835 #endif 836 837 } 838 839 #endif // HAVE_WINTLS 840