diff options
-rw-r--r-- | authfd.c | 36 | ||||
-rw-r--r-- | authfd.h | 3 | ||||
-rw-r--r-- | clientloop.c | 15 | ||||
-rw-r--r-- | readconf.c | 43 | ||||
-rw-r--r-- | readconf.h | 3 | ||||
-rw-r--r-- | ssh.c | 34 | ||||
-rw-r--r-- | ssh_config.5 | 15 |
7 files changed, 121 insertions, 28 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: authfd.c,v 1.120 2019/11/13 04:47:52 deraadt Exp $ */ | 1 | /* $OpenBSD: authfd.c,v 1.121 2019/12/21 02:19:13 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -82,21 +82,16 @@ decode_reply(u_char type) | |||
82 | return SSH_ERR_INVALID_FORMAT; | 82 | return SSH_ERR_INVALID_FORMAT; |
83 | } | 83 | } |
84 | 84 | ||
85 | /* Returns the number of the authentication fd, or -1 if there is none. */ | 85 | /* |
86 | * Opens an authentication socket at the provided path and stores the file | ||
87 | * descriptor in fdp. Returns 0 on success and an error on failure. | ||
88 | */ | ||
86 | int | 89 | int |
87 | ssh_get_authentication_socket(int *fdp) | 90 | ssh_get_authentication_socket_path(const char *authsocket, int *fdp) |
88 | { | 91 | { |
89 | const char *authsocket; | ||
90 | int sock, oerrno; | 92 | int sock, oerrno; |
91 | struct sockaddr_un sunaddr; | 93 | struct sockaddr_un sunaddr; |
92 | 94 | ||
93 | if (fdp != NULL) | ||
94 | *fdp = -1; | ||
95 | |||
96 | authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); | ||
97 | if (authsocket == NULL || *authsocket == '\0') | ||
98 | return SSH_ERR_AGENT_NOT_PRESENT; | ||
99 | |||
100 | memset(&sunaddr, 0, sizeof(sunaddr)); | 95 | memset(&sunaddr, 0, sizeof(sunaddr)); |
101 | sunaddr.sun_family = AF_UNIX; | 96 | sunaddr.sun_family = AF_UNIX; |
102 | strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path)); | 97 | strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path)); |
@@ -119,6 +114,25 @@ ssh_get_authentication_socket(int *fdp) | |||
119 | return 0; | 114 | return 0; |
120 | } | 115 | } |
121 | 116 | ||
117 | /* | ||
118 | * Opens the default authentication socket and stores the file descriptor in | ||
119 | * fdp. Returns 0 on success and an error on failure. | ||
120 | */ | ||
121 | int | ||
122 | ssh_get_authentication_socket(int *fdp) | ||
123 | { | ||
124 | const char *authsocket; | ||
125 | |||
126 | if (fdp != NULL) | ||
127 | *fdp = -1; | ||
128 | |||
129 | authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); | ||
130 | if (authsocket == NULL || *authsocket == '\0') | ||
131 | return SSH_ERR_AGENT_NOT_PRESENT; | ||
132 | |||
133 | return ssh_get_authentication_socket_path(authsocket, fdp); | ||
134 | } | ||
135 | |||
122 | /* Communicate with agent: send request and read reply */ | 136 | /* Communicate with agent: send request and read reply */ |
123 | static int | 137 | static int |
124 | ssh_request_reply(int sock, struct sshbuf *request, struct sshbuf *reply) | 138 | ssh_request_reply(int sock, struct sshbuf *request, struct sshbuf *reply) |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: authfd.h,v 1.47 2019/10/31 21:19:15 djm Exp $ */ | 1 | /* $OpenBSD: authfd.h,v 1.48 2019/12/21 02:19:13 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -24,6 +24,7 @@ struct ssh_identitylist { | |||
24 | }; | 24 | }; |
25 | 25 | ||
26 | int ssh_get_authentication_socket(int *fdp); | 26 | int ssh_get_authentication_socket(int *fdp); |
27 | int ssh_get_authentication_socket_path(const char *authsocket, int *fdp); | ||
27 | void ssh_close_authentication_socket(int sock); | 28 | void ssh_close_authentication_socket(int sock); |
28 | 29 | ||
29 | int ssh_lock_agent(int sock, int lock, const char *password); | 30 | 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 @@ | |||
1 | /* $OpenBSD: clientloop.c,v 1.329 2019/11/25 00:51:37 djm Exp $ */ | 1 | /* $OpenBSD: clientloop.c,v 1.330 2019/12/21 02:19:13 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * 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 */ | |||
135 | extern char *host; | 135 | extern char *host; |
136 | 136 | ||
137 | /* | 137 | /* |
138 | * If this field is not NULL, the ForwardAgent socket is this path and different | ||
139 | * instead of SSH_AUTH_SOCK. | ||
140 | */ | ||
141 | extern char *forward_agent_sock_path; | ||
142 | |||
143 | /* | ||
138 | * Flag to indicate that we have received a window change signal which has | 144 | * Flag to indicate that we have received a window change signal which has |
139 | * not yet been processed. This will cause a message indicating the new | 145 | * not yet been processed. This will cause a message indicating the new |
140 | * window size to be sent to the server a little later. This is volatile | 146 | * 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) | |||
1618 | "malicious server."); | 1624 | "malicious server."); |
1619 | return NULL; | 1625 | return NULL; |
1620 | } | 1626 | } |
1621 | if ((r = ssh_get_authentication_socket(&sock)) != 0) { | 1627 | if (forward_agent_sock_path == NULL) { |
1628 | r = ssh_get_authentication_socket(&sock); | ||
1629 | } else { | ||
1630 | r = ssh_get_authentication_socket_path(forward_agent_sock_path, &sock); | ||
1631 | } | ||
1632 | if (r != 0) { | ||
1622 | if (r != SSH_ERR_AGENT_NOT_PRESENT) | 1633 | if (r != SSH_ERR_AGENT_NOT_PRESENT) |
1623 | debug("%s: ssh_get_authentication_socket: %s", | 1634 | debug("%s: ssh_get_authentication_socket: %s", |
1624 | __func__, ssh_err(r)); | 1635 | __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 @@ | |||
1 | /* $OpenBSD: readconf.c,v 1.318 2019/12/20 02:42:42 dtucker Exp $ */ | 1 | /* $OpenBSD: readconf.c,v 1.319 2019/12/21 02:19:13 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -919,6 +919,34 @@ parse_time: | |||
919 | 919 | ||
920 | case oForwardAgent: | 920 | case oForwardAgent: |
921 | intptr = &options->forward_agent; | 921 | intptr = &options->forward_agent; |
922 | |||
923 | arg = strdelim(&s); | ||
924 | if (!arg || *arg == '\0') | ||
925 | fatal("%s line %d: missing argument.", | ||
926 | filename, linenum); | ||
927 | |||
928 | value = -1; | ||
929 | multistate_ptr = multistate_flag; | ||
930 | for (i = 0; multistate_ptr[i].key != NULL; i++) { | ||
931 | if (strcasecmp(arg, multistate_ptr[i].key) == 0) { | ||
932 | value = multistate_ptr[i].value; | ||
933 | break; | ||
934 | } | ||
935 | } | ||
936 | if (value != -1) { | ||
937 | if (*activep && *intptr == -1) | ||
938 | *intptr = value; | ||
939 | break; | ||
940 | } | ||
941 | /* ForwardAgent wasn't 'yes' or 'no', assume a path */ | ||
942 | if (*activep && *intptr == -1) | ||
943 | *intptr = 1; | ||
944 | |||
945 | charptr = &options->forward_agent_sock_path; | ||
946 | goto parse_agent_path; | ||
947 | |||
948 | case oForwardX11: | ||
949 | intptr = &options->forward_x11; | ||
922 | parse_flag: | 950 | parse_flag: |
923 | multistate_ptr = multistate_flag; | 951 | multistate_ptr = multistate_flag; |
924 | parse_multistate: | 952 | parse_multistate: |
@@ -940,10 +968,6 @@ parse_time: | |||
940 | *intptr = value; | 968 | *intptr = value; |
941 | break; | 969 | break; |
942 | 970 | ||
943 | case oForwardX11: | ||
944 | intptr = &options->forward_x11; | ||
945 | goto parse_flag; | ||
946 | |||
947 | case oForwardX11Trusted: | 971 | case oForwardX11Trusted: |
948 | intptr = &options->forward_x11_trusted; | 972 | intptr = &options->forward_x11_trusted; |
949 | goto parse_flag; | 973 | goto parse_flag; |
@@ -1736,6 +1760,7 @@ parse_keytypes: | |||
1736 | if (!arg || *arg == '\0') | 1760 | if (!arg || *arg == '\0') |
1737 | fatal("%.200s line %d: Missing argument.", | 1761 | fatal("%.200s line %d: Missing argument.", |
1738 | filename, linenum); | 1762 | filename, linenum); |
1763 | parse_agent_path: | ||
1739 | /* Extra validation if the string represents an env var. */ | 1764 | /* Extra validation if the string represents an env var. */ |
1740 | if (arg[0] == '$' && !valid_env_name(arg + 1)) { | 1765 | if (arg[0] == '$' && !valid_env_name(arg + 1)) { |
1741 | fatal("%.200s line %d: Invalid environment name %s.", | 1766 | fatal("%.200s line %d: Invalid environment name %s.", |
@@ -1853,6 +1878,7 @@ initialize_options(Options * options) | |||
1853 | { | 1878 | { |
1854 | memset(options, 'X', sizeof(*options)); | 1879 | memset(options, 'X', sizeof(*options)); |
1855 | options->forward_agent = -1; | 1880 | options->forward_agent = -1; |
1881 | options->forward_agent_sock_path = NULL; | ||
1856 | options->forward_x11 = -1; | 1882 | options->forward_x11 = -1; |
1857 | options->forward_x11_trusted = -1; | 1883 | options->forward_x11_trusted = -1; |
1858 | options->forward_x11_timeout = -1; | 1884 | options->forward_x11_timeout = -1; |
@@ -2636,7 +2662,6 @@ dump_client_config(Options *o, const char *host) | |||
2636 | dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings); | 2662 | dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings); |
2637 | dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure); | 2663 | dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure); |
2638 | dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash); | 2664 | dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash); |
2639 | dump_cfg_fmtint(oForwardAgent, o->forward_agent); | ||
2640 | dump_cfg_fmtint(oForwardX11, o->forward_x11); | 2665 | dump_cfg_fmtint(oForwardX11, o->forward_x11); |
2641 | dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted); | 2666 | dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted); |
2642 | dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); | 2667 | dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); |
@@ -2712,6 +2737,12 @@ dump_client_config(Options *o, const char *host) | |||
2712 | 2737 | ||
2713 | /* Special cases */ | 2738 | /* Special cases */ |
2714 | 2739 | ||
2740 | /* oForwardAgent */ | ||
2741 | if (o->forward_agent_sock_path == NULL) | ||
2742 | dump_cfg_fmtint(oForwardAgent, o->forward_agent); | ||
2743 | else | ||
2744 | dump_cfg_string(oForwardAgent, o->forward_agent_sock_path); | ||
2745 | |||
2715 | /* oConnectTimeout */ | 2746 | /* oConnectTimeout */ |
2716 | if (o->connection_timeout == -1) | 2747 | if (o->connection_timeout == -1) |
2717 | printf("connecttimeout none\n"); | 2748 | 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 @@ | |||
1 | /* $OpenBSD: readconf.h,v 1.130 2019/10/31 21:18:28 djm Exp $ */ | 1 | /* $OpenBSD: readconf.h,v 1.131 2019/12/21 02:19:13 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -29,6 +29,7 @@ struct allowed_cname { | |||
29 | 29 | ||
30 | typedef struct { | 30 | typedef struct { |
31 | int forward_agent; /* Forward authentication agent. */ | 31 | int forward_agent; /* Forward authentication agent. */ |
32 | char *forward_agent_sock_path; /* Optional path of the agent. */ | ||
32 | int forward_x11; /* Forward X11 display. */ | 33 | int forward_x11; /* Forward X11 display. */ |
33 | int forward_x11_timeout; /* Expiration for Cookies */ | 34 | int forward_x11_timeout; /* Expiration for Cookies */ |
34 | int forward_x11_trusted; /* Trust Forward X11 display. */ | 35 | int forward_x11_trusted; /* Trust Forward X11 display. */ |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh.c,v 1.509 2019/11/18 16:10:05 naddy Exp $ */ | 1 | /* $OpenBSD: ssh.c,v 1.510 2019/12/21 02:19:13 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -168,6 +168,12 @@ char *config = NULL; | |||
168 | */ | 168 | */ |
169 | char *host; | 169 | char *host; |
170 | 170 | ||
171 | /* | ||
172 | * A config can specify a path to forward, overriding SSH_AUTH_SOCK. If this is | ||
173 | * not NULL, forward the socket at this path instead. | ||
174 | */ | ||
175 | char *forward_agent_sock_path = NULL; | ||
176 | |||
171 | /* Various strings used to to percent_expand() arguments */ | 177 | /* Various strings used to to percent_expand() arguments */ |
172 | static char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; | 178 | static char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; |
173 | static char uidstr[32], *host_arg, *conn_hash_hex; | 179 | static char uidstr[32], *host_arg, *conn_hash_hex; |
@@ -1498,6 +1504,32 @@ main(int ac, char **av) | |||
1498 | } | 1504 | } |
1499 | } | 1505 | } |
1500 | 1506 | ||
1507 | if (options.forward_agent && (options.forward_agent_sock_path != NULL)) { | ||
1508 | p = tilde_expand_filename(options.forward_agent_sock_path, getuid()); | ||
1509 | cp = percent_expand(p, | ||
1510 | "d", pw->pw_dir, | ||
1511 | "h", host, | ||
1512 | "i", uidstr, | ||
1513 | "l", thishost, | ||
1514 | "r", options.user, | ||
1515 | "u", pw->pw_name, | ||
1516 | (char *)NULL); | ||
1517 | free(p); | ||
1518 | |||
1519 | if (cp[0] == '$') { | ||
1520 | if (!valid_env_name(cp + 1)) { | ||
1521 | fatal("Invalid ForwardAgent environment variable name %s", cp); | ||
1522 | } | ||
1523 | if ((p = getenv(cp + 1)) != NULL) | ||
1524 | forward_agent_sock_path = p; | ||
1525 | else | ||
1526 | options.forward_agent = 0; | ||
1527 | free(cp); | ||
1528 | } else { | ||
1529 | forward_agent_sock_path = cp; | ||
1530 | } | ||
1531 | } | ||
1532 | |||
1501 | /* Expand ~ in known host file names. */ | 1533 | /* Expand ~ in known host file names. */ |
1502 | tilde_expand_paths(options.system_hostfiles, | 1534 | tilde_expand_paths(options.system_hostfiles, |
1503 | options.num_system_hostfiles); | 1535 | 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 @@ | |||
33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
35 | .\" | 35 | .\" |
36 | .\" $OpenBSD: ssh_config.5,v 1.311 2019/12/19 15:09:30 naddy Exp $ | 36 | .\" $OpenBSD: ssh_config.5,v 1.312 2019/12/21 02:19:13 djm Exp $ |
37 | .Dd $Mdocdate: December 19 2019 $ | 37 | .Dd $Mdocdate: December 21 2019 $ |
38 | .Dt SSH_CONFIG 5 | 38 | .Dt SSH_CONFIG 5 |
39 | .Os | 39 | .Os |
40 | .Sh NAME | 40 | .Sh NAME |
@@ -669,11 +669,14 @@ and | |||
669 | .It Cm ForwardAgent | 669 | .It Cm ForwardAgent |
670 | Specifies whether the connection to the authentication agent (if any) | 670 | Specifies whether the connection to the authentication agent (if any) |
671 | will be forwarded to the remote machine. | 671 | will be forwarded to the remote machine. |
672 | The argument must be | 672 | The argument may be |
673 | .Cm yes | 673 | .Cm yes , |
674 | or | ||
675 | .Cm no | 674 | .Cm no |
676 | (the default). | 675 | (the default), |
676 | an explicit path to an agent socket or the name of an environment variable | ||
677 | (beginning with | ||
678 | .Sq $ ) | ||
679 | in which to find the path. | ||
677 | .Pp | 680 | .Pp |
678 | Agent forwarding should be enabled with caution. | 681 | Agent forwarding should be enabled with caution. |
679 | Users with the ability to bypass file permissions on the remote host | 682 | Users with the ability to bypass file permissions on the remote host |