Index | Thread | Search

From:
Jonathan Matthew <jonathan@d14n.org>
Subject:
allow wildcard altnames in acme-client.conf
To:
tech@openbsd.org
Cc:
florian@openbsd.org, tb@openbsd.org
Date:
Thu, 17 Sep 2026 07:48:46 +1000

Download raw body.

Thread
If you put a wildcard alternate name in acme-client.conf, you currently
get a syntax error:

/etc/acme-client.conf:20: syntax error

which is reasonable, since this generally requires answering challenges
that acme-client does not support, such as dns-01.

In some circumstances, though, acme-client doesn't need to answer any
challenges to get such a certificate issued.  For instance, our
commercial certificate provider will issue anything under our organization's
domain without any challenges, since EAB is enough proof for them.

Given that, I'd like to adjust the config parser so wildcards
are allowed in alternate names with the diff below.

If you try to use this against an ACME server that will require a
challenge, you get something like this (from pebble, in this case):

acme-client: https://localhost:14000/authZ/JsLllu81TMKVxklrqHxZnccTsX2WfSyer6uigfWBUJo: bad challenge

which is about as helpful as the syntax error to my mind.

ok?  or do I need to wait until there's a challenge type we can
support?


Index: parse.h
===================================================================
RCS file: /cvs/src/usr.sbin/acme-client/parse.h,v
diff -u -p -r1.18 parse.h
--- parse.h	23 Feb 2026 10:27:49 -0000	1.18
+++ parse.h	3 Sep 2026 05:51:33 -0000
@@ -94,6 +94,7 @@ struct authority_c	*authority_find0(stru
 struct domain_c		*domain_find_handle(struct acme_conf *, char *);
 
 int			 domain_valid(const char *);
+int			 altname_domain_valid(const char *);
 const char		*ip_valid(const char *);
 
 #endif /* PARSE_H */
Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/acme-client/parse.y,v
diff -u -p -r1.48 parse.y
--- parse.y	23 Feb 2026 10:27:49 -0000	1.48
+++ parse.y	3 Sep 2026 05:51:33 -0000
@@ -454,7 +454,7 @@ altname		: STRING {
 				if ((s = strdup(ip)) == NULL)
 					err(EXIT_FAILURE, "strdup");
 			} else {
-				if (!domain_valid($1)) {
+				if (!altname_domain_valid($1)) {
 					yyerror("bad domain name syntax");
 					YYERROR;
 				}
@@ -775,7 +775,7 @@ nodigits:
 	x != '!' && x != '=' && x != '#' && \
 	x != ','))
 
-	if (isalnum(c) || c == ':' || c == '_') {
+	if (isalnum(c) || c == ':' || c == '_' || c == '*') {
 		do {
 			*p++ = c;
 			if ((size_t)(p-buf) >= sizeof(buf)) {
@@ -1161,6 +1161,15 @@ domain_valid(const char *cp)
 		    *cp == '_' || isalnum((unsigned char)*cp)))
 			return 0;
 	return 1;
+}
+
+int
+altname_domain_valid(const char *cp)
+{
+	if (cp[0] == '*' && cp[1] == '.')
+		cp += 2;
+
+	return domain_valid(cp);
 }
 
 const char *