mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-07-28 16:24:39 +02:00
upstream: Add a StdinNull directive to ssh_config(5) that allows
the config file to do the same thing as -n does on the ssh(1) commandline. Patch from Volker Diels-Grabsch via GHPR231; ok dtucker OpenBSD-Commit-ID: 66ddf3f15c76796d4dcd22ff464aed1edd62468e
This commit is contained in:
parent
e3957e21ff
commit
e0c5088f1c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: clientloop.c,v 1.367 2021/07/16 09:00:23 djm Exp $ */
|
/* $OpenBSD: clientloop.c,v 1.368 2021/07/23 04:00:59 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
|
||||||
@ -115,9 +115,6 @@
|
|||||||
/* import options */
|
/* import options */
|
||||||
extern Options options;
|
extern Options options;
|
||||||
|
|
||||||
/* Flag indicating that stdin should be redirected from /dev/null. */
|
|
||||||
extern int stdin_null_flag;
|
|
||||||
|
|
||||||
/* Flag indicating that ssh should daemonise after authentication is complete */
|
/* Flag indicating that ssh should daemonise after authentication is complete */
|
||||||
extern int fork_after_authentication_flag;
|
extern int fork_after_authentication_flag;
|
||||||
|
|
||||||
|
7
mux.c
7
mux.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: mux.c,v 1.90 2021/07/13 23:48:36 djm Exp $ */
|
/* $OpenBSD: mux.c,v 1.91 2021/07/23 04:00:59 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
|
* Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
|
||||||
*
|
*
|
||||||
@ -71,7 +71,6 @@
|
|||||||
/* from ssh.c */
|
/* from ssh.c */
|
||||||
extern int tty_flag;
|
extern int tty_flag;
|
||||||
extern Options options;
|
extern Options options;
|
||||||
extern int stdin_null_flag;
|
|
||||||
extern char *host;
|
extern char *host;
|
||||||
extern struct sshbuf *command;
|
extern struct sshbuf *command;
|
||||||
extern volatile sig_atomic_t quit_pending;
|
extern volatile sig_atomic_t quit_pending;
|
||||||
@ -1879,7 +1878,7 @@ mux_client_request_session(int fd)
|
|||||||
|
|
||||||
ssh_signal(SIGPIPE, SIG_IGN);
|
ssh_signal(SIGPIPE, SIG_IGN);
|
||||||
|
|
||||||
if (stdin_null_flag && stdfd_devnull(1, 0, 0) == -1)
|
if (options.stdin_null && stdfd_devnull(1, 0, 0) == -1)
|
||||||
fatal_f("stdfd_devnull failed");
|
fatal_f("stdfd_devnull failed");
|
||||||
|
|
||||||
if ((term = lookup_env_in_list("TERM", options.setenv,
|
if ((term = lookup_env_in_list("TERM", options.setenv,
|
||||||
@ -2102,7 +2101,7 @@ mux_client_request_stdio_fwd(int fd)
|
|||||||
|
|
||||||
ssh_signal(SIGPIPE, SIG_IGN);
|
ssh_signal(SIGPIPE, SIG_IGN);
|
||||||
|
|
||||||
if (stdin_null_flag && stdfd_devnull(1, 0, 0) == -1)
|
if (options.stdin_null && stdfd_devnull(1, 0, 0) == -1)
|
||||||
fatal_f("stdfd_devnull failed");
|
fatal_f("stdfd_devnull failed");
|
||||||
|
|
||||||
if ((m = sshbuf_new()) == NULL)
|
if ((m = sshbuf_new()) == NULL)
|
||||||
|
13
readconf.c
13
readconf.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: readconf.c,v 1.359 2021/07/13 23:48:36 djm Exp $ */
|
/* $OpenBSD: readconf.c,v 1.360 2021/07/23 04:00:59 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
|
||||||
@ -167,7 +167,7 @@ typedef enum {
|
|||||||
oTunnel, oTunnelDevice,
|
oTunnel, oTunnelDevice,
|
||||||
oLocalCommand, oPermitLocalCommand, oRemoteCommand,
|
oLocalCommand, oPermitLocalCommand, oRemoteCommand,
|
||||||
oVisualHostKey,
|
oVisualHostKey,
|
||||||
oKexAlgorithms, oIPQoS, oRequestTTY, oSessionType,
|
oKexAlgorithms, oIPQoS, oRequestTTY, oSessionType, oStdinNull,
|
||||||
oIgnoreUnknown, oProxyUseFdpass,
|
oIgnoreUnknown, oProxyUseFdpass,
|
||||||
oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
|
oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
|
||||||
oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
|
oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
|
||||||
@ -299,6 +299,7 @@ static struct {
|
|||||||
{ "ipqos", oIPQoS },
|
{ "ipqos", oIPQoS },
|
||||||
{ "requesttty", oRequestTTY },
|
{ "requesttty", oRequestTTY },
|
||||||
{ "sessiontype", oSessionType },
|
{ "sessiontype", oSessionType },
|
||||||
|
{ "stdinnull", oStdinNull },
|
||||||
{ "proxyusefdpass", oProxyUseFdpass },
|
{ "proxyusefdpass", oProxyUseFdpass },
|
||||||
{ "canonicaldomains", oCanonicalDomains },
|
{ "canonicaldomains", oCanonicalDomains },
|
||||||
{ "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
|
{ "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
|
||||||
@ -1954,6 +1955,10 @@ parse_pubkey_algos:
|
|||||||
multistate_ptr = multistate_sessiontype;
|
multistate_ptr = multistate_sessiontype;
|
||||||
goto parse_multistate;
|
goto parse_multistate;
|
||||||
|
|
||||||
|
case oStdinNull:
|
||||||
|
intptr = &options->stdin_null;
|
||||||
|
goto parse_flag;
|
||||||
|
|
||||||
case oIgnoreUnknown:
|
case oIgnoreUnknown:
|
||||||
charptr = &options->ignored_unknown;
|
charptr = &options->ignored_unknown;
|
||||||
goto parse_string;
|
goto parse_string;
|
||||||
@ -2377,6 +2382,7 @@ initialize_options(Options * options)
|
|||||||
options->ip_qos_bulk = -1;
|
options->ip_qos_bulk = -1;
|
||||||
options->request_tty = -1;
|
options->request_tty = -1;
|
||||||
options->session_type = -1;
|
options->session_type = -1;
|
||||||
|
options->stdin_null = -1;
|
||||||
options->proxy_use_fdpass = -1;
|
options->proxy_use_fdpass = -1;
|
||||||
options->ignored_unknown = NULL;
|
options->ignored_unknown = NULL;
|
||||||
options->num_canonical_domains = 0;
|
options->num_canonical_domains = 0;
|
||||||
@ -2565,6 +2571,8 @@ fill_default_options(Options * options)
|
|||||||
options->request_tty = REQUEST_TTY_AUTO;
|
options->request_tty = REQUEST_TTY_AUTO;
|
||||||
if (options->session_type == -1)
|
if (options->session_type == -1)
|
||||||
options->session_type = SESSION_TYPE_DEFAULT;
|
options->session_type = SESSION_TYPE_DEFAULT;
|
||||||
|
if (options->stdin_null == -1)
|
||||||
|
options->stdin_null = 0;
|
||||||
if (options->proxy_use_fdpass == -1)
|
if (options->proxy_use_fdpass == -1)
|
||||||
options->proxy_use_fdpass = 0;
|
options->proxy_use_fdpass = 0;
|
||||||
if (options->canonicalize_max_dots == -1)
|
if (options->canonicalize_max_dots == -1)
|
||||||
@ -3243,6 +3251,7 @@ dump_client_config(Options *o, const char *host)
|
|||||||
dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
|
dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
|
||||||
dump_cfg_fmtint(oRequestTTY, o->request_tty);
|
dump_cfg_fmtint(oRequestTTY, o->request_tty);
|
||||||
dump_cfg_fmtint(oSessionType, o->session_type);
|
dump_cfg_fmtint(oSessionType, o->session_type);
|
||||||
|
dump_cfg_fmtint(oStdinNull, o->stdin_null);
|
||||||
dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
|
dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
|
||||||
dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
|
dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
|
||||||
dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
|
dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: readconf.h,v 1.142 2021/07/13 23:48:36 djm Exp $ */
|
/* $OpenBSD: readconf.h,v 1.143 2021/07/23 04:00:59 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
@ -147,6 +147,7 @@ typedef struct {
|
|||||||
|
|
||||||
int request_tty;
|
int request_tty;
|
||||||
int session_type;
|
int session_type;
|
||||||
|
int stdin_null;
|
||||||
|
|
||||||
int proxy_use_fdpass;
|
int proxy_use_fdpass;
|
||||||
|
|
||||||
|
10
ssh.1
10
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.422 2021/07/13 23:48:36 djm Exp $
|
.\" $OpenBSD: ssh.1,v 1.423 2021/07/23 04:00:59 djm Exp $
|
||||||
.Dd $Mdocdate: July 13 2021 $
|
.Dd $Mdocdate: July 23 2021 $
|
||||||
.Dt SSH 1
|
.Dt SSH 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -451,6 +451,11 @@ program will be put in the background.
|
|||||||
needs to ask for a password or passphrase; see also the
|
needs to ask for a password or passphrase; see also the
|
||||||
.Fl f
|
.Fl f
|
||||||
option.)
|
option.)
|
||||||
|
Refer to the description of
|
||||||
|
.Cm StdinNull
|
||||||
|
in
|
||||||
|
.Xr ssh_config 5
|
||||||
|
for details.
|
||||||
.Pp
|
.Pp
|
||||||
.It Fl O Ar ctl_cmd
|
.It Fl O Ar ctl_cmd
|
||||||
Control an active connection multiplexing master process.
|
Control an active connection multiplexing master process.
|
||||||
@ -553,6 +558,7 @@ For full details of the options listed below, and their possible values, see
|
|||||||
.It ServerAliveCountMax
|
.It ServerAliveCountMax
|
||||||
.It SessionType
|
.It SessionType
|
||||||
.It SetEnv
|
.It SetEnv
|
||||||
|
.It StdinNull
|
||||||
.It StreamLocalBindMask
|
.It StreamLocalBindMask
|
||||||
.It StreamLocalBindUnlink
|
.It StreamLocalBindUnlink
|
||||||
.It StrictHostKeyChecking
|
.It StrictHostKeyChecking
|
||||||
|
22
ssh.c
22
ssh.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh.c,v 1.562 2021/07/17 00:38:11 djm Exp $ */
|
/* $OpenBSD: ssh.c,v 1.563 2021/07/23 04:00:59 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
|
||||||
@ -126,12 +126,6 @@ int debug_flag = 0;
|
|||||||
/* Flag indicating whether a tty should be requested */
|
/* Flag indicating whether a tty should be requested */
|
||||||
int tty_flag = 0;
|
int tty_flag = 0;
|
||||||
|
|
||||||
/*
|
|
||||||
* Flag indicating that nothing should be read from stdin. This can be set
|
|
||||||
* on the command line.
|
|
||||||
*/
|
|
||||||
int stdin_null_flag = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flag indicating that the current process should be backgrounded and
|
* Flag indicating that the current process should be backgrounded and
|
||||||
* a new mux-client launched in the foreground for ControlPersist.
|
* a new mux-client launched in the foreground for ControlPersist.
|
||||||
@ -723,11 +717,11 @@ main(int ac, char **av)
|
|||||||
options.address_family = AF_INET6;
|
options.address_family = AF_INET6;
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
stdin_null_flag = 1;
|
options.stdin_null = 1;
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
fork_after_authentication_flag = 1;
|
fork_after_authentication_flag = 1;
|
||||||
stdin_null_flag = 1;
|
options.stdin_null = 1;
|
||||||
break;
|
break;
|
||||||
case 'x':
|
case 'x':
|
||||||
options.forward_x11 = 0;
|
options.forward_x11 = 0;
|
||||||
@ -1357,7 +1351,7 @@ main(int ac, char **av)
|
|||||||
(muxclient_command && muxclient_command != SSHMUX_COMMAND_PROXY))
|
(muxclient_command && muxclient_command != SSHMUX_COMMAND_PROXY))
|
||||||
tty_flag = 0;
|
tty_flag = 0;
|
||||||
/* Do not allocate a tty if stdin is not a tty. */
|
/* Do not allocate a tty if stdin is not a tty. */
|
||||||
if ((!isatty(fileno(stdin)) || stdin_null_flag) &&
|
if ((!isatty(fileno(stdin)) || options.stdin_null) &&
|
||||||
options.request_tty != REQUEST_TTY_FORCE) {
|
options.request_tty != REQUEST_TTY_FORCE) {
|
||||||
if (tty_flag)
|
if (tty_flag)
|
||||||
logit("Pseudo-terminal will not be allocated because "
|
logit("Pseudo-terminal will not be allocated because "
|
||||||
@ -1734,7 +1728,7 @@ control_persist_detach(void)
|
|||||||
default:
|
default:
|
||||||
/* Parent: set up mux client to connect to backgrounded master */
|
/* Parent: set up mux client to connect to backgrounded master */
|
||||||
debug2_f("background process is %ld", (long)pid);
|
debug2_f("background process is %ld", (long)pid);
|
||||||
stdin_null_flag = ostdin_null_flag;
|
options.stdin_null = ostdin_null_flag;
|
||||||
options.request_tty = orequest_tty;
|
options.request_tty = orequest_tty;
|
||||||
tty_flag = otty_flag;
|
tty_flag = otty_flag;
|
||||||
options.session_type = osession_type;
|
options.session_type = osession_type;
|
||||||
@ -2075,7 +2069,7 @@ ssh_session2_open(struct ssh *ssh)
|
|||||||
Channel *c;
|
Channel *c;
|
||||||
int window, packetmax, in, out, err;
|
int window, packetmax, in, out, err;
|
||||||
|
|
||||||
if (stdin_null_flag) {
|
if (options.stdin_null) {
|
||||||
in = open(_PATH_DEVNULL, O_RDONLY);
|
in = open(_PATH_DEVNULL, O_RDONLY);
|
||||||
} else {
|
} else {
|
||||||
in = dup(STDIN_FILENO);
|
in = dup(STDIN_FILENO);
|
||||||
@ -2144,11 +2138,11 @@ ssh_session2(struct ssh *ssh, const struct ssh_conn_info *cinfo)
|
|||||||
* async rfwd replies have been received for ExitOnForwardFailure).
|
* async rfwd replies have been received for ExitOnForwardFailure).
|
||||||
*/
|
*/
|
||||||
if (options.control_persist && muxserver_sock != -1) {
|
if (options.control_persist && muxserver_sock != -1) {
|
||||||
ostdin_null_flag = stdin_null_flag;
|
ostdin_null_flag = options.stdin_null;
|
||||||
osession_type = options.session_type;
|
osession_type = options.session_type;
|
||||||
orequest_tty = options.request_tty;
|
orequest_tty = options.request_tty;
|
||||||
otty_flag = tty_flag;
|
otty_flag = tty_flag;
|
||||||
stdin_null_flag = 1;
|
options.stdin_null = 1;
|
||||||
options.session_type = SESSION_TYPE_NONE;
|
options.session_type = SESSION_TYPE_NONE;
|
||||||
tty_flag = 0;
|
tty_flag = 0;
|
||||||
if (!fork_after_authentication_flag &&
|
if (!fork_after_authentication_flag &&
|
||||||
|
20
ssh_config.5
20
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.357 2021/07/14 06:46:38 jmc Exp $
|
.\" $OpenBSD: ssh_config.5,v 1.358 2021/07/23 04:00:59 djm Exp $
|
||||||
.Dd $Mdocdate: July 14 2021 $
|
.Dd $Mdocdate: July 23 2021 $
|
||||||
.Dt SSH_CONFIG 5
|
.Dt SSH_CONFIG 5
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -1675,6 +1675,22 @@ Similarly to
|
|||||||
with the exception of the
|
with the exception of the
|
||||||
.Ev TERM
|
.Ev TERM
|
||||||
variable, the server must be prepared to accept the environment variable.
|
variable, the server must be prepared to accept the environment variable.
|
||||||
|
.It Cm StdinNull
|
||||||
|
Redirects stdin from
|
||||||
|
.Pa /dev/null
|
||||||
|
(actually, prevents reading from stdin).
|
||||||
|
Either this or the equivalent
|
||||||
|
.Fl n
|
||||||
|
option must be used when
|
||||||
|
.Nm ssh
|
||||||
|
is run in the background.
|
||||||
|
The argument to this keyword must be
|
||||||
|
.Cm yes
|
||||||
|
(same as the
|
||||||
|
.Fl n
|
||||||
|
option) or
|
||||||
|
.Cm no
|
||||||
|
(the default).
|
||||||
.It Cm StreamLocalBindMask
|
.It Cm StreamLocalBindMask
|
||||||
Sets the octal file creation mode mask
|
Sets the octal file creation mode mask
|
||||||
.Pq umask
|
.Pq umask
|
||||||
|
118
sshsig.c
118
sshsig.c
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: sshsig.c,v 1.20 2021/01/31 10:50:10 dtucker Exp $ */
|
/* $OpenBSD: sshsig.c,v 1.21 2021/07/23 04:00:59 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2019 Google LLC
|
* Copyright (c) 2019 Google LLC
|
||||||
*
|
*
|
||||||
@ -616,6 +616,7 @@ sshsig_verify_fd(struct sshbuf *signature, int fd,
|
|||||||
struct sshsigopt {
|
struct sshsigopt {
|
||||||
int ca;
|
int ca;
|
||||||
char *namespaces;
|
char *namespaces;
|
||||||
|
uint64_t valid_after, valid_before;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sshsigopt *
|
struct sshsigopt *
|
||||||
@ -624,6 +625,7 @@ sshsigopt_parse(const char *opts, const char *path, u_long linenum,
|
|||||||
{
|
{
|
||||||
struct sshsigopt *ret;
|
struct sshsigopt *ret;
|
||||||
int r;
|
int r;
|
||||||
|
char *opt;
|
||||||
const char *errstr = NULL;
|
const char *errstr = NULL;
|
||||||
|
|
||||||
if ((ret = calloc(1, sizeof(*ret))) == NULL)
|
if ((ret = calloc(1, sizeof(*ret))) == NULL)
|
||||||
@ -643,6 +645,34 @@ sshsigopt_parse(const char *opts, const char *path, u_long linenum,
|
|||||||
ret->namespaces = opt_dequote(&opts, &errstr);
|
ret->namespaces = opt_dequote(&opts, &errstr);
|
||||||
if (ret->namespaces == NULL)
|
if (ret->namespaces == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
} else if (opt_match(&opts, "valid-after")) {
|
||||||
|
if (ret->valid_after != 0) {
|
||||||
|
errstr = "multiple \"valid-after\" clauses";
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if ((opt = opt_dequote(&opts, &errstr)) == NULL)
|
||||||
|
goto fail;
|
||||||
|
if (parse_absolute_time(opt, &ret->valid_after) != 0 ||
|
||||||
|
ret->valid_after == 0) {
|
||||||
|
free(opt);
|
||||||
|
errstr = "invalid \"valid-after\" time";
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
free(opt);
|
||||||
|
} else if (opt_match(&opts, "valid-before")) {
|
||||||
|
if (ret->valid_before != 0) {
|
||||||
|
errstr = "multiple \"valid-before\" clauses";
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if ((opt = opt_dequote(&opts, &errstr)) == NULL)
|
||||||
|
goto fail;
|
||||||
|
if (parse_absolute_time(opt, &ret->valid_before) != 0 ||
|
||||||
|
ret->valid_before == 0) {
|
||||||
|
free(opt);
|
||||||
|
errstr = "invalid \"valid-before\" time";
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
free(opt);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Skip the comma, and move to the next option
|
* Skip the comma, and move to the next option
|
||||||
@ -661,6 +691,12 @@ sshsigopt_parse(const char *opts, const char *path, u_long linenum,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* final consistency check */
|
||||||
|
if (ret->valid_after != 0 && ret->valid_before != 0 &&
|
||||||
|
ret->valid_before <= ret->valid_after) {
|
||||||
|
errstr = "\"valid-before\" time is before \"valid-after\"";
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
/* success */
|
/* success */
|
||||||
return ret;
|
return ret;
|
||||||
fail:
|
fail:
|
||||||
@ -779,12 +815,13 @@ parse_principals_key_and_options(const char *path, u_long linenum, char *line,
|
|||||||
static int
|
static int
|
||||||
check_allowed_keys_line(const char *path, u_long linenum, char *line,
|
check_allowed_keys_line(const char *path, u_long linenum, char *line,
|
||||||
const struct sshkey *sign_key, const char *principal,
|
const struct sshkey *sign_key, const char *principal,
|
||||||
const char *sig_namespace)
|
const char *sig_namespace, uint64_t verify_time)
|
||||||
{
|
{
|
||||||
struct sshkey *found_key = NULL;
|
struct sshkey *found_key = NULL;
|
||||||
int r, found = 0;
|
int r, success = 0;
|
||||||
const char *reason = NULL;
|
const char *reason = NULL;
|
||||||
struct sshsigopt *sigopts = NULL;
|
struct sshsigopt *sigopts = NULL;
|
||||||
|
char tvalid[64], tverify[64];
|
||||||
|
|
||||||
/* Parse the line */
|
/* Parse the line */
|
||||||
if ((r = parse_principals_key_and_options(path, linenum, line,
|
if ((r = parse_principals_key_and_options(path, linenum, line,
|
||||||
@ -793,6 +830,24 @@ check_allowed_keys_line(const char *path, u_long linenum, char *line,
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!sigopts->ca && sshkey_equal(found_key, sign_key)) {
|
||||||
|
/* Exact match of key */
|
||||||
|
debug("%s:%lu: matched key", path, linenum);
|
||||||
|
} else if (sigopts->ca && sshkey_is_cert(sign_key) &&
|
||||||
|
sshkey_equal_public(sign_key->cert->signature_key, found_key)) {
|
||||||
|
/* Match of certificate's CA key */
|
||||||
|
if ((r = sshkey_cert_check_authority(sign_key, 0, 1, 0,
|
||||||
|
verify_time, principal, &reason)) != 0) {
|
||||||
|
error("%s:%lu: certificate not authorized: %s",
|
||||||
|
path, linenum, reason);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
debug("%s:%lu: matched certificate CA key", path, linenum);
|
||||||
|
} else {
|
||||||
|
/* Didn't match key */
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check whether options preclude the use of this key */
|
/* Check whether options preclude the use of this key */
|
||||||
if (sigopts->namespaces != NULL &&
|
if (sigopts->namespaces != NULL &&
|
||||||
match_pattern_list(sig_namespace, sigopts->namespaces, 0) != 1) {
|
match_pattern_list(sig_namespace, sigopts->namespaces, 0) != 1) {
|
||||||
@ -801,36 +856,37 @@ check_allowed_keys_line(const char *path, u_long linenum, char *line,
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sigopts->ca && sshkey_equal(found_key, sign_key)) {
|
/* check key time validity */
|
||||||
/* Exact match of key */
|
format_absolute_time((uint64_t)verify_time, tverify, sizeof(tverify));
|
||||||
debug("%s:%lu: matched key and principal", path, linenum);
|
if (sigopts->valid_after != 0 &&
|
||||||
/* success */
|
(uint64_t)verify_time < sigopts->valid_after) {
|
||||||
found = 1;
|
format_absolute_time(sigopts->valid_after,
|
||||||
} else if (sigopts->ca && sshkey_is_cert(sign_key) &&
|
tvalid, sizeof(tvalid));
|
||||||
sshkey_equal_public(sign_key->cert->signature_key, found_key)) {
|
error("%s:%lu: key is not yet valid: "
|
||||||
/* Match of certificate's CA key */
|
"verify time %s < valid-after %s", path, linenum,
|
||||||
if ((r = sshkey_cert_check_authority(sign_key, 0, 1, 0,
|
tverify, tvalid);
|
||||||
principal, &reason)) != 0) {
|
|
||||||
error("%s:%lu: certificate not authorized: %s",
|
|
||||||
path, linenum, reason);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
debug("%s:%lu: matched certificate CA key", path, linenum);
|
|
||||||
/* success */
|
|
||||||
found = 1;
|
|
||||||
} else {
|
|
||||||
/* Principal matched but key didn't */
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (sigopts->valid_before != 0 &&
|
||||||
|
(uint64_t)verify_time > sigopts->valid_before) {
|
||||||
|
format_absolute_time(sigopts->valid_before,
|
||||||
|
tvalid, sizeof(tvalid));
|
||||||
|
error("%s:%lu: key has expired: "
|
||||||
|
"verify time %s > valid-before %s", path, linenum,
|
||||||
|
tverify, tvalid);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
success = 1;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
sshkey_free(found_key);
|
sshkey_free(found_key);
|
||||||
sshsigopt_free(sigopts);
|
sshsigopt_free(sigopts);
|
||||||
return found ? 0 : SSH_ERR_KEY_NOT_FOUND;
|
return success ? 0 : SSH_ERR_KEY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
sshsig_check_allowed_keys(const char *path, const struct sshkey *sign_key,
|
sshsig_check_allowed_keys(const char *path, const struct sshkey *sign_key,
|
||||||
const char *principal, const char *sig_namespace)
|
const char *principal, const char *sig_namespace, uint64_t verify_time)
|
||||||
{
|
{
|
||||||
FILE *f = NULL;
|
FILE *f = NULL;
|
||||||
char *line = NULL;
|
char *line = NULL;
|
||||||
@ -850,7 +906,7 @@ sshsig_check_allowed_keys(const char *path, const struct sshkey *sign_key,
|
|||||||
while (getline(&line, &linesize, f) != -1) {
|
while (getline(&line, &linesize, f) != -1) {
|
||||||
linenum++;
|
linenum++;
|
||||||
r = check_allowed_keys_line(path, linenum, line, sign_key,
|
r = check_allowed_keys_line(path, linenum, line, sign_key,
|
||||||
principal, sig_namespace);
|
principal, sig_namespace, verify_time);
|
||||||
free(line);
|
free(line);
|
||||||
line = NULL;
|
line = NULL;
|
||||||
linesize = 0;
|
linesize = 0;
|
||||||
@ -871,7 +927,7 @@ sshsig_check_allowed_keys(const char *path, const struct sshkey *sign_key,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
cert_filter_principals(const char *path, u_long linenum,
|
cert_filter_principals(const char *path, u_long linenum,
|
||||||
char **principalsp, const struct sshkey *cert)
|
char **principalsp, const struct sshkey *cert, uint64_t verify_time)
|
||||||
{
|
{
|
||||||
char *cp, *oprincipals, *principals;
|
char *cp, *oprincipals, *principals;
|
||||||
const char *reason;
|
const char *reason;
|
||||||
@ -894,7 +950,7 @@ cert_filter_principals(const char *path, u_long linenum,
|
|||||||
}
|
}
|
||||||
/* Check against principals list in certificate */
|
/* Check against principals list in certificate */
|
||||||
if ((r = sshkey_cert_check_authority(cert, 0, 1, 0,
|
if ((r = sshkey_cert_check_authority(cert, 0, 1, 0,
|
||||||
cp, &reason)) != 0) {
|
verify_time, cp, &reason)) != 0) {
|
||||||
debug("%s:%lu: principal \"%s\" not authorized: %s",
|
debug("%s:%lu: principal \"%s\" not authorized: %s",
|
||||||
path, linenum, cp, reason);
|
path, linenum, cp, reason);
|
||||||
continue;
|
continue;
|
||||||
@ -925,7 +981,7 @@ cert_filter_principals(const char *path, u_long linenum,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
get_matching_principals_from_line(const char *path, u_long linenum, char *line,
|
get_matching_principals_from_line(const char *path, u_long linenum, char *line,
|
||||||
const struct sshkey *sign_key, char **principalsp)
|
const struct sshkey *sign_key, uint64_t verify_time, char **principalsp)
|
||||||
{
|
{
|
||||||
struct sshkey *found_key = NULL;
|
struct sshkey *found_key = NULL;
|
||||||
char *principals = NULL;
|
char *principals = NULL;
|
||||||
@ -951,7 +1007,7 @@ get_matching_principals_from_line(const char *path, u_long linenum, char *line,
|
|||||||
sshkey_equal_public(sign_key->cert->signature_key, found_key)) {
|
sshkey_equal_public(sign_key->cert->signature_key, found_key)) {
|
||||||
/* Remove principals listed in file but not allowed by cert */
|
/* Remove principals listed in file but not allowed by cert */
|
||||||
if ((r = cert_filter_principals(path, linenum,
|
if ((r = cert_filter_principals(path, linenum,
|
||||||
&principals, sign_key)) != 0) {
|
&principals, sign_key, verify_time)) != 0) {
|
||||||
/* error already displayed */
|
/* error already displayed */
|
||||||
debug_r(r, "%s:%lu: cert_filter_principals",
|
debug_r(r, "%s:%lu: cert_filter_principals",
|
||||||
path, linenum);
|
path, linenum);
|
||||||
@ -977,7 +1033,7 @@ get_matching_principals_from_line(const char *path, u_long linenum, char *line,
|
|||||||
|
|
||||||
int
|
int
|
||||||
sshsig_find_principals(const char *path, const struct sshkey *sign_key,
|
sshsig_find_principals(const char *path, const struct sshkey *sign_key,
|
||||||
char **principals)
|
uint64_t verify_time, char **principals)
|
||||||
{
|
{
|
||||||
FILE *f = NULL;
|
FILE *f = NULL;
|
||||||
char *line = NULL;
|
char *line = NULL;
|
||||||
@ -996,7 +1052,7 @@ sshsig_find_principals(const char *path, const struct sshkey *sign_key,
|
|||||||
while (getline(&line, &linesize, f) != -1) {
|
while (getline(&line, &linesize, f) != -1) {
|
||||||
linenum++;
|
linenum++;
|
||||||
r = get_matching_principals_from_line(path, linenum, line,
|
r = get_matching_principals_from_line(path, linenum, line,
|
||||||
sign_key, principals);
|
sign_key, verify_time, principals);
|
||||||
free(line);
|
free(line);
|
||||||
line = NULL;
|
line = NULL;
|
||||||
linesize = 0;
|
linesize = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user