diff options
-rw-r--r-- | ssh.c | 137 | ||||
-rw-r--r-- | ssh_config.5 | 31 |
2 files changed, 109 insertions, 59 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh.c,v 1.526 2020/04/03 06:07:57 djm Exp $ */ | 1 | /* $OpenBSD: ssh.c,v 1.527 2020/04/10 00:52:07 dtucker 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 |
@@ -176,13 +176,6 @@ char *forward_agent_sock_path = NULL; | |||
176 | /* Various strings used to to percent_expand() arguments */ | 176 | /* Various strings used to to percent_expand() arguments */ |
177 | static char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; | 177 | static char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; |
178 | static char uidstr[32], *host_arg, *conn_hash_hex; | 178 | static char uidstr[32], *host_arg, *conn_hash_hex; |
179 | #define DEFAULT_CLIENT_PERCENT_EXPAND_ARGS \ | ||
180 | "C", conn_hash_hex, \ | ||
181 | "L", shorthost, \ | ||
182 | "i", uidstr, \ | ||
183 | "l", thishost, \ | ||
184 | "n", host_arg, \ | ||
185 | "p", portstr | ||
186 | 179 | ||
187 | /* socket address the host resolves to */ | 180 | /* socket address the host resolves to */ |
188 | struct sockaddr_storage hostaddr; | 181 | struct sockaddr_storage hostaddr; |
@@ -238,6 +231,34 @@ tilde_expand_paths(char **paths, u_int num_paths) | |||
238 | } | 231 | } |
239 | } | 232 | } |
240 | 233 | ||
234 | #define DEFAULT_CLIENT_PERCENT_EXPAND_ARGS \ | ||
235 | "C", conn_hash_hex, \ | ||
236 | "L", shorthost, \ | ||
237 | "i", uidstr, \ | ||
238 | "l", thishost, \ | ||
239 | "n", host_arg, \ | ||
240 | "p", portstr | ||
241 | |||
242 | /* | ||
243 | * Expands the set of percent_expand options used by the majority of keywords | ||
244 | * in the client that support percent expansion. | ||
245 | * Caller must free returned string. | ||
246 | */ | ||
247 | static char * | ||
248 | default_client_percent_expand(const char *str, const char *homedir, | ||
249 | const char *remhost, const char *remuser, const char *locuser) | ||
250 | { | ||
251 | return percent_expand(str, | ||
252 | /* values from statics above */ | ||
253 | DEFAULT_CLIENT_PERCENT_EXPAND_ARGS, | ||
254 | /* values from arguments */ | ||
255 | "d", homedir, | ||
256 | "h", remhost, | ||
257 | "r", remuser, | ||
258 | "u", locuser, | ||
259 | (char *)NULL); | ||
260 | } | ||
261 | |||
241 | /* | 262 | /* |
242 | * Attempt to resolve a host name / port to a set of addresses and | 263 | * Attempt to resolve a host name / port to a set of addresses and |
243 | * optionally return any CNAMEs encountered along the way. | 264 | * optionally return any CNAMEs encountered along the way. |
@@ -1345,13 +1366,8 @@ main(int ac, char **av) | |||
1345 | if (options.remote_command != NULL) { | 1366 | if (options.remote_command != NULL) { |
1346 | debug3("expanding RemoteCommand: %s", options.remote_command); | 1367 | debug3("expanding RemoteCommand: %s", options.remote_command); |
1347 | cp = options.remote_command; | 1368 | cp = options.remote_command; |
1348 | options.remote_command = percent_expand(cp, | 1369 | options.remote_command = default_client_percent_expand(cp, |
1349 | DEFAULT_CLIENT_PERCENT_EXPAND_ARGS, | 1370 | pw->pw_dir, host, options.user, pw->pw_name); |
1350 | "d", pw->pw_dir, | ||
1351 | "h", host, | ||
1352 | "r", options.user, | ||
1353 | "u", pw->pw_name, | ||
1354 | (char *)NULL); | ||
1355 | debug3("expanded RemoteCommand: %s", options.remote_command); | 1371 | debug3("expanded RemoteCommand: %s", options.remote_command); |
1356 | free(cp); | 1372 | free(cp); |
1357 | if ((r = sshbuf_put(command, options.remote_command, | 1373 | if ((r = sshbuf_put(command, options.remote_command, |
@@ -1362,25 +1378,15 @@ main(int ac, char **av) | |||
1362 | if (options.control_path != NULL) { | 1378 | if (options.control_path != NULL) { |
1363 | cp = tilde_expand_filename(options.control_path, getuid()); | 1379 | cp = tilde_expand_filename(options.control_path, getuid()); |
1364 | free(options.control_path); | 1380 | free(options.control_path); |
1365 | options.control_path = percent_expand(cp, | 1381 | options.control_path = default_client_percent_expand(cp, |
1366 | DEFAULT_CLIENT_PERCENT_EXPAND_ARGS, | 1382 | pw->pw_dir, host, options.user, pw->pw_name); |
1367 | "d", pw->pw_dir, | ||
1368 | "h", host, | ||
1369 | "r", options.user, | ||
1370 | "u", pw->pw_name, | ||
1371 | (char *)NULL); | ||
1372 | free(cp); | 1383 | free(cp); |
1373 | } | 1384 | } |
1374 | 1385 | ||
1375 | if (options.identity_agent != NULL) { | 1386 | if (options.identity_agent != NULL) { |
1376 | p = tilde_expand_filename(options.identity_agent, getuid()); | 1387 | p = tilde_expand_filename(options.identity_agent, getuid()); |
1377 | cp = percent_expand(p, | 1388 | cp = default_client_percent_expand(p, |
1378 | DEFAULT_CLIENT_PERCENT_EXPAND_ARGS, | 1389 | pw->pw_dir, host, options.user, pw->pw_name); |
1379 | "d", pw->pw_dir, | ||
1380 | "h", host, | ||
1381 | "r", options.user, | ||
1382 | "u", pw->pw_name, | ||
1383 | (char *)NULL); | ||
1384 | free(p); | 1390 | free(p); |
1385 | free(options.identity_agent); | 1391 | free(options.identity_agent); |
1386 | options.identity_agent = cp; | 1392 | options.identity_agent = cp; |
@@ -1389,18 +1395,59 @@ main(int ac, char **av) | |||
1389 | if (options.forward_agent_sock_path != NULL) { | 1395 | if (options.forward_agent_sock_path != NULL) { |
1390 | p = tilde_expand_filename(options.forward_agent_sock_path, | 1396 | p = tilde_expand_filename(options.forward_agent_sock_path, |
1391 | getuid()); | 1397 | getuid()); |
1392 | cp = percent_expand(p, | 1398 | cp = default_client_percent_expand(p, |
1393 | DEFAULT_CLIENT_PERCENT_EXPAND_ARGS, | 1399 | pw->pw_dir, host, options.user, pw->pw_name); |
1394 | "d", pw->pw_dir, | ||
1395 | "h", host, | ||
1396 | "r", options.user, | ||
1397 | "u", pw->pw_name, | ||
1398 | (char *)NULL); | ||
1399 | free(p); | 1400 | free(p); |
1400 | free(options.forward_agent_sock_path); | 1401 | free(options.forward_agent_sock_path); |
1401 | options.forward_agent_sock_path = cp; | 1402 | options.forward_agent_sock_path = cp; |
1402 | } | 1403 | } |
1403 | 1404 | ||
1405 | for (i = 0; i < options.num_local_forwards; i++) { | ||
1406 | if (options.local_forwards[i].listen_path != NULL) { | ||
1407 | cp = options.local_forwards[i].listen_path; | ||
1408 | p = options.local_forwards[i].listen_path = | ||
1409 | default_client_percent_expand(cp, | ||
1410 | pw->pw_dir, host, options.user, pw->pw_name); | ||
1411 | if (strcmp(cp, p) != 0) | ||
1412 | debug3("expanded LocalForward listen path " | ||
1413 | "'%s' -> '%s'", cp, p); | ||
1414 | free(cp); | ||
1415 | } | ||
1416 | if (options.local_forwards[i].connect_path != NULL) { | ||
1417 | cp = options.local_forwards[i].connect_path; | ||
1418 | p = options.local_forwards[i].connect_path = | ||
1419 | default_client_percent_expand(cp, | ||
1420 | pw->pw_dir, host, options.user, pw->pw_name); | ||
1421 | if (strcmp(cp, p) != 0) | ||
1422 | debug3("expanded LocalForward connect path " | ||
1423 | "'%s' -> '%s'", cp, p); | ||
1424 | free(cp); | ||
1425 | } | ||
1426 | } | ||
1427 | |||
1428 | for (i = 0; i < options.num_remote_forwards; i++) { | ||
1429 | if (options.remote_forwards[i].listen_path != NULL) { | ||
1430 | cp = options.remote_forwards[i].listen_path; | ||
1431 | p = options.remote_forwards[i].listen_path = | ||
1432 | default_client_percent_expand(cp, | ||
1433 | pw->pw_dir, host, options.user, pw->pw_name); | ||
1434 | if (strcmp(cp, p) != 0) | ||
1435 | debug3("expanded RemoteForward listen path " | ||
1436 | "'%s' -> '%s'", cp, p); | ||
1437 | free(cp); | ||
1438 | } | ||
1439 | if (options.remote_forwards[i].connect_path != NULL) { | ||
1440 | cp = options.remote_forwards[i].connect_path; | ||
1441 | p = options.remote_forwards[i].connect_path = | ||
1442 | default_client_percent_expand(cp, | ||
1443 | pw->pw_dir, host, options.user, pw->pw_name); | ||
1444 | if (strcmp(cp, p) != 0) | ||
1445 | debug3("expanded RemoteForward connect path " | ||
1446 | "'%s' -> '%s'", cp, p); | ||
1447 | free(cp); | ||
1448 | } | ||
1449 | } | ||
1450 | |||
1404 | if (config_test) { | 1451 | if (config_test) { |
1405 | dump_client_config(&options, host); | 1452 | dump_client_config(&options, host); |
1406 | exit(0); | 1453 | exit(0); |
@@ -2154,13 +2201,8 @@ load_public_identity_files(struct passwd *pw) | |||
2154 | continue; | 2201 | continue; |
2155 | } | 2202 | } |
2156 | cp = tilde_expand_filename(options.identity_files[i], getuid()); | 2203 | cp = tilde_expand_filename(options.identity_files[i], getuid()); |
2157 | filename = percent_expand(cp, | 2204 | filename = default_client_percent_expand(cp, |
2158 | DEFAULT_CLIENT_PERCENT_EXPAND_ARGS, | 2205 | pw->pw_dir, host, options.user, pw->pw_name); |
2159 | "d", pw->pw_dir, | ||
2160 | "h", host, | ||
2161 | "r", options.user, | ||
2162 | "u", pw->pw_name, | ||
2163 | (char *)NULL); | ||
2164 | free(cp); | 2206 | free(cp); |
2165 | check_load(sshkey_load_public(filename, &public, NULL), | 2207 | check_load(sshkey_load_public(filename, &public, NULL), |
2166 | filename, "pubkey"); | 2208 | filename, "pubkey"); |
@@ -2209,13 +2251,8 @@ load_public_identity_files(struct passwd *pw) | |||
2209 | for (i = 0; i < options.num_certificate_files; i++) { | 2251 | for (i = 0; i < options.num_certificate_files; i++) { |
2210 | cp = tilde_expand_filename(options.certificate_files[i], | 2252 | cp = tilde_expand_filename(options.certificate_files[i], |
2211 | getuid()); | 2253 | getuid()); |
2212 | filename = percent_expand(cp, | 2254 | filename = default_client_percent_expand(cp, |
2213 | DEFAULT_CLIENT_PERCENT_EXPAND_ARGS, | 2255 | pw->pw_dir, host, options.user, pw->pw_name); |
2214 | "d", pw->pw_dir, | ||
2215 | "h", host, | ||
2216 | "r", options.user, | ||
2217 | "u", pw->pw_name, | ||
2218 | (char *)NULL); | ||
2219 | free(cp); | 2256 | free(cp); |
2220 | 2257 | ||
2221 | check_load(sshkey_load_public(filename, &public, NULL), | 2258 | check_load(sshkey_load_public(filename, &public, NULL), |
diff --git a/ssh_config.5 b/ssh_config.5 index 9d89c13aa..7bbc76aa3 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.323 2020/04/03 02:27:12 dtucker Exp $ | 36 | .\" $OpenBSD: ssh_config.5,v 1.324 2020/04/10 00:52:07 dtucker Exp $ |
37 | .Dd $Mdocdate: April 3 2020 $ | 37 | .Dd $Mdocdate: April 10 2020 $ |
38 | .Dt SSH_CONFIG 5 | 38 | .Dt SSH_CONFIG 5 |
39 | .Os | 39 | .Os |
40 | .Sh NAME | 40 | .Sh NAME |
@@ -1125,12 +1125,15 @@ has been enabled. | |||
1125 | .It Cm LocalForward | 1125 | .It Cm LocalForward |
1126 | Specifies that a TCP port on the local machine be forwarded over | 1126 | Specifies that a TCP port on the local machine be forwarded over |
1127 | the secure channel to the specified host and port from the remote machine. | 1127 | the secure channel to the specified host and port from the remote machine. |
1128 | The first argument must be | 1128 | The first argument specifies the listener and may be |
1129 | .Sm off | 1129 | .Sm off |
1130 | .Oo Ar bind_address : Oc Ar port | 1130 | .Oo Ar bind_address : Oc Ar port |
1131 | .Sm on | 1131 | .Sm on |
1132 | and the second argument must be | 1132 | or a Unix domain socket path. |
1133 | .Ar host : Ns Ar hostport . | 1133 | The second argument is the destination and may be |
1134 | .Ar host : Ns Ar hostport | ||
1135 | or a Unix domain socket path if the remote host supports it. | ||
1136 | .Pp | ||
1134 | IPv6 addresses can be specified by enclosing addresses in square brackets. | 1137 | IPv6 addresses can be specified by enclosing addresses in square brackets. |
1135 | Multiple forwardings may be specified, and additional forwardings can be | 1138 | Multiple forwardings may be specified, and additional forwardings can be |
1136 | given on the command line. | 1139 | given on the command line. |
@@ -1149,6 +1152,9 @@ indicates that the listening port be bound for local use only, while an | |||
1149 | empty address or | 1152 | empty address or |
1150 | .Sq * | 1153 | .Sq * |
1151 | indicates that the port should be available from all interfaces. | 1154 | indicates that the port should be available from all interfaces. |
1155 | Unix domain socket paths accept the tokens described in the | ||
1156 | .Sx TOKENS | ||
1157 | section. | ||
1152 | .It Cm LogLevel | 1158 | .It Cm LogLevel |
1153 | Gives the verbosity level that is used when logging messages from | 1159 | Gives the verbosity level that is used when logging messages from |
1154 | .Xr ssh 1 . | 1160 | .Xr ssh 1 . |
@@ -1401,12 +1407,14 @@ the secure channel. | |||
1401 | The remote port may either be forwarded to a specified host and port | 1407 | The remote port may either be forwarded to a specified host and port |
1402 | from the local machine, or may act as a SOCKS 4/5 proxy that allows a remote | 1408 | from the local machine, or may act as a SOCKS 4/5 proxy that allows a remote |
1403 | client to connect to arbitrary destinations from the local machine. | 1409 | client to connect to arbitrary destinations from the local machine. |
1404 | The first argument must be | 1410 | The first argument is the listening specification and may be |
1405 | .Sm off | 1411 | .Sm off |
1406 | .Oo Ar bind_address : Oc Ar port | 1412 | .Oo Ar bind_address : Oc Ar port |
1407 | .Sm on | 1413 | .Sm on |
1414 | or, if the remote host supports it, a Unix domain socket path. | ||
1408 | If forwarding to a specific destination then the second argument must be | 1415 | If forwarding to a specific destination then the second argument must be |
1409 | .Ar host : Ns Ar hostport , | 1416 | .Ar host : Ns Ar hostport |
1417 | or a Unix domain socket path, | ||
1410 | otherwise if no destination argument is specified then the remote forwarding | 1418 | otherwise if no destination argument is specified then the remote forwarding |
1411 | will be established as a SOCKS proxy. | 1419 | will be established as a SOCKS proxy. |
1412 | .Pp | 1420 | .Pp |
@@ -1415,6 +1423,9 @@ Multiple forwardings may be specified, and additional | |||
1415 | forwardings can be given on the command line. | 1423 | forwardings can be given on the command line. |
1416 | Privileged ports can be forwarded only when | 1424 | Privileged ports can be forwarded only when |
1417 | logging in as root on the remote machine. | 1425 | logging in as root on the remote machine. |
1426 | Unix domain socket paths accept the tokens described in the | ||
1427 | .Sx TOKENS | ||
1428 | section. | ||
1418 | .Pp | 1429 | .Pp |
1419 | If the | 1430 | If the |
1420 | .Ar port | 1431 | .Ar port |
@@ -1845,13 +1856,15 @@ otherwise. | |||
1845 | The local username. | 1856 | The local username. |
1846 | .El | 1857 | .El |
1847 | .Pp | 1858 | .Pp |
1848 | .Cm Match exec , | ||
1849 | .Cm CertificateFile , | 1859 | .Cm CertificateFile , |
1850 | .Cm ControlPath , | 1860 | .Cm ControlPath , |
1851 | .Cm IdentityAgent , | 1861 | .Cm IdentityAgent , |
1852 | .Cm IdentityFile , | 1862 | .Cm IdentityFile , |
1863 | .Cm LocalForward, | ||
1864 | .Cm Match exec , | ||
1865 | .Cm RemoteCommand , | ||
1853 | and | 1866 | and |
1854 | .Cm RemoteCommand | 1867 | .Cm RemoteForward |
1855 | accept the tokens %%, %C, %d, %h, %i, %L, %l, %n, %p, %r, and %u. | 1868 | accept the tokens %%, %C, %d, %h, %i, %L, %l, %n, %p, %r, and %u. |
1856 | .Pp | 1869 | .Pp |
1857 | .Cm Hostname | 1870 | .Cm Hostname |