version 1.311, 2011/06/22 22:08:42 |
version 1.312, 2011/09/09 22:46:44 |
|
|
buffer_init(&c->output); |
buffer_init(&c->output); |
buffer_init(&c->extended); |
buffer_init(&c->extended); |
c->path = NULL; |
c->path = NULL; |
|
c->listening_addr = NULL; |
|
c->listening_port = 0; |
c->ostate = CHAN_OUTPUT_OPEN; |
c->ostate = CHAN_OUTPUT_OPEN; |
c->istate = CHAN_INPUT_OPEN; |
c->istate = CHAN_INPUT_OPEN; |
c->flags = 0; |
c->flags = 0; |
|
|
xfree(c->path); |
xfree(c->path); |
c->path = NULL; |
c->path = NULL; |
} |
} |
|
if (c->listening_addr) { |
|
xfree(c->listening_addr); |
|
c->listening_addr = NULL; |
|
} |
while ((cc = TAILQ_FIRST(&c->status_confirms)) != NULL) { |
while ((cc = TAILQ_FIRST(&c->status_confirms)) != NULL) { |
if (cc->abandon_cb != NULL) |
if (cc->abandon_cb != NULL) |
cc->abandon_cb(c, cc->ctx); |
cc->abandon_cb(c, cc->ctx); |
|
|
IPv4or6 = af; |
IPv4or6 = af; |
} |
} |
|
|
|
|
|
/* |
|
* Determine whether or not a port forward listens to loopback, the |
|
* specified address or wildcard. On the client, a specified bind |
|
* address will always override gateway_ports. On the server, a |
|
* gateway_ports of 1 (``yes'') will override the client's specification |
|
* and force a wildcard bind, whereas a value of 2 (``clientspecified'') |
|
* will bind to whatever address the client asked for. |
|
* |
|
* Special-case listen_addrs are: |
|
* |
|
* "0.0.0.0" -> wildcard v4/v6 if SSH_OLD_FORWARD_ADDR |
|
* "" (empty string), "*" -> wildcard v4/v6 |
|
* "localhost" -> loopback v4/v6 |
|
*/ |
|
static const char * |
|
channel_fwd_bind_addr(const char *listen_addr, int *wildcardp, |
|
int is_client, int gateway_ports) |
|
{ |
|
const char *addr = NULL; |
|
int wildcard = 0; |
|
|
|
if (listen_addr == NULL) { |
|
/* No address specified: default to gateway_ports setting */ |
|
if (gateway_ports) |
|
wildcard = 1; |
|
} else if (gateway_ports || is_client) { |
|
if (((datafellows & SSH_OLD_FORWARD_ADDR) && |
|
strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) || |
|
*listen_addr == '\0' || strcmp(listen_addr, "*") == 0 || |
|
(!is_client && gateway_ports == 1)) |
|
wildcard = 1; |
|
else if (strcmp(listen_addr, "localhost") != 0) |
|
addr = listen_addr; |
|
} |
|
if (wildcardp != NULL) |
|
*wildcardp = wildcard; |
|
return addr; |
|
} |
|
|
static int |
static int |
channel_setup_fwd_listener(int type, const char *listen_addr, |
channel_setup_fwd_listener(int type, const char *listen_addr, |
u_short listen_port, int *allocated_listen_port, |
u_short listen_port, int *allocated_listen_port, |
|
|
return 0; |
return 0; |
} |
} |
|
|
/* |
/* Determine the bind address, cf. channel_fwd_bind_addr() comment */ |
* Determine whether or not a port forward listens to loopback, |
addr = channel_fwd_bind_addr(listen_addr, &wildcard, |
* specified address or wildcard. On the client, a specified bind |
is_client, gateway_ports); |
* address will always override gateway_ports. On the server, a |
|
* gateway_ports of 1 (``yes'') will override the client's |
|
* specification and force a wildcard bind, whereas a value of 2 |
|
* (``clientspecified'') will bind to whatever address the client |
|
* asked for. |
|
* |
|
* Special-case listen_addrs are: |
|
* |
|
* "0.0.0.0" -> wildcard v4/v6 if SSH_OLD_FORWARD_ADDR |
|
* "" (empty string), "*" -> wildcard v4/v6 |
|
* "localhost" -> loopback v4/v6 |
|
*/ |
|
addr = NULL; |
|
if (listen_addr == NULL) { |
|
/* No address specified: default to gateway_ports setting */ |
|
if (gateway_ports) |
|
wildcard = 1; |
|
} else if (gateway_ports || is_client) { |
|
if (((datafellows & SSH_OLD_FORWARD_ADDR) && |
|
strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) || |
|
*listen_addr == '\0' || strcmp(listen_addr, "*") == 0 || |
|
(!is_client && gateway_ports == 1)) |
|
wildcard = 1; |
|
else if (strcmp(listen_addr, "localhost") != 0) |
|
addr = listen_addr; |
|
} |
|
|
|
debug3("channel_setup_fwd_listener: type %d wildcard %d addr %s", |
debug3("channel_setup_fwd_listener: type %d wildcard %d addr %s", |
type, wildcard, (addr == NULL) ? "NULL" : addr); |
type, wildcard, (addr == NULL) ? "NULL" : addr); |
|
|
|
|
c->path = xstrdup(host); |
c->path = xstrdup(host); |
c->host_port = port_to_connect; |
c->host_port = port_to_connect; |
c->listening_port = listen_port; |
c->listening_port = listen_port; |
|
c->listening_addr = addr == NULL ? NULL : xstrdup(addr); |
success = 1; |
success = 1; |
} |
} |
if (success == 0) |
if (success == 0) |
|
|
|
|
for (i = 0; i < channels_alloc; i++) { |
for (i = 0; i < channels_alloc; i++) { |
Channel *c = channels[i]; |
Channel *c = channels[i]; |
|
if (c == NULL || c->type != SSH_CHANNEL_RPORT_LISTENER) |
|
continue; |
|
if (strcmp(c->path, host) == 0 && c->listening_port == port) { |
|
debug2("%s: close channel %d", __func__, i); |
|
channel_free(c); |
|
found = 1; |
|
} |
|
} |
|
|
if (c != NULL && c->type == SSH_CHANNEL_RPORT_LISTENER && |
return (found); |
strcmp(c->path, host) == 0 && c->listening_port == port) { |
} |
|
|
|
int |
|
channel_cancel_lport_listener(const char *lhost, u_short lport, |
|
u_short cport, int gateway_ports) |
|
{ |
|
u_int i; |
|
int found = 0; |
|
const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, gateway_ports); |
|
|
|
for (i = 0; i < channels_alloc; i++) { |
|
Channel *c = channels[i]; |
|
if (c == NULL || c->type != SSH_CHANNEL_PORT_LISTENER) |
|
continue; |
|
if (c->listening_port != lport || c->host_port != cport) |
|
continue; |
|
if ((c->listening_addr == NULL && addr != NULL) || |
|
(c->listening_addr != NULL && addr == NULL)) |
|
continue; |
|
if (addr == NULL || strcmp(c->listening_addr, addr) == 0) { |
debug2("%s: close channel %d", __func__, i); |
debug2("%s: close channel %d", __func__, i); |
channel_free(c); |
channel_free(c); |
found = 1; |
found = 1; |
|
|
} |
} |
|
|
/* |
/* |
|
* Translate the requested rfwd listen host to something usable for |
|
* this server. |
|
*/ |
|
static const char * |
|
channel_rfwd_bind_host(const char *listen_host) |
|
{ |
|
if (listen_host == NULL) { |
|
if (datafellows & SSH_BUG_RFWD_ADDR) |
|
return "127.0.0.1"; |
|
else |
|
return "localhost"; |
|
} else if (*listen_host == '\0' || strcmp(listen_host, "*") == 0) { |
|
if (datafellows & SSH_BUG_RFWD_ADDR) |
|
return "0.0.0.0"; |
|
else |
|
return ""; |
|
} else |
|
return listen_host; |
|
} |
|
|
|
/* |
* Initiate forwarding of connections to port "port" on remote host through |
* Initiate forwarding of connections to port "port" on remote host through |
* the secure channel to host:port from local side. |
* the secure channel to host:port from local side. |
*/ |
*/ |
|
|
int |
int |
channel_request_remote_forwarding(const char *listen_host, u_short listen_port, |
channel_request_remote_forwarding(const char *listen_host, u_short listen_port, |
const char *host_to_connect, u_short port_to_connect) |
const char *host_to_connect, u_short port_to_connect) |
|
|
|
|
/* Send the forward request to the remote side. */ |
/* Send the forward request to the remote side. */ |
if (compat20) { |
if (compat20) { |
const char *address_to_bind; |
|
if (listen_host == NULL) { |
|
if (datafellows & SSH_BUG_RFWD_ADDR) |
|
address_to_bind = "127.0.0.1"; |
|
else |
|
address_to_bind = "localhost"; |
|
} else if (*listen_host == '\0' || |
|
strcmp(listen_host, "*") == 0) { |
|
if (datafellows & SSH_BUG_RFWD_ADDR) |
|
address_to_bind = "0.0.0.0"; |
|
else |
|
address_to_bind = ""; |
|
} else |
|
address_to_bind = listen_host; |
|
|
|
packet_start(SSH2_MSG_GLOBAL_REQUEST); |
packet_start(SSH2_MSG_GLOBAL_REQUEST); |
packet_put_cstring("tcpip-forward"); |
packet_put_cstring("tcpip-forward"); |
packet_put_char(1); /* boolean: want reply */ |
packet_put_char(1); /* boolean: want reply */ |
packet_put_cstring(address_to_bind); |
packet_put_cstring(channel_rfwd_bind_host(listen_host)); |
packet_put_int(listen_port); |
packet_put_int(listen_port); |
packet_send(); |
packet_send(); |
packet_write_wait(); |
packet_write_wait(); |
|
|
* Request cancellation of remote forwarding of connection host:port from |
* Request cancellation of remote forwarding of connection host:port from |
* local side. |
* local side. |
*/ |
*/ |
void |
int |
channel_request_rforward_cancel(const char *host, u_short port) |
channel_request_rforward_cancel(const char *host, u_short port) |
{ |
{ |
int i; |
int i; |
|
|
if (!compat20) |
if (!compat20) |
return; |
return -1; |
|
|
for (i = 0; i < num_permitted_opens; i++) { |
for (i = 0; i < num_permitted_opens; i++) { |
if (permitted_opens[i].host_to_connect != NULL && |
if (permitted_opens[i].host_to_connect != NULL && |
|
|
} |
} |
if (i >= num_permitted_opens) { |
if (i >= num_permitted_opens) { |
debug("%s: requested forward not found", __func__); |
debug("%s: requested forward not found", __func__); |
return; |
return -1; |
} |
} |
packet_start(SSH2_MSG_GLOBAL_REQUEST); |
packet_start(SSH2_MSG_GLOBAL_REQUEST); |
packet_put_cstring("cancel-tcpip-forward"); |
packet_put_cstring("cancel-tcpip-forward"); |
packet_put_char(0); |
packet_put_char(0); |
packet_put_cstring(host == NULL ? "" : host); |
packet_put_cstring(channel_rfwd_bind_host(host)); |
packet_put_int(port); |
packet_put_int(port); |
packet_send(); |
packet_send(); |
|
|
|
|
permitted_opens[i].port_to_connect = 0; |
permitted_opens[i].port_to_connect = 0; |
xfree(permitted_opens[i].host_to_connect); |
xfree(permitted_opens[i].host_to_connect); |
permitted_opens[i].host_to_connect = NULL; |
permitted_opens[i].host_to_connect = NULL; |
|
|
|
return 0; |
} |
} |
|
|
/* |
/* |