Commit c2de6b1a by Russell Belfer

Bring SSH error reporting up to base standards

The SSH error checking and reporting could still be further
improved by using the libssh2 native methods to get error info,
but at least this ensures that all error codes are checked and
translated into libgit2 error messages.
parent 68bc49a1
...@@ -33,8 +33,7 @@ int git_cred_userpass_plaintext_new( ...@@ -33,8 +33,7 @@ int git_cred_userpass_plaintext_new(
{ {
git_cred_userpass_plaintext *c; git_cred_userpass_plaintext *c;
if (!cred) assert(cred);
return -1;
c = git__malloc(sizeof(git_cred_userpass_plaintext)); c = git__malloc(sizeof(git_cred_userpass_plaintext));
GITERR_CHECK_ALLOC(c); GITERR_CHECK_ALLOC(c);
......
...@@ -55,6 +55,7 @@ static int gen_proto(git_buf *request, const char *cmd, const char *url) ...@@ -55,6 +55,7 @@ static int gen_proto(git_buf *request, const char *cmd, const char *url)
} }
if (!repo) { if (!repo) {
giterr_set(GITERR_NET, "Malformed git protocol URL");
return -1; return -1;
} }
...@@ -79,13 +80,11 @@ static int send_command(ssh_stream *s) ...@@ -79,13 +80,11 @@ static int send_command(ssh_stream *s)
if (error < 0) if (error < 0)
goto cleanup; goto cleanup;
error = libssh2_channel_exec( error = libssh2_channel_exec(s->channel, request.ptr);
s->channel, if (error < 0) {
request.ptr giterr_set(GITERR_NET, "SSH could not execute request");
);
if (0 != error)
goto cleanup; goto cleanup;
}
s->sent_command = 1; s->sent_command = 1;
...@@ -100,6 +99,7 @@ static int ssh_stream_read( ...@@ -100,6 +99,7 @@ static int ssh_stream_read(
size_t buf_size, size_t buf_size,
size_t *bytes_read) size_t *bytes_read)
{ {
int rc;
ssh_stream *s = (ssh_stream *)stream; ssh_stream *s = (ssh_stream *)stream;
*bytes_read = 0; *bytes_read = 0;
...@@ -107,9 +107,10 @@ static int ssh_stream_read( ...@@ -107,9 +107,10 @@ static int ssh_stream_read(
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); if ((rc = libssh2_channel_read(s->channel, buffer, buf_size)) < 0) {
if (rc < 0) giterr_set(GITERR_NET, "SSH could not read data");
return -1; return -1;
}
*bytes_read = rc; *bytes_read = rc;
...@@ -126,12 +127,12 @@ static int ssh_stream_write( ...@@ -126,12 +127,12 @@ static int ssh_stream_write(
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); if (libssh2_channel_write(s->channel, buffer, len) < 0) {
if (rc < 0) { giterr_set(GITERR_NET, "SSH could not write data");
return -1; return -1;
} }
return rc; return 0;
} }
static void ssh_stream_free(git_smart_subtransport_stream *stream) static void ssh_stream_free(git_smart_subtransport_stream *stream)
...@@ -151,12 +152,13 @@ static void ssh_stream_free(git_smart_subtransport_stream *stream) ...@@ -151,12 +152,13 @@ static void ssh_stream_free(git_smart_subtransport_stream *stream)
} }
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); (void)gitno_close(&s->socket);
assert(!ret); /* can't do anything here with error return value */
} }
git__free(s->url); git__free(s->url);
...@@ -171,8 +173,7 @@ static int ssh_stream_alloc( ...@@ -171,8 +173,7 @@ static int ssh_stream_alloc(
{ {
ssh_stream *s; ssh_stream *s;
if (!stream) assert(stream);
return -1;
s = git__calloc(sizeof(ssh_stream), 1); s = git__calloc(sizeof(ssh_stream), 1);
GITERR_CHECK_ALLOC(s); GITERR_CHECK_ALLOC(s);
...@@ -183,8 +184,8 @@ static int ssh_stream_alloc( ...@@ -183,8 +184,8 @@ static int ssh_stream_alloc(
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;
...@@ -217,8 +218,10 @@ static int git_ssh_extract_url_parts( ...@@ -217,8 +218,10 @@ static int git_ssh_extract_url_parts(
start = url; start = url;
*username = git__strdup(default_user); *username = git__strdup(default_user);
} }
GITERR_CHECK_ALLOC(*username);
*host = git__substrdup(start, colon - start); *host = git__substrdup(start, colon - start);
GITERR_CHECK_ALLOC(*host);
return 0; return 0;
} }
...@@ -229,67 +232,63 @@ static int _git_ssh_authenticate_session( ...@@ -229,67 +232,63 @@ static int _git_ssh_authenticate_session(
git_cred* cred) git_cred* cred)
{ {
int rc; int rc;
do { do {
switch (cred->credtype) { switch (cred->credtype) {
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, c->username, c->password);
session, break;
c->username, }
c->password case GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE: {
); git_cred_ssh_keyfile_passphrase *c = (git_cred_ssh_keyfile_passphrase *)cred;
break; rc = libssh2_userauth_publickey_fromfile(
} session, user, c->publickey, c->privatekey, c->passphrase);
case GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE: { break;
git_cred_ssh_keyfile_passphrase *c = (git_cred_ssh_keyfile_passphrase *)cred; }
rc = libssh2_userauth_publickey_fromfile( case GIT_CREDTYPE_SSH_PUBLICKEY: {
session, git_cred_ssh_publickey *c = (git_cred_ssh_publickey *)cred;
user, rc = libssh2_userauth_publickey(
c->publickey, session, user, (const unsigned char *)c->publickey,
c->privatekey, c->publickey_len, c->sign_callback, &c->sign_data);
c->passphrase break;
); }
break; default:
} rc = LIBSSH2_ERROR_AUTHENTICATION_FAILED;
case GIT_CREDTYPE_SSH_PUBLICKEY: {
git_cred_ssh_publickey *c = (git_cred_ssh_publickey *)cred;
rc = libssh2_userauth_publickey(
session,
user,
(const unsigned char *)c->publickey,
c->publickey_len,
c->sign_callback,
&c->sign_data
);
break;
}
default:
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; if (rc != 0) {
giterr_set(GITERR_NET, "Failed to authenticate SSH session");
return -1;
}
return 0;
} }
static int _git_ssh_session_create( static int _git_ssh_session_create(
LIBSSH2_SESSION** session, LIBSSH2_SESSION** session,
gitno_socket socket) gitno_socket socket)
{ {
if (!session) { int rc = 0;
return -1; LIBSSH2_SESSION* s;
}
LIBSSH2_SESSION* s = libssh2_session_init(); assert(session);
if (!s)
s = libssh2_session_init();
if (!s) {
giterr_set(GITERR_NET, "Failed to initialize SSH session");
return -1; return -1;
}
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; libssh2_session_free(s);
giterr_set(GITERR_NET, "Failed to start SSH session");
return -1;
} }
libssh2_session_set_blocking(s, 1); libssh2_session_set_blocking(s, 1);
...@@ -297,21 +296,13 @@ static int _git_ssh_session_create( ...@@ -297,21 +296,13 @@ static int _git_ssh_session_create(
*session = s; *session = s;
return 0; return 0;
on_error:
if (s) {
libssh2_session_free(s), s = NULL;
}
return -1;
} }
static int _git_ssh_setup_conn( static int _git_ssh_setup_conn(
ssh_subtransport *t, ssh_subtransport *t,
const char *url, const char *url,
const char *cmd, const char *cmd,
git_smart_subtransport_stream **stream git_smart_subtransport_stream **stream)
)
{ {
char *host, *port=NULL, *user=NULL, *pass=NULL; char *host, *port=NULL, *user=NULL, *pass=NULL;
const char *default_port="22"; const char *default_port="22";
...@@ -343,12 +334,17 @@ static int _git_ssh_setup_conn( ...@@ -343,12 +334,17 @@ static int _git_ssh_setup_conn(
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;
} else if (t->owner->cred_acquire_cb) { } else if (t->owner->cred_acquire_cb) {
if (t->owner->cred_acquire_cb(&t->cred, if (t->owner->cred_acquire_cb(
t->owner->url, &t->cred, t->owner->url, user,
user, GIT_CREDTYPE_USERPASS_PLAINTEXT |
GIT_CREDTYPE_USERPASS_PLAINTEXT | GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE, GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE,
t->owner->cred_acquire_payload) < 0) t->owner->cred_acquire_payload) < 0)
goto on_error; goto on_error;
if (!t->cred) {
giterr_set(GITERR_NET, "Callback failed to initialize SSH credentials");
goto on_error;
}
} else { } else {
giterr_set(GITERR_NET, "Cannot set up SSH connection without credentials"); giterr_set(GITERR_NET, "Cannot set up SSH connection without credentials");
goto on_error; goto on_error;
...@@ -357,17 +353,14 @@ static int _git_ssh_setup_conn( ...@@ -357,17 +353,14 @@ static int _git_ssh_setup_conn(
if (!user) { if (!user) {
user = git__strdup(default_user); user = git__strdup(default_user);
GITERR_CHECK_ALLOC(user);
} }
if (_git_ssh_session_create(&session, s->socket) < 0) { if (_git_ssh_session_create(&session, s->socket) < 0)
giterr_set(GITERR_NET, "Failed to initialize SSH session");
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)
giterr_set(GITERR_NET, "Failed to authenticate SSH session");
goto on_error; goto on_error;
}
channel = libssh2_channel_open_session(session); channel = libssh2_channel_open_session(session);
if (!channel) { if (!channel) {
...@@ -402,7 +395,7 @@ on_error: ...@@ -402,7 +395,7 @@ on_error:
git__free(pass); git__free(pass);
if (session) if (session)
libssh2_session_free(session), session = NULL; libssh2_session_free(session);
return -1; return -1;
} }
......
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