Commit a32d684f by Vicent Marti

Merge pull request #2282 from libgit2/cmn/remote-easier-bind

A few niceties for binding authors
parents dac95e4a bc0a6198
...@@ -468,6 +468,9 @@ struct git_remote_callbacks { ...@@ -468,6 +468,9 @@ struct git_remote_callbacks {
/** /**
* This will be called if the remote host requires * This will be called if the remote host requires
* authentication in order to connect to it. * 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); 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( ...@@ -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); 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. * Get the statistics structure that is filled in by the fetch operation.
*/ */
GIT_EXTERN(const git_transfer_progress *) git_remote_stats(git_remote *remote); GIT_EXTERN(const git_transfer_progress *) git_remote_stats(git_remote *remote);
......
...@@ -1253,6 +1253,13 @@ int git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *cal ...@@ -1253,6 +1253,13 @@ int git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *cal
return 0; 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) int git_remote_set_transport(git_remote *remote, git_transport *transport)
{ {
assert(remote && transport); assert(remote && transport);
......
...@@ -248,6 +248,7 @@ static int on_headers_complete(http_parser *parser) ...@@ -248,6 +248,7 @@ static int on_headers_complete(http_parser *parser)
http_subtransport *t = ctx->t; http_subtransport *t = ctx->t;
http_stream *s = ctx->s; http_stream *s = ctx->s;
git_buf buf = GIT_BUF_INIT; git_buf buf = GIT_BUF_INIT;
int error = 0, no_callback = 0;
/* Both parse_header_name and parse_header_value are populated /* Both parse_header_name and parse_header_value are populated
* and ready for consumption. */ * and ready for consumption. */
...@@ -256,29 +257,43 @@ static int on_headers_complete(http_parser *parser) ...@@ -256,29 +257,43 @@ static int on_headers_complete(http_parser *parser)
return t->parse_error = PARSE_ERROR_GENERIC; return t->parse_error = PARSE_ERROR_GENERIC;
/* Check for an authentication failure. */ /* Check for an authentication failure. */
if (parser->status_code == 401 && if (parser->status_code == 401 &&
get_verb == s->verb && get_verb == s->verb) {
t->owner->cred_acquire_cb) { if (!t->owner->cred_acquire_payload) {
int allowed_types = 0; 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, if (no_callback) {
&allowed_types, &t->auth_mechanism) < 0) giterr_set(GITERR_NET, "authentication required but no callback set");
return t->parse_error = PARSE_ERROR_GENERIC; 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;
} }
} }
......
...@@ -387,6 +387,7 @@ static int _git_ssh_setup_conn( ...@@ -387,6 +387,7 @@ static int _git_ssh_setup_conn(
{ {
char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL; char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL;
const char *default_port="22"; const char *default_port="22";
int no_callback = 0;
ssh_stream *s; ssh_stream *s;
LIBSSH2_SESSION* session=NULL; LIBSSH2_SESSION* session=NULL;
LIBSSH2_CHANNEL* channel=NULL; LIBSSH2_CHANNEL* channel=NULL;
...@@ -413,24 +414,31 @@ static int _git_ssh_setup_conn( ...@@ -413,24 +414,31 @@ static int _git_ssh_setup_conn(
if (user && pass) { if (user && pass) {
if (git_cred_userpass_plaintext_new(&t->cred, user, pass) < 0) if (git_cred_userpass_plaintext_new(&t->cred, user, pass) < 0)
goto on_error; goto on_error;
} else if (t->owner->cred_acquire_cb) { } else if (!t->owner->cred_acquire_cb) {
if (t->owner->cred_acquire_cb( no_callback = 1;
&t->cred, t->owner->url, user, } else {
GIT_CREDTYPE_USERPASS_PLAINTEXT | int error;
GIT_CREDTYPE_SSH_KEY | error = t->owner->cred_acquire_cb(&t->cred, t->owner->url, user,
GIT_CREDTYPE_SSH_INTERACTIVE | GIT_CREDTYPE_USERPASS_PLAINTEXT |
GIT_CREDTYPE_SSH_CUSTOM, GIT_CREDTYPE_SSH_KEY | GIT_CREDTYPE_SSH_CUSTOM |
t->owner->cred_acquire_payload) < 0) GIT_CREDTYPE_SSH_INTERACTIVE,
t->owner->cred_acquire_payload);
if (error == GIT_PASSTHROUGH)
no_callback = 1;
else if (error < 0)
goto on_error; goto on_error;
else if (!t->cred) {
if (!t->cred) {
giterr_set(GITERR_SSH, "Callback failed to initialize SSH credentials"); giterr_set(GITERR_SSH, "Callback failed to initialize SSH credentials");
goto on_error; 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; goto on_error;
} }
assert(t->cred); assert(t->cred);
if (_git_ssh_session_create(&session, s->socket) < 0) if (_git_ssh_session_create(&session, s->socket) < 0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment