Added support for ssh:// urls
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
diff --git a/src/transport.c b/src/transport.c
index 0d2a860..6a8e67d 100644
--- a/src/transport.c
+++ b/src/transport.c
@@ -18,21 +18,22 @@ typedef struct transport_definition {
void *param;
} transport_definition;
-static transport_definition local_transport_definition = { "file://", 1, git_transport_local, NULL };
-static transport_definition dummy_transport_definition = { NULL, 1, git_transport_dummy, NULL };
-
static git_smart_subtransport_definition http_subtransport_definition = { git_smart_subtransport_http, 1 };
static git_smart_subtransport_definition git_subtransport_definition = { git_smart_subtransport_git, 0 };
static git_smart_subtransport_definition ssh_subtransport_definition = { git_smart_subtransport_ssh, 0 };
+static transport_definition local_transport_definition = { "file://", 1, git_transport_local, NULL };
+#ifdef GIT_WIN32
+static transport_definition dummy_transport_definition = { NULL, 1, git_transport_dummy, NULL };
+#endif
+static transport_definition ssh_transport_definition = { "ssh://", 1, git_transport_smart, &ssh_subtransport_definition };
+
static transport_definition transports[] = {
{"git://", 1, git_transport_smart, &git_subtransport_definition},
{"http://", 1, git_transport_smart, &http_subtransport_definition},
{"https://", 1, git_transport_smart, &http_subtransport_definition},
{"file://", 1, git_transport_local, NULL},
- {"git+ssh://", 1, git_transport_smart, &ssh_subtransport_definition},
- {"ssh+git://", 1, git_transport_smart, &ssh_subtransport_definition},
- {"git@", 1, git_transport_smart, &ssh_subtransport_definition},
+ {"ssh://", 1, git_transport_smart, &ssh_subtransport_definition},
{NULL, 0, 0}
};
@@ -75,7 +76,7 @@ static int transport_find_fn(const char *url, git_transport_cb *callback, void *
/* It could be a SSH remote path. Check to see if there's a :
* SSH is an unsupported transport mechanism in this version of libgit2 */
if (!definition && strrchr(url, ':'))
- definition = &dummy_transport_definition;
+ definition = &ssh_transport_definition;
/* Check to see if the path points to a file on the local file system */
if (!definition && git_path_exists(url) && git_path_isdir(url))
diff --git a/src/transports/ssh.c b/src/transports/ssh.c
index 6e99e00..6e81c25 100644
--- a/src/transports/ssh.c
+++ b/src/transports/ssh.c
@@ -15,7 +15,7 @@
#define OWNING_SUBTRANSPORT(s) ((ssh_subtransport *)(s)->parent.subtransport)
static const char prefix_ssh[] = "ssh://";
-static const char prefix_git[] = "git@";
+static const char default_user[] = "git";
static const char cmd_uploadpack[] = "git-upload-pack";
static const char cmd_receivepack[] = "git-receive-pack";
@@ -26,7 +26,6 @@ typedef struct {
LIBSSH2_CHANNEL *channel;
const char *cmd;
char *url;
- char *path;
unsigned sent_command : 1;
} ssh_stream;
@@ -42,8 +41,21 @@ typedef struct {
*
* For example: git-upload-pack '/libgit2/libgit2'
*/
-static int gen_proto(git_buf *request, const char *cmd, const char *repo)
+static int gen_proto(git_buf *request, const char *cmd, const char *url)
{
+ char *repo;
+
+ if (!git__prefixcmp(url, prefix_ssh)) {
+ url = url + strlen(prefix_ssh);
+ repo = strchr(url, '/');
+ } else {
+ repo = strchr(url, ':');
+ }
+
+ if (!repo) {
+ return -1;
+ }
+
int len = strlen(cmd) + 1 /* Space */ + 1 /* Quote */ + strlen(repo) + 1 /* Quote */ + 1;
git_buf_grow(request, len);
@@ -61,7 +73,7 @@ static int send_command(ssh_stream *s)
int error;
git_buf request = GIT_BUF_INIT;
- error = gen_proto(&request, s->cmd, s->path);
+ error = gen_proto(&request, s->cmd, s->url);
if (error < 0)
goto cleanup;
@@ -183,18 +195,15 @@ static int ssh_stream_alloc(
return 0;
}
-/* Temp */
-static int gitssh_extract_url_parts(
+static int git_ssh_extract_url_parts(
char **host,
char **username,
- char **path,
const char *url)
{
char *colon, *at;
const char *start;
colon = strchr(url, ':');
- at = strchr(url, '@');
if (colon == NULL) {
giterr_set(GITERR_NET, "Malformed URL: missing :");
@@ -202,15 +211,15 @@ static int gitssh_extract_url_parts(
}
start = url;
+ at = strchr(url, '@');
if (at) {
start = at+1;
*username = git__substrdup(url, at - url);
} else {
- *username = "git";
+ *username = git__strdup(default_user);
}
*host = git__substrdup(start, colon - start);
- *path = colon+1;
return 0;
}
@@ -222,7 +231,8 @@ static int _git_ssh_setup_conn(
git_smart_subtransport_stream **stream
)
{
- char *host, *user=NULL;
+ char *host, *port, *user=NULL, *pass=NULL;
+ const char *default_port = "22";
ssh_stream *s;
*stream = NULL;
@@ -231,21 +241,35 @@ static int _git_ssh_setup_conn(
s = (ssh_stream *)*stream;
- if (gitssh_extract_url_parts(&host, &user, &s->path, url) < 0)
- goto on_error;
+ if (!git__prefixcmp(url, prefix_ssh)) {
+ url = url + strlen(prefix_ssh);
+ if (gitno_extract_url_parts(&host, &port, &user, &pass, url, default_port) < 0)
+ return -1;
+ } else {
+ if (git_ssh_extract_url_parts(&host, &user, url) < 0)
+ goto on_error;
+ port = git__strdup(default_port);
+ }
- if (gitno_connect(&s->socket, host, "22", 0) < 0)
+ if (gitno_connect(&s->socket, host, port, 0) < 0)
goto on_error;
- if (t->owner->cred_acquire_cb(&t->cred,
- t->owner->url,
- user,
- GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE,
- t->owner->cred_acquire_payload) < 0)
- return -1;
-
+ if (user && pass) {
+ git_cred_userpass_plaintext_new(&t->cred, user, pass);
+ } else {
+ if (t->owner->cred_acquire_cb(&t->cred,
+ t->owner->url,
+ user,
+ GIT_CREDTYPE_USERPASS_PLAINTEXT | GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE,
+ t->owner->cred_acquire_payload) < 0)
+ return -1;
+ }
assert(t->cred);
+ if (!user) {
+ user = git__strdup(default_user);
+ }
+
git_cred_ssh_keyfile_passphrase *cred = (git_cred_ssh_keyfile_passphrase *)t->cred;
LIBSSH2_SESSION* session = libssh2_session_init();