161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
#define BUG_SSH2_HMAC 2
#define BUG_NEEDS_SSH1_PLAIN_PASSWORD 4
#define BUG_CHOKES_ON_RSA 8
#define BUG_SSH2_RSA_PADDING 16
#define BUG_SSH2_DERIVEKEY 32
#define BUG_SSH2_REKEY 64
#define BUG_SSH2_PK_SESSIONID 128
#define translate(x) if (type == x) return #x
#define translatec(x,ctx) if (type == x && (pkt_ctx & ctx)) return #x
static char *ssh1_pkt_type(int type)
{
translate(SSH1_MSG_DISCONNECT);
translate(SSH1_SMSG_PUBLIC_KEY);
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
|
#define BUG_SSH2_HMAC 2
#define BUG_NEEDS_SSH1_PLAIN_PASSWORD 4
#define BUG_CHOKES_ON_RSA 8
#define BUG_SSH2_RSA_PADDING 16
#define BUG_SSH2_DERIVEKEY 32
#define BUG_SSH2_REKEY 64
#define BUG_SSH2_PK_SESSIONID 128
/*
* Codes for terminal modes.
* Most of these are the same in SSH-1 and SSH-2.
* This list is derived from draft-ietf-secsh-connect-25 and
* SSH-1 RFC-1.2.31.
*/
static const struct {
const char* const mode;
int opcode;
enum { TTY_OP_CHAR, TTY_OP_BOOL } type;
} ssh_ttymodes[] = {
/* "V" prefix discarded for special characters relative to SSH specs */
{ "INTR", 1, TTY_OP_CHAR },
{ "QUIT", 2, TTY_OP_CHAR },
{ "ERASE", 3, TTY_OP_CHAR },
{ "KILL", 4, TTY_OP_CHAR },
{ "EOF", 5, TTY_OP_CHAR },
{ "EOL", 6, TTY_OP_CHAR },
{ "EOL2", 7, TTY_OP_CHAR },
{ "START", 8, TTY_OP_CHAR },
{ "STOP", 9, TTY_OP_CHAR },
{ "SUSP", 10, TTY_OP_CHAR },
{ "DSUSP", 11, TTY_OP_CHAR },
{ "REPRINT", 12, TTY_OP_CHAR },
{ "WERASE", 13, TTY_OP_CHAR },
{ "LNEXT", 14, TTY_OP_CHAR },
{ "FLUSH", 15, TTY_OP_CHAR },
{ "SWTCH", 16, TTY_OP_CHAR },
{ "STATUS", 17, TTY_OP_CHAR },
{ "DISCARD", 18, TTY_OP_CHAR },
{ "IGNPAR", 30, TTY_OP_BOOL },
{ "PARMRK", 31, TTY_OP_BOOL },
{ "INPCK", 32, TTY_OP_BOOL },
{ "ISTRIP", 33, TTY_OP_BOOL },
{ "INLCR", 34, TTY_OP_BOOL },
{ "IGNCR", 35, TTY_OP_BOOL },
{ "ICRNL", 36, TTY_OP_BOOL },
{ "IUCLC", 37, TTY_OP_BOOL },
{ "IXON", 38, TTY_OP_BOOL },
{ "IXANY", 39, TTY_OP_BOOL },
{ "IXOFF", 40, TTY_OP_BOOL },
{ "IMAXBEL", 41, TTY_OP_BOOL },
{ "ISIG", 50, TTY_OP_BOOL },
{ "ICANON", 51, TTY_OP_BOOL },
{ "XCASE", 52, TTY_OP_BOOL },
{ "ECHO", 53, TTY_OP_BOOL },
{ "ECHOE", 54, TTY_OP_BOOL },
{ "ECHOK", 55, TTY_OP_BOOL },
{ "ECHONL", 56, TTY_OP_BOOL },
{ "NOFLSH", 57, TTY_OP_BOOL },
{ "TOSTOP", 58, TTY_OP_BOOL },
{ "IEXTEN", 59, TTY_OP_BOOL },
{ "ECHOCTL", 60, TTY_OP_BOOL },
{ "ECHOKE", 61, TTY_OP_BOOL },
{ "PENDIN", 62, TTY_OP_BOOL }, /* XXX is this a real mode? */
{ "OPOST", 70, TTY_OP_BOOL },
{ "OLCUC", 71, TTY_OP_BOOL },
{ "ONLCR", 72, TTY_OP_BOOL },
{ "OCRNL", 73, TTY_OP_BOOL },
{ "ONOCR", 74, TTY_OP_BOOL },
{ "ONLRET", 75, TTY_OP_BOOL },
{ "CS7", 90, TTY_OP_BOOL },
{ "CS8", 91, TTY_OP_BOOL },
{ "PARENB", 92, TTY_OP_BOOL },
{ "PARODD", 93, TTY_OP_BOOL }
};
/* Miscellaneous other tty-related constants. */
#define SSH_TTY_OP_END 0
/* The opcodes for ISPEED/OSPEED differ between SSH-1 and SSH-2. */
#define SSH1_TTY_OP_ISPEED 192
#define SSH1_TTY_OP_OSPEED 193
#define SSH2_TTY_OP_ISPEED 128
#define SSH2_TTY_OP_OSPEED 129
/* Helper functions for parsing tty-related config. */
static unsigned int ssh_tty_parse_specchar(char *s)
{
unsigned int ret;
if (*s) {
char *next = NULL;
ret = ctrlparse(s, &next);
if (!next) ret = s[0];
} else {
ret = 255; /* special value meaning "don't set" */
}
return ret;
}
static unsigned int ssh_tty_parse_boolean(char *s)
{
if (stricmp(s, "yes") == 0 ||
stricmp(s, "on") == 0 ||
stricmp(s, "true") == 0 ||
stricmp(s, "+") == 0)
return 1; /* true */
else if (stricmp(s, "no") == 0 ||
stricmp(s, "off") == 0 ||
stricmp(s, "false") == 0 ||
stricmp(s, "-") == 0)
return 0; /* false */
else
return (atoi(s) != 0);
}
#define translate(x) if (type == x) return #x
#define translatec(x,ctx) if (type == x && (pkt_ctx & ctx)) return #x
static char *ssh1_pkt_type(int type)
{
translate(SSH1_MSG_DISCONNECT);
translate(SSH1_SMSG_PUBLIC_KEY);
|
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
|
}
}
ssh_setup_portfwd(ssh, &ssh->cfg);
ssh->packet_dispatch[SSH1_MSG_PORT_OPEN] = ssh1_msg_port_open;
if (!ssh->cfg.nopty) {
/* Unpick the terminal-speed string. */
/* XXX perhaps we should allow no speeds to be sent. */
ssh->ospeed = 38400; ssh->ispeed = 38400; /* last-resort defaults */
sscanf(ssh->cfg.termspeed, "%d,%d", &ssh->ospeed, &ssh->ispeed);
/* Send the pty request. */
send_packet(ssh, SSH1_CMSG_REQUEST_PTY,
PKT_STR, ssh->cfg.termtype,
PKT_INT, ssh->term_height,
PKT_INT, ssh->term_width,
PKT_INT, 0, PKT_INT, 0, /* width,height in pixels */
PKT_CHAR, 192, PKT_INT, ssh->ispeed, /* TTY_OP_ISPEED */
PKT_CHAR, 193, PKT_INT, ssh->ospeed, /* TTY_OP_OSPEED */
PKT_CHAR, 0, PKT_END);
ssh->state = SSH_STATE_INTERMED;
do {
crReturnV;
} while (!pktin);
if (pktin->type != SSH1_SMSG_SUCCESS
&& pktin->type != SSH1_SMSG_FAILURE) {
bombout(("Protocol confusion"));
|
>
|
|
|
|
>
|
>
>
>
|
>
|
|
>
|
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
|
}
}
ssh_setup_portfwd(ssh, &ssh->cfg);
ssh->packet_dispatch[SSH1_MSG_PORT_OPEN] = ssh1_msg_port_open;
if (!ssh->cfg.nopty) {
struct Packet *pkt;
/* Unpick the terminal-speed string. */
/* XXX perhaps we should allow no speeds to be sent. */
ssh->ospeed = 38400; ssh->ispeed = 38400; /* last-resort defaults */
sscanf(ssh->cfg.termspeed, "%d,%d", &ssh->ospeed, &ssh->ispeed);
/* Send the pty request. */
pkt = ssh1_pkt_init(SSH1_CMSG_REQUEST_PTY);
ssh_pkt_addstring(pkt, ssh->cfg.termtype);
ssh_pkt_adduint32(pkt, ssh->term_height);
ssh_pkt_adduint32(pkt, ssh->term_width);
ssh_pkt_adduint32(pkt, 0); /* width in pixels */
ssh_pkt_adduint32(pkt, 0); /* height in pixels */
parse_ttymodes(ssh, ssh->cfg.ttymodes,
ssh1_send_ttymode, (void *)pkt);
ssh_pkt_addbyte(pkt, SSH1_TTY_OP_ISPEED);
ssh_pkt_adduint32(pkt, ssh->ispeed);
ssh_pkt_addbyte(pkt, SSH1_TTY_OP_OSPEED);
ssh_pkt_adduint32(pkt, ssh->ospeed);
ssh_pkt_addbyte(pkt, SSH_TTY_OP_END);
s_wrpkt(ssh, pkt);
ssh->state = SSH_STATE_INTERMED;
do {
crReturnV;
} while (!pktin);
if (pktin->type != SSH1_SMSG_SUCCESS
&& pktin->type != SSH1_SMSG_FAILURE) {
bombout(("Protocol confusion"));
|
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
|
ssh2_pkt_adduint32(pktout, c->remoteid);
ssh2_pkt_adduint32(pktout, c->localid);
ssh2_pkt_adduint32(pktout, c->v.v2.locwindow);
ssh2_pkt_adduint32(pktout, OUR_V2_MAXPKT); /* our max pkt size */
ssh2_pkt_send(ssh, pktout);
}
}
/*
* Handle the SSH-2 userauth and connection layers.
*/
static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
struct Packet *pktin)
{
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
|
ssh2_pkt_adduint32(pktout, c->remoteid);
ssh2_pkt_adduint32(pktout, c->localid);
ssh2_pkt_adduint32(pktout, c->v.v2.locwindow);
ssh2_pkt_adduint32(pktout, OUR_V2_MAXPKT); /* our max pkt size */
ssh2_pkt_send(ssh, pktout);
}
}
/* Helper function to deal with sending tty modes for "pty-req" */
static void ssh2_send_ttymode(void *data, char *mode, char *val)
{
struct Packet *pktout = (struct Packet *)data;
int i = 0;
unsigned int arg = 0;
while (strcmp(mode, ssh_ttymodes[i].mode) != 0) i++;
if (i == lenof(ssh_ttymodes)) return;
switch (ssh_ttymodes[i].type) {
case TTY_OP_CHAR:
arg = ssh_tty_parse_specchar(val);
break;
case TTY_OP_BOOL:
arg = ssh_tty_parse_boolean(val);
break;
}
ssh2_pkt_addbyte(pktout, ssh_ttymodes[i].opcode);
ssh2_pkt_adduint32(pktout, arg);
}
/*
* Handle the SSH-2 userauth and connection layers.
*/
static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen,
struct Packet *pktin)
{
|
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
|
ssh2_pkt_addbool(s->pktout, 1); /* want reply */
ssh2_pkt_addstring(s->pktout, ssh->cfg.termtype);
ssh2_pkt_adduint32(s->pktout, ssh->term_width);
ssh2_pkt_adduint32(s->pktout, ssh->term_height);
ssh2_pkt_adduint32(s->pktout, 0); /* pixel width */
ssh2_pkt_adduint32(s->pktout, 0); /* pixel height */
ssh2_pkt_addstring_start(s->pktout);
ssh2_pkt_addbyte(s->pktout, 128); /* TTY_OP_ISPEED */
ssh2_pkt_adduint32(s->pktout, ssh->ispeed);
ssh2_pkt_addbyte(s->pktout, 129); /* TTY_OP_OSPEED */
ssh2_pkt_adduint32(s->pktout, ssh->ospeed);
ssh2_pkt_addstring_data(s->pktout, "\0", 1); /* TTY_OP_END */
ssh2_pkt_send(ssh, s->pktout);
ssh->state = SSH_STATE_INTERMED;
crWaitUntilV(pktin);
|
>
>
|
|
|
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
|
ssh2_pkt_addbool(s->pktout, 1); /* want reply */
ssh2_pkt_addstring(s->pktout, ssh->cfg.termtype);
ssh2_pkt_adduint32(s->pktout, ssh->term_width);
ssh2_pkt_adduint32(s->pktout, ssh->term_height);
ssh2_pkt_adduint32(s->pktout, 0); /* pixel width */
ssh2_pkt_adduint32(s->pktout, 0); /* pixel height */
ssh2_pkt_addstring_start(s->pktout);
parse_ttymodes(ssh, ssh->cfg.ttymodes,
ssh2_send_ttymode, (void *)s->pktout);
ssh2_pkt_addbyte(s->pktout, SSH2_TTY_OP_ISPEED);
ssh2_pkt_adduint32(s->pktout, ssh->ispeed);
ssh2_pkt_addbyte(s->pktout, SSH2_TTY_OP_OSPEED);
ssh2_pkt_adduint32(s->pktout, ssh->ospeed);
ssh2_pkt_addstring_data(s->pktout, "\0", 1); /* TTY_OP_END */
ssh2_pkt_send(ssh, s->pktout);
ssh->state = SSH_STATE_INTERMED;
crWaitUntilV(pktin);
|