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.

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