Diff

Differences From Artifact [2252139a27]:

To Artifact [1a7301e6c1]:


311
312
313
314
315
316
317
318

319
320
321
322
323
324
325
311
312
313
314
315
316
317

318
319
320
321
322
323
324
325







-
+







static void ssh2_pkt_init(Ssh, int pkt_type);
static void ssh2_pkt_addbool(Ssh, unsigned char value);
static void ssh2_pkt_adduint32(Ssh, unsigned long value);
static void ssh2_pkt_addstring_start(Ssh);
static void ssh2_pkt_addstring_str(Ssh, char *data);
static void ssh2_pkt_addstring_data(Ssh, char *data, int len);
static void ssh2_pkt_addstring(Ssh, char *data);
static char *ssh2_mpint_fmt(Bignum b, int *len);
static unsigned char *ssh2_mpint_fmt(Bignum b, int *len);
static void ssh2_pkt_addmp(Ssh, Bignum b);
static int ssh2_pkt_construct(Ssh);
static void ssh2_pkt_send(Ssh);

/*
 * Buffer management constants. There are several of these for
 * various different purposes:
1212
1213
1214
1215
1216
1217
1218
1219

1220
1221
1222
1223
1224
1225
1226
1212
1213
1214
1215
1216
1217
1218

1219
1220
1221
1222
1223
1224
1225
1226







-
+







    return biglen + 4;
}

static void s_wrpkt(Ssh ssh)
{
    int len, backlog;
    len = s_wrpkt_prepare(ssh);
    backlog = sk_write(ssh->s, ssh->pktout.data, len);
    backlog = sk_write(ssh->s, (char *)ssh->pktout.data, len);
    if (backlog > SSH_MAX_BACKLOG)
	ssh_throttle_all(ssh, 1, backlog);
}

static void s_wrpkt_defer(Ssh ssh)
{
    int len;
1258
1259
1260
1261
1262
1263
1264
1265

1266
1267
1268
1269
1270
1271
1272
1258
1259
1260
1261
1262
1263
1264

1265
1266
1267
1268
1269
1270
1271
1272







-
+







	  case PKT_DATA:
	    (void) va_arg(ap1, unsigned char *);
	    arglen = va_arg(ap1, int);
	    pktlen += arglen;
	    break;
	  case PKT_STR:
	    argp = va_arg(ap1, unsigned char *);
	    arglen = strlen(argp);
	    arglen = strlen((char *)argp);
	    pktlen += 4 + arglen;
	    break;
	  case PKT_BIGNUM:
	    bn = va_arg(ap1, Bignum);
	    pktlen += ssh1_bignum_length(bn);
	    break;
	  default:
1293
1294
1295
1296
1297
1298
1299
1300

1301
1302
1303
1304
1305
1306
1307
1293
1294
1295
1296
1297
1298
1299

1300
1301
1302
1303
1304
1305
1306
1307







-
+







	    argp = va_arg(ap2, unsigned char *);
	    arglen = va_arg(ap2, int);
	    memcpy(p, argp, arglen);
	    p += arglen;
	    break;
	  case PKT_STR:
	    argp = va_arg(ap2, unsigned char *);
	    arglen = strlen(argp);
	    arglen = strlen((char *)argp);
	    PUT_32BIT(p, arglen);
	    memcpy(p + 4, argp, arglen);
	    p += 4 + arglen;
	    break;
	  case PKT_BIGNUM:
	    bn = va_arg(ap2, Bignum);
	    p += ssh1_write_bignum(p, bn);
1424
1425
1426
1427
1428
1429
1430
1431

1432
1433
1434
1435
1436
1437
1438
1424
1425
1426
1427
1428
1429
1430

1431
1432
1433
1434
1435
1436
1437
1438







-
+







	      ssh->pktout.length - ssh->pktout.savedpos);
}
static void ssh2_pkt_addstring(Ssh ssh, char *data)
{
    ssh2_pkt_addstring_start(ssh);
    ssh2_pkt_addstring_str(ssh, data);
}
static char *ssh2_mpint_fmt(Bignum b, int *len)
static unsigned char *ssh2_mpint_fmt(Bignum b, int *len)
{
    unsigned char *p;
    int i, n = (bignum_bitcount(b) + 7) / 8;
    p = smalloc(n + 1);
    if (!p)
	fatalbox("out of memory");
    p[0] = 0;
1447
1448
1449
1450
1451
1452
1453
1454

1455
1456
1457
1458
1459
1460
1461
1447
1448
1449
1450
1451
1452
1453

1454
1455
1456
1457
1458
1459
1460
1461







-
+







}
static void ssh2_pkt_addmp(Ssh ssh, Bignum b)
{
    unsigned char *p;
    int len;
    p = ssh2_mpint_fmt(b, &len);
    ssh2_pkt_addstring_start(ssh);
    ssh2_pkt_addstring_data(ssh, p, len);
    ssh2_pkt_addstring_data(ssh, (char *)p, len);
    sfree(p);
}

/*
 * Construct an SSH2 final-form packet: compress it, encrypt it,
 * put the MAC on it. Final packet, ready to be sent, is stored in
 * ssh->pktout.data. Total length is returned.
1518
1519
1520
1521
1522
1523
1524
1525

1526
1527
1528
1529
1530
1531
1532
1518
1519
1520
1521
1522
1523
1524

1525
1526
1527
1528
1529
1530
1531
1532







-
+







 * Construct and send an SSH2 packet immediately.
 */
