Diff

Differences From Artifact [5b84068c1d]:

To Artifact [95e6596d0f]:


351
352
353
354
355
356
357
358
359


360
361
362
363
364
365
366
351
352
353
354
355
356
357


358
359
360
361
362
363
364
365
366







-
-
+
+








    st->pad = 8 - (st->len % 8);
    st->biglen = st->len + st->pad;
    pktin.length = st->len - 5;

    if (pktin.maxlen < st->biglen) {
	pktin.maxlen = st->biglen;
	pktin.data = (pktin.data == NULL ? malloc(st->biglen+APIEXTRA) :
	              realloc(pktin.data, st->biglen+APIEXTRA));
	pktin.data = (pktin.data == NULL ? smalloc(st->biglen+APIEXTRA) :
	              srealloc(pktin.data, st->biglen+APIEXTRA));
	if (!pktin.data)
	    fatalbox("Out of memory");
    }

    st->to_read = st->biglen;
    st->p = pktin.data;
    while (st->to_read > 0) {
405
406
407
408
409
410
411
412

413
414
415
416
417
418

419
420
421
422
423
424
425
405
406
407
408
409
410
411

412
413
414
415
416
417

418
419
420
421
422
423
424
425







-
+





-
+







	debug(("\r\n"));
#endif
	zlib_decompress_block(pktin.body-1, pktin.length+1,
			      &decompblk, &decomplen);

	if (pktin.maxlen < st->pad + decomplen) {
	    pktin.maxlen = st->pad + decomplen;
	    pktin.data = realloc(pktin.data, pktin.maxlen+APIEXTRA);
	    pktin.data = srealloc(pktin.data, pktin.maxlen+APIEXTRA);
	    if (!pktin.data)
		fatalbox("Out of memory");
	}

	memcpy(pktin.body-1, decompblk, decomplen);
	free(decompblk);
	sfree(decompblk);
	pktin.length = decomplen-1;
#if 0
	debug(("Packet payload post-decompression:\n"));
	for (i = -1; i < pktin.length; i++)
	    debug(("  %02x", (unsigned char)pktin.body[i]));
	debug(("\r\n"));
#endif
471
472
473
474
475
476
477
478
479


480
481
482
483
484
485
486
471
472
473
474
475
476
477


478
479
480
481
482
483
484
485
486







-
-
+
+







    else
        st->cipherblk = 8;
    if (st->cipherblk < 8)
        st->cipherblk = 8;

    if (pktin.maxlen < st->cipherblk) {
	pktin.maxlen = st->cipherblk;
	pktin.data = (pktin.data == NULL ? malloc(st->cipherblk+APIEXTRA) :
	              realloc(pktin.data, st->cipherblk+APIEXTRA));
	pktin.data = (pktin.data == NULL ? smalloc(st->cipherblk+APIEXTRA) :
	              srealloc(pktin.data, st->cipherblk+APIEXTRA));
	if (!pktin.data)
	    fatalbox("Out of memory");
    }

    /*
     * Acquire and decrypt the first block of the packet. This will
     * contain the length and padding details.
519
520
521
522
523
524
525
526
527


528
529
530
531
532
533
534
519
520
521
522
523
524
525


526
527
528
529
530
531
532
533
534







-
-
+
+







    st->maclen = scmac ? scmac->len : 0;

    /*
     * Adjust memory allocation if packet is too big.
     */
    if (pktin.maxlen < st->packetlen+st->maclen) {
	pktin.maxlen = st->packetlen+st->maclen;
	pktin.data = (pktin.data == NULL ? malloc(pktin.maxlen+APIEXTRA) :
	              realloc(pktin.data, pktin.maxlen+APIEXTRA));
	pktin.data = (pktin.data == NULL ? smalloc(pktin.maxlen+APIEXTRA) :
	              srealloc(pktin.data, pktin.maxlen+APIEXTRA));
	if (!pktin.data)
	    fatalbox("Out of memory");
    }

    /*
     * Read and decrypt the remainder of the packet.
     */
565
566
567
568
569
570
571
572
573


574
575
576
577
578
579
580
581
582
583
584
585
586

587
588
589
590
591
592
593
565
566
567
568
569
570
571


572
573
574
575
576
577
578
579
580
581
582
583
584
585

586
587
588
589
590
591
592
593







-
-
+
+












-
+







    {
	unsigned char *newpayload;
	int newlen;
	if (sccomp && sccomp->decompress(pktin.data+5, pktin.length-5,
					 &newpayload, &newlen)) {
	    if (pktin.maxlen < newlen+5) {
		pktin.maxlen = newlen+5;
		pktin.data = (pktin.data == NULL ? malloc(pktin.maxlen+APIEXTRA) :
			      realloc(pktin.data, pktin.maxlen+APIEXTRA));
		pktin.data = (pktin.data == NULL ? smalloc(pktin.maxlen+APIEXTRA) :
			      srealloc(pktin.data, pktin.maxlen+APIEXTRA));
		if (!pktin.data)
		    fatalbox("Out of memory");
	    }
	    pktin.length = 5 + newlen;
	    memcpy(pktin.data+5, newpayload, newlen);
#if 0
	    debug(("Post-decompression payload:\r\n"));
	    for (st->i = 0; st->i < newlen; st->i++)
		debug(("  %02x", (unsigned char)pktin.data[5+st->i]));
	    debug(("\r\n"));
#endif

	    free(newpayload);
	    sfree(newpayload);
	}
    }

    pktin.savedpos = 6;
    pktin.type = pktin.data[5];

    if (pktin.type == SSH2_MSG_IGNORE || pktin.type == SSH2_MSG_DEBUG)
605
606
607
608
609
610
611
612
613


614
615
616


617
618
619
620
621
622
623
605
606
607
608
609
610
611


612
613
614


615
616
617
618
619
620
621
622
623







-
-
+
+

-
-
+
+








    pktout.length = len-5;
    if (pktout.maxlen < biglen) {
	pktout.maxlen = biglen;
#ifdef MSCRYPTOAPI
	/* Allocate enough buffer space for extra block
	 * for MS CryptEncrypt() */
	pktout.data = (pktout.data == NULL ? malloc(biglen+12) :
		       realloc(pktout.data, biglen+12));
	pktout.data = (pktout.data == NULL ? smalloc(biglen+12) :
		       srealloc(pktout.data, biglen+12));
#else
	pktout.data = (pktout.data == NULL ? malloc(biglen+4) :
		       realloc(pktout.data, biglen+4));
	pktout.data = (pktout.data == NULL ? smalloc(biglen+4) :
		       srealloc(pktout.data, biglen+4));
#endif
	if (!pktout.data)
	    fatalbox("Out of memory");
    }
    pktout.body = pktout.data+4+pad+1;
}

