diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2000-11-06 23:04:57 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2000-11-06 23:04:57 +0000 |
commit | fc999bd26244950d23a7403daf9c0488767c5b62 (patch) | |
tree | 80de5cffde33e213d3505e40e92ef1588d097a08 | |
parent | 4decdb614cdb61c05ab0fd1b10fc23405a572e66 (diff) |
agent forwarding and -R for ssh2, based on work from jhuuskon@messi.uku.fi
-rw-r--r-- | usr.bin/ssh/channels.c | 160 | ||||
-rw-r--r-- | usr.bin/ssh/channels.h | 18 | ||||
-rw-r--r-- | usr.bin/ssh/clientloop.c | 122 | ||||
-rw-r--r-- | usr.bin/ssh/nchan.c | 6 | ||||
-rw-r--r-- | usr.bin/ssh/serverloop.c | 128 | ||||
-rw-r--r-- | usr.bin/ssh/session.c | 17 | ||||
-rw-r--r-- | usr.bin/ssh/ssh.c | 111 |
7 files changed, 403 insertions, 159 deletions
diff --git a/usr.bin/ssh/channels.c b/usr.bin/ssh/channels.c index 81bd71598f1..5f82a56d022 100644 --- a/usr.bin/ssh/channels.c +++ b/usr.bin/ssh/channels.c @@ -40,7 +40,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: channels.c,v 1.72 2000/10/27 07:48:22 markus Exp $"); +RCSID("$OpenBSD: channels.c,v 1.73 2000/11/06 23:04:55 markus Exp $"); #include "ssh.h" #include "packet.h" @@ -588,9 +588,12 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset) struct sockaddr addr; int newsock, newch; socklen_t addrlen; - char buf[1024], *remote_hostname; + char buf[1024], *remote_hostname, *rtype; int remote_port; + rtype = (c->type == SSH_CHANNEL_RPORT_LISTENER) ? + "forwarded-tcpip" : "direct-tcpip"; + if (FD_ISSET(c->sock, readset)) { debug("Connection to port %d forwarding " "to %.100s port %d requested.", @@ -608,19 +611,26 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset) "connect from %.200s port %d", c->listening_port, c->path, c->host_port, remote_hostname, remote_port); - newch = channel_new("direct-tcpip", + + newch = channel_new(rtype, SSH_CHANNEL_OPENING, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, 0, xstrdup(buf), 1); if (compat20) { packet_start(SSH2_MSG_CHANNEL_OPEN); - packet_put_cstring("direct-tcpip"); + packet_put_cstring(rtype); packet_put_int(newch); packet_put_int(c->local_window_max); packet_put_int(c->local_maxpacket); - /* target host and port */ - packet_put_string(c->path, strlen(c->path)); - packet_put_int(c->host_port); + if (c->type == SSH_CHANNEL_RPORT_LISTENER) { + /* listen address, port */ + packet_put_string(c->path, strlen(c->path)); + packet_put_int(c->listening_port); + } else { + /* target host, port */ + packet_put_string(c->path, strlen(c->path)); + packet_put_int(c->host_port); + } /* originator host and port */ packet_put_cstring(remote_hostname); packet_put_int(remote_port); @@ -657,10 +667,20 @@ channel_post_auth_listener(Channel *c, fd_set * readset, fd_set * writeset) error("accept from auth socket: %.100s", strerror(errno)); return; } - newch = channel_allocate(SSH_CHANNEL_OPENING, newsock, - xstrdup("accepted auth socket")); - packet_start(SSH_SMSG_AGENT_OPEN); - packet_put_int(newch); + newch = channel_new("accepted auth socket", + SSH_CHANNEL_OPENING, newsock, newsock, -1, + c->local_window_max, c->local_maxpacket, + 0, xstrdup("accepted auth socket"), 1); + if (compat20) { + packet_start(SSH2_MSG_CHANNEL_OPEN); + packet_put_cstring("auth-agent@openssh.com"); + packet_put_int(newch); + packet_put_int(c->local_window_max); + packet_put_int(c->local_maxpacket); + } else { + packet_start(SSH_SMSG_AGENT_OPEN); + packet_put_int(newch); + } packet_send(); } } @@ -820,11 +840,15 @@ channel_handler_init_20(void) channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_20; channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; + channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener; channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; + channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_2; channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; + channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener; channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; + channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; } void @@ -1326,6 +1350,7 @@ channel_stop_listening() channel_free(i); break; case SSH_CHANNEL_PORT_LISTENER: + case SSH_CHANNEL_RPORT_LISTENER: case SSH_CHANNEL_X11_LISTENER: close(channels[i].sock); channel_free(i); @@ -1369,6 +1394,7 @@ channel_still_open() case SSH_CHANNEL_FREE: case SSH_CHANNEL_X11_LISTENER: case SSH_CHANNEL_PORT_LISTENER: + case SSH_CHANNEL_RPORT_LISTENER: case SSH_CHANNEL_CLOSED: case SSH_CHANNEL_AUTH_SOCKET: continue; @@ -1414,6 +1440,7 @@ channel_open_message() case SSH_CHANNEL_FREE: case SSH_CHANNEL_X11_LISTENER: case SSH_CHANNEL_PORT_LISTENER: + case SSH_CHANNEL_RPORT_LISTENER: case SSH_CHANNEL_CLOSED: case SSH_CHANNEL_AUTH_SOCKET: continue; @@ -1446,19 +1473,44 @@ channel_open_message() * Initiate forwarding of connections to local port "port" through the secure * channel to host:port from remote side. */ +void +channel_request_local_forwarding(u_short listen_port, const char *host_to_connect, + u_short port_to_connect, int gateway_ports) +{ + channel_request_forwarding( + NULL, listen_port, + host_to_connect, port_to_connect, + gateway_ports, /*remote_fwd*/ 0); +} +/* + * If 'remote_fwd' is true we have a '-R style' listener for protocol 2 + * (SSH_CHANNEL_RPORT_LISTENER). + */ void -channel_request_local_forwarding(u_short port, const char *host, - u_short host_port, int gateway_ports) +channel_request_forwarding( + const char *listen_address, u_short listen_port, + const char *host_to_connect, u_short port_to_connect, + int gateway_ports, int remote_fwd) { - int success, ch, sock, on = 1; + int success, ch, sock, on = 1, ctype; struct addrinfo hints, *ai, *aitop; char ntop[NI_MAXHOST], strport[NI_MAXSERV]; + const char *host; struct linger linger; + if (remote_fwd) { + host = listen_address; + ctype = SSH_CHANNEL_RPORT_LISTENER; + } else { + host = host_to_connect; + ctype =SSH_CHANNEL_PORT_LISTENER; + } + if (strlen(host) > sizeof(channels[0].path) - 1) packet_disconnect("Forward host name too long."); + /* XXX listen_address is currently ignored */ /* * getaddrinfo returns a loopback address if the hostname is * set to NULL and hints.ai_flags is not AI_PASSIVE @@ -1467,7 +1519,7 @@ channel_request_local_forwarding(u_short port, const char *host, hints.ai_family = IPv4or6; hints.ai_flags = gateway_ports ? AI_PASSIVE : 0; hints.ai_socktype = SOCK_STREAM; - snprintf(strport, sizeof strport, "%d", port); + snprintf(strport, sizeof strport, "%d", listen_port); if (getaddrinfo(NULL, strport, &hints, &aitop) != 0) packet_disconnect("getaddrinfo: fatal error"); @@ -1477,7 +1529,7 @@ channel_request_local_forwarding(u_short port, const char *host, continue; if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { - error("channel_request_local_forwarding: getnameinfo failed"); + error("channel_request_forwarding: getnameinfo failed"); continue; } /* Create a port to listen for the host. */ @@ -1511,18 +1563,16 @@ channel_request_local_forwarding(u_short port, const char *host, continue; } /* Allocate a channel number for the socket. */ - ch = channel_new( - "port listener", SSH_CHANNEL_PORT_LISTENER, - sock, sock, -1, + ch = channel_new("port listener", ctype, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, xstrdup("port listener"), 1); strlcpy(channels[ch].path, host, sizeof(channels[ch].path)); - channels[ch].host_port = host_port; - channels[ch].listening_port = port; + channels[ch].host_port = port_to_connect; + channels[ch].listening_port = listen_port; success = 1; } if (success == 0) - packet_disconnect("cannot listen port: %d", port); + packet_disconnect("cannot listen port: %d", listen_port); /*XXX ?disconnect? */ freeaddrinfo(aitop); } @@ -1532,19 +1582,15 @@ channel_request_local_forwarding(u_short port, const char *host, */ void -channel_request_remote_forwarding(u_short listen_port, const char *host_to_connect, - u_short port_to_connect) +channel_request_remote_forwarding(u_short listen_port, + const char *host_to_connect, u_short port_to_connect) { - int payload_len; + int payload_len, type, success = 0; + /* Record locally that connection to this host/port is permitted. */ if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION) fatal("channel_request_remote_forwarding: too many forwards"); - permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host_to_connect); - permitted_opens[num_permitted_opens].port_to_connect = port_to_connect; - permitted_opens[num_permitted_opens].listen_port = listen_port; - num_permitted_opens++; - /* Send the forward request to the remote side. */ if (compat20) { const char *address_to_bind = "0.0.0.0"; @@ -1553,6 +1599,10 @@ channel_request_remote_forwarding(u_short listen_port, const char *host_to_conne packet_put_char(0); /* boolean: want reply */ packet_put_cstring(address_to_bind); packet_put_int(listen_port); + packet_send(); + packet_write_wait(); + /* Assume that server accepts the request */ + success = 1; } else { packet_start(SSH_CMSG_PORT_FORWARD_REQUEST); packet_put_int(listen_port); @@ -1560,11 +1610,27 @@ channel_request_remote_forwarding(u_short listen_port, const char *host_to_conne packet_put_int(port_to_connect); packet_send(); packet_write_wait(); - /* - * Wait for response from the remote side. It will send a disconnect - * message on failure, and we will never see it here. - */ - packet_read_expect(&payload_len, SSH_SMSG_SUCCESS); + + /* Wait for response from the remote side. */ + type = packet_read(&payload_len); + switch (type) { + case SSH_SMSG_SUCCESS: + success = 1; + break; + case SSH_SMSG_FAILURE: + log("Warning: Server denied remote port forwarding."); + break; + default: + /* Unknown packet */ + packet_disconnect("Protocol error for port forward request:" + "received packet type %d.", type); + } + } + if (success) { + permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host_to_connect); + permitted_opens[num_permitted_opens].port_to_connect = port_to_connect; + permitted_opens[num_permitted_opens].listen_port = listen_port; + num_permitted_opens++; } } @@ -1592,9 +1658,7 @@ channel_input_port_forward_request(int is_root, int gateway_ports) if (port < IPPORT_RESERVED && !is_root) packet_disconnect("Requested forwarding of port %d but user is not root.", port); - /* - * Initiate forwarding, - */ + /* Initiate forwarding */ channel_request_local_forwarding(port, hostname, host_port, gateway_ports); /* Free the argument string. */ @@ -1650,6 +1714,19 @@ channel_connect_to(const char *host, u_short host_port) /* success */ return sock; } +int +channel_connect_by_listen_adress(u_short listen_port) +{ + int i; + for (i = 0; i < num_permitted_opens; i++) + if (permitted_opens[i].listen_port == listen_port) + return channel_connect_to( + permitted_opens[i].host_to_connect, + permitted_opens[i].port_to_connect); + debug("channel_connect_by_listen_adress: unknown listen_port %d", listen_port); + return -1; +} + /* * This is called after receiving PORT_OPEN message. This attempts to * connect to the given host:port, and sends back CHANNEL_OPEN_CONFIRMATION @@ -2174,8 +2251,11 @@ auth_input_request_forwarding(struct passwd * pw) packet_disconnect("listen: %.100s", strerror(errno)); /* Allocate a channel for the authentication agent socket. */ - newch = channel_allocate(SSH_CHANNEL_AUTH_SOCKET, sock, - xstrdup("auth socket")); + newch = channel_new("auth socket", + SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, + CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, + 0, xstrdup("auth socket"), 1); + strlcpy(channels[newch].path, channel_forwarded_auth_socket_name, sizeof(channels[newch].path)); return 1; diff --git a/usr.bin/ssh/channels.h b/usr.bin/ssh/channels.h index 00526860c3f..8f5e987fc4c 100644 --- a/usr.bin/ssh/channels.h +++ b/usr.bin/ssh/channels.h @@ -32,7 +32,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* RCSID("$OpenBSD: channels.h,v 1.22 2000/10/27 07:48:22 markus Exp $"); */ +/* RCSID("$OpenBSD: channels.h,v 1.23 2000/11/06 23:04:56 markus Exp $"); */ #ifndef CHANNELS_H #define CHANNELS_H @@ -49,7 +49,8 @@ #define SSH_CHANNEL_INPUT_DRAINING 8 /* sending remaining data to conn */ #define SSH_CHANNEL_OUTPUT_DRAINING 9 /* sending remaining data to app */ #define SSH_CHANNEL_LARVAL 10 /* larval session */ -#define SSH_CHANNEL_MAX_TYPE 11 +#define SSH_CHANNEL_RPORT_LISTENER 11 /* Listening to a R-style port */ +#define SSH_CHANNEL_MAX_TYPE 12 /* * Data structure for channel data. This is iniailized in channel_allocate @@ -147,7 +148,6 @@ void channel_input_open_confirmation(int type, int plen, void *ctxt); void channel_input_open_failure(int type, int plen, void *ctxt); void channel_input_port_open(int type, int plen, void *ctxt); void channel_input_window_adjust(int type, int plen, void *ctxt); -void channel_input_open(int type, int plen, void *ctxt); /* Sets specific protocol options. */ void channel_set_options(int hostname_in_open); @@ -202,12 +202,15 @@ char *channel_open_message(void); /* * Initiate forwarding of connections to local port "port" through the secure - * channel to host:port from remote side. This never returns if there was an - * error. + * channel to host:port from remote side. */ void -channel_request_local_forwarding(u_short port, const char *host, - u_short remote_port, int gateway_ports); +channel_request_local_forwarding(u_short listen_port, + const char *host_to_connect, u_short port_to_connect, int gateway_ports); +void +channel_request_forwarding(const char *listen_address, u_short listen_port, + const char *host_to_connect, u_short port_to_connect, int gateway_ports, + int remote_fwd); /* * Initiate forwarding of connections to port "port" on remote host through @@ -288,6 +291,7 @@ void auth_input_open_request(int type, int plen, void *ctxt); /* XXX */ int channel_connect_to(const char *host, u_short host_port); +int channel_connect_by_listen_adress(u_short listen_port); int x11_connect_display(void); #endif diff --git a/usr.bin/ssh/clientloop.c b/usr.bin/ssh/clientloop.c index bccb9be2f85..8f16d2fb9fa 100644 --- a/usr.bin/ssh/clientloop.c +++ b/usr.bin/ssh/clientloop.c @@ -59,7 +59,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: clientloop.c,v 1.39 2000/10/27 07:48:22 markus Exp $"); +RCSID("$OpenBSD: clientloop.c,v 1.40 2000/11/06 23:04:56 markus Exp $"); #include "xmalloc.h" #include "ssh.h" @@ -75,6 +75,10 @@ RCSID("$OpenBSD: clientloop.c,v 1.39 2000/10/27 07:48:22 markus Exp $"); #include "buffer.h" #include "bufaux.h" +#include <openssl/dsa.h> +#include <openssl/rsa.h> +#include "key.h" +#include "authfd.h" /* import options */ extern Options options; @@ -1016,13 +1020,99 @@ client_input_exit_status(int type, int plen, void *ctxt) quit_pending = 1; } +Channel * +client_request_forwarded_tcpip(const char *request_type, int rchan) +{ + Channel* c = NULL; + char *listen_address, *originator_address; + int listen_port, originator_port; + int sock, newch; + + /* Get rest of the packet */ + listen_address = packet_get_string(NULL); + listen_port = packet_get_int(); + originator_address = packet_get_string(NULL); + originator_port = packet_get_int(); + packet_done(); + + debug("client_request_forwarded_tcpip: listen %s port %d, originator %s port %d", + listen_address, listen_port, originator_address, originator_port); + + sock = channel_connect_by_listen_adress(listen_port); + if (sock >= 0) { + newch = channel_new("forwarded-tcpip", + SSH_CHANNEL_OPEN, sock, sock, -1, + CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, + xstrdup(originator_address), 1); + c = channel_lookup(newch); + } + xfree(originator_address); + xfree(listen_address); + return c; +} + +Channel* +client_request_x11(const char *request_type, int rchan) +{ + Channel *c = NULL; + char *originator; + int originator_port; + int sock, newch; + + if (!options.forward_x11) { + error("Warning: ssh server tried X11 forwarding."); + error("Warning: this is probably a break in attempt by a malicious server."); + return NULL; + } + originator = packet_get_string(NULL); + if (datafellows & SSH_BUG_X11FWD) { + debug2("buggy server: x11 request w/o originator_port"); + originator_port = 0; + } else { + originator_port = packet_get_int(); + } + packet_done(); + /* XXX check permission */ + sock = x11_connect_display(); + if (sock >= 0) { + newch = channel_new("x11", + SSH_CHANNEL_X11_OPEN, sock, sock, -1, + CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, + xstrdup("x11"), 1); + c = channel_lookup(newch); + } + xfree(originator); + return c; +} + +Channel* +client_request_agent(const char *request_type, int rchan) +{ + Channel *c = NULL; + int sock, newch; + + if (!options.forward_agent) { + error("Warning: ssh server tried agent forwarding."); + error("Warning: this is probably a break in attempt by a malicious server."); + return NULL; + } + sock = ssh_get_authentication_socket(); + if (sock >= 0) { + newch = channel_new("authentication agent connection", + SSH_CHANNEL_OPEN, sock, sock, -1, + CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, + xstrdup("authentication agent connection"), 1); + c = channel_lookup(newch); + } + return c; +} + /* XXXX move to generic input handler */ void client_input_channel_open(int type, int plen, void *ctxt) { Channel *c = NULL; char *ctype; - int id; unsigned int len; int rchan; int rmaxpack; @@ -1036,28 +1126,12 @@ client_input_channel_open(int type, int plen, void *ctxt) debug("client_input_channel_open: ctype %s rchan %d win %d max %d", ctype, rchan, rwindow, rmaxpack); - if (strcmp(ctype, "x11") == 0 && options.forward_x11) { - int sock; - char *originator; - int originator_port; - originator = packet_get_string(NULL); - if (datafellows & SSH_BUG_X11FWD) { - debug2("buggy server: x11 request w/o originator_port"); - originator_port = 0; - } else { - originator_port = packet_get_int(); - } - packet_done(); - /* XXX check permission */ - xfree(originator); - /* XXX move to channels.c */ - sock = x11_connect_display(); - if (sock >= 0) { - id = channel_new("x11", SSH_CHANNEL_X11_OPEN, - sock, sock, -1, CHAN_X11_WINDOW_DEFAULT, - CHAN_X11_PACKET_DEFAULT, 0, xstrdup("x11"), 1); - c = channel_lookup(id); - } + if (strcmp(ctype, "forwarded-tcpip") == 0) { + c = client_request_forwarded_tcpip(ctype, rchan); + } else if (strcmp(ctype, "x11") == 0) { + c = client_request_x11(ctype, rchan); + } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) { + c = client_request_agent(ctype, rchan); } /* XXX duplicate : */ if (c != NULL) { diff --git a/usr.bin/ssh/nchan.c b/usr.bin/ssh/nchan.c index 30c90b3b2b9..1424fd8da36 100644 --- a/usr.bin/ssh/nchan.c +++ b/usr.bin/ssh/nchan.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: nchan.c,v 1.19 2000/09/07 20:27:52 deraadt Exp $"); +RCSID("$OpenBSD: nchan.c,v 1.20 2000/11/06 23:04:56 markus Exp $"); #include "ssh.h" @@ -253,6 +253,8 @@ chan_send_oclose1(Channel *c) static void chan_delete_if_full_closed1(Channel *c) { + debug3("channel %d: chan_delete_if_full_closed1: istate %d ostate %d", + c->self, c->istate, c->ostate); if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) { debug("channel %d: full closed", c->self); channel_free(c->self); @@ -403,6 +405,8 @@ chan_send_close2(Channel *c) static void chan_delete_if_full_closed2(Channel *c) { + debug3("channel %d: chan_delete_if_full_closed2: istate %d ostate %d", + c->self, c->istate, c->ostate); if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) { if (!(c->flags & CHAN_CLOSE_SENT)) { chan_send_close2(c); diff --git a/usr.bin/ssh/serverloop.c b/usr.bin/ssh/serverloop.c index f63131d2b7b..45999d318de 100644 --- a/usr.bin/ssh/serverloop.c +++ b/usr.bin/ssh/serverloop.c @@ -35,7 +35,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: serverloop.c,v 1.34 2000/10/27 07:32:18 markus Exp $"); +RCSID("$OpenBSD: serverloop.c,v 1.35 2000/11/06 23:04:56 markus Exp $"); #include "xmalloc.h" #include "ssh.h" @@ -50,6 +50,7 @@ RCSID("$OpenBSD: serverloop.c,v 1.34 2000/10/27 07:32:18 markus Exp $"); #include "session.h" #include "dispatch.h" #include "auth-options.h" +#include "auth.h" extern ServerOptions options; @@ -720,10 +721,10 @@ server_input_window_size(int type, int plen, void *ctxt) pty_change_window_size(fdin, row, col, xpixel, ypixel); } -int -input_direct_tcpip(void) +Channel * +server_request_direct_tcpip(char *ctype) { - int sock; + int sock, newch; char *target, *originator; int target_port, originator_port; @@ -733,23 +734,52 @@ input_direct_tcpip(void) originator_port = packet_get_int(); packet_done(); - debug("open direct-tcpip: from %s port %d to %s port %d", + debug("server_request_direct_tcpip: originator %s port %d, target %s port %d", originator, originator_port, target, target_port); /* XXX check permission */ if (no_port_forwarding_flag || !options.allow_tcp_forwarding) { xfree(target); xfree(originator); - return -1; + return NULL; } sock = channel_connect_to(target, target_port); xfree(target); xfree(originator); if (sock < 0) - return -1; - return channel_new("direct-tcpip", SSH_CHANNEL_OPEN, + return NULL; + newch = channel_new(ctype, SSH_CHANNEL_OPEN, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, xstrdup("direct-tcpip"), 1); + return (newch >= 0) ? channel_lookup(newch) : NULL; +} + +Channel * +server_request_session(char *ctype) +{ + int newch; + + debug("input_session_request"); + packet_done(); + /* + * A server session has no fd to read or write until a + * CHANNEL_REQUEST for a shell is made, so we set the type to + * SSH_CHANNEL_LARVAL. Additionally, a callback for handling all + * CHANNEL_REQUEST messages is registered. + */ + newch = channel_new(ctype, SSH_CHANNEL_LARVAL, + -1, -1, -1, 0, CHAN_SES_PACKET_DEFAULT, + 0, xstrdup("server-session"), 1); + if (session_open(newch) == 1) { + channel_register_callback(newch, SSH2_MSG_CHANNEL_REQUEST, + session_input_channel_req, (void *)0); + channel_register_cleanup(newch, session_close_by_channel); + return channel_lookup(newch); + } else { + debug("session open failed, free channel %d", newch); + channel_free(newch); + } + return NULL; } void @@ -757,7 +787,6 @@ server_input_channel_open(int type, int plen, void *ctxt) { Channel *c = NULL; char *ctype; - int id; unsigned int len; int rchan; int rmaxpack; @@ -772,34 +801,12 @@ server_input_channel_open(int type, int plen, void *ctxt) ctype, rchan, rwindow, rmaxpack); if (strcmp(ctype, "session") == 0) { - debug("open session"); - packet_done(); - /* - * A server session has no fd to read or write - * until a CHANNEL_REQUEST for a shell is made, - * so we set the type to SSH_CHANNEL_LARVAL. - * Additionally, a callback for handling all - * CHANNEL_REQUEST messages is registered. - */ - id = channel_new(ctype, SSH_CHANNEL_LARVAL, - -1, -1, -1, 0, CHAN_SES_PACKET_DEFAULT, - 0, xstrdup("server-session"), 1); - if (session_open(id) == 1) { - channel_register_callback(id, SSH2_MSG_CHANNEL_REQUEST, - session_input_channel_req, (void *)0); - channel_register_cleanup(id, session_close_by_channel); - c = channel_lookup(id); - } else { - debug("session open failed, free channel %d", id); - channel_free(id); - } + c = server_request_session(ctype); } else if (strcmp(ctype, "direct-tcpip") == 0) { - id = input_direct_tcpip(); - if (id >= 0) - c = channel_lookup(id); + c = server_request_direct_tcpip(ctype); } if (c != NULL) { - debug("confirm %s", ctype); + debug("server_input_channel_open: confirm %s", ctype); c->remote_id = rchan; c->remote_window = rwindow; c->remote_maxpacket = rmaxpack; @@ -811,7 +818,7 @@ server_input_channel_open(int type, int plen, void *ctxt) packet_put_int(c->local_maxpacket); packet_send(); } else { - debug("failure %s", ctype); + debug("server_input_channel_open: failure %s", ctype); packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); packet_put_int(rchan); packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED); @@ -822,6 +829,56 @@ server_input_channel_open(int type, int plen, void *ctxt) xfree(ctype); } +void +server_input_global_request(int type, int plen, void *ctxt) +{ + char *rtype; + int want_reply; + int success = 0; + + rtype = packet_get_string(NULL); + want_reply = packet_get_char(); + debug("server_input_global_request: rtype %s want_reply %d", rtype, want_reply); + + if (strcmp(rtype, "tcpip-forward") == 0) { + struct passwd *pw; + char *listen_address; + u_short listen_port; + + pw = auth_get_user(); + if (pw == NULL) + fatal("server_input_global_request: no user"); + listen_address = packet_get_string(NULL); /* XXX currently ignored */ + listen_port = (u_short)packet_get_int(); + debug("server_input_global_request: tcpip-forward listen %s port %d", + listen_address, listen_port); + + /* check permissions */ + if (!options.allow_tcp_forwarding || + no_port_forwarding_flag || + (listen_port < IPPORT_RESERVED && pw->pw_uid != 0)) { + success = 0; + packet_send_debug("Server has disabled port forwarding."); + } else { + /* Start listening on the port */ + channel_request_forwarding( + listen_address, listen_port, + /*unspec host_to_connect*/ "<unspec host>", + /*unspec port_to_connect*/ 0, + options.gateway_ports, /*remote*/ 1); + success = 1; + } + xfree(listen_address); + } + if (want_reply) { + packet_start(success ? + SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); + packet_send(); + packet_write_wait(); + } + xfree(rtype); +} + void server_init_dispatch_20() { @@ -836,6 +893,7 @@ server_init_dispatch_20() dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request); dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust); + dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request); } void server_init_dispatch_13() diff --git a/usr.bin/ssh/session.c b/usr.bin/ssh/session.c index 13525f8f79a..1d80828588d 100644 --- a/usr.bin/ssh/session.c +++ b/usr.bin/ssh/session.c @@ -33,7 +33,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: session.c,v 1.42 2000/10/27 07:32:18 markus Exp $"); +RCSID("$OpenBSD: session.c,v 1.43 2000/11/06 23:04:56 markus Exp $"); #include "xmalloc.h" #include "ssh.h" @@ -1416,6 +1416,19 @@ session_exec_req(Session *s) return 1; } +int +session_auth_agent_req(Session *s) +{ + static int called = 0; + packet_done(); + if (called) { + return 0; + } else { + called = 1; + return auth_input_request_forwarding(s->pw); + } +} + void session_input_channel_req(int id, void *arg) { @@ -1452,6 +1465,8 @@ session_input_channel_req(int id, void *arg) success = session_pty_req(s); } else if (strcmp(rtype, "x11-req") == 0) { success = session_x11_req(s); + } else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) { + success = session_auth_agent_req(s); } else if (strcmp(rtype, "subsystem") == 0) { success = session_subsystem_req(s); } diff --git a/usr.bin/ssh/ssh.c b/usr.bin/ssh/ssh.c index f6717262611..179d1bc968e 100644 --- a/usr.bin/ssh/ssh.c +++ b/usr.bin/ssh/ssh.c @@ -39,7 +39,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh.c,v 1.69 2000/10/27 07:32:19 markus Exp $"); +RCSID("$OpenBSD: ssh.c,v 1.70 2000/11/06 23:04:56 markus Exp $"); #include <openssl/evp.h> #include <openssl/dsa.h> @@ -724,16 +724,57 @@ x11_get_proto(char *proto, int proto_len, char *data, int data_len) } } +void +ssh_init_forwarding(void) +{ + int i; + /* Initiate local TCP/IP port forwardings. */ + for (i = 0; i < options.num_local_forwards; i++) { + debug("Connections to local port %d forwarded to remote address %.200s:%d", + options.local_forwards[i].port, + options.local_forwards[i].host, + options.local_forwards[i].host_port); + channel_request_local_forwarding( + options.local_forwards[i].port, + options.local_forwards[i].host, + options.local_forwards[i].host_port, + options.gateway_ports); + } + + /* Initiate remote TCP/IP port forwardings. */ + for (i = 0; i < options.num_remote_forwards; i++) { + debug("Connections to remote port %d forwarded to local address %.200s:%d", + options.remote_forwards[i].port, + options.remote_forwards[i].host, + options.remote_forwards[i].host_port); + channel_request_remote_forwarding( + options.remote_forwards[i].port, + options.remote_forwards[i].host, + options.remote_forwards[i].host_port); + } +} + +void +check_agent_present(void) +{ + if (options.forward_agent) { + /* Clear agent forwarding if we don\'t have an agent. */ + int authfd = ssh_get_authentication_socket(); + if (authfd < 0) + options.forward_agent = 0; + else + ssh_close_authentication_socket(authfd); + } +} + int ssh_session(void) { int type; - int i; int plen; int interactive = 0; int have_tty = 0; struct winsize ws; - int authfd; char *cp; /* Enable compression if requested. */ @@ -817,14 +858,10 @@ ssh_session(void) /* Tell the packet module whether this is an interactive session. */ packet_set_interactive(interactive, options.keepalives); - /* Clear agent forwarding if we don\'t have an agent. */ - authfd = ssh_get_authentication_socket(); - if (authfd < 0) - options.forward_agent = 0; - else - ssh_close_authentication_socket(authfd); /* Request authentication agent forwarding if appropriate. */ + check_agent_present(); + if (options.forward_agent) { debug("Requesting authentication agent forwarding."); auth_request_forwarding(); @@ -835,28 +872,9 @@ ssh_session(void) if (type != SSH_SMSG_SUCCESS) log("Warning: Remote host denied authentication agent forwarding."); } - /* Initiate local TCP/IP port forwardings. */ - for (i = 0; i < options.num_local_forwards; i++) { - debug("Connections to local port %d forwarded to remote address %.200s:%d", - options.local_forwards[i].port, - options.local_forwards[i].host, - options.local_forwards[i].host_port); - channel_request_local_forwarding(options.local_forwards[i].port, - options.local_forwards[i].host, - options.local_forwards[i].host_port, - options.gateway_ports); - } - /* Initiate remote TCP/IP port forwardings. */ - for (i = 0; i < options.num_remote_forwards; i++) { - debug("Connections to remote port %d forwarded to local address %.200s:%d", - options.remote_forwards[i].port, - options.remote_forwards[i].host, - options.remote_forwards[i].host_port); - channel_request_remote_forwarding(options.remote_forwards[i].port, - options.remote_forwards[i].host, - options.remote_forwards[i].host_port); - } + /* Initiate port forwardings. */ + ssh_init_forwarding(); /* If requested, let ssh continue in the background. */ if (fork_after_authentication_flag) @@ -887,27 +905,10 @@ ssh_session(void) return client_loop(have_tty, tty_flag ? options.escape_char : -1, 0); } -void -init_local_fwd(void) -{ - int i; - /* Initiate local TCP/IP port forwardings. */ - for (i = 0; i < options.num_local_forwards; i++) { - debug("Connections to local port %d forwarded to remote address %.200s:%d", - options.local_forwards[i].port, - options.local_forwards[i].host, - options.local_forwards[i].host_port); - channel_request_local_forwarding(options.local_forwards[i].port, - options.local_forwards[i].host, - options.local_forwards[i].host_port, - options.gateway_ports); - } -} - extern void client_set_session_ident(int id); void -client_init(int id, void *arg) +ssh_session2_callback(int id, void *arg) { int len; debug("client_init id %d arg %d", id, (int)arg); @@ -946,6 +947,13 @@ client_init(int id, void *arg) /* XXX wait for reply */ } + check_agent_present(); + if (options.forward_agent) { + debug("Requesting authentication agent forwarding."); + channel_request_start(id, "auth-agent-req@openssh.com", 0); + packet_send(); + } + len = buffer_len(&command); if (len > 0) { if (len > 900) @@ -988,8 +996,8 @@ ssh_session2(void) if (!isatty(err)) set_nonblock(err); - /* should be pre-session */ - init_local_fwd(); + /* XXX should be pre-session */ + ssh_init_forwarding(); /* If requested, let ssh continue in the background. */ if (fork_after_authentication_flag) @@ -1008,7 +1016,8 @@ ssh_session2(void) xstrdup("client-session"), /*nonblock*/0); channel_open(id); - channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, client_init, (void *)0); + channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, + ssh_session2_callback, (void *)0); return client_loop(tty_flag, tty_flag ? options.escape_char : -1, id); } |