|
|
d7ff6e |
diff -up openssh-8.0p1/auth.c.sshdinclude openssh-8.0p1/auth.c
|
|
|
d7ff6e |
--- openssh-8.0p1/auth.c.sshdinclude 2021-10-20 15:18:49.740331098 +0200
|
|
|
d7ff6e |
+++ openssh-8.0p1/auth.c 2021-10-20 15:19:41.324781344 +0200
|
|
|
d7ff6e |
@@ -80,6 +80,7 @@
|
|
|
d7ff6e |
|
|
|
d7ff6e |
/* import */
|
|
|
d7ff6e |
extern ServerOptions options;
|
|
|
d7ff6e |
+extern struct include_list includes;
|
|
|
d7ff6e |
extern int use_privsep;
|
|
|
d7ff6e |
extern struct sshbuf *loginmsg;
|
|
|
d7ff6e |
extern struct passwd *privsep_pw;
|
|
|
d7ff6e |
@@ -573,7 +574,7 @@ getpwnamallow(struct ssh *ssh, const cha
|
|
|
d7ff6e |
|
|
|
d7ff6e |
ci = get_connection_info(ssh, 1, options.use_dns);
|
|
|
d7ff6e |
ci->user = user;
|
|
|
d7ff6e |
- parse_server_match_config(&options, ci);
|
|
|
d7ff6e |
+ parse_server_match_config(&options, &includes, ci);
|
|
|
d7ff6e |
log_change_level(options.log_level);
|
|
|
d7ff6e |
process_permitopen(ssh, &options);
|
|
|
d7ff6e |
|
|
|
d7ff6e |
diff -up openssh-8.0p1/readconf.c.sshdinclude openssh-8.0p1/readconf.c
|
|
|
d7ff6e |
--- openssh-8.0p1/readconf.c.sshdinclude 2021-10-20 15:21:43.541848103 +0200
|
|
|
d7ff6e |
+++ openssh-8.0p1/readconf.c 2021-10-20 15:22:06.302046768 +0200
|
|
|
d7ff6e |
@@ -711,7 +711,7 @@ match_cfg_line(Options *options, char **
|
|
|
d7ff6e |
static void
|
|
|
d7ff6e |
rm_env(Options *options, const char *arg, const char *filename, int linenum)
|
|
|
d7ff6e |
{
|
|
|
d7ff6e |
- int i, j;
|
|
|
d7ff6e |
+ int i, j, onum_send_env = options->num_send_env;
|
|
|
d7ff6e |
char *cp;
|
|
|
d7ff6e |
|
|
|
d7ff6e |
/* Remove an environment variable */
|
|
|
d7ff6e |
@@ -734,6 +734,11 @@ rm_env(Options *options, const char *arg
|
|
|
d7ff6e |
options->num_send_env--;
|
|
|
d7ff6e |
/* NB. don't increment i */
|
|
|
d7ff6e |
}
|
|
|
d7ff6e |
+ if (onum_send_env != options->num_send_env) {
|
|
|
d7ff6e |
+ options->send_env = xrecallocarray(options->send_env,
|
|
|
d7ff6e |
+ onum_send_env, options->num_send_env,
|
|
|
d7ff6e |
+ sizeof(*options->send_env));
|
|
|
d7ff6e |
+ }
|
|
|
d7ff6e |
}
|
|
|
d7ff6e |
|
|
|
d7ff6e |
/*
|
|
|
d7ff6e |
diff -up openssh-8.0p1/regress/Makefile.sshdinclude openssh-8.0p1/regress/Makefile
|
|
|
d7ff6e |
--- openssh-8.0p1/regress/Makefile.sshdinclude 2021-10-20 15:18:49.742331115 +0200
|
|
|
d7ff6e |
+++ openssh-8.0p1/regress/Makefile 2021-10-20 15:19:41.324781344 +0200
|
|
|
d7ff6e |
@@ -82,6 +82,7 @@ LTESTS= connect \
|
|
|
d7ff6e |
principals-command \
|
|
|
d7ff6e |
cert-file \
|
|
|
d7ff6e |
cfginclude \
|
|
|
d7ff6e |
+ servcfginclude \
|
|
|
d7ff6e |
allow-deny-users \
|
|
|
d7ff6e |
authinfo
|
|
|
d7ff6e |
|
|
|
d7ff6e |
@@ -118,7 +119,7 @@ CLEANFILES= *.core actual agent-key.* au
|
|
|
d7ff6e |
sftp-server.sh sftp.log ssh-log-wrapper.sh ssh.log \
|
|
|
d7ff6e |
ssh_config ssh_config.* ssh_proxy ssh_proxy_bak \
|
|
|
d7ff6e |
ssh_proxy_envpass sshd.log sshd_config sshd_config_minimal \
|
|
|
d7ff6e |
- sshd_config.orig sshd_proxy sshd_proxy.* sshd_proxy_bak \
|
|
|
d7ff6e |
+ sshd_config.* sshd_proxy sshd_proxy.* sshd_proxy_bak \
|
|
|
d7ff6e |
sshd_proxy_orig t10.out t10.out.pub t12.out t12.out.pub \
|
|
|
d7ff6e |
t2.out t3.out t6.out1 t6.out2 t7.out t7.out.pub \
|
|
|
d7ff6e |
t8.out t8.out.pub t9.out t9.out.pub testdata \
|
|
|
d7ff6e |
diff -up openssh-8.0p1/regress/servcfginclude.sh.sshdinclude openssh-8.0p1/regress/servcfginclude.sh
|
|
|
d7ff6e |
--- openssh-8.0p1/regress/servcfginclude.sh.sshdinclude 2021-10-20 15:18:49.744331132 +0200
|
|
|
d7ff6e |
+++ openssh-8.0p1/regress/servcfginclude.sh 2021-10-20 15:22:06.303046777 +0200
|
|
|
d7ff6e |
@@ -0,0 +1,188 @@
|
|
|
d7ff6e |
+# Placed in the Public Domain.
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+tid="server config include"
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+cat > $OBJ/sshd_config.i << _EOF
|
|
|
d7ff6e |
+HostKey $OBJ/host.ssh-ed25519
|
|
|
d7ff6e |
+Match host a
|
|
|
d7ff6e |
+ Banner /aa
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+Match host b
|
|
|
d7ff6e |
+ Banner /bb
|
|
|
d7ff6e |
+ Include $OBJ/sshd_config.i.*
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+Match host c
|
|
|
d7ff6e |
+ Include $OBJ/sshd_config.i.*
|
|
|
d7ff6e |
+ Banner /cc
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+Match host m
|
|
|
d7ff6e |
+ Include $OBJ/sshd_config.i.*
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+Match Host d
|
|
|
d7ff6e |
+ Banner /dd
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+Match Host e
|
|
|
d7ff6e |
+ Banner /ee
|
|
|
d7ff6e |
+ Include $OBJ/sshd_config.i.*
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+Match Host f
|
|
|
d7ff6e |
+ Include $OBJ/sshd_config.i.*
|
|
|
d7ff6e |
+ Banner /ff
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+Match Host n
|
|
|
d7ff6e |
+ Include $OBJ/sshd_config.i.*
|
|
|
d7ff6e |
+_EOF
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+cat > $OBJ/sshd_config.i.0 << _EOF
|
|
|
d7ff6e |
+Match host xxxxxx
|
|
|
d7ff6e |
+_EOF
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+cat > $OBJ/sshd_config.i.1 << _EOF
|
|
|
d7ff6e |
+Match host a
|
|
|
d7ff6e |
+ Banner /aaa
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+Match host b
|
|
|
d7ff6e |
+ Banner /bbb
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+Match host c
|
|
|
d7ff6e |
+ Banner /ccc
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+Match Host d
|
|
|
d7ff6e |
+ Banner /ddd
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+Match Host e
|
|
|
d7ff6e |
+ Banner /eee
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+Match Host f
|
|
|
d7ff6e |
+ Banner /fff
|
|
|
d7ff6e |
+_EOF
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+cat > $OBJ/sshd_config.i.2 << _EOF
|
|
|
d7ff6e |
+Match host a
|
|
|
d7ff6e |
+ Banner /aaaa
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+Match host b
|
|
|
d7ff6e |
+ Banner /bbbb
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+Match host c
|
|
|
d7ff6e |
+ Banner /cccc
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+Match Host d
|
|
|
d7ff6e |
+ Banner /dddd
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+Match Host e
|
|
|
d7ff6e |
+ Banner /eeee
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+Match Host f
|
|
|
d7ff6e |
+ Banner /ffff
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+Match all
|
|
|
d7ff6e |
+ Banner /xxxx
|
|
|
d7ff6e |
+_EOF
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+trial() {
|
|
|
d7ff6e |
+ _host="$1"
|
|
|
d7ff6e |
+ _exp="$2"
|
|
|
d7ff6e |
+ _desc="$3"
|
|
|
d7ff6e |
+ test -z "$_desc" && _desc="test match"
|
|
|
d7ff6e |
+ trace "$_desc host=$_host expect=$_exp"
|
|
|
d7ff6e |
+ ${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i -T \
|
|
|
d7ff6e |
+ -C "host=$_host,user=test,addr=127.0.0.1" > $OBJ/sshd_config.out ||
|
|
|
d7ff6e |
+ fatal "ssh config parse failed: $_desc host=$_host expect=$_exp"
|
|
|
d7ff6e |
+ _got=`grep -i '^banner ' $OBJ/sshd_config.out | awk '{print $2}'`
|
|
|
d7ff6e |
+ if test "x$_exp" != "x$_got" ; then
|
|
|
d7ff6e |
+ fail "$desc_ host $_host include fail: expected $_exp got $_got"
|
|
|
d7ff6e |
+ fi
|
|
|
d7ff6e |
+}
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+trial a /aa
|
|
|
d7ff6e |
+trial b /bb
|
|
|
d7ff6e |
+trial c /ccc
|
|
|
d7ff6e |
+trial d /dd
|
|
|
d7ff6e |
+trial e /ee
|
|
|
d7ff6e |
+trial f /fff
|
|
|
d7ff6e |
+trial m /xxxx
|
|
|
d7ff6e |
+trial n /xxxx
|
|
|
d7ff6e |
+trial x none
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+# Prepare an included config with an error.
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+cat > $OBJ/sshd_config.i.3 << _EOF
|
|
|
d7ff6e |
+Banner xxxx
|
|
|
d7ff6e |
+ Junk
|
|
|
d7ff6e |
+_EOF
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+trace "disallow invalid config host=a"
|
|
|
d7ff6e |
+${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i \
|
|
|
d7ff6e |
+ -C "host=a,user=test,addr=127.0.0.1" 2>/dev/null && \
|
|
|
d7ff6e |
+ fail "sshd include allowed invalid config"
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+trace "disallow invalid config host=x"
|
|
|
d7ff6e |
+${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i \
|
|
|
d7ff6e |
+ -C "host=x,user=test,addr=127.0.0.1" 2>/dev/null && \
|
|
|
d7ff6e |
+ fail "sshd include allowed invalid config"
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+rm -f $OBJ/sshd_config.i.*
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+# Ensure that a missing include is not fatal.
|
|
|
d7ff6e |
+cat > $OBJ/sshd_config.i << _EOF
|
|
|
d7ff6e |
+HostKey $OBJ/host.ssh-ed25519
|
|
|
d7ff6e |
+Include $OBJ/sshd_config.i.*
|
|
|
d7ff6e |
+Banner /aa
|
|
|
d7ff6e |
+_EOF
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+trial a /aa "missing include non-fatal"
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+# Ensure that Match/Host in an included config does not affect parent.
|
|
|
d7ff6e |
+cat > $OBJ/sshd_config.i.x << _EOF
|
|
|
d7ff6e |
+Match host x
|
|
|
d7ff6e |
+_EOF
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+trial a /aa "included file does not affect match state"
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+# Ensure the empty include directive is not accepted
|
|
|
d7ff6e |
+cat > $OBJ/sshd_config.i.x << _EOF
|
|
|
d7ff6e |
+Include
|
|
|
d7ff6e |
+_EOF
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+trace "disallow invalid with no argument"
|
|
|
d7ff6e |
+${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i.x -T \
|
|
|
d7ff6e |
+ -C "host=x,user=test,addr=127.0.0.1" 2>/dev/null && \
|
|
|
d7ff6e |
+ fail "sshd allowed Include with no argument"
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+# Ensure the Include before any Match block works as expected (bug #3122)
|
|
|
d7ff6e |
+cat > $OBJ/sshd_config.i << _EOF
|
|
|
d7ff6e |
+Banner /xx
|
|
|
d7ff6e |
+HostKey $OBJ/host.ssh-ed25519
|
|
|
d7ff6e |
+Include $OBJ/sshd_config.i.2
|
|
|
d7ff6e |
+Match host a
|
|
|
d7ff6e |
+ Banner /aaaa
|
|
|
d7ff6e |
+_EOF
|
|
|
d7ff6e |
+cat > $OBJ/sshd_config.i.2 << _EOF
|
|
|
d7ff6e |
+Match host a
|
|
|
d7ff6e |
+ Banner /aa
|
|
|
d7ff6e |
+_EOF
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+trace "Include before match blocks"
|
|
|
d7ff6e |
+trial a /aa "included file before match blocks is properly evaluated"
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+# Port in included file is correctly interpretted (bug #3169)
|
|
|
d7ff6e |
+cat > $OBJ/sshd_config.i << _EOF
|
|
|
d7ff6e |
+Include $OBJ/sshd_config.i.2
|
|
|
d7ff6e |
+Port 7722
|
|
|
d7ff6e |
+_EOF
|
|
|
d7ff6e |
+cat > $OBJ/sshd_config.i.2 << _EOF
|
|
|
d7ff6e |
+HostKey $OBJ/host.ssh-ed25519
|
|
|
d7ff6e |
+_EOF
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+trace "Port after included files"
|
|
|
d7ff6e |
+${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i -T \
|
|
|
d7ff6e |
+ -C "host=x,user=test,addr=127.0.0.1" > $OBJ/sshd_config.out || \
|
|
|
d7ff6e |
+ fail "failed to parse Port after included files"
|
|
|
d7ff6e |
+_port=`grep -i '^port ' $OBJ/sshd_config.out | awk '{print $2}'`
|
|
|
d7ff6e |
+if test "x7722" != "x$_port" ; then
|
|
|
d7ff6e |
+ fail "The Port in included file was intertepretted wrongly. Expected 7722, got $_port"
|
|
|
d7ff6e |
+fi
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+# cleanup
|
|
|
d7ff6e |
+rm -f $OBJ/sshd_config.i $OBJ/sshd_config.i.* $OBJ/sshd_config.out
|
|
|
d7ff6e |
diff -up openssh-8.0p1/regress/test-exec.sh.sshdinclude openssh-8.0p1/regress/test-exec.sh
|
|
|
d7ff6e |
--- openssh-8.0p1/regress/test-exec.sh.sshdinclude 2021-10-20 15:18:49.746331150 +0200
|
|
|
d7ff6e |
+++ openssh-8.0p1/regress/test-exec.sh 2021-10-20 15:19:41.324781344 +0200
|
|
|
d7ff6e |
@@ -220,6 +220,7 @@ echo "exec ${SSH} -E${TEST_SSH_LOGFILE}
|
|
|
d7ff6e |
|
|
|
d7ff6e |
chmod a+rx $OBJ/ssh-log-wrapper.sh
|
|
|
d7ff6e |
REAL_SSH="$SSH"
|
|
|
d7ff6e |
+REAL_SSHD="$SSHD"
|
|
|
d7ff6e |
SSH="$SSHLOGWRAP"
|
|
|
d7ff6e |
|
|
|
d7ff6e |
# Some test data. We make a copy because some tests will overwrite it.
|
|
|
d7ff6e |
diff -up openssh-8.0p1/servconf.c.sshdinclude openssh-8.0p1/servconf.c
|
|
|
d7ff6e |
--- openssh-8.0p1/servconf.c.sshdinclude 2021-10-20 15:18:49.748331167 +0200
|
|
|
d7ff6e |
+++ openssh-8.0p1/servconf.c 2021-10-20 15:22:06.303046777 +0200
|
|
|
d7ff6e |
@@ -40,6 +40,11 @@
|
|
|
d7ff6e |
#ifdef HAVE_UTIL_H
|
|
|
d7ff6e |
#include <util.h>
|
|
|
d7ff6e |
#endif
|
|
|
d7ff6e |
+#ifdef USE_SYSTEM_GLOB
|
|
|
d7ff6e |
+# include <glob.h>
|
|
|
d7ff6e |
+#else
|
|
|
d7ff6e |
+# include "openbsd-compat/glob.h"
|
|
|
d7ff6e |
+#endif
|
|
|
d7ff6e |
|
|
|
d7ff6e |
#include "openbsd-compat/sys-queue.h"
|
|
|
d7ff6e |
#include "xmalloc.h"
|
|
|
d7ff6e |
@@ -70,6 +75,9 @@ static void add_listen_addr(ServerOption
|
|
|
d7ff6e |
const char *, int);
|
|
|
d7ff6e |
static void add_one_listen_addr(ServerOptions *, const char *,
|
|
|
d7ff6e |
const char *, int);
|
|
|
d7ff6e |
+static void parse_server_config_depth(ServerOptions *options,
|
|
|
d7ff6e |
+ const char *filename, struct sshbuf *conf, struct include_list *includes,
|
|
|
d7ff6e |
+ struct connection_info *connectinfo, int flags, int *activep, int depth);
|
|
|
d7ff6e |
|
|
|
d7ff6e |
/* Use of privilege separation or not */
|
|
|
d7ff6e |
extern int use_privsep;
|
|
|
d7ff6e |
@@ -528,7 +536,7 @@ typedef enum {
|
|
|
d7ff6e |
sAcceptEnv, sSetEnv, sPermitTunnel,
|
|
|
d7ff6e |
sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,
|
|
|
d7ff6e |
sUsePrivilegeSeparation, sAllowAgentForwarding,
|
|
|
d7ff6e |
- sHostCertificate,
|
|
|
d7ff6e |
+ sHostCertificate, sInclude,
|
|
|
d7ff6e |
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
|
|
|
d7ff6e |
sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser,
|
|
|
d7ff6e |
sKexAlgorithms, sCASignatureAlgorithms, sIPQoS, sVersionAddendum,
|
|
|
d7ff6e |
@@ -540,9 +548,11 @@ typedef enum {
|
|
|
d7ff6e |
sDeprecated, sIgnore, sUnsupported
|
|
|
d7ff6e |
} ServerOpCodes;
|
|
|
d7ff6e |
|
|
|
d7ff6e |
-#define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */
|
|
|
d7ff6e |
-#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */
|
|
|
d7ff6e |
-#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH)
|
|
|
d7ff6e |
+#define SSHCFG_GLOBAL 0x01 /* allowed in main section of config */
|
|
|
d7ff6e |
+#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */
|
|
|
d7ff6e |
+#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH)
|
|
|
d7ff6e |
+#define SSHCFG_NEVERMATCH 0x04 /* Match never matches; internal only */
|
|
|
d7ff6e |
+#define SSHCFG_MATCH_ONLY 0x08 /* Match only in conditional blocks; internal only */
|
|
|
d7ff6e |
|
|
|
d7ff6e |
/* Textual representation of the tokens. */
|
|
|
d7ff6e |
static struct {
|
|
|
d7ff6e |
@@ -687,6 +697,7 @@ static struct {
|
|
|
d7ff6e |
{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
|
|
|
d7ff6e |
{ "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
|
|
|
d7ff6e |
{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL },
|
|
|
d7ff6e |
+ { "include", sInclude, SSHCFG_ALL },
|
|
|
d7ff6e |
{ "ipqos", sIPQoS, SSHCFG_ALL },
|
|
|
d7ff6e |
{ "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL },
|
|
|
d7ff6e |
{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
|
|
|
d7ff6e |
@@ -1259,13 +1270,14 @@ static const struct multistate multistat
|
|
|
d7ff6e |
{ NULL, -1 }
|
|
|
d7ff6e |
};
|
|
|
d7ff6e |
|
|
|
d7ff6e |
-int
|
|
|
d7ff6e |
-process_server_config_line(ServerOptions *options, char *line,
|
|
|
d7ff6e |
+static int
|
|
|
d7ff6e |
+process_server_config_line_depth(ServerOptions *options, char *line,
|
|
|
d7ff6e |
const char *filename, int linenum, int *activep,
|
|
|
d7ff6e |
- struct connection_info *connectinfo)
|
|
|
d7ff6e |
+ struct connection_info *connectinfo, int *inc_flags, int depth,
|
|
|
d7ff6e |
+ struct include_list *includes)
|
|
|
d7ff6e |
{
|
|
|
d7ff6e |
char ch, *cp, ***chararrayptr, **charptr, *arg, *arg2, *p;
|
|
|
d7ff6e |
- int cmdline = 0, *intptr, value, value2, n, port;
|
|
|
d7ff6e |
+ int cmdline = 0, *intptr, value, value2, n, port, oactive, r, found;
|
|
|
d7ff6e |
SyslogFacility *log_facility_ptr;
|
|
|
d7ff6e |
LogLevel *log_level_ptr;
|
|
|
d7ff6e |
ServerOpCodes opcode;
|
|
|
d7ff6e |
@@ -1274,6 +1286,8 @@ process_server_config_line(ServerOptions
|
|
|
d7ff6e |
long long val64;
|
|
|
d7ff6e |
const struct multistate *multistate_ptr;
|
|
|
d7ff6e |
const char *errstr;
|
|
|
d7ff6e |
+ struct include_item *item;
|
|
|
d7ff6e |
+ glob_t gbuf;
|
|
|
d7ff6e |
|
|
|
d7ff6e |
/* Strip trailing whitespace. Allow \f (form feed) at EOL only */
|
|
|
d7ff6e |
if ((len = strlen(line)) == 0)
|
|
|
d7ff6e |
@@ -1300,7 +1314,7 @@ process_server_config_line(ServerOptions
|
|
|
d7ff6e |
cmdline = 1;
|
|
|
d7ff6e |
activep = &cmdline;
|
|
|
d7ff6e |
}
|
|
|
d7ff6e |
- if (*activep && opcode != sMatch)
|
|
|
d7ff6e |
+ if (*activep && opcode != sMatch && opcode != sInclude)
|
|
|
d7ff6e |
debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
|
|
|
d7ff6e |
if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
|
|
|
d7ff6e |
if (connectinfo == NULL) {
|
|
|
d7ff6e |
@@ -1980,15 +1994,112 @@ process_server_config_line(ServerOptions
|
|
|
d7ff6e |
*intptr = value;
|
|
|
d7ff6e |
break;
|
|
|
d7ff6e |
|
|
|
d7ff6e |
+ case sInclude:
|
|
|
d7ff6e |
+ if (cmdline) {
|
|
|
d7ff6e |
+ fatal("Include directive not supported as a "
|
|
|
d7ff6e |
+ "command-line option");
|
|
|
d7ff6e |
+ }
|
|
|
d7ff6e |
+ value = 0;
|
|
|
d7ff6e |
+ while ((arg2 = strdelim(&cp)) != NULL && *arg2 != '\0') {
|
|
|
d7ff6e |
+ value++;
|
|
|
d7ff6e |
+ found = 0;
|
|
|
d7ff6e |
+ if (*arg2 != '/' && *arg2 != '~') {
|
|
|
d7ff6e |
+ xasprintf(&arg, "%s/%s", SSHDIR, arg2);
|
|
|
d7ff6e |
+ } else
|
|
|
d7ff6e |
+ arg = xstrdup(arg2);
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+ /*
|
|
|
d7ff6e |
+ * Don't let included files clobber the containing
|
|
|
d7ff6e |
+ * file's Match state.
|
|
|
d7ff6e |
+ */
|
|
|
d7ff6e |
+ oactive = *activep;
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+ /* consult cache of include files */
|
|
|
d7ff6e |
+ TAILQ_FOREACH(item, includes, entry) {
|
|
|
d7ff6e |
+ if (strcmp(item->selector, arg) != 0)
|
|
|
d7ff6e |
+ continue;
|
|
|
d7ff6e |
+ if (item->filename != NULL) {
|
|
|
d7ff6e |
+ parse_server_config_depth(options,
|
|
|
d7ff6e |
+ item->filename, item->contents,
|
|
|
d7ff6e |
+ includes, connectinfo,
|
|
|
d7ff6e |
+ (*inc_flags & SSHCFG_MATCH_ONLY
|
|
|
d7ff6e |
+ ? SSHCFG_MATCH_ONLY : (oactive
|
|
|
d7ff6e |
+ ? 0 : SSHCFG_NEVERMATCH)),
|
|
|
d7ff6e |
+ activep, depth + 1);
|
|
|
d7ff6e |
+ }
|
|
|
d7ff6e |
+ found = 1;
|
|
|
d7ff6e |
+ *activep = oactive;
|
|
|
d7ff6e |
+ }
|
|
|
d7ff6e |
+ if (found != 0) {
|
|
|
d7ff6e |
+ free(arg);
|
|
|
d7ff6e |
+ continue;
|
|
|
d7ff6e |
+ }
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+ /* requested glob was not in cache */
|
|
|
d7ff6e |
+ debug2("%s line %d: new include %s",
|
|
|
d7ff6e |
+ filename, linenum, arg);
|
|
|
d7ff6e |
+ if ((r = glob(arg, 0, NULL, &gbuf)) != 0) {
|
|
|
d7ff6e |
+ if (r != GLOB_NOMATCH) {
|
|
|
d7ff6e |
+ fatal("%s line %d: include \"%s\" "
|
|
|
d7ff6e |
+ "glob failed", filename,
|
|
|
d7ff6e |
+ linenum, arg);
|
|
|
d7ff6e |
+ }
|
|
|
d7ff6e |
+ /*
|
|
|
d7ff6e |
+ * If no entry matched then record a
|
|
|
d7ff6e |
+ * placeholder to skip later glob calls.
|
|
|
d7ff6e |
+ */
|
|
|
d7ff6e |
+ debug2("%s line %d: no match for %s",
|
|
|
d7ff6e |
+ filename, linenum, arg);
|
|
|
d7ff6e |
+ item = xcalloc(1, sizeof(*item));
|
|
|
d7ff6e |
+ item->selector = strdup(arg);
|
|
|
d7ff6e |
+ TAILQ_INSERT_TAIL(includes,
|
|
|
d7ff6e |
+ item, entry);
|
|
|
d7ff6e |
+ }
|
|
|
d7ff6e |
+ if (gbuf.gl_pathc > INT_MAX)
|
|
|
d7ff6e |
+ fatal("%s: too many glob results", __func__);
|
|
|
d7ff6e |
+ for (n = 0; n < (int)gbuf.gl_pathc; n++) {
|
|
|
d7ff6e |
+ debug2("%s line %d: including %s",
|
|
|
d7ff6e |
+ filename, linenum, gbuf.gl_pathv[n]);
|
|
|
d7ff6e |
+ item = xcalloc(1, sizeof(*item));
|
|
|
d7ff6e |
+ item->selector = strdup(arg);
|
|
|
d7ff6e |
+ item->filename = strdup(gbuf.gl_pathv[n]);
|
|
|
d7ff6e |
+ if ((item->contents = sshbuf_new()) == NULL) {
|
|
|
d7ff6e |
+ fatal("%s: sshbuf_new failed",
|
|
|
d7ff6e |
+ __func__);
|
|
|
d7ff6e |
+ }
|
|
|
d7ff6e |
+ load_server_config(item->filename,
|
|
|
d7ff6e |
+ item->contents);
|
|
|
d7ff6e |
+ parse_server_config_depth(options,
|
|
|
d7ff6e |
+ item->filename, item->contents,
|
|
|
d7ff6e |
+ includes, connectinfo,
|
|
|
d7ff6e |
+ (*inc_flags & SSHCFG_MATCH_ONLY
|
|
|
d7ff6e |
+ ? SSHCFG_MATCH_ONLY : (oactive
|
|
|
d7ff6e |
+ ? 0 : SSHCFG_NEVERMATCH)),
|
|
|
d7ff6e |
+ activep, depth + 1);
|
|
|
d7ff6e |
+ *activep = oactive;
|
|
|
d7ff6e |
+ TAILQ_INSERT_TAIL(includes, item, entry);
|
|
|
d7ff6e |
+ }
|
|
|
d7ff6e |
+ globfree(&gbuf);
|
|
|
d7ff6e |
+ free(arg);
|
|
|
d7ff6e |
+ }
|
|
|
d7ff6e |
+ if (value == 0) {
|
|
|
d7ff6e |
+ fatal("%s line %d: Include missing filename argument",
|
|
|
d7ff6e |
+ filename, linenum);
|
|
|
d7ff6e |
+ }
|
|
|
d7ff6e |
+ break;
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
case sMatch:
|
|
|
d7ff6e |
if (cmdline)
|
|
|
d7ff6e |
fatal("Match directive not supported as a command-line "
|
|
|
d7ff6e |
"option");
|
|
|
d7ff6e |
- value = match_cfg_line(&cp, linenum, connectinfo);
|
|
|
d7ff6e |
+ value = match_cfg_line(&cp, linenum,
|
|
|
d7ff6e |
+ (*inc_flags & SSHCFG_NEVERMATCH ? NULL : connectinfo));
|
|
|
d7ff6e |
if (value < 0)
|
|
|
d7ff6e |
fatal("%s line %d: Bad Match condition", filename,
|
|
|
d7ff6e |
linenum);
|
|
|
d7ff6e |
- *activep = value;
|
|
|
d7ff6e |
+ *activep = (*inc_flags & SSHCFG_NEVERMATCH) ? 0 : value;
|
|
|
d7ff6e |
+ /* The MATCH_ONLY is applicable only until the first match block */
|
|
|
d7ff6e |
+ *inc_flags &= ~SSHCFG_MATCH_ONLY;
|
|
|
d7ff6e |
break;
|
|
|
d7ff6e |
|
|
|
d7ff6e |
case sKerberosUseKuserok:
|
|
|
d7ff6e |
@@ -2275,6 +2386,18 @@ process_server_config_line(ServerOptions
|
|
|
d7ff6e |
return 0;
|
|
|
d7ff6e |
}
|
|
|
d7ff6e |
|
|
|
d7ff6e |
+int
|
|
|
d7ff6e |
+process_server_config_line(ServerOptions *options, char *line,
|
|
|
d7ff6e |
+ const char *filename, int linenum, int *activep,
|
|
|
d7ff6e |
+ struct connection_info *connectinfo, struct include_list *includes)
|
|
|
d7ff6e |
+{
|
|
|
d7ff6e |
+ int inc_flags = 0;
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+ return process_server_config_line_depth(options, line, filename,
|
|
|
d7ff6e |
+ linenum, activep, connectinfo, &inc_flags, 0, includes);
|
|
|
d7ff6e |
+}
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
/* Reads the server configuration file. */
|
|
|
d7ff6e |
|
|
|
d7ff6e |
void
|
|
|
d7ff6e |
@@ -2313,12 +2436,13 @@ load_server_config(const char *filename,
|
|
|
d7ff6e |
|
|
|
d7ff6e |
void
|
|
|
d7ff6e |
parse_server_match_config(ServerOptions *options,
|
|
|
d7ff6e |
- struct connection_info *connectinfo)
|
|
|
d7ff6e |
+ struct include_list *includes, struct connection_info *connectinfo)
|
|
|
d7ff6e |
{
|
|
|
d7ff6e |
ServerOptions mo;
|
|
|
d7ff6e |
|
|
|
d7ff6e |
initialize_server_options(&mo);
|
|
|
d7ff6e |
- parse_server_config(&mo, "reprocess config", cfg, connectinfo);
|
|
|
d7ff6e |
+ parse_server_config(&mo, "reprocess config", cfg, includes,
|
|
|
d7ff6e |
+ connectinfo);
|
|
|
d7ff6e |
copy_set_server_options(options, &mo, 0);
|
|
|
d7ff6e |
}
|
|
|
d7ff6e |
|
|
|
d7ff6e |
@@ -2464,28 +2588,44 @@ copy_set_server_options(ServerOptions *d
|
|
|
d7ff6e |
#undef M_CP_STROPT
|
|
|
d7ff6e |
#undef M_CP_STRARRAYOPT
|
|
|
d7ff6e |
|
|
|
d7ff6e |
-void
|
|
|
d7ff6e |
-parse_server_config(ServerOptions *options, const char *filename,
|
|
|
d7ff6e |
- struct sshbuf *conf, struct connection_info *connectinfo)
|
|
|
d7ff6e |
+#define SERVCONF_MAX_DEPTH 16
|
|
|
d7ff6e |
+static void
|
|
|
d7ff6e |
+parse_server_config_depth(ServerOptions *options, const char *filename,
|
|
|
d7ff6e |
+ struct sshbuf *conf, struct include_list *includes,
|
|
|
d7ff6e |
+ struct connection_info *connectinfo, int flags, int *activep, int depth)
|
|
|
d7ff6e |
{
|
|
|
d7ff6e |
- int active, linenum, bad_options = 0;
|
|
|
d7ff6e |
+ int linenum, bad_options = 0;
|
|
|
d7ff6e |
char *cp, *obuf, *cbuf;
|
|
|
d7ff6e |
|
|
|
d7ff6e |
- debug2("%s: config %s len %zu", __func__, filename, sshbuf_len(conf));
|
|
|
d7ff6e |
+ if (depth < 0 || depth > SERVCONF_MAX_DEPTH)
|
|
|
d7ff6e |
+ fatal("Too many recursive configuration includes");
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+ debug2("%s: config %s len %zu%s", __func__, filename, sshbuf_len(conf),
|
|
|
d7ff6e |
+ (flags & SSHCFG_NEVERMATCH ? " [checking syntax only]" : ""));
|
|
|
d7ff6e |
|
|
|
d7ff6e |
if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL)
|
|
|
d7ff6e |
fatal("%s: sshbuf_dup_string failed", __func__);
|
|
|
d7ff6e |
- active = connectinfo ? 0 : 1;
|
|
|
d7ff6e |
linenum = 1;
|
|
|
d7ff6e |
while ((cp = strsep(&cbuf, "\n")) != NULL) {
|
|
|
d7ff6e |
- if (process_server_config_line(options, cp, filename,
|
|
|
d7ff6e |
- linenum++, &active, connectinfo) != 0)
|
|
|
d7ff6e |
+ if (process_server_config_line_depth(options, cp,
|
|
|
d7ff6e |
+ filename, linenum++, activep, connectinfo, &flags,
|
|
|
d7ff6e |
+ depth, includes) != 0)
|
|
|
d7ff6e |
bad_options++;
|
|
|
d7ff6e |
}
|
|
|
d7ff6e |
free(obuf);
|
|
|
d7ff6e |
if (bad_options > 0)
|
|
|
d7ff6e |
fatal("%s: terminating, %d bad configuration options",
|
|
|
d7ff6e |
filename, bad_options);
|
|
|
d7ff6e |
+}
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+void
|
|
|
d7ff6e |
+parse_server_config(ServerOptions *options, const char *filename,
|
|
|
d7ff6e |
+ struct sshbuf *conf, struct include_list *includes,
|
|
|
d7ff6e |
+ struct connection_info *connectinfo)
|
|
|
d7ff6e |
+{
|
|
|
d7ff6e |
+ int active = connectinfo ? 0 : 1;
|
|
|
d7ff6e |
+ parse_server_config_depth(options, filename, conf, includes,
|
|
|
d7ff6e |
+ connectinfo, (connectinfo ? SSHCFG_MATCH_ONLY : 0), &active, 0);
|
|
|
d7ff6e |
process_queued_listen_addrs(options);
|
|
|
d7ff6e |
}
|
|
|
d7ff6e |
|
|
|
d7ff6e |
diff -up openssh-8.0p1/servconf.h.sshdinclude openssh-8.0p1/servconf.h
|
|
|
d7ff6e |
--- openssh-8.0p1/servconf.h.sshdinclude 2021-10-20 15:18:49.750331185 +0200
|
|
|
d7ff6e |
+++ openssh-8.0p1/servconf.h 2021-10-20 15:19:41.325781353 +0200
|
|
|
d7ff6e |
@@ -16,6 +16,8 @@
|
|
|
d7ff6e |
#ifndef SERVCONF_H
|
|
|
d7ff6e |
#define SERVCONF_H
|
|
|
d7ff6e |
|
|
|
d7ff6e |
+#include <sys/queue.h>
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
#define MAX_PORTS 256 /* Max # ports. */
|
|
|
d7ff6e |
|
|
|
d7ff6e |
#define MAX_SUBSYSTEMS 256 /* Max # subsystems. */
|
|
|
d7ff6e |
@@ -234,6 +236,15 @@ struct connection_info {
|
|
|
d7ff6e |
* unspecified */
|
|
|
d7ff6e |
};
|
|
|
d7ff6e |
|
|
|
d7ff6e |
+/* List of included files for re-exec from the parsed configuration */
|
|
|
d7ff6e |
+struct include_item {
|
|
|
d7ff6e |
+ char *selector;
|
|
|
d7ff6e |
+ char *filename;
|
|
|
d7ff6e |
+ struct sshbuf *contents;
|
|
|
d7ff6e |
+ TAILQ_ENTRY(include_item) entry;
|
|
|
d7ff6e |
+};
|
|
|
d7ff6e |
+TAILQ_HEAD(include_list, include_item);
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
|
|
|
d7ff6e |
/*
|
|
|
d7ff6e |
* These are string config options that must be copied between the
|
|
|
d7ff6e |
@@ -273,12 +284,13 @@ struct connection_info *get_connection_i
|
|
|
d7ff6e |
void initialize_server_options(ServerOptions *);
|
|
|
d7ff6e |
void fill_default_server_options(ServerOptions *);
|
|
|
d7ff6e |
int process_server_config_line(ServerOptions *, char *, const char *, int,
|
|
|
d7ff6e |
- int *, struct connection_info *);
|
|
|
d7ff6e |
+ int *, struct connection_info *, struct include_list *includes);
|
|
|
d7ff6e |
void process_permitopen(struct ssh *ssh, ServerOptions *options);
|
|
|
d7ff6e |
void load_server_config(const char *, struct sshbuf *);
|
|
|
d7ff6e |
void parse_server_config(ServerOptions *, const char *, struct sshbuf *,
|
|
|
d7ff6e |
- struct connection_info *);
|
|
|
d7ff6e |
-void parse_server_match_config(ServerOptions *, struct connection_info *);
|
|
|
d7ff6e |
+ struct include_list *includes, struct connection_info *);
|
|
|
d7ff6e |
+void parse_server_match_config(ServerOptions *,
|
|
|
d7ff6e |
+ struct include_list *includes, struct connection_info *);
|
|
|
d7ff6e |
int parse_server_match_testspec(struct connection_info *, char *);
|
|
|
d7ff6e |
int server_match_spec_complete(struct connection_info *);
|
|
|
d7ff6e |
void copy_set_server_options(ServerOptions *, ServerOptions *, int);
|
|
|
d7ff6e |
diff -up openssh-8.0p1/sshd_config.5.sshdinclude openssh-8.0p1/sshd_config.5
|
|
|
d7ff6e |
--- openssh-8.0p1/sshd_config.5.sshdinclude 2021-10-20 15:18:49.754331220 +0200
|
|
|
d7ff6e |
+++ openssh-8.0p1/sshd_config.5 2021-10-20 15:19:41.325781353 +0200
|
|
|
d7ff6e |
@@ -825,7 +825,20 @@ during
|
|
|
d7ff6e |
and use only the system-wide known hosts file
|
|
|
d7ff6e |
.Pa /etc/ssh/known_hosts .
|
|
|
d7ff6e |
The default is
|
|
|
d7ff6e |
-.Cm no .
|
|
|
d7ff6e |
+.Dq no .
|
|
|
d7ff6e |
+.It Cm Include
|
|
|
d7ff6e |
+Include the specified configuration file(s).
|
|
|
d7ff6e |
+Multiple path names may be specified and each pathname may contain
|
|
|
d7ff6e |
+.Xr glob 7
|
|
|
d7ff6e |
+wildcards.
|
|
|
d7ff6e |
+Files without absolute paths are assumed to be in
|
|
|
d7ff6e |
+.Pa /etc/ssh .
|
|
|
d7ff6e |
+A
|
|
|
d7ff6e |
+.Cm Include
|
|
|
d7ff6e |
+directive may appear inside a
|
|
|
d7ff6e |
+.Cm Match
|
|
|
d7ff6e |
+block
|
|
|
d7ff6e |
+to perform conditional inclusion.
|
|
|
d7ff6e |
.It Cm IPQoS
|
|
|
d7ff6e |
Specifies the IPv4 type-of-service or DSCP class for the connection.
|
|
|
d7ff6e |
Accepted values are
|
|
|
d7ff6e |
diff -up openssh-8.0p1/sshd.c.sshdinclude openssh-8.0p1/sshd.c
|
|
|
d7ff6e |
--- openssh-8.0p1/sshd.c.sshdinclude 2021-10-20 15:18:49.752331202 +0200
|
|
|
d7ff6e |
+++ openssh-8.0p1/sshd.c 2021-10-20 15:19:41.325781353 +0200
|
|
|
d7ff6e |
@@ -257,6 +257,9 @@ struct sshauthopt *auth_opts = NULL;
|
|
|
d7ff6e |
/* sshd_config buffer */
|
|
|
d7ff6e |
struct sshbuf *cfg;
|
|
|
d7ff6e |
|
|
|
d7ff6e |
+/* Included files from the configuration file */
|
|
|
d7ff6e |
+struct include_list includes = TAILQ_HEAD_INITIALIZER(includes);
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
/* message to be displayed after login */
|
|
|
d7ff6e |
struct sshbuf *loginmsg;
|
|
|
d7ff6e |
|
|
|
d7ff6e |
@@ -927,30 +930,45 @@ usage(void)
|
|
|
d7ff6e |
static void
|
|
|
d7ff6e |
send_rexec_state(int fd, struct sshbuf *conf)
|
|
|
d7ff6e |
{
|
|
|
d7ff6e |
- struct sshbuf *m;
|
|
|
d7ff6e |
+ struct sshbuf *m = NULL, *inc = NULL;
|
|
|
d7ff6e |
+ struct include_item *item = NULL;
|
|
|
d7ff6e |
int r;
|
|
|
d7ff6e |
|
|
|
d7ff6e |
debug3("%s: entering fd = %d config len %zu", __func__, fd,
|
|
|
d7ff6e |
sshbuf_len(conf));
|
|
|
d7ff6e |
|
|
|
d7ff6e |
+ if ((m = sshbuf_new()) == NULL || (inc = sshbuf_new()) == NULL)
|
|
|
d7ff6e |
+ fatal("%s: sshbuf_new failed", __func__);
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+ /* pack includes into a string */
|
|
|
d7ff6e |
+ TAILQ_FOREACH(item, &includes, entry) {
|
|
|
d7ff6e |
+ if ((r = sshbuf_put_cstring(inc, item->selector)) != 0 ||
|
|
|
d7ff6e |
+ (r = sshbuf_put_cstring(inc, item->filename)) != 0 ||
|
|
|
d7ff6e |
+ (r = sshbuf_put_stringb(inc, item->contents)) != 0)
|
|
|
d7ff6e |
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
|
d7ff6e |
+ }
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
/*
|
|
|
d7ff6e |
* Protocol from reexec master to child:
|
|
|
d7ff6e |
* string configuration
|
|
|
d7ff6e |
- * string rngseed (only if OpenSSL is not self-seeded)
|
|
|
d7ff6e |
+ * string included_files[] {
|
|
|
d7ff6e |
+ * string selector
|
|
|
d7ff6e |
+ * string filename
|
|
|
d7ff6e |
+ * string contents
|
|
|
d7ff6e |
+ * }
|
|
|
d7ff6e |
+ * string rng_seed (if required)
|
|
|
d7ff6e |
*/
|
|
|
d7ff6e |
- if ((m = sshbuf_new()) == NULL)
|
|
|
d7ff6e |
- fatal("%s: sshbuf_new failed", __func__);
|
|
|
d7ff6e |
- if ((r = sshbuf_put_stringb(m, conf)) != 0)
|
|
|
d7ff6e |
+ if ((r = sshbuf_put_stringb(m, conf)) != 0 ||
|
|
|
d7ff6e |
+ (r = sshbuf_put_stringb(m, inc)) != 0)
|
|
|
d7ff6e |
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
|
d7ff6e |
-
|
|
|
d7ff6e |
#if defined(WITH_OPENSSL) && !defined(OPENSSL_PRNG_ONLY)
|
|
|
d7ff6e |
rexec_send_rng_seed(m);
|
|
|
d7ff6e |
#endif
|
|
|
d7ff6e |
-
|
|
|
d7ff6e |
if (ssh_msg_send(fd, 0, m) == -1)
|
|
|
d7ff6e |
fatal("%s: ssh_msg_send failed", __func__);
|
|
|
d7ff6e |
|
|
|
d7ff6e |
sshbuf_free(m);
|
|
|
d7ff6e |
+ sshbuf_free(inc);
|
|
|
d7ff6e |
|
|
|
d7ff6e |
debug3("%s: done", __func__);
|
|
|
d7ff6e |
}
|
|
|
d7ff6e |
@@ -958,14 +976,15 @@ send_rexec_state(int fd, struct sshbuf *
|
|
|
d7ff6e |
static void
|
|
|
d7ff6e |
recv_rexec_state(int fd, struct sshbuf *conf)
|
|
|
d7ff6e |
{
|
|
|
d7ff6e |
- struct sshbuf *m;
|
|
|
d7ff6e |
+ struct sshbuf *m, *inc;
|
|
|
d7ff6e |
u_char *cp, ver;
|
|
|
d7ff6e |
size_t len;
|
|
|
d7ff6e |
int r;
|
|
|
d7ff6e |
+ struct include_item *item;
|
|
|
d7ff6e |
|
|
|
d7ff6e |
debug3("%s: entering fd = %d", __func__, fd);
|
|
|
d7ff6e |
|
|
|
d7ff6e |
- if ((m = sshbuf_new()) == NULL)
|
|
|
d7ff6e |
+ if ((m = sshbuf_new()) == NULL || (inc = sshbuf_new()) == NULL)
|
|
|
d7ff6e |
fatal("%s: sshbuf_new failed", __func__);
|
|
|
d7ff6e |
if (ssh_msg_recv(fd, m) == -1)
|
|
|
d7ff6e |
fatal("%s: ssh_msg_recv failed", __func__);
|
|
|
d7ff6e |
@@ -973,14 +992,28 @@ recv_rexec_state(int fd, struct sshbuf *
|
|
|
d7ff6e |
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
|
d7ff6e |
if (ver != 0)
|
|
|
d7ff6e |
fatal("%s: rexec version mismatch", __func__);
|
|
|
d7ff6e |
- if ((r = sshbuf_get_string(m, &cp, &len)) != 0)
|
|
|
d7ff6e |
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
|
d7ff6e |
- if (conf != NULL && (r = sshbuf_put(conf, cp, len)))
|
|
|
d7ff6e |
+ if ((r = sshbuf_get_string(m, &cp, &len)) != 0 ||
|
|
|
d7ff6e |
+ (r = sshbuf_get_stringb(m, inc)) != 0)
|
|
|
d7ff6e |
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
#if defined(WITH_OPENSSL) && !defined(OPENSSL_PRNG_ONLY)
|
|
|
d7ff6e |
rexec_recv_rng_seed(m);
|
|
|
d7ff6e |
#endif
|
|
|
d7ff6e |
|
|
|
d7ff6e |
+ if (conf != NULL && (r = sshbuf_put(conf, cp, len)))
|
|
|
d7ff6e |
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
+ while (sshbuf_len(inc) != 0) {
|
|
|
d7ff6e |
+ item = xcalloc(1, sizeof(*item));
|
|
|
d7ff6e |
+ if ((item->contents = sshbuf_new()) == NULL)
|
|
|
d7ff6e |
+ fatal("%s: sshbuf_new failed", __func__);
|
|
|
d7ff6e |
+ if ((r = sshbuf_get_cstring(inc, &item->selector, NULL)) != 0 ||
|
|
|
d7ff6e |
+ (r = sshbuf_get_cstring(inc, &item->filename, NULL)) != 0 ||
|
|
|
d7ff6e |
+ (r = sshbuf_get_stringb(inc, item->contents)) != 0)
|
|
|
d7ff6e |
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
|
d7ff6e |
+ TAILQ_INSERT_TAIL(&includes, item, entry);
|
|
|
d7ff6e |
+ }
|
|
|
d7ff6e |
+
|
|
|
d7ff6e |
free(cp);
|
|
|
d7ff6e |
sshbuf_free(m);
|
|
|
d7ff6e |
|
|
|
d7ff6e |
@@ -1661,7 +1694,7 @@ main(int ac, char **av)
|
|
|
d7ff6e |
case 'o':
|
|
|
d7ff6e |
line = xstrdup(optarg);
|
|
|
d7ff6e |
if (process_server_config_line(&options, line,
|
|
|
d7ff6e |
- "command-line", 0, NULL, NULL) != 0)
|
|
|
d7ff6e |
+ "command-line", 0, NULL, NULL, &includes) != 0)
|
|
|
d7ff6e |
exit(1);
|
|
|
d7ff6e |
free(line);
|
|
|
d7ff6e |
break;
|
|
|
d7ff6e |
@@ -1692,7 +1725,7 @@ main(int ac, char **av)
|
|
|
d7ff6e |
SYSLOG_LEVEL_INFO : options.log_level,
|
|
|
d7ff6e |
options.log_facility == SYSLOG_FACILITY_NOT_SET ?
|
|
|
d7ff6e |
SYSLOG_FACILITY_AUTH : options.log_facility,
|
|
|
d7ff6e |
- log_stderr || !inetd_flag);
|
|
|
d7ff6e |
+ log_stderr || !inetd_flag || debug_flag);
|
|
|
d7ff6e |
|
|
|
d7ff6e |
/*
|
|
|
d7ff6e |
* Unset KRB5CCNAME, otherwise the user's session may inherit it from
|
|
|
d7ff6e |
@@ -1725,12 +1758,11 @@ main(int ac, char **av)
|
|
|
d7ff6e |
*/
|
|
|
d7ff6e |
(void)atomicio(vwrite, startup_pipe, "\0", 1);
|
|
|
d7ff6e |
}
|
|
|
d7ff6e |
- }
|
|
|
d7ff6e |
- else if (strcasecmp(config_file_name, "none") != 0)
|
|
|
d7ff6e |
+ } else if (strcasecmp(config_file_name, "none") != 0)
|
|
|
d7ff6e |
load_server_config(config_file_name, cfg);
|
|
|
d7ff6e |
|
|
|
d7ff6e |
parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
|
|
|
d7ff6e |
- cfg, NULL);
|
|
|
d7ff6e |
+ cfg, &includes, NULL);
|
|
|
d7ff6e |
|
|
|
d7ff6e |
/* 'UsePAM no' is not supported in Fedora */
|
|
|
d7ff6e |
if (! options.use_pam)
|
|
|
d7ff6e |
@@ -1946,7 +1978,7 @@ main(int ac, char **av)
|
|
|
d7ff6e |
if (connection_info == NULL)
|
|
|
d7ff6e |
connection_info = get_connection_info(ssh, 0, 0);
|
|
|
d7ff6e |
connection_info->test = 1;
|
|
|
d7ff6e |
- parse_server_match_config(&options, connection_info);
|
|
|
d7ff6e |
+ parse_server_match_config(&options, &includes, connection_info);
|
|
|
d7ff6e |
dump_config(&options);
|
|
|
d7ff6e |
}
|
|
|
d7ff6e |
|