From 3f41c8c41063118c49610973c3ff80d307cb1827 Mon Sep 17 00:00:00 2001 From: bwireman Date: Tue, 31 Mar 2020 14:18:35 -0400 Subject: [PATCH 1/2] Allow for programaitc access of ssh types: Algorithms, DirectionAlgorithms, KexInitMsg --- lib/ssh/cipher.go | 6 +++--- lib/ssh/cipher_test.go | 4 ++-- lib/ssh/common.go | 18 +++++++++--------- lib/ssh/handshake.go | 14 +++++++------- lib/ssh/handshake_test.go | 2 +- lib/ssh/log.go | 6 +++--- lib/ssh/messages.go | 6 +++--- lib/ssh/messages_test.go | 10 +++++----- lib/ssh/transport.go | 6 +++--- 9 files changed, 36 insertions(+), 36 deletions(-) diff --git a/lib/ssh/cipher.go b/lib/ssh/cipher.go index 34d3917c..b77c1061 100644 --- a/lib/ssh/cipher.go +++ b/lib/ssh/cipher.go @@ -372,7 +372,7 @@ type cbcCipher struct { oracleCamouflage uint32 } -func newCBCCipher(c cipher.Block, iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) { +func newCBCCipher(c cipher.Block, iv, key, macKey []byte, algs DirectionAlgorithms) (packetCipher, error) { cbc := &cbcCipher{ mac: macModes[algs.MAC].new(macKey), decrypter: cipher.NewCBCDecrypter(c, iv), @@ -386,7 +386,7 @@ func newCBCCipher(c cipher.Block, iv, key, macKey []byte, algs directionAlgorith return cbc, nil } -func newAESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) { +func newAESCBCCipher(iv, key, macKey []byte, algs DirectionAlgorithms) (packetCipher, error) { c, err := aes.NewCipher(key) if err != nil { return nil, err @@ -400,7 +400,7 @@ func newAESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCi return cbc, nil } -func newTripleDESCBCCipher(iv, key, macKey []byte, algs directionAlgorithms) (packetCipher, error) { +func newTripleDESCBCCipher(iv, key, macKey []byte, algs DirectionAlgorithms) (packetCipher, error) { c, err := des.NewTripleDESCipher(key) if err != nil { return nil, err diff --git a/lib/ssh/cipher_test.go b/lib/ssh/cipher_test.go index e4bb1d92..2f4bd8a9 100644 --- a/lib/ssh/cipher_test.go +++ b/lib/ssh/cipher_test.go @@ -27,7 +27,7 @@ func TestPacketCiphers(t *testing.T) { for cipher := range cipherModes { kr := &kexResult{Hash: crypto.SHA1} - algs := directionAlgorithms{ + algs := DirectionAlgorithms{ Cipher: cipher, MAC: "hmac-sha1", Compression: "none", @@ -68,7 +68,7 @@ func TestCBCOracleCounterMeasure(t *testing.T) { defer delete(cipherModes, aes128cbcID) kr := &kexResult{Hash: crypto.SHA1} - algs := directionAlgorithms{ + algs := DirectionAlgorithms{ Cipher: aes128cbcID, MAC: "hmac-sha1", Compression: "none", diff --git a/lib/ssh/common.go b/lib/ssh/common.go index 5c232803..5219cd41 100644 --- a/lib/ssh/common.go +++ b/lib/ssh/common.go @@ -119,25 +119,25 @@ func findCommon(what string, client []string, server []string) (common string, e return "", fmt.Errorf("ssh: no common algorithm for %s; client offered: %v, server offered: %v", what, client, server) } -type directionAlgorithms struct { +type DirectionAlgorithms struct { Cipher string `json:"cipher"` MAC string `json:"mac"` Compression string `json:"compression"` } -type algorithms struct { +type Algorithms struct { kex string hostKey string - w directionAlgorithms - r directionAlgorithms + w DirectionAlgorithms + r DirectionAlgorithms } -func (alg *algorithms) MarshalJSON() ([]byte, error) { +func (alg *Algorithms) MarshalJSON() ([]byte, error) { aux := struct { Kex string `json:"dh_kex_algorithm"` HostKey string `json:"host_key_algorithm"` - W directionAlgorithms `json:"client_to_server_alg_group"` - R directionAlgorithms `json:"server_to_client_alg_group"` + W DirectionAlgorithms `json:"client_to_server_alg_group"` + R DirectionAlgorithms `json:"server_to_client_alg_group"` }{ Kex: alg.kex, HostKey: alg.hostKey, @@ -148,8 +148,8 @@ func (alg *algorithms) MarshalJSON() ([]byte, error) { return json.Marshal(aux) } -func findAgreedAlgorithms(clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms, err error) { - result := &algorithms{} +func findAgreedAlgorithms(clientKexInit, serverKexInit *KexInitMsg) (algs *Algorithms, err error) { + result := &Algorithms{} result.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos) if err != nil { diff --git a/lib/ssh/handshake.go b/lib/ssh/handshake.go index d66526bd..af17c410 100644 --- a/lib/ssh/handshake.go +++ b/lib/ssh/handshake.go @@ -28,7 +28,7 @@ type keyingTransport interface { // prepareKeyChange sets up a key change. The key change for a // direction will be effected if a msgNewKeys message is sent // or received. - prepareKeyChange(*algorithms, *kexResult) error + prepareKeyChange(*Algorithms, *kexResult) error } // handshakeTransport implements rekeying on top of a keyingTransport @@ -68,7 +68,7 @@ type handshakeTransport struct { mu sync.Mutex cond *sync.Cond sentInitPacket []byte - sentInitMsg *kexInitMsg + sentInitMsg *KexInitMsg writtenSinceKex uint64 writeError error @@ -264,7 +264,7 @@ func (t *handshakeTransport) requestKeyChange() error { // sendKexInitLocked sends a key change message. t.mu must be locked // while this happens. -func (t *handshakeTransport) sendKexInitLocked(isFirst keyChangeCategory) (*kexInitMsg, []byte, error) { +func (t *handshakeTransport) sendKexInitLocked(isFirst keyChangeCategory) (*KexInitMsg, []byte, error) { // kexInits may be sent either in response to the other side, // or because our side wants to initiate a key change, so we // may have already sent a kexInit. In that case, don't send a @@ -273,7 +273,7 @@ func (t *handshakeTransport) sendKexInitLocked(isFirst keyChangeCategory) (*kexI return t.sentInitMsg, t.sentInitPacket, nil } - msg := &kexInitMsg{ + msg := &KexInitMsg{ KexAlgos: t.config.KeyExchanges, CiphersClientServer: t.config.Ciphers, CiphersServerClient: t.config.Ciphers, @@ -352,7 +352,7 @@ func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) erro } } - otherInit := &kexInitMsg{} + otherInit := &KexInitMsg{} if err := Unmarshal(otherInitPacket, otherInit); err != nil { return err } @@ -447,7 +447,7 @@ func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) erro return nil } -func (t *handshakeTransport) server(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) { +func (t *handshakeTransport) server(kex kexAlgorithm, algs *Algorithms, magics *handshakeMagics) (*kexResult, error) { var hostKey Signer for _, k := range t.hostKeys { if algs.hostKey == k.PublicKey().Type() { @@ -459,7 +459,7 @@ func (t *handshakeTransport) server(kex kexAlgorithm, algs *algorithms, magics * return r, err } -func (t *handshakeTransport) client(kex kexAlgorithm, algs *algorithms, magics *handshakeMagics) (*kexResult, error) { +func (t *handshakeTransport) client(kex kexAlgorithm, algs *Algorithms, magics *handshakeMagics) (*kexResult, error) { result, err := kex.Client(t.conn, t.config.Rand, magics, t.config) if err != nil { return nil, err diff --git a/lib/ssh/handshake_test.go b/lib/ssh/handshake_test.go index da53d3a0..16c3779e 100644 --- a/lib/ssh/handshake_test.go +++ b/lib/ssh/handshake_test.go @@ -354,7 +354,7 @@ type errorKeyingTransport struct { readLeft, writeLeft int } -func (n *errorKeyingTransport) prepareKeyChange(*algorithms, *kexResult) error { +func (n *errorKeyingTransport) prepareKeyChange(*Algorithms, *kexResult) error { return nil } func (n *errorKeyingTransport) getSessionID() []byte { diff --git a/lib/ssh/log.go b/lib/ssh/log.go index 58209b38..a8981867 100644 --- a/lib/ssh/log.go +++ b/lib/ssh/log.go @@ -20,9 +20,9 @@ type HandshakeLog struct { Banner string `json:"banner,omitempty"` ServerID *EndpointId `json:"server_id,omitempty"` ClientID *EndpointId `json:"client_id,omitempty"` - ServerKex *kexInitMsg `json:"server_key_exchange,omitempty"` - ClientKex *kexInitMsg `json:"client_key_exchange,omitempty"` - AlgorithmSelection *algorithms `json:"algorithm_selection,omitempty"` + ServerKex *KexInitMsg `json:"server_key_exchange,omitempty"` + ClientKex *KexInitMsg `json:"client_key_exchange,omitempty"` + AlgorithmSelection *Algorithms `json:"algorithm_selection,omitempty"` DHKeyExchange kexAlgorithm `json:"key_exchange,omitempty"` UserAuth []string `json:"userauth,omitempty"` Crypto *kexResult `json:"crypto,omitempty"` diff --git a/lib/ssh/messages.go b/lib/ssh/messages.go index d46efec9..a3267448 100644 --- a/lib/ssh/messages.go +++ b/lib/ssh/messages.go @@ -54,7 +54,7 @@ func (d *disconnectMsg) Error() string { // See RFC 4253, section 7.1. const msgKexInit = 20 -type kexInitMsg struct { +type KexInitMsg struct { Cookie [16]byte `sshtype:"20"` KexAlgos []string ServerHostKeyAlgos []string @@ -86,7 +86,7 @@ type JsonKexInitMsg struct { Reserved uint32 `json:"reserved"` } -func (kex *kexInitMsg) MarshalJSON() ([]byte, error) { +func (kex *KexInitMsg) MarshalJSON() ([]byte, error) { temp := JsonKexInitMsg{ Cookie: kex.Cookie[:], KexAlgos: kex.KexAlgos, @@ -753,7 +753,7 @@ func decode(packet []byte) (interface{}, error) { case msgServiceAccept: msg = new(serviceAcceptMsg) case msgKexInit: - msg = new(kexInitMsg) + msg = new(KexInitMsg) case msgKexDHInit: msg = new(kexDHInitMsg) case msgKexDHReply: diff --git a/lib/ssh/messages_test.go b/lib/ssh/messages_test.go index e7907641..ae7a7347 100644 --- a/lib/ssh/messages_test.go +++ b/lib/ssh/messages_test.go @@ -166,7 +166,7 @@ func TestUnmarshalShortKexInitPacket(t *testing.T) { // This used to panic. // Issue 11348 packet := []byte{0x14, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xff, 0xff, 0xff, 0xff} - kim := &kexInitMsg{} + kim := &KexInitMsg{} if err := Unmarshal(packet, kim); err == nil { t.Error("truncated packet unmarshaled without error") } @@ -228,8 +228,8 @@ func randomInt(rand *rand.Rand) *big.Int { return new(big.Int).SetInt64(int64(int32(rand.Uint32()))) } -func (*kexInitMsg) Generate(rand *rand.Rand, size int) reflect.Value { - ki := &kexInitMsg{} +func (*KexInitMsg) Generate(rand *rand.Rand, size int) reflect.Value { + ki := &KexInitMsg{} randomBytes(ki.Cookie[:], rand) ki.KexAlgos = randomNameList(rand) ki.ServerHostKeyAlgos = randomNameList(rand) @@ -254,7 +254,7 @@ func (*kexDHInitMsg) Generate(rand *rand.Rand, size int) reflect.Value { } var ( - _kexInitMsg = new(kexInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface() + _kexInitMsg = new(KexInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface() _kexDHInitMsg = new(kexDHInitMsg).Generate(rand.New(rand.NewSource(0)), 10).Elem().Interface() _kexInit = Marshal(_kexInitMsg) @@ -268,7 +268,7 @@ func BenchmarkMarshalKexInitMsg(b *testing.B) { } func BenchmarkUnmarshalKexInitMsg(b *testing.B) { - m := new(kexInitMsg) + m := new(KexInitMsg) for i := 0; i < b.N; i++ { Unmarshal(_kexInit, m) } diff --git a/lib/ssh/transport.go b/lib/ssh/transport.go index 62fba629..04663105 100644 --- a/lib/ssh/transport.go +++ b/lib/ssh/transport.go @@ -68,7 +68,7 @@ type connectionState struct { // prepareKeyChange sets up key material for a keychange. The key changes in // both directions are triggered by reading and writing a msgNewKey packet // respectively. -func (t *transport) prepareKeyChange(algs *algorithms, kexResult *kexResult) error { +func (t *transport) prepareKeyChange(algs *Algorithms, kexResult *kexResult) error { if ciph, err := newPacketCipher(t.reader.dir, algs.r, kexResult); err != nil { return err } else { @@ -192,7 +192,7 @@ var ( ) // generateKeys generates key material for IV, MAC and encryption. -func generateKeys(d direction, algs directionAlgorithms, kex *kexResult) (iv, key, macKey []byte) { +func generateKeys(d direction, algs DirectionAlgorithms, kex *kexResult) (iv, key, macKey []byte) { cipherMode := cipherModes[algs.Cipher] macMode := macModes[algs.MAC] @@ -209,7 +209,7 @@ func generateKeys(d direction, algs directionAlgorithms, kex *kexResult) (iv, ke // setupKeys sets the cipher and MAC keys from kex.K, kex.H and sessionId, as // described in RFC 4253, section 6.4. direction should either be serverKeys // (to setup server->client keys) or clientKeys (for client->server keys). -func newPacketCipher(d direction, algs directionAlgorithms, kex *kexResult) (packetCipher, error) { +func newPacketCipher(d direction, algs DirectionAlgorithms, kex *kexResult) (packetCipher, error) { iv, key, macKey := generateKeys(d, algs, kex) if algs.Cipher == gcmCipherID { From ba247b5b5cf81bec23c4758fec6b56a62c17b938 Mon Sep 17 00:00:00 2001 From: bwireman Date: Tue, 31 Mar 2020 14:28:25 -0400 Subject: [PATCH 2/2] export inner members of Algorithms --- lib/ssh/common.go | 32 ++++++++++++++++---------------- lib/ssh/handshake.go | 8 ++++---- lib/ssh/transport.go | 4 ++-- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/lib/ssh/common.go b/lib/ssh/common.go index 5219cd41..1077fd84 100644 --- a/lib/ssh/common.go +++ b/lib/ssh/common.go @@ -126,10 +126,10 @@ type DirectionAlgorithms struct { } type Algorithms struct { - kex string - hostKey string - w DirectionAlgorithms - r DirectionAlgorithms + Kex string + HostKey string + W DirectionAlgorithms + R DirectionAlgorithms } func (alg *Algorithms) MarshalJSON() ([]byte, error) { @@ -139,10 +139,10 @@ func (alg *Algorithms) MarshalJSON() ([]byte, error) { W DirectionAlgorithms `json:"client_to_server_alg_group"` R DirectionAlgorithms `json:"server_to_client_alg_group"` }{ - Kex: alg.kex, - HostKey: alg.hostKey, - W: alg.w, - R: alg.r, + Kex: alg.Kex, + HostKey: alg.HostKey, + W: alg.W, + R: alg.R, } return json.Marshal(aux) @@ -151,42 +151,42 @@ func (alg *Algorithms) MarshalJSON() ([]byte, error) { func findAgreedAlgorithms(clientKexInit, serverKexInit *KexInitMsg) (algs *Algorithms, err error) { result := &Algorithms{} - result.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos) + result.Kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos) if err != nil { return } - result.hostKey, err = findCommon("host key", clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos) + result.HostKey, err = findCommon("host key", clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos) if err != nil { return } - result.w.Cipher, err = findCommon("client to server cipher", clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer) + result.W.Cipher, err = findCommon("client to server cipher", clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer) if err != nil { return } - result.r.Cipher, err = findCommon("server to client cipher", clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient) + result.R.Cipher, err = findCommon("server to client cipher", clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient) if err != nil { return } - result.w.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer) + result.W.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer) if err != nil { return } - result.r.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient) + result.R.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient) if err != nil { return } - result.w.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer) + result.W.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer) if err != nil { return } - result.r.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient) + result.R.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient) if err != nil { return } diff --git a/lib/ssh/handshake.go b/lib/ssh/handshake.go index af17c410..fa8e2299 100644 --- a/lib/ssh/handshake.go +++ b/lib/ssh/handshake.go @@ -403,12 +403,12 @@ func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) erro } } - kex, ok := kexAlgoMap[algs.kex] + kex, ok := kexAlgoMap[algs.Kex] if !ok { - return fmt.Errorf("ssh: unexpected key exchange algorithm %v", algs.kex) + return fmt.Errorf("ssh: unexpected key exchange algorithm %v", algs.Kex) } - kex = kex.GetNew(algs.kex) + kex = kex.GetNew(algs.Kex) if t.config.ConnLog != nil { t.config.ConnLog.DHKeyExchange = kex @@ -450,7 +450,7 @@ func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) erro func (t *handshakeTransport) server(kex kexAlgorithm, algs *Algorithms, magics *handshakeMagics) (*kexResult, error) { var hostKey Signer for _, k := range t.hostKeys { - if algs.hostKey == k.PublicKey().Type() { + if algs.HostKey == k.PublicKey().Type() { hostKey = k } } diff --git a/lib/ssh/transport.go b/lib/ssh/transport.go index 04663105..2683ad99 100644 --- a/lib/ssh/transport.go +++ b/lib/ssh/transport.go @@ -69,13 +69,13 @@ type connectionState struct { // both directions are triggered by reading and writing a msgNewKey packet // respectively. func (t *transport) prepareKeyChange(algs *Algorithms, kexResult *kexResult) error { - if ciph, err := newPacketCipher(t.reader.dir, algs.r, kexResult); err != nil { + if ciph, err := newPacketCipher(t.reader.dir, algs.R, kexResult); err != nil { return err } else { t.reader.pendingKeyChange <- ciph } - if ciph, err := newPacketCipher(t.writer.dir, algs.w, kexResult); err != nil { + if ciph, err := newPacketCipher(t.writer.dir, algs.W, kexResult); err != nil { return err } else { t.writer.pendingKeyChange <- ciph