Diff

Differences From Artifact [3bc8fb2ecc]:

To Artifact [da8ac6dffd]:


634
635
636
637
638
639
640
641
642
643







644
645
646
647
648
649

650
651
652

653
654






655
656
657
658
659
660
661
634
635
636
637
638
639
640



641
642
643
644
645
646
647
648
649
650
651
652

653
654
655

656
657

658
659
660
661
662
663
664
665
666
667
668
669
670







-
-
-
+
+
+
+
+
+
+





-
+


-
+

-
+
+
+
+
+
+







    struct rdpkt1_state_tag rdpkt1_state;
    struct rdpkt2_state_tag rdpkt2_state;

    void (*protocol) (Ssh ssh, unsigned char *in, int inlen, int ispkt);
    int (*s_rdpkt) (Ssh ssh, unsigned char **data, int *datalen);
};

#define logevent(s) { logevent(ssh->frontend, s); \
                      if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)) \
                      { fprintf(stderr, "%s\n", s); fflush(stderr); } }
#define logevent(s) do { \
    logevent(ssh->frontend, s); \
    if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)) { \
	fprintf(stderr, "%s\n", s); \
	fflush(stderr); \
    } \
} while (0)

/* logevent, only printf-formatted. */
void logeventf(Ssh ssh, char *fmt, ...)
{
    va_list ap;
    char stuff[200];
    char *buf;

    va_start(ap, fmt);
    vsprintf(stuff, fmt, ap);
    buf = dupvprintf(fmt, ap);
    va_end(ap);
    logevent(stuff);
    logevent(buf);
    if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)) {
	fprintf(stderr, "%s\n", buf);
	fflush(stderr);
    }
    sfree(buf);
}

#define bombout(msg) ( ssh->state = SSH_STATE_CLOSED, \
                          (ssh->s ? sk_close(ssh->s), ssh->s = NULL : 0), \
                          logeventf msg, connection_fatal msg )

static int ssh_channelcmp(void *av, void *bv)
1045
1046
1047
1048
1049
1050
1051
1052


1053
1054
1055

1056
1057
1058


1059
1060
1061


1062
1063

1064

1065
1066
1067
1068

1069
1070
1071
1072
1073
1074
1075

1076
1077
1078
1079
1080
1081
1082
1054
1055
1056
1057
1058
1059
1060

1061
1062
1063
1064

1065
1066


1067
1068
1069


1070
1071
1072
1073
1074

1075




1076

1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090







-
+
+


-
+

-
-
+
+

-
-
+
+


+
-
+
-
-
-
-
+
-






