Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for programaitc access of ssh types #260

Merged
merged 2 commits into from
Mar 31, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions lib/ssh/cipher.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions lib/ssh/cipher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down
46 changes: 23 additions & 23 deletions lib/ssh/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,74 +119,74 @@ 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 {
kex string
hostKey string
w directionAlgorithms
r directionAlgorithms
type Algorithms struct {
Kex string
HostKey string
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,
W: alg.w,
R: alg.r,
Kex: alg.Kex,
HostKey: alg.HostKey,
W: alg.W,
R: alg.R,
}

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)
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
}
Expand Down
22 changes: 11 additions & 11 deletions lib/ssh/handshake.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -68,7 +68,7 @@ type handshakeTransport struct {
mu sync.Mutex
cond *sync.Cond
sentInitPacket []byte
sentInitMsg *kexInitMsg
sentInitMsg *KexInitMsg
writtenSinceKex uint64
writeError error

Expand Down Expand Up @@ -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
Expand All @@ -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,
Expand Down Expand Up @@ -352,7 +352,7 @@ func (t *handshakeTransport) enterKeyExchangeLocked(otherInitPacket []byte) erro
}
}

otherInit := &kexInitMsg{}
otherInit := &KexInitMsg{}
if err := Unmarshal(otherInitPacket, otherInit); err != nil {
return err
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -447,10 +447,10 @@ 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() {
if algs.HostKey == k.PublicKey().Type() {
hostKey = k
}
}
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion lib/ssh/handshake_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
6 changes: 3 additions & 3 deletions lib/ssh/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand Down
6 changes: 3 additions & 3 deletions lib/ssh/messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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:
Expand Down
10 changes: 5 additions & 5 deletions lib/ssh/messages_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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)
}
Expand Down
10 changes: 5 additions & 5 deletions lib/ssh/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,14 @@ 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 {
if ciph, err := newPacketCipher(t.reader.dir, algs.r, kexResult); err != nil {
func (t *transport) prepareKeyChange(algs *Algorithms, kexResult *kexResult) error {
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
Expand Down Expand Up @@ -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]

Expand All @@ -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 {
Expand Down