@@ -3,11 +3,15 @@ package main
3
3
import (
4
4
"C"
5
5
"bufio"
6
+ "bytes"
7
+ "crypto/md5"
8
+ "crypto/sha1"
9
+ "crypto/sha256"
6
10
"fmt"
11
+ "hash"
7
12
"io"
8
13
"io/ioutil"
9
14
"log"
10
- "net"
11
15
"net/url"
12
16
"os"
13
17
"path/filepath"
@@ -16,7 +20,7 @@ import (
16
20
17
21
// git2go must be aligned with libgit2 version:
18
22
// https://github.com/libgit2/git2go#which-go-version-to-use
19
- git2go "github.com/libgit2/git2go/v33 "
23
+ git2go "github.com/libgit2/git2go/v31 "
20
24
21
25
"github.com/fluxcd/pkg/gittestserver"
22
26
"github.com/fluxcd/pkg/ssh"
@@ -68,17 +72,21 @@ func main() {
68
72
if err != nil {
69
73
panic (fmt .Errorf ("generating rsa key: %w" , err ))
70
74
}
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 )
71
79
72
80
test ("SSH clone with rsa key" ,
73
81
filepath .Join (testsDir , "/ssh-clone-rsa" ),
74
82
sshRepoURL ,
75
83
& git2go.CloneOptions {
76
84
Bare : true ,
77
- FetchOptions : git2go.FetchOptions {
85
+ FetchOptions : & git2go.FetchOptions {
78
86
RemoteCallbacks : git2go.RemoteCallbacks {
79
87
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 , "" )
82
90
},
83
91
CertificateCheckCallback : knownHostsCallback (u .Host , knownHosts ),
84
92
},
@@ -89,16 +97,21 @@ func main() {
89
97
if err != nil {
90
98
panic (fmt .Errorf ("generating ed25519 key: %w" , err ))
91
99
}
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
+
92
105
test ("SSH clone with ed25519 key" ,
93
106
filepath .Join (testsDir , "/ssh-clone-ed25519" ),
94
107
sshRepoURL ,
95
108
& git2go.CloneOptions {
96
109
Bare : true ,
97
- FetchOptions : git2go.FetchOptions {
110
+ FetchOptions : & git2go.FetchOptions {
98
111
RemoteCallbacks : git2go.RemoteCallbacks {
99
112
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 , "" )
102
115
},
103
116
CertificateCheckCallback : knownHostsCallback (u .Host , knownHosts ),
104
117
},
@@ -150,44 +163,39 @@ func test(description, targetDir, repoURI string, cloneOptions *git2go.CloneOpti
150
163
// the key of Git server against the given host and known_hosts for
151
164
// git.SSH Transports.
152
165
func 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 {
154
167
if cert == nil {
155
- return fmt . Errorf ( "no certificate returned for %s" , hostname )
168
+ return git2go . ErrorCodeCertificate
156
169
}
157
170
158
171
kh , err := parseKnownHosts (string (knownHosts ))
159
172
if err != nil {
160
- return err
173
+ return git2go . ErrorCodeCertificate
161
174
}
162
175
163
176
fmt .Printf ("Known keys: %d\n " , len (kh ))
164
177
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
-
174
178
// Check if the configured host matches the hostname given to
175
179
// 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
178
186
}
179
187
180
188
// We are now certain that the configured host and the hostname
181
189
// given to the callback match. Use the configured host (that
182
190
// includes the port), and normalize it, so we can check if there
183
191
// is an entry for the hostname _and_ port.
184
- h = knownhosts .Normalize (host )
192
+ h : = knownhosts .Normalize (host )
185
193
for _ , k := range kh {
186
194
if k .matches (h , cert .Hostkey ) {
187
- return nil
195
+ return git2go . ErrorCodeOK
188
196
}
189
197
}
190
- return fmt . Errorf ( "hostkey cannot be verified" )
198
+ return git2go . ErrorCodeCertificate
191
199
}
192
200
}
193
201
@@ -226,24 +234,26 @@ func parseKnownHosts(s string) ([]knownKey, error) {
226
234
227
235
func (k knownKey ) matches (host string , hostkey git2go.HostkeyCertificate ) bool {
228
236
if ! containsHost (k .hosts , host ) {
229
- fmt .Println ("HOST NOT FOUND" )
230
237
return false
231
238
}
232
239
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
243
254
}
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 )
247
257
}
248
258
249
259
func containsHost (hosts []string , host string ) bool {
0 commit comments