]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
upstream: Allow forwarding a different agent socket to the path
authordjm@openbsd.org <djm@openbsd.org>
Sat, 21 Dec 2019 02:19:13 +0000 (02:19 +0000)
committerDamien Miller <djm@mindrot.org>
Sat, 21 Dec 2019 02:22:07 +0000 (13:22 +1100)
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

authfd.c
authfd.h
clientloop.c
readconf.c
readconf.h
ssh.c
ssh_config.5

index ab63059446528041f6bc0ff8ee7e447921731d01..05fd45401e1273a3d635bdef90d393a43e7738db 100644 (file)
--- 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)
index 443771a000cbd24c33d0350001dd430873832560..c3bf6259aa9d0d4052b578b78dd3c23dab9cd662 100644 (file)
--- 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);
index 880abfda211e481761683daf06f462c4c5cba253..8f0332df415de9b4923591229097fabefd6fe9b8 100644 (file)
@@ -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
@@ -134,6 +134,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
@@ -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));
index 282afede6c3f4961be2dc50c235d6c7e61e8214f..cb3ae6dc7ea73461d994b14c27c9f28d4dcfdbb8 100644 (file)
@@ -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");
index 51d540b88bea774a0b6033cd2715b3b7c5222524..dcecfc54afe1b74044bf5819c6f832124937e905 100644 (file)
@@ -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 13299f7d1bbeea4322e2c275178facc3968d87da..12760af298ee8aca918e1b70a379b1c229dcf913 100644 (file)
--- 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);
index dc7a2143dc4938967b4e478b3acd2200f55ac6d5..186e07617831e7fa95b673d5782e4a26b042c42f 100644 (file)
@@ -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