641
642
643
644
645
646
647
648

649
650
651
652
653
654
655
641
642
643
644
645
646
647

648
649
650
651
652
653
654
655







-
+







	    debug(("  %02x", (unsigned char)pktout.body[i]));
	debug(("\r\n"));
#endif
	zlib_compress_block(pktout.body-1, pktout.length+1,
			    &compblk, &complen);
	ssh1_pktout_size(complen-1);
	memcpy(pktout.body-1, compblk, complen);
	free(compblk);
	sfree(compblk);
#if 0
	debug(("Packet payload post-compression:\n"));
	for (i = -1; i < pktout.length; i++)
	    debug(("  %02x", (unsigned char)pktout.body[i]));
	debug(("\r\n"));
#endif
    }
791
792
793
794
795
796
797
798
799


800
801
802
803
804
805
806
791
792
793
794
795
796
797


798
799
800
801
802
803
804
805
806







-
-
+
+







/*
 * SSH2 packet construction functions.
 */
static void ssh2_pkt_adddata(void *data, int len) {
    pktout.length += len;
    if (pktout.maxlen < pktout.length) {
        pktout.maxlen = pktout.length + 256;
	pktout.data = (pktout.data == NULL ? malloc(pktout.maxlen+APIEXTRA) :
                       realloc(pktout.data, pktout.maxlen+APIEXTRA));
	pktout.data = (pktout.data == NULL ? smalloc(pktout.maxlen+APIEXTRA) :
                       srealloc(pktout.data, pktout.maxlen+APIEXTRA));
        if (!pktout.data)
            fatalbox("Out of memory");
    }
    memcpy(pktout.data+pktout.length-len, data, len);
}
static void ssh2_pkt_addbyte(unsigned char byte) {
    ssh2_pkt_adddata(&byte, 1);
834
835
836
837
838
839
840
841

842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862

863
864
865
866
867
868
869
834
835
836
837
838
839
840

841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861

862
863
864
865
866
867
868
869







-
+




















-
+







static void ssh2_pkt_addstring(char *data) {
    ssh2_pkt_addstring_start();
    ssh2_pkt_addstring_str(data);
}
static char *ssh2_mpint_fmt(Bignum b, int *len) {
    unsigned char *p;
    int i, n = b[0];
    p = malloc(n * 2 + 1);
    p = smalloc(n * 2 + 1);
    if (!p)
        fatalbox("out of memory");
    p[0] = 0;
    for (i = 0; i < n; i++) {
        p[i*2+1] = (b[n-i] >> 8) & 0xFF;
        p[i*2+2] = (b[n-i]     ) & 0xFF;
    }
    i = 0;
    while (p[i] == 0 && (p[i+1] & 0x80) == 0)
        i++;
    memmove(p, p+i, n*2+1-i);
    *len = n*2+1-i;
    return p;
}
static void ssh2_pkt_addmp(Bignum b) {
    unsigned char *p;
    int len;
    p = ssh2_mpint_fmt(b, &len);
    ssh2_pkt_addstring_start();
    ssh2_pkt_addstring_data(p, len);
    free(p);
    sfree(p);
}
static void ssh2_pkt_send(void) {
    int cipherblk, maclen, padding, i;
    static unsigned long outgoing_sequence = 0;

    /*
     * Compress packet payload.
877
878
879
880
881
882
883
884

885
886
887
888
889
890
891
877
878
879
880
881
882
883

884
885
886
887
888
889
890
891







-
+







    {
	unsigned char *newpayload;
	int newlen;
	if (cscomp && cscomp->compress(pktout.data+5, pktout.length-5,
				       &newpayload, &newlen)) {
	    pktout.length = 5;
	    ssh2_pkt_adddata(newpayload, newlen);
	    free(newpayload);
	    sfree(newpayload);
	}
    }

    /*
     * Add padding. At least four bytes, and must also bring total
     * length (minus MAC) up to a multiple of the block size.
     */
921
922
923
924
925
926
927
928

929
930
931
932
933
934
935
936
937

938
939
940
941
942
943
944
921
922
923
924
925
926
927

928
929
930
931
932
933
934
935
936

937
938
939
940
941
942
943
944







-
+








-
+







    unsigned char *p;
    int i, len;
    p = ssh2_mpint_fmt(b, &len);
    debug(("%s", string));
    for (i = 0; i < len; i++)
        debug((" %02x", p[i]));
    debug(("\r\n"));
    free(p);
    sfree(p);
}
#endif

static void sha_mpint(SHA_State *s, Bignum b) {
    unsigned char *p;
    int len;
    p = ssh2_mpint_fmt(b, &len);
    sha_string(s, p, len);
    free(p);
    sfree(p);
}

/*
 * SSH2 packet decode functions.
 */
static unsigned long ssh2_pkt_getuint32(void) {
    unsigned long value;
1145
1146
1147
1148
1149
1150
1151
1152

1153
1154
1155
1156
1157
1158
1159
1145
1146
1147
1148
1149
1150
1151

1152
1153
1154
1155
1156
1157
1158
1159







-
+







    SockAddr addr;
    char *err;
#ifdef FWHACK
    char *FWhost;
    int FWport;
#endif

    savedhost = malloc(1+strlen(host));
    savedhost = smalloc(1+strlen(host));
    if (!savedhost)
	fatalbox("Out of memory");
    strcpy(savedhost, host);

    if (port < 0)
	port = 22;		       /* default ssh port */
    savedport = port;
1251
1252
1253
1254
1255
1256
1257
1258

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

1272
1273
1274
1275
1276
1277

1278
1279
1280
1281
1282
1283
1284
1251
1252
1253
1254
1255
1256
1257

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

1271
1272
1273
1274
1275
1276

1277
1278
1279
1280
1281
1282
1283
1284







-
+












-
+





-
+







    MD5Final(session_id, &md5c);

    for (i=0; i<32; i++)
	session_key[i] = random_byte();

    len = (hostkey.bytes > servkey.bytes ? hostkey.bytes : servkey.bytes);

    rsabuf = malloc(len);
    rsabuf = smalloc(len);
    if (!rsabuf)
	fatalbox("Out of memory");

    /*
     * Verify the host key.
     */
    {
        /*
         * First format the key into a string.
         */
        int len = rsastr_len(&hostkey);
        char fingerprint[100];
        char *keystr = malloc(len);
        char *keystr = smalloc(len);
        if (!keystr)
            fatalbox("Out of memory");
        rsastr_fmt(keystr, &hostkey);
        rsa_fingerprint(fingerprint, sizeof(fingerprint), &hostkey);
        verify_ssh_host_key(savedhost, savedport, "rsa", keystr, fingerprint);
        free(keystr);
        sfree(keystr);
    }

    for (i=0; i<32; i++) {
	rsabuf[i] = session_key[i];
	if (i < 16)
	    rsabuf[i] ^= session_id[i];
    }
1312
1313
1314
1315
1316
1317
1318
1319

1320
1321
1322
1323
1324
1325
1326
1312
1313
1314
1315
1316
1317
1318

1319
1320
1321
1322
1323
1324
1325
1326







-
+







                PKT_CHAR, (len*8) >> 8, PKT_CHAR, (len*8) & 0xFF,
                PKT_DATA, rsabuf, len,
                PKT_INT, 0,
                PKT_END);

    logevent("Trying to enable encryption...");

    free(rsabuf);
    sfree(rsabuf);

    cipher = cipher_type == SSH_CIPHER_BLOWFISH ? &ssh_blowfish_ssh1 :
             cipher_type == SSH_CIPHER_DES ? &ssh_des :
             &ssh_3des;
    cipher->sesskey(session_key);

    crWaitUntil(ispkt);
1456
1457
1458
1459
1460
1461
1462
1463

1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475

1476
1477
1478
1479
1480
1481

1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496

1497
1498
1499
1500
1501
1502
1503
1456
1457
1458
1459
1460
1461
1462

1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474

1475
1476
1477
1478
1479
1480

1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495

1496
1497
1498
1499
1500
1501
1502
1503







-
+











-
+





-
+














-
+







                        int len, retlen;
                        len = 1 + 4;   /* message type, bit count */
                        len += ssh1_bignum_length(key.exponent);
                        len += ssh1_bignum_length(key.modulus);
                        len += ssh1_bignum_length(challenge);
                        len += 16;     /* session id */
                        len += 4;      /* response format */
                        agentreq = malloc(4 + len);
                        agentreq = smalloc(4 + len);
                        PUT_32BIT(agentreq, len);
                        q = agentreq + 4;
                        *q++ = SSH_AGENTC_RSA_CHALLENGE;
                        PUT_32BIT(q, ssh1_bignum_bitcount(key.modulus));
                        q += 4;
                        q += ssh1_write_bignum(q, key.exponent);
                        q += ssh1_write_bignum(q, key.modulus);
                        q += ssh1_write_bignum(q, challenge);
                        memcpy(q, session_id, 16); q += 16;
                        PUT_32BIT(q, 1);   /* response format */
                        agent_query(agentreq, len+4, &ret, &retlen);
                        free(agentreq);
                        sfree(agentreq);
                        if (ret) {
                            if (ret[4] == SSH_AGENT_RSA_RESPONSE) {
                                logevent("Sending Pageant's response");
                                send_packet(SSH1_CMSG_AUTH_RSA_RESPONSE,
                                            PKT_DATA, ret+5, 16, PKT_END);
                                free(ret);
                                sfree(ret);
                                crWaitUntil(ispkt);
                                if (pktin.type == SSH1_SMSG_SUCCESS) {
                                    logevent("Pageant's response accepted");
                                    if (flags & FLAG_VERBOSE) {
                                        c_write("Authenticated using RSA key \"",
                                                29);
                                        c_write(commentp, commentlen);
                                        c_write("\" from agent\r\n", 14);
                                    }
                                    authed = TRUE;
                                } else
                                    logevent("Pageant's response not accepted");
                            } else {
                                logevent("Pageant failed to answer challenge");
                                free(ret);
                                sfree(ret);
                            }
                        } else {
                            logevent("No reply received from Pageant");
                        }
                    }
                    freebn(key.exponent);
                    freebn(key.modulus);
