Diff

Differences From Artifact [e5b7b14f5e]:

To Artifact [a28cd41eb3]:


118
119
120
121
122
123
124






125
126
127
128
129
130
131
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137







+
+
+
+
+
+







#define SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED     1    /* 0x1 */
#define SSH2_OPEN_CONNECT_FAILED                  2    /* 0x2 */
#define SSH2_OPEN_UNKNOWN_CHANNEL_TYPE            3    /* 0x3 */
#define SSH2_OPEN_RESOURCE_SHORTAGE               4    /* 0x4 */

#define SSH2_EXTENDED_DATA_STDERR                 1    /* 0x1 */

/*
 * Various remote-bug flags.
 */
#define BUG_CHOKES_ON_SSH1_IGNORE                 1
#define BUG_SSH2_HMAC                             2

#define GET_32BIT(cp) \
    (((unsigned long)(unsigned char)(cp)[0] << 24) | \
    ((unsigned long)(unsigned char)(cp)[1] << 16) | \
    ((unsigned long)(unsigned char)(cp)[2] << 8) | \
    ((unsigned long)(unsigned char)(cp)[3]))

#define PUT_32BIT(cp, value) { \
248
249
250
251
252
253
254

255
256
257
258
259
260
261
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268







+








static Socket s = NULL;

static unsigned char session_key[32];
static int ssh1_compressing;
static int ssh_agentfwd_enabled;
static int ssh_X11_fwd_enabled;
static int ssh_remote_bugs;
static const struct ssh_cipher *cipher = NULL;
static const struct ssh2_cipher *cscipher = NULL;
static const struct ssh2_cipher *sccipher = NULL;
static const struct ssh_mac *csmac = NULL;
static const struct ssh_mac *scmac = NULL;
static const struct ssh_compress *cscomp = NULL;
static const struct ssh_compress *sccomp = NULL;
655
656
657
658
659
660
661







662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678






679
680
681
682
683
684
685







+
+
+
+
+
+
+



-
-
-
-
-
-








