aboutsummaryrefslogtreecommitdiff
path: root/ssh
diff options
context:
space:
mode:
Diffstat (limited to 'ssh')
-rw-r--r--ssh/doc.go1
-rw-r--r--ssh/handshake.go10
-rw-r--r--ssh/messages.go14
-rw-r--r--ssh/mux.go6
4 files changed, 28 insertions, 3 deletions
diff --git a/ssh/doc.go b/ssh/doc.go
index f6bff60..edbe633 100644
--- a/ssh/doc.go
+++ b/ssh/doc.go
@@ -13,6 +13,7 @@ others.
References:
+ [PROTOCOL]: https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL?rev=HEAD
[PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD
[SSH-PARAMETERS]: http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1
diff --git a/ssh/handshake.go b/ssh/handshake.go
index b95b112..70a7369 100644
--- a/ssh/handshake.go
+++ b/ssh/handshake.go
@@ -647,16 +647,20 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
// On the server side, after the first SSH_MSG_NEWKEYS, send a SSH_MSG_EXT_INFO
// message with the server-sig-algs extension if the client supports it. See
- // RFC 8308, Sections 2.4 and 3.1.
+ // RFC 8308, Sections 2.4 and 3.1, and [PROTOCOL], Section 1.9.
if !isClient && firstKeyExchange && contains(clientInit.KexAlgos, "ext-info-c") {
extInfo := &extInfoMsg{
- NumExtensions: 1,
- Payload: make([]byte, 0, 4+15+4+len(supportedPubKeyAuthAlgosList)),
+ NumExtensions: 2,
+ Payload: make([]byte, 0, 4+15+4+len(supportedPubKeyAuthAlgosList)+4+16+4+1),
}
extInfo.Payload = appendInt(extInfo.Payload, len("server-sig-algs"))
extInfo.Payload = append(extInfo.Payload, "server-sig-algs"...)
extInfo.Payload = appendInt(extInfo.Payload, len(supportedPubKeyAuthAlgosList))
extInfo.Payload = append(extInfo.Payload, supportedPubKeyAuthAlgosList...)
+ extInfo.Payload = appendInt(extInfo.Payload, len("ping@openssh.com"))
+ extInfo.Payload = append(extInfo.Payload, "ping@openssh.com"...)
+ extInfo.Payload = appendInt(extInfo.Payload, 1)
+ extInfo.Payload = append(extInfo.Payload, "0"...)
if err := t.conn.writePacket(Marshal(extInfo)); err != nil {
return err
}
diff --git a/ssh/messages.go b/ssh/messages.go
index 922032d..b55f860 100644
--- a/ssh/messages.go
+++ b/ssh/messages.go
@@ -349,6 +349,20 @@ type userAuthGSSAPIError struct {
LanguageTag string
}
+// Transport layer OpenSSH extension. See [PROTOCOL], section 1.9
+const msgPing = 192
+
+type pingMsg struct {
+ Data string `sshtype:"192"`
+}
+
+// Transport layer OpenSSH extension. See [PROTOCOL], section 1.9
+const msgPong = 193
+
+type pongMsg struct {
+ Data string `sshtype:"193"`
+}
+
// typeTags returns the possible type bytes for the given reflect.Type, which
// should be a struct. The possible values are separated by a '|' character.
func typeTags(structType reflect.Type) (tags []byte) {
diff --git a/ssh/mux.go b/ssh/mux.go
index 9654c01..d2d24c6 100644
--- a/ssh/mux.go
+++ b/ssh/mux.go
@@ -231,6 +231,12 @@ func (m *mux) onePacket() error {
return m.handleChannelOpen(packet)
case msgGlobalRequest, msgRequestSuccess, msgRequestFailure:
return m.handleGlobalPacket(packet)
+ case msgPing:
+ var msg pingMsg
+ if err := Unmarshal(packet, &msg); err != nil {
+ return fmt.Errorf("failed to unmarshal ping@openssh.com message: %w", err)
+ }
+ return m.sendMessage(pongMsg(msg))
}
// assume a channel packet.