mirror of
git://anongit.mindrot.org/openssh.git
synced 2025-02-16 13:56:52 +00:00
upstream commit
When a forced-command appears in both a certificate and an authorized keys/principals command= restriction, refuse to accept the certificate unless they are identical. The previous (documented) behaviour of having the certificate forced- command override the other could be a bit confused and more error-prone. Pointed out by Jann Horn of Project Zero; ok dtucker@ Upstream-ID: 79d811b6eb6bbe1221bf146dde6928f92d2cd05f
This commit is contained in:
parent
7fc4766ac7
commit
fd6dcef203
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth-options.c,v 1.71 2016/03/07 19:02:43 djm Exp $ */
|
||||
/* $OpenBSD: auth-options.c,v 1.72 2016/11/30 02:57:40 djm Exp $ */
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
@ -601,7 +601,7 @@ parse_option_list(struct sshbuf *oblob, struct passwd *pw,
|
||||
* options so this must be called after auth_parse_options().
|
||||
*/
|
||||
int
|
||||
auth_cert_options(struct sshkey *k, struct passwd *pw)
|
||||
auth_cert_options(struct sshkey *k, struct passwd *pw, const char **reason)
|
||||
{
|
||||
int cert_no_port_forwarding_flag = 1;
|
||||
int cert_no_agent_forwarding_flag = 1;
|
||||
@ -611,6 +611,8 @@ auth_cert_options(struct sshkey *k, struct passwd *pw)
|
||||
char *cert_forced_command = NULL;
|
||||
int cert_source_address_done = 0;
|
||||
|
||||
*reason = "invalid certificate options";
|
||||
|
||||
/* Separate options and extensions for v01 certs */
|
||||
if (parse_option_list(k->cert->critical, pw,
|
||||
OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL,
|
||||
@ -632,11 +634,24 @@ auth_cert_options(struct sshkey *k, struct passwd *pw)
|
||||
no_x11_forwarding_flag |= cert_no_x11_forwarding_flag;
|
||||
no_pty_flag |= cert_no_pty_flag;
|
||||
no_user_rc |= cert_no_user_rc;
|
||||
/* CA-specified forced command supersedes key option */
|
||||
if (cert_forced_command != NULL) {
|
||||
free(forced_command);
|
||||
/*
|
||||
* Only permit both CA and key option forced-command if they match.
|
||||
* Otherwise refuse the certificate.
|
||||
*/
|
||||
if (cert_forced_command != NULL && forced_command != NULL) {
|
||||
if (strcmp(forced_command, cert_forced_command) == 0) {
|
||||
free(forced_command);
|
||||
forced_command = cert_forced_command;
|
||||
} else {
|
||||
*reason = "certificate and key options forced command "
|
||||
"do not match";
|
||||
free(cert_forced_command);
|
||||
return -1;
|
||||
}
|
||||
} else if (cert_forced_command != NULL)
|
||||
forced_command = cert_forced_command;
|
||||
}
|
||||
/* success */
|
||||
*reason = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth-options.h,v 1.21 2015/01/14 10:30:34 markus Exp $ */
|
||||
/* $OpenBSD: auth-options.h,v 1.22 2016/11/30 02:57:40 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||
@ -35,6 +35,6 @@ extern char *authorized_principals;
|
||||
|
||||
int auth_parse_options(struct passwd *, char *, char *, u_long);
|
||||
void auth_clear_options(void);
|
||||
int auth_cert_options(struct sshkey *, struct passwd *);
|
||||
int auth_cert_options(struct sshkey *, struct passwd *, const char **);
|
||||
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: auth2-pubkey.c,v 1.59 2016/09/21 17:44:20 djm Exp $ */
|
||||
/* $OpenBSD: auth2-pubkey.c,v 1.60 2016/11/30 02:57:40 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@ -757,17 +757,17 @@ static int
|
||||
check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
|
||||
{
|
||||
char line[SSH_MAX_PUBKEY_BYTES];
|
||||
const char *reason;
|
||||
int found_key = 0;
|
||||
u_long linenum = 0;
|
||||
Key *found;
|
||||
char *fp;
|
||||
|
||||
found_key = 0;
|
||||
|
||||
found = NULL;
|
||||
while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
|
||||
char *cp, *key_options = NULL;
|
||||
char *cp, *key_options = NULL, *fp = NULL;
|
||||
const char *reason = NULL;
|
||||
|
||||
if (found != NULL)
|
||||
key_free(found);
|
||||
found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);
|
||||
@ -832,10 +832,8 @@ check_authkeys_file(FILE *f, char *file, Key* key, struct passwd *pw)
|
||||
authorized_principals == NULL ? pw->pw_name : NULL,
|
||||
&reason) != 0)
|
||||
goto fail_reason;
|
||||
if (auth_cert_options(key, pw) != 0) {
|
||||
free(fp);
|
||||
continue;
|
||||
}
|
||||
if (auth_cert_options(key, pw, &reason) != 0)
|
||||
goto fail_reason;
|
||||
verbose("Accepted certificate ID \"%s\" (serial %llu) "
|
||||
"signed by %s CA %s via %s", key->cert->key_id,
|
||||
(unsigned long long)key->cert->serial,
|
||||
@ -913,8 +911,8 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
|
||||
if (key_cert_check_authority(key, 0, 1,
|
||||
use_authorized_principals ? NULL : pw->pw_name, &reason) != 0)
|
||||
goto fail_reason;
|
||||
if (auth_cert_options(key, pw) != 0)
|
||||
goto out;
|
||||
if (auth_cert_options(key, pw, &reason) != 0)
|
||||
goto fail_reason;
|
||||
|
||||
verbose("Accepted certificate ID \"%s\" (serial %llu) signed by "
|
||||
"%s CA %s via %s", key->cert->key_id,
|
||||
|
18
sshd.8
18
sshd.8
@ -33,8 +33,8 @@
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $OpenBSD: sshd.8,v 1.286 2016/08/19 03:18:06 djm Exp $
|
||||
.Dd $Mdocdate: August 19 2016 $
|
||||
.\" $OpenBSD: sshd.8,v 1.287 2016/11/30 02:57:40 djm Exp $
|
||||
.Dd $Mdocdate: November 30 2016 $
|
||||
.Dt SSHD 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -481,19 +481,27 @@ If an 8-bit clean channel is required,
|
||||
one must not request a pty or should specify
|
||||
.Cm no-pty .
|
||||
A quote may be included in the command by quoting it with a backslash.
|
||||
.Pp
|
||||
This option might be useful
|
||||
to restrict certain public keys to perform just a specific operation.
|
||||
An example might be a key that permits remote backups but nothing else.
|
||||
Note that the client may specify TCP and/or X11
|
||||
forwarding unless they are explicitly prohibited.
|
||||
forwarding unless they are explicitly prohibited, e.g. using the
|
||||
.Cm restrict
|
||||
key option.
|
||||
.Pp
|
||||
The command originally supplied by the client is available in the
|
||||
.Ev SSH_ORIGINAL_COMMAND
|
||||
environment variable.
|
||||
Note that this option applies to shell, command or subsystem execution.
|
||||
Also note that this command may be superseded by either a
|
||||
Also note that this command may be superseded by a
|
||||
.Xr sshd_config 5
|
||||
.Cm ForceCommand
|
||||
directive or a command embedded in a certificate.
|
||||
directive.
|
||||
.Pp
|
||||
If a command is specified and a forced-command is embedded in a certificate
|
||||
used for authentication, then the certificate will be accepted only if the
|
||||
two commands are identical.
|
||||
.It Cm environment="NAME=value"
|
||||
Specifies that the string is to be added to the environment when
|
||||
logging in using this key.
|
||||
|
Loading…
Reference in New Issue
Block a user