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
This commit is contained in:
djm@openbsd.org 2019-12-21 02:19:13 +00:00 committed by Damien Miller
parent 416f15372b
commit 40be78f503
7 changed files with 121 additions and 28 deletions

View File

@ -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)

View File

@ -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);

View 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));

View 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");

View 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. */

34
ssh.c
View File

@ -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);

View 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