123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758 |
- // Copyright 2011 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package ssh
- import (
- "bytes"
- "encoding/binary"
- "errors"
- "fmt"
- "io"
- "math/big"
- "reflect"
- "strconv"
- "strings"
- )
- // These are SSH message type numbers. They are scattered around several
- // documents but many were taken from [SSH-PARAMETERS].
- const (
- msgIgnore = 2
- msgUnimplemented = 3
- msgDebug = 4
- msgNewKeys = 21
- // Standard authentication messages
- msgUserAuthSuccess = 52
- msgUserAuthBanner = 53
- )
- // SSH messages:
- //
- // These structures mirror the wire format of the corresponding SSH messages.
- // They are marshaled using reflection with the marshal and unmarshal functions
- // in this file. The only wrinkle is that a final member of type []byte with a
- // ssh tag of "rest" receives the remainder of a packet when unmarshaling.
- // See RFC 4253, section 11.1.
- const msgDisconnect = 1
- // disconnectMsg is the message that signals a disconnect. It is also
- // the error type returned from mux.Wait()
- type disconnectMsg struct {
- Reason uint32 `sshtype:"1"`
- Message string
- Language string
- }
- func (d *disconnectMsg) Error() string {
- return fmt.Sprintf("ssh: disconnect, reason %d: %s", d.Reason, d.Message)
- }
- // See RFC 4253, section 7.1.
- const msgKexInit = 20
- type kexInitMsg struct {
- Cookie [16]byte `sshtype:"20"`
- KexAlgos []string
- ServerHostKeyAlgos []string
- CiphersClientServer []string
- CiphersServerClient []string
- MACsClientServer []string
- MACsServerClient []string
- CompressionClientServer []string
- CompressionServerClient []string
- LanguagesClientServer []string
- LanguagesServerClient []string
- FirstKexFollows bool
- Reserved uint32
- }
- // See RFC 4253, section 8.
- // Diffie-Helman
- const msgKexDHInit = 30
- type kexDHInitMsg struct {
- X *big.Int `sshtype:"30"`
- }
- const msgKexECDHInit = 30
- type kexECDHInitMsg struct {
- ClientPubKey []byte `sshtype:"30"`
- }
- const msgKexECDHReply = 31
- type kexECDHReplyMsg struct {
- HostKey []byte `sshtype:"31"`
- EphemeralPubKey []byte
- Signature []byte
- }
- const msgKexDHReply = 31
- type kexDHReplyMsg struct {
- HostKey []byte `sshtype:"31"`
- Y *big.Int
- Signature []byte
- }
- // See RFC 4253, section 10.
- const msgServiceRequest = 5
- type serviceRequestMsg struct {
- Service string `sshtype:"5"`
- }
- // See RFC 4253, section 10.
- const msgServiceAccept = 6
- type serviceAcceptMsg struct {
- Service string `sshtype:"6"`
- }
- // See RFC 4252, section 5.
- const msgUserAuthRequest = 50
- type userAuthRequestMsg struct {
- User string `sshtype:"50"`
- Service string
- Method string
- Payload []byte `ssh:"rest"`
- }
- // Used for debug printouts of packets.
- type userAuthSuccessMsg struct {
- }
- // See RFC 4252, section 5.1
- const msgUserAuthFailure = 51
- type userAuthFailureMsg struct {
- Methods []string `sshtype:"51"`
- PartialSuccess bool
- }
- // See RFC 4256, section 3.2
- const msgUserAuthInfoRequest = 60
- const msgUserAuthInfoResponse = 61
- type userAuthInfoRequestMsg struct {
- User string `sshtype:"60"`
- Instruction string
- DeprecatedLanguage string
- NumPrompts uint32
- Prompts []byte `ssh:"rest"`
- }
- // See RFC 4254, section 5.1.
- const msgChannelOpen = 90
- type channelOpenMsg struct {
- ChanType string `sshtype:"90"`
- PeersId uint32
- PeersWindow uint32
- MaxPacketSize uint32
- TypeSpecificData []byte `ssh:"rest"`
- }
- const msgChannelExtendedData = 95
- const msgChannelData = 94
- // Used for debug print outs of packets.
- type channelDataMsg struct {
- PeersId uint32 `sshtype:"94"`
- Length uint32
- Rest []byte `ssh:"rest"`
- }
- // See RFC 4254, section 5.1.
- const msgChannelOpenConfirm = 91
- type channelOpenConfirmMsg struct {
- PeersId uint32 `sshtype:"91"`
- MyId uint32
- MyWindow uint32
- MaxPacketSize uint32
- TypeSpecificData []byte `ssh:"rest"`
- }
- // See RFC 4254, section 5.1.
- const msgChannelOpenFailure = 92
- type channelOpenFailureMsg struct {
- PeersId uint32 `sshtype:"92"`
- Reason RejectionReason
- Message string
- Language string
- }
- const msgChannelRequest = 98
- type channelRequestMsg struct {
- PeersId uint32 `sshtype:"98"`
- Request string
- WantReply bool
- RequestSpecificData []byte `ssh:"rest"`
- }
- // See RFC 4254, section 5.4.
- const msgChannelSuccess = 99
- type channelRequestSuccessMsg struct {
- PeersId uint32 `sshtype:"99"`
- }
- // See RFC 4254, section 5.4.
- const msgChannelFailure = 100
- type channelRequestFailureMsg struct {
- PeersId uint32 `sshtype:"100"`
- }
- // See RFC 4254, section 5.3
- const msgChannelClose = 97
- type channelCloseMsg struct {
- PeersId uint32 `sshtype:"97"`
- }
- // See RFC 4254, section 5.3
- const msgChannelEOF = 96
- type channelEOFMsg struct {
- PeersId uint32 `sshtype:"96"`
- }
- // See RFC 4254, section 4
- const msgGlobalRequest = 80
- type globalRequestMsg struct {
- Type string `sshtype:"80"`
- WantReply bool
- Data []byte `ssh:"rest"`
- }
- // See RFC 4254, section 4
- const msgRequestSuccess = 81
- type globalRequestSuccessMsg struct {
- Data []byte `ssh:"rest" sshtype:"81"`
- }
- // See RFC 4254, section 4
- const msgRequestFailure = 82
- type globalRequestFailureMsg struct {
- Data []byte `ssh:"rest" sshtype:"82"`
- }
- // See RFC 4254, section 5.2
- const msgChannelWindowAdjust = 93
- type windowAdjustMsg struct {
- PeersId uint32 `sshtype:"93"`
- AdditionalBytes uint32
- }
- // See RFC 4252, section 7
- const msgUserAuthPubKeyOk = 60
- type userAuthPubKeyOkMsg struct {
- Algo string `sshtype:"60"`
- PubKey []byte
- }
- // typeTags returns the possible type bytes for the given reflect.Type, which
- // should be a struct. The possible values are separated by a '|' character.
- func typeTags(structType reflect.Type) (tags []byte) {
- tagStr := structType.Field(0).Tag.Get("sshtype")
- for _, tag := range strings.Split(tagStr, "|") {
- i, err := strconv.Atoi(tag)
- if err == nil {
- tags = append(tags, byte(i))
- }
- }
- return tags
- }
- func fieldError(t reflect.Type, field int, problem string) error {
- if problem != "" {
- problem = ": " + problem
- }
- return fmt.Errorf("ssh: unmarshal error for field %s of type %s%s", t.Field(field).Name, t.Name(), problem)
- }
- var errShortRead = errors.New("ssh: short read")
- // Unmarshal parses data in SSH wire format into a structure. The out
- // argument should be a pointer to struct. If the first member of the
- // struct has the "sshtype" tag set to a '|'-separated set of numbers
- // in decimal, the packet must start with one of those numbers. In
- // case of error, Unmarshal returns a ParseError or
- // UnexpectedMessageError.
- func Unmarshal(data []byte, out interface{}) error {
- v := reflect.ValueOf(out).Elem()
- structType := v.Type()
- expectedTypes := typeTags(structType)
- var expectedType byte
- if len(expectedTypes) > 0 {
- expectedType = expectedTypes[0]
- }
- if len(data) == 0 {
- return parseError(expectedType)
- }
- if len(expectedTypes) > 0 {
- goodType := false
- for _, e := range expectedTypes {
- if e > 0 && data[0] == e {
- goodType = true
- break
- }
- }
- if !goodType {
- return fmt.Errorf("ssh: unexpected message type %d (expected one of %v)", data[0], expectedTypes)
- }
- data = data[1:]
- }
- var ok bool
- for i := 0; i < v.NumField(); i++ {
- field := v.Field(i)
- t := field.Type()
- switch t.Kind() {
- case reflect.Bool:
- if len(data) < 1 {
- return errShortRead
- }
- field.SetBool(data[0] != 0)
- data = data[1:]
- case reflect.Array:
- if t.Elem().Kind() != reflect.Uint8 {
- return fieldError(structType, i, "array of unsupported type")
- }
- if len(data) < t.Len() {
- return errShortRead
- }
- for j, n := 0, t.Len(); j < n; j++ {
- field.Index(j).Set(reflect.ValueOf(data[j]))
- }
- data = data[t.Len():]
- case reflect.Uint64:
- var u64 uint64
- if u64, data, ok = parseUint64(data); !ok {
- return errShortRead
- }
- field.SetUint(u64)
- case reflect.Uint32:
- var u32 uint32
- if u32, data, ok = parseUint32(data); !ok {
- return errShortRead
- }
- field.SetUint(uint64(u32))
- case reflect.Uint8:
- if len(data) < 1 {
- return errShortRead
- }
- field.SetUint(uint64(data[0]))
- data = data[1:]
- case reflect.String:
- var s []byte
- if s, data, ok = parseString(data); !ok {
- return fieldError(structType, i, "")
- }
- field.SetString(string(s))
- case reflect.Slice:
- switch t.Elem().Kind() {
- case reflect.Uint8:
- if structType.Field(i).Tag.Get("ssh") == "rest" {
- field.Set(reflect.ValueOf(data))
- data = nil
- } else {
- var s []byte
- if s, data, ok = parseString(data); !ok {
- return errShortRead
- }
- field.Set(reflect.ValueOf(s))
- }
- case reflect.String:
- var nl []string
- if nl, data, ok = parseNameList(data); !ok {
- return errShortRead
- }
- field.Set(reflect.ValueOf(nl))
- default:
- return fieldError(structType, i, "slice of unsupported type")
- }
- case reflect.Ptr:
- if t == bigIntType {
- var n *big.Int
- if n, data, ok = parseInt(data); !ok {
- return errShortRead
- }
- field.Set(reflect.ValueOf(n))
- } else {
- return fieldError(structType, i, "pointer to unsupported type")
- }
- default:
- return fieldError(structType, i, fmt.Sprintf("unsupported type: %v", t))
- }
- }
- if len(data) != 0 {
- return parseError(expectedType)
- }
- return nil
- }
- // Marshal serializes the message in msg to SSH wire format. The msg
- // argument should be a struct or pointer to struct. If the first
- // member has the "sshtype" tag set to a number in decimal, that
- // number is prepended to the result. If the last of member has the
- // "ssh" tag set to "rest", its contents are appended to the output.
- func Marshal(msg interface{}) []byte {
- out := make([]byte, 0, 64)
- return marshalStruct(out, msg)
- }
- func marshalStruct(out []byte, msg interface{}) []byte {
- v := reflect.Indirect(reflect.ValueOf(msg))
- msgTypes := typeTags(v.Type())
- if len(msgTypes) > 0 {
- out = append(out, msgTypes[0])
- }
- for i, n := 0, v.NumField(); i < n; i++ {
- field := v.Field(i)
- switch t := field.Type(); t.Kind() {
- case reflect.Bool:
- var v uint8
- if field.Bool() {
- v = 1
- }
- out = append(out, v)
- case reflect.Array:
- if t.Elem().Kind() != reflect.Uint8 {
- panic(fmt.Sprintf("array of non-uint8 in field %d: %T", i, field.Interface()))
- }
- for j, l := 0, t.Len(); j < l; j++ {
- out = append(out, uint8(field.Index(j).Uint()))
- }
- case reflect.Uint32:
- out = appendU32(out, uint32(field.Uint()))
- case reflect.Uint64:
- out = appendU64(out, uint64(field.Uint()))
- case reflect.Uint8:
- out = append(out, uint8(field.Uint()))
- case reflect.String:
- s := field.String()
- out = appendInt(out, len(s))
- out = append(out, s...)
- case reflect.Slice:
- switch t.Elem().Kind() {
- case reflect.Uint8:
- if v.Type().Field(i).Tag.Get("ssh") != "rest" {
- out = appendInt(out, field.Len())
- }
- out = append(out, field.Bytes()...)
- case reflect.String:
- offset := len(out)
- out = appendU32(out, 0)
- if n := field.Len(); n > 0 {
- for j := 0; j < n; j++ {
- f := field.Index(j)
- if j != 0 {
- out = append(out, ',')
- }
- out = append(out, f.String()...)
- }
- // overwrite length value
- binary.BigEndian.PutUint32(out[offset:], uint32(len(out)-offset-4))
- }
- default:
- panic(fmt.Sprintf("slice of unknown type in field %d: %T", i, field.Interface()))
- }
- case reflect.Ptr:
- if t == bigIntType {
- var n *big.Int
- nValue := reflect.ValueOf(&n)
- nValue.Elem().Set(field)
- needed := intLength(n)
- oldLength := len(out)
- if cap(out)-len(out) < needed {
- newOut := make([]byte, len(out), 2*(len(out)+needed))
- copy(newOut, out)
- out = newOut
- }
- out = out[:oldLength+needed]
- marshalInt(out[oldLength:], n)
- } else {
- panic(fmt.Sprintf("pointer to unknown type in field %d: %T", i, field.Interface()))
- }
- }
- }
- return out
- }
- var bigOne = big.NewInt(1)
- func parseString(in []byte) (out, rest []byte, ok bool) {
- if len(in) < 4 {
- return
- }
- length := binary.BigEndian.Uint32(in)
- in = in[4:]
- if uint32(len(in)) < length {
- return
- }
- out = in[:length]
- rest = in[length:]
- ok = true
- return
- }
- var (
- comma = []byte{','}
- emptyNameList = []string{}
- )
- func parseNameList(in []byte) (out []string, rest []byte, ok bool) {
- contents, rest, ok := parseString(in)
- if !ok {
- return
- }
- if len(contents) == 0 {
- out = emptyNameList
- return
- }
- parts := bytes.Split(contents, comma)
- out = make([]string, len(parts))
- for i, part := range parts {
- out[i] = string(part)
- }
- return
- }
- func parseInt(in []byte) (out *big.Int, rest []byte, ok bool) {
- contents, rest, ok := parseString(in)
- if !ok {
- return
- }
- out = new(big.Int)
- if len(contents) > 0 && contents[0]&0x80 == 0x80 {
- // This is a negative number
- notBytes := make([]byte, len(contents))
- for i := range notBytes {
- notBytes[i] = ^contents[i]
- }
- out.SetBytes(notBytes)
- out.Add(out, bigOne)
- out.Neg(out)
- } else {
- // Positive number
- out.SetBytes(contents)
- }
- ok = true
- return
- }
- func parseUint32(in []byte) (uint32, []byte, bool) {
- if len(in) < 4 {
- return 0, nil, false
- }
- return binary.BigEndian.Uint32(in), in[4:], true
- }
- func parseUint64(in []byte) (uint64, []byte, bool) {
- if len(in) < 8 {
- return 0, nil, false
- }
- return binary.BigEndian.Uint64(in), in[8:], true
- }
- func intLength(n *big.Int) int {
- length := 4 /* length bytes */
- if n.Sign() < 0 {
- nMinus1 := new(big.Int).Neg(n)
- nMinus1.Sub(nMinus1, bigOne)
- bitLen := nMinus1.BitLen()
- if bitLen%8 == 0 {
- // The number will need 0xff padding
- length++
- }
- length += (bitLen + 7) / 8
- } else if n.Sign() == 0 {
- // A zero is the zero length string
- } else {
- bitLen := n.BitLen()
- if bitLen%8 == 0 {
- // The number will need 0x00 padding
- length++
- }
- length += (bitLen + 7) / 8
- }
- return length
- }
- func marshalUint32(to []byte, n uint32) []byte {
- binary.BigEndian.PutUint32(to, n)
- return to[4:]
- }
- func marshalUint64(to []byte, n uint64) []byte {
- binary.BigEndian.PutUint64(to, n)
- return to[8:]
- }
- func marshalInt(to []byte, n *big.Int) []byte {
- lengthBytes := to
- to = to[4:]
- length := 0
- if n.Sign() < 0 {
- // A negative number has to be converted to two's-complement
- // form. So we'll subtract 1 and invert. If the
- // most-significant-bit isn't set then we'll need to pad the
- // beginning with 0xff in order to keep the number negative.
- nMinus1 := new(big.Int).Neg(n)
- nMinus1.Sub(nMinus1, bigOne)
- bytes := nMinus1.Bytes()
- for i := range bytes {
- bytes[i] ^= 0xff
- }
- if len(bytes) == 0 || bytes[0]&0x80 == 0 {
- to[0] = 0xff
- to = to[1:]
- length++
- }
- nBytes := copy(to, bytes)
- to = to[nBytes:]
- length += nBytes
- } else if n.Sign() == 0 {
- // A zero is the zero length string
- } else {
- bytes := n.Bytes()
- if len(bytes) > 0 && bytes[0]&0x80 != 0 {
- // We'll have to pad this with a 0x00 in order to
- // stop it looking like a negative number.
- to[0] = 0
- to = to[1:]
- length++
- }
- nBytes := copy(to, bytes)
- to = to[nBytes:]
- length += nBytes
- }
- lengthBytes[0] = byte(length >> 24)
- lengthBytes[1] = byte(length >> 16)
- lengthBytes[2] = byte(length >> 8)
- lengthBytes[3] = byte(length)
- return to
- }
- func writeInt(w io.Writer, n *big.Int) {
- length := intLength(n)
- buf := make([]byte, length)
- marshalInt(buf, n)
- w.Write(buf)
- }
- func writeString(w io.Writer, s []byte) {
- var lengthBytes [4]byte
- lengthBytes[0] = byte(len(s) >> 24)
- lengthBytes[1] = byte(len(s) >> 16)
- lengthBytes[2] = byte(len(s) >> 8)
- lengthBytes[3] = byte(len(s))
- w.Write(lengthBytes[:])
- w.Write(s)
- }
- func stringLength(n int) int {
- return 4 + n
- }
- func marshalString(to []byte, s []byte) []byte {
- to[0] = byte(len(s) >> 24)
- to[1] = byte(len(s) >> 16)
- to[2] = byte(len(s) >> 8)
- to[3] = byte(len(s))
- to = to[4:]
- copy(to, s)
- return to[len(s):]
- }
- var bigIntType = reflect.TypeOf((*big.Int)(nil))
- // Decode a packet into its corresponding message.
- func decode(packet []byte) (interface{}, error) {
- var msg interface{}
- switch packet[0] {
- case msgDisconnect:
- msg = new(disconnectMsg)
- case msgServiceRequest:
- msg = new(serviceRequestMsg)
- case msgServiceAccept:
- msg = new(serviceAcceptMsg)
- case msgKexInit:
- msg = new(kexInitMsg)
- case msgKexDHInit:
- msg = new(kexDHInitMsg)
- case msgKexDHReply:
- msg = new(kexDHReplyMsg)
- case msgUserAuthRequest:
- msg = new(userAuthRequestMsg)
- case msgUserAuthSuccess:
- return new(userAuthSuccessMsg), nil
- case msgUserAuthFailure:
- msg = new(userAuthFailureMsg)
- case msgUserAuthPubKeyOk:
- msg = new(userAuthPubKeyOkMsg)
- case msgGlobalRequest:
- msg = new(globalRequestMsg)
- case msgRequestSuccess:
- msg = new(globalRequestSuccessMsg)
- case msgRequestFailure:
- msg = new(globalRequestFailureMsg)
- case msgChannelOpen:
- msg = new(channelOpenMsg)
- case msgChannelData:
- msg = new(channelDataMsg)
- case msgChannelOpenConfirm:
- msg = new(channelOpenConfirmMsg)
- case msgChannelOpenFailure:
- msg = new(channelOpenFailureMsg)
- case msgChannelWindowAdjust:
- msg = new(windowAdjustMsg)
- case msgChannelEOF:
- msg = new(channelEOFMsg)
- case msgChannelClose:
- msg = new(channelCloseMsg)
- case msgChannelRequest:
- msg = new(channelRequestMsg)
- case msgChannelSuccess:
- msg = new(channelRequestSuccessMsg)
- case msgChannelFailure:
- msg = new(channelRequestFailureMsg)
- default:
- return nil, unexpectedMessageError(0, packet[0])
- }
- if err := Unmarshal(packet, msg); err != nil {
- return nil, err
- }
- return msg, nil
- }
|