Leaked source code of windows server 2003
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.

805 lines
24 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. if (NULL != pCommOutput)
  33. {
  34. pCommOutput->cbData = 0;
  35. }
  36. MsgInput.pvBuffer = pCommInput->pvBuffer;
  37. MsgInput.cbBuffer = pCommInput->cbBuffer;
  38. MsgInput.cbData = pCommInput->cbData;
  39. // In the following states, we should decrypt the message:
  40. switch(pContext->State)
  41. {
  42. case SSL2_STATE_CLIENT_MASTER_KEY:
  43. case SSL2_STATE_CLIENT_FINISH:
  44. case SSL2_STATE_CLIENT_RESTART:
  45. {
  46. DWORD cbHeader;
  47. DWORD cbPadding;
  48. if (MsgInput.cbData < 3)
  49. {
  50. return PCT_INT_INCOMPLETE_MSG;
  51. }
  52. if(((PCHAR)pCommInput->pvBuffer)[0] & 0x80)
  53. {
  54. cbHeader = 2 + pContext->pHashInfo->cbCheckSum;
  55. cbPadding = 0;
  56. }
  57. else
  58. {
  59. cbHeader = 3 + pContext->pHashInfo->cbCheckSum;
  60. cbPadding = ((PCHAR)pCommInput->pvBuffer)[2];
  61. }
  62. MsgInput.pvBuffer = (PUCHAR)MsgInput.pvBuffer + cbHeader;
  63. MsgInput.cbBuffer -= cbHeader;
  64. MsgInput.cbData -= (cbHeader+cbPadding);
  65. pctRet = Ssl2DecryptMessage(pContext, pCommInput, &MsgInput);
  66. if (pctRet != PCT_ERR_OK)
  67. {
  68. // to handle incomplete message errors
  69. return(pctRet);
  70. }
  71. cMessageType = ((PUCHAR) MsgInput.pvBuffer)[0];
  72. fRaw = FALSE;
  73. break;
  74. }
  75. case SP_STATE_SHUTDOWN:
  76. case SP_STATE_SHUTDOWN_PENDING:
  77. cMessageType = 0;
  78. break;
  79. default:
  80. if(pCommInput->cbData < 3)
  81. {
  82. return PCT_INT_INCOMPLETE_MSG;
  83. }
  84. cMessageType = ((PUCHAR) MsgInput.pvBuffer)[2];
  85. break;
  86. }
  87. dwStateTransition = pContext->State | (cMessageType<<16);
  88. switch(dwStateTransition)
  89. {
  90. case SP_STATE_SHUTDOWN_PENDING:
  91. // There's no CloseNotify in SSL2, so just transition to
  92. // the shutdown state and leave the output buffer empty.
  93. pContext->State = SP_STATE_SHUTDOWN;
  94. break;
  95. case SP_STATE_SHUTDOWN:
  96. return PCT_INT_EXPIRED;
  97. case (SSL2_MT_SERVER_HELLO << 16) | UNI_STATE_CLIENT_HELLO:
  98. case (SSL2_MT_SERVER_HELLO << 16) | SSL2_STATE_CLIENT_HELLO:
  99. {
  100. PSsl2_Server_Hello pHello;
  101. // Attempt to recognize and handle various versions of Server
  102. // hello, start by trying to unpickle the oldest, and the next
  103. // version, until one unpickles. Then run the handle code.
  104. // We can also put unpickling and handling code in here for SSL
  105. // messages.
  106. pctRet = Ssl2UnpackServerHello(pCommInput, &pHello);
  107. if (PCT_ERR_OK == pctRet)
  108. {
  109. if (pHello->SessionIdHit)
  110. {
  111. pctRet = Ssl2CliHandleServerRestart(
  112. pContext,
  113. pCommInput,
  114. pHello,
  115. pCommOutput);
  116. if (PCT_ERR_OK == pctRet)
  117. {
  118. pContext->State = SSL2_STATE_CLIENT_RESTART;
  119. }
  120. }
  121. else
  122. {
  123. if(pContext->RipeZombie->hMasterKey != 0)
  124. {
  125. // We've attempted to do a reconnect and the server has
  126. // blown us off. In this case we must use a new and different
  127. // cache entry.
  128. pContext->RipeZombie->ZombieJuju = FALSE;
  129. if(!SPCacheClone(&pContext->RipeZombie))
  130. {
  131. pctRet = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  132. }
  133. }
  134. if (pctRet == PCT_ERR_OK)
  135. {
  136. pctRet = Ssl2CliHandleServerHello(
  137. pContext,
  138. pCommInput,
  139. pHello,
  140. pCommOutput);
  141. }
  142. if (PCT_ERR_OK == pctRet)
  143. {
  144. pContext->State = SSL2_STATE_CLIENT_MASTER_KEY;
  145. }
  146. }
  147. SPExternalFree(pHello);
  148. }
  149. else if(pctRet != PCT_INT_INCOMPLETE_MSG)
  150. {
  151. pctRet |= PCT_INT_DROP_CONNECTION;
  152. }
  153. if (SP_FATAL(pctRet))
  154. {
  155. pContext->State = PCT1_STATE_ERROR;
  156. }
  157. break;
  158. }
  159. case (SSL2_MT_SERVER_VERIFY << 16) | SSL2_STATE_CLIENT_MASTER_KEY:
  160. pctRet = Ssl2CliHandleServerVerify(
  161. pContext,
  162. &MsgInput,
  163. pCommOutput);
  164. if (PCT_ERR_OK == pctRet)
  165. {
  166. pContext->State =SSL2_STATE_CLIENT_FINISH;
  167. }
  168. if (SP_FATAL(pctRet))
  169. {
  170. pContext->State = PCT1_STATE_ERROR;
  171. }
  172. break;
  173. case (SSL2_MT_SERVER_VERIFY << 16) | SSL2_STATE_CLIENT_RESTART:
  174. pctRet = Ssl2CliFinishRestart(pContext, &MsgInput, pCommOutput);
  175. if (PCT_ERR_OK == pctRet)
  176. {
  177. pContext->State =SSL2_STATE_CLIENT_FINISH;
  178. }
  179. if (SP_FATAL(pctRet))
  180. {
  181. pContext->State = PCT1_STATE_ERROR;
  182. }
  183. // Note, we will transmit no data, but we expect a server finished message.
  184. // If the SSPI EXTRA DATA message is not processed by wininet
  185. // then we may be in trouble.
  186. break;
  187. case (SSL2_MT_SERVER_FINISHED_V2 << 16) | SSL2_STATE_CLIENT_FINISH:
  188. pctRet = Ssl2CliHandleServerFinish(
  189. pContext,
  190. &MsgInput,
  191. pCommOutput);
  192. if (SP_FATAL(pctRet))
  193. {
  194. pContext->State = PCT1_STATE_ERROR;
  195. }
  196. else
  197. {
  198. if (PCT_ERR_OK == pctRet)
  199. {
  200. pContext->State = SP_STATE_CONNECTED;
  201. pContext->DecryptHandler = Ssl2DecryptHandler;
  202. pContext->Encrypt = Ssl2EncryptMessage;
  203. pContext->Decrypt = Ssl2DecryptMessage;
  204. pContext->GetHeaderSize = Ssl2GetHeaderSize;
  205. }
  206. // We received a non-fatal error, so the state doesn't
  207. // change, giving the app time to deal with this.
  208. }
  209. break;
  210. default:
  211. DebugLog((DEB_WARN, "Error in protocol, dwStateTransition is %lx\n", dwStateTransition));
  212. pContext->State = PCT1_STATE_ERROR;
  213. pctRet = SP_LOG_RESULT(PCT_INT_ILLEGAL_MSG);
  214. break;
  215. }
  216. if (pctRet & PCT_INT_DROP_CONNECTION)
  217. {
  218. pContext->State &= ~SP_STATE_CONNECTED;
  219. }
  220. // To handle incomplete message errors:
  221. return(pctRet);
  222. }
  223. SP_STATUS
  224. Ssl2CliHandleServerHello(
  225. PSPContext pContext,
  226. PSPBuffer pCommInput,
  227. PSsl2_Server_Hello pHello,
  228. PSPBuffer pCommOutput)
  229. {
  230. /* error to return to peer */
  231. SP_STATUS pctRet=PCT_ERR_ILLEGAL_MESSAGE;
  232. Ssl2_Client_Master_Key Key;
  233. DWORD i,j;
  234. PSessCacheItem pZombie;
  235. UNREFERENCED_PARAMETER(pCommInput);
  236. pCommOutput->cbData = 0;
  237. SP_BEGIN("Ssl2CliHandleServerHello");
  238. pZombie = pContext->RipeZombie;
  239. pContext->ReadCounter++;
  240. #if DBG
  241. DebugLog((DEB_TRACE, "Hello = %x\n", pHello));
  242. DebugLog((DEB_TRACE, " Session ID hit \t%s\n", pHello->SessionIdHit ? "Yes" : "No"));
  243. DebugLog((DEB_TRACE, " Certificate Type\t%d\n", pHello->CertificateType));
  244. DebugLog((DEB_TRACE, " Certificate Len\t%d\n", pHello->cbCertificate));
  245. DebugLog((DEB_TRACE, " cCipherSpecs \t%d\n", pHello->cCipherSpecs));
  246. DebugLog((DEB_TRACE, " ConnectionId \t%d\n", pHello->cbConnectionID));
  247. for (i = 0 ; i < pHello->cCipherSpecs ; i++ )
  248. {
  249. DebugLog((DEB_TRACE, " Cipher[%i] = %06x (%s)\n", i, pHello->pCipherSpecs[i],
  250. DbgGetNameOfCrypto(pHello->pCipherSpecs[i]) ));
  251. }
  252. #endif
  253. /* Cycle throug the array of cipher tuples to spec mappings
  254. * to find one that we support */
  255. pContext->pCipherInfo = NULL;
  256. pContext->pHashInfo = NULL;
  257. pContext->pKeyExchInfo = NULL;
  258. for(j=0;j<pHello->cCipherSpecs;j++)
  259. {
  260. for(i = 0; i < UniNumCiphers; i++)
  261. {
  262. if(UniAvailableCiphers[i].CipherKind == pHello->pCipherSpecs[j])
  263. {
  264. break;
  265. }
  266. }
  267. if(i >= UniNumCiphers)
  268. {
  269. continue;
  270. }
  271. if(UniAvailableCiphers[i].CipherKind != pHello->pCipherSpecs[j])
  272. {
  273. continue;
  274. }
  275. // Some servers send SSL3 cipher suites in the ServerHello
  276. // message. Skip over these.
  277. if((UniAvailableCiphers[i].fProt & SP_PROT_SSL2_CLIENT) == 0)
  278. {
  279. continue;
  280. }
  281. // Copy all of the spec's to the cache
  282. pZombie->fProtocol = SP_PROT_SSL2_CLIENT;
  283. pZombie->aiCipher = UniAvailableCiphers[i].aiCipher;
  284. pZombie->dwStrength = UniAvailableCiphers[i].dwStrength;
  285. pZombie->aiHash = UniAvailableCiphers[i].aiHash;
  286. pZombie->SessExchSpec = UniAvailableCiphers[i].KeyExch;
  287. pctRet = ContextInitCiphersFromCache(pContext);
  288. if(pctRet != PCT_ERR_OK)
  289. {
  290. continue;
  291. }
  292. Key.CipherKind = pHello->pCipherSpecs[j];
  293. break;
  294. }
  295. // Go ahead and initialize the ciphers
  296. pctRet = ContextInitCiphers(pContext, TRUE, TRUE);
  297. if(pctRet != PCT_ERR_OK)
  298. {
  299. goto error;
  300. }
  301. pctRet = SPLoadCertificate(pZombie->fProtocol,
  302. pHello->CertificateType,
  303. pHello->pCertificate,
  304. pHello->cbCertificate,
  305. &pZombie->pRemoteCert);
  306. if(pctRet != PCT_ERR_OK)
  307. {
  308. goto error;
  309. }
  310. if(pContext->RipeZombie->pRemotePublic != NULL)
  311. {
  312. SPExternalFree(pContext->RipeZombie->pRemotePublic);
  313. pContext->RipeZombie->pRemotePublic = NULL;
  314. }
  315. pctRet = SPPublicKeyFromCert(pZombie->pRemoteCert,
  316. &pZombie->pRemotePublic,
  317. NULL);
  318. if(PCT_ERR_OK != pctRet)
  319. {
  320. goto error;
  321. }
  322. // Automatically validate server certificate if appropriate
  323. // context flag is set.
  324. pctRet = AutoVerifyServerCertificate(pContext);
  325. if(pctRet != PCT_ERR_OK)
  326. {
  327. SP_LOG_RESULT(pctRet);
  328. goto error;
  329. }
  330. // Generate Key Args
  331. if(pContext->pCipherInfo->dwBlockSize > 1)
  332. {
  333. pctRet = GenerateRandomBits(pZombie->pKeyArgs, pContext->pCipherInfo->dwBlockSize);
  334. if(!NT_SUCCESS(pctRet))
  335. {
  336. goto error;
  337. }
  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. goto error;
  361. }
  362. Key.pbEncryptedKey = SPExternalAlloc(Key.EncryptedKeyLen);
  363. if(Key.pbEncryptedKey == NULL)
  364. {
  365. pctRet = SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY);
  366. goto error;
  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. goto error;
  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. goto error;
  391. }
  392. pContext->WriteCounter++;
  393. SP_RETURN(PCT_ERR_OK);
  394. error:
  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. UNREFERENCED_PARAMETER(pCommInput);
  432. pCommOutput->cbData = 0;
  433. SP_BEGIN("Ssl2CliHandleServerRestart");
  434. pZombie = pContext->RipeZombie;
  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. goto error;
  441. }
  442. if(!pZombie->hMasterKey)
  443. {
  444. pctRet = SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE);
  445. goto error;
  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. goto error;
  461. }
  462. pctRet = ContextInitCiphers(pContext, TRUE, TRUE);
  463. if(PCT_ERR_OK != pctRet)
  464. {
  465. goto error;
  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. goto error;
  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. error:
  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_CLIENT_FINISHED pFinish;
  493. DWORD HeaderSize;
  494. SPBuffer MsgOutput;
  495. DWORD cPadding;
  496. BOOL fAlloced=FALSE;
  497. SP_BEGIN("Ssl2GenCliFinished");
  498. pCommOutput->cbData = 0;
  499. MsgOutput.cbData = sizeof(UCHAR) + pContext->cbConnectionID;
  500. cPadding = ((MsgOutput.cbData+pContext->pHashInfo->cbCheckSum) % pContext->pCipherInfo->dwBlockSize);
  501. if(cPadding)
  502. {
  503. cPadding = pContext->pCipherInfo->dwBlockSize - cPadding;
  504. }
  505. HeaderSize = (cPadding?3:2);
  506. pCommOutput->cbData = MsgOutput.cbData +
  507. pContext->pHashInfo->cbCheckSum +
  508. cPadding +
  509. HeaderSize;
  510. /* are we allocating our own memory? */
  511. if(pCommOutput->pvBuffer == NULL)
  512. {
  513. pCommOutput->pvBuffer = SPExternalAlloc(pCommOutput->cbData);
  514. if (NULL == pCommOutput->pvBuffer)
  515. {
  516. SP_RETURN(SP_LOG_RESULT(SEC_E_INSUFFICIENT_MEMORY));
  517. }
  518. fAlloced = TRUE;
  519. pCommOutput->cbBuffer = pCommOutput->cbData;
  520. }
  521. if(pCommOutput->cbData > pCommOutput->cbBuffer)
  522. {
  523. // Required buffer size returned in pCommOutput->cbData.
  524. SP_RETURN(SP_LOG_RESULT(PCT_INT_BUFF_TOO_SMALL));
  525. }
  526. MsgOutput.pvBuffer= (PUCHAR)pCommOutput->pvBuffer +
  527. HeaderSize +
  528. pContext->pHashInfo->cbCheckSum;
  529. MsgOutput.cbBuffer = pCommOutput->cbBuffer -
  530. (pContext->pHashInfo->cbCheckSum + HeaderSize);
  531. pFinish = (PSSL2_CLIENT_FINISHED) MsgOutput.pvBuffer;
  532. pFinish->MessageId = SSL2_MT_CLIENT_FINISHED_V2;
  533. CopyMemory( pFinish->ConnectionID,
  534. pContext->pConnectionID,
  535. pContext->cbConnectionID );
  536. pctRet = Ssl2EncryptMessage( pContext, &MsgOutput, pCommOutput);
  537. if(PCT_ERR_OK != pctRet)
  538. {
  539. SPExternalFree(pCommOutput->pvBuffer);
  540. pCommOutput->pvBuffer = NULL;
  541. pctRet |= PCT_INT_DROP_CONNECTION;
  542. pCommOutput->cbBuffer = 0;
  543. }
  544. SP_RETURN(pctRet);
  545. }
  546. SP_STATUS
  547. Ssl2CliHandleServerVerify(
  548. PSPContext pContext,
  549. PSPBuffer pCommInput,
  550. PSPBuffer pCommOutput)
  551. {
  552. SP_STATUS pctRet = PCT_ERR_ILLEGAL_MESSAGE;
  553. PSSL2_SERVER_VERIFY pVerify = NULL;
  554. /* Read and Write Counters are incremented by the encrypt and decrypt */
  555. SP_BEGIN("Ssl2CliHandleServerVerify");
  556. pCommOutput->cbData = 0;
  557. /* Note, there is no header in this message, as it has been pre-decrypted */
  558. if(pCommInput->cbData != sizeof(UCHAR) + pContext->cbChallenge)
  559. {
  560. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  561. }
  562. pVerify = pCommInput->pvBuffer;
  563. if (pVerify->MessageId != SSL2_MT_SERVER_VERIFY)
  564. {
  565. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  566. }
  567. if (memcmp( pVerify->ChallengeData,
  568. pContext->pChallenge,
  569. pContext->cbChallenge) )
  570. {
  571. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  572. }
  573. pctRet = Ssl2GenCliFinished( pContext, pCommOutput);
  574. SP_RETURN(pctRet);
  575. }
  576. SP_STATUS
  577. Ssl2CliFinishRestart(
  578. PSPContext pContext,
  579. PSPBuffer pCommInput,
  580. PSPBuffer pCommOutput)
  581. {
  582. PSSL2_SERVER_VERIFY pVerify = NULL;
  583. /* Read and Write Counters are incremented by the encrypt and decrypt */
  584. SP_BEGIN("Ssl2CliFinishRestart");
  585. pCommOutput->cbData = 0;
  586. /* Note, there is no header in this message, as it has been pre-decrypted */
  587. if(pCommInput->cbData != sizeof(UCHAR) + pContext->cbChallenge)
  588. {
  589. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  590. }
  591. pVerify = pCommInput->pvBuffer;
  592. if (pVerify->MessageId != SSL2_MT_SERVER_VERIFY)
  593. {
  594. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  595. }
  596. if (memcmp( pVerify->ChallengeData,
  597. pContext->pChallenge,
  598. pContext->cbChallenge) )
  599. {
  600. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  601. }
  602. SP_RETURN(PCT_ERR_OK);
  603. }
  604. SP_STATUS
  605. Ssl2CliHandleServerFinish(
  606. PSPContext pContext,
  607. PSPBuffer pCommInput,
  608. PSPBuffer pCommOutput)
  609. {
  610. PSSL2_SERVER_FINISHED pFinished = NULL;
  611. SP_BEGIN("Ssl2CliHandleServerFinish");
  612. pCommOutput->cbData = 0;
  613. /* Note, there is no header in this message, as it has been pre-decrypted */
  614. if(pCommInput->cbData < sizeof(UCHAR))
  615. {
  616. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  617. }
  618. pFinished = pCommInput->pvBuffer;
  619. if (pFinished->MessageId != SSL2_MT_SERVER_FINISHED_V2)
  620. {
  621. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  622. }
  623. if((pCommInput->cbData-1) != SSL2_SESSION_ID_LEN)
  624. {
  625. SP_RETURN(SP_LOG_RESULT(PCT_ERR_ILLEGAL_MESSAGE));
  626. }
  627. CopyMemory( pContext->RipeZombie->SessionID,
  628. pFinished->SessionID,
  629. pCommInput->cbData - 1);
  630. pContext->RipeZombie->cbSessionID = pCommInput->cbData - 1;
  631. SPCacheAdd(pContext);
  632. SP_RETURN(PCT_ERR_OK);
  633. }