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 {
/**
* 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);
......
......@@ -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);
......
......@@ -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,9 +257,12 @@ 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) {
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,
......@@ -268,19 +272,30 @@ static int on_headers_complete(http_parser *parser)
if (allowed_types &&
(!t->cred || 0 == (t->cred->credtype & allowed_types))) {
if (t->owner->cred_acquire_cb(&t->cred,
error = 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;
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 (no_callback) {
giterr_set(GITERR_NET, "authentication required but no callback set");
return t->parse_error = PARSE_ERROR_GENERIC;
}
}
/* Check for a redirect.
* Right now we only permit a redirect to the same hostname. */
......
......@@ -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,
} 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_INTERACTIVE |
GIT_CREDTYPE_SSH_CUSTOM,
t->owner->cred_acquire_payload) < 0)
goto on_error;
GIT_CREDTYPE_SSH_KEY | GIT_CREDTYPE_SSH_CUSTOM |
GIT_CREDTYPE_SSH_INTERACTIVE,
t->owner->cred_acquire_payload);
if (!t->cred) {
if (error == GIT_PASSTHROUGH)
no_callback = 1;
else if (error < 0)
goto on_error;
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)
......
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