1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
19 // These are SSH message type numbers. They are scattered around several
20 // documents but many were taken from [SSH-PARAMETERS].
30 // These structures mirror the wire format of the corresponding SSH messages.
31 // They are marshaled using reflection with the marshal and unmarshal functions
32 // in this file. The only wrinkle is that a final member of type []byte with a
33 // ssh tag of "rest" receives the remainder of a packet when unmarshaling.
35 // See RFC 4253, section 11.1.
36 const msgDisconnect = 1
38 // disconnectMsg is the message that signals a disconnect. It is also
39 // the error type returned from mux.Wait()
40 type disconnectMsg struct {
41 Reason uint32 `sshtype:"1"`
46 func (d *disconnectMsg) Error() string {
47 return fmt.Sprintf("ssh: disconnect, reason %d: %s", d.Reason, d.Message)
50 // See RFC 4253, section 7.1.
53 type kexInitMsg struct {
54 Cookie [16]byte `sshtype:"20"`
56 ServerHostKeyAlgos []string
57 CiphersClientServer []string
58 CiphersServerClient []string
59 MACsClientServer []string
60 MACsServerClient []string
61 CompressionClientServer []string
62 CompressionServerClient []string
63 LanguagesClientServer []string
64 LanguagesServerClient []string
69 // See RFC 4253, section 8.
72 const msgKexDHInit = 30
74 type kexDHInitMsg struct {
75 X *big.Int `sshtype:"30"`
78 const msgKexECDHInit = 30
80 type kexECDHInitMsg struct {
81 ClientPubKey []byte `sshtype:"30"`
84 const msgKexECDHReply = 31
86 type kexECDHReplyMsg struct {
87 HostKey []byte `sshtype:"31"`
88 EphemeralPubKey []byte
92 const msgKexDHReply = 31
94 type kexDHReplyMsg struct {
95 HostKey []byte `sshtype:"31"`
100 // See RFC 4253, section 10.
101 const msgServiceRequest = 5
103 type serviceRequestMsg struct {
104 Service string `sshtype:"5"`
107 // See RFC 4253, section 10.
108 const msgServiceAccept = 6
110 type serviceAcceptMsg struct {
111 Service string `sshtype:"6"`
114 // See RFC 4252, section 5.
115 const msgUserAuthRequest = 50
117 type userAuthRequestMsg struct {
118 User string `sshtype:"50"`
121 Payload []byte `ssh:"rest"`
124 // Used for debug printouts of packets.
125 type userAuthSuccessMsg struct {
128 // See RFC 4252, section 5.1
129 const msgUserAuthFailure = 51
131 type userAuthFailureMsg struct {
132 Methods []string `sshtype:"51"`
136 // See RFC 4252, section 5.1
137 const msgUserAuthSuccess = 52
139 // See RFC 4252, section 5.4
140 const msgUserAuthBanner = 53
142 type userAuthBannerMsg struct {
143 Message string `sshtype:"53"`
144 // unused, but required to allow message parsing
148 // See RFC 4256, section 3.2
149 const msgUserAuthInfoRequest = 60
150 const msgUserAuthInfoResponse = 61
152 type userAuthInfoRequestMsg struct {
153 User string `sshtype:"60"`
155 DeprecatedLanguage string
157 Prompts []byte `ssh:"rest"`
160 // See RFC 4254, section 5.1.
161 const msgChannelOpen = 90
163 type channelOpenMsg struct {
164 ChanType string `sshtype:"90"`
168 TypeSpecificData []byte `ssh:"rest"`
171 const msgChannelExtendedData = 95
172 const msgChannelData = 94
174 // Used for debug print outs of packets.
175 type channelDataMsg struct {
176 PeersID uint32 `sshtype:"94"`
178 Rest []byte `ssh:"rest"`
181 // See RFC 4254, section 5.1.
182 const msgChannelOpenConfirm = 91
184 type channelOpenConfirmMsg struct {
185 PeersID uint32 `sshtype:"91"`
189 TypeSpecificData []byte `ssh:"rest"`
192 // See RFC 4254, section 5.1.
193 const msgChannelOpenFailure = 92
195 type channelOpenFailureMsg struct {
196 PeersID uint32 `sshtype:"92"`
197 Reason RejectionReason
202 const msgChannelRequest = 98
204 type channelRequestMsg struct {
205 PeersID uint32 `sshtype:"98"`
208 RequestSpecificData []byte `ssh:"rest"`
211 // See RFC 4254, section 5.4.
212 const msgChannelSuccess = 99
214 type channelRequestSuccessMsg struct {
215 PeersID uint32 `sshtype:"99"`
218 // See RFC 4254, section 5.4.
219 const msgChannelFailure = 100
221 type channelRequestFailureMsg struct {
222 PeersID uint32 `sshtype:"100"`
225 // See RFC 4254, section 5.3
226 const msgChannelClose = 97
228 type channelCloseMsg struct {
229 PeersID uint32 `sshtype:"97"`
232 // See RFC 4254, section 5.3
233 const msgChannelEOF = 96
235 type channelEOFMsg struct {
236 PeersID uint32 `sshtype:"96"`
239 // See RFC 4254, section 4
240 const msgGlobalRequest = 80
242 type globalRequestMsg struct {
243 Type string `sshtype:"80"`
245 Data []byte `ssh:"rest"`
248 // See RFC 4254, section 4
249 const msgRequestSuccess = 81
251 type globalRequestSuccessMsg struct {
252 Data []byte `ssh:"rest" sshtype:"81"`
255 // See RFC 4254, section 4
256 const msgRequestFailure = 82
258 type globalRequestFailureMsg struct {
259 Data []byte `ssh:"rest" sshtype:"82"`
262 // See RFC 4254, section 5.2
263 const msgChannelWindowAdjust = 93
265 type windowAdjustMsg struct {
266 PeersID uint32 `sshtype:"93"`
267 AdditionalBytes uint32
270 // See RFC 4252, section 7
271 const msgUserAuthPubKeyOk = 60
273 type userAuthPubKeyOkMsg struct {
274 Algo string `sshtype:"60"`
278 // typeTags returns the possible type bytes for the given reflect.Type, which
279 // should be a struct. The possible values are separated by a '|' character.
280 func typeTags(structType reflect.Type) (tags []byte) {
281 tagStr := structType.Field(0).Tag.Get("sshtype")
283 for _, tag := range strings.Split(tagStr, "|") {
284 i, err := strconv.Atoi(tag)
286 tags = append(tags, byte(i))
293 func fieldError(t reflect.Type, field int, problem string) error {
295 problem = ": " + problem
297 return fmt.Errorf("ssh: unmarshal error for field %s of type %s%s", t.Field(field).Name, t.Name(), problem)
300 var errShortRead = errors.New("ssh: short read")
302 // Unmarshal parses data in SSH wire format into a structure. The out
303 // argument should be a pointer to struct. If the first member of the
304 // struct has the "sshtype" tag set to a '|'-separated set of numbers
305 // in decimal, the packet must start with one of those numbers. In
306 // case of error, Unmarshal returns a ParseError or
307 // UnexpectedMessageError.
308 func Unmarshal(data []byte, out interface{}) error {
309 v := reflect.ValueOf(out).Elem()
310 structType := v.Type()
311 expectedTypes := typeTags(structType)
313 var expectedType byte
314 if len(expectedTypes) > 0 {
315 expectedType = expectedTypes[0]
319 return parseError(expectedType)
322 if len(expectedTypes) > 0 {
324 for _, e := range expectedTypes {
325 if e > 0 && data[0] == e {
331 return fmt.Errorf("ssh: unexpected message type %d (expected one of %v)", data[0], expectedTypes)
337 for i := 0; i < v.NumField(); i++ {
345 field.SetBool(data[0] != 0)
348 if t.Elem().Kind() != reflect.Uint8 {
349 return fieldError(structType, i, "array of unsupported type")
351 if len(data) < t.Len() {
354 for j, n := 0, t.Len(); j < n; j++ {
355 field.Index(j).Set(reflect.ValueOf(data[j]))
357 data = data[t.Len():]
360 if u64, data, ok = parseUint64(data); !ok {
366 if u32, data, ok = parseUint32(data); !ok {
369 field.SetUint(uint64(u32))
374 field.SetUint(uint64(data[0]))
378 if s, data, ok = parseString(data); !ok {
379 return fieldError(structType, i, "")
381 field.SetString(string(s))
383 switch t.Elem().Kind() {
385 if structType.Field(i).Tag.Get("ssh") == "rest" {
386 field.Set(reflect.ValueOf(data))
390 if s, data, ok = parseString(data); !ok {
393 field.Set(reflect.ValueOf(s))
397 if nl, data, ok = parseNameList(data); !ok {
400 field.Set(reflect.ValueOf(nl))
402 return fieldError(structType, i, "slice of unsupported type")
407 if n, data, ok = parseInt(data); !ok {
410 field.Set(reflect.ValueOf(n))
412 return fieldError(structType, i, "pointer to unsupported type")
415 return fieldError(structType, i, fmt.Sprintf("unsupported type: %v", t))
420 return parseError(expectedType)
426 // Marshal serializes the message in msg to SSH wire format. The msg
427 // argument should be a struct or pointer to struct. If the first
428 // member has the "sshtype" tag set to a number in decimal, that
429 // number is prepended to the result. If the last of member has the
430 // "ssh" tag set to "rest", its contents are appended to the output.
431 func Marshal(msg interface{}) []byte {
432 out := make([]byte, 0, 64)
433 return marshalStruct(out, msg)
436 func marshalStruct(out []byte, msg interface{}) []byte {
437 v := reflect.Indirect(reflect.ValueOf(msg))
438 msgTypes := typeTags(v.Type())
439 if len(msgTypes) > 0 {
440 out = append(out, msgTypes[0])
443 for i, n := 0, v.NumField(); i < n; i++ {
445 switch t := field.Type(); t.Kind() {
453 if t.Elem().Kind() != reflect.Uint8 {
454 panic(fmt.Sprintf("array of non-uint8 in field %d: %T", i, field.Interface()))
456 for j, l := 0, t.Len(); j < l; j++ {
457 out = append(out, uint8(field.Index(j).Uint()))
460 out = appendU32(out, uint32(field.Uint()))
462 out = appendU64(out, uint64(field.Uint()))
464 out = append(out, uint8(field.Uint()))
467 out = appendInt(out, len(s))
468 out = append(out, s...)
470 switch t.Elem().Kind() {
472 if v.Type().Field(i).Tag.Get("ssh") != "rest" {
473 out = appendInt(out, field.Len())
475 out = append(out, field.Bytes()...)
478 out = appendU32(out, 0)
479 if n := field.Len(); n > 0 {
480 for j := 0; j < n; j++ {
483 out = append(out, ',')
485 out = append(out, f.String()...)
487 // overwrite length value
488 binary.BigEndian.PutUint32(out[offset:], uint32(len(out)-offset-4))
491 panic(fmt.Sprintf("slice of unknown type in field %d: %T", i, field.Interface()))
496 nValue := reflect.ValueOf(&n)
497 nValue.Elem().Set(field)
498 needed := intLength(n)
499 oldLength := len(out)
501 if cap(out)-len(out) < needed {
502 newOut := make([]byte, len(out), 2*(len(out)+needed))
506 out = out[:oldLength+needed]
507 marshalInt(out[oldLength:], n)
509 panic(fmt.Sprintf("pointer to unknown type in field %d: %T", i, field.Interface()))
517 var bigOne = big.NewInt(1)
519 func parseString(in []byte) (out, rest []byte, ok bool) {
523 length := binary.BigEndian.Uint32(in)
525 if uint32(len(in)) < length {
536 emptyNameList = []string{}
539 func parseNameList(in []byte) (out []string, rest []byte, ok bool) {
540 contents, rest, ok := parseString(in)
544 if len(contents) == 0 {
548 parts := bytes.Split(contents, comma)
549 out = make([]string, len(parts))
550 for i, part := range parts {
551 out[i] = string(part)
556 func parseInt(in []byte) (out *big.Int, rest []byte, ok bool) {
557 contents, rest, ok := parseString(in)
563 if len(contents) > 0 && contents[0]&0x80 == 0x80 {
564 // This is a negative number
565 notBytes := make([]byte, len(contents))
566 for i := range notBytes {
567 notBytes[i] = ^contents[i]
569 out.SetBytes(notBytes)
574 out.SetBytes(contents)
580 func parseUint32(in []byte) (uint32, []byte, bool) {
584 return binary.BigEndian.Uint32(in), in[4:], true
587 func parseUint64(in []byte) (uint64, []byte, bool) {
591 return binary.BigEndian.Uint64(in), in[8:], true
594 func intLength(n *big.Int) int {
595 length := 4 /* length bytes */
597 nMinus1 := new(big.Int).Neg(n)
598 nMinus1.Sub(nMinus1, bigOne)
599 bitLen := nMinus1.BitLen()
601 // The number will need 0xff padding
604 length += (bitLen + 7) / 8
605 } else if n.Sign() == 0 {
606 // A zero is the zero length string
610 // The number will need 0x00 padding
613 length += (bitLen + 7) / 8
619 func marshalUint32(to []byte, n uint32) []byte {
620 binary.BigEndian.PutUint32(to, n)
624 func marshalUint64(to []byte, n uint64) []byte {
625 binary.BigEndian.PutUint64(to, n)
629 func marshalInt(to []byte, n *big.Int) []byte {
635 // A negative number has to be converted to two's-complement
636 // form. So we'll subtract 1 and invert. If the
637 // most-significant-bit isn't set then we'll need to pad the
638 // beginning with 0xff in order to keep the number negative.
639 nMinus1 := new(big.Int).Neg(n)
640 nMinus1.Sub(nMinus1, bigOne)
641 bytes := nMinus1.Bytes()
642 for i := range bytes {
645 if len(bytes) == 0 || bytes[0]&0x80 == 0 {
650 nBytes := copy(to, bytes)
653 } else if n.Sign() == 0 {
654 // A zero is the zero length string
657 if len(bytes) > 0 && bytes[0]&0x80 != 0 {
658 // We'll have to pad this with a 0x00 in order to
659 // stop it looking like a negative number.
664 nBytes := copy(to, bytes)
669 lengthBytes[0] = byte(length >> 24)
670 lengthBytes[1] = byte(length >> 16)
671 lengthBytes[2] = byte(length >> 8)
672 lengthBytes[3] = byte(length)
676 func writeInt(w io.Writer, n *big.Int) {
677 length := intLength(n)
678 buf := make([]byte, length)
683 func writeString(w io.Writer, s []byte) {
684 var lengthBytes [4]byte
685 lengthBytes[0] = byte(len(s) >> 24)
686 lengthBytes[1] = byte(len(s) >> 16)
687 lengthBytes[2] = byte(len(s) >> 8)
688 lengthBytes[3] = byte(len(s))
689 w.Write(lengthBytes[:])
693 func stringLength(n int) int {
697 func marshalString(to []byte, s []byte) []byte {
698 to[0] = byte(len(s) >> 24)
699 to[1] = byte(len(s) >> 16)
700 to[2] = byte(len(s) >> 8)
707 var bigIntType = reflect.TypeOf((*big.Int)(nil))
709 // Decode a packet into its corresponding message.
710 func decode(packet []byte) (interface{}, error) {
714 msg = new(disconnectMsg)
715 case msgServiceRequest:
716 msg = new(serviceRequestMsg)
717 case msgServiceAccept:
718 msg = new(serviceAcceptMsg)
720 msg = new(kexInitMsg)
722 msg = new(kexDHInitMsg)
724 msg = new(kexDHReplyMsg)
725 case msgUserAuthRequest:
726 msg = new(userAuthRequestMsg)
727 case msgUserAuthSuccess:
728 return new(userAuthSuccessMsg), nil
729 case msgUserAuthFailure:
730 msg = new(userAuthFailureMsg)
731 case msgUserAuthPubKeyOk:
732 msg = new(userAuthPubKeyOkMsg)
733 case msgGlobalRequest:
734 msg = new(globalRequestMsg)
735 case msgRequestSuccess:
736 msg = new(globalRequestSuccessMsg)
737 case msgRequestFailure:
738 msg = new(globalRequestFailureMsg)
740 msg = new(channelOpenMsg)
742 msg = new(channelDataMsg)
743 case msgChannelOpenConfirm:
744 msg = new(channelOpenConfirmMsg)
745 case msgChannelOpenFailure:
746 msg = new(channelOpenFailureMsg)
747 case msgChannelWindowAdjust:
748 msg = new(windowAdjustMsg)
750 msg = new(channelEOFMsg)
751 case msgChannelClose:
752 msg = new(channelCloseMsg)
753 case msgChannelRequest:
754 msg = new(channelRequestMsg)
755 case msgChannelSuccess:
756 msg = new(channelRequestSuccessMsg)
757 case msgChannelFailure:
758 msg = new(channelRequestFailureMsg)
760 return nil, unexpectedMessageError(0, packet[0])
762 if err := Unmarshal(packet, msg); err != nil {