1569
1570
1571
1572
1573
1574
1575
1576

1577
1578
1579
1580
1581
1582
1583
1569
1570
1571
1572
1573
1574
1575

1576
1577
1578
1579
1580
1581
1582
1583







-
+







                c_write("Trying public key authentication.\r\n", 35);
            if (!rsakey_encrypted(cfg.keyfile, &comment)) {
                if (flags & FLAG_VERBOSE)
                    c_write("No passphrase required.\r\n", 25);
                goto tryauth;
            }
            sprintf(prompt, "Passphrase for key \"%.100s\": ", comment);
            free(comment);
            sfree(comment);
        }

	if (ssh_get_password) {
	    if (!ssh_get_password(prompt, password, sizeof(password))) {
                /*
                 * get_password failed to get a password (for
                 * example because one was supplied on the command
1813
1814
1815
1816
1817
1818
1819
1820

1821
1822
1823
1824
1825
1826
1827
1813
1814
1815
1816
1817
1818
1819

1820
1821
1822
1823
1824
1825
1826
1827







-
+







		} else {
		    i = 1;
		    for (c = first234(ssh_channels, &e); c; c = next234(&e)) {
			if (c->localid > i)
			    break;     /* found a free number */
			i = c->localid + 1;
		    }
		    c = malloc(sizeof(struct ssh_channel));
		    c = smalloc(sizeof(struct ssh_channel));
		    c->remoteid = GET_32BIT(pktin.body);
		    c->localid = i;
		    c->closes = 0;
		    c->type = SSH1_SMSG_AGENT_OPEN;/* identify channel type */
		    c->u.a.lensofar = 0;
		    add234(ssh_channels, c);
		    send_packet(SSH1_MSG_CHANNEL_OPEN_CONFIRMATION,
1837
1838
1839
1840
1841
1842
1843
1844

1845
1846
1847
1848
1849
1850
1851
1837
1838
1839
1840
1841
1842
1843

1844
1845
1846
1847
1848
1849
1850
1851







-
+







                if (c) {
                    int closetype;
                    closetype = (pktin.type == SSH1_MSG_CHANNEL_CLOSE ? 1 : 2);
                    send_packet(pktin.type, PKT_INT, c->remoteid, PKT_END);
                    c->closes |= closetype;
                    if (c->closes == 3) {
                        del234(ssh_channels, c);
                        free(c);
                        sfree(c);
                    }
                }
            } else if (pktin.type == SSH1_MSG_CHANNEL_DATA) {
                /* Data sent down one of our channels. */
                int i = GET_32BIT(pktin.body);
                int len = GET_32BIT(pktin.body+4);
                unsigned char *p = pktin.body+8;
1859
1860
1861
1862
1863
1864
1865
1866

1867
1868
1869
1870
1871
1872
1873
1859
1860
1861
1862
1863
1864
1865

1866
1867
1868
1869
1870
1871
1872
1873







-
+







                            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, l);
                                p += l; len -= l; c->u.a.lensofar += l;
                            }
                            if (c->u.a.lensofar == 4) {
                                c->u.a.totallen = 4 + GET_32BIT(c->u.a.msglen);
                                c->u.a.message = malloc(c->u.a.totallen);
                                c->u.a.message = smalloc(c->u.a.totallen);
                                memcpy(c->u.a.message, c->u.a.msglen, 4);
                            }
                            if (c->u.a.lensofar >= 4 && len > 0) {
                                int l = min(c->u.a.totallen - c->u.a.lensofar, len);
                                memcpy(c->u.a.message + c->u.a.lensofar, p, l);
                                p += l; len -= l; c->u.a.lensofar += l;
                            }
