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.

224 lines
4.8 KiB

  1. //=============================================================================
  2. //
  3. // MODULE: ASN1Base.cxx
  4. //
  5. // Description:
  6. //
  7. // Implementation of the ASN1ParserBase class
  8. //
  9. // Modification History
  10. //
  11. // Mark Pustilnik Date: 06/09/02 - created
  12. //
  13. //=============================================================================
  14. #include "ASN1Parser.hxx"
  15. //
  16. // For a frame which starts with 6a 82 01 30 ... (long form)
  17. //
  18. // 82 (*(Frame+1)) indicates "long form" where Size is 2 (0x82 & 0x7F)
  19. // and the return value is ( 0x01 << 8 ) | 0x30 = 0x130
  20. //
  21. // For a frame which starts with 6a 30 ... (short form)
  22. //
  23. // the return value is simply 0x30
  24. //
  25. DWORD
  26. ASN1ParserBase::DataLength(
  27. IN ASN1FRAME * Frame
  28. )
  29. {
  30. LPBYTE LengthPortion = Frame->Address + 1;
  31. if ( *LengthPortion & 0x80 ) // long form
  32. {
  33. USHORT i;
  34. DWORD Sum = 0;
  35. BYTE Size = *LengthPortion & 0x7F;
  36. for ( i = 1; i <= Size; i++ )
  37. {
  38. Sum <<= 8;
  39. Sum |= *(LengthPortion + i);
  40. }
  41. return Sum;
  42. }
  43. else // short form
  44. {
  45. return *LengthPortion;
  46. }
  47. }
  48. //
  49. // Calculates the length of the length header in either short or long form
  50. // Returns '3' for "82 01 30"
  51. // Returns '1' for "30"
  52. //
  53. ULONG
  54. ASN1ParserBase::HeaderLength(
  55. IN ULPBYTE Address
  56. )
  57. {
  58. if ( *Address & 0x80 )
  59. {
  60. //
  61. // If long form, assign size to value of bits 7-1
  62. //
  63. return ( 1 + *Address & 0x7F);
  64. }
  65. else
  66. {
  67. //
  68. // Short form only takes one octet
  69. //
  70. return 1;
  71. }
  72. }
  73. //
  74. // Verifies that the frame is pointing at the type of item we expect by
  75. // performing a descriptor comparison, then moves past the descriptor and
  76. // the length header. The caller uses this to point the frame at the next
  77. // item to be parsed.
  78. //
  79. DWORD
  80. ASN1ParserBase::VerifyAndSkipHeader(
  81. IN OUT ASN1FRAME * Frame
  82. )
  83. {
  84. DWORD dw;
  85. //
  86. // Check both optional descriptors associated with this frame
  87. //
  88. BYTE Descriptors[2] = { m_Descriptor, m_AppDescriptor };
  89. for ( ULONG i = 0; i < ARRAY_COUNT( Descriptors ); i++ )
  90. {
  91. if ( Descriptors[i] != 0 )
  92. {
  93. //
  94. // Verify the descriptor and bail on mismatch
  95. //
  96. if ( *Frame->Address != Descriptors[i] )
  97. {
  98. dw = ERROR_INVALID_USER_BUFFER;
  99. goto Cleanup;
  100. }
  101. //
  102. // Skip over the descriptor
  103. //
  104. Frame->Address++;
  105. //
  106. // Skip over the length header
  107. //
  108. Frame->Address += HeaderLength( Frame->Address );
  109. }
  110. }
  111. dw = ERROR_SUCCESS;
  112. Cleanup:
  113. return dw;
  114. }
  115. //
  116. // Displays the value of the unit, mapping between the ASN.1 encoding and the
  117. // actual parsed-out value as necessary
  118. //
  119. DWORD
  120. ASN1ParserBase::Display(
  121. IN ASN1FRAME * Frame,
  122. IN ASN1VALUE * Value,
  123. IN HPROPERTY hProperty,
  124. IN DWORD IFlags
  125. )
  126. {
  127. DWORD dw = ERROR_SUCCESS;
  128. DWORD Length;
  129. ULPVOID Address;
  130. switch( Value->ut )
  131. {
  132. case utGeneralizedTime:
  133. Length = sizeof( Value->st );
  134. Address = &Value->st;
  135. break;
  136. case utBoolean:
  137. Length = sizeof( Value->b );
  138. Address = &Value->b;
  139. break;
  140. case utInteger:
  141. case utBitString:
  142. //
  143. // ASN.1 integers are optimally encoded using the fewest number of bytes
  144. // This does not bode well with Netmon which insists on knowing how long
  145. // a value is before displaying it. The mapping below will show both
  146. // the raw buffer and the corresponding value properly
  147. //
  148. Length = sizeof( Value->dw );
  149. Address = &Value->dw;
  150. break;
  151. case utGeneralString:
  152. case utOctetString:
  153. if ( Value->string.l == 0 )
  154. {
  155. Address = "<empty string>";
  156. Length = strlen(( const char * )Address );
  157. }
  158. else
  159. {
  160. Address = Value->string.s;
  161. Length = Value->string.l;
  162. }
  163. break;
  164. default:
  165. //
  166. // By default, display unadulterated raw data pointed to by 'Value'
  167. //
  168. Length = Value->Length;
  169. Address = Value->Address;
  170. }
  171. if ( FALSE == AttachPropertyInstanceEx(
  172. Frame->hFrame,
  173. hProperty,
  174. Value->Length,
  175. Value->Address,
  176. Length,
  177. Address,
  178. 0,
  179. Frame->Level,
  180. IFlags ))
  181. {
  182. dw = ERROR_CAN_NOT_COMPLETE;
  183. }
  184. return dw;
  185. }