@@ -3,15 +3,20 @@ package git
3
3
/*
4
4
#include <git2.h>
5
5
#include <git2/credential.h>
6
+ #include <git2/sys/credential.h>
6
7
7
8
git_credential_t _go_git_credential_credtype(git_credential *cred);
9
+ void _go_git_populate_credential_ssh_custom(git_credential_ssh_custom *cred);
8
10
*/
9
11
import "C"
10
12
import (
13
+ "crypto/rand"
11
14
"fmt"
12
15
"runtime"
13
16
"strings"
14
17
"unsafe"
18
+
19
+ "golang.org/x/crypto/ssh"
15
20
)
16
21
17
22
// CredentialType is a bitmask of supported credential types.
@@ -192,6 +197,63 @@ func NewCredentialSSHKeyFromAgent(username string) (*Credential, error) {
192
197
return cred , nil
193
198
}
194
199
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
+
195
257
func NewCredentialDefault () (* Credential , error ) {
196
258
runtime .LockOSThread ()
197
259
defer runtime .UnlockOSThread ()
0 commit comments