[channels.c clientloop.c clientloop.h misc.c misc.h ssh.c ssh_config.5]
     implement support for X11 and agent forwarding over multiplex slave
     connections. Because of protocol limitations, the slave connections inherit
     the master's DISPLAY and SSH_AUTH_SOCK rather than distinctly forwarding
     their own.
     ok dtucker@ "put it in" deraadt@
This commit is contained in:
Damien Miller 2005-07-06 09:44:19 +10:00
Родитель a7270309fc
Коммит 1339002e8b
8 изменённых файлов: 127 добавлений и 58 удалений

Просмотреть файл

@ -3,6 +3,13 @@
- markus@cvs.openbsd.org 2005/07/01 13:19:47
[channels.c]
don't free() if getaddrinfo() fails; report mpech@
- djm@cvs.openbsd.org 2005/07/04 00:58:43
[channels.c clientloop.c clientloop.h misc.c misc.h ssh.c ssh_config.5]
implement support for X11 and agent forwarding over multiplex slave
connections. Because of protocol limitations, the slave connections inherit
the master's DISPLAY and SSH_AUTH_SOCK rather than distinctly forwarding
their own.
ok dtucker@ "put it in" deraadt@
20050626
- (djm) OpenBSD CVS Sync
@ -2769,4 +2776,4 @@
- (djm) Trim deprecated options from INSTALL. Mention UsePAM
- (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu
$Id: ChangeLog,v 1.3832 2005/07/05 23:36:05 djm Exp $
$Id: ChangeLog,v 1.3833 2005/07/05 23:44:19 djm Exp $

Просмотреть файл

@ -39,7 +39,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: channels.c,v 1.218 2005/07/01 13:19:47 markus Exp $");
RCSID("$OpenBSD: channels.c,v 1.219 2005/07/04 00:58:42 djm Exp $");
#include "ssh.h"
#include "ssh1.h"
@ -111,6 +111,9 @@ static int all_opens_permitted = 0;
/* Maximum number of fake X11 displays to try. */
#define MAX_DISPLAYS 1000
/* Saved X11 local (client) display. */
static char *x11_saved_display = NULL;
/* Saved X11 authentication protocol name. */
static char *x11_saved_proto = NULL;
@ -2955,12 +2958,18 @@ x11_request_forwarding_with_spoofing(int client_session_id, const char *disp,
const char *proto, const char *data)
{
u_int data_len = (u_int) strlen(data) / 2;
u_int i, value, len;
u_int i, value;
char *new_data;
int screen_number;
const char *cp;
u_int32_t rnd = 0;
if (x11_saved_display && strcmp(disp, x11_saved_display) != 0) {
error("x11_request_forwarding_with_spoofing: different "
"$DISPLAY already forwarded");
return;
}
cp = disp;
if (disp)
cp = strchr(disp, ':');
@ -2971,33 +2980,31 @@ x11_request_forwarding_with_spoofing(int client_session_id, const char *disp,
else
screen_number = 0;
/* Save protocol name. */
x11_saved_proto = xstrdup(proto);
/*
* Extract real authentication data and generate fake data of the
* same length.
*/
x11_saved_data = xmalloc(data_len);
x11_fake_data = xmalloc(data_len);
for (i = 0; i < data_len; i++) {
if (sscanf(data + 2 * i, "%2x", &value) != 1)
fatal("x11_request_forwarding: bad authentication data: %.100s", data);
if (i % 4 == 0)
rnd = arc4random();
x11_saved_data[i] = value;
x11_fake_data[i] = rnd & 0xff;
rnd >>= 8;
if (x11_saved_proto == NULL) {
/* Save protocol name. */
x11_saved_proto = xstrdup(proto);
/*
* Extract real authentication data and generate fake data
* of the same length.
*/
x11_saved_data = xmalloc(data_len);
x11_fake_data = xmalloc(data_len);
for (i = 0; i < data_len; i++) {
if (sscanf(data + 2 * i, "%2x", &value) != 1)
fatal("x11_request_forwarding: bad "
"authentication data: %.100s", data);
if (i % 4 == 0)
rnd = arc4random();
x11_saved_data[i] = value;
x11_fake_data[i] = rnd & 0xff;
rnd >>= 8;
}
x11_saved_data_len = data_len;
x11_fake_data_len = data_len;
}
x11_saved_data_len = data_len;
x11_fake_data_len = data_len;
/* Convert the fake data into hex. */
len = 2 * data_len + 1;
new_data = xmalloc(len);
for (i = 0; i < data_len; i++)
snprintf(new_data + 2 * i, len - 2 * i,
"%02x", (u_char) x11_fake_data[i]);
new_data = tohex(x11_fake_data, data_len);
/* Send the request packet. */
if (compat20) {

Просмотреть файл

@ -59,7 +59,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: clientloop.c,v 1.139 2005/06/17 02:44:32 djm Exp $");
RCSID("$OpenBSD: clientloop.c,v 1.140 2005/07/04 00:58:43 djm Exp $");
#include "ssh.h"
#include "ssh1.h"
@ -140,6 +140,8 @@ int session_ident = -1;
struct confirm_ctx {
int want_tty;
int want_subsys;
int want_x_fwd;
int want_agent_fwd;
Buffer cmd;
char *term;
struct termios tio;
@ -631,6 +633,7 @@ static void
client_extra_session2_setup(int id, void *arg)
{
struct confirm_ctx *cctx = arg;
const char *display;
Channel *c;
int i;
@ -639,6 +642,24 @@ client_extra_session2_setup(int id, void *arg)
if ((c = channel_lookup(id)) == NULL)
fatal("%s: no channel for id %d", __func__, id);
display = getenv("DISPLAY");
if (cctx->want_x_fwd && options.forward_x11 && display != NULL) {
char *proto, *data;
/* Get reasonable local authentication information. */
client_x11_get_proto(display, options.xauth_location,
options.forward_x11_trusted, &proto, &data);
/* Request forwarding with authentication spoofing. */
debug("Requesting X11 forwarding with authentication spoofing.");
x11_request_forwarding_with_spoofing(id, display, proto, data);
/* XXX wait for reply */
}
if (cctx->want_agent_fwd && options.forward_agent) {
debug("Requesting authentication agent forwarding.");
channel_request_start(id, "auth-agent-req@openssh.com", 0);
packet_send();
}
client_session2_setup(id, cctx->want_tty, cctx->want_subsys,
cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env,
client_subsystem_reply);
@ -704,7 +725,7 @@ client_process_control(fd_set * readset)
buffer_free(&m);
return;
}
if ((ver = buffer_get_char(&m)) != 1) {
if ((ver = buffer_get_char(&m)) != SSHMUX_VER) {
error("%s: wrong client version %d", __func__, ver);
buffer_free(&m);
close(client_fd);
@ -738,7 +759,7 @@ client_process_control(fd_set * readset)
buffer_clear(&m);
buffer_put_int(&m, allowed);
buffer_put_int(&m, getpid());
if (ssh_msg_send(client_fd, /* version */1, &m) == -1) {
if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
error("%s: client msg_send failed", __func__);
close(client_fd);
buffer_free(&m);
@ -758,7 +779,7 @@ client_process_control(fd_set * readset)
buffer_clear(&m);
buffer_put_int(&m, allowed);
buffer_put_int(&m, getpid());
if (ssh_msg_send(client_fd, /* version */1, &m) == -1) {
if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
error("%s: client msg_send failed", __func__);
close(client_fd);
buffer_free(&m);
@ -779,7 +800,7 @@ client_process_control(fd_set * readset)
buffer_free(&m);
return;
}
if ((ver = buffer_get_char(&m)) != 1) {
if ((ver = buffer_get_char(&m)) != SSHMUX_VER) {
error("%s: wrong client version %d", __func__, ver);
buffer_free(&m);
close(client_fd);
@ -790,6 +811,8 @@ client_process_control(fd_set * readset)
memset(cctx, 0, sizeof(*cctx));
cctx->want_tty = (flags & SSHMUX_FLAG_TTY) != 0;
cctx->want_subsys = (flags & SSHMUX_FLAG_SUBSYS) != 0;
cctx->want_x_fwd = (flags & SSHMUX_FLAG_X11_FWD) != 0;
cctx->want_agent_fwd = (flags & SSHMUX_FLAG_AGENT_FWD) != 0;
cctx->term = buffer_get_string(&m, &len);
cmd = buffer_get_string(&m, &len);
@ -823,7 +846,7 @@ client_process_control(fd_set * readset)
/* This roundtrip is just for synchronisation of ttymodes */
buffer_clear(&m);
if (ssh_msg_send(client_fd, /* version */1, &m) == -1) {
if (ssh_msg_send(client_fd, SSHMUX_VER, &m) == -1) {
error("%s: client msg_send failed", __func__);
close(client_fd);
close(new_fd[0]);

Просмотреть файл

@ -1,4 +1,4 @@
/* $OpenBSD: clientloop.h,v 1.13 2005/06/16 03:38:36 djm Exp $ */
/* $OpenBSD: clientloop.h,v 1.14 2005/07/04 00:58:43 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -43,6 +43,9 @@ void client_global_request_reply_fwd(int, u_int32_t, void *);
void client_session2_setup(int, int, int, const char *, struct termios *,
int, Buffer *, char **, dispatch_fn *);
/* Multiplexing protocol version */
#define SSHMUX_VER 1
/* Multiplexing control protocol flags */
#define SSHMUX_COMMAND_OPEN 1 /* Open new connection */
#define SSHMUX_COMMAND_ALIVE_CHECK 2 /* Check master is alive */
@ -50,3 +53,5 @@ void client_session2_setup(int, int, int, const char *, struct termios *,
#define SSHMUX_FLAG_TTY (1) /* Request tty on open */
#define SSHMUX_FLAG_SUBSYS (1<<1) /* Subsystem request on open */
#define SSHMUX_FLAG_X11_FWD (1<<2) /* Request X11 forwarding */
#define SSHMUX_FLAG_AGENT_FWD (1<<3) /* Request agent forwarding */

19
misc.c
Просмотреть файл

@ -24,7 +24,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: misc.c,v 1.32 2005/06/17 02:44:32 djm Exp $");
RCSID("$OpenBSD: misc.c,v 1.33 2005/07/04 00:58:43 djm Exp $");
#include "misc.h"
#include "log.h"
@ -506,3 +506,20 @@ read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz,
}
return -1;
}
char *
tohex(const u_char *d, u_int l)
{
char b[3], *r;
u_int i, hl;
hl = l * 2 + 1;
r = xmalloc(hl);
*r = '\0';
for (i = 0; i < l; i++) {
snprintf(b, sizeof(b), "%02x", d[i]);
strlcat(r, b, hl);
}
return (r);
}

3
misc.h
Просмотреть файл

@ -1,4 +1,4 @@
/* $OpenBSD: misc.h,v 1.23 2005/06/06 11:20:36 djm Exp $ */
/* $OpenBSD: misc.h,v 1.24 2005/07/04 00:58:43 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -26,6 +26,7 @@ char *colon(char *);
long convtime(const char *);
char *tilde_expand_filename(const char *, uid_t);
char *percent_expand(const char *, ...) __attribute__((sentinel));
char *tohex(const u_char *, u_int);
struct passwd *pwcopy(struct passwd *);

45
ssh.c
Просмотреть файл

@ -40,7 +40,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: ssh.c,v 1.246 2005/06/25 22:47:49 djm Exp $");
RCSID("$OpenBSD: ssh.c,v 1.247 2005/07/04 00:58:43 djm Exp $");
#include <openssl/evp.h>
#include <openssl/err.h>
@ -1250,41 +1250,44 @@ control_client(const char *path)
error("Control socket connect(%.100s): %s", path,
strerror(errno));
}
close(sock);
return;
}
if (stdin_null_flag) {
if ((fd = open(_PATH_DEVNULL, O_RDONLY)) == -1)
fatal("open(/dev/null): %s", strerror(errno));
if (dup2(fd, STDIN_FILENO) == -1)
fatal("dup2: %s", strerror(errno));
if (fd > STDERR_FILENO)
close(fd);
}
if ((term = getenv("TERM")) == NULL)
term = "";
close(sock);
return;
}
if (stdin_null_flag) {
if ((fd = open(_PATH_DEVNULL, O_RDONLY)) == -1)
fatal("open(/dev/null): %s", strerror(errno));
if (dup2(fd, STDIN_FILENO) == -1)
fatal("dup2: %s", strerror(errno));
if (fd > STDERR_FILENO)
close(fd);
}
term = getenv("TERM");
flags = 0;
if (tty_flag)
flags |= SSHMUX_FLAG_TTY;
if (subsystem_flag)
flags |= SSHMUX_FLAG_SUBSYS;
if (options.forward_x11)
flags |= SSHMUX_FLAG_X11_FWD;
if (options.forward_agent)
flags |= SSHMUX_FLAG_AGENT_FWD;
buffer_init(&m);
/* Send our command to server */
buffer_put_int(&m, mux_command);
buffer_put_int(&m, flags);
if (ssh_msg_send(sock, /* version */1, &m) == -1)
if (ssh_msg_send(sock, SSHMUX_VER, &m) == -1)
fatal("%s: msg_send", __func__);
buffer_clear(&m);
/* Get authorisation status and PID of controlee */
if (ssh_msg_recv(sock, &m) == -1)
fatal("%s: msg_recv", __func__);
if (buffer_get_char(&m) != 1)
if (buffer_get_char(&m) != SSHMUX_VER)
fatal("%s: wrong version", __func__);
if (buffer_get_int(&m) != 1)
fatal("Connection to master denied");
@ -1308,7 +1311,7 @@ control_client(const char *path)
}
/* SSHMUX_COMMAND_OPEN */
buffer_put_cstring(&m, term);
buffer_put_cstring(&m, term ? term : "");
buffer_append(&command, "\0", 1);
buffer_put_cstring(&m, buffer_ptr(&command));
@ -1330,7 +1333,7 @@ control_client(const char *path)
}
}
if (ssh_msg_send(sock, /* version */1, &m) == -1)
if (ssh_msg_send(sock, SSHMUX_VER, &m) == -1)
fatal("%s: msg_send", __func__);
mm_send_fd(sock, STDIN_FILENO);
@ -1341,7 +1344,7 @@ control_client(const char *path)
buffer_clear(&m);
if (ssh_msg_recv(sock, &m) == -1)
fatal("%s: msg_recv", __func__);
if (buffer_get_char(&m) != 1)
if (buffer_get_char(&m) != SSHMUX_VER)
fatal("%s: wrong version", __func__);
buffer_free(&m);

Просмотреть файл

@ -34,7 +34,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.
.\"
.\" $OpenBSD: ssh_config.5,v 1.57 2005/06/18 04:30:36 djm Exp $
.\" $OpenBSD: ssh_config.5,v 1.58 2005/07/04 00:58:43 djm Exp $
.Dd September 25, 1999
.Dt SSH_CONFIG 5
.Os
@ -279,6 +279,12 @@ can not be opened,
.Nm ssh
will continue without connecting to a master instance.
.Pp
X11 and
.Xr ssh-agent 4
forwarding is supported over these multiplexed connections, however the
display and agent fowarded will be the one belonging to the master
connection. I.e. it is not possible to forward multiple displays or agents.
.Pp
Two additional options allow for opportunistic multiplexing: try to use a
master connection but fall back to creating a new one if one does not already
exist.