Check hostkey type when validating hostkey
Signed-off-by: Philip Laine <philip.laine@gmail.com>
This commit is contained in:
parent
ca2bb803ee
commit
6b3d96ef3b
|
@ -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,13 +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 hostkey.Kind {
|
||||
case git2go.HostkeyMD5:
|
||||
fingerprint = hostkey.HashMD5[:]
|
||||
hasher = md5.New()
|
||||
case git2go.HostkeySHA1:
|
||||
fingerprint = hostkey.HashSHA1[:]
|
||||
hasher = sha1.New()
|
||||
case git2go.HostkeySHA256:
|
||||
fingerprint = hostkey.HashSHA256[:]
|
||||
hasher = sha256.New()
|
||||
default:
|
||||
return false
|
||||
}
|
||||
hasher.Write(k.key.Marshal())
|
||||
if bytes.Compare(hasher.Sum(nil), fingerprint) != 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
@ -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,51 @@ 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, HashSHA256: sha256Fingerprint("nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8")}, true},
|
||||
{"bad sha256 hostkey", git2go.HostkeyCertificate{Kind: git2go.HostkeySHA256, HashSHA256: sha256Fingerprint("ROQFvPThGrW4RuWLoL9tq9I9zJ42fK4XywyRtbOz/EQ")}, false},
|
||||
{"good sha1 hostkey", git2go.HostkeyCertificate{Kind: git2go.HostkeySHA1, HashSHA1: sha1Fingerprint("v2toJdKXfFEaR1u++4iq1UqSrHM")}, true},
|
||||
{"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 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