summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2019-12-21 03:19:13 +0100
committerDamien Miller <djm@mindrot.org>2019-12-21 03:22:07 +0100
commit40be78f503277bd91c958fa25ea9ef918a2ffd3d (patch)
treeb17303fad21f97437b44cf3264a03abfd503ebdf
parentupstream: SSH U2F keys can now be used as host keys. Fix a garden (diff)
downloadopenssh-40be78f503277bd91c958fa25ea9ef918a2ffd3d.tar.xz
openssh-40be78f503277bd91c958fa25ea9ef918a2ffd3d.zip
upstream: Allow forwarding a different agent socket to the path
specified by $SSH_AUTH_SOCK, by extending the existing ForwardAgent option to accepting an explicit path or the name of an environment variable in addition to yes/no. Patch by Eric Chiang, manpage by me; ok markus@ OpenBSD-Commit-ID: 98f2ed80bf34ea54d8b2ddd19ac14ebbf40e9265
-rw-r--r--authfd.c36
-rw-r--r--authfd.h3
-rw-r--r--clientloop.c15
-rw-r--r--readconf.c43
-rw-r--r--readconf.h3
-rw-r--r--ssh.c34
-rw-r--r--ssh_config.515
7 files changed, 121 insertions, 28 deletions
diff --git a/authfd.c b/authfd.c
index ab6305944..05fd45401 100644
--- a/authfd.c
+++ b/authfd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfd.c,v 1.120 2019/11/13 04:47:52 deraadt Exp $ */
+/* $OpenBSD: authfd.c,v 1.121 2019/12/21 02:19:13 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -82,21 +82,16 @@ decode_reply(u_char type)
return SSH_ERR_INVALID_FORMAT;
}
-/* Returns the number of the authentication fd, or -1 if there is none. */
+/*
+ * Opens an authentication socket at the provided path and stores the file
+ * descriptor in fdp. Returns 0 on success and an error on failure.
+ */
int
-ssh_get_authentication_socket(int *fdp)
+ssh_get_authentication_socket_path(const char *authsocket, int *fdp)
{
- const char *authsocket;
int sock, oerrno;
struct sockaddr_un sunaddr;
- if (fdp != NULL)
- *fdp = -1;
-
- authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
- if (authsocket == NULL || *authsocket == '\0')
- return SSH_ERR_AGENT_NOT_PRESENT;
-
memset(&sunaddr, 0, sizeof(sunaddr));
sunaddr.sun_family = AF_UNIX;
strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
@@ -119,6 +114,25 @@ ssh_get_authentication_socket(int *fdp)
return 0;
}
+/*
+ * Opens the default authentication socket and stores the file descriptor in
+ * fdp. Returns 0 on success and an error on failure.
+ */
+int
+ssh_get_authentication_socket(int *fdp)
+{
+ const char *authsocket;
+
+ if (fdp != NULL)
+ *fdp = -1;
+
+ authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
+ if (authsocket == NULL || *authsocket == '\0')
+ return SSH_ERR_AGENT_NOT_PRESENT;
+
+ return ssh_get_authentication_socket_path(authsocket, fdp);
+}
+
/* Communicate with agent: send request and read reply */
static int
ssh_request_reply(int sock, struct sshbuf *request, struct sshbuf *reply)
diff --git a/authfd.h b/authfd.h
index 443771a00..c3bf6259a 100644
--- a/authfd.h
+++ b/authfd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfd.h,v 1.47 2019/10/31 21:19:15 djm Exp $ */
+/* $OpenBSD: authfd.h,v 1.48 2019/12/21 02:19:13 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -24,6 +24,7 @@ struct ssh_identitylist {
};
int ssh_get_authentication_socket(int *fdp);
+int ssh_get_authentication_socket_path(const char *authsocket, int *fdp);
void ssh_close_authentication_socket(int sock);
int ssh_lock_agent(int sock, int lock, const char *password);
diff --git a/clientloop.c b/clientloop.c
index 880abfda2..8f0332df4 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.329 2019/11/25 00:51:37 djm Exp $ */
+/* $OpenBSD: clientloop.c,v 1.330 2019/12/21 02:19:13 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -135,6 +135,12 @@ extern int muxserver_sock; /* XXX use mux_client_cleanup() instead */
extern char *host;
/*
+ * If this field is not NULL, the ForwardAgent socket is this path and different
+ * instead of SSH_AUTH_SOCK.
+ */
+extern char *forward_agent_sock_path;
+
+/*
* Flag to indicate that we have received a window change signal which has
* not yet been processed. This will cause a message indicating the new
* window size to be sent to the server a little later. This is volatile
@@ -1618,7 +1624,12 @@ client_request_agent(struct ssh *ssh, const char *request_type, int rchan)
"malicious server.");
return NULL;
}
- if ((r = ssh_get_authentication_socket(&sock)) != 0) {
+ if (forward_agent_sock_path == NULL) {
+ r = ssh_get_authentication_socket(&sock);
+ } else {
+ r = ssh_get_authentication_socket_path(forward_agent_sock_path, &sock);
+ }
+ if (r != 0) {
if (r != SSH_ERR_AGENT_NOT_PRESENT)
debug("%s: ssh_get_authentication_socket: %s",
__func__, ssh_err(r));
diff --git a/readconf.c b/readconf.c
index 282afede6..cb3ae6dc7 100644
--- a/readconf.c
+++ b/readconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.c,v 1.318 2019/12/20 02:42:42 dtucker Exp $ */
+/* $OpenBSD: readconf.c,v 1.319 2019/12/21 02:19:13 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -919,6 +919,34 @@ parse_time:
case oForwardAgent:
intptr = &options->forward_agent;
+
+ arg = strdelim(&s);
+ if (!arg || *arg == '\0')
+ fatal("%s line %d: missing argument.",
+ filename, linenum);
+
+ value = -1;
+ multistate_ptr = multistate_flag;
+ for (i = 0; multistate_ptr[i].key != NULL; i++) {
+ if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
+ value = multistate_ptr[i].value;
+ break;
+ }
+ }
+ if (value != -1) {
+ if (*activep && *intptr == -1)
+ *intptr = value;
+ break;
+ }
+ /* ForwardAgent wasn't 'yes' or 'no', assume a path */
+ if (*activep && *intptr == -1)
+ *intptr = 1;
+
+ charptr = &options->forward_agent_sock_path;
+ goto parse_agent_path;
+
+ case oForwardX11:
+ intptr = &options->forward_x11;
parse_flag:
multistate_ptr = multistate_flag;
parse_multistate:
@@ -940,10 +968,6 @@ parse_time:
*intptr = value;
break;
- case oForwardX11:
- intptr = &options->forward_x11;
- goto parse_flag;
-
case oForwardX11Trusted:
intptr = &options->forward_x11_trusted;
goto parse_flag;
@@ -1736,6 +1760,7 @@ parse_keytypes:
if (!arg || *arg == '\0')
fatal("%.200s line %d: Missing argument.",
filename, linenum);
+ parse_agent_path:
/* Extra validation if the string represents an env var. */
if (arg[0] == '$' && !valid_env_name(arg + 1)) {
fatal("%.200s line %d: Invalid environment name %s.",
@@ -1853,6 +1878,7 @@ initialize_options(Options * options)
{
memset(options, 'X', sizeof(*options));
options->forward_agent = -1;
+ options->forward_agent_sock_path = NULL;
options->forward_x11 = -1;
options->forward_x11_trusted = -1;
options->forward_x11_timeout = -1;
@@ -2636,7 +2662,6 @@ dump_client_config(Options *o, const char *host)
dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
- dump_cfg_fmtint(oForwardAgent, o->forward_agent);
dump_cfg_fmtint(oForwardX11, o->forward_x11);
dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
@@ -2712,6 +2737,12 @@ dump_client_config(Options *o, const char *host)
/* Special cases */
+ /* oForwardAgent */
+ if (o->forward_agent_sock_path == NULL)
+ dump_cfg_fmtint(oForwardAgent, o->forward_agent);
+ else
+ dump_cfg_string(oForwardAgent, o->forward_agent_sock_path);
+
/* oConnectTimeout */
if (o->connection_timeout == -1)
printf("connecttimeout none\n");
diff --git a/readconf.h b/readconf.h
index 51d540b88..dcecfc54a 100644
--- a/readconf.h
+++ b/readconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.h,v 1.130 2019/10/31 21:18:28 djm Exp $ */
+/* $OpenBSD: readconf.h,v 1.131 2019/12/21 02:19:13 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -29,6 +29,7 @@ struct allowed_cname {
typedef struct {
int forward_agent; /* Forward authentication agent. */
+ char *forward_agent_sock_path; /* Optional path of the agent. */
int forward_x11; /* Forward X11 display. */
int forward_x11_timeout; /* Expiration for Cookies */
int forward_x11_trusted; /* Trust Forward X11 display. */
diff --git a/ssh.c b/ssh.c
index 13299f7d1..12760af29 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.c,v 1.509 2019/11/18 16:10:05 naddy Exp $ */
+/* $OpenBSD: ssh.c,v 1.510 2019/12/21 02:19:13 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -168,6 +168,12 @@ char *config = NULL;
*/
char *host;
+/*
+ * A config can specify a path to forward, overriding SSH_AUTH_SOCK. If this is
+ * not NULL, forward the socket at this path instead.
+ */
+char *forward_agent_sock_path = NULL;
+
/* Various strings used to to percent_expand() arguments */
static char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
static char uidstr[32], *host_arg, *conn_hash_hex;
@@ -1498,6 +1504,32 @@ main(int ac, char **av)
}
}
+ if (options.forward_agent && (options.forward_agent_sock_path != NULL)) {
+ p = tilde_expand_filename(options.forward_agent_sock_path, getuid());
+ cp = percent_expand(p,
+ "d", pw->pw_dir,
+ "h", host,
+ "i", uidstr,
+ "l", thishost,
+ "r", options.user,
+ "u", pw->pw_name,
+ (char *)NULL);
+ free(p);
+
+ if (cp[0] == '$') {
+ if (!valid_env_name(cp + 1)) {
+ fatal("Invalid ForwardAgent environment variable name %s", cp);
+ }
+ if ((p = getenv(cp + 1)) != NULL)
+ forward_agent_sock_path = p;
+ else
+ options.forward_agent = 0;
+ free(cp);
+ } else {
+ forward_agent_sock_path = cp;
+ }
+ }
+
/* Expand ~ in known host file names. */
tilde_expand_paths(options.system_hostfiles,
options.num_system_hostfiles);
diff --git a/ssh_config.5 b/ssh_config.5
index dc7a2143d..186e07617 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -33,8 +33,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.311 2019/12/19 15:09:30 naddy Exp $
-.Dd $Mdocdate: December 19 2019 $
+.\" $OpenBSD: ssh_config.5,v 1.312 2019/12/21 02:19:13 djm Exp $
+.Dd $Mdocdate: December 21 2019 $
.Dt SSH_CONFIG 5
.Os
.Sh NAME
@@ -669,11 +669,14 @@ and
.It Cm ForwardAgent
Specifies whether the connection to the authentication agent (if any)
will be forwarded to the remote machine.
-The argument must be
-.Cm yes
-or
+The argument may be
+.Cm yes ,
.Cm no
-(the default).
+(the default),
+an explicit path to an agent socket or the name of an environment variable
+(beginning with
+.Sq $ )
+in which to find the path.
.Pp
Agent forwarding should be enabled with caution.
Users with the ability to bypass file permissions on the remote host