anyone using certificates with an empty principals section?
Damien Miller
djm at mindrot.org
Tue Dec 16 11:24:14 AEDT 2025
On Wed, 26 Nov 2025, Damien Miller wrote:
> Hi,
>
> Is anyone on here using certificates with an empty principals section?
> If so then I'd like to hear from you.
>
> These were originally documented as being wildcard, i.e. matching any
> principal, though this was supported only inconsistently and AFAIK
> only for host certificates and not user certificates.
>
> IMO this behaviour is a footgun and I'd like to remove it.
> Specifically this would mean making certificates without a principals
> section never usable for anything.
>
> To make it possible to do wildcard host certificates, I'd like to
> add the ability to do explicit wildcards using '*' characters in
> principals, e.g. "*.example.com".
>
> This would be a breaking change if you're depending on the existing
> behaviour.
Here's a diff to implement this:
commit 02bd6acbbf146b89e1d5f0a1ffb427d56df99024
Author: Damien Miller <djm at mindrot.org>
Date: Thu Nov 20 10:52:29 2025 +1100
ban empty principals, allow wildcard hostnames
diff --git a/auth2-hostbased.c b/auth2-hostbased.c
index d264913..a26bfaa 100644
--- a/auth2-hostbased.c
+++ b/auth2-hostbased.c
@@ -210,8 +210,8 @@ hostbased_key_allowed(struct ssh *ssh, struct passwd *pw,
}
debug2_f("access allowed by auth_rhosts2");
- if (sshkey_is_cert(key) &&
- sshkey_cert_check_authority_now(key, 1, 0, 0, lookup, &reason)) {
+ if (sshkey_is_cert(key) && sshkey_cert_check_host(key, lookup,
+ options.ca_sign_algorithms, &reason) != 0) {
if ((fp = sshkey_fingerprint(key->cert->signature_key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
fatal_f("sshkey_fingerprint fail");
diff --git a/auth2-pubkeyfile.c b/auth2-pubkeyfile.c
index b580b89..4a109e6 100644
--- a/auth2-pubkeyfile.c
+++ b/auth2-pubkeyfile.c
@@ -363,7 +363,7 @@ auth_check_authkey_line(struct passwd *pw, struct sshkey *key,
reason = "Certificate does not contain an authorized principal";
goto cert_fail_reason;
}
- if (sshkey_cert_check_authority_now(key, 0, 0, 0,
+ if (sshkey_cert_check_authority_now(key, 0, 1, 0,
keyopts->cert_principals == NULL ? pw->pw_name : NULL,
&reason) != 0)
goto cert_fail_reason;
diff --git a/ssh-agent.c b/ssh-agent.c
index ebb573b..500acd1 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -389,7 +389,7 @@ match_key_hop(const char *tag, const struct sshkey *key,
return -1; /* shouldn't happen */
if (!sshkey_equal(key->cert->signature_key, dch->keys[i]))
continue;
- if (sshkey_cert_check_host(key, hostname, 1,
+ if (sshkey_cert_check_host(key, hostname,
SSH_ALLOWED_CA_SIGALGS, &reason) != 0) {
debug_f("cert %s / hostname %s rejected: %s",
key->cert->key_id, hostname, reason);
diff --git a/sshconnect.c b/sshconnect.c
index bd1359a..3d133c7 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -1054,7 +1054,7 @@ check_host_key(char *hostname, const struct ssh_conn_info *cinfo,
if (want_cert) {
if (sshkey_cert_check_host(host_key,
options.host_key_alias == NULL ?
- hostname : options.host_key_alias, 0,
+ hostname : options.host_key_alias,
options.ca_sign_algorithms, &fail_reason) != 0) {
error("%s", fail_reason);
goto fail;
diff --git a/sshkey.c b/sshkey.c
index 08425ad..91ce2f4 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -2418,12 +2418,11 @@ sshkey_cert_check_authority_now(const struct sshkey *k,
int
sshkey_cert_check_host(const struct sshkey *key, const char *host,
- int wildcard_principals, const char *ca_sign_algorithms,
- const char **reason)
+ const char *ca_sign_algorithms, const char **reason)
{
int r;
- if ((r = sshkey_cert_check_authority_now(key, 1, 0, wildcard_principals,
+ if ((r = sshkey_cert_check_authority_now(key, 1, 1, 1,
host, reason)) != 0)
return r;
if (sshbuf_len(key->cert->critical) != 0) {
diff --git a/sshkey.h b/sshkey.h
index a83ddfe..3a0a32b 100644
--- a/sshkey.h
+++ b/sshkey.h
@@ -217,7 +217,7 @@ int sshkey_cert_check_authority(const struct sshkey *, int, int, int,
int sshkey_cert_check_authority_now(const struct sshkey *, int, int, int,
const char *, const char **);
int sshkey_cert_check_host(const struct sshkey *, const char *,
- int , const char *, const char **);
+ const char *, const char **);
size_t sshkey_format_cert_validity(const struct sshkey_cert *,
char *, size_t) __attribute__((__bounded__(__string__, 2, 3)));
int sshkey_check_cert_sigtype(const struct sshkey *, const char *);
More information about the openssh-unix-dev
mailing list