mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-04 11:52:09 +00:00
Introduce git_cred_default for NTLM/SPNEGO auth
This commit is contained in:
parent
80fc7d6bf0
commit
84efffc33a
@ -31,13 +31,16 @@ GIT_BEGIN_DECL
|
|||||||
/** Authentication type requested */
|
/** Authentication type requested */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
/* git_cred_userpass_plaintext */
|
/* git_cred_userpass_plaintext */
|
||||||
GIT_CREDTYPE_USERPASS_PLAINTEXT = (1u << 0),
|
GIT_CREDTYPE_USERPASS_PLAINTEXT = (1u << 0),
|
||||||
|
|
||||||
/* git_cred_ssh_key */
|
/* git_cred_ssh_key */
|
||||||
GIT_CREDTYPE_SSH_KEY = (1u << 1),
|
GIT_CREDTYPE_SSH_KEY = (1u << 1),
|
||||||
|
|
||||||
/* git_cred_ssh_custom */
|
/* git_cred_ssh_custom */
|
||||||
GIT_CREDTYPE_SSH_CUSTOM = (1u << 2),
|
GIT_CREDTYPE_SSH_CUSTOM = (1u << 2),
|
||||||
|
|
||||||
|
/* git_cred_default */
|
||||||
|
GIT_CREDTYPE_DEFAULT = (1u << 3),
|
||||||
} git_credtype_t;
|
} git_credtype_t;
|
||||||
|
|
||||||
/* The base structure for all credential types */
|
/* The base structure for all credential types */
|
||||||
@ -48,7 +51,7 @@ struct git_cred {
|
|||||||
void (*free)(git_cred *cred);
|
void (*free)(git_cred *cred);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A plaintext username and password */
|
/** A plaintext username and password */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
git_cred parent;
|
git_cred parent;
|
||||||
char *username;
|
char *username;
|
||||||
@ -84,6 +87,9 @@ typedef struct git_cred_ssh_custom {
|
|||||||
void *sign_data;
|
void *sign_data;
|
||||||
} git_cred_ssh_custom;
|
} git_cred_ssh_custom;
|
||||||
|
|
||||||
|
/** A key for NTLM/Kerberos "default" credentials */
|
||||||
|
typedef struct git_cred git_cred_default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether a credential object contains username information.
|
* Check whether a credential object contains username information.
|
||||||
*
|
*
|
||||||
@ -150,6 +156,14 @@ GIT_EXTERN(int) git_cred_ssh_custom_new(
|
|||||||
git_cred_sign_callback sign_fn,
|
git_cred_sign_callback sign_fn,
|
||||||
void *sign_data);
|
void *sign_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a "default" credential usable for Negotiate mechanisms like NTLM
|
||||||
|
* or Kerberos authentication.
|
||||||
|
*
|
||||||
|
* @return 0 for success or an error code for failure
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_cred_default_new(git_cred **out);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signature of a function which acquires a credential object.
|
* Signature of a function which acquires a credential object.
|
||||||
*
|
*
|
||||||
|
@ -29,6 +29,10 @@ int git_cred_has_username(git_cred *cred)
|
|||||||
ret = !!c->username;
|
ret = !!c->username;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case GIT_CREDTYPE_DEFAULT: {
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -115,6 +119,13 @@ static void ssh_custom_free(struct git_cred *cred)
|
|||||||
git__free(c);
|
git__free(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void default_free(struct git_cred *cred)
|
||||||
|
{
|
||||||
|
git_cred_default *c = (git_cred_default *)cred;
|
||||||
|
|
||||||
|
git__free(c);
|
||||||
|
}
|
||||||
|
|
||||||
int git_cred_ssh_key_new(
|
int git_cred_ssh_key_new(
|
||||||
git_cred **cred,
|
git_cred **cred,
|
||||||
const char *username,
|
const char *username,
|
||||||
@ -191,3 +202,19 @@ int git_cred_ssh_custom_new(
|
|||||||
*cred = &c->parent;
|
*cred = &c->parent;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int git_cred_default_new(git_cred **cred)
|
||||||
|
{
|
||||||
|
git_cred_default *c;
|
||||||
|
|
||||||
|
assert(cred);
|
||||||
|
|
||||||
|
c = git__calloc(1, sizeof(git_cred_default));
|
||||||
|
GITERR_CHECK_ALLOC(c);
|
||||||
|
|
||||||
|
c->credtype = GIT_CREDTYPE_DEFAULT;
|
||||||
|
c->free = default_free;
|
||||||
|
|
||||||
|
*cred = c;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -52,6 +52,7 @@ static const int no_check_cert_flags = SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GIT_WINHTTP_AUTH_BASIC = 1,
|
GIT_WINHTTP_AUTH_BASIC = 1,
|
||||||
|
GIT_WINHTTP_AUTH_NEGOTIATE = 2,
|
||||||
} winhttp_authmechanism_t;
|
} winhttp_authmechanism_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -138,6 +139,22 @@ on_error:
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int apply_default_credentials(HINTERNET request)
|
||||||
|
{
|
||||||
|
/* If we are explicitly asked to deliver default credentials, turn set
|
||||||
|
* the security level to low which will guarantee they are delivered.
|
||||||
|
* The default is "medium" which applies to the intranet and sounds
|
||||||
|
* like it would correspond to Internet Explorer security zones, but
|
||||||
|
* in fact does not.
|
||||||
|
*/
|
||||||
|
DWORD data = WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW;
|
||||||
|
|
||||||
|
if (!WinHttpSetOption(request, WINHTTP_OPTION_AUTOLOGON_POLICY, &data, sizeof(DWORD)))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int winhttp_stream_connect(winhttp_stream *s)
|
static int winhttp_stream_connect(winhttp_stream *s)
|
||||||
{
|
{
|
||||||
winhttp_subtransport *t = OWNING_SUBTRANSPORT(s);
|
winhttp_subtransport *t = OWNING_SUBTRANSPORT(s);
|
||||||
@ -317,6 +334,11 @@ static int winhttp_stream_connect(winhttp_stream *s)
|
|||||||
t->auth_mechanism == GIT_WINHTTP_AUTH_BASIC &&
|
t->auth_mechanism == GIT_WINHTTP_AUTH_BASIC &&
|
||||||
apply_basic_credential(s->request, t->cred) < 0)
|
apply_basic_credential(s->request, t->cred) < 0)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
else if (t->cred &&
|
||||||
|
t->cred->credtype == GIT_CREDTYPE_DEFAULT &&
|
||||||
|
t->auth_mechanism == GIT_WINHTTP_AUTH_NEGOTIATE &&
|
||||||
|
apply_default_credentials(s->request) < 0)
|
||||||
|
goto on_error;
|
||||||
|
|
||||||
/* If no other credentials have been applied and the URL has username and
|
/* If no other credentials have been applied and the URL has username and
|
||||||
* password, use those */
|
* password, use those */
|
||||||
@ -361,6 +383,12 @@ static int parse_unauthorized_response(
|
|||||||
*auth_mechanism = GIT_WINHTTP_AUTH_BASIC;
|
*auth_mechanism = GIT_WINHTTP_AUTH_BASIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((WINHTTP_AUTH_SCHEME_NTLM & supported) ||
|
||||||
|
(WINHTTP_AUTH_SCHEME_NEGOTIATE & supported)) {
|
||||||
|
*allowed_types |= GIT_CREDTYPE_DEFAULT;
|
||||||
|
*auth_mechanism = GIT_WINHTTP_AUTH_NEGOTIATE;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,14 +9,17 @@
|
|||||||
|
|
||||||
static git_repository *_repo;
|
static git_repository *_repo;
|
||||||
|
|
||||||
|
static char *_remote_url;
|
||||||
|
|
||||||
static char *_remote_ssh_key;
|
static char *_remote_ssh_key;
|
||||||
static char *_remote_ssh_pubkey;
|
static char *_remote_ssh_pubkey;
|
||||||
static char *_remote_ssh_passphrase;
|
static char *_remote_ssh_passphrase;
|
||||||
|
|
||||||
static char *_remote_url;
|
|
||||||
static char *_remote_user;
|
static char *_remote_user;
|
||||||
static char *_remote_pass;
|
static char *_remote_pass;
|
||||||
|
|
||||||
|
static char *_remote_default;
|
||||||
|
|
||||||
static int cred_acquire_cb(git_cred **, const char *, const char *, unsigned int, void *);
|
static int cred_acquire_cb(git_cred **, const char *, const char *, unsigned int, void *);
|
||||||
|
|
||||||
static git_remote *_remote;
|
static git_remote *_remote;
|
||||||
@ -47,11 +50,21 @@ static int cred_acquire_cb(
|
|||||||
GIT_UNUSED(user_from_url);
|
GIT_UNUSED(user_from_url);
|
||||||
GIT_UNUSED(payload);
|
GIT_UNUSED(payload);
|
||||||
|
|
||||||
|
if (GIT_CREDTYPE_DEFAULT & allowed_types) {
|
||||||
|
if (!_remote_default) {
|
||||||
|
printf("GITTEST_REMOTE_DEFAULT must be set to use NTLM/Negotiate credentials\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return git_cred_default_new(cred);
|
||||||
|
}
|
||||||
|
|
||||||
if (GIT_CREDTYPE_SSH_KEY & allowed_types) {
|
if (GIT_CREDTYPE_SSH_KEY & allowed_types) {
|
||||||
if (!_remote_user || !_remote_ssh_pubkey || !_remote_ssh_key || !_remote_ssh_passphrase) {
|
if (!_remote_user || !_remote_ssh_pubkey || !_remote_ssh_key || !_remote_ssh_passphrase) {
|
||||||
printf("GITTEST_REMOTE_USER, GITTEST_REMOTE_SSH_PUBKEY, GITTEST_REMOTE_SSH_KEY and GITTEST_REMOTE_SSH_PASSPHRASE must be set\n");
|
printf("GITTEST_REMOTE_USER, GITTEST_REMOTE_SSH_PUBKEY, GITTEST_REMOTE_SSH_KEY and GITTEST_REMOTE_SSH_PASSPHRASE must be set\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return git_cred_ssh_key_new(cred, _remote_user, _remote_ssh_pubkey, _remote_ssh_key, _remote_ssh_passphrase);
|
return git_cred_ssh_key_new(cred, _remote_user, _remote_ssh_pubkey, _remote_ssh_key, _remote_ssh_passphrase);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,6 +311,7 @@ void test_online_push__initialize(void)
|
|||||||
_remote_ssh_key = cl_getenv("GITTEST_REMOTE_SSH_KEY");
|
_remote_ssh_key = cl_getenv("GITTEST_REMOTE_SSH_KEY");
|
||||||
_remote_ssh_pubkey = cl_getenv("GITTEST_REMOTE_SSH_PUBKEY");
|
_remote_ssh_pubkey = cl_getenv("GITTEST_REMOTE_SSH_PUBKEY");
|
||||||
_remote_ssh_passphrase = cl_getenv("GITTEST_REMOTE_SSH_PASSPHRASE");
|
_remote_ssh_passphrase = cl_getenv("GITTEST_REMOTE_SSH_PASSPHRASE");
|
||||||
|
_remote_default = cl_getenv("GITTEST_REMOTE_DEFAULT");
|
||||||
_remote = NULL;
|
_remote = NULL;
|
||||||
|
|
||||||
if (_remote_url) {
|
if (_remote_url) {
|
||||||
|
Loading…
Reference in New Issue
Block a user