Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 70 additions & 1 deletion include/git2/credential.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,14 @@ typedef enum {
*
* @see git_credential_ssh_key_memory_new
*/
GIT_CREDENTIAL_SSH_MEMORY = (1u << 6)
GIT_CREDENTIAL_SSH_MEMORY = (1u << 6),

/**
* An SSH key-based authentication request, with a custom signature by
* a security key
* @see git_credential_ssh_custom_sk_new
*/
GIT_CREDENTIAL_SSH_CUSTOM_SK = (1u << 7)
} git_credential_t;

/**
Expand Down Expand Up @@ -109,6 +116,11 @@ typedef struct git_credential_ssh_interactive git_credential_ssh_interactive;
*/
typedef struct git_credential_ssh_custom git_credential_ssh_custom;

/**
* A key with a custom signature function using a security key
*/
typedef struct git_credential_ssh_custom_sk git_credential_ssh_custom_sk;

/**
* Credential acquisition callback.
*
Expand Down Expand Up @@ -240,6 +252,7 @@ GIT_EXTERN(int) git_credential_ssh_key_memory_new(
*/
#ifndef LIBSSH2_VERSION
typedef struct _LIBSSH2_SESSION LIBSSH2_SESSION;
typedef struct _LIBSSH2_SK_SIG_INFO LIBSSH2_SK_SIG_INFO;
typedef struct _LIBSSH2_USERAUTH_KBDINT_PROMPT LIBSSH2_USERAUTH_KBDINT_PROMPT;
typedef struct _LIBSSH2_USERAUTH_KBDINT_RESPONSE LIBSSH2_USERAUTH_KBDINT_RESPONSE;
#endif
Expand Down Expand Up @@ -337,6 +350,62 @@ GIT_EXTERN(int) git_credential_ssh_custom_new(
git_credential_sign_cb sign_callback,
void *payload);

/**
* Callback for credential signing with security key.
*
* @param session The libssh2 session.
* @param sig_info The signature data used to build the response.
* @param data The challenge to be signed.
* @param data_len The length of the challenge.
* @param algorithm The algorithm (e.g. LIBSSH2_HOSTKEY_TYPE_ED25519).
* @param flags The security key flags.
* @param application The relaying party, typically "ssh:".
* @param key_handle The credential id.
* @param key_handle_len The length of the credential id.
* @param abstract Additional data to pass to the callback.
* @return 0 for success, < 0 to indicate an error, > 0 to indicate
* no credential was acquired
*/
typedef int GIT_CALLBACK(git_credential_sign_sk_cb)(
LIBSSH2_SESSION *session, LIBSSH2_SK_SIG_INFO *sig_info,
const unsigned char *data, size_t data_len,
int algorithm, uint8_t flags,
const char *application, const unsigned char *key_handle,
size_t handle_len,
void **abstract);

/**
* Create an ssh key credential with a custom signing function for a security
* key.
*
* This lets you use your own function to sign the challenge.
*
* This function and its credential type is provided for completeness
* and wraps `libssh2_userauth_publickey_sk()`, which is undocumented.
*
* The supplied credential parameter will be internally duplicated.
*
* @param out The newly created credential object.
* @param username username to use to authenticate
* @param publickey The bytes of the public key.
* @param publickey_len The length of the public key in bytes.
* @param privatekey The bytes of the private key.
* @param privatekey_len The length of the private key in bytes.
* @param sign_callback The callback method to sign the data during the challenge.
* @param payload Additional data to pass to the callback.
* @return 0 for success or an error code for failure
*/
GIT_EXTERN(int) git_credential_ssh_custom_sk_new(
git_credential **out,
const char *username,
const char *publickey,
size_t publickey_len,
const char *privatekey,
size_t privatekey_len,
const char *passphrase,
git_credential_sign_sk_cb sign_callback,
void *payload);

/** @} */
GIT_END_DECL

Expand Down
20 changes: 20 additions & 0 deletions include/git2/sys/credential.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,26 @@ struct git_credential_ssh_custom {
void *payload; /**< Payload passed to prompt_callback */
};

/**
* A security key with a custom signature function
*/
struct git_credential_ssh_custom_sk {
git_credential parent; /**< The parent credential */
char *username; /**< The username to authenticate as */
char *publickey; /**< The public key data */
size_t publickey_len; /**< Length of the public key */
char *privatekey; /**< The private key data */
size_t privatekey_len; /**< Length of the private key */
char *passphrase; /**< The passphrase for the security key */

/**
* Callback used to sign the data.
*/
git_credential_sign_sk_cb sign_callback;

void *payload; /**< Payload passed to prompt_callback */
};

/** @} */
GIT_END_DECL

