Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

807 lines
23 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: ssl2cli.c
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 8-08-95 RichardW Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <spbase.h>
  18. #include <ssl2msg.h>
  19. #include <ssl3msg.h>
  20. #include <ssl2prot.h>
  21. SP_STATUS WINAPI
  22. Ssl2ClientProtocolHandler(
  23. PSPContext pContext,
  24. PSPBuffer pCommInput,
  25. PSPBuffer pCommOutput)
  26. {
  27. SP_STATUS pctRet = 0;
  28. DWORD cMessageType;
  29. DWORD dwStateTransition;
  30. BOOL fRaw = TRUE;
  31. SPBuffer MsgInput;
  32. DWORD cbMsg;
  33. PUCHAR pb;
  34. UCHAR bCT;
  35. if (NULL != pCommOutput)
  36. {
  37. pCommOutput->cbData = 0;
  38. }
  39. MsgInput.pvBuffer = pCommInput->pvBuffer;
  40. MsgInput.cbBuffer = pCommInput->cbBuffer;
  41. MsgInput.cbData = pCommInput->cbData;
  42. // In the following states, we should decrypt the message:
  43. switch(pContext->State)
  44. {
  45. case SSL2_STATE_CLIENT_MASTER_KEY:
  46. case SSL2_STATE_CLIENT_FINISH:
  47. case SSL2_STATE_CLIENT_RESTART:
  48. {
  49. DWORD cbHeader;
  50. DWORD cbPadding;
  51. if (MsgInput.cbData < 3)
  52. {
  53. return PCT_INT_INCOMPLETE_MSG;
  54. }
  55. if(((PCHAR)pCommInput->pvBuffer)[0] & 0x80)
  56. {
  57. cbHeader = 2 + pContext->pHashInfo->cbCheckSum;
  58. cbPadding = 0;
  59. }
  60. else
  61. {
  62. cbHeader = 3 + pContext->pHashInfo->cbCheckSum;
  63. cbPadding = ((PCHAR)pCommInput->pvBuffer)[2];
  64. }
  65. (PUCHAR)MsgInput.pvBuffer += cbHeader;
  66. MsgInput.cbBuffer -= cbHeader;
  67. MsgInput.cbData -= (cbHeader+cbPadding);
  68. pctRet = Ssl2DecryptMessage(pContext, pCommInput, &MsgInput);
  69. if (pctRet != PCT_ERR_OK)
  70. {
  71. // to handle incomplete message errors
  72. return(pctRet);
  73. }
  74. cMessageType = ((PUCHAR) MsgInput.pvBuffer)[0];
  75. fRaw = FALSE;
  76. break;
  77. }
  78. case SP_STATE_SHUTDOWN:
  79. case SP_STATE_SHUTDOWN_PENDING:
  80. cMessageType = 0;
  81. break;
  82. default:
  83. if(pCommInput->cbData < 3)
  84. {
  85. return PCT_INT_INCOMPLETE_MSG;
  86. }
  87. cMessageType = ((PUCHAR) MsgInput.pvBuffer)[2];
  88. break;
  89. }
  90. dwStateTransition = pContext->State | (cMessageType<<16);
  91. switch(dwStateTransition)
  92. {
  93. case SP_STATE_SHUTDOWN_PENDING:
  94. // There's no CloseNotify in SSL2, so just transition to
  95. // the shutdown state and leave the output buffer empty.
  96. pContext->State = SP_STATE_SHUTDOWN;
  97. break;
  98. case SP_STATE_SHUTDOWN:
  99. return PCT_INT_EXPIRED;
  100. case (SSL2_MT_SERVER_HELLO << 16) | UNI_STATE_CLIENT_HELLO:
  101. case (SSL2_MT_SERVER_HELLO << 16) | SSL2_STATE_CLIENT_HELLO:
  102. {
  103. PSsl2_Server_Hello pHello;
  104. // Attempt to recognize and handle various versions of Server
  105. // hello, start by trying to unpickle the oldest, and the next
  106. // version, until one unpickles. Then run the handle code.
  107. // We can also put unpickling and handling code in here for SSL
  108. // messages.
  109. pctRet = Ssl2UnpackServerHello(pCommInput, &pHello);
  110. if (PCT_ERR_OK == pctRet)
  111. {
  112. if (pHello->SessionIdHit)
  113. {
  114. pctRet = Ssl2CliHandleServerRestart(
  115. pContext,
  116. pCommInput,
  117. pHello,
  118. pCommOutput);
  119. if (PCT_ERR_OK == pctRet)
  120. {
  121. pContext->State = SSL2_STATE_CLIENT_RESTART;
  122. }
  123. }
  124. else
  125. {
  126. if(pContext->RipeZombie->hMasterKey != 0)
  127. {
  128. // We've attempted to do a reconnect and the server has
  129. // blown us off. In this case we must use a new and different
  130. // cache entry.
  131. pContext->RipeZombie->ZombieJuju = FALSE;
  132. if(!SPCacheClone(&pContext->RipeZombie))
  133. {
  134. pctRet = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  135. }
  136. }
  137. if (pctRet == PCT_ERR_OK)
  138. {
  139. pctRet = Ssl2CliHandleServerHello(
  140. pContext,
  141. pCommInput,
  142. pHello,
  143. pCommOutput);
  144. }
  145. if (PCT_ERR_OK == pctRet)
  146. {
  147. pContext->State = SSL2_STATE_CLIENT_MASTER_KEY;
  148. }
  149. }
  150. SPExternalFree(pHello);
  151. }
  152. else if(pctRet != PCT_INT_INCOMPLETE_MSG)
  153. {
  154. pctRet |= PCT_INT_DROP_CONNECTION;
  155. }
  156. if (SP_FATAL(pctRet))
  157. {
  158. pContext->State = PCT1_STATE_ERROR;
  159. }
  160. break;
  161. }
  162. case (SSL2_MT_SERVER_VERIFY << 16) | SSL2_STATE_CLIENT_MASTER_KEY:
  163. pctRet = Ssl2CliHandleServerVerify(
  164. pContext,
  165. &MsgInput,
  166. pCommOutput);
  167. if (PCT_ERR_OK == pctRet)
  168. {
  169. pContext->State =SSL2_STATE_CLIENT_FINISH;
  170. }
  171. if (SP_FATAL(pctRet))
  172. {
  173. pContext->State = PCT1_STATE_ERROR;
  174. }
  175. break;
  176. case (SSL2_MT_SERVER_VERIFY << 16) | SSL2_STATE_CLIENT_RESTART:
  177. pctRet = Ssl2CliFinishRestart(pContext, &MsgInput, pCommOutput);
  178. if (PCT_ERR_OK == pctRet)
  179. {
  180. pContext->State =SSL2_STATE_CLIENT_FINISH;
  181. }
  182. if (SP_FATAL(pctRet))
  183. {
  184. pContext->State = PCT1_STATE_ERROR;
  185. }
  186. // Note, we will transmit no data, but we expect a server finished message.
  187. // If the SSPI EXTRA DATA message is not processed by wininet
  188. // then we may be in trouble.
  189. break;
  190. case (SSL2_MT_SERVER_FINISHED_V2 << 16) | SSL2_STATE_CLIENT_FINISH:
  191. pctRet = Ssl2CliHandleServerFinish(
  192. pContext,
  193. &MsgInput,
  194. pCommOutput);
  195. if (SP_FATAL(pctRet))
  196. {
  197. pContext->State = PCT1_STATE_ERROR;
  198. }
  199. else
  200. {
  201. if (PCT_ERR_OK == pctRet)
  202. {
  203. pContext->State = SP_STATE_CONNECTED;
  204. pContext->DecryptHandler = Ssl2DecryptHandler;
  205. pContext->Encrypt = Ssl2EncryptMessage;
  206. pContext->Decrypt = Ssl2DecryptMessage;
  207. pContext->GetHeaderSize = Ssl2GetHeaderSize;
  208. }
  209. // We received a non-fatal error, so the state doesn't
  210. // change, giving the app time to deal with this.
  211. }
  212. break;
  213. default:
  214. DebugLog((DEB_WARN, "Error in protocol, dwStateTransition is %lx\n", dwStateTransition));
  215. pContext->State = PCT1_STATE_ERROR;
  216. pctRet = SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG);
  217. break;
  218. }
  219. if (pctRet & PCT_INT_DROP_CONNECTION)
  220. {
  221. pContext->State &= ~SP_STATE_CONNECTED;
  222. }
  223. // To handle incomplete message errors:
  224. return(pctRet);
  225. }
  226. SP_STATUS
  227. Ssl2CliHandleServerHello(
  228. PSPContext pContext,
  229. PSPBuffer pCommInput,
  230. PSsl2_Server_Hello pHello,
  231. PSPBuffer pCommOutput)
  232. {
  233. /* error to return to peer */
  234. SP_STATUS pctRet=PCT_ERR_ILLEGAL_MESSAGE;
  235. Ssl2_Client_Master_Key Key;
  236. DWORD i,j;
  237. PUCHAR pPortionToEncrypt;
  238. PSessCacheItem pZombie;
  239. pCommOutput->cbData = 0;
  240. SP_BEGIN("Ssl2CliHandleServerHello");
  241. pZombie = pContext->RipeZombie;
  242. do {
  243. pContext->ReadCounter++;
  244. #if DBG
  245. DebugLog((DEB_TRACE, "Hello = %x\n", pHello));
  246. DebugLog((DEB_TRACE, " Session ID hit \t%s\n", pHello->SessionIdHit ? "Yes" : "No"));
  247. DebugLog((DEB_TRACE, " Certificate Type\t%d\n", pHello->CertificateType));
  248. DebugLog((DEB_TRACE, " Certificate Len\t%d\n", pHello->cbCertificate));
  249. DebugLog((DEB_TRACE, " cCipherSpecs \t%d\n", pHello->cCipherSpecs));
  250. DebugLog((DEB_TRACE, " ConnectionId \t%d\n", pHello->cbConnectionID));
  251. for (i = 0 ; i < pHello->cCipherSpecs ; i++ )
  252. {
  253. DebugLog((DEB_TRACE, " Cipher[%i] = %06x (%s)\n", i, pHello->pCipherSpecs[i],
  254. DbgGetNameOfCrypto(pHello->pCipherSpecs[i]) ));
  255. }
  256. #endif
  257. /* Cycle throug the array of cipher tuples to spec mappings
  258. * to find one that we support */
  259. pContext->pCipherInfo = NULL;
  260. pContext->pHashInfo = NULL;
  261. pContext->pKeyExchInfo = NULL;
  262. for(j=0;j<pHello->cCipherSpecs;j++)
  263. {
  264. for(i = 0; i < UniNumCiphers; i++)
  265. {
  266. if(UniAvailableCiphers[i].CipherKind == pHello->pCipherSpecs[j])
  267. {
  268. break;
  269. }
  270. }
  271. if(i >= UniNumCiphers)
  272. {
  273. continue;
  274. }
  275. if(UniAvailableCiphers[i].CipherKind != pHello->pCipherSpecs[j])
  276. {
  277. continue;
  278. }
  279. // Some servers send SSL3 cipher suites in the ServerHello
  280. // message. Skip over these.
  281. if((UniAvailableCiphers[i].fProt & SP_PROT_SSL2_CLIENT) == 0)
  282. {
  283. continue;
  284. }
  285. // Copy all of the spec's to the cache
  286. pZombie->fProtocol = SP_PROT_SSL2_CLIENT;
  287. pZombie->aiCipher = UniAvailableCiphers[i].aiCipher;
  288. pZombie->dwStrength = UniAvailableCiphers[i].dwStrength;
  289. pZombie->aiHash = UniAvailableCiphers[i].aiHash;
  290. pZombie->SessExchSpec = UniAvailableCiphers[i].KeyExch;
  291. pctRet = ContextInitCiphersFromCache(pContext);
  292. if(pctRet != PCT_ERR_OK)
  293. {
  294. continue;
  295. }
  296. Key.CipherKind = pHello->pCipherSpecs[j];
  297. break;
  298. }
  299. // Go ahead and initialize the ciphers
  300. pctRet = ContextInitCiphers(pContext, TRUE, TRUE);
  301. if(pctRet != PCT_ERR_OK)
  302. {
  303. break;
  304. }
  305. pctRet = SPLoadCertificate(pZombie->fProtocol,
  306. pHello->CertificateType,
  307. pHello->pCertificate,
  308. pHello->cbCertificate,
  309. &pZombie->pRemoteCert);
  310. if(pctRet != PCT_ERR_OK)
  311. {
  312. break;
  313. }
  314. if(pContext->RipeZombie->pRemotePublic != NULL)
  315. {
  316. SPExternalFree(pContext->RipeZombie->pRemotePublic);
  317. pContext->RipeZombie->pRemotePublic = NULL;
  318. }
  319. pctRet = SPPublicKeyFromCert(pZombie->pRemoteCert,
  320. &pZombie->pRemotePublic,
  321. NULL);
  322. if(PCT_ERR_OK != pctRet)
  323. {
  324. break;
  325. }
  326. // Automatically validate server certificate if appropriate
  327. // context flag is set.
  328. pctRet = AutoVerifyServerCertificate(pContext);
  329. if(pctRet != PCT_ERR_OK)
  330. {
  331. SP_LOG_RESULT(pctRet);
  332. break;
  333. }
  334. // Generate Key Args
  335. if(pContext->pCipherInfo->dwBlockSize > 1)
  336. {
  337. GenerateRandomBits(pZombie->pKeyArgs, pContext->pCipherInfo->dwBlockSize);
  338. pZombie->cbKeyArgs = Key.KeyArgLen = pContext->pCipherInfo->dwBlockSize;
  339. /* Copy over the key args */
  340. CopyMemory(Key.KeyArg,
  341. pZombie->pKeyArgs,
  342. pZombie->cbKeyArgs );
  343. }
  344. else
  345. {
  346. Key.KeyArgLen = 0;
  347. }
  348. CopyMemory(pContext->pConnectionID, pHello->ConnectionID, pHello->cbConnectionID);
  349. pContext->cbConnectionID = pHello->cbConnectionID;
  350. pctRet = pContext->pKeyExchInfo->System->GenerateClientExchangeValue(
  351. pContext,
  352. NULL,
  353. 0,
  354. Key.ClearKey,
  355. &Key.ClearKeyLen,
  356. NULL,
  357. &Key.EncryptedKeyLen);
  358. if(PCT_ERR_OK != pctRet)
  359. {
  360. break;
  361. }
  362. Key.pbEncryptedKey = SPExternalAlloc(Key.EncryptedKeyLen);
  363. if(Key.pbEncryptedKey == NULL)
  364. {
  365. pctRet = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  366. break;
  367. }
  368. pctRet = pContext->pKeyExchInfo->System->GenerateClientExchangeValue(
  369. pContext,
  370. NULL,
  371. 0,
  372. Key.ClearKey,
  373. &Key.ClearKeyLen,
  374. Key.pbEncryptedKey,
  375. &Key.EncryptedKeyLen);
  376. if(PCT_ERR_OK != pctRet)
  377. {
  378. SPExternalFree(Key.pbEncryptedKey);
  379. break;
  380. }
  381. // Activate session keys.
  382. pContext->hReadKey = pContext->hPendingReadKey;
  383. pContext->hWriteKey = pContext->hPendingWriteKey;
  384. pContext->hPendingReadKey = 0;
  385. pContext->hPendingWriteKey = 0;
  386. pctRet = Ssl2PackClientMasterKey(&Key, pCommOutput);
  387. SPExternalFree(Key.pbEncryptedKey);
  388. if(PCT_ERR_OK != pctRet)
  389. {
  390. break;
  391. }
  392. pContext->WriteCounter++;
  393. SP_RETURN(PCT_ERR_OK);
  394. } while(TRUE);
  395. if((pContext->Flags & CONTEXT_FLAG_EXT_ERR) &&
  396. (pctRet == PCT_ERR_SPECS_MISMATCH))
  397. {
  398. // Our SSL2 implementation does not do client auth,
  399. // so there is only one error message, cipher error.
  400. pCommOutput->cbData = 3; // MSG-ERROR + ERROR-CODE-MSB + ERROR-CODE-LSB
  401. if(pCommOutput->pvBuffer == NULL)
  402. {
  403. pCommOutput->pvBuffer = SPExternalAlloc(pCommOutput->cbData);
  404. if (NULL == pCommOutput->pvBuffer)
  405. {
  406. SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
  407. }
  408. pCommOutput->cbBuffer = pCommOutput->cbData;
  409. }
  410. if(pCommOutput->cbData > pCommOutput->cbBuffer)
  411. {
  412. // Required buffer size returned in pCommOutput->cbData.
  413. SP_RETURN(SP_LOG_RESULT(PCT_INT_BUFF_TOO_SMALL));
  414. }
  415. ((PUCHAR)pCommOutput->pvBuffer)[0] = SSL2_MT_ERROR;
  416. ((PUCHAR)pCommOutput->pvBuffer)[1] = MSBOF(SSL_PE_NO_CIPHER);
  417. ((PUCHAR)pCommOutput->pvBuffer)[2] = LSBOF(SSL_PE_NO_CIPHER);
  418. }
  419. SP_RETURN(pctRet | PCT_INT_DROP_CONNECTION);
  420. }
  421. SP_STATUS
  422. Ssl2CliHandleServerRestart(
  423. PSPContext pContext,
  424. PSPBuffer pCommInput,
  425. PSsl2_Server_Hello pHello,
  426. PSPBuffer pCommOutput)
  427. {
  428. /* error to return to peer */
  429. SP_STATUS pctRet=PCT_ERR_ILLEGAL_MESSAGE;
  430. PSessCacheItem pZombie;
  431. pCommOutput->cbData = 0;
  432. SP_BEGIN("Ssl2CliHandleServerRestart");
  433. pZombie = pContext->RipeZombie;
  434. do {
  435. pContext->ReadCounter++;
  436. /* if there's no zombie, the message is wrong. We can't restart. */
  437. if(pZombie == NULL)
  438. {
  439. pctRet = SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE);
  440. break;
  441. }
  442. if(!pZombie->hMasterKey)
  443. {
  444. pctRet = SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE);
  445. break;
  446. }
  447. if(!pZombie->ZombieJuju)
  448. {
  449. DebugLog((DEB_WARN, "Session expired on client machine, but not on server.\n"));
  450. }
  451. CopyMemory(pContext->pConnectionID,
  452. pHello->ConnectionID,
  453. pHello->cbConnectionID);
  454. pContext->cbConnectionID = pHello->cbConnectionID;
  455. /* Cert length, Cipher Specs, and Cert Type should be zero */
  456. // We know what our ciphers are, so init the cipher system
  457. pctRet = ContextInitCiphersFromCache(pContext);
  458. if(PCT_ERR_OK != pctRet)
  459. {
  460. break;
  461. }
  462. pctRet = ContextInitCiphers(pContext, TRUE, TRUE);
  463. if(PCT_ERR_OK != pctRet)
  464. {
  465. break;
  466. }
  467. // Make a new set of session keys.
  468. pctRet = MakeSessionKeys(pContext,
  469. pContext->RipeZombie->hMasterProv,
  470. pContext->RipeZombie->hMasterKey);
  471. if(PCT_ERR_OK != pctRet)
  472. {
  473. break;
  474. }
  475. // Activate session keys.
  476. pContext->hReadKey = pContext->hPendingReadKey;
  477. pContext->hWriteKey = pContext->hPendingWriteKey;
  478. pContext->hPendingReadKey = 0;
  479. pContext->hPendingWriteKey = 0;
  480. /* okay, now send the client finish */
  481. pctRet = Ssl2GenCliFinished(pContext, pCommOutput);
  482. SP_RETURN(pctRet);
  483. } while(TRUE);
  484. SP_RETURN(pctRet | PCT_INT_DROP_CONNECTION);
  485. }
  486. SP_STATUS
  487. Ssl2GenCliFinished(
  488. PSPContext pContext,
  489. PSPBuffer pCommOutput)
  490. {
  491. SP_STATUS pctRet = PCT_ERR_ILLEGAL_MESSAGE;
  492. PSSL2_SERVER_VERIFY pVerify = NULL;
  493. PSSL2_CLIENT_FINISHED pFinish;
  494. DWORD HeaderSize;
  495. SPBuffer MsgOutput;
  496. DWORD cPadding;
  497. BOOL fAlloced=FALSE;
  498. SP_BEGIN("Ssl2GenCliFinished");
  499. pCommOutput->cbData = 0;
  500. MsgOutput.cbData = sizeof(UCHAR) + pContext->cbConnectionID;
  501. cPadding = ((MsgOutput.cbData+pContext->pHashInfo->cbCheckSum) % pContext->pCipherInfo->dwBlockSize);
  502. if(cPadding)
  503. {
  504. cPadding = pContext->pCipherInfo->dwBlockSize - cPadding;
  505. }
  506. HeaderSize = (cPadding?3:2);
  507. pCommOutput->cbData = MsgOutput.cbData +
  508. pContext->pHashInfo->cbCheckSum +
  509. cPadding +
  510. HeaderSize;
  511. /* are we allocating our own memory? */
  512. if(pCommOutput->pvBuffer == NULL)
  513. {
  514. pCommOutput->pvBuffer = SPExternalAlloc(pCommOutput->cbData);
  515. if (NULL == pCommOutput->pvBuffer)
  516. {
  517. SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
  518. }
  519. fAlloced = TRUE;
  520. pCommOutput->cbBuffer = pCommOutput->cbData;
  521. }
  522. if(pCommOutput->cbData > pCommOutput->cbBuffer)
  523. {
  524. // Required buffer size returned in pCommOutput->cbData.
  525. SP_RETURN(SP_LOG_RESULT(PCT_INT_BUFF_TOO_SMALL));
  526. }
  527. MsgOutput.pvBuffer= (PUCHAR)pCommOutput->pvBuffer +
  528. HeaderSize +
  529. pContext->pHashInfo->cbCheckSum;
  530. MsgOutput.cbBuffer = pCommOutput->cbBuffer -
  531. (pContext->pHashInfo->cbCheckSum + HeaderSize);
  532. pFinish = (PSSL2_CLIENT_FINISHED) MsgOutput.pvBuffer;
  533. pFinish->MessageId = SSL2_MT_CLIENT_FINISHED_V2;
  534. CopyMemory( pFinish->ConnectionID,
  535. pContext->pConnectionID,
  536. pContext->cbConnectionID );
  537. pctRet = Ssl2EncryptMessage( pContext, &MsgOutput, pCommOutput);
  538. if(PCT_ERR_OK != pctRet)
  539. {
  540. SPExternalFree(pCommOutput->pvBuffer);
  541. pCommOutput->pvBuffer = NULL;
  542. pctRet |= PCT_INT_DROP_CONNECTION;
  543. pCommOutput->cbBuffer = 0;
  544. }
  545. SP_RETURN(pctRet);
  546. }
  547. SP_STATUS
  548. Ssl2CliHandleServerVerify(
  549. PSPContext pContext,
  550. PSPBuffer pCommInput,
  551. PSPBuffer pCommOutput)
  552. {
  553. SP_STATUS pctRet = PCT_ERR_ILLEGAL_MESSAGE;
  554. PSSL2_SERVER_VERIFY pVerify = NULL;
  555. /* Read and Write Counters are incremented by the encrypt and decrypt */
  556. SP_BEGIN("Ssl2CliHandleServerVerify");
  557. pCommOutput->cbData = 0;
  558. /* Note, there is no header in this message, as it has been pre-decrypted */
  559. if(pCommInput->cbData != sizeof(UCHAR) + pContext->cbChallenge)
  560. {
  561. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  562. }
  563. pVerify = pCommInput->pvBuffer;
  564. if (pVerify->MessageId != SSL2_MT_SERVER_VERIFY)
  565. {
  566. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  567. }
  568. if (memcmp( pVerify->ChallengeData,
  569. pContext->pChallenge,
  570. pContext->cbChallenge) )
  571. {
  572. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  573. }
  574. pctRet = Ssl2GenCliFinished( pContext, pCommOutput);
  575. SP_RETURN(pctRet);
  576. }
  577. SP_STATUS
  578. Ssl2CliFinishRestart(
  579. PSPContext pContext,
  580. PSPBuffer pCommInput,
  581. PSPBuffer pCommOutput)
  582. {
  583. SP_STATUS pctRet = PCT_ERR_ILLEGAL_MESSAGE;
  584. PSSL2_SERVER_VERIFY pVerify = NULL;
  585. /* Read and Write Counters are incremented by the encrypt and decrypt */
  586. SP_BEGIN("Ssl2CliFinishRestart");
  587. pCommOutput->cbData = 0;
  588. /* Note, there is no header in this message, as it has been pre-decrypted */
  589. if(pCommInput->cbData != sizeof(UCHAR) + pContext->cbChallenge)
  590. {
  591. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  592. }
  593. pVerify = pCommInput->pvBuffer;
  594. if (pVerify->MessageId != SSL2_MT_SERVER_VERIFY)
  595. {
  596. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  597. }
  598. if (memcmp( pVerify->ChallengeData,
  599. pContext->pChallenge,
  600. pContext->cbChallenge) )
  601. {
  602. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  603. }
  604. SP_RETURN(PCT_ERR_OK);
  605. }
  606. SP_STATUS
  607. Ssl2CliHandleServerFinish(
  608. PSPContext pContext,
  609. PSPBuffer pCommInput,
  610. PSPBuffer pCommOutput)
  611. {
  612. SP_STATUS pctRet = PCT_ERR_ILLEGAL_MESSAGE;
  613. PSSL2_SERVER_FINISHED pFinished = NULL;
  614. SP_BEGIN("Ssl2CliHandleServerFinish");
  615. pCommOutput->cbData = 0;
  616. /* Note, there is no header in this message, as it has been pre-decrypted */
  617. if(pCommInput->cbData < sizeof(UCHAR))
  618. {
  619. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  620. }
  621. pFinished = pCommInput->pvBuffer;
  622. if (pFinished->MessageId != SSL2_MT_SERVER_FINISHED_V2)
  623. {
  624. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  625. }
  626. if((pCommInput->cbData-1) != SSL2_SESSION_ID_LEN)
  627. {
  628. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  629. }
  630. CopyMemory( pContext->RipeZombie->SessionID,
  631. pFinished->SessionID,
  632. pCommInput->cbData - 1);
  633. pContext->RipeZombie->cbSessionID = pCommInput->cbData - 1;
  634. SPCacheAdd(pContext);
  635. SP_RETURN(PCT_ERR_OK);
  636. }