Diff

Differences From Artifact [739a10a321]:

To Artifact [74f3763e1d]:


1445
1446
1447
1448
1449
1450
1451
1452


1453
1454
1455
1456
1457
1458
1459
1445
1446
1447
1448
1449
1450
1451

1452
1453
1454
1455
1456
1457
1458
1459
1460







-
+
+







	    /* Feed that block to the MAC. */
	    ssh->scmac->bytes(ssh->sc_mac_ctx,
			      st->pktin->data + st->packetlen, st->cipherblk);
	    st->packetlen += st->cipherblk;
	    /* See if that gives us a valid packet. */
	    if (ssh->scmac->verresult(ssh->sc_mac_ctx,
				      st->pktin->data + st->packetlen) &&
		(st->len = GET_32BIT(st->pktin->data)) + 4 == st->packetlen)
		((st->len = toint(GET_32BIT(st->pktin->data))) ==
                 st->packetlen-4))
		    break;
	    if (st->packetlen >= OUR_V2_PACKETLIMIT) {
		bombout(("No valid incoming packet found"));
		ssh_free_packet(st->pktin);
		crStop(NULL);
	    }	    
	}
1478
1479
1480
1481
1482
1483
1484
1485

1486
1487
1488
1489
1490
1491
1492
1479
1480
1481
1482
1483
1484
1485

1486
1487
1488
1489
1490
1491
1492
1493







