From deb5a1423a72cb96c629d5514be58897cd7a24ce Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 16 Apr 2010 15:52:43 +1000 Subject: - djm@cvs.openbsd.org 2010/04/10 00:00:16 [ssh.c] bz#1746 - suppress spurious tty warning when using -O and stdin is not a tty; ok dtucker@ markus@ --- ssh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'ssh.c') diff --git a/ssh.c b/ssh.c index b9553d3e1..2230edd16 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.335 2010/02/26 20:29:54 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.336 2010/04/10 00:00:16 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -620,7 +620,7 @@ main(int ac, char **av) tty_flag = 1; /* Force no tty */ - if (no_tty_flag) + if (no_tty_flag || muxclient_command != 0) tty_flag = 0; /* Do not allocate a tty if stdin is not a tty. */ if ((!isatty(fileno(stdin)) || stdin_null_flag) && !force_tty_flag) { -- cgit v1.2.3 From d530f5f471491b6be9edb58a063f2590e4dce48d Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 21 May 2010 14:57:10 +1000 Subject: - djm@cvs.openbsd.org 2010/05/14 23:29:23 [channels.c channels.h mux.c ssh.c] Pause the mux channel while waiting for reply from aynch callbacks. Prevents misordering of replies if new requests arrive while waiting. Extend channel open confirm callback to allow signalling failure conditions as well as success. Use this to 1) fix a memory leak, 2) start using the above pause mechanism and 3) delay sending a success/ failure message on mux slave session open until we receive a reply from the server. motivated by and with feedback from markus@ --- ChangeLog | 12 ++++++++++++ channels.c | 16 +++++++++++----- channels.h | 8 +++++--- mux.c | 47 +++++++++++++++++++++++++++++++++++++---------- ssh.c | 7 +++++-- 5 files changed, 70 insertions(+), 20 deletions(-) (limited to 'ssh.c') diff --git a/ChangeLog b/ChangeLog index b90af22b0..a485000a8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,18 @@ [ssh-add.c] check that the certificate matches the corresponding private key before grafting it on + - djm@cvs.openbsd.org 2010/05/14 23:29:23 + [channels.c channels.h mux.c ssh.c] + Pause the mux channel while waiting for reply from aynch callbacks. + Prevents misordering of replies if new requests arrive while waiting. + + Extend channel open confirm callback to allow signalling failure + conditions as well as success. Use this to 1) fix a memory leak, 2) + start using the above pause mechanism and 3) delay sending a success/ + failure message on mux slave session open until we receive a reply from + the server. + + motivated by and with feedback from markus@ 20100511 - (dtucker) [Makefile.in] Bug #1770: Link libopenbsd-compat twice to solve diff --git a/channels.c b/channels.c index a55d27817..0f750c4d4 100644 --- a/channels.c +++ b/channels.c @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.c,v 1.303 2010/01/30 21:12:08 djm Exp $ */ +/* $OpenBSD: channels.c,v 1.304 2010/05/14 23:29:23 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -330,6 +330,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, c->ctl_chan = -1; c->mux_rcb = NULL; c->mux_ctx = NULL; + c->mux_pause = 0; c->delayed = 1; /* prevent call to channel_post handler */ TAILQ_INIT(&c->status_confirms); debug("channel %d: new [%s]", found, remote_name); @@ -703,7 +704,7 @@ channel_register_status_confirm(int id, channel_confirm_cb *cb, } void -channel_register_open_confirm(int id, channel_callback_fn *fn, void *ctx) +channel_register_open_confirm(int id, channel_open_fn *fn, void *ctx) { Channel *c = channel_lookup(id); @@ -991,7 +992,7 @@ channel_pre_x11_open(Channel *c, fd_set *readset, fd_set *writeset) static void channel_pre_mux_client(Channel *c, fd_set *readset, fd_set *writeset) { - if (c->istate == CHAN_INPUT_OPEN && + if (c->istate == CHAN_INPUT_OPEN && !c->mux_pause && buffer_check_alloc(&c->input, CHAN_RBUF)) FD_SET(c->rfd, readset); if (c->istate == CHAN_INPUT_WAIT_DRAIN) { @@ -1840,7 +1841,7 @@ channel_post_mux_client(Channel *c, fd_set *readset, fd_set *writeset) if (!compat20) fatal("%s: entered with !compat20", __func__); - if (c->rfd != -1 && FD_ISSET(c->rfd, readset) && + if (c->rfd != -1 && !c->mux_pause && FD_ISSET(c->rfd, readset) && (c->istate == CHAN_INPUT_OPEN || c->istate == CHAN_INPUT_WAIT_DRAIN)) { /* @@ -2463,7 +2464,7 @@ channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt) c->remote_maxpacket = packet_get_int(); if (c->open_confirm) { debug2("callback start"); - c->open_confirm(c->self, c->open_confirm_ctx); + c->open_confirm(c->self, 1, c->open_confirm_ctx); debug2("callback done"); } debug2("channel %d: open confirm rwindow %u rmax %u", c->self, @@ -2514,6 +2515,11 @@ channel_input_open_failure(int type, u_int32_t seq, void *ctxt) xfree(msg); if (lang != NULL) xfree(lang); + if (c->open_confirm) { + debug2("callback start"); + c->open_confirm(c->self, 0, c->open_confirm_ctx); + debug2("callback done"); + } } packet_check_eom(); /* Schedule the channel for cleanup/deletion. */ diff --git a/channels.h b/channels.h index cc71885f4..0680ed00e 100644 --- a/channels.h +++ b/channels.h @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.h,v 1.103 2010/01/26 01:28:35 djm Exp $ */ +/* $OpenBSD: channels.h,v 1.104 2010/05/14 23:29:23 djm Exp $ */ /* * Author: Tatu Ylonen @@ -60,6 +60,7 @@ struct Channel; typedef struct Channel Channel; +typedef void channel_open_fn(int, int, void *); typedef void channel_callback_fn(int, void *); typedef int channel_infilter_fn(struct Channel *, char *, int); typedef void channel_filter_cleanup_fn(int, void *); @@ -130,7 +131,7 @@ struct Channel { char *ctype; /* type */ /* callback */ - channel_callback_fn *open_confirm; + channel_open_fn *open_confirm; void *open_confirm_ctx; channel_callback_fn *detach_user; int detach_close; @@ -151,6 +152,7 @@ struct Channel { /* multiplexing protocol hook, called for each packet received */ mux_callback_fn *mux_rcb; void *mux_ctx; + int mux_pause; }; #define CHAN_EXTENDED_IGNORE 0 @@ -208,7 +210,7 @@ void channel_stop_listening(void); void channel_send_open(int); void channel_request_start(int, char *, int); void channel_register_cleanup(int, channel_callback_fn *, int); -void channel_register_open_confirm(int, channel_callback_fn *, void *); +void channel_register_open_confirm(int, channel_open_fn *, void *); void channel_register_filter(int, channel_infilter_fn *, channel_outfilter_fn *, channel_filter_cleanup_fn *, void *); void channel_register_status_confirm(int, channel_confirm_cb *, diff --git a/mux.c b/mux.c index ac477a0e7..18dfd99f3 100644 --- a/mux.c +++ b/mux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mux.c,v 1.16 2010/04/23 22:27:38 djm Exp $ */ +/* $OpenBSD: mux.c,v 1.17 2010/05/14 23:29:23 djm Exp $ */ /* * Copyright (c) 2002-2008 Damien Miller * @@ -106,6 +106,7 @@ struct mux_session_confirm_ctx { char *term; struct termios tio; char **env; + u_int rid; }; /* fd to control socket */ @@ -149,7 +150,7 @@ struct mux_master_state { #define MUX_FWD_REMOTE 2 #define MUX_FWD_DYNAMIC 3 -static void mux_session_confirm(int, void *); +static void mux_session_confirm(int, int, void *); static int process_mux_master_hello(u_int, Channel *, Buffer *, Buffer *); static int process_mux_new_session(u_int, Channel *, Buffer *, Buffer *); @@ -301,6 +302,7 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r) /* Reply for SSHMUX_COMMAND_OPEN */ cctx = xcalloc(1, sizeof(*cctx)); cctx->term = NULL; + cctx->rid = rid; cmd = reserved = NULL; if ((reserved = buffer_get_string_ret(m, NULL)) == NULL || buffer_get_int_ret(&cctx->want_tty, m) != 0 || @@ -454,14 +456,10 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r) channel_send_open(nc->self); channel_register_open_confirm(nc->self, mux_session_confirm, cctx); + c->mux_pause = 1; /* stop handling messages until open_confirm done */ channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1); - /* prepare reply */ - /* XXX defer until mux_session_confirm() fires */ - buffer_put_int(r, MUX_S_SESSION_OPENED); - buffer_put_int(r, rid); - buffer_put_int(r, nc->self); - + /* reply is deferred, sent by mux_session_confirm */ return 0; } @@ -1000,17 +998,31 @@ muxserver_listen(void) /* Callback on open confirmation in mux master for a mux client session. */ static void -mux_session_confirm(int id, void *arg) +mux_session_confirm(int id, int success, void *arg) { struct mux_session_confirm_ctx *cctx = arg; const char *display; - Channel *c; + Channel *c, *cc; int i; + Buffer reply; if (cctx == NULL) fatal("%s: cctx == NULL", __func__); if ((c = channel_by_id(id)) == NULL) fatal("%s: no channel for id %d", __func__, id); + if ((cc = channel_by_id(c->ctl_chan)) == NULL) + fatal("%s: channel %d lacks control channel %d", __func__, + id, c->ctl_chan); + + if (!success) { + debug3("%s: sending failure reply", __func__); + /* prepare reply */ + buffer_init(&reply); + buffer_put_int(&reply, MUX_S_FAILURE); + buffer_put_int(&reply, cctx->rid); + buffer_put_cstring(&reply, "Session open refused by peer"); + goto done; + } display = getenv("DISPLAY"); if (cctx->want_x_fwd && options.forward_x11 && display != NULL) { @@ -1033,6 +1045,21 @@ mux_session_confirm(int id, void *arg) client_session2_setup(id, cctx->want_tty, cctx->want_subsys, cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env); + debug3("%s: sending success reply", __func__); + /* prepare reply */ + buffer_init(&reply); + buffer_put_int(&reply, MUX_S_SESSION_OPENED); + buffer_put_int(&reply, cctx->rid); + buffer_put_int(&reply, c->self); + + done: + /* Send reply */ + buffer_put_string(&cc->output, buffer_ptr(&reply), buffer_len(&reply)); + buffer_free(&reply); + + if (cc->mux_pause <= 0) + fatal("%s: mux_pause %d", __func__, cc->mux_pause); + cc->mux_pause = 0; /* start processing messages again */ c->open_confirm_ctx = NULL; buffer_free(&cctx->cmd); xfree(cctx->term); diff --git a/ssh.c b/ssh.c index 2230edd16..ee224e9ff 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.336 2010/04/10 00:00:16 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.337 2010/05/14 23:29:23 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1175,12 +1175,15 @@ ssh_session(void) /* request pty/x11/agent/tcpfwd/shell for channel */ static void -ssh_session2_setup(int id, void *arg) +ssh_session2_setup(int id, int success, void *arg) { extern char **environ; const char *display; int interactive = tty_flag; + if (!success) + return; /* No need for error message, channels code sens one */ + display = getenv("DISPLAY"); if (options.forward_x11 && display != NULL) { char *proto, *data; -- cgit v1.2.3 From 388f6fc48561851dcedd5433aff75f60af573fb2 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 21 May 2010 14:57:35 +1000 Subject: - markus@cvs.openbsd.org 2010/05/16 12:55:51 [PROTOCOL.mux clientloop.h mux.c readconf.c readconf.h ssh.1 ssh.c] mux support for remote forwarding with dynamic port allocation, use with LPORT=`ssh -S muxsocket -R0:localhost:25 -O forward somehost` feedback and ok djm@ --- ChangeLog | 6 ++++ PROTOCOL.mux | 13 +++++-- clientloop.h | 3 +- mux.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- readconf.c | 3 +- readconf.h | 3 +- ssh.1 | 11 ++++-- ssh.c | 9 +++-- 8 files changed, 141 insertions(+), 20 deletions(-) (limited to 'ssh.c') diff --git a/ChangeLog b/ChangeLog index a485000a8..fffbd727e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -23,6 +23,12 @@ the server. motivated by and with feedback from markus@ + - markus@cvs.openbsd.org 2010/05/16 12:55:51 + [PROTOCOL.mux clientloop.h mux.c readconf.c readconf.h ssh.1 ssh.c] + mux support for remote forwarding with dynamic port allocation, + use with + LPORT=`ssh -S muxsocket -R0:localhost:25 -O forward somehost` + feedback and ok djm@ 20100511 - (dtucker) [Makefile.in] Bug #1770: Link libopenbsd-compat twice to solve diff --git a/PROTOCOL.mux b/PROTOCOL.mux index d22f7379c..1d8c463a7 100644 --- a/PROTOCOL.mux +++ b/PROTOCOL.mux @@ -109,8 +109,14 @@ A client may request the master to establish a port forward: forwarding type may be MUX_FWD_LOCAL, MUX_FWD_REMOTE, MUX_FWD_DYNAMIC. -A server may reply with a MUX_S_OK, a MUX_S_PERMISSION_DENIED or a -MUX_S_FAILURE. +A server may reply with a MUX_S_OK, a MUX_S_REMOTE_PORT, a +MUX_S_PERMISSION_DENIED or a MUX_S_FAILURE. + +For dynamically allocated listen port the server replies with + + uint32 MUX_S_REMOTE_PORT + uint32 client request id + uint32 allocated remote listen port 5. Requesting closure of port forwards @@ -178,6 +184,7 @@ The MUX_S_PERMISSION_DENIED and MUX_S_FAILURE include a reason: #define MUX_S_EXIT_MESSAGE 0x80000004 #define MUX_S_ALIVE 0x80000005 #define MUX_S_SESSION_OPENED 0x80000006 +#define MUX_S_REMOTE_PORT 0x80000007 #define MUX_FWD_LOCAL 1 #define MUX_FWD_REMOTE 2 @@ -193,4 +200,4 @@ XXX server->client error/warning notifications XXX port0 rfwd (need custom response message) XXX send signals via mux -$OpenBSD: PROTOCOL.mux,v 1.1 2010/01/26 01:28:35 djm Exp $ +$OpenBSD: PROTOCOL.mux,v 1.2 2010/05/16 12:55:51 markus Exp $ diff --git a/clientloop.h b/clientloop.h index 0b8257b99..a5bc246a3 100644 --- a/clientloop.h +++ b/clientloop.h @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.h,v 1.23 2010/01/26 01:28:35 djm Exp $ */ +/* $OpenBSD: clientloop.h,v 1.24 2010/05/16 12:55:51 markus Exp $ */ /* * Author: Tatu Ylonen @@ -63,6 +63,7 @@ void client_register_global_confirm(global_confirm_cb *, void *); #define SSHMUX_COMMAND_ALIVE_CHECK 2 /* Check master is alive */ #define SSHMUX_COMMAND_TERMINATE 3 /* Ask master to exit */ #define SSHMUX_COMMAND_STDIO_FWD 4 /* Open stdio fwd (ssh -W) */ +#define SSHMUX_COMMAND_FORWARD 5 /* Forward only, no command */ void muxserver_listen(void); void muxclient(const char *); diff --git a/mux.c b/mux.c index 18dfd99f3..3f5babccc 100644 --- a/mux.c +++ b/mux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mux.c,v 1.17 2010/05/14 23:29:23 djm Exp $ */ +/* $OpenBSD: mux.c,v 1.18 2010/05/16 12:55:51 markus Exp $ */ /* * Copyright (c) 2002-2008 Damien Miller * @@ -71,6 +71,7 @@ #include "xmalloc.h" #include "log.h" #include "ssh.h" +#include "ssh2.h" #include "pathnames.h" #include "misc.h" #include "match.h" @@ -109,6 +110,13 @@ struct mux_session_confirm_ctx { u_int rid; }; +/* Context for global channel callback */ +struct mux_channel_confirm_ctx { + u_int cid; /* channel id */ + u_int rid; /* request id */ + int fid; /* forward id */ +}; + /* fd to control socket */ int muxserver_sock = -1; @@ -144,6 +152,7 @@ struct mux_master_state { #define MUX_S_EXIT_MESSAGE 0x80000004 #define MUX_S_ALIVE 0x80000005 #define MUX_S_SESSION_OPENED 0x80000006 +#define MUX_S_REMOTE_PORT 0x80000007 /* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */ #define MUX_FWD_LOCAL 1 @@ -557,6 +566,61 @@ compare_forward(Forward *a, Forward *b) return 1; } +static void +mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) +{ + struct mux_channel_confirm_ctx *fctx = ctxt; + char *failmsg = NULL; + Forward *rfwd; + Channel *c; + Buffer out; + + if ((c = channel_by_id(fctx->cid)) == NULL) { + /* no channel for reply */ + error("%s: unknown channel", __func__); + return; + } + buffer_init(&out); + if (fctx->fid >= options.num_remote_forwards) { + xasprintf(&failmsg, "unknown forwarding id %d", fctx->fid); + goto fail; + } + rfwd = &options.remote_forwards[fctx->fid]; + debug("%s: %s for: listen %d, connect %s:%d", __func__, + type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", + rfwd->listen_port, rfwd->connect_host, rfwd->connect_port); + if (type == SSH2_MSG_REQUEST_SUCCESS) { + if (rfwd->listen_port == 0) { + rfwd->allocated_port = packet_get_int(); + logit("Allocated port %u for mux remote forward" + " to %s:%d", rfwd->allocated_port, + rfwd->connect_host, rfwd->connect_port); + buffer_put_int(&out, MUX_S_REMOTE_PORT); + buffer_put_int(&out, fctx->rid); + buffer_put_int(&out, rfwd->allocated_port); + } else { + buffer_put_int(&out, MUX_S_OK); + buffer_put_int(&out, fctx->rid); + } + goto out; + } else { + xasprintf(&failmsg, "remote port forwarding failed for " + "listen port %d", rfwd->listen_port); + } + fail: + error("%s: %s", __func__, failmsg); + buffer_put_int(&out, MUX_S_FAILURE); + buffer_put_int(&out, fctx->rid); + buffer_put_cstring(&out, failmsg); + xfree(failmsg); + out: + buffer_put_string(&c->output, buffer_ptr(&out), buffer_len(&out)); + buffer_free(&out); + if (c->mux_pause <= 0) + fatal("%s: mux_pause %d", __func__, c->mux_pause); + c->mux_pause = 0; /* start processing messages again */ +} + static int process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) { @@ -592,15 +656,16 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) ftype != MUX_FWD_DYNAMIC) { logit("%s: invalid forwarding type %u", __func__, ftype); invalid: - xfree(fwd.listen_host); - xfree(fwd.connect_host); + if (fwd.listen_host) + xfree(fwd.listen_host); + if (fwd.connect_host) + xfree(fwd.connect_host); buffer_put_int(r, MUX_S_FAILURE); buffer_put_int(r, rid); buffer_put_cstring(r, "Invalid forwarding request"); return 0; } - /* XXX support rport0 forwarding with reply of port assigned */ - if (fwd.listen_port == 0 || fwd.listen_port >= 65536) { + if (fwd.listen_port >= 65536) { logit("%s: invalid listen port %u", __func__, fwd.listen_port); goto invalid; @@ -635,8 +700,17 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) case MUX_FWD_REMOTE: for (i = 0; i < options.num_remote_forwards; i++) { if (compare_forward(&fwd, - options.remote_forwards + i)) - goto exists; + options.remote_forwards + i)) { + if (fwd.listen_port != 0) + goto exists; + debug2("%s: found allocated port", + __func__); + buffer_put_int(r, MUX_S_REMOTE_PORT); + buffer_put_int(r, rid); + buffer_put_int(r, + options.remote_forwards[i].allocated_port); + goto out; + } } break; } @@ -668,14 +742,24 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) add_local_forward(&options, &fwd); freefwd = 0; } else { - /* XXX wait for remote to confirm */ + struct mux_channel_confirm_ctx *fctx; + if (options.num_remote_forwards + 1 >= SSH_MAX_FORWARDS_PER_DIRECTION || channel_request_remote_forwarding(fwd.listen_host, fwd.listen_port, fwd.connect_host, fwd.connect_port) < 0) goto fail; add_remote_forward(&options, &fwd); + fctx = xcalloc(1, sizeof(*fctx)); + fctx->cid = c->self; + fctx->rid = rid; + fctx->fid = options.num_remote_forwards-1; + client_register_global_confirm(mux_confirm_remote_forward, + fctx); freefwd = 0; + c->mux_pause = 1; /* wait for mux_confirm_remote_forward */ + /* delayed reply in mux_confirm_remote_forward */ + goto out; } buffer_put_int(r, MUX_S_OK); buffer_put_int(r, rid); @@ -1392,6 +1476,15 @@ mux_client_request_forward(int fd, u_int ftype, Forward *fwd) switch (type) { case MUX_S_OK: break; + case MUX_S_REMOTE_PORT: + fwd->allocated_port = buffer_get_int(&m); + logit("Allocated port %u for remote forward to %s:%d", + fwd->allocated_port, + fwd->connect_host ? fwd->connect_host : "", + fwd->connect_port); + if (muxclient_command == SSHMUX_COMMAND_FORWARD) + fprintf(stdout, "%u\n", fwd->allocated_port); + break; case MUX_S_PERMISSION_DENIED: e = buffer_get_string(&m, NULL); buffer_free(&m); @@ -1758,6 +1851,10 @@ muxclient(const char *path) mux_client_request_terminate(sock); fprintf(stderr, "Exit request sent.\r\n"); exit(0); + case SSHMUX_COMMAND_FORWARD: + if (mux_client_request_forwards(sock) != 0) + fatal("%s: master forward request failed", __func__); + exit(0); case SSHMUX_COMMAND_OPEN: if (mux_client_request_forwards(sock) != 0) { error("%s: master forward request failed", __func__); diff --git a/readconf.c b/readconf.c index 8bdc8caf1..4bc98b77e 100644 --- a/readconf.c +++ b/readconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.c,v 1.183 2010/02/08 10:50:20 markus Exp $ */ +/* $OpenBSD: readconf.c,v 1.184 2010/05/16 12:55:51 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -283,6 +283,7 @@ add_remote_forward(Options *options, const Forward *newfwd) fwd->listen_port = newfwd->listen_port; fwd->connect_host = newfwd->connect_host; fwd->connect_port = newfwd->connect_port; + fwd->allocated_port = 0; } static void diff --git a/readconf.h b/readconf.h index 4264751c5..4fb29e2fa 100644 --- a/readconf.h +++ b/readconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.h,v 1.82 2010/02/08 10:50:20 markus Exp $ */ +/* $OpenBSD: readconf.h,v 1.83 2010/05/16 12:55:51 markus Exp $ */ /* * Author: Tatu Ylonen @@ -23,6 +23,7 @@ typedef struct { int listen_port; /* Port to forward. */ char *connect_host; /* Host to connect. */ int connect_port; /* Port to connect on connect_host. */ + int allocated_port; /* Dynamically allocated listen port */ } Forward; /* Data structure for representing option data. */ diff --git a/ssh.1 b/ssh.1 index 34bddbcbc..2a0fd5ddd 100644 --- a/ssh.1 +++ b/ssh.1 @@ -34,8 +34,8 @@ .\" (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.1,v 1.304 2010/03/26 06:54:36 jmc Exp $ -.Dd $Mdocdate: March 26 2010 $ +.\" $OpenBSD: ssh.1,v 1.305 2010/05/16 12:55:51 markus Exp $ +.Dd $Mdocdate: May 16 2010 $ .Dt SSH 1 .Os .Sh NAME @@ -421,7 +421,9 @@ option is specified, the argument is interpreted and passed to the master process. Valid commands are: .Dq check -(check that the master process is running) and +(check that the master process is running), +.Dq forward +(request forwardings without command execution) and .Dq exit (request the master to exit). .It Fl o Ar option @@ -557,6 +559,9 @@ argument is .Ql 0 , the listen port will be dynamically allocated on the server and reported to the client at run time. +When used together with +.Ic -O forward +the allocated port will be printed to the standard output. .It Fl S Ar ctl_path Specifies the location of a control socket for connection sharing, or the string diff --git a/ssh.c b/ssh.c index ee224e9ff..228afecf4 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.337 2010/05/14 23:29:23 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.338 2010/05/16 12:55:51 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -327,6 +327,8 @@ main(int ac, char **av) fatal("Multiplexing command already specified"); if (strcmp(optarg, "check") == 0) muxclient_command = SSHMUX_COMMAND_ALIVE_CHECK; + else if (strcmp(optarg, "forward") == 0) + muxclient_command = SSHMUX_COMMAND_FORWARD; else if (strcmp(optarg, "exit") == 0) muxclient_command = SSHMUX_COMMAND_TERMINATE; else @@ -877,9 +879,10 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", rfwd->listen_port, rfwd->connect_host, rfwd->connect_port); if (type == SSH2_MSG_REQUEST_SUCCESS && rfwd->listen_port == 0) { + rfwd->allocated_port = packet_get_int(); logit("Allocated port %u for remote forward to %s:%d", - packet_get_int(), - rfwd->connect_host, rfwd->connect_port); + rfwd->allocated_port, + rfwd->connect_host, rfwd->connect_port); } if (type == SSH2_MSG_REQUEST_FAILURE) { -- cgit v1.2.3 From 383ffe6c5f31d3ecd89caadc8aef1bc2b821d63a Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Sat, 26 Jun 2010 10:02:03 +1000 Subject: - djm@cvs.openbsd.org 2010/06/25 23:10:30 [ssh.c] log the hostname and address that we connected to at LogLevel=verbose after authentication is successful to mitigate "phishing" attacks by servers with trusted keys that accept authentication silently and automatically before presenting fake password/passphrase prompts; "nice!" markus@ --- ChangeLog | 7 +++++++ ssh.c | 9 ++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'ssh.c') diff --git a/ChangeLog b/ChangeLog index 2467840e0..b0f82de2f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -67,6 +67,13 @@ [auth1.c auth2-none.c] skip the initial check for access with an empty password when PermitEmptyPasswords=no; bz#1638; ok markus@ + - djm@cvs.openbsd.org 2010/06/25 23:10:30 + [ssh.c] + log the hostname and address that we connected to at LogLevel=verbose + after authentication is successful to mitigate "phishing" attacks by + servers with trusted keys that accept authentication silently and + automatically before presenting fake password/passphrase prompts; + "nice!" markus@ 20100622 - (djm) [loginrec.c] crank LINFO_NAMESIZE (username length) to 512 diff --git a/ssh.c b/ssh.c index 228afecf4..6537ad9a2 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.338 2010/05/16 12:55:51 markus Exp $ */ +/* $OpenBSD: ssh.c,v 1.339 2010/06/25 23:10:30 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -829,6 +829,13 @@ main(int ac, char **av) ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr, pw, timeout_ms); + if (packet_connection_is_on_socket()) { + verbose("Authenticated to %s ([%s]:%d).", host, + get_remote_ipaddr(), get_remote_port()); + } else { + verbose("Authenticated to %s (via proxy).", host); + } + /* We no longer need the private host keys. Clear them now. */ if (sensitive_data.nkeys != 0) { for (i = 0; i < sensitive_data.nkeys; i++) { -- cgit v1.2.3 From 1ab6a51f9b258a6e844f1ee442c15aec7fcb6a72 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Sat, 26 Jun 2010 10:02:24 +1000 Subject: - djm@cvs.openbsd.org 2010/06/25 23:10:30 [ssh.c] log the hostname and address that we connected to at LogLevel=verbose after authentication is successful to mitigate "phishing" attacks by servers with trusted keys that accept authentication silently and automatically before presenting fake password/passphrase prompts; "nice!" markus@ --- ChangeLog | 7 +++++++ clientloop.c | 26 ++++++++++++++++++++------ clientloop.h | 4 ++-- mux.c | 9 ++++++--- readconf.c | 14 +++++++++++--- readconf.h | 3 ++- ssh.c | 9 ++++++--- ssh_config.5 | 14 ++++++++++++-- 8 files changed, 66 insertions(+), 20 deletions(-) (limited to 'ssh.c') diff --git a/ChangeLog b/ChangeLog index b0f82de2f..d86960e31 100644 --- a/ChangeLog +++ b/ChangeLog @@ -74,6 +74,13 @@ servers with trusted keys that accept authentication silently and automatically before presenting fake password/passphrase prompts; "nice!" markus@ + - djm@cvs.openbsd.org 2010/06/25 23:10:30 + [ssh.c] + log the hostname and address that we connected to at LogLevel=verbose + after authentication is successful to mitigate "phishing" attacks by + servers with trusted keys that accept authentication silently and + automatically before presenting fake password/passphrase prompts; + "nice!" markus@ 20100622 - (djm) [loginrec.c] crank LINFO_NAMESIZE (username length) to 512 diff --git a/clientloop.c b/clientloop.c index 76de37213..5608bcc2e 100644 --- a/clientloop.c +++ b/clientloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.c,v 1.220 2010/04/10 02:08:44 djm Exp $ */ +/* $OpenBSD: clientloop.c,v 1.221 2010/06/25 23:15:36 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -155,11 +155,12 @@ static int stdin_eof; /* EOF has been encountered on stderr. */ static Buffer stdin_buffer; /* Buffer for stdin data. */ static Buffer stdout_buffer; /* Buffer for stdout data. */ static Buffer stderr_buffer; /* Buffer for stderr data. */ -static u_int buffer_high;/* Soft max buffer size. */ +static u_int buffer_high; /* Soft max buffer size. */ static int connection_in; /* Connection to server (input). */ static int connection_out; /* Connection to server (output). */ static int need_rekeying; /* Set to non-zero if rekeying is requested. */ -static int session_closed = 0; /* In SSH2: login session closed. */ +static int session_closed; /* In SSH2: login session closed. */ +static int x11_refuse_time; /* If >0, refuse x11 opens after this time. */ static void client_init_dispatch(void); int session_ident = -1; @@ -254,7 +255,7 @@ get_current_time(void) #define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" void client_x11_get_proto(const char *display, const char *xauth_path, - u_int trusted, char **_proto, char **_data) + u_int trusted, u_int timeout, char **_proto, char **_data) { char cmd[1024]; char line[512]; @@ -264,6 +265,7 @@ client_x11_get_proto(const char *display, const char *xauth_path, int got_data = 0, generated = 0, do_unlink = 0, i; char *xauthdir, *xauthfile; struct stat st; + u_int now; xauthdir = xauthfile = NULL; *_proto = proto; @@ -299,11 +301,18 @@ client_x11_get_proto(const char *display, const char *xauth_path, xauthdir); snprintf(cmd, sizeof(cmd), "%s -f %s generate %s " SSH_X11_PROTO - " untrusted timeout 1200 2>" _PATH_DEVNULL, - xauth_path, xauthfile, display); + " untrusted timeout %u 2>" _PATH_DEVNULL, + xauth_path, xauthfile, display, timeout); debug2("x11_get_proto: %s", cmd); if (system(cmd) == 0) generated = 1; + if (x11_refuse_time == 0) { + now = time(NULL) + 1; + if (UINT_MAX - timeout < now) + x11_refuse_time = UINT_MAX; + else + x11_refuse_time = now + timeout; + } } } @@ -1686,6 +1695,11 @@ client_request_x11(const char *request_type, int rchan) "malicious server."); return NULL; } + if (x11_refuse_time != 0 && time(NULL) >= x11_refuse_time) { + verbose("Rejected X11 connection after ForwardX11Timeout " + "expired"); + return NULL; + } originator = packet_get_string(NULL); if (datafellows & SSH_BUG_X11FWD) { debug2("buggy server: x11 request w/o originator_port"); diff --git a/clientloop.h b/clientloop.h index a5bc246a3..52115db6e 100644 --- a/clientloop.h +++ b/clientloop.h @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.h,v 1.24 2010/05/16 12:55:51 markus Exp $ */ +/* $OpenBSD: clientloop.h,v 1.25 2010/06/25 23:15:36 djm Exp $ */ /* * Author: Tatu Ylonen @@ -39,7 +39,7 @@ /* Client side main loop for the interactive session. */ int client_loop(int, int, int); -void client_x11_get_proto(const char *, const char *, u_int, +void client_x11_get_proto(const char *, const char *, u_int, u_int, char **, char **); void client_global_request_reply_fwd(int, u_int32_t, void *); void client_session2_setup(int, int, int, const char *, struct termios *, diff --git a/mux.c b/mux.c index fdf0385e0..5c3857ee8 100644 --- a/mux.c +++ b/mux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mux.c,v 1.20 2010/06/25 07:14:46 djm Exp $ */ +/* $OpenBSD: mux.c,v 1.21 2010/06/25 23:15:36 djm Exp $ */ /* * Copyright (c) 2002-2008 Damien Miller * @@ -1107,11 +1107,14 @@ mux_session_confirm(int id, int success, void *arg) 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); + options.forward_x11_trusted, options.forward_x11_timeout, + &proto, &data); /* Request forwarding with authentication spoofing. */ - debug("Requesting X11 forwarding with authentication spoofing."); + debug("Requesting X11 forwarding with authentication " + "spoofing."); x11_request_forwarding_with_spoofing(id, display, proto, data); /* XXX wait for reply */ } diff --git a/readconf.c b/readconf.c index aae9cef4b..da48ae7da 100644 --- a/readconf.c +++ b/readconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.c,v 1.185 2010/06/25 07:14:46 djm Exp $ */ +/* $OpenBSD: readconf.c,v 1.186 2010/06/25 23:15:36 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -110,8 +110,8 @@ typedef enum { oBadOption, - oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts, - oExitOnForwardFailure, + oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout, + oGatewayPorts, oExitOnForwardFailure, oPasswordAuthentication, oRSAAuthentication, oChallengeResponseAuthentication, oXAuthLocation, oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward, @@ -143,6 +143,7 @@ static struct { { "forwardagent", oForwardAgent }, { "forwardx11", oForwardX11 }, { "forwardx11trusted", oForwardX11Trusted }, + { "forwardx11timeout", oForwardX11Timeout }, { "exitonforwardfailure", oExitOnForwardFailure }, { "xauthlocation", oXAuthLocation }, { "gatewayports", oGatewayPorts }, @@ -414,6 +415,10 @@ parse_flag: case oForwardX11Trusted: intptr = &options->forward_x11_trusted; goto parse_flag; + + case oForwardX11Timeout: + intptr = &options->forward_x11_timeout; + goto parse_time; case oGatewayPorts: intptr = &options->gateway_ports; @@ -1018,6 +1023,7 @@ initialize_options(Options * options) options->forward_agent = -1; options->forward_x11 = -1; options->forward_x11_trusted = -1; + options->forward_x11_timeout = -1; options->exit_on_forward_failure = -1; options->xauth_location = NULL; options->gateway_ports = -1; @@ -1104,6 +1110,8 @@ fill_default_options(Options * options) options->forward_x11 = 0; if (options->forward_x11_trusted == -1) options->forward_x11_trusted = 0; + if (options->forward_x11_timeout == -1) + options->forward_x11_timeout = 1200; if (options->exit_on_forward_failure == -1) options->exit_on_forward_failure = 0; if (options->xauth_location == NULL) diff --git a/readconf.h b/readconf.h index 3c8eae9d2..66acafdef 100644 --- a/readconf.h +++ b/readconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.h,v 1.84 2010/06/25 07:14:46 djm Exp $ */ +/* $OpenBSD: readconf.h,v 1.85 2010/06/25 23:15:36 djm Exp $ */ /* * Author: Tatu Ylonen @@ -32,6 +32,7 @@ typedef struct { typedef struct { int forward_agent; /* Forward authentication agent. */ int forward_x11; /* Forward X11 display. */ + int forward_x11_timeout; /* Expiration for Cookies */ int forward_x11_trusted; /* Trust Forward X11 display. */ int exit_on_forward_failure; /* Exit if bind(2) fails for -L/-R */ char *xauth_location; /* Location for xauth program */ diff --git a/ssh.c b/ssh.c index 6537ad9a2..d8f0b214f 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.339 2010/06/25 23:10:30 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.340 2010/06/25 23:15:36 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1103,7 +1103,9 @@ ssh_session(void) char *proto, *data; /* Get reasonable local authentication information. */ client_x11_get_proto(display, options.xauth_location, - options.forward_x11_trusted, &proto, &data); + options.forward_x11_trusted, + options.forward_x11_timeout, + &proto, &data); /* Request forwarding with authentication spoofing. */ debug("Requesting X11 forwarding with authentication " "spoofing."); @@ -1199,7 +1201,8 @@ ssh_session2_setup(int id, int success, void *arg) char *proto, *data; /* Get reasonable local authentication information. */ client_x11_get_proto(display, options.xauth_location, - options.forward_x11_trusted, &proto, &data); + options.forward_x11_trusted, + options.forward_x11_timeout, &proto, &data); /* Request forwarding with authentication spoofing. */ debug("Requesting X11 forwarding with authentication " "spoofing."); diff --git a/ssh_config.5 b/ssh_config.5 index 2df948e62..6968a4488 100644 --- a/ssh_config.5 +++ b/ssh_config.5 @@ -34,8 +34,8 @@ .\" (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.133 2010/04/16 06:45:01 jmc Exp $ -.Dd $Mdocdate: April 16 2010 $ +.\" $OpenBSD: ssh_config.5,v 1.134 2010/06/25 23:15:36 djm Exp $ +.Dd $Mdocdate: June 25 2010 $ .Dt SSH_CONFIG 5 .Os .Sh NAME @@ -432,6 +432,16 @@ An attacker may then be able to perform activities such as keystroke monitoring if the .Cm ForwardX11Trusted option is also enabled. +.It Cm ForwardX11Timeout +Specify a timeout for untrusted X11 forwarding using the format described in +.Sx TIME FORMATS +section of +.Xr sshd_config 5 . +X11 connections received by +.Xr ssh 1 +after this time will be refused. +The default is to disable untrusted X11 forwarding after twenty minutes has +elapsed. .It Cm ForwardX11Trusted If this option is set to .Dq yes , -- cgit v1.2.3 From b96c441ee2e4d8ffae756d0d74e2777149c91067 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 2 Jul 2010 13:34:24 +1000 Subject: - djm@cvs.openbsd.org 2010/06/26 23:04:04 [ssh.c] oops, forgot to #include ; spotted and patch from chl@ --- ChangeLog | 3 +++ ssh.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'ssh.c') diff --git a/ChangeLog b/ChangeLog index d64ea5ce6..20b39f0de 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,9 @@ - jmc@cvs.openbsd.org 2010/06/26 00:57:07 [ssh_config.5] tweak previous; + - djm@cvs.openbsd.org 2010/06/26 23:04:04 + [ssh.c] + oops, forgot to #include ; spotted and patch from chl@ 20100627 - (tim) [openbsd-compat/port-uw.c] Reorder includes. auth-options.h now needs diff --git a/ssh.c b/ssh.c index d8f0b214f..a1cf01513 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.340 2010/06/25 23:15:36 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.341 2010/06/26 23:04:04 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -79,6 +79,7 @@ #include "ssh.h" #include "ssh1.h" #include "ssh2.h" +#include "canohost.h" #include "compat.h" #include "cipher.h" #include "packet.h" -- cgit v1.2.3 From 1f25ab43f4b374f920120b93ae3ed2f8521472c5 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 16 Jul 2010 13:56:23 +1000 Subject: - djm@cvs.openbsd.org 2010/07/12 22:38:52 [ssh.c] Make ExitOnForwardFailure work with fork-after-authentication ("ssh -f") for protocol 2. ok markus@ --- ChangeLog | 4 ++++ ssh.c | 11 ++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'ssh.c') diff --git a/ChangeLog b/ChangeLog index ea087e8b4..50073141f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,10 @@ AllowUsers "blah blah" blah was broken; report and fix in bz#1757 from bitman.zhou AT centrify.com ok dtucker; + - djm@cvs.openbsd.org 2010/07/12 22:38:52 + [ssh.c] + Make ExitOnForwardFailure work with fork-after-authentication ("ssh -f") + for protocol 2. ok markus@ 20100714 - (tim) [contrib/redhat/openssh.spec] Bug 1796: Test for skip_x11_askpass diff --git a/ssh.c b/ssh.c index a1cf01513..e6073af7b 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.341 2010/06/26 23:04:04 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.342 2010/07/12 22:38:52 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1301,8 +1301,13 @@ ssh_session2(void) /* Start listening for multiplex clients */ muxserver_listen(); - /* If requested, let ssh continue in the background. */ - if (fork_after_authentication_flag) { + /* + * If requested and we are not interested in replies to remote + * forwarding requests, then let ssh continue in the background. + */ + if (fork_after_authentication_flag && + (!options.exit_on_forward_failure || + options.num_remote_forwards == 0)) { fork_after_authentication_flag = 0; if (daemon(1, 1) < 0) fatal("daemon() failed: %.200s", strerror(errno)); -- cgit v1.2.3 From d0244d498ba970b9d9348429eaf7a4a0ef2b903c Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 16 Jul 2010 13:56:43 +1000 Subject: - djm@cvs.openbsd.org 2010/07/12 22:41:13 [ssh.c ssh_config.5] expand %h to the hostname in ssh_config Hostname options. While this sounds useless, it is actually handy for working with unqualified hostnames: Host *.* Hostname %h Host * Hostname %h.example.org "I like it" markus@ --- ChangeLog | 12 ++++++++++++ ssh.c | 15 ++++++++------- ssh_config.5 | 8 ++++++-- 3 files changed, 26 insertions(+), 9 deletions(-) (limited to 'ssh.c') diff --git a/ChangeLog b/ChangeLog index 50073141f..f652e6183 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,6 +10,18 @@ [ssh.c] Make ExitOnForwardFailure work with fork-after-authentication ("ssh -f") for protocol 2. ok markus@ + - djm@cvs.openbsd.org 2010/07/12 22:41:13 + [ssh.c ssh_config.5] + expand %h to the hostname in ssh_config Hostname options. While this + sounds useless, it is actually handy for working with unqualified + hostnames: + + Host *.* + Hostname %h + Host * + Hostname %h.example.org + + "I like it" markus@ 20100714 - (tim) [contrib/redhat/openssh.spec] Bug 1796: Test for skip_x11_askpass diff --git a/ssh.c b/ssh.c index e6073af7b..61fe10df0 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.342 2010/07/12 22:38:52 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.343 2010/07/12 22:41:13 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -679,6 +679,11 @@ main(int ac, char **av) options.port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT; } + if (options.hostname != NULL) { + host = percent_expand(options.hostname, + "h", host, (char *)NULL); + } + if (options.local_command != NULL) { char thishost[NI_MAXHOST]; @@ -688,16 +693,12 @@ main(int ac, char **av) debug3("expanding LocalCommand: %s", options.local_command); cp = options.local_command; options.local_command = percent_expand(cp, "d", pw->pw_dir, - "h", options.hostname? options.hostname : host, - "l", thishost, "n", host, "r", options.user, "p", buf, - "u", pw->pw_name, (char *)NULL); + "h", host, "l", thishost, "n", host, "r", options.user, + "p", buf, "u", pw->pw_name, (char *)NULL); debug3("expanded LocalCommand: %s", options.local_command); xfree(cp); } - if (options.hostname != NULL) - host = options.hostname; - /* force lowercase for hostkey matching */ if (options.host_key_alias != NULL) { for (p = options.host_key_alias; *p; p++) diff --git a/ssh_config.5 b/ssh_config.5 index 531a60b5e..e7bb21ebb 100644 --- a/ssh_config.5 +++ b/ssh_config.5 @@ -34,8 +34,8 @@ .\" (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.135 2010/06/26 00:57:07 jmc Exp $ -.Dd $Mdocdate: June 26 2010 $ +.\" $OpenBSD: ssh_config.5,v 1.136 2010/07/12 22:41:13 djm Exp $ +.Dd $Mdocdate: July 12 2010 $ .Dt SSH_CONFIG 5 .Os .Sh NAME @@ -537,6 +537,10 @@ or for multiple servers running on a single host. .It Cm HostName Specifies the real host name to log into. This can be used to specify nicknames or abbreviations for hosts. +If the hostname contains the character sequence +.Ql %h , +then this will be replaced with the host name specified on the commandline +(this is useful for manipulating unqualified names). The default is the name given on the command line. Numeric IP addresses are also permitted (both on the command line and in .Cm HostName -- cgit v1.2.3 From e11e1ea5d475ee8be0038d64aa3e47c776295ac2 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Tue, 3 Aug 2010 16:04:46 +1000 Subject: - djm@cvs.openbsd.org 2010/07/19 09:15:12 [clientloop.c readconf.c readconf.h ssh.c ssh_config.5] add a "ControlPersist" option that automatically starts a background ssh(1) multiplex master when connecting. This connection can stay alive indefinitely, or can be set to automatically close after a user-specified duration of inactivity. bz#1330 - patch by dwmw2 AT infradead.org, but further hacked on by wmertens AT cisco.com, apb AT cequrux.com, martin-mindrot-bugzilla AT earth.li and myself; "looks ok" markus@ --- ChangeLog | 8 ++++ clientloop.c | 63 ++++++++++++++++++++++++++++++-- readconf.c | 36 +++++++++++++++++- readconf.h | 4 +- ssh.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++----------- ssh_config.5 | 26 ++++++++++++- 6 files changed, 223 insertions(+), 31 deletions(-) (limited to 'ssh.c') diff --git a/ChangeLog b/ChangeLog index f4fb5f05f..b43074ec9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,14 @@ bz#1797: fix swapped args in upload_dir_internal(), breaking recursive upload depth checks and causing verbose printing of transfers to always be turned on; patch from imorgan AT nas.nasa.gov + - djm@cvs.openbsd.org 2010/07/19 09:15:12 + [clientloop.c readconf.c readconf.h ssh.c ssh_config.5] + add a "ControlPersist" option that automatically starts a background + ssh(1) multiplex master when connecting. This connection can stay alive + indefinitely, or can be set to automatically close after a user-specified + duration of inactivity. bz#1330 - patch by dwmw2 AT infradead.org, but + further hacked on by wmertens AT cisco.com, apb AT cequrux.com, + martin-mindrot-bugzilla AT earth.li and myself; "looks ok" markus@ 20100819 - (dtucker) [contrib/ssh-copy-ud.1] Bug #1786: update ssh-copy-id.1 with more diff --git a/clientloop.c b/clientloop.c index 5608bcc2e..de7979366 100644 --- a/clientloop.c +++ b/clientloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.c,v 1.221 2010/06/25 23:15:36 djm Exp $ */ +/* $OpenBSD: clientloop.c,v 1.222 2010/07/19 09:15:12 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -145,6 +145,9 @@ static volatile sig_atomic_t received_signal = 0; /* Flag indicating whether the user's terminal is in non-blocking mode. */ static int in_non_blocking_mode = 0; +/* Time when backgrounded control master using ControlPersist should exit */ +static time_t control_persist_exit_time = 0; + /* Common data for the client loop code. */ volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ static int escape_char1; /* Escape character. (proto1 only) */ @@ -252,6 +255,34 @@ get_current_time(void) return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0; } +/* + * Sets control_persist_exit_time to the absolute time when the + * backgrounded control master should exit due to expiry of the + * ControlPersist timeout. Sets it to 0 if we are not a backgrounded + * control master process, or if there is no ControlPersist timeout. + */ +static void +set_control_persist_exit_time(void) +{ + if (muxserver_sock == -1 || !options.control_persist + || options.control_persist_timeout == 0) + /* not using a ControlPersist timeout */ + control_persist_exit_time = 0; + else if (channel_still_open()) { + /* some client connections are still open */ + if (control_persist_exit_time > 0) + debug2("%s: cancel scheduled exit", __func__); + control_persist_exit_time = 0; + } else if (control_persist_exit_time <= 0) { + /* a client connection has recently closed */ + control_persist_exit_time = time(NULL) + + (time_t)options.control_persist_timeout; + debug2("%s: schedule exit in %d seconds", __func__, + options.control_persist_timeout); + } + /* else we are already counting down to the timeout */ +} + #define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" void client_x11_get_proto(const char *display, const char *xauth_path, @@ -533,6 +564,7 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, u_int *nallocp, int rekeying) { struct timeval tv, *tvp; + int timeout_secs; int ret; /* Add any selections by the channel mechanism. */ @@ -576,16 +608,27 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, /* * Wait for something to happen. This will suspend the process until * some selected descriptor can be read, written, or has some other - * event pending. + * event pending, or a timeout expires. */ - if (options.server_alive_interval == 0 || !compat20) + timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */ + if (options.server_alive_interval > 0 && compat20) + timeout_secs = options.server_alive_interval; + set_control_persist_exit_time(); + if (control_persist_exit_time > 0) { + timeout_secs = MIN(timeout_secs, + control_persist_exit_time - time(NULL)); + if (timeout_secs < 0) + timeout_secs = 0; + } + if (timeout_secs == INT_MAX) tvp = NULL; else { - tv.tv_sec = options.server_alive_interval; + tv.tv_sec = timeout_secs; tv.tv_usec = 0; tvp = &tv; } + ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); if (ret < 0) { char buf[100]; @@ -1478,6 +1521,18 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) */ if (FD_ISSET(connection_out, writeset)) packet_write_poll(); + + /* + * If we are a backgrounded control master, and the + * timeout has expired without any active client + * connections, then quit. + */ + if (control_persist_exit_time > 0) { + if (time(NULL) >= control_persist_exit_time) { + debug("ControlPersist timeout expired"); + break; + } + } } if (readset) xfree(readset); diff --git a/readconf.c b/readconf.c index da48ae7da..0296590e2 100644 --- a/readconf.c +++ b/readconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.c,v 1.186 2010/06/25 23:15:36 djm Exp $ */ +/* $OpenBSD: readconf.c,v 1.187 2010/07/19 09:15:12 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -128,7 +128,8 @@ typedef enum { oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, oAddressFamily, oGssAuthentication, oGssDelegateCreds, oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, - oSendEnv, oControlPath, oControlMaster, oHashKnownHosts, + oSendEnv, oControlPath, oControlMaster, oControlPersist, + oHashKnownHosts, oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication, oDeprecated, oUnsupported @@ -225,6 +226,7 @@ static struct { { "sendenv", oSendEnv }, { "controlpath", oControlPath }, { "controlmaster", oControlMaster }, + { "controlpersist", oControlPersist }, { "hashknownhosts", oHashKnownHosts }, { "tunnel", oTunnel }, { "tunneldevice", oTunnelDevice }, @@ -882,6 +884,30 @@ parse_int: *intptr = value; break; + case oControlPersist: + /* no/false/yes/true, or a time spec */ + intptr = &options->control_persist; + arg = strdelim(&s); + if (!arg || *arg == '\0') + fatal("%.200s line %d: Missing ControlPersist" + " argument.", filename, linenum); + value = 0; + value2 = 0; /* timeout */ + if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0) + value = 0; + else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0) + value = 1; + else if ((value2 = convtime(arg)) >= 0) + value = 1; + else + fatal("%.200s line %d: Bad ControlPersist argument.", + filename, linenum); + if (*activep && *intptr == -1) { + *intptr = value; + options->control_persist_timeout = value2; + } + break; + case oHashKnownHosts: intptr = &options->hash_known_hosts; goto parse_flag; @@ -1083,6 +1109,8 @@ initialize_options(Options * options) options->num_send_env = 0; options->control_path = NULL; options->control_master = -1; + options->control_persist = -1; + options->control_persist_timeout = 0; options->hash_known_hosts = -1; options->tun_open = -1; options->tun_local = -1; @@ -1218,6 +1246,10 @@ fill_default_options(Options * options) options->server_alive_count_max = 3; if (options->control_master == -1) options->control_master = 0; + if (options->control_persist == -1) { + options->control_persist = 0; + options->control_persist_timeout = 0; + } if (options->hash_known_hosts == -1) options->hash_known_hosts = 0; if (options->tun_open == -1) diff --git a/readconf.h b/readconf.h index 66acafdef..95d104674 100644 --- a/readconf.h +++ b/readconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.h,v 1.85 2010/06/25 23:15:36 djm Exp $ */ +/* $OpenBSD: readconf.h,v 1.86 2010/07/19 09:15:12 djm Exp $ */ /* * Author: Tatu Ylonen @@ -114,6 +114,8 @@ typedef struct { char *control_path; int control_master; + int control_persist; /* ControlPersist flag */ + int control_persist_timeout; /* ControlPersist timeout (seconds) */ int hash_known_hosts; diff --git a/ssh.c b/ssh.c index 61fe10df0..249be2db8 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.343 2010/07/12 22:41:13 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.344 2010/07/19 09:15:12 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -127,6 +127,15 @@ int no_shell_flag = 0; */ int stdin_null_flag = 0; +/* + * Flag indicating that the current process should be backgrounded and + * a new slave launched in the foreground for ControlPersist. + */ +int need_controlpersist_detach = 0; + +/* Copies of flags for ControlPersist foreground slave */ +int ostdin_null_flag, ono_shell_flag, ono_tty_flag, otty_flag; + /* * Flag indicating that ssh should fork after authentication. This is useful * so that the passphrase can be entered manually, and then ssh goes to the @@ -877,6 +886,50 @@ main(int ac, char **av) return exit_status; } +static void +control_persist_detach(void) +{ + pid_t pid; + + debug("%s: backgrounding master process", __func__); + + /* + * master (current process) into the background, and make the + * foreground process a client of the backgrounded master. + */ + switch ((pid = fork())) { + case -1: + fatal("%s: fork: %s", __func__, strerror(errno)); + case 0: + /* Child: master process continues mainloop */ + break; + default: + /* Parent: set up mux slave to connect to backgrounded master */ + debug2("%s: background process is %ld", __func__, (long)pid); + stdin_null_flag = ostdin_null_flag; + no_shell_flag = ono_shell_flag; + no_tty_flag = ono_tty_flag; + tty_flag = otty_flag; + close(muxserver_sock); + muxserver_sock = -1; + muxclient(options.control_path); + /* muxclient() doesn't return on success. */ + fatal("Failed to connect to new control master"); + } +} + +/* Do fork() after authentication. Used by "ssh -f" */ +static void +fork_postauth(void) +{ + if (need_controlpersist_detach) + control_persist_detach(); + debug("forking to background"); + fork_after_authentication_flag = 0; + if (daemon(1, 1) < 0) + fatal("daemon() failed: %.200s", strerror(errno)); +} + /* Callback for remote forward global requests */ static void ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) @@ -904,12 +957,8 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) } if (++remote_forward_confirms_received == options.num_remote_forwards) { debug("All remote forwarding requests processed"); - if (fork_after_authentication_flag) { - fork_after_authentication_flag = 0; - if (daemon(1, 1) < 0) - fatal("daemon() failed: %.200s", - strerror(errno)); - } + if (fork_after_authentication_flag) + fork_postauth(); } } @@ -1153,12 +1202,13 @@ ssh_session(void) * If requested and we are not interested in replies to remote * forwarding requests, then let ssh continue in the background. */ - if (fork_after_authentication_flag && - (!options.exit_on_forward_failure || - options.num_remote_forwards == 0)) { - fork_after_authentication_flag = 0; - if (daemon(1, 1) < 0) - fatal("daemon() failed: %.200s", strerror(errno)); + if (fork_after_authentication_flag) { + if (options.exit_on_forward_failure && + options.num_remote_forwards > 0) { + debug("deferring postauth fork until remote forward " + "confirmation received"); + } else + fork_postauth(); } /* @@ -1281,6 +1331,31 @@ ssh_session2(void) /* XXX should be pre-session */ ssh_init_forwarding(); + /* Start listening for multiplex clients */ + muxserver_listen(); + + /* + * If we are in control persist mode, then prepare to background + * ourselves and have a foreground client attach as a control + * slave. NB. we must save copies of the flags that we override for + * the backgrounding, since we defer attachment of the slave until + * after the connection is fully established (in particular, + * async rfwd replies have been received for ExitOnForwardFailure). + */ + if (options.control_persist && muxserver_sock != -1) { + ostdin_null_flag = stdin_null_flag; + ono_shell_flag = no_shell_flag; + ono_tty_flag = no_tty_flag; + otty_flag = tty_flag; + stdin_null_flag = 1; + no_shell_flag = 1; + no_tty_flag = 1; + tty_flag = 0; + if (!fork_after_authentication_flag) + need_controlpersist_detach = 1; + fork_after_authentication_flag = 1; + } + if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) id = ssh_session2_open(); @@ -1299,19 +1374,17 @@ ssh_session2(void) options.permit_local_command) ssh_local_cmd(options.local_command); - /* Start listening for multiplex clients */ - muxserver_listen(); - /* * If requested and we are not interested in replies to remote * forwarding requests, then let ssh continue in the background. */ - if (fork_after_authentication_flag && - (!options.exit_on_forward_failure || - options.num_remote_forwards == 0)) { - fork_after_authentication_flag = 0; - if (daemon(1, 1) < 0) - fatal("daemon() failed: %.200s", strerror(errno)); + if (fork_after_authentication_flag) { + if (options.exit_on_forward_failure && + options.num_remote_forwards > 0) { + debug("deferring postauth fork until remote forward " + "confirmation received"); + } else + fork_postauth(); } if (options.use_roaming) diff --git a/ssh_config.5 b/ssh_config.5 index e7bb21ebb..04df8184c 100644 --- a/ssh_config.5 +++ b/ssh_config.5 @@ -34,8 +34,8 @@ .\" (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.136 2010/07/12 22:41:13 djm Exp $ -.Dd $Mdocdate: July 12 2010 $ +.\" $OpenBSD: ssh_config.5,v 1.137 2010/07/19 09:15:12 djm Exp $ +.Dd $Mdocdate: July 19 2010 $ .Dt SSH_CONFIG 5 .Os .Sh NAME @@ -319,6 +319,28 @@ It is recommended that any used for opportunistic connection sharing include at least %h, %p, and %r. This ensures that shared connections are uniquely identified. +.It Cm ControlPersist +When used in conjunction with +.Cm ControlMaster , +specifies that the master connection should remain open +in the background (waiting for future client connections) +after the initial client connection has been closed. +If set to +.Dq no , +then the master connection will not be placed into the background, +and will close as soon as the initial client connection is closed. +If set to +.Dq yes , +then the master connection will remain in the background indefinitely +(until killed or closed via a mechanism such as the +.Xr ssh 1 +.Dq Fl O No exit +option). +If set to a time in seconds, or a time in any of the formats documented in +.Xr sshd_config 5 , +then the backgrounded master connection will automatically terminate +after it has remained idle (with no client connections) for the +specified time. .It Cm DynamicForward Specifies that a TCP port on the local machine be forwarded over the secure channel, and the application -- cgit v1.2.3 From c158331f8c7e059c6c1d099bffc7f5fc6087ddbd Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Thu, 5 Aug 2010 13:04:50 +1000 Subject: - djm@cvs.openbsd.org 2010/08/04 05:42:47 [auth.c auth2-hostbased.c authfile.c authfile.h ssh-keysign.8] [ssh-keysign.c ssh.c] enable certificates for hostbased authentication, from Iain Morgan; "looks ok" markus@ --- ChangeLog | 5 +++++ auth.c | 4 ++-- auth2-hostbased.c | 31 +++++++++++++++++++++++++--- authfile.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- authfile.h | 4 +++- ssh-keysign.8 | 7 +++++-- ssh-keysign.c | 4 ++-- ssh.c | 24 ++++++++++++++-------- 8 files changed, 120 insertions(+), 19 deletions(-) (limited to 'ssh.c') diff --git a/ChangeLog b/ChangeLog index 73954735a..7125eaa1e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,11 @@ [PROTOCOL.certkeys ssh-keygen.c] tighten the rules for certificate encoding by requiring that options appear in lexical order and make our ssh-keygen comply. ok markus@ + - djm@cvs.openbsd.org 2010/08/04 05:42:47 + [auth.c auth2-hostbased.c authfile.c authfile.h ssh-keysign.8] + [ssh-keysign.c ssh.c] + enable certificates for hostbased authentication, from Iain Morgan; + "looks ok" markus@ 20100903 - (dtucker) [monitor.c] Bug #1795: Initialize the values to be returned from diff --git a/auth.c b/auth.c index d1727a4a9..a27667f42 100644 --- a/auth.c +++ b/auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.c,v 1.88 2010/06/22 04:49:47 djm Exp $ */ +/* $OpenBSD: auth.c,v 1.89 2010/08/04 05:42:47 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -385,7 +385,7 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, HostStatus host_status; /* Check if we know the host and its host key. */ - found = key_new(key->type); + found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type); host_status = check_host_in_hostfile(sysfile, host, key, found, NULL); if (host_status != HOST_OK && userfile != NULL) { diff --git a/auth2-hostbased.c b/auth2-hostbased.c index 721646520..cdf442f97 100644 --- a/auth2-hostbased.c +++ b/auth2-hostbased.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-hostbased.c,v 1.13 2010/03/04 10:36:03 djm Exp $ */ +/* $OpenBSD: auth2-hostbased.c,v 1.14 2010/08/04 05:42:47 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -141,9 +141,10 @@ int hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, Key *key) { - const char *resolvedname, *ipaddr, *lookup; + const char *resolvedname, *ipaddr, *lookup, *reason; HostStatus host_status; int len; + char *fp; if (auth_key_is_revoked(key)) return 0; @@ -174,16 +175,40 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, } debug2("userauth_hostbased: access allowed by auth_rhosts2"); + if (key_is_cert(key) && + key_cert_check_authority(key, 1, 0, lookup, &reason)) { + error("%s", reason); + auth_debug_add("%s", reason); + return 0; + } + host_status = check_key_in_hostfiles(pw, key, lookup, _PATH_SSH_SYSTEM_HOSTFILE, options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE); /* backward compat if no key has been found. */ - if (host_status == HOST_NEW) + if (host_status == HOST_NEW) { host_status = check_key_in_hostfiles(pw, key, lookup, _PATH_SSH_SYSTEM_HOSTFILE2, options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE2); + } + + if (host_status == HOST_OK) { + if (key_is_cert(key)) { + fp = key_fingerprint(key->cert->signature_key, + SSH_FP_MD5, SSH_FP_HEX); + verbose("Accepted certificate ID \"%s\" signed by " + "%s CA %s from %s@%s", key->cert->key_id, + key_type(key->cert->signature_key), fp, + cuser, lookup); + } else { + fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); + verbose("Accepted %s public key %s from %s@%s", + key_type(key), fp, cuser, lookup); + } + xfree(fp); + } return (host_status == HOST_OK); } diff --git a/authfile.c b/authfile.c index 224c6aa80..6bf41db9a 100644 --- a/authfile.c +++ b/authfile.c @@ -1,4 +1,4 @@ -/* $OpenBSD: authfile.c,v 1.80 2010/03/04 10:36:03 djm Exp $ */ +/* $OpenBSD: authfile.c,v 1.81 2010/08/04 05:42:47 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -693,6 +693,64 @@ key_load_public(const char *filename, char **commentp) return NULL; } +/* Load the certificate associated with the named private key */ +Key * +key_load_cert(const char *filename) +{ + Key *pub; + char file[MAXPATHLEN]; + + pub = key_new(KEY_UNSPEC); + if ((strlcpy(file, filename, sizeof file) < sizeof(file)) && + (strlcat(file, "-cert.pub", sizeof file) < sizeof(file)) && + (key_try_load_public(pub, file, NULL) == 1)) + return pub; + key_free(pub); + return NULL; +} + +/* Load private key and certificate */ +Key * +key_load_private_cert(int type, const char *filename, const char *passphrase, + int *perm_ok) +{ + Key *key, *pub; + + switch (type) { + case KEY_RSA: + case KEY_DSA: + break; + default: + error("%s: unsupported key type", __func__); + return NULL; + } + + if ((key = key_load_private_type(type, filename, + passphrase, NULL, perm_ok)) == NULL) + return NULL; + + if ((pub = key_load_cert(filename)) == NULL) { + key_free(key); + return NULL; + } + + /* Make sure the private key matches the certificate */ + if (key_equal_public(key, pub) == 0) { + error("%s: certificate does not match private key %s", + __func__, filename); + } else if (key_to_certified(key, key_cert_is_legacy(pub)) != 0) { + error("%s: key_to_certified failed", __func__); + } else { + key_cert_copy(pub, key); + key_free(pub); + return key; + } + + key_free(key); + key_free(pub); + return NULL; +} + /* * Returns 1 if the specified "key" is listed in the file "filename", * 0 if the key is not listed or -1 on error. diff --git a/authfile.h b/authfile.h index 6dfa478e7..6745dc062 100644 --- a/authfile.h +++ b/authfile.h @@ -1,4 +1,4 @@ -/* $OpenBSD: authfile.h,v 1.14 2010/03/04 10:36:03 djm Exp $ */ +/* $OpenBSD: authfile.h,v 1.15 2010/08/04 05:42:47 djm Exp $ */ /* * Author: Tatu Ylonen @@ -16,9 +16,11 @@ #define AUTHFILE_H int key_save_private(Key *, const char *, const char *, const char *); +Key *key_load_cert(const char *); Key *key_load_public(const char *, char **); Key *key_load_public_type(int, const char *, char **); Key *key_load_private(const char *, const char *, char **); +Key *key_load_private_cert(int, const char *, const char *, int *); Key *key_load_private_type(int, const char *, const char *, char **, int *); Key *key_load_private_pem(int, int, const char *, char **); int key_perm_ok(int, const char *); diff --git a/ssh-keysign.8 b/ssh-keysign.8 index 3ba54b935..46c0ee9cd 100644 --- a/ssh-keysign.8 +++ b/ssh-keysign.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keysign.8,v 1.9 2007/05/31 19:20:16 jmc Exp $ +.\" $OpenBSD: ssh-keysign.8,v 1.10 2010/08/04 05:42:47 djm Exp $ .\" .\" Copyright (c) 2002 Markus Friedl. All rights reserved. .\" @@ -22,7 +22,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. .\" -.Dd $Mdocdate: May 31 2007 $ +.Dd $Mdocdate: August 4 2010 $ .Dt SSH-KEYSIGN 8 .Os .Sh NAME @@ -68,6 +68,9 @@ accessible to others. Since they are readable only by root, .Nm must be set-uid root if host-based authentication is used. +.It Pa /etc/ssh/ssh_host_dsa_key-cert.pub, /etc/ssh/ssh_host_rsa_key-cert.pub +If these files exist they are assumed to contain public certificate +information corresponding with the private keys above. .El .Sh SEE ALSO .Xr ssh 1 , diff --git a/ssh-keysign.c b/ssh-keysign.c index 0fdcebbd2..2f6ac99ab 100644 --- a/ssh-keysign.c +++ b/ssh-keysign.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keysign.c,v 1.30 2010/01/13 01:20:20 dtucker Exp $ */ +/* $OpenBSD: ssh-keysign.c,v 1.31 2010/08/04 05:42:47 djm Exp $ */ /* * Copyright (c) 2002 Markus Friedl. All rights reserved. * @@ -232,7 +232,7 @@ main(int argc, char **argv) found = 0; for (i = 0; i < 2; i++) { if (keys[i] != NULL && - key_equal(key, keys[i])) { + key_equal_public(key, keys[i])) { found = 1; break; } diff --git a/ssh.c b/ssh.c index 249be2db8..ab37c205d 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.344 2010/07/19 09:15:12 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.345 2010/08/04 05:42:47 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -774,26 +774,34 @@ main(int ac, char **av) sensitive_data.external_keysign = 0; if (options.rhosts_rsa_authentication || options.hostbased_authentication) { - sensitive_data.nkeys = 3; + sensitive_data.nkeys = 5; sensitive_data.keys = xcalloc(sensitive_data.nkeys, sizeof(Key)); PRIV_START; sensitive_data.keys[0] = key_load_private_type(KEY_RSA1, _PATH_HOST_KEY_FILE, "", NULL, NULL); - sensitive_data.keys[1] = key_load_private_type(KEY_DSA, + sensitive_data.keys[1] = key_load_private_cert(KEY_DSA, + _PATH_HOST_DSA_KEY_FILE, "", NULL); + sensitive_data.keys[2] = key_load_private_cert(KEY_RSA, + _PATH_HOST_RSA_KEY_FILE, "", NULL); + sensitive_data.keys[3] = key_load_private_type(KEY_DSA, _PATH_HOST_DSA_KEY_FILE, "", NULL, NULL); - sensitive_data.keys[2] = key_load_private_type(KEY_RSA, + sensitive_data.keys[4] = key_load_private_type(KEY_RSA, _PATH_HOST_RSA_KEY_FILE, "", NULL, NULL); PRIV_END; if (options.hostbased_authentication == 1 && sensitive_data.keys[0] == NULL && - sensitive_data.keys[1] == NULL && - sensitive_data.keys[2] == NULL) { - sensitive_data.keys[1] = key_load_public( + sensitive_data.keys[3] == NULL && + sensitive_data.keys[4] == NULL) { + sensitive_data.keys[1] = key_load_cert( + _PATH_HOST_DSA_KEY_FILE); + sensitive_data.keys[2] = key_load_cert( + _PATH_HOST_RSA_KEY_FILE); + sensitive_data.keys[3] = key_load_public( _PATH_HOST_DSA_KEY_FILE, NULL); - sensitive_data.keys[2] = key_load_public( + sensitive_data.keys[4] = key_load_public( _PATH_HOST_RSA_KEY_FILE, NULL); sensitive_data.external_keysign = 1; } -- cgit v1.2.3 From 00d9ae26db2a8176f8ff511c207fa0bc7fadd562 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Tue, 17 Aug 2010 01:59:31 +1000 Subject: - djm@cvs.openbsd.org 2010/08/12 21:49:44 [ssh.c] close any extra file descriptors inherited from parent at start and reopen stdin/stdout to /dev/null when forking for ControlPersist. prevents tools that fork and run a captive ssh for communication from failing to exit when the ssh completes while they wait for these fds to close. The inherited fds may persist arbitrarily long if a background mux master has been started by ControlPersist. cvs and scp were effected by this. "please commit" markus@ --- ChangeLog | 13 +++++++++++++ ssh.c | 19 ++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) (limited to 'ssh.c') diff --git a/ChangeLog b/ChangeLog index 2de42c4b5..f9496530c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,19 @@ openbsd-compat/openbsd-compat.h openbsd-compat/strptime.c] Add strptime to the compat library which helps on platforms like old IRIX. Based on work by djm, tested by Tom Christensen. + - OpenBSD CVS Sync + - djm@cvs.openbsd.org 2010/08/12 21:49:44 + [ssh.c] + close any extra file descriptors inherited from parent at start and + reopen stdin/stdout to /dev/null when forking for ControlPersist. + + prevents tools that fork and run a captive ssh for communication from + failing to exit when the ssh completes while they wait for these fds to + close. The inherited fds may persist arbitrarily long if a background + mux master has been started by ControlPersist. cvs and scp were effected + by this. + + "please commit" markus@ 20100812 - (tim) [regress/login-timeout.sh regress/reconfigure.sh regress/reexec.sh diff --git a/ssh.c b/ssh.c index ab37c205d..4419f7642 100644 --- a/ssh.c +++ b/ssh.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh.c,v 1.345 2010/08/04 05:42:47 djm Exp $ */ +/* $OpenBSD: ssh.c,v 1.346 2010/08/12 21:49:44 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -237,6 +237,12 @@ main(int ac, char **av) __progname = ssh_get_progname(av[0]); init_rng(); + /* + * Discard other fds that are hanging around. These can cause problem + * with backgrounded ssh processes started by ControlPersist. + */ + closefrom(STDERR_FILENO + 1); + /* * Save the original real uid. It will be needed later (uid-swapping * may clobber the real uid). @@ -898,6 +904,7 @@ static void control_persist_detach(void) { pid_t pid; + int devnull; debug("%s: backgrounding master process", __func__); @@ -924,6 +931,16 @@ control_persist_detach(void) /* muxclient() doesn't return on success. */ fatal("Failed to connect to new control master"); } + if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) { + error("%s: open(\"/dev/null\"): %s", __func__, + strerror(errno)); + } else { + if (dup2(devnull, STDIN_FILENO) == -1 || + dup2(devnull, STDOUT_FILENO) == -1) + error("%s: dup2: %s", __func__, strerror(errno)); + if (devnull > STDERR_FILENO) + close(devnull); + } } /* Do fork() after authentication. Used by "ssh -f" */ -- cgit v1.2.3