summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Straub <bs@github.com>2013-01-31 10:44:57 -0800
committerBen Straub <bs@github.com>2013-01-31 10:44:57 -0800
commit7602cb7c0ea0d69efd30640af234be20393bf57c (patch)
tree35fb50d5a1e118990f3f1f11b670371febae537c
parent2234b2b03153c03fc6d502dd61ae55e659be4b8b (diff)
downloadlibgit2-7602cb7c0ea0d69efd30640af234be20393bf57c.tar.gz
Add user-from-url param to auth callback
-rw-r--r--examples/network/clone.c1
-rw-r--r--include/git2/cred_helpers.h3
-rw-r--r--include/git2/transport.h3
-rw-r--r--src/transports/cred_helpers.c21
-rw-r--r--src/transports/http.c1
-rw-r--r--tests-clar/network/cred.c33
-rw-r--r--tests-clar/online/push.c8
7 files changed, 62 insertions, 8 deletions
diff --git a/examples/network/clone.c b/examples/network/clone.c
index 63072eea0..5b0a81073 100644
--- a/examples/network/clone.c
+++ b/examples/network/clone.c
@@ -61,6 +61,7 @@ static void checkout_progress(const char *path, size_t cur, size_t tot, void *pa
static int cred_acquire(git_cred **out,
const char * UNUSED(url),
+ const char * UNUSED(username_from_url),
unsigned int UNUSED(allowed_types),
void * UNUSED(payload))
{
diff --git a/include/git2/cred_helpers.h b/include/git2/cred_helpers.h
index 7c213c8dd..e3eb91d6c 100644
--- a/include/git2/cred_helpers.h
+++ b/include/git2/cred_helpers.h
@@ -34,6 +34,8 @@ typedef struct git_cred_userpass_payload {
*
* @param cred The newly created credential object.
* @param url The resource for which we are demanding a credential.
+ * @param username_from_url The username that was embedded in a "user@host"
+ * remote url, or NULL if not included.
* @param allowed_types A bitmask stating which cred types are OK to return.
* @param payload The payload provided when specifying this callback. (This is
* interpreted as a `git_cred_userpass_payload*`.)
@@ -41,6 +43,7 @@ typedef struct git_cred_userpass_payload {
GIT_EXTERN(int) git_cred_userpass(
git_cred **cred,
const char *url,
+ const char *user_from_url,
unsigned int allowed_types,
void *payload);
diff --git a/include/git2/transport.h b/include/git2/transport.h
index 4945ff151..469b43f72 100644
--- a/include/git2/transport.h
+++ b/include/git2/transport.h
@@ -62,6 +62,8 @@ GIT_EXTERN(int) git_cred_userpass_plaintext_new(
*
* @param cred The newly created credential object.
* @param url The resource for which we are demanding a credential.
+ * @param username_from_url The username that was embedded in a "user@host"
+ * remote url, or NULL if not included.
* @param allowed_types A bitmask stating which cred types are OK to return.
* @param payload The payload provided when specifying this callback.
* @return 0 for success or an error code for failure
@@ -69,6 +71,7 @@ GIT_EXTERN(int) git_cred_userpass_plaintext_new(
typedef int (*git_cred_acquire_cb)(
git_cred **cred,
const char *url,
+ const char *username_from_url,
unsigned int allowed_types,
void *payload);
diff --git a/src/transports/cred_helpers.c b/src/transports/cred_helpers.c
index 8d8eb9990..a05d5e874 100644
--- a/src/transports/cred_helpers.c
+++ b/src/transports/cred_helpers.c
@@ -11,17 +11,34 @@
int git_cred_userpass(
git_cred **cred,
const char *url,
+ const char *user_from_url,
unsigned int allowed_types,
void *payload)
{
git_cred_userpass_payload *userpass = (git_cred_userpass_payload*)payload;
+ const char *effective_username = NULL;
GIT_UNUSED(url);
- if (!userpass || !userpass->username || !userpass->password) return -1;
+ if (!userpass || !userpass->password) return -1;
+
+ /* Username resolution: a username can be passed with the URL, the
+ * credentials payload, or both. Here's what we do.
+ *
+ * | Payload | URL | Used |
+ * +-------------+----------+-----------+
+ * | yes | no | payload |
+ * | yes | yes | payload |
+ * | no | yes | url |
+ * | no | no | FAIL |
+ */
+ effective_username = userpass->username;
+ if (!userpass->username && user_from_url)
+ effective_username = user_from_url;
+ if (!effective_username) return -1;
if ((GIT_CREDTYPE_USERPASS_PLAINTEXT & allowed_types) == 0 ||
- git_cred_userpass_plaintext_new(cred, userpass->username, userpass->password) < 0)
+ git_cred_userpass_plaintext_new(cred, effective_username, userpass->password) < 0)
return -1;
return 0;
diff --git a/src/transports/http.c b/src/transports/http.c
index e5bb1071f..144906474 100644
--- a/src/transports/http.c
+++ b/src/transports/http.c
@@ -257,6 +257,7 @@ static int on_headers_complete(http_parser *parser)
if (t->owner->cred_acquire_cb(&t->cred,
t->owner->url,
+ t->user_from_url,
allowed_types,
t->owner->cred_acquire_payload) < 0)
return PARSE_ERROR_GENERIC;
diff --git a/tests-clar/network/cred.c b/tests-clar/network/cred.c
index b7f45c23b..6994cc0c3 100644
--- a/tests-clar/network/cred.c
+++ b/tests-clar/network/cred.c
@@ -6,14 +6,14 @@ void test_network_cred__stock_userpass_validates_args(void)
{
git_cred_userpass_payload payload = {0};
- cl_git_fail(git_cred_userpass(NULL, NULL, 0, NULL));
+ cl_git_fail(git_cred_userpass(NULL, NULL, NULL, 0, NULL));
payload.username = "user";
- cl_git_fail(git_cred_userpass(NULL, NULL, 0, &payload));
+ cl_git_fail(git_cred_userpass(NULL, NULL, NULL, 0, &payload));
payload.username = NULL;
payload.username = "pass";
- cl_git_fail(git_cred_userpass(NULL, NULL, 0, &payload));
+ cl_git_fail(git_cred_userpass(NULL, NULL, NULL, 0, &payload));
}
void test_network_cred__stock_userpass_validates_that_method_is_allowed(void)
@@ -21,7 +21,30 @@ void test_network_cred__stock_userpass_validates_that_method_is_allowed(void)
git_cred *cred;
git_cred_userpass_payload payload = {"user", "pass"};
- cl_git_fail(git_cred_userpass(&cred, NULL, 0, &payload));
- cl_git_pass(git_cred_userpass(&cred, NULL, GIT_CREDTYPE_USERPASS_PLAINTEXT, &payload));
+ cl_git_fail(git_cred_userpass(&cred, NULL, NULL, 0, &payload));
+ cl_git_pass(git_cred_userpass(&cred, NULL, NULL, GIT_CREDTYPE_USERPASS_PLAINTEXT, &payload));
+ cred->free(cred);
+}
+
+void test_network_cred__stock_userpass_properly_handles_username_in_url(void)
+{
+ git_cred *cred;
+ git_cred_userpass_plaintext *plain;
+ git_cred_userpass_payload payload = {"alice", "password"};
+
+ cl_git_pass(git_cred_userpass(&cred, NULL, NULL, GIT_CREDTYPE_USERPASS_PLAINTEXT, &payload));
+ plain = (git_cred_userpass_plaintext*)cred;
+ cl_assert_equal_s(plain->username, "alice");
+ cred->free(cred);
+
+ cl_git_pass(git_cred_userpass(&cred, NULL, "bob", GIT_CREDTYPE_USERPASS_PLAINTEXT, &payload));
+ plain = (git_cred_userpass_plaintext*)cred;
+ cl_assert_equal_s(plain->username, "alice");
+ cred->free(cred);
+
+ payload.username = NULL;
+ cl_git_pass(git_cred_userpass(&cred, NULL, "bob", GIT_CREDTYPE_USERPASS_PLAINTEXT, &payload));
+ plain = (git_cred_userpass_plaintext*)cred;
+ cl_assert_equal_s(plain->username, "bob");
cred->free(cred);
}
diff --git a/tests-clar/online/push.c b/tests-clar/online/push.c
index 8f92cdd5e..56183473a 100644
--- a/tests-clar/online/push.c
+++ b/tests-clar/online/push.c
@@ -30,9 +30,15 @@ static git_oid _tag_tree;
static git_oid _tag_blob;
static git_oid _tag_lightweight;
-static int cred_acquire_cb(git_cred **cred, const char *url, unsigned int allowed_types, void *payload)
+static int cred_acquire_cb(
+ git_cred **cred,
+ const char *url,
+ const char *user_from_url,
+ unsigned int allowed_types,
+ void *payload)
{
GIT_UNUSED(url);
+ GIT_UNUSED(user_from_url);
*((bool*)payload) = true;