Added SSH public key authentication
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
diff --git a/include/git2/transport.h b/include/git2/transport.h
index 31572c1..cc29f8b 100644
--- a/include/git2/transport.h
+++ b/include/git2/transport.h
@@ -11,6 +11,8 @@
#include "net.h"
#include "types.h"
+#include <libssh2.h>
+
/**
* @file git2/transport.h
* @brief Git transport interfaces and functions
@@ -28,6 +30,7 @@ typedef enum {
/* git_cred_userpass_plaintext */
GIT_CREDTYPE_USERPASS_PLAINTEXT = 1,
GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE = 2,
+ GIT_CREDTYPE_SSH_PUBLICKEY = 3,
} git_credtype_t;
/* The base structure for all credential types */
@@ -44,7 +47,7 @@ typedef struct git_cred_userpass_plaintext {
char *password;
} git_cred_userpass_plaintext;
-/* A plaintext username and password */
+/* A ssh key file and passphrase */
typedef struct git_cred_ssh_keyfile_passphrase {
git_cred parent;
char *publickey;
@@ -52,6 +55,15 @@ typedef struct git_cred_ssh_keyfile_passphrase {
char *passphrase;
} git_cred_ssh_keyfile_passphrase;
+/* A ssh public key and authentication callback */
+typedef struct git_cred_ssh_publickey {
+ git_cred parent;
+ char *publickey;
+ size_t publickey_len;
+ void *sign_callback;
+ void *sign_data;
+} git_cred_ssh_publickey;
+
/**
* Creates a new plain-text username and password credential object.
* The supplied credential parameter will be internally duplicated.
@@ -83,6 +95,24 @@ GIT_EXTERN(int) git_cred_ssh_keyfile_passphrase_new(
const char *passphrase);
/**
+ * Creates a new ssh public key credential object.
+ * The supplied credential parameter will be internally duplicated.
+ *
+ * @param out The newly created credential object.
+ * @param publickey The bytes of the public key.
+ * @param publickey_len The length of the public key in bytes.
+ * @param sign_callback The callback method for authenticating.
+ * @param sign_data The abstract data sent to the sign_callback method.
+ * @return 0 for success or an error code for failure
+ */
+GIT_EXTERN(int) git_cred_ssh_publickey_new(
+ git_cred **out,
+ const char *publickey,
+ size_t publickey_len,
+ LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)),
+ void *sign_data);
+
+/**
* Signature of a function which acquires a credential object.
*
* @param cred The newly created credential object.
diff --git a/src/transports/cred.c b/src/transports/cred.c
index 83820ec..5d5e745 100644
--- a/src/transports/cred.c
+++ b/src/transports/cred.c
@@ -135,3 +135,52 @@ int git_cred_ssh_keyfile_passphrase_new(
*cred = &c->parent;
return 0;
}
+
+static void ssh_publickey_free(struct git_cred *cred)
+{
+ git_cred_ssh_publickey *c = (git_cred_ssh_publickey *)cred;
+
+ git__free(c->publickey);
+
+ c->sign_callback = NULL;
+ c->sign_data = NULL;
+
+ memset(c, 0, sizeof(*c));
+
+ git__free(c);
+}
+
+int git_cred_ssh_publickey_new(
+ git_cred **cred,
+ const char *publickey,
+ size_t publickey_len,
+ LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)),
+ void *sign_data)
+{
+ git_cred_ssh_publickey *c;
+
+ if (!cred)
+ return -1;
+
+ c = git__malloc(sizeof(git_cred_ssh_publickey));
+ GITERR_CHECK_ALLOC(c);
+
+ c->parent.credtype = GIT_CREDTYPE_SSH_PUBLICKEY;
+ c->parent.free = ssh_publickey_free;
+
+ c->publickey = git__malloc(publickey_len);
+ memcpy(c->publickey, publickey, publickey_len);
+
+ if (!c->publickey) {
+ git__free(c);
+ return -1;
+ }
+
+ c->publickey_len = publickey_len;
+
+ c->sign_callback = sign_callback;
+ c->sign_data = sign_data;
+
+ *cred = &c->parent;
+ return 0;
+}
diff --git a/src/transports/ssh.c b/src/transports/ssh.c
index 9ee13be..a1df6c4 100644
--- a/src/transports/ssh.c
+++ b/src/transports/ssh.c
@@ -253,6 +253,18 @@ static int _git_ssh_authenticate_session(
);
break;
}
+ case GIT_CREDTYPE_SSH_PUBLICKEY: {
+ git_cred_ssh_publickey *c = (git_cred_ssh_publickey *)cred;
+ rc = libssh2_userauth_publickey(
+ session,
+ user,
+ (const unsigned char *)c->publickey,
+ c->publickey_len,
+ c->sign_callback,
+ &c->sign_data
+ );
+ break;
+ }
default:
rc = LIBSSH2_ERROR_AUTHENTICATION_FAILED;
}