Commit a3c062db by Russell Belfer

Make SSH APIs present even without SSH support

The SSH APIs will just return an error code and state that the
library was built without SSH support if they are called in
that case.
parent 82cb8e23
...@@ -36,14 +36,15 @@ typedef enum { ...@@ -36,14 +36,15 @@ typedef enum {
} git_credtype_t; } git_credtype_t;
/* The base structure for all credential types */ /* The base structure for all credential types */
typedef struct git_cred { typedef struct git_cred git_cred;
struct git_cred {
git_credtype_t credtype; git_credtype_t credtype;
void (*free)( void (*free)(git_cred *cred);
struct git_cred *cred); };
} git_cred;
/* A plaintext username and password */ /* A plaintext username and password */
typedef struct git_cred_userpass_plaintext { typedef struct {
git_cred parent; git_cred parent;
char *username; char *username;
char *password; char *password;
...@@ -51,6 +52,9 @@ typedef struct git_cred_userpass_plaintext { ...@@ -51,6 +52,9 @@ typedef struct git_cred_userpass_plaintext {
#ifdef GIT_SSH #ifdef GIT_SSH
typedef LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*git_cred_sign_callback)); typedef LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*git_cred_sign_callback));
#else
typedef int (*git_cred_sign_callback)(void *, ...);
#endif
/* A ssh key file and passphrase */ /* A ssh key file and passphrase */
typedef struct git_cred_ssh_keyfile_passphrase { typedef struct git_cred_ssh_keyfile_passphrase {
...@@ -68,7 +72,6 @@ typedef struct git_cred_ssh_publickey { ...@@ -68,7 +72,6 @@ typedef struct git_cred_ssh_publickey {
void *sign_callback; void *sign_callback;
void *sign_data; void *sign_data;
} git_cred_ssh_publickey; } git_cred_ssh_publickey;
#endif
/** /**
* Creates a new plain-text username and password credential object. * Creates a new plain-text username and password credential object.
...@@ -84,7 +87,6 @@ GIT_EXTERN(int) git_cred_userpass_plaintext_new( ...@@ -84,7 +87,6 @@ GIT_EXTERN(int) git_cred_userpass_plaintext_new(
const char *username, const char *username,
const char *password); const char *password);
#ifdef GIT_SSH
/** /**
* Creates a new ssh key file and passphrase credential object. * Creates a new ssh key file and passphrase credential object.
* The supplied credential parameter will be internally duplicated. * The supplied credential parameter will be internally duplicated.
...@@ -116,9 +118,8 @@ GIT_EXTERN(int) git_cred_ssh_publickey_new( ...@@ -116,9 +118,8 @@ GIT_EXTERN(int) git_cred_ssh_publickey_new(
git_cred **out, git_cred **out,
const char *publickey, const char *publickey,
size_t publickey_len, size_t publickey_len,
git_cred_sign_callback, git_cred_sign_callback sign_fn,
void *sign_data); void *sign_data);
#endif
/** /**
* Signature of a function which acquires a credential object. * Signature of a function which acquires a credential object.
...@@ -152,17 +153,21 @@ typedef enum { ...@@ -152,17 +153,21 @@ typedef enum {
typedef void (*git_transport_message_cb)(const char *str, int len, void *data); typedef void (*git_transport_message_cb)(const char *str, int len, void *data);
typedef struct git_transport { typedef struct git_transport git_transport;
struct git_transport {
unsigned int version; unsigned int version;
/* Set progress and error callbacks */ /* Set progress and error callbacks */
int (*set_callbacks)(struct git_transport *transport, int (*set_callbacks)(
git_transport *transport,
git_transport_message_cb progress_cb, git_transport_message_cb progress_cb,
git_transport_message_cb error_cb, git_transport_message_cb error_cb,
void *payload); void *payload);
/* Connect the transport to the remote repository, using the given /* Connect the transport to the remote repository, using the given
* direction. */ * direction. */
int (*connect)(struct git_transport *transport, int (*connect)(
git_transport *transport,
const char *url, const char *url,
git_cred_acquire_cb cred_acquire_cb, git_cred_acquire_cb cred_acquire_cb,
void *cred_acquire_payload, void *cred_acquire_payload,
...@@ -172,17 +177,19 @@ typedef struct git_transport { ...@@ -172,17 +177,19 @@ typedef struct git_transport {
/* This function may be called after a successful call to connect(). The /* This function may be called after a successful call to connect(). The
* provided callback is invoked for each ref discovered on the remote * provided callback is invoked for each ref discovered on the remote
* end. */ * end. */
int (*ls)(struct git_transport *transport, int (*ls)(
git_transport *transport,
git_headlist_cb list_cb, git_headlist_cb list_cb,
void *payload); void *payload);
/* Executes the push whose context is in the git_push object. */ /* Executes the push whose context is in the git_push object. */
int (*push)(struct git_transport *transport, git_push *push); int (*push)(git_transport *transport, git_push *push);
/* This function may be called after a successful call to connect(), when /* This function may be called after a successful call to connect(), when
* the direction is FETCH. The function performs a negotiation to calculate * the direction is FETCH. The function performs a negotiation to calculate
* the wants list for the fetch. */ * the wants list for the fetch. */
int (*negotiate_fetch)(struct git_transport *transport, int (*negotiate_fetch)(
git_transport *transport,
git_repository *repo, git_repository *repo,
const git_remote_head * const *refs, const git_remote_head * const *refs,
size_t count); size_t count);
...@@ -190,28 +197,29 @@ typedef struct git_transport { ...@@ -190,28 +197,29 @@ typedef struct git_transport {
/* This function may be called after a successful call to negotiate_fetch(), /* This function may be called after a successful call to negotiate_fetch(),
* when the direction is FETCH. This function retrieves the pack file for * when the direction is FETCH. This function retrieves the pack file for
* the fetch from the remote end. */ * the fetch from the remote end. */
int (*download_pack)(struct git_transport *transport, int (*download_pack)(
git_transport *transport,
git_repository *repo, git_repository *repo,
git_transfer_progress *stats, git_transfer_progress *stats,
git_transfer_progress_callback progress_cb, git_transfer_progress_callback progress_cb,
void *progress_payload); void *progress_payload);
/* Checks to see if the transport is connected */ /* Checks to see if the transport is connected */
int (*is_connected)(struct git_transport *transport); int (*is_connected)(git_transport *transport);
/* Reads the flags value previously passed into connect() */ /* Reads the flags value previously passed into connect() */
int (*read_flags)(struct git_transport *transport, int *flags); int (*read_flags)(git_transport *transport, int *flags);
/* Cancels any outstanding transport operation */ /* Cancels any outstanding transport operation */
void (*cancel)(struct git_transport *transport); void (*cancel)(git_transport *transport);
/* This function is the reverse of connect() -- it terminates the /* This function is the reverse of connect() -- it terminates the
* connection to the remote end. */ * connection to the remote end. */
int (*close)(struct git_transport *transport); int (*close)(git_transport *transport);
/* Frees/destructs the git_transport object. */ /* Frees/destructs the git_transport object. */
void (*free)(struct git_transport *transport); void (*free)(git_transport *transport);
} git_transport; };
#define GIT_TRANSPORT_VERSION 1 #define GIT_TRANSPORT_VERSION 1
#define GIT_TRANSPORT_INIT {GIT_TRANSPORT_VERSION} #define GIT_TRANSPORT_INIT {GIT_TRANSPORT_VERSION}
...@@ -299,35 +307,36 @@ typedef enum { ...@@ -299,35 +307,36 @@ typedef enum {
GIT_SERVICE_RECEIVEPACK = 4, GIT_SERVICE_RECEIVEPACK = 4,
} git_smart_service_t; } git_smart_service_t;
struct git_smart_subtransport; typedef struct git_smart_subtransport git_smart_subtransport;
typedef struct git_smart_subtransport_stream git_smart_subtransport_stream;
/* A stream used by the smart transport to read and write data /* A stream used by the smart transport to read and write data
* from a subtransport */ * from a subtransport */
typedef struct git_smart_subtransport_stream { struct git_smart_subtransport_stream {
/* The owning subtransport */ /* The owning subtransport */
struct git_smart_subtransport *subtransport; git_smart_subtransport *subtransport;
int (*read)( int (*read)(
struct git_smart_subtransport_stream *stream, git_smart_subtransport_stream *stream,
char *buffer, char *buffer,
size_t buf_size, size_t buf_size,
size_t *bytes_read); size_t *bytes_read);
int (*write)( int (*write)(
struct git_smart_subtransport_stream *stream, git_smart_subtransport_stream *stream,
const char *buffer, const char *buffer,
size_t len); size_t len);
void (*free)( void (*free)(
struct git_smart_subtransport_stream *stream); git_smart_subtransport_stream *stream);
} git_smart_subtransport_stream; };
/* An implementation of a subtransport which carries data for the /* An implementation of a subtransport which carries data for the
* smart transport */ * smart transport */
typedef struct git_smart_subtransport { struct git_smart_subtransport {
int (* action)( int (* action)(
git_smart_subtransport_stream **out, git_smart_subtransport_stream **out,
struct git_smart_subtransport *transport, git_smart_subtransport *transport,
const char *url, const char *url,
git_smart_service_t action); git_smart_service_t action);
...@@ -337,10 +346,10 @@ typedef struct git_smart_subtransport { ...@@ -337,10 +346,10 @@ typedef struct git_smart_subtransport {
* *
* 1. UPLOADPACK_LS -> UPLOADPACK * 1. UPLOADPACK_LS -> UPLOADPACK
* 2. RECEIVEPACK_LS -> RECEIVEPACK */ * 2. RECEIVEPACK_LS -> RECEIVEPACK */
int (* close)(struct git_smart_subtransport *transport); int (*close)(git_smart_subtransport *transport);
void (* free)(struct git_smart_subtransport *transport); void (*free)(git_smart_subtransport *transport);
} git_smart_subtransport; };
/* A function which creates a new subtransport for the smart transport */ /* A function which creates a new subtransport for the smart transport */
typedef int (*git_smart_subtransport_cb)( typedef int (*git_smart_subtransport_cb)(
......
...@@ -73,7 +73,7 @@ static int transport_find_fn(const char *url, git_transport_cb *callback, void * ...@@ -73,7 +73,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 : /* 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 */ * SSH is an unsupported transport mechanism in this version of libgit2 */
if (!definition && strrchr(url, ':')) if (!definition && strrchr(url, ':'))
definition = &dummy_transport_definition; definition = &dummy_transport_definition;
#else #else
/* For other systems, perform the SSH check first, to avoid going to the /* For other systems, perform the SSH check first, to avoid going to the
* filesystem if it is not necessary */ * filesystem if it is not necessary */
...@@ -97,7 +97,7 @@ static int transport_find_fn(const char *url, git_transport_cb *callback, void * ...@@ -97,7 +97,7 @@ static int transport_find_fn(const char *url, git_transport_cb *callback, void *
*callback = definition->fn; *callback = definition->fn;
*param = definition->param; *param = definition->param;
return 0; return 0;
} }
......
...@@ -68,7 +68,7 @@ static void ssh_keyfile_passphrase_free(struct git_cred *cred) ...@@ -68,7 +68,7 @@ static void ssh_keyfile_passphrase_free(struct git_cred *cred)
if (c->publickey) { if (c->publickey) {
git__free(c->publickey); git__free(c->publickey);
} }
git__free(c->privatekey); git__free(c->privatekey);
if (c->passphrase) { if (c->passphrase) {
...@@ -82,12 +82,28 @@ static void ssh_keyfile_passphrase_free(struct git_cred *cred) ...@@ -82,12 +82,28 @@ static void ssh_keyfile_passphrase_free(struct git_cred *cred)
git__free(c); git__free(c);
} }
static void ssh_publickey_free(struct git_cred *cred)
{
git_cred_ssh_publickey *c = (git_cred_ssh_publickey *)cred;
git__free(c->publickey);
c->sign_callback = NULL;
c->sign_data = NULL;
memset(c, 0, sizeof(*c));
git__free(c);
}
#endif
int git_cred_ssh_keyfile_passphrase_new( int git_cred_ssh_keyfile_passphrase_new(
git_cred **cred, git_cred **cred,
const char *publickey, const char *publickey,
const char *privatekey, const char *privatekey,
const char *passphrase) const char *passphrase)
{ {
#ifdef GIT_SSH
git_cred_ssh_keyfile_passphrase *c; git_cred_ssh_keyfile_passphrase *c;
assert(cred && privatekey); assert(cred && privatekey);
...@@ -97,15 +113,15 @@ int git_cred_ssh_keyfile_passphrase_new( ...@@ -97,15 +113,15 @@ int git_cred_ssh_keyfile_passphrase_new(
c->parent.credtype = GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE; c->parent.credtype = GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE;
c->parent.free = ssh_keyfile_passphrase_free; c->parent.free = ssh_keyfile_passphrase_free;
c->privatekey = git__strdup(privatekey); c->privatekey = git__strdup(privatekey);
GITERR_CHECK_ALLOC(c->privatekey); GITERR_CHECK_ALLOC(c->privatekey);
if (publickey) { if (publickey) {
c->publickey = git__strdup(publickey); c->publickey = git__strdup(publickey);
GITERR_CHECK_ALLOC(c->publickey); GITERR_CHECK_ALLOC(c->publickey);
} }
if (passphrase) { if (passphrase) {
c->passphrase = git__strdup(passphrase); c->passphrase = git__strdup(passphrase);
GITERR_CHECK_ALLOC(c->passphrase); GITERR_CHECK_ALLOC(c->passphrase);
...@@ -113,29 +129,27 @@ int git_cred_ssh_keyfile_passphrase_new( ...@@ -113,29 +129,27 @@ int git_cred_ssh_keyfile_passphrase_new(
*cred = &c->parent; *cred = &c->parent;
return 0; return 0;
} #else
GIT_UNUSED(publickey);
static void ssh_publickey_free(struct git_cred *cred) GIT_UNUSED(privatekey);
{ GIT_UNUSED(passphrase);
git_cred_ssh_publickey *c = (git_cred_ssh_publickey *)cred;
git__free(c->publickey); assert(cred);
*cred = NULL;
c->sign_callback = NULL;
c->sign_data = NULL;
memset(c, 0, sizeof(*c));
git__free(c); giterr_set(GITERR_INVALID, "Cannot create SSH credential. Library was built without SSH support");
return -1;
#endif
} }
int git_cred_ssh_publickey_new( int git_cred_ssh_publickey_new(
git_cred **cred, git_cred **cred,
const char *publickey, const char *publickey,
size_t publickey_len, size_t publickey_len,
LIBSSH2_USERAUTH_PUBLICKEY_SIGN_FUNC((*sign_callback)), git_cred_sign_callback sign_callback,
void *sign_data) void *sign_data)
{ {
#ifdef GIT_SSH
git_cred_ssh_publickey *c; git_cred_ssh_publickey *c;
if (!cred) if (!cred)
...@@ -146,17 +160,28 @@ int git_cred_ssh_publickey_new( ...@@ -146,17 +160,28 @@ int git_cred_ssh_publickey_new(
c->parent.credtype = GIT_CREDTYPE_SSH_PUBLICKEY; c->parent.credtype = GIT_CREDTYPE_SSH_PUBLICKEY;
c->parent.free = ssh_publickey_free; c->parent.free = ssh_publickey_free;
c->publickey = git__malloc(publickey_len); c->publickey = git__malloc(publickey_len);
GITERR_CHECK_ALLOC(c->publickey); GITERR_CHECK_ALLOC(c->publickey);
memcpy(c->publickey, publickey, publickey_len); memcpy(c->publickey, publickey, publickey_len);
c->publickey_len = publickey_len; c->publickey_len = publickey_len;
c->sign_callback = sign_callback; c->sign_callback = sign_callback;
c->sign_data = sign_data; c->sign_data = sign_data;
*cred = &c->parent; *cred = &c->parent;
return 0; return 0;
} #else
GIT_UNUSED(publickey);
GIT_UNUSED(publickey_len);
GIT_UNUSED(sign_callback);
GIT_UNUSED(sign_data);
assert(cred);
*cred = NULL;
giterr_set(GITERR_INVALID, "Cannot create SSH credential. Library was built without SSH support");
return -1;
#endif #endif
}
...@@ -5,13 +5,13 @@ ...@@ -5,13 +5,13 @@
* a Linking Exception. For full terms see the included COPYING file. * a Linking Exception. For full terms see the included COPYING file.
*/ */
#ifdef GIT_SSH
#include "git2.h" #include "git2.h"
#include "buffer.h" #include "buffer.h"
#include "netops.h" #include "netops.h"
#include "smart.h" #include "smart.h"
#ifdef GIT_SSH
#include <libssh2.h> #include <libssh2.h>
#define OWNING_SUBTRANSPORT(s) ((ssh_subtransport *)(s)->parent.subtransport) #define OWNING_SUBTRANSPORT(s) ((ssh_subtransport *)(s)->parent.subtransport)
...@@ -46,27 +46,27 @@ typedef struct { ...@@ -46,27 +46,27 @@ typedef struct {
static int gen_proto(git_buf *request, const char *cmd, const char *url) static int gen_proto(git_buf *request, const char *cmd, const char *url)
{ {
char *repo; char *repo;
if (!git__prefixcmp(url, prefix_ssh)) { if (!git__prefixcmp(url, prefix_ssh)) {
url = url + strlen(prefix_ssh); url = url + strlen(prefix_ssh);
repo = strchr(url, '/'); repo = strchr(url, '/');
} else { } else {
repo = strchr(url, ':'); repo = strchr(url, ':');
} }
if (!repo) { if (!repo) {
return -1; return -1;
} }
int len = strlen(cmd) + 1 /* Space */ + 1 /* Quote */ + strlen(repo) + 1 /* Quote */ + 1; int len = strlen(cmd) + 1 /* Space */ + 1 /* Quote */ + strlen(repo) + 1 /* Quote */ + 1;
git_buf_grow(request, len); git_buf_grow(request, len);
git_buf_printf(request, "%s '%s'", cmd, repo); git_buf_printf(request, "%s '%s'", cmd, repo);
git_buf_putc(request, '\0'); git_buf_putc(request, '\0');
if (git_buf_oom(request)) if (git_buf_oom(request))
return -1; return -1;
return 0; return 0;
} }
...@@ -74,11 +74,11 @@ static int send_command(ssh_stream *s) ...@@ -74,11 +74,11 @@ static int send_command(ssh_stream *s)
{ {
int error; int error;
git_buf request = GIT_BUF_INIT; git_buf request = GIT_BUF_INIT;
error = gen_proto(&request, s->cmd, s->url); error = gen_proto(&request, s->cmd, s->url);
if (error < 0) if (error < 0)
goto cleanup; goto cleanup;
error = libssh2_channel_exec( error = libssh2_channel_exec(
s->channel, s->channel,
request.ptr request.ptr
...@@ -86,9 +86,9 @@ static int send_command(ssh_stream *s) ...@@ -86,9 +86,9 @@ static int send_command(ssh_stream *s)
if (0 != error) if (0 != error)
goto cleanup; goto cleanup;
s->sent_command = 1; s->sent_command = 1;
cleanup: cleanup:
git_buf_free(&request); git_buf_free(&request);
return error; return error;
...@@ -101,18 +101,18 @@ static int ssh_stream_read( ...@@ -101,18 +101,18 @@ static int ssh_stream_read(
size_t *bytes_read) size_t *bytes_read)
{ {
ssh_stream *s = (ssh_stream *)stream; ssh_stream *s = (ssh_stream *)stream;
*bytes_read = 0; *bytes_read = 0;
if (!s->sent_command && send_command(s) < 0) if (!s->sent_command && send_command(s) < 0)
return -1; return -1;
int rc = libssh2_channel_read(s->channel, buffer, buf_size); int rc = libssh2_channel_read(s->channel, buffer, buf_size);
if (rc < 0) if (rc < 0)
return -1; return -1;
*bytes_read = rc; *bytes_read = rc;
return 0; return 0;
} }
...@@ -122,15 +122,15 @@ static int ssh_stream_write( ...@@ -122,15 +122,15 @@ static int ssh_stream_write(
size_t len) size_t len)
{ {
ssh_stream *s = (ssh_stream *)stream; ssh_stream *s = (ssh_stream *)stream;
if (!s->sent_command && send_command(s) < 0) if (!s->sent_command && send_command(s) < 0)
return -1; return -1;
int rc = libssh2_channel_write(s->channel, buffer, len); int rc = libssh2_channel_write(s->channel, buffer, len);
if (rc < 0) { if (rc < 0) {
return -1; return -1;
} }
return rc; return rc;
} }
...@@ -139,26 +139,26 @@ static void ssh_stream_free(git_smart_subtransport_stream *stream) ...@@ -139,26 +139,26 @@ static void ssh_stream_free(git_smart_subtransport_stream *stream)
ssh_stream *s = (ssh_stream *)stream; ssh_stream *s = (ssh_stream *)stream;
ssh_subtransport *t = OWNING_SUBTRANSPORT(s); ssh_subtransport *t = OWNING_SUBTRANSPORT(s);
int ret; int ret;
GIT_UNUSED(ret); GIT_UNUSED(ret);
t->current_stream = NULL; t->current_stream = NULL;
if (s->channel) { if (s->channel) {
libssh2_channel_close(s->channel); libssh2_channel_close(s->channel);
libssh2_channel_free(s->channel); libssh2_channel_free(s->channel);
s->channel = NULL; s->channel = NULL;
} }
if (s->session) { if (s->session) {
libssh2_session_free(s->session), s->session = NULL; libssh2_session_free(s->session), s->session = NULL;
} }
if (s->socket.socket) { if (s->socket.socket) {
ret = gitno_close(&s->socket); ret = gitno_close(&s->socket);
assert(!ret); assert(!ret);
} }
git__free(s->url); git__free(s->url);
git__free(s); git__free(s);
} }
...@@ -170,26 +170,26 @@ static int ssh_stream_alloc( ...@@ -170,26 +170,26 @@ static int ssh_stream_alloc(
git_smart_subtransport_stream **stream) git_smart_subtransport_stream **stream)
{ {
ssh_stream *s; ssh_stream *s;
if (!stream) if (!stream)
return -1; return -1;
s = git__calloc(sizeof(ssh_stream), 1); s = git__calloc(sizeof(ssh_stream), 1);
GITERR_CHECK_ALLOC(s); GITERR_CHECK_ALLOC(s);
s->parent.subtransport = &t->parent; s->parent.subtransport = &t->parent;
s->parent.read = ssh_stream_read; s->parent.read = ssh_stream_read;
s->parent.write = ssh_stream_write; s->parent.write = ssh_stream_write;
s->parent.free = ssh_stream_free; s->parent.free = ssh_stream_free;
s->cmd = cmd; s->cmd = cmd;
s->url = git__strdup(url); s->url = git__strdup(url);
if (!s->url) { if (!s->url) {
git__free(s); git__free(s);
return -1; return -1;
} }
*stream = &s->parent; *stream = &s->parent;
return 0; return 0;
} }
...@@ -201,14 +201,14 @@ static int git_ssh_extract_url_parts( ...@@ -201,14 +201,14 @@ static int git_ssh_extract_url_parts(
{ {
char *colon, *at; char *colon, *at;
const char *start; const char *start;
colon = strchr(url, ':'); colon = strchr(url, ':');
if (colon == NULL) { if (colon == NULL) {
giterr_set(GITERR_NET, "Malformed URL: missing :"); giterr_set(GITERR_NET, "Malformed URL: missing :");
return -1; return -1;
} }
at = strchr(url, '@'); at = strchr(url, '@');
if (at) { if (at) {
start = at+1; start = at+1;
...@@ -217,9 +217,9 @@ static int git_ssh_extract_url_parts( ...@@ -217,9 +217,9 @@ static int git_ssh_extract_url_parts(
start = url; start = url;
*username = git__strdup(default_user); *username = git__strdup(default_user);
} }
*host = git__substrdup(start, colon - start); *host = git__substrdup(start, colon - start);
return 0; return 0;
} }
...@@ -235,7 +235,7 @@ static int _git_ssh_authenticate_session( ...@@ -235,7 +235,7 @@ static int _git_ssh_authenticate_session(
case GIT_CREDTYPE_USERPASS_PLAINTEXT: { case GIT_CREDTYPE_USERPASS_PLAINTEXT: {
git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred; git_cred_userpass_plaintext *c = (git_cred_userpass_plaintext *)cred;
rc = libssh2_userauth_password( rc = libssh2_userauth_password(
session, session,
c->username, c->username,
c->password c->password
); );
...@@ -244,7 +244,7 @@ static int _git_ssh_authenticate_session( ...@@ -244,7 +244,7 @@ static int _git_ssh_authenticate_session(
case GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE: { case GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE: {
git_cred_ssh_keyfile_passphrase *c = (git_cred_ssh_keyfile_passphrase *)cred; git_cred_ssh_keyfile_passphrase *c = (git_cred_ssh_keyfile_passphrase *)cred;
rc = libssh2_userauth_publickey_fromfile( rc = libssh2_userauth_publickey_fromfile(
session, session,
user, user,
c->publickey, c->publickey,
c->privatekey, c->privatekey,
...@@ -268,7 +268,7 @@ static int _git_ssh_authenticate_session( ...@@ -268,7 +268,7 @@ static int _git_ssh_authenticate_session(
rc = LIBSSH2_ERROR_AUTHENTICATION_FAILED; rc = LIBSSH2_ERROR_AUTHENTICATION_FAILED;
} }
} while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc); } while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc);
return rc; return rc;
} }
...@@ -281,31 +281,31 @@ static int _git_ssh_session_create ...@@ -281,31 +281,31 @@ static int _git_ssh_session_create
if (!session) { if (!session) {
return -1; return -1;
} }
LIBSSH2_SESSION* s = libssh2_session_init(); LIBSSH2_SESSION* s = libssh2_session_init();
if (!s) if (!s)
return -1; return -1;
int rc = 0; int rc = 0;
do { do {
rc = libssh2_session_startup(s, socket.socket); rc = libssh2_session_startup(s, socket.socket);
} while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc); } while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc);
if (0 != rc) { if (0 != rc) {
goto on_error; goto on_error;
} }
libssh2_session_set_blocking(s, 1); libssh2_session_set_blocking(s, 1);
*session = s; *session = s;
return 0; return 0;
on_error: on_error:
if (s) { if (s) {
libssh2_session_free(s), s = NULL; libssh2_session_free(s), s = NULL;
} }
return -1; return -1;
} }
...@@ -321,13 +321,13 @@ static int _git_ssh_setup_conn( ...@@ -321,13 +321,13 @@ static int _git_ssh_setup_conn(
ssh_stream *s; ssh_stream *s;
LIBSSH2_SESSION* session=NULL; LIBSSH2_SESSION* session=NULL;
LIBSSH2_CHANNEL* channel=NULL; LIBSSH2_CHANNEL* channel=NULL;
*stream = NULL; *stream = NULL;
if (ssh_stream_alloc(t, url, cmd, stream) < 0) if (ssh_stream_alloc(t, url, cmd, stream) < 0)
return -1; return -1;
s = (ssh_stream *)*stream; s = (ssh_stream *)*stream;
if (!git__prefixcmp(url, prefix_ssh)) { if (!git__prefixcmp(url, prefix_ssh)) {
url = url + strlen(prefix_ssh); url = url + strlen(prefix_ssh);
if (gitno_extract_url_parts(&host, &port, &user, &pass, url, default_port) < 0) if (gitno_extract_url_parts(&host, &port, &user, &pass, url, default_port) < 0)
...@@ -338,10 +338,10 @@ static int _git_ssh_setup_conn( ...@@ -338,10 +338,10 @@ static int _git_ssh_setup_conn(
port = git__strdup(default_port); port = git__strdup(default_port);
GITERR_CHECK_ALLOC(port); GITERR_CHECK_ALLOC(port);
} }
if (gitno_connect(&s->socket, host, port, 0) < 0) if (gitno_connect(&s->socket, host, port, 0) < 0)
goto on_error; goto on_error;
if (user && pass) { if (user && pass) {
if (git_cred_userpass_plaintext_new(&t->cred, user, pass) < 0) if (git_cred_userpass_plaintext_new(&t->cred, user, pass) < 0)
goto on_error; goto on_error;
...@@ -354,26 +354,26 @@ static int _git_ssh_setup_conn( ...@@ -354,26 +354,26 @@ static int _git_ssh_setup_conn(
return -1; return -1;
} }
assert(t->cred); assert(t->cred);
if (!user) { if (!user) {
user = git__strdup(default_user); user = git__strdup(default_user);
} }
if (_git_ssh_session_create(&session, s->socket) < 0) if (_git_ssh_session_create(&session, s->socket) < 0)
goto on_error; goto on_error;
if (_git_ssh_authenticate_session(session, user, t->cred) < 0) if (_git_ssh_authenticate_session(session, user, t->cred) < 0)
goto on_error; goto on_error;
channel = libssh2_channel_open_session(session); channel = libssh2_channel_open_session(session);
if (!channel) if (!channel)
goto on_error; goto on_error;
libssh2_channel_set_blocking(channel, 1); libssh2_channel_set_blocking(channel, 1);
s->session = session; s->session = session;
s->channel = channel; s->channel = channel;
t->current_stream = s; t->current_stream = s;
git__free(host); git__free(host);
git__free(port); git__free(port);
...@@ -381,11 +381,11 @@ static int _git_ssh_setup_conn( ...@@ -381,11 +381,11 @@ static int _git_ssh_setup_conn(
git__free(pass); git__free(pass);
return 0; return 0;
on_error: on_error:
if (*stream) if (*stream)
ssh_stream_free(*stream); ssh_stream_free(*stream);
git__free(host); git__free(host);
git__free(port); git__free(port);
git__free(user); git__free(user);
...@@ -404,7 +404,7 @@ static int ssh_uploadpack_ls( ...@@ -404,7 +404,7 @@ static int ssh_uploadpack_ls(
{ {
if (_git_ssh_setup_conn(t, url, cmd_uploadpack, stream) < 0) if (_git_ssh_setup_conn(t, url, cmd_uploadpack, stream) < 0)
return -1; return -1;
return 0; return 0;
} }
...@@ -414,12 +414,12 @@ static int ssh_uploadpack( ...@@ -414,12 +414,12 @@ static int ssh_uploadpack(
git_smart_subtransport_stream **stream) git_smart_subtransport_stream **stream)
{ {
GIT_UNUSED(url); GIT_UNUSED(url);
if (t->current_stream) { if (t->current_stream) {
*stream = &t->current_stream->parent; *stream = &t->current_stream->parent;
return 0; return 0;
} }
giterr_set(GITERR_NET, "Must call UPLOADPACK_LS before UPLOADPACK"); giterr_set(GITERR_NET, "Must call UPLOADPACK_LS before UPLOADPACK");
return -1; return -1;
} }
...@@ -431,7 +431,7 @@ static int ssh_receivepack_ls( ...@@ -431,7 +431,7 @@ static int ssh_receivepack_ls(
{ {
if (_git_ssh_setup_conn(t, url, cmd_receivepack, stream) < 0) if (_git_ssh_setup_conn(t, url, cmd_receivepack, stream) < 0)
return -1; return -1;
return 0; return 0;
} }
...@@ -441,12 +441,12 @@ static int ssh_receivepack( ...@@ -441,12 +441,12 @@ static int ssh_receivepack(
git_smart_subtransport_stream **stream) git_smart_subtransport_stream **stream)
{ {
GIT_UNUSED(url); GIT_UNUSED(url);
if (t->current_stream) { if (t->current_stream) {
*stream = &t->current_stream->parent; *stream = &t->current_stream->parent;
return 0; return 0;
} }
giterr_set(GITERR_NET, "Must call RECEIVEPACK_LS before RECEIVEPACK"); giterr_set(GITERR_NET, "Must call RECEIVEPACK_LS before RECEIVEPACK");
return -1; return -1;
} }
...@@ -458,21 +458,21 @@ static int _ssh_action( ...@@ -458,21 +458,21 @@ static int _ssh_action(
git_smart_service_t action) git_smart_service_t action)
{ {
ssh_subtransport *t = (ssh_subtransport *) subtransport; ssh_subtransport *t = (ssh_subtransport *) subtransport;
switch (action) { switch (action) {
case GIT_SERVICE_UPLOADPACK_LS: case GIT_SERVICE_UPLOADPACK_LS:
return ssh_uploadpack_ls(t, url, stream); return ssh_uploadpack_ls(t, url, stream);
case GIT_SERVICE_UPLOADPACK: case GIT_SERVICE_UPLOADPACK:
return ssh_uploadpack(t, url, stream); return ssh_uploadpack(t, url, stream);
case GIT_SERVICE_RECEIVEPACK_LS: case GIT_SERVICE_RECEIVEPACK_LS:
return ssh_receivepack_ls(t, url, stream); return ssh_receivepack_ls(t, url, stream);
case GIT_SERVICE_RECEIVEPACK: case GIT_SERVICE_RECEIVEPACK:
return ssh_receivepack(t, url, stream); return ssh_receivepack(t, url, stream);
} }
*stream = NULL; *stream = NULL;
return -1; return -1;
} }
...@@ -480,40 +480,49 @@ static int _ssh_action( ...@@ -480,40 +480,49 @@ static int _ssh_action(
static int _ssh_close(git_smart_subtransport *subtransport) static int _ssh_close(git_smart_subtransport *subtransport)
{ {
ssh_subtransport *t = (ssh_subtransport *) subtransport; ssh_subtransport *t = (ssh_subtransport *) subtransport;
assert(!t->current_stream); assert(!t->current_stream);
GIT_UNUSED(t); GIT_UNUSED(t);
return 0; return 0;
} }
static void _ssh_free(git_smart_subtransport *subtransport) static void _ssh_free(git_smart_subtransport *subtransport)
{ {
ssh_subtransport *t = (ssh_subtransport *) subtransport; ssh_subtransport *t = (ssh_subtransport *) subtransport;
assert(!t->current_stream); assert(!t->current_stream);
git__free(t); git__free(t);
} }
#endif
int git_smart_subtransport_ssh(git_smart_subtransport **out, git_transport *owner) int git_smart_subtransport_ssh(
git_smart_subtransport **out, git_transport *owner)
{ {
#ifdef GIT_SSH
ssh_subtransport *t; ssh_subtransport *t;
if (!out) assert(out);
return -1;
t = git__calloc(sizeof(ssh_subtransport), 1); t = git__calloc(sizeof(ssh_subtransport), 1);
GITERR_CHECK_ALLOC(t); GITERR_CHECK_ALLOC(t);
t->owner = (transport_smart *)owner; t->owner = (transport_smart *)owner;
t->parent.action = _ssh_action; t->parent.action = _ssh_action;
t->parent.close = _ssh_close; t->parent.close = _ssh_close;
t->parent.free = _ssh_free; t->parent.free = _ssh_free;
*out = (git_smart_subtransport *) t; *out = (git_smart_subtransport *) t;
return 0; return 0;
} #else
GIT_UNUSED(owner);
assert(out);
*out = NULL;
giterr_set(GITERR_INVALID, "Cannot create SSH transport. Library was built without SSH support");
return -1;
#endif #endif
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment