Skip to content
Permalink
Browse files

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
  • Loading branch information
djmdjm committed Dec 21, 2019
1 parent 416f153 commit 40be78f503277bd91c958fa25ea9ef918a2ffd3d
Showing with 121 additions and 28 deletions.
  1. +25 −11 authfd.c
  2. +2 −1 authfd.h
  3. +13 −2 clientloop.c
  4. +37 −6 readconf.c
  5. +2 −1 readconf.h
  6. +33 −1 ssh.c
  7. +9 −6 ssh_config.5
@@ -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)
@@ -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);
@@ -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));
@@ -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 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host,

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 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host,
*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 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host,
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");
@@ -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. */
34 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);
@@ -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

0 comments on commit 40be78f

Please sign in to comment.
You can’t perform that action at this time.