9
9
"math"
10
10
"os"
11
11
"reflect"
12
+ "strconv"
13
+ "strings"
12
14
"time"
13
15
"unicode/utf8"
14
16
)
@@ -391,6 +393,10 @@ func readPacket(reader io.Reader) (*Packet, int, error) {
391
393
p .Value = DecodeString (content )
392
394
case TagNULL :
393
395
case TagObjectIdentifier :
396
+ oid , err := parseObjectIdentifier (content )
397
+ if err == nil {
398
+ p .Value = OIDToString (oid )
399
+ }
394
400
case TagObjectDescriptor :
395
401
case TagExternal :
396
402
case TagRealFloat :
@@ -406,6 +412,10 @@ func readPacket(reader io.Reader) (*Packet, int, error) {
406
412
p .Value = val
407
413
}
408
414
case TagRelativeOID :
415
+ oid , err := parseObjectIdentifier (content )
416
+ if err == nil {
417
+ p .Value = OIDToString (oid )
418
+ }
409
419
case TagSequence :
410
420
case TagSet :
411
421
case TagNumericString :
@@ -633,3 +643,166 @@ func NewReal(classType Class, tagType Type, tag Tag, value interface{}, descript
633
643
}
634
644
return p
635
645
}
646
+
647
+ func NewOID (classType Class , tagType Type , tag Tag , value interface {}, description string ) * Packet {
648
+ p := Encode (classType , tagType , tag , nil , description )
649
+
650
+ switch v := value .(type ) {
651
+ case string :
652
+ encoded , err := encodeOID (v )
653
+ if err != nil {
654
+ fmt .Printf ("failed writing %v" , err )
655
+ return nil
656
+ }
657
+ p .Value = v
658
+ p .Data .Write (encoded )
659
+ // TODO: support []int already ?
660
+ default :
661
+ panic (fmt .Sprintf ("Invalid type %T, expected float{64|32}" , v ))
662
+ }
663
+ return p
664
+ }
665
+
666
+ // encodeOID takes a string representation of an OID and returns its DER-encoded byte slice along with any error.
667
+ func encodeOID (oidString string ) ([]byte , error ) {
668
+ // Convert the string representation to an asn1.ObjectIdentifier
669
+ parts := strings .Split (oidString , "." )
670
+ oid := make ([]int , len (parts ))
671
+ for i , part := range parts {
672
+ var val int
673
+ if _ , err := fmt .Sscanf (part , "%d" , & val ); err != nil {
674
+ return nil , fmt .Errorf ("invalid OID part '%s': %w" , part , err )
675
+ }
676
+ oid [i ] = val
677
+ }
678
+ if len (oid ) < 2 || oid [0 ] > 2 || (oid [0 ] < 2 && oid [1 ] >= 40 ) {
679
+ panic (fmt .Sprintf ("invalid object identifier % d" , oid )) // TODO: not elegant
680
+ }
681
+ encoded := make ([]byte , 0 )
682
+
683
+ encoded = appendBase128Int (encoded [:0 ], int64 (oid [0 ]* 40 + oid [1 ]))
684
+ for i := 2 ; i < len (oid ); i ++ {
685
+ encoded = appendBase128Int (encoded , int64 (oid [i ]))
686
+ }
687
+
688
+ return encoded , nil
689
+ }
690
+
691
+ func appendBase128Int (dst []byte , n int64 ) []byte {
692
+ l := base128IntLength (n )
693
+
694
+ for i := l - 1 ; i >= 0 ; i -- {
695
+ o := byte (n >> uint (i * 7 ))
696
+ o &= 0x7f
697
+ if i != 0 {
698
+ o |= 0x80
699
+ }
700
+
701
+ dst = append (dst , o )
702
+ }
703
+
704
+ return dst
705
+ }
706
+ func base128IntLength (n int64 ) int {
707
+ if n == 0 {
708
+ return 1
709
+ }
710
+
711
+ l := 0
712
+ for i := n ; i > 0 ; i >>= 7 {
713
+ l ++
714
+ }
715
+
716
+ return l
717
+ }
718
+
719
+ func OIDToString (oi []int ) string {
720
+ var s strings.Builder
721
+ s .Grow (32 )
722
+
723
+ buf := make ([]byte , 0 , 19 )
724
+ for i , v := range oi {
725
+ if i > 0 {
726
+ s .WriteByte ('.' )
727
+ }
728
+ s .Write (strconv .AppendInt (buf , int64 (v ), 10 ))
729
+ }
730
+
731
+ return s .String ()
732
+ }
733
+
734
+ // parseObjectIdentifier parses an OBJECT IDENTIFIER from the given bytes and
735
+ // returns it. An object identifier is a sequence of variable length integers
736
+ // that are assigned in a hierarchy.
737
+ func parseObjectIdentifier (bytes []byte ) (s []int , err error ) {
738
+ if len (bytes ) == 0 {
739
+ err = fmt .Errorf ("zero length OBJECT IDENTIFIER" )
740
+ return
741
+ }
742
+
743
+ // In the worst case, we get two elements from the first byte (which is
744
+ // encoded differently) and then every varint is a single byte long.
745
+ s = make ([]int , len (bytes )+ 1 )
746
+
747
+ // The first varint is 40*value1 + value2:
748
+ // According to this packing, value1 can take the values 0, 1 and 2 only.
749
+ // When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2,
750
+ // then there are no restrictions on value2.
751
+ v , offset , err := parseBase128Int (bytes , 0 )
752
+ if err != nil {
753
+ return
754
+ }
755
+ if v < 80 {
756
+ s [0 ] = v / 40
757
+ s [1 ] = v % 40
758
+ } else {
759
+ s [0 ] = 2
760
+ s [1 ] = v - 80
761
+ }
762
+
763
+ i := 2
764
+ for ; offset < len (bytes ); i ++ {
765
+ v , offset , err = parseBase128Int (bytes , offset )
766
+ if err != nil {
767
+ return
768
+ }
769
+ s [i ] = v
770
+ }
771
+ s = s [0 :i ]
772
+ return
773
+ }
774
+
775
+ // parseBase128Int parses a base-128 encoded int from the given offset in the
776
+ // given byte slice. It returns the value and the new offset.
777
+ func parseBase128Int (bytes []byte , initOffset int ) (ret , offset int , err error ) {
778
+ offset = initOffset
779
+ var ret64 int64
780
+ for shifted := 0 ; offset < len (bytes ); shifted ++ {
781
+ // 5 * 7 bits per byte == 35 bits of data
782
+ // Thus the representation is either non-minimal or too large for an int32
783
+ if shifted == 5 {
784
+ err = fmt .Errorf ("base 128 integer too large" )
785
+ return
786
+ }
787
+ ret64 <<= 7
788
+ b := bytes [offset ]
789
+ // integers should be minimally encoded, so the leading octet should
790
+ // never be 0x80
791
+ if shifted == 0 && b == 0x80 {
792
+ err = fmt .Errorf ("integer is not minimally encoded" )
793
+ return
794
+ }
795
+ ret64 |= int64 (b & 0x7f )
796
+ offset ++
797
+ if b & 0x80 == 0 {
798
+ ret = int (ret64 )
799
+ // Ensure that the returned value fits in an int on all platforms
800
+ if ret64 > math .MaxInt32 {
801
+ err = fmt .Errorf ("base 128 integer too large" )
802
+ }
803
+ return
804
+ }
805
+ }
806
+ err = fmt .Errorf ("truncated base 128 integer" )
807
+ return
808
+ }
0 commit comments