Expand Down
87 changes: 87 additions & 0 deletions src/libgit2/transports/credential.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ const char *git_credential_get_username(git_credential *cred)
git_credential_ssh_custom *c = (git_credential_ssh_custom *) cred;
return c->username;
}
case GIT_CREDENTIAL_SSH_CUSTOM_SK:
{
git_credential_ssh_custom_sk *c = (git_credential_ssh_custom_sk *) cred;
return c->username;
}
case GIT_CREDENTIAL_SSH_INTERACTIVE:
{
git_credential_ssh_interactive *c = (git_credential_ssh_interactive *) cred;
Expand Down Expand Up @@ -169,6 +174,36 @@ static void ssh_custom_free(struct git_credential *cred)
git__free(c);
}

static void ssh_custom_sk_free(struct git_credential *cred)
{
git_credential_ssh_custom_sk *c = (git_credential_ssh_custom_sk *)cred;

git__free(c->username);

if (c->publickey) {
/* Zero the memory which previously held the publickey */
size_t key_len = strlen(c->publickey);
git__memzero(c->publickey, key_len);
git__free(c->publickey);
}

if (c->privatekey) {
/* Zero the memory which previously held the privatekey */
size_t key_len = strlen(c->privatekey);
git__memzero(c->privatekey, key_len);
git__free(c->privatekey);
}

if (c->passphrase) {
/* Zero the memory which previously held the passphrase */
size_t pass_len = strlen(c->passphrase);
git__memzero(c->passphrase, pass_len);
git__free(c->passphrase);
}

git__free(c);
}

static void default_free(struct git_credential *cred)
{
git_credential_default *c = (git_credential_default *)cred;
Expand Down Expand Up @@ -351,6 +386,58 @@ int git_credential_ssh_custom_new(
return 0;
}

int git_credential_ssh_custom_sk_new(
git_credential **cred,
const char *username,
const char *publickey,
size_t publickey_len,
const char *privatekey,
size_t privatekey_len,
const char *passphrase,
git_credential_sign_sk_cb sign_callback,
void *payload)
{
git_credential_ssh_custom_sk *c;

GIT_ASSERT_ARG(username);
GIT_ASSERT_ARG(cred);

c = git__calloc(1, sizeof(git_credential_ssh_custom_sk));
GIT_ERROR_CHECK_ALLOC(c);

c->parent.credtype = GIT_CREDENTIAL_SSH_CUSTOM_SK;
c->parent.free = ssh_custom_sk_free;

c->username = git__strdup(username);
GIT_ERROR_CHECK_ALLOC(c->username);

if (publickey_len > 0) {
c->publickey = git__malloc(publickey_len);
GIT_ERROR_CHECK_ALLOC(c->publickey);

memcpy(c->publickey, publickey, publickey_len);
}

if (privatekey_len > 0) {
c->privatekey = git__malloc(privatekey_len);
GIT_ERROR_CHECK_ALLOC(c->privatekey);

memcpy(c->privatekey, privatekey, privatekey_len);
}

c->publickey_len = publickey_len;
c->privatekey_len = privatekey_len;

c->passphrase = git__strdup(passphrase);
GIT_ERROR_CHECK_ALLOC(c->passphrase);

c->sign_callback = sign_callback;
c->payload = payload;

*cred = &c->parent;
return 0;
}

int git_credential_default_new(git_credential **cred)
{
git_credential_default *c;
Expand Down
11 changes: 11 additions & 0 deletions src/libgit2/transports/ssh_libssh2.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,16 @@ static int _git_ssh_authenticate_session(
c->publickey_len, c->sign_callback, &c->payload);
break;
}
case GIT_CREDENTIAL_SSH_CUSTOM_SK: {
git_credential_ssh_custom_sk *c = (git_credential_ssh_custom_sk *)cred;

rc = libssh2_userauth_publickey_sk(
session, c->username, strlen(c->username),
(const unsigned char *)c->publickey, c->publickey_len,
c->privatekey, c->privatekey_len,
c->passphrase, c->sign_callback, &c->payload);
break;
}
case GIT_CREDENTIAL_SSH_INTERACTIVE: {
void **abstract = libssh2_session_abstract(session);
git_credential_ssh_interactive *c = (git_credential_ssh_interactive *)cred;
Expand Down Expand Up @@ -1033,6 +1043,7 @@ static int list_auth_methods(int *out, LIBSSH2_SESSION *session, const char *use
if (!git__prefixcmp(ptr, SSH_AUTH_PUBLICKEY)) {
*out |= GIT_CREDENTIAL_SSH_KEY;
*out |= GIT_CREDENTIAL_SSH_CUSTOM;
*out |= GIT_CREDENTIAL_SSH_CUSTOM_SK;
#ifdef GIT_SSH_LIBSSH2_MEMORY_CREDENTIALS
*out |= GIT_CREDENTIAL_SSH_MEMORY;
#endif
Expand Down