summaryrefslogtreecommitdiff
path: root/usr.bin/ssh
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2000-04-28 08:10:21 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2000-04-28 08:10:21 +0000
commit93544d19d221ce4a71253f32a185b4e23015bc80 (patch)
tree5b92dd16f43099f8a1a7e6fff369582e9b3e7ac5 /usr.bin/ssh
parent16c4367694e71f24f65e5cf22ef7fbe55b61ba9e (diff)
support for x11-fwding, client+server
Diffstat (limited to 'usr.bin/ssh')
-rw-r--r--usr.bin/ssh/README.openssh222
-rw-r--r--usr.bin/ssh/channels.c211
-rw-r--r--usr.bin/ssh/channels.h7
-rw-r--r--usr.bin/ssh/clientloop.c67
-rw-r--r--usr.bin/ssh/session.c90
-rw-r--r--usr.bin/ssh/ssh.c102
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)