Diff

Differences From Artifact [2252139a27]:

To Artifact [1a7301e6c1]:


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 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:







|







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 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
    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);
    if (backlog > SSH_MAX_BACKLOG)
	ssh_throttle_all(ssh, 1, backlog);
}

static void s_wrpkt_defer(Ssh ssh)
{
    int len;







|







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, (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
	  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);
	    pktlen += 4 + arglen;
	    break;
	  case PKT_BIGNUM:
	    bn = va_arg(ap1, Bignum);
	    pktlen += ssh1_bignum_length(bn);
	    break;
	  default:







|







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((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
	    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);
	    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);







|







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((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
	      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)
{
    unsigned char *p;
    int i, n = (bignum_bitcount(b) + 7) / 8;
    p = smalloc(n + 1);
    if (!p)
	fatalbox("out of memory");
    p[0] = 0;







|







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 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
}
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);
    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.







|







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, (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
 * 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);
    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,







|







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, (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
/*
 * 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, ssh->deferred_send_data, 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);
}








>
|







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,
		       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
    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;
    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);
    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







|















|







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 = (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((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
	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);
	    /* dmemdump(sigblob, pos); */
	    pos += 4;		       /* point to start of actual sig */
	    PUT_32BIT(newlen, len);
	    ssh2_pkt_addstring_data(ssh, newlen, 4);
	    /* dmemdump(newlen, 4); */
	    newlen[0] = 0;
	    while (len-- > siglen) {
		ssh2_pkt_addstring_data(ssh, newlen, 1);
		/* dmemdump(newlen, 1); */
	    }
	    ssh2_pkt_addstring_data(ssh, 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);
}

/*
 * 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)







|



|



|


|








|







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, (char *)sigblob, pos);
	    /* dmemdump(sigblob, pos); */
	    pos += 4;		       /* point to start of actual sig */
	    PUT_32BIT(newlen, len);
	    ssh2_pkt_addstring_data(ssh, (char *)newlen, 4);
	    /* dmemdump(newlen, 4); */
	    newlen[0] = 0;
	    while (len-- > siglen) {
		ssh2_pkt_addstring_data(ssh, (char *)newlen, 1);
		/* dmemdump(newlen, 1); */
	    }
	    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, (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
    }
    return 0;
}

static int ssh_receive(Plug plug, int urgent, char *data, int len)
{
    Ssh ssh = (Ssh) plug;
    ssh_gotdata(ssh, data, len);
    if (ssh->state == SSH_STATE_CLOSED) {
	if (ssh->s) {
	    sk_close(ssh->s);
	    ssh->s = NULL;
	}
	return 0;
    }







|







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, (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
			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->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;







|







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 = (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
	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);
		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");







|







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,
				 (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
		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 = ssh->pktin.body+8; hostsize != 0; hostsize--) {
		    if (h+1 < host+sizeof(host))
			*h++ = *p;
		    p++;
		}
		*h = 0;
		port = GET_32BIT(p);








>
|







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);
		     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
		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);
			break;
		      case CHAN_SOCKDATA:
			bufsize = pfd_send(c->u.pfd.s, 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,







|


|







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, (char *)p, len);
			break;
		      case CHAN_SOCKDATA:
			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
	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)
{
    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);







|
>
|







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, 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
    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)) {
	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.)







|







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,
				 (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
			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->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->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);







|





|







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 = (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 = (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

		/*
		 * 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 = 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_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;







>
|
>
|








|
>







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 =
		    (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, (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
		    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);

		    /*
		     * 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,
					     sigdata_len, &sigblob_len);
		    ssh2_add_sigblob(ssh, pkblob, pkblob_len,
				     sigblob, sigblob_len);
		    sfree(pkblob);
		    sfree(sigblob);
		    sfree(sigdata);








|















|







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, (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, (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
		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);
	    s->try_send = TRUE;
	}
	if (s->try_send) {
	    int i;
	    struct ssh_channel *c;
	    /*
	     * Try to send data on all channels if we can.







|







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, (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
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);

    return ssh_sendbuffer(ssh);
}

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







|







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, (unsigned char *)buf, len, 0);

    return ssh_sendbuffer(ssh);
}

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