forked from zmap/zgrab
-
Notifications
You must be signed in to change notification settings - Fork 0
/
packet.go
135 lines (120 loc) · 2.57 KB
/
packet.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package ssh
import (
"encoding/binary"
"encoding/json"
"errors"
"math/big"
"strings"
)
type mpint struct {
big.Int
}
func (mp *mpint) Marshal() ([]byte, error) {
b := mp.Bytes()
if len(b) == 0 {
return nil, errors.New("Cannot encode empty mpint")
}
if b[0] < 0x80 {
return b, nil
}
out := make([]byte, len(b)+1)
out[0] = 0x00
copy(out[1:], b)
return out, nil
}
func (mp *mpint) Unmarshal(raw []byte) ([]byte, bool) {
b := raw
if len(b) < 4 {
return raw, false
}
mpLength := binary.BigEndian.Uint32(b)
b = b[4:]
if mpLength > uint32(len(b)) {
return raw, false
}
mp.SetBytes(b[0:mpLength])
b = b[mpLength:]
return b, true
}
func (mp *mpint) MarshalJSON() ([]byte, error) {
b := mp.Bytes()
return json.Marshal(b)
}
func (mp *mpint) UnmarshalJSON(raw []byte) error {
var b []byte
if err := json.Unmarshal(raw, b); err != nil {
return err
}
mp.SetBytes(b)
return nil
}
// Packet represents an SSH binary packet. See RFC
type packet struct {
packetLength uint32
paddingLength uint8
msgType byte
payload []byte
padding []byte
mac []byte
}
func expectedLength(packetLength uint32, macLength uint32) int {
totalLength := packetLength + macLength + 4
return int(totalLength)
}
// NameList represents the name-list structure described in RFC 4251.
// See https://tools.ietf.org/html/rfc4251 for details.
type NameList []string
func (n *NameList) MarshaledLength() int {
// 4 bytes for encoding the length
length := 4
nameCount := len(*n)
// No body if its empty
if nameCount <= 0 {
return length
}
// 1 byte per comma
length += nameCount - 1
// Add in lengths of string
for _, val := range *n {
length += len(val)
}
return length
}
func (n *NameList) MarshalInto(dest []byte) ([]byte, error) {
b := dest
if len(b) < 4 {
return dest, errShortBuffer
}
b = b[4:]
joined := strings.Join(*n, ",")
if len(b) < len(joined) {
return dest, errShortBuffer
}
length := len(joined)
binary.BigEndian.PutUint32(dest, uint32(length))
copy(b, joined[:])
b = b[length:]
return b, nil
}
// Unmarshal a NameList from a byte slice of the form
// [length:body:extra] where extra is optional. Returns [extra], true
// when successful, and raw, false when unsuccessful.
func (n *NameList) Unmarshal(raw []byte) ([]byte, bool) {
b := raw
if len(b) < 4 {
return raw, false
}
length := binary.BigEndian.Uint32(b)
b = b[4:]
if uint32(len(b)) < length {
return raw, false
}
s := string(b[0:length])
if len(s) == 0 {
*n = make([]string, 0)
} else {
*n = NameList(strings.Split(s, ","))
}
b = b[length:]
return b, true
}