Diff

Differences From Artifact [f5d23fad04]:

To Artifact [0eb425b572]:


517
518
519
520
521
522
523

524
525
526
527
528
529
530
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531







+







 */
struct ssh_portfwd {
    int keep;
    int type;
    unsigned sport, dport;
    char *saddr, *daddr;
    struct ssh_rportfwd *remote;
    int addressfamily;
    void *local;
};
#define free_portfwd(pf) ( \
    ((pf) ? (sfree((pf)->saddr), sfree((pf)->daddr)) : (void)0 ), sfree(pf) )

struct Packet {
    long length;
2445
2446
2447
2448
2449
2450
2451
2452
2453





2454
2455
2456
2457
2458
2459
2460
2446
2447
2448
2449
2450
2451
2452


2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464







-
-
+
+
+
+
+







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

    /*
     * Try to find host.
     */
    logeventf(ssh, "Looking up host \"%s\"", host);
    addr = name_lookup(host, port, realhost, &ssh->cfg);
    logeventf(ssh, "Looking up host \"%s\"%s", host,
	      (ssh->cfg.addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" :
	       (ssh->cfg.addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" : "")));
    addr = name_lookup(host, port, realhost, &ssh->cfg,
		       ssh->cfg.addressfamily);
    if ((err = sk_addr_error(addr)) != NULL) {
	sk_addr_free(addr);
	return err;
    }

    /*
     * Open socket.
3662
3663
3664
3665
3666
3667
3668
3669

3670
3671
3672
3673
3674
3675
3676
3666
3667
3668
3669
3670
3671
3672

3673
3674
3675
3676
3677
3678
3679
3680







-
+







	assert(rpf == pf);
	free_rportfwd(pf);
    }
}

static void ssh_setup_portfwd(Ssh ssh, const Config *cfg)
{
    char type;
    char address_family, type;
    int n;
    int sport,dport,sserv,dserv;
    char sports[256], dports[256], saddr[256], host[256];
    const char *portfwd_strptr;

    portfwd_strptr = cfg->portfwd;

3686
3687
3688
3689
3690
3691
3692










3693




3694

3695
3696
3697
3698
3699
3700
3701
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







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

+







	struct ssh_portfwd *epf;
	int i;
	for (i = 0; (epf = index234(ssh->portfwds, i)) != NULL; i++)
	    epf->keep = FALSE;
    }

    while (*portfwd_strptr) {
	address_family = 'A';
	type = 'L';
	while (*portfwd_strptr && *portfwd_strptr != '\t') {
	    if (*portfwd_strptr == 'A' ||
		*portfwd_strptr == '4' ||
		*portfwd_strptr == '6')
		address_family = *portfwd_strptr;
	    else if (*portfwd_strptr == 'L' ||
		*portfwd_strptr == 'R' ||
		*portfwd_strptr == 'D')
	type = *portfwd_strptr++;
		type = *portfwd_strptr;
	    portfwd_strptr++;
	}

	saddr[0] = '\0';

	n = 0;
	while (*portfwd_strptr && *portfwd_strptr != '\t') {
	    if (*portfwd_strptr == ':') {
		/*
		 * We've seen a colon in the middle of the
		 * source port number. This means that
		 * everything we've seen until now is the
3770
3771
3772
3773
3774
3775
3776



3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798




3799
3800
3801
3802
3803





3804
3805
3806
3807
3808
3809
3810
3811



3812
3813
3814
3815




3816

3817
3818
3819
3820
3821
3822
3823
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816



3817
3818
3819
3820





3821
3822
3823
3824
3825
3826
3827
3828
3829
3830



3831
3832
3833




3834
3835
3836
3837

3838
3839
3840
3841
3842
3843
3844
3845







+
+
+



















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





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







	    pfrec->type = type;
	    pfrec->saddr = *saddr ? dupstr(saddr) : NULL;
	    pfrec->sport = sport;
	    pfrec->daddr = dupstr(host);
	    pfrec->dport = dport;
	    pfrec->local = NULL;
	    pfrec->remote = NULL;
	    pfrec->addressfamily = (address_family == '4' ? ADDRTYPE_IPV4 :
				    address_family == '6' ? ADDRTYPE_IPV6 :
				    ADDRTYPE_UNSPEC);

	    epfrec = add234(ssh->portfwds, pfrec);
	    if (epfrec != pfrec) {
		/*
		 * We already have a port forwarding with precisely
		 * these parameters. Hence, no need to do anything;
		 * simply tag the existing one as `keep'.
		 */
		epfrec->keep = TRUE;
		free_portfwd(pfrec);
	    } else if (type == 'L') {
		/* Verbose description of the destination port */
		char *dportdesc = dupprintf("%s:%.*s%.*s%d%.*s",
					    host,
					    (int)(dserv ? strlen(dports) : 0), dports,
					    dserv, "(", dport, dserv, ")");
		const char *err = pfd_addforward(host, dport,
						 *saddr ? saddr : NULL,
						 sport, ssh, &ssh->cfg,
						 &pfrec->local);
		if (err) {
		    logeventf(ssh, "Local port %s forward to %s"
						 &pfrec->local,
						 pfrec->addressfamily);

		logeventf(ssh, "Local %sport %s forward to %s%s%s",
			      " failed: %s", sportdesc, dportdesc, err);
		} else {
		    logeventf(ssh, "Local port %s forwarding to %s",
			      sportdesc, dportdesc);
		}
			  pfrec->addressfamily == ADDRTYPE_IPV4 ? "IPv4 " :
			  pfrec->addressfamily == ADDRTYPE_IPV6 ? "IPv6 " : "",
			  sportdesc, dportdesc,
			  err ? " failed: " : "", err);

		sfree(dportdesc);
	    } else if (type == 'D') {
		const char *err = pfd_addforward(NULL, -1,
						 *saddr ? saddr : NULL,
						 sport, ssh, &ssh->cfg,
						 &pfrec->local);
		if (err) {
		    logeventf(ssh, "Local port %s SOCKS dynamic forward"
						 &pfrec->local,
						 pfrec->addressfamily);

			      " setup failed: %s", sportdesc, err);
		} else {
		    logeventf(ssh, "Local port %s doing SOCKS"
			      " dynamic forwarding", sportdesc);
			logeventf(ssh, "Local %sport %s SOCKS dynamic forward%s%s",
				  pfrec->addressfamily == ADDRTYPE_IPV4 ? "IPv4 " :
				  pfrec->addressfamily == ADDRTYPE_IPV6 ? "IPv6 " : "",
				  sportdesc,
		}
				  err ? " setup failed: " : "", err);
	    } else {
		struct ssh_rportfwd *pf;

		/*
		 * Ensure the remote port forwardings tree exists.
		 */
		if (!ssh->rportfwds) {
4041
4042
4043
4044
4045
4046
4047
4048

4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064

4065
4066

4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077

4078
4079
4080
4081
4082
4083
4084
4063
4064
4065
4066
4067
4068
4069

4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088

4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099

4100
4101
4102
4103
4104
4105
4106
4107







-
+
















+

-
+










-
+







}

static void ssh1_msg_port_open(Ssh ssh, struct Packet *pktin)
{
    /* Remote side is trying to open a channel to talk to a
     * forwarded port. Give them back a local channel number. */
    struct ssh_channel *c;
    struct ssh_rportfwd pf;
    struct ssh_rportfwd pf, *pfp;
    int remoteid;
    int hostsize, port;
    char *host, buf[1024];
    const char *e;
    c = snew(struct ssh_channel);
    c->ssh = ssh;

    remoteid = ssh_pkt_getuint32(pktin);
    ssh_pkt_getstring(pktin, &host, &hostsize);
    port = ssh_pkt_getuint32(pktin);

    if (hostsize >= lenof(pf.dhost))
	hostsize = lenof(pf.dhost)-1;
    memcpy(pf.dhost, host, hostsize);
    pf.dhost[hostsize] = '\0';
    pf.dport = port;
    pfp = find234(ssh->rportfwds, &pf, NULL);

    if (find234(ssh->rportfwds, &pf, NULL) == NULL) {
    if (pfp == NULL) {
	sprintf(buf, "Rejected remote port open request for %s:%d",
		pf.dhost, port);
	logevent(buf);
	send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,
		    PKT_INT, remoteid, PKT_END);
    } else {
	sprintf(buf, "Received remote port open request for %s:%d",
		pf.dhost, port);
	logevent(buf);
	e = pfd_newconnect(&c->u.pfd.s, pf.dhost, port,
			   c, &ssh->cfg);
			   c, &ssh->cfg, pfp->pfrec->addressfamily);
	if (e != NULL) {
	    char buf[256];
	    sprintf(buf, "Port open failed: %s", e);
	    logevent(buf);
	    sfree(c);
	    send_packet(ssh, SSH1_MSG_CHANNEL_OPEN_FAILURE,
			PKT_INT, remoteid, PKT_END);
5795
5796
5797
5798
5799
5800
5801
5802


5803
5804
5805
5806
5807
5808
5809
5818
5819
5820
5821
5822
5823
5824

5825
5826
5827
5828
5829
5830
5831
5832
5833







-
+
+







		  "from %s:%d", pf.sport, peeraddr, peerport);
	if (realpf == NULL) {
	    error = "Remote port is not recognised";
	} else {
	    const char *e = pfd_newconnect(&c->u.pfd.s,
					   realpf->dhost,
					   realpf->dport, c,
					   &ssh->cfg);
					   &ssh->cfg,
					   realpf->pfrec->addressfamily);
	    logeventf(ssh, "Attempting to forward remote port to "
		      "%s:%d", realpf->dhost, realpf->dport);
	    if (e != NULL) {
		logeventf(ssh, "Port open failed: %s", e);
		error = "Port open failed";
	    } else {
		logevent("Forwarded port opened successfully");