+







    switch (ssh->pktin.type) {
        /*
         * These packets we must handle instantly.
         */
      case SSH2_MSG_DISCONNECT:
        {
            /* log reason code in disconnect message */
            char buf[256];
            char *buf;
	    int nowlen;
            int reason = GET_32BIT(ssh->pktin.data + 6);
            unsigned msglen = GET_32BIT(ssh->pktin.data + 10);
            unsigned nowlen;

            if (reason > 0 && reason < lenof(ssh2_disconnect_reasons)) {
                sprintf(buf, "Received disconnect message (%s)",
                        ssh2_disconnect_reasons[reason]);
                buf = dupprintf("Received disconnect message (%s)",
				ssh2_disconnect_reasons[reason]);
            } else {
                sprintf(buf, "Received disconnect message (unknown type %d)",
                        reason);
                buf = dupprintf("Received disconnect message (unknown"
				" type %d)", reason);
            }
            logevent(buf);
	    sfree(buf);
            strcpy(buf, "Disconnection message text: ");
            buf = dupprintf("Disconnection message text: %n%.*s",
            nowlen = strlen(buf);
            if (msglen > sizeof(buf) - nowlen - 1)
                msglen = sizeof(buf) - nowlen - 1;
            memcpy(buf + nowlen, ssh->pktin.data + 14, msglen);
			    msglen, &nowlen, ssh->pktin.data + 14);
            buf[nowlen + msglen] = '\0';
            logevent(buf);
            bombout((ssh,"Server sent disconnect message\ntype %d (%s):\n\"%s\"",
                     reason,
                     (reason > 0 && reason < lenof(ssh2_disconnect_reasons)) ?
                     ssh2_disconnect_reasons[reason] : "unknown",
                     buf+nowlen));
	    sfree(buf);
            crReturn(0);
        }
        break;
      case SSH2_MSG_IGNORE:
	goto next_packet;
      case SSH2_MSG_DEBUG:
	{
1608
1609
1610
1611
1612
1613
1614

1615
1616
1617
1618
1619




1620
1621
1622
1623
1624
1625
1626
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627

1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638







+




-
+
+
+
+







	return 0;		       /* arrgh, no way to decline (FIXME?) */
    value = ssh->pktin.data[ssh->pktin.savedpos] != 0;
    ssh->pktin.savedpos++;
    return value;
}
static void ssh2_pkt_getstring(Ssh ssh, char **p, int *length)
{
    int len;
    *p = NULL;
    *length = 0;
    if (ssh->pktin.length - ssh->pktin.savedpos < 4)
	return;
    *length = GET_32BIT(ssh->pktin.data + ssh->pktin.savedpos);
    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)
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064

2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075

2076
2077

2078
2079
2080
2081
2082
2083
2084
2085
2067
2068
2069
2070
2071
2072
2073



2074


2075
2076
2077
2078
2079
2080
2081
2082

2083
2084

2085

2086
2087
2088
2089
2090
2091
2092







-
-
-
+
-
-








-
+

-
+
-







    if (port < 0)
	port = 22;		       /* default ssh port */
    ssh->savedport = port;

    /*
     * Try to find host.
     */
    {
	char buf[200];
	sprintf(buf, "Looking up host \"%.170s\"", host);
    logeventf(ssh, "Looking up host \"%s\"", host);
	logevent(buf);
    }
    addr = sk_namelookup(host, realhost);
    if ((err = sk_addr_error(addr)))
	return err;

    /*
     * Open socket.
     */
    {
	char buf[200], addrbuf[100];
	char addrbuf[100];
	sk_getaddr(addr, addrbuf, 100);
	sprintf(buf, "Connecting to %.100s port %d", addrbuf, port);
	logeventf(ssh, "Connecting to %s port %d", addrbuf, port);
	logevent(buf);
    }
    ssh->fn = &fn_table;
    ssh->s = new_connection(addr, *realhost, port, 0, 1, nodelay, (Plug) ssh);
    if ((err = sk_socket_error(ssh->s))) {
	ssh->s = NULL;
	return err;
    }
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401

2402
2403
2404
2405
2406
2407
2408
2409
2410
2399
2400
2401
2402
2403
2404
2405



2406


2407
2408
2409
2410
2411
2412
2413







-
-
-
+
-
-







    sfree(s->rsabuf);

    ssh->cipher = (s->cipher_type == SSH_CIPHER_BLOWFISH ? &ssh_blowfish_ssh1 :
		   s->cipher_type == SSH_CIPHER_DES ? &ssh_des :
		   &ssh_3des);
    ssh->v1_cipher_ctx = ssh->cipher->make_context();
    ssh->cipher->sesskey(ssh->v1_cipher_ctx, ssh->session_key);
    {
	char buf[256];
	sprintf(buf, "Initialised %.200s encryption", ssh->cipher->text_name);
    logeventf(ssh, "Initialised %s encryption", ssh->cipher->text_name);
	logevent(buf);
    }

    ssh->crcda_ctx = crcda_make_context();
    logevent("Installing CRC compensation attack detector");

    crWaitUntil(ispkt);

    if (ssh->pktin.type != SSH1_SMSG_SUCCESS) {
2660
2661
2662
2663
2664
2665
2666
2667

2668
2669
2670
2671
2672
2673
2674
2675
2663
2664
2665
2666
2667
2668
2669

2670

2671
2672
2673
2674
2675
2676
2677







-
+
-







	}
	if (s->pwpkt_type == SSH1_CMSG_AUTH_RSA) {
	    char *comment = NULL;
	    int type;
	    char msgbuf[256];
	    if (flags & FLAG_VERBOSE)
		c_write_str(ssh, "Trying public key authentication.\r\n");
	    sprintf(msgbuf, "Trying public key \"%.200s\"", cfg.keyfile);
	    logeventf(ssh, "Trying public key \"%s\"", cfg.keyfile);
	    logevent(msgbuf);
	    type = key_type(cfg.keyfile);
	    if (type != SSH_KEYTYPE_SSH1) {
		sprintf(msgbuf, "Key is of wrong type (%s)",
			key_type_to_str(type));
		logevent(msgbuf);
		c_write_str(ssh, msgbuf);
		c_write_str(ssh, "\r\n");
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3068
3069
3070
3071
3072
3073
3074

3075
3076
3077
3078
3079
3080
3081







-







    }

    {
	char type;
	int n;
	int sport,dport,sserv,dserv;
	char sports[256], dports[256], host[256];
	char buf[1024];

	ssh->rportfwds = newtree234(ssh_rportcmp_ssh1);
        /* Add port forwardings. */
	ssh->portfwd_strptr = cfg.portfwd;
	while (*ssh->portfwd_strptr) {
	    type = *ssh->portfwd_strptr++;
	    n = 0;
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105


3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117


3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130







3131
3132
3133
3134
3135
3136
3137
3138
3139
3140



3141
3142
3143
3144
3145
3146
3147
3148
3149
3150







3151
3152
3153
3154
3155
3156
3157
3158
3097
3098
3099
3100
3101
3102
3103



3104
3105

3106
3107
3108
3109
3110
3111
3112
3113



3114
3115

3116
3117
3118
3119
3120







3121
3122
3123
3124
3125
3126
3127

3128
3129
3130
3131
3132
3133



3134
3135
3136

3137
3138







3139
3140
3141
3142
3143
3144
3145

3146
3147
3148
3149
3150
3151
3152







-
-
-
+
+
-








-
-
-
+
+
-





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






-
-
-
+
+
+
-


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







	    ssh->portfwd_strptr++;
	    dport = atoi(dports);
	    dserv = 0;
	    if (dport == 0) {
		dserv = 1;
		dport = net_service_lookup(dports);
		if (!dport) {
		    sprintf(buf,
			    "Service lookup failed for destination port \"%s\"",
			    dports);
		    logeventf(ssh, "Service lookup failed for"
			      " destination port \"%s\"", dports);
		    logevent(buf);
		}
	    }
	    sport = atoi(sports);
	    sserv = 0;
	    if (sport == 0) {
		sserv = 1;
		sport = net_service_lookup(sports);
		if (!sport) {
		    sprintf(buf,
			    "Service lookup failed for source port \"%s\"",
			    sports);
		    logeventf(ssh, "Service lookup failed for source"
			      " port \"%s\"", sports);
		    logevent(buf);
		}
	    }
	    if (sport && dport) {
		if (type == 'L') {
		    pfd_addforward(host, dport, sport, ssh);
		    sprintf(buf, "Local port %.*s%.*s%d%.*s forwarding to"
			    " %s:%.*s%.*s%d%.*s",
			    (int)(sserv ? strlen(sports) : 0), sports,
			    sserv, "(", sport, sserv, ")",
			    host,
			    (int)(dserv ? strlen(dports) : 0), dports,
			    dserv, "(", dport, dserv, ")");
		    logeventf(ssh, "Local port %.*s%.*s%d%.*s forwarding to"
			      " %s:%.*s%.*s%d%.*s",
			      (int)(sserv ? strlen(sports) : 0), sports,
			      sserv, "(", sport, sserv, ")",
			      host,
			      (int)(dserv ? strlen(dports) : 0), dports,
			      dserv, "(", dport, dserv, ")");
		    logevent(buf);
		} else {
		    struct ssh_rportfwd *pf;
		    pf = smalloc(sizeof(*pf));
		    strcpy(pf->dhost, host);
		    pf->dport = dport;
		    if (add234(ssh->rportfwds, pf) != pf) {
			sprintf(buf, 
				"Duplicate remote port forwarding to %s:%d",
				host, dport);
			logeventf(ssh, 
				  "Duplicate remote port forwarding to %s:%d",
				  host, dport);
			logevent(buf);
			sfree(pf);
		    } else {
			sprintf(buf, "Requesting remote port %.*s%.*s%d%.*s"
				" forward to %s:%.*s%.*s%d%.*s",
			    (int)(sserv ? strlen(sports) : 0), sports,
			    sserv, "(", sport, sserv, ")",
			    host,
			    (int)(dserv ? strlen(dports) : 0), dports,
			    dserv, "(", dport, dserv, ")");
			logeventf(ssh, "Requesting remote port %.*s%.*s%d%.*s"
				  " forward to %s:%.*s%.*s%d%.*s",
				  (int)(sserv ? strlen(sports) : 0), sports,
				  sserv, "(", sport, sserv, ")",
				  host,
				  (int)(dserv ? strlen(dports) : 0), dports,
				  dserv, "(", dport, dserv, ")");
			logevent(buf);
			send_packet(ssh, SSH1_CMSG_PORT_FORWARD_REQUEST,
				    PKT_INT, sport,
				    PKT_STR, host,
				    PKT_INT, dport,
				    PKT_END);
			do {
			    crReturnV;
3572
3573
3574
3575
3576
3577
3578



3579

3580
3581
3582
3583
3584
3585
3586
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575

3576
3577
3578
3579
3580
3581
3582
3583







+
+
+
-
+







}

/*
 * Utility routine for decoding comma-separated strings in KEXINIT.
 */
static int in_commasep_string(char *needle, char *haystack, int haylen)
{
    int needlen;
    if (!needle || !haystack)	       /* protect against null pointers */
	return 0;
    int needlen = strlen(needle);
    needlen = strlen(needle);
    while (1) {
	/*
	 * Is it at the start of the string?
	 */
	if (haylen >= needlen &&       /* haystack is long enough */
	    !memcmp(needle, haystack, needlen) &&	/* initial match */
	    (haylen == needlen || haystack[needlen] == ',')
3807
3808
3809
3810
3811
3812
3813

3814

3815
3816
3817
3818
3819
3820
3821
3804
3805
3806
3807
3808
3809
3810
3811

3812
3813
3814
3815
3816
3817
3818
3819







+
-
+







    ssh->exhash = ssh->exhashbase;
    sha_string(&ssh->exhash, ssh->pktout.data + 5, ssh->pktout.length - 5);

    ssh2_pkt_send(ssh);

    if (!ispkt)
	crWaitUntil(ispkt);
    if (ssh->pktin.length > 5)
    sha_string(&ssh->exhash, ssh->pktin.data + 5, ssh->pktin.length - 5);
	sha_string(&ssh->exhash, ssh->pktin.data + 5, ssh->pktin.length - 5);

    /*
     * Now examine the other side's KEXINIT to see what we're up
     * to.
     */
    {
	char *str;
3868
3869
3870
3871
3872
3873
3874
3875


3876
3877
3878
3879
3880
3881
3882
3866
3867
3868
3869
3870
3871
3872

3873
3874
3875
3876
3877
3878
3879
3880
3881







-
+
+







	    if (s->cscipher_tobe) {
		if (s->warn)
		    askcipher(ssh->frontend, s->cscipher_tobe->name, 1);
		break;
	    }
	}
	if (!s->cscipher_tobe) {
	    bombout((ssh,"Couldn't agree a client-to-server cipher (available: %s)", str));
	    bombout((ssh,"Couldn't agree a client-to-server cipher (available: %s)",
		     str ? str : "(null)"));
	    crReturn(0);
	}

	ssh2_pkt_getstring(ssh, &str, &len);    /* server->client cipher */
	s->warn = 0;
	for (i = 0; i < s->n_preferred_ciphers; i++) {
	    const struct ssh2_ciphers *c = s->preferred_ciphers[i];
3893
3894
3895
3896
3897
3898
3899
3900


3901
3902
3903
3904
3905
3906
3907
3892
3893
3894
3895
3896
3897
3898

3899
3900
3901
3902
3903
3904
3905
3906
3907







-
+
+







	    if (s->sccipher_tobe) {
		if (s->warn)
		    askcipher(ssh->frontend, s->sccipher_tobe->name, 2);
		break;
	    }
	}
	if (!s->sccipher_tobe) {
	    bombout((ssh,"Couldn't agree a server-to-client cipher (available: %s)", str));
	    bombout((ssh,"Couldn't agree a server-to-client cipher (available: %s)",
		     str ? str : "(null)"));
	    crReturn(0);
	}

	ssh2_pkt_getstring(ssh, &str, &len);    /* client->server mac */
	for (i = 0; i < s->nmacs; i++) {
	    if (in_commasep_string(s->maclist[i]->name, str, len)) {
		s->csmac_tobe = s->maclist[i];
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124


4125
4126
4127


4128
4129
4130
4131



4132
4133
4134
4135
4136



4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4114
4115
4116
4117
4118
4119
4120




4121
4122



4123
4124




4125
4126
4127





4128
4129
4130




4131
4132
4133
4134
4135
4136
4137







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







	ssh2_mkkey(ssh,s->K,s->exchange_hash,ssh->v2_session_id,'B',keyspace);
	ssh->sccipher->setiv(ssh->sc_cipher_ctx, keyspace);
	ssh2_mkkey(ssh,s->K,s->exchange_hash,ssh->v2_session_id,'E',keyspace);
	ssh->csmac->setkey(ssh->cs_mac_ctx, keyspace);
	ssh2_mkkey(ssh,s->K,s->exchange_hash,ssh->v2_session_id,'F',keyspace);
	ssh->scmac->setkey(ssh->sc_mac_ctx, keyspace);
    }
    {
	char buf[256];
	sprintf(buf, "Initialised %.200s client->server encryption",
		ssh->cscipher->text_name);
    logeventf(ssh, "Initialised %.200s client->server encryption",
	      ssh->cscipher->text_name);
	logevent(buf);
	sprintf(buf, "Initialised %.200s server->client encryption",
		ssh->sccipher->text_name);
    logeventf(ssh, "Initialised %.200s server->client encryption",
	      ssh->sccipher->text_name);
	logevent(buf);
	if (ssh->cscomp->text_name) {
	    sprintf(buf, "Initialised %.200s compression",
		    ssh->cscomp->text_name);
    if (ssh->cscomp->text_name)
	logeventf(ssh, "Initialised %s compression",
		  ssh->cscomp->text_name);
	    logevent(buf);
	}
	if (ssh->sccomp->text_name) {
	    sprintf(buf, "Initialised %.200s decompression",
		    ssh->sccomp->text_name);
    if (ssh->sccomp->text_name)
	logeventf(ssh, "Initialised %s decompression",
		  ssh->sccomp->text_name);
	    logevent(buf);
	}
    }


    /*
     * If this is the first key exchange phase, we must pass the
     * SSH2_MSG_NEWKEYS packet to the next layer, not because it
     * wants to see it but because it will need time to initialise
     * itself before it sees an actual packet. In subsequent key
     * exchange phases, we don't pass SSH2_MSG_NEWKEYS on, because
4347
4348
4349
4350
4351
4352
4353
4354

4355
4356
4357
4358

4359

4360
4361
4362
4363
4364
4365
4366
4337
4338
4339
4340
4341
4342
4343

4344
4345
4346
4347

4348
4349
4350
4351
4352
4353
4354
4355
4356
4357







-
+



-
+

+







		} while (ret == 0);
		if (ret < 0)
		    cleanup_exit(0);
		c_write_str(ssh, "\r\n");
	    }
	    s->username[strcspn(s->username, "\n\r")] = '\0';
	} else {
	    char stuff[200];
	    char *stuff;
	    strncpy(s->username, cfg.username, sizeof(s->username));
	    s->username[sizeof(s->username)-1] = '\0';
	    if ((flags & FLAG_VERBOSE) || (flags & FLAG_INTERACTIVE)) {
		sprintf(stuff, "Using username \"%s\".\r\n", s->username);
		stuff = dupprintf("Using username \"%s\".\r\n", s->username);
		c_write_str(ssh, stuff);
		sfree(stuff);
	    }
	}
	s->got_username = TRUE;

	/*
	 * Send an authentication request using method "none": (a)
	 * just in case it succeeds, and (b) so that we know what
4388
4389
4390
4391
4392
4393
4394
4395

4396
4397
4398
4399
4400



4401

4402
4403
4404
4405
4406
4407
4408
4379
4380
4381
4382
4383
4384
4385

4386
4387
4388
4389


4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401







-
+



-
-
+
+
+

+







		      "Reading private key file \"%.150s\"", cfg.keyfile);
	    keytype = key_type(cfg.keyfile);
	    if (keytype == SSH_KEYTYPE_SSH2) {
		s->publickey_blob =
		    ssh2_userkey_loadpub(cfg.keyfile, NULL,
					 &s->publickey_bloblen);
	    } else {
		char msgbuf[256];
		char *msgbuf;
		logeventf(ssh->frontend,
			  "Unable to use this key file (%s)",
			  key_type_to_str(keytype));
		sprintf(msgbuf, "Unable to use key file \"%.150s\" (%s)\r\n",
			cfg.keyfile, key_type_to_str(keytype));
		msgbuf = dupprintf("Unable to use key file \"%.150s\""
				   " (%s)\r\n", cfg.keyfile,
				   key_type_to_str(keytype));
		c_write_str(ssh, msgbuf);
		sfree(msgbuf);
		s->publickey_blob = NULL;
	    }
	} else
	    s->publickey_blob = NULL;

	while (1) {
	    /*
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5101
5102
5103
5104
5105
5106
5107

5108
5109
5110
5111
5112
5113
5114







-







     * Enable port forwardings.
     */
    {
	char type;
	int n;
	int sport,dport,sserv,dserv;
	char sports[256], dports[256], host[256];
	char buf[1024];

	ssh->rportfwds = newtree234(ssh_rportcmp_ssh2);
        /* Add port forwardings. */
	ssh->portfwd_strptr = cfg.portfwd;
	while (*ssh->portfwd_strptr) {
	    type = *ssh->portfwd_strptr++;
	    n = 0;
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147


5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159


5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172







5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183


5184
5185
5186
5187
5188
5189
5190
5191
5192
5193







5194
5195
5196
5197
5198
5199
5200
5201
5130
5131
5132
5133
5134
5135
5136



5137
5138

5139
5140
5141
5142
5143
5144
5145
5146



5147
5148

5149
5150
5151
5152
5153







5154
5155
5156
5157
5158
5159
5160

5161
5162
5163
5164
5165
5166
5167



5168
5169

5170
5171







5172
5173
5174
5175
5176
5177
5178

5179
5180
5181
5182
5183
5184
5185







-
-
-
+
+
-








-
-
-
+
+
-





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







-
-
-
+
+
-


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







	    ssh->portfwd_strptr++;
	    dport = atoi(dports);
	    dserv = 0;
	    if (dport == 0) {
		dserv = 1;
		dport = net_service_lookup(dports);
		if (!dport) {
		    sprintf(buf,
			    "Service lookup failed for destination port \"%s\"",
			    dports);
		    logeventf(ssh, "Service lookup failed for destination"
			      " port \"%s\"", dports);
		    logevent(buf);
		}
	    }
	    sport = atoi(sports);
	    sserv = 0;
	    if (sport == 0) {
		sserv = 1;
		sport = net_service_lookup(sports);
		if (!sport) {
		    sprintf(buf,
			    "Service lookup failed for source port \"%s\"",
			    sports);
		    logeventf(ssh, "Service lookup failed for source"
			      " port \"%s\"", sports);
		    logevent(buf);
		}
	    }
	    if (sport && dport) {
		if (type == 'L') {
		    pfd_addforward(host, dport, sport, ssh);
		    sprintf(buf, "Local port %.*s%.*s%d%.*s forwarding to"
			    " %s:%.*s%.*s%d%.*s",
			    (int)(sserv ? strlen(sports) : 0), sports,
			    sserv, "(", sport, sserv, ")",
			    host,
			    (int)(dserv ? strlen(dports) : 0), dports,
			    dserv, "(", dport, dserv, ")");
		    logeventf(ssh, "Local port %.*s%.*s%d%.*s forwarding to"
			      " %s:%.*s%.*s%d%.*s",
			      (int)(sserv ? strlen(sports) : 0), sports,
			      sserv, "(", sport, sserv, ")",
			      host,
			      (int)(dserv ? strlen(dports) : 0), dports,
			      dserv, "(", dport, dserv, ")");
		    logevent(buf);
		} else {
		    struct ssh_rportfwd *pf;
		    pf = smalloc(sizeof(*pf));
		    strcpy(pf->dhost, host);
		    pf->dport = dport;
		    pf->sport = sport;
		    if (add234(ssh->rportfwds, pf) != pf) {
			sprintf(buf, 
				"Duplicate remote port forwarding to %s:%d",
				host, dport);
			logeventf(ssh, "Duplicate remote port forwarding"
				  " to %s:%d", host, dport);
			logevent(buf);
			sfree(pf);
		    } else {
			sprintf(buf, "Requesting remote port %.*s%.*s%d%.*s"
				" forward to %s:%.*s%.*s%d%.*s",
			    (int)(sserv ? strlen(sports) : 0), sports,
			    sserv, "(", sport, sserv, ")",
			    host,
			    (int)(dserv ? strlen(dports) : 0), dports,
			    dserv, "(", dport, dserv, ")");
			logeventf(ssh, "Requesting remote port %.*s%.*s%d%.*s"
				  " forward to %s:%.*s%.*s%d%.*s",
				  (int)(sserv ? strlen(sports) : 0), sports,
				  sserv, "(", sport, sserv, ")",
				  host,
				  (int)(dserv ? strlen(dports) : 0), dports,
				  dserv, "(", dport, dserv, ")");
			logevent(buf);
			ssh2_pkt_init(ssh, SSH2_MSG_GLOBAL_REQUEST);
			ssh2_pkt_addstring(ssh, "tcpip-forward");
			ssh2_pkt_addbool(ssh, 1);/* want reply */
			if (cfg.rport_acceptall)
			    ssh2_pkt_addstring(ssh, "0.0.0.0");
			else
			    ssh2_pkt_addstring(ssh, "127.0.0.1");
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733


5734
5735
5736

5737
5738
5739
5740
5741
5742
5743
5744
5708
5709
5710
5711
5712
5713
5714



5715
5716

5717

5718

5719
5720
5721
5722
5723
5724
5725







-
-
-
+
+
-

-
+
-







		    pf.sport = ssh2_pkt_getuint32(ssh);
		    realpf = find234(ssh->rportfwds, &pf, NULL);
		    if (realpf == NULL) {
			error = "Remote port is not recognised";
		    } else {
			char *e = pfd_newconnect(&c->u.pfd.s, realpf->dhost,
						 realpf->dport, c);
			char buf[1024];
			sprintf(buf, "Received remote port open request for %s:%d",
				realpf->dhost, realpf->dport);
			logeventf(ssh, "Received remote port open request"
				  " for %s:%d", realpf->dhost, realpf->dport);
			logevent(buf);
			if (e != NULL) {
			    sprintf(buf, "Port open failed: %s", e);
			    logeventf(ssh, "Port open failed: %s", e);
			    logevent(buf);
			    error = "Port open failed";
			} else {
			    logevent("Forwarded port opened successfully");
			    c->type = CHAN_SOCKDATA;
			}
		    }
		} else if (typelen == 22 &&
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097

6098
6099
6100
6101
6102
6103
6104
6105
6069
6070
6071
6072
6073
6074
6075

6076

6077

6078
6079
6080
6081
6082
6083
6084







-

-
+
-







    }
}

void ssh_send_port_open(void *channel, char *hostname, int port, char *org)
{
    struct ssh_channel *c = (struct ssh_channel *)channel;
    Ssh ssh = c->ssh;
    char buf[1024];

    sprintf(buf, "Opening forwarded connection to %.512s:%d", hostname, port);
    logeventf(ssh, "Opening forwarded connection to %s:%d", hostname, port);
    logevent(buf);

    if (ssh->version == 1) {
	send_packet(ssh, SSH1_MSG_PORT_OPEN,
		    PKT_INT, c->localid,
		    PKT_STR, hostname,
		    PKT_INT, port,
		    //PKT_STR, <org:orgport>,