summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/transports/cred_helpers.c3
-rw-r--r--src/transports/ssh.c69
-rw-r--r--tests/online/clone.c3
3 files changed, 41 insertions, 34 deletions
diff --git a/src/transports/cred_helpers.c b/src/transports/cred_helpers.c
index d420e3e3c..5cc9b0869 100644
--- a/src/transports/cred_helpers.c
+++ b/src/transports/cred_helpers.c
@@ -41,6 +41,9 @@ int git_cred_userpass(
else
return -1;
+ if (GIT_CREDTYPE_USERNAME & allowed_types)
+ return git_cred_username_new(cred, effective_username);
+
if ((GIT_CREDTYPE_USERPASS_PLAINTEXT & allowed_types) == 0 ||
git_cred_userpass_plaintext_new(cred, effective_username, userpass->password) < 0)
return -1;
diff --git a/src/transports/ssh.c b/src/transports/ssh.c
index d4c39bd39..6a7f67e99 100644
--- a/src/transports/ssh.c
+++ b/src/transports/ssh.c
@@ -9,6 +9,7 @@
#include "buffer.h"
#include "netops.h"
#include "smart.h"
+#include "cred.h"
#ifdef GIT_SSH
@@ -36,7 +37,7 @@ typedef struct {
ssh_stream *current_stream;
} ssh_subtransport;
-static int list_auth_methods(int *out, const char *host, const char *port);
+static int list_auth_methods(int *out, LIBSSH2_SESSION *session, const char *username);
static void ssh_error(LIBSSH2_SESSION *session, const char *errmsg)
{
@@ -377,6 +378,12 @@ static int request_creds(git_cred **out, ssh_subtransport *t, const char *user,
return -1;
}
+ if (!(cred->credtype & auth_methods)) {
+ cred->free(cred);
+ giterr_set(GITERR_SSH, "callback returned unsupported credentials type");
+ return -1;
+ }
+
*out = cred;
return 0;
@@ -444,26 +451,33 @@ static int _git_ssh_setup_conn(
GITERR_CHECK_ALLOC(port);
}
- if (list_auth_methods(&auth_methods, host, port) < 0) {
- auth_methods = GIT_CREDTYPE_USERPASS_PLAINTEXT |
- GIT_CREDTYPE_SSH_KEY | GIT_CREDTYPE_SSH_CUSTOM |
- GIT_CREDTYPE_SSH_INTERACTIVE;
- }
-
- if ((error = gitno_connect(&s->socket, host, port, 0)) < 0)
- goto on_error;
+ /* we need the username to ask for auth methods */
+ if (!user) {
+ if ((error = request_creds(&cred, t, NULL, GIT_CREDTYPE_USERNAME)) < 0)
+ goto on_error;
- if (user && pass) {
+ user = git__strdup(((git_cred_username *) cred)->username);
+ cred->free(cred);
+ cred = NULL;
+ if (!user)
+ goto on_error;
+ } else if (user && pass) {
if ((error = git_cred_userpass_plaintext_new(&cred, user, pass)) < 0)
goto on_error;
}
+ if ((error = gitno_connect(&s->socket, host, port, 0)) < 0)
+ goto on_error;
+
if ((error = _git_ssh_session_create(&session, s->socket)) < 0)
goto on_error;
+ if ((error = list_auth_methods(&auth_methods, session, user)) < 0)
+ goto on_error;
+
error = GIT_EAUTH;
/* if we already have something to try */
- if (cred)
+ if (cred && auth_methods & cred->credtype)
error = _git_ssh_authenticate_session(session, cred);
while (error == GIT_EAUTH) {
@@ -475,6 +489,12 @@ static int _git_ssh_setup_conn(
if ((error = request_creds(&cred, t, user, auth_methods)) < 0)
goto on_error;
+ if (strcmp(user, git_cred__username(cred))) {
+ giterr_set(GITERR_SSH, "username does not match previous request");
+ error = -1;
+ goto on_error;
+ }
+
error = _git_ssh_authenticate_session(session, cred);
}
@@ -628,26 +648,17 @@ static void _ssh_free(git_smart_subtransport *subtransport)
#define SSH_AUTH_PASSWORD "password"
#define SSH_AUTH_KEYBOARD_INTERACTIVE "keyboard-interactive"
-static int list_auth_methods(int *out, const char *host, const char *port)
+static int list_auth_methods(int *out, LIBSSH2_SESSION *session, const char *username)
{
- gitno_socket s;
- LIBSSH2_SESSION *session = NULL;
const char *list, *ptr;
*out = 0;
- if (gitno_connect(&s, host, port, 0) < 0)
- return -1;
-
- if (_git_ssh_session_create(&session, s) < 0)
- goto on_error;
-
- /* the username is dummy, we're throwing away the connection anyway */
- list = libssh2_userauth_list(session, "git", strlen("git"));
+ list = libssh2_userauth_list(session, username, strlen(username));
/* either error, or the remote accepts NONE auth, which is bizarre, let's punt */
- if (list == NULL)
- goto out;
+ if (list == NULL && !libssh2_userauth_authenticated(session))
+ return -1;
ptr = list;
while (ptr) {
@@ -677,17 +688,7 @@ static int list_auth_methods(int *out, const char *host, const char *port)
ptr = strchr(ptr, ',');
}
-out:
- libssh2_session_free(session);
- gitno_close(&s);
-
return 0;
-
-on_error:
- libssh2_session_free(session);
- gitno_close(&s);
-
- return -1;
}
#endif
diff --git a/tests/online/clone.c b/tests/online/clone.c
index a5f8ad1b0..de838e694 100644
--- a/tests/online/clone.c
+++ b/tests/online/clone.c
@@ -253,6 +253,9 @@ static int cred_count_calls_cb(git_cred **cred, const char *url, const char *use
GIT_UNUSED(url); GIT_UNUSED(user); GIT_UNUSED(allowed_types);
+ if (allowed_types == GIT_CREDTYPE_USERNAME)
+ return git_cred_username_new(cred, "foo");
+
(*counter)++;
if (*counter == 3)