PageRenderTime 52ms CodeModel.GetById 20ms 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

Large files files are truncated, but you can click here to view the full 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

Large files files are truncated, but you can click here to view the full file