diff --git a/libssh/channels1.c b/libssh/channels1.c index 9a827e39..6a7a3f26 100644 --- a/libssh/channels1.c +++ b/libssh/channels1.c @@ -4,6 +4,7 @@ * This file is part of the SSH Library * * Copyright (c) 2003-2008 by Aris Adamantiadis + * Copyright (c) 2009 by Andreas Schneider * * The SSH Library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -68,156 +69,257 @@ int channel_open_session1(CHANNEL *chan){ */ int channel_request_pty_size1(CHANNEL *channel, char *terminal, int col, - int row){ - STRING *str; - SSH_SESSION *session=channel->session; - str=string_from_char(terminal); - buffer_add_u8(session->out_buffer,SSH_CMSG_REQUEST_PTY); - buffer_add_ssh_string(session->out_buffer,str); - free(str); - buffer_add_u32(session->out_buffer,ntohl(row)); - buffer_add_u32(session->out_buffer,ntohl(col)); - buffer_add_u32(session->out_buffer,0); /* x */ - buffer_add_u32(session->out_buffer,0); /* y */ - buffer_add_u8(session->out_buffer,0); /* tty things */ - ssh_log(session, SSH_LOG_FUNCTIONS, "Opening a ssh1 pty"); - if(packet_send(session)) - return -1; - if(packet_read(session)) - return -1; - if(packet_translate(session)) - return -1; - switch (session->in_packet.type){ - case SSH_SMSG_SUCCESS: - ssh_log(session, SSH_LOG_RARE, "pty: Success"); - return 0; - break; - case SSH_SMSG_FAILURE: - ssh_set_error(session,SSH_REQUEST_DENIED, - "Server denied PTY allocation"); - ssh_log(session, SSH_LOG_RARE, "pty : denied\n"); - break; - default: - ssh_log(session, SSH_LOG_RARE, "pty : error\n"); - ssh_set_error(session,SSH_FATAL, - "Received unexpected packet type %d", - session->in_packet.type); - return -1; - } + int row) { + SSH_SESSION *session = channel->session; + STRING *str = NULL; + + str = string_from_char(terminal); + if (str == NULL) { return -1; -} + } -int channel_change_pty_size1(CHANNEL *channel, int cols, int rows){ - SSH_SESSION *session=channel->session; - buffer_add_u8(session->out_buffer,SSH_CMSG_WINDOW_SIZE); - buffer_add_u32(session->out_buffer,ntohl(rows)); - buffer_add_u32(session->out_buffer,ntohl(cols)); - buffer_add_u32(session->out_buffer,0); - buffer_add_u32(session->out_buffer,0); - if(packet_send(session)) - return -1; - ssh_log(session, SSH_LOG_RARE, "Change pty size send"); - packet_wait(session,SSH_SMSG_SUCCESS,1); - switch (session->in_packet.type){ - case SSH_SMSG_SUCCESS: - ssh_log(session, SSH_LOG_RARE, "pty size changed"); - return 0; - break; - case SSH_SMSG_FAILURE: - ssh_log(session, SSH_LOG_RARE, "pty size change denied"); - ssh_set_error(session,SSH_REQUEST_DENIED,"pty size change denied"); - return -1; - } - ssh_set_error(session,SSH_FATAL,"Received unexpected packet type %d", - session->in_packet.type); + if (buffer_add_u8(session->out_buffer, SSH_CMSG_REQUEST_PTY) < 0) { + string_free(str); return -1; + } + if (buffer_add_ssh_string(session->out_buffer, str) < 0) { + string_free(str); + return -1; + } + string_free(str); + + if (buffer_add_u32(session->out_buffer, ntohl(row)) < 0) { + return -1; + } + if (buffer_add_u32(session->out_buffer, ntohl(col)) < 0) { + return -1; + } + if (buffer_add_u32(session->out_buffer, 0) < 0) { /* x */ + return -1; + } + if (buffer_add_u32(session->out_buffer, 0) < 0) { /* y */ + return -1; + } + if (buffer_add_u8(session->out_buffer, 0); < 0) { /* tty things */ + return -1; + } + + ssh_log(session, SSH_LOG_FUNCTIONS, "Opening a ssh1 pty"); + if (packet_send(session) != SSH_OK) { + return -1; + } + if (packet_read(session) != SSH_OK) { + return -1; + } + if (packet_translate(session) != SSH_OK) { + return -1; + } + + switch (session->in_packet.type) { + case SSH_SMSG_SUCCESS: + ssh_log(session, SSH_LOG_RARE, "PTY: Success"); + return 0; + break; + case SSH_SMSG_FAILURE: + ssh_set_error(session, SSH_REQUEST_DENIED, + "Server denied PTY allocation"); + ssh_log(session, SSH_LOG_RARE, "PTY: denied\n"); + break; + default: + ssh_log(session, SSH_LOG_RARE, "PTY: error\n"); + ssh_set_error(session, SSH_FATAL, + "Received unexpected packet type %d", + session->in_packet.type); + return -1; + } + + return -1; } -int channel_request_shell1(CHANNEL *channel){ - SSH_SESSION *session=channel->session; - buffer_add_u8(session->out_buffer,SSH_CMSG_EXEC_SHELL); - if(packet_send(session)) - return -1; - ssh_log(session, SSH_LOG_RARE, "Launched a shell"); - return 0; +int channel_change_pty_size1(CHANNEL *channel, int cols, int rows) { + SSH_SESSION *session=channel->session; + + if (buffer_add_u8(session->out_buffer, SSH_CMSG_WINDOW_SIZE) < 0) { + return -1; + } + if (buffer_add_u32(session->out_buffer, ntohl(rows)) < 0) { + return -1; + } + if (buffer_add_u32(session->out_buffer, ntohl(cols)) < 0) { + return -1; + } + if (buffer_add_u32(session->out_buffer, 0) < 0) { + return -1; + } + if (buffer_add_u32(session->out_buffer, 0) < 0) { + return -1; + } + + if (packet_send(session)) { + return -1; + } + + ssh_log(session, SSH_LOG_RARE, "Change pty size send"); + + if (packet_wait(session, SSH_SMSG_SUCCESS, 1) < 0) { + return -1; + } + + switch (session->in_packet.type) { + case SSH_SMSG_SUCCESS: + ssh_log(session, SSH_LOG_RARE, "pty size changed"); + return 0; + case SSH_SMSG_FAILURE: + ssh_log(session, SSH_LOG_RARE, "pty size change denied"); + ssh_set_error(session, SSH_REQUEST_DENIED, "pty size change denied"); + return -1; + } + + ssh_set_error(session, SSH_FATAL, "Received unexpected packet type %d", + session->in_packet.type); + + return -1; } -int channel_request_exec1(CHANNEL *channel, char *cmd){ - SSH_SESSION *session=channel->session; - STRING *command=string_from_char(cmd); - buffer_add_u8(session->out_buffer,SSH_CMSG_EXEC_CMD); - buffer_add_ssh_string(session->out_buffer,command); - free(command); - if(packet_send(session)) - return -1; - ssh_log(session, SSH_LOG_RARE, "Executing %s ...",cmd); - return 0; +int channel_request_shell1(CHANNEL *channel) { + SSH_SESSION *session = channel->session; + + if (buffer_add_u8(session->out_buffer,SSH_CMSG_EXEC_SHELL) < 0) { + return -1; + } + + if (packet_send(session) != SSH_OK) { + return -1; + } + + ssh_log(session, SSH_LOG_RARE, "Launched a shell"); + + return 0; } -static void channel_rcv_data1(SSH_SESSION *session, int is_stderr){ - CHANNEL *channel; - STRING *str; - channel=session->channels; // Easy. hack this when multiple channel - // are comming - str=buffer_get_ssh_string(session->in_buffer); - if(!str){ - ssh_log(session, SSH_LOG_FUNCTIONS, "Invalid data packet !\n"); - return; +int channel_request_exec1(CHANNEL *channel, const char *cmd) { + SSH_SESSION *session = channel->session; + STRING *command = NULL; + + command = string_from_char(cmd); + if (command == NULL) { + return -1; + } + + if (buffer_add_u8(session->out_buffer, SSH_CMSG_EXEC_CMD) < 0) { + string_free(command); + return -1; + } + if (buffer_add_ssh_string(session->out_buffer, command) < 0) { + string_free(command); + return -1; + } + string_free(command); + + if(packet_send(session) != SSH_OK) { + return -1; + } + + ssh_log(session, SSH_LOG_RARE, "Executing %s ...", cmd); + + return 0; +} + +static int channel_rcv_data1(SSH_SESSION *session, int is_stderr) { + CHANNEL *channel = session->channels; + STRING *str = NULL; + + str = buffer_get_ssh_string(session->in_buffer); + if (str == NULL) { + ssh_log(session, SSH_LOG_FUNCTIONS, "Invalid data packet !\n"); + return -1; } + ssh_log(session, SSH_LOG_RARE, - "Adding %zd bytes data in %d", string_len(str), is_stderr); - channel_default_bufferize(channel,str->string,string_len(str), - is_stderr); - free(str); -} - -static void channel_rcv_close1(SSH_SESSION *session){ - CHANNEL *channel=session->channels; - u32 status; - buffer_get_u32(session->in_buffer,&status); - /* it's much more than a channel closing. spec says it's the last - * message sent by server (strange) - */ - /* actually status is lost somewhere */ - channel->open=0; - channel->remote_eof=1; - buffer_add_u8(session->out_buffer,SSH_CMSG_EXIT_CONFIRMATION); - packet_send(session); -} - -void channel_handle1(SSH_SESSION *session, int type){ - ssh_log(session, SSH_LOG_RARE, "Channel_handle1(%d)", type); - switch (type){ - case SSH_SMSG_STDOUT_DATA: - channel_rcv_data1(session,0); - break; - case SSH_SMSG_EXITSTATUS: - channel_rcv_close1(session); - break; - default: - ssh_log(session, SSH_LOG_FUNCTIONS, "Unexepected message %d", type); + "Adding %zu bytes data in %d", + string_len(str), is_stderr); + if (channel_default_bufferize(channel, str->string, string_len(str), + is_stderr) < 0) { + string_free(str); + return -1; } + string_free(str); + + return 0; } -int channel_write1(CHANNEL *channel, void *data, int len){ - SSH_SESSION *session=channel->session; - int origlen=len; - int effectivelen; - while(len>0){ - buffer_add_u8(session->out_buffer,SSH_CMSG_STDIN_DATA); - if(len > 32000) - effectivelen=32000; - else - effectivelen=len; - buffer_add_u32(session->out_buffer,htonl(effectivelen)); - buffer_add_data(session->out_buffer,data,effectivelen); - data+=effectivelen; - len-=effectivelen; - if(packet_send(session)) - return -1; +static int channel_rcv_close1(SSH_SESSION *session) { + CHANNEL *channel = session->channels; + u32 status; + + buffer_get_u32(session->in_buffer, &status); + /* + * It's much more than a channel closing. spec says it's the last + * message sent by server (strange) + */ + + /* actually status is lost somewhere */ + channel->open = 0; + channel->remote_eof = 1; + + if (buffer_add_u8(session->out_buffer, SSH_CMSG_EXIT_CONFIRMATION) < 0) { + return -1; + } + + if (packet_send(session) != SSH_OK) { + return -1; + } + + return 0; +} + +int channel_handle1(SSH_SESSION *session, int type) { + ssh_log(session, SSH_LOG_RARE, "Channel_handle1(%d)", type); + switch (type) { + case SSH_SMSG_STDOUT_DATA: + if (channel_rcv_data1(session,0) < 0) { + return -1; + } + break; + case SSH_SMSG_EXITSTATUS: + channel_rcv_close1(session); + break; + default: + ssh_log(session, SSH_LOG_FUNCTIONS, "Unexepected message %d", type); + } + + return 0; +} + +int channel_write1(CHANNEL *channel, void *data, int len) { + SSH_SESSION *session = channel->session; + int origlen = len; + int effectivelen; + + while (len > 0) { + if (buffer_add_u8(session->out_buffer, SSH_CMSG_STDIN_DATA) < 0) { + return -1; } - return origlen; + + effectivelen = len > 32000 ? 32000 : len; + + if (buffer_add_u32(session->out_buffer, htonl(effectivelen)) < 0) { + return -1; + } + if (buffer_add_data(session->out_buffer, data, effectivelen) < 0) { + return -1; + } + + data += effectivelen; + len -= effectivelen; + + if (packet_send(session) != SSH_OK) { + return -1; + } + } + + return origlen; } #endif /* HAVE_SSH1 */