static void ssh2_pkt_send(Ssh ssh)
{
    int len;
    int backlog;
    len = ssh2_pkt_construct(ssh);
    backlog = sk_write(ssh->s, ssh->pktout.data, len);
    backlog = sk_write(ssh->s, (char *)ssh->pktout.data, len);
    if (backlog > SSH_MAX_BACKLOG)
	ssh_throttle_all(ssh, 1, backlog);
}

/*
 * Construct an SSH2 packet and add it to a deferred data block.
 * Useful for sending multiple packets in a single sk_write() call,
1553
1554
1555
1556
1557
1558
1559

1560

1561
1562
1563
1564
1565
1566
1567
1553
1554
1555
1556
1557
1558
1559
1560

1561
1562
1563
1564
1565
1566
1567
1568







+
-
+







/*
 * Send the whole deferred data block constructed by
 * ssh2_pkt_defer() or SSH1's defer_packet().
 */
static void ssh_pkt_defersend(Ssh ssh)
{
    int backlog;
    backlog = sk_write(ssh->s, (char *)ssh->deferred_send_data,
    backlog = sk_write(ssh->s, ssh->deferred_send_data, ssh->deferred_len);
		       ssh->deferred_len);
    ssh->deferred_len = ssh->deferred_size = 0;
    sfree(ssh->deferred_send_data);
    ssh->deferred_send_data = NULL;
    if (backlog > SSH_MAX_BACKLOG)
	ssh_throttle_all(ssh, 1, backlog);
}

1619
1620
1621
1622
1623
1624
1625
1626

1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642

1643
1644
1645
1646
1647
1648
1649
1620
1621
1622
1623
1624
1625
1626

1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642

1643
1644
1645
1646
1647
1648
1649
1650







-
+















-
+







    len = GET_32BIT(ssh->pktin.data + ssh->pktin.savedpos);
    if (len < 0)
	return;
    *length = len;
    ssh->pktin.savedpos += 4;
    if (ssh->pktin.length - ssh->pktin.savedpos < *length)
	return;
    *p = ssh->pktin.data + ssh->pktin.savedpos;
    *p = (char *)(ssh->pktin.data + ssh->pktin.savedpos);
    ssh->pktin.savedpos += *length;
}
static Bignum ssh2_pkt_getmp(Ssh ssh)
{
    char *p;
    int length;
    Bignum b;

    ssh2_pkt_getstring(ssh, &p, &length);
    if (!p)
	return NULL;
    if (p[0] & 0x80) {
	bombout((ssh,"internal error: Can't handle negative mpints"));
	return NULL;
    }
    b = bignum_from_bytes(p, length);
    b = bignum_from_bytes((unsigned char *)p, length);
    return b;
}

