Skip to content

Commit dcc9331

Browse files
authored
Expose the ssh.PublicKey into the CertificateCheckCallback (#818)
This change exposes the raw SSH hostkey and the ssh.PublicKey into the CertificateCheckCallback, so that callers can do better validations.
1 parent 018647f commit dcc9331

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

remote.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ const (
252252
// Certificate represents the two possible certificates which libgit2
253253
// knows it might find. If Kind is CertficateX509 then the X509 field
254254
// will be filled. If Kind is CertificateHostkey then the Hostkey
255-
// field will be fille.d
255+
// field will be filled.
256256
type Certificate struct {
257257
Kind CertificateKind
258258
X509 *x509.Certificate
@@ -266,7 +266,7 @@ const (
266266
HostkeyMD5 HostkeyKind = C.GIT_CERT_SSH_MD5
267267
HostkeySHA1 HostkeyKind = C.GIT_CERT_SSH_SHA1
268268
HostkeySHA256 HostkeyKind = C.GIT_CERT_SSH_SHA256
269-
HostkeyRaw HostkeyKind = 1 << 3
269+
HostkeyRaw HostkeyKind = C.GIT_CERT_SSH_RAW
270270
)
271271

272272
// Server host key information. A bitmask containing the available fields.
@@ -476,6 +476,17 @@ func certificateCheckCallback(
476476
C.memcpy(unsafe.Pointer(&cert.Hostkey.HashMD5[0]), unsafe.Pointer(&ccert.hash_md5[0]), C.size_t(len(cert.Hostkey.HashMD5)))
477477
C.memcpy(unsafe.Pointer(&cert.Hostkey.HashSHA1[0]), unsafe.Pointer(&ccert.hash_sha1[0]), C.size_t(len(cert.Hostkey.HashSHA1)))
478478
C.memcpy(unsafe.Pointer(&cert.Hostkey.HashSHA256[0]), unsafe.Pointer(&ccert.hash_sha256[0]), C.size_t(len(cert.Hostkey.HashSHA256)))
479+
if (cert.Hostkey.Kind & HostkeyRaw) == HostkeyRaw {
480+
cert.Hostkey.Hostkey = C.GoBytes(unsafe.Pointer(ccert.hostkey), C.int(ccert.hostkey_len))
481+
var err error
482+
cert.Hostkey.SSHPublicKey, err = ssh.ParsePublicKey(cert.Hostkey.Hostkey)
483+
if err != nil {
484+
if data.errorTarget != nil {
485+
*data.errorTarget = err
486+
}
487+
return setCallbackError(errorMessage, err)
488+
}
489+
}
479490
} else {
480491
err := errors.New("unsupported certificate type")
481492
if data.errorTarget != nil {

transport.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,21 @@ func (t *Transport) SmartCertificateCheck(cert *Certificate, valid bool, hostnam
128128
parent: C.git_cert{
129129
cert_type: C.GIT_CERT_HOSTKEY_LIBSSH2,
130130
},
131-
_type: C.git_cert_ssh_t(cert.Kind),
131+
_type: C.git_cert_ssh_t(cert.Kind),
132+
hostkey: (*C.char)(C.CBytes(cert.Hostkey.Hostkey)),
133+
hostkey_len: C.size_t(len(cert.Hostkey.Hostkey)),
132134
}
135+
defer C.free(unsafe.Pointer(chostkeyCert.hostkey))
133136
C.memcpy(unsafe.Pointer(&chostkeyCert.hash_md5[0]), unsafe.Pointer(&cert.Hostkey.HashMD5[0]), C.size_t(len(cert.Hostkey.HashMD5)))
134137
C.memcpy(unsafe.Pointer(&chostkeyCert.hash_sha1[0]), unsafe.Pointer(&cert.Hostkey.HashSHA1[0]), C.size_t(len(cert.Hostkey.HashSHA1)))
135138
C.memcpy(unsafe.Pointer(&chostkeyCert.hash_sha256[0]), unsafe.Pointer(&cert.Hostkey.HashSHA256[0]), C.size_t(len(cert.Hostkey.HashSHA256)))
139+
if cert.Hostkey.SSHPublicKey.Type() == "ssh-rsa" {
140+
chostkeyCert.raw_type = C.GIT_CERT_SSH_RAW_TYPE_RSA
141+
} else if cert.Hostkey.SSHPublicKey.Type() == "ssh-dss" {
142+
chostkeyCert.raw_type = C.GIT_CERT_SSH_RAW_TYPE_DSS
143+
} else {
144+
chostkeyCert.raw_type = C.GIT_CERT_SSH_RAW_TYPE_UNKNOWN
145+
}
136146
ccert = (*C.git_cert)(unsafe.Pointer(&chostkeyCert))
137147

138148
case CertificateX509:

0 commit comments

Comments
 (0)