diff options
-rw-r--r-- | src/transports/ssh.c | 87 |
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; } |