-
+







	if (ssh->sccipher)
	    ssh->sccipher->decrypt(ssh->sc_cipher_ctx,
				   st->pktin->data, st->cipherblk);

	/*
	 * Now get the length figure.
	 */
	st->len = GET_32BIT(st->pktin->data);
	st->len = toint(GET_32BIT(st->pktin->data));

	/*
	 * _Completely_ silly lengths should be stomped on before they
	 * do us any more damage.
	 */
	if (st->len < 0 || st->len > OUR_V2_PACKETLIMIT ||
	    (st->len + 4) % st->cipherblk != 0) {
2309
2310
2311
2312
2313
2314
2315
2316

2317
2318
2319
2320
2321
2322
2323
2310
2311
2312
2313
2314
2315
2316

2317
2318
2319
2320
2321
2322
2323
2324







-
+







static void ssh_pkt_getstring(struct Packet *pkt, char **p, int *length)
{
    int len;
    *p = NULL;
    *length = 0;
    if (pkt->length - pkt->savedpos < 4)
	return;
    len = GET_32BIT(pkt->body + pkt->savedpos);
    len = toint(GET_32BIT(pkt->body + pkt->savedpos));
    if (len < 0)
	return;
    *length = len;
    pkt->savedpos += 4;
    if (pkt->length - pkt->savedpos < *length)
	return;
    *p = (char *)(pkt->body + pkt->savedpos);
2393
2394
2395
2396
2397
2398
2399
2400

2401
2402
2403
2404
2405
2406
2407
2408



2409
2410






2411
2412
2413
2414
2415
2416
2417
2418
2419


2420



2421
2422
2423
2424
2425
2426
2427
2394
2395
2396
2397
2398
2399
2400

2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412


2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429

2430
2431
2432
2433
2434
2435
2436
2437
2438
2439







-
+








+
+
+
-
-
+
+
+
+
+
+









+
+
-
+
+
+







    /* dmemdump(pkblob, pkblob_len); */
    /* dmemdump(sigblob, sigblob_len); */

    /*
     * See if this is in fact an ssh-rsa signature and a buggy
     * server; otherwise we can just do this the easy way.
     */
    if ((ssh->remote_bugs & BUG_SSH2_RSA_PADDING) &&
    if ((ssh->remote_bugs & BUG_SSH2_RSA_PADDING) && pkblob_len > 4+7+4 &&
	(GET_32BIT(pkblob) == 7 && !memcmp(pkblob+4, "ssh-rsa", 7))) {
	int pos, len, siglen;

	/*
	 * Find the byte length of the modulus.
	 */

	pos = 4+7;		       /* skip over "ssh-rsa" */
        len = toint(GET_32BIT(pkblob+pos)); /* get length of exponent */
        if (len < 0 || len > pkblob_len - pos - 4)
            goto give_up;
	pos += 4 + GET_32BIT(pkblob+pos);   /* skip over exponent */
	len = GET_32BIT(pkblob+pos);   /* find length of modulus */
	pos += 4 + len;                /* skip over exponent */
        if (pkblob_len - pos < 4)
            goto give_up;
	len = toint(GET_32BIT(pkblob+pos)); /* find length of modulus */
        if (len < 0 || len > pkblob_len - pos - 4)
            goto give_up;
	pos += 4;		       /* find modulus itself */
	while (len > 0 && pkblob[pos] == 0)
	    len--, pos++;
	/* debug(("modulus length is %d\n", len)); */

	/*
	 * Now find the signature integer.
	 */
	pos = 4+7;		       /* skip over "ssh-rsa" */
        if (sigblob_len < pos+4)
            goto give_up;
	siglen = GET_32BIT(sigblob+pos);
	siglen = toint(GET_32BIT(sigblob+pos));
        if (siglen != sigblob_len - pos - 4)
            goto give_up;
	/* debug(("signature length is %d\n", siglen)); */

	if (len != siglen) {
	    unsigned char newlen[4];
	    ssh2_pkt_addstring_start(pkt);
	    ssh2_pkt_addstring_data(pkt, (char *)sigblob, pos);
	    /* dmemdump(sigblob, pos); */
2435
2436
2437
2438
2439
2440
2441
2442




2443
2444
2445
2446
2447
2448
2449
2447
2448
2449
2450
2451
2452
2453

2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464







-
+
+
+
+







		/* dmemdump(newlen, 1); */
	    }
	    ssh2_pkt_addstring_data(pkt, (char *)(sigblob+pos), siglen);
	    /* dmemdump(sigblob+pos, siglen); */
	    return;
	}

	/* Otherwise fall through and do it the easy way. */
	/* Otherwise fall through and do it the easy way. We also come
         * here as a fallback if we discover above that the key blob
         * is misformatted in some way. */
      give_up:;
    }

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

/*
3673
3674
3675
3676
3677
3678
3679




3680


3681
3682
3683
3684
3685
3686
3687
3688
3689
3690

3691
3692
3693
3694
3695
3696

3697
3698
3699

3700
3701
3702
3703

3704

3705

3706
3707
3708
3709
3710
3711
3712
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698

3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709

3710
3711
3712
3713
3714
3715

3716
3717
3718

3719
3720
3721
3722

3723
3724
3725

3726
3727
3728
3729
3730
3731
3732
3733







+
+
+
+
-
+
+









-
+





-
+


-
+



-
+

+
-
+







		r = ssh->agent_response;
		s->responselen = ssh->agent_response_len;
	    }
	    s->response = (unsigned char *) r;
	    if (s->response && s->responselen >= 5 &&
		s->response[4] == SSH1_AGENT_RSA_IDENTITIES_ANSWER) {
		s->p = s->response + 5;
		s->nkeys = toint(GET_32BIT(s->p));
                if (s->nkeys < 0) {
                    logeventf(ssh, "Pageant reported negative key count %d",
                              s->nkeys);
		s->nkeys = GET_32BIT(s->p);
                    s->nkeys = 0;
                }
		s->p += 4;
		logeventf(ssh, "Pageant has %d SSH-1 keys", s->nkeys);
		for (s->keyi = 0; s->keyi < s->nkeys; s->keyi++) {
		    unsigned char *pkblob = s->p;
		    s->p += 4;
		    {
			int n, ok = FALSE;
			do {	       /* do while (0) to make breaking easy */
			    n = ssh1_read_bignum
				(s->p, s->responselen-(s->p-s->response),
				(s->p, toint(s->responselen-(s->p-s->response)),
				 &s->key.exponent);
			    if (n < 0)
				break;
			    s->p += n;
			    n = ssh1_read_bignum
				(s->p, s->responselen-(s->p-s->response),
				(s->p, toint(s->responselen-(s->p-s->response)),
				 &s->key.modulus);
			    if (n < 0)
			    break;
                                break;
			    s->p += n;
			    if (s->responselen - (s->p-s->response) < 4)
				break;
			    s->commentlen = GET_32BIT(s->p);
			    s->commentlen = toint(GET_32BIT(s->p));
			    s->p += 4;
			    if (s->commentlen < 0 ||
			    if (s->responselen - (s->p-s->response) <
                                toint(s->responselen - (s->p-s->response)) <
				s->commentlen)
				break;
			    s->commentp = (char *)s->p;
			    s->p += s->commentlen;
			    ok = TRUE;
			} while (0);
			if (!ok) {
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203










7204
7205


7206
7207
7208
7209
7210
7211
7212
7210
7211
7212
7213
7214
7215
7216








7217
7218
7219
7220
7221
7222
7223
7224
7225
7226


7227
7228
7229
7230
7231
7232
7233
7234
7235







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







		long len = pktin->length - pktin->savedpos;
		unsigned long num = GET_32BIT(p); /* what is it? */
		/* If it's 0, it hardly matters; assume string */
		if (num == 0) {
		    is_int = FALSE;
		} else {
		    int maybe_int = FALSE, maybe_str = FALSE;
#define CHECK_HYPOTHESIS(offset, result) \
    do { \
	long q = offset; \
	if (q >= 0 && q+4 <= len) { \
	    q = q + 4 + GET_32BIT(p+q); \
	    if (q >= 0 && q+4 <= len && \
		    ((q = q + 4 + GET_32BIT(p+q))!= 0) && q == len) \
		result = TRUE; \
#define CHECK_HYPOTHESIS(offset, result)                                \
                    do                                                  \
                    {                                                   \
                        int q = toint(offset);                          \
                        if (q >= 0 && q+4 <= len) {                     \
                            q = toint(q + 4 + GET_32BIT(p+q));          \
                            if (q >= 0 && q+4 <= len &&                 \
                                ((q = toint(q + 4 + GET_32BIT(p+q))) != 0) && \
                                q == len)                               \
                                result = TRUE;                          \
	} \
    } while(0)
                        }                                               \
                    } while(0)
		    CHECK_HYPOTHESIS(4+1, maybe_int);
		    CHECK_HYPOTHESIS(4+num+1, maybe_str);
#undef CHECK_HYPOTHESIS
		    if (maybe_int && !maybe_str)
			is_int = TRUE;
		    else if (!maybe_int && maybe_str)
			is_int = FALSE;
7892
7893
7894
7895
7896
7897
7898









7899
































7900
7901
7902
7903
7904
7905

7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916

7917
7918
7919
7920
7921
7922
7923
7924
7925

7926
7927
7928
7929
7930
7931
7932
7915
7916
7917
7918
7919
7920
7921
7922
7923
7924
7925
7926
7927
7928
7929
7930

7931
7932
7933
7934
7935
7936
7937
7938
7939
7940
7941
7942
7943
7944
7945
7946
7947
7948
7949
7950
7951
7952
7953
7954
7955
7956
7957
7958
7959
7960
7961
7962
7963
7964
7965
7966
7967

7968
7969
7970
7971
7972
7973
7974
7975
7976
7977
7978

7979
7980
7981
7982
7983
7984
7985
7986
7987
7988
7989
7990
7991
7992
7993
7994
7995
7996







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





-
+










-
+









+







	    }
	    s->agent_response = (unsigned char *) r;
	    if (s->agent_response && s->agent_responselen >= 5 &&
		s->agent_response[4] == SSH2_AGENT_IDENTITIES_ANSWER) {
		int keyi;
		unsigned char *p;
		p = s->agent_response + 5;
		s->nkeys = toint(GET_32BIT(p));

                /*
                 * Vet the Pageant response to ensure that the key
                 * count and blob lengths make sense.
                 */
                if (s->nkeys < 0) {
                    logeventf(ssh, "Pageant response contained a negative"
                              " key count %d", s->nkeys);
		s->nkeys = GET_32BIT(p);
                    s->nkeys = 0;
                    goto done_agent_query;
                } else {
                    unsigned char *q = p + 4;
                    int lenleft = s->agent_responselen - 5 - 4;

                    for (keyi = 0; keyi < s->nkeys; keyi++) {
                        int bloblen, commentlen;
                        if (lenleft < 4) {
                            logeventf(ssh, "Pageant response was truncated");
                            s->nkeys = 0;
                            goto done_agent_query;
                        }
                        bloblen = toint(GET_32BIT(q));
                        if (bloblen < 0 || bloblen > lenleft) {
                            logeventf(ssh, "Pageant response was truncated");
                            s->nkeys = 0;
                            goto done_agent_query;
                        }
                        lenleft -= 4 + bloblen;
                        q += 4 + bloblen;
                        commentlen = toint(GET_32BIT(q));
                        if (commentlen < 0 || commentlen > lenleft) {
                            logeventf(ssh, "Pageant response was truncated");
                            s->nkeys = 0;
                            goto done_agent_query;
                        }
                        lenleft -= 4 + commentlen;
                        q += 4 + commentlen;
                    }
                }

		p += 4;
		logeventf(ssh, "Pageant has %d SSH-2 keys", s->nkeys);
		if (s->publickey_blob) {
		    /* See if configured key is in agent. */
		    for (keyi = 0; keyi < s->nkeys; keyi++) {
			s->pklen = GET_32BIT(p);
			s->pklen = toint(GET_32BIT(p));
			if (s->pklen == s->publickey_bloblen &&
			    !memcmp(p+4, s->publickey_blob,
				    s->publickey_bloblen)) {
			    logeventf(ssh, "Pageant key #%d matches "
				      "configured key file", keyi);
			    s->keyi = keyi;
			    s->pkblob_in_agent = p;
			    break;
			}
			p += 4 + s->pklen;
			p += GET_32BIT(p) + 4; /* comment */
			p += toint(GET_32BIT(p)) + 4; /* comment */
		    }
		    if (!s->pkblob_in_agent) {
			logevent("Configured key file not in Pageant");
			s->nkeys = 0;
		    }
		}
	    } else {
                logevent("Failed to get reply from Pageant");
	    }
          done_agent_query:;
	}

    }

    /*
     * We repeat this whole loop, including the username prompt,
     * until we manage a successful authentication. If the user
8170
8171
8172
8173
8174
8175
8176
8177

8178
8179
8180
8181

8182
8183

8184
8185
8186
8187
8188
8189
8190
8234
8235
8236
8237
8238
8239
8240

8241
8242
8243
8244

8245
8246

8247
8248
8249
8250
8251
8252
8253
8254







-
+



-
+

-
+







		 */

		ssh->pkt_actx = SSH2_PKTCTX_PUBLICKEY;

		logeventf(ssh, "Trying Pageant key #%d", s->keyi);

		/* Unpack key from agent response */
		s->pklen = GET_32BIT(s->agentp);
		s->pklen = toint(GET_32BIT(s->agentp));
		s->agentp += 4;
		s->pkblob = (char *)s->agentp;
		s->agentp += s->pklen;
		s->alglen = GET_32BIT(s->pkblob);
		s->alglen = toint(GET_32BIT(s->pkblob));
		s->alg = s->pkblob + 4;
		s->commentlen = GET_32BIT(s->agentp);
		s->commentlen = toint(GET_32BIT(s->agentp));
		s->agentp += 4;
		s->commentp = (char *)s->agentp;
		s->agentp += s->commentlen;
		/* s->agentp now points at next key, if any */

		/* See if server will accept it */
		s->pktout = ssh2_pkt_init(SSH2_MSG_USERAUTH_REQUEST);
8280
8281
8282
8283
8284
8285
8286

8287


8288
8289
8290
8291
8292
8293
8294
8344
8345
8346
8347
8348
8349
8350
8351

8352
8353
8354
8355
8356
8357
8358
8359
8360







+
-
+
+







			} while (pktin || inlen > 0);
			vret = ssh->agent_response;
			s->retlen = ssh->agent_response_len;
		    }
		    s->ret = vret;
		    sfree(s->agentreq);
		    if (s->ret) {
			if (s->retlen >= 9 &&
			if (s->ret[4] == SSH2_AGENT_SIGN_RESPONSE) {
                            s->ret[4] == SSH2_AGENT_SIGN_RESPONSE &&
                            GET_32BIT(s->ret + 5) <= (unsigned)(s->retlen-9)) {
			    logevent("Sending Pageant's response");
			    ssh2_add_sigblob(ssh, s->pktout,
					     s->pkblob, s->pklen,
					     s->ret + 9,
					     GET_32BIT(s->ret + 5));
			    ssh2_pkt_send(ssh, s->pktout);
			    s->type = AUTH_TYPE_PUBLICKEY;