Phase II of packet loop migration: Clean code is good code

This commit is contained in:
Sara Golemon 2005-04-01 20:17:09 +00:00
parent 5d9c0d50f3
commit d3f854c21b
2 changed files with 246 additions and 308 deletions

View File

@ -106,6 +106,7 @@ LIBSSH2_CHANNEL *libssh2_channel_locate(LIBSSH2_SESSION *session, unsigned long
LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_open_ex(LIBSSH2_SESSION *session, char *channel_type, int channel_type_len, int window_size, int packet_size, LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_open_ex(LIBSSH2_SESSION *session, char *channel_type, int channel_type_len, int window_size, int packet_size,
char *message, int message_len) char *message, int message_len)
{ {
unsigned char reply_codes[3] = { SSH_MSG_CHANNEL_OPEN_CONFIRMATION, SSH_MSG_CHANNEL_OPEN_FAILURE, 0 };
LIBSSH2_CHANNEL *channel = NULL; LIBSSH2_CHANNEL *channel = NULL;
unsigned long local_channel = libssh2_channel_nextid(session); unsigned long local_channel = libssh2_channel_nextid(session);
unsigned char *s, *packet = NULL; unsigned char *s, *packet = NULL;
@ -113,7 +114,6 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_open_ex(LIBSSH2_SESSION *session, c
window_size(4) + packet_size(4) */ window_size(4) + packet_size(4) */
unsigned char *data = NULL; unsigned char *data = NULL;
unsigned long data_len; unsigned long data_len;
int polls = 0;
channel = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_CHANNEL)); channel = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_CHANNEL));
if (!channel) { if (!channel) {
@ -161,35 +161,25 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_open_ex(LIBSSH2_SESSION *session, c
goto channel_error; goto channel_error;
} }
while (session->socket_state != LIBSSH2_SOCKET_DISCONNECTED) { if (libssh2_packet_requirev_ex(session, reply_codes, &data, &data_len, 1, packet + 5 + channel_type_len, 4)) {
if (libssh2_packet_ask_ex(session, SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &data, &data_len, 1, packet + 5 + channel_type_len, 4, 1) == 0) { goto channel_error;
/* YAY! You like me! */
break;
}
if (libssh2_packet_ask_ex(session, SSH_MSG_CHANNEL_OPEN_FAILURE, &data, &data_len, 1, packet + 5 + channel_type_len, 4, 0) == 0) {
/* But! Dear! I thought we had something! */
/* TODO: provide reason code and description */
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE, "Channel open failure", 0);
goto channel_error;
}
usleep(LIBSSH2_SOCKET_POLL_UDELAY);
if (polls++ > LIBSSH2_SOCKET_POLL_MAXLOOPS) {
/* Give up waiting */
libssh2_error(session, LIBSSH2_ERROR_SOCKET_TIMEOUT, "Timed out waiting for response", 0);
goto channel_error;
}
} }
channel->remote.id = libssh2_ntohu32(data + 5); if (data[0] == SSH_MSG_CHANNEL_OPEN_CONFIRMATION) {
channel->local.window_size = libssh2_ntohu32(data + 9); channel->remote.id = libssh2_ntohu32(data + 5);
channel->local.window_size_initial = libssh2_ntohu32(data + 9); channel->local.window_size = libssh2_ntohu32(data + 9);
channel->local.packet_size = libssh2_ntohu32(data + 13); channel->local.window_size_initial = libssh2_ntohu32(data + 9);
channel->local.packet_size = libssh2_ntohu32(data + 13);
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
return channel; return channel;
}
if (data[0] == SSH_MSG_CHANNEL_OPEN_FAILURE) {
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_FAILURE, "Channel open failure", 0);
}
channel_error: channel_error:
@ -265,7 +255,8 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_direct_tcpip_ex(LIBSSH2_SESSION *se
*/ */
LIBSSH2_API LIBSSH2_LISTENER *libssh2_channel_forward_listen_ex(LIBSSH2_SESSION *session, char *host, int port, int *bound_port, int queue_maxsize) LIBSSH2_API LIBSSH2_LISTENER *libssh2_channel_forward_listen_ex(LIBSSH2_SESSION *session, char *host, int port, int *bound_port, int queue_maxsize)
{ {
unsigned char *packet, *s; unsigned char *packet, *s, *data, reply_codes[3] = { SSH_MSG_REQUEST_SUCCESS, SSH_MSG_REQUEST_FAILURE, 0 };
unsigned long data_len;
unsigned long host_len = (host ? strlen(host) : (sizeof("0.0.0.0") - 1)); unsigned long host_len = (host ? strlen(host) : (sizeof("0.0.0.0") - 1));
unsigned long packet_len = host_len + (sizeof("tcpip-forward") - 1) + 14; unsigned long packet_len = host_len + (sizeof("tcpip-forward") - 1) + 14;
/* packet_type(1) + request_len(4) + want_replay(1) + host_len(4) + port(4) */ /* packet_type(1) + request_len(4) + want_replay(1) + host_len(4) + port(4) */
@ -292,59 +283,58 @@ LIBSSH2_API LIBSSH2_LISTENER *libssh2_channel_forward_listen_ex(LIBSSH2_SESSION
} }
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
while (session->socket_state == LIBSSH2_SOCKET_CONNECTED) { if (libssh2_packet_requirev(session, reply_codes, &data, &data_len)) {
unsigned char *data; return NULL;
unsigned long data_len; }
if (libssh2_packet_ask(session, SSH_MSG_REQUEST_SUCCESS, &data, &data_len, 1) == 0) { if (data[0] == SSH_MSG_REQUEST_SUCCESS) {
LIBSSH2_LISTENER *listener; LIBSSH2_LISTENER *listener;
listener = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_LISTENER));
if (!listener) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for listener queue", 0);
LIBSSH2_FREE(session, data);
return NULL;
}
memset(listener, 0, sizeof(LIBSSH2_LISTENER));
listener->session = session;
listener->host = LIBSSH2_ALLOC(session, host_len + 1);
if (!listener->host) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for listener queue", 0);
LIBSSH2_FREE(session, listener);
LIBSSH2_FREE(session, data);
return NULL;
}
memcpy(listener->host, host ? host : "0.0.0.0", host_len);
listener->host[host_len] = 0;
if (data_len >= 5 && !port) {
listener->port = libssh2_ntohu32(data + 1);
} else {
listener->port = port;
}
listener->queue_size = 0;
listener->queue_maxsize = queue_maxsize;
listener->next = session->listeners;
listener->prev = NULL;
if (session->listeners) {
session->listeners->prev = listener;
}
session->listeners = listener;
if (bound_port) {
*bound_port = listener->port;
}
listener = LIBSSH2_ALLOC(session, sizeof(LIBSSH2_LISTENER));
if (!listener) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for listener queue", 0);
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
return listener;
}
if (libssh2_packet_ask(session, SSH_MSG_REQUEST_FAILURE, &data, &data_len, 0) == 0) {
LIBSSH2_FREE(session, data);
libssh2_error(session, LIBSSH2_ERROR_REQUEST_DENIED, "Unable to complete request for forward-listen", 0);
return NULL; return NULL;
} }
memset(listener, 0, sizeof(LIBSSH2_LISTENER));
listener->session = session;
listener->host = LIBSSH2_ALLOC(session, host_len + 1);
if (!listener->host) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for listener queue", 0);
LIBSSH2_FREE(session, listener);
LIBSSH2_FREE(session, data);
return NULL;
}
memcpy(listener->host, host ? host : "0.0.0.0", host_len);
listener->host[host_len] = 0;
if (data_len >= 5 && !port) {
listener->port = libssh2_ntohu32(data + 1);
} else {
listener->port = port;
}
listener->queue_size = 0;
listener->queue_maxsize = queue_maxsize;
listener->next = session->listeners;
listener->prev = NULL;
if (session->listeners) {
session->listeners->prev = listener;
}
session->listeners = listener;
if (bound_port) {
*bound_port = listener->port;
}
LIBSSH2_FREE(session, data);
return listener;
}
if (data[0] == SSH_MSG_REQUEST_FAILURE) {
LIBSSH2_FREE(session, data);
libssh2_error(session, LIBSSH2_ERROR_REQUEST_DENIED, "Unable to complete request for forward-listen", 0);
return NULL;
} }
return NULL; return NULL;
@ -451,7 +441,8 @@ LIBSSH2_API LIBSSH2_CHANNEL *libssh2_channel_forward_accept(LIBSSH2_LISTENER *li
LIBSSH2_API int libssh2_channel_setenv_ex(LIBSSH2_CHANNEL *channel, char *varname, int varname_len, char *value, int value_len) LIBSSH2_API int libssh2_channel_setenv_ex(LIBSSH2_CHANNEL *channel, char *varname, int varname_len, char *value, int value_len)
{ {
LIBSSH2_SESSION *session = channel->session; LIBSSH2_SESSION *session = channel->session;
unsigned char *s, *packet; unsigned char *s, *packet, *data, reply_codes[3] = { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 }, local_channel[4];
unsigned long data_len;
unsigned long packet_len = varname_len + value_len + 21; /* packet_type(1) + channel_id(4) + request_len(4) + request(3)"env" + unsigned long packet_len = varname_len + value_len + 21; /* packet_type(1) + channel_id(4) + request_len(4) + request(3)"env" +
want_reply(1) + varname_len(4) + value_len(4) */ want_reply(1) + varname_len(4) + value_len(4) */
@ -481,26 +472,18 @@ LIBSSH2_API int libssh2_channel_setenv_ex(LIBSSH2_CHANNEL *channel, char *varnam
} }
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
while (1) { libssh2_htonu32(local_channel, channel->local.id);
unsigned char *data; if (libssh2_packet_requirev_ex(session, reply_codes, &data, &data_len, 1, local_channel, 4)) {
unsigned long data_len; return -1;
unsigned char local_channel[4];
libssh2_htonu32(local_channel, channel->local.id);
if (libssh2_packet_ask_ex(session, SSH_MSG_CHANNEL_SUCCESS, &data, &data_len, 1, local_channel, 4, 1) == 0) {
LIBSSH2_FREE(session, data);
return 0;
}
if (libssh2_packet_ask_ex(session, SSH_MSG_CHANNEL_FAILURE, &data, &data_len, 1, local_channel, 4, 0) == 0) {
LIBSSH2_FREE(session, data);
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED, "Unable to complete request for channel-setenv", 0);
return -1;
}
} }
/* Never reached, just giving the compiler something to not complain about */ if (data[0] == SSH_MSG_CHANNEL_SUCCESS) {
LIBSSH2_FREE(session, data);
return 0;
}
LIBSSH2_FREE(session, data);
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED, "Unable to complete request for channel-setenv", 0);
return -1; return -1;
} }
/* }}} */ /* }}} */
@ -514,7 +497,8 @@ LIBSSH2_API int libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel, char *t
int width_px, int height_px) int width_px, int height_px)
{ {
LIBSSH2_SESSION *session = channel->session; LIBSSH2_SESSION *session = channel->session;
unsigned char *s, *packet; unsigned char *s, *packet, *data, reply_codes[3] = { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 }, local_channel[4];
unsigned long data_len;
unsigned long packet_len = term_len + modes_len + 41; /* packet_type(1) + channel(4) + pty_req_len(4) + "pty_req"(7) + want_reply(1) + unsigned long packet_len = term_len + modes_len + 41; /* packet_type(1) + channel(4) + pty_req_len(4) + "pty_req"(7) + want_reply(1) +
term_len(4) + width(4) + height(4) + width_px(4) + height_px(4) + modes_len(4) */ term_len(4) + width(4) + height(4) + width_px(4) + height_px(4) + modes_len(4) */
@ -553,26 +537,18 @@ LIBSSH2_API int libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel, char *t
} }
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
while (1) { libssh2_htonu32(local_channel, channel->local.id);
unsigned char *data; if (libssh2_packet_requirev_ex(session, reply_codes, &data, &data_len, 1, local_channel, 4)) {
unsigned long data_len; return -1;
unsigned char local_channel[4];
libssh2_htonu32(local_channel, channel->local.id);
if (libssh2_packet_ask_ex(session, SSH_MSG_CHANNEL_SUCCESS, &data, &data_len, 1, local_channel, 4, 1) == 0) {
LIBSSH2_FREE(session, data);
return 0;
}
if (libssh2_packet_ask_ex(session, SSH_MSG_CHANNEL_FAILURE, &data, &data_len, 1, local_channel, 4, 1) == 0) {
LIBSSH2_FREE(session, data);
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED, "Unable to complete request for channel request-pty", 0);
return -1;
}
} }
/* Never reached, just giving the compiler something to not complain about */ if (data[0] == SSH_MSG_CHANNEL_SUCCESS) {
LIBSSH2_FREE(session, data);
return 0;
}
LIBSSH2_FREE(session, data);
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED, "Unable to complete request for channel request-pty", 0);
return -1; return -1;
} }
/* }}} */ /* }}} */
@ -585,7 +561,8 @@ LIBSSH2_API int libssh2_channel_request_pty_ex(LIBSSH2_CHANNEL *channel, char *t
LIBSSH2_API int libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL *channel, int single_connection, char *auth_proto, char *auth_cookie, int screen_number) LIBSSH2_API int libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL *channel, int single_connection, char *auth_proto, char *auth_cookie, int screen_number)
{ {
LIBSSH2_SESSION *session = channel->session; LIBSSH2_SESSION *session = channel->session;
unsigned char *s, *packet; unsigned char *s, *packet, *data, reply_codes[3] = { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 }, local_channel[4];
unsigned long data_len;
unsigned long proto_len = auth_proto ? strlen(auth_proto) : (sizeof("MIT-MAGIC-COOKIE-1") - 1); unsigned long proto_len = auth_proto ? strlen(auth_proto) : (sizeof("MIT-MAGIC-COOKIE-1") - 1);
unsigned long cookie_len = auth_cookie ? strlen(auth_cookie) : LIBSSH2_X11_RANDOM_COOKIE_LEN; unsigned long cookie_len = auth_cookie ? strlen(auth_cookie) : LIBSSH2_X11_RANDOM_COOKIE_LEN;
unsigned long packet_len = proto_len + cookie_len + 41; /* packet_type(1) + channel(4) + x11_req_len(4) + "x11-req"(7) + want_reply(1) + unsigned long packet_len = proto_len + cookie_len + 41; /* packet_type(1) + channel(4) + x11_req_len(4) + "x11-req"(7) + want_reply(1) +
@ -632,26 +609,14 @@ LIBSSH2_API int libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL *channel, int single_
} }
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
while (1) { libssh2_htonu32(local_channel, channel->local.id);
unsigned char *data; if (libssh2_packet_requirev_ex(session, reply_codes, &data, &data_len, 1, local_channel, 4)) {
unsigned long data_len; LIBSSH2_FREE(session, data);
unsigned char local_channel[4]; return 0;
libssh2_htonu32(local_channel, channel->local.id);
if (libssh2_packet_ask_ex(session, SSH_MSG_CHANNEL_SUCCESS, &data, &data_len, 1, local_channel, 4, 1) == 0) {
LIBSSH2_FREE(session, data);
return 0;
}
if (libssh2_packet_ask_ex(session, SSH_MSG_CHANNEL_FAILURE, &data, &data_len, 1, local_channel, 4, 1) == 0) {
LIBSSH2_FREE(session, data);
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED, "Unable to complete request for channel x11-req", 0);
return -1;
}
} }
/* Never reached, just giving the compiler something to not complain about */ LIBSSH2_FREE(session, data);
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED, "Unable to complete request for channel x11-req", 0);
return -1; return -1;
} }
/* }}} */ /* }}} */
@ -662,7 +627,8 @@ LIBSSH2_API int libssh2_channel_x11_req_ex(LIBSSH2_CHANNEL *channel, int single_
LIBSSH2_API int libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, char *request, int request_len, char *message, int message_len) LIBSSH2_API int libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, char *request, int request_len, char *message, int message_len)
{ {
LIBSSH2_SESSION *session = channel->session; LIBSSH2_SESSION *session = channel->session;
unsigned char *s, *packet; unsigned char *s, *packet, *data, reply_codes[3] = { SSH_MSG_CHANNEL_SUCCESS, SSH_MSG_CHANNEL_FAILURE, 0 }, local_channel[4];
unsigned long data_len;
unsigned long packet_len = request_len + 10; /* packet_type(1) + channel(4) + request_len(4) + want_reply(1) */ unsigned long packet_len = request_len + 10; /* packet_type(1) + channel(4) + request_len(4) + want_reply(1) */
if (message) { if (message) {
@ -694,26 +660,18 @@ LIBSSH2_API int libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, char *
} }
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
while (1) { libssh2_htonu32(local_channel, channel->local.id);
unsigned char *data; if (libssh2_packet_requirev_ex(session, reply_codes, &data, &data_len, 1, local_channel, 4)) {
unsigned long data_len; return -1;
unsigned char local_channel[4];
libssh2_htonu32(local_channel, channel->local.id);
if (libssh2_packet_ask_ex(session, SSH_MSG_CHANNEL_SUCCESS, &data, &data_len, 1, local_channel, 4, 1) == 0) {
LIBSSH2_FREE(session, data);
return 0;
}
if (libssh2_packet_ask_ex(session, SSH_MSG_CHANNEL_FAILURE, &data, &data_len, 1, local_channel, 4, 0) == 0) {
LIBSSH2_FREE(session, data);
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED, "Unable to complete request for channel-process-startup", 0);
return -1;
}
} }
/* Never reached, just giving the compiler something to not complain about */ if (data[0] == SSH_MSG_CHANNEL_SUCCESS) {
LIBSSH2_FREE(session, data);
return 0;
}
LIBSSH2_FREE(session, data);
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED, "Unable to complete request for channel-process-startup", 0);
return -1; return -1;
} }
/* }}} */ /* }}} */

