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.

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