Skip to content

Commit

Permalink
Allow for programaitc access of ssh result types (zmap#260)
Browse files Browse the repository at this point in the history
  • Loading branch information
Benjamin Wireman authored Mar 31, 2020
1 parent 145470a commit d2e5038
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 56 deletions.
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

0 comments on commit d2e5038

Please sign in to comment.