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.

302 lines
7.1 KiB

  1. // BEROctet.cpp - Implementation of BEROctet class
  2. //
  3. // (c) Copyright Schlumberger Technology Corp., unpublished work, created
  4. // 1999. This computer program includes Confidential, Proprietary
  5. // Information and is a Trade Secret of Schlumberger Technology Corp. All
  6. // use, disclosure, and/or reproduction is prohibited unless authorized
  7. // in writing. All Rights Reserved.
  8. //////////////////////////////////////////////////////////////////////
  9. #include "pkiBEROctet.h"
  10. using namespace pki;
  11. BEROctet::BEROctet() : m_Octet(0)
  12. {
  13. }
  14. BEROctet::BEROctet(const BEROctet &oct)
  15. {
  16. m_Octet = 0;
  17. *this = oct;
  18. }
  19. BEROctet::BEROctet(const unsigned char *Buffer, const unsigned long Size)
  20. {
  21. m_Octet = new unsigned char[Size];
  22. memcpy(m_Octet,Buffer,Size);
  23. m_OctetSize = Size;
  24. Decode();
  25. }
  26. BEROctet::~BEROctet(void)
  27. {
  28. for(int i=0; i<m_SubOctetList.size(); i++) delete m_SubOctetList[i];
  29. if(m_Octet) delete[] m_Octet;
  30. }
  31. BEROctet& BEROctet::operator=(const BEROctet &Oct)
  32. {
  33. if(m_Octet) delete[] m_Octet;
  34. for(int i=0; i<m_SubOctetList.size(); i++) delete m_SubOctetList[i];
  35. m_SubOctetList.resize(0);
  36. if(Oct.m_Octet) {
  37. m_Octet = new unsigned char[Oct.m_OctetSize];
  38. memcpy(m_Octet,Oct.m_Octet,Oct.m_OctetSize);
  39. m_OctetSize = Oct.m_OctetSize;
  40. Decode();
  41. }
  42. else {
  43. m_Octet = 0;
  44. }
  45. return *this;
  46. }
  47. // Returns the octet data
  48. unsigned char *BEROctet::Octet() const
  49. {
  50. return m_Octet;
  51. }
  52. unsigned long BEROctet::OctetSize() const
  53. {
  54. if(!m_Octet) throw Exception(ccBEREmptyOctet);
  55. return m_OctetSize;
  56. }
  57. // Returns true if the octet is constructet, false otherwise
  58. bool BEROctet::Constructed() const
  59. {
  60. if(!m_Octet) throw Exception(ccBEREmptyOctet);
  61. return m_PrimConst ? true : false;
  62. }
  63. // Returns the class of the octet
  64. unsigned long BEROctet::Class() const
  65. {
  66. if(!m_Octet) throw Exception(ccBEREmptyOctet);
  67. return m_Class;
  68. }
  69. // Returns the tag of the octet
  70. unsigned long BEROctet::Tag() const
  71. {
  72. if(!m_Octet) throw Exception(ccBEREmptyOctet);
  73. return m_Tag;
  74. }
  75. // Returns a the data part of the octet
  76. unsigned char *BEROctet::Data() const
  77. {
  78. if(!m_Octet) throw Exception(ccBEREmptyOctet);
  79. return m_Data;
  80. }
  81. // Returns a the size of the data part of the octet
  82. unsigned long BEROctet::DataSize() const
  83. {
  84. if(!m_Octet) throw Exception(ccBEREmptyOctet);
  85. return m_DataSize;
  86. }
  87. // If the octet is a constructed type, this returns list of sub-octets
  88. std::vector<BEROctet*> BEROctet::SubOctetList() const
  89. {
  90. if(!m_Octet) throw Exception(ccBEREmptyOctet);
  91. return m_SubOctetList;
  92. }
  93. // If the octet is an OID, this returns the decoded version, otherwise an empty string
  94. std::string BEROctet::ObjectID() const
  95. {
  96. if(!m_Octet) throw Exception(ccBEREmptyOctet);
  97. std::string OID;
  98. if(m_Class==0 && m_Tag==6) {
  99. char text[40];
  100. unsigned long subid;
  101. unsigned char *c = m_Data;
  102. unsigned char *Last = m_Octet + m_OctetSize;
  103. bool First = true;
  104. while(c<Last) {
  105. subid = (*c)&0x7F;
  106. while((*c)&0x80) {
  107. c++; if(c>=Last) throw Exception(ccBERUnexpectedEndOfOctet);
  108. if(subid>0x01FFFFFF) throw Exception(ccBEROIDSubIdentifierOverflow);
  109. subid = (subid<<7) | ((*c)&0x7F);
  110. }
  111. if(First) {
  112. unsigned long X,Y;
  113. if(subid<40) X=0;
  114. else if(subid<80) X=1;
  115. else X=2;
  116. Y = subid-X*40;
  117. sprintf(text,"%d %d",X,Y);
  118. OID = text;
  119. First = false;
  120. }
  121. else {
  122. sprintf(text," %d",subid);
  123. OID += text;
  124. }
  125. c++;
  126. }
  127. }
  128. return OID;
  129. }
  130. // SearchOID returns all the constructed octets that contain a particular OID
  131. void BEROctet::SearchOID(std::string const &OID, std::vector<BEROctet const*> &result) const
  132. {
  133. for(int i=0; i<m_SubOctetList.size(); i++) {
  134. if(m_SubOctetList[i]->Class()==0 && m_SubOctetList[i]->Tag()==6) {
  135. if(OID==m_SubOctetList[i]->ObjectID()) {
  136. result.push_back(this);
  137. }
  138. }
  139. else if(m_SubOctetList[i]->Constructed()) {
  140. m_SubOctetList[i]->SearchOID(OID,result);
  141. }
  142. }
  143. return;
  144. }
  145. // SearchOIDNext returns all the octets following a particular OID
  146. void BEROctet::SearchOIDNext(std::string const &OID, std::vector<BEROctet const*> &result) const
  147. {
  148. for(int i=0; i<m_SubOctetList.size(); i++) {
  149. if(m_SubOctetList[i]->Class()==0 && m_SubOctetList[i]->Tag()==6) {
  150. if(OID==m_SubOctetList[i]->ObjectID()) {
  151. if((i+1) < m_SubOctetList.size()) result.push_back(m_SubOctetList[i+1]);
  152. }
  153. }
  154. else if(m_SubOctetList[i]->Constructed()) {
  155. m_SubOctetList[i]->SearchOIDNext(OID,result);
  156. }
  157. }
  158. return;
  159. }
  160. // Decodes recursively a BER octet.
  161. void BEROctet::Decode()
  162. {
  163. if(!m_Octet) throw Exception(ccBEREmptyOctet);
  164. long BufferSize = m_OctetSize;
  165. m_PrimConst = (m_Octet[0]>>5) & 0x1;
  166. m_Class = (m_Octet[0]>>6) & 0x3;
  167. unsigned char *c = m_Octet;
  168. unsigned char *Last = c + BufferSize - 1;
  169. m_Tag = *c & 0x1F;
  170. if(m_Tag>30) {
  171. m_Tag = 0;
  172. c++;
  173. if(c>Last) throw Exception(ccBERUnexpectedEndOfOctet);
  174. while (*c & 0x80) {
  175. m_Tag = (m_Tag << 7) | ((*c) & 0x7F);
  176. c++;
  177. if(c>Last) throw Exception(ccBERUnexpectedEndOfOctet);
  178. }
  179. if(m_Tag > 0x01FFFFFF) throw Exception(ccBERTagValueOverflow);
  180. m_Tag = (m_Tag << 7) | ((*c) & 0x7F);
  181. }
  182. c++;
  183. if(c>Last) throw Exception(ccBERUnexpectedEndOfOctet);
  184. long DataSize;
  185. if((*c)&0x80) {
  186. int n = (*c) & 0x7F;
  187. if(n) {
  188. DataSize = 0;
  189. for(int i=0; i<n; i++) {
  190. c++; if(c>Last) throw Exception(ccBERUnexpectedEndOfOctet);
  191. if(DataSize>0x007FFFFF) throw Exception(ccBERDataLengthOverflow);
  192. DataSize = (DataSize<<8) | (*c);
  193. }
  194. }
  195. else throw Exception(ccBERUnexpectedIndefiniteLength);
  196. }
  197. else DataSize = *c;
  198. c++;
  199. m_Data = c;
  200. m_DataSize = DataSize;
  201. unsigned long OctetSize = DataSize + (m_Data-m_Octet);
  202. if(OctetSize>BufferSize) throw Exception(ccBERInconsistentDataLength);
  203. m_OctetSize = OctetSize;
  204. for(int i=0; i<m_SubOctetList.size(); i++) delete m_SubOctetList[i];
  205. m_SubOctetList.resize(0);
  206. if(m_PrimConst) {
  207. // Constructed type
  208. unsigned char *TmpData = m_Data;
  209. unsigned long TmpDataSize = m_DataSize;
  210. while(TmpDataSize) {
  211. BEROctet *oct = new BEROctet(TmpData,TmpDataSize);
  212. m_SubOctetList.push_back(oct);
  213. TmpData += oct->OctetSize();
  214. TmpDataSize -=oct->OctetSize();
  215. }
  216. }
  217. }