1885
1886
1887
1888
1889
1890
1891
1892
1893


1894
1895
1896
1897
1898
1899
1900
1885
1886
1887
1888
1889
1890
1891


1892
1893
1894
1895
1896
1897
1898
1899
1900







-
-
+
+







                                }
                                send_packet(SSH1_MSG_CHANNEL_DATA,
                                            PKT_INT, c->remoteid,
                                            PKT_INT, replylen,
                                            PKT_DATA, sentreply, replylen,
                                            PKT_END);
                                if (reply)
                                    free(reply);
                                free(c->u.a.message);
                                    sfree(reply);
                                sfree(c->u.a.message);
                                c->u.a.lensofar = 0;
                            }
                        }
                        break;
                    }
                }                
	    } else if (pktin.type == SSH1_SMSG_SUCCESS) {
2238
2239
2240
2241
2242
2243
2244
2245
2246


2247
2248
2249
2250
2251
2252
2253
2238
2239
2240
2241
2242
2243
2244


2245
2246
2247
2248
2249
2250
2251
2252
2253







-
-
+
+







     */
    keystr = hostkey->fmtkey(hkey);
    fingerprint = hostkey->fingerprint(hkey);
    verify_ssh_host_key(savedhost, savedport, hostkey->keytype,
                        keystr, fingerprint);
    logevent("Host key fingerprint is:");
    logevent(fingerprint);
    free(fingerprint);
    free(keystr);
    sfree(fingerprint);
    sfree(keystr);
    hostkey->freekey(hkey);

    /*
     * Send SSH2_MSG_NEWKEYS.
     */
    ssh2_pkt_init(SSH2_MSG_NEWKEYS);
    ssh2_pkt_send();
2438
2439
2440
2441
2442
2443
2444
2445

2446
2447
2448
2449
2450
2451
2452
2438
2439
2440
2441
2442
2443
2444

2445
2446
2447
2448
2449
2450
2451
2452







-
+







     * connection protocol will automatically have started at this
     * point; there's no need to send SERVICE_REQUEST.
     */

    /*
     * So now create a channel with a session in it.
     */
    mainchan = malloc(sizeof(struct ssh_channel));
    mainchan = smalloc(sizeof(struct ssh_channel));
    mainchan->localid = 100;           /* as good as any */
    ssh2_pkt_init(SSH2_MSG_CHANNEL_OPEN);
    ssh2_pkt_addstring("session");
    ssh2_pkt_adduint32(mainchan->localid);
    ssh2_pkt_adduint32(0x8000UL);  /* our window size */
    ssh2_pkt_adduint32(0x4000UL);  /* our max pkt size */
    ssh2_pkt_send();