summaryrefslogtreecommitdiffstats
path: root/crypto/openssh/readconf.c
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2017-09-02 14:25:20 +0000
committerdes <des@FreeBSD.org>2017-09-02 14:25:20 +0000
commitce0d6faba2a9fd27ff0fc0942a4e51f5203bb88f (patch)
treee29bf4f30ea560420ac21b41c62cc53b42547a0b /crypto/openssh/readconf.c
parentfa127d1375fbc969c65e8d8a5f9f2f8efe4e36fc (diff)
downloadFreeBSD-src-ce0d6faba2a9fd27ff0fc0942a4e51f5203bb88f.zip
FreeBSD-src-ce0d6faba2a9fd27ff0fc0942a4e51f5203bb88f.tar.gz
MFH (r314527,r314576,r314601,r317998): Upgrade OpenSSH to 7.3p1.
Diffstat (limited to 'crypto/openssh/readconf.c')
-rw-r--r--crypto/openssh/readconf.c265
1 files changed, 241 insertions, 24 deletions
diff --git a/crypto/openssh/readconf.c b/crypto/openssh/readconf.c
index 4755473..170ae74 100644
--- a/crypto/openssh/readconf.c
+++ b/crypto/openssh/readconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.c,v 1.250 2016/02/08 23:40:12 djm Exp $ */
+/* $OpenBSD: readconf.c,v 1.259 2016/07/22 03:35:11 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -41,6 +41,11 @@ __RCSID("$FreeBSD$");
#include <stdio.h>
#include <string.h>
#include <unistd.h>
+#ifdef USE_SYSTEM_GLOB
+# include <glob.h>
+#else
+# include "openbsd-compat/glob.h"
+#endif
#ifdef HAVE_UTIL_H
#include <util.h>
#endif
@@ -128,18 +133,25 @@ __RCSID("$FreeBSD$");
*/
+static int read_config_file_depth(const char *filename, struct passwd *pw,
+ const char *host, const char *original_host, Options *options,
+ int flags, int *activep, int depth);
+static int process_config_line_depth(Options *options, struct passwd *pw,
+ const char *host, const char *original_host, char *line,
+ const char *filename, int linenum, int *activep, int flags, int depth);
+
/* Keyword tokens. */
typedef enum {
oBadOption,
oVersionAddendum,
- oHost, oMatch,
+ oHost, oMatch, oInclude,
oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
oGatewayPorts, oExitOnForwardFailure,
oPasswordAuthentication, oRSAAuthentication,
oChallengeResponseAuthentication, oXAuthLocation,
oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
- oCertificateFile, oAddKeysToAgent,
+ oCertificateFile, oAddKeysToAgent, oIdentityAgent,
oUser, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
@@ -162,7 +174,7 @@ typedef enum {
oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes,
- oPubkeyAcceptedKeyTypes,
+ oPubkeyAcceptedKeyTypes, oProxyJump,
oIgnoredUnknownOption, oDeprecated, oUnsupported
} OpCodes;
@@ -209,6 +221,7 @@ static struct {
{ "identitiesonly", oIdentitiesOnly },
{ "certificatefile", oCertificateFile },
{ "addkeystoagent", oAddKeysToAgent },
+ { "identityagent", oIdentityAgent },
{ "hostname", oHostName },
{ "hostkeyalias", oHostKeyAlias },
{ "proxycommand", oProxyCommand },
@@ -262,6 +275,7 @@ static struct {
{ "controlmaster", oControlMaster },
{ "controlpersist", oControlPersist },
{ "hashknownhosts", oHashKnownHosts },
+ { "include", oInclude },
{ "tunnel", oTunnel },
{ "tunneldevice", oTunnelDevice },
{ "localcommand", oLocalCommand },
@@ -285,6 +299,8 @@ static struct {
{ "hostbasedkeytypes", oHostbasedKeyTypes },
{ "pubkeyacceptedkeytypes", oPubkeyAcceptedKeyTypes },
{ "ignoreunknown", oIgnoreUnknown },
+ { "proxyjump", oProxyJump },
+
{ "hpndisabled", oDeprecated },
{ "hpnbuffersize", oDeprecated },
{ "tcprcvbufpoll", oDeprecated },
@@ -305,9 +321,8 @@ void
add_local_forward(Options *options, const struct Forward *newfwd)
{
struct Forward *fwd;
-#ifndef NO_IPPORT_RESERVED_CONCEPT
extern uid_t original_real_uid;
- int ipport_reserved;
+ int i, ipport_reserved;
#ifdef __FreeBSD__
size_t len_ipport_reserved = sizeof(ipport_reserved);
@@ -323,7 +338,11 @@ add_local_forward(Options *options, const struct Forward *newfwd)
if (newfwd->listen_port < ipport_reserved && original_real_uid != 0 &&
newfwd->listen_path == NULL)
fatal("Privileged ports can only be forwarded by root.");
-#endif
+ /* Don't add duplicates */
+ for (i = 0; i < options->num_local_forwards; i++) {
+ if (forward_equals(newfwd, options->local_forwards + i))
+ return;
+ }
options->local_forwards = xreallocarray(options->local_forwards,
options->num_local_forwards + 1,
sizeof(*options->local_forwards));
@@ -346,7 +365,13 @@ void
add_remote_forward(Options *options, const struct Forward *newfwd)
{
struct Forward *fwd;
+ int i;
+ /* Don't add duplicates */
+ for (i = 0; i < options->num_remote_forwards; i++) {
+ if (forward_equals(newfwd, options->remote_forwards + i))
+ return;
+ }
options->remote_forwards = xreallocarray(options->remote_forwards,
options->num_remote_forwards + 1,
sizeof(*options->remote_forwards));
@@ -796,22 +821,32 @@ static const struct multistate multistate_canonicalizehostname[] = {
* Processes a single option line as used in the configuration files. This
* only sets those values that have not already been set.
*/
-#define WHITESPACE " \t\r\n"
int
process_config_line(Options *options, struct passwd *pw, const char *host,
const char *original_host, char *line, const char *filename,
int linenum, int *activep, int flags)
{
+ return process_config_line_depth(options, pw, host, original_host,
+ line, filename, linenum, activep, flags, 0);
+}
+
+#define WHITESPACE " \t\r\n"
+static int
+process_config_line_depth(Options *options, struct passwd *pw, const char *host,
+ const char *original_host, char *line, const char *filename,
+ int linenum, int *activep, int flags, int depth)
+{
char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
char **cpptr, fwdarg[256];
u_int i, *uintptr, max_entries = 0;
- int negated, opcode, *intptr, value, value2, cmdline = 0;
+ int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
LogLevel *log_level_ptr;
long long val64;
size_t len;
struct Forward fwd;
const struct multistate *multistate_ptr;
struct allowed_cname *cname;
+ glob_t gl;
if (activep == NULL) { /* We are processing a command line directive */
cmdline = 1;
@@ -1110,6 +1145,9 @@ parse_char_array:
case oProxyCommand:
charptr = &options->proxy_command;
+ /* Ignore ProxyCommand if ProxyJump already specified */
+ if (options->jump_host != NULL)
+ charptr = &options->jump_host; /* Skip below */
parse_command:
if (s == NULL)
fatal("%.200s line %d: Missing argument.", filename, linenum);
@@ -1118,6 +1156,18 @@ parse_command:
*charptr = xstrdup(s + len);
return 0;
+ case oProxyJump:
+ if (s == NULL) {
+ fatal("%.200s line %d: Missing argument.",
+ filename, linenum);
+ }
+ len = strspn(s, WHITESPACE "=");
+ if (parse_jump(s + len, options, *activep) == -1) {
+ fatal("%.200s line %d: Invalid ProxyJump \"%s\"",
+ filename, linenum, s + len);
+ }
+ return 0;
+
case oPort:
intptr = &options->port;
parse_int:
@@ -1271,6 +1321,8 @@ parse_keytypes:
*activep = 0;
arg2 = NULL;
while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+ if ((flags & SSHCONF_NEVERMATCH) != 0)
+ break;
negated = *arg == '!';
if (negated)
arg++;
@@ -1303,7 +1355,7 @@ parse_keytypes:
if (value < 0)
fatal("%.200s line %d: Bad Match condition", filename,
linenum);
- *activep = value;
+ *activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
break;
case oEscapeChar:
@@ -1431,6 +1483,63 @@ parse_keytypes:
intptr = &options->visual_host_key;
goto parse_flag;
+ case oInclude:
+ if (cmdline)
+ fatal("Include directive not supported as a "
+ "command-line option");
+ value = 0;
+ while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+ /*
+ * Ensure all paths are anchored. User configuration
+ * files may begin with '~/' but system configurations
+ * must not. If the path is relative, then treat it
+ * as living in ~/.ssh for user configurations or
+ * /etc/ssh for system ones.
+ */
+ if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0)
+ fatal("%.200s line %d: bad include path %s.",
+ filename, linenum, arg);
+ if (*arg != '/' && *arg != '~') {
+ xasprintf(&arg2, "%s/%s",
+ (flags & SSHCONF_USERCONF) ?
+ "~/" _PATH_SSH_USER_DIR : SSHDIR, arg);
+ } else
+ arg2 = xstrdup(arg);
+ memset(&gl, 0, sizeof(gl));
+ r = glob(arg2, GLOB_TILDE, NULL, &gl);
+ if (r == GLOB_NOMATCH) {
+ debug("%.200s line %d: include %s matched no "
+ "files",filename, linenum, arg2);
+ continue;
+ } else if (r != 0 || gl.gl_pathc < 0)
+ fatal("%.200s line %d: glob failed for %s.",
+ filename, linenum, arg2);
+ free(arg2);
+ oactive = *activep;
+ for (i = 0; i < (u_int)gl.gl_pathc; i++) {
+ debug3("%.200s line %d: Including file %s "
+ "depth %d%s", filename, linenum,
+ gl.gl_pathv[i], depth,
+ oactive ? "" : " (parse only)");
+ r = read_config_file_depth(gl.gl_pathv[i],
+ pw, host, original_host, options,
+ flags | SSHCONF_CHECKPERM |
+ (oactive ? 0 : SSHCONF_NEVERMATCH),
+ activep, depth + 1);
+ /*
+ * don't let Match in includes clobber the
+ * containing file's Match state.
+ */
+ *activep = oactive;
+ if (r != 1)
+ value = -1;
+ }
+ globfree(&gl);
+ }
+ if (value != 0)
+ return value;
+ break;
+
case oIPQoS:
arg = strdelim(&s);
if ((value = parse_ipqos(arg)) == -1)
@@ -1583,6 +1692,10 @@ parse_keytypes:
multistate_ptr = multistate_yesnoaskconfirm;
goto parse_multistate;
+ case oIdentityAgent:
+ charptr = &options->identity_agent;
+ goto parse_string;
+
case oDeprecated:
debug("%s line %d: Deprecated option \"%s\"",
filename, linenum, keyword);
@@ -1605,22 +1718,35 @@ parse_keytypes:
return 0;
}
-
/*
* Reads the config file and modifies the options accordingly. Options
* should already be initialized before this call. This never returns if
* there is an error. If the file does not exist, this returns 0.
*/
-
int
read_config_file(const char *filename, struct passwd *pw, const char *host,
const char *original_host, Options *options, int flags)
{
+ int active = 1;
+
+ return read_config_file_depth(filename, pw, host, original_host,
+ options, flags, &active, 0);
+}
+
+#define READCONF_MAX_DEPTH 16
+static int
+read_config_file_depth(const char *filename, struct passwd *pw,
+ const char *host, const char *original_host, Options *options,
+ int flags, int *activep, int depth)
+{
FILE *f;
char line[1024];
- int active, linenum;
+ int linenum;
int bad_options = 0;
+ if (depth < 0 || depth > READCONF_MAX_DEPTH)
+ fatal("Too many recursive configuration includes");
+
if ((f = fopen(filename, "r")) == NULL)
return 0;
@@ -1640,13 +1766,12 @@ read_config_file(const char *filename, struct passwd *pw, const char *host,
* Mark that we are now processing the options. This flag is turned
* on/off by Host specifications.
*/
- active = 1;
linenum = 0;
while (fgets(line, sizeof(line), f)) {
/* Update line number counter. */
linenum++;
- if (process_config_line(options, pw, host, original_host,
- line, filename, linenum, &active, flags) != 0)
+ if (process_config_line_depth(options, pw, host, original_host,
+ line, filename, linenum, activep, flags, depth) != 0)
bad_options++;
}
fclose(f);
@@ -1679,6 +1804,9 @@ initialize_options(Options * options)
options->forward_x11 = -1;
options->forward_x11_trusted = -1;
options->forward_x11_timeout = -1;
+ options->stdio_forward_host = NULL;
+ options->stdio_forward_port = 0;
+ options->clear_forwardings = -1;
options->exit_on_forward_failure = -1;
options->xauth_location = NULL;
options->fwd_opts.gateway_ports = -1;
@@ -1717,6 +1845,10 @@ initialize_options(Options * options)
options->hostname = NULL;
options->host_key_alias = NULL;
options->proxy_command = NULL;
+ options->jump_user = NULL;
+ options->jump_host = NULL;
+ options->jump_port = -1;
+ options->jump_extra = NULL;
options->user = NULL;
options->escape_char = -1;
options->num_system_hostfiles = 0;
@@ -1725,7 +1857,6 @@ initialize_options(Options * options)
options->num_local_forwards = 0;
options->remote_forwards = NULL;
options->num_remote_forwards = 0;
- options->clear_forwardings = -1;
options->log_level = SYSLOG_LEVEL_NOT_SET;
options->preferred_authentications = NULL;
options->bind_address = NULL;
@@ -1750,6 +1881,7 @@ initialize_options(Options * options)
options->local_command = NULL;
options->permit_local_command = -1;
options->add_keys_to_agent = -1;
+ options->identity_agent = NULL;
options->visual_host_key = -1;
options->ip_qos_interactive = -1;
options->ip_qos_bulk = -1;
@@ -1798,8 +1930,19 @@ fill_default_options(Options * options)
options->forward_x11_trusted = 0;
if (options->forward_x11_timeout == -1)
options->forward_x11_timeout = 1200;
+ /*
+ * stdio forwarding (-W) changes the default for these but we defer
+ * setting the values so they can be overridden.
+ */
if (options->exit_on_forward_failure == -1)
- options->exit_on_forward_failure = 0;
+ options->exit_on_forward_failure =
+ options->stdio_forward_host != NULL ? 1 : 0;
+ if (options->clear_forwardings == -1)
+ options->clear_forwardings =
+ options->stdio_forward_host != NULL ? 1 : 0;
+ if (options->clear_forwardings == 1)
+ clear_forwardings(options);
+
if (options->xauth_location == NULL)
options->xauth_location = _PATH_XAUTH;
if (options->fwd_opts.gateway_ports == -1)
@@ -1890,8 +2033,6 @@ fill_default_options(Options * options)
}
if (options->log_level == SYSLOG_LEVEL_NOT_SET)
options->log_level = SYSLOG_LEVEL_INFO;
- if (options->clear_forwardings == 1)
- clear_forwardings(options);
if (options->no_host_authentication_for_localhost == - 1)
options->no_host_authentication_for_localhost = 0;
if (options->identities_only == -1)
@@ -1970,6 +2111,7 @@ fill_default_options(Options * options)
CLEAR_ON_NONE(options->proxy_command);
CLEAR_ON_NONE(options->control_path);
CLEAR_ON_NONE(options->revoked_host_keys);
+ /* options->identity_agent distinguishes NULL from 'none' */
/* options->user will be set in the main program if appropriate */
/* options->hostname will be set in the main program if appropriate */
/* options->host_key_alias should not be set by default */
@@ -2187,6 +2329,54 @@ parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remo
return (0);
}
+int
+parse_jump(const char *s, Options *o, int active)
+{
+ char *orig, *sdup, *cp;
+ char *host = NULL, *user = NULL;
+ int ret = -1, port = -1, first;
+
+ active &= o->proxy_command == NULL && o->jump_host == NULL;
+
+ orig = sdup = xstrdup(s);
+ first = active;
+ do {
+ if ((cp = strrchr(sdup, ',')) == NULL)
+ cp = sdup; /* last */
+ else
+ *cp++ = '\0';
+
+ if (first) {
+ /* First argument and configuration is active */
+ if (parse_user_host_port(cp, &user, &host, &port) != 0)
+ goto out;
+ } else {
+ /* Subsequent argument or inactive configuration */
+ if (parse_user_host_port(cp, NULL, NULL, NULL) != 0)
+ goto out;
+ }
+ first = 0; /* only check syntax for subsequent hosts */
+ } while (cp != sdup);
+ /* success */
+ if (active) {
+ o->jump_user = user;
+ o->jump_host = host;
+ o->jump_port = port;
+ o->proxy_command = xstrdup("none");
+ user = host = NULL;
+ if ((cp = strrchr(s, ',')) != NULL && cp != s) {
+ o->jump_extra = xstrdup(s);
+ o->jump_extra[cp - s] = '\0';
+ }
+ }
+ ret = 0;
+ out:
+ free(orig);
+ free(user);
+ free(host);
+ return ret;
+}
+
/* XXX the following is a near-vebatim copy from servconf.c; refactor */
static const char *
fmt_multistate_int(int val, const struct multistate *m)
@@ -2338,7 +2528,7 @@ void
dump_client_config(Options *o, const char *host)
{
int i;
- char vbuf[5];
+ char buf[8];
/* This is normally prepared in ssh_kex2 */
if (kex_assemble_names(KEX_DEFAULT_PK_ALG, &o->hostkeyalgorithms) != 0)
@@ -2359,6 +2549,7 @@ dump_client_config(Options *o, const char *host)
dump_cfg_fmtint(oCompression, o->compression);
dump_cfg_fmtint(oControlMaster, o->control_master);
dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
+ 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);
@@ -2407,6 +2598,7 @@ dump_client_config(Options *o, const char *host)
dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
dump_cfg_string(oHostKeyAlias, o->host_key_alias);
dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types);
+ dump_cfg_string(oIdentityAgent, o->identity_agent);
dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX);
dump_cfg_string(oLocalCommand, o->local_command);
@@ -2414,7 +2606,6 @@ dump_client_config(Options *o, const char *host)
dump_cfg_string(oMacs, o->macs ? o->macs : KEX_CLIENT_MAC);
dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
- dump_cfg_string(oProxyCommand, o->proxy_command);
dump_cfg_string(oPubkeyAcceptedKeyTypes, o->pubkey_key_types);
dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
dump_cfg_string(oXAuthLocation, o->xauth_location);
@@ -2475,8 +2666,8 @@ dump_client_config(Options *o, const char *host)
if (o->escape_char == SSH_ESCAPECHAR_NONE)
printf("escapechar none\n");
else {
- vis(vbuf, o->escape_char, VIS_WHITE, 0);
- printf("escapechar %s\n", vbuf);
+ vis(buf, o->escape_char, VIS_WHITE, 0);
+ printf("escapechar %s\n", buf);
}
/* oIPQoS */
@@ -2490,4 +2681,30 @@ dump_client_config(Options *o, const char *host)
/* oStreamLocalBindMask */
printf("streamlocalbindmask 0%o\n",
o->fwd_opts.streamlocal_bind_mask);
+
+ /* oProxyCommand / oProxyJump */
+ if (o->jump_host == NULL)
+ dump_cfg_string(oProxyCommand, o->proxy_command);
+ else {
+ /* Check for numeric addresses */
+ i = strchr(o->jump_host, ':') != NULL ||
+ strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
+ snprintf(buf, sizeof(buf), "%d", o->jump_port);
+ printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
+ /* optional additional jump spec */
+ o->jump_extra == NULL ? "" : o->jump_extra,
+ o->jump_extra == NULL ? "" : ",",
+ /* optional user */
+ o->jump_user == NULL ? "" : o->jump_user,
+ o->jump_user == NULL ? "" : "@",
+ /* opening [ if hostname is numeric */
+ i ? "[" : "",
+ /* mandatory hostname */
+ o->jump_host,
+ /* closing ] if hostname is numeric */
+ i ? "]" : "",
+ /* optional port number */
+ o->jump_port <= 0 ? "" : ":",
+ o->jump_port <= 0 ? "" : buf);
+ }
}
OpenPOWER on IntegriCloud