upstream: make sshd_config AuthorizedPrincipalsCommand and

AuthorizedKeysCommand accept the %D (routing domain) and a new %C (connection
address/port 4-tuple) as expansion sequences; ok markus

OpenBSD-Commit-ID: ee9a48bf1a74c4ace71b69de69cfdaa2a7388565
This commit is contained in:
djm@openbsd.org 2023-07-27 22:25:17 +00:00 committed by Damien Miller
parent 999a2886ca
commit d1ffde6b55
No known key found for this signature in database
2 changed files with 31 additions and 16 deletions

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-pubkey.c,v 1.118 2023/02/17 04:22:50 dtucker Exp $ */ /* $OpenBSD: auth2-pubkey.c,v 1.119 2023/07/27 22:25:17 djm Exp $ */
/* /*
* Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved.
@ -340,8 +340,8 @@ match_principals_file(struct passwd *pw, char *file,
* returns 1 if the principal is allowed or 0 otherwise. * returns 1 if the principal is allowed or 0 otherwise.
*/ */
static int static int
match_principals_command(struct passwd *user_pw, match_principals_command(struct passwd *user_pw, const struct sshkey *key,
const struct sshkey *key, struct sshauthopt **authoptsp) const char *conn_id, const char *rdomain, struct sshauthopt **authoptsp)
{ {
struct passwd *runas_pw = NULL; struct passwd *runas_pw = NULL;
const struct sshkey_cert *cert = key->cert; const struct sshkey_cert *cert = key->cert;
@ -416,6 +416,8 @@ match_principals_command(struct passwd *user_pw,
(unsigned long long)user_pw->pw_uid); (unsigned long long)user_pw->pw_uid);
for (i = 1; i < ac; i++) { for (i = 1; i < ac; i++) {
tmp = percent_expand(av[i], tmp = percent_expand(av[i],
"C", conn_id,
"D", rdomain,
"U", uidstr, "U", uidstr,
"u", user_pw->pw_name, "u", user_pw->pw_name,
"h", user_pw->pw_dir, "h", user_pw->pw_dir,
@ -477,7 +479,7 @@ match_principals_command(struct passwd *user_pw,
static int static int
user_cert_trusted_ca(struct passwd *pw, struct sshkey *key, user_cert_trusted_ca(struct passwd *pw, struct sshkey *key,
const char *remote_ip, const char *remote_host, const char *remote_ip, const char *remote_host,
struct sshauthopt **authoptsp) const char *conn_id, const char *rdomain, struct sshauthopt **authoptsp)
{ {
char *ca_fp, *principals_file = NULL; char *ca_fp, *principals_file = NULL;
const char *reason; const char *reason;
@ -514,7 +516,7 @@ user_cert_trusted_ca(struct passwd *pw, struct sshkey *key,
} }
/* Try querying command if specified */ /* Try querying command if specified */
if (!found_principal && match_principals_command(pw, key, if (!found_principal && match_principals_command(pw, key,
&principals_opts)) conn_id, rdomain, &principals_opts))
found_principal = 1; found_principal = 1;
/* If principals file or command is specified, then require a match */ /* If principals file or command is specified, then require a match */
use_authorized_principals = principals_file != NULL || use_authorized_principals = principals_file != NULL ||
@ -613,7 +615,7 @@ user_key_allowed2(struct passwd *pw, struct sshkey *key,
static int static int
user_key_command_allowed2(struct passwd *user_pw, struct sshkey *key, user_key_command_allowed2(struct passwd *user_pw, struct sshkey *key,
const char *remote_ip, const char *remote_host, const char *remote_ip, const char *remote_host,
struct sshauthopt **authoptsp) const char *conn_id, const char *rdomain, struct sshauthopt **authoptsp)
{ {
struct passwd *runas_pw = NULL; struct passwd *runas_pw = NULL;
FILE *f = NULL; FILE *f = NULL;
@ -675,6 +677,8 @@ user_key_command_allowed2(struct passwd *user_pw, struct sshkey *key,
(unsigned long long)user_pw->pw_uid); (unsigned long long)user_pw->pw_uid);
for (i = 1; i < ac; i++) { for (i = 1; i < ac; i++) {
tmp = percent_expand(av[i], tmp = percent_expand(av[i],
"C", conn_id,
"D", rdomain,
"U", uidstr, "U", uidstr,
"u", user_pw->pw_name, "u", user_pw->pw_name,
"h", user_pw->pw_dir, "h", user_pw->pw_dir,
@ -749,11 +753,9 @@ user_key_allowed(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
int auth_attempt, struct sshauthopt **authoptsp) int auth_attempt, struct sshauthopt **authoptsp)
{ {
u_int success = 0, i; u_int success = 0, i;
char *file; char *file, *conn_id;
struct sshauthopt *opts = NULL; struct sshauthopt *opts = NULL;
const char *remote_ip = ssh_remote_ipaddr(ssh); const char *rdomain, *remote_ip, *remote_host;
const char *remote_host = auth_get_canonical_hostname(ssh,
options.use_dns);
if (authoptsp != NULL) if (authoptsp != NULL)
*authoptsp = NULL; *authoptsp = NULL;
@ -764,6 +766,14 @@ user_key_allowed(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
auth_key_is_revoked(key->cert->signature_key)) auth_key_is_revoked(key->cert->signature_key))
return 0; return 0;
if ((rdomain = ssh_packet_rdomain_in(ssh)) == NULL)
rdomain = "";
remote_ip = ssh_remote_ipaddr(ssh);
remote_host = auth_get_canonical_hostname(ssh, options.use_dns);
xasprintf(&conn_id, "%s %d %s %d",
ssh_local_ipaddr(ssh), ssh_local_port(ssh),
remote_ip, ssh_remote_port(ssh));
for (i = 0; !success && i < options.num_authkeys_files; i++) { for (i = 0; !success && i < options.num_authkeys_files; i++) {
if (strcasecmp(options.authorized_keys_files[i], "none") == 0) if (strcasecmp(options.authorized_keys_files[i], "none") == 0)
continue; continue;
@ -781,18 +791,19 @@ user_key_allowed(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
goto out; goto out;
if ((success = user_cert_trusted_ca(pw, key, remote_ip, remote_host, if ((success = user_cert_trusted_ca(pw, key, remote_ip, remote_host,
&opts)) != 0) conn_id, rdomain, &opts)) != 0)
goto out; goto out;
sshauthopt_free(opts); sshauthopt_free(opts);
opts = NULL; opts = NULL;
if ((success = user_key_command_allowed2(pw, key, remote_ip, if ((success = user_key_command_allowed2(pw, key, remote_ip,
remote_host, &opts)) != 0) remote_host, conn_id, rdomain, &opts)) != 0)
goto out; goto out;
sshauthopt_free(opts); sshauthopt_free(opts);
opts = NULL; opts = NULL;
out: out:
free(conn_id);
if (success && authoptsp != NULL) { if (success && authoptsp != NULL) {
*authoptsp = opts; *authoptsp = opts;
opts = NULL; opts = NULL;

View File

@ -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: sshd_config.5,v 1.348 2023/03/03 04:36:20 djm Exp $ .\" $OpenBSD: sshd_config.5,v 1.349 2023/07/27 22:25:17 djm Exp $
.Dd $Mdocdate: March 3 2023 $ .Dd $Mdocdate: July 27 2023 $
.Dt SSHD_CONFIG 5 .Dt SSHD_CONFIG 5
.Os .Os
.Sh NAME .Sh NAME
@ -2021,6 +2021,10 @@ which are expanded at runtime:
.It %% .It %%
A literal A literal
.Sq % . .Sq % .
.It %C
Identifies the connection endpoints, containing
four space-separated values: client address, client port number,
server address, and server port number.
.It \&%D .It \&%D
The routing domain in which the incoming connection was received. The routing domain in which the incoming connection was received.
.It %F .It %F
@ -2048,13 +2052,13 @@ The username.
.El .El
.Pp .Pp
.Cm AuthorizedKeysCommand .Cm AuthorizedKeysCommand
accepts the tokens %%, %f, %h, %k, %t, %U, and %u. accepts the tokens %%, %C, %D, %f, %h, %k, %t, %U, and %u.
.Pp .Pp
.Cm AuthorizedKeysFile .Cm AuthorizedKeysFile
accepts the tokens %%, %h, %U, and %u. accepts the tokens %%, %h, %U, and %u.
.Pp .Pp
.Cm AuthorizedPrincipalsCommand .Cm AuthorizedPrincipalsCommand
accepts the tokens %%, %F, %f, %h, %i, %K, %k, %s, %T, %t, %U, and %u. accepts the tokens %%, %C, %D, %F, %f, %h, %i, %K, %k, %s, %T, %t, %U, and %u.
.Pp .Pp
.Cm AuthorizedPrincipalsFile .Cm AuthorizedPrincipalsFile
accepts the tokens %%, %h, %U, and %u. accepts the tokens %%, %h, %U, and %u.