From: Nick Bowler Date: Wed, 2 Nov 2022 04:15:02 +0000 (-0400) Subject: app-crypt/acme-client: New package. X-Git-Url: https://git.draconx.ca/gitweb/gentoo-draconx.git/commitdiff_plain/28e10d7f50f49e164a3605d53948973eb0f0f327 app-crypt/acme-client: New package. This is a port (by Wolf) of acme-client from OpenBSD. It seems to work fine, way simpler to use than certbot with far less dependency hell. As far as I can tell it does not support OCSP must-staple so the program is modified to introduce this feature. --- diff --git a/app-crypt/acme-client/Manifest b/app-crypt/acme-client/Manifest new file mode 100644 index 0000000..917fd69 --- /dev/null +++ b/app-crypt/acme-client/Manifest @@ -0,0 +1,7 @@ +AUX acme-client-1.3.1-allow-group-permissions.patch 471 BLAKE2B fbe7dc222b0debf869e961e61dedc70618f250c42329298f5226c76be8d46e075b2b3c270b50012856374512a0d67a5cb1a54a39a734dc5c91f3656b1f1319ef SHA512 9406f4139a56e3b4b32a5d7ab7e0e6d107dcbbeef420249507c008068fcefe0b64f6acf917e8a0c4c640e85a6a51b67e6ea37123de2c95be6dc36a7dffa0e67c +AUX acme-client-1.3.1-allow-nonroot.patch 445 BLAKE2B 5cd18441694f3b75a05d8efebff05c2a84913a0a3c772e4353a0e709fcfca74d9a410d6570777fffdcd9bea182319345ada5d81269189573e510a60f8e63fc28 SHA512 b5edca18fd29dbe7fe888bc3fdb081530933f3ab8d491f4ea1d7e85c276b5ebcd1d467dead190bdaaa55bdcf917f70029ce29e408efc02b2a77baa429d32cb97 +AUX acme-client-1.3.1-no-default-lto.patch 297 BLAKE2B d984514b1bfa47814ed5dfbc0645dbfe4dec7103a8bbfab7b3514ec69190dd8e83b68f20480a362b64a9e22b7a44281d8a94c6ce26ae8375f98378941dcd7c97 SHA512 723f6014986e5e66235cdb300ec75f03814eac43763d2a8e78c78fb3d66dde3de06295e5641e4d7643ac26d07839788e48973682dafabac89f01bfbcf6a55fdc +AUX acme-client-1.3.1-support-must-staple.patch 4955 BLAKE2B 756b2a0389dec62803ee980e342ee187c842af00c916cc977c246b32184db1fac31ad6446e58b4a6745cfdae1f39355667d27db462ca0449f06aab4599f81b15 SHA512 b517951f8efd6d07ecb5686d608a920622096bf26daac3c1e9cdc17a9ae81f26527f8d280975294b7a891a41964f3e5275dd1f1567ea1734a4d7584b2ec007e3 +AUX acme-client.conf.example 885 BLAKE2B fd1d46258729d37a32b5d2598fdef5e8176fba0fc57b66cfe1f7445d994ce943e0e3c26c6d28964aa1b44ee969f00f2e60682b91625087e3f230b804a501839e SHA512 12e262717109e389dfe880dad65f716809ebd8930c90da53543c111b7d6f6fd2c63d1459bd61ebd5709ac8fc7f8a9619bc70a17ee6738634770f3eee4ab38f7a +DIST acme-client-1.3.1.tar.gz 216464 BLAKE2B e18e42139115f9b6583fc5912d9ff91870def00c14021b56007535f0638311acdae635d11db51405bfd058b5544d5a7adbb5183821d45436d8390a84d2684003 SHA512 9e261c61b287bdd35c828289664b42e1364a4d575acd5021bea1618251bcd5d9fc7662e3a1c117676d9fc3d775674dbe3f4184090fd327b1b5832a01a7413355 +EBUILD acme-client-1.3.1.ebuild 820 BLAKE2B 608d08f572a5dad47e7009fc5522878e25edc0c4accac2ac60eb04bb934e6cd8d981facd1e9480f0424bc40e2d16f30ee670701ad77daafa4c3454d3686e77a0 SHA512 ee62282820fa92e8992892307d34a77e04855ea9d4ff325310f425197d28b913c31b68ee10fe655ab5fe3d4158fb10a993b2ca78b94b668edde948bf6784d410 diff --git a/app-crypt/acme-client/acme-client-1.3.1.ebuild b/app-crypt/acme-client/acme-client-1.3.1.ebuild new file mode 100644 index 0000000..80bb42b --- /dev/null +++ b/app-crypt/acme-client/acme-client-1.3.1.ebuild @@ -0,0 +1,38 @@ +# Copyright © 2022 Nick Bowler +# License GPLv3+: GNU General Public License version 3 or any later version. +# This is free software: you are free to change and redistribute it. +# There is NO WARRANTY, to the extent permitted by law. + +EAPI=8 + +inherit autotools + +DESCRIPTION="C-based ACME client ported from OpenBSD" +HOMEPAGE="https://sr.ht/~graywolf/acme-client-portable/" +SRC_URI="https://data.wolfsden.cz/sources/$P.tar.gz" + +LICENSE="GPL-2" +SLOT="0" +KEYWORDS="~amd64" + +RDEPEND="dev-libs/openssl" +DEPEND="virtual/yacc + $RDEPEND" + +PATCHES=( + "$FILESDIR/$P-no-default-lto.patch" + "$FILESDIR/$P-allow-nonroot.patch" + "$FILESDIR/$P-allow-group-permissions.patch" + "$FILESDIR/$P-support-must-staple.patch" +) + +src_prepare () { + default + eautoreconf +} + +src_install () { + dodoc "$FILESDIR/acme-client.conf.example" + + default +} diff --git a/app-crypt/acme-client/files/acme-client-1.3.1-allow-group-permissions.patch b/app-crypt/acme-client/files/acme-client-1.3.1-allow-group-permissions.patch new file mode 100644 index 0000000..d130b24 --- /dev/null +++ b/app-crypt/acme-client/files/acme-client-1.3.1-allow-group-permissions.patch @@ -0,0 +1,15 @@ +diff --git a/usr.sbin/acme-client/parse.y b/usr.sbin/acme-client/parse.y +index fa87dd7..0c02db9 100644 +--- a/usr.sbin/acme-client/parse.y ++++ b/usr.sbin/acme-client/parse.y +@@ -1129,8 +1129,8 @@ conf_check_file(char *s) + warn("cannot stat %s", s); + return 0; + } +- if (st.st_mode & (S_IRWXG | S_IRWXO)) { +- warnx("%s: group read/writable or world read/writable", s); ++ if (st.st_mode & S_IRWXO) { ++ warnx("%s: world read/writable", s); + return 0; + } + return 1; diff --git a/app-crypt/acme-client/files/acme-client-1.3.1-allow-nonroot.patch b/app-crypt/acme-client/files/acme-client-1.3.1-allow-nonroot.patch new file mode 100644 index 0000000..e6ccc45 --- /dev/null +++ b/app-crypt/acme-client/files/acme-client-1.3.1-allow-nonroot.patch @@ -0,0 +1,16 @@ +diff --git a/usr.sbin/acme-client/main.c b/usr.sbin/acme-client/main.c +index 073f917..c95ded1 100644 +--- a/usr.sbin/acme-client/main.c ++++ b/usr.sbin/acme-client/main.c +@@ -84,11 +84,6 @@ main(int argc, char *argv[]) + goto usage; + } + +-#if !ENABLE_TEST_BUILD +- if (getuid() != 0) +- errx(EXIT_FAILURE, "must be run as root"); +-#endif +- + /* parse config file */ + if ((conf = parse_config(conffile, popts)) == NULL) + return EXIT_FAILURE; diff --git a/app-crypt/acme-client/files/acme-client-1.3.1-no-default-lto.patch b/app-crypt/acme-client/files/acme-client-1.3.1-no-default-lto.patch new file mode 100644 index 0000000..25cc567 --- /dev/null +++ b/app-crypt/acme-client/files/acme-client-1.3.1-no-default-lto.patch @@ -0,0 +1,13 @@ +diff --git a/configure.ac b/configure.ac +index 0645506..697308b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -65,8 +65,6 @@ case "$host" in + # https://github.com/graywolf/acme-client-portable/pull/5#issuecomment-599510762 + ;; + *) +- AX_ADD_CFLAG([-flto]) +- AX_ADD_LDFLAG([-flto]) + ;; + esac + diff --git a/app-crypt/acme-client/files/acme-client-1.3.1-support-must-staple.patch b/app-crypt/acme-client/files/acme-client-1.3.1-support-must-staple.patch new file mode 100644 index 0000000..2cebcb2 --- /dev/null +++ b/app-crypt/acme-client/files/acme-client-1.3.1-support-must-staple.patch @@ -0,0 +1,147 @@ +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 + diff --git a/app-crypt/acme-client/files/acme-client.conf.example b/app-crypt/acme-client/files/acme-client.conf.example new file mode 100644 index 0000000..31dd96f --- /dev/null +++ b/app-crypt/acme-client/files/acme-client.conf.example @@ -0,0 +1,31 @@ +# +# $OpenBSD: acme-client.conf,v 1.4 2020/09/17 09:13:06 florian Exp $ +# +authority letsencrypt { + api url "https://acme-v02.api.letsencrypt.org/directory" + account key "/etc/acme/letsencrypt-privkey.pem" +} + +authority letsencrypt-staging { + api url "https://acme-staging-v02.api.letsencrypt.org/directory" + account key "/etc/acme/letsencrypt-staging-privkey.pem" +} + +authority buypass { + api url "https://api.buypass.com/acme/directory" + account key "/etc/acme/buypass-privkey.pem" + contact "mailto:me@example.com" +} + +authority buypass-test { + api url "https://api.test4.buypass.no/acme/directory" + account key "/etc/acme/buypass-test-privkey.pem" + contact "mailto:me@example.com" +} + +domain example.com { + alternative names { secure.example.com } + domain key "/etc/ssl/private/example.com.key" + domain full chain certificate "/etc/ssl/example.com.fullchain.pem" + sign with letsencrypt +}