diff options
author | Vicent Marti <vicent@github.com> | 2014-04-22 15:07:18 +0200 |
---|---|---|
committer | Vicent Marti <vicent@github.com> | 2014-04-22 15:07:18 +0200 |
commit | a32d684f866e7710fd139d69ad5d1a8d0ae527c4 (patch) | |
tree | e86cff8daec29c4eb82c214ca01baac4f9a43533 | |
parent | dac95e4aa33a21c2180566558726e1a3d5c0399a (diff) | |
parent | bc0a61986745b89258a98773f88bd98c44ef88d5 (diff) | |
download | libgit2-a32d684f866e7710fd139d69ad5d1a8d0ae527c4.tar.gz |
Merge pull request #2282 from libgit2/cmn/remote-easier-bind
A few niceties for binding authors
-rw-r--r-- | include/git2/remote.h | 14 | ||||
-rw-r--r-- | src/remote.c | 7 | ||||
-rw-r--r-- | src/transports/http.c | 55 | ||||
-rw-r--r-- | src/transports/ssh.c | 32 |
4 files changed, 76 insertions, 32 deletions
diff --git a/include/git2/remote.h b/include/git2/remote.h index d57321f03..ddde3e85e 100644 --- a/include/git2/remote.h +++ b/include/git2/remote.h @@ -468,6 +468,9 @@ struct git_remote_callbacks { /** * This will be called if the remote host requires * authentication in order to connect to it. + * + * Returning GIT_PASSTHROUGH will make libgit2 behave as + * though this field isn't set. */ int (*credentials)(git_cred **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *data); @@ -520,6 +523,17 @@ GIT_EXTERN(int) git_remote_init_callbacks( GIT_EXTERN(int) git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *callbacks); /** + * Retrieve the current callback structure + * + * This provides read access to the callbacks structure as the remote + * sees it. + * + * @param remote the remote to query + * @return a pointer to the callbacks structure + */ +GIT_EXTERN(const git_remote_callbacks *) git_remote_get_callbacks(git_remote *remote); + +/** * Get the statistics structure that is filled in by the fetch operation. */ GIT_EXTERN(const git_transfer_progress *) git_remote_stats(git_remote *remote); diff --git a/src/remote.c b/src/remote.c index 243086bf9..c23a4643e 100644 --- a/src/remote.c +++ b/src/remote.c @@ -1253,6 +1253,13 @@ int git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *cal return 0; } +const git_remote_callbacks *git_remote_get_callbacks(git_remote *remote) +{ + assert(remote); + + return &remote->callbacks; +} + int git_remote_set_transport(git_remote *remote, git_transport *transport) { assert(remote && transport); diff --git a/src/transports/http.c b/src/transports/http.c index c6aaeb9cf..a7eff7365 100644 --- a/src/transports/http.c +++ b/src/transports/http.c @@ -248,6 +248,7 @@ static int on_headers_complete(http_parser *parser) http_subtransport *t = ctx->t; http_stream *s = ctx->s; git_buf buf = GIT_BUF_INIT; + int error = 0, no_callback = 0; /* Both parse_header_name and parse_header_value are populated * and ready for consumption. */ @@ -256,29 +257,43 @@ static int on_headers_complete(http_parser *parser) return t->parse_error = PARSE_ERROR_GENERIC; /* Check for an authentication failure. */ + if (parser->status_code == 401 && - get_verb == s->verb && - t->owner->cred_acquire_cb) { - int allowed_types = 0; + get_verb == s->verb) { + if (!t->owner->cred_acquire_payload) { + no_callback = 1; + } else { + int allowed_types = 0; + + if (parse_unauthorized_response(&t->www_authenticate, + &allowed_types, &t->auth_mechanism) < 0) + return t->parse_error = PARSE_ERROR_GENERIC; + + if (allowed_types && + (!t->cred || 0 == (t->cred->credtype & allowed_types))) { + + error = t->owner->cred_acquire_cb(&t->cred, + t->owner->url, + t->connection_data.user, + allowed_types, + t->owner->cred_acquire_payload); + + if (error == GIT_PASSTHROUGH) { + no_callback = 1; + } else if (error < 0) { + return PARSE_ERROR_GENERIC; + } else { + assert(t->cred); + + /* Successfully acquired a credential. */ + return t->parse_error = PARSE_ERROR_REPLAY; + } + } + } - if (parse_unauthorized_response(&t->www_authenticate, - &allowed_types, &t->auth_mechanism) < 0) + if (no_callback) { + giterr_set(GITERR_NET, "authentication required but no callback set"); return t->parse_error = PARSE_ERROR_GENERIC; - - if (allowed_types && - (!t->cred || 0 == (t->cred->credtype & allowed_types))) { - - if (t->owner->cred_acquire_cb(&t->cred, - t->owner->url, - t->connection_data.user, - allowed_types, - t->owner->cred_acquire_payload) < 0) - return PARSE_ERROR_GENERIC; - - assert(t->cred); - - /* Successfully acquired a credential. */ - return t->parse_error = PARSE_ERROR_REPLAY; } } diff --git a/src/transports/ssh.c b/src/transports/ssh.c index dea990275..b403727c9 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -387,6 +387,7 @@ static int _git_ssh_setup_conn( { char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL; const char *default_port="22"; + int no_callback = 0; ssh_stream *s; LIBSSH2_SESSION* session=NULL; LIBSSH2_CHANNEL* channel=NULL; @@ -413,24 +414,31 @@ static int _git_ssh_setup_conn( if (user && pass) { if (git_cred_userpass_plaintext_new(&t->cred, user, pass) < 0) goto on_error; - } else if (t->owner->cred_acquire_cb) { - if (t->owner->cred_acquire_cb( - &t->cred, t->owner->url, user, - GIT_CREDTYPE_USERPASS_PLAINTEXT | - GIT_CREDTYPE_SSH_KEY | - GIT_CREDTYPE_SSH_INTERACTIVE | - GIT_CREDTYPE_SSH_CUSTOM, - t->owner->cred_acquire_payload) < 0) + } else if (!t->owner->cred_acquire_cb) { + no_callback = 1; + } else { + int error; + error = t->owner->cred_acquire_cb(&t->cred, t->owner->url, user, + GIT_CREDTYPE_USERPASS_PLAINTEXT | + GIT_CREDTYPE_SSH_KEY | GIT_CREDTYPE_SSH_CUSTOM | + GIT_CREDTYPE_SSH_INTERACTIVE, + t->owner->cred_acquire_payload); + + if (error == GIT_PASSTHROUGH) + no_callback = 1; + else if (error < 0) goto on_error; - - if (!t->cred) { + else if (!t->cred) { giterr_set(GITERR_SSH, "Callback failed to initialize SSH credentials"); goto on_error; } - } else { - giterr_set(GITERR_SSH, "Cannot set up SSH connection without credentials"); + } + + if (no_callback) { + giterr_set(GITERR_SSH, "authentication required but no callback set"); goto on_error; } + assert(t->cred); if (_git_ssh_session_create(&session, s->socket) < 0) |