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