/*
 * Helper function to add an SSH2 signature blob to a packet.
 * Expects to be shown the public key blob as well as the signature
 * blob. Normally works just like ssh2_pkt_addstring, but will
1685
1686
1687
1688
1689
1690
1691
1692

1693
1694
1695
1696

1697
1698
1699
1700

1701
1702
1703

1704
1705
1706
1707
1708
1709
1710
1711
1712

1713
1714
1715
1716
1717
1718
1719
1686
1687
1688
1689
1690
1691
1692

1693
1694
1695
1696

1697
1698
1699
1700

1701
1702
1703

1704
1705
1706
1707
1708
1709
1710
1711
1712

1713
1714
1715
1716
1717
1718
1719
1720







-
+



-
+



-
+


-
+








-
+







	pos = 4+7;		       /* skip over "ssh-rsa" */
	siglen = GET_32BIT(sigblob+pos);
	/* debug(("signature length is %d\n", siglen)); */

	if (len != siglen) {
	    unsigned char newlen[4];
	    ssh2_pkt_addstring_start(ssh);
	    ssh2_pkt_addstring_data(ssh, sigblob, pos);
	    ssh2_pkt_addstring_data(ssh, (char *)sigblob, pos);
	    /* dmemdump(sigblob, pos); */
	    pos += 4;		       /* point to start of actual sig */
	    PUT_32BIT(newlen, len);
	    ssh2_pkt_addstring_data(ssh, newlen, 4);
	    ssh2_pkt_addstring_data(ssh, (char *)newlen, 4);
	    /* dmemdump(newlen, 4); */
	    newlen[0] = 0;
	    while (len-- > siglen) {
		ssh2_pkt_addstring_data(ssh, newlen, 1);
		ssh2_pkt_addstring_data(ssh, (char *)newlen, 1);
		/* dmemdump(newlen, 1); */
	    }
	    ssh2_pkt_addstring_data(ssh, sigblob+pos, siglen);
	    ssh2_pkt_addstring_data(ssh, (char *)(sigblob+pos), siglen);
	    /* dmemdump(sigblob+pos, siglen); */
	    return;
	}

	/* Otherwise fall through and do it the easy way. */
    }

    ssh2_pkt_addstring_start(ssh);
    ssh2_pkt_addstring_data(ssh, sigblob, sigblob_len);
    ssh2_pkt_addstring_data(ssh, (char *)sigblob, sigblob_len);
}

/*
 * Examine the remote side's version string and compare it against
 * a list of known buggy implementations.
 */
static void ssh_detect_bugs(Ssh ssh, char *vstring)
2005
2006
2007
2008
2009
2010
2011
2012

2013
2014
2015
2016
2017
2018
2019
2006
2007
2008
2009
2010
2011
2012

2013
2014
2015
2016
2017
2018
2019
2020







-
+







    }
    return 0;
}