static int s_wrpkt_prepare(void) {
    int pad, len, biglen, i;
    unsigned long crc;

    pktout.body[-1] = pktout.type;

#if 0
    debug(("Packet payload pre-compression:\n"));
    for (i = -1; i < pktout.length; i++)
        debug(("  %02x", (unsigned char)pktout.body[i]));
    debug(("\r\n"));
#endif

    if (ssh1_compressing) {
	unsigned char *compblk;
	int complen;
#if 0
	debug(("Packet payload pre-compression:\n"));
	for (i = -1; i < pktout.length; i++)
	    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);
	sfree(compblk);
#if 0
	debug(("Packet payload post-compression:\n"));
1085
1086
1087
1088
1089
1090
1091



































1092
1093
1094
1095
1096
1097
1098
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







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

/*
 * Examine the remote side's version string and compare it against
 * a list of known buggy implementations.
 */
static void ssh_detect_bugs(char *vstring) {
    char *imp;                         /* pointer to implementation part */
    imp = vstring;
    imp += strcspn(imp, "-");
    imp += strcspn(imp, "-");

    ssh_remote_bugs = 0;

    if (!strcmp(imp, "1.2.18") || !strcmp(imp, "1.2.19") ||
        !strcmp(imp, "1.2.20") || !strcmp(imp, "1.2.21") ||
        !strcmp(imp, "1.2.22")) {
        /*
         * These versions don't support SSH1_MSG_IGNORE, so we have
         * to use a different defence against password length
         * sniffing.
         */
        ssh_remote_bugs |= BUG_CHOKES_ON_SSH1_IGNORE;
        logevent("We believe remote version has SSH1 ignore bug");
    }

    if (!strncmp(imp, "2.1.0", 5) || !strncmp(imp, "2.0.", 4) ||
        !strncmp(imp, "2.2.0", 5) || !strncmp(imp, "2.3.0", 5) ||
        !strncmp(imp, "2.1 ", 4)) {
        /*
         * These versions have the HMAC bug.
         */
        ssh_remote_bugs |= BUG_SSH2_HMAC;
        logevent("We believe remote version has SSH2 HMAC bug");
    }
}

static int do_ssh_init(unsigned char c) {
    static char *vsp;
    static char version[10];
    static char vstring[80];
    static char vlog[sizeof(vstring)+20];
    static int i;
1133
1134
1135
1136
1137
1138
1139

1140
1141
1142
1143
1144
1145
1146
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190







+







    }

    ssh_agentfwd_enabled = FALSE;
    rdpkt2_state.incoming_sequence = 0;

    *vsp = 0;
    sprintf(vlog, "Server version: %s", vstring);
    ssh_detect_bugs(vstring);
    vlog[strcspn(vlog, "\r\n")] = '\0';
    logevent(vlog);

    /*
     * Server version "1.99" means we can choose whether we use v1
     * or v2 protocol. Choice is based on cfg.sshprot.
     */
1831
1832
1833
1834
1835
1836
1837







1838

1839
1840



1841
1842
1843
1844
1845













1846








1847
1848
1849



1850
1851

1852
1853

1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
















1870
1871
1872
1873
1874
1875
1876
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890


1891
1892
1893
1894




1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916



1917
1918
1919
1920

1921
1922

1923
1924















1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947







+
+
+
+
+
+
+

+
-
-
+
+
+

-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
-
-
-
+
+
+

-
+

-
+

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







                 * 
                 *  - otherwise, we let N be the nearest multiple
                 *    of 8 below the password length, and send 8
                 *    packets containing string lengths N through
                 *    N+7. This won't obscure the order of
                 *    magnitude of the password length, but it will
                 *    introduce a bit of extra uncertainty.
                 * 
                 * A few servers (the old 1.2.18 through 1.2.22)
                 * can't deal with SSH1_MSG_IGNORE. For these
                 * servers, we need an alternative defence. We make
                 * use of the fact that the password is interpreted
                 * as a C string: so we can append a NUL, then some
                 * random data.
                 */
                if (ssh_remote_bugs & BUG_CHOKES_ON_SSH1_IGNORE) {
                int bottom, top, pwlen, i;
                char *randomstr;
                    char string[64];
                    char *s;
                    int len;

                pwlen = strlen(password);
                if (pwlen < 16) {
                    bottom = 1;
                    top = 15;
                    len = strlen(password);
                    if (len < sizeof(string)) {
                        s = string;
                        strcpy(string, password);
                        len++;         /* cover the zero byte */
                        while (len < sizeof(string)) {
                            string[len++] = (char)random_byte();
                        }
                    } else {
                        s = password;
                    }
                    send_packet(pwpkt_type, PKT_INT, len,
                                PKT_DATA, s, len, PKT_END);
                } else {
                    int bottom, top, pwlen, i;
                    char *randomstr;

                    pwlen = strlen(password);
                    if (pwlen < 16) {
                        bottom = 1;
                        top = 15;
                    } else {
                    bottom = pwlen &~ 7;
                    top = bottom + 7;
                }
                        bottom = pwlen &~ 7;
                        top = bottom + 7;
                    }

                assert(pwlen >= bottom && pwlen <= top);
                    assert(pwlen >= bottom && pwlen <= top);

                randomstr = smalloc(top+1);
                    randomstr = smalloc(top+1);

                for (i = bottom; i <= top; i++) {
                    if (i == pwlen)
                        defer_packet(pwpkt_type, PKT_STR, password, PKT_END);
                    else {
                        for (j = 0; j < i; j++) {
                            do {
                                randomstr[j] = random_byte();
                            } while (randomstr[j] == '\0');
                        }
                        randomstr[i] = '\0';
                        defer_packet(SSH1_MSG_IGNORE,
                                     PKT_STR, randomstr, PKT_END);
                    }
                }
                ssh_pkt_defersend();
                    for (i = bottom; i <= top; i++) {
                        if (i == pwlen)
                            defer_packet(pwpkt_type, PKT_STR, password, PKT_END);
                        else {
                            for (j = 0; j < i; j++) {
                                do {
                                    randomstr[j] = random_byte();
                                } while (randomstr[j] == '\0');
                            }
                            randomstr[i] = '\0';
                            defer_packet(SSH1_MSG_IGNORE,
                                         PKT_STR, randomstr, PKT_END);
                        }
                    }
                    ssh_pkt_defersend();
                }
            } else {
                send_packet(pwpkt_type, PKT_STR, password, PKT_END);
            }
        }
	logevent("Sent password");
	memset(password, 0, strlen(password));
	crWaitUntil(ispkt);
2303
2304
2305
2306
2307
2308
2309
2310

2311
2312
2313
2314
2315
2316
2317
2374
2375
2376
2377
2378
2379
2380

2381
2382
2383
2384
2385
2386
2387
2388







-
+







	preferred_comp = &ssh_zlib;
    else
	preferred_comp = &ssh_comp_none;

    /*
     * Be prepared to work around the buggy MAC problem.
     */
    if (cfg.buggymac)
    if (cfg.buggymac || (ssh_remote_bugs & BUG_SSH2_HMAC))
        maclist = buggymacs, nmacs = lenof(buggymacs);
    else
        maclist = macs, nmacs = lenof(macs);

    begin_key_exchange:
    /*
     * Construct and send our key exchange packet.