Diff

Differences From Artifact [fe4e917609]:

To Artifact [15e2d1e08e]:


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);
780
781
782
783
784
785
786























787
788
789
790
791
792
793
	pkt->logmode = blanktype;
}

static void end_log_omission(Ssh ssh, struct Packet *pkt)
{
    pkt->logmode = PKTLOG_EMIT;
}
























static int ssh_channelcmp(void *av, void *bv)
{
    struct ssh_channel *a = (struct ssh_channel *) av;
    struct ssh_channel *b = (struct ssh_channel *) bv;
    if (a->localid < b->localid)
	return -1;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
	pkt->logmode = blanktype;
}

static void end_log_omission(Ssh ssh, struct Packet *pkt)
{
    pkt->logmode = PKTLOG_EMIT;
}

/* Helper function for common bits of parsing cfg.ttymodes. */
static void parse_ttymodes(Ssh ssh, char *modes,
			   void (*do_mode)(void *data, char *mode, char *val),
			   void *data)
{
    while (*modes) {
	char *t = strchr(modes, '\t');
	char *m = snewn(t-modes+1, char);
	char *val;
	strncpy(m, modes, t-modes);
	m[t-modes] = '\0';
	if (*(t+1) == 'A')
	    val = get_ttymode(ssh->frontend, m);
	else
	    val = dupstr(t+2);
	if (val)
	    do_mode(data, m, val);
	sfree(m);
	sfree(val);
	modes += strlen(modes) + 1;
    }
}

static int ssh_channelcmp(void *av, void *bv)
{
    struct ssh_channel *a = (struct ssh_channel *) av;
    struct ssh_channel *b = (struct ssh_channel *) bv;
    if (a->localid < b->localid)
	return -1;
4406
4407
4408
4409
4410
4411
4412





















4413
4414
4415
4416
4417
4418
4419
     * session which we might mistake for another
     * encrypted packet, we close the session once
     * we've sent EXIT_CONFIRMATION.
     */
    ssh->close_expected = TRUE;
    ssh_closing((Plug)ssh, NULL, 0, 0);
}






















static void do_ssh1_connection(Ssh ssh, unsigned char *in, int inlen,
			       struct Packet *pktin)
{
    crBegin(ssh->do_ssh1_connection_crstate);

    ssh->packet_dispatch[SSH1_SMSG_STDOUT_DATA] = 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
     * session which we might mistake for another
     * encrypted packet, we close the session once
     * we've sent EXIT_CONFIRMATION.
     */
    ssh->close_expected = TRUE;
    ssh_closing((Plug)ssh, NULL, 0, 0);
}

/* Helper function to deal with sending tty modes for REQUEST_PTY */
static void ssh1_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_addbyte(pktout, arg);
}


static void do_ssh1_connection(Ssh ssh, unsigned char *in, int inlen,
			       struct Packet *pktin)
{
    crBegin(ssh->do_ssh1_connection_crstate);

    ssh->packet_dispatch[SSH1_SMSG_STDOUT_DATA] = 
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);