View File

@ -51,6 +51,7 @@
*/ */
LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session, char *username, int username_len) LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session, char *username, int username_len)
{ {
unsigned char reply_codes[3] = { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
unsigned long data_len = username_len + 31; /* packet_type(1) + username_len(4) + service_len(4) + service(14)"ssh-connection" + unsigned long data_len = username_len + 31; /* packet_type(1) + username_len(4) + service_len(4) + service(14)"ssh-connection" +
method_len(4) + method(4)"none" */ method_len(4) + method(4)"none" */
unsigned long methods_len; unsigned long methods_len;
@ -81,19 +82,15 @@ LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session, char *username
} }
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
while (1) { if (libssh2_packet_requirev(session, reply_codes, &data, &data_len)) {
if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_SUCCESS, &data, &data_len, 1) == 0) { return NULL;
/* Wow, who'dve thought... */ }
LIBSSH2_FREE(session, data);
session->state |= LIBSSH2_STATE_AUTHENTICATED;
return NULL;
}
if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_FAILURE, &data, &data_len, 0) == 0) { if (data[0] == SSH_MSG_USERAUTH_SUCCESS) {
/* What we *actually* wanted to happen */ /* Wow, who'dve thought... */
break; LIBSSH2_FREE(session, data);
} session->state |= LIBSSH2_STATE_AUTHENTICATED;
/* TODO: Timeout? */ return NULL;
} }
methods_len = libssh2_ntohu32(data + 1); methods_len = libssh2_ntohu32(data + 1);
@ -121,7 +118,7 @@ LIBSSH2_API int libssh2_userauth_password_ex(LIBSSH2_SESSION *session, char *use
char *password, int password_len, char *password, int password_len,
LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb))) LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb)))
{ {
unsigned char *data, *s; unsigned char *data, *s, reply_codes[4] = { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, 0 };
unsigned long data_len = username_len + password_len + 40; /* packet_type(1) + username_len(4) + service_len(4) + service(14)"ssh-connection" + unsigned long data_len = username_len + password_len + 40; /* packet_type(1) + username_len(4) + service_len(4) + service(14)"ssh-connection" +
method_len(4) + method(8)"password" + chgpwdbool(1) + password_len(4) */ method_len(4) + method(8)"password" + chgpwdbool(1) + password_len(4) */
@ -153,71 +150,72 @@ LIBSSH2_API int libssh2_userauth_password_ex(LIBSSH2_SESSION *session, char *use
} }
LIBSSH2_FREE(session, data); LIBSSH2_FREE(session, data);
while (1) { password_response:
if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_SUCCESS, &data, &data_len, 1) == 0) { if (libssh2_packet_requirev(session, reply_codes, &data, &data_len)) {
LIBSSH2_FREE(session, data); return -1;
session->state |= LIBSSH2_STATE_AUTHENTICATED;
return 0;
}
if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_FAILURE, &data, &data_len, 0) == 0) {
LIBSSH2_FREE(session, data);
return -1;
}
if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_PASSWD_CHANGEREQ, &data, &data_len, 0) == 0) {
char *newpw = NULL;
int newpw_len = 0;
LIBSSH2_FREE(session, data);
if (passwd_change_cb) {
passwd_change_cb(session, &newpw, &newpw_len, &session->abstract);
if (!newpw) {
libssh2_error(session, LIBSSH2_ERROR_PASSWORD_EXPIRED, "Password expired, and callback failed", 0);
return -1;
}
data_len = username_len + password_len + 44 + newpw_len; /* basic data_len + newpw_len(4) */
s = data = LIBSSH2_ALLOC(session, data_len);
if (!data) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for userauth-password-change request", 0);
return -1;
}
*(s++) = SSH_MSG_USERAUTH_REQUEST;
libssh2_htonu32(s, username_len); s += 4;
memcpy(s, username, username_len); s += username_len;
libssh2_htonu32(s, sizeof("ssh-connection") - 1); s += 4;
memcpy(s, "ssh-connection", sizeof("ssh-connection") - 1); s += sizeof("ssh-connection") - 1;
libssh2_htonu32(s, sizeof("password") - 1); s += 4;
memcpy(s, "password", sizeof("password") - 1); s += sizeof("password") - 1;
*s = 0xFF; s++;
libssh2_htonu32(s, password_len); s += 4;
memcpy(s, password, password_len); s += password_len;
libssh2_htonu32(s, newpw_len); s += 4;
memcpy(s, newpw, newpw_len); s += newpw_len;
if (libssh2_packet_write(session, data, data_len)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth-password-change request", 0);
LIBSSH2_FREE(session, data);
return -1;
}
LIBSSH2_FREE(session, data);
LIBSSH2_FREE(session, newpw);
/* TODO: Reset timeout? */
} else {
libssh2_error(session, LIBSSH2_ERROR_PASSWORD_EXPIRED, "Password Expired, and no callback specified", 0);
return -1;
}
}
/* TODO: Timeout? */
} }
return 0; if (data[0] == SSH_MSG_USERAUTH_SUCCESS) {
LIBSSH2_FREE(session, data);
session->state |= LIBSSH2_STATE_AUTHENTICATED;
return 0;
}
if (data[0] == SSH_MSG_USERAUTH_PASSWD_CHANGEREQ) {
char *newpw = NULL;
int newpw_len = 0;
LIBSSH2_FREE(session, data);
if (passwd_change_cb) {
passwd_change_cb(session, &newpw, &newpw_len, &session->abstract);
if (!newpw) {
libssh2_error(session, LIBSSH2_ERROR_PASSWORD_EXPIRED, "Password expired, and callback failed", 0);
return -1;
}
data_len = username_len + password_len + 44 + newpw_len; /* basic data_len + newpw_len(4) */
s = data = LIBSSH2_ALLOC(session, data_len);
if (!data) {
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for userauth-password-change request", 0);
return -1;
}
*(s++) = SSH_MSG_USERAUTH_REQUEST;
libssh2_htonu32(s, username_len); s += 4;
memcpy(s, username, username_len); s += username_len;
libssh2_htonu32(s, sizeof("ssh-connection") - 1); s += 4;
memcpy(s, "ssh-connection", sizeof("ssh-connection") - 1); s += sizeof("ssh-connection") - 1;
libssh2_htonu32(s, sizeof("password") - 1); s += 4;
memcpy(s, "password", sizeof("password") - 1); s += sizeof("password") - 1;
*s = 0xFF; s++;
libssh2_htonu32(s, password_len); s += 4;
memcpy(s, password, password_len); s += password_len;
libssh2_htonu32(s, newpw_len); s += 4;
memcpy(s, newpw, newpw_len); s += newpw_len;
if (libssh2_packet_write(session, data, data_len)) {
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send userauth-password-change request", 0);
LIBSSH2_FREE(session, data);
return -1;
}
LIBSSH2_FREE(session, data);
LIBSSH2_FREE(session, newpw);
/* Ugliest use of goto ever. Blame it on the askN => requirev migration. */
goto password_response;
} else {
libssh2_error(session, LIBSSH2_ERROR_PASSWORD_EXPIRED, "Password Expired, and no callback specified", 0);
return -1;
}
}
/* FAILURE */
LIBSSH2_FREE(session, data);
return -1;
} }
/* }}} */ /* }}} */
@ -344,8 +342,8 @@ LIBSSH2_API int libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION *session,
void *abstract; void *abstract;
unsigned char buf[5]; unsigned char buf[5];
struct iovec datavec[4]; struct iovec datavec[4];
unsigned char *method, *pubkeydata, *packet, *s, *sig; unsigned char *method, *pubkeydata, *packet, *s, *sig, *data, reply_codes[3] = { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, 0 };
unsigned long method_len, pubkeydata_len, packet_len, sig_len; unsigned long method_len, pubkeydata_len, packet_len, sig_len, data_len;
if (libssh2_file_read_publickey(session, &method, &method_len, &pubkeydata, &pubkeydata_len, publickey)) { if (libssh2_file_read_publickey(session, &method, &method_len, &pubkeydata, &pubkeydata_len, publickey)) {
return -1; return -1;
@ -438,27 +436,21 @@ LIBSSH2_API int libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION *session,
} }
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
while (1) { if (libssh2_packet_requirev(session, reply_codes, &data, &data_len)) {
unsigned char *data; return -1;
unsigned long data_len;
if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_SUCCESS, &data, &data_len, 1) == 0) {
/* We are us and we've proved it. */
LIBSSH2_FREE(session, data);
session->state |= LIBSSH2_STATE_AUTHENTICATED;
return 0;
}
if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_FAILURE, &data, &data_len, 0) == 0) {
/* This public key is not allowed for this user on this server */
LIBSSH2_FREE(session, data);
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, "Invalid signature for supplied public key, or bad username/public key combination", 0);
return -1;
}
/* TODO: Timeout? */
} }
return 0; if (data[0] == SSH_MSG_USERAUTH_SUCCESS) {
/* We are us and we've proved it. */
LIBSSH2_FREE(session, data);
session->state |= LIBSSH2_STATE_AUTHENTICATED;
return 0;
}
/* This public key is not allowed for this user on this server */
LIBSSH2_FREE(session, data);
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, "Invalid signature for supplied public key, or bad username/public key combination", 0);
return -1;
} }
/* }}} */ /* }}} */
@ -473,8 +465,9 @@ LIBSSH2_API int libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session,
void *abstract; void *abstract;
unsigned char buf[5]; unsigned char buf[5];
struct iovec datavec[4]; struct iovec datavec[4];
unsigned char *method, *pubkeydata, *packet, *s, *b, *sig; unsigned char *method, *pubkeydata, *packet, *s, *b, *sig, *data;
unsigned long method_len, pubkeydata_len, packet_len, sig_len; unsigned char reply_codes[4] = { SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, SSH_MSG_USERAUTH_PK_OK, 0 };
unsigned long method_len, pubkeydata_len, packet_len, sig_len, data_len;
if (libssh2_file_read_publickey(session, &method, &method_len, &pubkeydata, &pubkeydata_len, publickey)) { if (libssh2_file_read_publickey(session, &method, &method_len, &pubkeydata, &pubkeydata_len, publickey)) {
return -1; return -1;
@ -515,45 +508,35 @@ LIBSSH2_API int libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session,
return -1; return -1;
} }
while (1) { if (libssh2_packet_requirev(session, reply_codes, &data, &data_len)) {
unsigned char *data; LIBSSH2_FREE(session, packet);
unsigned long data_len; LIBSSH2_FREE(session, method);
LIBSSH2_FREE(session, pubkeydata);
if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_SUCCESS, &data, &data_len, 1) == 0) { return -1;
/* God help any SSH server that allows an UNVERIFIED public key to validate the user */
LIBSSH2_FREE(session, data);
LIBSSH2_FREE(session, packet);
LIBSSH2_FREE(session, method);
LIBSSH2_FREE(session, pubkeydata);
session->state |= LIBSSH2_STATE_AUTHENTICATED;
return 0;
}
if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_FAILURE, &data, &data_len, 0) == 0) {
/* This public key is not allowed for this user on this server */
LIBSSH2_FREE(session, data);
LIBSSH2_FREE(session, packet);
LIBSSH2_FREE(session, method);
LIBSSH2_FREE(session, pubkeydata);
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED, "Username/PublicKey combination invalid", 0);
return -1;
}
if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_PK_OK, &data, &data_len, 0) == 0) {
/* Semi-Success! */
if ((libssh2_ntohu32(data + 1) != method_len) ||
strncmp(data + 5, method, method_len) ||
(libssh2_ntohu32(data + 5 + method_len) != pubkeydata_len) ||
strncmp(data + 5 + method_len + 4, pubkeydata, pubkeydata_len)) {
/* Unlikely but possible, the server has responded to a different userauth public key request */
LIBSSH2_FREE(session, data);
continue;
}
LIBSSH2_FREE(session, data);
break;
}
/* TODO: Timeout? */
} }
if (data[0] == SSH_MSG_USERAUTH_SUCCESS) {
/* God help any SSH server that allows an UNVERIFIED public key to validate the user */
LIBSSH2_FREE(session, data);
LIBSSH2_FREE(session, packet);
LIBSSH2_FREE(session, method);
LIBSSH2_FREE(session, pubkeydata);
session->state |= LIBSSH2_STATE_AUTHENTICATED;
return 0;
}
if (data[0] == SSH_MSG_USERAUTH_FAILURE) {
/* This public key is not allowed for this user on this server */
LIBSSH2_FREE(session, data);
LIBSSH2_FREE(session, packet);
LIBSSH2_FREE(session, method);
LIBSSH2_FREE(session, pubkeydata);
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED, "Username/PublicKey combination invalid", 0);
return -1;
}
/* Semi-Success! */
LIBSSH2_FREE(session, data);
LIBSSH2_FREE(session, pubkeydata); LIBSSH2_FREE(session, pubkeydata);
if (libssh2_file_read_privatekey(session, &privkeyobj, &abstract, method, method_len, privatekey, passphrase)) { if (libssh2_file_read_privatekey(session, &privkeyobj, &abstract, method, method_len, privatekey, passphrase)) {
@ -614,26 +597,23 @@ LIBSSH2_API int libssh2_userauth_publickey_fromfile_ex(LIBSSH2_SESSION *session,
} }
LIBSSH2_FREE(session, packet); LIBSSH2_FREE(session, packet);
while (1) { /* PK_OK is no longer valid */
unsigned char *data; reply_codes[2] = 0;
unsigned long data_len;
if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_SUCCESS, &data, &data_len, 1) == 0) { if (libssh2_packet_requirev(session, reply_codes, &data, &data_len)) {
/* We are us and we've proved it. */ return -1;
LIBSSH2_FREE(session, data);
session->state |= LIBSSH2_STATE_AUTHENTICATED;
return 0;
}
if (libssh2_packet_ask(session, SSH_MSG_USERAUTH_FAILURE, &data, &data_len, 0) == 0) {
/* This public key is not allowed for this user on this server */
LIBSSH2_FREE(session, data);
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, "Invalid signature for supplied public key, or bad username/public key combination", 0);
return -1;
}
/* TODO: Timeout? */
} }
return 0; if (data[0] == SSH_MSG_USERAUTH_SUCCESS) {
/* We are us and we've proved it. */
LIBSSH2_FREE(session, data);
session->state |= LIBSSH2_STATE_AUTHENTICATED;
return 0;
}
/* This public key is not allowed for this user on this server */
LIBSSH2_FREE(session, data);
libssh2_error(session, LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED, "Invalid signature for supplied public key, or bad username/public key combination", 0);
return -1;
} }
/* }}} */ /* }}} */