ber.go 12 KB

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