Skip to content

Commit e57ff6c

Browse files
committed
Add NewCredentialSSHKeyFromSigner (#706)
This change adds `NewCredentialSSHKeyFromSigner`, which allows idiomatic use of SSH keys from Go. This also lets us spin off an SSH server in the tests. (cherry picked from commit abf02bc)
1 parent 07b98b4 commit e57ff6c

20 files changed

+421
-10
lines changed

.github/workflows/ci.yml

+5
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ jobs:
3434
GOPATH: /home/runner/work/git2go
3535
run: |
3636
git submodule update --init
37+
sudo apt-get install -y --no-install-recommends libssh2-1-dev
3738
make build-libgit2-static
3839
go get -tags static -t github.com/${{ github.repository }}/...
3940
go build -tags static github.com/${{ github.repository }}/...
@@ -62,6 +63,7 @@ jobs:
6263
- name: Build
6364
run: |
6465
git submodule update --init
66+
sudo apt-get install -y --no-install-recommends libssh2-1-dev
6567
make build-libgit2-static
6668
- name: Test
6769
run: make TEST_ARGS=-test.v test-static
@@ -84,6 +86,7 @@ jobs:
8486
- name: Build
8587
run: |
8688
git submodule update --init
89+
sudo apt-get install -y --no-install-recommends libssh2-1-dev
8790
make build-libgit2-dynamic
8891
- name: Test
8992
run: make TEST_ARGS=-test.v test-dynamic
@@ -108,6 +111,7 @@ jobs:
108111
- name: Build libgit2 ${{ matrix.libgit2 }}
109112
run: |
110113
git submodule update --init
114+
sudo apt-get install -y --no-install-recommends libssh2-1-dev
111115
sudo env BUILD_LIBGIT_REF=v${{ matrix.libgit2 }} ./script/build-libgit2.sh --dynamic --system
112116
- name: Test
113117
run: make TEST_ARGS=-test.v test
@@ -130,6 +134,7 @@ jobs:
130134
- name: Build libgit2
131135
run: |
132136
git submodule update --init
137+
sudo apt-get install -y --no-install-recommends libssh2-1-dev
133138
sudo ./script/build-libgit2.sh --static --system
134139
- name: Test
135140
run: go test --count=1 --tags "static,system_libgit2" ./...

.travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ go:
88
- tip
99

1010
install:
11+
- sudo apt-get install -y --no-install-recommends libssh2-1-dev
1112
- make build-libgit2-static
1213
- go get --tags "static" ./...
1314

credentials.go

+62
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,20 @@ package git
33
/*
44
#include <git2.h>
55
#include <git2/credential.h>
6+
#include <git2/sys/credential.h>
67
78
git_credential_t _go_git_credential_credtype(git_credential *cred);
9+
void _go_git_populate_credential_ssh_custom(git_credential_ssh_custom *cred);
810
*/
911
import "C"
1012
import (
13+
"crypto/rand"
1114
"fmt"
1215
"runtime"
1316
"strings"
1417
"unsafe"
18+
19+
"golang.org/x/crypto/ssh"
1520
)
1621

1722
// CredentialType is a bitmask of supported credential types.
@@ -192,6 +197,63 @@ func NewCredentialSSHKeyFromAgent(username string) (*Credential, error) {
192197
return cred, nil
193198
}
194199

200+
type credentialSSHCustomData struct {
201+
signer ssh.Signer
202+
}
203+
204+
//export credentialSSHCustomFree
205+
func credentialSSHCustomFree(cred *C.git_credential_ssh_custom) {
206+
if cred == nil {
207+
return
208+
}
209+
210+
C.free(unsafe.Pointer(cred.username))
211+
C.free(unsafe.Pointer(cred.publickey))
212+
pointerHandles.Untrack(cred.payload)
213+
C.free(unsafe.Pointer(cred))
214+
}
215+
216+
//export credentialSSHSignCallback
217+
func credentialSSHSignCallback(
218+
errorMessage **C.char,
219+
sig **C.uchar,
220+
sig_len *C.size_t,
221+
data *C.uchar,
222+
data_len C.size_t,
223+
handle unsafe.Pointer,
224+
) C.int {
225+
signer := pointerHandles.Get(handle).(*credentialSSHCustomData).signer
226+
signature, err := signer.Sign(rand.Reader, C.GoBytes(unsafe.Pointer(data), C.int(data_len)))
227+
if err != nil {
228+
return setCallbackError(errorMessage, err)
229+
}
230+
*sig = (*C.uchar)(C.CBytes(signature.Blob))
231+
*sig_len = C.size_t(len(signature.Blob))
232+
return C.int(ErrorCodeOK)
233+
}
234+
235+
// NewCredentialSSHKeyFromSigner creates new SSH credentials using the provided signer.
236+
func NewCredentialSSHKeyFromSigner(username string, signer ssh.Signer) (*Credential, error) {
237+
publicKey := signer.PublicKey().Marshal()
238+
239+
ccred := (*C.git_credential_ssh_custom)(C.calloc(1, C.size_t(unsafe.Sizeof(C.git_credential_ssh_custom{}))))
240+
ccred.parent.credtype = C.GIT_CREDENTIAL_SSH_CUSTOM
241+
ccred.username = C.CString(username)
242+
ccred.publickey = (*C.char)(C.CBytes(publicKey))
243+
ccred.publickey_len = C.size_t(len(publicKey))
244+
C._go_git_populate_credential_ssh_custom(ccred)
245+
246+
data := credentialSSHCustomData{
247+
signer: signer,
248+
}
249+
ccred.payload = pointerHandles.Track(&data)
250+
251+
cred := newCredential()
252+
cred.ptr = &ccred.parent
253+
254+
return cred, nil
255+
}
256+
195257
func NewCredentialDefault() (*Credential, error) {
196258
runtime.LockOSThread()
197259
defer runtime.UnlockOSThread()

go.mod

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,8 @@ module github.com/libgit2/git2go/v30
22

33
go 1.13
44

5-
require golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de
5+
require (
6+
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
7+
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c
8+
golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect
9+
)

go.sum

+9-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1+
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
2+
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
13
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
2-
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig=
3-
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
4+
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c h1:9HhBz5L/UjnK9XLtiZhYAdue5BVKep3PMmS2LuPDt8k=
5+
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
46
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
57
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
6-
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
8+
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
9+
golang.org/x/sys v0.0.0-20201204225414-ed752295db88 h1:KmZPnMocC93w341XZp26yTJg8Za7lhb2KhkYmixoeso=
10+
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
11+
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM=
12+
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
713
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

0 commit comments

Comments
 (0)