a geicko-2 based round robin ranking system designed to test c++ battleship submissions
battleship.dunkirk.sh
1// Copyright 2013 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 "errors"
9 "fmt"
10 "io"
11 "log"
12 "net"
13 "strings"
14 "sync"
15)
16
17// debugHandshake, if set, prints messages sent and received. Key
18// exchange messages are printed as if DH were used, so the debug
19// messages are wrong when using ECDH.
20const debugHandshake = false
21
22// chanSize sets the amount of buffering SSH connections. This is
23// primarily for testing: setting chanSize=0 uncovers deadlocks more
24// quickly.
25const chanSize = 16
26
27// maxPendingPackets sets the maximum number of packets to queue while waiting
28// for KEX to complete. This limits the total pending data to maxPendingPackets
29// * maxPacket bytes, which is ~16.8MB.
30const maxPendingPackets = 64
31
32// keyingTransport is a packet based transport that supports key
33// changes. It need not be thread-safe. It should pass through
34// msgNewKeys in both directions.
35type keyingTransport interface {
36 packetConn
37
38 // prepareKeyChange sets up a key change. The key change for a
39 // direction will be effected if a msgNewKeys message is sent
40 // or received.
41 prepareKeyChange(*NegotiatedAlgorithms, *kexResult) error
42
43 // setStrictMode sets the strict KEX mode, notably triggering
44 // sequence number resets on sending or receiving msgNewKeys.
45 // If the sequence number is already > 1 when setStrictMode
46 // is called, an error is returned.
47 setStrictMode() error
48
49 // setInitialKEXDone indicates to the transport that the initial key exchange
50 // was completed
51 setInitialKEXDone()
52}
53
54// handshakeTransport implements rekeying on top of a keyingTransport
55// and offers a thread-safe writePacket() interface.
56type handshakeTransport struct {
57 conn keyingTransport
58 config *Config
59
60 serverVersion []byte
61 clientVersion []byte
62
63 // hostKeys is non-empty if we are the server. In that case,
64 // it contains all host keys that can be used to sign the
65 // connection.
66 hostKeys []Signer
67
68 // publicKeyAuthAlgorithms is non-empty if we are the server. In that case,
69 // it contains the supported client public key authentication algorithms.
70 publicKeyAuthAlgorithms []string
71
72 // hostKeyAlgorithms is non-empty if we are the client. In that case,
73 // we accept these key types from the server as host key.
74 hostKeyAlgorithms []string
75
76 // On read error, incoming is closed, and readError is set.
77 incoming chan []byte
78 readError error
79
80 mu sync.Mutex
81 // Condition for the above mutex. It is used to notify a completed key
82 // exchange or a write failure. Writes can wait for this condition while a
83 // key exchange is in progress.
84 writeCond *sync.Cond
85 writeError error
86 sentInitPacket []byte
87 sentInitMsg *kexInitMsg
88 // Used to queue writes when a key exchange is in progress. The length is
89 // limited by pendingPacketsSize. Once full, writes will block until the key
90 // exchange is completed or an error occurs. If not empty, it is emptied
91 // all at once when the key exchange is completed in kexLoop.
92 pendingPackets [][]byte
93 writePacketsLeft uint32
94 writeBytesLeft int64
95 userAuthComplete bool // whether the user authentication phase is complete
96
97 // If the read loop wants to schedule a kex, it pings this
98 // channel, and the write loop will send out a kex
99 // message.
100 requestKex chan struct{}
101
102 // If the other side requests or confirms a kex, its kexInit
103 // packet is sent here for the write loop to find it.
104 startKex chan *pendingKex
105 kexLoopDone chan struct{} // closed (with writeError non-nil) when kexLoop exits
106
107 // data for host key checking
108 hostKeyCallback HostKeyCallback
109 dialAddress string
110 remoteAddr net.Addr
111
112 // bannerCallback is non-empty if we are the client and it has been set in
113 // ClientConfig. In that case it is called during the user authentication
114 // dance to handle a custom server's message.
115 bannerCallback BannerCallback
116
117 // Algorithms agreed in the last key exchange.
118 algorithms *NegotiatedAlgorithms
119
120 // Counters exclusively owned by readLoop.
121 readPacketsLeft uint32
122 readBytesLeft int64
123
124 // The session ID or nil if first kex did not complete yet.
125 sessionID []byte
126
127 // strictMode indicates if the other side of the handshake indicated
128 // that we should be following the strict KEX protocol restrictions.
129 strictMode bool
130}
131
132type pendingKex struct {
133 otherInit []byte
134 done chan error
135}
136
137func newHandshakeTransport(conn keyingTransport, config *Config, clientVersion, serverVersion []byte) *handshakeTransport {
138 t := &handshakeTransport{
139 conn: conn,
140 serverVersion: serverVersion,
141 clientVersion: clientVersion,
142 incoming: make(chan []byte, chanSize),
143 requestKex: make(chan struct{}, 1),
144 startKex: make(chan *pendingKex),
145 kexLoopDone: make(chan struct{}),
146
147 config: config,
148 }
149 t.writeCond = sync.NewCond(&t.mu)
150 t.resetReadThresholds()
151 t.resetWriteThresholds()
152
153 // We always start with a mandatory key exchange.
154 t.requestKex <- struct{}{}
155 return t
156}
157
158func newClientTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ClientConfig, dialAddr string, addr net.Addr) *handshakeTransport {
159 t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion)
160 t.dialAddress = dialAddr
161 t.remoteAddr = addr
162 t.hostKeyCallback = config.HostKeyCallback
163 t.bannerCallback = config.BannerCallback
164 if config.HostKeyAlgorithms != nil {
165 t.hostKeyAlgorithms = config.HostKeyAlgorithms
166 } else {
167 t.hostKeyAlgorithms = defaultHostKeyAlgos
168 }
169 go t.readLoop()
170 go t.kexLoop()
171 return t
172}
173
174func newServerTransport(conn keyingTransport, clientVersion, serverVersion []byte, config *ServerConfig) *handshakeTransport {
175 t := newHandshakeTransport(conn, &config.Config, clientVersion, serverVersion)
176 t.hostKeys = config.hostKeys
177 t.publicKeyAuthAlgorithms = config.PublicKeyAuthAlgorithms
178 go t.readLoop()
179 go t.kexLoop()
180 return t
181}
182
183func (t *handshakeTransport) getSessionID() []byte {
184 return t.sessionID
185}
186
187func (t *handshakeTransport) getAlgorithms() NegotiatedAlgorithms {
188 return *t.algorithms
189}
190
191// waitSession waits for the session to be established. This should be
192// the first thing to call after instantiating handshakeTransport.
193func (t *handshakeTransport) waitSession() error {
194 p, err := t.readPacket()
195 if err != nil {
196 return err
197 }
198 if p[0] != msgNewKeys {
199 return fmt.Errorf("ssh: first packet should be msgNewKeys")
200 }
201
202 return nil
203}
204
205func (t *handshakeTransport) id() string {
206 if len(t.hostKeys) > 0 {
207 return "server"
208 }
209 return "client"
210}
211
212func (t *handshakeTransport) printPacket(p []byte, write bool) {
213 action := "got"
214 if write {
215 action = "sent"
216 }
217
218 if p[0] == msgChannelData || p[0] == msgChannelExtendedData {
219 log.Printf("%s %s data (packet %d bytes)", t.id(), action, len(p))
220 } else {
221 msg, err := decode(p)
222 log.Printf("%s %s %T %v (%v)", t.id(), action, msg, msg, err)
223 }
224}
225
226func (t *handshakeTransport) readPacket() ([]byte, error) {
227 p, ok := <-t.incoming
228 if !ok {
229 return nil, t.readError
230 }
231 return p, nil
232}
233
234func (t *handshakeTransport) readLoop() {
235 first := true
236 for {
237 p, err := t.readOnePacket(first)
238 first = false
239 if err != nil {
240 t.readError = err
241 close(t.incoming)
242 break
243 }
244 // If this is the first kex, and strict KEX mode is enabled,
245 // we don't ignore any messages, as they may be used to manipulate
246 // the packet sequence numbers.
247 if !(t.sessionID == nil && t.strictMode) && (p[0] == msgIgnore || p[0] == msgDebug) {
248 continue
249 }
250 t.incoming <- p
251 }
252
253 // Stop writers too.
254 t.recordWriteError(t.readError)
255
256 // Unblock the writer should it wait for this.
257 close(t.startKex)
258
259 // Don't close t.requestKex; it's also written to from writePacket.
260}
261
262func (t *handshakeTransport) pushPacket(p []byte) error {
263 if debugHandshake {
264 t.printPacket(p, true)
265 }
266 return t.conn.writePacket(p)
267}
268
269func (t *handshakeTransport) getWriteError() error {
270 t.mu.Lock()
271 defer t.mu.Unlock()
272 return t.writeError
273}
274
275func (t *handshakeTransport) recordWriteError(err error) {
276 t.mu.Lock()
277 defer t.mu.Unlock()
278 if t.writeError == nil && err != nil {
279 t.writeError = err
280 t.writeCond.Broadcast()
281 }
282}
283
284func (t *handshakeTransport) requestKeyExchange() {
285 select {
286 case t.requestKex <- struct{}{}:
287 default:
288 // something already requested a kex, so do nothing.
289 }
290}
291
292func (t *handshakeTransport) resetWriteThresholds() {
293 t.writePacketsLeft = packetRekeyThreshold
294 if t.config.RekeyThreshold > 0 {
295 t.writeBytesLeft = int64(t.config.RekeyThreshold)
296 } else if t.algorithms != nil {
297 t.writeBytesLeft = t.algorithms.Write.rekeyBytes()
298 } else {
299 t.writeBytesLeft = 1 << 30
300 }
301}
302
303func (t *handshakeTransport) kexLoop() {
304
305write:
306 for t.getWriteError() == nil {
307 var request *pendingKex
308 var sent bool
309
310 for request == nil || !sent {
311 var ok bool
312 select {
313 case request, ok = <-t.startKex:
314 if !ok {
315 break write
316 }
317 case <-t.requestKex:
318 break
319 }
320
321 if !sent {
322 if err := t.sendKexInit(); err != nil {
323 t.recordWriteError(err)
324 break
325 }
326 sent = true
327 }
328 }
329
330 if err := t.getWriteError(); err != nil {
331 if request != nil {
332 request.done <- err
333 }
334 break
335 }
336
337 // We're not servicing t.requestKex, but that is OK:
338 // we never block on sending to t.requestKex.
339
340 // We're not servicing t.startKex, but the remote end
341 // has just sent us a kexInitMsg, so it can't send
342 // another key change request, until we close the done
343 // channel on the pendingKex request.
344
345 err := t.enterKeyExchange(request.otherInit)
346
347 t.mu.Lock()
348 t.writeError = err
349 t.sentInitPacket = nil
350 t.sentInitMsg = nil
351
352 t.resetWriteThresholds()
353
354 // we have completed the key exchange. Since the
355 // reader is still blocked, it is safe to clear out
356 // the requestKex channel. This avoids the situation
357 // where: 1) we consumed our own request for the
358 // initial kex, and 2) the kex from the remote side
359 // caused another send on the requestKex channel,
360 clear:
361 for {
362 select {
363 case <-t.requestKex:
364 //
365 default:
366 break clear
367 }
368 }
369
370 request.done <- t.writeError
371
372 // kex finished. Push packets that we received while
373 // the kex was in progress. Don't look at t.startKex
374 // and don't increment writtenSinceKex: if we trigger
375 // another kex while we are still busy with the last
376 // one, things will become very confusing.
377 for _, p := range t.pendingPackets {
378 t.writeError = t.pushPacket(p)
379 if t.writeError != nil {
380 break
381 }
382 }
383 t.pendingPackets = t.pendingPackets[:0]
384 // Unblock writePacket if waiting for KEX.
385 t.writeCond.Broadcast()
386 t.mu.Unlock()
387 }
388
389 // Unblock reader.
390 t.conn.Close()
391
392 // drain startKex channel. We don't service t.requestKex
393 // because nobody does blocking sends there.
394 for request := range t.startKex {
395 request.done <- t.getWriteError()
396 }
397
398 // Mark that the loop is done so that Close can return.
399 close(t.kexLoopDone)
400}
401
402// The protocol uses uint32 for packet counters, so we can't let them
403// reach 1<<32. We will actually read and write more packets than
404// this, though: the other side may send more packets, and after we
405// hit this limit on writing we will send a few more packets for the
406// key exchange itself.
407const packetRekeyThreshold = (1 << 31)
408
409func (t *handshakeTransport) resetReadThresholds() {
410 t.readPacketsLeft = packetRekeyThreshold
411 if t.config.RekeyThreshold > 0 {
412 t.readBytesLeft = int64(t.config.RekeyThreshold)
413 } else if t.algorithms != nil {
414 t.readBytesLeft = t.algorithms.Read.rekeyBytes()
415 } else {
416 t.readBytesLeft = 1 << 30
417 }
418}
419
420func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) {
421 p, err := t.conn.readPacket()
422 if err != nil {
423 return nil, err
424 }
425
426 if t.readPacketsLeft > 0 {
427 t.readPacketsLeft--
428 } else {
429 t.requestKeyExchange()
430 }
431
432 if t.readBytesLeft > 0 {
433 t.readBytesLeft -= int64(len(p))
434 } else {
435 t.requestKeyExchange()
436 }
437
438 if debugHandshake {
439 t.printPacket(p, false)
440 }
441
442 if first && p[0] != msgKexInit {
443 return nil, fmt.Errorf("ssh: first packet should be msgKexInit")
444 }
445
446 if p[0] != msgKexInit {
447 return p, nil
448 }
449
450 firstKex := t.sessionID == nil
451
452 kex := pendingKex{
453 done: make(chan error, 1),
454 otherInit: p,
455 }
456 t.startKex <- &kex
457 err = <-kex.done
458
459 if debugHandshake {
460 log.Printf("%s exited key exchange (first %v), err %v", t.id(), firstKex, err)
461 }
462
463 if err != nil {
464 return nil, err
465 }
466
467 t.resetReadThresholds()
468
469 // By default, a key exchange is hidden from higher layers by
470 // translating it into msgIgnore.
471 successPacket := []byte{msgIgnore}
472 if firstKex {
473 // sendKexInit() for the first kex waits for
474 // msgNewKeys so the authentication process is
475 // guaranteed to happen over an encrypted transport.
476 successPacket = []byte{msgNewKeys}
477 }
478
479 return successPacket, nil
480}
481
482const (
483 kexStrictClient = "kex-strict-c-v00@openssh.com"
484 kexStrictServer = "kex-strict-s-v00@openssh.com"
485)
486
487// sendKexInit sends a key change message.
488func (t *handshakeTransport) sendKexInit() error {
489 t.mu.Lock()
490 defer t.mu.Unlock()
491 if t.sentInitMsg != nil {
492 // kexInits may be sent either in response to the other side,
493 // or because our side wants to initiate a key change, so we
494 // may have already sent a kexInit. In that case, don't send a
495 // second kexInit.
496 return nil
497 }
498
499 msg := &kexInitMsg{
500 CiphersClientServer: t.config.Ciphers,
501 CiphersServerClient: t.config.Ciphers,
502 MACsClientServer: t.config.MACs,
503 MACsServerClient: t.config.MACs,
504 CompressionClientServer: supportedCompressions,
505 CompressionServerClient: supportedCompressions,
506 }
507 io.ReadFull(t.config.Rand, msg.Cookie[:])
508
509 // We mutate the KexAlgos slice, in order to add the kex-strict extension algorithm,
510 // and possibly to add the ext-info extension algorithm. Since the slice may be the
511 // user owned KeyExchanges, we create our own slice in order to avoid using user
512 // owned memory by mistake.
513 msg.KexAlgos = make([]string, 0, len(t.config.KeyExchanges)+2) // room for kex-strict and ext-info
514 msg.KexAlgos = append(msg.KexAlgos, t.config.KeyExchanges...)
515
516 isServer := len(t.hostKeys) > 0
517 if isServer {
518 for _, k := range t.hostKeys {
519 // If k is a MultiAlgorithmSigner, we restrict the signature
520 // algorithms. If k is a AlgorithmSigner, presume it supports all
521 // signature algorithms associated with the key format. If k is not
522 // an AlgorithmSigner, we can only assume it only supports the
523 // algorithms that matches the key format. (This means that Sign
524 // can't pick a different default).
525 keyFormat := k.PublicKey().Type()
526
527 switch s := k.(type) {
528 case MultiAlgorithmSigner:
529 for _, algo := range algorithmsForKeyFormat(keyFormat) {
530 if contains(s.Algorithms(), underlyingAlgo(algo)) {
531 msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, algo)
532 }
533 }
534 case AlgorithmSigner:
535 msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, algorithmsForKeyFormat(keyFormat)...)
536 default:
537 msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, keyFormat)
538 }
539 }
540
541 if t.sessionID == nil {
542 msg.KexAlgos = append(msg.KexAlgos, kexStrictServer)
543 }
544 } else {
545 msg.ServerHostKeyAlgos = t.hostKeyAlgorithms
546
547 // As a client we opt in to receiving SSH_MSG_EXT_INFO so we know what
548 // algorithms the server supports for public key authentication. See RFC
549 // 8308, Section 2.1.
550 //
551 // We also send the strict KEX mode extension algorithm, in order to opt
552 // into the strict KEX mode.
553 if firstKeyExchange := t.sessionID == nil; firstKeyExchange {
554 msg.KexAlgos = append(msg.KexAlgos, "ext-info-c")
555 msg.KexAlgos = append(msg.KexAlgos, kexStrictClient)
556 }
557
558 }
559
560 packet := Marshal(msg)
561
562 // writePacket destroys the contents, so save a copy.
563 packetCopy := make([]byte, len(packet))
564 copy(packetCopy, packet)
565
566 if err := t.pushPacket(packetCopy); err != nil {
567 return err
568 }
569
570 t.sentInitMsg = msg
571 t.sentInitPacket = packet
572
573 return nil
574}
575
576var errSendBannerPhase = errors.New("ssh: SendAuthBanner outside of authentication phase")
577
578func (t *handshakeTransport) writePacket(p []byte) error {
579 t.mu.Lock()
580 defer t.mu.Unlock()
581
582 switch p[0] {
583 case msgKexInit:
584 return errors.New("ssh: only handshakeTransport can send kexInit")
585 case msgNewKeys:
586 return errors.New("ssh: only handshakeTransport can send newKeys")
587 case msgUserAuthBanner:
588 if t.userAuthComplete {
589 return errSendBannerPhase
590 }
591 case msgUserAuthSuccess:
592 t.userAuthComplete = true
593 }
594
595 if t.writeError != nil {
596 return t.writeError
597 }
598
599 if t.sentInitMsg != nil {
600 if len(t.pendingPackets) < maxPendingPackets {
601 // Copy the packet so the writer can reuse the buffer.
602 cp := make([]byte, len(p))
603 copy(cp, p)
604 t.pendingPackets = append(t.pendingPackets, cp)
605 return nil
606 }
607 for t.sentInitMsg != nil {
608 // Block and wait for KEX to complete or an error.
609 t.writeCond.Wait()
610 if t.writeError != nil {
611 return t.writeError
612 }
613 }
614 }
615
616 if t.writeBytesLeft > 0 {
617 t.writeBytesLeft -= int64(len(p))
618 } else {
619 t.requestKeyExchange()
620 }
621
622 if t.writePacketsLeft > 0 {
623 t.writePacketsLeft--
624 } else {
625 t.requestKeyExchange()
626 }
627
628 if err := t.pushPacket(p); err != nil {
629 t.writeError = err
630 t.writeCond.Broadcast()
631 }
632
633 return nil
634}
635
636func (t *handshakeTransport) Close() error {
637 // Close the connection. This should cause the readLoop goroutine to wake up
638 // and close t.startKex, which will shut down kexLoop if running.
639 err := t.conn.Close()
640
641 // Wait for the kexLoop goroutine to complete.
642 // At that point we know that the readLoop goroutine is complete too,
643 // because kexLoop itself waits for readLoop to close the startKex channel.
644 <-t.kexLoopDone
645
646 return err
647}
648
649func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
650 if debugHandshake {
651 log.Printf("%s entered key exchange", t.id())
652 }
653
654 otherInit := &kexInitMsg{}
655 if err := Unmarshal(otherInitPacket, otherInit); err != nil {
656 return err
657 }
658
659 magics := handshakeMagics{
660 clientVersion: t.clientVersion,
661 serverVersion: t.serverVersion,
662 clientKexInit: otherInitPacket,
663 serverKexInit: t.sentInitPacket,
664 }
665
666 clientInit := otherInit
667 serverInit := t.sentInitMsg
668 isClient := len(t.hostKeys) == 0
669 if isClient {
670 clientInit, serverInit = serverInit, clientInit
671
672 magics.clientKexInit = t.sentInitPacket
673 magics.serverKexInit = otherInitPacket
674 }
675
676 var err error
677 t.algorithms, err = findAgreedAlgorithms(isClient, clientInit, serverInit)
678 if err != nil {
679 return err
680 }
681
682 if t.sessionID == nil && ((isClient && contains(serverInit.KexAlgos, kexStrictServer)) || (!isClient && contains(clientInit.KexAlgos, kexStrictClient))) {
683 t.strictMode = true
684 if err := t.conn.setStrictMode(); err != nil {
685 return err
686 }
687 }
688
689 // We don't send FirstKexFollows, but we handle receiving it.
690 //
691 // RFC 4253 section 7 defines the kex and the agreement method for
692 // first_kex_packet_follows. It states that the guessed packet
693 // should be ignored if the "kex algorithm and/or the host
694 // key algorithm is guessed wrong (server and client have
695 // different preferred algorithm), or if any of the other
696 // algorithms cannot be agreed upon". The other algorithms have
697 // already been checked above so the kex algorithm and host key
698 // algorithm are checked here.
699 if otherInit.FirstKexFollows && (clientInit.KexAlgos[0] != serverInit.KexAlgos[0] || clientInit.ServerHostKeyAlgos[0] != serverInit.ServerHostKeyAlgos[0]) {
700 // other side sent a kex message for the wrong algorithm,
701 // which we have to ignore.
702 if _, err := t.conn.readPacket(); err != nil {
703 return err
704 }
705 }
706
707 kex, ok := kexAlgoMap[t.algorithms.KeyExchange]
708 if !ok {
709 return fmt.Errorf("ssh: unexpected key exchange algorithm %v", t.algorithms.KeyExchange)
710 }
711
712 var result *kexResult
713 if len(t.hostKeys) > 0 {
714 result, err = t.server(kex, &magics)
715 } else {
716 result, err = t.client(kex, &magics)
717 }
718
719 if err != nil {
720 return err
721 }
722
723 firstKeyExchange := t.sessionID == nil
724 if firstKeyExchange {
725 t.sessionID = result.H
726 }
727 result.SessionID = t.sessionID
728
729 if err := t.conn.prepareKeyChange(t.algorithms, result); err != nil {
730 return err
731 }
732 if err = t.conn.writePacket([]byte{msgNewKeys}); err != nil {
733 return err
734 }
735
736 // On the server side, after the first SSH_MSG_NEWKEYS, send a SSH_MSG_EXT_INFO
737 // message with the server-sig-algs extension if the client supports it. See
738 // RFC 8308, Sections 2.4 and 3.1, and [PROTOCOL], Section 1.9.
739 if !isClient && firstKeyExchange && contains(clientInit.KexAlgos, "ext-info-c") {
740 supportedPubKeyAuthAlgosList := strings.Join(t.publicKeyAuthAlgorithms, ",")
741 extInfo := &extInfoMsg{
742 NumExtensions: 2,
743 Payload: make([]byte, 0, 4+15+4+len(supportedPubKeyAuthAlgosList)+4+16+4+1),
744 }
745 extInfo.Payload = appendInt(extInfo.Payload, len("server-sig-algs"))
746 extInfo.Payload = append(extInfo.Payload, "server-sig-algs"...)
747 extInfo.Payload = appendInt(extInfo.Payload, len(supportedPubKeyAuthAlgosList))
748 extInfo.Payload = append(extInfo.Payload, supportedPubKeyAuthAlgosList...)
749 extInfo.Payload = appendInt(extInfo.Payload, len("ping@openssh.com"))
750 extInfo.Payload = append(extInfo.Payload, "ping@openssh.com"...)
751 extInfo.Payload = appendInt(extInfo.Payload, 1)
752 extInfo.Payload = append(extInfo.Payload, "0"...)
753 if err := t.conn.writePacket(Marshal(extInfo)); err != nil {
754 return err
755 }
756 }
757
758 if packet, err := t.conn.readPacket(); err != nil {
759 return err
760 } else if packet[0] != msgNewKeys {
761 return unexpectedMessageError(msgNewKeys, packet[0])
762 }
763
764 if firstKeyExchange {
765 // Indicates to the transport that the first key exchange is completed
766 // after receiving SSH_MSG_NEWKEYS.
767 t.conn.setInitialKEXDone()
768 }
769
770 return nil
771}
772
773// algorithmSignerWrapper is an AlgorithmSigner that only supports the default
774// key format algorithm.
775//
776// This is technically a violation of the AlgorithmSigner interface, but it
777// should be unreachable given where we use this. Anyway, at least it returns an
778// error instead of panicing or producing an incorrect signature.
779type algorithmSignerWrapper struct {
780 Signer
781}
782
783func (a algorithmSignerWrapper) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {
784 if algorithm != underlyingAlgo(a.PublicKey().Type()) {
785 return nil, errors.New("ssh: internal error: algorithmSignerWrapper invoked with non-default algorithm")
786 }
787 return a.Sign(rand, data)
788}
789
790func pickHostKey(hostKeys []Signer, algo string) AlgorithmSigner {
791 for _, k := range hostKeys {
792 if s, ok := k.(MultiAlgorithmSigner); ok {
793 if !contains(s.Algorithms(), underlyingAlgo(algo)) {
794 continue
795 }
796 }
797
798 if algo == k.PublicKey().Type() {
799 return algorithmSignerWrapper{k}
800 }
801
802 k, ok := k.(AlgorithmSigner)
803 if !ok {
804 continue
805 }
806 for _, a := range algorithmsForKeyFormat(k.PublicKey().Type()) {
807 if algo == a {
808 return k
809 }
810 }
811 }
812 return nil
813}
814
815func (t *handshakeTransport) server(kex kexAlgorithm, magics *handshakeMagics) (*kexResult, error) {
816 hostKey := pickHostKey(t.hostKeys, t.algorithms.HostKey)
817 if hostKey == nil {
818 return nil, errors.New("ssh: internal error: negotiated unsupported signature type")
819 }
820
821 r, err := kex.Server(t.conn, t.config.Rand, magics, hostKey, t.algorithms.HostKey)
822 return r, err
823}
824
825func (t *handshakeTransport) client(kex kexAlgorithm, magics *handshakeMagics) (*kexResult, error) {
826 result, err := kex.Client(t.conn, t.config.Rand, magics)
827 if err != nil {
828 return nil, err
829 }
830
831 hostKey, err := ParsePublicKey(result.HostKey)
832 if err != nil {
833 return nil, err
834 }
835
836 if err := verifyHostKeySignature(hostKey, t.algorithms.HostKey, result); err != nil {
837 return nil, err
838 }
839
840 err = t.hostKeyCallback(t.dialAddress, t.remoteAddr, hostKey)
841 if err != nil {
842 return nil, err
843 }
844
845 return result, nil
846}