diff --git a/src/channel.c b/src/channel.c index 41b2cef..e2ac722 100644 --- a/src/channel.c +++ b/src/channel.c @@ -130,7 +130,8 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type, uint32_t channel_type_len, uint32_t window_size, uint32_t packet_size, - const char *message, unsigned int message_len) + const unsigned char *message, + size_t message_len) { static const unsigned char reply_codes[3] = { SSH_MSG_CHANNEL_OPEN_CONFIRMATION, @@ -146,7 +147,7 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type, session->open_data = NULL; /* 17 = packet_type(1) + channel_type_len(4) + sender_channel(4) + * window_size(4) + packet_size(4) */ - session->open_packet_len = channel_type_len + message_len + 17; + session->open_packet_len = channel_type_len + 17; session->open_local_channel = _libssh2_channel_nextid(session); /* Zero the whole thing out */ @@ -201,17 +202,16 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type, _libssh2_store_u32(&s, window_size); _libssh2_store_u32(&s, packet_size); - if (message && message_len) { - memcpy(s, message, message_len); - s += message_len; - } + /* Do not copy the message */ session->open_state = libssh2_NB_state_created; } if (session->open_state == libssh2_NB_state_created) { - rc = _libssh2_transport_write(session, session->open_packet, - session->open_packet_len); + rc = _libssh2_transport_send(session, + session->open_packet, + session->open_packet_len, + message, message_len); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, rc, "Would block sending channel-open request"); @@ -304,12 +304,6 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type, session->open_data = NULL; } - /* Free any state variables still holding data */ - if (session->open_channel->write_packet) { - LIBSSH2_FREE(session, session->open_channel->write_packet); - session->open_channel->write_packet = NULL; - } - LIBSSH2_FREE(session, session->open_channel); session->open_channel = NULL; } @@ -337,7 +331,8 @@ libssh2_channel_open_ex(LIBSSH2_SESSION *session, const char *type, BLOCK_ADJUST_ERRNO(ptr, session, _libssh2_channel_open(session, type, type_len, window_size, packet_size, - msg, msg_len)); + (unsigned char *)msg, + msg_len)); return ptr; } @@ -382,7 +377,7 @@ channel_direct_tcpip(LIBSSH2_SESSION * session, const char *host, sizeof("direct-tcpip") - 1, LIBSSH2_CHANNEL_WINDOW_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT, - (char *) session->direct_message, + session->direct_message, session->direct_message_len); if (!channel && @@ -434,9 +429,11 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host, { SSH_MSG_REQUEST_SUCCESS, SSH_MSG_REQUEST_FAILURE, 0 }; int rc; + if(!host) + host = "0.0.0.0"; + if (session->fwdLstn_state == libssh2_NB_state_idle) { - session->fwdLstn_host_len = - (host ? strlen(host) : (sizeof("0.0.0.0") - 1)); + session->fwdLstn_host_len = strlen(host); /* 14 = packet_type(1) + request_len(4) + want_replay(1) + host_len(4) + port(4) */ session->fwdLstn_packet_len = @@ -462,16 +459,17 @@ channel_forward_listen(LIBSSH2_SESSION * session, const char *host, _libssh2_store_str(&s, "tcpip-forward", sizeof("tcpip-forward") - 1); *(s++) = 0x01; /* want_reply */ - _libssh2_store_str(&s, host ? host : "0.0.0.0", - session->fwdLstn_host_len); + _libssh2_store_str(&s, host, session->fwdLstn_host_len); _libssh2_store_u32(&s, port); session->fwdLstn_state = libssh2_NB_state_created; } if (session->fwdLstn_state == libssh2_NB_state_created) { - rc = _libssh2_transport_write(session, session->fwdLstn_packet, - session->fwdLstn_packet_len); + rc = _libssh2_transport_send(session, + session->fwdLstn_packet, + session->fwdLstn_packet_len, + NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block sending global-request packet for " @@ -635,7 +633,7 @@ int _libssh2_channel_forward_cancel(LIBSSH2_LISTENER *listener) } if (listener->chanFwdCncl_state == libssh2_NB_state_created) { - rc = _libssh2_transport_write(session, packet, packet_len); + rc = _libssh2_transport_send(session, packet, packet_len, NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, rc, "Would block sending forward request"); @@ -804,8 +802,10 @@ static int channel_setenv(LIBSSH2_CHANNEL *channel, } if (channel->setenv_state == libssh2_NB_state_created) { - rc = _libssh2_transport_write(session, channel->setenv_packet, - channel->setenv_packet_len); + rc = _libssh2_transport_send(session, + channel->setenv_packet, + channel->setenv_packet_len, + NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, rc, "Would block sending setenv request"); @@ -894,6 +894,11 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel, /* 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) */ + if(term_len + modes_len > 256) { + return _libssh2_error(session, LIBSSH2_ERROR_INVAL, + "term + mode lengths too large"); + } + channel->reqPTY_packet_len = term_len + modes_len + 41; /* Zero the whole thing out */ @@ -904,12 +909,7 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel, "Allocating tty on channel %lu/%lu", channel->local.id, channel->remote.id); - s = channel->reqPTY_packet = - LIBSSH2_ALLOC(session, channel->reqPTY_packet_len); - if (!channel->reqPTY_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for pty-request"); - } + s = channel->reqPTY_packet; *(s++) = SSH_MSG_CHANNEL_REQUEST; _libssh2_store_u32(&s, channel->remote.id); @@ -928,22 +928,18 @@ static int channel_request_pty(LIBSSH2_CHANNEL *channel, } if (channel->reqPTY_state == libssh2_NB_state_created) { - rc = _libssh2_transport_write(session, channel->reqPTY_packet, - channel->reqPTY_packet_len); + rc = _libssh2_transport_send(session, channel->reqPTY_packet, + channel->reqPTY_packet_len, + NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, rc, "Would block sending pty request"); return rc; } else if (rc) { - LIBSSH2_FREE(session, channel->reqPTY_packet); - channel->reqPTY_packet = NULL; channel->reqPTY_state = libssh2_NB_state_idle; return _libssh2_error(session, rc, "Unable to send pty-request packet"); } - LIBSSH2_FREE(session, channel->reqPTY_packet); - channel->reqPTY_packet = NULL; - _libssh2_htonu32(channel->reqPTY_local_channel, channel->local.id); channel->reqPTY_state = libssh2_NB_state_sent; @@ -1019,12 +1015,7 @@ channel_request_pty_size(LIBSSH2_CHANNEL * channel, int width, channel->local.id, channel->remote.id); - s = channel->reqPTY_packet = - LIBSSH2_ALLOC(session, channel->reqPTY_packet_len); - - if (!channel->reqPTY_packet) - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for pty-request"); + s = channel->reqPTY_packet; *(s++) = SSH_MSG_CHANNEL_REQUEST; _libssh2_store_u32(&s, channel->remote.id); @@ -1040,21 +1031,18 @@ channel_request_pty_size(LIBSSH2_CHANNEL * channel, int width, } if (channel->reqPTY_state == libssh2_NB_state_created) { - rc = _libssh2_transport_write(session, channel->reqPTY_packet, - channel->reqPTY_packet_len); + rc = _libssh2_transport_send(session, channel->reqPTY_packet, + channel->reqPTY_packet_len, + NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, rc, "Would block sending window-change request"); return rc; } else if (rc) { - LIBSSH2_FREE(session, channel->reqPTY_packet); - channel->reqPTY_packet = NULL; channel->reqPTY_state = libssh2_NB_state_idle; return _libssh2_error(session, rc, "Unable to send window-change packet"); } - LIBSSH2_FREE(session, channel->reqPTY_packet); - channel->reqPTY_packet = NULL; _libssh2_htonu32(channel->reqPTY_local_channel, channel->local.id); channel->reqPTY_state = libssh2_NB_state_sent; @@ -1162,8 +1150,9 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection, } if (channel->reqX11_state == libssh2_NB_state_created) { - rc = _libssh2_transport_write(session, channel->reqX11_packet, - channel->reqX11_packet_len); + rc = _libssh2_transport_send(session, channel->reqX11_packet, + channel->reqX11_packet_len, + NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, rc, "Would block sending X11-req packet"); @@ -1258,7 +1247,7 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, sizeof(channel->process_packet_requirev_state)); if (message) - channel->process_packet_len += message_len + 4; + channel->process_packet_len += + 4; _libssh2_debug(session, LIBSSH2_TRACE_CONN, "starting request(%s) on channel %lu/%lu, message=%s", @@ -1277,14 +1266,16 @@ _libssh2_channel_process_startup(LIBSSH2_CHANNEL *channel, *(s++) = 0x01; if (message) - _libssh2_store_str(&s, message, message_len); + _libssh2_store_u32(&s, message_len); channel->process_state = libssh2_NB_state_created; } if (channel->process_state == libssh2_NB_state_created) { - rc = _libssh2_transport_write(session, channel->process_packet, - channel->process_packet_len); + rc = _libssh2_transport_send(session, + channel->process_packet, + channel->process_packet_len, + (unsigned char *)message, message_len); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, rc, "Would block sending channel request"); @@ -1588,7 +1579,8 @@ _libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL * channel, channel->adjust_state = libssh2_NB_state_created; } - rc = _libssh2_transport_write(channel->session, channel->adjust_adjust, 9); + rc = _libssh2_transport_send(channel->session, channel->adjust_adjust, 9, + NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(channel->session, rc, "Would block sending window adjust"); @@ -1987,7 +1979,7 @@ _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id) */ ssize_t _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, - const char *buf, size_t buflen) + const unsigned char *buf, size_t buflen) { LIBSSH2_SESSION *session = channel->session; int rc; @@ -2022,15 +2014,7 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, /* [13] 9 = packet_type(1) + channelno(4) [ + streamid(4) ] + buflen(4) */ - channel->write_packet_len = buflen + (stream_id ? 13 : 9); - channel->write_packet = - LIBSSH2_ALLOC(session, channel->write_packet_len); - if (!channel->write_packet) { - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocte space " - "for data transmission packet"); - } - + channel->write_packet_len = (stream_id ? 13 : 9); channel->write_state = libssh2_NB_state_allocated; } @@ -2079,7 +2063,9 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, channel->remote.id, stream_id); channel->write_bufwrite = channel->local.packet_size; } - _libssh2_store_str(&channel->write_s, buf, channel->write_bufwrite); + /* store the size here only, the buffer is passed in as-is to + _libssh2_transport_send() */ + _libssh2_store_u32(&channel->write_s, channel->write_bufwrite); _libssh2_debug(session, LIBSSH2_TRACE_CONN, "Sending %d bytes on channel %lu/%lu, stream_id=%d", @@ -2090,16 +2076,15 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, } if (channel->write_state == libssh2_NB_state_created) { - rc = _libssh2_transport_write(session, channel->write_packet, - channel->write_s - - channel->write_packet); + rc = _libssh2_transport_send(session, channel->write_packet, + channel->write_s - + channel->write_packet, + buf, channel->write_bufwrite); if (rc == LIBSSH2_ERROR_EAGAIN) { return _libssh2_error(session, rc, "Unable to send channel data"); } else if (rc) { - LIBSSH2_FREE(session, channel->write_packet); - channel->write_packet = NULL; channel->write_state = libssh2_NB_state_idle; return _libssh2_error(session, rc, "Unable to send channel data"); @@ -2122,9 +2107,6 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, } } - LIBSSH2_FREE(session, channel->write_packet); - channel->write_packet = NULL; - channel->write_state = libssh2_NB_state_idle; return wrote; @@ -2145,7 +2127,8 @@ libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, int stream_id, return LIBSSH2_ERROR_BAD_USE; BLOCK_ADJUST(rc, channel->session, - _libssh2_channel_write(channel, stream_id, buf, buflen)); + _libssh2_channel_write(channel, stream_id, + (unsigned char *)buf, buflen)); return rc; } @@ -2164,7 +2147,7 @@ static int channel_send_eof(LIBSSH2_CHANNEL *channel) channel->local.id, channel->remote.id); packet[0] = SSH_MSG_CHANNEL_EOF; _libssh2_htonu32(packet + 1, channel->remote.id); - rc = _libssh2_transport_write(session, packet, 5); + rc = _libssh2_transport_send(session, packet, 5, NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, rc, "Would block sending EOF"); @@ -2316,7 +2299,8 @@ int _libssh2_channel_close(LIBSSH2_CHANNEL * channel) } if (channel->close_state == libssh2_NB_state_created) { - retcode = _libssh2_transport_write(session, channel->close_packet, 5); + retcode = _libssh2_transport_send(session, channel->close_packet, 5, + NULL, 0); if (retcode == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, rc, "Would block sending close-channel"); @@ -2508,18 +2492,12 @@ int _libssh2_channel_free(LIBSSH2_CHANNEL *channel) if (channel->setenv_packet) { LIBSSH2_FREE(session, channel->setenv_packet); } - if (channel->reqPTY_packet) { - LIBSSH2_FREE(session, channel->reqPTY_packet); - } if (channel->reqX11_packet) { LIBSSH2_FREE(session, channel->reqX11_packet); } if (channel->process_packet) { LIBSSH2_FREE(session, channel->process_packet); } - if (channel->write_packet) { - LIBSSH2_FREE(session, channel->write_packet); - } LIBSSH2_FREE(session, channel); diff --git a/src/channel.h b/src/channel.h index ab4d5b6..1623080 100644 --- a/src/channel.h +++ b/src/channel.h @@ -80,7 +80,7 @@ _libssh2_channel_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode); */ ssize_t _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, - const char *buf, size_t buflen); + const unsigned char *buf, size_t buflen); /* * _libssh2_channel_open @@ -92,7 +92,7 @@ _libssh2_channel_open(LIBSSH2_SESSION * session, const char *channel_type, uint32_t channel_type_len, uint32_t window_size, uint32_t packet_size, - const char *message, unsigned int message_len); + const unsigned char *message, unsigned int message_len); /* diff --git a/src/keepalive.c b/src/keepalive.c index 7ac7c0f..260206a 100644 --- a/src/keepalive.c +++ b/src/keepalive.c @@ -68,7 +68,8 @@ libssh2_keepalive_send (LIBSSH2_SESSION *session, now = time (NULL); if (session->keepalive_last_sent + session->keepalive_interval <= now) { -/* Format is "SSH_MSG_GLOBAL_REQUEST || 4-byte len || str || want-reply". */ + /* Format is + "SSH_MSG_GLOBAL_REQUEST || 4-byte len || str || want-reply". */ unsigned char keepalive_data[] = "\x50\x00\x00\x00\x15keepalive@libssh2.orgW"; size_t len = sizeof (keepalive_data) - 1; @@ -76,9 +77,9 @@ libssh2_keepalive_send (LIBSSH2_SESSION *session, keepalive_data[len - 1] = session->keepalive_want_reply; - rc = _libssh2_transport_write(session, keepalive_data, len); -/* Silently ignore PACKET_EAGAIN here: if the write buffer is - already full, sending another keepalive is not useful. */ + rc = _libssh2_transport_send(session, keepalive_data, len, NULL, 0); + /* Silently ignore PACKET_EAGAIN here: if the write buffer is + already full, sending another keepalive is not useful. */ if (rc && rc != LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send keepalive message"); diff --git a/src/kex.c b/src/kex.c index 23ce7dd..54527ea 100644 --- a/src/kex.c +++ b/src/kex.c @@ -141,8 +141,9 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, } if (exchange_state->state == libssh2_NB_state_created) { - rc = _libssh2_transport_write(session, exchange_state->e_packet, - exchange_state->e_packet_len); + rc = _libssh2_transport_send(session, exchange_state->e_packet, + exchange_state->e_packet_len, + NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) { return rc; } else if (rc) { @@ -411,7 +412,7 @@ static int diffie_hellman_sha1(LIBSSH2_SESSION *session, } if (exchange_state->state == libssh2_NB_state_sent2) { - rc = _libssh2_transport_write(session, &exchange_state->c, 1); + rc = _libssh2_transport_send(session, &exchange_state->c, 1, NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) { return rc; } else if (rc) { @@ -844,8 +845,8 @@ kex_method_diffie_hellman_group_exchange_sha1_key_exchange } if (key_state->state == libssh2_NB_state_created) { - rc = _libssh2_transport_write(session, key_state->request, - key_state->request_len); + rc = _libssh2_transport_send(session, key_state->request, + key_state->request_len, NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) { return rc; } else if (rc) { @@ -1139,7 +1140,7 @@ static int kexinit(LIBSSH2_SESSION * session) session->kexinit_data_len = 0; } - rc = _libssh2_transport_write(session, data, data_len); + rc = _libssh2_transport_send(session, data, data_len, NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) { session->kexinit_data = data; session->kexinit_data_len = data_len; diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h index 4994a1d..f2e9b07 100644 --- a/src/libssh2_priv.h +++ b/src/libssh2_priv.h @@ -359,9 +359,10 @@ struct _LIBSSH2_CHANNEL unsigned char setenv_local_channel[4]; packet_requirev_state_t setenv_packet_requirev_state; - /* State variables used in libssh2_channel_request_pty_ex() */ + /* State variables used in libssh2_channel_request_pty_ex() + libssh2_channel_request_pty_size_ex() */ libssh2_nonblocking_states reqPTY_state; - unsigned char *reqPTY_packet; + unsigned char reqPTY_packet[41 + 256]; size_t reqPTY_packet_len; unsigned char reqPTY_local_channel[4]; packet_requirev_state_t reqPTY_packet_requirev_state; @@ -396,7 +397,7 @@ struct _LIBSSH2_CHANNEL /* State variables used in libssh2_channel_write_ex() */ libssh2_nonblocking_states write_state; - unsigned char *write_packet; + unsigned char write_packet[13]; unsigned char *write_s; size_t write_packet_len; size_t write_bufwrote; @@ -495,8 +496,7 @@ struct transportpacket unsigned char outbuf[MAX_SSH_PACKET_LEN]; /* area for the outgoing data */ int ototal_num; /* size of outbuf in number of bytes */ - unsigned char *odata; /* original pointer to the data we stored in - outbuf */ + const unsigned char *odata; /* original pointer to the data */ size_t olen; /* original size of the data we stored in outbuf */ size_t osent; /* number of bytes already sent */ @@ -774,7 +774,7 @@ struct _LIBSSH2_SESSION /* State variables used in libssh2_session_disconnect_ex() */ libssh2_nonblocking_states disconnect_state; - unsigned char *disconnect_data; + unsigned char disconnect_data[256 + 13]; size_t disconnect_data_len; /* State variables used in libssh2_packet_read() */ diff --git a/src/packet.c b/src/packet.c index bcf84bb..94affbc 100644 --- a/src/packet.c +++ b/src/packet.c @@ -1,6 +1,6 @@ /* Copyright (c) 2004-2007, Sara Golemon * Copyright (c) 2005,2006 Mikhail Gusarov - * Copyright (c) 2009 by Daniel Stenberg + * Copyright (c) 2009-2010 by Daniel Stenberg * Copyright (c) 2010 Simon Josefsson * All rights reserved. * @@ -204,8 +204,8 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, } if (listen_state->state == libssh2_NB_state_created) { - rc = _libssh2_transport_write(session, listen_state->packet, - 17); + rc = _libssh2_transport_send(session, listen_state->packet, + 17, NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) return rc; else if (rc) { @@ -239,8 +239,8 @@ packet_queue_listener(LIBSSH2_SESSION * session, unsigned char *data, _libssh2_store_str(&p, FwdNotReq, sizeof(FwdNotReq) - 1); _libssh2_htonu32(p, 0); - rc = _libssh2_transport_write(session, listen_state->packet, - packet_len); + rc = _libssh2_transport_send(session, listen_state->packet, + packet_len, NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) { return rc; } else if (rc) { @@ -349,7 +349,8 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data, } if (x11open_state->state == libssh2_NB_state_created) { - rc = _libssh2_transport_write(session, x11open_state->packet, 17); + rc = _libssh2_transport_send(session, x11open_state->packet, 17, + NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) { return rc; } else if (rc) { @@ -384,7 +385,8 @@ packet_x11_open(LIBSSH2_SESSION * session, unsigned char *data, _libssh2_store_str(&p, X11FwdUnAvil, sizeof(X11FwdUnAvil) - 1); _libssh2_htonu32(p, 0); - rc = _libssh2_transport_write(session, x11open_state->packet, packet_len); + rc = _libssh2_transport_send(session, x11open_state->packet, packet_len, + NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) { return rc; } else if (rc) { @@ -589,7 +591,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, libssh2_packet_add_jump_point5: session->packAdd_state = libssh2_NB_state_jump5; data[0] = SSH_MSG_REQUEST_FAILURE; - rc = _libssh2_transport_write(session, data, 1); + rc = _libssh2_transport_send(session, data, 1, NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) return rc; LIBSSH2_FREE(session, data); @@ -800,7 +802,7 @@ _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data, libssh2_packet_add_jump_point4: session->packAdd_state = libssh2_NB_state_jump4; data[0] = SSH_MSG_CHANNEL_FAILURE; - rc = _libssh2_transport_write(session, data, 5); + rc = _libssh2_transport_send(session, data, 5, NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) return rc; LIBSSH2_FREE(session, data); diff --git a/src/publickey.c b/src/publickey.c index 2ccfa08..ab76ab2 100644 --- a/src/publickey.c +++ b/src/publickey.c @@ -378,7 +378,7 @@ static LIBSSH2_PUBLICKEY *publickey_init(LIBSSH2_SESSION *session) if (session->pkeyInit_state == libssh2_NB_state_sent2) { rc = _libssh2_channel_write(session->pkeyInit_channel, 0, - (char *)session->pkeyInit_buffer, + session->pkeyInit_buffer, 19 - session->pkeyInit_buffer_sent); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, @@ -644,7 +644,7 @@ libssh2_publickey_add_ex(LIBSSH2_PUBLICKEY *pkey, const unsigned char *name, } if (pkey->add_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, (char *) pkey->add_packet, + rc = _libssh2_channel_write(channel, 0, pkey->add_packet, (pkey->add_s - pkey->add_packet)); if (rc == LIBSSH2_ERROR_EAGAIN) { return rc; @@ -727,7 +727,7 @@ libssh2_publickey_remove_ex(LIBSSH2_PUBLICKEY * pkey, } if (pkey->remove_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, (char *) pkey->remove_packet, + rc = _libssh2_channel_write(channel, 0, pkey->remove_packet, (pkey->remove_s - pkey->remove_packet)); if (rc == LIBSSH2_ERROR_EAGAIN) { return rc; @@ -794,7 +794,7 @@ libssh2_publickey_list_fetch(LIBSSH2_PUBLICKEY * pkey, unsigned long *num_keys, if (pkey->listFetch_state == libssh2_NB_state_created) { rc = _libssh2_channel_write(channel, 0, - (char *) pkey->listFetch_buffer, + pkey->listFetch_buffer, (pkey->listFetch_s - pkey->listFetch_buffer)); if (rc == LIBSSH2_ERROR_EAGAIN) { diff --git a/src/scp.c b/src/scp.c index 01e01ae..1005c01 100644 --- a/src/scp.c +++ b/src/scp.c @@ -360,7 +360,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb) if (session->scpRecv_state == libssh2_NB_state_sent1) { rc = _libssh2_channel_write(session->scpRecv_channel, 0, - (char *) session->scpRecv_response, 1); + session->scpRecv_response, 1); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block sending initial wakeup"); @@ -550,8 +550,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb) if (session->scpRecv_state == libssh2_NB_state_sent3) { rc = _libssh2_channel_write(session->scpRecv_channel, 0, - (char *) session-> - scpRecv_response, 1); + session->scpRecv_response, 1); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting to send SCP ACK"); @@ -708,8 +707,7 @@ scp_recv(LIBSSH2_SESSION * session, const char *path, struct stat * sb) if (session->scpRecv_state == libssh2_NB_state_sent6) { rc = _libssh2_channel_write(session->scpRecv_channel, 0, - (char *) session-> - scpRecv_response, 1); + session->scpRecv_response, 1); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block sending SCP ACK"); @@ -904,7 +902,7 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode, if (mtime || atime) { if (session->scpSend_state == libssh2_NB_state_sent2) { rc = _libssh2_channel_write(session->scpSend_channel, 0, - (char *) session->scpSend_response, + session->scpSend_response, session->scpSend_response_len); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, @@ -970,7 +968,7 @@ scp_send(LIBSSH2_SESSION * session, const char *path, int mode, if (session->scpSend_state == libssh2_NB_state_sent5) { rc = _libssh2_channel_write(session->scpSend_channel, 0, - (char *) session->scpSend_response, + session->scpSend_response, session->scpSend_response_len); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, diff --git a/src/session.c b/src/session.c index 679b9c9..716c0b7 100644 --- a/src/session.c +++ b/src/session.c @@ -683,8 +683,9 @@ session_startup(LIBSSH2_SESSION *session, libssh2_socket_t sock) } if (session->startup_state == libssh2_NB_state_sent3) { - rc = _libssh2_transport_write(session, session->startup_service, - sizeof("ssh-userauth") + 5 - 1); + rc = _libssh2_transport_send(session, session->startup_service, + sizeof("ssh-userauth") + 5 - 1, + NULL, 0); if (rc) { return _libssh2_error(session, rc, "Unable to ask for ssh-userauth service"); @@ -772,7 +773,6 @@ session_free(LIBSSH2_SESSION *session) LIBSSH2_PACKET *pkg; LIBSSH2_CHANNEL *ch; LIBSSH2_LISTENER *l; - struct transportpacket *p = &session->packet; if (session->free_state == libssh2_NB_state_idle) { _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Freeing session resource", @@ -903,9 +903,6 @@ session_free(LIBSSH2_SESSION *session) if (session->startup_data) { LIBSSH2_FREE(session, session->startup_data); } - if (session->disconnect_data) { - LIBSSH2_FREE(session, session->disconnect_data); - } if (session->userauth_list_data) { LIBSSH2_FREE(session, session->userauth_list_data); } @@ -1014,7 +1011,8 @@ libssh2_session_free(LIBSSH2_SESSION * session) */ static int session_disconnect(LIBSSH2_SESSION *session, int reason, - const char *description, const char *lang) + const char *description, + const char *lang) { unsigned char *s; unsigned long descr_len = 0, lang_len = 0; @@ -1024,40 +1022,36 @@ session_disconnect(LIBSSH2_SESSION *session, int reason, _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Disconnecting: reason=%d, desc=%s, lang=%s", reason, description, lang); - if (description) { + if (description) descr_len = strlen(description); - } - if (lang) { + + if (lang) lang_len = strlen(lang); - } + + if(descr_len > 256) + return _libssh2_error(session, LIBSSH2_ERROR_INVAL, + "too long description"); + /* 13 = packet_type(1) + reason code(4) + descr_len(4) + lang_len(4) */ session->disconnect_data_len = descr_len + lang_len + 13; - s = session->disconnect_data = - LIBSSH2_ALLOC(session, session->disconnect_data_len); - if (!session->disconnect_data) { - session->disconnect_state = libssh2_NB_state_idle; - return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, - "Unable to allocate memory for " - "disconnect packet"); - } + s = session->disconnect_data; *(s++) = SSH_MSG_DISCONNECT; _libssh2_store_u32(&s, reason); _libssh2_store_str(&s, description, descr_len); - _libssh2_store_str(&s, lang, lang_len); + /* store length only, lang is sent separately */ + _libssh2_store_u32(&s, lang_len); session->disconnect_state = libssh2_NB_state_created; } - rc = _libssh2_transport_write(session, session->disconnect_data, - session->disconnect_data_len); - if (rc == LIBSSH2_ERROR_EAGAIN) { + rc = _libssh2_transport_send(session, session->disconnect_data, + session->disconnect_data_len, + (unsigned char *)lang, lang_len); + if (rc == LIBSSH2_ERROR_EAGAIN) return rc; - } - LIBSSH2_FREE(session, session->disconnect_data); - session->disconnect_data = NULL; session->disconnect_state = libssh2_NB_state_idle; return 0; diff --git a/src/sftp.c b/src/sftp.c index 6520952..b9a0e83 100644 --- a/src/sftp.c +++ b/src/sftp.c @@ -611,7 +611,7 @@ static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session) if (session->sftpInit_state == libssh2_NB_state_sent2) { /* sent off what's left of the init buffer to send */ rc = _libssh2_channel_write(session->sftpInit_channel, 0, - (char *)session->sftpInit_buffer + + session->sftpInit_buffer + session->sftpInit_sent, 9 - session->sftpInit_sent); if (rc == LIBSSH2_ERROR_EAGAIN) { @@ -877,7 +877,7 @@ sftp_open(LIBSSH2_SFTP *sftp, const char *filename, } if (sftp->open_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, (char *) sftp->open_packet+ + rc = _libssh2_channel_write(channel, 0, sftp->open_packet+ sftp->open_packet_sent, sftp->open_packet_len - sftp->open_packet_sent); @@ -1108,8 +1108,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, } if (sftp->read_state == libssh2_NB_state_created) { - retcode = _libssh2_channel_write(channel, 0, (char *) packet, - packet_len); + retcode = _libssh2_channel_write(channel, 0, packet, packet_len); if (retcode == LIBSSH2_ERROR_EAGAIN) { sftp->read_packet = packet; sftp->read_request_id = request_id; @@ -1300,8 +1299,7 @@ static int sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer, if (sftp->readdir_state == libssh2_NB_state_created) { _libssh2_debug(session, LIBSSH2_TRACE_SFTP, "Reading entries from directory handle"); - retcode = _libssh2_channel_write(channel, 0, - (char *) sftp->readdir_packet, + retcode = _libssh2_channel_write(channel, 0, sftp->readdir_packet, packet_len); if (retcode == LIBSSH2_ERROR_EAGAIN) { return retcode; @@ -1429,7 +1427,7 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer, } if (sftp->write_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, (char *)sftp->write_packet, + rc = _libssh2_channel_write(channel, 0, sftp->write_packet, packet_len); if(rc < 0) { /* error */ @@ -1533,7 +1531,7 @@ static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle, } if (sftp->fstat_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, (char *) sftp->fstat_packet, + rc = _libssh2_channel_write(channel, 0, sftp->fstat_packet, packet_len); if (rc == LIBSSH2_ERROR_EAGAIN) { return rc; @@ -1682,7 +1680,7 @@ sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle) } if (handle->close_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, (char *) handle->close_packet, + rc = _libssh2_channel_write(channel, 0, handle->close_packet, packet_len); if (rc == LIBSSH2_ERROR_EAGAIN) { return rc; @@ -1793,7 +1791,7 @@ static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename, } if (sftp->unlink_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, (char *) sftp->unlink_packet, + rc = _libssh2_channel_write(channel, 0, sftp->unlink_packet, packet_len); if (rc == LIBSSH2_ERROR_EAGAIN) { return rc; @@ -1904,7 +1902,7 @@ static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename, } if (sftp->rename_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, (char *) sftp->rename_packet, + rc = _libssh2_channel_write(channel, 0, sftp->rename_packet, sftp->rename_s - sftp->rename_packet); if (rc == LIBSSH2_ERROR_EAGAIN) { return rc; @@ -2027,7 +2025,7 @@ static int sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st) } if (sftp->fstatvfs_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, (char *) packet, packet_len); + rc = _libssh2_channel_write(channel, 0, packet, packet_len); if (rc == LIBSSH2_ERROR_EAGAIN || (0 <= rc && rc < packet_len)) { sftp->fstatvfs_packet = packet; return LIBSSH2_ERROR_EAGAIN; @@ -2139,7 +2137,7 @@ static int sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path, } if (sftp->statvfs_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, (char *) packet, packet_len); + rc = _libssh2_channel_write(channel, 0, packet, packet_len); if (rc == LIBSSH2_ERROR_EAGAIN || (0 <= rc && rc < packet_len)) { sftp->statvfs_packet = packet; return LIBSSH2_ERROR_EAGAIN; @@ -2259,7 +2257,7 @@ static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path, } if (sftp->mkdir_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, (char *) packet, packet_len); + rc = _libssh2_channel_write(channel, 0, packet, packet_len); if (rc == LIBSSH2_ERROR_EAGAIN) { sftp->mkdir_packet = packet; return rc; @@ -2352,7 +2350,7 @@ static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path, } if (sftp->rmdir_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, (char *) sftp->rmdir_packet, + rc = _libssh2_channel_write(channel, 0, sftp->rmdir_packet, packet_len); if (rc == LIBSSH2_ERROR_EAGAIN) { return rc; @@ -2466,8 +2464,7 @@ static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path, } if (sftp->stat_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, (char *) sftp->stat_packet, - packet_len); + rc = _libssh2_channel_write(channel, 0, sftp->stat_packet, packet_len); if (rc == LIBSSH2_ERROR_EAGAIN) { return rc; } else if (packet_len != rc) { @@ -2596,7 +2593,7 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path, } if (sftp->symlink_state == libssh2_NB_state_created) { - rc = _libssh2_channel_write(channel, 0, (char *) sftp->symlink_packet, + rc = _libssh2_channel_write(channel, 0, sftp->symlink_packet, packet_len); if (rc == LIBSSH2_ERROR_EAGAIN) { return rc; diff --git a/src/transport.c b/src/transport.c index e3ef072..7a9afaa 100644 --- a/src/transport.c +++ b/src/transport.c @@ -54,7 +54,7 @@ #define UNPRINTABLE_CHAR '.' static void debugdump(LIBSSH2_SESSION * session, - const char *desc, unsigned char *ptr, size_t size) + const char *desc, const unsigned char *ptr, size_t size) { size_t i; size_t c; @@ -598,8 +598,8 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session) } static int -send_existing(LIBSSH2_SESSION * session, unsigned char *data, - size_t data_len, ssize_t * ret) +send_existing(LIBSSH2_SESSION *session, const unsigned char *data, + size_t data_len, ssize_t *ret) { ssize_t rc; ssize_t length; @@ -661,26 +661,30 @@ send_existing(LIBSSH2_SESSION * session, unsigned char *data, } /* - * libssh2_transport_write + * libssh2_transport_send * * Send a packet, encrypting it and adding a MAC code if necessary * Returns 0 on success, non-zero on failure. * + * The data is provided as _two_ data areas that are combined by this + * function. The 'data' part is sent immediately before 'data2'. 'data2' may + * be set to NULL to only use a single part. + * * Returns LIBSSH2_ERROR_EAGAIN if it would block or if the whole packet was * not sent yet. If it does so, the caller should call this function again as * soon as it is likely that more data can be sent, and this function MUST * then be called with the same argument set (same data pointer and same * data_len) until ERROR_NONE or failure is returned. * - * This function DOES not call _libssh2_error() on any errors. + * This function DOES NOT call _libssh2_error() on any errors. */ -int -_libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data, - size_t data_len) +int _libssh2_transport_send(LIBSSH2_SESSION *session, + const unsigned char *data, size_t data_len, + const unsigned char *data2, size_t data2_len) { int blocksize = - (session->state & LIBSSH2_STATE_NEWKEYS) ? session->local.crypt-> - blocksize : 8; + (session->state & LIBSSH2_STATE_NEWKEYS) ? + session->local.crypt->blocksize : 8; int padding_length; int packet_length; int total_length; @@ -693,17 +697,15 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data, int i; ssize_t ret; int rc; - unsigned char *orgdata = data; + const unsigned char *orgdata = data; size_t orgdata_len = data_len; - if(data_len >= (MAX_SSH_PACKET_LEN-0x100)) - /* too large packet, return error for this until we make this function - split it up and send multiple SSH packets */ - return LIBSSH2_ERROR_INVAL; - debugdump(session, "libssh2_transport_write plain", data, data_len); + if(data2) + debugdump(session, "libssh2_transport_write plain2", data2, data2_len); - /* FIRST, check if we have a pending write to complete */ + /* FIRST, check if we have a pending write to complete. send_existing + only sanity-check data and data_len and not data2 and data2_len!! */ rc = send_existing(session, data, data_len, &ret); if (rc) return rc; @@ -717,20 +719,51 @@ _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data, encrypted = (session->state & LIBSSH2_STATE_NEWKEYS) ? 1 : 0; if (encrypted && session->local.comp->compress) { + /* the idea here is that these function must fail if the output gets + larger than what fits in the assigned buffer so thus they don't + check the input size as we don't know how much it compresses */ + size_t dest_len = MAX_SSH_PACKET_LEN-5-256; + size_t dest2_len = dest_len; + /* compress directly to the target buffer */ rc = session->local.comp->comp(session, - data, &data_len, - &p->outbuf[5], MAX_SSH_PACKET_LEN-5, + &p->outbuf[5], &dest_len, + data, data_len, &session->local.comp_abstract); if(rc) return rc; /* compression failure */ + if(data2 && data2_len) { + /* compress directly to the target buffer right after where the + previous call put data */ + dest2_len -= dest_len; + + rc = session->local.comp->comp(session, + &p->outbuf[5+dest_len], &dest2_len, + data2, data2_len, + &session->local.comp_abstract); + } + else + dest2_len = 0; + if(rc) + return rc; /* compression failure */ + data = p->outbuf; - /* data_len is already updated by the compression function */ + data_len = dest_len + dest2_len; /* use the combined length */ } - else + else { + if((data_len + data2_len) >= (MAX_SSH_PACKET_LEN-0x100)) + /* too large packet, return error for this until we make this + function split it up and send multiple SSH packets */ + return LIBSSH2_ERROR_INVAL; + /* copy the payload data */ memcpy(&p->outbuf[5], data, data_len); + if(data2 && data2_len) + memcpy(&p->outbuf[5+data_len], data2, data2_len); + data_len += data2_len; /* use the combined length */ + } + /* RFC4253 says: Note that the length of the concatenation of 'packet_length', 'padding_length', 'payload', and 'random padding' diff --git a/src/transport.h b/src/transport.h index 81d7c0d..89982a6 100644 --- a/src/transport.h +++ b/src/transport.h @@ -44,23 +44,29 @@ #include "libssh2_priv.h" #include "packet.h" + /* - * libssh2_transport_write + * libssh2_transport_send * * Send a packet, encrypting it and adding a MAC code if necessary * Returns 0 on success, non-zero on failure. * - * Returns PACKET_EAGAIN if it would block - and if it does so, you should - * call this function again as soon as it is likely that more data can be - * sent, and this function should then be called with the same argument set - * (same data pointer and same data_len) until zero or failure is returned. + * The data is provided as _two_ data areas that are combined by this + * function. The 'data' part is sent immediately before 'data2'. 'data2' can + * be set to NULL (or data2_len to 0) to only use a single part. * - * NOTE: this function does not verify that 'data_len' is less than ~35000 - * which is what all implementations should support at least as packet size. - * (RFC4253 section 6.1) + * Returns LIBSSH2_ERROR_EAGAIN if it would block or if the whole packet was + * not sent yet. If it does so, the caller should call this function again as + * soon as it is likely that more data can be sent, and this function MUST + * then be called with the same argument set (same data pointer and same + * data_len) until ERROR_NONE or failure is returned. + * + * This function DOES NOT call _libssh2_error() on any errors. */ -int _libssh2_transport_write(LIBSSH2_SESSION * session, unsigned char *data, - size_t data_len); +int _libssh2_transport_send(LIBSSH2_SESSION *session, + const unsigned char *data, size_t data_len, + const unsigned char *data2, size_t data2_len); + /* * _libssh2_transport_read * diff --git a/src/userauth.c b/src/userauth.c index e22b865..9333d7d 100644 --- a/src/userauth.c +++ b/src/userauth.c @@ -1,6 +1,6 @@ /* Copyright (c) 2004-2007, Sara Golemon * Copyright (c) 2005 Mikhail Gusarov - * Copyright (c) 2009 by Daniel Stenberg + * Copyright (c) 2009-2010 by Daniel Stenberg * All rights reserved. * * Redistribution and use in source and binary forms, @@ -89,14 +89,15 @@ static char *userauth_list(LIBSSH2_SESSION *session, const char *username, *(s++) = SSH_MSG_USERAUTH_REQUEST; _libssh2_store_str(&s, username, username_len); _libssh2_store_str(&s, "ssh-connection", 14); - _libssh2_store_str(&s, "none", 4); + _libssh2_store_u32(&s, 4); /* send "none" separately */ session->userauth_list_state = libssh2_NB_state_created; } if (session->userauth_list_state == libssh2_NB_state_created) { - rc = _libssh2_transport_write(session, session->userauth_list_data, - session->userauth_list_data_len); + rc = _libssh2_transport_send(session, session->userauth_list_data, + session->userauth_list_data_len, + (unsigned char *)"none", 4); if (rc == LIBSSH2_ERROR_EAGAIN) { _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block requesting userauth list"); @@ -192,9 +193,9 @@ libssh2_userauth_authenticated(LIBSSH2_SESSION * session) * Plain ol' login */ static int -userauth_password(LIBSSH2_SESSION *session, const char *username, - unsigned int username_len, const char *password, - unsigned int password_len, +userauth_password(LIBSSH2_SESSION *session, + const char *username, unsigned int username_len, + const unsigned char *password, unsigned int password_len, LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb))) { unsigned char *s; @@ -213,10 +214,12 @@ userauth_password(LIBSSH2_SESSION *session, const char *username, * 40 = acket_type(1) + username_len(4) + service_len(4) + * service(14)"ssh-connection" + method_len(4) + method(8)"password" + * chgpwdbool(1) + password_len(4) */ - session->userauth_pswd_data_len = username_len + password_len + 40; + session->userauth_pswd_data_len = username_len + 40; session->userauth_pswd_data0 = ~SSH_MSG_USERAUTH_PASSWD_CHANGEREQ; + /* TODO: remove this alloc with a fixed buffer in the session + struct */ s = session->userauth_pswd_data = LIBSSH2_ALLOC(session, session->userauth_pswd_data_len); if (!session->userauth_pswd_data) { @@ -230,7 +233,8 @@ userauth_password(LIBSSH2_SESSION *session, const char *username, _libssh2_store_str(&s, "ssh-connection", sizeof("ssh-connection") - 1); _libssh2_store_str(&s, "password", sizeof("password") - 1); *s++ = '\0'; - _libssh2_store_str(&s, password, password_len); + _libssh2_store_u32(&s, password_len); + /* 'password' is sent separately */ _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Attempting to login using password authentication"); @@ -239,8 +243,9 @@ userauth_password(LIBSSH2_SESSION *session, const char *username, } if (session->userauth_pswd_state == libssh2_NB_state_created) { - rc = _libssh2_transport_write(session, session->userauth_pswd_data, - session->userauth_pswd_data_len); + rc = _libssh2_transport_send(session, session->userauth_pswd_data, + session->userauth_pswd_data_len, + password, password_len); if (rc == LIBSSH2_ERROR_EAGAIN) { return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block writing password request"); @@ -335,8 +340,7 @@ userauth_password(LIBSSH2_SESSION *session, const char *username, /* basic data_len + newpw_len(4) */ session->userauth_pswd_data_len = - username_len + password_len + 44 + - session->userauth_pswd_newpw_len; + username_len + password_len + 44; s = session->userauth_pswd_data = LIBSSH2_ALLOC(session, @@ -358,18 +362,21 @@ userauth_password(LIBSSH2_SESSION *session, const char *username, _libssh2_store_str(&s, "password", sizeof("password") - 1); *s++ = 0x01; - _libssh2_store_str(&s, password, password_len); - _libssh2_store_str(&s, session->userauth_pswd_newpw, + _libssh2_store_str(&s, (char *)password, password_len); + _libssh2_store_u32(&s, session->userauth_pswd_newpw_len); + /* send session->userauth_pswd_newpw separately */ session->userauth_pswd_state = libssh2_NB_state_sent2; } if (session->userauth_pswd_state == libssh2_NB_state_sent2) { - rc = _libssh2_transport_write(session, - session->userauth_pswd_data, - session-> - userauth_pswd_data_len); + rc = _libssh2_transport_send(session, + session->userauth_pswd_data, + session->userauth_pswd_data_len, + (unsigned char *) + session->userauth_pswd_newpw, + session->userauth_pswd_newpw_len); if (rc == LIBSSH2_ERROR_EAGAIN) { return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block waiting"); @@ -429,7 +436,7 @@ libssh2_userauth_password_ex(LIBSSH2_SESSION *session, const char *username, int rc; BLOCK_ADJUST(rc, session, userauth_password(session, username, username_len, - password, password_len, + (unsigned char *)password, password_len, passwd_change_cb)); return rc; } @@ -776,9 +783,10 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session, } if (session->userauth_host_state == libssh2_NB_state_created) { - rc = _libssh2_transport_write(session, session->userauth_host_packet, - session->userauth_host_s - - session->userauth_host_packet); + rc = _libssh2_transport_send(session, session->userauth_host_packet, + session->userauth_host_s - + session->userauth_host_packet, + NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) { return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); } @@ -964,7 +972,8 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, _libssh2_store_str(&s, (const char *)session->userauth_pblc_method, session->userauth_pblc_method_len); - _libssh2_store_str(&s, (const char *)pubkeydata, pubkeydata_len); + _libssh2_store_u32(&s, pubkeydata_len); + /* send pubkeydata separately */ _libssh2_debug(session, LIBSSH2_TRACE_AUTH, "Attempting publickey authentication"); @@ -972,8 +981,9 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, } if (session->userauth_pblc_state == libssh2_NB_state_created) { - rc = _libssh2_transport_write(session, session->userauth_pblc_packet, - session->userauth_pblc_packet_len); + rc = _libssh2_transport_send(session, session->userauth_pblc_packet, + session->userauth_pblc_packet_len, + pubkeydata, pubkeydata_len); if (rc == LIBSSH2_ERROR_EAGAIN) return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); else if (rc) { @@ -1130,9 +1140,10 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session, } if (session->userauth_pblc_state == libssh2_NB_state_sent2) { - rc = _libssh2_transport_write(session, session->userauth_pblc_packet, - session->userauth_pblc_s - - session->userauth_pblc_packet); + rc = _libssh2_transport_send(session, session->userauth_pblc_packet, + session->userauth_pblc_s - + session->userauth_pblc_packet, + NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) { return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); } else if (rc) { @@ -1348,8 +1359,9 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session, } if (session->userauth_kybd_state == libssh2_NB_state_created) { - rc = _libssh2_transport_write(session, session->userauth_kybd_data, - session->userauth_kybd_packet_len); + rc = _libssh2_transport_send(session, session->userauth_kybd_data, + session->userauth_kybd_packet_len, + NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) { return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block"); } else if (rc) { @@ -1551,8 +1563,9 @@ userauth_keyboard_interactive(LIBSSH2_SESSION * session, } if (session->userauth_kybd_state == libssh2_NB_state_sent1) { - rc = _libssh2_transport_write(session, session->userauth_kybd_data, - session->userauth_kybd_packet_len); + rc = _libssh2_transport_send(session, session->userauth_kybd_data, + session->userauth_kybd_packet_len, + NULL, 0); if (rc == LIBSSH2_ERROR_EAGAIN) { return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, "Would block");