...

Source file src/golang.org/x/crypto/ssh/messages.go

Documentation: golang.org/x/crypto/ssh

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

View as plain text