blob: cebb5609db38711e01f8992923e126b4bb9374f5 [file] [log] [blame]
Adam Langley605e57d2011-09-17 15:57:24 -04001// 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 (
Adam Langley605e57d2011-09-17 15:57:24 -04008 "bytes"
9 "io"
Rob Pike30aa7012011-11-08 15:40:58 -080010 "math/big"
Adam Langley605e57d2011-09-17 15:57:24 -040011 "reflect"
12)
13
14// These are SSH message type numbers. They are scattered around several
15// documents but many were taken from
16// http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1
17const (
18 msgDisconnect = 1
19 msgIgnore = 2
20 msgUnimplemented = 3
21 msgDebug = 4
22 msgServiceRequest = 5
23 msgServiceAccept = 6
24
25 msgKexInit = 20
26 msgNewKeys = 21
27
28 msgKexDHInit = 30
29 msgKexDHReply = 31
30
31 msgUserAuthRequest = 50
32 msgUserAuthFailure = 51
33 msgUserAuthSuccess = 52
34 msgUserAuthBanner = 53
35 msgUserAuthPubKeyOk = 60
36
37 msgGlobalRequest = 80
38 msgRequestSuccess = 81
39 msgRequestFailure = 82
40
41 msgChannelOpen = 90
42 msgChannelOpenConfirm = 91
43 msgChannelOpenFailure = 92
44 msgChannelWindowAdjust = 93
45 msgChannelData = 94
46 msgChannelExtendedData = 95
47 msgChannelEOF = 96
48 msgChannelClose = 97
49 msgChannelRequest = 98
50 msgChannelSuccess = 99
51 msgChannelFailure = 100
52)
53
54// SSH messages:
55//
56// These structures mirror the wire format of the corresponding SSH messages.
57// They are marshaled using reflection with the marshal and unmarshal functions
58// in this file. The only wrinkle is that a final member of type []byte with a
Rob Pikef3050db2011-09-27 10:22:42 -070059// ssh tag of "rest" receives the remainder of a packet when unmarshaling.
Adam Langley605e57d2011-09-17 15:57:24 -040060
Dave Cheneyaa2a31e2011-09-26 10:25:13 -040061// See RFC 4253, section 11.1.
62type disconnectMsg struct {
63 Reason uint32
64 Message string
65 Language string
66}
67
Adam Langley605e57d2011-09-17 15:57:24 -040068// See RFC 4253, section 7.1.
69type kexInitMsg struct {
70 Cookie [16]byte
71 KexAlgos []string
72 ServerHostKeyAlgos []string
73 CiphersClientServer []string
74 CiphersServerClient []string
75 MACsClientServer []string
76 MACsServerClient []string
77 CompressionClientServer []string
78 CompressionServerClient []string
79 LanguagesClientServer []string
80 LanguagesServerClient []string
81 FirstKexFollows bool
82 Reserved uint32
83}
84
85// See RFC 4253, section 8.
86type kexDHInitMsg struct {
87 X *big.Int
88}
89
90type kexDHReplyMsg struct {
91 HostKey []byte
92 Y *big.Int
93 Signature []byte
94}
95
96// See RFC 4253, section 10.
97type serviceRequestMsg struct {
98 Service string
99}
100
101// See RFC 4253, section 10.
102type serviceAcceptMsg struct {
103 Service string
104}
105
106// See RFC 4252, section 5.
107type userAuthRequestMsg struct {
108 User string
109 Service string
110 Method string
Rob Pikef3050db2011-09-27 10:22:42 -0700111 Payload []byte `ssh:"rest"`
Adam Langley605e57d2011-09-17 15:57:24 -0400112}
113
114// See RFC 4252, section 5.1
115type userAuthFailureMsg struct {
116 Methods []string
117 PartialSuccess bool
118}
119
120// See RFC 4254, section 5.1.
121type channelOpenMsg struct {
122 ChanType string
123 PeersId uint32
124 PeersWindow uint32
125 MaxPacketSize uint32
Rob Pikef3050db2011-09-27 10:22:42 -0700126 TypeSpecificData []byte `ssh:"rest"`
Adam Langley605e57d2011-09-17 15:57:24 -0400127}
128
129// See RFC 4254, section 5.1.
130type channelOpenConfirmMsg struct {
131 PeersId uint32
132 MyId uint32
133 MyWindow uint32
134 MaxPacketSize uint32
Rob Pikef3050db2011-09-27 10:22:42 -0700135 TypeSpecificData []byte `ssh:"rest"`
Adam Langley605e57d2011-09-17 15:57:24 -0400136}
137
138// See RFC 4254, section 5.1.
139type channelOpenFailureMsg struct {
140 PeersId uint32
141 Reason uint32
142 Message string
143 Language string
144}
145
146type channelRequestMsg struct {
147 PeersId uint32
148 Request string
149 WantReply bool
Rob Pikef3050db2011-09-27 10:22:42 -0700150 RequestSpecificData []byte `ssh:"rest"`
Adam Langley605e57d2011-09-17 15:57:24 -0400151}
152
153// See RFC 4254, section 5.4.
154type channelRequestSuccessMsg struct {
155 PeersId uint32
156}
157
158// See RFC 4254, section 5.4.
159type channelRequestFailureMsg struct {
160 PeersId uint32
161}
162
163// See RFC 4254, section 5.3
164type channelCloseMsg struct {
165 PeersId uint32
166}
167
168// See RFC 4254, section 5.3
169type channelEOFMsg struct {
170 PeersId uint32
171}
172
173// See RFC 4254, section 4
174type globalRequestMsg struct {
175 Type string
176 WantReply bool
177}
178
179// See RFC 4254, section 5.2
180type windowAdjustMsg struct {
181 PeersId uint32
182 AdditionalBytes uint32
183}
184
185// See RFC 4252, section 7
186type userAuthPubKeyOkMsg struct {
187 Algo string
188 PubKey string
189}
190
191// unmarshal parses the SSH wire data in packet into out using reflection.
192// expectedType is the expected SSH message type. It either returns nil on
193// success, or a ParseError or UnexpectedMessageError on error.
Russ Coxc2049d22011-11-01 22:04:37 -0400194func unmarshal(out interface{}, packet []byte, expectedType uint8) error {
Adam Langley605e57d2011-09-17 15:57:24 -0400195 if len(packet) == 0 {
196 return ParseError{expectedType}
197 }
198 if packet[0] != expectedType {
199 return UnexpectedMessageError{expectedType, packet[0]}
200 }
201 packet = packet[1:]
202
203 v := reflect.ValueOf(out).Elem()
204 structType := v.Type()
205 var ok bool
206 for i := 0; i < v.NumField(); i++ {
207 field := v.Field(i)
208 t := field.Type()
209 switch t.Kind() {
210 case reflect.Bool:
211 if len(packet) < 1 {
212 return ParseError{expectedType}
213 }
214 field.SetBool(packet[0] != 0)
215 packet = packet[1:]
216 case reflect.Array:
217 if t.Elem().Kind() != reflect.Uint8 {
218 panic("array of non-uint8")
219 }
220 if len(packet) < t.Len() {
221 return ParseError{expectedType}
222 }
223 for j := 0; j < t.Len(); j++ {
224 field.Index(j).Set(reflect.ValueOf(packet[j]))
225 }
226 packet = packet[t.Len():]
227 case reflect.Uint32:
228 var u32 uint32
229 if u32, packet, ok = parseUint32(packet); !ok {
230 return ParseError{expectedType}
231 }
232 field.SetUint(uint64(u32))
233 case reflect.String:
234 var s []byte
235 if s, packet, ok = parseString(packet); !ok {
236 return ParseError{expectedType}
237 }
238 field.SetString(string(s))
239 case reflect.Slice:
240 switch t.Elem().Kind() {
241 case reflect.Uint8:
Rob Pikef3050db2011-09-27 10:22:42 -0700242 if structType.Field(i).Tag.Get("ssh") == "rest" {
Adam Langley605e57d2011-09-17 15:57:24 -0400243 field.Set(reflect.ValueOf(packet))
244 packet = nil
245 } else {
246 var s []byte
247 if s, packet, ok = parseString(packet); !ok {
248 return ParseError{expectedType}
249 }
250 field.Set(reflect.ValueOf(s))
251 }
252 case reflect.String:
253 var nl []string
254 if nl, packet, ok = parseNameList(packet); !ok {
255 return ParseError{expectedType}
256 }
257 field.Set(reflect.ValueOf(nl))
258 default:
259 panic("slice of unknown type")
260 }
261 case reflect.Ptr:
262 if t == bigIntType {
263 var n *big.Int
264 if n, packet, ok = parseInt(packet); !ok {
265 return ParseError{expectedType}
266 }
267 field.Set(reflect.ValueOf(n))
268 } else {
269 panic("pointer to unknown type")
270 }
271 default:
272 panic("unknown type")
273 }
274 }
275
276 if len(packet) != 0 {
277 return ParseError{expectedType}
278 }
279
280 return nil
281}
282
283// marshal serializes the message in msg, using the given message type.
284func marshal(msgType uint8, msg interface{}) []byte {
285 var out []byte
286 out = append(out, msgType)
287
288 v := reflect.ValueOf(msg)
289 structType := v.Type()
290 for i := 0; i < v.NumField(); i++ {
291 field := v.Field(i)
292 t := field.Type()
293 switch t.Kind() {
294 case reflect.Bool:
295 var v uint8
296 if field.Bool() {
297 v = 1
298 }
299 out = append(out, v)
300 case reflect.Array:
301 if t.Elem().Kind() != reflect.Uint8 {
302 panic("array of non-uint8")
303 }
304 for j := 0; j < t.Len(); j++ {
305 out = append(out, byte(field.Index(j).Uint()))
306 }
307 case reflect.Uint32:
308 u32 := uint32(field.Uint())
309 out = append(out, byte(u32>>24))
310 out = append(out, byte(u32>>16))
311 out = append(out, byte(u32>>8))
312 out = append(out, byte(u32))
313 case reflect.String:
314 s := field.String()
315 out = append(out, byte(len(s)>>24))
316 out = append(out, byte(len(s)>>16))
317 out = append(out, byte(len(s)>>8))
318 out = append(out, byte(len(s)))
Christopher Wedgwood707e5ac2011-10-12 13:42:04 -0700319 out = append(out, s...)
Adam Langley605e57d2011-09-17 15:57:24 -0400320 case reflect.Slice:
321 switch t.Elem().Kind() {
322 case reflect.Uint8:
323 length := field.Len()
Rob Pikef3050db2011-09-27 10:22:42 -0700324 if structType.Field(i).Tag.Get("ssh") != "rest" {
Adam Langley605e57d2011-09-17 15:57:24 -0400325 out = append(out, byte(length>>24))
326 out = append(out, byte(length>>16))
327 out = append(out, byte(length>>8))
328 out = append(out, byte(length))
329 }
330 for j := 0; j < length; j++ {
331 out = append(out, byte(field.Index(j).Uint()))
332 }
333 case reflect.String:
334 var length int
335 for j := 0; j < field.Len(); j++ {
336 if j != 0 {
337 length++ /* comma */
338 }
339 length += len(field.Index(j).String())
340 }
341
342 out = append(out, byte(length>>24))
343 out = append(out, byte(length>>16))
344 out = append(out, byte(length>>8))
345 out = append(out, byte(length))
346 for j := 0; j < field.Len(); j++ {
347 if j != 0 {
348 out = append(out, ',')
349 }
Christopher Wedgwood707e5ac2011-10-12 13:42:04 -0700350 out = append(out, field.Index(j).String()...)
Adam Langley605e57d2011-09-17 15:57:24 -0400351 }
352 default:
353 panic("slice of unknown type")
354 }
355 case reflect.Ptr:
356 if t == bigIntType {
357 var n *big.Int
358 nValue := reflect.ValueOf(&n)
359 nValue.Elem().Set(field)
360 needed := intLength(n)
361 oldLength := len(out)
362
363 if cap(out)-len(out) < needed {
364 newOut := make([]byte, len(out), 2*(len(out)+needed))
365 copy(newOut, out)
366 out = newOut
367 }
368 out = out[:oldLength+needed]
369 marshalInt(out[oldLength:], n)
370 } else {
371 panic("pointer to unknown type")
372 }
373 }
374 }
375
376 return out
377}
378
379var bigOne = big.NewInt(1)
380
381func parseString(in []byte) (out, rest []byte, ok bool) {
382 if len(in) < 4 {
383 return
384 }
385 length := uint32(in[0])<<24 | uint32(in[1])<<16 | uint32(in[2])<<8 | uint32(in[3])
386 if uint32(len(in)) < 4+length {
387 return
388 }
389 out = in[4 : 4+length]
390 rest = in[4+length:]
391 ok = true
392 return
393}
394
Dave Cheney00f9b762011-11-16 10:19:56 -0500395var (
396 comma = []byte{','}
397 emptyNameList = []string{}
398)
Adam Langley605e57d2011-09-17 15:57:24 -0400399
400func parseNameList(in []byte) (out []string, rest []byte, ok bool) {
401 contents, rest, ok := parseString(in)
402 if !ok {
403 return
404 }
405 if len(contents) == 0 {
Dave Cheney00f9b762011-11-16 10:19:56 -0500406 out = emptyNameList
Adam Langley605e57d2011-09-17 15:57:24 -0400407 return
408 }
409 parts := bytes.Split(contents, comma)
410 out = make([]string, len(parts))
411 for i, part := range parts {
412 out[i] = string(part)
413 }
414 return
415}
416
417func parseInt(in []byte) (out *big.Int, rest []byte, ok bool) {
418 contents, rest, ok := parseString(in)
419 if !ok {
420 return
421 }
422 out = new(big.Int)
423
424 if len(contents) > 0 && contents[0]&0x80 == 0x80 {
425 // This is a negative number
426 notBytes := make([]byte, len(contents))
427 for i := range notBytes {
428 notBytes[i] = ^contents[i]
429 }
430 out.SetBytes(notBytes)
431 out.Add(out, bigOne)
432 out.Neg(out)
433 } else {
434 // Positive number
435 out.SetBytes(contents)
436 }
437 ok = true
438 return
439}
440
441func parseUint32(in []byte) (out uint32, rest []byte, ok bool) {
442 if len(in) < 4 {
443 return
444 }
445 out = uint32(in[0])<<24 | uint32(in[1])<<16 | uint32(in[2])<<8 | uint32(in[3])
446 rest = in[4:]
447 ok = true
448 return
449}
450
Adam Langley605e57d2011-09-17 15:57:24 -0400451func nameListLength(namelist []string) int {
452 length := 4 /* uint32 length prefix */
453 for i, name := range namelist {
454 if i != 0 {
455 length++ /* comma */
456 }
457 length += len(name)
458 }
459 return length
460}
461
462func intLength(n *big.Int) int {
463 length := 4 /* length bytes */
464 if n.Sign() < 0 {
465 nMinus1 := new(big.Int).Neg(n)
466 nMinus1.Sub(nMinus1, bigOne)
467 bitLen := nMinus1.BitLen()
468 if bitLen%8 == 0 {
469 // The number will need 0xff padding
470 length++
471 }
472 length += (bitLen + 7) / 8
473 } else if n.Sign() == 0 {
474 // A zero is the zero length string
475 } else {
476 bitLen := n.BitLen()
477 if bitLen%8 == 0 {
478 // The number will need 0x00 padding
479 length++
480 }
481 length += (bitLen + 7) / 8
482 }
483
484 return length
485}
486
487func marshalInt(to []byte, n *big.Int) []byte {
488 lengthBytes := to
489 to = to[4:]
490 length := 0
491
492 if n.Sign() < 0 {
493 // A negative number has to be converted to two's-complement
494 // form. So we'll subtract 1 and invert. If the
495 // most-significant-bit isn't set then we'll need to pad the
496 // beginning with 0xff in order to keep the number negative.
497 nMinus1 := new(big.Int).Neg(n)
498 nMinus1.Sub(nMinus1, bigOne)
499 bytes := nMinus1.Bytes()
500 for i := range bytes {
501 bytes[i] ^= 0xff
502 }
503 if len(bytes) == 0 || bytes[0]&0x80 == 0 {
504 to[0] = 0xff
505 to = to[1:]
506 length++
507 }
508 nBytes := copy(to, bytes)
509 to = to[nBytes:]
510 length += nBytes
511 } else if n.Sign() == 0 {
512 // A zero is the zero length string
513 } else {
514 bytes := n.Bytes()
515 if len(bytes) > 0 && bytes[0]&0x80 != 0 {
516 // We'll have to pad this with a 0x00 in order to
517 // stop it looking like a negative number.
518 to[0] = 0
519 to = to[1:]
520 length++
521 }
522 nBytes := copy(to, bytes)
523 to = to[nBytes:]
524 length += nBytes
525 }
526
527 lengthBytes[0] = byte(length >> 24)
528 lengthBytes[1] = byte(length >> 16)
529 lengthBytes[2] = byte(length >> 8)
530 lengthBytes[3] = byte(length)
531 return to
532}
533
534func writeInt(w io.Writer, n *big.Int) {
535 length := intLength(n)
536 buf := make([]byte, length)
537 marshalInt(buf, n)
538 w.Write(buf)
539}
540
541func writeString(w io.Writer, s []byte) {
542 var lengthBytes [4]byte
543 lengthBytes[0] = byte(len(s) >> 24)
544 lengthBytes[1] = byte(len(s) >> 16)
545 lengthBytes[2] = byte(len(s) >> 8)
546 lengthBytes[3] = byte(len(s))
547 w.Write(lengthBytes[:])
548 w.Write(s)
549}
550
551func stringLength(s []byte) int {
552 return 4 + len(s)
553}
554
555func marshalString(to []byte, s []byte) []byte {
556 to[0] = byte(len(s) >> 24)
557 to[1] = byte(len(s) >> 16)
558 to[2] = byte(len(s) >> 8)
559 to[3] = byte(len(s))
560 to = to[4:]
561 copy(to, s)
562 return to[len(s):]
563}
564
565var bigIntType = reflect.TypeOf((*big.Int)(nil))
Dave Cheneyaa2a31e2011-09-26 10:25:13 -0400566
567// Decode a packet into it's corresponding message.
568func decode(packet []byte) interface{} {
569 var msg interface{}
570 switch packet[0] {
571 case msgDisconnect:
572 msg = new(disconnectMsg)
573 case msgServiceRequest:
574 msg = new(serviceRequestMsg)
575 case msgServiceAccept:
576 msg = new(serviceAcceptMsg)
577 case msgKexInit:
578 msg = new(kexInitMsg)
579 case msgKexDHInit:
580 msg = new(kexDHInitMsg)
581 case msgKexDHReply:
582 msg = new(kexDHReplyMsg)
583 case msgUserAuthRequest:
584 msg = new(userAuthRequestMsg)
585 case msgUserAuthFailure:
586 msg = new(userAuthFailureMsg)
587 case msgUserAuthPubKeyOk:
588 msg = new(userAuthPubKeyOkMsg)
589 case msgGlobalRequest:
590 msg = new(globalRequestMsg)
591 case msgRequestSuccess:
592 msg = new(channelRequestSuccessMsg)
593 case msgRequestFailure:
594 msg = new(channelRequestFailureMsg)
595 case msgChannelOpen:
596 msg = new(channelOpenMsg)
597 case msgChannelOpenConfirm:
598 msg = new(channelOpenConfirmMsg)
599 case msgChannelOpenFailure:
600 msg = new(channelOpenFailureMsg)
601 case msgChannelWindowAdjust:
602 msg = new(windowAdjustMsg)
Dave Cheneyaa2a31e2011-09-26 10:25:13 -0400603 case msgChannelEOF:
604 msg = new(channelEOFMsg)
605 case msgChannelClose:
606 msg = new(channelCloseMsg)
607 case msgChannelRequest:
608 msg = new(channelRequestMsg)
609 case msgChannelSuccess:
610 msg = new(channelRequestSuccessMsg)
611 case msgChannelFailure:
612 msg = new(channelRequestFailureMsg)
613 default:
614 return UnexpectedMessageError{0, packet[0]}
615 }
616 if err := unmarshal(msg, packet, packet[0]); err != nil {
617 return err
618 }
619 return msg
620}