From 261275a2582deaf6682cb46b0c20385e698fb2bb Mon Sep 17 00:00:00 2001 From: Nick Bowler 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