diff options
author | Vicent Martà <vicent@github.com> | 2013-11-20 07:06:35 -0800 |
---|---|---|
committer | Vicent Martà <vicent@github.com> | 2013-11-20 07:06:35 -0800 |
commit | a2e873d1a15df03d7ecfac2a1bec56cf66b8cc40 (patch) | |
tree | c08a1c8fbaab807ae3af00a186ee98d94a989c24 | |
parent | 43cb8b32428b1b29994874349ec22eb5372e152c (diff) | |
parent | 138e014c389a750715cf4f60cceef96692b4ea51 (diff) | |
download | libgit2-a2e873d1a15df03d7ecfac2a1bec56cf66b8cc40.tar.gz |
Merge pull request #1972 from ghedo/ssh_agent
ssh: add support for ssh-agent authentication
-rw-r--r-- | include/git2/transport.h | 12 | ||||
-rw-r--r-- | src/transports/cred.c | 22 | ||||
-rw-r--r-- | src/transports/ssh.c | 54 |
3 files changed, 86 insertions, 2 deletions
diff --git a/include/git2/transport.h b/include/git2/transport.h index caabd0465..039321088 100644 --- a/include/git2/transport.h +++ b/include/git2/transport.h @@ -131,6 +131,18 @@ GIT_EXTERN(int) git_cred_ssh_key_new( const char *passphrase); /** + * Create a new ssh key credential object used for querying an ssh-agent. + * The supplied credential parameter will be internally duplicated. + * + * @param out The newly created credential object. + * @param username username to use to authenticate + * @return 0 for success or an error code for failure + */ +GIT_EXTERN(int) git_cred_ssh_key_from_agent( + git_cred **out, + const char *username); + +/** * Create an ssh key credential with a custom signing function. * * This lets you use your own function to sign the challenge. diff --git a/src/transports/cred.c b/src/transports/cred.c index 05d2c8dc6..abae70b51 100644 --- a/src/transports/cred.c +++ b/src/transports/cred.c @@ -165,6 +165,28 @@ int git_cred_ssh_key_new( return 0; } +int git_cred_ssh_key_from_agent(git_cred **cred, const char *username) { + git_cred_ssh_key *c; + + assert(cred); + + c = git__calloc(1, sizeof(git_cred_ssh_key)); + GITERR_CHECK_ALLOC(c); + + c->parent.credtype = GIT_CREDTYPE_SSH_KEY; + c->parent.free = ssh_key_free; + + if (username) { + c->username = git__strdup(username); + GITERR_CHECK_ALLOC(c->username); + } + + c->privatekey = NULL; + + *cred = &c->parent; + return 0; +} + int git_cred_ssh_custom_new( git_cred **cred, const char *username, diff --git a/src/transports/ssh.c b/src/transports/ssh.c index 4a905e3c9..37f17080a 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -235,6 +235,50 @@ static int git_ssh_extract_url_parts( return 0; } +static int ssh_agent_auth(LIBSSH2_SESSION *session, git_cred_ssh_key *c) { + int rc = LIBSSH2_ERROR_NONE; + + struct libssh2_agent_publickey *curr, *prev = NULL; + + LIBSSH2_AGENT *agent = libssh2_agent_init(session); + + if (agent == NULL) + return -1; + + rc = libssh2_agent_connect(agent); + + if (rc != LIBSSH2_ERROR_NONE) + goto shutdown; + + rc = libssh2_agent_list_identities(agent); + + if (rc != LIBSSH2_ERROR_NONE) + goto shutdown; + + while (1) { + rc = libssh2_agent_get_identity(agent, &curr, prev); + + if (rc < 0) + goto shutdown; + + if (rc == 1) + goto shutdown; + + rc = libssh2_agent_userauth(agent, c->username, curr); + + if (rc == 0) + break; + + prev = curr; + } + +shutdown: + libssh2_agent_disconnect(agent); + libssh2_agent_free(agent); + + return rc; +} + static int _git_ssh_authenticate_session( LIBSSH2_SESSION* session, const char *user, @@ -253,8 +297,14 @@ static int _git_ssh_authenticate_session( case GIT_CREDTYPE_SSH_KEY: { git_cred_ssh_key *c = (git_cred_ssh_key *)cred; user = c->username ? c->username : user; - rc = libssh2_userauth_publickey_fromfile( - session, c->username, c->publickey, c->privatekey, c->passphrase); + + if (c->privatekey) + rc = libssh2_userauth_publickey_fromfile( + session, c->username, c->publickey, + c->privatekey, c->passphrase); + else + rc = ssh_agent_auth(session, c); + break; } case GIT_CREDTYPE_SSH_CUSTOM: { |