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.

504 lines
12 KiB

  1. package ber
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "os"
  8. "reflect"
  9. )
  10. type Packet struct {
  11. Identifier
  12. Value interface{}
  13. ByteValue []byte
  14. Data *bytes.Buffer
  15. Children []*Packet
  16. Description string
  17. }
  18. type Identifier struct {
  19. ClassType Class
  20. TagType Type
  21. Tag Tag
  22. }
  23. type Tag uint64
  24. const (
  25. TagEOC Tag = 0x00
  26. TagBoolean Tag = 0x01
  27. TagInteger Tag = 0x02
  28. TagBitString Tag = 0x03
  29. TagOctetString Tag = 0x04
  30. TagNULL Tag = 0x05
  31. TagObjectIdentifier Tag = 0x06
  32. TagObjectDescriptor Tag = 0x07
  33. TagExternal Tag = 0x08
  34. TagRealFloat Tag = 0x09
  35. TagEnumerated Tag = 0x0a
  36. TagEmbeddedPDV Tag = 0x0b
  37. TagUTF8String Tag = 0x0c
  38. TagRelativeOID Tag = 0x0d
  39. TagSequence Tag = 0x10
  40. TagSet Tag = 0x11
  41. TagNumericString Tag = 0x12
  42. TagPrintableString Tag = 0x13
  43. TagT61String Tag = 0x14
  44. TagVideotexString Tag = 0x15
  45. TagIA5String Tag = 0x16
  46. TagUTCTime Tag = 0x17
  47. TagGeneralizedTime Tag = 0x18
  48. TagGraphicString Tag = 0x19
  49. TagVisibleString Tag = 0x1a
  50. TagGeneralString Tag = 0x1b
  51. TagUniversalString Tag = 0x1c
  52. TagCharacterString Tag = 0x1d
  53. TagBMPString Tag = 0x1e
  54. TagBitmask Tag = 0x1f // xxx11111b
  55. // HighTag indicates the start of a high-tag byte sequence
  56. HighTag Tag = 0x1f // xxx11111b
  57. // HighTagContinueBitmask indicates the high-tag byte sequence should continue
  58. HighTagContinueBitmask Tag = 0x80 // 10000000b
  59. // HighTagValueBitmask obtains the tag value from a high-tag byte sequence byte
  60. HighTagValueBitmask Tag = 0x7f // 01111111b
  61. )
  62. const (
  63. // LengthLongFormBitmask is the mask to apply to the length byte to see if a long-form byte sequence is used
  64. LengthLongFormBitmask = 0x80
  65. // LengthValueBitmask is the mask to apply to the length byte to get the number of bytes in the long-form byte sequence
  66. LengthValueBitmask = 0x7f
  67. // LengthIndefinite is returned from readLength to indicate an indefinite length
  68. LengthIndefinite = -1
  69. )
  70. var tagMap = map[Tag]string{
  71. TagEOC: "EOC (End-of-Content)",
  72. TagBoolean: "Boolean",
  73. TagInteger: "Integer",
  74. TagBitString: "Bit String",
  75. TagOctetString: "Octet String",
  76. TagNULL: "NULL",
  77. TagObjectIdentifier: "Object Identifier",
  78. TagObjectDescriptor: "Object Descriptor",
  79. TagExternal: "External",
  80. TagRealFloat: "Real (float)",
  81. TagEnumerated: "Enumerated",
  82. TagEmbeddedPDV: "Embedded PDV",
  83. TagUTF8String: "UTF8 String",
  84. TagRelativeOID: "Relative-OID",
  85. TagSequence: "Sequence and Sequence of",
  86. TagSet: "Set and Set OF",
  87. TagNumericString: "Numeric String",
  88. TagPrintableString: "Printable String",
  89. TagT61String: "T61 String",
  90. TagVideotexString: "Videotex String",
  91. TagIA5String: "IA5 String",
  92. TagUTCTime: "UTC Time",
  93. TagGeneralizedTime: "Generalized Time",
  94. TagGraphicString: "Graphic String",
  95. TagVisibleString: "Visible String",
  96. TagGeneralString: "General String",
  97. TagUniversalString: "Universal String",
  98. TagCharacterString: "Character String",
  99. TagBMPString: "BMP String",
  100. }
  101. type Class uint8
  102. const (
  103. ClassUniversal Class = 0 // 00xxxxxxb
  104. ClassApplication Class = 64 // 01xxxxxxb
  105. ClassContext Class = 128 // 10xxxxxxb
  106. ClassPrivate Class = 192 // 11xxxxxxb
  107. ClassBitmask Class = 192 // 11xxxxxxb
  108. )
  109. var ClassMap = map[Class]string{
  110. ClassUniversal: "Universal",
  111. ClassApplication: "Application",
  112. ClassContext: "Context",
  113. ClassPrivate: "Private",
  114. }
  115. type Type uint8
  116. const (
  117. TypePrimitive Type = 0 // xx0xxxxxb
  118. TypeConstructed Type = 32 // xx1xxxxxb
  119. TypeBitmask Type = 32 // xx1xxxxxb
  120. )
  121. var TypeMap = map[Type]string{
  122. TypePrimitive: "Primitive",
  123. TypeConstructed: "Constructed",
  124. }
  125. var Debug bool = false
  126. func PrintBytes(out io.Writer, buf []byte, indent string) {
  127. data_lines := make([]string, (len(buf)/30)+1)
  128. num_lines := make([]string, (len(buf)/30)+1)
  129. for i, b := range buf {
  130. data_lines[i/30] += fmt.Sprintf("%02x ", b)
  131. num_lines[i/30] += fmt.Sprintf("%02d ", (i+1)%100)
  132. }
  133. for i := 0; i < len(data_lines); i++ {
  134. out.Write([]byte(indent + data_lines[i] + "\n"))
  135. out.Write([]byte(indent + num_lines[i] + "\n\n"))
  136. }
  137. }
  138. func PrintPacket(p *Packet) {
  139. printPacket(os.Stdout, p, 0, false)
  140. }
  141. func printPacket(out io.Writer, p *Packet, indent int, printBytes bool) {
  142. indent_str := ""
  143. for len(indent_str) != indent {
  144. indent_str += " "
  145. }
  146. class_str := ClassMap[p.ClassType]
  147. tagtype_str := TypeMap[p.TagType]
  148. tag_str := fmt.Sprintf("0x%02X", p.Tag)
  149. if p.ClassType == ClassUniversal {
  150. tag_str = tagMap[p.Tag]
  151. }
  152. value := fmt.Sprint(p.Value)
  153. description := ""
  154. if p.Description != "" {
  155. description = p.Description + ": "
  156. }
  157. fmt.Fprintf(out, "%s%s(%s, %s, %s) Len=%d %q\n", indent_str, description, class_str, tagtype_str, tag_str, p.Data.Len(), value)
  158. if printBytes {
  159. PrintBytes(out, p.Bytes(), indent_str)
  160. }
  161. for _, child := range p.Children {
  162. printPacket(out, child, indent+1, printBytes)
  163. }
  164. }
  165. // ReadPacket reads a single Packet from the reader
  166. func ReadPacket(reader io.Reader) (*Packet, error) {
  167. p, _, err := readPacket(reader)
  168. if err != nil {
  169. return nil, err
  170. }
  171. return p, nil
  172. }
  173. func DecodeString(data []byte) string {
  174. return string(data)
  175. }
  176. func parseInt64(bytes []byte) (ret int64, err error) {
  177. if len(bytes) > 8 {
  178. // We'll overflow an int64 in this case.
  179. err = fmt.Errorf("integer too large")
  180. return
  181. }
  182. for bytesRead := 0; bytesRead < len(bytes); bytesRead++ {
  183. ret <<= 8
  184. ret |= int64(bytes[bytesRead])
  185. }
  186. // Shift up and down in order to sign extend the result.
  187. ret <<= 64 - uint8(len(bytes))*8
  188. ret >>= 64 - uint8(len(bytes))*8
  189. return
  190. }
  191. func encodeInteger(i int64) []byte {
  192. n := int64Length(i)
  193. out := make([]byte, n)
  194. var j int
  195. for ; n > 0; n-- {
  196. out[j] = (byte(i >> uint((n-1)*8)))
  197. j++
  198. }
  199. return out
  200. }
  201. func int64Length(i int64) (numBytes int) {
  202. numBytes = 1
  203. for i > 127 {
  204. numBytes++
  205. i >>= 8
  206. }
  207. for i < -128 {
  208. numBytes++
  209. i >>= 8
  210. }
  211. return
  212. }
  213. // DecodePacket decodes the given bytes into a single Packet
  214. // If a decode error is encountered, nil is returned.
  215. func DecodePacket(data []byte) *Packet {
  216. p, _, _ := readPacket(bytes.NewBuffer(data))
  217. return p
  218. }
  219. // DecodePacketErr decodes the given bytes into a single Packet
  220. // If a decode error is encountered, nil is returned
  221. func DecodePacketErr(data []byte) (*Packet, error) {
  222. p, _, err := readPacket(bytes.NewBuffer(data))
  223. if err != nil {
  224. return nil, err
  225. }
  226. return p, nil
  227. }
  228. // readPacket reads a single Packet from the reader, returning the number of bytes read
  229. func readPacket(reader io.Reader) (*Packet, int, error) {
  230. identifier, length, read, err := readHeader(reader)
  231. if err != nil {
  232. return nil, read, err
  233. }
  234. p := &Packet{
  235. Identifier: identifier,
  236. }
  237. p.Data = new(bytes.Buffer)
  238. p.Children = make([]*Packet, 0, 2)
  239. p.Value = nil
  240. if p.TagType == TypeConstructed {
  241. // TODO: if universal, ensure tag type is allowed to be constructed
  242. // Track how much content we've read
  243. contentRead := 0
  244. for {
  245. if length != LengthIndefinite {
  246. // End if we've read what we've been told to
  247. if contentRead == length {
  248. break
  249. }
  250. // Detect if a packet boundary didn't fall on the expected length
  251. if contentRead > length {
  252. return nil, read, fmt.Errorf("expected to read %d bytes, read %d", length, contentRead)
  253. }
  254. }
  255. // Read the next packet
  256. child, r, err := readPacket(reader)
  257. if err != nil {
  258. return nil, read, err
  259. }
  260. contentRead += r
  261. read += r
  262. // Test is this is the EOC marker for our packet
  263. if isEOCPacket(child) {
  264. if length == LengthIndefinite {
  265. break
  266. }
  267. return nil, read, errors.New("eoc child not allowed with definite length")
  268. }
  269. // Append and continue
  270. p.AppendChild(child)
  271. }
  272. return p, read, nil
  273. }
  274. if length == LengthIndefinite {
  275. return nil, read, errors.New("indefinite length used with primitive type")
  276. }
  277. // Read definite-length content
  278. content := make([]byte, length, length)
  279. if length > 0 {
  280. _, err := io.ReadFull(reader, content)
  281. if err != nil {
  282. if err == io.EOF {
  283. return nil, read, io.ErrUnexpectedEOF
  284. }
  285. return nil, read, err
  286. }
  287. read += length
  288. }
  289. if p.ClassType == ClassUniversal {
  290. p.Data.Write(content)
  291. p.ByteValue = content
  292. switch p.Tag {
  293. case TagEOC:
  294. case TagBoolean:
  295. val, _ := parseInt64(content)
  296. p.Value = val != 0
  297. case TagInteger:
  298. p.Value, _ = parseInt64(content)
  299. case TagBitString:
  300. case TagOctetString:
  301. // the actual string encoding is not known here
  302. // (e.g. for LDAP content is already an UTF8-encoded
  303. // string). Return the data without further processing
  304. p.Value = DecodeString(content)
  305. case TagNULL:
  306. case TagObjectIdentifier:
  307. case TagObjectDescriptor:
  308. case TagExternal:
  309. case TagRealFloat:
  310. case TagEnumerated:
  311. p.Value, _ = parseInt64(content)
  312. case TagEmbeddedPDV:
  313. case TagUTF8String:
  314. p.Value = DecodeString(content)
  315. case TagRelativeOID:
  316. case TagSequence:
  317. case TagSet:
  318. case TagNumericString:
  319. case TagPrintableString:
  320. p.Value = DecodeString(content)
  321. case TagT61String:
  322. case TagVideotexString:
  323. case TagIA5String:
  324. case TagUTCTime:
  325. case TagGeneralizedTime:
  326. case TagGraphicString:
  327. case TagVisibleString:
  328. case TagGeneralString:
  329. case TagUniversalString:
  330. case TagCharacterString:
  331. case TagBMPString:
  332. }
  333. } else {
  334. p.Data.Write(content)
  335. }
  336. return p, read, nil
  337. }
  338. func (p *Packet) Bytes() []byte {
  339. var out bytes.Buffer
  340. out.Write(encodeIdentifier(p.Identifier))
  341. out.Write(encodeLength(p.Data.Len()))
  342. out.Write(p.Data.Bytes())
  343. return out.Bytes()
  344. }
  345. func (p *Packet) AppendChild(child *Packet) {
  346. p.Data.Write(child.Bytes())
  347. p.Children = append(p.Children, child)
  348. }
  349. func Encode(ClassType Class, TagType Type, Tag Tag, Value interface{}, Description string) *Packet {
  350. p := new(Packet)
  351. p.ClassType = ClassType
  352. p.TagType = TagType
  353. p.Tag = Tag
  354. p.Data = new(bytes.Buffer)
  355. p.Children = make([]*Packet, 0, 2)
  356. p.Value = Value
  357. p.Description = Description
  358. if Value != nil {
  359. v := reflect.ValueOf(Value)
  360. if ClassType == ClassUniversal {
  361. switch Tag {
  362. case TagOctetString:
  363. sv, ok := v.Interface().(string)
  364. if ok {
  365. p.Data.Write([]byte(sv))
  366. }
  367. }
  368. }
  369. }
  370. return p
  371. }
  372. func NewSequence(Description string) *Packet {
  373. return Encode(ClassUniversal, TypeConstructed, TagSequence, nil, Description)
  374. }
  375. func NewBoolean(ClassType Class, TagType Type, Tag Tag, Value bool, Description string) *Packet {
  376. intValue := int64(0)
  377. if Value {
  378. intValue = 1
  379. }
  380. p := Encode(ClassType, TagType, Tag, nil, Description)
  381. p.Value = Value
  382. p.Data.Write(encodeInteger(intValue))
  383. return p
  384. }
  385. func NewInteger(ClassType Class, TagType Type, Tag Tag, Value interface{}, Description string) *Packet {
  386. p := Encode(ClassType, TagType, Tag, nil, Description)
  387. p.Value = Value
  388. switch v := Value.(type) {
  389. case int:
  390. p.Data.Write(encodeInteger(int64(v)))
  391. case uint:
  392. p.Data.Write(encodeInteger(int64(v)))
  393. case int64:
  394. p.Data.Write(encodeInteger(v))
  395. case uint64:
  396. // TODO : check range or add encodeUInt...
  397. p.Data.Write(encodeInteger(int64(v)))
  398. case int32:
  399. p.Data.Write(encodeInteger(int64(v)))
  400. case uint32:
  401. p.Data.Write(encodeInteger(int64(v)))
  402. case int16:
  403. p.Data.Write(encodeInteger(int64(v)))
  404. case uint16:
  405. p.Data.Write(encodeInteger(int64(v)))
  406. case int8:
  407. p.Data.Write(encodeInteger(int64(v)))
  408. case uint8:
  409. p.Data.Write(encodeInteger(int64(v)))
  410. default:
  411. // TODO : add support for big.Int ?
  412. panic(fmt.Sprintf("Invalid type %T, expected {u|}int{64|32|16|8}", v))
  413. }
  414. return p
  415. }
  416. func NewString(ClassType Class, TagType Type, Tag Tag, Value, Description string) *Packet {
  417. p := Encode(ClassType, TagType, Tag, nil, Description)
  418. p.Value = Value
  419. p.Data.Write([]byte(Value))
  420. return p
  421. }