static int ssh_receive(Plug plug, int urgent, char *data, int len)
{
    Ssh ssh = (Ssh) plug;
    ssh_gotdata(ssh, data, len);
    ssh_gotdata(ssh, (unsigned char *)data, len);
    if (ssh->state == SSH_STATE_CLOSED) {
	if (ssh->s) {
	    sk_close(ssh->s);
	    ssh->s = NULL;
	}
	return 0;
    }
2512
2513
2514
2515
2516
2517
2518
2519

2520
2521
2522
2523
2524
2525
2526
2513
2514
2515
2516
2517
2518
2519

2520
2521
2522
2523
2524
2525
2526
2527







-
+







			s->tried_publickey = 1;
		    }
		    s->p += 4;
		    s->p += ssh1_read_bignum(s->p, &s->key.exponent);
		    s->p += ssh1_read_bignum(s->p, &s->key.modulus);
		    s->commentlen = GET_32BIT(s->p);
		    s->p += 4;
		    s->commentp = s->p;
		    s->commentp = (char *)s->p;
		    s->p += s->commentlen;
		    send_packet(ssh, SSH1_CMSG_AUTH_RSA,
				PKT_BIGNUM, s->key.modulus, PKT_END);
		    crWaitUntil(ispkt);
		    if (ssh->pktin.type != SSH1_SMSG_AUTH_RSA_CHALLENGE) {
			logevent("Key refused");
			continue;
3263
3264
3265
3266
3267
3268
3269
3270

3271
3272
3273
3274
3275
3276
3277
3264
3265
3266
3267
3268
3269
3270

3271
3272
3273
3274
3275
3276
3277
3278







-
+







	if (ispkt) {
	    if (ssh->pktin.type == SSH1_SMSG_STDOUT_DATA ||
		ssh->pktin.type == SSH1_SMSG_STDERR_DATA) {
		long len = GET_32BIT(ssh->pktin.body);
		int bufsize =
		    from_backend(ssh->frontend,
				 ssh->pktin.type == SSH1_SMSG_STDERR_DATA,
				 ssh->pktin.body + 4, len);
				 (char *)(ssh->pktin.body) + 4, len);
		if (!ssh->v1_stdout_throttling && bufsize > SSH1_BUFFER_LIMIT) {
		    ssh->v1_stdout_throttling = 1;
		    ssh1_throttle(ssh, +1);
		}
	    } else if (ssh->pktin.type == SSH1_MSG_DISCONNECT) {
		ssh->state = SSH_STATE_CLOSED;
		logevent("Received disconnect request");
3344
3345
3346
3347
3348
3349
3350

3351

3352
3353
3354
3355
3356
3357
3358
3345
3346
3347
3348
3349
3350
3351
3352

3353
3354
3355
3356
3357
3358
3359
3360







+
-
+







		int hostsize, port;
		char host[256], buf[1024];
		char *p, *h, *e;
		c = smalloc(sizeof(struct ssh_channel));
		c->ssh = ssh;

		hostsize = GET_32BIT(ssh->pktin.body+4);
		for (h = host, p = (char *)(ssh->pktin.body+8);
		for(h = host, p = ssh->pktin.body+8; hostsize != 0; hostsize--) {
		     hostsize != 0; hostsize--) {
		    if (h+1 < host+sizeof(host))
			*h++ = *p;
		    p++;
		}
		*h = 0;
		port = GET_32BIT(p);

3476
3477
3478
3479
3480
3481
3482
3483

3484
3485
3486

3487
3488
3489
3490
3491
3492
3493
3478
3479
3480
3481
3482
3483
3484

3485
3486
3487

3488
3489
3490
3491
3492
3493
3494
3495







-
+


-
+







		unsigned char *p = ssh->pktin.body + 8;
		struct ssh_channel *c;
		c = find234(ssh->channels, &i, ssh_channelfind);
		if (c) {
		    int bufsize;
		    switch (c->type) {
		      case CHAN_X11:
			bufsize = x11_send(c->u.x11.s, p, len);
			bufsize = x11_send(c->u.x11.s, (char *)p, len);
			break;
		      case CHAN_SOCKDATA:
			bufsize = pfd_send(c->u.pfd.s, p, len);
			bufsize = pfd_send(c->u.pfd.s, (char *)p, len);
			break;
		      case CHAN_AGENT:
			/* Data for an agent message. Buffer it. */
			while (len > 0) {
			    if (c->u.a.lensofar < 4) {
				int l = min(4 - c->u.a.lensofar, len);
				memcpy(c->u.a.msglen + c->u.a.lensofar, p,
3613
3614
3615
3616
3617
3618
3619
3620
3621



3622
3623
3624
3625
3626
3627
3628
3615
3616
3617
3618
3619
3620
3621


3622
3623
3624
3625
3626
3627
3628
3629
3630
3631







-
-
+
+
+







	haylen--, haystack++;	       /* skip over comma itself */
    }
}

/*
 * SSH2 key creation method.
 */
static void ssh2_mkkey(Ssh ssh, Bignum K, char *H, char *sessid, char chr,
		       char *keyspace)
static void ssh2_mkkey(Ssh ssh, Bignum K, unsigned char *H,
		       unsigned char *sessid, char chr,
		       unsigned char *keyspace)
{
    SHA_State s;
    /* First 20 bytes. */
    SHA_Init(&s);
    if (!(ssh->remote_bugs & BUG_SSH2_DERIVEKEY))
	sha_mpint(&s, K);
    SHA_Bytes(&s, H, 20);
4040
4041
4042
4043
4044
4045
4046
4047

4048
4049
4050
4051
4052
4053
4054
4043
4044
4045
4046
4047
4048
4049

4050
4051
4052
4053
4054
4055
4056
4057







-
+







    debug(("Exchange hash is:\n"));
    dmemdump(s->exchange_hash, 20);
#endif

    s->hkey = ssh->hostkey->newkey(s->hostkeydata, s->hostkeylen);
    if (!s->hkey ||
	!ssh->hostkey->verifysig(s->hkey, s->sigdata, s->siglen,
				 s->exchange_hash, 20)) {
				 (char *)s->exchange_hash, 20)) {
	bombout((ssh,"Server's host key did not match the signature supplied"));
	crReturn(0);
    }

    /*
     * Authenticate remote host: verify host key. (We've already
     * checked the signature of the exchange hash.)
4578
4579
4580
4581
4582
4583
4584
4585

4586
4587
4588
4589
4590
4591

4592
4593
4594
4595
4596
4597
4598
4581
4582
4583
4584
4585
4586
4587

4588
4589
4590
4591
4592
4593

4594
4595
4596
4597
4598
4599
4600
4601







-
+





-
+







			if (s->publickey_blob &&
			    s->pklen == s->publickey_bloblen &&
			    !memcmp(s->p, s->publickey_blob,
				    s->publickey_bloblen)) {
			    logevent("This key matches configured key file");
			    s->tried_pubkey_config = 1;
			}
			s->pkblob = s->p;
			s->pkblob = (char *)s->p;
			s->p += s->pklen;
			s->alglen = GET_32BIT(s->pkblob);
			s->alg = s->pkblob + 4;
			s->commentlen = GET_32BIT(s->p);
			s->p += 4;
			s->commentp = s->p;
			s->commentp = (char *)s->p;
			s->p += s->commentlen;
			ssh2_pkt_init(ssh, SSH2_MSG_USERAUTH_REQUEST);
			ssh2_pkt_addstring(ssh, s->username);
			ssh2_pkt_addstring(ssh, "ssh-connection");	/* service requested */
			ssh2_pkt_addstring(ssh, "publickey");	/* method */
			ssh2_pkt_addbool(ssh, FALSE);	/* no signature included */
			ssh2_pkt_addstring_start(ssh);
4690
4691
4692
4693
4694
4695
4696

4697
4698



4699
4700
4701
4702
4703
4704
4705
4706
4707


4708
4709
4710
4711
4712
4713
4714
4693
4694
4695
4696
4697
4698
4699
4700


4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711

4712
4713
4714
4715
4716
4717
4718
4719
4720







+
-
-
+
+
+








-
+
+








		/*
		 * Try the public key supplied in the configuration.
		 *
		 * First, offer the public blob to see if the server is
		 * willing to accept it.
		 */
		pub_blob =
		pub_blob = ssh2_userkey_loadpub(cfg.keyfile, &algorithm,
						&pub_blob_len);
		    (unsigned char *)ssh2_userkey_loadpub(cfg.keyfile,
							  &algorithm,
							  &pub_blob_len);
		if (pub_blob) {
		    ssh2_pkt_init(ssh, SSH2_MSG_USERAUTH_REQUEST);
		    ssh2_pkt_addstring(ssh, s->username);
		    ssh2_pkt_addstring(ssh, "ssh-connection");	/* service requested */
		    ssh2_pkt_addstring(ssh, "publickey");	/* method */
		    ssh2_pkt_addbool(ssh, FALSE);	/* no signature included */
		    ssh2_pkt_addstring(ssh, algorithm);
		    ssh2_pkt_addstring_start(ssh);
		    ssh2_pkt_addstring_data(ssh, pub_blob, pub_blob_len);
		    ssh2_pkt_addstring_data(ssh, (char *)pub_blob,
					    pub_blob_len);
		    ssh2_pkt_send(ssh);
		    logevent("Offered public key");	/* FIXME */

		    crWaitUntilV(ispkt);
		    if (ssh->pktin.type != SSH2_MSG_USERAUTH_PK_OK) {
			s->gotit = TRUE;
			s->type = AUTH_TYPE_PUBLICKEY_OFFER_LOUD;
4901
4902
4903
4904
4905
4906
4907
4908

4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924

4925
4926
4927
4928
4929
4930
4931
4907
4908
4909
4910
4911
4912
4913

4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929

4930
4931
4932
4933
4934
4935
4936
4937







-
+















-
+







		    ssh2_pkt_addstring(ssh, s->username);
		    ssh2_pkt_addstring(ssh, "ssh-connection");	/* service requested */
		    ssh2_pkt_addstring(ssh, "publickey");	/* method */
		    ssh2_pkt_addbool(ssh, TRUE);
		    ssh2_pkt_addstring(ssh, key->alg->name);
		    pkblob = key->alg->public_blob(key->data, &pkblob_len);
		    ssh2_pkt_addstring_start(ssh);
		    ssh2_pkt_addstring_data(ssh, pkblob, pkblob_len);
		    ssh2_pkt_addstring_data(ssh, (char *)pkblob, pkblob_len);

		    /*
		     * The data to be signed is:
		     *
		     *   string  session-id
		     *
		     * followed by everything so far placed in the
		     * outgoing packet.
		     */
		    sigdata_len = ssh->pktout.length - 5 + 4 + 20;
		    sigdata = smalloc(sigdata_len);
		    PUT_32BIT(sigdata, 20);
		    memcpy(sigdata + 4, ssh->v2_session_id, 20);
		    memcpy(sigdata + 24, ssh->pktout.data + 5,
			   ssh->pktout.length - 5);
		    sigblob = key->alg->sign(key->data, sigdata,
		    sigblob = key->alg->sign(key->data, (char *)sigdata,
					     sigdata_len, &sigblob_len);
		    ssh2_add_sigblob(ssh, pkblob, pkblob_len,
				     sigblob, sigblob_len);
		    sfree(pkblob);
		    sfree(sigblob);
		    sfree(sigdata);

5805
5806
5807
5808
5809
5810
5811
5812

5813
5814
5815
5816
5817
5818
5819
5811
5812
5813
5814
5815
5816
5817

5818
5819
5820
5821
5822
5823
5824
5825







-
+







		bombout((ssh,"Strange packet received: type %d", ssh->pktin.type));
		crReturnV;
	    }
	} else {
	    /*
	     * We have spare data. Add it to the channel buffer.
	     */
	    ssh2_add_channel_data(ssh->mainchan, in, inlen);
	    ssh2_add_channel_data(ssh->mainchan, (char *)in, inlen);
	    s->try_send = TRUE;
	}
	if (s->try_send) {
	    int i;
	    struct ssh_channel *c;
	    /*
	     * Try to send data on all channels if we can.
5950
5951
5952
5953
5954
5955
5956
5957

5958
5959
5960
5961
5962
5963
5964
5956
5957
5958
5959
5960
5961
5962

5963
5964
5965
5966
5967
5968
5969
5970







-
+







static int ssh_send(void *handle, char *buf, int len)
{
    Ssh ssh = (Ssh) handle;

    if (ssh == NULL || ssh->s == NULL || ssh->protocol == NULL)
	return 0;

    ssh->protocol(ssh, buf, len, 0);
    ssh->protocol(ssh, (unsigned char *)buf, len, 0);

    return ssh_sendbuffer(ssh);
}

/*
 * Called to query the current amount of buffered stdin data.
 */