vendor/libgit2/src/transports/ssh.c in rugged-1.3.2.3 vs vendor/libgit2/src/transports/ssh.c in rugged-1.4.2
- old
+ new
@@ -10,12 +10,10 @@
#ifdef GIT_SSH
#include <libssh2.h>
#endif
#include "runtime.h"
-#include "git2.h"
-#include "buffer.h"
#include "net.h"
#include "netops.h"
#include "smart.h"
#include "streams/socket.h"
@@ -24,22 +22,20 @@
#ifdef GIT_SSH
#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";
typedef struct {
git_smart_subtransport_stream parent;
git_stream *io;
LIBSSH2_SESSION *session;
LIBSSH2_CHANNEL *channel;
const char *cmd;
- char *url;
+ git_net_url url;
unsigned sent_command : 1;
} ssh_stream;
typedef struct {
git_smart_subtransport parent;
@@ -63,57 +59,41 @@
/*
* Create a git protocol request.
*
* For example: git-upload-pack '/libgit2/libgit2'
*/
-static int gen_proto(git_buf *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];
+ repo = url->path;
- if (!git__prefixcmp(url, p)) {
- url = url + strlen(p);
- repo = strchr(url, '/');
- if (repo && repo[1] == '~')
- ++repo;
+ if (repo && repo[0] == '/' && repo[1] == '~')
+ repo++;
- goto done;
- }
- }
- repo = strchr(url, ':');
- if (repo) 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_puts(request, cmd);
+ git_str_puts(request, " '");
+ git_str_puts(request, repo);
+ git_str_puts(request, "'");
- git_buf_grow(request, len);
- git_buf_puts(request, cmd);
- git_buf_puts(request, " '");
- git_buf_decode_percent(request, repo, strlen(repo));
- git_buf_puts(request, "'");
-
- if (git_buf_oom(request))
+ if (git_str_oom(request))
return -1;
return 0;
}
static int send_command(ssh_stream *s)
{
int error;
- git_buf request = GIT_BUF_INIT;
+ 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;
error = libssh2_channel_exec(s->channel, request.ptr);
if (error < LIBSSH2_ERROR_NONE) {
@@ -122,11 +102,11 @@
}
s->sent_command = 1;
cleanup:
- git_buf_dispose(&request);
+ git_str_dispose(&request);
return error;
}
static int ssh_stream_read(
git_smart_subtransport_stream *stream,
@@ -224,17 +204,16 @@
git_stream_close(s->io);
git_stream_free(s->io);
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)
{
ssh_stream *s;
@@ -248,51 +227,14 @@
s->parent.write = ssh_stream_write;
s->parent.free = ssh_stream_free;
s->cmd = cmd;
- s->url = git__strdup(url);
- if (!s->url) {
- git__free(s);
- return -1;
- }
-
*stream = &s->parent;
return 0;
}
-static int git_ssh_extract_url_parts(
- git_net_url *urldata,
- const char *url)
-{
- char *colon, *at;
- const char *start;
-
- colon = strchr(url, ':');
-
-
- at = strchr(url, '@');
- if (at) {
- start = at + 1;
- urldata->username = git__substrdup(url, at - url);
- GIT_ERROR_CHECK_ALLOC(urldata->username);
- } else {
- start = url;
- urldata->username = NULL;
- }
-
- if (colon == NULL || (colon < start)) {
- git_error_set(GIT_ERROR_NET, "malformed URL");
- return -1;
- }
-
- urldata->host = git__substrdup(start, colon - start);
- GIT_ERROR_CHECK_ALLOC(urldata->host);
-
- return 0;
-}
-
static int ssh_agent_auth(LIBSSH2_SESSION *session, git_credential_ssh_key *c) {
int rc = LIBSSH2_ERROR_NONE;
struct libssh2_agent_publickey *curr, *prev = NULL;
@@ -441,15 +383,19 @@
static int request_creds(git_credential **out, ssh_subtransport *t, const char *user, int auth_methods)
{
int error, no_callback = 0;
git_credential *cred = NULL;
- if (!t->owner->cred_acquire_cb) {
+ if (!t->owner->connect_opts.callbacks.credentials) {
no_callback = 1;
} else {
- error = t->owner->cred_acquire_cb(&cred, t->owner->url, user, auth_methods,
- t->owner->cred_acquire_payload);
+ error = t->owner->connect_opts.callbacks.credentials(
+ &cred,
+ t->owner->url,
+ user,
+ auth_methods,
+ t->owner->connect_opts.callbacks.payload);
if (error == GIT_PASSTHROUGH) {
no_callback = 1;
} else if (error < 0) {
return error;
@@ -514,55 +460,42 @@
ssh_subtransport *t,
const char *url,
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;
LIBSSH2_CHANNEL *channel=NULL;
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_net_str_is_url(url))
+ error = git_net_url_parse(&s->url, url);
+ else
+ error = git_net_url_parse_scp(&s->url, url);
- if (!git__prefixcmp(url, p)) {
- if ((error = git_net_url_parse(&urldata, url)) < 0)
- goto done;
-
- goto post_extract;
- }
- }
- if ((error = git_ssh_extract_url_parts(&urldata, url)) < 0)
+ if (error < 0)
goto done;
- if (urldata.port == NULL)
- urldata.port = git__strdup(SSH_DEFAULT_PORT);
-
- GIT_ERROR_CHECK_ALLOC(urldata.port);
-
-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;
if ((error = _git_ssh_session_create(&session, s->io)) < 0)
goto done;
- if (t->owner->certificate_check_cb != NULL) {
+ if (t->owner->connect_opts.callbacks.certificate_check != NULL) {
git_cert_hostkey cert = {{ 0 }}, *cert_ptr;
const char *key;
size_t cert_len;
int cert_type;
@@ -578,11 +511,11 @@
cert.raw_type = GIT_CERT_SSH_RAW_TYPE_RSA;
break;
case LIBSSH2_HOSTKEY_TYPE_DSS:
cert.raw_type = GIT_CERT_SSH_RAW_TYPE_DSS;
break;
-
+
#ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_256
case LIBSSH2_HOSTKEY_TYPE_ECDSA_256:
cert.raw_type = GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_256;
break;
case LIBSSH2_HOSTKEY_TYPE_ECDSA_384:
@@ -590,11 +523,11 @@
break;
case LIBSSH2_KNOWNHOST_KEY_ECDSA_521:
cert.raw_type = GIT_CERT_SSH_RAW_TYPE_KEY_ECDSA_521;
break;
#endif
-
+
#ifdef LIBSSH2_HOSTKEY_TYPE_ED25519
case LIBSSH2_HOSTKEY_TYPE_ED25519:
cert.raw_type = GIT_CERT_SSH_RAW_TYPE_KEY_ED25519;
break;
#endif
@@ -632,36 +565,40 @@
/* We don't currently trust any hostkeys */
git_error_clear();
cert_ptr = &cert;
- error = t->owner->certificate_check_cb((git_cert *) cert_ptr, 0, urldata.host, t->owner->message_cb_payload);
+ error = t->owner->connect_opts.callbacks.certificate_check(
+ (git_cert *)cert_ptr,
+ 0,
+ s->url.host,
+ t->owner->connect_opts.callbacks.payload);
if (error < 0 && error != GIT_PASSTHROUGH) {
if (!git_error_last())
git_error_set(GIT_ERROR_NET, "user cancelled hostkey check");
goto done;
}
}
/* 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;
/* if we already have something to try */
if (cred && auth_methods & cred->credtype)
@@ -671,24 +608,24 @@
if (cred) {
cred->free(cred);
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;
}
error = _git_ssh_authenticate_session(session, cred);
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;
}
}
@@ -719,12 +656,10 @@
}
if (cred)
cred->free(cred);
- git_net_url_dispose(&urldata);
-
return error;
}
static int ssh_uploadpack_ls(
ssh_subtransport *t,
@@ -868,10 +803,10 @@
*out |= GIT_CREDENTIAL_SSH_INTERACTIVE;
ptr += strlen(SSH_AUTH_KEYBOARD_INTERACTIVE);
continue;
}
- /* Skipt it if we don't know it */
+ /* Skip it if we don't know it */
ptr = strchr(ptr, ',');
}
return 0;
}