Merge pull request #290 from fluxcd/fix/hash-type
libgit2: check hostkey type when validating hostkey
This commit is contained in:
commit
d1ee61844d
|
@ -19,9 +19,12 @@ package libgit2
|
|||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"hash"
|
||||
"net"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
@ -157,7 +160,7 @@ func (s *PublicKeyAuth) Method(secret corev1.Secret) (*git.Auth, error) {
|
|||
// is an entry for the hostname _and_ port.
|
||||
host = knownhosts.Normalize(s.host)
|
||||
for _, k := range kk {
|
||||
if k.matches(host, cert.Hostkey.HashSHA1[:]) {
|
||||
if k.matches(host, cert.Hostkey) {
|
||||
return git2go.ErrOk
|
||||
}
|
||||
}
|
||||
|
@ -195,17 +198,28 @@ func parseKnownHosts(s string) ([]knownKey, error) {
|
|||
return knownHosts, nil
|
||||
}
|
||||
|
||||
func (k knownKey) matches(host string, key []byte) bool {
|
||||
func (k knownKey) matches(host string, hostkey git2go.HostkeyCertificate) bool {
|
||||
if !containsHost(k.hosts, host) {
|
||||
return false
|
||||
}
|
||||
|
||||
hash := sha1.Sum(k.key.Marshal())
|
||||
if bytes.Compare(hash[:], key) != 0 {
|
||||
var fingerprint []byte
|
||||
var hasher hash.Hash
|
||||
switch {
|
||||
case hostkey.Kind&git2go.HostkeySHA256 > 0:
|
||||
fingerprint = hostkey.HashSHA256[:]
|
||||
hasher = sha256.New()
|
||||
case hostkey.Kind&git2go.HostkeySHA1 > 0:
|
||||
fingerprint = hostkey.HashSHA1[:]
|
||||
hasher = sha1.New()
|
||||
case hostkey.Kind&git2go.HostkeyMD5 > 0:
|
||||
fingerprint = hostkey.HashMD5[:]
|
||||
hasher = md5.New()
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
hasher.Write(k.key.Marshal())
|
||||
return bytes.Compare(hasher.Sum(nil), fingerprint) == 0
|
||||
}
|
||||
|
||||
func containsHost(hosts []string, host string) bool {
|
||||
|
|
|
@ -17,9 +17,11 @@ limitations under the License.
|
|||
package libgit2
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
git2go "github.com/libgit2/git2go/v31"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
||||
"github.com/fluxcd/source-controller/pkg/git"
|
||||
|
@ -145,3 +147,60 @@ func TestPublicKeyStrategy_Method(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestKnownKeyHash(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
hostkey git2go.HostkeyCertificate
|
||||
wantMatches bool
|
||||
}{
|
||||
{"good sha256 hostkey", git2go.HostkeyCertificate{Kind: git2go.HostkeySHA256 | git2go.HostkeySHA1 | git2go.HostkeyMD5, HashSHA256: sha256Fingerprint("nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8")}, true},
|
||||
{"bad sha256 hostkey", git2go.HostkeyCertificate{Kind: git2go.HostkeySHA256 | git2go.HostkeySHA1 | git2go.HostkeyMD5, HashSHA256: sha256Fingerprint("ROQFvPThGrW4RuWLoL9tq9I9zJ42fK4XywyRtbOz/EQ")}, false},
|
||||
{"good sha1 hostkey", git2go.HostkeyCertificate{Kind: git2go.HostkeySHA1 | git2go.HostkeyMD5, HashSHA1: sha1Fingerprint("v2toJdKXfFEaR1u++4iq1UqSrHM")}, true},
|
||||
{"bad sha1 hostkey", git2go.HostkeyCertificate{Kind: git2go.HostkeySHA1 | git2go.HostkeyMD5, HashSHA1: sha1Fingerprint("tfpLlQhDDFP3yGdewTvHNxWmAdk")}, false},
|
||||
{"good md5 hostkey", git2go.HostkeyCertificate{Kind: git2go.HostkeyMD5, HashMD5: md5Fingerprint("\x16\x27\xac\xa5\x76\x28\x2d\x36\x63\x1b\x56\x4d\xeb\xdf\xa6\x48")}, true},
|
||||
{"bad md5 hostkey", git2go.HostkeyCertificate{Kind: git2go.HostkeyMD5, HashMD5: md5Fingerprint("\xb6\x03\x0e\x39\x97\x9e\xd0\xe7\x24\xce\xa3\x77\x3e\x01\x42\x09")}, false},
|
||||
{"invalid hostkey", git2go.HostkeyCertificate{}, false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
knownKeys, err := parseKnownHosts(knownHostsFixture)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
matches := knownKeys[0].matches("github.com", tt.hostkey)
|
||||
if matches != tt.wantMatches {
|
||||
t.Errorf("Method() matches = %v, wantMatches %v", matches, tt.wantMatches)
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func md5Fingerprint(in string) [16]byte {
|
||||
var out [16]byte
|
||||
copy(out[:], []byte(in))
|
||||
return out
|
||||
}
|
||||
|
||||
func sha1Fingerprint(in string) [20]byte {
|
||||
d, err := base64.RawStdEncoding.DecodeString(in)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var out [20]byte
|
||||
copy(out[:], d)
|
||||
return out
|
||||
}
|
||||
|
||||
func sha256Fingerprint(in string) [32]byte {
|
||||
d, err := base64.RawStdEncoding.DecodeString(in)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var out [32]byte
|
||||
copy(out[:], d)
|
||||
return out
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue