summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorDarren Tucker <dtucker@cvs.openbsd.org>2020-04-03 02:27:13 +0000
committerDarren Tucker <dtucker@cvs.openbsd.org>2020-04-03 02:27:13 +0000
commit4143603998c07eeeca0dca039a19c1b1292d4245 (patch)
tree2962335e23042d74760013cb36218224f42942df /usr.bin
parent2586386661cc7dbd67c42858e911510d538f6776 (diff)
Make with config keywords support which percent_expansions more consistent.
- %C is moved into its own function and added to Match Exec. - move the common (global) options into a macro. This is ugly but it's the least-ugly way I could come up with. - move IdentityAgent and ForwardAgent percent expansion to before the config dump to make it regression-testable. - document all of the above ok jmc@ for man page bits, "makes things less terrible" djm@ for the rest.
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/ssh/readconf.c26
-rw-r--r--usr.bin/ssh/readconf.h4
-rw-r--r--usr.bin/ssh/ssh.c120
-rw-r--r--usr.bin/ssh/ssh_config.530
4 files changed, 92 insertions, 88 deletions
diff --git a/usr.bin/ssh/readconf.c b/usr.bin/ssh/readconf.c
index 886ebcdcadf..dce08a7e7ad 100644
--- a/usr.bin/ssh/readconf.c
+++ b/usr.bin/ssh/readconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.c,v 1.326 2020/02/06 22:46:31 djm Exp $ */
+/* $OpenBSD: readconf.c,v 1.327 2020/04/03 02:27:12 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -310,6 +310,24 @@ kex_default_pk_alg(void)
return kex_default_pk_alg_filtered;
}
+char *
+ssh_connection_hash(const char *thishost, const char *host, const char *portstr,
+ const char *user)
+{
+ struct ssh_digest_ctx *md;
+ u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
+
+ if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL ||
+ ssh_digest_update(md, thishost, strlen(thishost)) < 0 ||
+ ssh_digest_update(md, host, strlen(host)) < 0 ||
+ ssh_digest_update(md, portstr, strlen(portstr)) < 0 ||
+ ssh_digest_update(md, user, strlen(user)) < 0 ||
+ ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0)
+ fatal("%s: mux digest failed", __func__);
+ ssh_digest_free(md);
+ return tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1));
+}
+
/*
* Adds a local TCP/IP port forward to options. Never returns if there is an
* error.
@@ -632,6 +650,8 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,
if (r == (negate ? 1 : 0))
this_result = result = 0;
} else if (strcasecmp(attrib, "exec") == 0) {
+ char *conn_hash_hex;
+
if (gethostname(thishost, sizeof(thishost)) == -1)
fatal("gethostname: %s", strerror(errno));
strlcpy(shorthost, thishost, sizeof(shorthost));
@@ -639,8 +659,11 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,
snprintf(portstr, sizeof(portstr), "%d", port);
snprintf(uidstr, sizeof(uidstr), "%llu",
(unsigned long long)pw->pw_uid);
+ conn_hash_hex = ssh_connection_hash(thishost, host,
+ portstr, pw->pw_name);
cmd = percent_expand(arg,
+ "C", conn_hash_hex,
"L", shorthost,
"d", pw->pw_dir,
"h", host,
@@ -651,6 +674,7 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,
"u", pw->pw_name,
"i", uidstr,
(char *)NULL);
+ free(conn_hash_hex);
if (result != 1) {
/* skip execution if prior predicate failed */
debug3("%.200s line %d: skipped exec "
diff --git a/usr.bin/ssh/readconf.h b/usr.bin/ssh/readconf.h
index feedb3d202c..e143a1082ae 100644
--- a/usr.bin/ssh/readconf.h
+++ b/usr.bin/ssh/readconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.h,v 1.132 2020/01/23 02:46:49 dtucker Exp $ */
+/* $OpenBSD: readconf.h,v 1.133 2020/04/03 02:27:12 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -200,6 +200,8 @@ typedef struct {
#define SSH_STRICT_HOSTKEY_ASK 3
const char *kex_default_pk_alg(void);
+char *ssh_connection_hash(const char *thishost, const char *host,
+ const char *portstr, const char *user);
void initialize_options(Options *);
void fill_default_options(Options *);
void fill_default_options_for_canonicalization(Options *);
diff --git a/usr.bin/ssh/ssh.c b/usr.bin/ssh/ssh.c
index 1bc5443f361..3ed4cd73342 100644
--- a/usr.bin/ssh/ssh.c
+++ b/usr.bin/ssh/ssh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.c,v 1.521 2020/03/06 18:20:02 markus Exp $ */
+/* $OpenBSD: ssh.c,v 1.522 2020/04/03 02:27:12 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -76,7 +76,6 @@
#include "canohost.h"
#include "compat.h"
#include "cipher.h"
-#include "digest.h"
#include "packet.h"
#include "sshbuf.h"
#include "channels.h"
@@ -161,6 +160,13 @@ 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;
+#define DEFAULT_CLIENT_PERCENT_EXPAND_ARGS \
+ "C", conn_hash_hex, \
+ "L", shorthost, \
+ "i", uidstr, \
+ "l", thishost, \
+ "n", host_arg, \
+ "p", portstr
/* socket address the host resolves to */
struct sockaddr_storage hostaddr;
@@ -585,8 +591,6 @@ main(int ac, char **av)
extern char *optarg;
struct Forward fwd;
struct addrinfo *addrs = NULL;
- struct ssh_digest_ctx *md;
- u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
size_t n, len;
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
@@ -1309,15 +1313,8 @@ main(int ac, char **av)
snprintf(uidstr, sizeof(uidstr), "%llu",
(unsigned long long)pw->pw_uid);
- if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL ||
- ssh_digest_update(md, thishost, strlen(thishost)) < 0 ||
- ssh_digest_update(md, host, strlen(host)) < 0 ||
- ssh_digest_update(md, portstr, strlen(portstr)) < 0 ||
- ssh_digest_update(md, options.user, strlen(options.user)) < 0 ||
- ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0)
- fatal("%s: mux digest failed", __func__);
- ssh_digest_free(md);
- conn_hash_hex = tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1));
+ conn_hash_hex = ssh_connection_hash(thishost, host, portstr,
+ options.user);
/*
* Expand tokens in arguments. NB. LocalCommand is expanded later,
@@ -1328,14 +1325,9 @@ main(int ac, char **av)
debug3("expanding RemoteCommand: %s", options.remote_command);
cp = options.remote_command;
options.remote_command = percent_expand(cp,
- "C", conn_hash_hex,
- "L", shorthost,
+ DEFAULT_CLIENT_PERCENT_EXPAND_ARGS,
"d", pw->pw_dir,
"h", host,
- "i", uidstr,
- "l", thishost,
- "n", host_arg,
- "p", portstr,
"r", options.user,
"u", pw->pw_name,
(char *)NULL);
@@ -1350,20 +1342,44 @@ main(int ac, char **av)
cp = tilde_expand_filename(options.control_path, getuid());
free(options.control_path);
options.control_path = percent_expand(cp,
- "C", conn_hash_hex,
- "L", shorthost,
+ DEFAULT_CLIENT_PERCENT_EXPAND_ARGS,
+ "d", pw->pw_dir,
"h", host,
- "i", uidstr,
- "l", thishost,
- "n", host_arg,
- "p", portstr,
"r", options.user,
"u", pw->pw_name,
- "i", uidstr,
(char *)NULL);
free(cp);
}
+ if (options.identity_agent != NULL) {
+ p = tilde_expand_filename(options.identity_agent, getuid());
+ cp = percent_expand(p,
+ DEFAULT_CLIENT_PERCENT_EXPAND_ARGS,
+ "d", pw->pw_dir,
+ "h", host,
+ "r", options.user,
+ "u", pw->pw_name,
+ (char *)NULL);
+ free(p);
+ free(options.identity_agent);
+ options.identity_agent = cp;
+ }
+
+ if (options.forward_agent_sock_path != NULL) {
+ p = tilde_expand_filename(options.forward_agent_sock_path,
+ getuid());
+ cp = percent_expand(p,
+ DEFAULT_CLIENT_PERCENT_EXPAND_ARGS,
+ "d", pw->pw_dir,
+ "h", host,
+ "r", options.user,
+ "u", pw->pw_name,
+ (char *)NULL);
+ free(p);
+ free(options.forward_agent_sock_path);
+ options.forward_agent_sock_path = cp;
+ }
+
if (config_test) {
dump_client_config(&options, host);
exit(0);
@@ -1482,23 +1498,7 @@ main(int ac, char **av)
if (strcmp(options.identity_agent, "none") == 0) {
unsetenv(SSH_AUTHSOCKET_ENV_NAME);
} else {
- p = tilde_expand_filename(options.identity_agent,
- 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 identity_agent represents an environment variable
- * then recheck that it is valid (since processing with
- * percent_expand() may have changed it) and substitute
- * its value.
- */
+ cp = options.identity_agent;
if (cp[0] == '$') {
if (!valid_env_name(cp + 1)) {
fatal("Invalid IdentityAgent "
@@ -1512,22 +1512,10 @@ main(int ac, char **av)
/* identity_agent specifies a path directly */
setenv(SSH_AUTHSOCKET_ENV_NAME, cp, 1);
}
- free(cp);
}
}
- 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 (options.forward_agent && options.forward_agent_sock_path != NULL) {
if (cp[0] == '$') {
if (!valid_env_name(cp + 1)) {
fatal("Invalid ForwardAgent environment variable name %s", cp);
@@ -1952,14 +1940,9 @@ ssh_session2(struct ssh *ssh, struct passwd *pw)
debug3("expanding LocalCommand: %s", options.local_command);
cp = options.local_command;
options.local_command = percent_expand(cp,
- "C", conn_hash_hex,
- "L", shorthost,
+ DEFAULT_CLIENT_PERCENT_EXPAND_ARGS,
"d", pw->pw_dir,
"h", host,
- "i", uidstr,
- "l", thishost,
- "n", host_arg,
- "p", portstr,
"r", options.user,
"u", pw->pw_name,
"T", tun_fwd_ifname == NULL ? "NONE" : tun_fwd_ifname,
@@ -2116,9 +2099,13 @@ load_public_identity_files(struct passwd *pw)
continue;
}
cp = tilde_expand_filename(options.identity_files[i], getuid());
- filename = percent_expand(cp, "d", pw->pw_dir,
- "u", pw->pw_name, "l", thishost, "h", host,
- "r", options.user, (char *)NULL);
+ filename = percent_expand(cp,
+ DEFAULT_CLIENT_PERCENT_EXPAND_ARGS,
+ "d", pw->pw_dir,
+ "h", host,
+ "r", options.user,
+ "u", pw->pw_name,
+ (char *)NULL);
free(cp);
check_load(sshkey_load_public(filename, &public, NULL),
filename, "pubkey");
@@ -2168,10 +2155,9 @@ load_public_identity_files(struct passwd *pw)
cp = tilde_expand_filename(options.certificate_files[i],
getuid());
filename = percent_expand(cp,
+ DEFAULT_CLIENT_PERCENT_EXPAND_ARGS,
"d", pw->pw_dir,
"h", host,
- "i", uidstr,
- "l", thishost,
"r", options.user,
"u", pw->pw_name,
(char *)NULL);
diff --git a/usr.bin/ssh/ssh_config.5 b/usr.bin/ssh/ssh_config.5
index 14afcdbd602..1a51b82c575 100644
--- a/usr.bin/ssh/ssh_config.5
+++ b/usr.bin/ssh/ssh_config.5
@@ -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.322 2020/02/07 03:54:44 dtucker Exp $
-.Dd $Mdocdate: February 7 2020 $
+.\" $OpenBSD: ssh_config.5,v 1.323 2020/04/03 02:27:12 dtucker Exp $
+.Dd $Mdocdate: April 3 2020 $
.Dt SSH_CONFIG 5
.Os
.Sh NAME
@@ -1846,31 +1846,23 @@ otherwise.
The local username.
.El
.Pp
-.Cm Match exec
-accepts the tokens %%, %h, %i, %L, %l, %n, %p, %r, and %u.
-.Pp
-.Cm CertificateFile
-accepts the tokens %%, %d, %h, %i, %l, %r, and %u.
-.Pp
-.Cm ControlPath
-accepts the tokens %%, %C, %h, %i, %L, %l, %n, %p, %r, and %u.
+.Cm Match exec ,
+.Cm CertificateFile ,
+.Cm ControlPath ,
+.Cm IdentityAgent ,
+.Cm IdentityFile ,
+and
+.Cm RemoteCommand
+accept the tokens %%, %C, %d, %h, %i, %L, %l, %n, %p, %r, and %u.
.Pp
.Cm Hostname
accepts the tokens %% and %h.
.Pp
-.Cm IdentityAgent
-and
-.Cm IdentityFile
-accept the tokens %%, %d, %h, %i, %l, %r, and %u.
-.Pp
.Cm LocalCommand
-accepts the tokens %%, %C, %d, %h, %i, %l, %n, %p, %r, %T, and %u.
+accepts all tokens.
.Pp
.Cm ProxyCommand
accepts the tokens %%, %h, %n, %p, and %r.
-.Pp
-.Cm RemoteCommand
-accepts the tokens %%, %C, %d, %h, %i, %l, %n, %p, %r, and %u.
.Sh FILES
.Bl -tag -width Ds
.It Pa ~/.ssh/config