From d04c384036ec6f843bbbb45a87d9d451c35cf29a Mon Sep 17 00:00:00 2001 From: Brad Morgan Date: Fri, 3 May 2013 14:53:23 -0400 Subject: [PATCH] Adding ssh transport logic --- src/transport.c | 6 +-- src/transports/ssh.c | 100 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 86 insertions(+), 20 deletions(-) diff --git a/src/transport.c b/src/transport.c index 7b7a5aa85..0d2a860fe 100644 --- a/src/transport.c +++ b/src/transport.c @@ -30,9 +30,9 @@ static transport_definition transports[] = { {"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, &git_smart_subtransport_ssh}, - {"ssh+git://", 1, git_transport_smart, &git_smart_subtransport_ssh}, - {"git@", 1, git_transport_smart, &git_smart_subtransport_ssh}, + {"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}, {NULL, 0, 0} }; diff --git a/src/transports/ssh.c b/src/transports/ssh.c index b8dc9b1b6..8f36a6549 100644 --- a/src/transports/ssh.c +++ b/src/transports/ssh.c @@ -13,8 +13,7 @@ #define OWNING_SUBTRANSPORT(s) ((ssh_subtransport *)(s)->parent.subtransport) -static const char prefix_git_ssh[] = "git+ssh://"; -static const char prefix_ssh_git[] = "ssh+git://"; +static const char prefix_ssh[] = "ssh://"; static const char prefix_git[] = "git@"; static const char cmd_uploadpack[] = "git-upload-pack"; static const char cmd_receivepack[] = "git-receive-pack"; @@ -36,7 +35,7 @@ typedef struct { /* * Create a git protocol request. * - * For example: 0035git-upload-pack /libgit2/libgit2\0host=github.com\0 + * For example: 0035git-upload-pack /libgit2/libgit2\0 */ static int gen_proto(git_buf *request, const char *cmd, const char *url) { @@ -178,6 +177,38 @@ static int ssh_stream_alloc( return 0; } +/* Temp */ +static int gitssh_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 :"); + return -1; + } + + start = url; + if (at) { + start = at+1; + *username = git__substrdup(url, at - url); + } else { + *username = "git"; + } + + *host = git__substrdup(start, colon - start); + *path = colon+1; + + return 0; +} + static int _git_uploadpack_ls( ssh_subtransport *t, const char *url, @@ -188,8 +219,8 @@ static int _git_uploadpack_ls( *stream = NULL; - if (!git__prefixcmp(url, prefix_git)) - url += strlen(prefix_git); + if (!git__prefixcmp(url, prefix_ssh)) + url += strlen(prefix_ssh); if (ssh_stream_alloc(t, url, cmd_uploadpack, stream) < 0) return -1; @@ -239,30 +270,65 @@ static int _git_receivepack_ls( const char *url, git_smart_subtransport_stream **stream) { - char *host, *port, *user=NULL, *pass=NULL; + char *host, *path, *user=NULL; ssh_stream *s; *stream = NULL; - - if (!git__prefixcmp(url, prefix_git)) - url += strlen(prefix_git); - if (ssh_stream_alloc(t, url, cmd_receivepack, stream) < 0) return -1; s = (ssh_stream *)*stream; - if (gitno_extract_url_parts(&host, &port, &user, &pass, url, GIT_DEFAULT_PORT) < 0) + if (gitssh_extract_url_parts(&host, &user, &path, url) < 0) goto on_error; - if (gitno_connect(&s->socket, host, port, 0) < 0) + if (gitno_connect(&s->socket, host, "22", 0) < 0) goto on_error; + LIBSSH2_SESSION* session = libssh2_session_init(); + if (!session) + goto on_error; + + int rc = 0; + do { + rc = libssh2_session_startup(session, s->socket.socket); + } while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc); + + if (0 != rc) { + goto on_error; + } + + libssh2_trace(session, 0x1FF); + libssh2_session_set_blocking(session, 1); + + do { + rc = libssh2_userauth_publickey_fromfile_ex( + session, + user, + strlen(user), + NULL, + "/Users/bradfordmorgan/.ssh/id_rsa", + NULL + ); + } while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc); + + if (0 != rc) { + goto on_error; + } + + LIBSSH2_CHANNEL* channel = NULL; + do { + channel = libssh2_channel_open_session(session); + } while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc); + + if (!channel) { + goto on_error; + } + + libssh2_channel_set_blocking(channel, 1); + t->current_stream = s; git__free(host); - git__free(port); - git__free(user); - git__free(pass); return 0; on_error: @@ -270,7 +336,7 @@ on_error: ssh_stream_free(*stream); git__free(host); - git__free(port); + git__free(path); return -1; } @@ -336,7 +402,7 @@ static void _git_free(git_smart_subtransport *subtransport) git__free(t); } -int git_smart_subtransport_git(git_smart_subtransport **out, git_transport *owner) +int git_smart_subtransport_ssh(git_smart_subtransport **out, git_transport *owner) { ssh_subtransport *t;