github.com/Psiphon-Labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/crypto/ssh/messages.go (about)

     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.
     4  
     5  package ssh
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/binary"
    10  	"errors"
    11  	"fmt"
    12  	"io"
    13  	"math/big"
    14  	"reflect"
    15  	"strconv"
    16  	"strings"
    17  )
    18  
    19  // These are SSH message type numbers. They are scattered around several
    20  // documents but many were taken from [SSH-PARAMETERS].
    21  const (
    22  	msgIgnore        = 2
    23  	msgUnimplemented = 3
    24  	msgDebug         = 4
    25  	msgNewKeys       = 21
    26  )
    27  
    28  // SSH messages:
    29  //
    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.
    34  
    35  // See RFC 4253, section 11.1.
    36  const msgDisconnect = 1
    37  
    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"`
    42  	Message  string
    43  	Language string
    44  }
    45  
    46  func (d *disconnectMsg) Error() string {
    47  	return fmt.Sprintf("ssh: disconnect, reason %d: %s", d.Reason, d.Message)
    48  }
    49  
    50  // See RFC 4253, section 7.1.
    51  const msgKexInit = 20
    52  
    53  type kexInitMsg struct {
    54  	Cookie                  [16]byte `sshtype:"20"`
    55  	KexAlgos                []string
    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
    65  	FirstKexFollows         bool
    66  	Reserved                uint32
    67  }
    68  
    69  // See RFC 4253, section 8.
    70  
    71  // Diffie-Helman
    72  const msgKexDHInit = 30
    73  
    74  type kexDHInitMsg struct {
    75  	X *big.Int `sshtype:"30"`
    76  }
    77  
    78  const msgKexECDHInit = 30
    79  
    80  type kexECDHInitMsg struct {
    81  	ClientPubKey []byte `sshtype:"30"`
    82  }
    83  
    84  const msgKexECDHReply = 31
    85  
    86  type kexECDHReplyMsg struct {
    87  	HostKey         []byte `sshtype:"31"`
    88  	EphemeralPubKey []byte
    89  	Signature       []byte
    90  }
    91  
    92  const msgKexDHReply = 31
    93  
    94  type kexDHReplyMsg struct {
    95  	HostKey   []byte `sshtype:"31"`
    96  	Y         *big.Int
    97  	Signature []byte
    98  }
    99  
   100  // See RFC 4419, section 5.
   101  const msgKexDHGexGroup = 31
   102  
   103  type kexDHGexGroupMsg struct {
   104  	P *big.Int `sshtype:"31"`
   105  	G *big.Int
   106  }
   107  
   108  const msgKexDHGexInit = 32
   109  
   110  type kexDHGexInitMsg struct {
   111  	X *big.Int `sshtype:"32"`
   112  }
   113  
   114  const msgKexDHGexReply = 33
   115  
   116  type kexDHGexReplyMsg struct {
   117  	HostKey   []byte `sshtype:"33"`
   118  	Y         *big.Int
   119  	Signature []byte
   120  }
   121  
   122  const msgKexDHGexRequest = 34
   123  
   124  type kexDHGexRequestMsg struct {
   125  	MinBits      uint32 `sshtype:"34"`
   126  	PreferedBits uint32
   127  	MaxBits      uint32
   128  }
   129  
   130  // See RFC 4253, section 10.
   131  const msgServiceRequest = 5
   132  
   133  type serviceRequestMsg struct {
   134  	Service string `sshtype:"5"`
   135  }
   136  
   137  // See RFC 4253, section 10.
   138  const msgServiceAccept = 6
   139  
   140  type serviceAcceptMsg struct {
   141  	Service string `sshtype:"6"`
   142  }
   143  
   144  // See RFC 4252, section 5.
   145  const msgUserAuthRequest = 50
   146  
   147  type userAuthRequestMsg struct {
   148  	User    string `sshtype:"50"`
   149  	Service string
   150  	Method  string
   151  	Payload []byte `ssh:"rest"`
   152  }
   153  
   154  // Used for debug printouts of packets.
   155  type userAuthSuccessMsg struct {
   156  }
   157  
   158  // See RFC 4252, section 5.1
   159  const msgUserAuthFailure = 51
   160  
   161  type userAuthFailureMsg struct {
   162  	Methods        []string `sshtype:"51"`
   163  	PartialSuccess bool
   164  }
   165  
   166  // See RFC 4252, section 5.1
   167  const msgUserAuthSuccess = 52
   168  
   169  // See RFC 4252, section 5.4
   170  const msgUserAuthBanner = 53
   171  
   172  type userAuthBannerMsg struct {
   173  	Message string `sshtype:"53"`
   174  	// unused, but required to allow message parsing
   175  	Language string
   176  }
   177  
   178  // See RFC 4256, section 3.2
   179  const msgUserAuthInfoRequest = 60
   180  const msgUserAuthInfoResponse = 61
   181  
   182  type userAuthInfoRequestMsg struct {
   183  	User               string `sshtype:"60"`
   184  	Instruction        string
   185  	DeprecatedLanguage string
   186  	NumPrompts         uint32
   187  	Prompts            []byte `ssh:"rest"`
   188  }
   189  
   190  // See RFC 4254, section 5.1.
   191  const msgChannelOpen = 90
   192  
   193  type channelOpenMsg struct {
   194  	ChanType         string `sshtype:"90"`
   195  	PeersID          uint32
   196  	PeersWindow      uint32
   197  	MaxPacketSize    uint32
   198  	TypeSpecificData []byte `ssh:"rest"`
   199  }
   200  
   201  const msgChannelExtendedData = 95
   202  const msgChannelData = 94
   203  
   204  // Used for debug print outs of packets.
   205  type channelDataMsg struct {
   206  	PeersID uint32 `sshtype:"94"`
   207  	Length  uint32
   208  	Rest    []byte `ssh:"rest"`
   209  }
   210  
   211  // See RFC 4254, section 5.1.
   212  const msgChannelOpenConfirm = 91
   213  
   214  type channelOpenConfirmMsg struct {
   215  	PeersID          uint32 `sshtype:"91"`
   216  	MyID             uint32
   217  	MyWindow         uint32
   218  	MaxPacketSize    uint32
   219  	TypeSpecificData []byte `ssh:"rest"`
   220  }
   221  
   222  // See RFC 4254, section 5.1.
   223  const msgChannelOpenFailure = 92
   224  
   225  type channelOpenFailureMsg struct {
   226  	PeersID  uint32 `sshtype:"92"`
   227  	Reason   RejectionReason
   228  	Message  string
   229  	Language string
   230  }
   231  
   232  const msgChannelRequest = 98
   233  
   234  type channelRequestMsg struct {
   235  	PeersID             uint32 `sshtype:"98"`
   236  	Request             string
   237  	WantReply           bool
   238  	RequestSpecificData []byte `ssh:"rest"`
   239  }
   240  
   241  // See RFC 4254, section 5.4.
   242  const msgChannelSuccess = 99
   243  
   244  type channelRequestSuccessMsg struct {
   245  	PeersID uint32 `sshtype:"99"`
   246  }
   247  
   248  // See RFC 4254, section 5.4.
   249  const msgChannelFailure = 100
   250  
   251  type channelRequestFailureMsg struct {
   252  	PeersID uint32 `sshtype:"100"`
   253  }
   254  
   255  // See RFC 4254, section 5.3
   256  const msgChannelClose = 97
   257  
   258  type channelCloseMsg struct {
   259  	PeersID uint32 `sshtype:"97"`
   260  }
   261  
   262  // See RFC 4254, section 5.3
   263  const msgChannelEOF = 96
   264  
   265  type channelEOFMsg struct {
   266  	PeersID uint32 `sshtype:"96"`
   267  }
   268  
   269  // See RFC 4254, section 4
   270  const msgGlobalRequest = 80
   271  
   272  type globalRequestMsg struct {
   273  	Type      string `sshtype:"80"`
   274  	WantReply bool
   275  	Data      []byte `ssh:"rest"`
   276  }
   277  
   278  // See RFC 4254, section 4
   279  const msgRequestSuccess = 81
   280  
   281  type globalRequestSuccessMsg struct {
   282  	Data []byte `ssh:"rest" sshtype:"81"`
   283  }
   284  
   285  // See RFC 4254, section 4
   286  const msgRequestFailure = 82
   287  
   288  type globalRequestFailureMsg struct {
   289  	Data []byte `ssh:"rest" sshtype:"82"`
   290  }
   291  
   292  // See RFC 4254, section 5.2
   293  const msgChannelWindowAdjust = 93
   294  
   295  type windowAdjustMsg struct {
   296  	PeersID         uint32 `sshtype:"93"`
   297  	AdditionalBytes uint32
   298  }
   299  
   300  // See RFC 4252, section 7
   301  const msgUserAuthPubKeyOk = 60
   302  
   303  type userAuthPubKeyOkMsg struct {
   304  	Algo   string `sshtype:"60"`
   305  	PubKey []byte
   306  }
   307  
   308  // See RFC 4462, section 3
   309  const msgUserAuthGSSAPIResponse = 60
   310  
   311  type userAuthGSSAPIResponse struct {
   312  	SupportMech []byte `sshtype:"60"`
   313  }
   314  
   315  const msgUserAuthGSSAPIToken = 61
   316  
   317  type userAuthGSSAPIToken struct {
   318  	Token []byte `sshtype:"61"`
   319  }
   320  
   321  const msgUserAuthGSSAPIMIC = 66
   322  
   323  type userAuthGSSAPIMIC struct {
   324  	MIC []byte `sshtype:"66"`
   325  }
   326  
   327  // See RFC 4462, section 3.9
   328  const msgUserAuthGSSAPIErrTok = 64
   329  
   330  type userAuthGSSAPIErrTok struct {
   331  	ErrorToken []byte `sshtype:"64"`
   332  }
   333  
   334  // See RFC 4462, section 3.8
   335  const msgUserAuthGSSAPIError = 65
   336  
   337  type userAuthGSSAPIError struct {
   338  	MajorStatus uint32 `sshtype:"65"`
   339  	MinorStatus uint32
   340  	Message     string
   341  	LanguageTag string
   342  }
   343  
   344  // typeTags returns the possible type bytes for the given reflect.Type, which
   345  // should be a struct. The possible values are separated by a '|' character.
   346  func typeTags(structType reflect.Type) (tags []byte) {
   347  	tagStr := structType.Field(0).Tag.Get("sshtype")
   348  
   349  	for _, tag := range strings.Split(tagStr, "|") {
   350  		i, err := strconv.Atoi(tag)
   351  		if err == nil {
   352  			tags = append(tags, byte(i))
   353  		}
   354  	}
   355  
   356  	return tags
   357  }
   358  
   359  func fieldError(t reflect.Type, field int, problem string) error {
   360  	if problem != "" {
   361  		problem = ": " + problem
   362  	}
   363  	return fmt.Errorf("ssh: unmarshal error for field %s of type %s%s", t.Field(field).Name, t.Name(), problem)
   364  }
   365  
   366  var errShortRead = errors.New("ssh: short read")
   367  
   368  // Unmarshal parses data in SSH wire format into a structure. The out
   369  // argument should be a pointer to struct. If the first member of the
   370  // struct has the "sshtype" tag set to a '|'-separated set of numbers
   371  // in decimal, the packet must start with one of those numbers. In
   372  // case of error, Unmarshal returns a ParseError or
   373  // UnexpectedMessageError.
   374  func Unmarshal(data []byte, out interface{}) error {
   375  	v := reflect.ValueOf(out).Elem()
   376  	structType := v.Type()
   377  	expectedTypes := typeTags(structType)
   378  
   379  	var expectedType byte
   380  	if len(expectedTypes) > 0 {
   381  		expectedType = expectedTypes[0]
   382  	}
   383  
   384  	if len(data) == 0 {
   385  		return parseError(expectedType)
   386  	}
   387  
   388  	if len(expectedTypes) > 0 {
   389  		goodType := false
   390  		for _, e := range expectedTypes {
   391  			if e > 0 && data[0] == e {
   392  				goodType = true
   393  				break
   394  			}
   395  		}
   396  		if !goodType {
   397  			return fmt.Errorf("ssh: unexpected message type %d (expected one of %v)", data[0], expectedTypes)
   398  		}
   399  		data = data[1:]
   400  	}
   401  
   402  	var ok bool
   403  	for i := 0; i < v.NumField(); i++ {
   404  		field := v.Field(i)
   405  		t := field.Type()
   406  		switch t.Kind() {
   407  		case reflect.Bool:
   408  			if len(data) < 1 {
   409  				return errShortRead
   410  			}
   411  			field.SetBool(data[0] != 0)
   412  			data = data[1:]
   413  		case reflect.Array:
   414  			if t.Elem().Kind() != reflect.Uint8 {
   415  				return fieldError(structType, i, "array of unsupported type")
   416  			}
   417  			if len(data) < t.Len() {
   418  				return errShortRead
   419  			}
   420  			for j, n := 0, t.Len(); j < n; j++ {
   421  				field.Index(j).Set(reflect.ValueOf(data[j]))
   422  			}
   423  			data = data[t.Len():]
   424  		case reflect.Uint64:
   425  			var u64 uint64
   426  			if u64, data, ok = parseUint64(data); !ok {
   427  				return errShortRead
   428  			}
   429  			field.SetUint(u64)
   430  		case reflect.Uint32:
   431  			var u32 uint32
   432  			if u32, data, ok = parseUint32(data); !ok {
   433  				return errShortRead
   434  			}
   435  			field.SetUint(uint64(u32))
   436  		case reflect.Uint8:
   437  			if len(data) < 1 {
   438  				return errShortRead
   439  			}
   440  			field.SetUint(uint64(data[0]))
   441  			data = data[1:]
   442  		case reflect.String:
   443  			var s []byte
   444  			if s, data, ok = parseString(data); !ok {
   445  				return fieldError(structType, i, "")
   446  			}
   447  			field.SetString(string(s))
   448  		case reflect.Slice:
   449  			switch t.Elem().Kind() {
   450  			case reflect.Uint8:
   451  				if structType.Field(i).Tag.Get("ssh") == "rest" {
   452  					field.Set(reflect.ValueOf(data))
   453  					data = nil
   454  				} else {
   455  					var s []byte
   456  					if s, data, ok = parseString(data); !ok {
   457  						return errShortRead
   458  					}
   459  					field.Set(reflect.ValueOf(s))
   460  				}
   461  			case reflect.String:
   462  				var nl []string
   463  				if nl, data, ok = parseNameList(data); !ok {
   464  					return errShortRead
   465  				}
   466  				field.Set(reflect.ValueOf(nl))
   467  			default:
   468  				return fieldError(structType, i, "slice of unsupported type")
   469  			}
   470  		case reflect.Ptr:
   471  			if t == bigIntType {
   472  				var n *big.Int
   473  				if n, data, ok = parseInt(data); !ok {
   474  					return errShortRead
   475  				}
   476  				field.Set(reflect.ValueOf(n))
   477  			} else {
   478  				return fieldError(structType, i, "pointer to unsupported type")
   479  			}
   480  		default:
   481  			return fieldError(structType, i, fmt.Sprintf("unsupported type: %v", t))
   482  		}
   483  	}
   484  
   485  	if len(data) != 0 {
   486  		return parseError(expectedType)
   487  	}
   488  
   489  	return nil
   490  }
   491  
   492  // Marshal serializes the message in msg to SSH wire format.  The msg
   493  // argument should be a struct or pointer to struct. If the first
   494  // member has the "sshtype" tag set to a number in decimal, that
   495  // number is prepended to the result. If the last of member has the
   496  // "ssh" tag set to "rest", its contents are appended to the output.
   497  func Marshal(msg interface{}) []byte {
   498  	out := make([]byte, 0, 64)
   499  	return marshalStruct(out, msg)
   500  }
   501  
   502  func marshalStruct(out []byte, msg interface{}) []byte {
   503  	v := reflect.Indirect(reflect.ValueOf(msg))
   504  	msgTypes := typeTags(v.Type())
   505  	if len(msgTypes) > 0 {
   506  		out = append(out, msgTypes[0])
   507  	}
   508  
   509  	for i, n := 0, v.NumField(); i < n; i++ {
   510  		field := v.Field(i)
   511  		switch t := field.Type(); t.Kind() {
   512  		case reflect.Bool:
   513  			var v uint8
   514  			if field.Bool() {
   515  				v = 1
   516  			}
   517  			out = append(out, v)
   518  		case reflect.Array:
   519  			if t.Elem().Kind() != reflect.Uint8 {
   520  				panic(fmt.Sprintf("array of non-uint8 in field %d: %T", i, field.Interface()))
   521  			}
   522  			for j, l := 0, t.Len(); j < l; j++ {
   523  				out = append(out, uint8(field.Index(j).Uint()))
   524  			}
   525  		case reflect.Uint32:
   526  			out = appendU32(out, uint32(field.Uint()))
   527  		case reflect.Uint64:
   528  			out = appendU64(out, uint64(field.Uint()))
   529  		case reflect.Uint8:
   530  			out = append(out, uint8(field.Uint()))
   531  		case reflect.String:
   532  			s := field.String()
   533  			out = appendInt(out, len(s))
   534  			out = append(out, s...)
   535  		case reflect.Slice:
   536  			switch t.Elem().Kind() {
   537  			case reflect.Uint8:
   538  				if v.Type().Field(i).Tag.Get("ssh") != "rest" {
   539  					out = appendInt(out, field.Len())
   540  				}
   541  				out = append(out, field.Bytes()...)
   542  			case reflect.String:
   543  				offset := len(out)
   544  				out = appendU32(out, 0)
   545  				if n := field.Len(); n > 0 {
   546  					for j := 0; j < n; j++ {
   547  						f := field.Index(j)
   548  						if j != 0 {
   549  							out = append(out, ',')
   550  						}
   551  						out = append(out, f.String()...)
   552  					}
   553  					// overwrite length value
   554  					binary.BigEndian.PutUint32(out[offset:], uint32(len(out)-offset-4))
   555  				}
   556  			default:
   557  				panic(fmt.Sprintf("slice of unknown type in field %d: %T", i, field.Interface()))
   558  			}
   559  		case reflect.Ptr:
   560  			if t == bigIntType {
   561  				var n *big.Int
   562  				nValue := reflect.ValueOf(&n)
   563  				nValue.Elem().Set(field)
   564  				needed := intLength(n)
   565  				oldLength := len(out)
   566  
   567  				if cap(out)-len(out) < needed {
   568  					newOut := make([]byte, len(out), 2*(len(out)+needed))
   569  					copy(newOut, out)
   570  					out = newOut
   571  				}
   572  				out = out[:oldLength+needed]
   573  				marshalInt(out[oldLength:], n)
   574  			} else {
   575  				panic(fmt.Sprintf("pointer to unknown type in field %d: %T", i, field.Interface()))
   576  			}
   577  		}
   578  	}
   579  
   580  	return out
   581  }
   582  
   583  var bigOne = big.NewInt(1)
   584  
   585  func parseString(in []byte) (out, rest []byte, ok bool) {
   586  	if len(in) < 4 {
   587  		return
   588  	}
   589  	length := binary.BigEndian.Uint32(in)
   590  	in = in[4:]
   591  	if uint32(len(in)) < length {
   592  		return
   593  	}
   594  	out = in[:length]
   595  	rest = in[length:]
   596  	ok = true
   597  	return
   598  }
   599  
   600  var (
   601  	comma         = []byte{','}
   602  	emptyNameList = []string{}
   603  )
   604  
   605  func parseNameList(in []byte) (out []string, rest []byte, ok bool) {
   606  	contents, rest, ok := parseString(in)
   607  	if !ok {
   608  		return
   609  	}
   610  	if len(contents) == 0 {
   611  		out = emptyNameList
   612  		return
   613  	}
   614  	parts := bytes.Split(contents, comma)
   615  	out = make([]string, len(parts))
   616  	for i, part := range parts {
   617  		out[i] = string(part)
   618  	}
   619  	return
   620  }
   621  
   622  func parseInt(in []byte) (out *big.Int, rest []byte, ok bool) {
   623  	contents, rest, ok := parseString(in)
   624  	if !ok {
   625  		return
   626  	}
   627  	out = new(big.Int)
   628  
   629  	if len(contents) > 0 && contents[0]&0x80 == 0x80 {
   630  		// This is a negative number
   631  		notBytes := make([]byte, len(contents))
   632  		for i := range notBytes {
   633  			notBytes[i] = ^contents[i]
   634  		}
   635  		out.SetBytes(notBytes)
   636  		out.Add(out, bigOne)
   637  		out.Neg(out)
   638  	} else {
   639  		// Positive number
   640  		out.SetBytes(contents)
   641  	}
   642  	ok = true
   643  	return
   644  }
   645  
   646  func parseUint32(in []byte) (uint32, []byte, bool) {
   647  	if len(in) < 4 {
   648  		return 0, nil, false
   649  	}
   650  	return binary.BigEndian.Uint32(in), in[4:], true
   651  }
   652  
   653  func parseUint64(in []byte) (uint64, []byte, bool) {
   654  	if len(in) < 8 {
   655  		return 0, nil, false
   656  	}
   657  	return binary.BigEndian.Uint64(in), in[8:], true
   658  }
   659  
   660  func intLength(n *big.Int) int {
   661  	length := 4 /* length bytes */
   662  	if n.Sign() < 0 {
   663  		nMinus1 := new(big.Int).Neg(n)
   664  		nMinus1.Sub(nMinus1, bigOne)
   665  		bitLen := nMinus1.BitLen()
   666  		if bitLen%8 == 0 {
   667  			// The number will need 0xff padding
   668  			length++
   669  		}
   670  		length += (bitLen + 7) / 8
   671  	} else if n.Sign() == 0 {
   672  		// A zero is the zero length string
   673  	} else {
   674  		bitLen := n.BitLen()
   675  		if bitLen%8 == 0 {
   676  			// The number will need 0x00 padding
   677  			length++
   678  		}
   679  		length += (bitLen + 7) / 8
   680  	}
   681  
   682  	return length
   683  }
   684  
   685  func marshalUint32(to []byte, n uint32) []byte {
   686  	binary.BigEndian.PutUint32(to, n)
   687  	return to[4:]
   688  }
   689  
   690  func marshalUint64(to []byte, n uint64) []byte {
   691  	binary.BigEndian.PutUint64(to, n)
   692  	return to[8:]
   693  }
   694  
   695  func marshalInt(to []byte, n *big.Int) []byte {
   696  	lengthBytes := to
   697  	to = to[4:]
   698  	length := 0
   699  
   700  	if n.Sign() < 0 {
   701  		// A negative number has to be converted to two's-complement
   702  		// form. So we'll subtract 1 and invert. If the
   703  		// most-significant-bit isn't set then we'll need to pad the
   704  		// beginning with 0xff in order to keep the number negative.
   705  		nMinus1 := new(big.Int).Neg(n)
   706  		nMinus1.Sub(nMinus1, bigOne)
   707  		bytes := nMinus1.Bytes()
   708  		for i := range bytes {
   709  			bytes[i] ^= 0xff
   710  		}
   711  		if len(bytes) == 0 || bytes[0]&0x80 == 0 {
   712  			to[0] = 0xff
   713  			to = to[1:]
   714  			length++
   715  		}
   716  		nBytes := copy(to, bytes)
   717  		to = to[nBytes:]
   718  		length += nBytes
   719  	} else if n.Sign() == 0 {
   720  		// A zero is the zero length string
   721  	} else {
   722  		bytes := n.Bytes()
   723  		if len(bytes) > 0 && bytes[0]&0x80 != 0 {
   724  			// We'll have to pad this with a 0x00 in order to
   725  			// stop it looking like a negative number.
   726  			to[0] = 0
   727  			to = to[1:]
   728  			length++
   729  		}
   730  		nBytes := copy(to, bytes)
   731  		to = to[nBytes:]
   732  		length += nBytes
   733  	}
   734  
   735  	lengthBytes[0] = byte(length >> 24)
   736  	lengthBytes[1] = byte(length >> 16)
   737  	lengthBytes[2] = byte(length >> 8)
   738  	lengthBytes[3] = byte(length)
   739  	return to
   740  }
   741  
   742  func writeInt(w io.Writer, n *big.Int) {
   743  	length := intLength(n)
   744  	buf := make([]byte, length)
   745  	marshalInt(buf, n)
   746  	w.Write(buf)
   747  }
   748  
   749  func writeString(w io.Writer, s []byte) {
   750  	var lengthBytes [4]byte
   751  	lengthBytes[0] = byte(len(s) >> 24)
   752  	lengthBytes[1] = byte(len(s) >> 16)
   753  	lengthBytes[2] = byte(len(s) >> 8)
   754  	lengthBytes[3] = byte(len(s))
   755  	w.Write(lengthBytes[:])
   756  	w.Write(s)
   757  }
   758  
   759  func stringLength(n int) int {
   760  	return 4 + n
   761  }
   762  
   763  func marshalString(to []byte, s []byte) []byte {
   764  	to[0] = byte(len(s) >> 24)
   765  	to[1] = byte(len(s) >> 16)
   766  	to[2] = byte(len(s) >> 8)
   767  	to[3] = byte(len(s))
   768  	to = to[4:]
   769  	copy(to, s)
   770  	return to[len(s):]
   771  }
   772  
   773  var bigIntType = reflect.TypeOf((*big.Int)(nil))
   774  
   775  // Decode a packet into its corresponding message.
   776  func decode(packet []byte) (interface{}, error) {
   777  	var msg interface{}
   778  	switch packet[0] {
   779  	case msgDisconnect:
   780  		msg = new(disconnectMsg)
   781  	case msgServiceRequest:
   782  		msg = new(serviceRequestMsg)
   783  	case msgServiceAccept:
   784  		msg = new(serviceAcceptMsg)
   785  	case msgKexInit:
   786  		msg = new(kexInitMsg)
   787  	case msgKexDHInit:
   788  		msg = new(kexDHInitMsg)
   789  	case msgKexDHReply:
   790  		msg = new(kexDHReplyMsg)
   791  	case msgUserAuthRequest:
   792  		msg = new(userAuthRequestMsg)
   793  	case msgUserAuthSuccess:
   794  		return new(userAuthSuccessMsg), nil
   795  	case msgUserAuthFailure:
   796  		msg = new(userAuthFailureMsg)
   797  	case msgUserAuthPubKeyOk:
   798  		msg = new(userAuthPubKeyOkMsg)
   799  	case msgGlobalRequest:
   800  		msg = new(globalRequestMsg)
   801  	case msgRequestSuccess:
   802  		msg = new(globalRequestSuccessMsg)
   803  	case msgRequestFailure:
   804  		msg = new(globalRequestFailureMsg)
   805  	case msgChannelOpen:
   806  		msg = new(channelOpenMsg)
   807  	case msgChannelData:
   808  		msg = new(channelDataMsg)
   809  	case msgChannelOpenConfirm:
   810  		msg = new(channelOpenConfirmMsg)
   811  	case msgChannelOpenFailure:
   812  		msg = new(channelOpenFailureMsg)
   813  	case msgChannelWindowAdjust:
   814  		msg = new(windowAdjustMsg)
   815  	case msgChannelEOF:
   816  		msg = new(channelEOFMsg)
   817  	case msgChannelClose:
   818  		msg = new(channelCloseMsg)
   819  	case msgChannelRequest:
   820  		msg = new(channelRequestMsg)
   821  	case msgChannelSuccess:
   822  		msg = new(channelRequestSuccessMsg)
   823  	case msgChannelFailure:
   824  		msg = new(channelRequestFailureMsg)
   825  	case msgUserAuthGSSAPIToken:
   826  		msg = new(userAuthGSSAPIToken)
   827  	case msgUserAuthGSSAPIMIC:
   828  		msg = new(userAuthGSSAPIMIC)
   829  	case msgUserAuthGSSAPIErrTok:
   830  		msg = new(userAuthGSSAPIErrTok)
   831  	case msgUserAuthGSSAPIError:
   832  		msg = new(userAuthGSSAPIError)
   833  	default:
   834  		return nil, unexpectedMessageError(0, packet[0])
   835  	}
   836  	if err := Unmarshal(packet, msg); err != nil {
   837  		return nil, err
   838  	}
   839  	return msg, nil
   840  }
   841  
   842  var packetTypeNames = map[byte]string{
   843  	msgDisconnect:          "disconnectMsg",
   844  	msgServiceRequest:      "serviceRequestMsg",
   845  	msgServiceAccept:       "serviceAcceptMsg",
   846  	msgKexInit:             "kexInitMsg",
   847  	msgKexDHInit:           "kexDHInitMsg",
   848  	msgKexDHReply:          "kexDHReplyMsg",
   849  	msgUserAuthRequest:     "userAuthRequestMsg",
   850  	msgUserAuthSuccess:     "userAuthSuccessMsg",
   851  	msgUserAuthFailure:     "userAuthFailureMsg",
   852  	msgUserAuthPubKeyOk:    "userAuthPubKeyOkMsg",
   853  	msgGlobalRequest:       "globalRequestMsg",
   854  	msgRequestSuccess:      "globalRequestSuccessMsg",
   855  	msgRequestFailure:      "globalRequestFailureMsg",
   856  	msgChannelOpen:         "channelOpenMsg",
   857  	msgChannelData:         "channelDataMsg",
   858  	msgChannelOpenConfirm:  "channelOpenConfirmMsg",
   859  	msgChannelOpenFailure:  "channelOpenFailureMsg",
   860  	msgChannelWindowAdjust: "windowAdjustMsg",
   861  	msgChannelEOF:          "channelEOFMsg",
   862  	msgChannelClose:        "channelCloseMsg",
   863  	msgChannelRequest:      "channelRequestMsg",
   864  	msgChannelSuccess:      "channelRequestSuccessMsg",
   865  	msgChannelFailure:      "channelRequestFailureMsg",
   866  }