main
Raw Download raw file
  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
  5package ssh
  6
  7import (
  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].
 21const (
 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.
 36const msgDisconnect = 1
 37
 38// disconnectMsg is the message that signals a disconnect. It is also
 39// the error type returned from mux.Wait()
 40type disconnectMsg struct {
 41	Reason   uint32 `sshtype:"1"`
 42	Message  string
 43	Language string
 44}
 45
 46func (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.
 51const msgKexInit = 20
 52
 53type 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
 72const msgKexDHInit = 30
 73
 74type kexDHInitMsg struct {
 75	X *big.Int `sshtype:"30"`
 76}
 77
 78const msgKexECDHInit = 30
 79
 80type kexECDHInitMsg struct {
 81	ClientPubKey []byte `sshtype:"30"`
 82}
 83
 84const msgKexECDHReply = 31
 85
 86type kexECDHReplyMsg struct {
 87	HostKey         []byte `sshtype:"31"`
 88	EphemeralPubKey []byte
 89	Signature       []byte
 90}
 91
 92const msgKexDHReply = 31
 93
 94type kexDHReplyMsg struct {
 95	HostKey   []byte `sshtype:"31"`
 96	Y         *big.Int
 97	Signature []byte
 98}
 99
100// See RFC 4419, section 5.
101const msgKexDHGexGroup = 31
102
103type kexDHGexGroupMsg struct {
104	P *big.Int `sshtype:"31"`
105	G *big.Int
106}
107
108const msgKexDHGexInit = 32
109
110type kexDHGexInitMsg struct {
111	X *big.Int `sshtype:"32"`
112}
113
114const msgKexDHGexReply = 33
115
116type kexDHGexReplyMsg struct {
117	HostKey   []byte `sshtype:"33"`
118	Y         *big.Int
119	Signature []byte
120}
121
122const msgKexDHGexRequest = 34
123
124type kexDHGexRequestMsg struct {
125	MinBits      uint32 `sshtype:"34"`
126	PreferedBits uint32
127	MaxBits      uint32
128}
129
130// See RFC 4253, section 10.
131const msgServiceRequest = 5
132
133type serviceRequestMsg struct {
134	Service string `sshtype:"5"`
135}
136
137// See RFC 4253, section 10.
138const msgServiceAccept = 6
139
140type serviceAcceptMsg struct {
141	Service string `sshtype:"6"`
142}
143
144// See RFC 8308, section 2.3
145const msgExtInfo = 7
146
147type extInfoMsg struct {
148	NumExtensions uint32 `sshtype:"7"`
149	Payload       []byte `ssh:"rest"`
150}
151
152// See RFC 4252, section 5.
153const msgUserAuthRequest = 50
154
155type 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.
163type userAuthSuccessMsg struct {
164}
165
166// See RFC 4252, section 5.1
167const msgUserAuthFailure = 51
168
169type userAuthFailureMsg struct {
170	Methods        []string `sshtype:"51"`
171	PartialSuccess bool
172}
173
174// See RFC 4252, section 5.1
175const msgUserAuthSuccess = 52
176
177// See RFC 4252, section 5.4
178const msgUserAuthBanner = 53
179
180type 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
187const msgUserAuthInfoRequest = 60
188const msgUserAuthInfoResponse = 61
189
190type 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.
199const msgChannelOpen = 90
200
201type channelOpenMsg struct {
202	ChanType         string `sshtype:"90"`
203	PeersID          uint32
204	PeersWindow      uint32
205	MaxPacketSize    uint32
206	TypeSpecificData []byte `ssh:"rest"`
207}
208
209const msgChannelExtendedData = 95
210const msgChannelData = 94
211
212// Used for debug print outs of packets.
213type channelDataMsg struct {
214	PeersID uint32 `sshtype:"94"`
215	Length  uint32
216	Rest    []byte `ssh:"rest"`
217}
218
219// See RFC 4254, section 5.1.
220const msgChannelOpenConfirm = 91
221
222type 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.
231const msgChannelOpenFailure = 92
232
233type channelOpenFailureMsg struct {
234	PeersID  uint32 `sshtype:"92"`
235	Reason   RejectionReason
236	Message  string
237	Language string
238}
239
240const msgChannelRequest = 98
241
242type 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.
250const msgChannelSuccess = 99
251
252type channelRequestSuccessMsg struct {
253	PeersID uint32 `sshtype:"99"`
254}
255
256// See RFC 4254, section 5.4.
257const msgChannelFailure = 100
258
259type channelRequestFailureMsg struct {
260	PeersID uint32 `sshtype:"100"`
261}
262
263// See RFC 4254, section 5.3
264const msgChannelClose = 97
265
266type channelCloseMsg struct {
267	PeersID uint32 `sshtype:"97"`
268}
269
270// See RFC 4254, section 5.3
271const msgChannelEOF = 96
272
273type channelEOFMsg struct {
274	PeersID uint32 `sshtype:"96"`
275}
276
277// See RFC 4254, section 4
278const msgGlobalRequest = 80
279
280type globalRequestMsg struct {
281	Type      string `sshtype:"80"`
282	WantReply bool
283	Data      []byte `ssh:"rest"`
284}
285
286// See RFC 4254, section 4
287const msgRequestSuccess = 81
288
289type globalRequestSuccessMsg struct {
290	Data []byte `ssh:"rest" sshtype:"81"`
291}
292
293// See RFC 4254, section 4
294const msgRequestFailure = 82
295
296type globalRequestFailureMsg struct {
297	Data []byte `ssh:"rest" sshtype:"82"`
298}
299
300// See RFC 4254, section 5.2
301const msgChannelWindowAdjust = 93
302
303type windowAdjustMsg struct {
304	PeersID         uint32 `sshtype:"93"`
305	AdditionalBytes uint32
306}
307
308// See RFC 4252, section 7
309const msgUserAuthPubKeyOk = 60
310
311type userAuthPubKeyOkMsg struct {
312	Algo   string `sshtype:"60"`
313	PubKey []byte
314}
315
316// See RFC 4462, section 3
317const msgUserAuthGSSAPIResponse = 60
318
319type userAuthGSSAPIResponse struct {
320	SupportMech []byte `sshtype:"60"`
321}
322
323const msgUserAuthGSSAPIToken = 61
324
325type userAuthGSSAPIToken struct {
326	Token []byte `sshtype:"61"`
327}
328
329const msgUserAuthGSSAPIMIC = 66
330
331type userAuthGSSAPIMIC struct {
332	MIC []byte `sshtype:"66"`
333}
334
335// See RFC 4462, section 3.9
336const msgUserAuthGSSAPIErrTok = 64
337
338type userAuthGSSAPIErrTok struct {
339	ErrorToken []byte `sshtype:"64"`
340}
341
342// See RFC 4462, section 3.8
343const msgUserAuthGSSAPIError = 65
344
345type 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
353const msgPing = 192
354
355type pingMsg struct {
356	Data string `sshtype:"192"`
357}
358
359// Transport layer OpenSSH extension. See [PROTOCOL], section 1.9
360const msgPong = 193
361
362type 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.
368func 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
381func 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
388var 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.
396func 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.
519func Marshal(msg interface{}) []byte {
520	out := make([]byte, 0, 64)
521	return marshalStruct(out, msg)
522}
523
524func 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
605var bigOne = big.NewInt(1)
606
607func 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
622var (
623	comma         = []byte{','}
624	emptyNameList = []string{}
625)
626
627func 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
644func 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
668func 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
675func 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
682func 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
707func marshalUint32(to []byte, n uint32) []byte {
708	binary.BigEndian.PutUint32(to, n)
709	return to[4:]
710}
711
712func marshalUint64(to []byte, n uint64) []byte {
713	binary.BigEndian.PutUint64(to, n)
714	return to[8:]
715}
716
717func 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
764func 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
771func 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
781func stringLength(n int) int {
782	return 4 + n
783}
784
785func 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
795var bigIntType = reflect.TypeOf((*big.Int)(nil))
796
797// Decode a packet into its corresponding message.
798func 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 msgUserAuthBanner:
822		msg = new(userAuthBannerMsg)
823	case msgUserAuthPubKeyOk:
824		msg = new(userAuthPubKeyOkMsg)
825	case msgGlobalRequest:
826		msg = new(globalRequestMsg)
827	case msgRequestSuccess:
828		msg = new(globalRequestSuccessMsg)
829	case msgRequestFailure:
830		msg = new(globalRequestFailureMsg)
831	case msgChannelOpen:
832		msg = new(channelOpenMsg)
833	case msgChannelData:
834		msg = new(channelDataMsg)
835	case msgChannelOpenConfirm:
836		msg = new(channelOpenConfirmMsg)
837	case msgChannelOpenFailure:
838		msg = new(channelOpenFailureMsg)
839	case msgChannelWindowAdjust:
840		msg = new(windowAdjustMsg)
841	case msgChannelEOF:
842		msg = new(channelEOFMsg)
843	case msgChannelClose:
844		msg = new(channelCloseMsg)
845	case msgChannelRequest:
846		msg = new(channelRequestMsg)
847	case msgChannelSuccess:
848		msg = new(channelRequestSuccessMsg)
849	case msgChannelFailure:
850		msg = new(channelRequestFailureMsg)
851	case msgUserAuthGSSAPIToken:
852		msg = new(userAuthGSSAPIToken)
853	case msgUserAuthGSSAPIMIC:
854		msg = new(userAuthGSSAPIMIC)
855	case msgUserAuthGSSAPIErrTok:
856		msg = new(userAuthGSSAPIErrTok)
857	case msgUserAuthGSSAPIError:
858		msg = new(userAuthGSSAPIError)
859	default:
860		return nil, unexpectedMessageError(0, packet[0])
861	}
862	if err := Unmarshal(packet, msg); err != nil {
863		return nil, err
864	}
865	return msg, nil
866}
867
868var packetTypeNames = map[byte]string{
869	msgDisconnect:          "disconnectMsg",
870	msgServiceRequest:      "serviceRequestMsg",
871	msgServiceAccept:       "serviceAcceptMsg",
872	msgExtInfo:             "extInfoMsg",
873	msgKexInit:             "kexInitMsg",
874	msgKexDHInit:           "kexDHInitMsg",
875	msgKexDHReply:          "kexDHReplyMsg",
876	msgUserAuthRequest:     "userAuthRequestMsg",
877	msgUserAuthSuccess:     "userAuthSuccessMsg",
878	msgUserAuthFailure:     "userAuthFailureMsg",
879	msgUserAuthPubKeyOk:    "userAuthPubKeyOkMsg",
880	msgGlobalRequest:       "globalRequestMsg",
881	msgRequestSuccess:      "globalRequestSuccessMsg",
882	msgRequestFailure:      "globalRequestFailureMsg",
883	msgChannelOpen:         "channelOpenMsg",
884	msgChannelData:         "channelDataMsg",
885	msgChannelOpenConfirm:  "channelOpenConfirmMsg",
886	msgChannelOpenFailure:  "channelOpenFailureMsg",
887	msgChannelWindowAdjust: "windowAdjustMsg",
888	msgChannelEOF:          "channelEOFMsg",
889	msgChannelClose:        "channelCloseMsg",
890	msgChannelRequest:      "channelRequestMsg",
891	msgChannelSuccess:      "channelRequestSuccessMsg",
892	msgChannelFailure:      "channelRequestFailureMsg",
893}