@@ -3,11 +3,15 @@ package main
33import (
44 "C"
55 "bufio"
6+ "bytes"
7+ "crypto/md5"
8+ "crypto/sha1"
9+ "crypto/sha256"
610 "fmt"
11+ "hash"
712 "io"
813 "io/ioutil"
914 "log"
10- "net"
1115 "net/url"
1216 "os"
1317 "path/filepath"
@@ -16,7 +20,7 @@ import (
1620
1721 // git2go must be aligned with libgit2 version:
1822 // https://github.com/libgit2/git2go#which-go-version-to-use
19- git2go "github.com/libgit2/git2go/v33 "
23+ git2go "github.com/libgit2/git2go/v31 "
2024
2125 "github.com/fluxcd/pkg/gittestserver"
2226 "github.com/fluxcd/pkg/ssh"
@@ -68,17 +72,21 @@ func main() {
6872 if err != nil {
6973 panic (fmt .Errorf ("generating rsa key: %w" , err ))
7074 }
75+ privateKey := filepath .Join (testsDir , "id_rsa" )
76+ os .WriteFile (privateKey , rsa .PrivateKey , 0o644 )
77+ pubKey := filepath .Join (testsDir , "id_rsa.pub" )
78+ os .WriteFile (pubKey , rsa .PrivateKey , 0o644 )
7179
7280 test ("SSH clone with rsa key" ,
7381 filepath .Join (testsDir , "/ssh-clone-rsa" ),
7482 sshRepoURL ,
7583 & git2go.CloneOptions {
7684 Bare : true ,
77- FetchOptions : git2go.FetchOptions {
85+ FetchOptions : & git2go.FetchOptions {
7886 RemoteCallbacks : git2go.RemoteCallbacks {
7987 CredentialsCallback : func (url string , username string , allowedTypes git2go.CredentialType ) (* git2go.Credential , error ) {
80- return git2go .NewCredentialSSHKeyFromMemory ("git" ,
81- string ( rsa . PublicKey ), string ( rsa . PrivateKey ) , "" )
88+ return git2go .NewCredentialSSHKey ("git" ,
89+ pubKey , privateKey , "" )
8290 },
8391 CertificateCheckCallback : knownHostsCallback (u .Host , knownHosts ),
8492 },
@@ -89,16 +97,21 @@ func main() {
8997 if err != nil {
9098 panic (fmt .Errorf ("generating ed25519 key: %w" , err ))
9199 }
100+ privateKey = filepath .Join (testsDir , "id_ed25519" )
101+ os .WriteFile (privateKey , ed25519 .PrivateKey , 0o644 )
102+ pubKey = filepath .Join (testsDir , "id_ed25519.pub" )
103+ os .WriteFile (pubKey , ed25519 .PrivateKey , 0o644 )
104+
92105 test ("SSH clone with ed25519 key" ,
93106 filepath .Join (testsDir , "/ssh-clone-ed25519" ),
94107 sshRepoURL ,
95108 & git2go.CloneOptions {
96109 Bare : true ,
97- FetchOptions : git2go.FetchOptions {
110+ FetchOptions : & git2go.FetchOptions {
98111 RemoteCallbacks : git2go.RemoteCallbacks {
99112 CredentialsCallback : func (url string , username string , allowedTypes git2go.CredentialType ) (* git2go.Credential , error ) {
100- return git2go .NewCredentialSSHKeyFromMemory ("git" ,
101- string ( ed25519 . PublicKey ), string ( ed25519 . PrivateKey ) , "" )
113+ return git2go .NewCredentialSSHKey ("git" ,
114+ pubKey , privateKey , "" )
102115 },
103116 CertificateCheckCallback : knownHostsCallback (u .Host , knownHosts ),
104117 },
@@ -150,44 +163,39 @@ func test(description, targetDir, repoURI string, cloneOptions *git2go.CloneOpti
150163// the key of Git server against the given host and known_hosts for
151164// git.SSH Transports.
152165func knownHostsCallback (host string , knownHosts []byte ) git2go.CertificateCheckCallback {
153- return func (cert * git2go.Certificate , valid bool , hostname string ) error {
166+ return func (cert * git2go.Certificate , valid bool , hostname string ) git2go. ErrorCode {
154167 if cert == nil {
155- return fmt . Errorf ( "no certificate returned for %s" , hostname )
168+ return git2go . ErrorCodeCertificate
156169 }
157170
158171 kh , err := parseKnownHosts (string (knownHosts ))
159172 if err != nil {
160- return err
173+ return git2go . ErrorCodeCertificate
161174 }
162175
163176 fmt .Printf ("Known keys: %d\n " , len (kh ))
164177
165- // First, attempt to split the configured host and port to validate
166- // the port-less hostname given to the callback.
167- h , _ , err := net .SplitHostPort (host )
168- if err != nil {
169- // SplitHostPort returns an error if the host is missing
170- // a port, assume the host has no port.
171- h = host
172- }
173-
174178 // Check if the configured host matches the hostname given to
175179 // the callback.
176- if h != hostname {
177- return fmt .Errorf ("host mismatch: %q %q\n " , h , hostname )
180+ // In libgit 1.1.* hostname also includes its with port.
181+ if host != hostname {
182+ fmt .Printf ("host and hostname:\n %q\n %q\n " ,
183+ host ,
184+ hostname )
185+ return git2go .ErrorCodeUser
178186 }
179187
180188 // We are now certain that the configured host and the hostname
181189 // given to the callback match. Use the configured host (that
182190 // includes the port), and normalize it, so we can check if there
183191 // is an entry for the hostname _and_ port.
184- h = knownhosts .Normalize (host )
192+ h : = knownhosts .Normalize (host )
185193 for _ , k := range kh {
186194 if k .matches (h , cert .Hostkey ) {
187- return nil
195+ return git2go . ErrorCodeOK
188196 }
189197 }
190- return fmt . Errorf ( "hostkey cannot be verified" )
198+ return git2go . ErrorCodeCertificate
191199 }
192200}
193201
@@ -226,24 +234,26 @@ func parseKnownHosts(s string) ([]knownKey, error) {
226234
227235func (k knownKey ) matches (host string , hostkey git2go.HostkeyCertificate ) bool {
228236 if ! containsHost (k .hosts , host ) {
229- fmt .Println ("HOST NOT FOUND" )
230237 return false
231238 }
232239
233- if hostkey .Kind & git2go .HostkeySHA256 > 0 {
234- knownFingerprint := cryptossh .FingerprintSHA256 (k .key )
235- returnedFingerprint := cryptossh .FingerprintSHA256 (hostkey .SSHPublicKey )
236-
237- fmt .Printf ("known and found fingerprints:\n %q\n %q\n " ,
238- knownFingerprint ,
239- returnedFingerprint )
240- if returnedFingerprint == knownFingerprint {
241- return true
242- }
240+ var fingerprint []byte
241+ var hasher hash.Hash
242+ switch {
243+ case hostkey .Kind & git2go .HostkeySHA256 > 0 :
244+ fingerprint = hostkey .HashSHA256 [:]
245+ hasher = sha256 .New ()
246+ case hostkey .Kind & git2go .HostkeySHA1 > 0 :
247+ fingerprint = hostkey .HashSHA1 [:]
248+ hasher = sha1 .New ()
249+ case hostkey .Kind & git2go .HostkeyMD5 > 0 :
250+ fingerprint = hostkey .HashMD5 [:]
251+ hasher = md5 .New ()
252+ default :
253+ return false
243254 }
244-
245- fmt .Println ("host kind not supported" )
246- return false
255+ hasher .Write (k .key .Marshal ())
256+ return bytes .Equal (hasher .Sum (nil ), fingerprint )
247257}
248258
249259func containsHost (hosts []string , host string ) bool {
0 commit comments