1 From 261275a2582deaf6682cb46b0c20385e698fb2bb Mon Sep 17 00:00:00 2001
2 From: Nick Bowler <nbowler@draconx.ca>
3 Date: Tue, 1 Nov 2022 23:03:30 -0400
4 Subject: [PATCH] Add support for OCSP must-staple.
7 usr.sbin/acme-client/acme-client.conf.5 | 3 +++
8 usr.sbin/acme-client/extern.h | 2 +-
9 usr.sbin/acme-client/keyproc.c | 16 ++++++++++++++--
10 usr.sbin/acme-client/main.c | 2 +-
11 usr.sbin/acme-client/parse.h | 3 +++
12 usr.sbin/acme-client/parse.y | 10 +++++++++-
13 6 files changed, 31 insertions(+), 5 deletions(-)
15 diff --git a/usr.sbin/acme-client/acme-client.conf.5 b/usr.sbin/acme-client/acme-client.conf.5
16 index eb5f19e..113ed62 100644
17 --- a/usr.sbin/acme-client/acme-client.conf.5
18 +++ b/usr.sbin/acme-client/acme-client.conf.5
19 @@ -187,6 +187,9 @@ A backup with name
23 +.It Ic domain muststaple
24 +The certificate signing request will include the status_request extension,
25 +which requires the use of OCSP stapling with the resulting certificate.
26 .It Ic sign with Ar authority
27 The certificate authority (as declared above in the
29 diff --git a/usr.sbin/acme-client/extern.h b/usr.sbin/acme-client/extern.h
30 index a2426e9..e354868 100644
31 --- a/usr.sbin/acme-client/extern.h
32 +++ b/usr.sbin/acme-client/extern.h
33 @@ -219,7 +219,7 @@ int revokeproc(int, const char *, int, int, const char *const *,
34 int fileproc(int, const char *, const char *, const char *,
36 int keyproc(int, const char *, const char **, size_t,
38 + enum keytype, unsigned int);
39 int netproc(int, int, int, int, int, int, int,
40 struct authority_c *, const char *const *,
42 diff --git a/usr.sbin/acme-client/keyproc.c b/usr.sbin/acme-client/keyproc.c
43 index be3696d..f4dcdb5 100644
44 --- a/usr.sbin/acme-client/keyproc.c
45 +++ b/usr.sbin/acme-client/keyproc.c
46 @@ -76,7 +76,7 @@ add_ext(STACK_OF(X509_EXTENSION) *sk, int nid, const char *value)
49 keyproc(int netsock, const char *keyfile, const char **alts, size_t altsz,
50 - enum keytype keytype)
51 + enum keytype keytype, unsigned int csrflags)
53 char *der64 = NULL, *der = NULL, *dercp;
54 char *sans = NULL, *san = NULL;
55 @@ -215,7 +215,19 @@ keyproc(int netsock, const char *keyfile, const char **alts, size_t altsz,
56 if (!add_ext(exts, nid, sans)) {
59 - } else if (!X509_REQ_add_extensions(x, exts)) {
63 + * If requested, enable OCSP must-staple feature in CSR.
65 + if (csrflags & DOMAIN_FLAG_MUSTSTAPLE) {
66 + if (!add_ext(exts, NID_tlsfeature, "status_request")) {
72 + if (!X509_REQ_add_extensions(x, exts)) {
73 warnx("X509_REQ_add_extensions");
76 diff --git a/usr.sbin/acme-client/main.c b/usr.sbin/acme-client/main.c
77 index c95ded1..7284ff0 100644
78 --- a/usr.sbin/acme-client/main.c
79 +++ b/usr.sbin/acme-client/main.c
80 @@ -246,7 +246,7 @@ main(int argc, char *argv[])
82 c = keyproc(key_fds[0], domain->key,
83 (const char **)alts, altsz,
85 + domain->keytype, domain->csrflags);
86 exit(c ? EXIT_SUCCESS : EXIT_FAILURE);
89 diff --git a/usr.sbin/acme-client/parse.h b/usr.sbin/acme-client/parse.h
90 index 2179b2d..7551014 100644
91 --- a/usr.sbin/acme-client/parse.h
92 +++ b/usr.sbin/acme-client/parse.h
94 #define AUTH_MAXLEN 120 /* max length of an authority_c name */
95 #define DOMAIN_MAXLEN 255 /* max len of a domain name (rfc2181) */
97 +#define DOMAIN_FLAG_MUSTSTAPLE 1u /* Add OCSP must-staple extension to CSR */
100 * XXX other size limits needed?
101 * limit all paths to PATH_MAX
102 @@ -49,6 +51,7 @@ struct domain_c {
103 TAILQ_ENTRY(domain_c) entry;
104 TAILQ_HEAD(, altname_c) altname_list;
106 + unsigned int csrflags;
107 enum keytype keytype;
110 diff --git a/usr.sbin/acme-client/parse.y b/usr.sbin/acme-client/parse.y
111 index f8e76b2..fa87dd7 100644
112 --- a/usr.sbin/acme-client/parse.y
113 +++ b/usr.sbin/acme-client/parse.y
114 @@ -101,7 +101,7 @@ typedef struct {
117 %token AUTHORITY URL API ACCOUNT CONTACT
118 -%token DOMAIN ALTERNATIVE NAME NAMES CERT FULL CHAIN KEY SIGN WITH CHALLENGEDIR
119 +%token DOMAIN ALTERNATIVE NAME NAMES CERT FULL CHAIN KEY SIGN WITH CHALLENGEDIR MUSTSTAPLE
123 @@ -393,6 +393,13 @@ domainoptsl : ALTERNATIVE NAMES '{' altname_l '}'
124 err(EXIT_FAILURE, "strdup");
125 domain->challengedir = s;
127 + | DOMAIN MUSTSTAPLE {
128 + if (domain->csrflags & DOMAIN_FLAG_MUSTSTAPLE) {
129 + yyerror("duplicate muststaple");
132 + domain->csrflags |= DOMAIN_FLAG_MUSTSTAPLE;
136 altname_l : altname comma altname_l
137 @@ -468,6 +475,7 @@ lookup(char *s)
139 {"include", INCLUDE},
141 + {"muststaple", MUSTSTAPLE},