diff --git a/include/git2/cred_helpers.h b/include/git2/cred_helpers.h new file mode 100644 index 000000000..7c213c8dd --- /dev/null +++ b/include/git2/cred_helpers.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ +#ifndef INCLUDE_git_cred_helpers_h__ +#define INCLUDE_git_cred_helpers_h__ + +#include "git2/transport.h" + +/** + * @file git2/cred_helpers.h + * @brief Utility functions for credential management + * @defgroup git_cred_helpers credential management helpers + * @ingroup Git + * @{ + */ +GIT_BEGIN_DECL + +/** + * Payload for git_cred_stock_userpass_plaintext. + */ +typedef struct git_cred_userpass_payload { + char *username; + char *password; +} git_cred_userpass_payload; + + +/** + * Stock callback usable as a git_cred_acquire_cb. This calls + * git_cred_userpass_plaintext_new unless the protocol has not specified + * GIT_CREDTYPE_USERPASS_PLAINTEXT as an allowed type. + * + * @param cred The newly created credential object. + * @param url The resource for which we are demanding a credential. + * @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*`.) + */ +GIT_EXTERN(int) git_cred_userpass( + git_cred **cred, + const char *url, + unsigned int allowed_types, + void *payload); + + +/** @} */ +GIT_END_DECL +#endif diff --git a/include/git2/transport.h b/include/git2/transport.h index fba5fb920..1aa87cabe 100644 --- a/include/git2/transport.h +++ b/include/git2/transport.h @@ -61,6 +61,7 @@ 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 allowed_types A bitmask stating which cred types are OK to return. + * @param payload The payload provided when specifying this callback. */ typedef int (*git_cred_acquire_cb)( git_cred **cred, diff --git a/src/transports/cred.c b/src/transports/cred.c index 85472bd6a..ecb026062 100644 --- a/src/transports/cred.c +++ b/src/transports/cred.c @@ -7,6 +7,7 @@ #include "git2.h" #include "smart.h" +#include "git2/cred_helpers.h" static void plaintext_free(struct git_cred *cred) { diff --git a/src/transports/cred_helpers.c b/src/transports/cred_helpers.c new file mode 100644 index 000000000..8d8eb9990 --- /dev/null +++ b/src/transports/cred_helpers.c @@ -0,0 +1,28 @@ +/* + * Copyright (C) the libgit2 contributors. All rights reserved. + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "common.h" +#include "git2/cred_helpers.h" + +int git_cred_userpass( + git_cred **cred, + const char *url, + unsigned int allowed_types, + void *payload) +{ + git_cred_userpass_payload *userpass = (git_cred_userpass_payload*)payload; + + GIT_UNUSED(url); + + if (!userpass || !userpass->username || !userpass->password) return -1; + + if ((GIT_CREDTYPE_USERPASS_PLAINTEXT & allowed_types) == 0 || + git_cred_userpass_plaintext_new(cred, userpass->username, userpass->password) < 0) + return -1; + + return 0; +} diff --git a/tests-clar/network/cred.c b/tests-clar/network/cred.c new file mode 100644 index 000000000..0fdcf3aa0 --- /dev/null +++ b/tests-clar/network/cred.c @@ -0,0 +1,27 @@ +#include "clar_libgit2.h" + +#include "git2/cred_helpers.h" + +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)); + + payload.username = "user"; + cl_git_fail(git_cred_userpass(NULL, NULL, 0, &payload)); + + payload.username = NULL; + payload.username = "pass"; + cl_git_fail(git_cred_userpass(NULL, NULL, 0, &payload)); +} + +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)); + git__free(cred); +} diff --git a/tests-clar/online/clone.c b/tests-clar/online/clone.c index 082ed52b3..8226bd054 100644 --- a/tests-clar/online/clone.c +++ b/tests-clar/online/clone.c @@ -1,6 +1,7 @@ #include "clar_libgit2.h" #include "git2/clone.h" +#include "git2/cred_helpers.h" #include "repository.h" #define LIVE_REPO_URL "http://github.com/libgit2/TestGitRepository" @@ -121,7 +122,7 @@ static int update_tips(const char *refname, const git_oid *a, const git_oid *b, return 0; } -void test_clone_network__custom_remote_callbacks(void) +void test_online_clone__custom_remote_callbacks(void) { git_remote_callbacks remote_callbacks = GIT_REMOTE_CALLBACKS_INIT; int callcount = 0; @@ -134,39 +135,18 @@ void test_clone_network__custom_remote_callbacks(void) cl_assert(callcount > 0); } -struct cred_user_pass { - const char *user; - const char *pass; -}; - -static int cred_acquire( - git_cred **cred, - const char *url, - unsigned int allowed_types, - void *payload) -{ - struct cred_user_pass *user_pass = (struct cred_user_pass*)payload; - - GIT_UNUSED(url); - if ((GIT_CREDTYPE_USERPASS_PLAINTEXT & allowed_types) == 0 || - git_cred_userpass_plaintext_new(cred, user_pass->user, user_pass->pass) < 0) - return -1; - - return 0; -} - -void test_clone_network__credentials(void) +void test_online_clone__credentials(void) { /* Remote URL environment variable must be set. User and password are optional. */ const char *remote_url = cl_getenv("GITTEST_REMOTE_URL"); - struct cred_user_pass user_pass = { + git_cred_userpass_payload user_pass = { cl_getenv("GITTEST_REMOTE_USER"), cl_getenv("GITTEST_REMOTE_PASS") }; if (!remote_url) return; - g_options.cred_acquire_cb = cred_acquire; + g_options.cred_acquire_cb = git_cred_userpass; g_options.cred_acquire_payload = &user_pass; cl_git_pass(git_clone(&g_repo, remote_url, "./foo", &g_options));