upstream commit
Include directive for ssh_config(5); feedback & ok markus@ Upstream-ID: ae3b76e2e343322b9f74acde6f1e1c5f027d5fff
This commit is contained in:
parent
85bdcd7c92
commit
dc7990be86
116
readconf.c
116
readconf.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: readconf.c,v 1.251 2016/04/06 06:42:17 djm Exp $ */
|
/* $OpenBSD: readconf.c,v 1.252 2016/04/15 00:30:19 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -39,6 +39,11 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#ifdef USE_SYSTEM_GLOB
|
||||||
|
# include <glob.h>
|
||||||
|
#else
|
||||||
|
# include "openbsd-compat/glob.h"
|
||||||
|
#endif
|
||||||
#ifdef HAVE_UTIL_H
|
#ifdef HAVE_UTIL_H
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -125,11 +130,18 @@
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
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. */
|
/* Keyword tokens. */
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
oBadOption,
|
oBadOption,
|
||||||
oHost, oMatch,
|
oHost, oMatch, oInclude,
|
||||||
oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
|
oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
|
||||||
oGatewayPorts, oExitOnForwardFailure,
|
oGatewayPorts, oExitOnForwardFailure,
|
||||||
oPasswordAuthentication, oRSAAuthentication,
|
oPasswordAuthentication, oRSAAuthentication,
|
||||||
|
@ -258,6 +270,7 @@ static struct {
|
||||||
{ "controlmaster", oControlMaster },
|
{ "controlmaster", oControlMaster },
|
||||||
{ "controlpersist", oControlPersist },
|
{ "controlpersist", oControlPersist },
|
||||||
{ "hashknownhosts", oHashKnownHosts },
|
{ "hashknownhosts", oHashKnownHosts },
|
||||||
|
{ "include", oInclude },
|
||||||
{ "tunnel", oTunnel },
|
{ "tunnel", oTunnel },
|
||||||
{ "tunneldevice", oTunnelDevice },
|
{ "tunneldevice", oTunnelDevice },
|
||||||
{ "localcommand", oLocalCommand },
|
{ "localcommand", oLocalCommand },
|
||||||
|
@ -783,22 +796,32 @@ static const struct multistate multistate_canonicalizehostname[] = {
|
||||||
* Processes a single option line as used in the configuration files. This
|
* Processes a single option line as used in the configuration files. This
|
||||||
* only sets those values that have not already been set.
|
* only sets those values that have not already been set.
|
||||||
*/
|
*/
|
||||||
#define WHITESPACE " \t\r\n"
|
|
||||||
int
|
int
|
||||||
process_config_line(Options *options, struct passwd *pw, const char *host,
|
process_config_line(Options *options, struct passwd *pw, const char *host,
|
||||||
const char *original_host, char *line, const char *filename,
|
const char *original_host, char *line, const char *filename,
|
||||||
int linenum, int *activep, int flags)
|
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 *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
|
||||||
char **cpptr, fwdarg[256];
|
char **cpptr, fwdarg[256];
|
||||||
u_int i, *uintptr, max_entries = 0;
|
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;
|
LogLevel *log_level_ptr;
|
||||||
long long val64;
|
long long val64;
|
||||||
size_t len;
|
size_t len;
|
||||||
struct Forward fwd;
|
struct Forward fwd;
|
||||||
const struct multistate *multistate_ptr;
|
const struct multistate *multistate_ptr;
|
||||||
struct allowed_cname *cname;
|
struct allowed_cname *cname;
|
||||||
|
glob_t gl;
|
||||||
|
|
||||||
if (activep == NULL) { /* We are processing a command line directive */
|
if (activep == NULL) { /* We are processing a command line directive */
|
||||||
cmdline = 1;
|
cmdline = 1;
|
||||||
|
@ -1258,6 +1281,8 @@ parse_keytypes:
|
||||||
*activep = 0;
|
*activep = 0;
|
||||||
arg2 = NULL;
|
arg2 = NULL;
|
||||||
while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
|
while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
|
||||||
|
if ((flags & SSHCONF_NEVERMATCH) != 0)
|
||||||
|
break;
|
||||||
negated = *arg == '!';
|
negated = *arg == '!';
|
||||||
if (negated)
|
if (negated)
|
||||||
arg++;
|
arg++;
|
||||||
|
@ -1290,7 +1315,7 @@ parse_keytypes:
|
||||||
if (value < 0)
|
if (value < 0)
|
||||||
fatal("%.200s line %d: Bad Match condition", filename,
|
fatal("%.200s line %d: Bad Match condition", filename,
|
||||||
linenum);
|
linenum);
|
||||||
*activep = value;
|
*activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case oEscapeChar:
|
case oEscapeChar:
|
||||||
|
@ -1418,6 +1443,63 @@ parse_keytypes:
|
||||||
intptr = &options->visual_host_key;
|
intptr = &options->visual_host_key;
|
||||||
goto parse_flag;
|
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:
|
case oIPQoS:
|
||||||
arg = strdelim(&s);
|
arg = strdelim(&s);
|
||||||
if ((value = parse_ipqos(arg)) == -1)
|
if ((value = parse_ipqos(arg)) == -1)
|
||||||
|
@ -1576,22 +1658,35 @@ parse_keytypes:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reads the config file and modifies the options accordingly. Options
|
* Reads the config file and modifies the options accordingly. Options
|
||||||
* should already be initialized before this call. This never returns if
|
* should already be initialized before this call. This never returns if
|
||||||
* there is an error. If the file does not exist, this returns 0.
|
* there is an error. If the file does not exist, this returns 0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
read_config_file(const char *filename, struct passwd *pw, const char *host,
|
read_config_file(const char *filename, struct passwd *pw, const char *host,
|
||||||
const char *original_host, Options *options, int flags)
|
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;
|
FILE *f;
|
||||||
char line[1024];
|
char line[1024];
|
||||||
int active, linenum;
|
int linenum;
|
||||||
int bad_options = 0;
|
int bad_options = 0;
|
||||||
|
|
||||||
|
if (depth < 0 || depth > READCONF_MAX_DEPTH)
|
||||||
|
fatal("Too many recursive configuration includes");
|
||||||
|
|
||||||
if ((f = fopen(filename, "r")) == NULL)
|
if ((f = fopen(filename, "r")) == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -1611,13 +1706,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
|
* Mark that we are now processing the options. This flag is turned
|
||||||
* on/off by Host specifications.
|
* on/off by Host specifications.
|
||||||
*/
|
*/
|
||||||
active = 1;
|
|
||||||
linenum = 0;
|
linenum = 0;
|
||||||
while (fgets(line, sizeof(line), f)) {
|
while (fgets(line, sizeof(line), f)) {
|
||||||
/* Update line number counter. */
|
/* Update line number counter. */
|
||||||
linenum++;
|
linenum++;
|
||||||
if (process_config_line(options, pw, host, original_host,
|
if (process_config_line_depth(options, pw, host, original_host,
|
||||||
line, filename, linenum, &active, flags) != 0)
|
line, filename, linenum, activep, flags, depth) != 0)
|
||||||
bad_options++;
|
bad_options++;
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: readconf.h,v 1.113 2016/01/14 16:17:40 markus Exp $ */
|
/* $OpenBSD: readconf.h,v 1.114 2016/04/15 00:30:19 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
|
@ -179,6 +179,7 @@ typedef struct {
|
||||||
#define SSHCONF_CHECKPERM 1 /* check permissions on config file */
|
#define SSHCONF_CHECKPERM 1 /* check permissions on config file */
|
||||||
#define SSHCONF_USERCONF 2 /* user provided config file not system */
|
#define SSHCONF_USERCONF 2 /* user provided config file not system */
|
||||||
#define SSHCONF_POSTCANON 4 /* After hostname canonicalisation */
|
#define SSHCONF_POSTCANON 4 /* After hostname canonicalisation */
|
||||||
|
#define SSHCONF_NEVERMATCH 8 /* Match/Host never matches; internal only */
|
||||||
|
|
||||||
#define SSH_UPDATE_HOSTKEYS_NO 0
|
#define SSH_UPDATE_HOSTKEYS_NO 0
|
||||||
#define SSH_UPDATE_HOSTKEYS_YES 1
|
#define SSH_UPDATE_HOSTKEYS_YES 1
|
||||||
|
|
5
ssh.1
5
ssh.1
|
@ -33,8 +33,8 @@
|
||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.\" $OpenBSD: ssh.1,v 1.369 2016/02/17 07:38:19 jmc Exp $
|
.\" $OpenBSD: ssh.1,v 1.370 2016/04/15 00:30:19 djm Exp $
|
||||||
.Dd $Mdocdate: February 17 2016 $
|
.Dd $Mdocdate: April 15 2016 $
|
||||||
.Dt SSH 1
|
.Dt SSH 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -503,6 +503,7 @@ For full details of the options listed below, and their possible values, see
|
||||||
.It HostName
|
.It HostName
|
||||||
.It IdentityFile
|
.It IdentityFile
|
||||||
.It IdentitiesOnly
|
.It IdentitiesOnly
|
||||||
|
.It Include
|
||||||
.It IPQoS
|
.It IPQoS
|
||||||
.It KbdInteractiveAuthentication
|
.It KbdInteractiveAuthentication
|
||||||
.It KbdInteractiveDevices
|
.It KbdInteractiveDevices
|
||||||
|
|
23
ssh_config.5
23
ssh_config.5
|
@ -33,8 +33,8 @@
|
||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.\" $OpenBSD: ssh_config.5,v 1.228 2016/02/20 23:01:46 sobrado Exp $
|
.\" $OpenBSD: ssh_config.5,v 1.229 2016/04/15 00:30:19 djm Exp $
|
||||||
.Dd $Mdocdate: February 20 2016 $
|
.Dd $Mdocdate: April 15 2016 $
|
||||||
.Dt SSH_CONFIG 5
|
.Dt SSH_CONFIG 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -1019,6 +1019,25 @@ It is recommended that
|
||||||
.Cm IgnoreUnknown
|
.Cm IgnoreUnknown
|
||||||
be listed early in the configuration file as it will not be applied
|
be listed early in the configuration file as it will not be applied
|
||||||
to unknown options that appear before it.
|
to unknown options that appear before it.
|
||||||
|
.It Cm Include
|
||||||
|
Include the specified configuration file(s).
|
||||||
|
Multiple path names may be specified and each pathname may contain
|
||||||
|
.Xr glob 3
|
||||||
|
wildcards and, for user configurations, shell-like
|
||||||
|
.Dq ~
|
||||||
|
references to user home directories.
|
||||||
|
Files without absolute paths are assumed to be in
|
||||||
|
.Pa ~/.ssh
|
||||||
|
if included in a user configurations file or
|
||||||
|
.Pa /etc/ssh
|
||||||
|
if included from the system configuration file.
|
||||||
|
.Cm Include
|
||||||
|
directive may appear inside a
|
||||||
|
.Cm Match
|
||||||
|
or
|
||||||
|
.Cm Host
|
||||||
|
block
|
||||||
|
to perform conditional inclusion.
|
||||||
.It Cm IPQoS
|
.It Cm IPQoS
|
||||||
Specifies the IPv4 type-of-service or DSCP class for connections.
|
Specifies the IPv4 type-of-service or DSCP class for connections.
|
||||||
Accepted values are
|
Accepted values are
|
||||||
|
|
Loading…
Reference in New Issue