PageRenderTime 76ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/trunk/LibUltimateTCPIP/Security/Source/UTSecureSocket.cpp

#
C++ | 2421 lines | 1480 code | 302 blank | 639 comment | 313 complexity | df61f846cfac9c8d7c4ceb80ff9f6007 MD5 | raw file
  1. //=================================================================
  2. // class: CUT_SecureSocket
  3. // File: CUT_SecureSocket.cpp
  4. //
  5. // Purpose:
  6. //
  7. // Security socket layer implementation
  8. //
  9. // ===================================================================
  10. // Ultimate TCP/IP v4.2
  11. // This software along with its related components, documentation and files ("The Libraries")
  12. // is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
  13. // governed by a software license agreement ("Agreement"). Copies of the Agreement are
  14. // available at The Code Project (www.codeproject.com), as part of the package you downloaded
  15. // to obtain this file, or directly from our office. For a copy of the license governing
  16. // this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
  17. // ===================================================================
  18. // v4.2 - update 01 - VS2008/64-bit - generates warning - revisit this
  19. #ifdef _WINSOCK_2_0_
  20. #define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */
  21. /* Remove this line if you are using WINSOCK 1.1 */
  22. #endif
  23. #include "stdafx.h"
  24. #include "ut_strop.h"
  25. // Suppress warnings for non-safe str fns. Transitional, for VC6 support.
  26. #pragma warning (push)
  27. #pragma warning (disable : 4996)
  28. #ifdef CUT_SECURE_SOCKET
  29. #include "ut_clnt.h"
  30. #include "UTSecureSocket.h"
  31. #include "UTCertifMan.h"
  32. #ifndef SEC_I_CONTEXT_EXPIRED
  33. //
  34. // this can be removed when it the error code is added to WinError.h
  35. //
  36. #define SEC_I_CONTEXT_EXPIRED ((HRESULT)0x00090317L)
  37. #endif
  38. // ===================================================================
  39. // CUT_SecureSocket class
  40. // ===================================================================
  41. /***********************************************
  42. CUT_SecureSocket
  43. Constructor
  44. Params
  45. none
  46. Return
  47. none
  48. ************************************************/
  49. CUT_SecureSocket::CUT_SecureSocket() :
  50. m_bSecureConnection(FALSE),
  51. m_hSecurity(NULL),
  52. m_hCertStore(NULL),
  53. m_dwProtocol(0),
  54. m_phCreds(NULL),
  55. m_phContext(NULL),
  56. m_dwIoBufferLength(0),
  57. m_lpszIoBuffer(NULL),
  58. m_lpszExtraReceivedData(NULL),
  59. m_dwExtraReceivedDataSize(0),
  60. m_lpszDecodedData(NULL),
  61. m_dwDecodedDataSize(0),
  62. m_dwDecodedDataMaxSize(0),
  63. m_lpszMessageBuffer(NULL),
  64. m_dwMaxCipherStrength(0),
  65. m_dwMinCipherStrength(0),
  66. m_CertValidation(CERT_VERIFY_AND_ASK),
  67. m_bCloseStore(FALSE)
  68. {
  69. // Initialize user name
  70. ZeroMemory(m_szCertSubjStr, sizeof(m_szCertSubjStr));
  71. // Initialize store name
  72. ZeroMemory(m_szCertStoreName, sizeof(m_szCertStoreName));
  73. _tcscpy(m_szCertStoreName, _T("MY"));
  74. // Allocate decoded data buffer
  75. m_lpszDecodedData = (char *)LocalAlloc(LMEM_FIXED, IO_BUFFER_SIZE);
  76. m_dwDecodedDataMaxSize = IO_BUFFER_SIZE - 1;
  77. }
  78. /***********************************************
  79. ~CUT_SecureSocket
  80. Destructor
  81. Params
  82. none
  83. Return
  84. none
  85. ************************************************/
  86. CUT_SecureSocket::~CUT_SecureSocket()
  87. {
  88. // Free security library if loaded
  89. FreeSecurityLibrary();
  90. // Free extra read data
  91. if(m_lpszExtraReceivedData != NULL)
  92. LocalFree(m_lpszExtraReceivedData);
  93. // Free decoded data buffer
  94. LocalFree(m_lpszDecodedData);
  95. }
  96. /***********************************************
  97. SocketRecv
  98. Receives data from the connected secure/nonsecure socket
  99. Params
  100. s - socket to receive data from
  101. buf - data buffer for reading
  102. len - data buffer size
  103. flags - a flag specifying the way in which the call is made.
  104. Return
  105. SOCKET_ERROR or number of bytes received
  106. ************************************************/
  107. int CUT_SecureSocket::SocketRecv(SOCKET s, char FAR* buf, int len, int flags)
  108. {
  109. DWORD dwBytesToCopy = 0;
  110. // Call non secure socket function
  111. if(m_bSecureConnection == FALSE)
  112. return CUT_Socket::SocketRecv(s, buf, len, flags);
  113. // Check the security context
  114. if(m_phContext == NULL)
  115. return SOCKET_ERROR;
  116. // If no data in the buffer - receive more messages
  117. if(m_dwDecodedDataSize == 0)
  118. {
  119. if(MessageRecv(s) != UTE_SUCCESS)
  120. return SOCKET_ERROR;
  121. }
  122. // Copy data from the decrypted data buffer
  123. if(m_dwDecodedDataSize > 0)
  124. {
  125. dwBytesToCopy = min((int)m_dwDecodedDataSize, len);
  126. MoveMemory(buf, m_lpszDecodedData, dwBytesToCopy);
  127. if((flags & MSG_PEEK) == FALSE)
  128. {
  129. // Remove data from the buffer
  130. MoveMemory(m_lpszDecodedData, m_lpszDecodedData + dwBytesToCopy, m_dwDecodedDataSize - dwBytesToCopy);
  131. m_dwDecodedDataSize -= dwBytesToCopy;
  132. }
  133. }
  134. return dwBytesToCopy;
  135. }
  136. /***********************************************
  137. SocketSend
  138. Sends data to the connected secure/nonsecure socket
  139. Params
  140. s - socket to receive data from
  141. buf - data buffer for sending
  142. len - data size
  143. flags - a flag specifying the way in which the call is made.
  144. Return
  145. SOCKET_ERROR or number of bytes sent
  146. ************************************************/
  147. int CUT_SecureSocket::SocketSend(SOCKET s, char FAR* buf, int len, int flags)
  148. {
  149. // Call non secure socket function
  150. if(!m_bSecureConnection)
  151. return CUT_Socket::SocketSend(s, buf, len, flags);
  152. // Check the security context
  153. if(m_phContext == NULL)
  154. return SOCKET_ERROR;
  155. DWORD dwMessageSize = 0;
  156. SecBufferDesc Message;
  157. SecBuffer Buffers[4];
  158. SECURITY_STATUS Status;
  159. DWORD dwData;
  160. DWORD dwBytesSent = 0;
  161. // Check parameters
  162. if(buf == NULL)
  163. return SOCKET_ERROR;
  164. // Split data into the smaller chunks if nessesary
  165. while(dwBytesSent < (DWORD)len)
  166. {
  167. // Set message size
  168. dwMessageSize = min(len - dwBytesSent, m_StreamSizes.cbMaximumMessage);
  169. // Copy data into the buffer
  170. MoveMemory(m_lpszMessageBuffer, buf + dwBytesSent, dwMessageSize);
  171. // Encrypt data before sending
  172. Buffers[0].pvBuffer = m_lpszIoBuffer;
  173. Buffers[0].cbBuffer = m_StreamSizes.cbHeader;
  174. Buffers[0].BufferType = SECBUFFER_STREAM_HEADER;
  175. Buffers[1].pvBuffer = m_lpszMessageBuffer;
  176. Buffers[1].cbBuffer = dwMessageSize;
  177. Buffers[1].BufferType = SECBUFFER_DATA;
  178. Buffers[2].pvBuffer = m_lpszMessageBuffer + dwMessageSize;
  179. Buffers[2].cbBuffer = m_StreamSizes.cbTrailer;
  180. Buffers[2].BufferType = SECBUFFER_STREAM_TRAILER;
  181. Buffers[3].BufferType = SECBUFFER_EMPTY;
  182. Message.ulVersion = SECBUFFER_VERSION;
  183. Message.cBuffers = 4;
  184. Message.pBuffers = Buffers;
  185. Status = m_SecurityFunc.EncryptMessage(m_phContext, 0, &Message, 0);
  186. if(FAILED(Status))
  187. {
  188. HandleSecurityError(_T("Failed to encrypt security message."));
  189. return SOCKET_ERROR;
  190. }
  191. // Send the encrypted data to the server.
  192. dwData = send(s, m_lpszIoBuffer,
  193. Buffers[0].cbBuffer + Buffers[1].cbBuffer + Buffers[2].cbBuffer,
  194. 0);
  195. if(dwData == SOCKET_ERROR || dwData == 0)
  196. {
  197. HandleSecurityError(_T("Error sending secure data to the server."));
  198. return dwData;
  199. }
  200. // Increase the number of bytes sent
  201. dwBytesSent += dwMessageSize;
  202. }
  203. return len;
  204. }
  205. /***********************************************
  206. SocketOnConnected
  207. Negotiates a secure connection on the specified
  208. socket.
  209. Params
  210. s - a descriptor identifying a socket
  211. lpszName - server name
  212. Return
  213. UTE_SUCCESS
  214. UTE_LOAD_SECURITY_LIBRARIES_FAILED
  215. UTE_OUT_OF_MEMORY
  216. UTE_NULL_PARAM
  217. UTE_FAILED_TO_GET_SECURITY_STREAM_SIZE
  218. UTE_FAILED_TO_CREATE_SECURITY_CREDENTIALS
  219. UTE_HANDSHAKE_FAILED
  220. ************************************************/
  221. int CUT_SecureSocket::SocketOnConnected(SOCKET s, const char *lpszName)
  222. {
  223. SecBuffer ExtraData;
  224. int nError = UTE_SUCCESS;
  225. // Call non secure socket function
  226. if(!m_bSecureConnection) {
  227. return CUT_Socket::SocketOnConnected(s, lpszName);
  228. }
  229. // Check parameter
  230. if(lpszName == NULL)
  231. return UTE_NULL_PARAM;
  232. // Load security library
  233. if(!LoadSecurityLibrary())
  234. return UTE_LOAD_SECURITY_LIBRARIES_FAILED;
  235. // Create security credentials
  236. if((nError = CreateCredentials()) != UTE_SUCCESS)
  237. return UTE_FAILED_TO_CREATE_SECURITY_CREDENTIALS;
  238. // Perform handshake
  239. // v4.2 Using WC here. lpszname is char in core code, and doing this here avoids messy overload of protected PerformHandshake")
  240. if((nError = PerformHandshake(s, WC(lpszName), &ExtraData)) != UTE_SUCCESS)
  241. {
  242. delete m_phContext;
  243. m_phContext = NULL;
  244. return UTE_HANDSHAKE_FAILED;
  245. }
  246. //************************************************
  247. //** Allocate a working IO buffer
  248. //************************************************
  249. // Read stream encryption properties.
  250. if(m_SecurityFunc.QueryContextAttributes(m_phContext, SECPKG_ATTR_STREAM_SIZES, &m_StreamSizes) != SEC_E_OK)
  251. {
  252. HandleSecurityError(_T("Error reading security stream sizes."));
  253. return UTE_FAILED_TO_GET_SECURITY_STREAM_SIZE;
  254. }
  255. // Free previous IO buffer memory
  256. if(m_lpszIoBuffer != NULL)
  257. LocalFree(m_lpszIoBuffer);
  258. // Allocate a working buffer. The plaintext sent to EncryptMessage
  259. // should never be more than 'm_StreamSizes.cbMaximumMessage', so a buffer
  260. // size of this plus the header and trailer m_StreamSizes should be safe enough.
  261. m_dwIoBufferLength = m_StreamSizes.cbHeader + m_StreamSizes.cbMaximumMessage + m_StreamSizes.cbTrailer;
  262. if(m_dwIoBufferLength * 2 < 0x10000) // AB: ensure doubling will not exceed 64k
  263. m_dwIoBufferLength *= 2;
  264. else
  265. m_dwIoBufferLength = 0xFFFF;
  266. m_lpszIoBuffer = (char *)LocalAlloc(LMEM_FIXED, m_dwIoBufferLength); //AB: + 10);
  267. if(m_lpszIoBuffer == NULL)
  268. {
  269. HandleSecurityError(_T("Out of memory."));
  270. return UTE_OUT_OF_MEMORY;
  271. }
  272. // Initialize pointer to the message data
  273. m_lpszMessageBuffer = m_lpszIoBuffer + m_StreamSizes.cbHeader;
  274. // Clear received data buffer
  275. m_dwDecodedDataSize = 0;
  276. // Free extra read data buffer
  277. if(m_lpszExtraReceivedData != NULL)
  278. {
  279. LocalFree(m_lpszExtraReceivedData);
  280. m_lpszExtraReceivedData = NULL;
  281. m_dwExtraReceivedDataSize = 0;
  282. }
  283. //************************************************
  284. //** Verify sertificate
  285. //************************************************
  286. if((nError = VerifyCertificate((PTSTR)lpszName, 0)) != UTE_SUCCESS)
  287. {
  288. HandleSecurityError(_T("Error authenticating security credentials."));
  289. return nError;
  290. }
  291. return UTE_SUCCESS;
  292. }
  293. /***********************************************
  294. SocketClose
  295. Close a secure/nonsecure connection to a
  296. specifed socket.
  297. Params
  298. s - a descriptor identifying connected socket
  299. Return
  300. Socket error or 0
  301. ************************************************/
  302. int CUT_SecureSocket::SocketClose(SOCKET s)
  303. {
  304. // Notify server about disconnection
  305. if(m_bSecureConnection)
  306. DisconnectNotify(s);
  307. // Close socket connection
  308. return CUT_Socket::SocketClose(s);
  309. }
  310. /***********************************************
  311. SocketShutDown
  312. Shuts down a secure/nonsecure connection to a
  313. specifed socket.
  314. Params
  315. s - a descriptor identifying connected socket
  316. how - SD_RECEIVE, SD_SEND, SD_BOTH
  317. Return
  318. Socket error or 0
  319. ************************************************/
  320. int CUT_SecureSocket::SocketShutDown(SOCKET s, int how)
  321. {
  322. // Notify server about disconnection
  323. if(m_bSecureConnection)
  324. DisconnectNotify(s);
  325. return CUT_Socket::SocketShutDown(s, how);
  326. }
  327. /***********************************************
  328. SocketIsDataWaiting
  329. Checks if data waiting on the connected socket
  330. Params
  331. s - a descriptor identifying connected socket
  332. Return
  333. TRUE if data is waiting to be read
  334. ************************************************/
  335. BOOL CUT_SecureSocket::SocketIsDataWaiting(SOCKET s) const
  336. {
  337. // Call non secure socket function
  338. if(!m_bSecureConnection)
  339. return CUT_Socket::SocketIsDataWaiting(s);
  340. BOOL bResult = CUT_Socket::SocketIsDataWaiting(s);
  341. // If there is something in the decoded data buffer
  342. if( m_dwDecodedDataSize > 0)
  343. bResult = TRUE;
  344. return bResult;
  345. }
  346. /***********************************************
  347. SocketWaitForReceive
  348. Waits specified amount of time for the incoming
  349. data
  350. Params
  351. s - a descriptor identifying connected socket
  352. secs - seconds to wait
  353. uSecs - milliseconds to wait
  354. Return
  355. UTE_SUCCESS - success
  356. UTE_ERROR - failure
  357. ************************************************/
  358. int CUT_SecureSocket::SocketWaitForReceive(SOCKET s, long secs, long uSecs)
  359. {
  360. // Call non secure socket function
  361. if(!m_bSecureConnection)
  362. return CUT_Socket::SocketWaitForReceive(s, secs, uSecs);
  363. if( m_dwDecodedDataSize > 0)
  364. return UTE_SUCCESS;
  365. if(MessageRecv(s) == UTE_SUCCESS)
  366. return UTE_SUCCESS;
  367. if (CUT_Socket::SocketWaitForReceive(s, secs, uSecs)== UTE_SUCCESS)
  368. return UTE_SUCCESS;
  369. //
  370. return UTE_ERROR;
  371. // return CUT_Socket::SocketWaitForReceive(s, secs, uSecs);
  372. }
  373. /***********************************************
  374. HandleError
  375. Virtual function which receives the security
  376. errors descriptions.
  377. Params
  378. lpszErrorDescription - error description string
  379. Return
  380. none
  381. ************************************************/
  382. void CUT_SecureSocket::HandleSecurityError(_TCHAR *lpszErrorDescription)
  383. {
  384. #ifdef _DEBUG
  385. MessageBox(NULL,lpszErrorDescription, _T("HandleSecurityError Error") , MB_OK);
  386. #else
  387. UNREFERENCED_PARAMETER(lpszErrorDescription);
  388. #endif
  389. }
  390. /***********************************************
  391. OnCertVerifyError
  392. Function can be overwritten to handle certificate verifications errors
  393. Params
  394. certServer - remote certificate
  395. lpszServerName - remote name
  396. nError - error code
  397. CERT_E_EXPIRED
  398. CERT_E_VALIDITYPERIODNESTING
  399. CERT_E_ROLE
  400. CERT_E_PATHLENCONST
  401. CERT_E_CRITICAL
  402. CERT_E_PURPOSE
  403. CERT_E_ISSUERCHAINING
  404. CERT_E_MALFORMED
  405. CERT_E_UNTRUSTEDROOT
  406. CERT_E_CHAINING
  407. TRUST_E_FAIL
  408. CERT_E_REVOKED
  409. CERT_E_UNTRUSTEDTESTROOT
  410. CERT_E_REVOCATION_FAILURE
  411. CERT_E_CN_NO_MATCH
  412. CERT_E_WRONG_USAGE
  413. Return
  414. TRUE - accept the certificate
  415. FALSE - do not accept the certificate
  416. ************************************************/
  417. // v4.2 Should server name be included in message?
  418. BOOL CUT_SecureSocket::OnCertVerifyError(CUT_Certificate &certServer, int nError, _TCHAR * /* lpszServerName */)
  419. {
  420. // Show dialog with the remote certificate information and
  421. // ask if we should trust it
  422. if(m_CertValidation == CERT_VERIFY_AND_ASK && certServer.GetContext() != NULL)
  423. {
  424. // Prepare message text
  425. LPCTSTR lpszIssuedTo = certServer.GetIssuedTo();
  426. LPCTSTR lpszIssuer = certServer.GetIssuer();
  427. _TCHAR *lpszBuffer = new _TCHAR[500 + _tcslen(lpszIssuedTo) + _tcslen(lpszIssuer)];
  428. switch (nError)
  429. {
  430. case TRUST_E_PROVIDER_UNKNOWN: // #define TRUST_E_PROVIDER_UNKNOWN _HRESULT_TYPEDEF_(0x800B0001L)
  431. _tcscpy(lpszBuffer, _T("The specified trust provider is not known on this system.\r\n\r\n"));
  432. break;
  433. //
  434. //
  435. case TRUST_E_ACTION_UNKNOWN://
  436. _tcscpy(lpszBuffer, _T("The trust verification action specified is not supported by the specified trust provider.\r\n\r\n"));
  437. break;
  438. //
  439. //
  440. case TRUST_E_SUBJECT_FORM_UNKNOWN://
  441. _tcscpy(lpszBuffer, _T("The form specified for the subject is not one supported or known by the specified trust provider..\r\n\r\n"));
  442. break;
  443. //
  444. //
  445. case TRUST_E_SUBJECT_NOT_TRUSTED://
  446. _tcscpy(lpszBuffer, _T("The subject is not trusted for the specified action..\r\n\r\n"));
  447. break;
  448. //
  449. //
  450. case DIGSIG_E_ENCODE ://
  451. _tcscpy(lpszBuffer, _T("Error due to problem in ASN.1 encoding process.\r\n\r\n"));
  452. break;
  453. //
  454. //
  455. case DIGSIG_E_DECODE://
  456. _tcscpy(lpszBuffer, _T("Error due to problem in ASN.1 decoding process.\r\n\r\n"));
  457. break;
  458. //
  459. //
  460. case DIGSIG_E_EXTENSIBILITY://
  461. _tcscpy(lpszBuffer, _T(" Reading / writing Extensions where Attributes are appropriate, and visa versa.\r\n\r\n"));
  462. break;
  463. //
  464. //
  465. case DIGSIG_E_CRYPTO ://
  466. _tcscpy(lpszBuffer, _T("Unspecified cryptographic failure.\r\n\r\n"));
  467. break;
  468. //
  469. //
  470. case PERSIST_E_SIZEDEFINITE://
  471. _tcscpy(lpszBuffer, _T("The size of the data could not be determined.\r\n\r\n"));
  472. break;
  473. //
  474. //
  475. case PERSIST_E_SIZEINDEFINITE: //
  476. _tcscpy(lpszBuffer, _T("The size of the indefinite-sized data could not be determined.\r\n\r\n"));
  477. break;
  478. //
  479. //
  480. //
  481. case PERSIST_E_NOTSELFSIZING://
  482. _tcscpy(lpszBuffer, _T("This object does not read and write self-sizing data.\r\n\r\n"));
  483. break;
  484. //
  485. //
  486. //
  487. case TRUST_E_NOSIGNATURE://
  488. _tcscpy(lpszBuffer, _T("No signature was present in the subject.\r\n\r\n"));
  489. break;
  490. //
  491. //
  492. //
  493. case CERT_E_EXPIRED://
  494. _tcscpy(lpszBuffer, _T("A required certificate is not within its validity period.\r\n\r\n"));
  495. break;
  496. //
  497. //
  498. case CERT_E_VALIDITYPERIODNESTING://
  499. _tcscpy(lpszBuffer, _T("The validity periods of the certification chain do not nest correctly.\r\n\r\n"));
  500. break;
  501. //
  502. //
  503. case CERT_E_ROLE://
  504. _tcscpy(lpszBuffer, _T("A certificate that can only be used as an end-entity is being used as a CA or visa versa.\r\n\r\n"));
  505. break;
  506. //
  507. //
  508. case CERT_E_PATHLENCONST://
  509. _tcscpy(lpszBuffer, _T("A path length constraint in the certification chain has been violated.\r\n\r\n"));
  510. break;
  511. //
  512. //
  513. case CERT_E_CRITICAL ://
  514. _tcscpy(lpszBuffer, _T("An extension of unknown type that is labeled 'critical' is present in a certificate.\r\n\r\n"));
  515. break;
  516. //
  517. case CERT_E_PURPOSE ://
  518. _tcscpy(lpszBuffer, _T("A certificate is being used for a purpose other than that for which it is permitted.\r\n\r\n"));
  519. break;
  520. //
  521. //
  522. case CERT_E_ISSUERCHAINING ://
  523. _tcscpy(lpszBuffer, _T("A parent of a given certificate in fact did not issue that child certificate.\r\n\r\n"));
  524. break;
  525. //
  526. //
  527. case CERT_E_MALFORMED://
  528. _tcscpy(lpszBuffer, _T("A certificate is missing or has an empty value for an important field, such as a subject or issuer name.\r\n\r\n"));
  529. break;
  530. //
  531. //
  532. case CERT_E_UNTRUSTEDROOT://
  533. _tcscpy(lpszBuffer, _T("A certification chain processed correctly, but terminated in a root certificate which isn't trusted by the trust provider.\r\n\r\n"));
  534. break;
  535. //
  536. //
  537. case CERT_E_CHAINING://
  538. _tcscpy(lpszBuffer, _T("A chain of certs didn't chain as they should in a certain application of chaining.\r\n\r\n"));
  539. break;
  540. //
  541. //
  542. case TRUST_E_FAIL://
  543. _tcscpy(lpszBuffer, _T("Generic Trust Failure.\r\n\r\n"));
  544. break;
  545. //
  546. case CERT_E_REVOKED://
  547. _tcscpy(lpszBuffer, _T("A certificate was explicitly revoked by its issuer.\r\n\r\n"));
  548. break;
  549. //
  550. case CERT_E_UNTRUSTEDTESTROOT ://
  551. _tcscpy(lpszBuffer, _T("The root certificate is a testing certificate and the policy settings disallow test certificates.\r\n\r\n"));
  552. break;
  553. //
  554. case CERT_E_REVOCATION_FAILURE ://
  555. _tcscpy(lpszBuffer, _T("The revocation process could not continue - the certificate(s) could not be checked.\r\n\r\n"));
  556. break;
  557. case CERT_E_CN_NO_MATCH://
  558. _tcscpy(lpszBuffer, _T("The certificate's CN name does not match the passed value.\r\n\r\n"));
  559. break;
  560. case CERT_E_WRONG_USAGE://
  561. _tcscpy(lpszBuffer, _T("The certificate is not valid for the requested usage.\r\n\r\n"));
  562. break;
  563. default:
  564. _tcscpy(lpszBuffer, _T("The certificate veryfication failed.\r\n\r\n"));
  565. break;
  566. }
  567. _tcscat(lpszBuffer, _T("Certificate issued to: "));
  568. _tcscat(lpszBuffer, lpszIssuedTo);
  569. _tcscat(lpszBuffer, _T("\r\nCertificate issued by: "));
  570. _tcscat(lpszBuffer, lpszIssuer);
  571. _tcscat(lpszBuffer, _T("\r\n\r\nDo you want to proceed with the connection?"));
  572. int nResult = MessageBox(NULL, lpszBuffer, _T("Non trusted certificate"), MB_YESNO | MB_DEFBUTTON2 | MB_SYSTEMMODAL);
  573. // Free memory
  574. delete [] lpszBuffer;
  575. // Accept connection
  576. if(nResult == IDYES)
  577. return TRUE;
  578. }
  579. return FALSE;
  580. }
  581. /***********************************************
  582. LoadSecurityLibrary
  583. Load and initialize the security library .
  584. Params
  585. none
  586. Return
  587. TRUE - if success
  588. ************************************************/
  589. BOOL CUT_SecureSocket::LoadSecurityLibrary(void)
  590. {
  591. PSecurityFunctionTable pSecurityFunc;
  592. INIT_SECURITY_INTERFACE pInitSecurityInterface;
  593. // Check if the library was already initialized
  594. if(m_hSecurity != NULL)
  595. return TRUE;
  596. // Load security libarary
  597. m_hSecurity = LoadLibrary(NT_SECURITY_DLL_NAME);
  598. if(m_hSecurity == NULL)
  599. {
  600. // Try to load security DLL for 95/98/ME
  601. m_hSecurity = LoadLibrary(NT_SECURITY_DLL_NAME_98);
  602. if(m_hSecurity == NULL)
  603. {
  604. HandleSecurityError(_T("Error loading security.dll."));
  605. FreeSecurityLibrary();
  606. return FALSE;
  607. }
  608. }
  609. // Get security entry point function
  610. // v4.2 changes - note SECURITY_ENTRYPOINT_ANSIW vs SECURITY_ENTRYPOINT_ANSIA
  611. #if defined _UNICODE
  612. pInitSecurityInterface = (INIT_SECURITY_INTERFACE)GetProcAddress(m_hSecurity, SECURITY_ENTRYPOINT_ANSIW);
  613. #else
  614. pInitSecurityInterface = (INIT_SECURITY_INTERFACE)GetProcAddress(m_hSecurity, SECURITY_ENTRYPOINT_ANSIA);
  615. #endif
  616. if(pInitSecurityInterface == NULL)
  617. {
  618. HandleSecurityError(_T("Error reading InitSecurityInterface entry point."));
  619. FreeSecurityLibrary();
  620. return FALSE;
  621. }
  622. // Get dispatch table that contains pointers to the functions defined in SSPI
  623. pSecurityFunc = pInitSecurityInterface();
  624. if(pSecurityFunc == NULL)
  625. {
  626. HandleSecurityError(_T("Error reading security interface."));
  627. FreeSecurityLibrary();
  628. return FALSE;
  629. }
  630. // Copy the dispatch table
  631. CopyMemory(&m_SecurityFunc, pSecurityFunc, sizeof(m_SecurityFunc));
  632. return TRUE;
  633. }
  634. /***********************************************
  635. FreeSecurityLibrary
  636. Unload the security library .
  637. Params
  638. none
  639. Return
  640. none
  641. ************************************************/
  642. void CUT_SecureSocket::FreeSecurityLibrary(void)
  643. {
  644. // Free security context handle.
  645. if(m_phContext != NULL)
  646. {
  647. m_SecurityFunc.DeleteSecurityContext(m_phContext);
  648. delete m_phContext;
  649. m_phContext = NULL;
  650. }
  651. // Free SSPI credentials handle.
  652. if(m_phCreds != NULL)
  653. {
  654. m_SecurityFunc.FreeCredentialsHandle(m_phCreds);
  655. delete m_phCreds;
  656. m_phCreds = NULL;
  657. }
  658. // Free security library
  659. if(m_hSecurity != NULL)
  660. {
  661. FreeLibrary(m_hSecurity);
  662. m_hSecurity = NULL;
  663. }
  664. // Close certificate store.
  665. if(m_hCertStore != NULL)
  666. {
  667. if(m_bCloseStore)
  668. CertCloseStore(m_hCertStore, 0);
  669. m_hCertStore = NULL;
  670. }
  671. // Free IO buffer memory
  672. if(m_lpszIoBuffer != NULL)
  673. {
  674. LocalFree(m_lpszIoBuffer);
  675. m_lpszIoBuffer = NULL;
  676. }
  677. }
  678. /***********************************************
  679. DisplayWinVerifyTrustError
  680. Get error Process error by code
  681. Params
  682. Status - error code
  683. Return
  684. none
  685. ************************************************/
  686. void CUT_SecureSocket::DisplayWinVerifyTrustError(DWORD Status)
  687. {
  688. LPTSTR pszName = NULL;
  689. _TCHAR szBuffer[1024];
  690. switch(Status)
  691. {
  692. case CERT_E_EXPIRED: pszName = _T("CERT_E_EXPIRED"); break;
  693. case CERT_E_VALIDITYPERIODNESTING: pszName = _T("CERT_E_VALIDITYPERIODNESTING"); break;
  694. case CERT_E_ROLE: pszName = _T("CERT_E_ROLE"); break;
  695. case CERT_E_PATHLENCONST: pszName = _T("CERT_E_PATHLENCONST"); break;
  696. case CERT_E_CRITICAL: pszName = _T("CERT_E_CRITICAL"); break;
  697. case CERT_E_PURPOSE: pszName = _T("CERT_E_PURPOSE"); break;
  698. case CERT_E_ISSUERCHAINING: pszName = _T("CERT_E_ISSUERCHAINING"); break;
  699. case CERT_E_MALFORMED: pszName = _T("CERT_E_MALFORMED"); break;
  700. case CERT_E_UNTRUSTEDROOT: pszName = _T("CERT_E_UNTRUSTEDROOT"); break;
  701. case CERT_E_CHAINING: pszName = _T("CERT_E_CHAINING"); break;
  702. case TRUST_E_FAIL: pszName = _T("TRUST_E_FAIL"); break;
  703. case CERT_E_REVOKED: pszName = _T("CERT_E_REVOKED"); break;
  704. case CERT_E_UNTRUSTEDTESTROOT: pszName = _T("CERT_E_UNTRUSTEDTESTROOT"); break;
  705. case CERT_E_REVOCATION_FAILURE: pszName = _T("CERT_E_REVOCATION_FAILURE"); break;
  706. case CERT_E_CN_NO_MATCH: pszName = _T("CERT_E_CN_NO_MATCH"); break;
  707. case CERT_E_WRONG_USAGE: pszName = _T("CERT_E_WRONG_USAGE"); break;
  708. default: pszName = _T("(unknown)"); break;
  709. }
  710. _sntprintf(szBuffer,sizeof(szBuffer)/sizeof(_TCHAR)-1, _T("Error 0x%x (%s) returned by CertVerifyCertificateChainPolicy!\n"), Status, pszName);
  711. HandleSecurityError(szBuffer);
  712. }
  713. /***********************************************
  714. DisconnectNotify
  715. Notify schannel that we are about to close the connection.
  716. Params
  717. Socket - connected socket
  718. Return
  719. UTE_SUCCESS
  720. UTE_FAILED_TO_APPLY_CONTROL_TOKEN
  721. UTE_FAILED_TO_INITIALIZE_SECURITY_CONTEXT
  722. UTE_SOCK_SEND_ERROR
  723. ************************************************/
  724. int CUT_SecureSocket::DisconnectNotify(SOCKET Socket)
  725. {
  726. DWORD dwType;
  727. PBYTE pbMessage;
  728. DWORD cbMessage;
  729. DWORD cbData;
  730. SecBufferDesc OutBuffer;
  731. SecBuffer OutBuffers[1];
  732. DWORD dwSSPIFlags;
  733. DWORD dwSSPIOutFlags;
  734. TimeStamp tsExpiry;
  735. DWORD Status;
  736. int nError = UTE_SUCCESS;
  737. // Check if we already notified the server
  738. if(m_phContext == NULL)
  739. return UTE_SUCCESS;
  740. // Notify schannel that we are about to close the connection.
  741. dwType = SCHANNEL_SHUTDOWN;
  742. OutBuffers[0].pvBuffer = &dwType;
  743. OutBuffers[0].BufferType = SECBUFFER_TOKEN;
  744. OutBuffers[0].cbBuffer = sizeof(dwType);
  745. OutBuffer.cBuffers = 1;
  746. OutBuffer.pBuffers = OutBuffers;
  747. OutBuffer.ulVersion = SECBUFFER_VERSION;
  748. Status = m_SecurityFunc.ApplyControlToken(m_phContext, &OutBuffer);
  749. if(FAILED(Status))
  750. {
  751. nError = UTE_FAILED_TO_APPLY_CONTROL_TOKEN;
  752. HandleSecurityError(_T("Error returned by ApplyControlToken."));
  753. }
  754. else
  755. {
  756. // Build an SSL close notify message.
  757. dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT |
  758. ISC_REQ_REPLAY_DETECT |
  759. ISC_REQ_CONFIDENTIALITY |
  760. ISC_RET_EXTENDED_ERROR |
  761. ISC_REQ_ALLOCATE_MEMORY |
  762. ISC_REQ_STREAM;
  763. OutBuffers[0].pvBuffer = NULL;
  764. OutBuffers[0].BufferType = SECBUFFER_TOKEN;
  765. OutBuffers[0].cbBuffer = 0;
  766. OutBuffer.cBuffers = 1;
  767. OutBuffer.pBuffers = OutBuffers;
  768. OutBuffer.ulVersion = SECBUFFER_VERSION;
  769. Status = m_SecurityFunc.InitializeSecurityContext(
  770. m_phCreds,
  771. m_phContext,
  772. NULL,
  773. dwSSPIFlags,
  774. 0,
  775. SECURITY_NATIVE_DREP,
  776. NULL,
  777. 0,
  778. m_phContext,
  779. &OutBuffer,
  780. &dwSSPIOutFlags,
  781. &tsExpiry);
  782. if(FAILED(Status))
  783. {
  784. nError = UTE_FAILED_TO_INITIALIZE_SECURITY_CONTEXT;
  785. HandleSecurityError(_T("Failed to initialize the security context."));
  786. }
  787. else
  788. {
  789. pbMessage = (PBYTE)OutBuffers[0].pvBuffer;
  790. cbMessage = OutBuffers[0].cbBuffer;
  791. // Send the close notify message
  792. if(pbMessage != NULL && cbMessage != 0)
  793. {
  794. cbData = send(Socket, (const char *)pbMessage, cbMessage, 0);
  795. if(cbData == SOCKET_ERROR || cbData == 0)
  796. {
  797. Status = WSAGetLastError();
  798. nError = UTE_SOCK_SEND_ERROR;
  799. }
  800. // Free output buffer.
  801. m_SecurityFunc.FreeContextBuffer(pbMessage);
  802. }
  803. }
  804. }
  805. // Free the security context.
  806. m_SecurityFunc.DeleteSecurityContext(m_phContext);
  807. delete m_phContext;
  808. m_phContext = NULL;
  809. return nError;
  810. }
  811. /***********************************************
  812. MessageRecv
  813. Receive message from the secure socket
  814. Params
  815. s - socket to receive data from
  816. Return
  817. UTE_SUCCESS
  818. UTE_SOCK_RECEIVE_ERROR
  819. UTE_FAILED_TO_RECEIVE_SECURITY_MESSAGE
  820. UTE_SECURITY_CONTEXT_EXPIRED
  821. UTE_FAILED_TO_DECRYPT_SECURITY_MESSAGE
  822. ************************************************/
  823. int CUT_SecureSocket::MessageRecv(SOCKET s)
  824. {
  825. DWORD dwIoBuffer = 0;
  826. SecBufferDesc Message;
  827. SecBuffer Buffers[4];
  828. SECURITY_STATUS Status = SEC_E_OK;
  829. DWORD dwData;
  830. SecBuffer * pDataBuffer;
  831. SecBuffer * pExtraBuffer;
  832. SecBuffer ExtraBuffer;
  833. BOOL bCanReadMore = TRUE;
  834. int nError = UTE_SUCCESS;
  835. // Copy extra read data from the previous calls to the function
  836. if(m_lpszExtraReceivedData != NULL)
  837. {
  838. MoveMemory(m_lpszIoBuffer, m_lpszExtraReceivedData, m_dwExtraReceivedDataSize);
  839. dwIoBuffer = m_dwExtraReceivedDataSize;
  840. // Free extra read data
  841. LocalFree(m_lpszExtraReceivedData);
  842. m_lpszExtraReceivedData = NULL;
  843. m_dwExtraReceivedDataSize = 0;
  844. }
  845. // Read data from the socket
  846. // v4.2 changed - was while(TRUE)
  847. for (;;)
  848. {
  849. // Read some data.
  850. if(0 == dwIoBuffer || Status == SEC_E_INCOMPLETE_MESSAGE)
  851. {
  852. // Check if we need to read more data
  853. if(!bCanReadMore)
  854. {
  855. // Save extra read data
  856. if(m_lpszExtraReceivedData != NULL)
  857. LocalFree(m_lpszExtraReceivedData);
  858. m_lpszExtraReceivedData = (char *)LocalAlloc(LMEM_FIXED, dwIoBuffer + 10);
  859. MoveMemory(m_lpszExtraReceivedData, m_lpszIoBuffer, dwIoBuffer);
  860. m_dwExtraReceivedDataSize = dwIoBuffer;
  861. return UTE_SUCCESS;
  862. }
  863. // Read more data
  864. dwData = recv(s, m_lpszIoBuffer + dwIoBuffer,
  865. m_dwIoBufferLength - dwIoBuffer, 0);
  866. if(dwData == SOCKET_ERROR)
  867. {
  868. HandleSecurityError(_T("Error reading secure data from the server."));
  869. return UTE_SOCK_RECEIVE_ERROR;
  870. }
  871. else if(dwData == 0)
  872. {
  873. // Server disconnected.
  874. if(dwIoBuffer)
  875. {
  876. HandleSecurityError(_T("Server unexpectedly disconnected."));
  877. return UTE_FAILED_TO_RECEIVE_SECURITY_MESSAGE;
  878. }
  879. else
  880. {
  881. break;
  882. }
  883. }
  884. else
  885. {
  886. dwIoBuffer += dwData;
  887. }
  888. }
  889. // Attempt to decrypt the received data.
  890. Buffers[0].pvBuffer = m_lpszIoBuffer;
  891. Buffers[0].cbBuffer = dwIoBuffer;
  892. Buffers[0].BufferType = SECBUFFER_DATA;
  893. Buffers[1].BufferType = SECBUFFER_EMPTY;
  894. Buffers[2].BufferType = SECBUFFER_EMPTY;
  895. Buffers[3].BufferType = SECBUFFER_EMPTY;
  896. Message.ulVersion = SECBUFFER_VERSION;
  897. Message.cBuffers = 4;
  898. Message.pBuffers = Buffers;
  899. Status = m_SecurityFunc.DecryptMessage(m_phContext, &Message, 0, NULL);
  900. if(Status == SEC_E_INCOMPLETE_MESSAGE)
  901. {
  902. // The input buffer contains only a fragment of an
  903. // encrypted record. Loop around and read some more data.
  904. continue;
  905. }
  906. // Server signalled end of session
  907. if( Status == SEC_I_CONTEXT_EXPIRED || Status == SEC_E_CONTEXT_EXPIRED )
  908. {
  909. // nError = UTE_SECURITY_CONTEXT_EXPIRED;
  910. break;
  911. }
  912. if( Status != SEC_E_OK &&
  913. Status != SEC_I_RENEGOTIATE &&
  914. Status != SEC_E_CONTEXT_EXPIRED &&
  915. Status != SEC_I_CONTEXT_EXPIRED
  916. )
  917. {
  918. HandleSecurityError(_T("Failed to decrypt security message."));
  919. return UTE_FAILED_TO_DECRYPT_SECURITY_MESSAGE;
  920. }
  921. // Locate data and (optional) extra buffers.
  922. pDataBuffer = NULL;
  923. pExtraBuffer = NULL;
  924. for(int i = 1; i < 4; i++)
  925. {
  926. if(pDataBuffer == NULL && Buffers[i].BufferType == SECBUFFER_DATA)
  927. {
  928. pDataBuffer = &Buffers[i];
  929. }
  930. if(pExtraBuffer == NULL && Buffers[i].BufferType == SECBUFFER_EXTRA)
  931. {
  932. pExtraBuffer = &Buffers[i];
  933. }
  934. }
  935. // Check decoded data buffer size
  936. if(pDataBuffer->cbBuffer > (m_dwDecodedDataMaxSize - m_dwDecodedDataSize))
  937. {
  938. HandleSecurityError(_T("Decrypted data buffer overflow."));
  939. return UTE_FAILED_TO_DECRYPT_SECURITY_MESSAGE;
  940. }
  941. // Move received and decoded data into the buffer
  942. MoveMemory( m_lpszDecodedData + m_dwDecodedDataSize,
  943. pDataBuffer->pvBuffer,
  944. pDataBuffer->cbBuffer);
  945. m_dwDecodedDataSize += pDataBuffer->cbBuffer;
  946. // Do not read any more data from the socket
  947. // We'll do it only on the next call to the MessageRecv
  948. bCanReadMore = FALSE;
  949. // Move any "extra" data to the input buffer.
  950. if(pExtraBuffer)
  951. {
  952. MoveMemory(m_lpszIoBuffer, pExtraBuffer->pvBuffer, pExtraBuffer->cbBuffer);
  953. dwIoBuffer = pExtraBuffer->cbBuffer;
  954. }
  955. else
  956. {
  957. dwIoBuffer = 0;
  958. }
  959. // The server wants to perform another handshake sequence.
  960. if(Status == SEC_I_RENEGOTIATE)
  961. {
  962. int nError = HandshakeLoop(s, FALSE, &ExtraBuffer);
  963. if(nError != UTE_SUCCESS)
  964. return nError;
  965. // Move any "extra" data to the input buffer.
  966. if(ExtraBuffer.pvBuffer)
  967. {
  968. MoveMemory(m_lpszIoBuffer, ExtraBuffer.pvBuffer, ExtraBuffer.cbBuffer);
  969. dwIoBuffer = ExtraBuffer.cbBuffer;
  970. }
  971. }
  972. }
  973. return nError;
  974. }
  975. // ===================================================================
  976. // CUT_SecureSocketClient class
  977. // ===================================================================
  978. /***********************************************
  979. CUT_SecureSocketClient
  980. Constructor
  981. Params
  982. none
  983. Return
  984. none
  985. ************************************************/
  986. CUT_SecureSocketClient::CUT_SecureSocketClient() :
  987. m_aiKeyExch(0)
  988. {
  989. }
  990. /***********************************************
  991. ~CUT_SecureSocketClient
  992. Destructor
  993. Params
  994. none
  995. Return
  996. none
  997. ************************************************/
  998. CUT_SecureSocketClient::~CUT_SecureSocketClient()
  999. {
  1000. }
  1001. /***********************************************
  1002. CreateCredentials
  1003. Create security credentials
  1004. Params
  1005. Credentials are Data used by a principal to establish its own identity, such as
  1006. a password, or a Kerberos protocol ticket
  1007. SSPI credential functions enable applications to gain access
  1008. to the credentials of a principal and to free such access.
  1009. Schannel credentials are based on the X.509 certificate.
  1010. Schannel still supports version 1 certificates, but using version 3
  1011. certificates is recommended. Schannel does not perform certificate management.
  1012. It relies on the application to perform certificate management using
  1013. CryptoAPI functions.
  1014. Return
  1015. UTE_SUCCESS
  1016. UTE_OPEN_CERTIFICATE_STORE_FAILED
  1017. UTE_OUT_OF_MEMORY
  1018. UTE_PARAMETER_INVALID_VALUE
  1019. UTE_FAILED_TO_FIND_CERTIFICATE
  1020. UTE_FAILED_TO_CREATE_SECURITY_CREDENTIALS
  1021. ************************************************/
  1022. int CUT_SecureSocketClient::CreateCredentials()
  1023. {
  1024. TimeStamp tsExpiry;
  1025. SECURITY_STATUS Status;
  1026. DWORD dwSupportedAlgs = 0;
  1027. ALG_ID rgbSupportedAlgs[16];
  1028. PCCERT_CONTEXT pCertContext = NULL;
  1029. // If certificate context was set
  1030. if(m_Certificate.GetContext() != NULL)
  1031. {
  1032. pCertContext = CertDuplicateCertificateContext(m_Certificate.GetContext());
  1033. if(m_bCloseStore)
  1034. CertCloseStore(m_hCertStore, 0);
  1035. m_hCertStore = pCertContext->hCertStore;
  1036. m_bCloseStore = FALSE;
  1037. }
  1038. else
  1039. {
  1040. // Open the certificate store, which is where Internet Explorer
  1041. // stores its client certificates.
  1042. if(m_hCertStore == NULL)
  1043. {
  1044. // Open the system certificate store
  1045. m_hCertStore = CertOpenSystemStore(0, m_szCertStoreName);
  1046. if(m_hCertStore == NULL)
  1047. {
  1048. HandleSecurityError(_T("Failed to open system certificate store."));
  1049. return UTE_OPEN_CERTIFICATE_STORE_FAILED;
  1050. }
  1051. m_bCloseStore = TRUE;
  1052. }
  1053. // If a user name is specified, then attempt to find a client
  1054. // certificate. Otherwise, just create a NULL credential.
  1055. if(*m_szCertSubjStr != NULL)
  1056. {
  1057. // Find client certificate.
  1058. pCertContext = CertFindCertificateInStore(m_hCertStore,
  1059. X509_ASN_ENCODING,
  1060. 0,
  1061. CERT_FIND_SUBJECT_STR_A,
  1062. m_szCertSubjStr,
  1063. NULL);
  1064. if(pCertContext == NULL)
  1065. {
  1066. HandleSecurityError(_T("Failed to find the certificate."));
  1067. return UTE_FAILED_TO_FIND_CERTIFICATE;
  1068. }
  1069. }
  1070. }
  1071. // Check if certificate valid
  1072. if(pCertContext && CertVerifyTimeValidity(NULL, pCertContext->pCertInfo) != 0)
  1073. {
  1074. // Free the certificate context.
  1075. if(pCertContext)
  1076. CertFreeCertificateContext(pCertContext);
  1077. HandleSecurityError(_T("Security certificate date is not valid."));
  1078. return UTE_CERTIFICATE_INVALID_DATE;
  1079. }
  1080. // Build Schannel credential structure.
  1081. ZeroMemory(&m_SchannelCred, sizeof(m_SchannelCred));
  1082. m_SchannelCred.dwVersion = SCHANNEL_CRED_VERSION;
  1083. // Set credential certificate
  1084. if(pCertContext)
  1085. {
  1086. m_SchannelCred.cCreds = 1;
  1087. m_SchannelCred.paCred = &pCertContext;
  1088. }
  1089. // Set the protocol
  1090. m_SchannelCred.grbitEnabledProtocols = m_dwProtocol;
  1091. // Set the algorithm ID
  1092. if(m_aiKeyExch)
  1093. {
  1094. rgbSupportedAlgs[dwSupportedAlgs++] = m_aiKeyExch;
  1095. m_SchannelCred.cSupportedAlgs = dwSupportedAlgs;
  1096. m_SchannelCred.palgSupportedAlgs = rgbSupportedAlgs;
  1097. }
  1098. m_SchannelCred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS;
  1099. m_SchannelCred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION;
  1100. // Set cipher strength
  1101. m_SchannelCred.dwMaximumCipherStrength = m_dwMaxCipherStrength;
  1102. m_SchannelCred.dwMinimumCipherStrength = m_dwMinCipherStrength;
  1103. // Free SSPI credentials handle (if we create it before) or create a new one
  1104. if(m_phCreds != NULL)
  1105. m_SecurityFunc.FreeCredentialsHandle(m_phCreds);
  1106. else
  1107. m_phCreds = new CredHandle;
  1108. // Create an SSPI credential.
  1109. //
  1110. // Data used by a principal to establish its own identity, such as
  1111. // a password, or a Kerberos protocol ticket
  1112. // SSPI credential functions enable applications to gain access
  1113. // to the credentials of a principal and to free such access.
  1114. // Schannel credentials are based on the X.509 certificate.
  1115. // Schannel still supports version 1 certificates, but using version 3
  1116. // certificates is recommended. Schannel does not perform certificate management.
  1117. // It relies on the application to perform certificate management using CryptoAPI functions
  1118. Status = m_SecurityFunc.AcquireCredentialsHandle(
  1119. NULL, // Name of principal
  1120. UNISP_NAME, // Name of package
  1121. SECPKG_CRED_OUTBOUND, // Flags indicating use
  1122. NULL, // Pointer to logon ID
  1123. &m_SchannelCred, // Package specific data
  1124. NULL, // Pointer to GetKey() func
  1125. NULL, // Value to pass to GetKey()
  1126. m_phCreds, // (out) Cred Handle
  1127. &tsExpiry); // (out) Lifetime (optional)
  1128. // Free the certificate context.
  1129. if(pCertContext)
  1130. CertFreeCertificateContext(pCertContext);
  1131. // Check status
  1132. if(Status != SEC_E_OK)
  1133. {
  1134. HandleSecurityError(_T("Failed to acquire credentials handle."));
  1135. delete m_phCreds;
  1136. m_phCreds = NULL;
  1137. return UTE_FAILED_TO_CREATE_SECURITY_CREDENTIALS;
  1138. }
  1139. return UTE_SUCCESS;
  1140. }
  1141. /***********************************************
  1142. PerformHandshake
  1143. Perform client handshake
  1144. Params
  1145. Socket - connected socket
  1146. le - server name
  1147. pExtraData - extra data returned by handshake
  1148. Return
  1149. UTE_SUCCESS
  1150. UTE_FAILED_TO_INITIALIZE_SECURITY_CONTEXT
  1151. UTE_SOCK_SEND_ERROR
  1152. ************************************************/
  1153. int CUT_SecureSocketClient::PerformHandshake(
  1154. SOCKET Socket, // in
  1155. const _TCHAR * lpszServerName, // in
  1156. SecBuffer * pExtraData) // out
  1157. {
  1158. SecBufferDesc OutBuffer;
  1159. SecBuffer OutBuffers[1];
  1160. DWORD dwSSPIFlags;
  1161. DWORD dwSSPIOutFlags;
  1162. TimeStamp tsExpiry;
  1163. SECURITY_STATUS scRet;
  1164. DWORD cbData;
  1165. dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT |
  1166. ISC_REQ_REPLAY_DETECT |
  1167. ISC_REQ_CONFIDENTIALITY |
  1168. ISC_RET_EXTENDED_ERROR |
  1169. ISC_REQ_ALLOCATE_MEMORY |
  1170. ISC_REQ_STREAM;
  1171. // Initiate a ClientHello message and generate a token.
  1172. OutBuffers[0].pvBuffer = NULL;
  1173. OutBuffers[0].BufferType = SECBUFFER_TOKEN;
  1174. OutBuffers[0].cbBuffer = 0;
  1175. OutBuffer.cBuffers = 1;
  1176. OutBuffer.pBuffers = OutBuffers;
  1177. OutBuffer.ulVersion = SECBUFFER_VERSION;
  1178. // Create new or delete old context
  1179. if(m_phContext != NULL)
  1180. m_SecurityFunc.DeleteSecurityContext(m_phContext);
  1181. else
  1182. m_phContext = new CtxtHandle;
  1183. scRet = m_SecurityFunc.InitializeSecurityContext(
  1184. m_phCreds,
  1185. NULL,
  1186. (_TCHAR*)lpszServerName,
  1187. dwSSPIFlags,
  1188. 0,
  1189. SECURITY_NATIVE_DREP,
  1190. NULL,
  1191. 0,
  1192. m_phContext,
  1193. &OutBuffer,
  1194. &dwSSPIOutFlags,
  1195. &tsExpiry);
  1196. if(scRet != SEC_I_CONTINUE_NEEDED)
  1197. {
  1198. HandleSecurityError(_T("Failed to initialize security context."));
  1199. delete m_phCreds;
  1200. m_phCreds = NULL;
  1201. return UTE_FAILED_TO_INITIALIZE_SECURITY_CONTEXT;
  1202. }
  1203. // Send response to server if there is one.
  1204. if(OutBuffers[0].cbBuffer != 0 && OutBuffers[0].pvBuffer != NULL)
  1205. {
  1206. cbData = send(Socket, (const char *)OutBuffers[0].pvBuffer, OutBuffers[0].cbBuffer, 0);
  1207. if(cbData == SOCKET_ERROR || cbData == 0)
  1208. {
  1209. HandleSecurityError(_T("Error sending secure data to the server."));
  1210. m_SecurityFunc.FreeContextBuffer(OutBuffers[0].pvBuffer);
  1211. m_SecurityFunc.DeleteSecurityContext(m_phContext);
  1212. return UTE_SOCK_SEND_ERROR;
  1213. }
  1214. // Free output buffer.
  1215. m_SecurityFunc.FreeContextBuffer(OutBuffers[0].pvBuffer);
  1216. OutBuffers[0].pvBuffer = NULL;
  1217. }
  1218. return HandshakeLoop(Socket, TRUE, pExtraData);
  1219. }
  1220. /***********************************************
  1221. HandshakeLoop
  1222. Helper function used in the handshake
  1223. Params
  1224. Socket - connected socket
  1225. fDoInitialRead - should read first
  1226. pExtraData - extra data returned by handshake
  1227. Return
  1228. UTE_SUCCESS
  1229. UTE_OUT_OF_MEMORY
  1230. UTE_SOCK_RECEIVE_ERROR
  1231. UTE_SOCK_SEND_ERROR
  1232. UTE_FAILED_TO_INITIALIZE_SECURITY_CONTEXT
  1233. ************************************************/
  1234. int CUT_SecureSocketClient::HandshakeLoop(
  1235. SOCKET Socket, // in
  1236. BOOL fDoInitialRead, // in
  1237. SecBuffer * pExtraData) // out
  1238. {
  1239. SecBufferDesc InBuffer;
  1240. SecBuffer InBuffers[2];
  1241. SecBufferDesc OutBuffer;
  1242. SecBuffer OutBuffers[1];
  1243. DWORD dwSSPIFlags;
  1244. DWORD dwSSPIOutFlags;
  1245. TimeStamp tsExpiry;
  1246. SECURITY_STATUS scRet;
  1247. DWORD cbData;
  1248. PUCHAR IoBuffer;
  1249. DWORD dwIoBuffer;
  1250. BOOL bDoRead;
  1251. int nError = UTE_SUCCESS;
  1252. dwSSPIFlags = ISC_REQ_SEQUENCE_DETECT |
  1253. ISC_REQ_REPLAY_DETECT |
  1254. ISC_REQ_CONFIDENTIALITY |
  1255. ISC_RET_EXTENDED_ERROR |
  1256. ISC_REQ_ALLOCATE_MEMORY |
  1257. ISC_REQ_STREAM;
  1258. // Allocate data buffer.
  1259. IoBuffer = (PUCHAR)LocalAlloc(LMEM_FIXED, IO_BUFFER_SIZE);
  1260. if(IoBuffer == NULL)
  1261. return UTE_OUT_OF_MEMORY;
  1262. dwIoBuffer = 0;
  1263. bDoRead = fDoInitialRead;
  1264. // Loop until the handshake is finished or an error occurs.
  1265. scRet = SEC_I_CONTINUE_NEEDED;
  1266. while(scRet == SEC_I_CONTINUE_NEEDED ||
  1267. scRet == SEC_E_INCOMPLETE_MESSAGE ||
  1268. scRet == SEC_I_INCOMPLETE_CREDENTIALS)
  1269. {
  1270. // Read data from server.
  1271. if(dwIoBuffer == 0 || scRet == SEC_E_INCOMPLETE_MESSAGE)
  1272. {
  1273. if(bDoRead)
  1274. {
  1275. cbData = recv(Socket, (char *)IoBuffer + dwIoBuffer, IO_BUFFER_SIZE - dwIoBuffer, 0);
  1276. if(cbData == SOCKET_ERROR || cbData == 0)
  1277. {
  1278. HandleSecurityError(_T("Error reading secure data from the server."));
  1279. nError = UTE_SOCK_RECEIVE_ERROR;
  1280. break;
  1281. }
  1282. dwIoBuffer += cbData;
  1283. }
  1284. else
  1285. {
  1286. bDoRead = TRUE;
  1287. }
  1288. }
  1289. // Set up the input buffers. Buffer 0 is used to pass in data
  1290. // received from the server. Schannel will consume some or all
  1291. // of this. Leftover data (if any) will be placed in buffer 1 and
  1292. // given a buffer type of SECBUFFER_EXTRA.
  1293. InBuffers[0].pvBuffer = IoBuffer;
  1294. InBuffers[0].cbBuffer = dwIoBuffer;
  1295. InBuffers[0].BufferType = SECBUFFER_TOKEN;
  1296. InBuffers[1].pvBuffer = NULL;
  1297. InBuffers[1].cbBuffer = 0;
  1298. InBuffers[1].BufferType = SECBUFFER_EMPTY;
  1299. InBuffer.cBuffers = 2;
  1300. InBuffer.pBuffers = InBuffers;
  1301. InBuffer.ulVersion = SECBUFFER_VERSION;
  1302. // Set up the output buffers. These are initialized to NULL
  1303. // so as to make it less likely we'll attempt to free random
  1304. // garbage later.
  1305. OutBuffers[0].pvBuffer = NULL;
  1306. OutBuffers[0].BufferType= SECBUFFER_TOKEN;
  1307. OutBuffers[0].cbBuffer = 0;
  1308. OutBuffer.cBuffers = 1;
  1309. OutBuffer.pBuffers = OutBuffers;
  1310. OutBuffer.ulVersion = SECBUFFER_VERSION;
  1311. // Call InitializeSecurityContext.
  1312. scRet = m_SecurityFunc.InitializeSecurityContext(m_phCreds,
  1313. m_phContext,
  1314. NULL,
  1315. dwSSPIFlags,
  1316. 0,
  1317. SECURITY_NATIVE_DREP,
  1318. &InBuffer,
  1319. 0,
  1320. NULL,
  1321. &OutBuffer,
  1322. &dwSSPIOutFlags,
  1323. &tsExpiry);
  1324. // If InitializeSecurityContext was successful (or if the error was
  1325. // one of the special extended ones), send the contends of the output
  1326. // buffer to the server.
  1327. if(scRet == SEC_E_OK ||
  1328. scRet == SEC_I_CONTINUE_NEEDED ||
  1329. FAILED(scRet) && (dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR))
  1330. {
  1331. if(OutBuffers[0].cbBuffer != 0 && OutBuffers[0].pvBuffer != NULL)
  1332. {
  1333. cbData = send(Socket, (const char *)OutBuffers[0].pvBuffer, OutBuffers[0].cbBuffer, 0);
  1334. if(cbData == SOCKET_ERROR || cbData == 0)
  1335. {
  1336. HandleSecurityError(_T("Error secure sending data to the server."));
  1337. m_SecurityFunc.FreeContextBuffer(OutBuffers[0].pvBuffer);
  1338. m_SecurityFunc.DeleteSecurityContext(m_phContext);
  1339. return UTE_SOCK_SEND_ERROR;
  1340. }
  1341. // Free output buffer.
  1342. m_SecurityFunc.FreeContextBuffer(OutBuffers[0].pvBuffer);
  1343. OutBuffers[0].pvBuffer = NULL;
  1344. }
  1345. }
  1346. // If InitializeSecurityContext returned SEC_E_INCOMPLETE_MESSAGE,
  1347. // then we need to read more data from the server and try again.
  1348. if(scRet == SEC_E_INCOMPLETE_MESSAGE)
  1349. {
  1350. continue;
  1351. }
  1352. // If InitializeSecurityContext returned SEC_E_OK, then the
  1353. // handshake completed successfully.
  1354. if(scRet == SEC_E_OK)
  1355. {
  1356. // If the "extra" buffer contains data, this is encrypted application
  1357. // protocol layer stuff. It needs to be saved. The application layer
  1358. // will later decrypt it with DecryptMessage.
  1359. if(InBuffers[1].BufferType == SECBUFFER_EXTRA)
  1360. {
  1361. pExtraData->pvBuffer = LocalAlloc(LMEM_FIXED, InBuffers[1].cbBuffer);
  1362. if(pExtraData->pvBuffer == NULL)
  1363. {
  1364. HandleSecurityError(_T("Out of memory."));
  1365. return UTE_OUT_OF_MEMORY;
  1366. }
  1367. MoveMemory(pExtraData->pvBuffer,
  1368. IoBuffer + (dwIoBuffer - InBuffers[1].cbBuffer),
  1369. InBuffers[1].cbBuffer);
  1370. pExtraData->cbBuffer = InBuffers[1].cbBuffer;
  1371. pExtraData->BufferType = SECBUFFER_TOKEN;
  1372. }
  1373. else
  1374. {
  1375. pExtraData->pvBuffer = NULL;
  1376. pExtraData->cbBuffer = 0;
  1377. pExtraData->BufferType = SECBUFFER_EMPTY;
  1378. }
  1379. // Quit
  1380. nError = UTE_SUCCESS;
  1381. break;
  1382. }
  1383. // Check for fatal error.
  1384. if(FAILED(scRet))
  1385. {
  1386. HandleSecurityError(_T("Failed to initialize security context."));
  1387. nError = UTE_FAILED_TO_INITIALIZE_SECURITY_CONTEXT;
  1388. break;
  1389. }
  1390. // If InitializeSecurityContext returned SEC_I_INCOMPLETE_CREDENTIALS,
  1391. // then the server just requested client authentication.
  1392. if(scRet == SEC_I_INCOMPLETE_CREDENTIALS)
  1393. {
  1394. // Display trusted issuers info.
  1395. GetNewCredentials();
  1396. // Go around again.
  1397. bDoRead = FALSE;
  1398. scRet = SEC_I_CONTINUE_NEEDED;
  1399. continue;
  1400. }
  1401. // Copy any leftover data from the "extra" buffer, and go around again
  1402. if ( InBuffers[1].BufferType == SECBUFFER_EXTRA )
  1403. {
  1404. MoveMemory(IoBuffer,
  1405. IoBuffer + (dwIoBuffer - InBuffers[1].cbBuffer),
  1406. InBuffers[1].cbBuffer);
  1407. dwIoBuffer = InBuffers[1].cbBuffer;
  1408. }
  1409. else
  1410. {
  1411. dwIoBuffer = 0;
  1412. }
  1413. }
  1414. // Delete the security context in the case of a fatal error.
  1415. if(FAILED(scRet))
  1416. m_SecurityFunc.DeleteSecurityContext(m_phContext);
  1417. LocalFree(IoBuffer);
  1418. return nError;
  1419. }
  1420. /***********************************************
  1421. GetNewCredentials
  1422. Helper function used in the handshake
  1423. Params
  1424. none
  1425. Return
  1426. SECURITY_STATUS
  1427. ************************************************/
  1428. void CUT_SecureSocketClient::GetNewCredentials()
  1429. {
  1430. SecPkgContext_IssuerListInfoEx IssuerListInfo;
  1431. CERT_CHAIN_FIND_BY_ISSUER_PARA FindByIssuerPara;
  1432. PCCERT_CHAIN_CONTEXT pChainContext;
  1433. CredHandle hCreds;
  1434. PCCERT_CONTEXT pCertContext;
  1435. TimeStamp tsExpiry;
  1436. SECURITY_STATUS Status;
  1437. // Read list of trusted issuers from schannel.
  1438. Status = m_SecurityFunc.QueryContextAttributes(m_phContext,
  1439. SECPKG_ATTR_ISSUER_LIST_EX,
  1440. (PVOID)&IssuerListInfo);
  1441. if(Status != SEC_E_OK)
  1442. {
  1443. m_SecurityFunc.FreeContextBuffer((PVOID)&IssuerListInfo);
  1444. HandleSecurityError(_T("Error querying issuer list info."));
  1445. return;
  1446. }
  1447. // Enumerate the client certificates.
  1448. ZeroMemory(&FindByIssuerPara, sizeof(FindByIssuerPara));
  1449. FindByIssuerPara.cbSize = sizeof(FindByIssuerPara);
  1450. FindByIssuerPara.pszUsageIdentifier = szOID_PKIX_KP_CLIENT_AUTH;
  1451. FindByIssuerPara.dwKeySpec = 0;
  1452. FindByIssuerPara.cIssuer = IssuerListInfo.cIssuers;
  1453. FindByIssuerPara.rgIssuer = IssuerListInfo.aIssuers;
  1454. pChainContext = NULL;
  1455. // v4.2 changed - was while(TRUE)
  1456. for (;;)
  1457. {
  1458. // Find a certificate chain.
  1459. pChainContext = CertFindChainInStore(m_hCertStore,
  1460. X509_ASN_ENCODING,
  1461. 0,
  1462. CERT_CHAIN_FIND_BY_ISSUER,
  1463. &FindByIssuerPara,
  1464. pChainContext);
  1465. if(pChainContext == NULL)
  1466. {
  1467. HandleSecurityError(_T("Error finding certificate chain."));
  1468. break;
  1469. }
  1470. // Get pointer to leaf certificate context.
  1471. pCertContext = pChainContext->rgpChain[0]->rgpElement[0]->pCertContext;
  1472. // Create schannel credential.
  1473. m_SchannelCred.cCreds = 1;
  1474. m_SchannelCred.paCred = &pCertContext;
  1475. // Set cipher strength
  1476. m_SchannelCred.dwMaximumCipherStrength = m_dwMaxCipherStrength;
  1477. m_SchannelCred.dwMinimumCipherStrength = m_dwMinCipherStrength;
  1478. Status = m_SecurityFunc.AcquireCredentialsHandle(
  1479. NULL, // Name of principal
  1480. UNISP_NAME, // Name of package
  1481. SECPKG_CRED_OUTBOUND, // Flags indicating use
  1482. NULL, // Pointer to logon ID
  1483. &m_SchannelCred, // Package specific data
  1484. NULL, // Pointer to GetKey() func
  1485. NULL, // Value to pass to GetKey()
  1486. &hCreds, // (out) Cred Handle
  1487. &tsExpiry); // (out) Lifetime (optional)
  1488. if(Status != SEC_E_OK)
  1489. {
  1490. HandleSecurityError(_T("Failed to acquire credentials handle."));
  1491. continue;
  1492. }
  1493. // Destroy the old credentials.
  1494. m_SecurityFunc.FreeCredentialsHandle(m_phCreds);
  1495. *m_phCreds = hCreds;
  1496. break;
  1497. }
  1498. m_SecurityFunc.FreeContextBuffer((PVOID)&IssuerListInfo);
  1499. }
  1500. /***********************************************
  1501. VerifyCertificate
  1502. Verifies server's sertificate
  1503. Params
  1504. pszServerName - server's name
  1505. dwCertFlags - sertificate flags
  1506. Return
  1507. UTE_SUCCESS
  1508. UTE_OUT_OF_MEMORY
  1509. UTE_FAILED_TO_QUERY_CERTIFICATE
  1510. UTE_NULL_PARAM
  1511. UTE_PARAMETER_INVALID_VALUE
  1512. UTE_FAILED_TO_GET_CERTIFICATE_CHAIN
  1513. UTE_FAILED_TO_VERIFY_CERTIFICATE_CHAIN
  1514. UTE_FAILED_TO_VERIFY_CERTIFICATE_TRUST
  1515. ************************************************/
  1516. int CUT_SecureSocketClient::VerifyCertificate(
  1517. PTSTR pszServerName,
  1518. DWORD dwCertFlags)
  1519. {
  1520. HTTPSPolicyCallbackData polHttps;
  1521. CERT_CHAIN_POLICY_PARA PolicyPara;
  1522. CERT_CHAIN_POLICY_STATUS PolicyStatus;
  1523. CERT_CHAIN_PARA ChainPara;
  1524. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  1525. PCCERT_CONTEXT pRemoteCertContext = NULL;
  1526. DWORD Status;
  1527. PWSTR pwszServerName;
  1528. int nError = UTE_SUCCESS;
  1529. // Client authentication flag not set
  1530. if(m_CertValidation == CERT_DONOT_VERIFY)
  1531. return UTE_SUCCESS;
  1532. // Get server's certificate.
  1533. Status = m_SecurityFunc.QueryContextAttributes(m_phContext,
  1534. SECPKG_ATTR_REMOTE_CERT_CONTEXT,
  1535. (PVOID)&pRemoteCertContext);
  1536. if(Status != SEC_E_OK)
  1537. {
  1538. HandleSecurityError(_T("Error querying remote certificate."));
  1539. CertFreeCertificateContext(pRemoteCertContext);
  1540. pRemoteCertContext = NULL;
  1541. return UTE_FAILED_TO_QUERY_CERTIFICATE;
  1542. }
  1543. if(pszServerName == NULL || _tcslen(pszServerName) == 0)
  1544. return UTE_NULL_PARAM;
  1545. // v4.2 changes - previous code all ascii
  1546. #if !defined _UNICODE
  1547. // Convert server name to unicode.
  1548. DWORD cchServerName;
  1549. cchServerName = MultiByteToWideChar(CP_ACP, 0, pszServerName, -1, NULL, 0);
  1550. pwszServerName = (PWSTR)LocalAlloc(LMEM_FIXED, cchServerName * sizeof(WCHAR));
  1551. if(pwszServerName == NULL)
  1552. {
  1553. if (pRemoteCertContext)
  1554. {
  1555. CertFreeCertificateContext(pRemoteCertContext);
  1556. pRemoteCertContext = NULL;
  1557. }
  1558. return UTE_OUT_OF_MEMORY;
  1559. }
  1560. cchServerName = MultiByteToWideChar(CP_ACP, 0, pszServerName, -1, pwszServerName, cchServerName);
  1561. if(cchServerName == 0)
  1562. {
  1563. // Free memory
  1564. LocalFree(pwszServerName);
  1565. if (pRemoteCertContext)
  1566. {
  1567. CertFreeCertificateContext(pRemoteCertContext);
  1568. pRemoteCertContext = NULL;
  1569. }
  1570. return UTE_PARAMETER_INVALID_VALUE;
  1571. }
  1572. #else
  1573. pwszServerName = (PWSTR)LocalAlloc(LMEM_FIXED, _tcslen(pszServerName) * sizeof(WCHAR) + sizeof(WCHAR));
  1574. _tcscpy(pwszServerName, pszServerName);
  1575. #endif
  1576. // Build certificate chain.
  1577. ZeroMemory(&ChainPara, sizeof(ChainPara));
  1578. ChainPara.cbSize = sizeof(ChainPara);
  1579. if(!CertGetCertificateChain(
  1580. NULL,
  1581. pRemoteCertContext,
  1582. NULL,
  1583. pRemoteCertContext->hCertStore,
  1584. &ChainPara,
  1585. 0,
  1586. NULL,
  1587. &pChainContext))
  1588. {
  1589. Status = GetLastError();
  1590. nError = UTE_FAILED_TO_GET_CERTIFICATE_CHAIN;
  1591. HandleSecurityError(_T("Failed to get the certificate chain."));
  1592. }
  1593. else
  1594. {
  1595. // Validate certificate chain.
  1596. ZeroMemory(&polHttps, sizeof(HTTPSPolicyCallbackData));
  1597. polHttps.cbStruct = sizeof(HTTPSPolicyCallbackData);
  1598. polHttps.dwAuthType = AUTHTYPE_SERVER;
  1599. polHttps.fdwChecks = dwCertFlags;
  1600. polHttps.pwszServerName = pwszServerName;
  1601. memset(&PolicyPara, 0, sizeof(PolicyPara));
  1602. PolicyPara.cbSize = sizeof(PolicyPara);
  1603. PolicyPara.pvExtraPolicyPara = &polHttps;
  1604. memset(&PolicyStatus, 0, sizeof(PolicyStatus));
  1605. PolicyStatus.cbSize = sizeof(PolicyStatus);
  1606. if(!CertVerifyCertificateChainPolicy(
  1607. CERT_CHAIN_POLICY_SSL,
  1608. pChainContext,
  1609. &PolicyPara,
  1610. &PolicyStatus))
  1611. {
  1612. Status = GetLastError();
  1613. nError = UTE_FAILED_TO_VERIFY_CERTIFICATE_CHAIN;
  1614. HandleSecurityError(_T("Failed to verify certificate chain policy."));
  1615. }
  1616. else
  1617. {
  1618. nError = UTE_SUCCESS;
  1619. if(PolicyStatus.dwError)
  1620. {
  1621. // if(!OnCertVerifyError(CUT_Certificate(pRemoteCertContext), PolicyStatus.dwError, pszServerName))
  1622. // v4.2 changed to avert warning")
  1623. CUT_Certificate cert(pRemoteCertContext);
  1624. if(!OnCertVerifyError(cert, PolicyStatus.dwError, pszServerName))
  1625. {
  1626. Status = PolicyStatus.dwError;
  1627. nError = UTE_FAILED_TO_VERIFY_CERTIFICATE_TRUST;
  1628. DisplayWinVerifyTrustError(Status);
  1629. }
  1630. }
  1631. }
  1632. // Free memory
  1633. LocalFree(pwszServerName);
  1634. }
  1635. // Prevent Memory leak of LSAHost of Win2000
  1636. if (pRemoteCertContext)
  1637. {
  1638. CertFreeCertificateContext(pRemoteCertContext);
  1639. pRemoteCertContext = NULL;
  1640. }
  1641. return nError;
  1642. }
  1643. // ===================================================================
  1644. // CUT_SecureSocketServer class
  1645. // ===================================================================
  1646. /***********************************************
  1647. CUT_SecureSocketServer
  1648. Constructor
  1649. Params
  1650. none
  1651. Return
  1652. none
  1653. ************************************************/
  1654. CUT_SecureSocketServer::CUT_SecureSocketServer() :
  1655. m_bMachineStore(FALSE),
  1656. m_bClientAuth(FALSE)
  1657. {
  1658. // No certificate validation on the server by default
  1659. m_CertValidation = CERT_DONOT_VERIFY;
  1660. }
  1661. /***********************************************
  1662. ~CUT_SecureSocketServer
  1663. Destructor
  1664. Params
  1665. none
  1666. Return
  1667. none
  1668. ************************************************/
  1669. CUT_SecureSocketServer::~CUT_SecureSocketServer()
  1670. {
  1671. }
  1672. /***********************************************
  1673. CreateCredentials
  1674. Create security credentials
  1675. Params
  1676. Credentials are Data used by a principal to establish its own identity, such as
  1677. a password, or a Kerberos protocol ticket
  1678. SSPI credential functions enable applications to gain access
  1679. to the credentials of a principal and to free such access.
  1680. Schannel credentials are based on the X.509 certificate.
  1681. Schannel still supports version 1 certificates, but using version 3
  1682. certificates is recommended. Schannel does not perform certificate management.
  1683. It relies on the application to perform certificate management using
  1684. CryptoAPI functions.
  1685. Return
  1686. UTE_SUCCESS
  1687. UTE_NULL_PARAM
  1688. UTE_OPEN_CERTIFICATE_STORE_FAILED
  1689. UTE_OUT_OF_MEMORY
  1690. UTE_FAILED_TO_CREATE_SECURITY_CREDENTIALS
  1691. UTE_CERTIFICATE_INVALID_DATE
  1692. ************************************************/
  1693. int CUT_SecureSocketServer::CreateCredentials()
  1694. {
  1695. SCHANNEL_CRED SchannelCred;
  1696. TimeStamp tsExpiry;
  1697. SECURITY_STATUS Status;
  1698. PCCERT_CONTEXT pCertContext = NULL;
  1699. // Already created
  1700. if(m_phCreds != NULL)
  1701. return UTE_SUCCESS;
  1702. // If certificate context was set
  1703. if(m_Certificate.GetContext() != NULL)
  1704. {
  1705. pCertContext = CertDuplicateCertificateContext(m_Certificate.GetContext());
  1706. if(m_bCloseStore)
  1707. CertCloseStore(m_hCertStore, 0);
  1708. m_hCertStore = pCertContext->hCertStore;
  1709. m_bCloseStore = FALSE;
  1710. }
  1711. else
  1712. {
  1713. // Check parameters
  1714. if(m_szCertSubjStr == NULL || _tcslen(m_szCertSubjStr) == 0)
  1715. {
  1716. HandleSecurityError(_T("No certificate specified!"));
  1717. return UTE_NULL_PARAM;
  1718. }
  1719. // Open the certificate store
  1720. if(m_hCertStore == NULL)
  1721. {
  1722. PWSTR pwszCertStoreName;
  1723. // v4.2 changes - previous code all ascii
  1724. #if !defined _UNICODE
  1725. // Convert store name protocol name to Unicode
  1726. DWORD dwCertStoreName;
  1727. dwCertStoreName = MultiByteToWideChar(CP_ACP, 0, m_szCertStoreName, -1, NULL, 0);
  1728. pwszCertStoreName = (PWSTR)LocalAlloc(LMEM_FIXED, dwCertStoreName * sizeof(WCHAR));
  1729. if(dwCertStoreName == NULL)
  1730. return UTE_OUT_OF_MEMORY;
  1731. dwCertStoreName = MultiByteToWideChar(CP_ACP, 0, m_szCertStoreName, -1, pwszCertStoreName, dwCertStoreName);
  1732. if(dwCertStoreName == 0)
  1733. {
  1734. // Free memory
  1735. LocalFree(pwszCertStoreName);
  1736. return UTE_PARAMETER_INVALID_VALUE;
  1737. }
  1738. #else
  1739. pwszCertStoreName = (PWSTR)LocalAlloc(LMEM_FIXED, _tcslen(m_szCertStoreName) * sizeof(WCHAR) + sizeof(WCHAR));
  1740. _tcscpy(pwszCertStoreName, m_szCertStoreName);
  1741. #endif
  1742. m_hCertStore = CertOpenStore(
  1743. CERT_STORE_PROV_SYSTEM,
  1744. X509_ASN_ENCODING ,
  1745. 0,
  1746. (m_bMachineStore) ? CERT_SYSTEM_STORE_LOCAL_MACHINE : CERT_SYSTEM_STORE_CURRENT_USER,
  1747. pwszCertStoreName);
  1748. // Free memory
  1749. LocalFree(pwszCertStoreName);
  1750. if(!m_hCertStore)
  1751. {
  1752. HandleSecurityError(_T("Failed to open certificate store."));
  1753. return UTE_OPEN_CERTIFICATE_STORE_FAILED;
  1754. }
  1755. m_bCloseStore = TRUE;
  1756. }
  1757. // Find certificate.
  1758. pCertContext = CertFindCertificateInStore(m_hCertStore,
  1759. X509_ASN_ENCODING,
  1760. 0,
  1761. CERT_FIND_SUBJECT_STR,
  1762. m_szCertSubjStr,
  1763. NULL);
  1764. if(pCertContext == NULL)
  1765. {
  1766. HandleSecurityError(_T("Failed to find the certificate."));
  1767. return UTE_FAILED_TO_FIND_CERTIFICATE;
  1768. }
  1769. }
  1770. // Check if certificate valid
  1771. if(CertVerifyTimeValidity(NULL, pCertContext->pCertInfo) != 0)
  1772. {
  1773. // Free the certificate context.
  1774. if(pCertContext)
  1775. CertFreeCertificateContext(pCertContext);
  1776. HandleSecurityError(_T("Security certificate date is not valid."));
  1777. return UTE_CERTIFICATE_INVALID_DATE;
  1778. }
  1779. // Build Schannel credential structure.
  1780. ZeroMemory(&SchannelCred, sizeof(SchannelCred));
  1781. SchannelCred.dwVersion = SCHANNEL_CRED_VERSION;
  1782. SchannelCred.cCreds = 1;
  1783. SchannelCred.paCred = &pCertContext;
  1784. SchannelCred.grbitEnabledProtocols = m_dwProtocol;
  1785. // Set cipher strength
  1786. SchannelCred.dwMaximumCipherStrength = m_dwMaxCipherStrength;
  1787. SchannelCred.dwMinimumCipherStrength = m_dwMinCipherStrength;
  1788. // Free SSPI credentials handle (if we create it before) or create a new one
  1789. if(m_phCreds != NULL)
  1790. m_SecurityFunc.FreeCredentialsHandle(m_phCreds);
  1791. else
  1792. m_phCreds = new CredHandle;
  1793. // Create an SSPI credential.
  1794. Status = m_SecurityFunc.AcquireCredentialsHandle(
  1795. NULL, // Name of principal
  1796. UNISP_NAME, // Name of package
  1797. SECPKG_CRED_INBOUND, // Flags indicating use
  1798. NULL, // Pointer to logon ID
  1799. &SchannelCred, // Package specific data
  1800. NULL, // Pointer to GetKey() func
  1801. NULL, // Value to pass to GetKey()
  1802. m_phCreds, // (out) Cred Handle
  1803. &tsExpiry); // (out) Lifetime (optional)
  1804. // Free the certificate context.
  1805. if(pCertContext)
  1806. CertFreeCertificateContext(pCertContext);
  1807. // Check status
  1808. if(Status != SEC_E_OK)
  1809. {
  1810. HandleSecurityError(_T("Failed to acquire credentials handle."));
  1811. delete m_phCreds;
  1812. m_phCreds = NULL;
  1813. return UTE_FAILED_TO_CREATE_SECURITY_CREDENTIALS;
  1814. }
  1815. return UTE_SUCCESS;
  1816. }
  1817. /***********************************************
  1818. PerformHandshake
  1819. Perform client handshake
  1820. Params
  1821. Socket - connected socket
  1822. lpszServerName - server name
  1823. pExtraData - extra data returned by handshake
  1824. Return
  1825. UTE_SUCCESS
  1826. UTE_OUT_OF_MEMORY
  1827. UTE_SOCK_RECEIVE_ERROR
  1828. UTE_FAILED_TO_ACCEPT_SECURITY_CONTEXT
  1829. UTE_HANDSHAKE_FAILED
  1830. ************************************************/
  1831. int CUT_SecureSocketServer::PerformHandshake(
  1832. SOCKET Socket, // in
  1833. const TCHAR * /* lpszServerName */, // in
  1834. SecBuffer * /* pExtraData */) // out
  1835. {
  1836. TimeStamp tsExpiry;
  1837. SECURITY_STATUS scRet = SEC_E_SECPKG_NOT_FOUND; // default error if we run out of packages
  1838. SecBufferDesc InBuffer;
  1839. SecBufferDesc OutBuffer;
  1840. SecBuffer InBuffers[2];
  1841. SecBuffer OutBuffers[1];
  1842. DWORD err = 0;
  1843. BOOL bDoRead = TRUE;
  1844. BOOL bInitContext = TRUE;
  1845. DWORD dwIoBuffer = 0, dwSSPIFlags, dwSSPIOutFlags;
  1846. dwSSPIFlags = ASC_REQ_SEQUENCE_DETECT |
  1847. ASC_REQ_REPLAY_DETECT |
  1848. ASC_REQ_CONFIDENTIALITY |
  1849. ASC_REQ_EXTENDED_ERROR |
  1850. ASC_REQ_ALLOCATE_MEMORY |
  1851. ASC_REQ_STREAM;
  1852. if(m_bClientAuth)
  1853. dwSSPIFlags |= ASC_REQ_MUTUAL_AUTH;
  1854. // Allocate temp IO buffer memory
  1855. if(m_lpszIoBuffer == NULL)
  1856. {
  1857. // Allocate a working buffer.
  1858. m_dwIoBufferLength = IO_BUFFER_SIZE;
  1859. m_lpszIoBuffer = (char *)LocalAlloc(LMEM_FIXED, m_dwIoBufferLength + 10);
  1860. if(m_lpszIoBuffer == NULL)
  1861. return UTE_OUT_OF_MEMORY;
  1862. }
  1863. // Set OutBuffer for InitializeSecurityContext call
  1864. OutBuffer.cBuffers = 1;
  1865. OutBuffer.pBuffers = OutBuffers;
  1866. OutBuffer.ulVersion = SECBUFFER_VERSION;
  1867. // Check to see if we've done
  1868. scRet = SEC_I_CONTINUE_NEEDED;
  1869. while( scRet == SEC_I_CONTINUE_NEEDED ||
  1870. scRet == SEC_E_INCOMPLETE_MESSAGE ||
  1871. scRet == SEC_I_INCOMPLETE_CREDENTIALS)
  1872. {
  1873. if(0 == dwIoBuffer || scRet == SEC_E_INCOMPLETE_MESSAGE)
  1874. {
  1875. if(bDoRead)
  1876. {
  1877. err = recv(Socket, m_lpszIoBuffer+dwIoBuffer, IO_BUFFER_SIZE, 0);
  1878. if (err == SOCKET_ERROR || err == 0)
  1879. {
  1880. HandleSecurityError(_T("Failed to receive secure data."));
  1881. return UTE_SOCK_RECEIVE_ERROR;
  1882. }
  1883. else
  1884. {
  1885. dwIoBuffer += err;
  1886. }
  1887. }
  1888. else
  1889. {
  1890. bDoRead = TRUE;
  1891. }
  1892. }
  1893. // InBuffers[1] is for getting extra data that
  1894. // SSPI/SCHANNEL doesn't proccess on this
  1895. // run around the loop.
  1896. InBuffers[0].pvBuffer = m_lpszIoBuffer;
  1897. InBuffers[0].cbBuffer = dwIoBuffer;
  1898. InBuffers[0].BufferType = SECBUFFER_TOKEN;
  1899. InBuffers[1].pvBuffer = NULL;
  1900. InBuffers[1].cbBuffer = 0;
  1901. InBuffers[1].BufferType = SECBUFFER_EMPTY;
  1902. InBuffer.cBuffers = 2;
  1903. InBuffer.pBuffers = InBuffers;
  1904. InBuffer.ulVersion = SECBUFFER_VERSION;
  1905. // Initialize these so if we fail, pvBuffer contains NULL,
  1906. // so we don't try to free random garbage at the quit
  1907. OutBuffers[0].pvBuffer = NULL;
  1908. OutBuffers[0].BufferType = SECBUFFER_TOKEN;
  1909. OutBuffers[0].cbBuffer = 0;
  1910. // Create new context
  1911. if(m_phContext == NULL)
  1912. {
  1913. m_phContext = new CtxtHandle;
  1914. m_phContext->dwLower = NULL;
  1915. m_phContext->dwUpper = NULL;
  1916. bInitContext = TRUE;
  1917. }
  1918. else
  1919. {
  1920. bInitContext = FALSE;
  1921. }
  1922. scRet = m_SecurityFunc.AcceptSecurityContext(
  1923. m_phCreds,
  1924. (bInitContext)?NULL:m_phContext,
  1925. &InBuffer,
  1926. dwSSPIFlags,
  1927. SECURITY_NATIVE_DREP,
  1928. (bInitContext)?m_phContext:NULL,
  1929. &OutBuffer,
  1930. &dwSSPIOutFlags,
  1931. &tsExpiry);
  1932. if ( scRet == SEC_E_OK ||
  1933. scRet == SEC_I_CONTINUE_NEEDED ||
  1934. (FAILED(scRet) && (0 != (dwSSPIOutFlags & ISC_RET_EXTENDED_ERROR))))
  1935. {
  1936. if (OutBuffers[0].cbBuffer != 0 &&
  1937. OutBuffers[0].pvBuffer != NULL )
  1938. {
  1939. // Send response if there is one
  1940. err = send( Socket,
  1941. (const char *)OutBuffers[0].pvBuffer,
  1942. OutBuffers[0].cbBuffer,
  1943. 0 );
  1944. m_SecurityFunc.FreeContextBuffer( OutBuffers[0].pvBuffer );
  1945. OutBuffers[0].pvBuffer = NULL;
  1946. }
  1947. }
  1948. if ( scRet == SEC_E_OK )
  1949. {
  1950. if ( InBuffers[1].BufferType == SECBUFFER_EXTRA )
  1951. {
  1952. memcpy(m_lpszIoBuffer,
  1953. (LPBYTE) (m_lpszIoBuffer + (dwIoBuffer - InBuffers[1].cbBuffer)),
  1954. InBuffers[1].cbBuffer);
  1955. dwIoBuffer = InBuffers[1].cbBuffer;
  1956. }
  1957. else
  1958. {
  1959. dwIoBuffer = 0;
  1960. }
  1961. return UTE_SUCCESS;
  1962. }
  1963. else if (FAILED(scRet) && (scRet != SEC_E_INCOMPLETE_MESSAGE))
  1964. {
  1965. HandleSecurityError(_T("Failed to accept security context."));
  1966. return UTE_FAILED_TO_ACCEPT_SECURITY_CONTEXT;
  1967. }
  1968. if ( scRet != SEC_E_INCOMPLETE_MESSAGE &&
  1969. scRet != SEC_I_INCOMPLETE_CREDENTIALS)
  1970. {
  1971. if ( InBuffers[1].BufferType == SECBUFFER_EXTRA )
  1972. {
  1973. memcpy(m_lpszIoBuffer,
  1974. (LPBYTE) (m_lpszIoBuffer + (dwIoBuffer - InBuffers[1].cbBuffer)),
  1975. InBuffers[1].cbBuffer);
  1976. dwIoBuffer = InBuffers[1].cbBuffer;
  1977. }
  1978. else
  1979. {
  1980. // Prepare for next receive
  1981. dwIoBuffer = 0;
  1982. }
  1983. }
  1984. }
  1985. return UTE_HANDSHAKE_FAILED;
  1986. }
  1987. /***********************************************
  1988. HandshakeLoop
  1989. Helper function used in the handshake
  1990. Params
  1991. Socket - connected socket
  1992. fDoInitialRead - should read first
  1993. pExtraData - extra data returned by handshake
  1994. Return
  1995. UTE_HANDSHAKE_FAILED
  1996. ************************************************/
  1997. int CUT_SecureSocketServer::HandshakeLoop(
  1998. SOCKET /* Socket */, // in
  1999. BOOL /* fDoInitialRead */, // in
  2000. SecBuffer * /* pExtraData */) // out
  2001. {
  2002. return UTE_HANDSHAKE_FAILED;
  2003. }
  2004. /***********************************************
  2005. GetNewCredentials
  2006. Helper function used in the handshake
  2007. Params
  2008. none
  2009. Return
  2010. SECURITY_STATUS
  2011. ************************************************/
  2012. void CUT_SecureSocketServer::GetNewCredentials()
  2013. {
  2014. }
  2015. /***********************************************
  2016. VerifyCertificate
  2017. Verifies server's sertificate
  2018. Params
  2019. pszServerName - server's name
  2020. dwCertFlags - sertificate flags
  2021. Return
  2022. UTE_SUCCESS
  2023. UTE_FAILED_TO_QUERY_CERTIFICATE
  2024. UTE_FAILED_TO_GET_CERTIFICATE_CHAIN
  2025. UTE_FAILED_TO_VERIFY_CERTIFICATE_CHAIN
  2026. UTE_FAILED_TO_VERIFY_CERTIFICATE_TRUST
  2027. ************************************************/
  2028. int CUT_SecureSocketServer::VerifyCertificate(
  2029. PTSTR pszServerName,
  2030. DWORD dwCertFlags)
  2031. {
  2032. HTTPSPolicyCallbackData polHttps;
  2033. CERT_CHAIN_POLICY_PARA PolicyPara;
  2034. CERT_CHAIN_POLICY_STATUS PolicyStatus;
  2035. CERT_CHAIN_PARA ChainPara;
  2036. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  2037. PCCERT_CONTEXT pRemoteCertContext = NULL;
  2038. SECURITY_STATUS Status;
  2039. int nError = UTE_SUCCESS;
  2040. // Client authentication flag not set
  2041. if(!m_bClientAuth && m_CertValidation == CERT_DONOT_VERIFY)
  2042. return UTE_SUCCESS;
  2043. // Read the client certificate.
  2044. Status = m_SecurityFunc.QueryContextAttributes(m_phContext,
  2045. SECPKG_ATTR_REMOTE_CERT_CONTEXT,
  2046. (PVOID)&pRemoteCertContext);
  2047. if(Status != SEC_E_OK)
  2048. {
  2049. HandleSecurityError(_T("Error querying client certificate."));
  2050. return UTE_FAILED_TO_QUERY_CERTIFICATE;
  2051. }
  2052. // Build certificate chain.
  2053. ZeroMemory(&ChainPara, sizeof(ChainPara));
  2054. ChainPara.cbSize = sizeof(ChainPara);
  2055. if(!CertGetCertificateChain(
  2056. NULL,
  2057. pRemoteCertContext,
  2058. NULL,
  2059. pRemoteCertContext->hCertStore,
  2060. &ChainPara,
  2061. 0,
  2062. NULL,
  2063. &pChainContext))
  2064. {
  2065. Status = GetLastError();
  2066. nError = UTE_FAILED_TO_GET_CERTIFICATE_CHAIN;
  2067. HandleSecurityError(_T("Failed to get the certificate chain."));
  2068. }
  2069. else
  2070. {
  2071. // Validate certificate chain.
  2072. ZeroMemory(&polHttps, sizeof(HTTPSPolicyCallbackData));
  2073. polHttps.cbStruct = sizeof(HTTPSPolicyCallbackData);
  2074. polHttps.dwAuthType = AUTHTYPE_CLIENT;
  2075. polHttps.fdwChecks = dwCertFlags;
  2076. polHttps.pwszServerName = NULL;
  2077. memset(&PolicyPara, 0, sizeof(PolicyPara));
  2078. PolicyPara.cbSize = sizeof(PolicyPara);
  2079. PolicyPara.pvExtraPolicyPara = &polHttps;
  2080. memset(&PolicyStatus, 0, sizeof(PolicyStatus));
  2081. PolicyStatus.cbSize = sizeof(PolicyStatus);
  2082. if(!CertVerifyCertificateChainPolicy(
  2083. CERT_CHAIN_POLICY_SSL,
  2084. pChainContext,
  2085. &PolicyPara,
  2086. &PolicyStatus))
  2087. {
  2088. Status = GetLastError();
  2089. nError = UTE_FAILED_TO_VERIFY_CERTIFICATE_CHAIN;
  2090. HandleSecurityError(_T("Failed to verify certificate chain policy."));
  2091. }
  2092. else
  2093. {
  2094. nError = UTE_SUCCESS;
  2095. if(PolicyStatus.dwError)
  2096. {
  2097. // if(!OnCertVerifyError(CUT_Certificate(pRemoteCertContext), PolicyStatus.dwError, pszServerName))
  2098. // v4.2 changed to avert warning
  2099. CUT_Certificate cert(pRemoteCertContext);
  2100. if(!OnCertVerifyError(cert, PolicyStatus.dwError, pszServerName))
  2101. {
  2102. Status = PolicyStatus.dwError;
  2103. nError = UTE_FAILED_TO_VERIFY_CERTIFICATE_TRUST;
  2104. DisplayWinVerifyTrustError(Status);
  2105. }
  2106. }
  2107. }
  2108. }
  2109. if(pChainContext)
  2110. CertFreeCertificateChain(pChainContext);
  2111. if (pRemoteCertContext)
  2112. CertFreeCertificateContext(pRemoteCertContext);
  2113. return nError;
  2114. }
  2115. #endif // CUT_SECURE_SOCKET
  2116. #pragma warning ( pop )