--- /dev/null
+From 261275a2582deaf6682cb46b0c20385e698fb2bb Mon Sep 17 00:00:00 2001
+From: Nick Bowler <nbowler@draconx.ca>
+Date: Tue, 1 Nov 2022 23:03:30 -0400
+Subject: [PATCH] Add support for OCSP must-staple.
+
+---
+ usr.sbin/acme-client/acme-client.conf.5 | 3 +++
+ usr.sbin/acme-client/extern.h | 2 +-
+ usr.sbin/acme-client/keyproc.c | 16 ++++++++++++++--
+ usr.sbin/acme-client/main.c | 2 +-
+ usr.sbin/acme-client/parse.h | 3 +++
+ usr.sbin/acme-client/parse.y | 10 +++++++++-
+ 6 files changed, 31 insertions(+), 5 deletions(-)
+
+diff --git a/usr.sbin/acme-client/acme-client.conf.5 b/usr.sbin/acme-client/acme-client.conf.5
+index eb5f19e..113ed62 100644
+--- a/usr.sbin/acme-client/acme-client.conf.5
++++ b/usr.sbin/acme-client/acme-client.conf.5
+@@ -187,6 +187,9 @@ A backup with name
+ is created if
+ .Ar file
+ exists.
++.It Ic domain muststaple
++The certificate signing request will include the status_request extension,
++which requires the use of OCSP stapling with the resulting certificate.
+ .It Ic sign with Ar authority
+ The certificate authority (as declared above in the
+ .Sx AUTHORITIES
+diff --git a/usr.sbin/acme-client/extern.h b/usr.sbin/acme-client/extern.h
+index a2426e9..e354868 100644
+--- a/usr.sbin/acme-client/extern.h
++++ b/usr.sbin/acme-client/extern.h
+@@ -219,7 +219,7 @@ int revokeproc(int, const char *, int, int, const char *const *,
+ int fileproc(int, const char *, const char *, const char *,
+ const char *);
+ int keyproc(int, const char *, const char **, size_t,
+- enum keytype);
++ enum keytype, unsigned int);
+ int netproc(int, int, int, int, int, int, int,
+ struct authority_c *, const char *const *,
+ size_t);
+diff --git a/usr.sbin/acme-client/keyproc.c b/usr.sbin/acme-client/keyproc.c
+index be3696d..f4dcdb5 100644
+--- a/usr.sbin/acme-client/keyproc.c
++++ b/usr.sbin/acme-client/keyproc.c
+@@ -76,7 +76,7 @@ add_ext(STACK_OF(X509_EXTENSION) *sk, int nid, const char *value)
+ */
+ int
+ keyproc(int netsock, const char *keyfile, const char **alts, size_t altsz,
+- enum keytype keytype)
++ enum keytype keytype, unsigned int csrflags)
+ {
+ char *der64 = NULL, *der = NULL, *dercp;
+ char *sans = NULL, *san = NULL;
+@@ -215,7 +215,19 @@ keyproc(int netsock, const char *keyfile, const char **alts, size_t altsz,
+ if (!add_ext(exts, nid, sans)) {
+ warnx("add_ext");
+ goto out;
+- } else if (!X509_REQ_add_extensions(x, exts)) {
++ }
++
++ /*
++ * If requested, enable OCSP must-staple feature in CSR.
++ */
++ if (csrflags & DOMAIN_FLAG_MUSTSTAPLE) {
++ if (!add_ext(exts, NID_tlsfeature, "status_request")) {
++ warnx("add_ext");
++ goto out;
++ }
++ }
++
++ if (!X509_REQ_add_extensions(x, exts)) {
+ warnx("X509_REQ_add_extensions");
+ goto out;
+ }
+diff --git a/usr.sbin/acme-client/main.c b/usr.sbin/acme-client/main.c
+index c95ded1..7284ff0 100644
+--- a/usr.sbin/acme-client/main.c
++++ b/usr.sbin/acme-client/main.c
+@@ -246,7 +246,7 @@ main(int argc, char *argv[])
+ close(file_fds[1]);
+ c = keyproc(key_fds[0], domain->key,
+ (const char **)alts, altsz,
+- domain->keytype);
++ domain->keytype, domain->csrflags);
+ exit(c ? EXIT_SUCCESS : EXIT_FAILURE);
+ }
+
+diff --git a/usr.sbin/acme-client/parse.h b/usr.sbin/acme-client/parse.h
+index 2179b2d..7551014 100644
+--- a/usr.sbin/acme-client/parse.h
++++ b/usr.sbin/acme-client/parse.h
+@@ -26,6 +26,8 @@
+ #define AUTH_MAXLEN 120 /* max length of an authority_c name */
+ #define DOMAIN_MAXLEN 255 /* max len of a domain name (rfc2181) */
+
++#define DOMAIN_FLAG_MUSTSTAPLE 1u /* Add OCSP must-staple extension to CSR */
++
+ /*
+ * XXX other size limits needed?
+ * limit all paths to PATH_MAX
+@@ -49,6 +51,7 @@ struct domain_c {
+ TAILQ_ENTRY(domain_c) entry;
+ TAILQ_HEAD(, altname_c) altname_list;
+ int altname_count;
++ unsigned int csrflags;
+ enum keytype keytype;
+ char *handle;
+ char *domain;
+diff --git a/usr.sbin/acme-client/parse.y b/usr.sbin/acme-client/parse.y
+index f8e76b2..fa87dd7 100644
+--- a/usr.sbin/acme-client/parse.y
++++ b/usr.sbin/acme-client/parse.y
+@@ -101,7 +101,7 @@ typedef struct {
+ %}
+
+ %token AUTHORITY URL API ACCOUNT CONTACT
+-%token DOMAIN ALTERNATIVE NAME NAMES CERT FULL CHAIN KEY SIGN WITH CHALLENGEDIR
++%token DOMAIN ALTERNATIVE NAME NAMES CERT FULL CHAIN KEY SIGN WITH CHALLENGEDIR MUSTSTAPLE
+ %token YES NO
+ %token INCLUDE
+ %token ERROR
+@@ -393,6 +393,13 @@ domainoptsl : ALTERNATIVE NAMES '{' altname_l '}'
+ err(EXIT_FAILURE, "strdup");
+ domain->challengedir = s;
+ }
++ | DOMAIN MUSTSTAPLE {
++ if (domain->csrflags & DOMAIN_FLAG_MUSTSTAPLE) {
++ yyerror("duplicate muststaple");
++ YYERROR;
++ }
++ domain->csrflags |= DOMAIN_FLAG_MUSTSTAPLE;
++ }
+ ;
+
+ altname_l : altname comma altname_l
+@@ -468,6 +475,7 @@ lookup(char *s)
+ {"full", FULL},
+ {"include", INCLUDE},
+ {"key", KEY},
++ {"muststaple", MUSTSTAPLE},
+ {"name", NAME},
+ {"names", NAMES},
+ {"rsa", RSA},
+--
+2.37.4
+