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.

354 lines
10 KiB

  1. #include "precomp.h"
  2. DEBUG_FILEZONE(ZONE_T120_GCCNC);
  3. /*
  4. * ogcccode.cpp
  5. *
  6. * Copyright (c) 1994 by DataBeam Corporation, Lexington, KY
  7. *
  8. * Abstract:
  9. * This is the implementation file for the CGCCCoder class. This class
  10. * is responsible for encoding and decoding GCC (T.124) PDU's using ASN.1
  11. * encoding rules via the ASN.1 toolkit. This class is also capable
  12. * of determining the size of both the encoded and decoded PDU's.
  13. *
  14. * Static Variables:
  15. *
  16. * Caveats:
  17. * Only one instance of this class should be in existance at any one time
  18. * due to the static variable.
  19. *
  20. * Author:
  21. * John B. O'Nan
  22. */
  23. /*
  24. * External Interfaces
  25. */
  26. #include <string.h>
  27. #include "ogcccode.h"
  28. /*
  29. * This is a global variable that has a pointer to the one GCC coder that
  30. * is instantiated by the GCC Controller. Most objects know in advance
  31. * whether they need to use the MCS or the GCC coder, so, they do not need
  32. * this pointer in their constructors.
  33. */
  34. CGCCCoder *g_GCCCoder;
  35. /*
  36. * CGCCCoder ()
  37. *
  38. * Public
  39. *
  40. * Functional Description:
  41. * This is the constructor for the CGCCCoder class. It initializes
  42. * the ASN.1 encoder/decoder and sets the encoding rules to the
  43. * Packed-Aligned variant.
  44. */
  45. CGCCCoder::CGCCCoder ()
  46. :m_pEncInfo(NULL),
  47. m_pDecInfo(NULL)
  48. {
  49. // lonchanc: We should move Init out of constructor. However,
  50. // to minimize the changes in the GCC/MCS code, we put it here for now.
  51. // Otherwise, we need to change MCS and Packet interfaces.
  52. // We will move it out and call Init() separately.
  53. Init();
  54. }
  55. BOOL CGCCCoder::Init ( void )
  56. {
  57. BOOL fRet = FALSE;
  58. GCCPDU_Module_Startup();
  59. if (GCCPDU_Module != NULL)
  60. {
  61. if (ASN1_CreateEncoder(
  62. GCCPDU_Module, // ptr to mdule
  63. &m_pEncInfo, // ptr to encoder info
  64. NULL, // buffer ptr
  65. 0, // buffer size
  66. NULL) // parent ptr
  67. == ASN1_SUCCESS)
  68. {
  69. ASSERT(m_pEncInfo != NULL);
  70. fRet = (ASN1_CreateDecoder(
  71. GCCPDU_Module, // ptr to mdule
  72. &m_pDecInfo, // ptr to decoder info
  73. NULL, // buffer ptr
  74. 0, // buffer size
  75. NULL) // parent ptr
  76. == ASN1_SUCCESS);
  77. ASSERT(fRet && m_pDecInfo != NULL);
  78. }
  79. }
  80. ASSERT(fRet);
  81. return fRet;
  82. }
  83. /*
  84. * ~CGCCCoder ()
  85. *
  86. * Public Functional Description:
  87. * This is a virtual destructor. It is used to clean up after ASN.1.
  88. */
  89. CGCCCoder::~CGCCCoder ()
  90. {
  91. if (GCCPDU_Module != NULL)
  92. {
  93. ASN1_CloseEncoder(m_pEncInfo);
  94. ASN1_CloseDecoder(m_pDecInfo);
  95. GCCPDU_Module_Cleanup();
  96. }
  97. }
  98. /*
  99. * Encode ()
  100. *
  101. * Public Functional Description:
  102. * This function encodes GCC Protocol Data Units (PDU's) into ASN.1
  103. * compliant byte streams using the ASN.1 toolkit.
  104. * The coder allocates the buffer space for the encoded data.
  105. */
  106. BOOL CGCCCoder::Encode(LPVOID pdu_structure,
  107. int pdu_type,
  108. UINT nEncodingRule_not_used,
  109. LPBYTE *encoding_buffer,
  110. UINT *encoding_buffer_length)
  111. {
  112. BOOL fRet = FALSE;
  113. int return_value;
  114. ConnectData connect_data_structure;
  115. // clean up local buffer pointer
  116. connect_data_structure.connect_pdu.value = NULL;
  117. /*
  118. * If the PDU to be encoded is a "ConnectGCC" PDU we must first encode the
  119. * "ConnectGCC" PDU. A "ConnectData" PDU structure is then built which
  120. * contains the encoded "ConnectGCC" PDU along with object identifier key.
  121. * The "ConnectData" PDU is then encoded into the provided buffer.
  122. */
  123. if (pdu_type == CONNECT_GCC_PDU)
  124. {
  125. return_value = ASN1_Encode(m_pEncInfo, // ptr to encoder info
  126. pdu_structure, // pdu data structure
  127. pdu_type, // pdu id
  128. ASN1ENCODE_ALLOCATEBUFFER, // flags
  129. NULL, // do not provide buffer
  130. 0); // buffer size if provided
  131. if (ASN1_FAILED(return_value))
  132. {
  133. ERROR_OUT(("CGCCCoder::Encode: ASN1_Encode failed, err=%d in CONNECT_GCC_PDU.",
  134. return_value));
  135. ASSERT(FALSE);
  136. goto MyExit;
  137. }
  138. ASSERT(return_value == ASN1_SUCCESS);
  139. /*
  140. * Fill in the "ConnectData" PDU structure and encode it.
  141. */
  142. connect_data_structure.t124_identifier = t124identifier;
  143. connect_data_structure.connect_pdu.length = m_pEncInfo->len; // len of encoded data in buffer
  144. connect_data_structure.connect_pdu.value = m_pEncInfo->buf; // buffer to encode into
  145. // Prepare for the encode call
  146. pdu_structure = (LPVOID) &connect_data_structure;
  147. pdu_type = CONNECT_DATA_PDU;
  148. }
  149. /*
  150. * Encode the Non-Connect PDU into the buffer provided.
  151. */
  152. return_value = ASN1_Encode(m_pEncInfo, // ptr to encoder info
  153. pdu_structure, // pdu data structure
  154. pdu_type, // pdu id
  155. ASN1ENCODE_ALLOCATEBUFFER, // flags
  156. NULL, // do not provide buffer
  157. 0); // buffer size if provided
  158. if (ASN1_FAILED(return_value))
  159. {
  160. ERROR_OUT(("CGCCCoder::Encode: ASN1_Encode failed, err=%d", return_value));
  161. ASSERT(FALSE);
  162. goto MyExit;
  163. }
  164. ASSERT(return_value == ASN1_SUCCESS);
  165. *encoding_buffer_length = m_pEncInfo->len; // len of encoded data in buffer
  166. *encoding_buffer = m_pEncInfo->buf; // buffer to encode into
  167. fRet = TRUE;
  168. MyExit:
  169. /*
  170. * If this was a CONNECT_DATA_PDU we need to free the buffer that
  171. * was allocated by ASN.1.
  172. */
  173. if (CONNECT_DATA_PDU == pdu_type && connect_data_structure.connect_pdu.value != NULL)
  174. {
  175. ASN1_FreeEncoded(m_pEncInfo, connect_data_structure.connect_pdu.value);
  176. }
  177. return fRet;
  178. }
  179. /*
  180. * Decode ()
  181. *
  182. * Public Functional Description:
  183. * This function decodes ASN.1 compliant byte streams into the
  184. * appropriate GCC PDU structures using the ASN.1 toolkit.
  185. */
  186. BOOL CGCCCoder::Decode(LPBYTE encoded_buffer,
  187. UINT encoded_buffer_length,
  188. int pdu_type,
  189. UINT nEncodingRule_not_used,
  190. LPVOID *pdecoding_buffer,
  191. UINT *pdecoding_buffer_length)
  192. {
  193. BOOL fRet = FALSE;
  194. int return_value;
  195. LPVOID connect_data_decoding_buffer = NULL;
  196. ASN1optionparam_s OptParam;
  197. /*
  198. * If the PDU is a "ConnectGCC" PDU then after it is decoded we must decode
  199. * the "ConnectGCC" PDU which is actually contained within a "ConnectData"
  200. * PDU.
  201. */
  202. if (pdu_type == CONNECT_GCC_PDU)
  203. {
  204. return_value = ASN1_Decode(m_pDecInfo, // ptr to decoder info
  205. &connect_data_decoding_buffer, // destination buffer
  206. CONNECT_DATA_PDU, // pdu type
  207. ASN1DECODE_SETBUFFER, // flags
  208. encoded_buffer, // source buffer
  209. encoded_buffer_length); // source buffer size
  210. if (ASN1_FAILED(return_value))
  211. {
  212. ERROR_OUT(("CGCCCoder::Decode: ASN1_Decode failed, err=%d", return_value));
  213. ASSERT(FALSE);
  214. goto MyExit;
  215. }
  216. ASSERT(return_value == ASN1_SUCCESS);
  217. /*
  218. * If the decoded PDU is a "ConnectData" PDU, then we first must check
  219. * to make sure this PDU originated from a T.124-compliant source.
  220. * If so we then decode the "ConnectGCC" PDU which is held in the
  221. * "connect_pdu" field. If the PDU is not T.124-compliant, we will
  222. * report an error which will cause the PDU to be rejected.
  223. */
  224. if (IsObjectIDCompliant(&(((PConnectData) connect_data_decoding_buffer)->t124_identifier))
  225. == FALSE)
  226. {
  227. ERROR_OUT(("CGCCCoder::Decode: Non-T.124 objectID"));
  228. ASSERT (FALSE);
  229. goto MyExit;
  230. }
  231. ASSERT(connect_data_decoding_buffer != NULL);
  232. encoded_buffer = (PUChar)((PConnectData) connect_data_decoding_buffer)->
  233. connect_pdu.value;
  234. encoded_buffer_length = (UINT)((PConnectData) connect_data_decoding_buffer)->
  235. connect_pdu.length;
  236. }
  237. /*
  238. * Decode the Non-Connect PDU into the buffer provided.
  239. */
  240. return_value = ASN1_Decode(m_pDecInfo, // ptr to decoder info
  241. pdecoding_buffer, // destination buffer
  242. pdu_type, // pdu type
  243. ASN1DECODE_SETBUFFER, // flags
  244. encoded_buffer, // source buffer
  245. encoded_buffer_length); // source buffer size
  246. if (ASN1_FAILED(return_value))
  247. {
  248. ERROR_OUT(("CCCCoder::Decode: ASN1_Decode failed, err=%d", return_value));
  249. ASSERT(FALSE);
  250. goto MyExit;
  251. }
  252. ASSERT(return_value == ASN1_SUCCESS);
  253. OptParam.eOption = ASN1OPT_GET_DECODED_BUFFER_SIZE;
  254. return_value = ASN1_GetDecoderOption(m_pDecInfo, &OptParam);
  255. if (ASN1_FAILED(return_value))
  256. {
  257. ERROR_OUT(("CGCCCoder::Decode: ASN1_GetDecoderOption failed, err=%d", return_value));
  258. ASSERT(FALSE);
  259. goto MyExit;
  260. }
  261. *pdecoding_buffer_length = OptParam.cbRequiredDecodedBufSize;
  262. ASSERT(return_value == ASN1_SUCCESS);
  263. ASSERT(*pdecoding_buffer_length > 0);
  264. fRet = TRUE;
  265. MyExit:
  266. /*
  267. * Free the PDU structure allocated by decoder for the Connect-Data PDU.
  268. */
  269. if (connect_data_decoding_buffer != NULL)
  270. {
  271. ASSERT (pdu_type == CONNECT_GCC_PDU);
  272. ASN1_FreeDecoded(m_pDecInfo, connect_data_decoding_buffer, CONNECT_DATA_PDU);
  273. }
  274. return fRet;
  275. }
  276. /*
  277. * IsObjectIDCompliant ()
  278. *
  279. * Private Functional Description:
  280. * This function is used to verify that the object identifier contained
  281. * in a "Connect" PDU is compliant with this version of GCC.
  282. */
  283. BOOL CGCCCoder::IsObjectIDCompliant (PKey t124_identifier)
  284. {
  285. BOOL return_value = TRUE;
  286. PSetOfObjectID test_object_id_set;
  287. PSetOfObjectID valid_object_id_set;
  288. /*
  289. * First check to make sure that the identifier is a standard Object
  290. * Identifier type.
  291. */
  292. if (t124_identifier->choice == OBJECT_CHOSEN)
  293. {
  294. /*
  295. * Retrieve the object identifier to test and the valid T.124
  296. * identifier ("t124identifier) to use as a comparison.
  297. */
  298. test_object_id_set = t124_identifier->u.object;
  299. valid_object_id_set = t124identifier.u.object;
  300. while ((valid_object_id_set != NULL) && (test_object_id_set != NULL))
  301. {
  302. if (test_object_id_set->value != valid_object_id_set->value)
  303. {
  304. return_value = FALSE;
  305. break;
  306. }
  307. test_object_id_set = test_object_id_set->next;
  308. valid_object_id_set = valid_object_id_set->next;
  309. }
  310. }
  311. else
  312. return_value = FALSE;
  313. return (return_value);
  314. }
  315. void CGCCCoder::FreeEncoded (PUChar encoded_buffer)
  316. {
  317. ASN1_FreeEncoded(m_pEncInfo, encoded_buffer);
  318. }
  319. void CGCCCoder::FreeDecoded (int pdu_type, LPVOID decoded_buffer)
  320. {
  321. ASN1_FreeDecoded(m_pDecInfo, decoded_buffer, pdu_type);
  322. }