Re: anyone using certificates with an empty principals section?
Ashutosh Ghosh via openssh-unix-dev <[email protected]>
| Newsgroups | gmane.network.openssh.devel |
|---|---|
| Message-ID | <[email protected]> |
Hi, I'm very late to this party, sorry! I have been using host certificates with empty principals and today I got the first user with an OpenSSH 10.3 client report an issue (I think macOS 26.6 released a few days ago is bundling OpenSSH 10.3p1). I think the way this patch is implemented makes it impossible to have a backwards compatible host certificate. If I set the principals to "*", then a pre-10.3 client will not accept it; if I don't set it to "*" for a wildcard certificate then a post-10.3 client will not accept it. For my use case, the hostname and IP address are not stable so I don't have a way to express the set of valid hostnames in advance. Am I missing something? Is there a way to issue a certificate that is effectively a wildcard for both old and new clients? A last resort that I don't want to do is issue every host 2 certificates - one with an empty principals and one with "*" principals. Cheers, Ashutosh On 15/12/2025, 16:24, "Damien Miller" <djm mindrot ! org> wrote: 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 <[email protected]> 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 *); _______________________________________________ openssh-unix-dev mailing list [email protected] https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev