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.

1870 lines
59 KiB

  1. //--------------------------------------------------------------------
  2. // Copyright (C)1998 Microsoft Corporation, All Rights Reserved.
  3. //
  4. // scep.cpp
  5. //
  6. // This file holds most of the implementation of CSCEP_CONNECTION
  7. // objects. Each active connection to a camera is represented by
  8. // a separate CSCEP_CONNECTION object. The CSCEP_CONNECTION is then
  9. // destroyed when the connection (socket) to the camera is closed.
  10. //
  11. // Author:
  12. //
  13. // Edward Reus (edwardr) 02-24-98 Initial coding.
  14. //
  15. //--------------------------------------------------------------------
  16. #include "precomp.h"
  17. typedef struct _ATTRIBUTE_TOKEN
  18. {
  19. DWORD dwTokenType;
  20. UCHAR *pChars;
  21. DWORD dwSize;
  22. } ATTRIBUTE_TOKEN;
  23. #define ATTRIBUTE_NAME_SIZE 2
  24. #define COLON ':'
  25. #define ONE '1'
  26. #define SPACE ' '
  27. #define TAB '\t'
  28. #define CR 0x0d
  29. #define LF 0x0a
  30. #define ATTRIBUTE_NAME 0
  31. #define ATTRIBUTE_COLON 1
  32. #define ATTRIBUTE_VALUE 2
  33. #define ATTRIBUTE_CRLF 3
  34. #define ATTR_PDU_SIZE 0
  35. #define ATTR_PRODUCT_ID 1
  36. #define ATTR_USER_NAME 2
  37. #define ATTR_PASSWORD 3
  38. //--------------------------------------------------------------------
  39. // Globals:
  40. //--------------------------------------------------------------------
  41. static DWORD g_adwPduSizes[]
  42. = { PDU_SIZE_1, PDU_SIZE_2, PDU_SIZE_3, PDU_SIZE_4 };
  43. #ifdef DBG_MEM
  44. static LONG g_lCScepConnectionCount = 0;
  45. #endif
  46. //--------------------------------------------------------------------
  47. // SkipBlanks()
  48. //
  49. //--------------------------------------------------------------------
  50. void SkipBlanks( IN OUT UCHAR **ppAttributes,
  51. IN OUT DWORD *pdwAttributeSize )
  52. {
  53. while ( (*pdwAttributeSize > 0)
  54. && ((**ppAttributes == SPACE)||(**ppAttributes == TAB)) )
  55. {
  56. (*ppAttributes)++;
  57. (*pdwAttributeSize)--;
  58. }
  59. }
  60. //--------------------------------------------------------------------
  61. // NextToken()
  62. //
  63. //--------------------------------------------------------------------
  64. ATTRIBUTE_TOKEN *NextToken( IN DWORD dwTokenType,
  65. IN OUT UCHAR **ppAttributes,
  66. IN OUT DWORD *pdwAttributeSize )
  67. {
  68. ATTRIBUTE_TOKEN *pToken = 0;
  69. SkipBlanks(ppAttributes,pdwAttributeSize);
  70. if ((!*ppAttributes) || (*pdwAttributeSize == 0))
  71. {
  72. return 0;
  73. }
  74. pToken = (ATTRIBUTE_TOKEN*)AllocateMemory(sizeof(ATTRIBUTE_TOKEN));
  75. if (!pToken)
  76. {
  77. return 0;
  78. }
  79. pToken->dwTokenType = dwTokenType;
  80. switch (dwTokenType)
  81. {
  82. case ATTRIBUTE_NAME:
  83. if (*pdwAttributeSize < ATTRIBUTE_NAME_SIZE)
  84. {
  85. FreeMemory(pToken);
  86. pToken = 0;
  87. break;
  88. }
  89. pToken->pChars = *ppAttributes;
  90. pToken->dwSize = ATTRIBUTE_NAME_SIZE;
  91. *ppAttributes += ATTRIBUTE_NAME_SIZE;
  92. *pdwAttributeSize -= ATTRIBUTE_NAME_SIZE;
  93. break;
  94. case ATTRIBUTE_COLON:
  95. if (**ppAttributes == COLON)
  96. {
  97. pToken->pChars = *ppAttributes;
  98. pToken->dwSize = 1;
  99. *ppAttributes += 1;
  100. *pdwAttributeSize -= 1;
  101. }
  102. break;
  103. case ATTRIBUTE_VALUE:
  104. pToken->pChars = *ppAttributes;
  105. pToken->dwSize = 0;
  106. while ((**ppAttributes != CR) && (*pdwAttributeSize > 0))
  107. {
  108. (*ppAttributes)++;
  109. (*pdwAttributeSize)--;
  110. (pToken->dwSize)++;
  111. }
  112. break;
  113. case ATTRIBUTE_CRLF:
  114. pToken->pChars = *ppAttributes;
  115. pToken->dwSize = 2;
  116. *ppAttributes += 2;
  117. *pdwAttributeSize -= 2;
  118. if ((pToken->pChars[0] != CR)||(pToken->pChars[1] != LF))
  119. {
  120. FreeMemory(pToken);
  121. pToken = 0;
  122. }
  123. break;
  124. default:
  125. FreeMemory(pToken);
  126. pToken = 0;
  127. break;
  128. }
  129. return pToken;
  130. }
  131. //--------------------------------------------------------------------
  132. // IsAttributeName()
  133. //
  134. //--------------------------------------------------------------------
  135. BOOL IsAttributeName( ATTRIBUTE_TOKEN *pToken,
  136. int *piAttribute )
  137. {
  138. BOOL fIsName = FALSE;
  139. if ((pToken->pChars[0] == 'f')&&(pToken->pChars[1] == 'r'))
  140. {
  141. fIsName = TRUE;
  142. *piAttribute = ATTR_PDU_SIZE;
  143. }
  144. else
  145. if ((pToken->pChars[0] == 'i')&&(pToken->pChars[1] == 'd'))
  146. {
  147. fIsName = TRUE;
  148. *piAttribute = ATTR_PRODUCT_ID;
  149. }
  150. else
  151. if ((pToken->pChars[0] == 'n')&&(pToken->pChars[1] == 'm'))
  152. {
  153. fIsName = TRUE;
  154. *piAttribute = ATTR_USER_NAME;
  155. }
  156. else
  157. if ((pToken->pChars[0] == 'p')&&(pToken->pChars[1] == 'w'))
  158. {
  159. fIsName = TRUE;
  160. *piAttribute = ATTR_PASSWORD;
  161. }
  162. return fIsName;
  163. }
  164. //--------------------------------------------------------------------
  165. // NewTokenString()
  166. //
  167. //--------------------------------------------------------------------
  168. UCHAR *NewTokenString( IN ATTRIBUTE_TOKEN *pToken,
  169. OUT DWORD *pdwStatus )
  170. {
  171. UCHAR *pszNewStr = (UCHAR*)AllocateMemory(1+pToken->dwSize);
  172. if (!pszNewStr)
  173. {
  174. *pdwStatus = ERROR_IRTRANP_OUT_OF_MEMORY;
  175. return 0;
  176. }
  177. memcpy(pszNewStr,pToken->pChars,pToken->dwSize);
  178. pszNewStr[pToken->dwSize] = 0;
  179. return pszNewStr;
  180. }
  181. //--------------------------------------------------------------------
  182. // CSCEP_CONNECTION::CSCEP_CONNECTION()
  183. //
  184. //--------------------------------------------------------------------
  185. CSCEP_CONNECTION::CSCEP_CONNECTION()
  186. {
  187. m_dwConnectionState = STATE_CLOSED;
  188. m_dwPduSendSize = PDU_SIZE_1; // default is 512 bytes.
  189. m_dwPduReceiveSize = PDU_SIZE_4;
  190. m_CFlag = 0;
  191. m_pPrimaryMachineId = 0;
  192. m_pSecondaryMachineId = 0;
  193. m_DestPid = DEFAULT_PID;
  194. m_SrcPid = DEFAULT_PID;
  195. m_pszUserName = 0;
  196. m_pszPassword = 0;
  197. m_pAssembleBuffer = 0;
  198. m_dwAssembleBufferSize = 0;
  199. m_dwMaxAssembleBufferSize = 0;
  200. m_fDidByteSwap = FALSE;
  201. m_Fragmented = FALSE;
  202. m_DFlag = 0;
  203. m_dwSequenceNo = 0;
  204. m_dwRestNo = 0;
  205. m_dwCommandId = 0;
  206. m_pCommandHeader = 0;
  207. m_pszFileName = 0;
  208. m_pszLongFileName = 0;
  209. m_pwszFileName = 0;
  210. m_CreateTime.dwLowDateTime = 0; // Picture create date/time.
  211. m_CreateTime.dwHighDateTime = 0;
  212. }
  213. //--------------------------------------------------------------------
  214. // CSCEP_CONNECTION::~CSCEP_CONNECTION()
  215. //
  216. //--------------------------------------------------------------------
  217. CSCEP_CONNECTION::~CSCEP_CONNECTION()
  218. {
  219. if (m_pPrimaryMachineId)
  220. {
  221. FreeMemory(m_pPrimaryMachineId);
  222. }
  223. if (m_pSecondaryMachineId)
  224. {
  225. FreeMemory(m_pSecondaryMachineId);
  226. }
  227. if (m_pszUserName)
  228. {
  229. FreeMemory(m_pszUserName);
  230. }
  231. if (m_pszPassword)
  232. {
  233. FreeMemory(m_pszPassword);
  234. }
  235. if (m_pAssembleBuffer)
  236. {
  237. FreeMemory(m_pAssembleBuffer);
  238. }
  239. if (m_pCommandHeader)
  240. {
  241. FreeMemory(m_pCommandHeader);
  242. }
  243. if (m_pszFileName)
  244. {
  245. FreeMemory(m_pszFileName);
  246. }
  247. if (m_pszLongFileName)
  248. {
  249. FreeMemory(m_pszLongFileName);
  250. }
  251. if (m_pwszFileName)
  252. {
  253. FreeMemory(m_pwszFileName);
  254. }
  255. }
  256. //------------------------------------------------------------------------
  257. // CSCEP_CONNECTION::operator new()
  258. //
  259. //------------------------------------------------------------------------
  260. void *CSCEP_CONNECTION::operator new( IN size_t Size )
  261. {
  262. void *pObj = AllocateMemory(Size);
  263. #ifdef DBG_MEM
  264. if (pObj)
  265. {
  266. InterlockedIncrement(&g_lCScepConnectionCount);
  267. }
  268. #endif
  269. return pObj;
  270. }
  271. //------------------------------------------------------------------------
  272. // CSCEP_CONNECTION::operator delete()
  273. //
  274. //------------------------------------------------------------------------
  275. void CSCEP_CONNECTION::operator delete( IN void *pObj,
  276. IN size_t Size )
  277. {
  278. if (pObj)
  279. {
  280. DWORD dwStatus = FreeMemory(pObj);
  281. #ifdef DBG_MEM
  282. if (dwStatus)
  283. {
  284. DbgPrint("IrXfer: IrTran-P: CSCEP_CONNECTION::delete: FreeMemory() Failed: %d\n"dwStatus);
  285. }
  286. InterlockedDecrement(&g_lCScepConnectionCount);
  287. if (g_lCScepConnectionCount < 0)
  288. {
  289. DbgPrint("IrXfer: IrTran-P: CSCEP_CONNECTION::delete: Count: %d\n",
  290. g_lCScepConnectionCount);
  291. }
  292. #endif
  293. }
  294. }
  295. //--------------------------------------------------------------------
  296. // CSCEP_CONNECTION::AssemblePdu()
  297. //
  298. // Take in bits of data as its read in. When a complete SCEP PDU has
  299. // been read and assembled return it.
  300. //
  301. // pInputData - This is the data that just came in.
  302. //
  303. // dwInputDataSize - Size in bytes of pInputData.
  304. //
  305. // ppPdu - Returns a complete SCEP PDU when this function
  306. // returns NO_ERROR, otherwise set to 0.
  307. //
  308. // pdwPduSize - Size of the returned PDU.
  309. //
  310. // Return values:
  311. //
  312. // NO_ERROR - A new SCEP PDU is complete and ready.
  313. // ERROR_CONTINUE - Data read so far is Ok, still waiting for more.
  314. // ERROR_SCEP_INVALID_PROTOCOL
  315. // ERROR_IRTRANP_OUT_OF_MEMORY
  316. //
  317. //--------------------------------------------------------------------
  318. DWORD CSCEP_CONNECTION::AssemblePdu( IN void *pInputData,
  319. IN DWORD dwInputDataSize,
  320. OUT SCEP_HEADER **ppPdu,
  321. OUT DWORD *pdwPduSize )
  322. {
  323. DWORD dwStatus = ERROR_CONTINUE;
  324. UCHAR *pEnd;
  325. if (dwInputDataSize > MAX_PDU_SIZE)
  326. return ERROR_SCEP_INVALID_PROTOCOL;
  327. *ppPdu = 0;
  328. *pdwPduSize = 0;
  329. if (dwInputDataSize > 0)
  330. {
  331. if (!m_pAssembleBuffer)
  332. {
  333. m_dwMaxAssembleBufferSize = 2*MAX_PDU_SIZE;
  334. m_pAssembleBuffer
  335. = (UCHAR*)AllocateMemory(m_dwMaxAssembleBufferSize);
  336. if (!m_pAssembleBuffer)
  337. {
  338. return ERROR_IRTRANP_OUT_OF_MEMORY;
  339. }
  340. memcpy(m_pAssembleBuffer,pInputData,dwInputDataSize);
  341. m_dwAssembleBufferSize = dwInputDataSize;
  342. #ifdef DBG_ASSEMBLE
  343. DbgPrint("Assemble: Start: %d\n",m_dwAssembleBufferSize);
  344. #endif
  345. }
  346. else
  347. {
  348. if (m_dwAssembleBufferSize+dwInputDataSize >= m_dwMaxAssembleBufferSize)
  349. {
  350. #ifdef DBG_ERROR
  351. DbgPrint("CSCEP_CONNECTION::AssemblePdu(): Buffer Overrun!\n");
  352. #endif
  353. return ERROR_SCEP_INVALID_PROTOCOL;
  354. }
  355. pEnd = &(m_pAssembleBuffer[m_dwAssembleBufferSize]);
  356. memcpy(pEnd,pInputData,dwInputDataSize);
  357. m_dwAssembleBufferSize += dwInputDataSize;
  358. #ifdef DBG_ASSEMBLE
  359. DbgPrint("Assemble: Add: %d NewSize: %d\n",
  360. dwInputDataSize,m_dwAssembleBufferSize);
  361. #endif
  362. }
  363. }
  364. // Check to see if enough data has come in for a complete PDU.
  365. dwStatus = CheckPdu(ppPdu,pdwPduSize);
  366. return dwStatus;
  367. }
  368. //--------------------------------------------------------------------
  369. // CSCEP_CONNECTION::CheckPdu()
  370. //
  371. // Run through the "current" PDU and see if its complete. If its
  372. // not yet complete, return ERROR_CONTINUE. If it is complete then
  373. // return NO_ERROR.
  374. //
  375. // Return values:
  376. //
  377. // NO_ERROR - The current SCEP PDU is complete and ready.
  378. // ERROR_CONTINUE - Data read so far is Ok, still waiting for more.
  379. // ERROR_SCEP_INVALID_PROTOCOL
  380. // ERROR_IRTRANP_OUT_OF_MEMORY
  381. //
  382. //--------------------------------------------------------------------
  383. DWORD CSCEP_CONNECTION::CheckPdu( OUT SCEP_HEADER **ppPdu,
  384. OUT DWORD *pdwPduSize )
  385. {
  386. DWORD dwStatus;
  387. DWORD dwSize;
  388. SCEP_NEGOTIATION *pInfNegotiation;
  389. if (m_dwAssembleBufferSize < 2)
  390. {
  391. return ERROR_CONTINUE;
  392. }
  393. switch ( ((SCEP_HEADER*)m_pAssembleBuffer)->MsgType )
  394. {
  395. case MSG_TYPE_CONNECT_REQ:
  396. dwStatus = CheckConnectPdu(ppPdu,pdwPduSize);
  397. break;
  398. case MSG_TYPE_CONNECT_RESP:
  399. dwStatus = CheckConnectRespPdu(ppPdu,pdwPduSize);
  400. break;
  401. case MSG_TYPE_DATA:
  402. dwStatus = CheckDataPdu(ppPdu,pdwPduSize);
  403. break;
  404. case MSG_TYPE_DISCONNECT:
  405. dwStatus = CheckDisconnectPdu(ppPdu,pdwPduSize);
  406. break;
  407. default:
  408. #ifdef DBG_ERROR
  409. DbgPrint("CheckPdu(): Invalid Msgtype: %d\n",
  410. ((SCEP_HEADER*)m_pAssembleBuffer)->MsgType );
  411. #endif
  412. dwStatus = ERROR_SCEP_INVALID_PROTOCOL;
  413. break;
  414. }
  415. return dwStatus;
  416. }
  417. //--------------------------------------------------------------------
  418. // CSCEP_CONNECTION::CheckConnectPdu()
  419. //
  420. //--------------------------------------------------------------------
  421. DWORD CSCEP_CONNECTION::CheckConnectPdu( OUT SCEP_HEADER **ppPdu,
  422. OUT DWORD *pdwPduSize )
  423. {
  424. DWORD dwStatus;
  425. DWORD dwSize;
  426. SCEP_VERSION *pInfVersion;
  427. SCEP_NEGOTIATION *pInfNegotiation;
  428. SCEP_EXTEND *pInfExtend;
  429. ASSERT( ((SCEP_HEADER*)m_pAssembleBuffer)->MsgType
  430. == MSG_TYPE_CONNECT_REQ);
  431. if (m_dwAssembleBufferSize < MIN_PDU_SIZE_CONNECT)
  432. {
  433. return ERROR_CONTINUE;
  434. }
  435. if (m_dwAssembleBufferSize > MAX_PDU_SIZE_CONNECT)
  436. {
  437. return ERROR_SCEP_INVALID_PROTOCOL;
  438. }
  439. pInfVersion = (SCEP_VERSION*)(((SCEP_HEADER*)m_pAssembleBuffer)->Rest);
  440. pInfNegotiation = (SCEP_NEGOTIATION*)( sizeof(SCEP_VERSION)
  441. + (char*)pInfVersion );
  442. pInfExtend = (SCEP_EXTEND*)( FIELD_OFFSET(SCEP_NEGOTIATION,InfVersion)
  443. + pInfNegotiation->Length
  444. + (char*)pInfNegotiation );
  445. // Check to see if we have a complete connect PDU size-wise:
  446. dwSize = 10 + pInfNegotiation->Length;
  447. if (m_dwAssembleBufferSize == dwSize)
  448. {
  449. // Have a complete PDU.
  450. dwStatus = NO_ERROR;
  451. }
  452. else if (m_dwAssembleBufferSize < dwSize)
  453. {
  454. // Need to wait for more data to arrive
  455. dwStatus = ERROR_CONTINUE;
  456. }
  457. else
  458. {
  459. // Too much data...
  460. dwStatus = ERROR_SCEP_INVALID_PROTOCOL;
  461. }
  462. if (dwStatus == NO_ERROR)
  463. {
  464. // Check to make sure the contents of the PDU "look" Ok:
  465. if ( (pInfVersion->InfType != INF_TYPE_VERSION)
  466. || (pInfVersion->Version != PROTOCOL_VERSION) )
  467. {
  468. dwStatus = ERROR_SCEP_INVALID_PROTOCOL;
  469. }
  470. if ( (pInfNegotiation->InfType != INF_TYPE_NEGOTIATION)
  471. || (pInfNegotiation->InfVersion < INF_VERSION) )
  472. {
  473. dwStatus = ERROR_SCEP_INVALID_PROTOCOL;
  474. }
  475. if ( (pInfExtend->InfType != INF_TYPE_EXTEND)
  476. || (pInfExtend->Length != (sizeof(pInfExtend->Parameter1)
  477. +sizeof(pInfExtend->Parameter2)))
  478. || (pInfExtend->Parameter1 != 0)
  479. || (pInfExtend->Parameter2 != 0) )
  480. {
  481. dwStatus = ERROR_SCEP_INVALID_PROTOCOL;
  482. }
  483. }
  484. if (dwStatus == NO_ERROR)
  485. {
  486. *ppPdu = NewPdu();
  487. if (!*ppPdu)
  488. {
  489. #ifdef DBG_ERROR
  490. DbgPrint("CSCEP_CONNECTION::CheckConnectPdu(): Out of memory.\n");
  491. #endif
  492. dwStatus = ERROR_IRTRANP_OUT_OF_MEMORY;
  493. }
  494. else
  495. {
  496. *pdwPduSize = m_dwAssembleBufferSize;
  497. memcpy(*ppPdu,m_pAssembleBuffer,m_dwAssembleBufferSize);
  498. m_dwAssembleBufferSize = 0;
  499. #ifdef DBG_ASSEMBLE
  500. DbgPrint("Assemble: PDU: %d Reset: %d\n",
  501. *pdwPduSize, m_dwAssembleBufferSize );
  502. #endif
  503. }
  504. }
  505. return dwStatus;
  506. }
  507. //--------------------------------------------------------------------
  508. // CSCEP_CONNECTION::CheckConnectRespPdu() CLIENT
  509. //
  510. // A connect response from the IrTran-P server is either a ACK or
  511. // NACK PDU. If we get here then it's an ACK. We'll make sure the
  512. // entire PDU is here and that it is formatted correctly. There is
  513. // a specific message type for ACK PDUs, the NACK is just a special
  514. // case of MSG_TYPE_DATA and is handled elsewere (CheckDataPdu()).
  515. //
  516. //--------------------------------------------------------------------
  517. DWORD CSCEP_CONNECTION::CheckConnectRespPdu( OUT SCEP_HEADER **ppPdu,
  518. OUT DWORD *pdwPduSize )
  519. {
  520. DWORD dwStatus;
  521. DWORD dwSize;
  522. SCEP_HEADER *pHeader;
  523. SCEP_NEGOTIATION *pInfNegotiation;
  524. ASSERT( ((SCEP_HEADER*)m_pAssembleBuffer)->MsgType
  525. == MSG_TYPE_CONNECT_RESP);
  526. if (m_dwAssembleBufferSize < MIN_PDU_SIZE_CONNECT_RESP)
  527. {
  528. return ERROR_CONTINUE;
  529. }
  530. if (m_dwAssembleBufferSize > MAX_PDU_SIZE_CONNECT_RESP)
  531. {
  532. return ERROR_SCEP_INVALID_PROTOCOL;
  533. }
  534. pHeader = (SCEP_HEADER*)m_pAssembleBuffer;
  535. pInfNegotiation = (SCEP_NEGOTIATION*)(pHeader->Rest);
  536. // Check to see if we have a complete connect PDU size-wise:
  537. dwSize = sizeof(SCEP_HEADER)
  538. + FIELD_OFFSET(SCEP_NEGOTIATION,InfVersion)
  539. + pInfNegotiation->Length;
  540. if (m_dwAssembleBufferSize == dwSize)
  541. {
  542. // Have a complete PDU.
  543. dwStatus = NO_ERROR;
  544. }
  545. else if (m_dwAssembleBufferSize < dwSize)
  546. {
  547. // Need to wait for more data to arrive
  548. dwStatus = ERROR_CONTINUE;
  549. }
  550. else
  551. {
  552. // Too much data...
  553. dwStatus = ERROR_SCEP_INVALID_PROTOCOL;
  554. }
  555. if (dwStatus == NO_ERROR)
  556. {
  557. // Check to make sure the contents of the PDU "look" Ok:
  558. if ( (pInfNegotiation->InfType != INF_TYPE_NEGOTIATION)
  559. || (pInfNegotiation->InfVersion < INF_VERSION) )
  560. {
  561. dwStatus = ERROR_SCEP_INVALID_PROTOCOL;
  562. }
  563. }
  564. if (dwStatus == NO_ERROR)
  565. {
  566. *ppPdu = NewPdu();
  567. if (!*ppPdu)
  568. {
  569. #ifdef DBG_ERROR
  570. DbgPrint("CSCEP_CONNECTION::CheckConnectRespPdu(): Out of memory.\n");
  571. #endif
  572. dwStatus = ERROR_IRTRANP_OUT_OF_MEMORY;
  573. }
  574. else
  575. {
  576. *pdwPduSize = m_dwAssembleBufferSize;
  577. memcpy(*ppPdu,m_pAssembleBuffer,m_dwAssembleBufferSize);
  578. m_dwAssembleBufferSize = 0;
  579. #ifdef DBG_ASSEMBLE
  580. DbgPrint("Assemble: PDU: %d Reset: %d\n",
  581. *pdwPduSize, m_dwAssembleBufferSize );
  582. #endif
  583. }
  584. }
  585. return dwStatus;
  586. }
  587. //--------------------------------------------------------------------
  588. // CSCEP_CONNECTION::CheckDisconnectPdu()
  589. //
  590. //--------------------------------------------------------------------
  591. DWORD CSCEP_CONNECTION::CheckDisconnectPdu( OUT SCEP_HEADER **ppPdu,
  592. OUT DWORD *pdwPduSize )
  593. {
  594. DWORD dwStatus = NO_ERROR;
  595. DWORD dwSize;
  596. SCEP_DISCONNECT *pDisconnect;
  597. ASSERT( ((SCEP_HEADER*)m_pAssembleBuffer)->MsgType
  598. == MSG_TYPE_DISCONNECT);
  599. if (m_dwAssembleBufferSize < MIN_PDU_SIZE_DISCONNECT)
  600. {
  601. return ERROR_CONTINUE;
  602. }
  603. pDisconnect = (SCEP_DISCONNECT*)(((SCEP_HEADER*)m_pAssembleBuffer)->Rest);
  604. // Check to make sure the contents of the PDU "look" Ok:
  605. if (pDisconnect->InfType != INF_TYPE_REASON)
  606. {
  607. dwStatus = ERROR_SCEP_INVALID_PROTOCOL;
  608. }
  609. if (pDisconnect->Length1 != sizeof(USHORT))
  610. {
  611. dwStatus = ERROR_SCEP_INVALID_PROTOCOL;
  612. }
  613. if (dwStatus == NO_ERROR)
  614. {
  615. *ppPdu = NewPdu();
  616. if (!*ppPdu)
  617. {
  618. #ifdef DBG_ERROR
  619. DbgPrint("CSCEP_CONNECTION::CheckDisonnectPdu(): Out of memory.\n");
  620. #endif
  621. dwStatus = ERROR_IRTRANP_OUT_OF_MEMORY;
  622. }
  623. else
  624. {
  625. *pdwPduSize = sizeof(SCEP_HEADER) + 2 + pDisconnect->Length1;
  626. memcpy(*ppPdu,m_pAssembleBuffer,*pdwPduSize);
  627. m_dwAssembleBufferSize -= *pdwPduSize;
  628. #ifdef DBG_ASSEMBLE
  629. DbgPrint("Assemble: PDU: %d Reset: %d\n",
  630. *pdwPduSize, m_dwAssembleBufferSize );
  631. #endif
  632. }
  633. }
  634. return dwStatus;
  635. }
  636. //--------------------------------------------------------------------
  637. // CSCEP_CONNECTION::CheckDataPdu()
  638. //
  639. // The goal here is to check to see if we have a complete formatted
  640. // PDU, if yes the return NO_ERROR, if the PDU looks ok so far, but
  641. // isn't complete (we need to read more), then return ERROR_CONTINUE.
  642. //
  643. // Also if this is a little-endian machine, byteswap the header
  644. // fields accordingly.
  645. //--------------------------------------------------------------------
  646. DWORD CSCEP_CONNECTION::CheckDataPdu( OUT SCEP_HEADER **ppPdu,
  647. OUT DWORD *pdwPduSize )
  648. {
  649. DWORD dwStatus;
  650. DWORD dwExpectedPduSize;
  651. UCHAR *pEnd;
  652. SCEP_REQ_HEADER_SHORT *pReqHeaderShort;
  653. SCEP_REQ_HEADER_LONG *pReqHeaderLong;
  654. ASSERT( ((SCEP_HEADER*)m_pAssembleBuffer)->MsgType == MSG_TYPE_DATA);
  655. if (m_dwAssembleBufferSize < MIN_PDU_SIZE_DATA)
  656. {
  657. return ERROR_CONTINUE;
  658. }
  659. // Get the length out of the PDU and see if we have a
  660. // complete PDU:
  661. pReqHeaderShort = (SCEP_REQ_HEADER_SHORT*)
  662. (((SCEP_HEADER*)m_pAssembleBuffer)->Rest);
  663. if (pReqHeaderShort->Length1 == USE_LENGTH2)
  664. {
  665. // We have a long PDU:
  666. pReqHeaderLong = (SCEP_REQ_HEADER_LONG*)(pReqHeaderShort);
  667. #ifdef LITTLE_ENDIAN
  668. if (!m_fDidByteSwap)
  669. {
  670. ByteSwapReqHeaderLong(pReqHeaderLong);
  671. m_fDidByteSwap = TRUE;
  672. }
  673. #endif
  674. dwExpectedPduSize = sizeof(SCEP_HEADER)
  675. + FIELD_OFFSET(SCEP_REQ_HEADER_LONG,InfVersion)
  676. + pReqHeaderLong->Length2;
  677. }
  678. else
  679. {
  680. // We have a short PDU:
  681. #ifdef LITTLE_ENDIAN
  682. if (!m_fDidByteSwap)
  683. {
  684. ByteSwapReqHeaderShort(pReqHeaderShort);
  685. m_fDidByteSwap = TRUE;
  686. }
  687. #endif
  688. dwExpectedPduSize = sizeof(SCEP_HEADER)
  689. + FIELD_OFFSET(SCEP_REQ_HEADER_SHORT,InfVersion)
  690. + pReqHeaderShort->Length1;
  691. }
  692. // Ok, see if we have a complete PDU:
  693. if (m_dwAssembleBufferSize == dwExpectedPduSize)
  694. {
  695. *ppPdu = NewPdu();
  696. if (!*ppPdu)
  697. {
  698. #ifdef DBG_ERROR
  699. DbgPrint("CSCEP_CONNECTION::CheckDataPdu(): Out of memory.\n");
  700. #endif
  701. dwStatus = ERROR_IRTRANP_OUT_OF_MEMORY;
  702. }
  703. else
  704. {
  705. *pdwPduSize = dwExpectedPduSize;
  706. memcpy(*ppPdu,m_pAssembleBuffer,dwExpectedPduSize);
  707. m_dwAssembleBufferSize = 0;
  708. m_fDidByteSwap = FALSE;
  709. #ifdef DBG_ASSEMBLE
  710. DbgPrint("Assemble: PDU: %d Reset: %d\n",
  711. *pdwPduSize, m_dwAssembleBufferSize );
  712. #endif
  713. dwStatus = NO_ERROR;
  714. }
  715. }
  716. else if (m_dwAssembleBufferSize > dwExpectedPduSize)
  717. {
  718. *ppPdu = NewPdu();
  719. if (!*ppPdu)
  720. {
  721. #ifdef DBG_ERROR
  722. DbgPrint("CSCEP_CONNECTION::CheckDataPdu(): Out of memory.\n");
  723. #endif
  724. dwStatus = ERROR_IRTRANP_OUT_OF_MEMORY;
  725. }
  726. else
  727. {
  728. *pdwPduSize = dwExpectedPduSize;
  729. memcpy(*ppPdu,m_pAssembleBuffer,dwExpectedPduSize);
  730. pEnd = dwExpectedPduSize + (UCHAR*)m_pAssembleBuffer;
  731. m_dwAssembleBufferSize -= dwExpectedPduSize;
  732. m_fDidByteSwap = FALSE;
  733. //
  734. // move the data remaining to the front of the buffer
  735. //
  736. memmove(m_pAssembleBuffer,pEnd,m_dwAssembleBufferSize);
  737. #ifdef DBG_ASSEMBLE
  738. DbgPrint("Assemble: PDU: %d Reset: %d\n",
  739. *pdwPduSize, m_dwAssembleBufferSize );
  740. #endif
  741. dwStatus = NO_ERROR;
  742. }
  743. }
  744. else
  745. {
  746. dwStatus = ERROR_CONTINUE;
  747. }
  748. return dwStatus;
  749. }
  750. //--------------------------------------------------------------------
  751. // CSCEP_CONNECTION::ParseConnectPdu()
  752. //
  753. // AssemblePDU() already did basic integrity checking of the PDU
  754. // (via CheckConnectPdu()), so at this point we'll assume everything
  755. // is Ok.
  756. //
  757. // NOTE: The Connect PDU is limited to 256 bytes in total length,
  758. // so it will never be fragmented.
  759. //--------------------------------------------------------------------
  760. DWORD CSCEP_CONNECTION::ParseConnectPdu( IN SCEP_HEADER *pPdu,
  761. IN DWORD dwInputDataSize )
  762. {
  763. DWORD dwStatus;
  764. DWORD dwLength;
  765. if (dwInputDataSize > MAX_PDU_SIZE_CONNECT)
  766. {
  767. return ERROR_SCEP_INVALID_PROTOCOL;
  768. }
  769. SCEP_VERSION *pInfVersion;
  770. SCEP_NEGOTIATION *pInfNegotiation;
  771. SCEP_EXTEND *pInfExtend;
  772. pInfVersion = (SCEP_VERSION*)pPdu->Rest;
  773. pInfNegotiation = (SCEP_NEGOTIATION*)( sizeof(SCEP_VERSION)
  774. + (char*)pInfVersion );
  775. pInfExtend = (SCEP_EXTEND*)( FIELD_OFFSET(SCEP_NEGOTIATION,InfVersion)
  776. + pInfNegotiation->Length
  777. + (char*)pInfNegotiation );
  778. //
  779. m_CFlag = pInfNegotiation->CFlag;
  780. m_pSecondaryMachineId = (UCHAR*)AllocateMemory(MACHINE_ID_SIZE);
  781. if (!m_pSecondaryMachineId)
  782. {
  783. return ERROR_IRTRANP_OUT_OF_MEMORY;
  784. }
  785. memcpy( m_pSecondaryMachineId,
  786. pInfNegotiation->SecondaryMachineId,
  787. MACHINE_ID_SIZE );
  788. m_pPrimaryMachineId = (UCHAR*)AllocateMemory(MACHINE_ID_SIZE);
  789. if (!m_pPrimaryMachineId)
  790. {
  791. FreeMemory(m_pSecondaryMachineId);
  792. return ERROR_IRTRANP_OUT_OF_MEMORY;
  793. }
  794. memcpy( m_pPrimaryMachineId,
  795. pInfNegotiation->PrimaryMachineId,
  796. MACHINE_ID_SIZE );
  797. // NOTE: The size of the negotiaion "text" is 18 bytes less than
  798. // the length in the SCEP_NEGOTIATION record:
  799. dwLength = pInfNegotiation->Length
  800. - ( sizeof(pInfNegotiation->InfVersion)
  801. + sizeof(pInfNegotiation->CFlag)
  802. + sizeof(pInfNegotiation->SecondaryMachineId)
  803. + sizeof(pInfNegotiation->PrimaryMachineId));
  804. dwStatus = ParseNegotiation( pInfNegotiation->Negotiation, dwLength );
  805. return dwStatus;
  806. }
  807. //--------------------------------------------------------------------
  808. // CSCEP_CONNECTION::ParseConnectRespPdu()
  809. //
  810. // AssemblePDU() already did basic integrity checking of the PDU
  811. // (via CheckConnectRespPdu()), so at this point we'll assume
  812. // everything is Ok.
  813. //
  814. // NOTE: The Connect Response PDU is limited to 255 bytes in total
  815. // length, so it will never be fragmented.
  816. //--------------------------------------------------------------------
  817. DWORD CSCEP_CONNECTION::ParseConnectRespPdu( IN SCEP_HEADER *pPdu,
  818. IN DWORD dwPduSize )
  819. {
  820. DWORD dwStatus;
  821. DWORD dwLength;
  822. SCEP_NEGOTIATION *pInfNegotiation;
  823. if (dwPduSize > MAX_PDU_SIZE_CONNECT)
  824. {
  825. return ERROR_SCEP_INVALID_PROTOCOL;
  826. }
  827. pInfNegotiation = (SCEP_NEGOTIATION*)( sizeof(SCEP_HEADER)
  828. + (char*)pPdu );
  829. // This is the CFlag sent by the other machine.
  830. m_CFlag = pInfNegotiation->CFlag;
  831. m_pSecondaryMachineId = (UCHAR*)AllocateMemory(MACHINE_ID_SIZE);
  832. if (!m_pSecondaryMachineId)
  833. {
  834. return ERROR_IRTRANP_OUT_OF_MEMORY;
  835. }
  836. memcpy( m_pSecondaryMachineId,
  837. pInfNegotiation->SecondaryMachineId,
  838. MACHINE_ID_SIZE );
  839. m_pPrimaryMachineId = (UCHAR*)AllocateMemory(MACHINE_ID_SIZE);
  840. if (!m_pPrimaryMachineId)
  841. {
  842. FreeMemory(m_pSecondaryMachineId);
  843. return ERROR_IRTRANP_OUT_OF_MEMORY;
  844. }
  845. memcpy( m_pPrimaryMachineId,
  846. pInfNegotiation->PrimaryMachineId,
  847. MACHINE_ID_SIZE );
  848. // NOTE: The size of the negotiaion "text" is 18 bytes less than
  849. // the length in the SCEP_NEGOTIATION record:
  850. dwLength = pInfNegotiation->Length
  851. - ( sizeof(pInfNegotiation->InfVersion)
  852. + sizeof(pInfNegotiation->CFlag)
  853. + sizeof(pInfNegotiation->SecondaryMachineId)
  854. + sizeof(pInfNegotiation->PrimaryMachineId));
  855. dwStatus = ParseNegotiation( pInfNegotiation->Negotiation, dwLength );
  856. return dwStatus;
  857. }
  858. //--------------------------------------------------------------------
  859. // CSCEP_CONNECTION::ParseNegotiation()
  860. //
  861. //--------------------------------------------------------------------
  862. DWORD CSCEP_CONNECTION::ParseNegotiation( IN UCHAR *pNegotiation,
  863. IN DWORD dwNegotiationSize )
  864. {
  865. DWORD dwStatus = NO_ERROR;
  866. UCHAR *pNext = pNegotiation;
  867. DWORD dwSize = dwNegotiationSize;
  868. if (dwNegotiationSize <= 1)
  869. {
  870. return NO_ERROR;
  871. }
  872. if (*(pNext++) < NEGOTIATION_VERSION)
  873. {
  874. return ERROR_SCEP_INVALID_PROTOCOL;
  875. }
  876. dwSize--;
  877. while (pNext=ParseAttribute(pNext,
  878. &dwSize,
  879. &dwStatus))
  880. {
  881. if (dwStatus != NO_ERROR)
  882. {
  883. break;
  884. }
  885. }
  886. return dwStatus;
  887. }
  888. //--------------------------------------------------------------------
  889. // CSCEP_CONNECTION::ParseAttribute()
  890. //
  891. // Attributes are of the form:
  892. //
  893. // Attr <- AttrName Colon AttrValue CrLf
  894. //
  895. // AttrName <- Two byte attribute name.
  896. //
  897. // Colon <- ':'
  898. //
  899. // AttrValue <- Character string (bytes > 0x1f and < 0x8f).
  900. //
  901. // CrLf <- 0x0d 0x0a
  902. //
  903. //--------------------------------------------------------------------
  904. UCHAR *CSCEP_CONNECTION::ParseAttribute( IN UCHAR *pAttributes,
  905. IN DWORD *pdwAttributeSize,
  906. OUT DWORD *pdwStatus )
  907. {
  908. int iAttribute;
  909. int iPduSize;
  910. ATTRIBUTE_TOKEN *pToken1 = 0;
  911. ATTRIBUTE_TOKEN *pToken2 = 0;
  912. ATTRIBUTE_TOKEN *pToken3 = 0;
  913. ATTRIBUTE_TOKEN *pToken4 = 0;
  914. *pdwStatus = NO_ERROR;
  915. if ( (pToken1=NextToken(ATTRIBUTE_NAME,&pAttributes,pdwAttributeSize))
  916. && (IsAttributeName(pToken1,&iAttribute))
  917. && (pToken2=NextToken(ATTRIBUTE_COLON,&pAttributes,pdwAttributeSize))
  918. && (pToken3=NextToken(ATTRIBUTE_VALUE,&pAttributes,pdwAttributeSize))
  919. && (pToken4=NextToken(ATTRIBUTE_CRLF,&pAttributes,pdwAttributeSize)) )
  920. {
  921. if (iAttribute == ATTR_PDU_SIZE)
  922. {
  923. iPduSize = pToken3->pChars[0] - ONE;
  924. if ((pToken3->dwSize == 1)&&(iPduSize >= 1)&&(iPduSize <= 4))
  925. {
  926. m_dwPduSendSize = g_adwPduSizes[iPduSize];
  927. #ifdef DBG_IO
  928. DbgPrint("ParseAttribute(): PduSendSize: %d\n",m_dwPduSendSize);
  929. #endif
  930. }
  931. }
  932. else
  933. if (iAttribute == ATTR_PRODUCT_ID)
  934. {
  935. m_pszProductId = NewTokenString(pToken3,pdwStatus);
  936. if (!m_pszProductId)
  937. {
  938. pAttributes = 0;
  939. #ifdef DBG_IO
  940. DbgPrint("ParseAttribute(): Product: %s\n",m_pszProductId);
  941. #endif
  942. }
  943. }
  944. else
  945. if (iAttribute == ATTR_USER_NAME)
  946. {
  947. m_pszUserName = NewTokenString(pToken3,pdwStatus);
  948. if (!m_pszUserName)
  949. {
  950. pAttributes = 0;
  951. }
  952. }
  953. else
  954. if (iAttribute == ATTR_PASSWORD)
  955. {
  956. m_pszPassword = NewTokenString(pToken3,pdwStatus);
  957. if (!m_pszPassword)
  958. {
  959. pAttributes = 0;
  960. }
  961. }
  962. }
  963. else
  964. {
  965. if (*pdwAttributeSize > 0)
  966. {
  967. *pdwStatus = ERROR_SCEP_INVALID_PROTOCOL;
  968. }
  969. pAttributes = 0;
  970. }
  971. if (pToken1) FreeMemory(pToken1);
  972. if (pToken2) FreeMemory(pToken2);
  973. if (pToken3) FreeMemory(pToken3);
  974. if (pToken4) FreeMemory(pToken4);
  975. return pAttributes;
  976. }
  977. //--------------------------------------------------------------------
  978. // CSCEP_CONNECTION::ParseDataPdu()
  979. //
  980. // AssemblePDU() already did basic integrity checking of the PDU
  981. // (via CheckConnectPdu()), so at this point we'll assume everything
  982. // is Ok.
  983. //
  984. // NOTE: The Data PDU is limited to m_dwPduReceiveSize bytes in total
  985. // length, if data is longer then you will get the fragmented versions
  986. // of the Data PDU.
  987. //--------------------------------------------------------------------
  988. DWORD CSCEP_CONNECTION::ParseDataPdu( IN SCEP_HEADER *pPdu,
  989. IN DWORD dwPduSize,
  990. OUT COMMAND_HEADER **ppCommand,
  991. OUT UCHAR **ppUserData,
  992. OUT DWORD *pdwUserDataSize )
  993. {
  994. DWORD dwStatus = NO_ERROR;
  995. DWORD dwLengthOffset1;
  996. DWORD dwLengthOffset3;
  997. // There are four cases of Data PDUs, single (unfragmented)
  998. // "short" and "long" PDUs, and fragmented "short" and
  999. // "long" PDUs:
  1000. SCEP_REQ_HEADER_SHORT *pReqHeaderShort;
  1001. SCEP_REQ_HEADER_LONG *pReqHeaderLong;
  1002. SCEP_REQ_HEADER_SHORT_FRAG *pReqHeaderShortFrag;
  1003. SCEP_REQ_HEADER_LONG_FRAG *pReqHeaderLongFrag;
  1004. *ppCommand = 0;
  1005. // Make sure the packet length makes sense...
  1006. if (dwPduSize > m_dwPduReceiveSize)
  1007. {
  1008. return ERROR_SCEP_INVALID_PROTOCOL;
  1009. }
  1010. pReqHeaderShort = (SCEP_REQ_HEADER_SHORT*)(pPdu->Rest);
  1011. if (pReqHeaderShort->InfType != INF_TYPE_USER_DATA)
  1012. {
  1013. return ERROR_SCEP_INVALID_PROTOCOL;
  1014. }
  1015. //
  1016. // See if we have a short or long PDU:
  1017. //
  1018. if (pReqHeaderShort->Length1 != USE_LENGTH2)
  1019. {
  1020. // This is a short PDU (use Length1).
  1021. m_DFlag = pReqHeaderShort->DFlag;
  1022. if ( (pReqHeaderShort->DFlag == DFLAG_SINGLE_PDU)
  1023. || (pReqHeaderShort->DFlag == DFLAG_CONNECT_REJECT))
  1024. {
  1025. //
  1026. // This is a short unfragmented PDU.
  1027. //
  1028. // Make sure that a command header is present:
  1029. if (pReqHeaderShort->Length1 > 4)
  1030. {
  1031. *ppCommand = (COMMAND_HEADER*)(pReqHeaderShort->CommandHeader);
  1032. m_SrcPid = (*ppCommand)->SrcPid;
  1033. m_DestPid = (*ppCommand)->DestPid;
  1034. m_dwCommandId = (*ppCommand)->CommandId;
  1035. }
  1036. else
  1037. {
  1038. *ppCommand = 0;
  1039. }
  1040. *ppUserData = COMMAND_HEADER_SIZE + pReqHeaderShort->CommandHeader;
  1041. *pdwUserDataSize = pReqHeaderShort->Length3 - COMMAND_HEADER_SIZE;
  1042. m_Fragmented = FALSE;
  1043. m_dwSequenceNo = 0;
  1044. m_dwRestNo = 0;
  1045. // In this case, there are two different lengths
  1046. // in the PDU that must add up to dwPduSize...
  1047. //
  1048. // Note: Not currently testing Length1 for consistency...
  1049. //
  1050. dwLengthOffset3 = sizeof(SCEP_HEADER)
  1051. + FIELD_OFFSET(SCEP_REQ_HEADER_SHORT,CommandHeader);
  1052. if (dwPduSize != dwLengthOffset3+pReqHeaderShort->Length3)
  1053. {
  1054. dwStatus = ERROR_SCEP_INVALID_PROTOCOL;
  1055. }
  1056. }
  1057. else if (pReqHeaderShort->DFlag == DFLAG_FIRST_FRAGMENT)
  1058. {
  1059. //
  1060. // This is a short fragmented PDU, and is the first
  1061. // fragment, so it will contain a COMMAND_HEADER.
  1062. //
  1063. // In practice, this should probably never show up...
  1064. pReqHeaderShortFrag = (SCEP_REQ_HEADER_SHORT_FRAG*)pReqHeaderShort;
  1065. // The command header is present only on the first fragment
  1066. // of a multi-fragment PDU:
  1067. if (pReqHeaderShortFrag->SequenceNo == 0)
  1068. {
  1069. *ppCommand
  1070. = (COMMAND_HEADER*)(pReqHeaderShortFrag->CommandHeader);
  1071. m_SrcPid = (*ppCommand)->SrcPid;
  1072. m_DestPid = (*ppCommand)->DestPid;
  1073. m_dwCommandId = (*ppCommand)->CommandId;
  1074. }
  1075. else
  1076. {
  1077. *ppCommand = 0;
  1078. }
  1079. *ppUserData
  1080. = COMMAND_HEADER_SIZE + pReqHeaderShortFrag->CommandHeader;
  1081. *pdwUserDataSize
  1082. = pReqHeaderShortFrag->Length3 - COMMAND_HEADER_SIZE;
  1083. m_Fragmented = TRUE;
  1084. m_dwSequenceNo = pReqHeaderShortFrag->SequenceNo;
  1085. m_dwRestNo = pReqHeaderShortFrag->RestNo;
  1086. // Check the two length fields for consistency:
  1087. dwLengthOffset1 = sizeof(SCEP_HEADER)
  1088. + FIELD_OFFSET(SCEP_REQ_HEADER_SHORT_FRAG,InfVersion);
  1089. dwLengthOffset3 = sizeof(SCEP_HEADER)
  1090. + FIELD_OFFSET(SCEP_REQ_HEADER_SHORT_FRAG,SequenceNo);
  1091. if ( (dwPduSize != dwLengthOffset1+pReqHeaderShortFrag->Length1)
  1092. || (dwPduSize != dwLengthOffset3+pReqHeaderShortFrag->Length3) )
  1093. {
  1094. dwStatus = ERROR_SCEP_INVALID_PROTOCOL;
  1095. }
  1096. }
  1097. else if ( (pReqHeaderShort->DFlag == DFLAG_FRAGMENT)
  1098. || (pReqHeaderShort->DFlag == DFLAG_LAST_FRAGMENT))
  1099. {
  1100. //
  1101. // This is a short fragmented PDU.
  1102. //
  1103. // The 2nd through last fragmented PDUs don't contain a
  1104. // COMMAND_HEADER, just data after Length3.
  1105. pReqHeaderShortFrag = (SCEP_REQ_HEADER_SHORT_FRAG*)pReqHeaderShort;
  1106. // The command header is present only on the first fragment
  1107. // of a multi-fragment PDU:
  1108. if (pReqHeaderShortFrag->SequenceNo == 0)
  1109. {
  1110. *ppCommand
  1111. = (COMMAND_HEADER*)(pReqHeaderShortFrag->CommandHeader);
  1112. m_SrcPid = (*ppCommand)->SrcPid;
  1113. m_DestPid = (*ppCommand)->DestPid;
  1114. m_dwCommandId = (*ppCommand)->CommandId;
  1115. }
  1116. else
  1117. {
  1118. *ppCommand = 0;
  1119. }
  1120. *ppUserData = pReqHeaderShortFrag->CommandHeader;
  1121. *pdwUserDataSize = pReqHeaderShortFrag->Length3;
  1122. m_Fragmented = TRUE;
  1123. m_dwSequenceNo = pReqHeaderShortFrag->SequenceNo;
  1124. m_dwRestNo = pReqHeaderShortFrag->RestNo;
  1125. // Check the two length fields for consistency:
  1126. dwLengthOffset1 = sizeof(SCEP_HEADER)
  1127. + FIELD_OFFSET(SCEP_REQ_HEADER_SHORT_FRAG,InfVersion);
  1128. dwLengthOffset3 = sizeof(SCEP_HEADER)
  1129. + FIELD_OFFSET(SCEP_REQ_HEADER_SHORT_FRAG,SequenceNo);
  1130. if ( (dwPduSize != dwLengthOffset1+pReqHeaderShortFrag->Length1)
  1131. || (dwPduSize != dwLengthOffset3+pReqHeaderShortFrag->Length3) )
  1132. {
  1133. dwStatus = ERROR_SCEP_INVALID_PROTOCOL;
  1134. }
  1135. }
  1136. else
  1137. {
  1138. // Undefined DFlag, we've got a problem...
  1139. dwStatus = ERROR_SCEP_INVALID_PROTOCOL;
  1140. }
  1141. }
  1142. else
  1143. {
  1144. // We have a long PDU.
  1145. pReqHeaderLong = (SCEP_REQ_HEADER_LONG*)pReqHeaderShort;
  1146. m_DFlag = pReqHeaderLong->DFlag;
  1147. if ( (pReqHeaderLong->DFlag == DFLAG_SINGLE_PDU)
  1148. || (pReqHeaderLong->DFlag == DFLAG_CONNECT_REJECT))
  1149. {
  1150. //
  1151. // This is a long unfragmented PDU.
  1152. //
  1153. *ppCommand = (COMMAND_HEADER*)(pReqHeaderLong->CommandHeader);
  1154. *ppUserData = COMMAND_HEADER_SIZE + pReqHeaderLong->CommandHeader;
  1155. *pdwUserDataSize = pReqHeaderLong->Length3 - COMMAND_HEADER_SIZE;
  1156. m_Fragmented = FALSE;
  1157. m_dwSequenceNo = 0;
  1158. m_dwRestNo = 0;
  1159. m_SrcPid = (*ppCommand)->SrcPid;
  1160. m_DestPid = (*ppCommand)->DestPid;
  1161. m_dwCommandId = (*ppCommand)->CommandId;
  1162. // In this case, there are two different lengths
  1163. // in the PDU that must add up to dwPduSize...
  1164. if ( (dwPduSize != 6UL+pReqHeaderLong->Length2)
  1165. || (dwPduSize != 10UL+pReqHeaderLong->Length3))
  1166. {
  1167. dwStatus = ERROR_SCEP_INVALID_PROTOCOL;
  1168. }
  1169. }
  1170. else if (pReqHeaderLong->DFlag == DFLAG_FIRST_FRAGMENT)
  1171. {
  1172. //
  1173. // This is the first fragment of a long fragmented PDU.
  1174. //
  1175. pReqHeaderLongFrag = (SCEP_REQ_HEADER_LONG_FRAG*)pReqHeaderLong;
  1176. m_pCommandHeader = (COMMAND_HEADER*)AllocateMemory(sizeof(COMMAND_HEADER));
  1177. if (!m_pCommandHeader)
  1178. {
  1179. dwStatus = ERROR_IRTRANP_OUT_OF_MEMORY;
  1180. }
  1181. else
  1182. {
  1183. memcpy(m_pCommandHeader,
  1184. pReqHeaderLongFrag->CommandHeader,
  1185. COMMAND_HEADER_SIZE );
  1186. *ppCommand = m_pCommandHeader;
  1187. }
  1188. *ppUserData = COMMAND_HEADER_SIZE + pReqHeaderLongFrag->CommandHeader;
  1189. *pdwUserDataSize = pReqHeaderLongFrag->Length3 - COMMAND_HEADER_SIZE;
  1190. m_Fragmented = TRUE;
  1191. m_dwSequenceNo = pReqHeaderLongFrag->SequenceNo;
  1192. m_dwRestNo = pReqHeaderLongFrag->RestNo;
  1193. if (*ppCommand)
  1194. {
  1195. m_dwCommandId = (*ppCommand)->CommandId;
  1196. }
  1197. else
  1198. {
  1199. m_dwCommandId = 0;
  1200. }
  1201. // Check the two length fields for consistency:
  1202. if ( (dwPduSize != (DWORD)6+pReqHeaderLongFrag->Length2)
  1203. || (dwPduSize != (DWORD)18+pReqHeaderLongFrag->Length3) )
  1204. {
  1205. dwStatus = ERROR_SCEP_INVALID_PROTOCOL;
  1206. }
  1207. }
  1208. else if ( (pReqHeaderLong->DFlag == DFLAG_FRAGMENT)
  1209. || (pReqHeaderLong->DFlag == DFLAG_LAST_FRAGMENT) )
  1210. {
  1211. //
  1212. // This is the second through last fragment of a long
  1213. // fragmented PDU.
  1214. //
  1215. // In this case the PDU doesn't contain a command
  1216. // header, just more user data...
  1217. //
  1218. pReqHeaderLongFrag = (SCEP_REQ_HEADER_LONG_FRAG*)pReqHeaderLong;
  1219. *ppCommand = m_pCommandHeader;
  1220. *ppUserData = (UCHAR*)(pReqHeaderLongFrag->CommandHeader);
  1221. *pdwUserDataSize = pReqHeaderLongFrag->Length3;
  1222. m_Fragmented = TRUE;
  1223. m_dwSequenceNo = pReqHeaderLongFrag->SequenceNo;
  1224. m_dwRestNo = pReqHeaderLongFrag->RestNo;
  1225. m_dwCommandId = (*ppCommand)->CommandId;
  1226. // Check the two length fields for consistency:
  1227. if ( (dwPduSize != (DWORD)6+pReqHeaderLongFrag->Length2)
  1228. || (dwPduSize != (DWORD)18+pReqHeaderLongFrag->Length3) )
  1229. {
  1230. dwStatus = ERROR_SCEP_INVALID_PROTOCOL;
  1231. }
  1232. }
  1233. else
  1234. {
  1235. // Undefined DFlag, we've got a problem...
  1236. dwStatus = ERROR_SCEP_INVALID_PROTOCOL;
  1237. }
  1238. }
  1239. return dwStatus;
  1240. }
  1241. //--------------------------------------------------------------------
  1242. // CSCEP_CONNECTION::ParseDisconnectPdu()
  1243. //
  1244. // NOTE: In practice, reason codes should always be 2 bytes for
  1245. // SCEP version 1.0.
  1246. //--------------------------------------------------------------------
  1247. DWORD CSCEP_CONNECTION::ParseDisconnectPdu( IN SCEP_HEADER *pPdu,
  1248. IN DWORD dwPduSize )
  1249. {
  1250. DWORD dwStatus;
  1251. SCEP_DISCONNECT *pDisconnect = (SCEP_DISCONNECT*)(pPdu->Rest);
  1252. if ( (pDisconnect->InfType != INF_TYPE_REASON)
  1253. || (pDisconnect->Length1 != sizeof(USHORT))
  1254. || (pDisconnect->ReasonCode == 0) )
  1255. {
  1256. dwStatus = ERROR_SCEP_UNSPECIFIED_DISCONNECT;
  1257. }
  1258. else if (pDisconnect->ReasonCode == 1)
  1259. {
  1260. dwStatus = ERROR_SCEP_USER_DISCONNECT;
  1261. }
  1262. else if (pDisconnect->ReasonCode == 2)
  1263. {
  1264. dwStatus = ERROR_SCEP_PROVIDER_DISCONNECT;
  1265. }
  1266. else
  1267. {
  1268. dwStatus = ERROR_SCEP_UNSPECIFIED_DISCONNECT;
  1269. }
  1270. return dwStatus;
  1271. }
  1272. //--------------------------------------------------------------------
  1273. // CSCEP_CONNECTION::ParsePdu()
  1274. //
  1275. //--------------------------------------------------------------------
  1276. DWORD CSCEP_CONNECTION::ParsePdu( IN SCEP_HEADER *pPdu,
  1277. IN DWORD dwPduSize,
  1278. OUT COMMAND_HEADER **ppCommandHeader,
  1279. OUT UCHAR **ppUserData,
  1280. OUT DWORD *pdwUserDataSize )
  1281. {
  1282. DWORD dwStatus = NO_ERROR;
  1283. *ppCommandHeader = 0;
  1284. *ppUserData = 0;
  1285. *pdwUserDataSize = 0;
  1286. switch (pPdu->MsgType)
  1287. {
  1288. case MSG_TYPE_CONNECT_REQ:
  1289. dwStatus = ParseConnectPdu( pPdu, dwPduSize );
  1290. break;
  1291. case MSG_TYPE_CONNECT_RESP:
  1292. dwStatus = ParseConnectRespPdu( pPdu, dwPduSize );
  1293. break;
  1294. case MSG_TYPE_DATA:
  1295. dwStatus = ParseDataPdu( pPdu,
  1296. dwPduSize,
  1297. ppCommandHeader,
  1298. ppUserData,
  1299. pdwUserDataSize );
  1300. break;
  1301. case MSG_TYPE_DISCONNECT:
  1302. dwStatus = ParseDisconnectPdu( pPdu, dwPduSize );
  1303. break;
  1304. }
  1305. return dwStatus;
  1306. }
  1307. //--------------------------------------------------------------------
  1308. // CSCEP_CONNECTION::BuildConnectPdu()
  1309. //
  1310. //--------------------------------------------------------------------
  1311. DWORD CSCEP_CONNECTION::BuildConnectPdu( OUT SCEP_HEADER **ppPdu,
  1312. OUT DWORD *pdwPduSize )
  1313. {
  1314. DWORD dwStatus = NO_ERROR;
  1315. DWORD dwPduSize;
  1316. SCEP_HEADER *pHeader;
  1317. SCEP_VERSION *pVersion;
  1318. SCEP_NEGOTIATION *pNegotiation;
  1319. SCEP_EXTEND *pExtend;
  1320. *ppPdu = 0;
  1321. *pdwPduSize = 0;
  1322. // Note that the PDU size doesn't include a trailing zero, as you
  1323. // would think by lookin at "sizeof(CONNECT_PDU_ATTRIBUTES)" below.
  1324. // The extra byte is for the first byte of the Negotiation string
  1325. // (which is the Negotiation version), so the eqn below is +1-1...
  1326. dwPduSize = sizeof(SCEP_HEADER)
  1327. + sizeof(SCEP_VERSION)
  1328. + sizeof(SCEP_NEGOTIATION)
  1329. + sizeof(CONNECT_PDU_ATTRIBUTES)
  1330. + sizeof(SCEP_EXTEND);
  1331. pHeader = NewPdu(); // Defaulting dwPduSize to MAX_PDU_SIZE
  1332. if (!pHeader)
  1333. {
  1334. return ERROR_IRTRANP_OUT_OF_MEMORY;
  1335. }
  1336. memset(pHeader,0,MAX_PDU_SIZE); // MAX_PDU_SIZE since dwPduSize is defauled above.
  1337. pHeader->Null = 0;
  1338. pHeader->MsgType = MSG_TYPE_CONNECT_REQ;
  1339. pVersion = (SCEP_VERSION*)(pHeader->Rest);
  1340. pVersion->InfType = INF_TYPE_VERSION;
  1341. pVersion->Version = PROTOCOL_VERSION;
  1342. pNegotiation = (SCEP_NEGOTIATION*)((char*)pVersion + sizeof(SCEP_VERSION));
  1343. pNegotiation->InfType = INF_TYPE_NEGOTIATION;
  1344. pNegotiation->Length = 18 + sizeof(CONNECT_PDU_ATTRIBUTES);
  1345. pNegotiation->InfVersion = INF_VERSION;
  1346. pNegotiation->CFlag = CFLAG_ISSUE_OR_EXECUTE;
  1347. // pNegotiation->SecondaryMachineId -- Leave set to zeros...
  1348. // pNegotiation->PrimaryMachineId -- Leave set to zeros...
  1349. pNegotiation->Negotiation[0] = NEGOTIATION_VERSION;
  1350. memcpy( &(pNegotiation->Negotiation[1]),
  1351. CONNECT_PDU_ATTRIBUTES,
  1352. sizeof(CONNECT_PDU_ATTRIBUTES)-1 ); // No Trailing zero...
  1353. pExtend = (SCEP_EXTEND*)( (char*)pHeader + dwPduSize - sizeof(SCEP_EXTEND));
  1354. pExtend->InfType = INF_TYPE_EXTEND;
  1355. pExtend->Length = 2;
  1356. pExtend->Parameter1 = 0;
  1357. pExtend->Parameter2 = 0;
  1358. *ppPdu = pHeader;
  1359. *pdwPduSize = dwPduSize;
  1360. return dwStatus;
  1361. }
  1362. //--------------------------------------------------------------------
  1363. // CSCEP_CONNECTION::BuildConnectRespPdu()
  1364. //
  1365. // This is the response PDU for a connection request from a camera.
  1366. //--------------------------------------------------------------------
  1367. DWORD CSCEP_CONNECTION::BuildConnectRespPdu( OUT SCEP_HEADER **ppPdu,
  1368. OUT DWORD *pdwPduSize )
  1369. {
  1370. DWORD dwStatus = NO_ERROR;
  1371. DWORD dwPduSize;
  1372. SCEP_HEADER *pHeader;
  1373. SCEP_NEGOTIATION *pNegotiation;
  1374. *ppPdu = 0;
  1375. *pdwPduSize = 0;
  1376. // Note that the PDU size doesn't include a trailing zero, as you
  1377. // would think by lookin at "sizeof(RESPONSE_PDU_ATTRIBUTES)" below,
  1378. // the extra byte in for the first byte of the Negotiation string
  1379. // which is the Negotiation version, so the eqn below is +1-1...
  1380. dwPduSize = sizeof(SCEP_HEADER)
  1381. + sizeof(SCEP_NEGOTIATION)
  1382. + sizeof(RESPONSE_PDU_ATTRIBUTES);
  1383. pHeader = NewPdu();
  1384. if (!pHeader)
  1385. {
  1386. return ERROR_IRTRANP_OUT_OF_MEMORY;
  1387. }
  1388. memset(pHeader,0,MAX_PDU_SIZE); // MAX_PDU_SIZE is default arg in NewPdu().
  1389. pHeader->Null = 0;
  1390. pHeader->MsgType = MSG_TYPE_CONNECT_RESP;
  1391. pNegotiation = (SCEP_NEGOTIATION*)(pHeader->Rest);
  1392. pNegotiation->InfType = INF_TYPE_NEGOTIATION;
  1393. pNegotiation->Length = 18 + sizeof(RESPONSE_PDU_ATTRIBUTES);
  1394. pNegotiation->InfVersion = INF_VERSION;
  1395. pNegotiation->CFlag = CFLAG_ISSUE_OR_EXECUTE;
  1396. memcpy( pNegotiation->SecondaryMachineId,
  1397. m_pPrimaryMachineId,
  1398. MACHINE_ID_SIZE );
  1399. memcpy( pNegotiation->PrimaryMachineId,
  1400. m_pSecondaryMachineId,
  1401. MACHINE_ID_SIZE );
  1402. pNegotiation->Negotiation[0] = NEGOTIATION_VERSION;
  1403. memcpy( &(pNegotiation->Negotiation[1]),
  1404. RESPONSE_PDU_ATTRIBUTES,
  1405. sizeof(RESPONSE_PDU_ATTRIBUTES)-1 ); // No Trailing zero...
  1406. *ppPdu = pHeader;
  1407. *pdwPduSize = dwPduSize;
  1408. return dwStatus;
  1409. }
  1410. //--------------------------------------------------------------------
  1411. // CSCEP_CONNECTION::BuildConnectNackPdu()
  1412. //
  1413. // This is the response PDU for a connection request from a camera
  1414. // when we want to reject the connection request.
  1415. //--------------------------------------------------------------------
  1416. DWORD CSCEP_CONNECTION::BuildConnectNackPdu( OUT SCEP_HEADER **ppPdu,
  1417. OUT DWORD *pdwPduSize )
  1418. {
  1419. DWORD dwStatus = NO_ERROR;
  1420. DWORD dwPduSize;
  1421. SCEP_HEADER *pHeader;
  1422. SCEP_REQ_HEADER_SHORT *pReqHeader;
  1423. *ppPdu = 0;
  1424. *pdwPduSize = 0;
  1425. // A short PDU, there is now command header, so Length3 is zero...
  1426. dwPduSize = sizeof(SCEP_HEADER)
  1427. + sizeof(SCEP_REQ_HEADER_SHORT)
  1428. - sizeof(COMMAND_HEADER);
  1429. pHeader = NewPdu();
  1430. if (!pHeader)
  1431. {
  1432. return ERROR_IRTRANP_OUT_OF_MEMORY;
  1433. }
  1434. memset(pHeader,0,MAX_PDU_SIZE);
  1435. pHeader->Null = 0;
  1436. pHeader->MsgType = MSG_TYPE_CONNECT_REQ;
  1437. pReqHeader = (SCEP_REQ_HEADER_SHORT*)(pHeader->Rest);
  1438. pReqHeader->InfType = INF_TYPE_USER_DATA;
  1439. pReqHeader->Length1 = sizeof(pReqHeader->InfVersion)
  1440. + sizeof(pReqHeader->DFlag)
  1441. + sizeof(pReqHeader->Length3);
  1442. pReqHeader->InfVersion = INF_VERSION;
  1443. pReqHeader->DFlag = DFLAG_CONNECT_REJECT;
  1444. pReqHeader->Length3 = 0;
  1445. *ppPdu = pHeader;
  1446. *pdwPduSize = dwPduSize;
  1447. return dwStatus;
  1448. }
  1449. //--------------------------------------------------------------------
  1450. // CSCEP_CONNECTION::BuildAbortPdu()
  1451. //
  1452. //--------------------------------------------------------------------
  1453. DWORD CSCEP_CONNECTION::BuildAbortPdu( OUT SCEP_HEADER **ppPdu,
  1454. OUT DWORD *pdwPduSize )
  1455. {
  1456. DWORD dwStatus = NO_ERROR;
  1457. DWORD dwPduSize;
  1458. SCEP_HEADER *pHeader;
  1459. COMMAND_HEADER *pCommandHeader;
  1460. SCEP_REQ_HEADER_SHORT *pReqHeader;
  1461. *ppPdu = 0;
  1462. *pdwPduSize = 0;
  1463. dwPduSize = sizeof(SCEP_HEADER) + sizeof(SCEP_REQ_HEADER_SHORT);
  1464. pHeader = NewPdu();
  1465. if (!pHeader)
  1466. {
  1467. return ERROR_IRTRANP_OUT_OF_MEMORY;
  1468. }
  1469. memset(pHeader,0,MAX_PDU_SIZE); // MAX_PDU_SIZE is default arg for NewPdu().
  1470. pHeader->Null = 0;
  1471. pHeader->MsgType = MSG_TYPE_DATA;
  1472. pReqHeader = (SCEP_REQ_HEADER_SHORT*)(pHeader->Rest);
  1473. pReqHeader->InfType = INF_TYPE_USER_DATA;
  1474. pReqHeader->Length1 = 4 + sizeof(COMMAND_HEADER);
  1475. pReqHeader->InfVersion = INF_VERSION;
  1476. pReqHeader->DFlag = DFLAG_SINGLE_PDU;
  1477. pReqHeader->Length3 = sizeof(COMMAND_HEADER);
  1478. #ifdef LITTLE_ENDIAN
  1479. pReqHeader->Length3 = ByteSwapShort(pReqHeader->Length3);
  1480. #endif
  1481. pCommandHeader = (COMMAND_HEADER*)(pReqHeader->CommandHeader);
  1482. pCommandHeader->Marker58h = 0x58;
  1483. pCommandHeader->PduType = PDU_TYPE_ABORT;
  1484. pCommandHeader->Length4 = 22;
  1485. pCommandHeader->DestPid = m_SrcPid;
  1486. pCommandHeader->SrcPid = m_DestPid;
  1487. pCommandHeader->CommandId = (USHORT)m_dwCommandId;
  1488. #ifdef LITTLE_ENDIAN
  1489. ByteSwapCommandHeader(pCommandHeader);
  1490. #endif
  1491. *ppPdu = pHeader;
  1492. *pdwPduSize = dwPduSize;
  1493. return dwStatus;
  1494. }
  1495. //--------------------------------------------------------------------
  1496. // CSCEP_CONNECTION::BuildStopPdu()
  1497. //
  1498. //--------------------------------------------------------------------
  1499. DWORD CSCEP_CONNECTION::BuildStopPdu( OUT SCEP_HEADER **ppPdu,
  1500. OUT DWORD *pdwPduSize )
  1501. {
  1502. DWORD dwStatus = NO_ERROR;
  1503. DWORD dwPduSize;
  1504. SCEP_HEADER *pHeader;
  1505. SCEP_REQ_HEADER_SHORT *pReqHeader;
  1506. *ppPdu = 0;
  1507. *pdwPduSize = 0;
  1508. dwPduSize = sizeof(SCEP_HEADER)
  1509. + sizeof(SCEP_REQ_HEADER_SHORT)
  1510. - sizeof(COMMAND_HEADER);
  1511. pHeader = NewPdu();
  1512. if (!pHeader)
  1513. {
  1514. return ERROR_IRTRANP_OUT_OF_MEMORY;
  1515. }
  1516. memset(pHeader,0,MAX_PDU_SIZE); // MAX_PDU_SIZE is default arg for NewPdu() above.
  1517. pHeader->Null = 0;
  1518. pHeader->MsgType = MSG_TYPE_DATA;
  1519. pReqHeader = (SCEP_REQ_HEADER_SHORT*)(pHeader->Rest);
  1520. pReqHeader->InfType = INF_TYPE_USER_DATA;
  1521. pReqHeader->Length1 = 4;
  1522. pReqHeader->InfVersion = INF_VERSION;
  1523. pReqHeader->DFlag = DFLAG_INTERRUPT;
  1524. pReqHeader->Length3 = 0;
  1525. *ppPdu = pHeader;
  1526. *pdwPduSize = dwPduSize;
  1527. return dwStatus;
  1528. }
  1529. //--------------------------------------------------------------------
  1530. // CSCEP_CONNECTION::BuildDisconnectPdu()
  1531. //
  1532. //--------------------------------------------------------------------
  1533. DWORD CSCEP_CONNECTION::BuildDisconnectPdu( IN USHORT ReasonCode,
  1534. OUT SCEP_HEADER **ppPdu,
  1535. OUT DWORD *pdwPduSize )
  1536. {
  1537. DWORD dwStatus = NO_ERROR;
  1538. DWORD dwPduSize;
  1539. SCEP_HEADER *pHeader;
  1540. SCEP_DISCONNECT *pDisconnect;
  1541. *ppPdu = 0;
  1542. *pdwPduSize = 0;
  1543. dwPduSize = sizeof(SCEP_HEADER)
  1544. + sizeof(SCEP_DISCONNECT);
  1545. pHeader = NewPdu();
  1546. if (!pHeader)
  1547. {
  1548. return ERROR_IRTRANP_OUT_OF_MEMORY;
  1549. }
  1550. memset(pHeader,0,MAX_PDU_SIZE); // MAX_PDU_SIZE is default arg for NewPdu() above.
  1551. pHeader->Null = 0;
  1552. pHeader->MsgType = MSG_TYPE_DISCONNECT;
  1553. pDisconnect = (SCEP_DISCONNECT*)(pHeader->Rest);
  1554. pDisconnect->InfType = INF_TYPE_REASON;
  1555. pDisconnect->Length1 = sizeof(pDisconnect->ReasonCode);
  1556. pDisconnect->ReasonCode = ReasonCode;
  1557. #ifdef LITTLE_ENDIAN
  1558. pDisconnect->ReasonCode = ByteSwapShort(pDisconnect->ReasonCode);
  1559. #endif
  1560. *ppPdu = pHeader;
  1561. *pdwPduSize = dwPduSize;
  1562. return dwStatus;
  1563. }
  1564. //--------------------------------------------------------------------
  1565. // CSCEP_CONNECTION::SetScepLength()
  1566. //
  1567. // Update the length fields in a PDU to reflect the total length
  1568. // of a PDU.
  1569. //
  1570. // WARNING: Currently only supports long fragmented PDUs.
  1571. //--------------------------------------------------------------------
  1572. DWORD CSCEP_CONNECTION::SetScepLength( IN SCEP_HEADER *pPdu,
  1573. IN DWORD dwTotalPduSize )
  1574. {
  1575. DWORD dwStatus = NO_ERROR;
  1576. SCEP_REQ_HEADER_LONG_FRAG *pScepHeader;
  1577. if (dwTotalPduSize > MAX_PDU_SIZE)
  1578. {
  1579. dwStatus = ERROR_SCEP_PDU_TOO_LARGE;
  1580. }
  1581. else
  1582. {
  1583. pScepHeader = (SCEP_REQ_HEADER_LONG_FRAG *)(pPdu->Rest);
  1584. pScepHeader->Length1 = USE_LENGTH2;
  1585. pScepHeader->Length2 = (USHORT)dwTotalPduSize - 6;
  1586. pScepHeader->Length3 = (USHORT)dwTotalPduSize - 18;
  1587. #ifdef LITTLE_ENDIAN
  1588. pScepHeader->Length2 = ByteSwapShort(pScepHeader->Length2);
  1589. pScepHeader->Length3 = ByteSwapShort(pScepHeader->Length3);
  1590. #endif
  1591. }
  1592. return dwStatus;
  1593. }