diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2000-04-28 08:10:21 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2000-04-28 08:10:21 +0000 |
commit | 93544d19d221ce4a71253f32a185b4e23015bc80 (patch) | |
tree | 5b92dd16f43099f8a1a7e6fff369582e9b3e7ac5 /usr.bin/ssh | |
parent | 16c4367694e71f24f65e5cf22ef7fbe55b61ba9e (diff) |
support for x11-fwding, client+server
Diffstat (limited to 'usr.bin/ssh')
-rw-r--r-- | usr.bin/ssh/README.openssh2 | 22 | ||||
-rw-r--r-- | usr.bin/ssh/channels.c | 211 | ||||
-rw-r--r-- | usr.bin/ssh/channels.h | 7 | ||||
-rw-r--r-- | usr.bin/ssh/clientloop.c | 67 | ||||
-rw-r--r-- | usr.bin/ssh/session.c | 90 | ||||
-rw-r--r-- | usr.bin/ssh/ssh.c | 102 |
6 files changed, 349 insertions, 150 deletions
diff --git a/usr.bin/ssh/README.openssh2 b/usr.bin/ssh/README.openssh2 index fca3173aef3..ea8c9788932 100644 --- a/usr.bin/ssh/README.openssh2 +++ b/usr.bin/ssh/README.openssh2 @@ -1,4 +1,4 @@ -$Id: README.openssh2,v 1.6 2000/04/27 13:42:58 provos Exp $ +$Id: README.openssh2,v 1.7 2000/04/28 08:10:20 markus Exp $ howto: 1) generate server key: @@ -6,7 +6,8 @@ howto: 2) enable ssh2: server: add 'Protocol 2,1' to /etc/sshd_config client: ssh -o 'Protocol 2,1', or add to .ssh/config - 3) interop w/ ssh.com dsa-keys: + 3) DSA authentication similar to RSA (add keys to ~/.ssh/authorized_keys2) + interop w/ ssh.com dsa-keys: ssh-keygen -f /key/from/ssh.com -X >> ~/.ssh/authorized_keys2 and vice versa ssh-keygen -f /privatekey/from/openssh -x > ~/.ssh2/mykey.pub @@ -18,21 +19,20 @@ works: encryption: blowfish-cbc, 3des-cbc, arcfour, cast128-cbc mac: hmac-md5, hmac-sha1, (hmac-ripemd160) compression: zlib, none - secsh-userauth: passwd only + secsh-userauth: passwd and pubkey with DSA secsh-connection: pty+shell or command, flow control works (window adjust) - tcp-forwarding: -L works - dss: verification works, - key database in ~/.ssh/known_hosts with bits == 0 hack - dss: signature works, keygen w/ openssl + tcp-forwarding: -L works, -R incomplete + x11-fwd + dss/dsa: host key database in ~/.ssh/known_hosts2 client interops w/ sshd2, lshd server interops w/ ssh2, lsh, ssh.com's Windows client, SecureCRT, F-Secure SSH Client 4.0 server supports multiple concurrent sessions (e.g. with SSH.com Windows client) todo: re-keying secsh-connection features: - tcp-forwarding, agent-fwd, x11-fwd - auth other than passwd: - pubkey, keyboard-interactive + tcp-forwarding, agent-fwd + auth other than passwd, and DSA-pubkey: + keyboard-interactive, (PGP-pubkey?) config server-auth w/ old host-keys cleanup @@ -41,4 +41,4 @@ todo: sftp -markus -$Date: 2000/04/27 13:42:58 $ +$Date: 2000/04/28 08:10:20 $ diff --git a/usr.bin/ssh/channels.c b/usr.bin/ssh/channels.c index c2fb3d27a91..11ef2ffc740 100644 --- a/usr.bin/ssh/channels.c +++ b/usr.bin/ssh/channels.c @@ -17,7 +17,7 @@ */ #include "includes.h" -RCSID("$Id: channels.c,v 1.50 2000/04/16 16:40:43 markus Exp $"); +RCSID("$Id: channels.c,v 1.51 2000/04/28 08:10:20 markus Exp $"); #include "ssh.h" #include "packet.h" @@ -40,9 +40,11 @@ RCSID("$Id: channels.c,v 1.50 2000/04/16 16:40:43 markus Exp $"); /* Max len of agent socket */ #define MAX_SOCKET_NAME 100 -/* default buffer for tcp-fwd-channel */ -#define CHAN_WINDOW_DEFAULT (8*1024) -#define CHAN_PACKET_DEFAULT (CHAN_WINDOW_DEFAULT/2) +/* default window/packet sizes for tcp/x11-fwd-channel */ +#define CHAN_TCP_WINDOW_DEFAULT (8*1024) +#define CHAN_TCP_PACKET_DEFAULT (CHAN_TCP_WINDOW_DEFAULT/2) +#define CHAN_X11_WINDOW_DEFAULT (4*1024) +#define CHAN_X11_PACKET_DEFAULT (CHAN_X11_WINDOW_DEFAULT/2) /* * Pointer to an array containing all allocated channels. The array is @@ -204,17 +206,15 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, c->self = found; c->type = type; c->ctype = ctype; - c->local_window = window; - c->local_window_max = window; - c->local_consumed = 0; - c->local_maxpacket = maxpack; - c->remote_window = 0; - c->remote_maxpacket = 0; c->rfd = rfd; c->wfd = wfd; c->sock = (rfd == wfd) ? rfd : -1; c->efd = efd; c->extended_usage = extended_usage; + c->local_window = window; + c->local_window_max = window; + c->local_consumed = 0; + c->local_maxpacket = maxpack; c->remote_id = -1; c->remote_name = remote_name; c->remote_window = 0; @@ -371,6 +371,7 @@ channel_pre_output_draining(Channel *c, fd_set * readset, fd_set * writeset) * state until the first packet has been completely read. The authentication * data in that packet is then substituted by the real data if it matches the * fake data, and the channel is put into normal mode. + * XXX All this happens at the client side. */ int x11_open_helper(Channel *c) @@ -456,7 +457,7 @@ channel_pre_x11_open_13(Channel *c, fd_set * readset, fd_set * writeset) } void -channel_pre_x11_open_15(Channel *c, fd_set * readset, fd_set * writeset) +channel_pre_x11_open(Channel *c, fd_set * readset, fd_set * writeset) { int ret = x11_open_helper(c); if (ret == 1) { @@ -464,7 +465,7 @@ channel_pre_x11_open_15(Channel *c, fd_set * readset, fd_set * writeset) channel_pre_open_15(c, readset, writeset); } else if (ret == -1) { debug("X11 rejected %d i%d/o%d", c->self, c->istate, c->ostate); - chan_read_failed(c); + chan_read_failed(c); /** force close? */ chan_write_failed(c); debug("X11 closed %d i%d/o%d", c->self, c->istate, c->ostate); } @@ -478,6 +479,7 @@ channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset) int newsock, newch; socklen_t addrlen; char buf[16384], *remote_hostname; + int remote_port; if (FD_ISSET(c->sock, readset)) { debug("X11 connection requested."); @@ -488,16 +490,32 @@ channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset) return; } remote_hostname = get_remote_hostname(newsock); + remote_port = get_peer_port(newsock); snprintf(buf, sizeof buf, "X11 connection from %.200s port %d", - remote_hostname, get_peer_port(newsock)); + remote_hostname, remote_port); + + newch = channel_new("x11", + SSH_CHANNEL_OPENING, newsock, newsock, -1, + c->local_window_max, c->local_maxpacket, + 0, xstrdup(buf)); + if (compat20) { + packet_start(SSH2_MSG_CHANNEL_OPEN); + packet_put_cstring("x11"); + packet_put_int(newch); + packet_put_int(c->local_window_max); + packet_put_int(c->local_maxpacket); + /* originator host and port */ + packet_put_cstring(remote_hostname); + packet_put_int(remote_port); + packet_send(); + } else { + packet_start(SSH_SMSG_X11_OPEN); + packet_put_int(newch); + if (have_hostname_in_open) + packet_put_string(buf, strlen(buf)); + packet_send(); + } xfree(remote_hostname); - newch = channel_allocate(SSH_CHANNEL_OPENING, newsock, - xstrdup(buf)); - packet_start(SSH_SMSG_X11_OPEN); - packet_put_int(newch); - if (have_hostname_in_open) - packet_put_string(buf, strlen(buf)); - packet_send(); } } @@ -597,7 +615,7 @@ channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset) FD_ISSET(c->rfd, readset)) { len = read(c->rfd, buf, sizeof(buf)); if (len <= 0) { - debug("channel %d: read<0 rfd %d len %d", + debug("channel %d: read<=0 rfd %d len %d", c->self, c->rfd, len); if (compat13) { buffer_consume(&c->output, buffer_len(&c->output)); @@ -729,10 +747,13 @@ void 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_X11_LISTENER] = &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_X11_LISTENER] = &channel_post_x11_listener; } void @@ -757,7 +778,7 @@ void channel_handler_init_15(void) { channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open_15; - channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open_15; + channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; @@ -1424,7 +1445,7 @@ channel_request_local_forwarding(u_short port, const char *host, ch = channel_new( "port listener", SSH_CHANNEL_PORT_LISTENER, sock, sock, -1, - CHAN_WINDOW_DEFAULT, CHAN_PACKET_DEFAULT, + CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, xstrdup("port listener")); strlcpy(channels[ch].path, host, sizeof(channels[ch].path)); channels[ch].host_port = host_port; @@ -1713,8 +1734,10 @@ x11_create_display_inet(int screen_number, int x11_display_offset) /* Allocate a channel for each socket. */ for (n = 0; n < num_socks; n++) { sock = socks[n]; - (void) channel_allocate(SSH_CHANNEL_X11_LISTENER, sock, - xstrdup("X11 inet listener")); + (void) channel_new("x11 listener", + SSH_CHANNEL_X11_LISTENER, sock, sock, -1, + CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, + 0, xstrdup("X11 inet listener")); } /* Return a suitable value for the DISPLAY environment variable. */ @@ -1754,44 +1777,21 @@ connect_local_xsocket(unsigned int dnr) return -1; } - -/* - * This is called when SSH_SMSG_X11_OPEN is received. The packet contains - * the remote channel number. We should do whatever we want, and respond - * with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE. - */ - -void -x11_input_open(int type, int plen) +int +x11_connect_display(void) { - int remote_channel, display_number, sock = 0, newch; + int display_number, sock = 0; const char *display; - char buf[1024], *cp, *remote_host; - unsigned int remote_len; + char buf[1024], *cp; struct addrinfo hints, *ai, *aitop; char strport[NI_MAXSERV]; int gaierr; - /* Get remote channel number. */ - remote_channel = packet_get_int(); - - /* Get remote originator name. */ - if (have_hostname_in_open) { - remote_host = packet_get_string(&remote_len); - remote_len += 4; - } else { - remote_host = xstrdup("unknown (remote did not supply name)"); - remote_len = 0; - } - - debug("Received X11 open request."); - packet_integrity_check(plen, 4 + remote_len, SSH_SMSG_X11_OPEN); - /* Try to open a socket for the local X server. */ display = getenv("DISPLAY"); if (!display) { error("DISPLAY not set."); - goto fail; + return -1; } /* * Now we decode the value of the DISPLAY variable and make a @@ -1808,15 +1808,15 @@ x11_input_open(int type, int plen) if (sscanf(strrchr(display, ':') + 1, "%d", &display_number) != 1) { error("Could not parse display number from DISPLAY: %.100s", display); - goto fail; + return -1; } /* Create a socket. */ sock = connect_local_xsocket(display_number); if (sock < 0) - goto fail; + return -1; /* OK, we now have a connection to the display. */ - goto success; + return sock; } /* * Connect to an inet socket. The DISPLAY value is supposedly @@ -1827,14 +1827,14 @@ x11_input_open(int type, int plen) cp = strchr(buf, ':'); if (!cp) { error("Could not find ':' in DISPLAY: %.100s", display); - goto fail; + return -1; } *cp = 0; /* buf now contains the host name. But first we parse the display number. */ if (sscanf(cp + 1, "%d", &display_number) != 1) { error("Could not parse display number from DISPLAY: %.100s", display); - goto fail; + return -1; } /* Look up the host address */ @@ -1844,7 +1844,7 @@ x11_input_open(int type, int plen) snprintf(strport, sizeof strport, "%d", 6000 + display_number); if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) { error("%.100s: unknown host. (%s)", buf, gai_strerror(gaierr)); - goto fail; + return -1; } for (ai = aitop; ai; ai = ai->ai_next) { /* Create a socket. */ @@ -1867,31 +1867,60 @@ x11_input_open(int type, int plen) if (!ai) { error("connect %.100s port %d: %.100s", buf, 6000 + display_number, strerror(errno)); - goto fail; + return -1; } -success: - /* We have successfully obtained a connection to the real X display. */ + return sock; +} - /* Allocate a channel for this connection. */ - if (x11_saved_proto == NULL) - newch = channel_allocate(SSH_CHANNEL_OPEN, sock, remote_host); - else - newch = channel_allocate(SSH_CHANNEL_X11_OPEN, sock, remote_host); - channels[newch].remote_id = remote_channel; +/* + * This is called when SSH_SMSG_X11_OPEN is received. The packet contains + * the remote channel number. We should do whatever we want, and respond + * with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE. + */ - /* Send a confirmation to the remote host. */ - packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); - packet_put_int(remote_channel); - packet_put_int(newch); - packet_send(); +void +x11_input_open(int type, int plen) +{ + int remote_channel, sock = 0, newch; + char *remote_host; + unsigned int remote_len; - return; + /* Get remote channel number. */ + remote_channel = packet_get_int(); -fail: - /* Send refusal to the remote host. */ - packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); - packet_put_int(remote_channel); - packet_send(); + /* Get remote originator name. */ + if (have_hostname_in_open) { + remote_host = packet_get_string(&remote_len); + remote_len += 4; + } else { + remote_host = xstrdup("unknown (remote did not supply name)"); + remote_len = 0; + } + + debug("Received X11 open request."); + packet_integrity_check(plen, 4 + remote_len, SSH_SMSG_X11_OPEN); + + /* Obtain a connection to the real X display. */ + sock = x11_connect_display(); + if (sock == -1) { + /* Send refusal to the remote host. */ + packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); + packet_put_int(remote_channel); + packet_send(); + } else { + /* Allocate a channel for this connection. */ + newch = channel_allocate( + (x11_saved_proto == NULL) ? + SSH_CHANNEL_OPEN : SSH_CHANNEL_X11_OPEN, + sock, remote_host); + channels[newch].remote_id = remote_channel; + + /* Send a confirmation to the remote host. */ + packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); + packet_put_int(remote_channel); + packet_put_int(newch); + packet_send(); + } } /* @@ -1900,7 +1929,8 @@ fail: */ void -x11_request_forwarding_with_spoofing(const char *proto, const char *data) +x11_request_forwarding_with_spoofing(int client_session_id, + const char *proto, const char *data) { unsigned int data_len = (unsigned int) strlen(data) / 2; unsigned int i, value; @@ -1946,9 +1976,14 @@ x11_request_forwarding_with_spoofing(const char *proto, const char *data) sprintf(new_data + 2 * i, "%02x", (unsigned char) x11_fake_data[i]); /* Send the request packet. */ - packet_start(SSH_CMSG_X11_REQUEST_FORWARDING); - packet_put_string(proto, strlen(proto)); - packet_put_string(new_data, strlen(new_data)); + if (compat20) { + channel_request_start(client_session_id, "x11-req", 0); + packet_put_char(0); /* XXX bool single connection */ + } else { + packet_start(SSH_CMSG_X11_REQUEST_FORWARDING); + } + packet_put_cstring(proto); + packet_put_cstring(new_data); packet_put_int(screen_number); packet_send(); packet_write_wait(); @@ -2098,20 +2133,26 @@ auth_input_open_request(int type, int plen) } void -channel_open(int id) +channel_start_open(int id) { Channel *c = channel_lookup(id); if (c == NULL) { log("channel_open: %d: bad id", id); return; } + debug("send channel open %d", id); packet_start(SSH2_MSG_CHANNEL_OPEN); packet_put_cstring(c->ctype); packet_put_int(c->self); packet_put_int(c->local_window); packet_put_int(c->local_maxpacket); +} +void +channel_open(int id) +{ + /* XXX REMOVE ME */ + channel_start_open(id); packet_send(); - debug("channel open %d", id); } void channel_request(int id, char *service, int wantconfirm) diff --git a/usr.bin/ssh/channels.h b/usr.bin/ssh/channels.h index 307ad8fc4f7..0ea881ffe26 100644 --- a/usr.bin/ssh/channels.h +++ b/usr.bin/ssh/channels.h @@ -1,4 +1,4 @@ -/* RCSID("$Id: channels.h,v 1.9 2000/04/14 10:30:30 markus Exp $"); */ +/* RCSID("$Id: channels.h,v 1.10 2000/04/28 08:10:20 markus Exp $"); */ #ifndef CHANNELS_H #define CHANNELS_H @@ -207,7 +207,9 @@ void x11_request_forwarding(void); * Requests forwarding for X11 connections, with authentication spoofing. * This should be called in the client only. */ -void x11_request_forwarding_with_spoofing(const char *proto, const char *data); +void +x11_request_forwarding_with_spoofing(int client_session_id, + const char *proto, const char *data); /* Sends a message to the server to request authentication fd forwarding. */ void auth_request_forwarding(void); @@ -230,5 +232,6 @@ void auth_input_open_request(int type, int plen); /* XXX */ int channel_connect_to(const char *host, u_short host_port); +int x11_connect_display(void); #endif diff --git a/usr.bin/ssh/clientloop.c b/usr.bin/ssh/clientloop.c index b77a6895a5b..13ebcd45cfb 100644 --- a/usr.bin/ssh/clientloop.c +++ b/usr.bin/ssh/clientloop.c @@ -16,7 +16,7 @@ */ #include "includes.h" -RCSID("$Id: clientloop.c,v 1.21 2000/04/19 07:05:48 deraadt Exp $"); +RCSID("$Id: clientloop.c,v 1.22 2000/04/28 08:10:20 markus Exp $"); #include "xmalloc.h" #include "ssh.h" @@ -954,6 +954,69 @@ client_input_exit_status(int type, int plen) quit_pending = 1; } +/* XXXX move to generic input handler */ +void +client_input_channel_open(int type, int plen) +{ + Channel *c = NULL; + char *ctype; + int id; + unsigned int len; + int rchan; + int rmaxpack; + int rwindow; + + ctype = packet_get_string(&len); + rchan = packet_get_int(); + rwindow = packet_get_int(); + rmaxpack = packet_get_int(); + + log("server_input_open: ctype %s rchan %d win %d max %d", + ctype, rchan, rwindow, rmaxpack); + + if (strcmp(ctype, "x11") == 0) { + int sock; + char *originator; + int originator_port; + originator = packet_get_string(NULL); + 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, 4*1024, 32*1024, 0, + xstrdup("x11")); + c = channel_lookup(id); + } + } +/* XXX duplicate : */ + if (c != NULL) { + debug("confirm %s", ctype); + c->remote_id = rchan; + c->remote_window = rwindow; + c->remote_maxpacket = rmaxpack; + + packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); + packet_put_int(c->remote_id); + packet_put_int(c->self); + packet_put_int(c->local_window); + packet_put_int(c->local_maxpacket); + packet_send(); + } else { + debug("failure %s", ctype); + packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); + packet_put_int(rchan); + packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED); + packet_put_cstring("bla bla"); + packet_put_cstring(""); + packet_send(); + } + xfree(ctype); +} + void client_init_dispatch_20() { @@ -962,6 +1025,7 @@ client_init_dispatch_20() dispatch_set(SSH2_MSG_CHANNEL_DATA, &channel_input_data); dispatch_set(SSH2_MSG_CHANNEL_EOF, &channel_input_ieof); dispatch_set(SSH2_MSG_CHANNEL_EXTENDED_DATA, &channel_input_extended_data); + dispatch_set(SSH2_MSG_CHANNEL_OPEN, &client_input_channel_open); dispatch_set(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation); dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request); @@ -974,7 +1038,6 @@ client_init_dispatch_13() dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close); dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation); dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data); - dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data); dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation); dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure); dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open); diff --git a/usr.bin/ssh/session.c b/usr.bin/ssh/session.c index 6adaaa64082..e63889bedca 100644 --- a/usr.bin/ssh/session.c +++ b/usr.bin/ssh/session.c @@ -8,7 +8,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: session.c,v 1.6 2000/04/27 15:23:02 markus Exp $"); +RCSID("$OpenBSD: session.c,v 1.7 2000/04/28 08:10:20 markus Exp $"); #include "xmalloc.h" #include "ssh.h" @@ -34,6 +34,7 @@ typedef struct Session Session; struct Session { int used; int self; + int extended; struct passwd *pw; pid_t pid; /* tty */ @@ -46,6 +47,7 @@ struct Session { int screen; char *auth_proto; char *auth_data; + int single_connection; /* proto 2 */ int chanid; }; @@ -165,6 +167,7 @@ do_authenticated(struct passwd * pw) channel_permit_all_opens(); s = session_new(); + s->pw = pw; /* * We stay in this loop until the client requests to execute a shell @@ -274,6 +277,7 @@ do_authenticated(struct passwd * pw) xauthfile, strerror(errno)); xfree(xauthfile); xauthfile = NULL; + /* XXXX remove listening channels */ break; } strlcat(xauthfile, "/cookies", MAXPATHLEN); @@ -453,7 +457,7 @@ do_exec_no_pty(Session *s, const char *command, struct passwd * pw) close(perr[1]); if (compat20) { - session_set_fds(s, pin[1], pout[0], perr[0]); + session_set_fds(s, pin[1], pout[0], s->extended ? perr[0] : -1); } else { /* Enter the interactive session. */ server_loop(pid, pin[1], pout[0], perr[0]); @@ -469,7 +473,7 @@ do_exec_no_pty(Session *s, const char *command, struct passwd * pw) * handle the case that fdin and fdout are the same. */ if (compat20) { - session_set_fds(s, inout[1], inout[1], err[1]); + session_set_fds(s, inout[1], inout[1], s->extended ? err[1] : -1); } else { server_loop(pid, inout[1], inout[1], err[1]); /* server_loop has closed inout[1] and err[1]. */ @@ -1046,6 +1050,7 @@ session_new(void) Session *s = &sessions[i]; if (! s->used) { s->pid = 0; + s->extended = 0; s->chanid = -1; s->ptyfd = -1; s->ttyfd = -1; @@ -1056,6 +1061,7 @@ session_new(void) s->auth_data = NULL; s->auth_proto = NULL; s->used = 1; + s->pw = NULL; debug("session_new: session %d", i); return s; } @@ -1087,12 +1093,11 @@ session_open(int chanid) error("no more sessions"); return 0; } - debug("session_open: session %d: link with channel %d", s->self, chanid); - s->chanid = chanid; s->pw = auth_get_user(); if (s->pw == NULL) - fatal("no user for session %i channel %d", - s->self, s->chanid); + fatal("no user for session %i", s->self); + debug("session_open: session %d: link with channel %d", s->self, chanid); + s->chanid = chanid; return 1; } @@ -1184,6 +1189,69 @@ session_pty_req(Session *s) return 1; } +int +session_subsystem_req(Session *s) +{ + unsigned int len; + int success = 0; + char *subsys = packet_get_string(&len); + + packet_done(); + log("subsystem request for %s", subsys); + + xfree(subsys); + return success; +} + +int +session_x11_req(Session *s) +{ + if (!options.x11_forwarding) { + debug("X11 forwarding disabled in server configuration file."); + return 0; + } + if (xauthfile != NULL) { + debug("X11 fwd already started."); + return 0; + } + + debug("Received request for X11 forwarding with auth spoofing."); + if (s->display != NULL) + packet_disconnect("Protocol error: X11 display already set."); + + s->single_connection = packet_get_char(); + s->auth_proto = packet_get_string(NULL); + s->auth_data = packet_get_string(NULL); + s->screen = packet_get_int(); + packet_done(); + + s->display = x11_create_display_inet(s->screen, options.x11_display_offset); + if (s->display == NULL) { + xfree(s->auth_proto); + xfree(s->auth_data); + return 0; + } + xauthfile = xmalloc(MAXPATHLEN); + strlcpy(xauthfile, "/tmp/ssh-XXXXXXXX", MAXPATHLEN); + temporarily_use_uid(s->pw->pw_uid); + if (mkdtemp(xauthfile) == NULL) { + restore_uid(); + error("private X11 dir: mkdtemp %s failed: %s", + xauthfile, strerror(errno)); + xfree(xauthfile); + xauthfile = NULL; + xfree(s->auth_proto); + xfree(s->auth_data); + /* XXXX remove listening channels */ + return 0; + } + strlcat(xauthfile, "/cookies", MAXPATHLEN); + open(xauthfile, O_RDWR|O_CREAT|O_EXCL, 0600); + restore_uid(); + fatal_add_cleanup(xauthfile_cleanup_proc, s); + return 1; +} + void session_input_channel_req(int id, void *arg) { @@ -1214,6 +1282,7 @@ session_input_channel_req(int id, void *arg) if (c->type == SSH_CHANNEL_LARVAL) { if (strcmp(rtype, "shell") == 0) { packet_done(); + s->extended = 1; if (s->ttyfd == -1) do_exec_no_pty(s, NULL, s->pw); else @@ -1222,6 +1291,7 @@ session_input_channel_req(int id, void *arg) } else if (strcmp(rtype, "exec") == 0) { char *command = packet_get_string(&len); packet_done(); + s->extended = 1; if (s->ttyfd == -1) do_exec_no_pty(s, command, s->pw); else @@ -1230,6 +1300,10 @@ session_input_channel_req(int id, void *arg) success = 1; } else if (strcmp(rtype, "pty-req") == 0) { success = session_pty_req(s); + } else if (strcmp(rtype, "x11-req") == 0) { + success = session_x11_req(s); + } else if (strcmp(rtype, "subsystem") == 0) { + success = session_subsystem_req(s); } } if (strcmp(rtype, "window-change") == 0) { @@ -1403,4 +1477,6 @@ do_authenticated2(void) */ alarm(0); server_loop2(); + if (xauthfile) + xauthfile_cleanup_proc(NULL); } diff --git a/usr.bin/ssh/ssh.c b/usr.bin/ssh/ssh.c index 5d6079e9b6e..434e92c1293 100644 --- a/usr.bin/ssh/ssh.c +++ b/usr.bin/ssh/ssh.c @@ -11,7 +11,7 @@ */ #include "includes.h" -RCSID("$Id: ssh.c,v 1.49 2000/04/26 20:56:30 markus Exp $"); +RCSID("$Id: ssh.c,v 1.50 2000/04/28 08:10:20 markus Exp $"); #include <openssl/evp.h> #include <openssl/dsa.h> @@ -656,6 +656,45 @@ main(int ac, char **av) return exit_status; } +void +x11_get_proto(char *proto, int proto_len, char *data, int data_len) +{ + char line[512]; + FILE *f; + int got_data = 0, i; + +#ifdef XAUTH_PATH + /* Try to get Xauthority information for the display. */ + snprintf(line, sizeof line, "%.100s list %.200s 2>/dev/null", + XAUTH_PATH, getenv("DISPLAY")); + f = popen(line, "r"); + if (f && fgets(line, sizeof(line), f) && + sscanf(line, "%*s %s %s", proto, data) == 2) + got_data = 1; + if (f) + pclose(f); +#endif /* XAUTH_PATH */ + /* + * If we didn't get authentication data, just make up some + * data. The forwarding code will check the validity of the + * response anyway, and substitute this data. The X11 + * server, however, will ignore this fake data and use + * whatever authentication mechanisms it was using otherwise + * for the local connection. + */ + if (!got_data) { + u_int32_t rand = 0; + + strlcpy(proto, "MIT-MAGIC-COOKIE-1", proto_len); + for (i = 0; i < 16; i++) { + if (i % 4 == 0) + rand = arc4random(); + snprintf(data + 2 * i, data_len - 2 * i, "%02x", rand & 0xff); + rand >>= 8; + } + } +} + int ssh_session(void) { @@ -729,56 +768,22 @@ ssh_session(void) } /* Request X11 forwarding if enabled and DISPLAY is set. */ if (options.forward_x11 && getenv("DISPLAY") != NULL) { - char line[512], proto[512], data[512]; - FILE *f; - int forwarded = 0, got_data = 0, i; - -#ifdef XAUTH_PATH - /* Try to get Xauthority information for the display. */ - snprintf(line, sizeof line, "%.100s list %.200s 2>/dev/null", - XAUTH_PATH, getenv("DISPLAY")); - f = popen(line, "r"); - if (f && fgets(line, sizeof(line), f) && - sscanf(line, "%*s %s %s", proto, data) == 2) - got_data = 1; - if (f) - pclose(f); -#endif /* XAUTH_PATH */ - /* - * If we didn't get authentication data, just make up some - * data. The forwarding code will check the validity of the - * response anyway, and substitute this data. The X11 - * server, however, will ignore this fake data and use - * whatever authentication mechanisms it was using otherwise - * for the local connection. - */ - if (!got_data) { - u_int32_t rand = 0; - - strlcpy(proto, "MIT-MAGIC-COOKIE-1", sizeof proto); - for (i = 0; i < 16; i++) { - if (i % 4 == 0) - rand = arc4random(); - snprintf(data + 2 * i, sizeof data - 2 * i, "%02x", rand & 0xff); - rand >>= 8; - } - } - /* - * Got local authentication reasonable information. Request - * forwarding with authentication spoofing. - */ + char proto[512], data[512]; + /* Get reasonable local authentication information. */ + x11_get_proto(proto, sizeof proto, data, sizeof data); + /* Request forwarding with authentication spoofing. */ debug("Requesting X11 forwarding with authentication spoofing."); - x11_request_forwarding_with_spoofing(proto, data); + x11_request_forwarding_with_spoofing(0, proto, data); /* Read response from the server. */ type = packet_read(&plen); if (type == SSH_SMSG_SUCCESS) { - forwarded = 1; interactive = 1; - } else if (type == SSH_SMSG_FAILURE) + } else if (type == SSH_SMSG_FAILURE) { log("Warning: Remote host denied X11 forwarding."); - else + } else { packet_disconnect("Protocol error waiting for X11 forwarding"); + } } /* Tell the packet module whether this is an interactive session. */ packet_set_interactive(interactive, options.keepalives); @@ -901,6 +906,17 @@ client_init(int id, void *arg) packet_send(); /* XXX wait for reply */ } + if (options.forward_x11 && + getenv("DISPLAY") != NULL) { + char proto[512], data[512]; + /* Get reasonable local authentication information. */ + x11_get_proto(proto, sizeof proto, data, sizeof data); + /* Request forwarding with authentication spoofing. */ + debug("Requesting X11 forwarding with authentication spoofing."); + x11_request_forwarding_with_spoofing(id, proto, data); + /* XXX wait for reply */ + } + len = buffer_len(&command); if (len > 0) { if (len > 900) |