summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/transports/ssh.c87
1 files changed, 26 insertions, 61 deletions
diff --git a/src/transports/ssh.c b/src/transports/ssh.c
index 0f4a0fcc5..75b8e8b81 100644
--- a/src/transports/ssh.c
+++ b/src/transports/ssh.c
@@ -24,8 +24,6 @@
#define OWNING_SUBTRANSPORT(s) ((ssh_subtransport *)(s)->parent.subtransport)
-static const char *ssh_prefixes[] = { "ssh://", "ssh+git://", "git+ssh://" };
-
static const char cmd_uploadpack[] = "git-upload-pack";
static const char cmd_receivepack[] = "git-receive-pack";
@@ -35,7 +33,7 @@ typedef struct {
LIBSSH2_SESSION *session;
LIBSSH2_CHANNEL *channel;
const char *cmd;
- char *url;
+ git_net_url url;
unsigned sent_command : 1;
} ssh_stream;
@@ -63,39 +61,23 @@ static void ssh_error(LIBSSH2_SESSION *session, const char *errmsg)
*
* For example: git-upload-pack '/libgit2/libgit2'
*/
-static int gen_proto(git_str *request, const char *cmd, const char *url)
+static int gen_proto(git_str *request, const char *cmd, git_net_url *url)
{
const char *repo;
- int len;
- size_t i;
-
- for (i = 0; i < ARRAY_SIZE(ssh_prefixes); ++i) {
- const char *p = ssh_prefixes[i];
- if (!git__prefixcmp(url, p)) {
- url = url + strlen(p);
- repo = strchr(url, '/');
- if (repo && repo[1] == '~')
- ++repo;
+ repo = url->path;
- goto done;
- }
- }
- repo = strchr(url, ':');
- if (repo) repo++;
+ if (repo && repo[0] == '/' && repo[1] == '~')
+ repo++;
-done:
- if (!repo) {
+ if (!repo || !repo[0]) {
git_error_set(GIT_ERROR_NET, "malformed git protocol URL");
return -1;
}
- len = strlen(cmd) + 1 /* Space */ + 1 /* Quote */ + strlen(repo) + 1 /* Quote */ + 1;
-
- git_str_grow(request, len);
git_str_puts(request, cmd);
git_str_puts(request, " '");
- git_str_decode_percent(request, repo, strlen(repo));
+ git_str_puts(request, repo);
git_str_puts(request, "'");
if (git_str_oom(request))
@@ -109,7 +91,7 @@ static int send_command(ssh_stream *s)
int error;
git_str request = GIT_STR_INIT;
- error = gen_proto(&request, s->cmd, s->url);
+ error = gen_proto(&request, s->cmd, &s->url);
if (error < 0)
goto cleanup;
@@ -224,13 +206,12 @@ static void ssh_stream_free(git_smart_subtransport_stream *stream)
s->io = NULL;
}
- git__free(s->url);
+ git_net_url_dispose(&s->url);
git__free(s);
}
static int ssh_stream_alloc(
ssh_subtransport *t,
- const char *url,
const char *cmd,
git_smart_subtransport_stream **stream)
{
@@ -248,12 +229,6 @@ static int ssh_stream_alloc(
s->cmd = cmd;
- s->url = git__strdup(url);
- if (!s->url) {
- git__free(s);
- return -1;
- }
-
*stream = &s->parent;
return 0;
}
@@ -487,9 +462,7 @@ static int _git_ssh_setup_conn(
const char *cmd,
git_smart_subtransport_stream **stream)
{
- git_net_url urldata = GIT_NET_URL_INIT;
int auth_methods, error = 0;
- size_t i;
ssh_stream *s;
git_credential *cred = NULL;
LIBSSH2_SESSION *session=NULL;
@@ -498,28 +471,22 @@ static int _git_ssh_setup_conn(
t->current_stream = NULL;
*stream = NULL;
- if (ssh_stream_alloc(t, url, cmd, stream) < 0)
+ if (ssh_stream_alloc(t, cmd, stream) < 0)
return -1;
s = (ssh_stream *)*stream;
s->session = NULL;
s->channel = NULL;
- for (i = 0; i < ARRAY_SIZE(ssh_prefixes); ++i) {
- const char *p = ssh_prefixes[i];
-
- if (!git__prefixcmp(url, p)) {
- if ((error = git_net_url_parse(&urldata, url)) < 0)
- goto done;
+ if (git_net_str_is_url(url))
+ error = git_net_url_parse(&s->url, url);
+ else
+ error = git_net_url_parse_scp(&s->url, url);
- goto post_extract;
- }
- }
- if ((error = git_net_url_parse_scp(&urldata, url)) < 0)
+ if (error < 0)
goto done;
-post_extract:
- if ((error = git_socket_stream_new(&s->io, urldata.host, urldata.port)) < 0 ||
+ if ((error = git_socket_stream_new(&s->io, s->url.host, s->url.port)) < 0 ||
(error = git_stream_connect(s->io)) < 0)
goto done;
@@ -603,7 +570,7 @@ post_extract:
error = t->owner->connect_opts.callbacks.certificate_check(
(git_cert *)cert_ptr,
0,
- urldata.host,
+ s->url.host,
t->owner->connect_opts.callbacks.payload);
if (error < 0 && error != GIT_PASSTHROUGH) {
@@ -615,21 +582,21 @@ post_extract:
}
/* we need the username to ask for auth methods */
- if (!urldata.username) {
+ if (!s->url.username) {
if ((error = request_creds(&cred, t, NULL, GIT_CREDENTIAL_USERNAME)) < 0)
goto done;
- urldata.username = git__strdup(((git_credential_username *) cred)->username);
+ s->url.username = git__strdup(((git_credential_username *) cred)->username);
cred->free(cred);
cred = NULL;
- if (!urldata.username)
+ if (!s->url.username)
goto done;
- } else if (urldata.username && urldata.password) {
- if ((error = git_credential_userpass_plaintext_new(&cred, urldata.username, urldata.password)) < 0)
+ } else if (s->url.username && s->url.password) {
+ if ((error = git_credential_userpass_plaintext_new(&cred, s->url.username, s->url.password)) < 0)
goto done;
}
- if ((error = list_auth_methods(&auth_methods, session, urldata.username)) < 0)
+ if ((error = list_auth_methods(&auth_methods, session, s->url.username)) < 0)
goto done;
error = GIT_EAUTH;
@@ -643,10 +610,10 @@ post_extract:
cred = NULL;
}
- if ((error = request_creds(&cred, t, urldata.username, auth_methods)) < 0)
+ if ((error = request_creds(&cred, t, s->url.username, auth_methods)) < 0)
goto done;
- if (strcmp(urldata.username, git_credential_get_username(cred))) {
+ if (strcmp(s->url.username, git_credential_get_username(cred))) {
git_error_set(GIT_ERROR_SSH, "username does not match previous request");
error = -1;
goto done;
@@ -656,7 +623,7 @@ post_extract:
if (error == GIT_EAUTH) {
/* refresh auth methods */
- if ((error = list_auth_methods(&auth_methods, session, urldata.username)) < 0)
+ if ((error = list_auth_methods(&auth_methods, session, s->url.username)) < 0)
goto done;
else
error = GIT_EAUTH;
@@ -691,8 +658,6 @@ done:
if (cred)
cred->free(cred);
- git_net_url_dispose(&urldata);
-
return error;
}