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 (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/md5"
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
|
"crypto/sha256"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"hash"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -157,7 +160,7 @@ func (s *PublicKeyAuth) Method(secret corev1.Secret) (*git.Auth, error) {
|
||||||
// is an entry for the hostname _and_ port.
|
// is an entry for the hostname _and_ port.
|
||||||
host = knownhosts.Normalize(s.host)
|
host = knownhosts.Normalize(s.host)
|
||||||
for _, k := range kk {
|
for _, k := range kk {
|
||||||
if k.matches(host, cert.Hostkey.HashSHA1[:]) {
|
if k.matches(host, cert.Hostkey) {
|
||||||
return git2go.ErrOk
|
return git2go.ErrOk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -195,13 +198,28 @@ func parseKnownHosts(s string) ([]knownKey, error) {
|
||||||
return knownHosts, nil
|
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) {
|
if !containsHost(k.hosts, host) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
hash := sha1.Sum(k.key.Marshal())
|
var fingerprint []byte
|
||||||
if bytes.Compare(hash[:], key) != 0 {
|
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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,11 @@ limitations under the License.
|
||||||
package libgit2
|
package libgit2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/base64"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
git2go "github.com/libgit2/git2go/v31"
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
|
||||||
"github.com/fluxcd/source-controller/pkg/git"
|
"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