diff options
Diffstat (limited to 'src/libgit2/transports/credential.c')
-rw-r--r-- | src/libgit2/transports/credential.c | 486 |
1 files changed, 486 insertions, 0 deletions
diff --git a/src/libgit2/transports/credential.c b/src/libgit2/transports/credential.c new file mode 100644 index 000000000..6e00b0282 --- /dev/null +++ b/src/libgit2/transports/credential.c @@ -0,0 +1,486 @@ +/* + * 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/credential.h" +#include "git2/sys/credential.h" +#include "git2/credential_helpers.h" + +static int git_credential_ssh_key_type_new( + git_credential **cred, + const char *username, + const char *publickey, + const char *privatekey, + const char *passphrase, + git_credential_t credtype); + +int git_credential_has_username(git_credential *cred) +{ + if (cred->credtype == GIT_CREDENTIAL_DEFAULT) + return 0; + + return 1; +} + +const char *git_credential_get_username(git_credential *cred) +{ + switch (cred->credtype) { + case GIT_CREDENTIAL_USERNAME: + { + git_credential_username *c = (git_credential_username *) cred; + return c->username; + } + case GIT_CREDENTIAL_USERPASS_PLAINTEXT: + { + git_credential_userpass_plaintext *c = (git_credential_userpass_plaintext *) cred; + return c->username; + } + case GIT_CREDENTIAL_SSH_KEY: + case GIT_CREDENTIAL_SSH_MEMORY: + { + git_credential_ssh_key *c = (git_credential_ssh_key *) cred; + return c->username; + } + case GIT_CREDENTIAL_SSH_CUSTOM: + { + git_credential_ssh_custom *c = (git_credential_ssh_custom *) cred; + return c->username; + } + case GIT_CREDENTIAL_SSH_INTERACTIVE: + { + git_credential_ssh_interactive *c = (git_credential_ssh_interactive *) cred; + return c->username; + } + + default: + return NULL; + } +} + +static void plaintext_free(struct git_credential *cred) +{ + git_credential_userpass_plaintext *c = (git_credential_userpass_plaintext *)cred; + + git__free(c->username); + + /* Zero the memory which previously held the password */ + if (c->password) { + size_t pass_len = strlen(c->password); + git__memzero(c->password, pass_len); + git__free(c->password); + } + + git__free(c); +} + +int git_credential_userpass_plaintext_new( + git_credential **cred, + const char *username, + const char *password) +{ + git_credential_userpass_plaintext *c; + + GIT_ASSERT_ARG(cred); + GIT_ASSERT_ARG(username); + GIT_ASSERT_ARG(password); + + c = git__malloc(sizeof(git_credential_userpass_plaintext)); + GIT_ERROR_CHECK_ALLOC(c); + + c->parent.credtype = GIT_CREDENTIAL_USERPASS_PLAINTEXT; + c->parent.free = plaintext_free; + c->username = git__strdup(username); + + if (!c->username) { + git__free(c); + return -1; + } + + c->password = git__strdup(password); + + if (!c->password) { + git__free(c->username); + git__free(c); + return -1; + } + + *cred = &c->parent; + return 0; +} + +static void ssh_key_free(struct git_credential *cred) +{ + git_credential_ssh_key *c = + (git_credential_ssh_key *)cred; + + git__free(c->username); + + if (c->privatekey) { + /* Zero the memory which previously held the private key */ + size_t key_len = strlen(c->privatekey); + git__memzero(c->privatekey, key_len); + git__free(c->privatekey); + } + + if (c->passphrase) { + /* Zero the memory which previously held the passphrase */ + size_t pass_len = strlen(c->passphrase); + git__memzero(c->passphrase, pass_len); + git__free(c->passphrase); + } + + if (c->publickey) { + /* Zero the memory which previously held the public key */ + size_t key_len = strlen(c->publickey); + git__memzero(c->publickey, key_len); + git__free(c->publickey); + } + + git__free(c); +} + +static void ssh_interactive_free(struct git_credential *cred) +{ + git_credential_ssh_interactive *c = (git_credential_ssh_interactive *)cred; + + git__free(c->username); + + git__free(c); +} + +static void ssh_custom_free(struct git_credential *cred) +{ + git_credential_ssh_custom *c = (git_credential_ssh_custom *)cred; + + git__free(c->username); + + if (c->publickey) { + /* Zero the memory which previously held the publickey */ + size_t key_len = strlen(c->publickey); + git__memzero(c->publickey, key_len); + git__free(c->publickey); + } + + git__free(c); +} + +static void default_free(struct git_credential *cred) +{ + git_credential_default *c = (git_credential_default *)cred; + + git__free(c); +} + +static void username_free(struct git_credential *cred) +{ + git__free(cred); +} + +int git_credential_ssh_key_new( + git_credential **cred, + const char *username, + const char *publickey, + const char *privatekey, + const char *passphrase) +{ + return git_credential_ssh_key_type_new( + cred, + username, + publickey, + privatekey, + passphrase, + GIT_CREDENTIAL_SSH_KEY); +} + +int git_credential_ssh_key_memory_new( + git_credential **cred, + const char *username, + const char *publickey, + const char *privatekey, + const char *passphrase) +{ +#ifdef GIT_SSH_MEMORY_CREDENTIALS + return git_credential_ssh_key_type_new( + cred, + username, + publickey, + privatekey, + passphrase, + GIT_CREDENTIAL_SSH_MEMORY); +#else + GIT_UNUSED(cred); + GIT_UNUSED(username); + GIT_UNUSED(publickey); + GIT_UNUSED(privatekey); + GIT_UNUSED(passphrase); + + git_error_set(GIT_ERROR_INVALID, + "this version of libgit2 was not built with ssh memory credentials."); + return -1; +#endif +} + +static int git_credential_ssh_key_type_new( + git_credential **cred, + const char *username, + const char *publickey, + const char *privatekey, + const char *passphrase, + git_credential_t credtype) +{ + git_credential_ssh_key *c; + + GIT_ASSERT_ARG(username); + GIT_ASSERT_ARG(cred); + GIT_ASSERT_ARG(privatekey); + + c = git__calloc(1, sizeof(git_credential_ssh_key)); + GIT_ERROR_CHECK_ALLOC(c); + + c->parent.credtype = credtype; + c->parent.free = ssh_key_free; + + c->username = git__strdup(username); + GIT_ERROR_CHECK_ALLOC(c->username); + + c->privatekey = git__strdup(privatekey); + GIT_ERROR_CHECK_ALLOC(c->privatekey); + + if (publickey) { + c->publickey = git__strdup(publickey); + GIT_ERROR_CHECK_ALLOC(c->publickey); + } + + if (passphrase) { + c->passphrase = git__strdup(passphrase); + GIT_ERROR_CHECK_ALLOC(c->passphrase); + } + + *cred = &c->parent; + return 0; +} + +int git_credential_ssh_interactive_new( + git_credential **out, + const char *username, + git_credential_ssh_interactive_cb prompt_callback, + void *payload) +{ + git_credential_ssh_interactive *c; + + GIT_ASSERT_ARG(out); + GIT_ASSERT_ARG(username); + GIT_ASSERT_ARG(prompt_callback); + + c = git__calloc(1, sizeof(git_credential_ssh_interactive)); + GIT_ERROR_CHECK_ALLOC(c); + + c->parent.credtype = GIT_CREDENTIAL_SSH_INTERACTIVE; + c->parent.free = ssh_interactive_free; + + c->username = git__strdup(username); + GIT_ERROR_CHECK_ALLOC(c->username); + + c->prompt_callback = prompt_callback; + c->payload = payload; + + *out = &c->parent; + return 0; +} + +int git_credential_ssh_key_from_agent(git_credential **cred, const char *username) { + git_credential_ssh_key *c; + + GIT_ASSERT_ARG(username); + GIT_ASSERT_ARG(cred); + + c = git__calloc(1, sizeof(git_credential_ssh_key)); + GIT_ERROR_CHECK_ALLOC(c); + + c->parent.credtype = GIT_CREDENTIAL_SSH_KEY; + c->parent.free = ssh_key_free; + + c->username = git__strdup(username); + GIT_ERROR_CHECK_ALLOC(c->username); + + c->privatekey = NULL; + + *cred = &c->parent; + return 0; +} + +int git_credential_ssh_custom_new( + git_credential **cred, + const char *username, + const char *publickey, + size_t publickey_len, + git_credential_sign_cb sign_callback, + void *payload) +{ + git_credential_ssh_custom *c; + + GIT_ASSERT_ARG(username); + GIT_ASSERT_ARG(cred); + + c = git__calloc(1, sizeof(git_credential_ssh_custom)); + GIT_ERROR_CHECK_ALLOC(c); + + c->parent.credtype = GIT_CREDENTIAL_SSH_CUSTOM; + c->parent.free = ssh_custom_free; + + c->username = git__strdup(username); + GIT_ERROR_CHECK_ALLOC(c->username); + + if (publickey_len > 0) { + c->publickey = git__malloc(publickey_len); + GIT_ERROR_CHECK_ALLOC(c->publickey); + + memcpy(c->publickey, publickey, publickey_len); + } + + c->publickey_len = publickey_len; + c->sign_callback = sign_callback; + c->payload = payload; + + *cred = &c->parent; + return 0; +} + +int git_credential_default_new(git_credential **cred) +{ + git_credential_default *c; + + GIT_ASSERT_ARG(cred); + + c = git__calloc(1, sizeof(git_credential_default)); + GIT_ERROR_CHECK_ALLOC(c); + + c->credtype = GIT_CREDENTIAL_DEFAULT; + c->free = default_free; + + *cred = c; + return 0; +} + +int git_credential_username_new(git_credential **cred, const char *username) +{ + git_credential_username *c; + size_t len, allocsize; + + GIT_ASSERT_ARG(cred); + + len = strlen(username); + + GIT_ERROR_CHECK_ALLOC_ADD(&allocsize, sizeof(git_credential_username), len); + GIT_ERROR_CHECK_ALLOC_ADD(&allocsize, allocsize, 1); + c = git__malloc(allocsize); + GIT_ERROR_CHECK_ALLOC(c); + + c->parent.credtype = GIT_CREDENTIAL_USERNAME; + c->parent.free = username_free; + memcpy(c->username, username, len + 1); + + *cred = (git_credential *) c; + return 0; +} + +void git_credential_free(git_credential *cred) +{ + if (!cred) + return; + + cred->free(cred); +} + +/* Deprecated credential functions */ + +#ifndef GIT_DEPRECATE_HARD +int git_cred_has_username(git_credential *cred) +{ + return git_credential_has_username(cred); +} + +const char *git_cred_get_username(git_credential *cred) +{ + return git_credential_get_username(cred); +} + +int git_cred_userpass_plaintext_new( + git_credential **out, + const char *username, + const char *password) +{ + return git_credential_userpass_plaintext_new(out,username, password); +} + +int git_cred_default_new(git_credential **out) +{ + return git_credential_default_new(out); +} + +int git_cred_username_new(git_credential **out, const char *username) +{ + return git_credential_username_new(out, username); +} + +int git_cred_ssh_key_new( + git_credential **out, + const char *username, + const char *publickey, + const char *privatekey, + const char *passphrase) +{ + return git_credential_ssh_key_new(out, username, + publickey, privatekey, passphrase); +} + +int git_cred_ssh_key_memory_new( + git_credential **out, + const char *username, + const char *publickey, + const char *privatekey, + const char *passphrase) +{ + return git_credential_ssh_key_memory_new(out, username, + publickey, privatekey, passphrase); +} + +int git_cred_ssh_interactive_new( + git_credential **out, + const char *username, + git_credential_ssh_interactive_cb prompt_callback, + void *payload) +{ + return git_credential_ssh_interactive_new(out, username, + prompt_callback, payload); +} + +int git_cred_ssh_key_from_agent( + git_credential **out, + const char *username) +{ + return git_credential_ssh_key_from_agent(out, username); +} + +int git_cred_ssh_custom_new( + git_credential **out, + const char *username, + const char *publickey, + size_t publickey_len, + git_credential_sign_cb sign_callback, + void *payload) +{ + return git_credential_ssh_custom_new(out, username, + publickey, publickey_len, sign_callback, payload); +} + +void git_cred_free(git_credential *cred) +{ + git_credential_free(cred); +} +#endif |