2
* channels1.c - Support for SSH-1 type channels
4
* This file is part of the SSH Library
6
* Copyright (c) 2003-2008 by Aris Adamantiadis
7
* Copyright (c) 2009 by Andreas Schneider <mail@cynapses.org>
9
* The SSH Library is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU Lesser General Public License as published by
11
* the Free Software Foundation; either version 2.1 of the License, or (at your
12
* option) any later version.
14
* The SSH Library is distributed in the hope that it will be useful, but
15
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17
* License for more details.
19
* You should have received a copy of the GNU Lesser General Public License
20
* along with the SSH Library; see the file COPYING. If not, write to
21
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
29
#include <arpa/inet.h>
33
#include "libssh/priv.h"
34
#include "libssh/ssh1.h"
35
#include "libssh/buffer.h"
36
#include "libssh/packet.h"
37
#include "libssh/channels.h"
38
#include "libssh/session.h"
43
* This is a big hack. In fact, SSH1 doesn't make a clever use of channels.
44
* The whole packets concerning shells are sent outside of a channel.
45
* Thus, an inside limitation of this behavior is that you can't only
47
* The question is still how they managed to embed two "channel" into one
51
int channel_open_session1(ssh_channel chan) {
53
* We guess we are requesting an *exec* channel. It can only have one exec
54
* channel. So we abort with an error if we need more than one.
56
ssh_session session = chan->session;
57
if (session->exec_channel_opened) {
58
ssh_set_error(session, SSH_REQUEST_DENIED,
59
"SSH1 supports only one execution channel. "
60
"One has already been opened");
63
session->exec_channel_opened = 1;
64
chan->state = SSH_CHANNEL_STATE_OPEN;
65
chan->local_maxpacket = 32000;
66
chan->local_window = 64000;
67
ssh_log(session, SSH_LOG_PACKET, "Opened a SSH1 channel session");
72
/* 10 SSH_CMSG_REQUEST_PTY
74
* string TERM environment variable value (e.g. vt100)
75
* 32-bit int terminal height, rows (e.g., 24)
76
* 32-bit int terminal width, columns (e.g., 80)
77
* 32-bit int terminal width, pixels (0 if no graphics) (e.g., 480)
78
* 32-bit int terminal height, pixels (0 if no graphics) (e.g., 640)
79
* n bytes tty modes encoded in binary
80
* Some day, someone should have a look at that nasty tty encoded. It's
81
* much simplier under ssh2. I just hope the defaults values are ok ...
84
int channel_request_pty_size1(ssh_channel channel, const char *terminal, int col,
86
ssh_session session = channel->session;
87
ssh_string str = NULL;
88
if(channel->request_state != SSH_CHANNEL_REQ_STATE_NONE){
89
ssh_set_error(session,SSH_REQUEST_DENIED,"Wrong request state");
92
str = ssh_string_from_char(terminal);
94
ssh_set_error_oom(session);
98
if (buffer_add_u8(session->out_buffer, SSH_CMSG_REQUEST_PTY) < 0 ||
99
buffer_add_ssh_string(session->out_buffer, str) < 0) {
100
ssh_string_free(str);
103
ssh_string_free(str);
105
if (buffer_add_u32(session->out_buffer, ntohl(row)) < 0 ||
106
buffer_add_u32(session->out_buffer, ntohl(col)) < 0 ||
107
buffer_add_u32(session->out_buffer, 0) < 0 || /* x */
108
buffer_add_u32(session->out_buffer, 0) < 0 || /* y */
109
buffer_add_u8(session->out_buffer, 0) < 0) { /* tty things */
113
ssh_log(session, SSH_LOG_FUNCTIONS, "Opening a ssh1 pty");
115
if (packet_send(session) == SSH_ERROR) {
118
switch(channel->request_state){
119
case SSH_CHANNEL_REQ_STATE_ERROR:
120
case SSH_CHANNEL_REQ_STATE_PENDING:
121
case SSH_CHANNEL_REQ_STATE_NONE:
122
channel->request_state=SSH_CHANNEL_REQ_STATE_NONE;
124
case SSH_CHANNEL_REQ_STATE_ACCEPTED:
125
channel->request_state=SSH_CHANNEL_REQ_STATE_NONE;
126
ssh_log(session, SSH_LOG_RARE, "PTY: Success");
128
case SSH_CHANNEL_REQ_STATE_DENIED:
129
channel->request_state=SSH_CHANNEL_REQ_STATE_NONE;
130
ssh_set_error(session, SSH_REQUEST_DENIED,
131
"Server denied PTY allocation");
132
ssh_log(session, SSH_LOG_RARE, "PTY: denied\n");
139
int channel_change_pty_size1(ssh_channel channel, int cols, int rows) {
140
ssh_session session = channel->session;
141
if(channel->request_state != SSH_CHANNEL_REQ_STATE_NONE){
142
ssh_set_error(session,SSH_REQUEST_DENIED,"Wrong request state");
145
if (buffer_add_u8(session->out_buffer, SSH_CMSG_WINDOW_SIZE) < 0 ||
146
buffer_add_u32(session->out_buffer, ntohl(rows)) < 0 ||
147
buffer_add_u32(session->out_buffer, ntohl(cols)) < 0 ||
148
buffer_add_u32(session->out_buffer, 0) < 0 ||
149
buffer_add_u32(session->out_buffer, 0) < 0) {
152
channel->request_state=SSH_CHANNEL_REQ_STATE_PENDING;
153
if (packet_send(session) == SSH_ERROR) {
157
ssh_log(session, SSH_LOG_PROTOCOL, "Change pty size send");
158
while(channel->request_state==SSH_CHANNEL_REQ_STATE_PENDING){
159
ssh_handle_packets(session,-1);
161
switch(channel->request_state){
162
case SSH_CHANNEL_REQ_STATE_ERROR:
163
case SSH_CHANNEL_REQ_STATE_PENDING:
164
case SSH_CHANNEL_REQ_STATE_NONE:
165
channel->request_state=SSH_CHANNEL_REQ_STATE_NONE;
167
case SSH_CHANNEL_REQ_STATE_ACCEPTED:
168
channel->request_state=SSH_CHANNEL_REQ_STATE_NONE;
169
ssh_log(session, SSH_LOG_PROTOCOL, "pty size changed");
171
case SSH_CHANNEL_REQ_STATE_DENIED:
172
channel->request_state=SSH_CHANNEL_REQ_STATE_NONE;
173
ssh_log(session, SSH_LOG_RARE, "pty size change denied");
174
ssh_set_error(session, SSH_REQUEST_DENIED, "pty size change denied");
182
int channel_request_shell1(ssh_channel channel) {
183
ssh_session session = channel->session;
185
if (buffer_add_u8(session->out_buffer,SSH_CMSG_EXEC_SHELL) < 0) {
189
if (packet_send(session) == SSH_ERROR) {
193
ssh_log(session, SSH_LOG_RARE, "Launched a shell");
198
int channel_request_exec1(ssh_channel channel, const char *cmd) {
199
ssh_session session = channel->session;
200
ssh_string command = NULL;
202
command = ssh_string_from_char(cmd);
203
if (command == NULL) {
207
if (buffer_add_u8(session->out_buffer, SSH_CMSG_EXEC_CMD) < 0 ||
208
buffer_add_ssh_string(session->out_buffer, command) < 0) {
209
ssh_string_free(command);
212
ssh_string_free(command);
214
if(packet_send(session) == SSH_ERROR) {
218
ssh_log(session, SSH_LOG_RARE, "Executing %s ...", cmd);
223
SSH_PACKET_CALLBACK(ssh_packet_data1){
224
ssh_channel channel = session->channels;
225
ssh_string str = NULL;
226
int is_stderr=(type==SSH_SMSG_STDOUT_DATA ? 0 : 1);
228
str = buffer_get_ssh_string(packet);
230
ssh_log(session, SSH_LOG_FUNCTIONS, "Invalid data packet !\n");
231
return SSH_PACKET_USED;
234
ssh_log(session, SSH_LOG_PROTOCOL,
235
"Adding %" PRIdS " bytes data in %d",
236
ssh_string_len(str), is_stderr);
238
if (channel_default_bufferize(channel, ssh_string_data(str), ssh_string_len(str),
240
ssh_string_free(str);
241
return SSH_PACKET_USED;
243
ssh_string_free(str);
245
return SSH_PACKET_USED;
248
SSH_PACKET_CALLBACK(ssh_packet_close1){
249
ssh_channel channel = session->channels;
253
buffer_get_u32(packet, &status);
255
* It's much more than a channel closing. spec says it's the last
256
* message sent by server (strange)
259
/* actually status is lost somewhere */
260
channel->state = SSH_CHANNEL_STATE_CLOSED;
261
channel->remote_eof = 1;
263
buffer_add_u8(session->out_buffer, SSH_CMSG_EXIT_CONFIRMATION);
264
packet_send(session);
266
return SSH_PACKET_USED;
270
int channel_write1(ssh_channel channel, const void *data, int len) {
271
ssh_session session = channel->session;
274
const unsigned char *ptr=data;
276
if (buffer_add_u8(session->out_buffer, SSH_CMSG_STDIN_DATA) < 0) {
280
effectivelen = len > 32000 ? 32000 : len;
282
if (buffer_add_u32(session->out_buffer, htonl(effectivelen)) < 0 ||
283
buffer_add_data(session->out_buffer, ptr, effectivelen) < 0) {
290
if (packet_send(session) == SSH_ERROR) {
298
#endif /* WITH_SSH1 */
299
/* vim: set ts=2 sw=2 et cindent: */