diff --git a/.gitignore b/.gitignore index 56f099b..ea5f9c3 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ clog /certs.tar.xz .build*.log /pesign-*/ +/results_pesign/ diff --git a/0001-cms-kill-generate_integer-it-doesn-t-build-on-i686-a.patch b/0001-cms-kill-generate_integer-it-doesn-t-build-on-i686-a.patch deleted file mode 100644 index 0c82dcf..0000000 --- a/0001-cms-kill-generate_integer-it-doesn-t-build-on-i686-a.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 33bcca8303cad962606df3bfc6a031a9b0626375 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 21 Apr 2016 10:47:34 -0400 -Subject: [PATCH 01/29] cms: kill generate_integer(), it doesn't build on i686 - and it's unused. - -Signed-off-by: Peter Jones ---- - src/cms_common.c | 34 ---------------------------------- - src/cms_common.h | 1 - - 2 files changed, 35 deletions(-) - -diff --git a/src/cms_common.c b/src/cms_common.c -index b19bc62..6a4e6a7 100644 ---- a/src/cms_common.c -+++ b/src/cms_common.c -@@ -641,40 +641,6 @@ generate_string(cms_context *cms, SECItem *der, char *str) - return 0; - } - --static SEC_ASN1Template IntegerTemplate[] = { -- {.kind = SEC_ASN1_INTEGER, -- .offset = 0, -- .sub = NULL, -- .size = sizeof(long), -- }, -- { 0 }, --}; -- --int --generate_integer(cms_context *cms, SECItem *der, unsigned long integer) --{ -- void *ret; -- -- uint32_t u32; -- -- SECItem input = { -- .data = (void *)&integer, -- .len = sizeof(integer), -- .type = siUnsignedInteger, -- }; -- -- if (integer < 0x100000000) { -- u32 = integer & 0xffffffffUL; -- input.data = (void *)&u32; -- input.len = sizeof(u32); -- } -- -- ret = SEC_ASN1EncodeItem(cms->arena, der, &input, IntegerTemplate); -- if (ret == NULL) -- cmsreterr(-1, cms, "could not encode data"); -- return 0; --} -- - int - generate_time(cms_context *cms, SECItem *encoded, time_t when) - { -diff --git a/src/cms_common.h b/src/cms_common.h -index 7d77faf..c7d7268 100644 ---- a/src/cms_common.h -+++ b/src/cms_common.h -@@ -117,7 +117,6 @@ extern int generate_object_id(cms_context *ctx, SECItem *encoded, - SECOidTag tag); - extern int generate_empty_sequence(cms_context *ctx, SECItem *encoded); - extern int generate_time(cms_context *ctx, SECItem *encoded, time_t when); --extern int generate_integer(cms_context *cms, SECItem *der, unsigned long integer); - extern int generate_string(cms_context *cms, SECItem *der, char *str); - extern int wrap_in_set(cms_context *cms, SECItem *der, SECItem **items); - extern int wrap_in_seq(cms_context *cms, SECItem *der, --- -2.13.4 - diff --git a/0030-efikeygen-Fix-the-build-with-nss-3.44.patch b/0001-efikeygen-Fix-the-build-with-nss-3.44.patch similarity index 91% rename from 0030-efikeygen-Fix-the-build-with-nss-3.44.patch rename to 0001-efikeygen-Fix-the-build-with-nss-3.44.patch index e583369..af7e91a 100644 --- a/0030-efikeygen-Fix-the-build-with-nss-3.44.patch +++ b/0001-efikeygen-Fix-the-build-with-nss-3.44.patch @@ -1,7 +1,7 @@ -From b535d1ac5cbcdf18a97d97a92581e38080d9e521 Mon Sep 17 00:00:00 2001 +From 2eb9f3fa837d5fac5fd4e543df25477cc3dbcb1a Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Tue, 14 May 2019 11:28:38 -0400 -Subject: [PATCH] efikeygen: Fix the build with nss 3.44 +Subject: [PATCH 01/42] efikeygen: Fix the build with nss 3.44 NSS 3.44 adds some certificate types, which changes a type and makes some encoding stuff weird. As a result, we get: @@ -28,7 +28,7 @@ Signed-off-by: Peter Jones 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/efikeygen.c b/src/efikeygen.c -index ede76ef0b48..2cd953e9781 100644 +index 121a238685b..848480a9b01 100644 --- a/src/efikeygen.c +++ b/src/efikeygen.c @@ -208,7 +208,7 @@ static int @@ -41,5 +41,5 @@ index ede76ef0b48..2cd953e9781 100644 if (is_ca) type |= NS_CERT_TYPE_SSL_CA | -- -2.23.0 +2.29.2 diff --git a/0002-Fix-command-line-parsing.patch b/0002-Fix-command-line-parsing.patch deleted file mode 100644 index 9c03eeb..0000000 --- a/0002-Fix-command-line-parsing.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 5be0515dee24308fd7e270bf2e0fb5e5a7a78f32 Mon Sep 17 00:00:00 2001 -From: Julien Cristau -Date: Thu, 9 Jun 2016 14:30:37 +0200 -Subject: [PATCH 02/29] Fix command line parsing - -The gettext translation domain should be passed as .arg, not .descrip, -otherwise popt won't process any of the command line options (it stops -looping over the struct poptOption array when an entry has unset -longName, shortName and arg). - -Signed-off-by: Julien Cristau ---- - src/client.c | 2 +- - src/efikeygen.c | 2 +- - src/efisiglist.c | 2 +- - src/pesigcheck.c | 2 +- - 4 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/client.c b/src/client.c -index 028419f..575c873 100644 ---- a/src/client.c -+++ b/src/client.c -@@ -555,7 +555,7 @@ main(int argc, char *argv[]) - - struct poptOption options[] = { - {.argInfo = POPT_ARG_INTL_DOMAIN, -- .descrip = "pesign" }, -+ .arg = "pesign" }, - {.longName = "token", - .shortName = 't', - .argInfo = POPT_ARG_STRING|POPT_ARGFLAG_SHOW_DEFAULT, -diff --git a/src/efikeygen.c b/src/efikeygen.c -index 6278849..8a515a5 100644 ---- a/src/efikeygen.c -+++ b/src/efikeygen.c -@@ -486,7 +486,7 @@ int main(int argc, char *argv[]) - poptContext optCon; - struct poptOption options[] = { - {.argInfo = POPT_ARG_INTL_DOMAIN, -- .descrip = "pesign" }, -+ .arg = "pesign" }, - /* global nss-ish things */ - {.longName = "dbdir", - .shortName = 'd', -diff --git a/src/efisiglist.c b/src/efisiglist.c -index cd3f1ae..40d6a93 100644 ---- a/src/efisiglist.c -+++ b/src/efisiglist.c -@@ -126,7 +126,7 @@ main(int argc, char *argv[]) - - struct poptOption options[] = { - {.argInfo = POPT_ARG_INTL_DOMAIN, -- .descrip = "pesign" }, -+ .arg = "pesign" }, - {.longName = "infile", - .shortName = 'i', - .argInfo = POPT_ARG_STRING, -diff --git a/src/pesigcheck.c b/src/pesigcheck.c -index 1328fe9..0d49c1a 100644 ---- a/src/pesigcheck.c -+++ b/src/pesigcheck.c -@@ -214,7 +214,7 @@ main(int argc, char *argv[]) - poptContext optCon; - struct poptOption options[] = { - {.argInfo = POPT_ARG_INTL_DOMAIN, -- .descrip = "pesign" }, -+ .arg = "pesign" }, - {.longName = "dbfile", - .shortName = 'D', - .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_POST, --- -2.13.4 - diff --git a/0002-pesigcheck-Fix-a-wrong-assignment.patch b/0002-pesigcheck-Fix-a-wrong-assignment.patch new file mode 100644 index 0000000..d291b78 --- /dev/null +++ b/0002-pesigcheck-Fix-a-wrong-assignment.patch @@ -0,0 +1,49 @@ +From 8b985ccb2bf86aed612cac9813eadbe03905b91a Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 18 Feb 2020 16:28:56 -0500 +Subject: [PATCH 02/42] pesigcheck: Fix a wrong assignment + +gcc says: + + pesigcheck.c: In function 'check_signature': + pesigcheck.c:321:17: error: implicit conversion from 'enum ' to 'enum ' [-Werror=enum-conversion] + 321 | reason->type = siBuffer; + | ^ + pesigcheck.c:333:17: error: implicit conversion from 'enum ' to 'enum ' [-Werror=enum-conversion] + 333 | reason->type = siBuffer; + | ^ + cc1: all warnings being treated as errors + +And indeed, that line of code makes no sense at all - it was supposed to +be reason->sig.type. + +Signed-off-by: Peter Jones +--- + src/pesigcheck.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/pesigcheck.c b/src/pesigcheck.c +index 524cce307bf..8fa0f1ad03d 100644 +--- a/src/pesigcheck.c ++++ b/src/pesigcheck.c +@@ -318,7 +318,7 @@ check_signature(pesigcheck_context *ctx, int *nreasons, + reason->type = SIGNATURE; + reason->sig.data = data; + reason->sig.len = datalen; +- reason->type = siBuffer; ++ reason->sig.type = siBuffer; + nreason += 1; + is_invalid = true; + } +@@ -330,7 +330,7 @@ check_signature(pesigcheck_context *ctx, int *nreasons, + reason->type = SIGNATURE; + reason->sig.data = data; + reason->sig.len = datalen; +- reason->type = siBuffer; ++ reason->sig.type = siBuffer; + nreason += 1; + has_valid_cert = true; + } +-- +2.29.2 + diff --git a/0003-Make-0.112-client-and-server-work-with-the-113-proto.patch b/0003-Make-0.112-client-and-server-work-with-the-113-proto.patch new file mode 100644 index 0000000..eced585 --- /dev/null +++ b/0003-Make-0.112-client-and-server-work-with-the-113-proto.patch @@ -0,0 +1,317 @@ +From 3c525aa069dd52d85e3504e6179886a74aa14cd2 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 11 Jun 2020 16:23:14 -0400 +Subject: [PATCH 03/42] Make 0.112 client and server work with the 113 protocol + and vise versa + +This makes the version of the sign API that takes a file type optional, +and makes the client attempt to negotiate which version it's getting. +It also leaves the server able to still handle the version from before +the file type was added. + +Signed-off-by: Peter Jones +--- + src/client.c | 74 +++++++++++++++++++++++++++++++++++++--------------- + src/daemon.c | 63 +++++++++++++++++++++++++++++--------------- + src/daemon.h | 2 ++ + 3 files changed, 97 insertions(+), 42 deletions(-) + +diff --git a/src/client.c b/src/client.c +index 4a9a44e915c..a4f1d1dbbe7 100644 +--- a/src/client.c ++++ b/src/client.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -96,8 +97,8 @@ connect_to_server(void) + static int32_t + check_response(int sd, char **srvmsg); + +-static void +-check_cmd_version(int sd, uint32_t command, char *name, int32_t version) ++static int ++check_cmd_version(int sd, uint32_t command, char *name, int32_t version, bool do_exit) + { + struct msghdr msg; + struct iovec iov[1]; +@@ -116,7 +117,7 @@ check_cmd_version(int sd, uint32_t command, char *name, int32_t version) + ssize_t n; + n = sendmsg(sd, &msg, 0); + if (n < 0) { +- fprintf(stderr, "check-cmd-version: kill daemon failed: %m\n"); ++ fprintf(stderr, "check-cmd-version: sendmsg failed: %m\n"); + exit(1); + } + +@@ -132,11 +133,17 @@ check_cmd_version(int sd, uint32_t command, char *name, int32_t version) + + char *srvmsg = NULL; + int32_t rc = check_response(sd, &srvmsg); +- if (rc < 0) ++ ++ if (do_exit && rc < 0) + errx(1, "command \"%s\" not known by server", name); +- if (rc != version) ++ ++ if (do_exit && rc != version) + errx(1, "command \"%s\": client version %d, server version %d", + name, version, rc); ++ ++ if (rc < 0) ++ return rc; ++ return rc == version; + } + + static void +@@ -146,7 +153,7 @@ send_kill_daemon(int sd) + struct iovec iov; + pesignd_msghdr pm; + +- check_cmd_version(sd, CMD_KILL_DAEMON, "kill-daemon", 0); ++ check_cmd_version(sd, CMD_KILL_DAEMON, "kill-daemon", 0, true); + + pm.version = PESIGND_VERSION; + pm.command = CMD_KILL_DAEMON; +@@ -288,7 +295,7 @@ unlock_token(int sd, char *tokenname, char *pin) + + uint32_t size1 = pesignd_string_size(pin); + +- check_cmd_version(sd, CMD_UNLOCK_TOKEN, "unlock-token", 0); ++ check_cmd_version(sd, CMD_UNLOCK_TOKEN, "unlock-token", 0, true); + + pm.version = PESIGND_VERSION; + pm.command = CMD_UNLOCK_TOKEN; +@@ -365,7 +372,7 @@ is_token_unlocked(int sd, char *tokenname) + + uint32_t size0 = pesignd_string_size(tokenname); + +- check_cmd_version(sd, CMD_IS_TOKEN_UNLOCKED, "is-token-unlocked", 0); ++ check_cmd_version(sd, CMD_IS_TOKEN_UNLOCKED, "is-token-unlocked", 0, true); + + pm.version = PESIGND_VERSION; + pm.command = CMD_IS_TOKEN_UNLOCKED; +@@ -464,6 +471,9 @@ static void + sign(int sd, char *infile, char *outfile, char *tokenname, char *certname, + int attached, uint32_t format) + { ++ int rc; ++ bool add_file_type; ++ + int infd = open(infile, O_RDONLY); + if (infd < 0) { + fprintf(stderr, "pesign-client: could not open input file " +@@ -493,12 +503,28 @@ oom: + exit(1); + } + +- check_cmd_version(sd, attached ? CMD_SIGN_ATTACHED : CMD_SIGN_DETACHED, +- attached ? "sign-attached" : "sign-detached", 0); ++ rc = check_cmd_version(sd, ++ attached ? CMD_SIGN_ATTACHED_WITH_FILE_TYPE ++ : CMD_SIGN_DETACHED_WITH_FILE_TYPE, ++ attached ? "sign-attached" : "sign-detached", ++ 0, format == FORMAT_KERNEL_MODULE); ++ if (rc >= 0) { ++ add_file_type = true; ++ } else { ++ add_file_type = false; ++ check_cmd_version(sd, attached ? CMD_SIGN_ATTACHED ++ : CMD_SIGN_DETACHED, ++ attached ? "sign-attached" : "sign-detached", ++ 0, true); ++ } + ++ printf("add_file_type:%d\n", add_file_type); + pm->version = PESIGND_VERSION; +- pm->command = attached ? CMD_SIGN_ATTACHED : CMD_SIGN_DETACHED; +- pm->size = size0 + size1 + sizeof(format); ++ pm->command = attached ? (add_file_type ? CMD_SIGN_ATTACHED_WITH_FILE_TYPE ++ : CMD_SIGN_ATTACHED) ++ : (add_file_type ? CMD_SIGN_DETACHED_WITH_FILE_TYPE ++ : CMD_SIGN_DETACHED); ++ pm->size = size0 + size1 + (add_file_type ? sizeof(format) : 0); + iov[0].iov_base = pm; + iov[0].iov_len = sizeof (*pm); + +@@ -515,25 +541,31 @@ oom: + } + + char *buffer; +- buffer = malloc(size0 + size1); ++ buffer = malloc(pm->size); + if (!buffer) + goto oom; + +- iov[0].iov_base = &format; +- iov[0].iov_len = sizeof(format); ++ int pos = 0; ++ ++ if (add_file_type) { ++ iov[pos].iov_base = &format; ++ iov[pos].iov_len = sizeof(format); ++ pos++; ++ } + + pesignd_string *tn = (pesignd_string *)buffer; + pesignd_string_set(tn, tokenname); +- iov[1].iov_base = tn; +- iov[1].iov_len = size0; ++ iov[pos].iov_base = tn; ++ iov[pos].iov_len = size0; ++ pos++; + + pesignd_string *cn = pesignd_string_next(tn); + pesignd_string_set(cn, certname); +- iov[2].iov_base = cn; +- iov[2].iov_len = size1; ++ iov[pos].iov_base = cn; ++ iov[pos].iov_len = size1; + + msg.msg_iov = iov; +- msg.msg_iovlen = 3; ++ msg.msg_iovlen = add_file_type ? 3 : 2; + + n = sendmsg(sd, &msg, 0); + if (n < 0) { +@@ -547,7 +579,7 @@ oom: + send_fd(sd, outfd); + + char *srvmsg = NULL; +- int rc = check_response(sd, &srvmsg); ++ rc = check_response(sd, &srvmsg); + if (rc < 0) { + fprintf(stderr, "pesign-client: signing failed: \"%s\"\n", + srvmsg); +diff --git a/src/daemon.c b/src/daemon.c +index 84b9ebcb13f..8522250c2b4 100644 +--- a/src/daemon.c ++++ b/src/daemon.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -569,7 +570,7 @@ out: + + static void + handle_signing(context *ctx, struct pollfd *pollfd, socklen_t size, +- int attached) ++ int attached, bool with_file_type) + { + struct msghdr msg; + struct iovec iov; +@@ -593,8 +594,12 @@ oom: + + n = recvmsg(pollfd->fd, &msg, MSG_WAITALL); + +- file_format = *((uint32_t *) buffer); +- n -= sizeof(uint32_t); ++ if (with_file_type) { ++ file_format = *((uint32_t *) buffer); ++ n -= sizeof(uint32_t); ++ } else { ++ file_format = FORMAT_PE_BINARY; ++ } + + pesignd_string *tn = (pesignd_string *)(buffer + sizeof(uint32_t)); + if (n < (long long)sizeof(tn->size)) { +@@ -674,34 +679,44 @@ finish: + teardown_digests(ctx->cms); + } + ++static inline void ++handle_sign_helper(context *ctx, struct pollfd *pollfd, socklen_t size, ++ int attached, bool with_file_type) ++{ ++ int rc = cms_context_alloc(&ctx->cms); ++ if (rc < 0) ++ return; ++ ++ steal_from_cms(ctx->backup_cms, ctx->cms); ++ ++ handle_signing(ctx, pollfd, size, attached, with_file_type); ++ ++ hide_stolen_goods_from_cms(ctx->cms, ctx->backup_cms); ++ cms_context_fini(ctx->cms); ++} ++ + static void + handle_sign_attached(context *ctx, struct pollfd *pollfd, socklen_t size) + { +- int rc = cms_context_alloc(&ctx->cms); +- if (rc < 0) +- return; ++ handle_sign_helper(ctx, pollfd, size, 1, false); ++} + +- steal_from_cms(ctx->backup_cms, ctx->cms); +- +- handle_signing(ctx, pollfd, size, 1); +- +- hide_stolen_goods_from_cms(ctx->cms, ctx->backup_cms); +- cms_context_fini(ctx->cms); ++static void ++handle_sign_attached_with_file_type(context *ctx, struct pollfd *pollfd, socklen_t size) ++{ ++ handle_sign_helper(ctx, pollfd, size, 1, true); + } + + static void + handle_sign_detached(context *ctx, struct pollfd *pollfd, socklen_t size) + { +- int rc = cms_context_alloc(&ctx->cms); +- if (rc < 0) +- return; ++ handle_sign_helper(ctx, pollfd, size, 0, false); ++} + +- steal_from_cms(ctx->backup_cms, ctx->cms); +- +- handle_signing(ctx, pollfd, size, 0); +- +- hide_stolen_goods_from_cms(ctx->cms, ctx->backup_cms); +- cms_context_fini(ctx->cms); ++static void ++handle_sign_detached_with_file_type(context *ctx, struct pollfd *pollfd, socklen_t size) ++{ ++ handle_sign_helper(ctx, pollfd, size, 0, true); + } + + static void +@@ -733,6 +748,12 @@ cmd_table_t cmd_table[] = { + { CMD_UNLOCK_TOKEN, handle_unlock_token, "unlock-token", 0 }, + { CMD_SIGN_ATTACHED, handle_sign_attached, "sign-attached", 0 }, + { CMD_SIGN_DETACHED, handle_sign_detached, "sign-detached", 0 }, ++ { CMD_SIGN_ATTACHED_WITH_FILE_TYPE, ++ handle_sign_attached_with_file_type, ++ "sign-attached-with-file-type", 0 }, ++ { CMD_SIGN_DETACHED_WITH_FILE_TYPE, ++ handle_sign_detached_with_file_type, ++ "sign-detached-with-file-type", 0 }, + { CMD_RESPONSE, NULL, "response", 0 }, + { CMD_IS_TOKEN_UNLOCKED, handle_is_token_unlocked, + "is-token-unlocked", 0 }, +diff --git a/src/daemon.h b/src/daemon.h +index 69384ce775c..0368dc9256c 100644 +--- a/src/daemon.h ++++ b/src/daemon.h +@@ -45,6 +45,8 @@ typedef enum { + CMD_RESPONSE, + CMD_IS_TOKEN_UNLOCKED, + CMD_GET_CMD_VERSION, ++ CMD_SIGN_ATTACHED_WITH_FILE_TYPE, ++ CMD_SIGN_DETACHED_WITH_FILE_TYPE, + CMD_LIST_END + } pesignd_cmd; + +-- +2.29.2 + diff --git a/0003-gcc-don-t-error-on-stuff-in-includes.patch b/0003-gcc-don-t-error-on-stuff-in-includes.patch deleted file mode 100644 index cf4e61d..0000000 --- a/0003-gcc-don-t-error-on-stuff-in-includes.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 6de291458cbab99bcc317e282c16e1523d6de9b8 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Wed, 10 Aug 2016 17:12:39 -0400 -Subject: [PATCH 03/29] gcc: don't error on stuff in includes. - -Signed-off-by: Peter Jones ---- - Make.defaults | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/Make.defaults b/Make.defaults -index c97b452..3511080 100644 ---- a/Make.defaults -+++ b/Make.defaults -@@ -19,7 +19,7 @@ PKG_CONFIG = $(CROSS_COMPILE)pkg-config - CC := $(if $(filter default,$(origin CC)),$(CROSS_COMPILE)gcc,$(CC)) - CCLD := $(if $(filter undefined,$(origin CCLD)),$(CC),$(CCLD)) - CFLAGS ?= -O0 -g3 -fvar-tracking -fvar-tracking-assignments \ -- -Wall -Werror -Wextra -+ -Wall -Werror -Wextra -Wno-error=cpp - AS := $(CROSS_COMPILE)as - AR := $(CROSS_COMPILE)gcc-ar - RANLIB := $(CROSS_COMPILE)gcc-ranlib --- -2.13.4 - diff --git a/0004-Fix-certficate-argument-name.patch b/0004-Fix-certficate-argument-name.patch deleted file mode 100644 index 08509ff..0000000 --- a/0004-Fix-certficate-argument-name.patch +++ /dev/null @@ -1,39 +0,0 @@ -From b20fc54c08e8afe1365e56cacade3ec39984da8d Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 18 Apr 2017 19:00:34 -0400 -Subject: [PATCH 04/29] Fix "certficate" argument name. - -This fixes our typoed argument name by making the incorrectly spelled -version be a popt alias, and fixing the real implementation to be -spelled right in pesign.c . - -Signed-off-by: Peter Jones ---- - src/pesign.c | 2 +- - src/pesign.popt | 1 + - 2 files changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/pesign.c b/src/pesign.c -index af374b6..279a17a 100644 ---- a/src/pesign.c -+++ b/src/pesign.c -@@ -438,7 +438,7 @@ main(int argc, char *argv[]) - .arg = &ctxp->outfile, - .descrip = "specify output file", - .argDescrip = "" }, -- {.longName = "certficate", -+ {.longName = "certificate", - .shortName = 'c', - .argInfo = POPT_ARG_STRING, - .arg = &certname, -diff --git a/src/pesign.popt b/src/pesign.popt -index 7b3385d..5a97748 100644 ---- a/src/pesign.popt -+++ b/src/pesign.popt -@@ -1,2 +1,3 @@ - pesign alias --cert --certificate -+pesign alias --certficate --certificate - pesign alias --daemon --daemonize --- -2.13.4 - diff --git a/0004-Rename-var-run-to-run.patch b/0004-Rename-var-run-to-run.patch new file mode 100644 index 0000000..bbaf6cc --- /dev/null +++ b/0004-Rename-var-run-to-run.patch @@ -0,0 +1,46 @@ +From b9dd6b7826fdc540365776b860fe5190c51ab088 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 12 Jun 2020 11:49:44 -0400 +Subject: [PATCH 04/42] Rename /var/run/ to /run/ + +Signed-off-by: Peter Jones +--- + src/macros.pesign | 12 ++++++------ + src/tmpfiles.conf | 2 +- + 2 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/src/macros.pesign b/src/macros.pesign +index 7c5cba170e9..21bf3917795 100644 +--- a/src/macros.pesign ++++ b/src/macros.pesign +@@ -45,14 +45,14 @@ + rm -rf ${sattrs} ${sattrs}.sig ${nss} \ + elif [ "$(id -un)" == "kojibuilder" -a \\\ + grep -q ID=fedora /etc/os-release -a \\\ +- ! -S /var/run/pesign/socket ]; then \ ++ ! -S /run/pesign/socket ]; then \ + echo "No socket even though this is kojibuilder" 1>&2 \ +- ls -ld /var/run/pesign 1>&2 \ +- ls -l /var/run/pesign/socket 1>&2 \ +- getfacl /var/run/pesign 1>&2 \ +- getfacl /var/run/pesign/socket 1>&2 \ ++ ls -ld /run/pesign 1>&2 \ ++ ls -l /run/pesign/socket 1>&2 \ ++ getfacl /run/pesign 1>&2 \ ++ getfacl /run/pesign/socket 1>&2 \ + exit 1 \ +- elif [ -S /var/run/pesign/socket ]; then \ ++ elif [ -S /run/pesign/socket ]; then \ + %{_pesign_client} -t %{__pesign_client_token} \\\ + -c %{__pesign_client_cert} \\\ + %{-i} %{-o} %{-e} %{-s} %{-C} \ +diff --git a/src/tmpfiles.conf b/src/tmpfiles.conf +index c1cf35597d8..3375ad52a44 100644 +--- a/src/tmpfiles.conf ++++ b/src/tmpfiles.conf +@@ -1 +1 @@ +-D /var/run/pesign 0770 pesign pesign - ++D /run/pesign 0770 pesign pesign - +-- +2.29.2 + diff --git a/0005-Apparently-opensc-got-updated-and-the-token-name-cha.patch b/0005-Apparently-opensc-got-updated-and-the-token-name-cha.patch new file mode 100644 index 0000000..8f64804 --- /dev/null +++ b/0005-Apparently-opensc-got-updated-and-the-token-name-cha.patch @@ -0,0 +1,31 @@ +From 002371099d65b790e4850bc734dccddac790bb10 Mon Sep 17 00:00:00 2001 +From: Jeremy Cline +Date: Tue, 18 Feb 2020 16:37:53 -0500 +Subject: [PATCH 05/42] Apparently opensc got updated and the token name + changed + +All the kernel builds started failing yesterday because the signing +token could not be found. Update the token name in the macro shipped by +pesign. + +Signed-off-by: Peter Jones +--- + src/macros.pesign | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/macros.pesign b/src/macros.pesign +index 21bf3917795..5a6da1c6809 100644 +--- a/src/macros.pesign ++++ b/src/macros.pesign +@@ -9,7 +9,7 @@ + %__pesign_token %{nil}%{?pe_signing_token:-t "%{pe_signing_token}"} + %__pesign_cert %{!?pe_signing_cert:"Red Hat Test Certificate"}%{?pe_signing_cert:"%{pe_signing_cert}"} + +-%__pesign_client_token %{!?pe_signing_token:"Fedora Signer (OpenSC Card)"}%{?pe_signing_token:"%{pe_signing_token}"} ++%__pesign_client_token %{!?pe_signing_token:"OpenSC Card (Fedora Signer)"}%{?pe_signing_token:"%{pe_signing_token}"} + %__pesign_client_cert %{!?pe_signing_cert:"/CN=Fedora Secure Boot Signer"}%{?pe_signing_cert:"%{pe_signing_cert}"} + + %_pesign /usr/bin/pesign +-- +2.29.2 + diff --git a/0005-Fix-description-of-ascii-armor-option-in-manpage.patch b/0005-Fix-description-of-ascii-armor-option-in-manpage.patch deleted file mode 100644 index 6a5b02d..0000000 --- a/0005-Fix-description-of-ascii-armor-option-in-manpage.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 7bc8e8b04c74be5c4e0ebf211affc37cf9f5db37 Mon Sep 17 00:00:00 2001 -From: Julien Cristau -Date: Mon, 27 Jun 2016 15:38:38 +0200 -Subject: [PATCH 05/29] Fix description of --ascii-armor option in manpage - -The --ascii option does not exist. ---- - src/pesign.1 | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/pesign.1 b/src/pesign.1 -index 47d1aec..29ae060 100644 ---- a/src/pesign.1 -+++ b/src/pesign.1 -@@ -81,7 +81,7 @@ Export the public key specified by \-\-certificate to \fIoutkey\fR - Export the certificate specified by \-\-certificate to \fIoutcert\fR - - .TP --\fB-\-ascii\fR -+\fB-\-ascii\-armor\fR - Use ascii armoring on exported certificates. - - .TP --- -2.13.4 - diff --git a/0006-Add-some-more-utility-functions-and-fix-a-typo-in-AL.patch b/0006-Add-some-more-utility-functions-and-fix-a-typo-in-AL.patch new file mode 100644 index 0000000..0ca885b --- /dev/null +++ b/0006-Add-some-more-utility-functions-and-fix-a-typo-in-AL.patch @@ -0,0 +1,1266 @@ +From 93b241c8260dab03a9e7c45cd2d8e4ec377b981e Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 27 Apr 2020 15:55:44 -0400 +Subject: [PATCH 06/42] Add some more utility functions, and fix a typo in + ALIGNED() + +This adds a bunch of convenience macros, including a linked list +implementation derived from the kernel's, but without the +__list_add_valid() and __list_del_entry_valid() calls. + +I think the idea of the __list_add_valid() and __list_del_entry_valid() +calls, which always return true, is to force the compiler to evaluate +things at an earlier pass. With -Wanalyzer, the compiler notices that +these are called from a conditional and assumes it can return false, +even though returning true is *literally the only thing they do*, and +then it complains about the other path that could (not possibly) be +taken. So we just don't need them here. + +Signed-off-by: Peter Jones +--- + src/actions.c | 4 +- + libdpe/common.h | 2 - + src/compiler.h | 74 +++- + src/err.h | 70 ++++ + src/list.h | 943 ++++++++++++++++++++++++++++++++++++++++++++++++ + src/util.h | 37 +- + src/wincert.h | 2 - + 7 files changed, 1123 insertions(+), 9 deletions(-) + create mode 100644 src/err.h + create mode 100644 src/list.h + +diff --git a/src/actions.c b/src/actions.c +index a68b665201d..69f9e3e1c1a 100644 +--- a/src/actions.c ++++ b/src/actions.c +@@ -317,11 +317,11 @@ parse_signature(pesign_context *ctx) + unsigned char *dertmp; + dertmp = ATOB_AsciiToData(base64, &derlen); + +- der = malloc(derlen); ++ der = xcalloc(1, derlen); + memmove(der, dertmp, derlen); + PORT_Free(dertmp); + } else { +- der = malloc(siglen); ++ der = xcalloc(1, siglen); + memmove(der, sig, siglen); + derlen = siglen; + } +diff --git a/libdpe/common.h b/libdpe/common.h +index 25c36c46339..8d0661db985 100644 +--- a/libdpe/common.h ++++ b/libdpe/common.h +@@ -33,8 +33,6 @@ + + #define is_64_bit(pe) ((pe)->flags & IMAGE_FILE_32BIT_MACHINE) + +-#define ALIGNMENT_PADDING(address, align) ((align - (address % align)) % align) +- + #define xfree(x) ({if (x) { free(x); x = NULL; }}) + #define xmunmap(addr, size) ({if (addr) { munmap(addr,size); addr = NULL; }}) + +diff --git a/src/compiler.h b/src/compiler.h +index 7c7cc57aec8..31379ef9b33 100644 +--- a/src/compiler.h ++++ b/src/compiler.h +@@ -6,6 +6,8 @@ + #ifndef COMPILER_H_ + #define COMPILER_H_ + ++#include ++ + #define UNUSED __attribute__((__unused__)) + #define HIDDEN __attribute__((__visibility__ ("hidden"))) + #define PUBLIC __attribute__((__visibility__ ("default"))) +@@ -18,7 +20,75 @@ + #define PACKED __attribute__((__packed__)) + #define VERSION(sym, ver) __asm__(".symver " # sym "," # ver) + #define NORETURN __attribute__((__noreturn__)) +-#define ALIGNED(n) __attribute__((__aligned__(N))) ++#define ALIGNED(n) __attribute__((__aligned__(n))) ++#define CLEANUP_FUNC(x) __attribute__((__cleanup__(x))) ++ ++#define __CONCAT3(a, b, c) a ## b ## c ++#define CONCATENATE(a, b) __CONCAT(a, b) ++#define CAT(a, b) __CONCAT(a, b) ++#define CAT3(a, b, c) __CONCAT3(a, b, c) ++#define STRING(x) __STRING(x) ++ ++#define WRITE_ONCE(var, val) \ ++ (*((volatile typeof(val) *)(&(var))) = (val)) ++ ++#define READ_ONCE(var) (*((volatile typeof(var) *)(&(var)))) ++ ++#define likely(x) __builtin_expect(!!(x), 1) ++#define unlikely(x) __builtin_expect(!!(x), 0) ++ ++/* Are two types/vars the same type (ignoring qualifiers)? */ ++#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) ++ ++/* Compile time object size, -1 for unknown */ ++#ifndef __compiletime_object_size ++# define __compiletime_object_size(obj) -1 ++#endif ++#ifndef __compiletime_warning ++# define __compiletime_warning(message) ++#endif ++#ifndef __compiletime_error ++# define __compiletime_error(message) ++#endif ++ ++#define __compiletime_assert(condition, msg, prefix, suffix) \ ++ do { \ ++ extern void prefix ## suffix(void) __compiletime_error(msg); \ ++ if (!(condition)) \ ++ prefix ## suffix(); \ ++ } while (0) ++ ++#define _compiletime_assert(condition, msg, prefix, suffix) \ ++ __compiletime_assert(condition, msg, prefix, suffix) ++ ++/** ++ * compiletime_assert - break build and emit msg if condition is false ++ * @condition: a compile-time constant condition to check ++ * @msg: a message to emit if condition is false ++ * ++ * In tradition of POSIX assert, this macro will break the build if the ++ * supplied condition is *false*, emitting the supplied error message if the ++ * compiler has support to do so. ++ */ ++#define compiletime_assert(condition, msg) \ ++ _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__) ++ ++/** ++ * BUILD_BUG_ON_MSG - break compile if a condition is true & emit supplied ++ * error message. ++ * @condition: the condition which the compiler should know is false. ++ * ++ * See BUILD_BUG_ON for description. ++ */ ++#define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) ++ ++#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) ++#define __ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a) - 1) ++#define ALIGN(x, a) __ALIGN((x), (a)) ++#define ALIGN_DOWN(x, a) __ALIGN((x) - ((a) - 1), (a)) ++ ++#define ALIGNMENT_PADDING(value, align) ((align - (value % align)) % align) ++#define ALIGN_UP(value, align) ((value) + ALIGNMENT_PADDING(value, align)) + + #endif /* !COMPILER_H_ */ +-// vim:fenc=utf-8:tw=75:et ++// vim:fenc=utf-8:tw=75:noet +diff --git a/src/err.h b/src/err.h +new file mode 100644 +index 00000000000..1f2aa9c30c1 +--- /dev/null ++++ b/src/err.h +@@ -0,0 +1,70 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++#ifndef _LINUX_ERR_H ++#define _LINUX_ERR_H ++ ++#include ++#include ++ ++#include "compiler.h" ++ ++/* ++ * Kernel pointers have redundant information, so we can use a ++ * scheme where we can return either an error code or a normal ++ * pointer with the same return value. ++ * ++ * This should be a per-architecture thing, to allow different ++ * error and pointer decisions. ++ */ ++#define MAX_ERRNO 4095 ++ ++#ifndef __ASSEMBLY__ ++ ++#define IS_ERR_VALUE(x) unlikely((unsigned long)(void *)(x) >= (unsigned long)-MAX_ERRNO) ++ ++static inline void * ERR_PTR(long error) ++{ ++ return (void *) error; ++} ++ ++static inline long PTR_ERR(const void *ptr) ++{ ++ return (long) ptr; ++} ++ ++static inline bool IS_ERR(const void *ptr) ++{ ++ return IS_ERR_VALUE((unsigned long)ptr); ++} ++ ++static inline bool IS_ERR_OR_NULL(const void *ptr) ++{ ++ return unlikely(!ptr) || IS_ERR_VALUE((unsigned long)ptr); ++} ++ ++/** ++ * ERR_CAST - Explicitly cast an error-valued pointer to another pointer type ++ * @ptr: The pointer to cast. ++ * ++ * Explicitly cast an error-valued pointer to another pointer type in such a ++ * way as to make it clear that's what's going on. ++ */ ++static inline void * ERR_CAST(const void *ptr) ++{ ++ /* cast away the const */ ++ return (void *) ptr; ++} ++ ++static inline int PTR_ERR_OR_ZERO(const void *ptr) ++{ ++ if (IS_ERR(ptr)) ++ return PTR_ERR(ptr); ++ else ++ return 0; ++} ++ ++/* Deprecated */ ++#define PTR_RET(p) PTR_ERR_OR_ZERO(p) ++ ++#endif ++ ++#endif /* _LINUX_ERR_H */ +diff --git a/src/list.h b/src/list.h +new file mode 100644 +index 00000000000..f126b541f87 +--- /dev/null ++++ b/src/list.h +@@ -0,0 +1,943 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* Copied from the Linux kernel, in linux/include/linux/list.h */ ++ ++#ifndef _LINUX_LIST_H ++#define _LINUX_LIST_H ++ ++#include ++ ++#include "compiler.h" ++#include "err.h" ++ ++# define POISON_POINTER_DELTA 0 ++/* ++ * These are non-NULL pointers that will result in page faults ++ * under normal circumstances, used to verify that nobody uses ++ * non-initialized list entries. ++ */ ++#define LIST_POISON1 ((void *) 0x100 + POISON_POINTER_DELTA) ++#define LIST_POISON2 ((void *) 0x200 + POISON_POINTER_DELTA) ++ ++/** ++ * container_of - cast a member of a structure out to the containing structure ++ * @ptr: the pointer to the member. ++ * @type: the type of the container struct this is embedded in. ++ * @member: the name of the member within the struct. ++ * ++ */ ++#define container_of(ptr, type, member) ({ \ ++ void *__mptr = (void *)(ptr); \ ++ BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ ++ !__same_type(*(ptr), void), \ ++ "pointer type mismatch in container_of()"); \ ++ ((type *)(__mptr - offsetof(type, member))); }) ++ ++/** ++ * container_of_safe - cast a member of a structure out to the containing structure ++ * @ptr: the pointer to the member. ++ * @type: the type of the container struct this is embedded in. ++ * @member: the name of the member within the struct. ++ * ++ * If IS_ERR_OR_NULL(ptr), ptr is returned unchanged. ++ */ ++#define container_of_safe(ptr, type, member) ({ \ ++ void *__mptr = (void *)(ptr); \ ++ BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ ++ !__same_type(*(ptr), void), \ ++ "pointer type mismatch in container_of()"); \ ++ IS_ERR_OR_NULL(__mptr) ? ERR_CAST(__mptr) : \ ++ ((type *)(__mptr - offsetof(type, member))); }) ++ ++ ++ ++/* ++ * Simple doubly linked list implementation. ++ * ++ * Some of the internal functions ("__xxx") are useful when ++ * manipulating whole lists rather than single entries, as ++ * sometimes we already know the next/prev entries and we can ++ * generate better code by using them directly rather than ++ * using the generic single-entry routines. ++ */ ++ ++struct list_head { ++ struct list_head *next, *prev; ++}; ++ ++struct hlist_head { ++ struct hlist_node *first; ++}; ++ ++struct hlist_node { ++ struct hlist_node *next, **pprev; ++}; ++ ++typedef struct list_head list_t; ++ ++#define LIST_HEAD_INIT(name) { &(name), &(name) } ++ ++#define LIST_HEAD(name) \ ++ struct list_head name = LIST_HEAD_INIT(name) ++ ++#define INIT_LIST_HEAD(ptr) ({ (ptr)->next = (ptr); (ptr)->prev = (ptr); }) ++ ++/* ++ * Insert a new entry between two known consecutive entries. ++ * ++ * This is only for internal list manipulation where we know ++ * the prev/next entries already! ++ */ ++static inline void __list_add(struct list_head * new, ++ struct list_head * prev, ++ struct list_head * next) ++{ ++ next->prev = new; ++ new->next = next; ++ new->prev = prev; ++ WRITE_ONCE(prev->next, new); ++} ++ ++/** ++ * list_add - add a new entry ++ * @new: new entry to be added ++ * @head: list head to add it after ++ * ++ * Insert a new entry after the specified head. ++ * This is good for implementing stacks. ++ */ ++static inline void list_add(struct list_head *new, struct list_head *head) ++{ ++ __list_add(new, head, head->next); ++} ++ ++ ++/** ++ * list_add_tail - add a new entry ++ * @new: new entry to be added ++ * @head: list head to add it before ++ * ++ * Insert a new entry before the specified head. ++ * This is useful for implementing queues. ++ */ ++static inline void list_add_tail(struct list_head *new, struct list_head *head) ++{ ++ __list_add(new, head->prev, head); ++} ++ ++/* ++ * Delete a list entry by making the prev/next entries ++ * point to each other. ++ * ++ * This is only for internal list manipulation where we know ++ * the prev/next entries already! ++ */ ++static inline void __list_del(struct list_head * prev, struct list_head * next) ++{ ++ next->prev = prev; ++ WRITE_ONCE(prev->next, next); ++} ++ ++/** ++ * list_del - deletes entry from list. ++ * @entry: the element to delete from the list. ++ * Note: list_empty() on entry does not return true after this, the entry is ++ * in an undefined state. ++ */ ++static inline void __list_del_entry(struct list_head *entry) ++{ ++ __list_del(entry->prev, entry->next); ++} ++ ++static inline void list_del(struct list_head *entry) ++{ ++ __list_del_entry(entry); ++ entry->next = LIST_POISON1; ++ entry->prev = LIST_POISON2; ++} ++ ++/** ++ * list_replace - replace old entry by new one ++ * @old : the element to be replaced ++ * @new : the new element to insert ++ * ++ * If @old was empty, it will be overwritten. ++ */ ++static inline void list_replace(struct list_head *old, ++ struct list_head *new) ++{ ++ new->next = old->next; ++ new->next->prev = new; ++ new->prev = old->prev; ++ new->prev->next = new; ++} ++ ++static inline void list_replace_init(struct list_head *old, ++ struct list_head *new) ++{ ++ list_replace(old, new); ++ INIT_LIST_HEAD(old); ++} ++ ++/** ++ * list_del_init - deletes entry from list and reinitialize it. ++ * @entry: the element to delete from the list. ++ */ ++static inline void list_del_init(struct list_head *entry) ++{ ++ __list_del_entry(entry); ++ INIT_LIST_HEAD(entry); ++} ++ ++/** ++ * list_move - delete from one list and add as another's head ++ * @list: the entry to move ++ * @head: the head that will precede our entry ++ */ ++static inline void list_move(struct list_head *list, struct list_head *head) ++{ ++ __list_del_entry(list); ++ list_add(list, head); ++} ++ ++/** ++ * list_move_tail - delete from one list and add as another's tail ++ * @list: the entry to move ++ * @head: the head that will follow our entry ++ */ ++static inline void list_move_tail(struct list_head *list, ++ struct list_head *head) ++{ ++ __list_del_entry(list); ++ list_add_tail(list, head); ++} ++ ++/** ++ * list_bulk_move_tail - move a subsection of a list to its tail ++ * @head: the head that will follow our entry ++ * @first: first entry to move ++ * @last: last entry to move, can be the same as first ++ * ++ * Move all entries between @first and including @last before @head. ++ * All three entries must belong to the same linked list. ++ */ ++static inline void list_bulk_move_tail(struct list_head *head, ++ struct list_head *first, ++ struct list_head *last) ++{ ++ first->prev->next = last->next; ++ last->next->prev = first->prev; ++ ++ head->prev->next = first; ++ first->prev = head->prev; ++ ++ last->next = head; ++ head->prev = last; ++} ++ ++/** ++ * list_is_first -- tests whether @ list is the first entry in list @head ++ * @list: the entry to test ++ * @head: the head of the list ++ */ ++static inline int list_is_first(const struct list_head *list, ++ const struct list_head *head) ++{ ++ return list->prev == head; ++} ++ ++/** ++ * list_is_last - tests whether @list is the last entry in list @head ++ * @list: the entry to test ++ * @head: the head of the list ++ */ ++static inline int list_is_last(const struct list_head *list, ++ const struct list_head *head) ++{ ++ return list->next == head; ++} ++ ++/** ++ * list_empty - tests whether a list is empty ++ * @head: the list to test. ++ */ ++static inline int list_empty(const struct list_head *head) ++{ ++ return READ_ONCE(head->next) == head; ++} ++ ++/** ++ * list_empty_careful - tests whether a list is empty and not being modified ++ * @head: the list to test ++ * ++ * Description: ++ * tests whether a list is empty _and_ checks that no other CPU might be ++ * in the process of modifying either member (next or prev) ++ * ++ * NOTE: using list_empty_careful() without synchronization ++ * can only be safe if the only activity that can happen ++ * to the list entry is list_del_init(). Eg. it cannot be used ++ * if another CPU could re-list_add() it. ++ */ ++static inline int list_empty_careful(const struct list_head *head) ++{ ++ struct list_head *next = head->next; ++ return (next == head) && (next == head->prev); ++} ++ ++/** ++ * list_rotate_left - rotate the list to the left ++ * @head: the head of the list ++ */ ++static inline void list_rotate_left(struct list_head *head) ++{ ++ struct list_head *first; ++ ++ if (!list_empty(head)) { ++ first = head->next; ++ list_move_tail(first, head); ++ } ++} ++ ++/** ++ * list_is_singular - tests whether a list has just one entry. ++ * @head: the list to test. ++ */ ++static inline int list_is_singular(const struct list_head *head) ++{ ++ return !list_empty(head) && (head->next == head->prev); ++} ++ ++static inline void __list_cut_position(struct list_head *list, ++ struct list_head *head, struct list_head *entry) ++{ ++ struct list_head *new_first = entry->next; ++ list->next = head->next; ++ list->next->prev = list; ++ list->prev = entry; ++ entry->next = list; ++ head->next = new_first; ++ new_first->prev = head; ++} ++ ++/** ++ * list_cut_position - cut a list into two ++ * @list: a new list to add all removed entries ++ * @head: a list with entries ++ * @entry: an entry within head, could be the head itself ++ * and if so we won't cut the list ++ * ++ * This helper moves the initial part of @head, up to and ++ * including @entry, from @head to @list. You should ++ * pass on @entry an element you know is on @head. @list ++ * should be an empty list or a list you do not care about ++ * losing its data. ++ * ++ */ ++static inline void list_cut_position(struct list_head *list, ++ struct list_head *head, struct list_head *entry) ++{ ++ if (list_empty(head)) ++ return; ++ if (list_is_singular(head) && ++ (head->next != entry && head != entry)) ++ return; ++ if (entry == head) ++ INIT_LIST_HEAD(list); ++ else ++ __list_cut_position(list, head, entry); ++} ++ ++/** ++ * list_cut_before - cut a list into two, before given entry ++ * @list: a new list to add all removed entries ++ * @head: a list with entries ++ * @entry: an entry within head, could be the head itself ++ * ++ * This helper moves the initial part of @head, up to but ++ * excluding @entry, from @head to @list. You should pass ++ * in @entry an element you know is on @head. @list should ++ * be an empty list or a list you do not care about losing ++ * its data. ++ * If @entry == @head, all entries on @head are moved to ++ * @list. ++ */ ++static inline void list_cut_before(struct list_head *list, ++ struct list_head *head, ++ struct list_head *entry) ++{ ++ if (head->next == entry) { ++ INIT_LIST_HEAD(list); ++ return; ++ } ++ list->next = head->next; ++ list->next->prev = list; ++ list->prev = entry->prev; ++ list->prev->next = list; ++ head->next = entry; ++ entry->prev = head; ++} ++ ++static inline void __list_splice(const struct list_head *list, ++ struct list_head *prev, ++ struct list_head *next) ++{ ++ struct list_head *first = list->next; ++ struct list_head *last = list->prev; ++ ++ first->prev = prev; ++ prev->next = first; ++ ++ last->next = next; ++ next->prev = last; ++} ++ ++/** ++ * list_splice - join two lists, this is designed for stacks ++ * @list: the new list to add. ++ * @head: the place to add it in the first list. ++ */ ++static inline void list_splice(const struct list_head *list, ++ struct list_head *head) ++{ ++ if (!list_empty(list)) ++ __list_splice(list, head, head->next); ++} ++ ++/** ++ * list_splice_tail - join two lists, each list being a queue ++ * @list: the new list to add. ++ * @head: the place to add it in the first list. ++ */ ++static inline void list_splice_tail(struct list_head *list, ++ struct list_head *head) ++{ ++ if (!list_empty(list)) ++ __list_splice(list, head->prev, head); ++} ++ ++/** ++ * list_splice_init - join two lists and reinitialise the emptied list. ++ * @list: the new list to add. ++ * @head: the place to add it in the first list. ++ * ++ * The list at @list is reinitialised ++ */ ++static inline void list_splice_init(struct list_head *list, ++ struct list_head *head) ++{ ++ if (!list_empty(list)) { ++ __list_splice(list, head, head->next); ++ INIT_LIST_HEAD(list); ++ } ++} ++ ++/** ++ * list_splice_tail_init - join two lists and reinitialise the emptied list ++ * @list: the new list to add. ++ * @head: the place to add it in the first list. ++ * ++ * Each of the lists is a queue. ++ * The list at @list is reinitialised ++ */ ++static inline void list_splice_tail_init(struct list_head *list, ++ struct list_head *head) ++{ ++ if (!list_empty(list)) { ++ __list_splice(list, head->prev, head); ++ INIT_LIST_HEAD(list); ++ } ++} ++ ++/** ++ * list_entry - get the struct for this entry ++ * @ptr: the &struct list_head pointer. ++ * @type: the type of the struct this is embedded in. ++ * @member: the name of the list_head within the struct. ++ */ ++#define list_entry(ptr, type, member) \ ++ container_of(ptr, type, member) ++ ++/** ++ * list_first_entry - get the first element from a list ++ * @ptr: the list head to take the element from. ++ * @type: the type of the struct this is embedded in. ++ * @member: the name of the list_head within the struct. ++ * ++ * Note, that list is expected to be not empty. ++ */ ++#define list_first_entry(ptr, type, member) \ ++ list_entry((ptr)->next, type, member) ++ ++/** ++ * list_last_entry - get the last element from a list ++ * @ptr: the list head to take the element from. ++ * @type: the type of the struct this is embedded in. ++ * @member: the name of the list_head within the struct. ++ * ++ * Note, that list is expected to be not empty. ++ */ ++#define list_last_entry(ptr, type, member) \ ++ list_entry((ptr)->prev, type, member) ++ ++/** ++ * list_first_entry_or_null - get the first element from a list ++ * @ptr: the list head to take the element from. ++ * @type: the type of the struct this is embedded in. ++ * @member: the name of the list_head within the struct. ++ * ++ * Note that if the list is empty, it returns NULL. ++ */ ++#define list_first_entry_or_null(ptr, type, member) ({ \ ++ struct list_head *head__ = (ptr); \ ++ struct list_head *pos__ = READ_ONCE(head__->next); \ ++ pos__ != head__ ? list_entry(pos__, type, member) : NULL; \ ++}) ++ ++/** ++ * list_next_entry - get the next element in list ++ * @pos: the type * to cursor ++ * @member: the name of the list_head within the struct. ++ */ ++#define list_next_entry(pos, member) \ ++ list_entry((pos)->member.next, typeof(*(pos)), member) ++ ++/** ++ * list_prev_entry - get the prev element in list ++ * @pos: the type * to cursor ++ * @member: the name of the list_head within the struct. ++ */ ++#define list_prev_entry(pos, member) \ ++ list_entry((pos)->member.prev, typeof(*(pos)), member) ++ ++/** ++ * list_for_each - iterate over a list ++ * @pos: the &struct list_head to use as a loop cursor. ++ * @head: the head for your list. ++ */ ++#define list_for_each(pos, head) \ ++ for (pos = (head)->next; pos != (head); pos = pos->next) ++ ++/** ++ * list_for_each_prev - iterate over a list backwards ++ * @pos: the &struct list_head to use as a loop cursor. ++ * @head: the head for your list. ++ */ ++#define list_for_each_prev(pos, head) \ ++ for (pos = (head)->prev; pos != (head); pos = pos->prev) ++ ++/** ++ * list_for_each_safe - iterate over a list safe against removal of list entry ++ * @pos: the &struct list_head to use as a loop cursor. ++ * @n: another &struct list_head to use as temporary storage ++ * @head: the head for your list. ++ */ ++#define list_for_each_safe(pos, n, head) \ ++ for (pos = (head)->next, n = pos->next; pos != (head); \ ++ pos = n, n = pos->next) ++ ++/** ++ * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry ++ * @pos: the &struct list_head to use as a loop cursor. ++ * @n: another &struct list_head to use as temporary storage ++ * @head: the head for your list. ++ */ ++#define list_for_each_prev_safe(pos, n, head) \ ++ for (pos = (head)->prev, n = pos->prev; \ ++ pos != (head); \ ++ pos = n, n = pos->prev) ++ ++/** ++ * list_for_each_entry - iterate over list of given type ++ * @pos: the type * to use as a loop cursor. ++ * @head: the head for your list. ++ * @member: the name of the list_head within the struct. ++ */ ++#define list_for_each_entry(pos, head, member) \ ++ for (pos = list_first_entry(head, typeof(*pos), member); \ ++ &pos->member != (head); \ ++ pos = list_next_entry(pos, member)) ++ ++/** ++ * list_for_each_entry_reverse - iterate backwards over list of given type. ++ * @pos: the type * to use as a loop cursor. ++ * @head: the head for your list. ++ * @member: the name of the list_head within the struct. ++ */ ++#define list_for_each_entry_reverse(pos, head, member) \ ++ for (pos = list_last_entry(head, typeof(*pos), member); \ ++ &pos->member != (head); \ ++ pos = list_prev_entry(pos, member)) ++ ++/** ++ * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() ++ * @pos: the type * to use as a start point ++ * @head: the head of the list ++ * @member: the name of the list_head within the struct. ++ * ++ * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). ++ */ ++#define list_prepare_entry(pos, head, member) \ ++ ((pos) ? : list_entry(head, typeof(*pos), member)) ++ ++/** ++ * list_for_each_entry_continue - continue iteration over list of given type ++ * @pos: the type * to use as a loop cursor. ++ * @head: the head for your list. ++ * @member: the name of the list_head within the struct. ++ * ++ * Continue to iterate over list of given type, continuing after ++ * the current position. ++ */ ++#define list_for_each_entry_continue(pos, head, member) \ ++ for (pos = list_next_entry(pos, member); \ ++ &pos->member != (head); \ ++ pos = list_next_entry(pos, member)) ++ ++/** ++ * list_for_each_entry_continue_reverse - iterate backwards from the given point ++ * @pos: the type * to use as a loop cursor. ++ * @head: the head for your list. ++ * @member: the name of the list_head within the struct. ++ * ++ * Start to iterate over list of given type backwards, continuing after ++ * the current position. ++ */ ++#define list_for_each_entry_continue_reverse(pos, head, member) \ ++ for (pos = list_prev_entry(pos, member); \ ++ &pos->member != (head); \ ++ pos = list_prev_entry(pos, member)) ++ ++/** ++ * list_for_each_entry_from - iterate over list of given type from the current point ++ * @pos: the type * to use as a loop cursor. ++ * @head: the head for your list. ++ * @member: the name of the list_head within the struct. ++ * ++ * Iterate over list of given type, continuing from current position. ++ */ ++#define list_for_each_entry_from(pos, head, member) \ ++ for (; &pos->member != (head); \ ++ pos = list_next_entry(pos, member)) ++ ++/** ++ * list_for_each_entry_from_reverse - iterate backwards over list of given type ++ * from the current point ++ * @pos: the type * to use as a loop cursor. ++ * @head: the head for your list. ++ * @member: the name of the list_head within the struct. ++ * ++ * Iterate backwards over list of given type, continuing from current position. ++ */ ++#define list_for_each_entry_from_reverse(pos, head, member) \ ++ for (; &pos->member != (head); \ ++ pos = list_prev_entry(pos, member)) ++ ++/** ++ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry ++ * @pos: the type * to use as a loop cursor. ++ * @n: another type * to use as temporary storage ++ * @head: the head for your list. ++ * @member: the name of the list_head within the struct. ++ */ ++#define list_for_each_entry_safe(pos, n, head, member) \ ++ for (pos = list_first_entry(head, typeof(*pos), member), \ ++ n = list_next_entry(pos, member); \ ++ &pos->member != (head); \ ++ pos = n, n = list_next_entry(n, member)) ++ ++/** ++ * list_for_each_entry_safe_continue - continue list iteration safe against removal ++ * @pos: the type * to use as a loop cursor. ++ * @n: another type * to use as temporary storage ++ * @head: the head for your list. ++ * @member: the name of the list_head within the struct. ++ * ++ * Iterate over list of given type, continuing after current point, ++ * safe against removal of list entry. ++ */ ++#define list_for_each_entry_safe_continue(pos, n, head, member) \ ++ for (pos = list_next_entry(pos, member), \ ++ n = list_next_entry(pos, member); \ ++ &pos->member != (head); \ ++ pos = n, n = list_next_entry(n, member)) ++ ++/** ++ * list_for_each_entry_safe_from - iterate over list from current point safe against removal ++ * @pos: the type * to use as a loop cursor. ++ * @n: another type * to use as temporary storage ++ * @head: the head for your list. ++ * @member: the name of the list_head within the struct. ++ * ++ * Iterate over list of given type from current point, safe against ++ * removal of list entry. ++ */ ++#define list_for_each_entry_safe_from(pos, n, head, member) \ ++ for (n = list_next_entry(pos, member); \ ++ &pos->member != (head); \ ++ pos = n, n = list_next_entry(n, member)) ++ ++/** ++ * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal ++ * @pos: the type * to use as a loop cursor. ++ * @n: another type * to use as temporary storage ++ * @head: the head for your list. ++ * @member: the name of the list_head within the struct. ++ * ++ * Iterate backwards over list of given type, safe against removal ++ * of list entry. ++ */ ++#define list_for_each_entry_safe_reverse(pos, n, head, member) \ ++ for (pos = list_last_entry(head, typeof(*pos), member), \ ++ n = list_prev_entry(pos, member); \ ++ &pos->member != (head); \ ++ pos = n, n = list_prev_entry(n, member)) ++ ++/** ++ * list_safe_reset_next - reset a stale list_for_each_entry_safe loop ++ * @pos: the loop cursor used in the list_for_each_entry_safe loop ++ * @n: temporary storage used in list_for_each_entry_safe ++ * @member: the name of the list_head within the struct. ++ * ++ * list_safe_reset_next is not safe to use in general if the list may be ++ * modified concurrently (eg. the lock is dropped in the loop body). An ++ * exception to this is if the cursor element (pos) is pinned in the list, ++ * and list_safe_reset_next is called after re-taking the lock and before ++ * completing the current iteration of the loop body. ++ */ ++#define list_safe_reset_next(pos, n, member) \ ++ n = list_next_entry(pos, member) ++ ++/* ++ * Count the number of items in a list ++ */ ++static inline int list_count_entries(struct list_head *head) ++{ ++ struct list_head *pos; ++ int n = 0; ++ list_for_each(pos, head) ++ n++; ++ return n; ++} ++ ++/* ++ * Sort a list with cmp() ++ * creates a temporary array on the heap ++ */ ++static inline int ++list_sort(struct list_head *head, ++ int (*cmp)(const void *a, const void *b, void *state), ++ void *state) ++{ ++ struct list_head **array = NULL, *pos; ++ unsigned int nmemb = 0; ++ ++ /* ++ * This always allocates in page-sized units to avoid realloc actually ++ * doing anything most of the time. On 64-bit machines we'll do an ++ * allocation for every 512 entries. ++ */ ++ const size_t pgcnt = 4096 / sizeof(void *); ++ ++ array = calloc(ALIGN_UP(1, pgcnt), sizeof(void *)); ++ if (!array) ++ return -1; ++ ++ list_for_each(pos, head) { ++ struct list_head **new_array; ++ size_t newmemb = ALIGN_UP(nmemb + 1, pgcnt); ++ ++ new_array = reallocarray(array, newmemb, sizeof(*new_array)); ++ if (!new_array) { ++ if (array) ++ free(array); ++ return -1; ++ } ++ array = new_array; ++ array[nmemb++] = pos; ++ } ++ ++ qsort_r(array, nmemb, sizeof(*array), cmp, state); ++ ++ INIT_LIST_HEAD(head); ++ for (unsigned int i = 0; i < nmemb; i++) { ++ INIT_LIST_HEAD(array[i]); ++ list_add(array[i], head); ++ } ++ free(array); ++ ++ return 0; ++} ++ ++/* ++ * Double linked lists with a single pointer list head. ++ * Mostly useful for hash tables where the two pointer list head is ++ * too wasteful. ++ * You lose the ability to access the tail in O(1). ++ */ ++ ++#define HLIST_HEAD_INIT { .first = NULL } ++#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } ++#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) ++static inline void INIT_HLIST_NODE(struct hlist_node *h) ++{ ++ h->next = NULL; ++ h->pprev = NULL; ++} ++ ++static inline int hlist_unhashed(const struct hlist_node *h) ++{ ++ return !h->pprev; ++} ++ ++static inline int hlist_empty(const struct hlist_head *h) ++{ ++ return !READ_ONCE(h->first); ++} ++ ++static inline void __hlist_del(struct hlist_node *n) ++{ ++ struct hlist_node *next = n->next; ++ struct hlist_node **pprev = n->pprev; ++ ++ WRITE_ONCE(*pprev, next); ++ if (next) ++ next->pprev = pprev; ++} ++ ++static inline void hlist_del(struct hlist_node *n) ++{ ++ __hlist_del(n); ++ n->next = LIST_POISON1; ++ n->pprev = LIST_POISON2; ++} ++ ++static inline void hlist_del_init(struct hlist_node *n) ++{ ++ if (!hlist_unhashed(n)) { ++ __hlist_del(n); ++ INIT_HLIST_NODE(n); ++ } ++} ++ ++static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) ++{ ++ struct hlist_node *first = h->first; ++ n->next = first; ++ if (first) ++ first->pprev = &n->next; ++ WRITE_ONCE(h->first, n); ++ n->pprev = &h->first; ++} ++ ++/* next must be != NULL */ ++static inline void hlist_add_before(struct hlist_node *n, ++ struct hlist_node *next) ++{ ++ n->pprev = next->pprev; ++ n->next = next; ++ next->pprev = &n->next; ++ WRITE_ONCE(*(n->pprev), n); ++} ++ ++static inline void hlist_add_behind(struct hlist_node *n, ++ struct hlist_node *prev) ++{ ++ n->next = prev->next; ++ WRITE_ONCE(prev->next, n); ++ n->pprev = &prev->next; ++ ++ if (n->next) ++ n->next->pprev = &n->next; ++} ++ ++/* after that we'll appear to be on some hlist and hlist_del will work */ ++static inline void hlist_add_fake(struct hlist_node *n) ++{ ++ n->pprev = &n->next; ++} ++ ++static inline bool hlist_fake(struct hlist_node *h) ++{ ++ return h->pprev == &h->next; ++} ++ ++/* ++ * Check whether the node is the only node of the head without ++ * accessing head: ++ */ ++static inline bool ++hlist_is_singular_node(struct hlist_node *n, struct hlist_head *h) ++{ ++ return !n->next && n->pprev == &h->first; ++} ++ ++/* ++ * Move a list from one list head to another. Fixup the pprev ++ * reference of the first entry if it exists. ++ */ ++static inline void hlist_move_list(struct hlist_head *old, ++ struct hlist_head *new) ++{ ++ new->first = old->first; ++ if (new->first) ++ new->first->pprev = &new->first; ++ old->first = NULL; ++} ++ ++#define hlist_entry(ptr, type, member) container_of(ptr,type,member) ++ ++#define hlist_for_each(pos, head) \ ++ for (pos = (head)->first; pos ; pos = pos->next) ++ ++#define hlist_for_each_safe(pos, n, head) \ ++ for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ ++ pos = n) ++ ++#define hlist_entry_safe(ptr, type, member) \ ++ ({ typeof(ptr) ____ptr = (ptr); \ ++ ____ptr ? hlist_entry(____ptr, type, member) : NULL; \ ++ }) ++ ++/** ++ * hlist_for_each_entry - iterate over list of given type ++ * @pos: the type * to use as a loop cursor. ++ * @head: the head for your list. ++ * @member: the name of the hlist_node within the struct. ++ */ ++#define hlist_for_each_entry(pos, head, member) \ ++ for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\ ++ pos; \ ++ pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member)) ++ ++/** ++ * hlist_for_each_entry_continue - iterate over a hlist continuing after current point ++ * @pos: the type * to use as a loop cursor. ++ * @member: the name of the hlist_node within the struct. ++ */ ++#define hlist_for_each_entry_continue(pos, member) \ ++ for (pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member);\ ++ pos; \ ++ pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member)) ++ ++/** ++ * hlist_for_each_entry_from - iterate over a hlist continuing from current point ++ * @pos: the type * to use as a loop cursor. ++ * @member: the name of the hlist_node within the struct. ++ */ ++#define hlist_for_each_entry_from(pos, member) \ ++ for (; pos; \ ++ pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member)) ++ ++/** ++ * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry ++ * @pos: the type * to use as a loop cursor. ++ * @n: another &struct hlist_node to use as temporary storage ++ * @head: the head for your list. ++ * @member: the name of the hlist_node within the struct. ++ */ ++#define hlist_for_each_entry_safe(pos, n, head, member) \ ++ for (pos = hlist_entry_safe((head)->first, typeof(*pos), member);\ ++ pos && ({ n = pos->member.next; 1; }); \ ++ pos = hlist_entry_safe(n, typeof(*pos), member)) ++ ++#endif +diff --git a/src/util.h b/src/util.h +index 917a7d2d73f..362c3559293 100644 +--- a/src/util.h ++++ b/src/util.h +@@ -19,6 +19,8 @@ + #ifndef PESIGN_UTIL_H + #define PESIGN_UTIL_H 1 + ++#include ++#include + #include + #include + #include +@@ -28,8 +30,15 @@ + #include + + #include "compiler.h" ++#include "list.h" + +-#define xfree(x) ({if (x) { free(x); x = NULL; }}) ++#define xfree(x) ({ if (x) { free(x); x = NULL; } }) ++#define xclose(fd) ({ if ((fd) >= 0) { close(fd); (fd) = -1; } }) ++#define xopen(path, flags, args...) ({ int fd_ = open(path, flags, ## args); if (fd_ < 0) liberr(1, "Could not open file \"%s\"", arg); fd_; }) ++#define xrealloc(o, s) ({ void *o_ = realloc(o, s); if (!o_) liberr(1, "Could not allocate %zd bytes", (size_t)s); o_; }) ++#define xcalloc(n, s) ({ void *p_ = calloc(n, s); if (!p_) liberr(1, "Could not allocate %lu entries of %lu bytes", (unsigned long)n, (unsigned long)s); p_; }) ++#define xstrdup(s) ({ void *p_ = strdup(s); if (!p_) liberr(1, "Could not allocate memory"); p_; }) ++#define xpfstat(path, fd, sb) ({ int rc_ = fstat(fd, sb); if (rc_ < 0) liberr(1, "Could not stat \"%s\"", path); }) + + #define save_errno(x) \ + ({ \ +@@ -44,17 +53,43 @@ + __libpe_seterrno(__saved_errno); \ + }) + ++#define conderr(cond, val, fmt, args...) ({ \ ++ if (cond) \ ++ err(val, fmt, ## args); \ ++ }) ++#define conderrx(cond, val, fmt, args...) ({ \ ++ if (cond) \ ++ errx(val, fmt, ## args); \ ++ }) ++ ++#define condwarn(cond, fmt, args...) ({ \ ++ if (cond) \ ++ warn(fmt, ## args); \ ++ }) ++#define condwarnx(cond, fmt, args...) ({ \ ++ if (cond) \ ++ warnx(fmt, ## args); \ ++ }) ++ + #define nsserr(rv, fmt, args...) ({ \ + errx((rv), "%s:%s:%d: " fmt ": %s", \ + __FILE__, __func__, __LINE__, ##args, \ + PORT_ErrorToString(PORT_GetError())); \ + }) ++#define condnsserr(cond, rv, fmt, args...) ({ \ ++ if ((cond)) \ ++ nsserr(rv, fmt, ## args); \ ++ }) + #define nssreterr(rv, fmt, args...) ({ \ + fprintf(stderr, "%s:%s:%d: " fmt ": %s\n", \ + __FILE__, __func__, __LINE__, ##args, \ + PORT_ErrorToString(PORT_GetError())); \ + return rv; \ + }) ++#define condnssreterr(cond, rv, fmt, args...) ({ \ ++ if ((cond)) \ ++ nssreterr(rv, fmt, ## args); \ ++ }) + #define liberr(rv, fmt, args...) ({ \ + err((rv), "%s:%s:%d: " fmt, \ + __FILE__, __func__, __LINE__, ##args); \ +diff --git a/src/wincert.h b/src/wincert.h +index fc8dc7d9e7c..d0d2b3fe6bf 100644 +--- a/src/wincert.h ++++ b/src/wincert.h +@@ -61,6 +61,4 @@ extern int finalize_signatures(SECItem **sigs, int num_sigs, Pe *pe); + extern size_t get_reserved_sig_space(cms_context *cms, Pe *pe); + extern ssize_t get_sigspace_extend_amount(cms_context *cms, Pe *pe, SECItem *sig); + +-#define ALIGNMENT_PADDING(address, align) ((align - (address % align)) % align) +- + #endif /* PESIGN_WINCERT_H */ +-- +2.29.2 + diff --git a/0006-Make-ascii-work-since-we-documented-it.patch b/0006-Make-ascii-work-since-we-documented-it.patch deleted file mode 100644 index d0165f9..0000000 --- a/0006-Make-ascii-work-since-we-documented-it.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 9f411f4e797e983d2e8cb51dc5b9ab8db250c2e3 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 18 Apr 2017 19:05:40 -0400 -Subject: [PATCH 06/29] Make --ascii work, since we documented it. - -Signed-off-by: Peter Jones ---- - src/pesign.popt | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/pesign.popt b/src/pesign.popt -index 5a97748..5ae0c5c 100644 ---- a/src/pesign.popt -+++ b/src/pesign.popt -@@ -1,3 +1,4 @@ - pesign alias --cert --certificate - pesign alias --certficate --certificate - pesign alias --daemon --daemonize -+pesign alias --ascii --ascii-armor --- -2.13.4 - diff --git a/0007-Add-hex-utilities.patch b/0007-Add-hex-utilities.patch new file mode 100644 index 0000000..b9bfc0e --- /dev/null +++ b/0007-Add-hex-utilities.patch @@ -0,0 +1,65 @@ +From 2fd010b0edc814e46955c85a7ec2cfa8c12a7862 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 3 Feb 2020 15:42:52 -0500 +Subject: [PATCH 07/42] Add hex utilities. + +Signed-off-by: Peter Jones +--- + src/hex.h | 45 +++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 45 insertions(+) + create mode 100644 src/hex.h + +diff --git a/src/hex.h b/src/hex.h +new file mode 100644 +index 00000000000..24014eb3056 +--- /dev/null ++++ b/src/hex.h +@@ -0,0 +1,45 @@ ++// SPDX-License-Identifier: GPLv2 ++/* ++ * hex.h - hexidecimal conversion helpers ++ * Copyright Peter Jones ++ */ ++#ifndef HEX_H_ ++#define HEX_H_ ++ ++static inline uint8_t hexchar_to_bin(char hex) ++{ ++ if (hex >= '0' && hex <= '9') ++ return hex - '0'; ++ if (hex >= 'A' && hex <= 'F') ++ return hex - 'A' + 10; ++ if (hex >= 'a' && hex <= 'f') ++ return hex - 'a' + 10; ++ return -1; ++} ++ ++static inline int ++hex_to_bin(const char *hex, uint8_t *out, size_t size) ++{ ++ for (size_t i = 0, j = 0; j < size; i+= 2, j++) { ++ uint8_t val; ++ ++ val = hexchar_to_bin(hex[i]); ++ if (val > 15) ++ goto out_of_range; ++ out[j] = (val & 0xf) << 4; ++ ++ val = hexchar_to_bin(hex[i+1]); ++ if (val > 15) ++ goto out_of_range; ++ out[j] |= val & 0xf; ++ } ++ ++ errno = 0; ++ return 0; ++out_of_range: ++ errno = ERANGE; ++ return -1; ++} ++ ++#endif /* !HEX_H_ */ ++// vim:fenc=utf-8:tw=75:noet +-- +2.29.2 + diff --git a/0007-Switch-pesign-client-to-also-accept-token-cert-macro.patch b/0007-Switch-pesign-client-to-also-accept-token-cert-macro.patch deleted file mode 100644 index faa78ec..0000000 --- a/0007-Switch-pesign-client-to-also-accept-token-cert-macro.patch +++ /dev/null @@ -1,32 +0,0 @@ -From d618de733865eab359890b4e677c368a133dad99 Mon Sep 17 00:00:00 2001 -From: Pat Riehecky -Date: Mon, 7 Nov 2016 11:37:08 -0600 -Subject: [PATCH 07/29] Switch pesign client to also accept token/cert macros - rather than use hard coded values - ---- - src/macros.pesign | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/macros.pesign b/src/macros.pesign -index 18e5b5e..69280e9 100644 ---- a/src/macros.pesign -+++ b/src/macros.pesign -@@ -41,11 +41,11 @@ - --certdir ${nss} -c signer %{-o} \ - rm -rf ${sattrs} ${sattrs}.sig ${nss} \ - elif [ -S /var/run/pesign/socket ]; then \ -- %{_pesign_client} -t "OpenSC Card (Fedora Signer)" \\\ -- -c "/CN=Fedora Secure Boot Signer" \\\ -+ %{_pesign_client} -t %{__pesign_token} \\\ -+ -c %{__pesign_cert} \\\ - %{-i} %{-o} %{-e} %{-s} %{-C} \ - else \ -- %{_pesign} %{__pesign_token} -c %{__pesign_cert} \\\ -+ %{_pesign} -t %{__pesign_token} -c %{__pesign_cert} \\\ - --certdir ${_pesign_nssdir} \\\ - %{-i} %{-o} %{-e} %{-s} %{-C} \ - fi \ --- -2.13.4 - diff --git a/0008-Add-some-text-parsing-helpers.patch b/0008-Add-some-text-parsing-helpers.patch new file mode 100644 index 0000000..1489a93 --- /dev/null +++ b/0008-Add-some-text-parsing-helpers.patch @@ -0,0 +1,367 @@ +From 2cd818c0ef885276cc66ff39bcbe01a90d385db8 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 22 Jun 2020 10:35:22 -0400 +Subject: [PATCH 08/42] Add some text parsing helpers + +Signed-off-by: Peter Jones +--- + src/text.c | 259 +++++++++++++++++++++++++++++++++++++++++++++++++++ + src/pesign.h | 1 + + src/text.h | 53 +++++++++++ + src/Makefile | 2 +- + 4 files changed, 314 insertions(+), 1 deletion(-) + create mode 100644 src/text.c + create mode 100644 src/text.h + +diff --git a/src/text.c b/src/text.c +new file mode 100644 +index 00000000000..e463e8d05eb +--- /dev/null ++++ b/src/text.c +@@ -0,0 +1,259 @@ ++// SPDX-License-Identifier: GPLv2 ++/* ++ * text.c - helpers for text strings ++ * Copyright Peter Jones ++ */ ++#include "compiler.h" ++#include "text.h" ++ ++#include ++#include ++#include ++#include ++ ++const char * const eol_chars = "\f\r\v\n"; ++// static const char * const whitespace_chars = "\t "; ++const char * const whitespace_and_eol_chars = "\t \f\r\v\n"; ++ ++// static const char * const binary_digits = "01"; ++static const char * const octal_digits = "01234567"; ++// static const char * const decimal_digits = "0123456789"; ++static const char * const hex_digits = "0123456789abcdefABCDEF"; ++ ++static const char * const cnt_nl = "\\\n"; ++static const char * const cnt_lfnl = "\\\r\n"; ++static const char * const cnt_lf = "\\\r"; ++static const char * const cnt_ff = "\\\f"; ++static const char * const cnt_vt = "\\\v"; ++ ++static const char * const line_continuation_strs[] = { ++ cnt_nl, ++ cnt_lfnl, ++ cnt_lf, ++ cnt_ff, ++ cnt_vt, ++ NULL ++}; ++ ++/* ++ * unbreak_line_coninutations: remove all line continuations ++ * @buf: the buffer to operate on ++ * @bufsz: the size of the buffer ++ */ ++void ++unbreak_line_continuations(char *buf, size_t bufsz) ++{ ++ char *to = buf; ++ bool found = true; ++ ++ while (found) { ++ found = false; ++ ++ for (unsigned int i = 0; line_continuation_strs[i]; i++) { ++ size_t cntsz = strlen(line_continuation_strs[i]); ++ char *needle = strstr(to, line_continuation_strs[i]); ++ char *from; ++ size_t sz; ++ ++ if (!needle) ++ continue; ++ ++ found = true; ++ from = needle + cntsz; ++ sz = bufsz - (from - buf); ++ ++ to = needle; ++ memmove(to, from, sz); ++ } ++ } ++} ++ ++/* ++ * stresccspn: calculate the number of bytes which do not contain escape ++ * sequences. ++ * @buf: the buffer to search ++ * ++ * Returns the size of the initial segment of buf which does not contain ++ * any escape sequences. If no escape sequence is found, buf[return] will ++ * point to the NUL terminator. ++ */ ++size_t stresccspn(const char * const buf) ++{ ++ size_t span = strcspn(buf, "\\"); ++ ++ return span; ++} ++ ++/* ++ * escape_func: parse the value for one single escape character ++ * @delimiter: the delimiter as to which kind of escape sequence this is ++ * (i.e. 'x' for \x1abc) ++ * @buf: the buffer being parsed ++ * @val: the parsed value is placed in val ++ * @valsz: how many bytes of val are meaningful ++ * ++ * Returns the number of bytes of buf to advance to skip the escape ++ * sequence, including the delimiter character but not the initial escape ++ * character. If the initial segment of buf is not an escape sequence, ++ * *valsz and the return value will both be 0. ++ */ ++typedef size_t (*escape_func)(uint32_t delimiter, const char * const buf, ++ char val[9], size_t *valsz); ++ ++static size_t ++simple_escape_sequence(uint32_t delimiter, const char * const buf UNUSED, ++ char val[9], size_t *valsz) ++{ ++ val[0] = delimiter & 0xffu; ++ *valsz = 1; ++ ++ return 1; ++} ++ ++static size_t ++digits_escape_sequence(uint32_t delimiter, const char * const buf, ++ char val[2], size_t *valsz) ++{ ++ size_t span; ++ unsigned long long ul; ++ char tmpbuf[4] = { 0, }; ++ int base; ++ ++ if (delimiter == 'x') { ++ span = strspn(buf, hex_digits); ++ base = 16; ++ if (span > 2) ++ span = 2; ++ strncpy(tmpbuf, buf, span); ++ } else { ++ span = strspn(buf, octal_digits); ++ base = 8; ++ if (span > 2) ++ span = 2; ++ tmpbuf[0] = delimiter & 0xffu; ++ strncpy(&tmpbuf[1], buf, span); ++ span += 1; ++ } ++ if (span == 0) { ++ val[0] = delimiter & 0xffu; ++ *valsz = 1; ++ return 1; ++ } ++ ++ tmpbuf[span+1] = '\0'; ++ ul = strtoul(tmpbuf, NULL, base); ++ ++ val[0] = ul & 0xffu; ++ *valsz = 1; ++ ++ return span; ++} ++ ++struct escape_handler { ++ const char * const escapes; ++ escape_func func; ++}; ++static struct escape_handler escape_handlers[] = { ++ {.escapes = " \"\'\?\a\b\f\n\r\t\v\\", ++ .func = simple_escape_sequence }, ++ {.escapes = "x01234567", ++ .func = digits_escape_sequence }, ++ {.escapes = 0, ++ .func = NULL } ++}; ++ ++/* ++ * parse_escape: parses one escape string ++ * @buf: the buffer being parsed ++ * @val: the parsed value is placed in val ++ * @valsz: how many bytes of val are meaningful ++ * ++ * Returns the number of bytes of buf to advance to skip the escape ++ * sequence. If the initial segment of buf is not an escape sequence, ++ * *valsz and the return value will both be 0. ++ */ ++static size_t ++parse_escape(const char * const buf, char val[9], size_t *valsz) ++{ ++ struct escape_handler *eh = NULL; ++ ++ if (buf[0] != '\\') ++ return 0; ++ ++ for(size_t i = 0; escape_handlers[i].escapes != 0; i++) { ++ char *match; ++ eh = &escape_handlers[i]; ++ ++ match = strchrnul(eh->escapes, buf[1]); ++ if (match[0] != buf[1]) ++ continue; ++ } ++ if (eh && eh->func) ++ return eh->func(buf[1], &buf[2], val, valsz); ++ return 0; ++} ++ ++/* ++ * strescspn: calculate the size of an escape sequence. ++ * @buf: a NUL-terminated utf-8 buffer. ++ * ++ * returns the number of bytes which are part of a single escape sequence. ++ * If no escape sequnce can be parsed, returns 0. ++ */ ++size_t strescspn(const char * const buf) ++{ ++ size_t advance = 0, valsz = 0; ++ char val[9] = { 0, }; ++ ++ if (!buf[0] || buf[0] != '\\') ++ return 0; ++ ++ advance = parse_escape(&buf[1], val, &valsz); ++ if (advance == 0) { ++ /* ++ * If we come to illegal escape values like "\\xzz" then ++ * we just use the delimiter character (in this case 'x'), ++ * so the span here is 2. ++ */ ++ return 2; ++ } ++ return valsz + 1; ++} ++ ++/* ++ * resolve_escapes: parse all instances of escape sequences in buf ++ * @buf: the buffer to operate on ++ * ++ * Returns the size of buf once escape sequnces have been replaced. ++ */ ++size_t ++resolve_escapes(char *buf) ++{ ++ size_t to = 0; ++ for (size_t from = 0; buf[from]; from++) { ++ size_t advance, valsz = 0; ++ char val[9]; ++ if (buf[from] != '\\') { ++ buf[to++] = buf[from]; ++ continue; ++ } ++ ++ advance = parse_escape(&buf[from], val, &valsz); ++ if (advance == 0) { ++ /* ++ * If we come to illegal escape values like "\\xzz" ++ * then just move the '\\' out of the way... ++ */ ++ buf[to++] = buf[++from]; ++ continue; ++ } ++ ++ for (size_t j = 0; j < valsz; j++) ++ buf[to+j] = val[j]; ++ to += advance + 1; ++ } ++ buf[to++] = '\0'; ++ return to; ++} ++ ++// vim:fenc=utf-8:tw=75:noet +diff --git a/src/pesign.h b/src/pesign.h +index 9f80a9ad108..1b404223d31 100644 +--- a/src/pesign.h ++++ b/src/pesign.h +@@ -25,6 +25,7 @@ + #include + + #include "util.h" ++#include "text.h" + #include "cms_common.h" + #include "pesign_context.h" + +diff --git a/src/text.h b/src/text.h +new file mode 100644 +index 00000000000..e5722c7aee1 +--- /dev/null ++++ b/src/text.h +@@ -0,0 +1,53 @@ ++// SPDX-License-Identifier: GPLv2 ++/* ++ * text.c - helpers for text strings ++ * Copyright Peter Jones ++ */ ++#ifndef TEXT_H_ ++#define TEXT_H_ ++ ++#include ++ ++/* ++ * Characters that can be considered whitespace or end-of-line markers. ++ */ ++extern const char * const eol_chars; ++extern const char * const whitespace_and_eol_chars; ++ ++/* ++ * unbreak_line_coninutations: remove all line continuations ++ * @buf: the buffer to operate on ++ * @bufsz: the size of the buffer ++ */ ++extern void unbreak_line_continuations(char *buf, size_t bufsz); ++ ++/* ++ * strescspn: calculate the size of an escape sequence. ++ * @buf: a NUL-terminated utf-8 buffer. ++ * ++ * returns the number of bytes which are part of a single escape sequence. ++ * If no escape sequnce can be parsed, returns 0. ++ */ ++extern size_t strescspn(const char * const buf); ++ ++/* ++ * stresccspn: calculate the number of bytes which do not contain escape ++ * sequences. ++ * @buf: the buffer to search ++ * ++ * Returns the size of the initial segment of buf which does not contain ++ * any escape sequences. If no escape sequence is found, buf[return] will ++ * point to the NUL terminator. ++ */ ++extern size_t stresccspn(const char * const buf); ++ ++/* ++ * resolve_escapes: parse all instances of escape sequences in buf ++ * @buf: the buffer to operate on ++ * ++ * Returns the size of buf once escape sequnces have been replaced. ++ */ ++extern size_t resolve_escapes(char *buf); ++ ++#endif /* !TEXT_H_ */ ++// vim:fenc=utf-8:tw=75:noet +diff --git a/src/Makefile b/src/Makefile +index 74327ba13f3..dfdc7c5e4c5 100644 +--- a/src/Makefile ++++ b/src/Makefile +@@ -12,7 +12,7 @@ TARGETS=$(BINTARGETS) $(SVCTARGETS) + all : deps $(TARGETS) + + COMMON_SOURCES = cms_common.c content_info.c oid.c password.c \ +- signed_data.c signer_info.c ucs2.c ++ signed_data.c signer_info.c text.c ucs2.c + COMMON_PE_SOURCES = wincert.c cms_pe_common.c + AUTHVAR_SOURCES = authvar.c authvar_context.c + CLIENT_SOURCES = pesign_context.c actions.c client.c +-- +2.29.2 + diff --git a/0008-pesigcheck-Verify-with-the-cert-as-an-object-signer.patch b/0008-pesigcheck-Verify-with-the-cert-as-an-object-signer.patch deleted file mode 100644 index 2226498..0000000 --- a/0008-pesigcheck-Verify-with-the-cert-as-an-object-signer.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 2cd211bcc612ad8cb99c778461ca02a9f3e5e44b Mon Sep 17 00:00:00 2001 -From: David Michael -Date: Thu, 16 Feb 2017 15:08:30 -0800 -Subject: [PATCH 08/29] pesigcheck: Verify with the cert as an object signer - ---- - src/certdb.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/certdb.c b/src/certdb.c -index 2a08042..b7c99bb 100644 ---- a/src/certdb.c -+++ b/src/certdb.c -@@ -339,7 +339,7 @@ check_cert(pesigcheck_context *ctx, SECItem *sig, efi_guid_t *sigtype, - } - /* Verify the signature */ - result = SEC_PKCS7VerifyDetachedSignatureAtTime(cinfo, -- certUsageSSLServer, -+ certUsageObjectSigner, - digest, HASH_AlgSHA256, - PR_FALSE, atTime); - if (!result) { --- -2.13.4 - diff --git a/0009-libdpe-fix-some-minor-analyzer-discoveries.patch b/0009-libdpe-fix-some-minor-analyzer-discoveries.patch new file mode 100644 index 0000000..0174d86 --- /dev/null +++ b/0009-libdpe-fix-some-minor-analyzer-discoveries.patch @@ -0,0 +1,113 @@ +From d6787fbed0a1f993af6418c758c781361d553219 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 29 Apr 2020 18:23:30 -0400 +Subject: [PATCH 09/42] libdpe: fix some minor analyzer discoveries. + +I don't think we can meaningfully hit any of these in any use that +actually matters, but may as well fix them. + +Signed-off-by: Peter Jones +--- + libdpe/pe_begin.c | 3 +++ + libdpe/pe_getdatadir.c | 2 +- + libdpe/pe_opthdr.c | 12 ++++++------ + include/libdpe/libdpe.h | 4 ++-- + 4 files changed, 12 insertions(+), 9 deletions(-) + +diff --git a/libdpe/pe_begin.c b/libdpe/pe_begin.c +index 51189f8069c..3bcc2c70c61 100644 +--- a/libdpe/pe_begin.c ++++ b/libdpe/pe_begin.c +@@ -156,6 +156,9 @@ __libpe_read_mmapped_file(int fildes, void *map_address, size_t maxsize, + case PE_K_PE_EXE: + return file_read_pe_exe(fildes, map_address, p_ident, + maxsize, cmd, parent); ++ case PE_K_MZ: ++ errno = ENOSYS; ++ return NULL; + default: + break; + } +diff --git a/libdpe/pe_getdatadir.c b/libdpe/pe_getdatadir.c +index 08f46787304..f080f3a9998 100644 +--- a/libdpe/pe_getdatadir.c ++++ b/libdpe/pe_getdatadir.c +@@ -24,7 +24,7 @@ pe_getdatadir(Pe *pe, data_directory **dd) + { + int rc = -1; + +- if (!dd) { ++ if (!pe || !dd) { + __libpe_seterrno(PE_E_INVALID_INDEX); + return rc; + } +diff --git a/libdpe/pe_opthdr.c b/libdpe/pe_opthdr.c +index 02075e5cd49..ae74a897500 100644 +--- a/libdpe/pe_opthdr.c ++++ b/libdpe/pe_opthdr.c +@@ -32,7 +32,7 @@ pe_getopthdr(Pe *pe) + } + } + +-uint32_t ++int32_t + pe_get_file_alignment(Pe *pe) + { + struct pe32_opt_hdr *pe32opthdr = NULL; +@@ -42,12 +42,12 @@ pe_get_file_alignment(Pe *pe) + case PE_K_PE_EXE: { + void *opthdr = pe_getopthdr(pe); + pe32opthdr = opthdr; +- return pe32opthdr->file_align; ++ return pe32opthdr ? (int32_t)pe32opthdr->file_align : -1; + } + case PE_K_PE64_EXE: { + void *opthdr = pe_getopthdr(pe); + pe64opthdr = opthdr; +- return pe64opthdr->file_align; ++ return pe64opthdr ? (int32_t)pe64opthdr->file_align : -1; + break; + } + default: +@@ -56,7 +56,7 @@ pe_get_file_alignment(Pe *pe) + return -1; + } + +-uint32_t ++int32_t + pe_get_scn_alignment(Pe *pe) + { + struct pe32_opt_hdr *pe32opthdr = NULL; +@@ -66,12 +66,12 @@ pe_get_scn_alignment(Pe *pe) + case PE_K_PE_EXE: { + void *opthdr = pe_getopthdr(pe); + pe32opthdr = opthdr; +- return pe32opthdr->section_align; ++ return pe32opthdr ? (int32_t)pe32opthdr->section_align : -1; + } + case PE_K_PE64_EXE: { + void *opthdr = pe_getopthdr(pe); + pe64opthdr = opthdr; +- return pe64opthdr->section_align; ++ return pe64opthdr ? (int32_t)pe64opthdr->section_align : -1; + break; + } + default: +diff --git a/include/libdpe/libdpe.h b/include/libdpe/libdpe.h +index 09f56a2a05e..895a208fe7d 100644 +--- a/include/libdpe/libdpe.h ++++ b/include/libdpe/libdpe.h +@@ -87,8 +87,8 @@ extern struct pe_hdr *pe_getpehdr(Pe *pe, struct pe_hdr *pehdr); + extern char *pe_rawfile(Pe *pe, size_t *ptr); + extern int pe_getdatadir(Pe *pe, data_directory **dd); + extern void *pe_getopthdr(Pe *pe); +-extern uint32_t pe_get_file_alignment(Pe *pe); +-extern uint32_t pe_get_scn_alignment(Pe *pe); ++extern int32_t pe_get_file_alignment(Pe *pe); ++extern int32_t pe_get_scn_alignment(Pe *pe); + extern int pe_set_image_size(Pe *pe); + + extern int pe_extend_file(Pe *pe, size_t size, uint32_t *new_space, int align); +-- +2.29.2 + diff --git a/0009-pesigcheck-make-certfile-actually-work.patch b/0009-pesigcheck-make-certfile-actually-work.patch deleted file mode 100644 index 8b77417..0000000 --- a/0009-pesigcheck-make-certfile-actually-work.patch +++ /dev/null @@ -1,47 +0,0 @@ -From e0238e2363f9668aee07b2e44a8f358e694551c0 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 24 Apr 2017 15:18:10 -0400 -Subject: [PATCH 09/29] pesigcheck: make --certfile actually work - -Signed-off-by: Peter Jones ---- - src/pesigcheck.c | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - -diff --git a/src/pesigcheck.c b/src/pesigcheck.c -index 0d49c1a..d7be542 100644 ---- a/src/pesigcheck.c -+++ b/src/pesigcheck.c -@@ -130,7 +130,7 @@ check_signature(pesigcheck_context *ctx) - cert_iter iter; - - generate_digest(ctx->cms_ctx, ctx->inpe, 1); -- -+ - if (check_db_hash(DBX, ctx) == FOUND) - return -1; - -@@ -225,6 +225,11 @@ main(int argc, char *argv[]) - .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_POST, - .arg = (void *)callback, - .descrip = (void *)ctxp }, -+ {.longName = "certfile", -+ .shortName = 'c', -+ .argInfo = POPT_ARG_CALLBACK|POPT_CBFLAG_POST, -+ .arg = (void *)callback, -+ .descrip = (void *)ctxp }, - {.longName = "in", - .shortName = 'i', - .argInfo = POPT_ARG_STRING, -@@ -258,7 +263,7 @@ main(int argc, char *argv[]) - .shortName = 'c', - .argInfo = POPT_ARG_STRING, - .arg = &certfile, -- .descrip = "the certificate (in DER form) for verification ", -+ .descrip = "import certfile (in DER encoding) for allowed certificate", - .argDescrip = "" }, - POPT_AUTOALIAS - POPT_AUTOHELP --- -2.13.4 - diff --git a/0010-libdpe-check-for-NULL-pe-at-more-places.patch b/0010-libdpe-check-for-NULL-pe-at-more-places.patch new file mode 100644 index 0000000..f0e32fd --- /dev/null +++ b/0010-libdpe-check-for-NULL-pe-at-more-places.patch @@ -0,0 +1,132 @@ +From 8677eea21fc9b634b6b97e132a8c4295f2a9aa15 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 21 May 2020 14:27:01 -0400 +Subject: [PATCH 10/42] libdpe: check for NULL pe at more places. + +This isn't so much to fix a bug as to make "gcc -Wanalyze-..." output +smaller where these things are called. + +Signed-off-by: Peter Jones +--- + libdpe/pe_addcert.c | 17 +++++++++++++++++ + libdpe/pe_allocspace.c | 19 +++++++++++++++++++ + libdpe/libdpe_priv.h | 2 ++ + 3 files changed, 38 insertions(+) + +diff --git a/libdpe/pe_addcert.c b/libdpe/pe_addcert.c +index 803ed61f7f0..b1251992ade 100644 +--- a/libdpe/pe_addcert.c ++++ b/libdpe/pe_addcert.c +@@ -17,6 +17,7 @@ + * Author(s): Peter Jones + */ + #include ++ + #include "libdpe_priv.h" + + int +@@ -25,6 +26,11 @@ pe_clearcert(Pe *pe) + int rc; + data_directory *dd = NULL; + ++ if (!pe) { ++ errno = EINVAL; ++ return -1; ++ } ++ + rc = pe_getdatadir(pe, &dd); + if (rc < 0) + return rc; +@@ -43,6 +49,11 @@ pe_alloccert(Pe *pe, size_t size) + int rc; + data_directory *dd = NULL; + ++ if (!pe) { ++ errno = EINVAL; ++ return -1; ++ } ++ + pe_clearcert(pe); + + uint32_t new_space = 0; +@@ -69,6 +80,12 @@ pe_populatecert(Pe *pe, void *cert, size_t size) + { + int rc; + data_directory *dd = NULL; ++ ++ if (!pe) { ++ errno = EINVAL; ++ return -1; ++ } ++ + rc = pe_getdatadir(pe, &dd); + if (rc < 0) + return rc; +diff --git a/libdpe/pe_allocspace.c b/libdpe/pe_allocspace.c +index a2898f6d446..be704c52cf8 100644 +--- a/libdpe/pe_allocspace.c ++++ b/libdpe/pe_allocspace.c +@@ -56,6 +56,11 @@ pe_fix_addresses(Pe *pe, int64_t offset) + int + pe_set_image_size(Pe *pe) + { ++ if (!pe) { ++ errno = EINVAL; ++ return -1; ++ } ++ + uint32_t image_size = 0; + struct pe_hdr *pehdr = pe->state.pe.pehdr; + struct pe32plus_opt_hdr *opthdr = pe->state.pe32plus_exe.opthdr; +@@ -86,6 +91,11 @@ pe_set_image_size(Pe *pe) + int + pe_extend_file(Pe *pe, size_t size, uint32_t *new_space, int align) + { ++ if (!pe) { ++ errno = EINVAL; ++ return -1; ++ } ++ + void *new = NULL; + + if (align) +@@ -120,6 +130,10 @@ pe_shorten_file(Pe *pe, size_t size) + { + void *new = NULL; + ++ if (!pe) { ++ errno = EINVAL; ++ return -1; ++ } + new = mremap(pe->map_address, pe->maximum_size, + pe->maximum_size - size, 0); + if (new == MAP_FAILED) { +@@ -138,6 +152,11 @@ pe_shorten_file(Pe *pe, size_t size) + int + pe_freespace(Pe *pe, uint32_t offset, size_t size) + { ++ if (!pe) { ++ errno = EINVAL; ++ return -1; ++ } ++ + void *addr = compute_mem_addr(pe, offset); + memset(addr, '\0', size); + +diff --git a/libdpe/libdpe_priv.h b/libdpe/libdpe_priv.h +index 26e50498c1d..e207772097a 100644 +--- a/libdpe/libdpe_priv.h ++++ b/libdpe/libdpe_priv.h +@@ -19,7 +19,9 @@ + #ifndef LIBDPE_PRIV_H + #define LIBDPE_PRIV_H 1 + ++#include + #include ++ + #include "compiler.h" + #include "endian.h" + +-- +2.29.2 + diff --git a/0010-signerInfos-make-sure-err-is-always-initialized.patch b/0010-signerInfos-make-sure-err-is-always-initialized.patch deleted file mode 100644 index 08d1da7..0000000 --- a/0010-signerInfos-make-sure-err-is-always-initialized.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 799808b265ac6f82fa1268fd696d70357acce69c Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 25 Apr 2017 16:15:07 -0400 -Subject: [PATCH 10/29] signerInfos: make sure err is always initialized - -Signed-off-by: Peter Jones ---- - src/signed_data.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/signed_data.c b/src/signed_data.c -index 721db90..9e0af23 100644 ---- a/src/signed_data.c -+++ b/src/signed_data.c -@@ -132,7 +132,8 @@ int - generate_signerInfo_list(cms_context *cms, SpcSignerInfo ***signerInfo_list_p, SignerInfoType type) - { - SpcSignerInfo **signerInfo_list; -- int err, rc; -+ int err = 0; -+ int rc; - - if (!signerInfo_list_p) - return -1; --- -2.13.4 - diff --git a/0011-pesign-make-pesign-h-tell-you-the-file-name.patch b/0011-pesign-make-pesign-h-tell-you-the-file-name.patch deleted file mode 100644 index 3e15617..0000000 --- a/0011-pesign-make-pesign-h-tell-you-the-file-name.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 868b42b338d919917ea31cfbf0f96e9586947eaf Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 25 Apr 2017 16:23:36 -0400 -Subject: [PATCH 11/29] pesign: make "pesign -h" tell you the file name. - -Signed-off-by: Peter Jones ---- - src/pesign.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/pesign.c b/src/pesign.c -index 279a17a..5879cfc 100644 ---- a/src/pesign.c -+++ b/src/pesign.c -@@ -387,7 +387,7 @@ print_digest(pesign_context *pctx) - if (!ctx) - return; - -- printf("hash: "); -+ printf("%s ", pctx->infile); - int j = ctx->selected_digest; - for (unsigned int i = 0; i < ctx->digests[j].pe_digest->len; i++) - printf("%02x", --- -2.13.4 - diff --git a/0011-wincert-try-to-convince-the-gcc-analyzer-of-the-pain.patch b/0011-wincert-try-to-convince-the-gcc-analyzer-of-the-pain.patch new file mode 100644 index 0000000..f946508 --- /dev/null +++ b/0011-wincert-try-to-convince-the-gcc-analyzer-of-the-pain.patch @@ -0,0 +1,36 @@ +From b4de3e4891be5f4de2c9a19740fc48c3bc28c68f Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 21 May 2020 15:23:11 -0400 +Subject: [PATCH 11/42] wincert: try to convince the gcc analyzer of the + painfully obvious. + +Signed-off-by: Peter Jones +--- + src/wincert.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/src/wincert.c b/src/wincert.c +index 4ccf528efad..7c802d22025 100644 +--- a/src/wincert.c ++++ b/src/wincert.c +@@ -364,9 +364,16 @@ err: + if (signatures) { + for (i = 0; i < nsigs; i++) { + if (signatures[i]) { +- if (signatures[i]->data) ++ if (signatures[i]->data) /* <-- see below */ + free(signatures[i]->data); + free(signatures[i]); ++ /* ++ * in gcc-10.1.1-1.fc32 , -fanalyzer believes the test ++ * above is a use-after free. I really don't see how, ++ * but this somehow convinces it there's nothing wrong ++ * there. ++ */ ++ signatures[i] = NULL; + } + } + free(signatures); +-- +2.29.2 + diff --git a/0012-Add-coverity-build-scripts.patch b/0012-Add-coverity-build-scripts.patch deleted file mode 100644 index f3f0a89..0000000 --- a/0012-Add-coverity-build-scripts.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 95327e6d9bd4f70980acd8fd6c9524265990dc4d Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Wed, 10 May 2017 10:49:57 -0400 -Subject: [PATCH 12/29] Add coverity build scripts - -Signed-off-by: Peter Jones ---- - .gitignore | 1 + - Make.coverity | 37 +++++++++++++++++++++++++++++++++++++ - Make.defaults | 2 ++ - Make.rules | 4 ++++ - Makefile | 1 + - 5 files changed, 45 insertions(+) - create mode 100644 Make.coverity - -diff --git a/.gitignore b/.gitignore -index 1635ba2..847e172 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -12,3 +12,4 @@ - *.tar.* - *.rpm - core.* -+cov-int -diff --git a/Make.coverity b/Make.coverity -new file mode 100644 -index 0000000..b80b091 ---- /dev/null -+++ b/Make.coverity -@@ -0,0 +1,37 @@ -+include $(TOPDIR)/Make.version -+include $(TOPDIR)/Make.rules -+include $(TOPDIR)/Make.defaults -+ -+COV_EMAIL=$(call get-config,coverity.email) -+COV_TOKEN=$(call get-config,coverity.token) -+COV_URL=$(call get-config,coverity.url) -+COV_FILE=$(NAME)-coverity-$(VERSION)-$(COMMIT_ID).tar.bz2 -+ -+cov-int : clean -+ cov-build --dir cov-int make all -+ -+cov-clean : -+ @rm -vf $(NAME)-coverity-*.tar.* -+ @if [[ -d cov-int ]]; then rm -rf cov-int && echo "removed 'cov-int'"; fi -+ -+cov-file : | $(COV_FILE) -+ -+$(COV_FILE) : cov-int -+ tar caf $@ cov-int -+ -+cov-upload : -+ @if [[ -n "$(COV_URL)" ]] && \ -+ [[ -n "$(COV_TOKEN)" ]] && \ -+ [[ -n "$(COV_EMAIL)" ]] ; \ -+ then \ -+ echo curl --form token=$(COV_TOKEN) --form email="$(COV_EMAIL)" --form file=@"$(COV_FILE)" --form version=$(VERSION).1 --form description="$(COMMIT_ID)" "$(COV_URL)" ; \ -+ curl --form token=$(COV_TOKEN) --form email="$(COV_EMAIL)" --form file=@"$(COV_FILE)" --form version=$(VERSION).1 --form description="$(COMMIT_ID)" "$(COV_URL)" ; \ -+ else \ -+ echo Coverity output is in $(COV_FILE) ; \ -+ fi -+ -+coverity : cov-file cov-upload -+ -+clean : | cov-clean -+ -+.PHONY : coverity cov-upload cov-clean cov-file -diff --git a/Make.defaults b/Make.defaults -index 3511080..39b78f0 100644 ---- a/Make.defaults -+++ b/Make.defaults -@@ -1,3 +1,5 @@ -+NAME = pesign -+COMMIT_ID ?= $(shell git log -1 --pretty=%H 2>/dev/null || echo master) - prefix ?= /usr/ - prefix := $(abspath $(prefix))/ - libdir ?= $(prefix)lib64/ -diff --git a/Make.rules b/Make.rules -index af5ecfe..5e3c83d 100644 ---- a/Make.rules -+++ b/Make.rules -@@ -79,3 +79,7 @@ endef - - $(TOPDIR)/libdpe/%.a $(TOPDIR)/libdpe/% : - $(MAKE) -C $(TOPDIR)/libdpe $(notdir $@) -+ -+define get-config = -+$(shell git config --local --get "$(NAME).$(1)") -+endef -diff --git a/Makefile b/Makefile -index db8eb7e..ca1a359 100644 ---- a/Makefile -+++ b/Makefile -@@ -4,6 +4,7 @@ TOPDIR = $(realpath .) - include $(TOPDIR)/Make.version - include $(TOPDIR)/Make.rules - include $(TOPDIR)/Make.defaults -+include $(TOPDIR)/Make.coverity - - SUBDIRS := include libdpe src - --- -2.13.4 - diff --git a/0012-Fix-a-missing-malloc-return-value-check.patch b/0012-Fix-a-missing-malloc-return-value-check.patch new file mode 100644 index 0000000..a380aef --- /dev/null +++ b/0012-Fix-a-missing-malloc-return-value-check.patch @@ -0,0 +1,26 @@ +From 998e825efd44d3f5098022537f7967c24d208841 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 5 Jun 2020 10:20:30 -0400 +Subject: [PATCH 12/42] Fix a missing malloc() return value check. + +Signed-off-by: Peter Jones +--- + src/pesigcheck.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/pesigcheck.c b/src/pesigcheck.c +index 8fa0f1ad03d..961a32a6ad7 100644 +--- a/src/pesigcheck.c ++++ b/src/pesigcheck.c +@@ -116,6 +116,8 @@ cert_matches_digest(pesigcheck_context *ctx, void *data, ssize_t datalen, + digest = content->data + content->len - pe_digest->len; + if (digest_out) { + digest_out->data = malloc(pe_digest->len); ++ if (!digest_out->data) ++ goto out; + digest_out->len = pe_digest->len; + digest_out->type = pe_digest->type; + memcpy(digest_out->data, digest, pe_digest->len); +-- +2.29.2 + diff --git a/0013-Document-implicit-fallthrough.patch b/0013-Document-implicit-fallthrough.patch deleted file mode 100644 index 3731a3f..0000000 --- a/0013-Document-implicit-fallthrough.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 4b9e7cf3e869de36daf2ea705b9efef55ae87ef8 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Sat, 8 Jul 2017 16:31:18 -0400 -Subject: [PATCH 13/29] Document implicit fallthrough. - -Signed-off-by: Peter Jones ---- - src/authvar.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/authvar.c b/src/authvar.c -index ad659ca..03e0c47 100644 ---- a/src/authvar.c -+++ b/src/authvar.c -@@ -511,6 +511,7 @@ main(int argc, char *argv[]) - case IMPORT|SET: - case IMPORT|SIGN|SET: - fprintf(stderr, "authvar: not implemented\n"); -+ /* fallthrough. */ - case IMPORT|SIGN|EXPORT: - default: - fprintf(stderr, "authvar: invalid flags: "); --- -2.13.4 - diff --git a/0013-Fix-some-missed-OOM-error-path-fanalyzer-found.patch b/0013-Fix-some-missed-OOM-error-path-fanalyzer-found.patch new file mode 100644 index 0000000..2451c9c --- /dev/null +++ b/0013-Fix-some-missed-OOM-error-path-fanalyzer-found.patch @@ -0,0 +1,67 @@ +From 1f81f3ec196365d6bdf490d05776ba7a4e0257b0 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 21 May 2020 15:23:54 -0400 +Subject: [PATCH 13/42] Fix some missed OOM error path -fanalyzer found. + +Amazingly, it seems to find more *real* problems (surprisingly) *and* +present them more readably (not surprisingly at all) without -flto. + +Signed-off-by: Peter Jones +--- + src/actions.c | 19 +++++++++---------- + 1 file changed, 9 insertions(+), 10 deletions(-) + +diff --git a/src/actions.c b/src/actions.c +index 69f9e3e1c1a..d0f538e81d4 100644 +--- a/src/actions.c ++++ b/src/actions.c +@@ -68,8 +68,8 @@ insert_signature(cms_context *cms, int signum) + sizeof (SECItem *) * (cms->num_signatures + 1)); + if (!signatures) { + err: +- cms->log(cms, LOG_ERR, "insert signature: could not allocate " +- "memory: %m"); ++ cms->log(cms, LOG_ERR, ++ "insert signature: could not allocate memory: %m"); + exit(1); + } + cms->signatures = signatures; +@@ -80,6 +80,9 @@ err: + } + + SECItem *newsig = malloc(sizeof (*newsig)); ++ if (!newsig) ++ goto err; ++ + memcpy(newsig, sig, sizeof (*newsig)); + newsig->data = malloc(sig->len); + if (!newsig->data) +@@ -293,10 +296,8 @@ parse_signature(pesign_context *ctx) + size_t siglen; + + rc = read_file(ctx->insigfd, &sig, &siglen); +- if (rc < 0) { +- fprintf(stderr, "pesign: could not read signature.\n"); +- exit(1); +- } ++ if (rc < 0) ++ liberr(1, "pesign: could not read signature"); + + unsigned char *der; + unsigned int derlen; +@@ -306,10 +307,8 @@ parse_signature(pesign_context *ctx) + if (base64) { + base64 += strlen(sig_begin_marker); + char *end = strstr(base64, sig_end_marker); +- if (!end) { +- fprintf(stderr, "pesign: Invalid signature.\n"); +- exit(1); +- } ++ if (!end) ++ liberr(1, "pesign: Invalid signature"); + + derlen = end - base64; + base64[derlen] = '\0'; +-- +2.29.2 + diff --git a/0014-Actually-setfacl-each-directory-of-our-key-storage.patch b/0014-Actually-setfacl-each-directory-of-our-key-storage.patch deleted file mode 100644 index 4b62cb3..0000000 --- a/0014-Actually-setfacl-each-directory-of-our-key-storage.patch +++ /dev/null @@ -1,50 +0,0 @@ -From a95e28e5cb10d417c81c8720e8521eb63793da37 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 16 May 2016 15:25:53 -0400 -Subject: [PATCH 14/29] Actually setfacl /each/ directory of our key storage. - -Signed-off-by: Peter Jones ---- - src/pesign-authorize-groups | 6 +++--- - src/pesign-authorize-users | 6 +++--- - 2 files changed, 6 insertions(+), 6 deletions(-) - -diff --git a/src/pesign-authorize-groups b/src/pesign-authorize-groups -index a4f895e..cf51fb6 100644 ---- a/src/pesign-authorize-groups -+++ b/src/pesign-authorize-groups -@@ -18,10 +18,10 @@ if [ -r /etc/pesign/groups ]; then - setfacl -m g:${group}:rw /var/run/pesign/socket - fi - fi -- for x in /etc/pki/pesign* ; do -+ for x in /etc/pki/pesign*/ ; do - if [ -d ${x} ]; then -- setfacl -m g:${group}:rx /etc/pki/pesign -- for y in ${x}/{cert8,key3,secmod}.db ; do -+ setfacl -m g:${group}:rx ${x} -+ for y in ${x}{cert8,key3,secmod}.db ; do - setfacl -m g:${group}:rw ${y} - done - fi -diff --git a/src/pesign-authorize-users b/src/pesign-authorize-users -index 8b9a885..940138e 100644 ---- a/src/pesign-authorize-users -+++ b/src/pesign-authorize-users -@@ -18,10 +18,10 @@ if [ -r /etc/pesign/users ]; then - setfacl -m g:${username}:rw /var/run/pesign/socket - fi - fi -- for x in /etc/pki/pesign* ; do -+ for x in /etc/pki/pesign*/ ; do - if [ -d ${x} ]; then -- setfacl -m g:${username}:rx /etc/pki/pesign -- for y in ${x}/{cert8,key3,secmod}.db ; do -+ setfacl -m g:${username}:rx ${x} -+ for y in ${x}{cert8,key3,secmod}.db ; do - setfacl -m g:${username}:rw ${y} - done - fi --- -2.13.4 - diff --git a/0014-Don-t-allow-or-require-module-or-kernel-with-ca.patch b/0014-Don-t-allow-or-require-module-or-kernel-with-ca.patch new file mode 100644 index 0000000..cb7e17f --- /dev/null +++ b/0014-Don-t-allow-or-require-module-or-kernel-with-ca.patch @@ -0,0 +1,189 @@ +From d14dce18a8fa31e2097d99a717d87b23539b9098 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Wed, 15 May 2019 15:55:17 -0400 +Subject: [PATCH 14/42] Don't allow (or require) --module or --kernel with + --ca. + +If you're doing a CA/signer split setup, the CA shouldn't be allowed to +sign things other than other certificates. + +Signed-off-by: Peter Jones +--- + src/efikeygen.c | 55 ++++++++++++++++++++++++++++++++----------------- + src/efikeygen.1 | 6 ++++-- + 2 files changed, 40 insertions(+), 21 deletions(-) + +diff --git a/src/efikeygen.c b/src/efikeygen.c +index 848480a9b01..b8b0c961739 100644 +--- a/src/efikeygen.c ++++ b/src/efikeygen.c +@@ -54,6 +54,13 @@ + #include "cms_common.h" + #include "oid.h" + ++enum { ++ MODSIGN_EKU_NONE, ++ MODSIGN_EKU_KERNEL, ++ MODSIGN_EKU_MODULE, ++ MODSIGN_EKU_CA ++}; ++ + typedef struct { + SECItem data; + SECAlgorithmID keytype; +@@ -183,8 +190,7 @@ add_key_usage(cms_context *cms, void *extHandle, int is_ca) + + if (is_ca) { + usage = KU_KEY_CERT_SIGN | +- KU_CRL_SIGN | +- KU_DIGITAL_SIGNATURE; ++ KU_CRL_SIGN; + } else { + usage = KU_KEY_ENCIPHERMENT | + KU_DATA_ENCIPHERMENT | +@@ -252,7 +258,7 @@ add_basic_constraints(cms_context *cms, void *extHandle) + } + + static int +-add_extended_key_usage(cms_context *cms, int modsign_only, void *extHandle) ++add_extended_key_usage(cms_context *cms, int modsign_eku, void *extHandle) + { + SECItem values[2]; + SECItem wrapped = { 0 }; +@@ -260,7 +266,11 @@ add_extended_key_usage(cms_context *cms, int modsign_only, void *extHandle) + SECOidTag tag; + int rc; + +- if (modsign_only < 1 || modsign_only > 2) ++ if (modsign_eku == MODSIGN_EKU_CA) ++ return 0; ++ ++ if (modsign_eku != MODSIGN_EKU_KERNEL ++ && modsign_eku != MODSIGN_EKU_MODULE) + cmsreterr(-1, cms, "could not encode extended key usage"); + + rc = make_eku_oid(cms, &values[0], SEC_OID_EXT_KEY_USAGE_CODE_SIGN); +@@ -273,11 +283,10 @@ add_extended_key_usage(cms_context *cms, int modsign_only, void *extHandle) + if (rc < 0) + cmsreterr(-1, cms, "could not encode extended key usage"); + +- rc = wrap_in_seq(cms, &wrapped, values, modsign_only); ++ rc = wrap_in_seq(cms, &wrapped, values, modsign_eku); + if (rc < 0) + cmsreterr(-1, cms, "could not encode extended key usage"); + +- + status = CERT_AddExtension(extHandle, SEC_OID_X509_EXT_KEY_USAGE, + &wrapped, PR_FALSE, PR_TRUE); + if (status != SECSuccess) +@@ -311,7 +320,7 @@ static int + add_extensions_to_crq(cms_context *cms, CERTCertificateRequest *crq, + int is_ca, int is_self_signed, SECKEYPublicKey *pubkey, + SECKEYPublicKey *spubkey, +- char *url, int modsign_only) ++ char *url, int modsign_eku) + { + void *mark = PORT_ArenaMark(cms->arena); + +@@ -336,7 +345,7 @@ add_extensions_to_crq(cms_context *cms, CERTCertificateRequest *crq, + if (rc < 0) + cmsreterr(-1, cms, "could not generate certificate extensions"); + +- rc = add_extended_key_usage(cms, modsign_only, extHandle); ++ rc = add_extended_key_usage(cms, modsign_eku, extHandle); + if (rc < 0) + cmsreterr(-1, cms, "could not generate certificate extensions"); + +@@ -486,7 +495,7 @@ int main(int argc, char *argv[]) + { + int is_ca = 0; + int is_self_signed = -1; +- int modsign_only = 0; ++ int modsign_eku = MODSIGN_EKU_NONE; + char *tokenname = "NSS Certificate DB"; + char *signer = NULL; + char *nickname = NULL; +@@ -543,14 +552,14 @@ int main(int argc, char *argv[]) + {.longName = "kernel", + .shortName = 'k', + .argInfo = POPT_ARG_VAL|POPT_ARGFLAG_OR, +- .arg = &modsign_only, +- .val = 1, ++ .arg = &modsign_eku, ++ .val = MODSIGN_EKU_KERNEL, + .descrip = "Generate a kernel-signing certificate" }, + {.longName = "module", + .shortName = 'm', + .argInfo = POPT_ARG_VAL|POPT_ARGFLAG_OR, +- .arg = &modsign_only, +- .val = 2, ++ .arg = &modsign_eku, ++ .val = MODSIGN_EKU_MODULE, + .descrip = "Generate a module-signing certificate" }, + {.longName = "nickname", + .shortName = 'n', +@@ -622,10 +631,12 @@ int main(int argc, char *argv[]) + /* + * Scenarios that are okay (x == valid combination) + * +- * is_ca is_self_signed pubkey +- * i_c x x x +- * i_s_s x x o +- * pubkey x o o ++ * is_ca is_self_signed pubkey modules kernel ++ * i_c x x x o o ++ * i_s_s x x o o o ++ * pubkey x o x x x ++ * modules o x x x x ++ * kernel o x x x x + */ + + if (is_self_signed == -1) +@@ -660,8 +671,14 @@ int main(int argc, char *argv[]) + liberr(1, "could not allocate cms context"); + } + +- if (modsign_only < 1 || modsign_only > 2) ++ if (is_ca) { ++ if (modsign_eku != MODSIGN_EKU_NONE) ++ errx(1, "CA certificates cannot have kernel or module signing credentials."); ++ modsign_eku = MODSIGN_EKU_CA; ++ } else if (modsign_eku != MODSIGN_EKU_KERNEL ++ && modsign_eku != MODSIGN_EKU_MODULE) { + errx(1, "either --kernel or --module must be used"); ++ } + + SECStatus status = NSS_InitReadWrite(dbdir); + if (status != SECSuccess) +@@ -752,7 +769,7 @@ int main(int argc, char *argv[]) + crq = CERT_CreateCertificateRequest(name, spki, &attributes); + + rc = add_extensions_to_crq(cms, crq, is_ca, is_self_signed, pubkey, +- spubkey, url, modsign_only); ++ spubkey, url, modsign_eku); + if (rc < 0) + exit(1); + +diff --git a/src/efikeygen.1 b/src/efikeygen.1 +index 255fadc3979..88ee7c2f7c0 100644 +--- a/src/efikeygen.1 ++++ b/src/efikeygen.1 +@@ -33,11 +33,13 @@ Nickname of certificate to be used to sign the generated certificate. + + .TP + \fB-\-kernel\fR +-The generated certificate is to be used to sign kernels. ++The generated certificate is to be used to sign kernels. Not to be used for CA ++certificates. + + .TP + \fB-\-module\fR +-The generated certificate is to be used to sign kernel modules. ++The generated certificate is to be used to sign kernel modules. Not to be used ++for CA certificates. + + .TP + \fB-\-token\fR=\fItoken\fR +-- +2.29.2 + diff --git a/0015-Add-super-convenient-errno-guard-implementation.patch b/0015-Add-super-convenient-errno-guard-implementation.patch new file mode 100644 index 0000000..7e43d2b --- /dev/null +++ b/0015-Add-super-convenient-errno-guard-implementation.patch @@ -0,0 +1,331 @@ +From af3e0b8857825d68dde9661b74c382279e90c512 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 17 May 2019 13:47:14 -0400 +Subject: [PATCH 15/42] Add super convenient errno-guard implementation. + +This confuses the gcc analyzer either less or far more than +save_errno()'s fire-once loop. + +Signed-off-by: Peter Jones +--- + src/certdb.c | 32 ++++++++++++++--------- + src/cms_common.c | 4 ++- + src/efikeygen.c | 1 + + src/errno-guard.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++ + src/errno-guard.h | 26 +++++++++++++++++++ + src/pesigcheck.h | 1 + + src/pesign.h | 2 ++ + src/util.h | 19 ++++---------- + src/Makefile | 9 +++++-- + 9 files changed, 131 insertions(+), 29 deletions(-) + create mode 100644 src/errno-guard.c + create mode 100644 src/errno-guard.h + +diff --git a/src/certdb.c b/src/certdb.c +index 9a4aae45f1d..f1eee3bf490 100644 +--- a/src/certdb.c ++++ b/src/certdb.c +@@ -40,21 +40,23 @@ add_db_file(pesigcheck_context *ctx, db_specifier which, const char *dbfile, + db_f_type type) + { + dblist *db = calloc(1, sizeof (dblist)); ++ int errno_guard; + + if (!db) + return -1; + + db->type = type; + db->fd = open(dbfile, O_RDONLY); ++ set_errno_guard_with_override(&errno_guard); + if (db->fd < 0) { +- save_errno(free(db)); ++ free(db); + return -1; + } + + char *path = strdup(dbfile); + if (!path) { +- save_errno(close(db->fd); +- free(db)); ++ override_errno_guard(&errno_guard, errno); ++ free(db); + return -1; + } + +@@ -62,17 +64,19 @@ add_db_file(pesigcheck_context *ctx, db_specifier which, const char *dbfile, + db->path = strdup(db->path); + free(path); + if (!db->path) { +- save_errno(close(db->fd); +- free(db)); ++ override_errno_guard(&errno_guard, errno); ++ close(db->fd); ++ free(db); + return -1; + } + + struct stat sb; + int rc = fstat(db->fd, &sb); + if (rc < 0) { +- save_errno(close(db->fd); +- free(db->path); +- free(db)); ++ override_errno_guard(&errno_guard, errno); ++ close(db->fd); ++ free(db->path); ++ free(db); + return -1; + } + db->size = sb.st_size; +@@ -83,9 +87,10 @@ add_db_file(pesigcheck_context *ctx, db_specifier which, const char *dbfile, + size_t sz = 0; + rc = read_file(db->fd, (char **)&db->map, &sz); + if (rc < 0) { +- save_errno(close(db->fd); +- free(db->path); +- free(db)); ++ override_errno_guard(&errno_guard, errno); ++ close(db->fd); ++ free(db->path); ++ free(db); + return -1; + } + } +@@ -108,8 +113,10 @@ add_db_file(pesigcheck_context *ctx, db_specifier which, const char *dbfile, + db->datalen = db->size + sizeof(EFI_SIGNATURE_LIST) + + sizeof(efi_guid_t); + db->data = calloc(1, db->datalen); +- if (!db->data) ++ if (!db->data) { ++ override_errno_guard(&errno_guard, errno); + return -1; ++ } + + certlist = (EFI_SIGNATURE_LIST *)db->data; + memcpy((void *)&certlist->SignatureType, &efi_x509, sizeof(efi_guid_t)); +@@ -129,6 +136,7 @@ add_db_file(pesigcheck_context *ctx, db_specifier which, const char *dbfile, + db->next = *tmp; + *tmp = db; + ++ override_errno_guard(&errno_guard, 0); + return 0; + } + +diff --git a/src/cms_common.c b/src/cms_common.c +index d13b2cb0f33..17f7bf252c7 100644 +--- a/src/cms_common.c ++++ b/src/cms_common.c +@@ -241,7 +241,9 @@ cms_context_alloc(cms_context **cmsp) + + int rc = cms_context_init(cms); + if (rc < 0) { +- save_errno(free(cms)); ++ set_errno_guard(); ++ xfree(cms); ++ cms = NULL; + return -1; + } + *cmsp = cms; +diff --git a/src/efikeygen.c b/src/efikeygen.c +index b8b0c961739..ac2ce45a420 100644 +--- a/src/efikeygen.c ++++ b/src/efikeygen.c +@@ -52,6 +52,7 @@ + + #include "util.h" + #include "cms_common.h" ++#include "errno-guard.h" + #include "oid.h" + + enum { +diff --git a/src/errno-guard.c b/src/errno-guard.c +new file mode 100644 +index 00000000000..331692d8d70 +--- /dev/null ++++ b/src/errno-guard.c +@@ -0,0 +1,66 @@ ++/* ++ * errno-guard.c ++ * Copyright 2019 Peter Jones ++ * ++ */ ++#ifndef _GNU_SOURCE ++#define _GNU_SOURCE ++#endif ++ ++#include ++#include ++ ++#include "compiler.h" ++#include "errno-guard.h" ++ ++__thread int errno_guards_[ERRNO_GUARD_ENTRIES_]; ++__thread int errno_guard_no_ = -1; ++ ++void ++clean_up_errno_guard_(int *handle) ++{ ++ if (*handle < 0 ++ || *handle >= ERRNO_GUARD_ENTRIES_ ++ || *handle > errno_guard_no_) ++ return; ++ ++ if (errno_guards_[*handle] >= 0) { ++ errno = errno_guards_[*handle]; ++ errno_guard_no_ = *handle - 1; ++ } ++ *handle = -1; ++} ++ ++int ++set_up_errno_guard_(int *handle) ++{ ++ int guard_var = ++errno_guard_no_; ++ ++ if (guard_var < ERRNO_GUARD_ENTRIES_) ++ errno_guards_[guard_var] = errno; ++ ++ if (handle) ++ *handle = guard_var; ++ return guard_var; ++} ++ ++int ++override_errno_guard(int *handle, int error) ++{ ++ if (handle == NULL ++ || *handle < 0 ++ || *handle >= ERRNO_GUARD_ENTRIES_) ++ return -1; ++ ++ if (*handle > errno_guard_no_) { ++ *handle = -1; ++ return -1; ++ } ++ ++ errno = error; ++ errno_guard_no_ = *handle; ++ ++ return *handle; ++} ++ ++// vim:fenc=utf-8:tw=75:noet +diff --git a/src/errno-guard.h b/src/errno-guard.h +new file mode 100644 +index 00000000000..e413cec95a4 +--- /dev/null ++++ b/src/errno-guard.h +@@ -0,0 +1,26 @@ ++/* ++ * errno-guard.h ++ * Copyright 2019 Peter Jones ++ */ ++ ++#ifndef ERRNO_GUARD_H_ ++#define ERRNO_GUARD_H_ ++ ++#define ERRNO_GUARD_ENTRIES_ ((int)(4096 / sizeof(int))) ++ ++extern __thread int errno_guards_[ERRNO_GUARD_ENTRIES_]; ++extern __thread int errno_guard_no_; ++ ++extern void clean_up_errno_guard_(int *handle); ++extern int set_up_errno_guard_(int *handle); ++ ++#define guard_errno_(handle, guard_var) \ ++ CLEANUP_FUNC(clean_up_errno_guard_) UNUSED int guard_var = set_up_errno_guard_(handle) ++#define errno_guard_var_ CAT(CAT(CAT(CAT(errno_guard_,__LINE__),_),__COUNTER__),_) ++ ++extern int override_errno_guard(int *handle, int error); ++#define set_errno_guard() guard_errno_(NULL, errno_guard_var_) ++#define set_errno_guard_with_override(handle) guard_errno_(handle, errno_guard_var_) ++ ++#endif /* !ERRNO_GUARD_H_ */ ++// vim:fenc=utf-8:tw=75:noet +diff --git a/src/pesigcheck.h b/src/pesigcheck.h +index 20e8040cc06..e4dbe54c59a 100644 +--- a/src/pesigcheck.h ++++ b/src/pesigcheck.h +@@ -29,6 +29,7 @@ + #include "certdb.h" + + #include "endian.h" ++#include "errno-guard.h" + #include "oid.h" + #include "wincert.h" + #include "content_info.h" +diff --git a/src/pesign.h b/src/pesign.h +index 1b404223d31..91d30b57c02 100644 +--- a/src/pesign.h ++++ b/src/pesign.h +@@ -32,7 +32,9 @@ + #include "daemon.h" + #include "efitypes.h" + #include "actions.h" ++#include "errno-guard.h" + #include "endian.h" ++#include "errno-guard.h" + #include "oid.h" + #include "wincert.h" + #include "content_info.h" +diff --git a/src/util.h b/src/util.h +index 362c3559293..1b115a993f6 100644 +--- a/src/util.h ++++ b/src/util.h +@@ -23,9 +23,8 @@ + #include + #include + #include +-#include + #include +-#include ++#include + + #include + +@@ -40,18 +39,10 @@ + #define xstrdup(s) ({ void *p_ = strdup(s); if (!p_) liberr(1, "Could not allocate memory"); p_; }) + #define xpfstat(path, fd, sb) ({ int rc_ = fstat(fd, sb); if (rc_ < 0) liberr(1, "Could not stat \"%s\"", path); }) + +-#define save_errno(x) \ +- ({ \ +- typeof (errno) __saved_errno = errno; \ +- x; \ +- errno = __saved_errno; \ +- }) +-#define save_pe_errno(x) \ +- ({ \ +- typeof (errno) __saved_errno = pe_errno(); \ +- x; \ +- __libpe_seterrno(__saved_errno); \ +- }) ++#define saved_errno_0_ CONCATENATE(CONCATENATE(error_,__LINE__),_0_) ++#define saved_errno_1_ CONCATENATE(CONCATENATE(error_,__LINE__),_1_) ++#define save_pe_errno() \ ++ for (int saved_errno_0_ = 0, saved_errno_1_ = pe_errno(); saved_errno_0_ < 1; saved_errno_0_++, __libdpe_seterrno(saved_errno_1_)) + + #define conderr(cond, val, fmt, args...) ({ \ + if (cond) \ +diff --git a/src/Makefile b/src/Makefile +index dfdc7c5e4c5..bc3e5931456 100644 +--- a/src/Makefile ++++ b/src/Makefile +@@ -11,8 +11,13 @@ TARGETS=$(BINTARGETS) $(SVCTARGETS) + + all : deps $(TARGETS) + +-COMMON_SOURCES = cms_common.c content_info.c oid.c password.c \ +- signed_data.c signer_info.c text.c ucs2.c ++COMMON_SOURCES = cms_common.c content_info.c \ ++ errno-guard.c \ ++ oid.c \ ++ password.c \ ++ signed_data.c signer_info.c \ ++ text.c \ ++ ucs2.c + COMMON_PE_SOURCES = wincert.c cms_pe_common.c + AUTHVAR_SOURCES = authvar.c authvar_context.c + CLIENT_SOURCES = pesign_context.c actions.c client.c +-- +2.29.2 + diff --git a/0015-oid-add-SHIM_EKU_MODULE_SIGNING_ONLY-and-fix-our-arr.patch b/0015-oid-add-SHIM_EKU_MODULE_SIGNING_ONLY-and-fix-our-arr.patch deleted file mode 100644 index d5428b5..0000000 --- a/0015-oid-add-SHIM_EKU_MODULE_SIGNING_ONLY-and-fix-our-arr.patch +++ /dev/null @@ -1,59 +0,0 @@ -From a3cc2ad5d49ed61187527281da351e80d8f76a89 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 22 Aug 2016 13:31:38 -0400 -Subject: [PATCH 15/29] oid: add SHIM_EKU_MODULE_SIGNING_ONLY and fix our array - indices. - -That was all kinds of wrong. - -Signed-off-by: Peter Jones ---- - src/oid.c | 10 +++++++--- - src/oid.h | 1 + - 2 files changed, 8 insertions(+), 3 deletions(-) - -diff --git a/src/oid.c b/src/oid.c -index 9d8154f..7037e1e 100644 ---- a/src/oid.c -+++ b/src/oid.c -@@ -33,6 +33,7 @@ static uint8_t oiddata[] = { - 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x0f, - 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x15, - 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x01, -+ 0x2b, 0x06, 0x01, 0x04, 0x01, 0x92, 0x08, 0x10, 0x01, 0x02, - }; - - #define OID(num, desc_s, oidtype, length, value) \ -@@ -53,11 +54,14 @@ static struct { - OID(SPC_STATEMENT_TYPE_OBJID, "Statement Type", siDEROID, 10, - &oiddata[10]), - OID(SPC_PE_IMAGE_DATA_OBJID, "PE Image Data", siDEROID, 10, -- &oiddata[30]), -+ &oiddata[20]), - OID(SPC_INDIVIDUAL_SP_KEY_PURPOSE_OBJID, "Individual Key", siDEROID, -- 10, &oiddata[40]), -+ 10, &oiddata[30]), - OID(szOID_CERTSRV_CA_VERSION, "Certification server CA version", -- siAsciiString, 9, &oiddata[50]), -+ siAsciiString, 9, &oiddata[40]), -+ OID(SHIM_EKU_MODULE_SIGNING_ONLY, -+ "Certificate is used for kernel modules only", siDEROID, 10, -+ &oiddata[49]), - { .oid = END_OID_LIST } - }; - -diff --git a/src/oid.h b/src/oid.h -index 599f49d..0e00781 100644 ---- a/src/oid.h -+++ b/src/oid.h -@@ -25,6 +25,7 @@ typedef enum { - SPC_PE_IMAGE_DATA_OBJID, /* 1.3.6.1.4.1.311.2.1.15 */ - SPC_INDIVIDUAL_SP_KEY_PURPOSE_OBJID, /* 1.3.6.1.4.1.311.2.1.21 */ - szOID_CERTSRV_CA_VERSION, /* 1.3.6.1.4.1.311.21.1 */ -+ SHIM_EKU_MODULE_SIGNING_ONLY, /* 1.3.6.1.4.1.2312.16.1.2 */ - END_OID_LIST - } ms_oid_t; - --- -2.13.4 - diff --git a/0016-Make-save_port_err-saner-to-read.patch b/0016-Make-save_port_err-saner-to-read.patch new file mode 100644 index 0000000..713cbc2 --- /dev/null +++ b/0016-Make-save_port_err-saner-to-read.patch @@ -0,0 +1,343 @@ +From d2b39d942ab696d8aaf11280f4b037142ebc3643 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 17 May 2019 14:04:48 -0400 +Subject: [PATCH 16/42] Make save_port_err() { } saner to read. + +Signed-off-by: Peter Jones +--- + src/cms_common.c | 65 ++++++++++++++++++++++++++++++++++------------- + src/signed_data.c | 39 ++++++++++++++++++++-------- + src/cms_common.h | 14 +++++----- + 3 files changed, 83 insertions(+), 35 deletions(-) + +diff --git a/src/cms_common.c b/src/cms_common.c +index 17f7bf252c7..9218f69ef9e 100644 +--- a/src/cms_common.c ++++ b/src/cms_common.c +@@ -350,7 +350,9 @@ unlock_nss_token(cms_context *cms) + PK11SlotListElement *psle = NULL; + psle = PK11_GetFirstSafe(slots); + if (!psle) { +- save_port_err(PK11_FreeSlotList(slots)); ++ save_port_err() { ++ PK11_FreeSlotList(slots); ++ } + cmsreterr(-1, cms, "could not get pk11 safe"); + } + +@@ -362,7 +364,9 @@ unlock_nss_token(cms_context *cms) + } + + if (!psle) { +- save_port_err(PK11_FreeSlotList(slots)); ++ save_port_err() { ++ PK11_FreeSlotList(slots); ++ } + cms->log(cms, LOG_ERR, "could not find token \"%s\"", + cms->tokenname); + return -1; +@@ -406,7 +410,9 @@ find_certificate(cms_context *cms, int needs_private_key) + PK11SlotListElement *psle = NULL; + psle = PK11_GetFirstSafe(slots); + if (!psle) { +- save_port_err(PK11_FreeSlotList(slots)); ++ save_port_err() { ++ PK11_FreeSlotList(slots); ++ } + cmsreterr(-1, cms, "could not get pk11 safe"); + } + +@@ -418,7 +424,9 @@ find_certificate(cms_context *cms, int needs_private_key) + } + + if (!psle) { +- save_port_err(PK11_FreeSlotList(slots)); ++ save_port_err() { ++ PK11_FreeSlotList(slots); ++ } + cms->log(cms, LOG_ERR, "could not find token \"%s\"", + cms->tokenname); + return -1; +@@ -439,9 +447,10 @@ find_certificate(cms_context *cms, int needs_private_key) + CERTCertList *certlist = NULL; + certlist = PK11_ListCertsInSlot(psle->slot); + if (!certlist) { +- save_port_err( ++ save_port_err() { + PK11_DestroySlotListElement(slots, &psle); +- PK11_FreeSlotList(slots)); ++ PK11_FreeSlotList(slots); ++ } + cmsreterr(-1, cms, "could not get certificate list"); + } + +@@ -466,10 +475,11 @@ find_certificate(cms_context *cms, int needs_private_key) + &cbdata); + } + if (status != SECSuccess || cbdata.cert == NULL) { +- save_port_err( ++ save_port_err() { + CERT_DestroyCertList(certlist); + PK11_DestroySlotListElement(slots, &psle); +- PK11_FreeSlotList(slots)); ++ PK11_FreeSlotList(slots); ++ } + cmsreterr(-1, cms, "could not find certificate in list"); + } + +@@ -502,7 +512,9 @@ find_slot_for_token(cms_context *cms, PK11SlotInfo **slot) + PK11SlotListElement *psle = NULL; + psle = PK11_GetFirstSafe(slots); + if (!psle) { +- save_port_err(PK11_FreeSlotList(slots)); ++ save_port_err() { ++ PK11_FreeSlotList(slots); ++ } + cmsreterr(-1, cms, "could not get pk11 safe"); + } + +@@ -514,7 +526,9 @@ find_slot_for_token(cms_context *cms, PK11SlotInfo **slot) + } + + if (!psle) { +- save_port_err(PK11_FreeSlotList(slots)); ++ save_port_err() { ++ PK11_FreeSlotList(slots); ++ } + cms->log(cms, LOG_ERR, "could not find token \"%s\"", + cms->tokenname); + return -1; +@@ -555,7 +569,9 @@ find_named_certificate(cms_context *cms, char *name, CERTCertificate **cert) + PK11SlotListElement *psle = NULL; + psle = PK11_GetFirstSafe(slots); + if (!psle) { +- save_port_err(PK11_FreeSlotList(slots)); ++ save_port_err() { ++ PK11_FreeSlotList(slots); ++ } + cmsreterr(-1, cms, "could not get pk11 safe"); + } + +@@ -567,7 +583,9 @@ find_named_certificate(cms_context *cms, char *name, CERTCertificate **cert) + } + + if (!psle) { +- save_port_err(PK11_FreeSlotList(slots)); ++ save_port_err() { ++ PK11_FreeSlotList(slots); ++ } + cms->log(cms, LOG_ERR, "could not find token \"%s\"", + cms->tokenname); + return -1; +@@ -588,9 +606,10 @@ find_named_certificate(cms_context *cms, char *name, CERTCertificate **cert) + CERTCertList *certlist = NULL; + certlist = PK11_ListCertsInSlot(psle->slot); + if (!certlist) { +- save_port_err( ++ save_port_err() { + PK11_DestroySlotListElement(slots, &psle); +- PK11_FreeSlotList(slots)); ++ PK11_FreeSlotList(slots); ++ } + cmsreterr(-1, cms, "could not get certificate list"); + } + +@@ -1158,7 +1177,9 @@ wrap_in_seq(cms_context *cms, SECItem *der, SECItem *items, int num_items) + int rc = 0; + ret = SEC_ASN1EncodeItem(cms->arena, der, items, tmpl); + if (ret == NULL) { +- save_port_err(PORT_ArenaRelease(cms->arena, mark)); ++ save_port_err() { ++ PORT_ArenaRelease(cms->arena, mark); ++ } + cmsreterr(-1, cms, "could not encode set"); + } + PORT_ArenaUnmark(cms->arena, mark); +@@ -1261,7 +1282,9 @@ generate_ava(cms_context *cms, SECItem *der, CERTAVA *certava) + + oid = SECOID_FindOID(&certava->type); + if (!oid) { +- save_port_err(PORT_FreeArena(arena, PR_TRUE)); ++ save_port_err() { ++ PORT_FreeArena(arena, PR_TRUE); ++ } + cms->arena = real_arena; + cmsreterr(-1, cms, "could not find OID"); + } +@@ -1279,7 +1302,9 @@ generate_ava(cms_context *cms, SECItem *der, CERTAVA *certava) + SECItem tmp; + ret = SEC_ASN1EncodeItem(arena, &tmp, &ava, AVATemplate); + if (ret == NULL) { +- save_port_err(PORT_FreeArena(arena, PR_TRUE)); ++ save_port_err() { ++ PORT_FreeArena(arena, PR_TRUE); ++ } + cms->arena = real_arena; + cmsreterr(-1, cms, "could not encode AVA"); + } +@@ -1288,7 +1313,9 @@ generate_ava(cms_context *cms, SECItem *der, CERTAVA *certava) + der->len = tmp.len; + der->data = PORT_ArenaAlloc(real_arena, tmp.len); + if (!der->data) { +- save_port_err(PORT_FreeArena(arena, PR_TRUE)); ++ save_port_err() { ++ PORT_FreeArena(arena, PR_TRUE); ++ } + cms->arena = real_arena; + cmsreterr(-1, cms, "could not allocate AVA"); + } +@@ -1479,3 +1506,5 @@ generate_keys(cms_context *cms, PK11SlotInfo *slot, + cmsreterr(-1, cms, "could not generate RSA keypair"); + return 0; + } ++ ++// vim:fenc=utf-8:tw=75:noet +diff --git a/src/signed_data.c b/src/signed_data.c +index af3a84ff4ab..c6dff5481bb 100644 +--- a/src/signed_data.c ++++ b/src/signed_data.c +@@ -81,14 +81,18 @@ generate_certificate_list(cms_context *cms, SECItem ***certificate_list_p) + + certificates = PORT_ArenaZAlloc(cms->arena, sizeof (SECItem *) * 3); + if (!certificates) { +- save_port_err(PORT_ArenaRelease(cms->arena, mark)); ++ save_port_err() { ++ PORT_ArenaRelease(cms->arena, mark); ++ } + cmsreterr(-1, cms, "could not allocate certificate list"); + } + int i = 0; + + certificates[i] = PORT_ArenaZAlloc(cms->arena, sizeof (SECItem)); + if (!certificates[i]) { +- save_port_err(PORT_ArenaRelease(cms->arena, mark)); ++ save_port_err() { ++ PORT_ArenaRelease(cms->arena, mark); ++ } + cmsreterr(-1, cms, "could not allocate certificate entry"); + } + SECITEM_CopyItem(cms->arena, certificates[i++], &cms->cert->derCert); +@@ -106,8 +110,9 @@ generate_certificate_list(cms_context *cms, SECItem ***certificate_list_p) + certificates[i] = PORT_ArenaZAlloc(cms->arena, + sizeof (SECItem)); + if (!certificates[i]) { +- save_port_err( +- PORT_ArenaRelease(cms->arena, mark)); ++ save_port_err() { ++ PORT_ArenaRelease(cms->arena, mark); ++ } + cmsreterr(-1, cms,"could not allocate " + "certificate entry"); + } +@@ -275,7 +280,9 @@ generate_spc_signed_data(cms_context *cms, SECItem *sdp) + void *mark = PORT_ArenaMark(cms->arena); + + if (SEC_ASN1EncodeInteger(cms->arena, &sd.version, 1) == NULL) { +- save_port_err(PORT_ArenaRelease(cms->arena, mark)); ++ save_port_err() { ++ PORT_ArenaRelease(cms->arena, mark); ++ } + cms->ci_digest = NULL; + cmsreterr(-1, cms, "could not encode integer"); + } +@@ -309,7 +316,9 @@ generate_spc_signed_data(cms_context *cms, SECItem *sdp) + SECItem encoded = { 0, }; + if (SEC_ASN1EncodeItem(cms->arena, &encoded, &sd, SignedDataTemplate) + == NULL) { +- save_port_err(PORT_ArenaRelease(cms->arena, mark)); ++ save_port_err() { ++ PORT_ArenaRelease(cms->arena, mark); ++ } + cms->ci_digest = NULL; + cmsreterr(-1, cms, "could not encode SignedData"); + } +@@ -325,7 +334,9 @@ generate_spc_signed_data(cms_context *cms, SECItem *sdp) + SECItem wrapper = { 0, }; + if (SEC_ASN1EncodeItem(cms->arena, &wrapper, &sdw, + ContentInfoTemplate) == NULL) { +- save_port_err(PORT_ArenaRelease(cms->arena, mark)); ++ save_port_err() { ++ PORT_ArenaRelease(cms->arena, mark); ++ } + cms->ci_digest = NULL; + cmsreterr(-1, cms, "could not encode SignedData"); + } +@@ -347,7 +358,9 @@ generate_authvar_signed_data(cms_context *cms, SECItem *sdp) + void *mark = PORT_ArenaMark(cms->arena); + + if (SEC_ASN1EncodeInteger(cms->arena, &sd.version, 1) == NULL) { +- save_port_err(PORT_ArenaRelease(cms->arena, mark)); ++ save_port_err() { ++ PORT_ArenaRelease(cms->arena, mark); ++ } + cmsreterr(-1, cms, "could not encode integer"); + } + +@@ -376,7 +389,9 @@ generate_authvar_signed_data(cms_context *cms, SECItem *sdp) + SECItem encoded = { 0, }; + if (SEC_ASN1EncodeItem(cms->arena, &encoded, &sd, SignedDataTemplate) + == NULL) { +- save_port_err(PORT_ArenaRelease(cms->arena, mark)); ++ save_port_err() { ++ PORT_ArenaRelease(cms->arena, mark); ++ } + cmsreterr(-1, cms, "could not encode SignedData"); + } + +@@ -391,7 +406,9 @@ generate_authvar_signed_data(cms_context *cms, SECItem *sdp) + SECItem wrapper = { 0, }; + if (SEC_ASN1EncodeItem(cms->arena, &wrapper, &sdw, + ContentInfoTemplate) == NULL) { +- save_port_err(PORT_ArenaRelease(cms->arena, mark)); ++ save_port_err() { ++ PORT_ArenaRelease(cms->arena, mark); ++ } + cmsreterr(-1, cms, "could not encode SignedData"); + } + +@@ -399,3 +416,5 @@ generate_authvar_signed_data(cms_context *cms, SECItem *sdp) + PORT_ArenaUnmark(cms->arena, mark); + return 0; + } ++ ++// vim:fenc=utf-8:tw=75:noet +diff --git a/src/cms_common.h b/src/cms_common.h +index c2b5981ba66..266fa224be0 100644 +--- a/src/cms_common.h ++++ b/src/cms_common.h +@@ -19,21 +19,20 @@ + #ifndef CMS_COMMON_H + #define CMS_COMMON_H 1 + +-#include + #include + #include ++ ++#include + #include + #include + #include + #include + #include + +-#define save_port_err(x) \ +- ({ \ +- int __saved_errno = PORT_GetError(); \ +- x; \ +- PORT_SetError(__saved_errno); \ +- }) ++#include "util.h" ++ ++#define save_port_err() \ ++ for (error_t saved_errno_0_ = 0, saved_errno_1_ = PORT_GetError(); saved_errno_0_ < 1; saved_errno_0_++, PORT_SetError(saved_errno_1_)) + + #define cmserr(rv, cms, fmt, args...) ({ \ + (cms)->log((cms), LOG_ERR, "%s:%s:%d: " fmt ": %s", \ +@@ -173,3 +172,4 @@ typedef struct { + } secuPWData; + + #endif /* CMS_COMMON_H */ ++// vim:fenc=utf-8:tw=75:noet +-- +2.29.2 + diff --git a/0016-efikeygen-add-modsign.patch b/0016-efikeygen-add-modsign.patch deleted file mode 100644 index 8324334..0000000 --- a/0016-efikeygen-add-modsign.patch +++ /dev/null @@ -1,197 +0,0 @@ -From 9b4b12928c0450ac69d83293e179eec439465c03 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 22 Aug 2016 13:43:56 -0400 -Subject: [PATCH 16/29] efikeygen: add --modsign - ---- - src/cms_common.c | 29 ++++++++++++++++++++++++++++ - src/cms_common.h | 1 + - src/efikeygen.c | 59 ++++++++++++++++++++++++++++++++++++++++++++------------ - 3 files changed, 77 insertions(+), 12 deletions(-) - -diff --git a/src/cms_common.c b/src/cms_common.c -index 6a4e6a7..2df2cfe 100644 ---- a/src/cms_common.c -+++ b/src/cms_common.c -@@ -715,6 +715,35 @@ make_context_specific(cms_context *cms, int ctxt, SECItem *encoded, - return 0; - } - -+static SEC_ASN1Template EKUOidSequence[] = { -+ { -+ .kind = SEC_ASN1_OBJECT_ID, -+ .offset = 0, -+ .sub = &SEC_AnyTemplate, -+ .size = sizeof (SECItem), -+ }, -+ { 0 } -+}; -+ -+int -+make_eku_oid(cms_context *cms, SECItem *encoded, SECOidTag oid_tag) -+{ -+ void *rv; -+ SECOidData *oid_data; -+ -+ oid_data = SECOID_FindOIDByTag(oid_tag); -+ if (!oid_data) -+ cmsreterr(-1, cms, "could not encode eku oid data"); -+ -+ rv = SEC_ASN1EncodeItem(cms->arena, encoded, &oid_data->oid, -+ EKUOidSequence); -+ if (rv == NULL) -+ cmsreterr(-1, cms, "could not encode eku oid data"); -+ -+ encoded->type = siBuffer; -+ return 0; -+} -+ - int - generate_octet_string(cms_context *cms, SECItem *encoded, SECItem *original) - { -diff --git a/src/cms_common.h b/src/cms_common.h -index c7d7268..7a31273 100644 ---- a/src/cms_common.h -+++ b/src/cms_common.h -@@ -123,6 +123,7 @@ extern int wrap_in_seq(cms_context *cms, SECItem *der, - SECItem *items, int num_items); - extern int make_context_specific(cms_context *cms, int ctxt, SECItem *encoded, - SECItem *original); -+extern int make_eku_oid(cms_context *cms, SECItem *encoded, SECOidTag oid_tag); - extern int generate_validity(cms_context *cms, SECItem *der, time_t start, - time_t end); - extern int generate_common_name(cms_context *cms, SECItem *der, char *cn); -diff --git a/src/efikeygen.c b/src/efikeygen.c -index 8a515a5..9390578 100644 ---- a/src/efikeygen.c -+++ b/src/efikeygen.c -@@ -49,6 +49,7 @@ - #include - - #include "cms_common.h" -+#include "oid.h" - #include "util.h" - - typedef struct { -@@ -249,20 +250,34 @@ add_basic_constraints(cms_context *cms, void *extHandle) - } - - static int --add_extended_key_usage(cms_context *cms, void *extHandle) -+add_extended_key_usage(cms_context *cms, int modsign_only, void *extHandle) - { -- SECItem value = { -- .data = (unsigned char *)"\x30\x0a\x06\x08\x2b\x06\x01" -- "\x05\x05\x07\x03\x03", -- .len = 12, -- .type = siBuffer -- }; -+ SECItem values[2]; -+ SECItem wrapped = { 0 }; -+ SECStatus status; -+ SECOidTag tag; -+ int rc; -+ -+ if (modsign_only < 1 || modsign_only > 2) -+ cmsreterr(-1, cms, "could not encode extended key usage"); - -+ rc = make_eku_oid(cms, &values[0], SEC_OID_EXT_KEY_USAGE_CODE_SIGN); -+ if (rc < 0) -+ cmsreterr(-1, cms, "could not encode extended key usage"); -+ -+ tag = find_ms_oid_tag(SHIM_EKU_MODULE_SIGNING_ONLY); -+ printf("tag: %d\n", tag); -+ rc = make_eku_oid(cms, &values[1], tag); -+ if (rc < 0) -+ cmsreterr(-1, cms, "could not encode extended key usage"); -+ -+ rc = wrap_in_seq(cms, &wrapped, values, modsign_only); -+ if (rc < 0) -+ cmsreterr(-1, cms, "could not encode extended key usage"); - -- SECStatus status; - - status = CERT_AddExtension(extHandle, SEC_OID_X509_EXT_KEY_USAGE, -- &value, PR_FALSE, PR_TRUE); -+ &wrapped, PR_FALSE, PR_TRUE); - if (status != SECSuccess) - cmsreterr(-1, cms, "could not encode extended key usage"); - -@@ -294,7 +309,7 @@ static int - add_extensions_to_crq(cms_context *cms, CERTCertificateRequest *crq, - int is_ca, int is_self_signed, SECKEYPublicKey *pubkey, - SECKEYPublicKey *spubkey, -- char *url) -+ char *url, int modsign_only) - { - void *mark = PORT_ArenaMark(cms->arena); - -@@ -319,7 +334,7 @@ add_extensions_to_crq(cms_context *cms, CERTCertificateRequest *crq, - if (rc < 0) - cmsreterr(-1, cms, "could not generate certificate extensions"); - -- rc = add_extended_key_usage(cms, extHandle); -+ rc = add_extended_key_usage(cms, modsign_only, extHandle); - if (rc < 0) - cmsreterr(-1, cms, "could not generate certificate extensions"); - -@@ -469,6 +484,7 @@ int main(int argc, char *argv[]) - { - int is_ca = 0; - int is_self_signed = -1; -+ int modsign_only = 0; - char *tokenname = "NSS Certificate DB"; - char *signer = NULL; - char *nickname = NULL; -@@ -522,6 +538,18 @@ int main(int argc, char *argv[]) - .descrip = "Generate a self-signed certificate" }, - - /* stuff about the generated key */ -+ {.longName = "kernel", -+ .shortName = 'k', -+ .argInfo = POPT_ARG_VAL|POPT_ARGFLAG_OR, -+ .arg = &modsign_only, -+ .val = 1, -+ .descrip = "Generate a kernel-signing certificate" }, -+ {.longName = "module", -+ .shortName = 'm', -+ .argInfo = POPT_ARG_VAL|POPT_ARGFLAG_OR, -+ .arg = &modsign_only, -+ .val = 2, -+ .descrip = "Generate a module-signing certificate" }, - {.longName = "nickname", - .shortName = 'n', - .argInfo = POPT_ARG_STRING, -@@ -628,6 +656,9 @@ int main(int argc, char *argv[]) - liberr(1, "could not allocate cms context"); - } - -+ if (modsign_only < 1 || modsign_only > 2) -+ errx(1, "either --kernel or --module must be used"); -+ - SECStatus status = NSS_InitReadWrite(dbdir); - if (status != SECSuccess) - nsserr(1, "could not initialize NSS"); -@@ -639,6 +670,10 @@ int main(int argc, char *argv[]) - SECKEYPublicKey *pubkey = NULL; - SECKEYPrivateKey *privkey = NULL; - -+ status = register_oids(cms); -+ if (status != SECSuccess) -+ nsserr(1, "Could not register OIDs"); -+ - PK11SlotInfo *slot = NULL; - if (pubfile) { - rc = get_pubkey_from_file(pubfile, &pubkey); -@@ -713,7 +748,7 @@ int main(int argc, char *argv[]) - crq = CERT_CreateCertificateRequest(name, spki, &attributes); - - rc = add_extensions_to_crq(cms, crq, is_ca, is_self_signed, pubkey, -- spubkey, url); -+ spubkey, url, modsign_only); - if (rc < 0) - exit(1); - --- -2.13.4 - diff --git a/0017-Make-for_each_cert-cl-iter-for-certificate-list-trav.patch b/0017-Make-for_each_cert-cl-iter-for-certificate-list-trav.patch new file mode 100644 index 0000000..3464e8f --- /dev/null +++ b/0017-Make-for_each_cert-cl-iter-for-certificate-list-trav.patch @@ -0,0 +1,71 @@ +From 03e2f49111fb846254f73ba9a2cce29ea13d3a99 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 17 May 2019 14:06:04 -0400 +Subject: [PATCH 17/42] Make for_each_cert(cl, iter) for certificate list + traversal. + +Signed-off-by: Peter Jones +--- + src/cms_common.c | 18 ++++++++---------- + src/cms_common.h | 3 +++ + 2 files changed, 11 insertions(+), 10 deletions(-) + +diff --git a/src/cms_common.c b/src/cms_common.c +index 9218f69ef9e..75a95f053a2 100644 +--- a/src/cms_common.c ++++ b/src/cms_common.c +@@ -614,20 +614,20 @@ find_named_certificate(cms_context *cms, char *name, CERTCertificate **cert) + } + + CERTCertListNode *node = NULL; +- for (node = CERT_LIST_HEAD(certlist); !CERT_LIST_END(node,certlist); +- node = CERT_LIST_NEXT(node)) { +- if (!strcmp(node->cert->subjectName, name)) ++ for_each_cert(certlist, tmpnode) { ++ if (!strcmp(tmpnode->cert->subjectName, name)) { ++ node = tmpnode; + break; ++ } + } + /* If we're looking up the issuer of some cert, and the issuer isn't + * in the database, we'll get back what is essentially a template + * that's in NSS's cache waiting to be filled out. We can't use that, + * it'll just cause CERT_DupCertificate() to segfault. */ +- if (CERT_LIST_END(node, certlist) +- || !node->cert || !node->cert->derCert.data +- || !node->cert->derCert.len +- || !node->cert->derIssuer.data +- || !node->cert->derIssuer.len) { ++ if (!node || !node->cert || !node->cert->derCert.data ++ || !node->cert->derCert.len ++ || !node->cert->derIssuer.data ++ || !node->cert->derIssuer.len) { + PK11_DestroySlotListElement(slots, &psle); + PK11_FreeSlotList(slots); + CERT_DestroyCertList(certlist); +@@ -635,8 +635,6 @@ find_named_certificate(cms_context *cms, char *name, CERTCertificate **cert) + return -1; + } + +- +- + *cert = CERT_DupCertificate(node->cert); + + PK11_DestroySlotListElement(slots, &psle); +diff --git a/src/cms_common.h b/src/cms_common.h +index 266fa224be0..b0dc12fc3ab 100644 +--- a/src/cms_common.h ++++ b/src/cms_common.h +@@ -34,6 +34,9 @@ + #define save_port_err() \ + for (error_t saved_errno_0_ = 0, saved_errno_1_ = PORT_GetError(); saved_errno_0_ < 1; saved_errno_0_++, PORT_SetError(saved_errno_1_)) + ++#define for_each_cert(cl, node) \ ++ for (CERTCertListNode *node = CERT_LIST_HEAD(cl); !CERT_LIST_END(node, cl); node = CERT_LIST_NEXT(node)) ++ + #define cmserr(rv, cms, fmt, args...) ({ \ + (cms)->log((cms), LOG_ERR, "%s:%s:%d: " fmt ": %s", \ + __FILE__, __func__, __LINE__, ## args, \ +-- +2.29.2 + diff --git a/0017-check_cert_db-try-even-harder-to-pick-a-reasonable-v.patch b/0017-check_cert_db-try-even-harder-to-pick-a-reasonable-v.patch deleted file mode 100644 index acebc3a..0000000 --- a/0017-check_cert_db-try-even-harder-to-pick-a-reasonable-v.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 0456758e0c0873d1251bdf77d27f0f6175cbf289 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 25 Apr 2017 16:25:02 -0400 -Subject: [PATCH 17/29] check_cert_db(): try even harder to pick a reasonable - validation time. - -Signed-off-by: Peter Jones ---- - src/certdb.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------- - 1 file changed, 66 insertions(+), 9 deletions(-) - -diff --git a/src/certdb.c b/src/certdb.c -index b7c99bb..1a4baf1 100644 ---- a/src/certdb.c -+++ b/src/certdb.c -@@ -250,12 +250,53 @@ check_db_hash(db_specifier which, pesigcheck_context *ctx) - return check_db(which, ctx, check_hash, NULL, 0); - } - --static PRTime --determine_reasonable_time(CERTCertificate *cert) -+static void -+find_cert_times(SEC_PKCS7ContentInfo *cinfo, -+ PRTime *notBefore, PRTime *notAfter) - { -- PRTime notBefore, notAfter; -- CERT_GetCertTimes(cert, ¬Before, ¬After); -- return notBefore; -+ CERTCertDBHandle *defaultdb, *certdb; -+ SEC_PKCS7SignedData *sdp; -+ CERTCertificate **certs = NULL; -+ SECItem **rawcerts; -+ int i, certcount; -+ SECStatus rv; -+ -+ if (cinfo->contentTypeTag->offset != SEC_OID_PKCS7_SIGNED_DATA) { -+err: -+ *notBefore = 0; -+ *notAfter = 0x7fffffffffffffff; -+ return; -+ } -+ -+ sdp = cinfo->content.signedData; -+ rawcerts = sdp->rawCerts; -+ -+ defaultdb = CERT_GetDefaultCertDB(); -+ -+ certdb = defaultdb; -+ if (certdb == NULL) -+ goto err; -+ -+ certcount = 0; -+ if (rawcerts != NULL) { -+ for (; rawcerts[certcount] != NULL; certcount++) -+ ; -+ } -+ rv = CERT_ImportCerts(certdb, certUsageObjectSigner, certcount, -+ rawcerts, &certs, PR_FALSE, PR_FALSE, NULL); -+ if (rv != SECSuccess) -+ goto err; -+ -+ for (i = 0; i < certcount; i++) { -+ PRTime nb = 0, na = 0x7fffffffffff; -+ CERT_GetCertTimes(certs[i], &nb, &na); -+ if (*notBefore < nb) -+ *notBefore = nb; -+ if (*notAfter > na) -+ *notAfter = na; -+ } -+ -+ CERT_DestroyCertArray(certs, certcount); - } - - static db_status -@@ -271,6 +312,8 @@ check_cert(pesigcheck_context *ctx, SECItem *sig, efi_guid_t *sigtype, - PRBool result; - SECStatus rv; - db_status status = NOT_FOUND; -+ PRTime earlyNow = 0, lateNow = 0x7fffffffffffffff; -+ PRTime notBefore = 0, notAfter = 0x7fffffffffffffff; - - efi_guid_t efi_x509 = efi_guid_x509_cert; - -@@ -327,16 +370,30 @@ check_cert(pesigcheck_context *ctx, SECItem *sig, efi_guid_t *sigtype, - } - cert->timeOK = PR_TRUE; - -+ find_cert_times(cinfo, ¬Before, ¬After); -+ if (earlyNow < notBefore) -+ earlyNow = notBefore; -+ if (lateNow > notAfter) -+ lateNow = notAfter; -+ - SECItem *eTime; - PRTime atTime; - // atTime = determine_reasonable_time(cert); - eTime = SEC_PKCS7GetSigningTime(cinfo); - if (eTime != NULL) { -- if (DER_DecodeTimeChoice (&atTime, eTime) != SECSuccess) -- atTime = determine_reasonable_time(cert); -- } else { -- atTime = determine_reasonable_time(cert); -+ if (DER_DecodeTimeChoice (&atTime, eTime) == SECSuccess) { -+ if (earlyNow < atTime) -+ earlyNow = atTime; -+ if (lateNow > atTime) -+ lateNow = atTime; -+ } - } -+ -+ if (lateNow < earlyNow) -+ printf("Impossible time constraints: %ld <= %ld\n", -+ earlyNow / 1000000, lateNow / 1000000); -+ atTime = earlyNow / 2 + lateNow / 2; -+ - /* Verify the signature */ - result = SEC_PKCS7VerifyDetachedSignatureAtTime(cinfo, - certUsageObjectSigner, --- -2.13.4 - diff --git a/0018-file_pe-make-most-of-our-input-and-output-checkers-b.patch b/0018-file_pe-make-most-of-our-input-and-output-checkers-b.patch new file mode 100644 index 0000000..2b4d811 --- /dev/null +++ b/0018-file_pe-make-most-of-our-input-and-output-checkers-b.patch @@ -0,0 +1,266 @@ +From fc554b55d45a552982ba9949645e407231f06748 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 21 May 2019 13:54:37 -0400 +Subject: [PATCH 18/42] file_pe: make most of our input and output checkers be + generated + +Signed-off-by: Peter Jones +--- + src/file_pe.c | 237 ++++++++++++-------------------------------------- + 1 file changed, 57 insertions(+), 180 deletions(-) + +diff --git a/src/file_pe.c b/src/file_pe.c +index 0555c28ebff..fcac6292d94 100644 +--- a/src/file_pe.c ++++ b/src/file_pe.c +@@ -118,190 +118,67 @@ open_output(pesign_context *ctx) + + Pe_Cmd cmd = ctx->outfd == STDOUT_FILENO ? PE_C_RDWR : PE_C_RDWR_MMAP; + ctx->outpe = pe_begin(ctx->outfd, cmd, NULL); +- if (!ctx->outpe) { +- fprintf(stderr, "pesign: could not load output file: %s\n", +- pe_errmsg(pe_errno())); +- exit(1); +- } ++ conderrx(!ctx->outpe, 1, "could not load output file \"%s\": %s", ++ ctx->outfile, pe_errmsg(pe_errno())); + + pe_clearcert(ctx->outpe); + } + +-static void +-open_rawsig_input(pesign_context *ctx) +-{ +- if (!ctx->rawsig) { +- fprintf(stderr, "pesign: No input file specified.\n"); +- exit(1); +- } +- +- ctx->rawsigfd = open(ctx->rawsig, O_RDONLY|O_CLOEXEC); +- if (ctx->rawsigfd < 0) { +- fprintf(stderr, "pesign: Error opening raw signature for input:" +- " %m\n"); +- exit(1); +- } +-} +- +-static void +-close_rawsig_input(pesign_context *ctx) +-{ +- close(ctx->rawsigfd); +- ctx->rawsigfd = -1; +-} +- +-static void +-open_sattr_input(pesign_context *ctx) +-{ +- if (!ctx->insattrs) { +- fprintf(stderr, "pesign: No input file specified.\n"); +- exit(1); +- } +- +- ctx->insattrsfd = open(ctx->insattrs, O_RDONLY|O_CLOEXEC); +- if (ctx->insattrsfd < 0) { +- fprintf(stderr, "pesign: Error opening signed attributes " +- "for input: %m\n"); +- exit(1); +- } +-} +- +-static void +-close_sattr_input(pesign_context *ctx) +-{ +- close(ctx->insattrsfd); +- ctx->insattrsfd = -1; +-} +- +-static void +-open_sattr_output(pesign_context *ctx) +-{ +- if (!ctx->outsattrs) { +- fprintf(stderr, "pesign: No output file specified.\n"); +- exit(1); +- } +- +- if (access(ctx->outsattrs, F_OK) == 0 && ctx->force == 0) { +- fprintf(stderr, "pesign: \"%s\" exists and --force " +- "was not given.\n", ctx->outsattrs); +- exit(1); +- } +- +- ctx->outsattrsfd = open(ctx->outsattrs, +- O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, +- ctx->outmode); +- if (ctx->outsattrsfd < 0) { +- fprintf(stderr, "pesign: Error opening signed attributes " +- "for output: %m\n"); +- exit(1); +- } +-} +- +-static void +-close_sattr_output(pesign_context *ctx) +-{ +- close(ctx->outsattrsfd); +- ctx->outsattrsfd = -1; +-} +- +-static void +-open_sig_input(pesign_context *ctx) +-{ +- if (!ctx->insig) { +- fprintf(stderr, "pesign: No input file specified.\n"); +- exit(1); +- } +- +- ctx->insigfd = open(ctx->insig, O_RDONLY|O_CLOEXEC); +- if (ctx->insigfd < 0) { +- fprintf(stderr, "pesign: Error opening signature for input: " +- "%m\n"); +- exit(1); +- } +-} +- +-static void +-close_sig_input(pesign_context *ctx) +-{ +- close(ctx->insigfd); +- ctx->insigfd = -1; +-} +- +-static void +-open_sig_output(pesign_context *ctx) +-{ +- if (!ctx->outsig) { +- fprintf(stderr, "pesign: No output file specified.\n"); +- exit(1); +- } +- +- if (access(ctx->outsig, F_OK) == 0 && ctx->force == 0) { +- fprintf(stderr, "pesign: \"%s\" exists and --force " +- "was not given.\n", ctx->outsig); +- exit(1); +- } +- +- ctx->outsigfd = open(ctx->outsig, O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, +- ctx->outmode); +- if (ctx->outsigfd < 0) { +- fprintf(stderr, "pesign: Error opening signature for output: " +- "%m\n"); +- exit(1); +- } +-} +- +-static void +-close_sig_output(pesign_context *ctx) +-{ +- close(ctx->outsigfd); +- ctx->outsigfd = -1; +-} +- +-static void +-open_pubkey_output(pesign_context *ctx) +-{ +- if (!ctx->outkey) { +- fprintf(stderr, "pesign: No output file specified.\n"); +- exit(1); +- } +- +- if (access(ctx->outkey, F_OK) == 0 && ctx->force == 0) { +- fprintf(stderr, "pesign: \"%s\" exists and --force " +- "was not given.\n", ctx->outkey); +- exit(1); +- } +- +- ctx->outkeyfd = open(ctx->outkey, O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, +- ctx->outmode); +- if (ctx->outkeyfd < 0) { +- fprintf(stderr, "pesign: Error opening pubkey for output: " +- "%m\n"); +- exit(1); +- } +-} +- +-static void +-open_cert_output(pesign_context *ctx) +-{ +- if (!ctx->outcert) { +- fprintf(stderr, "pesign: No output file specified.\n"); +- exit(1); +- } +- +- if (access(ctx->outcert, F_OK) == 0 && ctx->force == 0) { +- fprintf(stderr, "pesign: \"%s\" exists and --force " +- "was not given.\n", ctx->outcert); +- exit(1); +- } +- +- ctx->outcertfd = open(ctx->outcert, O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, +- ctx->outmode); +- if (ctx->outcertfd < 0) { +- fprintf(stderr, "pesign: Error opening certificate for output: " +- "%m\n"); +- exit(1); +- } +-} ++#define define_input_file(fname, name, descr) \ ++ static void \ ++ CAT3(open_, fname, _input)(pesign_context *ctx) \ ++ { \ ++ conderrx(!ctx->name, 1, \ ++ "No input file specified for %s", \ ++ descr); \ ++ ctx->CAT(name, fd) = \ ++ open(ctx->name, O_RDONLY|O_CLOEXEC); \ ++ conderr(ctx->CAT(name, fd) < 0, 1, \ ++ "Error opening %s file \"%s\" for input", \ ++ descr, ctx->name); \ ++ } \ ++ static void \ ++ CAT3(close_, fname, _input)(pesign_context *ctx) \ ++ { \ ++ close(ctx->CAT(name, fd)); \ ++ ctx->CAT(name, fd) = -1; \ ++ } ++ ++#define define_output_file(fname, name, descr) \ ++ static void \ ++ CAT3(open_, fname, _output)(pesign_context *ctx) \ ++ { \ ++ conderrx(!ctx->name, 1, \ ++ "No output file specified for %s.", \ ++ descr); \ ++ \ ++ if (access(ctx->name, F_OK) == 0 && ctx->force == 0) \ ++ errx(1, \ ++ "\"%s\" exists and --force was not given.",\ ++ ctx->name); \ ++ \ ++ ctx->CAT(name, fd) = \ ++ open(ctx->name, \ ++ O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, \ ++ ctx->outmode); \ ++ conderr(ctx->CAT(name, fd) < 0, 1, \ ++ "Error opening %s file \"%s\" for output", \ ++ descr, ctx->name); \ ++ } \ ++ static void \ ++ CAT3(close_, fname, _output)(pesign_context *ctx) \ ++ { \ ++ close(ctx->CAT(name,fd)); \ ++ ctx->CAT(name,fd) = -1; \ ++ } ++ ++define_input_file(rawsig, rawsig, "raw signature"); ++define_input_file(sattr, insattrs, "signed attributes"); ++define_output_file(sattr, outsattrs, "signed attributes"); ++define_input_file(sig, insig, "signature"); ++define_output_file(sig, outsig, "signature"); ++define_output_file(pubkey, outkey, "pubkey"); ++define_output_file(cert, outcert, "certificate"); + + static void + check_inputs(pesign_context *ctx) +-- +2.29.2 + diff --git a/0018-show-which-db-we-re-checking.patch b/0018-show-which-db-we-re-checking.patch deleted file mode 100644 index 2b92f83..0000000 --- a/0018-show-which-db-we-re-checking.patch +++ /dev/null @@ -1,137 +0,0 @@ -From 01b89fb7a191f4639a93c5a7c47a80752118ba95 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 25 Apr 2017 16:58:50 -0400 -Subject: [PATCH 18/29] show which db we're checking - ---- - src/certdb.c | 35 ++++++++++++++++++++++++++++++++++- - src/pesigcheck_context.c | 2 ++ - src/pesigcheck_context.h | 1 + - 3 files changed, 37 insertions(+), 1 deletion(-) - -diff --git a/src/certdb.c b/src/certdb.c -index 1a4baf1..673e074 100644 ---- a/src/certdb.c -+++ b/src/certdb.c -@@ -18,6 +18,7 @@ - */ - - #include -+#include - #include - #include - #include -@@ -42,17 +43,33 @@ add_db_file(pesigcheck_context *ctx, db_specifier which, const char *dbfile, - return -1; - - db->type = type; -- - db->fd = open(dbfile, O_RDONLY); - if (db->fd < 0) { - save_errno(free(db)); - return -1; - } - -+ char *path = strdup(dbfile); -+ if (!path) { -+ save_errno(close(db->fd); -+ free(db)); -+ return -1; -+ } -+ -+ db->path = basename(path); -+ db->path = strdup(db->path); -+ free(path); -+ if (!db->path) { -+ save_errno(close(db->fd); -+ free(db)); -+ return -1; -+ } -+ - struct stat sb; - int rc = fstat(db->fd, &sb); - if (rc < 0) { - save_errno(close(db->fd); -+ free(db->path); - free(db)); - return -1; - } -@@ -65,6 +82,7 @@ add_db_file(pesigcheck_context *ctx, db_specifier which, const char *dbfile, - rc = read_file(db->fd, (char **)&db->map, &sz); - if (rc < 0) { - save_errno(close(db->fd); -+ free(db->path); - free(db)); - return -1; - } -@@ -133,6 +151,7 @@ add_cert_file(pesigcheck_context *ctx, const char *filename) - #define DB_PATH "/sys/firmware/efi/efivars/db-d719b2cb-3d3a-4596-a3bc-dad00e67656f" - #define MOK_PATH "/sys/firmware/efi/efivars/MokListRT-605dab50-e046-4300-abb6-3dd810dd8b23" - #define DBX_PATH "/sys/firmware/efi/efivars/dbx-d719b2cb-3d3a-4596-a3bc-dad00e67656f" -+#define MOKX_PATH "/sys/firmware/efi/efivars/MokListXRT-605dab50-e046-4300-abb6-3dd810dd8b23" - - void - init_cert_db(pesigcheck_context *ctx, int use_system_dbs) -@@ -167,6 +186,18 @@ init_cert_db(pesigcheck_context *ctx, int use_system_dbs) - "database \"%s\": %m\n", DBX_PATH); - exit(1); - } -+ -+ rc = add_db_file(ctx, DBX, MOKX_PATH, DB_EFIVAR); -+ if (rc < 0 && errno != ENOENT) { -+ fprintf(stderr, "pesigcheck: Could not add key database " -+ "\"%s\": %m\n", MOKX_PATH); -+ exit(1); -+ } -+ -+ if (ctx->dbx == NULL) { -+ fprintf(stderr, "pesigcheck: warning: " -+ "No key recovation database available\n"); -+ } - } - - typedef db_status (*checkfn)(pesigcheck_context *ctx, SECItem *sig, -@@ -187,6 +218,8 @@ check_db(db_specifier which, pesigcheck_context *ctx, checkfn check, - sig.type = siBuffer; - - while (dbl) { -+ printf("Searching %s %s\n", which == DB ? "db" : "dbx", -+ dbl->path); - EFI_SIGNATURE_LIST *certlist; - EFI_SIGNATURE_DATA *cert; - size_t dbsize = dbl->datalen; -diff --git a/src/pesigcheck_context.c b/src/pesigcheck_context.c -index b934cbe..5a355b1 100644 ---- a/src/pesigcheck_context.c -+++ b/src/pesigcheck_context.c -@@ -87,6 +87,7 @@ pesigcheck_context_fini(pesigcheck_context *ctx) - munmap(db->map, db->size); - close(db->fd); - ctx->db = db->next; -+ free(db->path); - free(db); - } - while (ctx->dbx) { -@@ -95,6 +96,7 @@ pesigcheck_context_fini(pesigcheck_context *ctx) - if (db->type == DB_CERT) - free(db->data); - munmap(db->map, db->size); -+ free(db->path); - close(db->fd); - ctx->dbx = db->next; - free(db); -diff --git a/src/pesigcheck_context.h b/src/pesigcheck_context.h -index 1b916e3..7b5cc89 100644 ---- a/src/pesigcheck_context.h -+++ b/src/pesigcheck_context.h -@@ -34,6 +34,7 @@ typedef enum { - - struct dblist { - db_f_type type; -+ char *path; - int fd; - struct dblist *next; - size_t size; --- -2.13.4 - diff --git a/0019-file_pe-user-err-errx-etc.patch b/0019-file_pe-user-err-errx-etc.patch new file mode 100644 index 0000000..bc4af1a --- /dev/null +++ b/0019-file_pe-user-err-errx-etc.patch @@ -0,0 +1,275 @@ +From 61bdc2689de3ab4f3960bee9a1ac7c63386cf727 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 21 May 2019 14:04:30 -0400 +Subject: [PATCH 19/42] file_pe: user err() errx() etc. + +Signed-off-by: Peter Jones +--- + src/file_pe.c | 146 +++++++++++++++----------------------------------- + 1 file changed, 44 insertions(+), 102 deletions(-) + +diff --git a/src/file_pe.c b/src/file_pe.c +index fcac6292d94..ad076eba961 100644 +--- a/src/file_pe.c ++++ b/src/file_pe.c +@@ -29,36 +29,23 @@ + static void + open_input(pesign_context *ctx) + { +- if (!ctx->infile) { +- fprintf(stderr, "pesign: No input file specified.\n"); +- exit(1); +- } ++ conderrx(!ctx->infile, 1, "No input file specified."); + + struct stat statbuf; + ctx->infd = open(ctx->infile, O_RDONLY|O_CLOEXEC); + stat(ctx->infile, &statbuf); + ctx->outmode = statbuf.st_mode; + +- if (ctx->infd < 0) { +- fprintf(stderr, "pesign: Error opening input: %m\n"); +- exit(1); +- } ++ conderr(ctx->infd < 0, 1, "Error opening input"); + + Pe_Cmd cmd = ctx->infd == STDIN_FILENO ? PE_C_READ : PE_C_READ_MMAP; + ctx->inpe = pe_begin(ctx->infd, cmd, NULL); +- if (!ctx->inpe) { +- fprintf(stderr, "pesign: could not load input file: %s\n", +- pe_errmsg(pe_errno())); +- exit(1); +- } ++ conderrx(!ctx->inpe, 1, "could not load input file \"%s\": %s", ++ ctx->infile, pe_errmsg(pe_errno())); + + int rc = parse_signatures(&ctx->cms_ctx->signatures, + &ctx->cms_ctx->num_signatures, ctx->inpe); +- if (rc < 0) { +- fprintf(stderr, "pesign: could not parse signature list in " +- "EFI binary\n"); +- exit(1); +- } ++ conderrx(rc < 0, 1, "could not parse signature list in EFI binary"); + } + + static void +@@ -89,23 +76,16 @@ close_output(pesign_context *ctx) + static void + open_output(pesign_context *ctx) + { +- if (!ctx->outfile) { +- fprintf(stderr, "pesign: No output file specified.\n"); +- exit(1); +- } ++ conderrx(!ctx->outfile, 1, "No output file specified."); + +- if (access(ctx->outfile, F_OK) == 0 && ctx->force == 0) { +- fprintf(stderr, "pesign: \"%s\" exists and --force was " +- "not given.\n", ctx->outfile); +- exit(1); +- } ++ if (access(ctx->outfile, F_OK) == 0 && ctx->force == 0) ++ errx(1, "\"%s\" exists and --force was not given.", ++ ctx->outfile); + + ctx->outfd = open(ctx->outfile, O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, + ctx->outmode); +- if (ctx->outfd < 0) { +- fprintf(stderr, "pesign: Error opening output: %m\n"); +- exit(1); +- } ++ conderr(ctx->outfd < 0, 1, "Error opening \"%s\" for output", ++ ctx->outfile); + + size_t size; + char *addr; +@@ -119,7 +99,7 @@ open_output(pesign_context *ctx) + Pe_Cmd cmd = ctx->outfd == STDOUT_FILENO ? PE_C_RDWR : PE_C_RDWR_MMAP; + ctx->outpe = pe_begin(ctx->outfd, cmd, NULL); + conderrx(!ctx->outpe, 1, "could not load output file \"%s\": %s", +- ctx->outfile, pe_errmsg(pe_errno())); ++ ctx->outfile, pe_errmsg(pe_errno())); + + pe_clearcert(ctx->outpe); + } +@@ -183,21 +163,11 @@ define_output_file(cert, outcert, "certificate"); + static void + check_inputs(pesign_context *ctx) + { +- if (!ctx->infile) { +- fprintf(stderr, "pesign: No input file specified.\n"); +- exit(1); +- } ++ conderrx(!ctx->infile, 1, "No input file specified."); ++ conderrx(!ctx->outfile, 1, "No output file specified."); + +- if (!ctx->outfile) { +- fprintf(stderr, "pesign: No output file specified.\n"); +- exit(1); +- } +- +- if (!strcmp(ctx->infile, ctx->outfile)) { +- fprintf(stderr, "pesign: in-place file editing " +- "is not yet supported\n"); +- exit(1); +- } ++ conderrx(!strcmp(ctx->infile, ctx->outfile), 1, ++ "in-place file editing is not yet supported."); + } + + static void +@@ -232,12 +202,8 @@ pe_handle_action(pesign_context *ctxp, int action, int padding) + case IMPORT_RAW_SIGNATURE|IMPORT_SATTRS: + check_inputs(ctxp); + rc = find_certificate(ctxp->cms_ctx, 0); +- if (rc < 0) { +- fprintf(stderr, "pesign: Could not find " +- "certificate %s\n", +- ctxp->cms_ctx->certname); +- exit(1); +- } ++ conderrx(rc < 0, 1, "Could not find certificate %s\n", ++ ctxp->cms_ctx->certname); + open_rawsig_input(ctxp); + open_sattr_input(ctxp); + import_raw_signature(ctxp); +@@ -266,10 +232,8 @@ pe_handle_action(pesign_context *ctxp, int action, int padding) + /* add a signature from a file */ + case IMPORT_SIGNATURE: + check_inputs(ctxp); +- if (ctxp->signum > ctxp->cms_ctx->num_signatures + 1) { +- fprintf(stderr, "Invalid signature number.\n"); +- exit(1); +- } ++ conderrx(ctxp->signum > ctxp->cms_ctx->num_signatures + 1, ++ 1, "Invalid signature number."); + open_input(ctxp); + open_output(ctxp); + close_input(ctxp); +@@ -285,23 +249,15 @@ pe_handle_action(pesign_context *ctxp, int action, int padding) + break; + case EXPORT_PUBKEY: + rc = find_certificate(ctxp->cms_ctx, 1); +- if (rc < 0) { +- fprintf(stderr, "pesign: Could not find " +- "certificate %s\n", +- ctxp->cms_ctx->certname); +- exit(1); +- } ++ conderrx(rc < 0, 1, "Could not find certificate %s", ++ ctxp->cms_ctx->certname); + open_pubkey_output(ctxp); + export_pubkey(ctxp); + break; + case EXPORT_CERT: + rc = find_certificate(ctxp->cms_ctx, 0); +- if (rc < 0) { +- fprintf(stderr, "pesign: Could not find " +- "certificate %s\n", +- ctxp->cms_ctx->certname); +- exit(1); +- } ++ conderrx(rc < 0, 1, "Could not find certificate %s", ++ ctxp->cms_ctx->certname); + open_cert_output(ctxp); + export_cert(ctxp); + break; +@@ -309,17 +265,12 @@ pe_handle_action(pesign_context *ctxp, int action, int padding) + case EXPORT_SIGNATURE: + open_input(ctxp); + open_sig_output(ctxp); +- if (ctxp->signum > ctxp->cms_ctx->num_signatures) { +- fprintf(stderr, "Invalid signature number.\n"); +- exit(1); +- } ++ conderrx(ctxp->signum > ctxp->cms_ctx->num_signatures, ++ 1, "Invalid signature number."); + if (ctxp->signum < 0) + ctxp->signum = 0; +- if (ctxp->signum >= ctxp->cms_ctx->num_signatures) { +- fprintf(stderr, "No valid signature #%d.\n", +- ctxp->signum); +- exit(1); +- } ++ conderrx(ctxp->signum >= ctxp->cms_ctx->num_signatures, ++ 1, "No valid signature #%d.", ctxp->signum); + memcpy(&ctxp->cms_ctx->newsig, + ctxp->cms_ctx->signatures[ctxp->signum], + sizeof (ctxp->cms_ctx->newsig)); +@@ -335,14 +286,12 @@ pe_handle_action(pesign_context *ctxp, int action, int padding) + open_input(ctxp); + open_output(ctxp); + close_input(ctxp); +- if (ctxp->signum < 0 || +- ctxp->signum >= +- ctxp->cms_ctx->num_signatures) { +- fprintf(stderr, "Invalid signature number %d. " +- "Must be between 0 and %d.\n", +- ctxp->signum, +- ctxp->cms_ctx->num_signatures - 1); +- exit(1); ++ if(ctxp->signum < 0 || ++ ctxp->signum >= ctxp->cms_ctx->num_signatures) { ++ warnx("Invalid signature number %d.", ++ ctxp->signum); ++ errx(1, "Must be between 0 and %d.", ++ ctxp->cms_ctx->num_signatures - 1); + } + remove_signature(ctxp); + close_output(ctxp); +@@ -365,12 +314,8 @@ pe_handle_action(pesign_context *ctxp, int action, int padding) + /* generate a signature and save it in a separate file */ + case EXPORT_SIGNATURE|GENERATE_SIGNATURE: + rc = find_certificate(ctxp->cms_ctx, 1); +- if (rc < 0) { +- fprintf(stderr, "pesign: Could not find " +- "certificate %s\n", +- ctxp->cms_ctx->certname); +- exit(1); +- } ++ conderrx(rc < 0, 1, "Could not find certificate %s", ++ ctxp->cms_ctx->certname); + open_input(ctxp); + open_sig_output(ctxp); + generate_digest(ctxp->cms_ctx, ctxp->inpe, 1); +@@ -381,16 +326,10 @@ pe_handle_action(pesign_context *ctxp, int action, int padding) + case IMPORT_SIGNATURE|GENERATE_SIGNATURE: + check_inputs(ctxp); + rc = find_certificate(ctxp->cms_ctx, 1); +- if (rc < 0) { +- fprintf(stderr, "pesign: Could not find " +- "certificate %s\n", +- ctxp->cms_ctx->certname); +- exit(1); +- } +- if (ctxp->signum > ctxp->cms_ctx->num_signatures + 1) { +- fprintf(stderr, "Invalid signature number.\n"); +- exit(1); +- } ++ conderrx(rc < 0, 1, "Could not find certificate %s", ++ ctxp->cms_ctx->certname); ++ conderrx(ctxp->signum > ctxp->cms_ctx->num_signatures + 1, ++ 1, "Invalid signature number."); + open_input(ctxp); + open_output(ctxp); + close_input(ctxp); +@@ -404,7 +343,8 @@ pe_handle_action(pesign_context *ctxp, int action, int padding) + close_output(ctxp); + break; + default: +- fprintf(stderr, "Incompatible flags (0x%08x): ", action); ++ fprintf(stderr, "%s: Incompatible flags (0x%08x): ", ++ program_invocation_short_name, action); + for (int i = 1; i < FLAG_LIST_END; i <<= 1) { + if (action & i) + print_flag_name(stderr, i); +@@ -413,3 +353,5 @@ pe_handle_action(pesign_context *ctxp, int action, int padding) + exit(1); + } + } ++ ++// vim:fenc=utf-8:tw=75:noet +-- +2.29.2 + diff --git a/0019-more-about-the-time.patch b/0019-more-about-the-time.patch deleted file mode 100644 index 2570bf8..0000000 --- a/0019-more-about-the-time.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 713e61448a6ffa3e6029a7c89fad61b8cb08c9ff Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 25 Apr 2017 17:00:46 -0400 -Subject: [PATCH 19/29] more about the time - ---- - src/certdb.c | 59 +++++++++++++++++++++++++++++++++-------------------------- - 1 file changed, 33 insertions(+), 26 deletions(-) - -diff --git a/src/certdb.c b/src/certdb.c -index 673e074..1078a8a 100644 ---- a/src/certdb.c -+++ b/src/certdb.c -@@ -345,8 +345,10 @@ check_cert(pesigcheck_context *ctx, SECItem *sig, efi_guid_t *sigtype, - PRBool result; - SECStatus rv; - db_status status = NOT_FOUND; -+ PRTime atTime = PR_Now(); -+ SECItem *eTime; - PRTime earlyNow = 0, lateNow = 0x7fffffffffffffff; -- PRTime notBefore = 0, notAfter = 0x7fffffffffffffff; -+ PRTime notBefore, notAfter; - - efi_guid_t efi_x509 = efi_guid_x509_cert; - -@@ -358,6 +360,36 @@ check_cert(pesigcheck_context *ctx, SECItem *sig, efi_guid_t *sigtype, - if (!cinfo) - goto out; - -+ notBefore = earlyNow; -+ notAfter = lateNow; -+ find_cert_times(cinfo, ¬Before, ¬After); -+ if (earlyNow < notBefore) -+ earlyNow = notBefore; -+ if (lateNow > notAfter) -+ lateNow = notAfter; -+ -+ // atTime = determine_reasonable_time(cert); -+ eTime = SEC_PKCS7GetSigningTime(cinfo); -+ if (eTime != NULL) { -+ if (DER_DecodeTimeChoice (&atTime, eTime) == SECSuccess) { -+ if (earlyNow < atTime) -+ earlyNow = atTime; -+ if (lateNow > atTime) -+ lateNow = atTime; -+ } -+ } -+ -+ if (lateNow < earlyNow) -+ printf("Signature has impossible time constraint: %ld <= %ld\n", -+ earlyNow / 1000000, lateNow / 1000000); -+ atTime = earlyNow / 2 + lateNow / 2; -+ -+ -+ cinfo = SEC_PKCS7DecodeItem(pkcs7sig, NULL, NULL, NULL, NULL, NULL, -+ NULL, NULL); -+ if (!cinfo) -+ goto out; -+ - /* Generate the digest of contentInfo */ - /* XXX support only sha256 for now */ - digest = SECITEM_AllocItem(NULL, NULL, 32); -@@ -401,31 +433,6 @@ check_cert(pesigcheck_context *ctx, SECItem *sig, efi_guid_t *sigtype, - PORT_ErrorToString(PORT_GetError())); - goto out; - } -- cert->timeOK = PR_TRUE; -- -- find_cert_times(cinfo, ¬Before, ¬After); -- if (earlyNow < notBefore) -- earlyNow = notBefore; -- if (lateNow > notAfter) -- lateNow = notAfter; -- -- SECItem *eTime; -- PRTime atTime; -- // atTime = determine_reasonable_time(cert); -- eTime = SEC_PKCS7GetSigningTime(cinfo); -- if (eTime != NULL) { -- if (DER_DecodeTimeChoice (&atTime, eTime) == SECSuccess) { -- if (earlyNow < atTime) -- earlyNow = atTime; -- if (lateNow > atTime) -- lateNow = atTime; -- } -- } -- -- if (lateNow < earlyNow) -- printf("Impossible time constraints: %ld <= %ld\n", -- earlyNow / 1000000, lateNow / 1000000); -- atTime = earlyNow / 2 + lateNow / 2; - - /* Verify the signature */ - result = SEC_PKCS7VerifyDetachedSignatureAtTime(cinfo, --- -2.13.4 - diff --git a/0020-pesign_kmod-user-err-errx-etc.patch b/0020-pesign_kmod-user-err-errx-etc.patch new file mode 100644 index 0000000..91e9159 --- /dev/null +++ b/0020-pesign_kmod-user-err-errx-etc.patch @@ -0,0 +1,165 @@ +From 43d7021bc1a4d78cfaa8ad8a31c73058005e26ef Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 21 May 2019 14:45:24 -0400 +Subject: [PATCH 20/42] pesign_kmod: user err() errx() etc. + +Signed-off-by: Peter Jones +--- + src/pesign_kmod.c | 80 +++++++++++++++-------------------------------- + 1 file changed, 26 insertions(+), 54 deletions(-) + +diff --git a/src/pesign_kmod.c b/src/pesign_kmod.c +index 5d78131a69b..916ae52ebe2 100644 +--- a/src/pesign_kmod.c ++++ b/src/pesign_kmod.c +@@ -122,6 +122,7 @@ import_sig_input(pesign_context *ctx) + { + unsigned char *map; + struct stat statbuf; ++ int rc; + + if (!ctx->insig) { + fprintf(stderr, "pesign: No input file specified.\n"); +@@ -135,23 +136,17 @@ import_sig_input(pesign_context *ctx) + exit(1); + } + +- if (fstat(ctx->insigfd, &statbuf)) { +- fprintf(stderr, "pesign: Error on stat signature: %m\n"); +- exit(1); +- } ++ rc = fstat(ctx->insigfd, &statbuf); ++ conderr(rc < 0, 1, "Could not fstat signature file \"%s\"", ++ ctx->insig); + + /* Copy original module data */ + + map = mmap(NULL, ctx->inlength, PROT_READ, MAP_PRIVATE, ctx->infd, 0); +- if (map == MAP_FAILED) { +- fprintf(stderr, "pesign: Error mapping input: %m\n"); +- exit(1); +- } ++ conderr(map == MAP_FAILED, 1, "Could not map kmod input"); + +- if (write_file(ctx->outfd, map, ctx->inlength) < 0) { +- fprintf(stderr, "pesign: failed to write module data: %m\n"); +- exit(1); +- } ++ rc = write_file(ctx->outfd, map, ctx->inlength); ++ conderr(rc < 0, 1, "Failed to write module data"); + + munmap(map, ctx->inlength); + +@@ -159,15 +154,11 @@ import_sig_input(pesign_context *ctx) + + map = mmap(NULL, statbuf.st_size, PROT_READ, MAP_PRIVATE, ctx->insigfd, + 0); +- if (map == MAP_FAILED) { +- fprintf(stderr, "pesign: failed to map signature: %m\n"); +- exit(1); +- } ++ conderr(map == MAP_FAILED, 1, "Could not map signature input \"%s\"", ++ ctx->insig); + +- if (write_file(ctx->outfd, map, statbuf.st_size) < 0) { +- fprintf(stderr, "pesign: Error writing output: %m\n"); +- exit(1); +- } ++ rc = write_file(ctx->outfd, map, statbuf.st_size); ++ conderr(rc < 0, 1, "Error writing output"); + + munmap(map, statbuf.st_size); + } +@@ -180,20 +171,15 @@ handle_signing(pesign_context *ctx, int outfd, int attached) + ssize_t sig_len; + + inmap = mmap(NULL, ctx->inlength, PROT_READ, MAP_PRIVATE, ctx->infd, 0); +- if (inmap == MAP_FAILED) { +- fprintf(stderr, "pesign: Error mapping input: %m\n"); +- exit(1); +- } ++ conderrx(inmap == MAP_FAILED, 1, "Error mapping input kmod"); + + rc = kmod_generate_digest(ctx->cms_ctx, inmap, ctx->inlength); + if (rc < 0) + exit(1); + + if (attached) { +- if (write_file(outfd, inmap, ctx->inlength) < 0) { +- fprintf(stderr, "pesign: failed to write module data: %m\n"); +- exit(1); +- } ++ rc = write_file(outfd, inmap, ctx->inlength); ++ conderr(rc < 0, 1, "Failed to write module data"); + } + munmap(inmap, ctx->inlength); + +@@ -214,16 +200,10 @@ kmod_handle_action(pesign_context *ctxp, int action) + /* generate a signature and embed it in the module */ + case IMPORT_SIGNATURE|GENERATE_SIGNATURE: + rc = find_certificate(ctxp->cms_ctx, 1); +- if (rc < 0) { +- fprintf(stderr, "pesign: Could not find " +- "certificate %s\n", +- ctxp->cms_ctx->certname); +- exit(1); +- } +- if (ctxp->signum > ctxp->cms_ctx->num_signatures + 1) { +- fprintf(stderr, "Invalid signature number.\n"); +- exit(1); +- } ++ conderrx(rc < 0, 1, "Could not find certificate \"%s\"", ++ ctxp->cms_ctx->certname); ++ conderrx(ctxp->signum > ctxp->cms_ctx->num_signatures + 1, ++ 1, "Invalid signature number."); + + open_input(ctxp); + open_output(ctxp); +@@ -235,16 +215,10 @@ kmod_handle_action(pesign_context *ctxp, int action) + /* generate a signature and save it in a separate file */ + case EXPORT_SIGNATURE|GENERATE_SIGNATURE: + rc = find_certificate(ctxp->cms_ctx, 1); +- if (rc < 0) { +- fprintf(stderr, "pesign: Could not find " +- "certificate %s\n", +- ctxp->cms_ctx->certname); +- exit(1); +- } +- if (ctxp->signum > ctxp->cms_ctx->num_signatures + 1) { +- fprintf(stderr, "Invalid signature number.\n"); +- exit(1); +- } ++ conderrx(rc < 0, 1, "Could not find certificate \"%s\"", ++ ctxp->cms_ctx->certname); ++ conderrx(ctxp->signum > ctxp->cms_ctx->num_signatures + 1, ++ 1, "Invalid signature number."); + + open_input(ctxp); + open_sig_output(ctxp); +@@ -255,10 +229,8 @@ kmod_handle_action(pesign_context *ctxp, int action) + + /* add a signature from a file */ + case IMPORT_SIGNATURE: +- if (ctxp->signum > ctxp->cms_ctx->num_signatures + 1) { +- fprintf(stderr, "Invalid signature number.\n"); +- exit(1); +- } ++ conderrx(ctxp->signum > ctxp->cms_ctx->num_signatures + 1, ++ 1, "Invalid signature number."); + open_input(ctxp); + open_output(ctxp); + import_sig_input(ctxp); +@@ -267,8 +239,8 @@ kmod_handle_action(pesign_context *ctxp, int action) + break; + + default: +- fprintf(stderr, "Incompatible flags (0x%08x): ", +- action); ++ fprintf(stderr, "%s: Incompatible flags (0x%08x): ", ++ program_invocation_short_name, action); + for (int i = 1; i < FLAG_LIST_END; i <<= 1) { + if (action & i) + print_flag_name(stderr, i); +-- +2.29.2 + diff --git a/0020-try-to-say-why-something-fails.patch b/0020-try-to-say-why-something-fails.patch deleted file mode 100644 index 96bdd60..0000000 --- a/0020-try-to-say-why-something-fails.patch +++ /dev/null @@ -1,419 +0,0 @@ -From 81583146602bba96728fa7544c8e856b32c22ee4 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 25 Apr 2017 17:01:13 -0400 -Subject: [PATCH 20/29] try to say why something fails - -Signed-off-by: Peter Jones ---- - src/certdb.c | 15 ++- - src/certdb.h | 2 +- - src/pesigcheck.c | 244 ++++++++++++++++++++++++++++++++++++++++++----- - src/pesigcheck_context.h | 1 + - 4 files changed, 233 insertions(+), 29 deletions(-) - -diff --git a/src/certdb.c b/src/certdb.c -index 1078a8a..fae80af 100644 ---- a/src/certdb.c -+++ b/src/certdb.c -@@ -205,7 +205,7 @@ typedef db_status (*checkfn)(pesigcheck_context *ctx, SECItem *sig, - - static db_status - check_db(db_specifier which, pesigcheck_context *ctx, checkfn check, -- void *data, ssize_t datalen) -+ void *data, ssize_t datalen, SECItem *match) - { - SECItem pkcs7sig, sig; - dblist *dbl = which == DB ? ctx->db : ctx->dbx; -@@ -241,8 +241,12 @@ check_db(db_specifier which, pesigcheck_context *ctx, checkfn check, - found = check(ctx, &sig, - &certlist->SignatureType, - &pkcs7sig); -- if (found == FOUND) -+ if (found == FOUND) { -+ if (match) -+ memcpy(match, &sig, -+ sizeof(sig)); - return FOUND; -+ } - cert = (EFI_SIGNATURE_DATA *)((uint8_t *)cert + - certlist->SignatureSize); - } -@@ -280,7 +284,7 @@ check_hash(pesigcheck_context *ctx, SECItem *sig, efi_guid_t *sigtype, - db_status - check_db_hash(db_specifier which, pesigcheck_context *ctx) - { -- return check_db(which, ctx, check_hash, NULL, 0); -+ return check_db(which, ctx, check_hash, NULL, 0, NULL); - } - - static void -@@ -459,7 +463,8 @@ out: - } - - db_status --check_db_cert(db_specifier which, pesigcheck_context *ctx, void *data, ssize_t datalen) -+check_db_cert(db_specifier which, pesigcheck_context *ctx, -+ void *data, ssize_t datalen, SECItem *match) - { -- return check_db(which, ctx, check_cert, data, datalen); -+ return check_db(which, ctx, check_cert, data, datalen, match); - } -diff --git a/src/certdb.h b/src/certdb.h -index ccf3c87..8402299 100644 ---- a/src/certdb.h -+++ b/src/certdb.h -@@ -43,7 +43,7 @@ typedef struct { - - extern db_status check_db_hash(db_specifier which, pesigcheck_context *ctx); - extern db_status check_db_cert(db_specifier which, pesigcheck_context *ctx, -- void *data, ssize_t datalen); -+ void *data, ssize_t datalen, SECItem *match); - - extern void init_cert_db(pesigcheck_context *ctx, int use_system_dbs); - extern int add_cert_db(pesigcheck_context *ctx, const char *filename); -diff --git a/src/pesigcheck.c b/src/pesigcheck.c -index d7be542..c8e1086 100644 ---- a/src/pesigcheck.c -+++ b/src/pesigcheck.c -@@ -17,7 +17,9 @@ - * Author(s): Peter Jones - */ - -+#include - #include -+#include - #include - #include - #include -@@ -88,7 +90,8 @@ check_inputs(pesigcheck_context *ctx) - } - - static int --cert_matches_digest(pesigcheck_context *ctx, void *data, ssize_t datalen) -+cert_matches_digest(pesigcheck_context *ctx, void *data, ssize_t datalen, -+ SECItem *digest_out) - { - SECItem sig, *pe_digest, *content; - uint8_t *digest; -@@ -109,6 +112,12 @@ cert_matches_digest(pesigcheck_context *ctx, void *data, ssize_t datalen) - pe_digest = ctx->cms_ctx->digests[0].pe_digest; - content = cinfo->content.signedData->contentInfo.content.data; - digest = content->data + content->len - pe_digest->len; -+ if (digest_out) { -+ digest_out->data = malloc(pe_digest->len); -+ digest_out->len = pe_digest->len; -+ digest_out->type = pe_digest->type; -+ memcpy(digest_out->data, digest, pe_digest->len); -+ } - if (memcmp(pe_digest->data, digest, pe_digest->len) != 0) - goto out; - -@@ -120,22 +129,149 @@ out: - return ret; - } - -+struct reason { -+ enum { -+ WHITELISTED = 0, -+ INVALID = 1, -+ BLACKLISTED = 2, -+ NO_WHITELIST = 3, -+ } reason; -+ enum { -+ NONE = 0, -+ DIGEST = 1, -+ SIGNATURE = 2, -+ } type; -+ union { -+ struct { -+ SECItem digest; -+ }; -+ struct { -+ SECItem sig; -+ SECItem db_cert; -+ }; -+ }; -+}; -+ -+static void -+print_digest(SECItem *digest) -+{ -+ char buf[digest->len * 2 + 2]; -+ -+ for (unsigned int i = 0; i < digest->len; i++) -+ snprintf(buf + i * 2, digest->len * 2, "%02x", -+ digest->data[i]); -+ buf[digest->len * 2] = '\0'; -+ printf("%s\n", buf); -+} -+ -+static void -+print_certificate(SECItem *cert) -+{ -+ printf("put a breakpoint at %s:%d\n", __FILE__, __LINE__); -+ printf("cert: %p\n", cert); -+} -+ -+static void -+print_signatures(SECItem *database_cert, SECItem *signature) -+{ -+ printf("put a breakpoint at %s:%d\n", __FILE__, __LINE__); -+ print_certificate(database_cert); -+ print_certificate(signature); -+} -+ -+static void -+print_reason(struct reason *reason) -+{ -+ switch (reason->reason) { -+ case WHITELISTED: -+ printf("Whitelist entry: "); -+ if (reason->type == DIGEST) -+ print_digest(&reason->digest); -+ else if (reason->type == SIGNATURE) -+ print_signatures(&reason->sig, &reason->db_cert); -+ else -+ errx(1, "Unknown data type %d\n", reason->type); -+ break; -+ case INVALID: -+ if (reason->type == DIGEST) { -+ printf("Invalid digest: "); -+ print_digest(&reason->digest); -+ } else if (reason->type == SIGNATURE) { -+ printf("Invalid signature: "); -+ print_signatures(&reason->sig, &reason->db_cert); -+ } else { -+ errx(1, "Unknown data type %d\n", reason->type); -+ } -+ break; -+ case BLACKLISTED: -+ if (reason->type == DIGEST) { -+ printf("Invalid digest: "); -+ print_digest(&reason->digest); -+ } else if (reason->type == SIGNATURE) { -+ printf("Invalid signature: "); -+ print_signatures(&reason->sig, &reason->db_cert); -+ } else { -+ errx(1, "Unknown data type %d\n", reason->type); -+ } -+ break; -+ case NO_WHITELIST: -+ if (reason->type == NONE) -+ printf("No matching whitelist entry.\n"); -+ else -+ errx(1, "Invalid data type %d\n", reason->type); -+ break; -+ default: -+ errx(1, "Unknown reason type %d\n", reason->reason); -+ break; -+ } -+} -+ -+static void -+get_digest(pesigcheck_context *ctx, SECItem *digest) -+{ -+ struct cms_context *cms = ctx->cms_ctx; -+ struct digest *cms_digest = &cms->digests[cms->selected_digest]; -+ -+ memcpy(digest, cms_digest->pe_digest, sizeof (*digest)); -+} -+ - static int --check_signature(pesigcheck_context *ctx) -+check_signature(pesigcheck_context *ctx, int *nreasons, -+ struct reason **reasons) - { -- int has_valid_cert = 0; -- int has_invalid_cert = 0; -+ bool has_valid_cert = false; -+ bool is_invalid = false; -+ struct reason *reasonps = NULL, *reason; -+ int num_reasons = 16; -+ int nreason = 0; - int rc = 0; -+ int ret = -1; - - cert_iter iter; - -+ reasonps = calloc(sizeof(struct reason), 512); -+ if (!reasonps) -+ err(1, "check_signature"); -+ - generate_digest(ctx->cms_ctx, ctx->inpe, 1); - -- if (check_db_hash(DBX, ctx) == FOUND) -- return -1; -+ if (check_db_hash(DBX, ctx) == FOUND) { -+ reason = &reasonps[nreason]; -+ reason->reason = BLACKLISTED; -+ reason->type = DIGEST; -+ get_digest(ctx, &reason->digest); -+ reason += 1; -+ is_invalid = true; -+ } - -- if (check_db_hash(DB, ctx) == FOUND) -- has_valid_cert = 1; -+ if (check_db_hash(DB, ctx) == FOUND) { -+ reason = &reasonps[nreason]; -+ reason->reason = WHITELISTED; -+ reason->type = DIGEST; -+ get_digest(ctx, &reason->digest); -+ nreason += 1; -+ has_valid_cert = true; -+ } - - rc = cert_iter_init(&iter, ctx->inpe); - if (rc < 0) -@@ -145,32 +281,81 @@ check_signature(pesigcheck_context *ctx) - ssize_t datalen; - - while (1) { -+ /* -+ * Make sure we always have enough for this iteration of the -+ * loop, plus one "NO_WHITELIST" entry at the end. -+ */ -+ if (nreason >= num_reasons - 4) { -+ struct reason *new_reasons; -+ -+ num_reasons += 16; -+ -+ new_reasons = calloc(sizeof(struct reason), num_reasons); -+ if (!new_reasons) -+ err(1, "check_signature"); -+ reasonps = new_reasons; -+ } -+ - rc = next_cert(&iter, &data, &datalen); - if (rc <= 0) - break; - -- if (cert_matches_digest(ctx, data, datalen) < 0) { -- has_invalid_cert = 1; -- break; -+ reason = &reasonps[nreason]; -+ if (cert_matches_digest(ctx, data, datalen, -+ &reason->digest) < 0) { -+ reason->reason = INVALID; -+ reason->type = DIGEST; -+ nreason += 1; -+ is_invalid = true; - } - -- if (check_db_cert(DBX, ctx, data, datalen) == FOUND) { -- has_invalid_cert = 1; -- break; -+ reason = &reasonps[nreason]; -+ if (check_db_cert(DBX, ctx, data, datalen, -+ &reason->db_cert) == FOUND) { -+ reason->reason = INVALID; -+ reason->type = SIGNATURE; -+ reason->sig.data = data; -+ reason->sig.len = datalen; -+ reason->type = siBuffer; -+ nreason += 1; -+ is_invalid = true; - } - -- if (check_db_cert(DB, ctx, data, datalen) == FOUND) -- has_valid_cert = 1; -+ reason = &reasonps[nreason]; -+ if (check_db_cert(DB, ctx, data, datalen, -+ &reason->db_cert) == FOUND) { -+ reason->reason = WHITELISTED; -+ reason->type = SIGNATURE; -+ reason->sig.data = data; -+ reason->sig.len = datalen; -+ reason->type = siBuffer; -+ nreason += 1; -+ has_valid_cert = true; -+ } - } - - err: -- if (has_invalid_cert) -- return -1; -+ if (has_valid_cert != true) { -+ if (is_invalid != true) { -+ reason = &reasonps[nreason]; -+ reason->reason = NO_WHITELIST; -+ reason->type = NONE; -+ nreason += 1; -+ } -+ is_invalid = true; -+ } - -- if (has_valid_cert) -- return 0; -+ if (is_invalid == false) -+ ret = 0; - -- return -1; -+ if (nreasons && reasons) { -+ *nreasons = nreason; -+ *reasons = reasonps; -+ } else { -+ free(reasonps); -+ } -+ -+ return ret; - } - - void -@@ -204,6 +389,9 @@ main(int argc, char *argv[]) - - pesigcheck_context ctx, *ctxp = &ctx; - -+ struct reason *reasons = NULL; -+ int nreasons = 0; -+ - char *dbfile = NULL; - char *dbxfile = NULL; - char *certfile = NULL; -@@ -242,6 +430,12 @@ main(int argc, char *argv[]) - .arg = &ctx.quiet, - .val = 1, - .descrip = "return only; no text output." }, -+ {.longName = "verbose", -+ .shortName = 'v', -+ .argInfo = POPT_BIT_SET, -+ .arg = &ctx.verbose, -+ .val = 1, -+ .descrip = "print reasons for success and failure." }, - {.longName = "no-system-db", - .shortName = 'n', - .argInfo = POPT_ARG_INT, -@@ -308,12 +502,16 @@ main(int argc, char *argv[]) - exit(1); - } - -- rc = check_signature(ctxp); -+ rc = check_signature(ctxp, &nreasons, &reasons); - -- close_input(ctxp); -+ if (!ctx.quiet && ctx.verbose) { -+ for (int i = 0; i < nreasons; i++) -+ print_reason(&reasons[i]); -+ } - if (!ctx.quiet) - printf("pesigcheck: \"%s\" is %s.\n", ctx.infile, - rc >= 0 ? "valid" : "invalid"); -+ close_input(ctxp); - pesigcheck_context_fini(&ctx); - - NSS_Shutdown(); -diff --git a/src/pesigcheck_context.h b/src/pesigcheck_context.h -index 7b5cc89..aec415e 100644 ---- a/src/pesigcheck_context.h -+++ b/src/pesigcheck_context.h -@@ -61,6 +61,7 @@ typedef struct pesigcheck_context { - Pe *inpe; - - int quiet; -+ int verbose; - - hashlist *hashes; - --- -2.13.4 - diff --git a/0021-Fix-race-condition-in-SEC_GetPassword.patch b/0021-Fix-race-condition-in-SEC_GetPassword.patch deleted file mode 100644 index 3088923..0000000 --- a/0021-Fix-race-condition-in-SEC_GetPassword.patch +++ /dev/null @@ -1,34 +0,0 @@ -From a40c584691ae071e93e8adf4e5c05bcd90c68159 Mon Sep 17 00:00:00 2001 -From: Julien Cristau -Date: Sat, 6 May 2017 22:45:34 +0200 -Subject: [PATCH 21/29] Fix race condition in SEC_GetPassword - -A side effect of echoOff is to discard unread input, so if we print the -prompt before echoOff, the user (or process) at the other end might -react to it by writing the password in between those steps, which is -then discarded. This bit me when trying to drive pesign with an expect -script. - -Signed-off-by: Julien Cristau ---- - src/password.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/password.c b/src/password.c -index cd1c07e..d4eae0d 100644 ---- a/src/password.c -+++ b/src/password.c -@@ -71,9 +71,9 @@ static char *SEC_GetPassword(FILE *input, FILE *output, char *prompt, - for (;;) { - /* Prompt for password */ - if (isTTY) { -+ echoOff(infd); - fprintf(output, "%s", prompt); - fflush (output); -- echoOff(infd); - } - - fgets ( phrase, sizeof(phrase), input); --- -2.13.4 - diff --git a/0021-share-input-output-checker-macros-between-pesign_kmo.patch b/0021-share-input-output-checker-macros-between-pesign_kmo.patch new file mode 100644 index 0000000..bde7edc --- /dev/null +++ b/0021-share-input-output-checker-macros-between-pesign_kmo.patch @@ -0,0 +1,411 @@ +From 9209c1e45ca7fa0c821f0da57dd6e1ff746de267 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 21 May 2019 14:29:24 -0400 +Subject: [PATCH 21/42] share input/output checker macros between pesign_kmod + and file_pe + +Signed-off-by: Peter Jones +--- + src/file_pe.c | 48 --------------- + src/pesign.c | 2 + + src/pesign_kmod.c | 142 ++++++++----------------------------------- + src/pesign_context.h | 20 ++++-- + src/util.h | 65 ++++++++++++++++++++ + 5 files changed, 110 insertions(+), 167 deletions(-) + +diff --git a/src/file_pe.c b/src/file_pe.c +index ad076eba961..31672c68f79 100644 +--- a/src/file_pe.c ++++ b/src/file_pe.c +@@ -104,54 +104,6 @@ open_output(pesign_context *ctx) + pe_clearcert(ctx->outpe); + } + +-#define define_input_file(fname, name, descr) \ +- static void \ +- CAT3(open_, fname, _input)(pesign_context *ctx) \ +- { \ +- conderrx(!ctx->name, 1, \ +- "No input file specified for %s", \ +- descr); \ +- ctx->CAT(name, fd) = \ +- open(ctx->name, O_RDONLY|O_CLOEXEC); \ +- conderr(ctx->CAT(name, fd) < 0, 1, \ +- "Error opening %s file \"%s\" for input", \ +- descr, ctx->name); \ +- } \ +- static void \ +- CAT3(close_, fname, _input)(pesign_context *ctx) \ +- { \ +- close(ctx->CAT(name, fd)); \ +- ctx->CAT(name, fd) = -1; \ +- } +- +-#define define_output_file(fname, name, descr) \ +- static void \ +- CAT3(open_, fname, _output)(pesign_context *ctx) \ +- { \ +- conderrx(!ctx->name, 1, \ +- "No output file specified for %s.", \ +- descr); \ +- \ +- if (access(ctx->name, F_OK) == 0 && ctx->force == 0) \ +- errx(1, \ +- "\"%s\" exists and --force was not given.",\ +- ctx->name); \ +- \ +- ctx->CAT(name, fd) = \ +- open(ctx->name, \ +- O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, \ +- ctx->outmode); \ +- conderr(ctx->CAT(name, fd) < 0, 1, \ +- "Error opening %s file \"%s\" for output", \ +- descr, ctx->name); \ +- } \ +- static void \ +- CAT3(close_, fname, _output)(pesign_context *ctx) \ +- { \ +- close(ctx->CAT(name,fd)); \ +- ctx->CAT(name,fd) = -1; \ +- } +- + define_input_file(rawsig, rawsig, "raw signature"); + define_input_file(sattr, insattrs, "signed attributes"); + define_output_file(sattr, outsattrs, "signed attributes"); +diff --git a/src/pesign.c b/src/pesign.c +index 95a832df9e4..d2f3f221df0 100644 +--- a/src/pesign.c ++++ b/src/pesign.c +@@ -462,3 +462,5 @@ main(int argc, char *argv[]) + + return (rc < 0); + } ++ ++// vim:fenc=utf-8:tw=75:noet +diff --git a/src/pesign_kmod.c b/src/pesign_kmod.c +index 916ae52ebe2..a9799b83fa8 100644 +--- a/src/pesign_kmod.c ++++ b/src/pesign_kmod.c +@@ -26,96 +26,10 @@ + #include "pesign_standalone.h" + #include "file_kmod.h" + +-static void +-open_input(pesign_context *ctx) +-{ +- struct stat statbuf; +- +- if (!ctx->infile) { +- fprintf(stderr, "pesign: No input file specified.\n"); +- exit(1); +- } +- +- ctx->infd = open(ctx->infile, O_RDONLY|O_CLOEXEC); +- if (ctx->infd < 0) { +- fprintf(stderr, "pesign: Error opening input: %m\n"); +- exit(1); +- } +- +- if (fstat(ctx->infd, &statbuf)) { +- fprintf(stderr, "pesign: Error on stat input: %m\n"); +- exit(1); +- } +- +- ctx->outmode = statbuf.st_mode; +- ctx->inlength = statbuf.st_size; +-} +- +-static void +-close_input(pesign_context *ctx) +-{ +- close(ctx->infd); +- ctx->infd = -1; +-} +- +-static void +-open_output(pesign_context *ctx) +-{ +- if (!ctx->outfile) { +- fprintf(stderr, "pesign: No output file specified.\n"); +- exit(1); +- } +- +- if (access(ctx->outfile, F_OK) == 0 && ctx->force == 0) { +- fprintf(stderr, "pesign: \"%s\" exists and --force was " +- "not given.\n", ctx->outfile); +- exit(1); +- } +- +- ctx->outfd = open(ctx->outfile, O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, +- ctx->outmode); +- if (ctx->outfd < 0) { +- fprintf(stderr, "pesign: Error opening output: %m\n"); +- exit(1); +- } +-} +- +-static void +-close_output(pesign_context *ctx) +-{ +- close(ctx->outfd); +- ctx->outfd = -1; +-} +- +-static void +-open_sig_output(pesign_context *ctx) +-{ +- if (!ctx->outsig) { +- fprintf(stderr, "pesign: No output file specified.\n"); +- exit(1); +- } +- +- if (access(ctx->outsig, F_OK) == 0 && ctx->force == 0) { +- fprintf(stderr, "pesign: \"%s\" exists and --force " +- "was not given.\n", ctx->outsig); +- exit(1); +- } +- +- ctx->outsigfd = open(ctx->outsig, O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, +- ctx->outmode); +- if (ctx->outsigfd < 0) { +- fprintf(stderr, "pesign: Error opening signature for output: " +- "%m\n"); +- exit(1); +- } +-} +- +-static void +-close_sig_output(pesign_context *ctx) +-{ +- close(ctx->outsigfd); +- ctx->outsigfd = -1; +-} ++define_input_file(kmod, inkmod, "kmod"); ++define_output_file(kmod, outkmod, "kmod"); ++define_output_file(sig, outsig, "signature"); ++define_input_file(sig, insig, "signature"); + + static void + import_sig_input(pesign_context *ctx) +@@ -124,17 +38,7 @@ import_sig_input(pesign_context *ctx) + struct stat statbuf; + int rc; + +- if (!ctx->insig) { +- fprintf(stderr, "pesign: No input file specified.\n"); +- exit(1); +- } +- +- ctx->insigfd = open(ctx->insig, O_RDONLY|O_CLOEXEC); +- if (ctx->insigfd < 0) { +- fprintf(stderr, "pesign: Error opening signature for input: " +- "%m\n"); +- exit(1); +- } ++ open_sig_input(ctx); + + rc = fstat(ctx->insigfd, &statbuf); + conderr(rc < 0, 1, "Could not fstat signature file \"%s\"", +@@ -143,10 +47,10 @@ import_sig_input(pesign_context *ctx) + /* Copy original module data */ + + map = mmap(NULL, ctx->inlength, PROT_READ, MAP_PRIVATE, ctx->infd, 0); +- conderr(map == MAP_FAILED, 1, "Could not map kmod input"); ++ conderr(map == MAP_FAILED, 1, "Could not map kmod input file \"%s\"", ctx->inkmod); + + rc = write_file(ctx->outfd, map, ctx->inlength); +- conderr(rc < 0, 1, "Failed to write module data"); ++ conderr(rc < 0, 1, "Failed to write module data to \"%s\"", ctx->outkmod); + + munmap(map, ctx->inlength); + +@@ -171,7 +75,7 @@ handle_signing(pesign_context *ctx, int outfd, int attached) + ssize_t sig_len; + + inmap = mmap(NULL, ctx->inlength, PROT_READ, MAP_PRIVATE, ctx->infd, 0); +- conderrx(inmap == MAP_FAILED, 1, "Error mapping input kmod"); ++ conderr(inmap == MAP_FAILED, 1, "Could not map input kmod file \"%s\"", ctx->inkmod); + + rc = kmod_generate_digest(ctx->cms_ctx, inmap, ctx->inlength); + if (rc < 0) +@@ -179,7 +83,7 @@ handle_signing(pesign_context *ctx, int outfd, int attached) + + if (attached) { + rc = write_file(outfd, inmap, ctx->inlength); +- conderr(rc < 0, 1, "Failed to write module data"); ++ conderr(rc < 0, 1, "Failed to write module data to \"%s\"", ctx->outkmod); + } + munmap(inmap, ctx->inlength); + +@@ -205,11 +109,13 @@ kmod_handle_action(pesign_context *ctxp, int action) + conderrx(ctxp->signum > ctxp->cms_ctx->num_signatures + 1, + 1, "Invalid signature number."); + +- open_input(ctxp); +- open_output(ctxp); ++ open_kmod_input(ctxp); ++ proxy_fd_mode(ctxp->inkmodfd, ctxp->inkmod, ++ &ctxp->outmode, &ctxp->inlength); ++ open_kmod_output(ctxp); + handle_signing(ctxp, ctxp->outfd, 1); +- close_output(ctxp); +- close_input(ctxp); ++ close_kmod_output(ctxp); ++ close_kmod_input(ctxp); + break; + + /* generate a signature and save it in a separate file */ +@@ -220,22 +126,26 @@ kmod_handle_action(pesign_context *ctxp, int action) + conderrx(ctxp->signum > ctxp->cms_ctx->num_signatures + 1, + 1, "Invalid signature number."); + +- open_input(ctxp); ++ open_kmod_input(ctxp); ++ proxy_fd_mode(ctxp->inkmodfd, ctxp->inkmod, ++ &ctxp->outmode, &ctxp->inlength); + open_sig_output(ctxp); + handle_signing(ctxp, ctxp->outsigfd, 0); + close_sig_output(ctxp); +- close_input(ctxp); ++ close_kmod_input(ctxp); + break; + + /* add a signature from a file */ + case IMPORT_SIGNATURE: + conderrx(ctxp->signum > ctxp->cms_ctx->num_signatures + 1, + 1, "Invalid signature number."); +- open_input(ctxp); +- open_output(ctxp); ++ open_kmod_input(ctxp); ++ proxy_fd_mode(ctxp->inkmodfd, ctxp->inkmod, ++ &ctxp->outmode, &ctxp->inlength); ++ open_kmod_output(ctxp); + import_sig_input(ctxp); +- close_input(ctxp); +- close_output(ctxp); ++ close_kmod_input(ctxp); ++ close_kmod_output(ctxp); + break; + + default: +@@ -249,3 +159,5 @@ kmod_handle_action(pesign_context *ctxp, int action) + exit(1); + } + } ++ ++// vim:fenc=utf-8:tw=75:noet +diff --git a/src/pesign_context.h b/src/pesign_context.h +index 8d8dfbd294e..45d6831aa7f 100644 +--- a/src/pesign_context.h ++++ b/src/pesign_context.h +@@ -32,10 +32,22 @@ typedef enum { + } file_format; + + typedef struct { +- int infd; +- int outfd; +- char *infile; +- char *outfile; ++ union { ++ int infd; ++ int inkmodfd; ++ }; ++ union { ++ int outfd; ++ int outkmodfd; ++ }; ++ union { ++ char *infile; ++ char *inkmod; ++ }; ++ union { ++ char *outfile; ++ char *outkmod; ++ }; + size_t inlength; + mode_t outmode; + +diff --git a/src/util.h b/src/util.h +index 1b115a993f6..9b34f7b8886 100644 +--- a/src/util.h ++++ b/src/util.h +@@ -24,6 +24,8 @@ + #include + #include + #include ++#include ++#include + #include + + #include +@@ -207,4 +209,67 @@ content_is_empty(uint8_t *data, ssize_t len) + return 1; + } + ++#define define_input_file(fname, name, descr) \ ++ static void \ ++ CAT3(open_, fname, _input)(pesign_context *ctx) \ ++ { \ ++ conderrx(!ctx->name, 1, \ ++ "No input file specified for %s", \ ++ descr); \ ++ ctx->CAT(name, fd) = \ ++ open(ctx->name, O_RDONLY|O_CLOEXEC); \ ++ conderr(ctx->CAT(name, fd) < 0, 1, \ ++ "Error opening %s file \"%s\" for input", \ ++ descr, ctx->name); \ ++ } \ ++ static void \ ++ CAT3(close_, fname, _input)(pesign_context *ctx) \ ++ { \ ++ close(ctx->CAT(name, fd)); \ ++ ctx->CAT(name, fd) = -1; \ ++ } ++ ++#define define_output_file(fname, name, descr) \ ++ static void \ ++ CAT3(open_, fname, _output)(pesign_context *ctx) \ ++ { \ ++ conderrx(!ctx->name, 1, \ ++ "No output file specified for %s.", \ ++ descr); \ ++ \ ++ if (access(ctx->name, F_OK) == 0 && ctx->force == 0) \ ++ errx(1, \ ++ "\"%s\" exists and --force was not given.",\ ++ ctx->name); \ ++ \ ++ ctx->CAT(name, fd) = \ ++ open(ctx->name, \ ++ O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, \ ++ ctx->outmode); \ ++ conderr(ctx->CAT(name, fd) < 0, 1, \ ++ "Error opening %s file \"%s\" for output", \ ++ descr, ctx->name); \ ++ } \ ++ static void \ ++ CAT3(close_, fname, _output)(pesign_context *ctx) \ ++ { \ ++ close(ctx->CAT(name,fd)); \ ++ ctx->CAT(name,fd) = -1; \ ++ } ++ ++static inline void ++proxy_fd_mode(int fd, char *infile, mode_t *outmode, size_t *inlength) ++{ ++ struct stat statbuf; ++ int rc; ++ ++ rc = fstat(fd, &statbuf); ++ conderr(rc < 0, 1, "Could not fstat \"%s\"", infile); ++ if (outmode) ++ *outmode = statbuf.st_mode; ++ if (inlength) ++ *inlength = statbuf.st_size; ++} ++ + #endif /* PESIGN_UTIL_H */ ++// vim:fenc=utf-8:tw=75:noet +-- +2.29.2 + diff --git a/0022-Make-verbose-work-in-efisiglist.patch b/0022-Make-verbose-work-in-efisiglist.patch new file mode 100644 index 0000000..a91e38a --- /dev/null +++ b/0022-Make-verbose-work-in-efisiglist.patch @@ -0,0 +1,66 @@ +From 1ec1a523216aa9b63120fa36c3732de3c4cbf546 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 16 Feb 2021 13:24:54 -0500 +Subject: [PATCH 22/42] Make verbose work in efisiglist + +Signed-off-by: Peter Jones +--- + src/efisiglist.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/src/efisiglist.c b/src/efisiglist.c +index b91e15bfb7b..48ff89c5661 100644 +--- a/src/efisiglist.c ++++ b/src/efisiglist.c +@@ -114,6 +114,15 @@ out_of_range: + return ret; + } + ++static long *verbose; ++ ++long verbosity(void) ++{ ++ if (!verbose) ++ return 0; ++ return *verbose; ++} ++ + int + main(int argc, char *argv[]) + { +@@ -128,9 +137,12 @@ main(int argc, char *argv[]) + int certfd = -1; + void *cert_data = NULL; + size_t cert_size = 0; ++ long esl_verbose = 0; + + int add = 1; + ++ verbose = &esl_verbose; ++ + struct poptOption options[] = { + {.argInfo = POPT_ARG_INTL_DOMAIN, + .arg = "pesign" }, +@@ -175,6 +187,19 @@ main(int argc, char *argv[]) + .arg = &certfile, + .descrip = "certificate to add", + .argDescrip = "" }, ++ {.longName = "verbose", ++ .shortName = 'v', ++ .argInfo = POPT_ARG_VAL|POPT_ARG_LONG|POPT_ARGFLAG_OPTIONAL, ++ .arg = &esl_verbose, ++ .val = 1, ++ .descrip = "be more verbose" }, ++ {.longName = "debug", ++ .shortName = '\0', ++ .argInfo = POPT_ARG_VAL|POPT_ARG_LONG|POPT_ARGFLAG_OPTIONAL, ++ .arg = &esl_verbose, ++ .val = 2, ++ .descrip = "be very verbose" }, ++ + POPT_AUTOALIAS + POPT_AUTOHELP + POPT_TABLEEND +-- +2.29.2 + diff --git a/0022-sysvinit-Create-the-socket-directory-at-runtime.patch b/0022-sysvinit-Create-the-socket-directory-at-runtime.patch deleted file mode 100644 index 06980ee..0000000 --- a/0022-sysvinit-Create-the-socket-directory-at-runtime.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 27afa5a4ea8de1679603f5871935096280d0b12e Mon Sep 17 00:00:00 2001 -From: David Michael -Date: Tue, 13 Jun 2017 13:20:16 -0700 -Subject: [PATCH 22/29] sysvinit: Create the socket directory at runtime - -This better supports non-systemd configurations with tmpfs on /run. ---- - src/pesign.sysvinit.in | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/src/pesign.sysvinit.in b/src/pesign.sysvinit.in -index d8fffca..dc508d8 100644 ---- a/src/pesign.sysvinit.in -+++ b/src/pesign.sysvinit.in -@@ -20,6 +20,9 @@ RETVAL=0 - - start(){ - echo -n "Starting pesign: " -+ mkdir /var/run/pesign 2>/dev/null && -+ chown pesign:pesign /var/run/pesign && -+ chmod 0770 /var/run/pesign - daemon /usr/bin/pesign --daemonize - RETVAL=$? - echo --- -2.13.4 - diff --git a/0023-Better-authorization-scripts.-Again.patch b/0023-Better-authorization-scripts.-Again.patch deleted file mode 100644 index c778c94..0000000 --- a/0023-Better-authorization-scripts.-Again.patch +++ /dev/null @@ -1,217 +0,0 @@ -From 31560e2784722b986b8a73cc28e3510870180b07 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 8 Aug 2017 15:44:44 -0400 -Subject: [PATCH 23/29] Better authorization scripts. Again. - -Signed-off-by: Peter Jones ---- - src/Makefile | 12 ++++++---- - src/pesign-authorize | 56 +++++++++++++++++++++++++++++++++++++++++++++ - src/pesign-authorize-groups | 30 ------------------------ - src/pesign-authorize-users | 30 ------------------------ - src/pesign.service.in | 3 +-- - src/pesign.sysvinit.in | 3 +-- - 6 files changed, 65 insertions(+), 69 deletions(-) - create mode 100755 src/pesign-authorize - delete mode 100644 src/pesign-authorize-groups - delete mode 100644 src/pesign-authorize-users - -diff --git a/src/Makefile b/src/Makefile -index 654b792..84ad130 100644 ---- a/src/Makefile -+++ b/src/Makefile -@@ -7,7 +7,7 @@ include $(TOPDIR)/Make.defaults - - BINTARGETS=authvar client efikeygen efisiglist pesigcheck pesign - SVCTARGETS=pesign.sysvinit pesign.service --TARGETS=$(BINTARGETS) $(SVCTARGETS) -+TARGETS=$(BINTARGETS) $(SVCTARGETS) pesign-users pesign-groups - - all : deps $(TARGETS) - -@@ -65,6 +65,9 @@ install_sysvinit: pesign.sysvinit - $(INSTALL) -d -m 755 $(INSTALLROOT)/etc/rc.d/init.d/ - $(INSTALL) -m 755 pesign.sysvinit $(INSTALLROOT)/etc/rc.d/init.d/pesign - -+pesign-users pesign-groups : -+ echo pesign > $@ -+ - install : - $(INSTALL) -d -m 700 $(INSTALLROOT)/etc/pki/pesign/ - $(INSTALL) -d -m 700 $(INSTALLROOT)/etc/pki/pesign-rh-test/ -@@ -88,10 +91,9 @@ install : - $(INSTALL) -d -m 755 $(INSTALLROOT)/etc/rpm/ - $(INSTALL) -m 644 macros.pesign $(INSTALLROOT)/etc/rpm/ - $(INSTALL) -d -m 755 $(INSTALLROOT)$(libexecdir)/pesign/ -- $(INSTALL) -m 750 pesign-authorize-users $(INSTALLROOT)$(libexecdir)/pesign/ -- $(INSTALL) -m 750 pesign-authorize-groups $(INSTALLROOT)$(libexecdir)/pesign/ -+ $(INSTALL) -m 750 pesign-authorize $(INSTALLROOT)$(libexecdir)/pesign/ - $(INSTALL) -d -m 700 $(INSTALLROOT)/etc/pesign -- $(INSTALL) -m 600 /dev/null $(INSTALLROOT)/etc/pesign/users -- $(INSTALL) -m 600 /dev/null $(INSTALLROOT)/etc/pesign/groups -+ $(INSTALL) -m 600 pesign-users $(INSTALLROOT)/etc/pesign/users -+ $(INSTALL) -m 600 pesign-groups $(INSTALLROOT)/etc/pesign/groups - - .PHONY: all deps clean install -diff --git a/src/pesign-authorize b/src/pesign-authorize -new file mode 100755 -index 0000000..a496f60 ---- /dev/null -+++ b/src/pesign-authorize -@@ -0,0 +1,56 @@ -+#!/bin/bash -+set -e -+set -u -+ -+# -+# With /run/pesign/socket on tmpfs, a simple way of restoring the -+# acls for specific users is useful -+# -+# Compare to: http://infrastructure.fedoraproject.org/cgit/ansible.git/tree/roles/bkernel/tasks/main.yml?id=17198dadebf59d8090b7ed621bc8ab22152d2eb6 -+# -+ -+# License: GPLv2 -+declare -a fileusers=() -+declare -a dirusers=() -+for user in $(cat /etc/pesign/users); do -+ dirusers[${#dirusers[@]}]=-m -+ dirusers[${#dirusers[@]}]="u:$user:rwx" -+ fileusers[${#fileusers[@]}]=-m -+ fileusers[${#fileusers[@]}]="u:$user:rw" -+done -+ -+declare -a filegroups=() -+declare -a dirgroups=() -+for group in $(cat /etc/pesign/groups); do -+ dirgroups[${#dirgroups[@]}]=-m -+ dirgroups[${#dirgroups[@]}]="g:$group:rwx" -+ filegroups[${#filegroups[@]}]=-m -+ filegroups[${#filegroups[@]}]="g:$group:rw" -+done -+ -+update_subdir() { -+ subdir=$1 && shift -+ -+ setfacl -bk "${subdir}" -+ setfacl "${dirusers[@]}" "${dirgroups[@]}" "${subdir}" -+ for x in "${subdir}"* ; do -+ if [ -d "${x}" ]; then -+ setfacl -bk ${x} -+ setfacl "${dirusers[@]}" "${dirgroups[@]}" ${x} -+ update_subdir "${x}/" -+ elif [ -e "${x}" ]; then -+ setfacl -bk ${x} -+ setfacl "${fileusers[@]}" "${filegroups[@]}" ${x} -+ else -+ :; -+ fi -+ done -+} -+ -+for x in /var/run/pesign/ /etc/pki/pesign*/ ; do -+ if [ -d "${x}" ]; then -+ update_subdir "${x}" -+ else -+ :; -+ fi -+done -diff --git a/src/pesign-authorize-groups b/src/pesign-authorize-groups -deleted file mode 100644 -index cf51fb6..0000000 ---- a/src/pesign-authorize-groups -+++ /dev/null -@@ -1,30 +0,0 @@ --#!/bin/bash --set -e -- --# --# With /run/pesign/socket on tmpfs, a simple way of restoring the --# acls for specific groups is useful --# --# Compare to: http://infrastructure.fedoraproject.org/cgit/ansible.git/tree/roles/bkernel/tasks/main.yml?id=17198dadebf59d8090b7ed621bc8ab22152d2eb6 --# -- --# License: GPLv2 -- --if [ -r /etc/pesign/groups ]; then -- for group in $(cat /etc/pesign/groups); do -- if [ -d /var/run/pesign ]; then -- setfacl -m g:${group}:rx /var/run/pesign -- if [ -e /var/run/pesign/socket ]; then -- setfacl -m g:${group}:rw /var/run/pesign/socket -- fi -- fi -- for x in /etc/pki/pesign*/ ; do -- if [ -d ${x} ]; then -- setfacl -m g:${group}:rx ${x} -- for y in ${x}{cert8,key3,secmod}.db ; do -- setfacl -m g:${group}:rw ${y} -- done -- fi -- done -- done --fi -diff --git a/src/pesign-authorize-users b/src/pesign-authorize-users -deleted file mode 100644 -index 940138e..0000000 ---- a/src/pesign-authorize-users -+++ /dev/null -@@ -1,30 +0,0 @@ --#!/bin/bash --set -e -- --# --# With /run/pesign/socket on tmpfs, a simple way of restoring the --# acls for specific users is useful --# --# Compare to: http://infrastructure.fedoraproject.org/cgit/ansible.git/tree/roles/bkernel/tasks/main.yml?id=17198dadebf59d8090b7ed621bc8ab22152d2eb6 --# -- --# License: GPLv2 -- --if [ -r /etc/pesign/users ]; then -- for username in $(cat /etc/pesign/users); do -- if [ -d /var/run/pesign ]; then -- setfacl -m g:${username}:rx /var/run/pesign -- if [ -e /var/run/pesign/socket ]; then -- setfacl -m g:${username}:rw /var/run/pesign/socket -- fi -- fi -- for x in /etc/pki/pesign*/ ; do -- if [ -d ${x} ]; then -- setfacl -m g:${username}:rx ${x} -- for y in ${x}{cert8,key3,secmod}.db ; do -- setfacl -m g:${username}:rw ${y} -- done -- fi -- done -- done --fi -diff --git a/src/pesign.service.in b/src/pesign.service.in -index aaa408e..c75a000 100644 ---- a/src/pesign.service.in -+++ b/src/pesign.service.in -@@ -6,5 +6,4 @@ PrivateTmp=true - Type=forking - PIDFile=/var/run/pesign.pid - ExecStart=/usr/bin/pesign --daemonize --ExecStartPost=@@LIBEXECDIR@@/pesign/pesign-authorize-users --ExecStartPost=@@LIBEXECDIR@@/pesign/pesign-authorize-groups -+ExecStartPost=@@LIBEXECDIR@@/pesign/pesign-authorize -diff --git a/src/pesign.sysvinit.in b/src/pesign.sysvinit.in -index dc508d8..b0e0f84 100644 ---- a/src/pesign.sysvinit.in -+++ b/src/pesign.sysvinit.in -@@ -27,8 +27,7 @@ start(){ - RETVAL=$? - echo - touch /var/lock/subsys/pesign -- @@LIBEXECDIR@@/pesign/pesign-authorize-users -- @@LIBEXECDIR@@/pesign/pesign-authorize-groups -+ @@LIBEXECDIR@@/pesign/pesign-authorize - } - - stop(){ --- -2.13.4 - diff --git a/0023-Make-verbose-and-debug-more-similar-across-tools.patch b/0023-Make-verbose-and-debug-more-similar-across-tools.patch new file mode 100644 index 0000000..45d8526 --- /dev/null +++ b/0023-Make-verbose-and-debug-more-similar-across-tools.patch @@ -0,0 +1,321 @@ +From 8fc539b9712c0e736abfdd3b493d97f7107e91ec Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 28 Apr 2020 10:08:03 -0400 +Subject: [PATCH 23/42] Make --verbose and --debug more similar across tools + +Signed-off-by: Peter Jones +--- + src/authvar.c | 21 +++++++++++++++++++++ + src/client.c | 18 ++++++++++++++++++ + src/cms_pe_common.c | 6 ------ + src/efikeygen.c | 21 +++++++++++++++++++++ + src/pesigcheck.c | 18 +++++++++++++++++- + src/pesign.c | 19 ++++++++++++++++++- + src/authvar_context.h | 2 ++ + src/pesigcheck_context.h | 2 +- + src/pesign_context.h | 2 +- + src/util.h | 14 +++++++++++++- + 10 files changed, 112 insertions(+), 11 deletions(-) + +diff --git a/src/authvar.c b/src/authvar.c +index f9a7dcef9f7..a6c3970e4dc 100644 +--- a/src/authvar.c ++++ b/src/authvar.c +@@ -260,6 +260,15 @@ show_signature_support(void) + return 0; + } + ++static long *verbose; ++ ++long verbosity(void) ++{ ++ if (!verbose) ++ return 0; ++ return *verbose; ++} ++ + int + main(int argc, char *argv[]) + { +@@ -370,6 +379,18 @@ main(int argc, char *argv[]) + .arg = &ctx.cms_ctx->certname, + .descrip = "sign variable with certificate ", + .argDescrip = "" }, ++ {.longName = "verbose", ++ .shortName = 'v', ++ .argInfo = POPT_ARG_VAL|POPT_ARG_LONG|POPT_ARGFLAG_OPTIONAL, ++ .arg = &ctxp->verbose, ++ .val = 1, ++ .descrip = "be more verbose" }, ++ {.longName = "debug", ++ .shortName = '\0', ++ .argInfo = POPT_ARG_VAL|POPT_ARG_LONG|POPT_ARGFLAG_OPTIONAL, ++ .arg = &ctxp->verbose, ++ .val = 2, ++ .descrip = "be very verbose" }, + POPT_AUTOALIAS + POPT_AUTOHELP + POPT_TABLEEND +diff --git a/src/client.c b/src/client.c +index a4f1d1dbbe7..a00b20f5dde 100644 +--- a/src/client.c ++++ b/src/client.c +@@ -600,6 +600,12 @@ oom: + return; + } + ++static long verbose; ++long verbosity(void) ++{ ++ return verbose; ++} ++ + int + main(int argc, char *argv[]) + { +@@ -687,6 +693,18 @@ main(int argc, char *argv[]) + .arg = &pinfile, + .descrip = "read named file for pin information", + .argDescrip = "" }, ++ {.longName = "verbose", ++ .shortName = 'v', ++ .argInfo = POPT_ARG_VAL, ++ .arg = &verbose, ++ .val = 1, ++ .descrip = "be more verbose" }, ++ {.longName = "debug", ++ .shortName = '\0', ++ .argInfo = POPT_ARG_VAL|POPT_ARG_LONG|POPT_ARGFLAG_OPTIONAL, ++ .arg = &verbose, ++ .val = 2, ++ .descrip = "be very verbose" }, + POPT_AUTOALIAS + POPT_AUTOHELP + POPT_TABLEEND +diff --git a/src/cms_pe_common.c b/src/cms_pe_common.c +index 05f72e4431a..00061804a78 100644 +--- a/src/cms_pe_common.c ++++ b/src/cms_pe_common.c +@@ -42,12 +42,6 @@ + #include + #include + +-#if 1 +-#define dprintf(fmt, ...) +-#else +-#define dprintf(fmt, args...) printf(fmt, ## args) +-#endif +- + static int + check_pointer_and_size(Pe *pe, void *ptr, size_t size) + { +diff --git a/src/efikeygen.c b/src/efikeygen.c +index ac2ce45a420..b1cac4705e8 100644 +--- a/src/efikeygen.c ++++ b/src/efikeygen.c +@@ -492,6 +492,13 @@ SEC_ASN1EncodeLongLong(PRArenaPool *poolp, SECItem *dest, + return dest; + } + ++static long verbose = 0; ++ ++long verbosity(void) ++{ ++ return verbose; ++} ++ + int main(int argc, char *argv[]) + { + int is_ca = 0; +@@ -586,6 +593,18 @@ int main(int argc, char *argv[]) + .arg = &serial_str, + .descrip = "Serial number (default: random)", + .argDescrip = "" }, ++ {.longName = "verbose", ++ .shortName = 'v', ++ .argInfo = POPT_ARG_VAL, ++ .arg = &verbose, ++ .val = 1, ++ .descrip = "Be more verbose" }, ++ {.longName = "debug", ++ .shortName = '\0', ++ .argInfo = POPT_ARG_VAL|POPT_ARG_LONG|POPT_ARGFLAG_OPTIONAL, ++ .arg = &verbose, ++ .val = 2, ++ .descrip = "Be very verbose" }, + + /* hidden things */ + {.longName = "pubkey", +@@ -870,3 +889,5 @@ int main(int argc, char *argv[]) + NSS_Shutdown(); + return 0; + } ++ ++// vim:fenc=utf-8:tw=75:noet +diff --git a/src/pesigcheck.c b/src/pesigcheck.c +index 961a32a6ad7..87d4960a9a9 100644 +--- a/src/pesigcheck.c ++++ b/src/pesigcheck.c +@@ -386,6 +386,15 @@ callback(poptContext con UNUSED, + } + } + ++static long *verbose; ++ ++long verbosity(void) ++{ ++ if (!verbose) ++ return 0; ++ return *verbose; ++} ++ + int + main(int argc, char *argv[]) + { +@@ -436,10 +445,16 @@ main(int argc, char *argv[]) + .descrip = "return only; no text output." }, + {.longName = "verbose", + .shortName = 'v', +- .argInfo = POPT_BIT_SET, ++ .argInfo = POPT_ARG_VAL|POPT_ARG_LONG|POPT_ARGFLAG_OPTIONAL, + .arg = &ctx.verbose, + .val = 1, + .descrip = "print reasons for success and failure." }, ++ {.longName = "debug", ++ .shortName = '\0', ++ .argInfo = POPT_ARG_VAL|POPT_ARG_LONG|POPT_ARGFLAG_OPTIONAL, ++ .arg = &ctxp->verbose, ++ .val = 2, ++ .descrip = "be very verbose" }, + {.longName = "no-system-db", + .shortName = 'n', + .argInfo = POPT_ARG_INT, +@@ -475,6 +490,7 @@ main(int argc, char *argv[]) + fprintf(stderr, "pesigcheck: Could not initialize context: %m\n"); + exit(1); + } ++ verbose = &ctxp->verbose; + + optCon = poptGetContext("pesigcheck", argc, (const char **)argv, + options,0); +diff --git a/src/pesign.c b/src/pesign.c +index d2f3f221df0..854120c15c5 100644 +--- a/src/pesign.c ++++ b/src/pesign.c +@@ -64,6 +64,15 @@ print_flag_name(FILE *f, int flag) + } + } + ++static long *verbose; ++ ++long verbosity(void) ++{ ++ if (!verbose) ++ return 0; ++ return *verbose; ++} ++ + int + main(int argc, char *argv[]) + { +@@ -94,6 +103,7 @@ main(int argc, char *argv[]) + fprintf(stderr, "Could not initialize context: %m\n"); + exit(1); + } ++ verbose = &ctxp->verbose; + + poptContext optCon; + struct poptOption options[] = { +@@ -234,10 +244,17 @@ main(int argc, char *argv[]) + .descrip = "don't fork when daemonizing" }, + {.longName = "verbose", + .shortName = 'v', +- .argInfo = POPT_ARG_VAL, ++ .argInfo = POPT_ARG_VAL|POPT_ARG_LONG|POPT_ARGFLAG_OPTIONAL, + .arg = &ctxp->verbose, + .val = 1, ++ .descrip = "be more verbose" }, ++ {.longName = "debug", ++ .shortName = '\0', ++ .argInfo = POPT_ARG_VAL|POPT_ARG_LONG|POPT_ARGFLAG_OPTIONAL, ++ .arg = &ctxp->verbose, ++ .val = 2, + .descrip = "be very verbose" }, ++ + {.longName = "padding", + .shortName = 'P', + .argInfo = POPT_ARG_VAL, +diff --git a/src/authvar_context.h b/src/authvar_context.h +index e9250dd250f..13c18a988f4 100644 +--- a/src/authvar_context.h ++++ b/src/authvar_context.h +@@ -20,6 +20,8 @@ + #define AUTHVAR_CONTEXT_H 1 + + typedef struct { ++ long verbose; ++ + char *namespace; + efi_guid_t guid; + char *name; +diff --git a/src/pesigcheck_context.h b/src/pesigcheck_context.h +index aec415e0cbe..fa72439c875 100644 +--- a/src/pesigcheck_context.h ++++ b/src/pesigcheck_context.h +@@ -61,7 +61,7 @@ typedef struct pesigcheck_context { + Pe *inpe; + + int quiet; +- int verbose; ++ long verbose; + + hashlist *hashes; + +diff --git a/src/pesign_context.h b/src/pesign_context.h +index 45d6831aa7f..0af044d92b4 100644 +--- a/src/pesign_context.h ++++ b/src/pesign_context.h +@@ -52,7 +52,7 @@ typedef struct { + mode_t outmode; + + int force; +- int verbose; ++ long verbose; + + char *rawsig; + int rawsigfd; +diff --git a/src/util.h b/src/util.h +index 9b34f7b8886..21a846c10ee 100644 +--- a/src/util.h ++++ b/src/util.h +@@ -24,8 +24,9 @@ + #include + #include + #include +-#include + #include ++#include ++#include + #include + + #include +@@ -271,5 +272,16 @@ proxy_fd_mode(int fd, char *infile, mode_t *outmode, size_t *inlength) + *inlength = statbuf.st_size; + } + ++extern long verbosity(void); ++ ++#define dprintf_(tv, file, func, line, fmt, args...) ({struct timeval tv; gettimeofday(&tv, NULL); warnx("%ld.%lu %s:%s():%d: " fmt, tv.tv_sec, tv.tv_usec, file, func, line, ##args); }) ++#if defined(PESIGN_DEBUG) ++#define dprintf(fmt, args...) dprintf_(CAT(CAT(CAT(tv_,__COUNTER__),__LINE__),_), __FILE__, __func__, __LINE__, fmt, ##args) ++#else ++#define dprintf(fmt, args...) ({ if (verbosity() > 1) dprintf_(CAT(CAT(CAT(tv_,__COUNTER__),__LINE__),_), __FILE__, __func__, __LINE__, fmt, ##args); 0; }) ++#endif ++#define ingress() dprintf("ingress"); ++#define egress() dprintf("egress"); ++ + #endif /* PESIGN_UTIL_H */ + // vim:fenc=utf-8:tw=75:noet +-- +2.29.2 + diff --git a/0024-Make-the-daemon-also-try-to-give-better-errors-on-EP.patch b/0024-Make-the-daemon-also-try-to-give-better-errors-on-EP.patch deleted file mode 100644 index 8f4a380..0000000 --- a/0024-Make-the-daemon-also-try-to-give-better-errors-on-EP.patch +++ /dev/null @@ -1,95 +0,0 @@ -From a7b0f7e1ce2de1acea9a8c286a0ff3dd9bc245cb Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Tue, 8 Aug 2017 17:28:19 -0400 -Subject: [PATCH 24/29] Make the daemon also try to give better errors on - -EPERM etc. - -Basically 6796e5f but also for the daemon. This also tries to fix them -up to save errno better, for more accurate reporting. - -Signed-off-by: Peter Jones ---- - src/daemon.c | 27 +++++++++++++++++++++++++-- - src/pesign.c | 8 ++++++-- - 2 files changed, 31 insertions(+), 4 deletions(-) - -diff --git a/src/daemon.c b/src/daemon.c -index 7f694b2..942d576 100644 ---- a/src/daemon.c -+++ b/src/daemon.c -@@ -19,6 +19,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -1104,10 +1105,32 @@ daemonize(cms_context *cms_ctx, char *certdir, int do_fork) - "pesignd starting (pid %d)", ctx.pid); - - SECStatus status = NSS_Init(certdir); -+ int error = errno; - if (status != SECSuccess) { -+ char *globpattern = NULL; -+ rc = asprintf(&globpattern, "%s/cert*.db", -+ certdir); -+ if (rc > 0) { -+ glob_t globbuf; -+ memset(&globbuf, 0, sizeof(globbuf)); -+ rc = glob(globpattern, GLOB_ERR, NULL, -+ &globbuf); -+ if (rc != 0) { -+ errno = error; -+ ctx.backup_cms->log(ctx.backup_cms, -+ ctx.priority|LOG_NOTICE, -+ "Could not open NSS database (\"%s\"): %m", -+ PORT_ErrorToString(PORT_GetError())); -+ exit(1); -+ } -+ } -+ } -+ if (status != SECSuccess) { -+ errno = error; - ctx.backup_cms->log(ctx.backup_cms, ctx.priority|LOG_NOTICE, -- "Could not initialize nss: %s\n", -- PORT_ErrorToString(PORT_GetError())); -+ "Could not initialize nss.\n" -+ "NSS says \"%s\" errno says \"%m\"\n", -+ PORT_ErrorToString(PORT_GetError())); - exit(1); - } - -diff --git a/src/pesign.c b/src/pesign.c -index 5879cfc..6ceda34 100644 ---- a/src/pesign.c -+++ b/src/pesign.c -@@ -660,10 +660,12 @@ main(int argc, char *argv[]) - - if (!daemon) { - SECStatus status; -+ int error; - if (need_db) { - status = NSS_Init(certdir); - if (status != SECSuccess) { - char *globpattern = NULL; -+ error = errno; - rc = asprintf(&globpattern, "%s/cert*.db", - certdir); - if (rc > 0) { -@@ -680,8 +682,10 @@ main(int argc, char *argv[]) - } else - status = NSS_NoDB_Init(NULL); - if (status != SECSuccess) { -- errx(1, "Could not initialize nss. NSS says \"%s\" errno says \"%m\"\n", -- PORT_ErrorToString(PORT_GetError())); -+ errno = error; -+ errx(1, "Could not initialize nss.\n" -+ "NSS says \"%s\" errno says \"%m\"\n", -+ PORT_ErrorToString(PORT_GetError())); - } - - status = register_oids(ctxp->cms_ctx); --- -2.13.4 - diff --git a/0024-Work-around-some-NSS-SECOID_AddEntry-bugs.patch b/0024-Work-around-some-NSS-SECOID_AddEntry-bugs.patch new file mode 100644 index 0000000..102e5e4 --- /dev/null +++ b/0024-Work-around-some-NSS-SECOID_AddEntry-bugs.patch @@ -0,0 +1,46 @@ +From fe2c0facc37f01bdcca8362cc4db7dbd701b6959 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 28 Apr 2020 10:18:08 -0400 +Subject: [PATCH 24/42] Work around some NSS SECOID_AddEntry() bugs + +Signed-off-by: Peter Jones +--- + src/oid.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/src/oid.c b/src/oid.c +index 4d95ede4046..a2e63093c00 100644 +--- a/src/oid.c ++++ b/src/oid.c +@@ -72,17 +72,25 @@ static struct { + SECStatus + register_oids(cms_context *cms) + { ++ int err = PORT_GetError(); ++ PORT_SetError(0); + for (int i = 0; oids[i].oid != END_OID_LIST; i++) { + SECOidTag rc; + rc = SECOID_AddEntry(&oids[i].sod); + oids[i].sod.offset = rc; + if (rc == SEC_OID_UNKNOWN) { +- cms->log(cms, LOG_ERR, "SECOid_AddEntry() failed: %s", +- PORT_ErrorToString(PORT_GetError())); +- return SECFailure; ++ cmsreterr(SECFailure, cms, ++ "SECOid_AddEntry() failed: %s", ++ PORT_ErrorToString(PORT_GetError())); ++ } else { + } + } + ++ /* ++ * SECOID_AddEntry() leaves the error status that it ++ * used to look it up set. This is very annoying. ++ */ ++ PORT_SetError(err); + return SECSuccess; + } + +-- +2.29.2 + diff --git a/0025-Rework-the-wildly-undocumented-NSS-password-file-goo.patch b/0025-Rework-the-wildly-undocumented-NSS-password-file-goo.patch new file mode 100644 index 0000000..9a0be72 --- /dev/null +++ b/0025-Rework-the-wildly-undocumented-NSS-password-file-goo.patch @@ -0,0 +1,1385 @@ +From db4e0e71d71d794b4d95bfc90145ea243f7d064b Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 28 Apr 2020 10:21:52 -0400 +Subject: [PATCH 25/42] Rework the wildly undocumented NSS password file goo. + +This probably doesn't work yet. +--- + src/cms_common.c | 223 ++++++++++------ + src/cms_pe_common.c | 2 +- + src/daemon.c | 8 +- + src/password.c | 614 +++++++++++++++++++++++++++++--------------- + src/pesign.c | 45 +++- + src/signer_info.c | 9 +- + src/cms_common.h | 57 +++- + 7 files changed, 646 insertions(+), 312 deletions(-) + +diff --git a/src/cms_common.c b/src/cms_common.c +index 75a95f053a2..c2f34e515a2 100644 +--- a/src/cms_common.c ++++ b/src/cms_common.c +@@ -164,11 +164,31 @@ cms_context_fini(cms_context *cms) + cms->cert = NULL; + } + ++ switch (cms->pwdata.source) { ++ case PW_SOURCE_INVALID: ++ case PW_PROMPT: ++ case PW_DEVICE: ++ case PW_FROMFILEDB: ++ case PW_FROMENV: ++ case PW_SOURCE_MAX: ++ break; ++ case PW_DATABASE: ++ xfree(cms->pwdata.data); ++ break; ++ case PW_PLAINTEXT: ++ memset(cms->pwdata.data, 0, strlen(cms->pwdata.data)); ++ xfree(cms->pwdata.data); ++ break; ++ } ++ cms->pwdata.source = PW_SOURCE_INVALID; ++ cms->pwdata.orig_source = PW_SOURCE_INVALID; ++ + if (cms->privkey) { + free(cms->privkey); + cms->privkey = NULL; + } + ++ + /* These were freed when the arena was destroyed */ + if (cms->tokenname) + cms->tokenname = NULL; +@@ -255,9 +275,35 @@ void cms_set_pw_callback(cms_context *cms, PK11PasswordFunc func) + cms->func = func; + } + +-void cms_set_pw_data(cms_context *cms, void *pwdata) ++void cms_set_pw_data(cms_context *cms, secuPWData *pwdata) + { +- cms->pwdata = pwdata; ++ ingress(); ++ ++ switch (cms->pwdata.source) { ++ case PW_SOURCE_INVALID: ++ case PW_PROMPT: ++ case PW_DEVICE: ++ case PW_SOURCE_MAX: ++ break; ++ ++ case PW_FROMENV: ++ case PW_FROMFILEDB: ++ case PW_PLAINTEXT: ++ memset(cms->pwdata.data, 0, strlen(cms->pwdata.data)); ++ xfree(cms->pwdata.data); ++ break; ++ ++ case PW_DATABASE: ++ xfree(cms->pwdata.data); ++ break; ++ } ++ memmove(&cms->pwdata, pwdata, sizeof(*pwdata)); ++ ++ dprintf("pwdata:%p", pwdata); ++ dprintf("pwdata->source:%d", pwdata->source); ++ dprintf("pwdata->data:%p (\"%s\")", pwdata->data, ++ pwdata->data ? pwdata->data : "(null)"); ++ egress(); + } + + int +@@ -280,24 +326,26 @@ set_digest_parameters(cms_context *cms, char *name) + return -1; + } + +-struct cbdata { +- CERTCertificate *cert; ++struct validity_cbdata { ++ cms_context *cms; + PK11SlotListElement *psle; +- secuPWData *pwdata; ++ PK11SlotInfo *slot; ++ CERTCertificate *cert; + }; + + static SECStatus + is_valid_cert(CERTCertificate *cert, void *data) + { +- struct cbdata *cbdata = (struct cbdata *)data; +- +- PK11SlotInfo *slot = cbdata->psle->slot; +- void *pwdata = cbdata->pwdata; +- ++ struct validity_cbdata *cbd = (struct validity_cbdata *)data; ++ PK11SlotInfo *slot = cbd->slot; + SECKEYPrivateKey *privkey = NULL; +- privkey = PK11_FindPrivateKeyFromCert(slot, cert, pwdata); ++ ++ if (cert == NULL) ++ return SECFailure; ++ ++ privkey = PK11_FindPrivateKeyFromCert(slot, cert, cbd->cms); + if (privkey != NULL) { +- cbdata->cert = cert; ++ cbd->cert = CERT_DupCertificate(cert); + SECKEY_DestroyPrivateKey(privkey); + return SECSuccess; + } +@@ -307,9 +355,15 @@ is_valid_cert(CERTCertificate *cert, void *data) + static SECStatus + is_valid_cert_without_private_key(CERTCertificate *cert, void *data) + { +- struct cbdata *cbdata = (struct cbdata *)data; +- if (cert) { +- cbdata->cert = cert; ++ struct validity_cbdata *cbd = (struct validity_cbdata *)data; ++ PK11SlotInfo *slot = cbd->slot; ++ SECKEYPrivateKey *privkey = NULL; ++ ++ if (cert == NULL) ++ return SECFailure; ++ privkey = PK11_FindPrivateKeyFromCert(slot, cert, cbd->cms); ++ if (privkey == NULL) { ++ cbd->cert = CERT_DupCertificate(cert); + return SECSuccess; + } + return SECFailure; +@@ -338,12 +392,10 @@ PK11_DestroySlotListElement(PK11SlotList *slots, PK11SlotListElement **psle) + int + unlock_nss_token(cms_context *cms) + { +- secuPWData pwdata_val = { 0, 0 }; +- void *pwdata = cms->pwdata ? cms->pwdata : &pwdata_val; + PK11_SetPasswordFunc(cms->func ? cms->func : SECU_GetModulePassword); + + PK11SlotList *slots = NULL; +- slots = PK11_GetAllTokens(CKM_RSA_PKCS, PR_FALSE, PR_TRUE, pwdata); ++ slots = PK11_GetAllTokens(CKM_RSA_PKCS, PR_FALSE, PR_TRUE, cms); + if (!slots) + cmsreterr(-1, cms, "could not get pk11 token list"); + +@@ -367,20 +419,21 @@ unlock_nss_token(cms_context *cms) + save_port_err() { + PK11_FreeSlotList(slots); + } +- cms->log(cms, LOG_ERR, "could not find token \"%s\"", +- cms->tokenname); +- return -1; ++ nssreterr(-1, "Could not find token \"%s\"", cms->tokenname); + } + + SECStatus status; + if (PK11_NeedLogin(psle->slot) && +- !PK11_IsLoggedIn(psle->slot, pwdata)) { +- status = PK11_Authenticate(psle->slot, PR_TRUE, pwdata); ++ !PK11_IsLoggedIn(psle->slot, cms)) { ++ status = PK11_Authenticate(psle->slot, PR_TRUE, cms); + if (status != SECSuccess) { +- PK11_DestroySlotListElement(slots, &psle); +- PK11_FreeSlotList(slots); +- cms->log(cms, LOG_ERR, "authentication failed for " +- "token \"%s\"", cms->tokenname); ++ save_port_err() { ++ PK11_DestroySlotListElement(slots, &psle); ++ PK11_FreeSlotList(slots); ++ cms->log(cms, LOG_ERR, ++ "authentication failed for token \"%s\"", ++ cms->tokenname); ++ } + return -1; + } + } +@@ -393,17 +446,16 @@ unlock_nss_token(cms_context *cms) + int + find_certificate(cms_context *cms, int needs_private_key) + { ++ struct validity_cbdata cbd; + if (!cms->certname || !*cms->certname) { + cms->log(cms, LOG_ERR, "no certificate name specified"); + return -1; + } + +- secuPWData pwdata_val = { 0, 0 }; +- void *pwdata = cms->pwdata ? cms->pwdata : &pwdata_val; + PK11_SetPasswordFunc(cms->func ? cms->func : SECU_GetModulePassword); + + PK11SlotList *slots = NULL; +- slots = PK11_GetAllTokens(CKM_RSA_PKCS, PR_FALSE, PR_TRUE, pwdata); ++ slots = PK11_GetAllTokens(CKM_RSA_PKCS, PR_FALSE, PR_TRUE, cms); + if (!slots) + cmsreterr(-1, cms, "could not get pk11 token list"); + +@@ -427,19 +479,20 @@ find_certificate(cms_context *cms, int needs_private_key) + save_port_err() { + PK11_FreeSlotList(slots); + } +- cms->log(cms, LOG_ERR, "could not find token \"%s\"", +- cms->tokenname); +- return -1; ++ nssreterr(-1, "Could not find token \"%s\"", cms->tokenname); + } + + SECStatus status; +- if (PK11_NeedLogin(psle->slot) && !PK11_IsLoggedIn(psle->slot, pwdata)) { +- status = PK11_Authenticate(psle->slot, PR_TRUE, pwdata); ++ if (PK11_NeedLogin(psle->slot) && !PK11_IsLoggedIn(psle->slot, cms)) { ++ status = PK11_Authenticate(psle->slot, PR_TRUE, cms); + if (status != SECSuccess) { +- PK11_DestroySlotListElement(slots, &psle); +- PK11_FreeSlotList(slots); +- cms->log(cms, LOG_ERR, "authentication failed for " +- "token \"%s\"", cms->tokenname); ++ save_port_err() { ++ PK11_DestroySlotListElement(slots, &psle); ++ PK11_FreeSlotList(slots); ++ cms->log(cms, LOG_ERR, ++ "authentication failed for token \"%s\"", ++ cms->tokenname); ++ } + return -1; + } + } +@@ -459,35 +512,37 @@ find_certificate(cms_context *cms, int needs_private_key) + .len = strlen(cms->certname) + 1, + .type = siUTF8String, + }; +- struct cbdata cbdata = { +- .cert = NULL, +- .psle = psle, +- .pwdata = pwdata, +- }; ++ ++ cms->psle = psle; ++ ++ cbd.cms = cms; ++ cbd.psle = psle; ++ cbd.slot = psle->slot; ++ cbd.cert = NULL; + + if (needs_private_key) { + status = PK11_TraverseCertsForNicknameInSlot(&nickname, +- psle->slot, is_valid_cert, &cbdata); ++ psle->slot, is_valid_cert, &cbd); + } else { + status = PK11_TraverseCertsForNicknameInSlot(&nickname, + psle->slot, + is_valid_cert_without_private_key, +- &cbdata); ++ &cbd); + } +- if (status != SECSuccess || cbdata.cert == NULL) { +- save_port_err() { +- CERT_DestroyCertList(certlist); +- PK11_DestroySlotListElement(slots, &psle); +- PK11_FreeSlotList(slots); +- } ++ if (status == SECSuccess && cbd.cert != NULL) { ++ if (cms->cert) ++ CERT_DestroyCertificate(cms->cert); ++ cms->cert = CERT_DupCertificate(cbd.cert); ++ } ++ ++ save_port_err() { ++ CERT_DestroyCertList(certlist); ++ PK11_DestroySlotListElement(slots, &psle); ++ PK11_FreeSlotList(slots); ++ cms->psle = NULL; ++ } ++ if (status != SECSuccess || cms->cert == NULL) + cmsreterr(-1, cms, "could not find certificate in list"); +- } +- +- cms->cert = CERT_DupCertificate(cbdata.cert); +- +- PK11_DestroySlotListElement(slots, &psle); +- PK11_FreeSlotList(slots); +- CERT_DestroyCertList(certlist); + + return 0; + } +@@ -500,12 +555,10 @@ find_slot_for_token(cms_context *cms, PK11SlotInfo **slot) + return -1; + } + +- secuPWData pwdata_val = { 0, 0 }; +- void *pwdata = cms->pwdata ? cms->pwdata : &pwdata_val; + PK11_SetPasswordFunc(cms->func ? cms->func : SECU_GetModulePassword); + + PK11SlotList *slots = NULL; +- slots = PK11_GetAllTokens(CKM_RSA_PKCS, PR_FALSE, PR_TRUE, pwdata); ++ slots = PK11_GetAllTokens(CKM_RSA_PKCS, PR_FALSE, PR_TRUE, cms); + if (!slots) + cmsreterr(-1, cms, "could not get pk11 token list"); + +@@ -529,19 +582,20 @@ find_slot_for_token(cms_context *cms, PK11SlotInfo **slot) + save_port_err() { + PK11_FreeSlotList(slots); + } +- cms->log(cms, LOG_ERR, "could not find token \"%s\"", +- cms->tokenname); +- return -1; ++ nssreterr(-1, "Could not find token \"%s\"", cms->tokenname); + } + + SECStatus status; +- if (PK11_NeedLogin(psle->slot) && !PK11_IsLoggedIn(psle->slot, pwdata)) { +- status = PK11_Authenticate(psle->slot, PR_TRUE, pwdata); ++ if (PK11_NeedLogin(psle->slot) && !PK11_IsLoggedIn(psle->slot, cms)) { ++ status = PK11_Authenticate(psle->slot, PR_TRUE, cms); + if (status != SECSuccess) { +- PK11_DestroySlotListElement(slots, &psle); +- PK11_FreeSlotList(slots); +- cms->log(cms, LOG_ERR, "authentication failed for " +- "token \"%s\"", cms->tokenname); ++ save_port_err() { ++ PK11_DestroySlotListElement(slots, &psle); ++ PK11_FreeSlotList(slots); ++ cms->log(cms, LOG_ERR, ++ "authentication failed for token \"%s\"", ++ cms->tokenname); ++ } + return -1; + } + } +@@ -557,12 +611,10 @@ find_named_certificate(cms_context *cms, char *name, CERTCertificate **cert) + return -1; + } + +- secuPWData pwdata_val = { 0, 0 }; +- void *pwdata = cms->pwdata ? cms->pwdata : &pwdata_val; + PK11_SetPasswordFunc(cms->func ? cms->func : SECU_GetModulePassword); + + PK11SlotList *slots = NULL; +- slots = PK11_GetAllTokens(CKM_RSA_PKCS, PR_FALSE, PR_TRUE, pwdata); ++ slots = PK11_GetAllTokens(CKM_RSA_PKCS, PR_FALSE, PR_TRUE, cms); + if (!slots) + cmsreterr(-1, cms, "could not get pk11 token list"); + +@@ -585,20 +637,23 @@ find_named_certificate(cms_context *cms, char *name, CERTCertificate **cert) + if (!psle) { + save_port_err() { + PK11_FreeSlotList(slots); ++ cms->log(cms, LOG_ERR, "could not find token \"%s\"", ++ cms->tokenname); + } +- cms->log(cms, LOG_ERR, "could not find token \"%s\"", +- cms->tokenname); + return -1; + } + + SECStatus status; +- if (PK11_NeedLogin(psle->slot) && !PK11_IsLoggedIn(psle->slot, pwdata)) { +- status = PK11_Authenticate(psle->slot, PR_TRUE, pwdata); ++ if (PK11_NeedLogin(psle->slot) && !PK11_IsLoggedIn(psle->slot, cms)) { ++ status = PK11_Authenticate(psle->slot, PR_TRUE, cms); + if (status != SECSuccess) { +- PK11_DestroySlotListElement(slots, &psle); +- PK11_FreeSlotList(slots); +- cms->log(cms, LOG_ERR, "authentication failed for " +- "token \"%s\"", cms->tokenname); ++ save_port_err() { ++ PK11_DestroySlotListElement(slots, &psle); ++ PK11_FreeSlotList(slots); ++ cms->log(cms, LOG_ERR, ++ "authentication failed for token \"%s\"", ++ cms->tokenname); ++ } + return -1; + } + } +@@ -1492,14 +1547,14 @@ generate_keys(cms_context *cms, PK11SlotInfo *slot, + }; + + SECStatus rv; +- rv = PK11_Authenticate(slot, PR_TRUE, cms->pwdata); ++ rv = PK11_Authenticate(slot, PR_TRUE, cms); + if (rv != SECSuccess) + cmsreterr(-1, cms, "could not authenticate with pk11 service"); + + void *params = &rsaparams; + *privkey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, + params, pubkey, PR_TRUE, PR_TRUE, +- cms->pwdata); ++ cms); + if (!*privkey) + cmsreterr(-1, cms, "could not generate RSA keypair"); + return 0; +diff --git a/src/cms_pe_common.c b/src/cms_pe_common.c +index 00061804a78..bd96fe91d69 100644 +--- a/src/cms_pe_common.c ++++ b/src/cms_pe_common.c +@@ -275,7 +275,7 @@ generate_digest(cms_context *cms, Pe *pe, int padded) + char *name = shdrs[i].name; + if (name && name[0] == '/') + name = get_str(pe, name + 1); +- dprintf("section:\"%s\"\n", name); ++ dprintf("section:\"%s\"\n", name ? name : "(null)"); + if (name && !strcmp(name, ".vendor_cert")) { + dprintf("skipping .vendor_cert section\n"); + hashed_bytes += hash_size; +diff --git a/src/daemon.c b/src/daemon.c +index 8522250c2b4..9a804b37e64 100644 +--- a/src/daemon.c ++++ b/src/daemon.c +@@ -237,8 +237,14 @@ malformed: + if (!pin) + goto oom; + ++ secuPWData pwdata; ++ ++ memset(&pwdata, 0, sizeof(pwdata)); ++ pwdata.source = pwdata.orig_source = PW_PLAINTEXT; ++ pwdata.data = pin; ++ + cms_set_pw_callback(ctx->cms, get_password_passthrough); +- cms_set_pw_data(ctx->cms, pin); ++ cms_set_pw_data(ctx->cms, &pwdata); + + rc = unlock_nss_token(ctx->cms); + +diff --git a/src/password.c b/src/password.c +index 0da880a659d..0a4ef411ff7 100644 +--- a/src/password.c ++++ b/src/password.c +@@ -19,14 +19,17 @@ + + #include "fix_coverity.h" + ++#include + #include + #include ++#include + #include + #include + + #include "pesign.h" + + #include ++#include + #include + #include + #include +@@ -35,207 +38,324 @@ + #include + #include + +-static void echoOff(int fd) ++#include "list.h" ++ ++static const char * const pw_source_names[] = { ++ [PW_SOURCE_INVALID] = "PW_SOURCE_INVALID", ++ [PW_PROMPT] = "PW_PROMPT", ++ [PW_DEVICE] = "PW_DEVICE", ++ [PW_PLAINTEXT] = "PW_PLAINTEXT", ++ [PW_FROMFILEDB] = "PW_FROMFILEDB", ++ [PW_DATABASE] = "PW_DATABASE", ++ [PW_FROMENV] = "PW_FROMENV", ++ ++ [PW_SOURCE_MAX] = "PW_SOURCE_MAX" ++}; ++ ++static void ++print_prompt(FILE *in, FILE *out, char *prompt) + { +- if (isatty(fd)) { ++ int infd = fileno(in); + struct termios tio; +- tcgetattr(fd, &tio); ++ ++ if (!isatty(infd)) ++ return; ++ ++ fprintf(out, "%s", prompt); ++ fflush(out); ++ ++ tcgetattr(infd, &tio); + tio.c_lflag &= ~ECHO; +- tcsetattr(fd, TCSAFLUSH, &tio); +- } ++ tcsetattr(infd, TCSAFLUSH, &tio); + } + +-static void echoOn(int fd) ++static inline char * ++get_env(const char *name) + { +- if (isatty(fd)) { ++ char *value; ++ ++ value = secure_getenv(name); ++ if (value) ++ value = strdup(value); ++ return value; ++} ++ ++static int ++read_password(FILE *in, FILE *out, char *buf, size_t bufsz) ++{ ++ int infd = fileno(in); + struct termios tio; +- tcgetattr(fd, &tio); +- tio.c_lflag |= ECHO; +- tcsetattr(fd, TCSAFLUSH, &tio); +- } ++ char *ret; ++ ++ ret = fgets(buf, bufsz, in); ++ ++ if (isatty(infd)) { ++ fprintf(out, "\n"); ++ fflush(out); ++ ++ tcgetattr(infd, &tio); ++ tio.c_lflag |= ECHO; ++ tcsetattr(infd, TCSAFLUSH, &tio); ++ } ++ if (ret == NULL) ++ return -1; ++ ++ buf[strlen(buf)-1] = '\0'; ++ return 0; + } + +-static PRBool SEC_BlindCheckPassword(char *cp) ++static PRBool ++check_password(char *cp) + { +- if (cp != NULL) { ++ unsigned int i; ++ ++ if (cp == NULL) ++ return PR_FALSE; ++ ++ for (i = 0; cp[i] != 0; i++) { ++ if (!isprint(cp[i])) ++ return PR_FALSE; ++ } ++ if (i == 0) ++ return PR_FALSE; + return PR_TRUE; +- } +- return PR_FALSE; + } + +-static char *SEC_GetPassword(FILE *input, FILE *output, char *prompt, +- PRBool (*ok)(char *)) ++static char * ++get_password(FILE *input, FILE *output, char *prompt, PRBool (*ok)(char *)) + { +- int infd = fileno(input); +- int isTTY = isatty(infd); +- char phrase[200] = {'\0'}; /* ensure EOF doesn't return junk */ +- +- for (;;) { +- /* Prompt for password */ +- if (isTTY) { +- echoOff(infd); +- fprintf(output, "%s", prompt); +- fflush (output); +- } ++ int infd = fileno(input); ++ char phrase[200]; ++ size_t size = sizeof(phrase); + +- fgets ( phrase, sizeof(phrase), input); ++ ingress(); ++ memset(phrase, 0, size); + +- if (isTTY) { +- fprintf(output, "\n"); +- echoOn(infd); +- } ++ while(true) { ++ int rc; + +- /* stomp on newline */ +- phrase[PORT_Strlen(phrase)-1] = 0; ++ print_prompt(input, output, prompt); ++ rc = read_password(input, output, phrase, size); ++ if (rc < 0) ++ return NULL; + +- /* Validate password */ +- if (!(*ok)(phrase)) { +- /* Not weird enough */ +- if (!isTTY) return 0; +- fprintf(output, "Password must be at least 8 characters long with one or more\n"); +- fprintf(output, "non-alphabetic characters\n"); +- continue; ++ if (!ok) ++ break; ++ ++ if ((*ok)(phrase)) ++ break; ++ ++ if (!isatty(infd)) ++ return NULL; ++ fprintf(output, "Password does not meet requirements.\n"); ++ fflush(output); + } +- return (char*) PORT_Strdup(phrase); +- } +-} + +-static char consoleName[] = { "/dev/tty" }; ++ egress(); ++ return (char *)PORT_Strdup(phrase); ++} + + static char * +-SECU_GetPasswordString(void *arg UNUSED, +- char *prompt UNUSED) ++SECU_GetPasswordString(void *arg UNUSED, char *prompt) ++{ ++ char *ret; ++ ingress(); ++ ret = get_password(stdin, stdout, prompt, check_password); ++ egress(); ++ return ret; ++} ++ ++static int token_pass_cmp(const void *tp0p, const void *tp1p) ++{ ++ const struct token_pass * const tp0 = (const struct token_pass * const)tp0p; ++ const struct token_pass * const tp1 = (const struct token_pass * const)tp1p; ++ int rc; ++ ++ if (!tp1->token || !tp0->token) ++ return tp1->token - tp0->token; ++ rc = strcmp(tp0->token, tp1->token); ++ if (rc == 0) ++ rc = strcmp(tp0->pass, tp1->pass); ++ return rc; ++} ++ ++static int ++parse_pwfile_line(char *start, struct token_pass *tp) + { +- char *p = NULL; +- FILE *input, *output; +- +- /* open terminal */ +- input = fopen(consoleName, "r"); +- if (input == NULL) { +- fprintf(stderr, "Error opening input terminal %s for read\n", +- consoleName); +- return NULL; +- } +- +- output = fopen(consoleName, "w"); +- if (output == NULL) { +- fclose(input); +- fprintf(stderr, "Error opening output terminal %s for write\n", +- consoleName); +- return NULL; +- } +- +- p = SEC_GetPassword (input, output, prompt, SEC_BlindCheckPassword); +- +- fclose(input); +- fclose(output); +- +- return p; ++ size_t span, escspan; ++ char *line = start; ++ size_t offset = 0; ++ ++ span = strspn(line, whitespace_and_eol_chars); ++ dprintf("whitespace span is %zd", span); ++ if (span == 0 && line[span] == '\0') ++ return -1; ++ line += span; ++ ++ tp->token = NULL; ++ tp->pass = line; ++ ++ offset = 0; ++ do { ++ span = strcspn(line + offset, whitespace_and_eol_chars); ++ escspan = strescspn(line + offset); ++ if (escspan < span) ++ offset += escspan + 2; ++ } while(escspan < span); ++ span += offset; ++ dprintf("non-whitespace span is %zd", span); ++ ++ if (line[span] == '\0') { ++ dprintf("returning %ld", (line + span) - start); ++ return (line + span) - start; ++ } ++ line[span] = '\0'; ++ ++ line += span + 1; ++ span = strspn(line, whitespace_and_eol_chars); ++ dprintf("whitespace span is %zd", span); ++ line += span; ++ tp->token = tp->pass; ++ tp->pass = line; ++ ++ offset = 0; ++ do { ++ span = strcspn(line + offset, whitespace_and_eol_chars); ++ escspan = strescspn(line + offset); ++ if (escspan < span) ++ offset += escspan + 2; ++ } while(escspan < span); ++ span += offset; ++ dprintf("non-whitespace span is %zd", span); ++ if (line[span] != '\0') ++ line[span++] = '\0'; ++ ++ resolve_escapes(tp->token); ++ dprintf("Setting token pass %p to { %p, %p }", tp, tp->token, tp->pass); ++ dprintf("token:\"%s\"", tp->token); ++ dprintf("pass:\"%s\"", tp->pass); ++ dprintf("returning %ld", (line + span) - start); ++ return (line + span) - start; + } + +-/* +- * p a s s w o r d _ h a r d c o d e +- * +- * A function to use the password passed in the -f(pwfile) argument +- * of the command line. +- * After use once, null it out otherwise PKCS11 calls us forever.? +- * +- */ + static char * + SECU_FilePasswd(PK11SlotInfo *slot, PRBool retry, void *arg) + { +- char* phrases, *phrase; +- PRFileDesc *fd; +- PRInt32 nb; +- char *pwFile = arg; +- int i; +- const long maxPwdFileSize = 4096; +- char* tokenName = NULL; +- int tokenLen = 0; ++ cms_context *cms = (cms_context *)arg; ++ int fd; ++ char *file = NULL; ++ char *token_name = slot ? PK11_GetTokenName(slot) : NULL; ++ struct token_pass *phrases = NULL; ++ size_t nphrases = 0; ++ char *phrase = NULL; ++ char *start; ++ char *ret = NULL; ++ char *path; + +- if (!pwFile) +- return 0; ++ ingress(); ++ dprintf("token_name: %s", token_name); ++ path = cms->pwdata.data; + +- if (retry) { +- return 0; /* no good retrying - the files contents will be the same */ +- } ++ if (!path || retry) ++ goto err; + +- phrases = PORT_ZAlloc(maxPwdFileSize); ++ phrases = calloc(1, sizeof(struct token_pass)); ++ if (!phrases) ++ goto err; + +- if (!phrases) { +- return 0; /* out of memory */ +- } +- +- fd = PR_Open(pwFile, PR_RDONLY, 0); +- if (!fd) { +- fprintf(stderr, "No password file \"%s\" exists.\n", pwFile); +- PORT_Free(phrases); +- return NULL; +- } ++ fd = open(path, O_RDONLY|O_CLOEXEC); ++ if (fd < 0) { ++ goto err_phrases; ++ } else { ++ size_t file_len = 0; ++ int rc; ++ rc = read_file(fd, &file, &file_len); ++ set_errno_guard(); ++ close(fd); + +- nb = PR_Read(fd, phrases, maxPwdFileSize); +- +- PR_Close(fd); ++ if (rc < 0 || file_len < 1) ++ goto err_file; ++ file[file_len-1] = '\0'; ++ dprintf("file_len:%zd", file_len); ++ dprintf("file:\"%s\"", file); + +- if (nb == 0) { +- fprintf(stderr,"password file contains no data\n"); +- PORT_Free(phrases); +- return NULL; +- } ++ unbreak_line_continuations(file, file_len); ++ } + +- if (slot) { +- tokenName = PK11_GetTokenName(slot); +- if (tokenName) { +- tokenLen = PORT_Strlen(tokenName); +- } +- } +- i = 0; +- do +- { +- int startphrase = i; +- int phraseLen; ++ start = file; ++ while (start && start[0]) { ++ size_t span; ++ struct token_pass *new_phrases; ++ int rc; ++ char c; + +- /* handle the Windows EOL case */ +- while (phrases[i] != '\r' && phrases[i] != '\n' && i < nb) i++; +- /* terminate passphrase */ +- phrases[i++] = '\0'; +- /* clean up any EOL before the start of the next passphrase */ +- while ( (ipwdata.source = PW_DATABASE; ++ xfree(cms->pwdata.data); ++ cms->pwdata.pwdb.phrases = phrases; ++ cms->pwdata.pwdb.nphrases = nphrases; ++ ++ for (size_t i = 0; i < nphrases; i++) { ++ if (phrases[i].token == NULL || phrases[i].token[0] == '\0' ++ || (token_name && !strcmp(token_name, phrases[i].token))) { ++ phrase = phrases[i].pass; ++ break; ++ } ++ } ++ ++ if (phrase) { ++ ret = PORT_Strdup(phrase); ++ if (!ret) ++ errno = ENOMEM; ++ } ++ ++err_file: ++ xfree(file); ++err_phrases: ++ xfree(phrases); ++err: ++ dprintf("ret:\"%s\"", ret ? ret : "(null)"); ++ egress(); ++ return ret; + } + + char * + get_password_passthrough(PK11SlotInfo *slot UNUSED, + PRBool retry, void *arg) + { +- if (retry) ++ if (retry || !arg) + return NULL; + +- if (!arg) +- return arg; +- + char *ret = strdup(arg); +- if (!ret) { +- fprintf(stderr, "Failed to allocate memory\n"); +- exit(1); +- } ++ if (!ret) ++ err(1, "Could not allocate memory"); ++ + return ret; + } + +@@ -247,54 +367,126 @@ get_password_fail(PK11SlotInfo *slot UNUSED, + return NULL; + } + ++static bool ++can_prompt_again(secuPWData *pwdata) ++{ ++ if (pwdata->orig_source == PW_PROMPT) ++ return true; ++ ++ if (pwdata->source == PW_DEVICE) ++ return true; ++ ++ return false; ++} ++ + char * + SECU_GetModulePassword(PK11SlotInfo *slot, PRBool retry, void *arg) + { +- char prompt[255]; +- secuPWData *pwdata = (secuPWData *)arg; +- secuPWData pwnull = { PW_NONE, 0 }; +- secuPWData pwxtrn = { PW_EXTERNAL, "external" }; +- char *pw; +- +- if (pwdata == NULL) +- pwdata = &pwnull; +- +- if (PK11_ProtectedAuthenticationPath(slot)) { +- pwdata = &pwxtrn; +- } +- if (retry && pwdata->source != PW_NONE) { +- PR_fprintf(PR_STDERR, "Incorrect password/PIN entered.\n"); ++ char *prompt = NULL; ++ cms_context *cms = (cms_context *)arg; ++ secuPWData *pwdata; ++ secuPWData pwxtrn = { .source = PW_DEVICE, .orig_source = PW_DEVICE, .data = NULL }; ++ char *pw; ++ int rc; ++ ++ ingress(); ++ ++ if (PK11_ProtectedAuthenticationPath(slot)) { ++ dprintf("prompting for PW_DEVICE data"); ++ pwdata = &pwxtrn; ++ } else { ++ dprintf("using pwdata from cms"); ++ pwdata = &cms->pwdata; ++ } ++ ++ if (pwdata->source <= PW_SOURCE_INVALID || ++ pwdata->source >= PW_SOURCE_MAX || ++ pwdata->orig_source <= PW_SOURCE_INVALID || ++ pwdata->orig_source >= PW_SOURCE_MAX) { ++ dprintf("pwdata is invalid"); ++ return NULL; ++ } ++ ++ dprintf("pwdata:%p retry:%d", pwdata, retry); ++ dprintf("pwdata->source:%s (%d) orig:%s (%d)", ++ pw_source_names[pwdata->source], pwdata->source, ++ pw_source_names[pwdata->orig_source], pwdata->orig_source); ++ dprintf("pwdata->data:%p (\"%s\")", pwdata->data, ++ pwdata->data ? pwdata->data : "(null)"); ++ ++ if (retry) { ++ warnx("Incorrect password/PIN entered."); ++ if (!can_prompt_again(pwdata)) { ++ egress(); ++ return NULL; ++ } ++ } ++ ++ switch (pwdata->source) { ++ case PW_PROMPT: ++ rc = asprintf(&prompt, "Enter Password or Pin for \"%s\":", ++ PK11_GetTokenName(slot)); ++ if (rc < 0) ++ return NULL; ++ pw = SECU_GetPasswordString(NULL, prompt); ++ if (!pw) ++ return NULL; ++ free(prompt); ++ ++ pwdata->source = PW_PLAINTEXT; ++ egress(); ++ return pw; ++ ++ case PW_DEVICE: ++ dprintf("pwdata->source:PW_DEVICE"); ++ rc = asprintf(&prompt, ++ "Press Enter, then enter PIN for \"%s\" on external device.\n", ++ PK11_GetTokenName(slot)); ++ if (rc < 0) ++ return NULL; ++ pw = SECU_GetPasswordString(NULL, prompt); ++ free(prompt); ++ return pw; ++ ++ case PW_FROMFILEDB: ++ case PW_DATABASE: ++ dprintf("pwdata->source:%s", pw_source_names[pwdata->source]); ++ /* Instead of opening and closing the file every time, get the pw ++ * once, then keep it in memory (duh). ++ */ ++ pw = SECU_FilePasswd(slot, retry, cms); ++ if (pw != NULL) { ++ pwdata->source = PW_PLAINTEXT; ++ pwdata->data = strdup(pw); ++ } ++ /* it's already been dup'ed */ ++ egress(); ++ return pw; ++ ++ case PW_FROMENV: ++ dprintf("pwdata->source:PW_FROMENV"); ++ if (!pwdata || !pwdata->data) ++ break; ++ pw = get_env(pwdata->data); ++ dprintf("env:%s pw:%s", pwdata->data, pw ? pw : "(null)"); ++ pwdata->data = pw; ++ pwdata->source = PW_PLAINTEXT; ++ goto PW_PLAINTEXT; ++ ++ PW_PLAINTEXT: ++ case PW_PLAINTEXT: ++ egress(); ++ if (pwdata && pwdata->data) ++ return strdup(pwdata->data); ++ return NULL; ++ ++ default: ++ break; ++ } ++ ++ warnx("Password check failed: No password found."); ++ egress(); + return NULL; +- } +- +- switch (pwdata->source) { +- case PW_NONE: +- sprintf(prompt, "Enter Password or Pin for \"%s\":", +- PK11_GetTokenName(slot)); +- return SECU_GetPasswordString(NULL, prompt); +- case PW_FROMFILE: +- /* Instead of opening and closing the file every time, get the pw +- * once, then keep it in memory (duh). +- */ +- pw = SECU_FilePasswd(slot, retry, pwdata->data); +- pwdata->source = PW_PLAINTEXT; +- pwdata->data = PL_strdup(pw); +- /* it's already been dup'ed */ +- return pw; +- case PW_EXTERNAL: +- sprintf(prompt, +- "Press Enter, then enter PIN for \"%s\" on external device.\n", +- PK11_GetTokenName(slot)); +- (void) SECU_GetPasswordString(NULL, prompt); +- /* Fall Through */ +- case PW_PLAINTEXT: +- return PL_strdup(pwdata->data); +- default: +- break; +- } +- +- PR_fprintf(PR_STDERR, "Password check failed: No password found.\n"); +- return NULL; + } + + #if 0 +@@ -307,28 +499,31 @@ readpw(PK11SlotInfo *slot UNUSED, + { + struct termios sio, tio; + char line[LINE_MAX], *p; ++ char *ret; + ++ ingress(); + memset(line, '\0', sizeof (line)); + + if (tcgetattr(fileno(stdin), &sio) < 0) { +- fprintf(stderr, "Could not read password from standard input.\n"); ++ warnx("Could not read password from standard input."); + return NULL; + } + tio = sio; + tio.c_lflag &= ~ECHO; + if (tcsetattr(fileno(stdin), 0, &tio) < 0) { +- fprintf(stderr, "Could not read password from standard input.\n"); ++ warnx("Could not read password from standard input."); + return NULL; + } + + fprintf(stdout, "Enter passphrase for private key: "); +- if (fgets(line, sizeof(line), stdin) == NULL) { +- fprintf(stdout, "\n"); +- tcsetattr(fileno(stdin), 0, &sio); +- return NULL; +- } +- fprintf(stdout, "\n"); ++ fflush(stdout); ++ ret = fgets(line, sizeof(line), stdin); ++ set_errno_guard(); + tcsetattr(fileno(stdin), 0, &sio); ++ fprintf(stdout, "\n"); ++ fflush(stdout); ++ if (ret == NULL) ++ return NULL; + + p = line + strcspn(line, "\r\n"); + if (p == NULL) +@@ -336,11 +531,14 @@ readpw(PK11SlotInfo *slot UNUSED, + if (p != NULL) + *p = '\0'; + +- char *ret = strdup(line); ++ ret = strdup(line); + memset(line, '\0', sizeof (line)); + if (!ret) { +- fprintf(stderr, "Could not read passphrase.\n"); ++ warnx("Could not read passphrase."); + return NULL; + } ++ egress(); + return ret; + } ++ ++// vim:fenc=utf-8:tw=75:noet +diff --git a/src/pesign.c b/src/pesign.c +index 854120c15c5..e68a141b935 100644 +--- a/src/pesign.c ++++ b/src/pesign.c +@@ -73,6 +73,10 @@ long verbosity(void) + return *verbose; + } + ++enum { ++ POPT_RET_PWDB = 0x40000001 ++}; ++ + int + main(int argc, char *argv[]) + { +@@ -96,6 +100,10 @@ main(int argc, char *argv[]) + char *certdir = "/etc/pki/pesign"; + char *signum = NULL; + ++ secuPWData pwdata; ++ ++ memset(&pwdata, 0, sizeof(pwdata)); ++ + setenv("NSS_DEFAULT_DB_TYPE", "sql", 0); + + rc = pesign_context_new(&ctxp); +@@ -273,6 +281,12 @@ main(int argc, char *argv[]) + .arg = &check_vendor_cert, + .val = 0, + .descrip = "do not hash the .vendor_cert section." }, ++ {.longName = "pwfile", ++ .shortName = '\0', ++ .argInfo = POPT_ARG_STRING|POPT_ARGFLAG_DOC_HIDDEN, ++ .arg = &pwdata.data, ++ .descrip = "file to read passwords from.", ++ .argDescrip = "" }, + POPT_AUTOALIAS + POPT_AUTOHELP + POPT_TABLEEND +@@ -287,8 +301,32 @@ main(int argc, char *argv[]) + exit(1); + } + +- while ((rc = poptGetNextOpt(optCon)) > 0) +- ; ++ while ((rc = poptGetNextOpt(optCon)) > 0) { ++ switch (rc) { ++ case POPT_RET_PWDB: ++ dprintf("POPT_RET_PWDB:\"%s\"", pwdata.data ? pwdata.data : "(null)"); ++ if (pwdata.source != PW_SOURCE_INVALID) ++ errx(1, "only one password/pin method can be used at a time"); ++ if (pwdata.data == NULL) ++ errx(1, "--pwfile requires a file name as an argument"); ++ pwdata.source = PW_FROMFILEDB; ++ pwdata.data = strdup(pwdata.data); ++ if (!pwdata.data) ++ err(1, "could not allocate memory"); ++ continue; ++ } ++ } ++ ++ dprintf("pwdata.source:%d %schecking for PESIGN_TOKEN_PIN", ++ pwdata.source, ++ pwdata.source == PW_SOURCE_INVALID ? "" : "not "); ++ if (pwdata.source == PW_SOURCE_INVALID && secure_getenv("PESIGN_TOKEN_PIN")) { ++ pwdata.source = PW_FROMENV; ++ pwdata.data = strdup(secure_getenv("PESIGN_TOKEN_PIN")); ++ if (!pwdata.data) ++ err(1, "could not allocate memory"); ++ } ++ pwdata.orig_source = pwdata.source; + + if (rc < -1) { + fprintf(stderr, "pesign: Invalid argument: %s: %s\n", +@@ -411,6 +449,9 @@ main(int argc, char *argv[]) + exit(!is_help); + } + ++ if (pwdata.source != PW_DEVICE) ++ cms_set_pw_data(ctxp->cms_ctx, &pwdata); ++ + ctxp->cms_ctx->omit_vendor_cert = !check_vendor_cert; + + ctxp->cms_ctx->tokenname = tokenname ? +diff --git a/src/signer_info.c b/src/signer_info.c +index afa00e2c52e..6b73bce45d7 100644 +--- a/src/signer_info.c ++++ b/src/signer_info.c +@@ -173,15 +173,14 @@ sign_blob(cms_context *cms, SECItem *sigitem, SECItem *sign_content) + if (!oid) + goto err; + +- PK11_SetPasswordFunc(cms->func ? cms->func : readpw); +- SECKEYPrivateKey *privkey = PK11_FindKeyByAnyCert(cms->cert, +- cms->pwdata ? cms->pwdata : NULL); ++ PK11_SetPasswordFunc(cms->func ? cms->func : SECU_GetModulePassword); ++ SECKEYPrivateKey *privkey = PK11_FindKeyByAnyCert(cms->cert, cms); + if (!privkey) { + cms->log(cms, LOG_ERR, "could not get private key: %s", + PORT_ErrorToString(PORT_GetError())); + goto err; + } +- ++ + SECItem *signature, tmp; + memset (&tmp, '\0', sizeof (tmp)); + +@@ -446,3 +445,5 @@ generate_authvar_signer_info(cms_context *cms, SpcSignerInfo *sip) + err: + return -1; + } ++ ++// vim:fenc=utf-8:tw=75:noet +diff --git a/src/cms_common.h b/src/cms_common.h +index b0dc12fc3ab..34ab6551ddd 100644 +--- a/src/cms_common.h ++++ b/src/cms_common.h +@@ -25,11 +25,15 @@ + #include + #include + #include ++#include ++#include ++#include + #include + #include + #include + + #include "util.h" ++#include "password.h" + + #define save_port_err() \ + for (error_t saved_errno_0_ = 0, saved_errno_1_ = PORT_GetError(); saved_errno_0_ < 1; saved_errno_0_++, PORT_SetError(saved_errno_1_)) +@@ -56,6 +60,44 @@ struct digest { + SECItem *pe_digest; + }; + ++struct token_pass { ++ char *token; ++ char *pass; ++}; ++ ++struct pw_database { ++ struct token_pass *phrases; ++ size_t nphrases; ++}; ++ ++typedef enum { ++ // used only for bounds checking ++ PW_SOURCE_INVALID = 0, ++ // prompt the user (pwdata->data is NULL) ++ PW_PROMPT = 1, ++ // prompt the user to use a device (pwdata->data is NULL) ++ PW_DEVICE = 2, ++ // pwdata->data is plain text ++ PW_PLAINTEXT = 3, ++ // pwdata->data is a filename for a database ++ PW_FROMFILEDB = 4, ++ // pwdata->data is the database data ++ PW_DATABASE = 5, ++ // pwdata->data is the name of an environment variable ++ PW_FROMENV = 6, ++ ++ // used only for bounds checking ++ PW_SOURCE_MAX ++} pw_source_t; ++ ++typedef struct { ++ pw_source_t source; ++ pw_source_t orig_source; ++ ++ struct pw_database pwdb; ++ char *data; ++} secuPWData; ++ + struct cms_context; + + typedef int (*cms_common_logger)(struct cms_context *, int priority, +@@ -68,8 +110,9 @@ typedef struct cms_context { + char *tokenname; + char *certname; + CERTCertificate *cert; ++ PK11SlotListElement *psle; + PK11PasswordFunc func; +- void *pwdata; ++ secuPWData pwdata; + + struct digest *digests; + int selected_digest; +@@ -156,7 +199,7 @@ extern SECOidTag digest_get_encryption_oid(cms_context *cms); + extern SECOidTag digest_get_signature_oid(cms_context *cms); + extern int digest_get_digest_size(cms_context *cms); + extern void cms_set_pw_callback(cms_context *cms, PK11PasswordFunc func); +-extern void cms_set_pw_data(cms_context *cms, void *pwdata); ++extern void cms_set_pw_data(cms_context *cms, secuPWData *pwdata); + + extern int set_digest_parameters(cms_context *ctx, char *name); + +@@ -164,15 +207,5 @@ extern int generate_digest_begin(cms_context *cms); + extern void generate_digest_step(cms_context *cms, void *data, size_t len); + extern int generate_digest_finish(cms_context *cms); + +-typedef struct { +- enum { +- PW_NONE = 0, +- PW_FROMFILE = 1, +- PW_PLAINTEXT = 2, +- PW_EXTERNAL = 3 +- } source; +- char *data; +-} secuPWData; +- + #endif /* CMS_COMMON_H */ + // vim:fenc=utf-8:tw=75:noet +-- +2.29.2 + diff --git a/0025-certdb-fix-PRTime-printfs-for-i686.patch b/0025-certdb-fix-PRTime-printfs-for-i686.patch deleted file mode 100644 index 0fc2ad8..0000000 --- a/0025-certdb-fix-PRTime-printfs-for-i686.patch +++ /dev/null @@ -1,31 +0,0 @@ -From bc1043bf2b428971e29a61a341da9a57595bada5 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Wed, 9 Aug 2017 17:40:33 -0400 -Subject: [PATCH 25/29] certdb: fix PRTime printfs for i686 - -Signed-off-by: Peter Jones ---- - src/certdb.c | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/src/certdb.c b/src/certdb.c -index fae80af..29c9502 100644 ---- a/src/certdb.c -+++ b/src/certdb.c -@@ -384,11 +384,10 @@ check_cert(pesigcheck_context *ctx, SECItem *sig, efi_guid_t *sigtype, - } - - if (lateNow < earlyNow) -- printf("Signature has impossible time constraint: %ld <= %ld\n", -- earlyNow / 1000000, lateNow / 1000000); -+ printf("Signature has impossible time constraint: %lld <= %lld\n", -+ earlyNow / 1000000LL, lateNow / 1000000LL); - atTime = earlyNow / 2 + lateNow / 2; - -- - cinfo = SEC_PKCS7DecodeItem(pkcs7sig, NULL, NULL, NULL, NULL, NULL, - NULL, NULL); - if (!cinfo) --- -2.13.4 - diff --git a/0026-Clean-up-gcc-command-lines-a-little.patch b/0026-Clean-up-gcc-command-lines-a-little.patch deleted file mode 100644 index 928d62d..0000000 --- a/0026-Clean-up-gcc-command-lines-a-little.patch +++ /dev/null @@ -1,41 +0,0 @@ -From a44115c9b4f43a1a7219f897bd33555e653d2e20 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 10 Aug 2017 10:02:38 -0400 -Subject: [PATCH 26/29] Clean up gcc command lines a little - -Signed-off-by: Peter Jones ---- - Make.defaults | 9 ++++----- - 1 file changed, 4 insertions(+), 5 deletions(-) - -diff --git a/Make.defaults b/Make.defaults -index 39b78f0..b6c0381 100644 ---- a/Make.defaults -+++ b/Make.defaults -@@ -20,8 +20,7 @@ CROSS_COMPILE ?= $(bindir) - PKG_CONFIG = $(CROSS_COMPILE)pkg-config - CC := $(if $(filter default,$(origin CC)),$(CROSS_COMPILE)gcc,$(CC)) - CCLD := $(if $(filter undefined,$(origin CCLD)),$(CC),$(CCLD)) --CFLAGS ?= -O0 -g3 -fvar-tracking -fvar-tracking-assignments \ -- -Wall -Werror -Wextra -Wno-error=cpp -+CFLAGS ?= -O0 -g3 -fvar-tracking -fvar-tracking-assignments -Wno-error=cpp - AS := $(CROSS_COMPILE)as - AR := $(CROSS_COMPILE)gcc-ar - RANLIB := $(CROSS_COMPILE)gcc-ranlib -@@ -36,10 +35,10 @@ ARCH := $(shell uname -m | sed s,i[3456789]86,ia32,) - - SOFLAGS = -shared - clang_cflags = --gcc_cflags = -Wmaybe-uninitialized -+gcc_cflags = -Wmaybe-uninitialized -grecord-gcc-switches - cflags = $(CFLAGS) $(ARCH3264) \ -- -Wall -Werror -Wno-cpp -Wsign-compare -Wno-unused-result \ -- -Wno-unused-function\ -+ -Wall -Werror -Wextra -Wsign-compare -Wno-unused-result \ -+ -Wno-unused-function -Wsign-compare \ - -std=gnu11 -fshort-wchar -fPIC -flto -fno-strict-aliasing \ - -fno-merge-constants -fkeep-inline-functions \ - -D_GNU_SOURCE -DCONFIG_$(ARCH) -I${TOPDIR}/include \ --- -2.13.4 - diff --git a/0026-Minor-whitespace-housekeeping.patch b/0026-Minor-whitespace-housekeeping.patch new file mode 100644 index 0000000..20536f5 --- /dev/null +++ b/0026-Minor-whitespace-housekeeping.patch @@ -0,0 +1,56 @@ +From e89e23ff5970e9a2194bcb393fa579c123e37bd1 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 28 Apr 2020 10:34:31 -0400 +Subject: [PATCH 26/42] Minor whitespace housekeeping + +Signed-off-by: Peter Jones +--- + src/cms_pe_common.c | 2 +- + src/pesigcheck.c | 2 ++ + src/cms_common.h | 3 +-- + 3 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/src/cms_pe_common.c b/src/cms_pe_common.c +index bd96fe91d69..b5ef2b73058 100644 +--- a/src/cms_pe_common.c ++++ b/src/cms_pe_common.c +@@ -331,4 +331,4 @@ error: + return -1; + } + +-/* vim:fenc=utf-8:sw=8:sts=8:noet */ ++// vim:fenc=utf-8:tw=75:noet +diff --git a/src/pesigcheck.c b/src/pesigcheck.c +index 87d4960a9a9..ada042e2f7e 100644 +--- a/src/pesigcheck.c ++++ b/src/pesigcheck.c +@@ -544,3 +544,5 @@ main(int argc, char *argv[]) + + return (rc < 0); + } ++ ++// vim:fenc=utf-8:tw=75:noet +diff --git a/src/cms_common.h b/src/cms_common.h +index 34ab6551ddd..a8c66cd3f9f 100644 +--- a/src/cms_common.h ++++ b/src/cms_common.h +@@ -41,7 +41,7 @@ + #define for_each_cert(cl, node) \ + for (CERTCertListNode *node = CERT_LIST_HEAD(cl); !CERT_LIST_END(node, cl); node = CERT_LIST_NEXT(node)) + +-#define cmserr(rv, cms, fmt, args...) ({ \ ++#define cmserr(rv, cms, fmt, args...) ({ \ + (cms)->log((cms), LOG_ERR, "%s:%s:%d: " fmt ": %s", \ + __FILE__, __func__, __LINE__, ## args, \ + PORT_ErrorToString(PORT_GetError())); \ +@@ -54,7 +54,6 @@ + return rv; \ + }) + +- + struct digest { + PK11Context *pk11ctx; + SECItem *pe_digest; +-- +2.29.2 + diff --git a/0027-Make-pesign-users-groups-static-in-the-repo.patch b/0027-Make-pesign-users-groups-static-in-the-repo.patch deleted file mode 100644 index 4131de3..0000000 --- a/0027-Make-pesign-users-groups-static-in-the-repo.patch +++ /dev/null @@ -1,54 +0,0 @@ -From a133d051c3f8acf3e058e92711eb528c3c0f41f9 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Thu, 10 Aug 2017 10:03:37 -0400 -Subject: [PATCH 27/29] Make pesign-{users,groups} static in the repo. - -Signed-off-by: Peter Jones ---- - src/Makefile | 5 +---- - src/pesign-groups | 1 + - src/pesign-users | 1 + - 3 files changed, 3 insertions(+), 4 deletions(-) - create mode 100644 src/pesign-groups - create mode 100644 src/pesign-users - -diff --git a/src/Makefile b/src/Makefile -index 84ad130..7d68fa1 100644 ---- a/src/Makefile -+++ b/src/Makefile -@@ -7,7 +7,7 @@ include $(TOPDIR)/Make.defaults - - BINTARGETS=authvar client efikeygen efisiglist pesigcheck pesign - SVCTARGETS=pesign.sysvinit pesign.service --TARGETS=$(BINTARGETS) $(SVCTARGETS) pesign-users pesign-groups -+TARGETS=$(BINTARGETS) $(SVCTARGETS) - - all : deps $(TARGETS) - -@@ -65,9 +65,6 @@ install_sysvinit: pesign.sysvinit - $(INSTALL) -d -m 755 $(INSTALLROOT)/etc/rc.d/init.d/ - $(INSTALL) -m 755 pesign.sysvinit $(INSTALLROOT)/etc/rc.d/init.d/pesign - --pesign-users pesign-groups : -- echo pesign > $@ -- - install : - $(INSTALL) -d -m 700 $(INSTALLROOT)/etc/pki/pesign/ - $(INSTALL) -d -m 700 $(INSTALLROOT)/etc/pki/pesign-rh-test/ -diff --git a/src/pesign-groups b/src/pesign-groups -new file mode 100644 -index 0000000..7f57cc5 ---- /dev/null -+++ b/src/pesign-groups -@@ -0,0 +1 @@ -+pesign -diff --git a/src/pesign-users b/src/pesign-users -new file mode 100644 -index 0000000..7f57cc5 ---- /dev/null -+++ b/src/pesign-users -@@ -0,0 +1 @@ -+pesign --- -2.13.4 - diff --git a/0027-libdpe-make-the-initial-read-buffer-always-big-enoug.patch b/0027-libdpe-make-the-initial-read-buffer-always-big-enoug.patch new file mode 100644 index 0000000..1e89c05 --- /dev/null +++ b/0027-libdpe-make-the-initial-read-buffer-always-big-enoug.patch @@ -0,0 +1,34 @@ +From 5c6ef128d03bad6fc3e4335935c8f5b20a4b4d51 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Fri, 5 Jun 2020 14:00:10 -0400 +Subject: [PATCH 27/42] libdpe: make the initial read buffer always big enough + for the opt header + +Signed-off-by: Peter Jones +--- + libdpe/pe_begin.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/libdpe/pe_begin.c b/libdpe/pe_begin.c +index 3bcc2c70c61..c6a22ab8c43 100644 +--- a/libdpe/pe_begin.c ++++ b/libdpe/pe_begin.c +@@ -174,8 +174,14 @@ read_unmmapped_file(int fildes, size_t maxsize, Pe_Cmd cmd, Pe *parent) + struct { + struct mz_hdr mz; + struct pe_hdr pe; ++ union { ++ struct pe32_opt_hdr opt_hdr_32; ++ struct pe32plus_opt_hdr opt_hdr_64; ++ }; + }; +- unsigned char raw[1]; ++ unsigned char raw[sizeof(struct mz_hdr) ++ + sizeof(struct pe_hdr) ++ + sizeof(struct pe32plus_opt_hdr)]; + } mem; + + ssize_t nread = pread_retry (fildes, &mem.mz, sizeof(mem.mz), 0); +-- +2.29.2 + diff --git a/0028-Fix-some-memory-leaks.patch b/0028-Fix-some-memory-leaks.patch new file mode 100644 index 0000000..0e88f37 --- /dev/null +++ b/0028-Fix-some-memory-leaks.patch @@ -0,0 +1,88 @@ +From df954024f6e89d4b5947f1016f2e4e95505b45b1 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 16 Jun 2020 10:34:19 -0400 +Subject: [PATCH 28/42] Fix some memory leaks + +Signed-off-by: Peter Jones +--- + src/cms_common.c | 10 ++++++++++ + src/pesign.c | 7 +++++++ + 2 files changed, 17 insertions(+) + +diff --git a/src/cms_common.c b/src/cms_common.c +index c2f34e515a2..7cd98bc994f 100644 +--- a/src/cms_common.c ++++ b/src/cms_common.c +@@ -345,7 +345,10 @@ is_valid_cert(CERTCertificate *cert, void *data) + + privkey = PK11_FindPrivateKeyFromCert(slot, cert, cbd->cms); + if (privkey != NULL) { ++ if (cbd->cert) ++ CERT_DestroyCertificate(cbd->cert); + cbd->cert = CERT_DupCertificate(cert); ++ CERT_DestroyCertificate(cert); + SECKEY_DestroyPrivateKey(privkey); + return SECSuccess; + } +@@ -363,8 +366,15 @@ is_valid_cert_without_private_key(CERTCertificate *cert, void *data) + return SECFailure; + privkey = PK11_FindPrivateKeyFromCert(slot, cert, cbd->cms); + if (privkey == NULL) { ++ if (cbd->cert) ++ CERT_DestroyCertificate(cbd->cert); ++ PORT_SetError(0); + cbd->cert = CERT_DupCertificate(cert); ++ CERT_DestroyCertificate(cert); + return SECSuccess; ++ } else { ++ SECKEY_DestroyPrivateKey(privkey); ++ CERT_DestroyCertificate(cert); + } + return SECFailure; + } +diff --git a/src/pesign.c b/src/pesign.c +index e68a141b935..0e7ce3d0a4e 100644 +--- a/src/pesign.c ++++ b/src/pesign.c +@@ -94,10 +94,12 @@ main(int argc, char *argv[]) + int check_vendor_cert = 1; + + char *digest_name = "sha256"; ++ char *orig_digest_name = digest_name; + char *tokenname = "NSS Certificate DB"; + char *origtoken = tokenname; + char *certname = NULL; + char *certdir = "/etc/pki/pesign"; ++ char *orig_certdir = certdir; + char *signum = NULL; + + secuPWData pwdata; +@@ -349,6 +351,7 @@ main(int argc, char *argv[]) + fprintf(stderr, "invalid signature number: %m\n"); + exit(1); + } ++ free(signum); + } + + int action = 0; +@@ -473,6 +476,8 @@ main(int argc, char *argv[]) + } + if (certname) + free(certname); ++ if (digest_name && digest_name != orig_digest_name) ++ free(digest_name); + + + if (ctxp->sign) { +@@ -507,6 +512,8 @@ main(int argc, char *argv[]) + break; + } + } ++ if (certdir && certdir != orig_certdir) ++ free(certdir); + pesign_context_free(ctxp); + + if (!daemon) { +-- +2.29.2 + diff --git a/0028-rpm-Make-the-client-signer-use-the-fedora-values-unl.patch b/0028-rpm-Make-the-client-signer-use-the-fedora-values-unl.patch deleted file mode 100644 index 3f0b2e1..0000000 --- a/0028-rpm-Make-the-client-signer-use-the-fedora-values-unl.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 025eb8aea94761fdc45507b6192aafdef80d4842 Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Wed, 9 Aug 2017 17:31:31 -0400 -Subject: [PATCH 28/29] rpm: Make the client signer use the fedora values - unless overridden - -Signed-off-by: Peter Jones ---- - src/macros.pesign | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - -diff --git a/src/macros.pesign b/src/macros.pesign -index 69280e9..22a3ee6 100644 ---- a/src/macros.pesign -+++ b/src/macros.pesign -@@ -9,6 +9,9 @@ - %__pesign_token %{nil}%{?pe_signing_token:-t "%{pe_signing_token}"} - %__pesign_cert %{!?pe_signing_cert:"Red Hat Test Certificate"}%{?pe_signing_cert:"%{pe_signing_cert}"} - -+%__pesign_client_token %{!?pe_signing_token:"Fedora Signer (OpenSC Card)"}%{?pe_signing_token:"%{pe_signing_token}"} -+%__pesign_client_cert %{!?pe_signing_cert:"/CN=Fedora Secure Boot Signer"}%{?pe_signing_cert:"%{pe_signing_cert}"} -+ - %_pesign /usr/bin/pesign - %_pesign_client /usr/bin/pesign-client - -@@ -41,11 +44,11 @@ - --certdir ${nss} -c signer %{-o} \ - rm -rf ${sattrs} ${sattrs}.sig ${nss} \ - elif [ -S /var/run/pesign/socket ]; then \ -- %{_pesign_client} -t %{__pesign_token} \\\ -- -c %{__pesign_cert} \\\ -+ %{_pesign_client} -t %{__pesign_client_token} \\\ -+ -c %{__pesign_client_cert} \\\ - %{-i} %{-o} %{-e} %{-s} %{-C} \ - else \ -- %{_pesign} -t %{__pesign_token} -c %{__pesign_cert} \\\ -+ %{_pesign} %{__pesign_token} -c %{__pesign_cert} \\\ - --certdir ${_pesign_nssdir} \\\ - %{-i} %{-o} %{-e} %{-s} %{-C} \ - fi \ --- -2.13.4 - diff --git a/0029-Improve-debug-output.patch b/0029-Improve-debug-output.patch new file mode 100644 index 0000000..eb2e9b2 --- /dev/null +++ b/0029-Improve-debug-output.patch @@ -0,0 +1,494 @@ +From 5347765052981b323622c9a5684577778fc7cbab Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 16 Jun 2020 10:43:32 -0400 +Subject: [PATCH 29/42] Improve debug output + +--- + src/cms_common.c | 78 ++++++++++++++++++++++++++++++++++++++------- + src/cms_pe_common.c | 20 ++++++------ + src/file_kmod.c | 5 +-- + src/file_pe.c | 7 ++++ + src/password.c | 36 +++++++++++++++------ + src/pesign.c | 10 ++++++ + src/cms_common.h | 3 +- + 7 files changed, 125 insertions(+), 34 deletions(-) + +diff --git a/src/cms_common.c b/src/cms_common.c +index 7cd98bc994f..e2ca5c097d4 100644 +--- a/src/cms_common.c ++++ b/src/cms_common.c +@@ -339,9 +339,19 @@ is_valid_cert(CERTCertificate *cert, void *data) + struct validity_cbdata *cbd = (struct validity_cbdata *)data; + PK11SlotInfo *slot = cbd->slot; + SECKEYPrivateKey *privkey = NULL; ++ int errnum; + +- if (cert == NULL) ++ errnum = PORT_GetError(); ++ if (errnum == SEC_ERROR_EXTENSION_NOT_FOUND) { ++ dprintf("Got SEC_ERROR_EXTENSION_NOT_FOUND; clearing"); ++ PORT_SetError(0); ++ errnum = 0; ++ } ++ if (cert == NULL) { ++ if (!errnum) ++ PORT_SetError(SEC_ERROR_UNKNOWN_CERT); + return SECFailure; ++ } + + privkey = PK11_FindPrivateKeyFromCert(slot, cert, cbd->cms); + if (privkey != NULL) { +@@ -350,6 +360,7 @@ is_valid_cert(CERTCertificate *cert, void *data) + cbd->cert = CERT_DupCertificate(cert); + CERT_DestroyCertificate(cert); + SECKEY_DestroyPrivateKey(privkey); ++ PORT_SetError(0); + return SECSuccess; + } + return SECFailure; +@@ -361,9 +372,20 @@ is_valid_cert_without_private_key(CERTCertificate *cert, void *data) + struct validity_cbdata *cbd = (struct validity_cbdata *)data; + PK11SlotInfo *slot = cbd->slot; + SECKEYPrivateKey *privkey = NULL; ++ int errnum; + +- if (cert == NULL) ++ errnum = PORT_GetError(); ++ if (errnum == SEC_ERROR_EXTENSION_NOT_FOUND) { ++ dprintf("Got SEC_ERROR_EXTENSION_NOT_FOUND; clearing"); ++ PORT_SetError(0); ++ errnum = 0; ++ } ++ if (cert == NULL) { ++ if (!errnum) ++ PORT_SetError(SEC_ERROR_UNKNOWN_CERT); + return SECFailure; ++ } ++ + privkey = PK11_FindPrivateKeyFromCert(slot, cert, cbd->cms); + if (privkey == NULL) { + if (cbd->cert) +@@ -402,6 +424,7 @@ PK11_DestroySlotListElement(PK11SlotList *slots, PK11SlotListElement **psle) + int + unlock_nss_token(cms_context *cms) + { ++ dprintf("setting password function to %s", cms->func ? "cms->func" : "SECU_GetModulePassword"); + PK11_SetPasswordFunc(cms->func ? cms->func : SECU_GetModulePassword); + + PK11SlotList *slots = NULL; +@@ -438,11 +461,12 @@ unlock_nss_token(cms_context *cms) + status = PK11_Authenticate(psle->slot, PR_TRUE, cms); + if (status != SECSuccess) { + save_port_err() { ++ int err = PORT_GetError(); + PK11_DestroySlotListElement(slots, &psle); + PK11_FreeSlotList(slots); + cms->log(cms, LOG_ERR, +- "authentication failed for token \"%s\"", +- cms->tokenname); ++ "authentication failed for token \"%s\": %s", ++ cms->tokenname, PORT_ErrorToString(err)); + } + return -1; + } +@@ -462,6 +486,7 @@ find_certificate(cms_context *cms, int needs_private_key) + return -1; + } + ++ dprintf("setting password function to %s", cms->func ? "cms->func" : "SECU_GetModulePassword"); + PK11_SetPasswordFunc(cms->func ? cms->func : SECU_GetModulePassword); + + PK11SlotList *slots = NULL; +@@ -479,8 +504,12 @@ find_certificate(cms_context *cms, int needs_private_key) + } + + while (psle) { +- if (!strcmp(cms->tokenname, PK11_GetTokenName(psle->slot))) ++ dprintf("looking for token \"%s\", got \"%s\"", ++ cms->tokenname, PK11_GetTokenName(psle->slot)); ++ if (!strcmp(cms->tokenname, PK11_GetTokenName(psle->slot))) { ++ dprintf("found token \"%s\"", cms->tokenname); + break; ++ } + + psle = PK11_GetNextSafe(slots, psle, PR_FALSE); + } +@@ -492,16 +521,18 @@ find_certificate(cms_context *cms, int needs_private_key) + nssreterr(-1, "Could not find token \"%s\"", cms->tokenname); + } + ++ int errnum; + SECStatus status; + if (PK11_NeedLogin(psle->slot) && !PK11_IsLoggedIn(psle->slot, cms)) { + status = PK11_Authenticate(psle->slot, PR_TRUE, cms); + if (status != SECSuccess) { + save_port_err() { ++ errnum = PORT_GetError(); + PK11_DestroySlotListElement(slots, &psle); + PK11_FreeSlotList(slots); + cms->log(cms, LOG_ERR, +- "authentication failed for token \"%s\"", +- cms->tokenname); ++ "authentication failed for token \"%s\": %s", ++ cms->tokenname, PORT_ErrorToString(errnum)); + } + return -1; + } +@@ -530,29 +561,48 @@ find_certificate(cms_context *cms, int needs_private_key) + cbd.slot = psle->slot; + cbd.cert = NULL; + ++ PORT_SetError(SEC_ERROR_UNKNOWN_CERT); + if (needs_private_key) { + status = PK11_TraverseCertsForNicknameInSlot(&nickname, + psle->slot, is_valid_cert, &cbd); ++ errnum = PORT_GetError(); ++ if (errnum) ++ dprintf("PK11_TraverseCertsForNicknameInSlot():%s:%s", ++ PORT_ErrorToName(errnum), PORT_ErrorToString(errnum)); + } else { + status = PK11_TraverseCertsForNicknameInSlot(&nickname, + psle->slot, + is_valid_cert_without_private_key, + &cbd); ++ errnum = PORT_GetError(); ++ if (errnum) ++ dprintf("PK11_TraverseCertsForNicknameInSlot():%s:%s", ++ PORT_ErrorToName(errnum), PORT_ErrorToString(errnum)); + } ++ dprintf("status:%d cbd.cert:%p", status, cbd.cert); + if (status == SECSuccess && cbd.cert != NULL) { + if (cms->cert) + CERT_DestroyCertificate(cms->cert); + cms->cert = CERT_DupCertificate(cbd.cert); ++ } else { ++ errnum = PORT_GetError(); ++ dprintf("token traversal %s; cert %sfound:%s:%s", ++ status == SECSuccess ? "succeeded" : "failed", ++ cbd.cert == NULL ? "not" : "", ++ PORT_ErrorToName(errnum), PORT_ErrorToString(errnum)); + } + + save_port_err() { ++ dprintf("Destroying cert list"); + CERT_DestroyCertList(certlist); ++ dprintf("Destroying slot list element"); + PK11_DestroySlotListElement(slots, &psle); ++ dprintf("Destroying slot list"); + PK11_FreeSlotList(slots); + cms->psle = NULL; + } + if (status != SECSuccess || cms->cert == NULL) +- cmsreterr(-1, cms, "could not find certificate in list"); ++ cmsreterr(-1, cms, "could not find certificate"); + + return 0; + } +@@ -565,6 +615,7 @@ find_slot_for_token(cms_context *cms, PK11SlotInfo **slot) + return -1; + } + ++ dprintf("setting password function to %s", cms->func ? "cms->func" : "SECU_GetModulePassword"); + PK11_SetPasswordFunc(cms->func ? cms->func : SECU_GetModulePassword); + + PK11SlotList *slots = NULL; +@@ -600,11 +651,12 @@ find_slot_for_token(cms_context *cms, PK11SlotInfo **slot) + status = PK11_Authenticate(psle->slot, PR_TRUE, cms); + if (status != SECSuccess) { + save_port_err() { ++ int err = PORT_GetError(); + PK11_DestroySlotListElement(slots, &psle); + PK11_FreeSlotList(slots); + cms->log(cms, LOG_ERR, +- "authentication failed for token \"%s\"", +- cms->tokenname); ++ "authentication failed for token \"%s\": %s", ++ cms->tokenname, PORT_ErrorToString(err)); + } + return -1; + } +@@ -621,6 +673,7 @@ find_named_certificate(cms_context *cms, char *name, CERTCertificate **cert) + return -1; + } + ++ dprintf("setting password function to %s", cms->func ? "cms->func" : "SECU_GetModulePassword"); + PK11_SetPasswordFunc(cms->func ? cms->func : SECU_GetModulePassword); + + PK11SlotList *slots = NULL; +@@ -658,11 +711,12 @@ find_named_certificate(cms_context *cms, char *name, CERTCertificate **cert) + status = PK11_Authenticate(psle->slot, PR_TRUE, cms); + if (status != SECSuccess) { + save_port_err() { ++ int err = PORT_GetError(); + PK11_DestroySlotListElement(slots, &psle); + PK11_FreeSlotList(slots); + cms->log(cms, LOG_ERR, +- "authentication failed for token \"%s\"", +- cms->tokenname); ++ "authentication failed for token \"%s\": %s", ++ cms->tokenname, PORT_ErrorToString(err)); + } + return -1; + } +diff --git a/src/cms_pe_common.c b/src/cms_pe_common.c +index b5ef2b73058..e5a33eb6fe1 100644 +--- a/src/cms_pe_common.c ++++ b/src/cms_pe_common.c +@@ -198,8 +198,8 @@ generate_digest(cms_context *cms, Pe *pe, int padded) + __FILE__, __func__, __LINE__); + goto error; + } +- dprintf("beginning of hash\n"); +- dprintf("digesting %lx + %lx\n", hash_base - map, hash_size); ++ dprintf("beginning of hash"); ++ dprintf("digesting %lx + %lx", hash_base - map, hash_size); + generate_digest_step(cms, hash_base, hash_size); + + /* 5. Skip over the image checksum +@@ -224,7 +224,7 @@ generate_digest(cms_context *cms, Pe *pe, int padded) + goto error; + } + generate_digest_step(cms, hash_base, hash_size); +- dprintf("digesting %lx + %lx\n", hash_base - map, hash_size); ++ dprintf("digesting %lx + %lx", hash_base - map, hash_size); + + /* 8. Skip over the crt dir + * 9. Hash everything up to the end of the image header. */ +@@ -239,7 +239,7 @@ generate_digest(cms_context *cms, Pe *pe, int padded) + goto error; + } + generate_digest_step(cms, hash_base, hash_size); +- dprintf("digesting %lx + %lx\n", hash_base - map, hash_size); ++ dprintf("digesting %lx + %lx", hash_base - map, hash_size); + + /* 10. Set SUM_OF_BYTES_HASHED to the size of the header. */ + hashed_bytes = pe32opthdr ? pe32opthdr->header_size +@@ -275,16 +275,16 @@ generate_digest(cms_context *cms, Pe *pe, int padded) + char *name = shdrs[i].name; + if (name && name[0] == '/') + name = get_str(pe, name + 1); +- dprintf("section:\"%s\"\n", name ? name : "(null)"); ++ dprintf("section:\"%s\"", name ? name : "(null)"); + if (name && !strcmp(name, ".vendor_cert")) { +- dprintf("skipping .vendor_cert section\n"); ++ dprintf("skipping .vendor_cert section"); + hashed_bytes += hash_size; + continue; + } + } + + generate_digest_step(cms, hash_base, hash_size); +- dprintf("digesting %lx + %lx\n", hash_base - map, hash_size); ++ dprintf("digesting %lx + %lx", hash_base - map, hash_size); + + hashed_bytes += hash_size; + } +@@ -305,13 +305,13 @@ generate_digest(cms_context *cms, Pe *pe, int padded) + memset(tmp_array, '\0', tmp_size); + memcpy(tmp_array, hash_base, hash_size); + generate_digest_step(cms, tmp_array, tmp_size); +- dprintf("digesting %lx + %lx\n", (unsigned long)tmp_array, tmp_size); ++ dprintf("digesting %lx + %lx", (unsigned long)tmp_array, tmp_size); + } else { + generate_digest_step(cms, hash_base, hash_size); +- dprintf("digesting %lx + %lx\n", hash_base - map, hash_size); ++ dprintf("digesting %lx + %lx", hash_base - map, hash_size); + } + } +- dprintf("end of hash\n"); ++ dprintf("end of hash"); + + rc = generate_digest_finish(cms); + if (rc < 0) +diff --git a/src/file_kmod.c b/src/file_kmod.c +index 077f0579e77..994e5639e71 100644 +--- a/src/file_kmod.c ++++ b/src/file_kmod.c +@@ -84,8 +84,9 @@ kmod_write_signature(cms_context *cms, int outfd) + digest_get_digest_oid(cms), + digest, NULL, NULL); + if (!cinfo) { +- cms->log(cms, LOG_ERR, "failed to create signed data: %s", +- PORT_ErrorToString(PORT_GetError())); ++ cms->log(cms, LOG_ERR, "failed to create signed data: %s (%s)", ++ PORT_ErrorToString(PORT_GetError()), ++ PORT_ErrorToName(PORT_GetError())); + return -1; + } + +diff --git a/src/file_pe.c b/src/file_pe.c +index 31672c68f79..5b6ac21763a 100644 +--- a/src/file_pe.c ++++ b/src/file_pe.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + + #include "pesign.h" + #include "pesign_standalone.h" +@@ -144,6 +145,7 @@ void + pe_handle_action(pesign_context *ctxp, int action, int padding) + { + ssize_t sigspace = 0; ++ int err; + int rc; + + switch (action) { +@@ -265,6 +267,9 @@ pe_handle_action(pesign_context *ctxp, int action, int padding) + break; + /* generate a signature and save it in a separate file */ + case EXPORT_SIGNATURE|GENERATE_SIGNATURE: ++ err = PORT_GetError(); ++ dprintf("PORT_GetError():%s:%s", PORT_ErrorToName(err), PORT_ErrorToString(err)); ++ PORT_SetError(0); + rc = find_certificate(ctxp->cms_ctx, 1); + conderrx(rc < 0, 1, "Could not find certificate %s", + ctxp->cms_ctx->certname); +@@ -277,6 +282,8 @@ pe_handle_action(pesign_context *ctxp, int action, int padding) + /* generate a signature and embed it in the binary */ + case IMPORT_SIGNATURE|GENERATE_SIGNATURE: + check_inputs(ctxp); ++ err = PORT_GetError(); ++ dprintf("PORT_GetError():%s:%s", PORT_ErrorToName(err), PORT_ErrorToString(err)); + rc = find_certificate(ctxp->cms_ctx, 1); + conderrx(rc < 0, 1, "Could not find certificate %s", + ctxp->cms_ctx->certname); +diff --git a/src/password.c b/src/password.c +index 0a4ef411ff7..13bd9b12320 100644 +--- a/src/password.c ++++ b/src/password.c +@@ -58,15 +58,19 @@ print_prompt(FILE *in, FILE *out, char *prompt) + int infd = fileno(in); + struct termios tio; + ++ ingress(); + if (!isatty(infd)) + return; + +- fprintf(out, "%s", prompt); +- fflush(out); ++ if (out) { ++ fprintf(out, "%s", prompt); ++ fflush(out); ++ } + + tcgetattr(infd, &tio); + tio.c_lflag &= ~ECHO; + tcsetattr(infd, TCSAFLUSH, &tio); ++ egress(); + } + + static inline char * +@@ -87,11 +91,14 @@ read_password(FILE *in, FILE *out, char *buf, size_t bufsz) + struct termios tio; + char *ret; + ++ ingress(); + ret = fgets(buf, bufsz, in); + + if (isatty(infd)) { +- fprintf(out, "\n"); +- fflush(out); ++ if (out) { ++ fprintf(out, "\n"); ++ fflush(out); ++ } + + tcgetattr(infd, &tio); + tio.c_lflag |= ECHO; +@@ -101,6 +108,7 @@ read_password(FILE *in, FILE *out, char *buf, size_t bufsz) + return -1; + + buf[strlen(buf)-1] = '\0'; ++ egress(); + return 0; + } + +@@ -109,15 +117,23 @@ check_password(char *cp) + { + unsigned int i; + +- if (cp == NULL) ++ ingress(); ++ if (cp == NULL) { ++ egress(); + return PR_FALSE; ++ } + + for (i = 0; cp[i] != 0; i++) { +- if (!isprint(cp[i])) ++ if (!isprint(cp[i])) { ++ egress(); + return PR_FALSE; ++ } + } +- if (i == 0) ++ if (i == 0) { ++ egress(); + return PR_FALSE; ++ } ++ egress(); + return PR_TRUE; + } + +@@ -134,7 +150,8 @@ get_password(FILE *input, FILE *output, char *prompt, PRBool (*ok)(char *)) + while(true) { + int rc; + +- print_prompt(input, output, prompt); ++ if (prompt) ++ print_prompt(input, output, prompt); + rc = read_password(input, output, phrase, size); + if (rc < 0) + return NULL; +@@ -160,7 +177,8 @@ SECU_GetPasswordString(void *arg UNUSED, char *prompt) + { + char *ret; + ingress(); +- ret = get_password(stdin, stdout, prompt, check_password); ++ ret = get_password(stdin, stdout, prompt, NULL); ++ dprintf("password:\"%s\"", ret ? ret : "(null)"); + egress(); + return ret; + } +diff --git a/src/pesign.c b/src/pesign.c +index 0e7ce3d0a4e..b5c9823e1d4 100644 +--- a/src/pesign.c ++++ b/src/pesign.c +@@ -434,6 +434,16 @@ main(int argc, char *argv[]) + "NSS says \"%s\" errno says \"%m\"\n", + PORT_ErrorToString(PORT_GetError())); + } ++ /* ++ * At this point there is *often* an error set, but we ++ * should not get here if it was really an error; one ++ * example is PR_LOAD_LIBRARY_ERROR is often set by PKCS11 ++ * modules that aren't present or whose physical token ++ * devices aren't available. ++ * ++ * Clear it. ++ */ ++ PORT_SetError(0); + + status = register_oids(ctxp->cms_ctx); + if (status != SECSuccess) { +diff --git a/src/cms_common.h b/src/cms_common.h +index a8c66cd3f9f..ee06f812a77 100644 +--- a/src/cms_common.h ++++ b/src/cms_common.h +@@ -48,8 +48,9 @@ + exit(rv); \ + }) + #define cmsreterr(rv, cms, fmt, args...) ({ \ +- (cms)->log((cms), LOG_ERR, "%s:%s:%d: " fmt ": %s", \ ++ (cms)->log((cms), LOG_ERR, "%s:%s:%d: " fmt ":%s:%s", \ + __FILE__, __func__, __LINE__, ## args, \ ++ PORT_ErrorToName(PORT_GetError()), \ + PORT_ErrorToString(PORT_GetError())); \ + return rv; \ + }) +-- +2.29.2 + diff --git a/0029-Make-macros.pesign-error-in-kojibuilder-if-we-don-t-.patch b/0029-Make-macros.pesign-error-in-kojibuilder-if-we-don-t-.patch deleted file mode 100644 index 753afe8..0000000 --- a/0029-Make-macros.pesign-error-in-kojibuilder-if-we-don-t-.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 86a6b02e4b95ab3629446e71895cc5e57ad4482f Mon Sep 17 00:00:00 2001 -From: Peter Jones -Date: Mon, 14 Aug 2017 11:37:43 -0400 -Subject: [PATCH 29/29] Make macros.pesign error in kojibuilder if we don't - have perms on the socket - ---- - src/macros.pesign | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/src/macros.pesign b/src/macros.pesign -index 22a3ee6..1665b4c 100644 ---- a/src/macros.pesign -+++ b/src/macros.pesign -@@ -43,6 +43,21 @@ - %{_pesign} -R ${sattrs}.sig -I ${sattrs} %{-i} \\\ - --certdir ${nss} -c signer %{-o} \ - rm -rf ${sattrs} ${sattrs}.sig ${nss} \ -+ elif [ "%{vendor}" == "Fedora Project" -a \\\ -+ "$(id -un)" == "mockbuild" -a \\\ -+ "$(uname -m)" == "x86_64" ] && \\\ -+ grep -q ID=fedora /etc/os-release && \\\ -+ [[ "%{_buildhost}" =~ ^bkernel.* ]] && \\\ -+ ! [ -S /var/run/pesign/socket ]; then \ -+ echo "No socket even though this is %{_buildhost}" \ -+ ls -ld /var/run/pesign || : \ -+ getfacl /var/run/pesign || : \ -+ ls -l /var/run/pesign/socket || : \ -+ getfacl /var/run/pesign/socket || : \ -+ echo =========== env ============== \ -+ set \ -+ echo =========== env ============== \ -+ exit 1 \ - elif [ -S /var/run/pesign/socket ]; then \ - %{_pesign_client} -t %{__pesign_client_token} \\\ - -c %{__pesign_client_cert} \\\ --- -2.13.4 - diff --git a/0030-support-uri-token-names.patch b/0030-support-uri-token-names.patch new file mode 100644 index 0000000..81b1be1 --- /dev/null +++ b/0030-support-uri-token-names.patch @@ -0,0 +1,256 @@ +From 1465c77dc36a9d5464f42e2477758e250b797fac Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Sat, 20 Jun 2020 17:13:17 -0400 +Subject: [PATCH 30/42] support uri token names + +Signed-off-by: Peter Jones +--- + src/cms_common.c | 103 ++++++++++++++++++++++++++++++++++++++++------- + 1 file changed, 89 insertions(+), 14 deletions(-) + +diff --git a/src/cms_common.c b/src/cms_common.c +index e2ca5c097d4..e9c2d08f94c 100644 +--- a/src/cms_common.c ++++ b/src/cms_common.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -42,6 +43,8 @@ + #include + #include + ++#include "hex.h" ++ + struct digest_param { + char *name; + SECOidTag digest_tag; +@@ -421,9 +424,74 @@ PK11_DestroySlotListElement(PK11SlotList *slots, PK11SlotListElement **psle) + *psle = PK11_GetNextSafe(slots, *psle, PR_FALSE); + } + ++static inline void ++unescape_html_in_place(char *s) ++{ ++ size_t sz = strlen(s) + 1; ++ size_t pos = 0; ++ char *s1; ++ ++ dprintf("unescaping pos:%zd sz:%zd \"%s\"", pos, sz, s); ++ do { ++ s1 = strchrnul(&s[pos], '%'); ++ if (s1[0] == '\0') ++ break; ++ dprintf("s1 is \"%s\"", s1); ++ if ((size_t)(s1 - s) < (size_t)(sz - 3)) { ++ int c; ++ ++ c = (hexchar_to_bin(s1[1]) << 4) ++ | (hexchar_to_bin(s1[2]) & 0xf); ++ dprintf("replacing %%%c%c with 0x%02hhx", s1[1], s1[2], (char)c); ++ s1[0] = c; ++ memmove(&s1[1], &s1[3], sz - (&s1[3] - s)); ++ sz -= 2; ++ pos = &s1[1] - s; ++ dprintf("new pos:%zd sz:%zd s:\"%s\"", pos, sz, s); ++ } ++ } while (pos < sz); ++} ++ ++static inline void ++resolve_pkcs11_token_in_place(char *tokenname) ++{ ++ char *ntn = tokenname; ++ size_t pos = 0; ++ ++ while (*ntn) { ++ char *cp = strchrnul(ntn, ';'); ++ char c = *cp; ++ *cp = '\0'; ++ ++ dprintf("ntn:\"%s\"", ntn); ++ if (!strncmp(&ntn[pos], "token=", 6)) { ++ ntn += 6; ++ memmove(tokenname, ntn, cp - ntn + 1); ++ break; ++ } ++ ++ *cp = c; ++ ntn = cp + (c ? 1 : 0); ++ } ++ unescape_html_in_place(tokenname); ++ dprintf("token name is \"%s\"", tokenname); ++} ++ ++#define resolve_token_name(tn) ({ \ ++ char *s_ = tn; \ ++ if (!strncmp(tn, "pkcs11:", 7)) { \ ++ dprintf("provided token name is pkcs11 uri; parsing"); \ ++ s_ = strdupa(tn+7); \ ++ resolve_pkcs11_token_in_place(s_); \ ++ } \ ++ s_; \ ++}) ++ + int + unlock_nss_token(cms_context *cms) + { ++ char *tokenname = resolve_token_name(cms->tokenname); ++ + dprintf("setting password function to %s", cms->func ? "cms->func" : "SECU_GetModulePassword"); + PK11_SetPasswordFunc(cms->func ? cms->func : SECU_GetModulePassword); + +@@ -432,6 +500,7 @@ unlock_nss_token(cms_context *cms) + if (!slots) + cmsreterr(-1, cms, "could not get pk11 token list"); + ++ + PK11SlotListElement *psle = NULL; + psle = PK11_GetFirstSafe(slots); + if (!psle) { +@@ -442,7 +511,7 @@ unlock_nss_token(cms_context *cms) + } + + while (psle) { +- if (!strcmp(cms->tokenname, PK11_GetTokenName(psle->slot))) ++ if (!strcmp(tokenname, PK11_GetTokenName(psle->slot))) + break; + + psle = PK11_GetNextSafe(slots, psle, PR_FALSE); +@@ -452,7 +521,7 @@ unlock_nss_token(cms_context *cms) + save_port_err() { + PK11_FreeSlotList(slots); + } +- nssreterr(-1, "Could not find token \"%s\"", cms->tokenname); ++ nssreterr(-1, "Could not find token \"%s\"", tokenname); + } + + SECStatus status; +@@ -466,7 +535,7 @@ unlock_nss_token(cms_context *cms) + PK11_FreeSlotList(slots); + cms->log(cms, LOG_ERR, + "authentication failed for token \"%s\": %s", +- cms->tokenname, PORT_ErrorToString(err)); ++ tokenname, PORT_ErrorToString(err)); + } + return -1; + } +@@ -480,6 +549,8 @@ unlock_nss_token(cms_context *cms) + int + find_certificate(cms_context *cms, int needs_private_key) + { ++ char *tokenname = resolve_token_name(cms->tokenname); ++ + struct validity_cbdata cbd; + if (!cms->certname || !*cms->certname) { + cms->log(cms, LOG_ERR, "no certificate name specified"); +@@ -505,9 +576,9 @@ find_certificate(cms_context *cms, int needs_private_key) + + while (psle) { + dprintf("looking for token \"%s\", got \"%s\"", +- cms->tokenname, PK11_GetTokenName(psle->slot)); +- if (!strcmp(cms->tokenname, PK11_GetTokenName(psle->slot))) { +- dprintf("found token \"%s\"", cms->tokenname); ++ tokenname, PK11_GetTokenName(psle->slot)); ++ if (!strcmp(tokenname, PK11_GetTokenName(psle->slot))) { ++ dprintf("found token \"%s\"", tokenname); + break; + } + +@@ -518,7 +589,7 @@ find_certificate(cms_context *cms, int needs_private_key) + save_port_err() { + PK11_FreeSlotList(slots); + } +- nssreterr(-1, "Could not find token \"%s\"", cms->tokenname); ++ nssreterr(-1, "Could not find token \"%s\"", tokenname); + } + + int errnum; +@@ -532,7 +603,7 @@ find_certificate(cms_context *cms, int needs_private_key) + PK11_FreeSlotList(slots); + cms->log(cms, LOG_ERR, + "authentication failed for token \"%s\": %s", +- cms->tokenname, PORT_ErrorToString(errnum)); ++ tokenname, PORT_ErrorToString(errnum)); + } + return -1; + } +@@ -615,6 +686,8 @@ find_slot_for_token(cms_context *cms, PK11SlotInfo **slot) + return -1; + } + ++ char *tokenname = resolve_token_name(cms->tokenname); ++ + dprintf("setting password function to %s", cms->func ? "cms->func" : "SECU_GetModulePassword"); + PK11_SetPasswordFunc(cms->func ? cms->func : SECU_GetModulePassword); + +@@ -633,7 +706,7 @@ find_slot_for_token(cms_context *cms, PK11SlotInfo **slot) + } + + while (psle) { +- if (!strcmp(cms->tokenname, PK11_GetTokenName(psle->slot))) ++ if (!strcmp(tokenname, PK11_GetTokenName(psle->slot))) + break; + + psle = PK11_GetNextSafe(slots, psle, PR_FALSE); +@@ -643,7 +716,7 @@ find_slot_for_token(cms_context *cms, PK11SlotInfo **slot) + save_port_err() { + PK11_FreeSlotList(slots); + } +- nssreterr(-1, "Could not find token \"%s\"", cms->tokenname); ++ nssreterr(-1, "Could not find token \"%s\"", tokenname); + } + + SECStatus status; +@@ -656,7 +729,7 @@ find_slot_for_token(cms_context *cms, PK11SlotInfo **slot) + PK11_FreeSlotList(slots); + cms->log(cms, LOG_ERR, + "authentication failed for token \"%s\": %s", +- cms->tokenname, PORT_ErrorToString(err)); ++ tokenname, PORT_ErrorToString(err)); + } + return -1; + } +@@ -668,6 +741,8 @@ find_slot_for_token(cms_context *cms, PK11SlotInfo **slot) + int + find_named_certificate(cms_context *cms, char *name, CERTCertificate **cert) + { ++ char *tokenname = resolve_token_name(cms->tokenname); ++ + if (!name) { + cms->log(cms, LOG_ERR, "no certificate name specified"); + return -1; +@@ -691,7 +766,7 @@ find_named_certificate(cms_context *cms, char *name, CERTCertificate **cert) + } + + while (psle) { +- if (!strcmp(cms->tokenname, PK11_GetTokenName(psle->slot))) ++ if (!strcmp(tokenname, PK11_GetTokenName(psle->slot))) + break; + + psle = PK11_GetNextSafe(slots, psle, PR_FALSE); +@@ -701,7 +776,7 @@ find_named_certificate(cms_context *cms, char *name, CERTCertificate **cert) + save_port_err() { + PK11_FreeSlotList(slots); + cms->log(cms, LOG_ERR, "could not find token \"%s\"", +- cms->tokenname); ++ tokenname); + } + return -1; + } +@@ -716,7 +791,7 @@ find_named_certificate(cms_context *cms, char *name, CERTCertificate **cert) + PK11_FreeSlotList(slots); + cms->log(cms, LOG_ERR, + "authentication failed for token \"%s\": %s", +- cms->tokenname, PORT_ErrorToString(err)); ++ tokenname, PORT_ErrorToString(err)); + } + return -1; + } +-- +2.29.2 + diff --git a/0031-cms_common-add-some-more-ways-to-find-a-cert.patch b/0031-cms_common-add-some-more-ways-to-find-a-cert.patch new file mode 100644 index 0000000..20a9852 --- /dev/null +++ b/0031-cms_common-add-some-more-ways-to-find-a-cert.patch @@ -0,0 +1,178 @@ +From 1b3f668daa34372308d94cf322b1f809e83fe4aa Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 22 Jun 2020 13:54:10 -0400 +Subject: [PATCH 31/42] cms_common: add some more ways to find a cert + +Signed-off-by: Peter Jones +--- + src/cms_common.c | 109 +++++++++++++++++++++++++++++++++++++++-------- + src/cms_common.h | 9 ++++ + 2 files changed, 101 insertions(+), 17 deletions(-) + +diff --git a/src/cms_common.c b/src/cms_common.c +index e9c2d08f94c..e274a8a50da 100644 +--- a/src/cms_common.c ++++ b/src/cms_common.c +@@ -739,12 +739,18 @@ find_slot_for_token(cms_context *cms, PK11SlotInfo **slot) + } + + int +-find_named_certificate(cms_context *cms, char *name, CERTCertificate **cert) ++find_certificate_by_callback(cms_context *cms, ++ find_cert_match_t *match, void *cbdata, ++ CERTCertificate **cert) + { + char *tokenname = resolve_token_name(cms->tokenname); + +- if (!name) { +- cms->log(cms, LOG_ERR, "no certificate name specified"); ++ if (!match) { ++ cms->log(cms, LOG_ERR, "no certificate match callback not specified"); ++ return -1; ++ } ++ if (!cbdata) { ++ cms->log(cms, LOG_ERR, "no certificate callback data not specified"); + return -1; + } + +@@ -809,25 +815,29 @@ find_named_certificate(cms_context *cms, char *name, CERTCertificate **cert) + + CERTCertListNode *node = NULL; + for_each_cert(certlist, tmpnode) { +- if (!strcmp(tmpnode->cert->subjectName, name)) { ++ /* If we're looking up the issuer of some cert, and the ++ * issuer isn't in the database, we'll get back what is ++ * essentially a template that's in NSS's cache waiting to ++ * be filled out. We can't use that, it'll just cause ++ * CERT_DupCertificate() to segfault. */ ++ if (!tmpnode || !tmpnode->cert ++ || !tmpnode->cert->derCert.data ++ || !tmpnode->cert->derCert.len ++ || !tmpnode->cert->derIssuer.data ++ || !tmpnode->cert->derIssuer.len ++ || !tmpnode->cert->serialNumber.data ++ || !tmpnode->cert->serialNumber.len) ++ continue; ++ ++ int rc = match(tmpnode->cert, cbdata); ++ if (rc == 0) { + node = tmpnode; + break; + } + } +- /* If we're looking up the issuer of some cert, and the issuer isn't +- * in the database, we'll get back what is essentially a template +- * that's in NSS's cache waiting to be filled out. We can't use that, +- * it'll just cause CERT_DupCertificate() to segfault. */ +- if (!node || !node->cert || !node->cert->derCert.data +- || !node->cert->derCert.len +- || !node->cert->derIssuer.data +- || !node->cert->derIssuer.len) { +- PK11_DestroySlotListElement(slots, &psle); +- PK11_FreeSlotList(slots); +- CERT_DestroyCertList(certlist); + +- return -1; +- } ++ if (!node) ++ cmsreterr(-1, cms, "Could not find certificate"); + + *cert = CERT_DupCertificate(node->cert); + +@@ -836,6 +846,71 @@ find_named_certificate(cms_context *cms, char *name, CERTCertificate **cert) + CERT_DestroyCertList(certlist); + + return 0; ++ ++} ++ ++static int ++match_subject(CERTCertificate *cert, void *cbdatap) ++{ ++ if (!cert->subjectName) ++ return 0; ++ ++ if (!strcmp(cert->subjectName, (char *)cbdatap)) ++ return 1; ++ ++ return 0; ++} ++ ++int ++find_named_certificate(cms_context *cms, char *name, CERTCertificate **cert) ++{ ++ if (!name) ++ cmsreterr(-1, cms, "no subject name specified"); ++ ++ return find_certificate_by_callback(cms, match_subject, name, cert); ++} ++ ++static int ++match_issuer_and_serial(CERTCertificate *cert, void *cbdatap) ++{ ++ CERTIssuerAndSN *ias = cbdatap; ++ bool found = false; ++ ++ if (ias->derIssuer.len == cert->derIssuer.len && ++ ias->derIssuer.len != 0) { ++ if (memcmp(ias->derIssuer.data, cert->derIssuer.data, ++ ias->derIssuer.len)) ++ return 0; ++ found = true; ++ } ++ ++ if (!found) { ++ SECComparison seccomp; ++ ++ seccomp = CERT_CompareName(&ias->issuer, &cert->issuer); ++ if (seccomp != SECEqual) ++ return 0; ++ } ++ ++ if (ias->serialNumber.len != cert->serialNumber.len) ++ return 0; ++ ++ if (memcmp(ias->serialNumber.data, cert->serialNumber.data, ++ ias->serialNumber.len)) ++ return 0; ++ ++ return 1; ++} ++ ++int ++find_certificate_by_issuer_and_sn(cms_context *cms, ++ CERTIssuerAndSN *ias, ++ CERTCertificate **cert) ++{ ++ if (!ias) ++ cmsreterr(-1, cms, "invalid issuer and serial number"); ++ ++ return find_certificate_by_callback(cms, match_issuer_and_serial, &ias, cert); + } + + int +diff --git a/src/cms_common.h b/src/cms_common.h +index ee06f812a77..04974035f0c 100644 +--- a/src/cms_common.h ++++ b/src/cms_common.h +@@ -190,8 +190,17 @@ extern int generate_keys(cms_context *cms, PK11SlotInfo *slot, + SECKEYPrivateKey **privkey, SECKEYPublicKey **pubkey); + extern int is_issuer_of(CERTCertificate *c0, CERTCertificate *c1); + ++typedef int (find_cert_match_t)(CERTCertificate *cert, void *cbdata); ++extern int find_certificate_by_callback(cms_context *cms, ++ find_cert_match_t *match, void *cbdata, ++ CERTCertificate **cert); ++ + extern int find_named_certificate(cms_context *cms, char *name, + CERTCertificate **cert); ++extern int find_certificate_by_issuer_and_sn(cms_context *cms, ++ CERTIssuerAndSN *ias, ++ CERTCertificate **cert); ++ + extern int find_slot_for_token(cms_context *cms, PK11SlotInfo **slot); + + extern SECOidTag digest_get_digest_oid(cms_context *cms); +-- +2.29.2 + diff --git a/0032-client-try-run-and-var-run-for-the-socket-path.patch b/0032-client-try-run-and-var-run-for-the-socket-path.patch new file mode 100644 index 0000000..8a3544b --- /dev/null +++ b/0032-client-try-run-and-var-run-for-the-socket-path.patch @@ -0,0 +1,86 @@ +From 2dd5d6653ff965e2afc14a2abfba308f26934a65 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 6 Jul 2020 16:13:09 -0400 +Subject: [PATCH 32/42] client: try /run and /var/run for the socket path. + +Signed-off-by: Peter Jones +--- + src/client.c | 40 +++++++++++++++++++++++++++++----------- + 1 file changed, 29 insertions(+), 11 deletions(-) + +diff --git a/src/client.c b/src/client.c +index a00b20f5dde..914f2c8bd55 100644 +--- a/src/client.c ++++ b/src/client.c +@@ -61,24 +61,24 @@ print_flag_name(FILE *f, int flag) + } + + static int +-connect_to_server(void) ++connect_to_server_helper(const char * const sockpath) + { +- int rc = access(SOCKPATH, R_OK); ++ int rc = access(sockpath, R_OK); + if (rc != 0) { +- fprintf(stderr, "pesign-client: could not connect to server: " +- "%m\n"); +- exit(1); ++ warn("could not access socket \"%s\"", sockpath); ++ return rc; + } + + struct sockaddr_un addr_un = { + .sun_family = AF_UNIX, +- .sun_path = SOCKPATH, + }; ++ strncpy(addr_un.sun_path, sockpath, sizeof(addr_un.sun_path)); ++ addr_un.sun_path[sizeof(addr_un.sun_path)-1] = '\0'; + + int sd = socket(AF_UNIX, SOCK_STREAM, 0); + if (sd < 0) { +- fprintf(stderr, "pesign-client: could not open socket: %m\n"); +- exit(1); ++ warn("could not open socket \"%s\"", sockpath); ++ return sd; + } + + socklen_t len = strlen(addr_un.sun_path) + +@@ -86,14 +86,32 @@ connect_to_server(void) + + rc = connect(sd, (struct sockaddr *)&addr_un, len); + if (rc < 0) { +- fprintf(stderr, "pesign-client: could not connect to daemon: " +- "%m\n"); +- exit(1); ++ warn("could not connect to daemon"); ++ return sd; + } + + return sd; + } + ++static int ++connect_to_server(void) ++{ ++ int rc, i; ++ const char * const sockets[] = { ++ "/run/pesign/socket", ++ "/var/run/pesign/socket", ++ NULL ++ }; ++ ++ for (i = 0; sockets[i] != NULL; i++) { ++ rc = connect_to_server_helper(sockets[i]); ++ if (rc >= 0) ++ return rc; ++ } ++ ++ exit(1); ++} ++ + static int32_t + check_response(int sd, char **srvmsg); + +-- +2.29.2 + diff --git a/0033-client-remove-an-extra-debug-print.patch b/0033-client-remove-an-extra-debug-print.patch new file mode 100644 index 0000000..0e2051f --- /dev/null +++ b/0033-client-remove-an-extra-debug-print.patch @@ -0,0 +1,25 @@ +From 8ce83e63dd221beb775378981090deacd17e2166 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 14 Jul 2020 16:44:09 -0400 +Subject: [PATCH 33/42] client: remove an extra debug print + +Signed-off-by: Peter Jones +--- + src/client.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/client.c b/src/client.c +index 914f2c8bd55..48fdeaba6a4 100644 +--- a/src/client.c ++++ b/src/client.c +@@ -536,7 +536,6 @@ oom: + 0, true); + } + +- printf("add_file_type:%d\n", add_file_type); + pm->version = PESIGND_VERSION; + pm->command = attached ? (add_file_type ? CMD_SIGN_ATTACHED_WITH_FILE_TYPE + : CMD_SIGN_ATTACHED) +-- +2.29.2 + diff --git a/0034-Move-most-of-macros.pesign-to-pesign-rpmbuild-helper.patch b/0034-Move-most-of-macros.pesign-to-pesign-rpmbuild-helper.patch new file mode 100644 index 0000000..ebb3d8c --- /dev/null +++ b/0034-Move-most-of-macros.pesign-to-pesign-rpmbuild-helper.patch @@ -0,0 +1,379 @@ +From 8fd6066496fc148945570371863597769b8ffe1d Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Mon, 6 Jul 2020 13:54:35 -0400 +Subject: [PATCH 34/42] Move most of macros.pesign to pesign-rpmbuild-helper + +Signed-off-by: Peter Jones +--- + Make.defaults | 1 + + src/Makefile | 8 +- + src/macros.pesign | 74 ++++-------- + src/pesign-rpmbuild-helper.in | 222 ++++++++++++++++++++++++++++++++++ + 4 files changed, 252 insertions(+), 53 deletions(-) + create mode 100644 src/pesign-rpmbuild-helper.in + +diff --git a/Make.defaults b/Make.defaults +index 0bacafe0d01..d4cd626c11e 100644 +--- a/Make.defaults ++++ b/Make.defaults +@@ -16,6 +16,7 @@ INSTALLROOT = $(DESTDIR) + + INSTALL ?= install + CROSS_COMPILE ?= ++EFI_ARCHES ?= aa64 ia32 x64 + + PKG_CONFIG = $(CROSS_COMPILE)pkg-config + CC := $(if $(filter default,$(origin CC)),$(CROSS_COMPILE)gcc,$(CC)) +diff --git a/src/Makefile b/src/Makefile +index bc3e5931456..82c2dfdec3f 100644 +--- a/src/Makefile ++++ b/src/Makefile +@@ -5,7 +5,7 @@ include $(TOPDIR)/Make.version + include $(TOPDIR)/Make.rules + include $(TOPDIR)/Make.defaults + +-BINTARGETS=authvar client efikeygen efisiglist pesigcheck pesign ++BINTARGETS=authvar client efikeygen efisiglist pesigcheck pesign pesign-rpmbuild-helper + SVCTARGETS=pesign.sysvinit pesign.service + TARGETS=$(BINTARGETS) $(SVCTARGETS) + +@@ -54,6 +54,11 @@ pesign : $(call objects-of,$(PESIGN_SOURCES) $(COMMON_SOURCES) $(COMMON_PE_SOURC + pesign : LDLIBS+=$(TOPDIR)/libdpe/libdpe.a + pesign : PKGS=efivar nss nspr popt + ++pesign-rpmbuild-helper: pesign-rpmbuild-helper.in ++ sed \ ++ -e "s/@@EFI_ARCHES@@/$(EFI_ARCHES)/g" \ ++ $^ > $@ ++ + deps : PKGS=efivar nss nspr popt uuid + deps : $(ALL_SOURCES) + $(MAKE) -f $(TOPDIR)/Make.deps \ +@@ -99,6 +104,7 @@ install : + $(INSTALL) -m 644 macros.pesign $(INSTALLROOT)/etc/rpm/ + $(INSTALL) -d -m 755 $(INSTALLROOT)$(libexecdir)/pesign/ + $(INSTALL) -m 750 pesign-authorize $(INSTALLROOT)$(libexecdir)/pesign/ ++ $(INSTALL) -m 755 pesign-rpmbuild-helper $(INSTALLROOT)$(libexecdir)/pesign/ + $(INSTALL) -d -m 700 $(INSTALLROOT)/etc/pesign + $(INSTALL) -m 600 pesign-users $(INSTALLROOT)/etc/pesign/users + $(INSTALL) -m 600 pesign-groups $(INSTALLROOT)/etc/pesign/groups +diff --git a/src/macros.pesign b/src/macros.pesign +index 5a6da1c6809..34af57c5b3b 100644 +--- a/src/macros.pesign ++++ b/src/macros.pesign +@@ -6,7 +6,7 @@ + # %pesign -s -i shim.orig -o shim.efi + # And magically get the right thing. + +-%__pesign_token %{nil}%{?pe_signing_token:-t "%{pe_signing_token}"} ++%__pesign_token %{nil}%{?pe_signing_token:--token "%{pe_signing_token}"} + %__pesign_cert %{!?pe_signing_cert:"Red Hat Test Certificate"}%{?pe_signing_cert:"%{pe_signing_cert}"} + + %__pesign_client_token %{!?pe_signing_token:"OpenSC Card (Fedora Signer)"}%{?pe_signing_token:"%{pe_signing_token}"} +@@ -24,54 +24,24 @@ + # -a # rhel only + # -s # perform signing + %pesign(i:o:C:e:c:n:a:s) \ +- _pesign_nssdir=/etc/pki/pesign \ +- if [ %{__pesign_cert} = "Red Hat Test Certificate" ]; then \ +- _pesign_nssdir=/etc/pki/pesign-rh-test \ +- fi \ +- if [ -x %{_pesign} ] && \\\ +- [ "%{_target_cpu}" == "x86_64" -o \\\ +- "%{_target_cpu}" == "aarch64" ]; then \ +- if [ "0%{?rhel}" -ge "7" -a -f /usr/bin/rpm-sign ]; then \ +- nss=$(mktemp -p $PWD -d) \ +- echo > ${nss}/pwfile \ +- certutil -N -d ${nss} -f ${nss}/pwfile \ +- certutil -A -n "ca" -t "CT,C," -i %{-a*} -d ${nss} \ +- certutil -A -n "signer" -t ",c," -i %{-c*} -d ${nss} \ +- sattrs=$(mktemp -p $PWD --suffix=.der) \ +- %{_pesign} %{-i} -E ${sattrs} --certdir ${nss} --force \ +- rpm-sign --key "%{-n*}" --rsadgstsign ${sattrs} \ +- %{_pesign} -R ${sattrs}.sig -I ${sattrs} %{-i} \\\ +- --certdir ${nss} -c signer %{-o} \ +- rm -rf ${sattrs} ${sattrs}.sig ${nss} \ +- elif [ "$(id -un)" == "kojibuilder" -a \\\ +- grep -q ID=fedora /etc/os-release -a \\\ +- ! -S /run/pesign/socket ]; then \ +- echo "No socket even though this is kojibuilder" 1>&2 \ +- ls -ld /run/pesign 1>&2 \ +- ls -l /run/pesign/socket 1>&2 \ +- getfacl /run/pesign 1>&2 \ +- getfacl /run/pesign/socket 1>&2 \ +- exit 1 \ +- elif [ -S /run/pesign/socket ]; then \ +- %{_pesign_client} -t %{__pesign_client_token} \\\ +- -c %{__pesign_client_cert} \\\ +- %{-i} %{-o} %{-e} %{-s} %{-C} \ +- else \ +- %{_pesign} %{__pesign_token} -c %{__pesign_cert} \\\ +- --certdir ${_pesign_nssdir} \\\ +- %{-i} %{-o} %{-e} %{-s} %{-C} \ +- fi \ +- else \ +- if [ -n "%{-i*}" -a -n "%{-o*}" ]; then \ +- mv %{-i*} %{-o*} \ +- elif [ -n "%{-i*}" -a -n "%{-e*}" ]; then \ +- touch %{-e*} \ +- fi \ +- fi \ +- if [ ! -s %{-o} ]; then \ +- if [ -e "%{-o*}" ]; then \ +- rm -f %{-o*} \ +- fi \ +- exit 1 \ +- fi ; +- ++ %{_libexecdir}/pesign/pesign-rpmbuild-helper \\\ ++ "%{_target_cpu}" \\\ ++ "%{_pesign}" \\\ ++ "%{_pesign_client}" \\\ ++ %{?__pesign_client_token:--client-token %{__pesign_client_token}} \\\ ++ %{?__pesign_client_cert:--client-cert %{__pesign_client_cert}} \\\ ++ %{?__pesign_token:%{__pesign_token}} \\\ ++ %{?__pesign_cert:--cert %{__pesign_cert}} \\\ ++ %{?_buildhost:--hostname "%{_buildhost}"} \\\ ++ %{?vendor:--vendor "%{vendor}"} \\\ ++ %{?_rhel:--rhelver "%{_rhel}"} \\\ ++ %{?-n:--rhelcert %{-n*}}%{?!-n:--rhelcert %{__pesign_cert}} \\\ ++ %{?-a:--rhelcafile "%{-a*}"} \\\ ++ %{?-c:--rhelcertfile "%{-c*}"} \\\ ++ %{?-C:--certout "%{-C*}"} \\\ ++ %{?-e:--sattrout "%{-e*}"} \\\ ++ %{?-i:--in "%{-i*}"} \\\ ++ %{?-o:--out "%{-o*}"} \\\ ++ %{?-s:--sign} \\\ ++ ; \ ++%{nil} +diff --git a/src/pesign-rpmbuild-helper.in b/src/pesign-rpmbuild-helper.in +new file mode 100644 +index 00000000000..c5287c27e0c +--- /dev/null ++++ b/src/pesign-rpmbuild-helper.in +@@ -0,0 +1,222 @@ ++#!/bin/bash ++# shellcheck shell=bash ++ ++set -eu ++set -x ++ ++usage() { ++ local status="${1}" && shift ++ local out ++ if [[ "${status}" -eq 0 ]] ; then ++ out=/dev/stdout ++ else ++ out=/dev/stderr ++ fi ++ ++ if [[ $# -gt 0 ]] ; then ++ echo "${0}: error: $*" >>"${out}" ++ fi ++ echo "usage: ${0} TARGET_CPU PESIGN_BINARY PESIGN_CLIENT_BINARY [OPTIONS]" >>"${out}" ++ exit "${status}" ++} ++ ++is_efi_arch() { ++ local arch="${1}" ++ local arches=(@@EFI_ARCHES@@) ++ local x ++ for x in "${arches[@]}" ; do ++ if [[ "${arch}" = "${x}" ]] ; then ++ return 0 ++ fi ++ done ++ return 1 ++} ++ ++error_on_empty() { ++ local f="${1}" ++ if [[ ! -s "${f}" ]] ; then ++ if [[ -e "${f}" ]] ; then ++ rm -f "${f}" ++ fi ++ echo "${0}: error: empty result file \"${f}\"">>/dev/stderr ++ exit 1 ++ fi ++} ++ ++main() { ++ if [[ $# -lt 3 ]] ; then ++ usage 1 not enough arguments ++ fi ++ local target_cpu="${1}" && shift ++ local bin="${1}" && shift ++ local client="${1}" && shift ++ ++ local rhelcafile="" || : ++ local rhelcertfile="" || : ++ ++ local certout=() || : ++ local sattrout=() || : ++ local input=() || : ++ local output=() || : ++ local client_token=() || : ++ local client_cert=() || : ++ local token=() || : ++ local cert=() || : ++ local rhelcert=() || : ++ local rhelver=0 || : ++ local sign="" || : ++ local arch="" || : ++ local vendor="" || : ++ local HOSTNAME="" || : ++ ++ while [[ $# -ge 2 ]] ; do ++ case " ${1} " in ++ " --rhelcafile ") ++ rhelcafile="${2}" ++ ;; ++ " --rhelcertfile ") ++ rhelcertfile="${2}" ++ ;; ++ " --hostname ") ++ HOSTNAME="${2}" ++ ;; ++ " --certout ") ++ certout[0]=-C ++ certout[1]="${2}" ++ ;; ++ " --sattrout ") ++ sattrout[0]=-e ++ sattrout[1]="${2}" ++ ;; ++ " --client-token ") ++ client_token[0]=-t ++ client_token[1]="${2}" ++ ;; ++ " --client-cert ") ++ client_cert[0]=-c ++ client_cert[1]="${2}" ++ ;; ++ " --token ") ++ token[0]=-t ++ token[1]="${2}" ++ ;; ++ " --cert ") ++ cert[0]=-c ++ cert[1]="${2}" ++ ;; ++ " --rhelcert ") ++ rhelcert[0]=-c ++ rhelcert[1]="${2}" ++ ;; ++ " --in ") ++ input[0]=-i ++ input[1]="${2}" ++ ;; ++ " --out ") ++ output[0]=-o ++ output[1]="${2}" ++ ;; ++ " --rhelver ") ++ rhelver="${2}" ++ ;; ++ " --vendor ") ++ vendor="${2}" ++ ;; ++ *) ++ break ++ ;; ++ esac ++ shift ++ shift ++ done ++ if [[ $# -ge 1 ]] && [[ "${1}" = --sign ]] ; then ++ sign=-s ++ shift ++ fi ++ ++ if [[ -z "${target_cpu}" ]] ; then ++ target_cpu="$(uname -m)" ++ fi ++ ++ target_cpu="${target_cpu/i?86/ia32}" ++ target_cpu="${target_cpu/x86_64/x64}" ++ target_cpu="${target_cpu/aarch64/aa64}" ++ target_cpu="${target_cpu/arm*/arm/}" ++ ++ local nssdir=/etc/pki/pesign ++ if [[ "${#cert[@]}" -eq 2 ]] && ++ [[ "${cert[1]}" == "Red Hat Test Certificate" ]] ; then ++ nssdir=/etc/pki/pesign-rh-test ++ fi ++ ++ # is_efi_arch is ultimately returning "is pesign configured to sign these ++ # using the rpm macro", so if it isn't, we're just copying the input to ++ # the output ++ if [[ -x "${bin}" ]] && ! is_efi_arch "${target_cpu}" ; then ++ if [[ -n "${input[*]}" ]] && [[ -n "${output[*]}" ]] ; then ++ cp -v "${input[1]}" "${output[1]}" ++ elif [[ -n "${input[*]}" ]] && [[ -n "${sattrout[*]}" ]] ; then ++ touch "${sattrout[1]}" ++ fi ++ ++ # if there's a 0-sized output file, delete it and error out ++ error_on_empty "${output[1]}" ++ return 0 ++ fi ++ ++ USERNAME="${USERNAME:-$(id -un)}" ++ ++ local socket="" || : ++ if grep -q ID=fedora /etc/os-release \ ++ && [[ "${rhelver}" -lt 7 ]] \ ++ && [[ "${USERNAME}" = "mockbuild" ]] \ ++ && [[ "${vendor}" = "Fedora Project" ]] \ ++ && [[ "${HOSTNAME}" =~ bkernel.* ]] ++ then ++ if [[ -S /run/pesign/socket ]] ; then ++ socket=/run/pesign/socket ++ elif [[ -S /var/run/pesign/socket ]]; then ++ socket=/var/run/pesign/socket ++ else ++ echo "Warning: no pesign socket even though user is ${USERNAME}" 1>&2 ++ echo "Warning: if this is a non-scratch koji build, this is wrong" 1>&2 ++ ls -ld /run/pesign /var/run/pesign 1>&2 ||: ++ ls -l /run/pesign/socket /var/run/pesign/socket 1>&2 ||: ++ getfacl /run/pesign /run/pesign/socket /var/run/pesign /var/run/pesign/socket 1>&2 ||: ++ getfacl -n /run/pesign /run/pesign/socket /var/run/pesign /var/run/pesign/socket 1>&2 ||: ++ fi ++ fi ++ ++ if [[ "${rhelver}" -ge 7 ]] ; then ++ nssdir="$(mktemp -p "${PWD}" -d)" ++ echo > "${nssdir}/pwfile" ++ certutil -N -d "${nssdir}" -f "${nssdir}/pwfile" ++ certutil -A -n "ca" -t "CTu,CTu,CTu" -i "${rhelcafile}" -d "${nssdir}" ++ certutil -A -n "signer" -t "CTu,CTu,CTu" -i "${rhelcertfile}" -d "${nssdir}" ++ sattrs="$(mktemp -p "${PWD}" --suffix=.der)" ++ "${bin}" -E "${sattrs}" --certdir "${nssdir}" \ ++ "${input[@]}" --force ++ rpm-sign --key "${rhelcert[1]}" --rsadgstsign "${sattrs}" ++ "${bin}" -R "${sattrs}.sig" -I "${sattrs}" \ ++ --certdir "${nssdir}" -c signer \ ++ "${input[@]}" "${output[@]}" ++ rm -rf "${sattrs}" "${sattrs}.sig" "${nssdir}" ++ elif [[ -n "${socket}" ]] ; then ++ "${client}" "${client_token[@]}" "${client_cert[@]}" \ ++ "${sattrout[@]}" "${certout[@]}" \ ++ ${sign} "${input[@]}" "${output[@]}" ++ else ++ "${bin}" --certdir "${nssdir}" "${token[@]}" \ ++ "${cert[@]}" ${sign} "${sattrout[@]}" \ ++ "${certout[@]}" "${input[@]}" "${output[@]}" ++ fi ++ ++ # if there's a 0-sized output file, delete it and error out ++ if [[ "${#output[@]}" -eq 2 ]] ; then ++ error_on_empty "${output[1]}" ++ fi ++} ++ ++main "${@}" ++ ++# vim:filetype=sh:fenc=utf-8:tw=78:sts=4:sw=4 +-- +2.29.2 + diff --git a/0035-pesign-authorize-shellcheck.patch b/0035-pesign-authorize-shellcheck.patch new file mode 100644 index 0000000..0066657 --- /dev/null +++ b/0035-pesign-authorize-shellcheck.patch @@ -0,0 +1,60 @@ +From 556e51ec7cdd4225de5e1764fc7fac114bd926d1 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 14 Jul 2020 15:07:32 -0400 +Subject: [PATCH 35/42] pesign-authorize: shellcheck + +Signed-off-by: Peter Jones +--- + src/pesign-authorize | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/src/pesign-authorize b/src/pesign-authorize +index a496f601ab4..55cd5c4e55b 100755 +--- a/src/pesign-authorize ++++ b/src/pesign-authorize +@@ -12,21 +12,21 @@ set -u + # License: GPLv2 + declare -a fileusers=() + declare -a dirusers=() +-for user in $(cat /etc/pesign/users); do ++while read -r user ; do + dirusers[${#dirusers[@]}]=-m + dirusers[${#dirusers[@]}]="u:$user:rwx" + fileusers[${#fileusers[@]}]=-m + fileusers[${#fileusers[@]}]="u:$user:rw" +-done ++done +Date: Tue, 14 Jul 2020 15:08:15 -0400 +Subject: [PATCH 36/42] pesign-authorize: don't setfacl /etc/pki/pesign-foo/ + +Signed-off-by: Peter Jones +--- + src/pesign-authorize | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/pesign-authorize b/src/pesign-authorize +index 55cd5c4e55b..c5448329c2c 100755 +--- a/src/pesign-authorize ++++ b/src/pesign-authorize +@@ -47,7 +47,7 @@ update_subdir() { + done + } + +-for x in /var/run/pesign/ /etc/pki/pesign*/ ; do ++for x in /var/run/pesign/ /etc/pki/pesign/ ; do + if [ -d "${x}" ]; then + update_subdir "${x}" + else +-- +2.29.2 + diff --git a/0037-kernel-building-hack.patch b/0037-kernel-building-hack.patch new file mode 100644 index 0000000..89b4741 --- /dev/null +++ b/0037-kernel-building-hack.patch @@ -0,0 +1,41 @@ +From 59e539c55f22e838b7781efb3357da0d8f4de7db Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 14 Jul 2020 16:42:39 -0400 +Subject: [PATCH 37/42] kernel building hack + +Signed-off-by: Peter Jones +--- + src/pesign-rpmbuild-helper.in | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/src/pesign-rpmbuild-helper.in b/src/pesign-rpmbuild-helper.in +index c5287c27e0c..27b8261bc17 100644 +--- a/src/pesign-rpmbuild-helper.in ++++ b/src/pesign-rpmbuild-helper.in +@@ -202,6 +202,23 @@ main() { + "${input[@]}" "${output[@]}" + rm -rf "${sattrs}" "${sattrs}.sig" "${nssdir}" + elif [[ -n "${socket}" ]] ; then ++ ### welcome haaaaack city ++ if [[ "${client_token[1]}" = "OpenSC Card (Fedora Signer)" ]] ; then ++ if [[ "${input[1]}" =~ (/|^)vmlinuz($|[_.-]) ]] \ ++ || [[ "${input[1]}" =~ (/|^)bzImage($|[_.-]) ]] ; then ++ if [[ "${rhelcertfile}" =~ redhatsecureboot501.* ]] \ ++ || [[ "${rhelcertfile}" =~ redhatsecureboot401.* ]] \ ++ || [[ "${rhelcertfile}" =~ centossecureboot201.* ]] ; then ++ client_cert[1]=kernel-signer ++ elif [[ "${rhelcertfile}" =~ redhatsecureboot502.* ]] \ ++ || [[ "${rhelcertfile}" =~ centossecureboot202.* ]] ; then ++ client_cert[1]=grub2-signer ++ elif [[ "${rhelcertfile}" =~ redhatsecureboot503.* ]] \ ++ || [[ "${rhelcertfile}" =~ centossecureboot203.* ]] ; then ++ client_cert[1]=fwupd-signer ++ fi ++ fi ++ fi + "${client}" "${client_token[@]}" "${client_cert[@]}" \ + "${sattrout[@]}" "${certout[@]}" \ + ${sign} "${input[@]}" "${output[@]}" +-- +2.29.2 + diff --git a/0038-Use-run-not-var-run.patch b/0038-Use-run-not-var-run.patch new file mode 100644 index 0000000..fbc9786 --- /dev/null +++ b/0038-Use-run-not-var-run.patch @@ -0,0 +1,105 @@ +From 36a87a0471f79346dc245ba62bdaaddf1e9c908e Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Thu, 16 Jul 2020 16:28:26 -0400 +Subject: [PATCH 38/42] Use /run not /var/run + +Signed-off-by: Peter Jones +--- + src/daemon.h | 4 ++-- + src/Makefile | 2 +- + src/pesign-authorize | 2 +- + src/pesign.service.in | 2 +- + src/pesign.sysvinit.in | 10 +++++----- + 5 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/src/daemon.h b/src/daemon.h +index 0368dc9256c..5fcd97ea717 100644 +--- a/src/daemon.h ++++ b/src/daemon.h +@@ -51,8 +51,8 @@ typedef enum { + } pesignd_cmd; + + #define PESIGND_VERSION 0x2a9edaf0 +-#define SOCKPATH "/var/run/pesign/socket" +-#define PIDFILE "/var/run/pesign.pid" ++#define SOCKPATH "/run/pesign/socket" ++#define PIDFILE "/run/pesign.pid" + + static inline uint32_t UNUSED + pesignd_string_size(char *buffer) +diff --git a/src/Makefile b/src/Makefile +index 82c2dfdec3f..e24bd600af0 100644 +--- a/src/Makefile ++++ b/src/Makefile +@@ -83,7 +83,7 @@ install_sysvinit: pesign.sysvinit + install : + $(INSTALL) -d -m 700 $(INSTALLROOT)/etc/pki/pesign/ + $(INSTALL) -d -m 700 $(INSTALLROOT)/etc/pki/pesign-rh-test/ +- $(INSTALL) -d -m 770 $(INSTALLROOT)/var/run/pesign/ ++ $(INSTALL) -d -m 770 $(INSTALLROOT)/run/pesign/ + $(INSTALL) -d -m 755 $(INSTALLROOT)$(bindir) + $(INSTALL) -m 755 authvar $(INSTALLROOT)$(bindir) + $(INSTALL) -m 755 pesign $(INSTALLROOT)$(bindir) +diff --git a/src/pesign-authorize b/src/pesign-authorize +index c5448329c2c..2381302440c 100755 +--- a/src/pesign-authorize ++++ b/src/pesign-authorize +@@ -47,7 +47,7 @@ update_subdir() { + done + } + +-for x in /var/run/pesign/ /etc/pki/pesign/ ; do ++for x in /run/pesign/ /var/run/pesign/ /etc/pki/pesign/ ; do + if [ -d "${x}" ]; then + update_subdir "${x}" + else +diff --git a/src/pesign.service.in b/src/pesign.service.in +index c75a000892a..4ac2199bce2 100644 +--- a/src/pesign.service.in ++++ b/src/pesign.service.in +@@ -4,6 +4,6 @@ Description=Pesign signing daemon + [Service] + PrivateTmp=true + Type=forking +-PIDFile=/var/run/pesign.pid ++PIDFile=/run/pesign.pid + ExecStart=/usr/bin/pesign --daemonize + ExecStartPost=@@LIBEXECDIR@@/pesign/pesign-authorize +diff --git a/src/pesign.sysvinit.in b/src/pesign.sysvinit.in +index b0e0f84ff0b..bf8edec8ff3 100644 +--- a/src/pesign.sysvinit.in ++++ b/src/pesign.sysvinit.in +@@ -4,7 +4,7 @@ + # + # chkconfig: - 50 50 + # processname: /usr/bin/pesign +-# pidfile: /var/run/pesign.pid ++# pidfile: /run/pesign.pid + ### BEGIN INIT INFO + # Provides: pesign + # Default-Start: +@@ -20,9 +20,9 @@ RETVAL=0 + + start(){ + echo -n "Starting pesign: " +- mkdir /var/run/pesign 2>/dev/null && +- chown pesign:pesign /var/run/pesign && +- chmod 0770 /var/run/pesign ++ mkdir /run/pesign 2>/dev/null && ++ chown pesign:pesign /run/pesign && ++ chmod 0770 /run/pesign + daemon /usr/bin/pesign --daemonize + RETVAL=$? + echo +@@ -32,7 +32,7 @@ start(){ + + stop(){ + echo -n "Stopping pesign: " +- killproc -p /var/run/pesign.pid pesignd ++ killproc -p /run/pesign.pid pesignd + RETVAL=$? + echo + rm -f /var/lock/subsys/pesign +-- +2.29.2 + diff --git a/0039-efikeygen-return-error-on-AKID-encoding-failures.patch b/0039-efikeygen-return-error-on-AKID-encoding-failures.patch new file mode 100644 index 0000000..b8a739d --- /dev/null +++ b/0039-efikeygen-return-error-on-AKID-encoding-failures.patch @@ -0,0 +1,43 @@ +From 854b9ea4fe5b743f643f8622e5a1ec26dd1eb2dc Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 16 Feb 2021 11:38:27 -0500 +Subject: [PATCH 39/42] efikeygen: return error on AKID encoding failures + +Clearly some of these exiting with nonsense error codes and some of them +returning error values is not how it's supposed to be. + +Signed-off-by: Peter Jones +--- + src/efikeygen.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/efikeygen.c b/src/efikeygen.c +index b1cac4705e8..8bf67c2ec20 100644 +--- a/src/efikeygen.c ++++ b/src/efikeygen.c +@@ -156,11 +156,11 @@ add_auth_key_id(cms_context *cms, void *extHandle, SECKEYPublicKey *pubkey) + { + SECItem *pubkey_der = PK11_DEREncodePublicKey(pubkey); + if (!pubkey_der) +- cmserr(-1, cms, "could not encode CA Key ID extension"); ++ cmsreterr(-1, cms, "could not encode CA Key ID extension"); + + SECItem *encoded = PK11_MakeIDFromPubKey(pubkey_der); + if (!encoded) +- cmserr(-1, cms, "could not encode CA Key ID extension"); ++ cmsreterr(-1, cms, "could not encode CA Key ID extension"); + + SECItem cspecific = { 0 }; + int rc = make_context_specific(cms, 0, &cspecific, encoded); +@@ -178,7 +178,7 @@ add_auth_key_id(cms_context *cms, void *extHandle, SECKEYPublicKey *pubkey) + status = CERT_AddExtension(extHandle, SEC_OID_X509_AUTH_KEY_ID, + &wrapped, PR_FALSE, PR_TRUE); + if (status != SECSuccess) +- cmserr(-1, cms, "could not encode CA Key ID extension"); ++ cmsreterr(-1, cms, "could not encode CA Key ID extension"); + return 0; + } + +-- +2.29.2 + diff --git a/0040-Rename-some-cms-error-functions.patch b/0040-Rename-some-cms-error-functions.patch new file mode 100644 index 0000000..a3b2c86 --- /dev/null +++ b/0040-Rename-some-cms-error-functions.patch @@ -0,0 +1,567 @@ +From eaf8471d14e54aa17802ce4d131db2d2440a69f9 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 16 Feb 2021 12:00:50 -0500 +Subject: [PATCH 40/42] Rename some cms error functions + +Some of these were really not clear, and efikeygen was misusing them. +This adds a couple more and disambiguates some of their names a bit. + +Signed-off-by: Peter Jones +--- + src/cms_common.c | 141 +++++++++++++++++++------------------------- + src/cms_pe_common.c | 8 +-- + src/cms_common.h | 23 ++++++-- + 3 files changed, 80 insertions(+), 92 deletions(-) + +diff --git a/src/cms_common.c b/src/cms_common.c +index e274a8a50da..4bbd5f5cfa9 100644 +--- a/src/cms_common.c ++++ b/src/cms_common.c +@@ -152,7 +152,7 @@ cms_context_init(cms_context *cms) + + cms->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (!cms->arena) +- cmsreterr(-1, cms, "could not create cryptographic arena"); ++ cnreterr(-1, cms, "could not create cryptographic arena"); + + cms->selected_digest = -1; + +@@ -498,7 +498,7 @@ unlock_nss_token(cms_context *cms) + PK11SlotList *slots = NULL; + slots = PK11_GetAllTokens(CKM_RSA_PKCS, PR_FALSE, PR_TRUE, cms); + if (!slots) +- cmsreterr(-1, cms, "could not get pk11 token list"); ++ cnreterr(-1, cms, "could not get pk11 token list"); + + + PK11SlotListElement *psle = NULL; +@@ -507,7 +507,7 @@ unlock_nss_token(cms_context *cms) + save_port_err() { + PK11_FreeSlotList(slots); + } +- cmsreterr(-1, cms, "could not get pk11 safe"); ++ cnreterr(-1, cms, "could not get pk11 safe"); + } + + while (psle) { +@@ -563,7 +563,7 @@ find_certificate(cms_context *cms, int needs_private_key) + PK11SlotList *slots = NULL; + slots = PK11_GetAllTokens(CKM_RSA_PKCS, PR_FALSE, PR_TRUE, cms); + if (!slots) +- cmsreterr(-1, cms, "could not get pk11 token list"); ++ cnreterr(-1, cms, "could not get pk11 token list"); + + PK11SlotListElement *psle = NULL; + psle = PK11_GetFirstSafe(slots); +@@ -571,7 +571,7 @@ find_certificate(cms_context *cms, int needs_private_key) + save_port_err() { + PK11_FreeSlotList(slots); + } +- cmsreterr(-1, cms, "could not get pk11 safe"); ++ cnreterr(-1, cms, "could not get pk11 safe"); + } + + while (psle) { +@@ -616,7 +616,7 @@ find_certificate(cms_context *cms, int needs_private_key) + PK11_DestroySlotListElement(slots, &psle); + PK11_FreeSlotList(slots); + } +- cmsreterr(-1, cms, "could not get certificate list"); ++ cnreterr(-1, cms, "could not get certificate list"); + } + + SECItem nickname = { +@@ -673,7 +673,7 @@ find_certificate(cms_context *cms, int needs_private_key) + cms->psle = NULL; + } + if (status != SECSuccess || cms->cert == NULL) +- cmsreterr(-1, cms, "could not find certificate"); ++ cnreterr(-1, cms, "could not find certificate"); + + return 0; + } +@@ -694,7 +694,7 @@ find_slot_for_token(cms_context *cms, PK11SlotInfo **slot) + PK11SlotList *slots = NULL; + slots = PK11_GetAllTokens(CKM_RSA_PKCS, PR_FALSE, PR_TRUE, cms); + if (!slots) +- cmsreterr(-1, cms, "could not get pk11 token list"); ++ cnreterr(-1, cms, "could not get pk11 token list"); + + PK11SlotListElement *psle = NULL; + psle = PK11_GetFirstSafe(slots); +@@ -702,7 +702,7 @@ find_slot_for_token(cms_context *cms, PK11SlotInfo **slot) + save_port_err() { + PK11_FreeSlotList(slots); + } +- cmsreterr(-1, cms, "could not get pk11 safe"); ++ cnreterr(-1, cms, "could not get pk11 safe"); + } + + while (psle) { +@@ -760,7 +760,7 @@ find_certificate_by_callback(cms_context *cms, + PK11SlotList *slots = NULL; + slots = PK11_GetAllTokens(CKM_RSA_PKCS, PR_FALSE, PR_TRUE, cms); + if (!slots) +- cmsreterr(-1, cms, "could not get pk11 token list"); ++ cnreterr(-1, cms, "could not get pk11 token list"); + + PK11SlotListElement *psle = NULL; + psle = PK11_GetFirstSafe(slots); +@@ -768,7 +768,7 @@ find_certificate_by_callback(cms_context *cms, + save_port_err() { + PK11_FreeSlotList(slots); + } +- cmsreterr(-1, cms, "could not get pk11 safe"); ++ cnreterr(-1, cms, "could not get pk11 safe"); + } + + while (psle) { +@@ -810,7 +810,7 @@ find_certificate_by_callback(cms_context *cms, + PK11_DestroySlotListElement(slots, &psle); + PK11_FreeSlotList(slots); + } +- cmsreterr(-1, cms, "could not get certificate list"); ++ cnreterr(-1, cms, "could not get certificate list"); + } + + CERTCertListNode *node = NULL; +@@ -837,7 +837,7 @@ find_certificate_by_callback(cms_context *cms, + } + + if (!node) +- cmsreterr(-1, cms, "Could not find certificate"); ++ cnreterr(-1, cms, "Could not find certificate"); + + *cert = CERT_DupCertificate(node->cert); + +@@ -865,7 +865,7 @@ int + find_named_certificate(cms_context *cms, char *name, CERTCertificate **cert) + { + if (!name) +- cmsreterr(-1, cms, "no subject name specified"); ++ cnreterr(-1, cms, "no subject name specified"); + + return find_certificate_by_callback(cms, match_subject, name, cert); + } +@@ -908,7 +908,7 @@ find_certificate_by_issuer_and_sn(cms_context *cms, + CERTCertificate **cert) + { + if (!ias) +- cmsreterr(-1, cms, "invalid issuer and serial number"); ++ cnreterr(-1, cms, "invalid issuer and serial number"); + + return find_certificate_by_callback(cms, match_issuer_and_serial, &ias, cert); + } +@@ -926,7 +926,7 @@ generate_string(cms_context *cms, SECItem *der, char *str) + ret = SEC_ASN1EncodeItem(cms->arena, der, &input, + SEC_PrintableStringTemplate); + if (ret == NULL) +- cmsreterr(-1, cms, "could not encode string"); ++ cnreterr(-1, cms, "could not encode string"); + return 0; + } + +@@ -946,11 +946,11 @@ generate_time(cms_context *cms, SECItem *encoded, time_t when) + tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + if (whenitem.len == 32) +- cmsreterr(-1, cms, "could not encode timestamp"); ++ cnreterr(-1, cms, "could not encode timestamp"); + + if (SEC_ASN1EncodeItem(cms->arena, encoded, &whenitem, + SEC_UTCTimeTemplate) == NULL) +- cmsreterr(-1, cms, "could not encode timestamp"); ++ cnreterr(-1, cms, "could not encode timestamp"); + return 0; + } + +@@ -975,7 +975,7 @@ generate_empty_sequence(cms_context *cms, SECItem *encoded) + ret = SEC_ASN1EncodeItem(cms->arena, encoded, &empty, + EmptySequenceTemplate); + if (ret == NULL) +- cmsreterr(-1, cms, "could not encode empty sequence"); ++ cnreterr(-1, cms, "could not encode empty sequence"); + return 0; + } + +@@ -1000,7 +1000,7 @@ make_context_specific(cms_context *cms, int ctxt, SECItem *encoded, + rv = SEC_ASN1EncodeItem(cms->arena, encoded, original, + ContextSpecificSequence); + if (rv == NULL) +- cmsreterr(-1, cms, "could not encode context specific data"); ++ cnreterr(-1, cms, "could not encode context specific data"); + return 0; + } + +@@ -1022,12 +1022,12 @@ make_eku_oid(cms_context *cms, SECItem *encoded, SECOidTag oid_tag) + + oid_data = SECOID_FindOIDByTag(oid_tag); + if (!oid_data) +- cmsreterr(-1, cms, "could not encode eku oid data"); ++ cnreterr(-1, cms, "could not encode eku oid data"); + + rv = SEC_ASN1EncodeItem(cms->arena, encoded, &oid_data->oid, + EKUOidSequence); + if (rv == NULL) +- cmsreterr(-1, cms, "could not encode eku oid data"); ++ cnreterr(-1, cms, "could not encode eku oid data"); + + encoded->type = siBuffer; + return 0; +@@ -1042,7 +1042,7 @@ generate_octet_string(cms_context *cms, SECItem *encoded, SECItem *original) + } + if (SEC_ASN1EncodeItem(cms->arena, encoded, original, + SEC_OctetStringTemplate) == NULL) +- cmsreterr(-1, cms, "could not encode octet string"); ++ cnreterr(-1, cms, "could not encode octet string"); + + return 0; + } +@@ -1054,13 +1054,13 @@ generate_object_id(cms_context *cms, SECItem *der, SECOidTag tag) + + oid = SECOID_FindOIDByTag(tag); + if (!oid) +- cmsreterr(-1, cms, "could not find OID"); ++ cnreterr(-1, cms, "could not find OID"); + + void *ret; + ret = SEC_ASN1EncodeItem(cms->arena, der, &oid->oid, + SEC_ObjectIDTemplate); + if (ret == NULL) +- cmsreterr(-1, cms, "could not encode ODI"); ++ cnreterr(-1, cms, "could not encode ODI"); + return 0; + } + +@@ -1109,7 +1109,7 @@ encode_algorithm_id(cms_context *cms, SECItem *der, SECOidTag tag) + ret = SEC_ASN1EncodeItem(cms->arena, der, &id, + SECOID_AlgorithmIDTemplate); + if (ret == NULL) +- cmsreterr(-1, cms, "could not encode Algorithm ID"); ++ cnreterr(-1, cms, "could not encode Algorithm ID"); + + return 0; + } +@@ -1144,14 +1144,14 @@ generate_spc_string(cms_context *cms, SECItem *ssp, char *str, int len) + SECITEM_AllocItem(cms->arena, &ss.unicode, len); + if (len != 0) { + if (!ss.unicode.data) +- cmsreterr(-1, cms, "could not allocate memory"); ++ cnreterr(-1, cms, "could not allocate memory"); + + memcpy(ss.unicode.data, str, len); + } + ss.unicode.type = siBMPString; + + if (SEC_ASN1EncodeItem(cms->arena, ssp, &ss, SpcStringTemplate) == NULL) +- cmsreterr(-1, cms, "could not encode SpcString"); ++ cnreterr(-1, cms, "could not encode SpcString"); + + return 0; + } +@@ -1224,19 +1224,14 @@ generate_digest_begin(cms_context *cms) + } else { + digests = PORT_ZAlloc(n_digest_params * sizeof (*digests)); + if (digests == NULL) +- cmsreterr(-1, cms, "could not allocate digest context"); ++ cnreterr(-1, cms, "could not allocate digest context"); + } + + for (int i = 0; i < n_digest_params; i++) { + digests[i].pk11ctx = PK11_CreateDigestContext( + digest_params[i].digest_tag); +- if (!digests[i].pk11ctx) { +- cms->log(cms, LOG_ERR, "%s:%s:%d could not create " +- "digest context: %s", +- __FILE__, __func__, __LINE__, +- PORT_ErrorToString(PORT_GetError())); +- goto err; +- } ++ if (!digests[i].pk11ctx) ++ cngotoerr(err, cms, "could not create digest context"); + + PK11_DigestBegin(digests[i].pk11ctx); + } +@@ -1268,22 +1263,14 @@ generate_digest_finish(cms_context *cms) + + for (int i = 0; i < n_digest_params; i++) { + SECItem *digest = PORT_ArenaZAlloc(cms->arena,sizeof (SECItem)); +- if (digest == NULL) { +- cms->log(cms, LOG_ERR, "%s:%s:%d could not allocate " +- "memory: %s", __FILE__, __func__, __LINE__, +- PORT_ErrorToString(PORT_GetError())); +- goto err; +- } ++ if (digest == NULL) ++ cngotoerr(err, cms, "could not allocate memory"); + + digest->type = siBuffer; + digest->len = digest_params[i].size; + digest->data = PORT_ArenaZAlloc(cms->arena, digest_params[i].size); +- if (digest->data == NULL) { +- cms->log(cms, LOG_ERR, "%s:%s:%d could not allocate " +- "memory: %s", __FILE__, __func__, __LINE__, +- PORT_ErrorToString(PORT_GetError())); +- goto err; +- } ++ if (digest->data == NULL) ++ cngotoerr(err, cms, "could not allocate memory"); + + PK11_DigestFinal(cms->digests[i].pk11ctx, + digest->data, &digest->len, digest_params[i].size); +@@ -1319,29 +1306,23 @@ generate_signature(cms_context *cms) + { + int rc = 0; + +- if (cms->digests[cms->selected_digest].pe_digest == NULL) { +- cms->log(cms, LOG_ERR, "%s:%s:%d PE digest has not been " +- "allocated", __FILE__, __func__, __LINE__); +- return -1; +- } ++ if (cms->digests[cms->selected_digest].pe_digest == NULL) ++ cnreterr(-1, cms, "PE digest has not been allocated"); + + if (content_is_empty(cms->digests[cms->selected_digest].pe_digest->data, +- cms->digests[cms->selected_digest].pe_digest->len)) { +- cms->log(cms, LOG_ERR, "%s:%s:%d PE binary has not been " +- "digested", __FILE__, __func__, __LINE__); +- return -1; +- } ++ cms->digests[cms->selected_digest].pe_digest->len)) ++ cnreterr(-1, cms, "PE binary has not been digested"); + + SECItem sd_der; + memset(&sd_der, '\0', sizeof(sd_der)); + rc = generate_spc_signed_data(cms, &sd_der); + if (rc < 0) +- cmsreterr(-1, cms, "could not create signed data"); ++ cnreterr(-1, cms, "could not create signed data"); + + memcpy(&cms->newsig, &sd_der, sizeof (cms->newsig)); + cms->newsig.data = malloc(sd_der.len); + if (!cms->newsig.data) +- cmsreterr(-1, cms, "could not allocate signed data"); ++ cnreterr(-1, cms, "could not allocate signed data"); + memcpy(cms->newsig.data, sd_der.data, sd_der.len); + return 0; + } +@@ -1387,7 +1368,7 @@ generate_validity(cms_context *cms, SECItem *der, time_t start, time_t end) + void *ret; + ret = SEC_ASN1EncodeItem(cms->arena, der, &validity, ValidityTemplate); + if (ret == NULL) +- cmsreterr(-1, cms, "could not encode validity"); ++ cnreterr(-1, cms, "could not encode validity"); + return 0; + } + +@@ -1405,7 +1386,7 @@ wrap_in_set(cms_context *cms, SECItem *der, SECItem **items) + + ret = SEC_ASN1EncodeItem(cms->arena, der, &items, &SetTemplate); + if (ret == NULL) +- cmsreterr(-1, cms, "could not encode set"); ++ cnreterr(-1, cms, "could not encode set"); + return 0; + } + +@@ -1447,7 +1428,7 @@ wrap_in_seq(cms_context *cms, SECItem *der, SECItem *items, int num_items) + save_port_err() { + PORT_ArenaRelease(cms->arena, mark); + } +- cmsreterr(-1, cms, "could not encode set"); ++ cnreterr(-1, cms, "could not encode set"); + } + PORT_ArenaUnmark(cms->arena, mark); + return rc; +@@ -1494,7 +1475,7 @@ generate_common_name(cms_context *cms, SECItem *der, char *cn_str) + void *ret; + ret = SEC_ASN1EncodeItem(cms->arena, &cn_item, &cn, CommonNameTemplate); + if (ret == NULL) +- cmsreterr(-1, cms, "could not encode common name"); ++ cnreterr(-1, cms, "could not encode common name"); + + SECItem cn_set; + SECItem *items[2] = {&cn_item, NULL}; +@@ -1542,7 +1523,7 @@ generate_ava(cms_context *cms, SECItem *der, CERTAVA *certava) + + void *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (arena == NULL) +- cmsreterr(-1, cms, "could not create arena"); ++ cnreterr(-1, cms, "could not create arena"); + + void *real_arena = cms->arena; + cms->arena = arena; +@@ -1553,7 +1534,7 @@ generate_ava(cms_context *cms, SECItem *der, CERTAVA *certava) + PORT_FreeArena(arena, PR_TRUE); + } + cms->arena = real_arena; +- cmsreterr(-1, cms, "could not find OID"); ++ cnreterr(-1, cms, "could not find OID"); + } + + int rc = generate_object_id(cms, &ava.type, oid->offset); +@@ -1573,7 +1554,7 @@ generate_ava(cms_context *cms, SECItem *der, CERTAVA *certava) + PORT_FreeArena(arena, PR_TRUE); + } + cms->arena = real_arena; +- cmsreterr(-1, cms, "could not encode AVA"); ++ cnreterr(-1, cms, "could not encode AVA"); + } + + der->type = tmp.type; +@@ -1584,7 +1565,7 @@ generate_ava(cms_context *cms, SECItem *der, CERTAVA *certava) + PORT_FreeArena(arena, PR_TRUE); + } + cms->arena = real_arena; +- cmsreterr(-1, cms, "could not allocate AVA"); ++ cnreterr(-1, cms, "could not allocate AVA"); + } + memcpy(der->data, tmp.data, tmp.len); + PORT_FreeArena(arena, PR_TRUE); +@@ -1612,7 +1593,7 @@ generate_name(cms_context *cms, SECItem *der, CERTName *certname) + + if (num_items == 0) { + PORT_ArenaRelease(cms->arena, marka); +- cmsreterr(-1, cms, "No name items to encode"); ++ cnreterr(-1, cms, "No name items to encode"); + } + + SECItem items[num_items]; +@@ -1698,7 +1679,7 @@ generate_auth_info(cms_context *cms, SECItem *der, char *url) + + SECOidData *oid = SECOID_FindOIDByTag(SEC_OID_PKIX_CA_ISSUERS); + if (!oid) +- cmsreterr(-1, cms, "could not get CA issuers OID"); ++ cnreterr(-1, cms, "could not get CA issuers OID"); + + memcpy(&ai.oid, &oid->oid, sizeof (ai.oid)); + +@@ -1715,7 +1696,7 @@ generate_auth_info(cms_context *cms, SECItem *der, char *url) + SECItem unwrapped; + ret = SEC_ASN1EncodeItem(cms->arena, &unwrapped, &ai, AuthInfoTemplate); + if (ret == NULL) +- cmsreterr(-1, cms, "could not encode CA Issuers"); ++ cnreterr(-1, cms, "could not encode CA Issuers"); + + rc = wrap_in_seq(cms, der, &unwrapped, 1); + if (rc < 0) +@@ -1725,19 +1706,17 @@ generate_auth_info(cms_context *cms, SECItem *der, char *url) + /* I've no idea how to get SEC_ASN1EncodeItem to spit out the thing + * we actually want here. So once again, just force the data to + * look correct :( */ +- if (unwrapped.len < 12) { +- cms->log(cms, LOG_ERR, "%s:%s:%d generated CA Issuers Info " +- "cannot possibly be valid", +- __FILE__, __func__, __LINE__); +- return -1; +- } ++ if (unwrapped.len < 12) ++ cnreterr(-1, cms, ++ "generated CA Issuers Info cannot possibly be valid"); ++ + unwrapped.data[12] = 0x86; + unwrapped.type = siBuffer; + + AuthInfo wrapper; + oid = SECOID_FindOIDByTag(SEC_OID_X509_AUTH_INFO_ACCESS); + if (!oid) +- cmsreterr(-1, cms, "could not find Auth Info Access OID"); ++ cnreterr(-1, cms, "could not find Auth Info Access OID"); + + memcpy(&wrapper.oid, &oid->oid, sizeof (ai.oid)); + +@@ -1746,7 +1725,7 @@ generate_auth_info(cms_context *cms, SECItem *der, char *url) + ret = SEC_ASN1EncodeItem(cms->arena, der, &wrapper, + AuthInfoWrapperTemplate); + if (ret == NULL) +- cmsreterr(-1, cms, "could not encode CA Issuers OID"); ++ cnreterr(-1, cms, "could not encode CA Issuers OID"); + + return 0; + } +@@ -1763,14 +1742,14 @@ generate_keys(cms_context *cms, PK11SlotInfo *slot, + SECStatus rv; + rv = PK11_Authenticate(slot, PR_TRUE, cms); + if (rv != SECSuccess) +- cmsreterr(-1, cms, "could not authenticate with pk11 service"); ++ cnreterr(-1, cms, "could not authenticate with pk11 service"); + + void *params = &rsaparams; + *privkey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, + params, pubkey, PR_TRUE, PR_TRUE, + cms); + if (!*privkey) +- cmsreterr(-1, cms, "could not generate RSA keypair"); ++ cnreterr(-1, cms, "could not generate RSA keypair"); + return 0; + } + +diff --git a/src/cms_pe_common.c b/src/cms_pe_common.c +index e5a33eb6fe1..f6c5cffc6a9 100644 +--- a/src/cms_pe_common.c ++++ b/src/cms_pe_common.c +@@ -165,7 +165,7 @@ generate_digest(cms_context *cms, Pe *pe, int padded) + * 2. Initialize SHA hash context. */ + map = pe_rawfile(pe, &map_size); + if (!map) +- pereterr(-1, "could not get raw output file address"); ++ cmsreterr(-1, cms, "could not get raw output file address"); + + /* 3. Calculate the distance from the base of the image header to the + * image checksum. +@@ -174,10 +174,8 @@ generate_digest(cms_context *cms, Pe *pe, int padded) + hash_base = map; + + opthdr = pe_getopthdr(pe); +- if (opthdr == NULL) { +- cms->log(cms, LOG_ERR, "%s:%s:%d PE header is invalid", __FILE__, __func__, __LINE__); +- goto error; +- } ++ if (opthdr == NULL) ++ cmsgotoerr(error, cms, "PE header is invalid"); + + switch (pe_kind(pe)) { + case PE_K_PE_EXE: { +diff --git a/src/cms_common.h b/src/cms_common.h +index 04974035f0c..1bffdcd034b 100644 +--- a/src/cms_common.h ++++ b/src/cms_common.h +@@ -41,19 +41,30 @@ + #define for_each_cert(cl, node) \ + for (CERTCertListNode *node = CERT_LIST_HEAD(cl); !CERT_LIST_END(node, cl); node = CERT_LIST_NEXT(node)) + +-#define cmserr(rv, cms, fmt, args...) ({ \ +- (cms)->log((cms), LOG_ERR, "%s:%s:%d: " fmt ": %s", \ +- __FILE__, __func__, __LINE__, ## args, \ +- PORT_ErrorToString(PORT_GetError())); \ +- exit(rv); \ ++#define cmsreterr(rv, cms, fmt, args...) ({ \ ++ (cms)->log((cms), LOG_ERR, "%s:%s:%d: " fmt, \ ++ __FILE__, __func__, __LINE__, ## args); \ ++ return rv; \ + }) +-#define cmsreterr(rv, cms, fmt, args...) ({ \ ++#define cmsgotoerr(errlabel, cms, fmt, args...) ({ \ ++ (cms)->log((cms), LOG_ERR, "%s:%s:%d: " fmt, \ ++ __FILE__, __func__, __LINE__, ## args); \ ++ goto errlabel; \ ++ }) ++#define cnreterr(rv, cms, fmt, args...) ({ \ + (cms)->log((cms), LOG_ERR, "%s:%s:%d: " fmt ":%s:%s", \ + __FILE__, __func__, __LINE__, ## args, \ + PORT_ErrorToName(PORT_GetError()), \ + PORT_ErrorToString(PORT_GetError())); \ + return rv; \ + }) ++#define cngotoerr(errlabel, cms, fmt, args...) ({ \ ++ (cms)->log((cms), LOG_ERR, "%s:%s:%d: " fmt ":%s:%s", \ ++ __FILE__, __func__, __LINE__, ## args, \ ++ PORT_ErrorToName(PORT_GetError()), \ ++ PORT_ErrorToString(PORT_GetError())); \ ++ goto errlabel; \ ++ }) + + struct digest { + PK11Context *pk11ctx; +-- +2.29.2 + diff --git a/0041-Make-cms_pe_common-bounds-check-errors-more-verbose.patch b/0041-Make-cms_pe_common-bounds-check-errors-more-verbose.patch new file mode 100644 index 0000000..46d45a3 --- /dev/null +++ b/0041-Make-cms_pe_common-bounds-check-errors-more-verbose.patch @@ -0,0 +1,181 @@ +From 2802ad709872f8291786ce31400a3496bbe23b14 Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 16 Feb 2021 11:19:30 -0500 +Subject: [PATCH 41/42] Make cms_pe_common bounds check errors more verbose + +One of these is failing for hughsie, and that's weird, so I want to know +why. + +Signed-off-by: Peter Jones +--- + src/cms_pe_common.c | 76 +++++++++++++++++++-------------------------- + 1 file changed, 32 insertions(+), 44 deletions(-) + +diff --git a/src/cms_pe_common.c b/src/cms_pe_common.c +index f6c5cffc6a9..bdcfaff99f8 100644 +--- a/src/cms_pe_common.c ++++ b/src/cms_pe_common.c +@@ -43,29 +43,30 @@ + #include + + static int +-check_pointer_and_size(Pe *pe, void *ptr, size_t size) ++check_pointer_and_size(cms_context *cms, Pe *pe, void *ptr, size_t size) + { + void *map = NULL; + size_t map_size = 0; + + map = pe_rawfile(pe, &map_size); + if (!map || map_size < 1) +- return 0; ++ cmsreterr(0, cms, "mmap is %p mmap size is %zd end is %p", ++ map, map_size, (void *)((uintptr_t)map + map_size)); + + if ((uintptr_t)ptr < (uintptr_t)map) +- return 0; ++ cmsreterr(0, cms, "pointer %p is below mmap at %p", ptr, map); + + if ((uintptr_t)ptr + size > (uintptr_t)map + map_size) +- return 0; +- +- if (ptr <= map && size >= map_size) +- return 0; ++ cmsreterr(0, cms, ++ "pointer region end %p is above mmap end at %p", ++ (void *)((uintptr_t)ptr + size), ++ (void *)((uintptr_t)map + map_size)); + + return 1; + } + + static void * +-get_strtab(Pe *pe) ++get_strtab(cms_context *cms, Pe *pe) + { + static void *ret = NULL; + uint32_t *ptr; +@@ -91,17 +92,17 @@ get_strtab(Pe *pe) + intret += pehdr.symbols * sizeof(struct pe_symtab_entry); + + ptr = (uint32_t *)((intptr_t)map + intret); +- if (!check_pointer_and_size(pe, ptr, 4)) ++ if (!check_pointer_and_size(cms, pe, ptr, 4)) + pereterr(NULL, "invalid string table start"); + +- if (!check_pointer_and_size(pe, ptr, *ptr)) ++ if (!check_pointer_and_size(cms, pe, ptr, *ptr)) + pereterr(NULL, "invalid string table size"); + ret = ptr; + return ret; + } + + static char * +-get_str(Pe *pe, char *strnum) ++get_str(cms_context *cms, Pe *pe, char *strnum) + { + size_t sz; + unsigned long num; +@@ -120,7 +121,7 @@ get_str(Pe *pe, char *strnum) + if (errno != 0) + return NULL; + +- strtab = get_strtab(pe); ++ strtab = get_strtab(cms, pe); + if (!strtab) + return NULL; + +@@ -191,11 +192,8 @@ generate_digest(cms_context *cms, Pe *pe, int padded) + default: + goto error; + } +- if (!check_pointer_and_size(pe, hash_base, hash_size)) { +- cms->log(cms, LOG_ERR, "%s:%s:%d PE header is invalid", +- __FILE__, __func__, __LINE__); +- goto error; +- } ++ if (!check_pointer_and_size(cms, pe, hash_base, hash_size)) ++ cmsgotoerr(error, cms, "PE header is invalid"); + dprintf("beginning of hash"); + dprintf("digesting %lx + %lx", hash_base - map, hash_size); + generate_digest_step(cms, hash_base, hash_size); +@@ -209,18 +207,13 @@ generate_digest(cms_context *cms, Pe *pe, int padded) + data_directory *dd; + + rc = pe_getdatadir(pe, &dd); +- if (rc < 0 || !dd || !check_pointer_and_size(pe, dd, sizeof(*dd))) { +- cms->log(cms, LOG_ERR, "%s:%s:%d PE data directory is invalid", +- __FILE__, __func__, __LINE__); +- goto error; +- } ++ if (rc < 0 || !dd || !check_pointer_and_size(cms, pe, dd, sizeof(*dd))) ++ cmsgotoerr(error, cms, "PE data directory is invalid"); + + hash_size = (uintptr_t)&dd->certs - (uintptr_t)hash_base; +- if (!check_pointer_and_size(pe, hash_base, hash_size)) { +- cms->log(cms, LOG_ERR, "%s:%s:%d PE data directory is invalid", +- __FILE__, __func__, __LINE__); +- goto error; +- } ++ if (!check_pointer_and_size(cms, pe, hash_base, hash_size)) ++ cmsgotoerr(error, cms, "PE data directory is invalid"); ++ + generate_digest_step(cms, hash_base, hash_size); + dprintf("digesting %lx + %lx", hash_base - map, hash_size); + +@@ -231,11 +224,9 @@ generate_digest(cms_context *cms, Pe *pe, int padded) + : pe64opthdr->header_size) - + ((uintptr_t)&dd->base_relocations - (uintptr_t)map); + +- if (!check_pointer_and_size(pe, hash_base, hash_size)) { +- cms->log(cms, LOG_ERR, "%s:%s:%d PE relocations table is " +- "invalid", __FILE__, __func__, __LINE__); +- goto error; +- } ++ if (!check_pointer_and_size(cms, pe, hash_base, hash_size)) ++ cmsgotoerr(error, cms, "PE relocations table is invalid"); ++ + generate_digest_step(cms, hash_base, hash_size); + dprintf("digesting %lx + %lx", hash_base - map, hash_size); + +@@ -262,17 +253,15 @@ generate_digest(cms_context *cms, Pe *pe, int padded) + hash_base = (void *)((uintptr_t)map + shdrs[i].data_addr); + hash_size = shdrs[i].raw_data_size; + +- if (!check_pointer_and_size(pe, hash_base, hash_size)) { +- cms->log(cms, LOG_ERR, "%s:%s:%d PE section \"%s\" " +- "has invalid address", +- __FILE__, __func__, __LINE__, shdrs[i].name); +- goto error_shdrs; +- } ++ if (!check_pointer_and_size(cms, pe, hash_base, hash_size)) ++ cmsgotoerr(error_shdrs, cms, ++ "PE section \"%s\" has invalid address", ++ shdrs[i].name); + + if (cms->omit_vendor_cert) { + char *name = shdrs[i].name; + if (name && name[0] == '/') +- name = get_str(pe, name + 1); ++ name = get_str(cms, pe, name + 1); + dprintf("section:\"%s\"", name ? name : "(null)"); + if (name && !strcmp(name, ".vendor_cert")) { + dprintf("skipping .vendor_cert section"); +@@ -291,11 +280,10 @@ generate_digest(cms_context *cms, Pe *pe, int padded) + hash_base = (void *)((uintptr_t)map + hashed_bytes); + hash_size = map_size - dd->certs.size - hashed_bytes; + +- if (!check_pointer_and_size(pe, hash_base, hash_size)) { +- cms->log(cms, LOG_ERR, "%s:%s:%d PE has invalid " +- "trailing data", __FILE__, __func__, __LINE__); +- goto error_shdrs; +- } ++ if (!check_pointer_and_size(cms, pe, hash_base, hash_size)) ++ cmsgotoerr(error_shdrs, cms, ++ "PE has invalid trailing data"); ++ + if (hash_size % 8 != 0 && padded) { + size_t tmp_size = hash_size + + ALIGNMENT_PADDING(hash_size, 8); +-- +2.29.2 + diff --git a/0042-Fix-our-error-message-line-numbers-hopefully.patch b/0042-Fix-our-error-message-line-numbers-hopefully.patch new file mode 100644 index 0000000..fd78c8a --- /dev/null +++ b/0042-Fix-our-error-message-line-numbers-hopefully.patch @@ -0,0 +1,152 @@ +From 25bc2f4ce9215cd39fb448ada642824a5d20205f Mon Sep 17 00:00:00 2001 +From: Peter Jones +Date: Tue, 16 Feb 2021 11:47:00 -0500 +Subject: [PATCH 42/42] Fix our error message line numbers, hopefully. + +Most of these seem to be off by a line or two; it's pretty obvious why. + +Signed-off-by: Peter Jones +--- + src/cms_common.h | 10 ++++++---- + src/compiler.h | 5 ++++- + src/util.h | 32 +++++++++++++++++++++++--------- + 3 files changed, 33 insertions(+), 14 deletions(-) + +diff --git a/src/cms_common.h b/src/cms_common.h +index 1bffdcd034b..6cc31d5c6f0 100644 +--- a/src/cms_common.h ++++ b/src/cms_common.h +@@ -43,24 +43,26 @@ + + #define cmsreterr(rv, cms, fmt, args...) ({ \ + (cms)->log((cms), LOG_ERR, "%s:%s:%d: " fmt, \ +- __FILE__, __func__, __LINE__, ## args); \ ++ __FILE__, __func__, __LINE__ - 2, \ ++ ## args); \ + return rv; \ + }) + #define cmsgotoerr(errlabel, cms, fmt, args...) ({ \ + (cms)->log((cms), LOG_ERR, "%s:%s:%d: " fmt, \ +- __FILE__, __func__, __LINE__, ## args); \ ++ __FILE__, __func__, __LINE__ - 2, \ ++ ## args); \ + goto errlabel; \ + }) + #define cnreterr(rv, cms, fmt, args...) ({ \ + (cms)->log((cms), LOG_ERR, "%s:%s:%d: " fmt ":%s:%s", \ +- __FILE__, __func__, __LINE__, ## args, \ ++ __FILE__, __func__, __LINE__ - 2, ## args, \ + PORT_ErrorToName(PORT_GetError()), \ + PORT_ErrorToString(PORT_GetError())); \ + return rv; \ + }) + #define cngotoerr(errlabel, cms, fmt, args...) ({ \ + (cms)->log((cms), LOG_ERR, "%s:%s:%d: " fmt ":%s:%s", \ +- __FILE__, __func__, __LINE__, ## args, \ ++ __FILE__, __func__, __LINE__ - 2, ## args, \ + PORT_ErrorToName(PORT_GetError()), \ + PORT_ErrorToString(PORT_GetError())); \ + goto errlabel; \ +diff --git a/src/compiler.h b/src/compiler.h +index 31379ef9b33..5d979c9d977 100644 +--- a/src/compiler.h ++++ b/src/compiler.h +@@ -23,6 +23,9 @@ + #define ALIGNED(n) __attribute__((__aligned__(n))) + #define CLEANUP_FUNC(x) __attribute__((__cleanup__(x))) + ++#ifndef __CONCAT ++#define __CONCAT(a, b) a ## b ++#endif + #define __CONCAT3(a, b, c) a ## b ## c + #define CONCATENATE(a, b) __CONCAT(a, b) + #define CAT(a, b) __CONCAT(a, b) +@@ -71,7 +74,7 @@ + * compiler has support to do so. + */ + #define compiletime_assert(condition, msg) \ +- _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__) ++ _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__ - 1) + + /** + * BUILD_BUG_ON_MSG - break compile if a condition is true & emit supplied +diff --git a/src/util.h b/src/util.h +index 21a846c10ee..e2893b71c39 100644 +--- a/src/util.h ++++ b/src/util.h +@@ -67,7 +67,7 @@ + + #define nsserr(rv, fmt, args...) ({ \ + errx((rv), "%s:%s:%d: " fmt ": %s", \ +- __FILE__, __func__, __LINE__, ##args, \ ++ __FILE__, __func__, __LINE__ - 2, ##args, \ + PORT_ErrorToString(PORT_GetError())); \ + }) + #define condnsserr(cond, rv, fmt, args...) ({ \ +@@ -76,7 +76,7 @@ + }) + #define nssreterr(rv, fmt, args...) ({ \ + fprintf(stderr, "%s:%s:%d: " fmt ": %s\n", \ +- __FILE__, __func__, __LINE__, ##args, \ ++ __FILE__, __func__, __LINE__ - 2, ##args, \ + PORT_ErrorToString(PORT_GetError())); \ + return rv; \ + }) +@@ -86,21 +86,21 @@ + }) + #define liberr(rv, fmt, args...) ({ \ + err((rv), "%s:%s:%d: " fmt, \ +- __FILE__, __func__, __LINE__, ##args); \ ++ __FILE__, __func__, __LINE__ - 2, ##args); \ + }) + #define libreterr(rv, fmt, args...) ({ \ + fprintf(stderr, "%s:%s:%d: " fmt ": %m\n", \ +- __FILE__, __func__, __LINE__, ##args); \ ++ __FILE__, __func__, __LINE__ - 2, ##args); \ + return rv; \ + }) + #define peerr(rv, fmt, args...) ({ \ + errx((rv), "%s:%s:%d: " fmt ": %s", \ +- __FILE__, __func__, __LINE__, ##args, \ ++ __FILE__, __func__, __LINE__ - 2, ##args, \ + pe_errmsg(pe_errno())); \ + }) + #define pereterr(rv, fmt, args...) ({ \ + fprintf(stderr, "%s:%s:%d: " fmt ": %s\n", \ +- __FILE__, __func__, __LINE__, ##args, \ ++ __FILE__, __func__, __LINE__ - 2, ##args, \ + pe_errmsg(pe_errno())); \ + return rv; \ + }) +@@ -274,11 +274,25 @@ proxy_fd_mode(int fd, char *infile, mode_t *outmode, size_t *inlength) + + extern long verbosity(void); + +-#define dprintf_(tv, file, func, line, fmt, args...) ({struct timeval tv; gettimeofday(&tv, NULL); warnx("%ld.%lu %s:%s():%d: " fmt, tv.tv_sec, tv.tv_usec, file, func, line, ##args); }) ++#define dprintf_(tv, file, func, line, fmt, args...) ({ \ ++ struct timeval tv; \ ++ gettimeofday(&tv, NULL); \ ++ warnx("%ld.%lu %s:%s():%d: " fmt, \ ++ tv.tv_sec, tv.tv_usec, \ ++ file, func, line, ##args); \ ++ }) + #if defined(PESIGN_DEBUG) +-#define dprintf(fmt, args...) dprintf_(CAT(CAT(CAT(tv_,__COUNTER__),__LINE__),_), __FILE__, __func__, __LINE__, fmt, ##args) ++#define dprintf(fmt, args...) \ ++ dprintf_(CAT(CAT(CAT(tv_,__COUNTER__),__LINE__),_), \ ++ __FILE__, __func__, __LINE__ - 2, fmt, ##args) + #else +-#define dprintf(fmt, args...) ({ if (verbosity() > 1) dprintf_(CAT(CAT(CAT(tv_,__COUNTER__),__LINE__),_), __FILE__, __func__, __LINE__, fmt, ##args); 0; }) ++#define dprintf(fmt, args...) ({ \ ++ if (verbosity() > 1) \ ++ dprintf_(CAT(CAT(CAT(tv_,__COUNTER__),__LINE__),_), \ ++ __FILE__, __func__, __LINE__ - 3, \ ++ fmt, ##args); \ ++ 0; \ ++ }) + #endif + #define ingress() dprintf("ingress"); + #define egress() dprintf("egress"); +-- +2.29.2 + diff --git a/pesign.spec b/pesign.spec index 134921a..c52f883 100644 --- a/pesign.spec +++ b/pesign.spec @@ -2,8 +2,8 @@ Name: pesign Summary: Signing utility for UEFI binaries -Version: 0.112 -Release: 28%{?dist} +Version: 113 +Release: 13%{?dist} License: GPLv2 URL: https://github.com/vathpela/pesign @@ -28,6 +28,7 @@ BuildRequires: systemd-rpm-macros %endif Requires: nspr Requires: nss +Requires: nss-tools >= 3.53 Requires: nss-util Requires: popt Requires: rpm @@ -37,59 +38,60 @@ ExclusiveArch: %{ix86} x86_64 ia64 aarch64 %{arm} BuildRequires: rh-signing-tools >= 1.20-2 %endif -Source0: https://github.com/vathpela/pesign/releases/download/%{version}/pesign-%{version}.tar.bz2 +Source0: https://github.com/rhboot/pesign/releases/download/%{version}/pesign-%{version}.tar.bz2 Source1: certs.tar.xz Source2: pesign.py -Patch0001: 0001-cms-kill-generate_integer-it-doesn-t-build-on-i686-a.patch -Patch0002: 0002-Fix-command-line-parsing.patch -Patch0003: 0003-gcc-don-t-error-on-stuff-in-includes.patch -Patch0004: 0004-Fix-certficate-argument-name.patch -Patch0005: 0005-Fix-description-of-ascii-armor-option-in-manpage.patch -Patch0006: 0006-Make-ascii-work-since-we-documented-it.patch -Patch0007: 0007-Switch-pesign-client-to-also-accept-token-cert-macro.patch -Patch0008: 0008-pesigcheck-Verify-with-the-cert-as-an-object-signer.patch -Patch0009: 0009-pesigcheck-make-certfile-actually-work.patch -Patch0010: 0010-signerInfos-make-sure-err-is-always-initialized.patch -Patch0011: 0011-pesign-make-pesign-h-tell-you-the-file-name.patch -Patch0012: 0012-Add-coverity-build-scripts.patch -Patch0013: 0013-Document-implicit-fallthrough.patch -Patch0014: 0014-Actually-setfacl-each-directory-of-our-key-storage.patch -Patch0015: 0015-oid-add-SHIM_EKU_MODULE_SIGNING_ONLY-and-fix-our-arr.patch -Patch0016: 0016-efikeygen-add-modsign.patch -Patch0017: 0017-check_cert_db-try-even-harder-to-pick-a-reasonable-v.patch -Patch0018: 0018-show-which-db-we-re-checking.patch -Patch0019: 0019-more-about-the-time.patch -Patch0020: 0020-try-to-say-why-something-fails.patch -Patch0021: 0021-Fix-race-condition-in-SEC_GetPassword.patch -Patch0022: 0022-sysvinit-Create-the-socket-directory-at-runtime.patch -Patch0023: 0023-Better-authorization-scripts.-Again.patch -Patch0024: 0024-Make-the-daemon-also-try-to-give-better-errors-on-EP.patch -Patch0025: 0025-certdb-fix-PRTime-printfs-for-i686.patch -Patch0026: 0026-Clean-up-gcc-command-lines-a-little.patch -Patch0027: 0027-Make-pesign-users-groups-static-in-the-repo.patch -Patch0028: 0028-rpm-Make-the-client-signer-use-the-fedora-values-unl.patch -Patch0029: 0029-Make-macros.pesign-error-in-kojibuilder-if-we-don-t-.patch -Patch0030: 0030-efikeygen-Fix-the-build-with-nss-3.44.patch +Patch0001: 0001-efikeygen-Fix-the-build-with-nss-3.44.patch +Patch0002: 0002-pesigcheck-Fix-a-wrong-assignment.patch +Patch0003: 0003-Make-0.112-client-and-server-work-with-the-113-proto.patch +Patch0004: 0004-Rename-var-run-to-run.patch +Patch0005: 0005-Apparently-opensc-got-updated-and-the-token-name-cha.patch +Patch0006: 0006-Add-some-more-utility-functions-and-fix-a-typo-in-AL.patch +Patch0007: 0007-Add-hex-utilities.patch +Patch0008: 0008-Add-some-text-parsing-helpers.patch +Patch0009: 0009-libdpe-fix-some-minor-analyzer-discoveries.patch +Patch0010: 0010-libdpe-check-for-NULL-pe-at-more-places.patch +Patch0011: 0011-wincert-try-to-convince-the-gcc-analyzer-of-the-pain.patch +Patch0012: 0012-Fix-a-missing-malloc-return-value-check.patch +Patch0013: 0013-Fix-some-missed-OOM-error-path-fanalyzer-found.patch +Patch0014: 0014-Don-t-allow-or-require-module-or-kernel-with-ca.patch +Patch0015: 0015-Add-super-convenient-errno-guard-implementation.patch +Patch0016: 0016-Make-save_port_err-saner-to-read.patch +Patch0017: 0017-Make-for_each_cert-cl-iter-for-certificate-list-trav.patch +Patch0018: 0018-file_pe-make-most-of-our-input-and-output-checkers-b.patch +Patch0019: 0019-file_pe-user-err-errx-etc.patch +Patch0020: 0020-pesign_kmod-user-err-errx-etc.patch +Patch0021: 0021-share-input-output-checker-macros-between-pesign_kmo.patch +Patch0022: 0022-Make-verbose-work-in-efisiglist.patch +Patch0023: 0023-Make-verbose-and-debug-more-similar-across-tools.patch +Patch0024: 0024-Work-around-some-NSS-SECOID_AddEntry-bugs.patch +Patch0025: 0025-Rework-the-wildly-undocumented-NSS-password-file-goo.patch +Patch0026: 0026-Minor-whitespace-housekeeping.patch +Patch0027: 0027-libdpe-make-the-initial-read-buffer-always-big-enoug.patch +Patch0028: 0028-Fix-some-memory-leaks.patch +Patch0029: 0029-Improve-debug-output.patch +Patch0030: 0030-support-uri-token-names.patch +Patch0031: 0031-cms_common-add-some-more-ways-to-find-a-cert.patch +Patch0032: 0032-client-try-run-and-var-run-for-the-socket-path.patch +Patch0033: 0033-client-remove-an-extra-debug-print.patch +Patch0034: 0034-Move-most-of-macros.pesign-to-pesign-rpmbuild-helper.patch +Patch0035: 0035-pesign-authorize-shellcheck.patch +Patch0036: 0036-pesign-authorize-don-t-setfacl-etc-pki-pesign-foo.patch +Patch0037: 0037-kernel-building-hack.patch +Patch0038: 0038-Use-run-not-var-run.patch +Patch0039: 0039-efikeygen-return-error-on-AKID-encoding-failures.patch +Patch0040: 0040-Rename-some-cms-error-functions.patch +Patch0041: 0041-Make-cms_pe_common-bounds-check-errors-more-verbose.patch +Patch0042: 0042-Fix-our-error-message-line-numbers-hopefully.patch %description This package contains the pesign utility for signing UEFI binaries as well as other associated tools. %prep -%setup -q -T -b 0 +%autosetup -S git_am -n pesign-%{version} %setup -q -T -D -c -n pesign-%{version}/ -a 1 -git init -git config user.email "pesign-owner@fedoraproject.org" -git config user.name "Fedora Ninjas" -git add . -git commit -a -q -m "%{version} baseline." -git am %{patches} /dev/null || groupadd -r pesign getent passwd pesign >/dev/null || \ - useradd -r -g pesign -d /var/run/pesign -s /sbin/nologin \ + useradd -r -g pesign -d /run/pesign -s /sbin/nologin \ -c "Group for the pesign signing daemon" pesign exit 0 @@ -136,14 +138,21 @@ exit 0 %post %systemd_post pesign.service -#%%posttrans -#%%{_libexecdir}/pesign/pesign-authorize - %preun %systemd_preun pesign.service %postun %systemd_postun_with_restart pesign.service + +%posttrans +certutil -d %{_sysconfdir}/pki/pesign/ -X -L > /dev/null + +# this is disabled currently because it breaks the fedora kernel build root +# generation - because we don't currently have a good way of populating +# /etc/pesign/{users,groups} before the buildroot is installed, or +# populating them and re-running pesign-authorize afterwards but before the +# package build of e.g. kernel +#%%{_libexecdir}/pesign/pesign-authorize %endif %files @@ -162,14 +171,15 @@ exit 0 %dir %attr(0775,pesign,pesign) %{_sysconfdir}/pki/pesign-rh-test/ %config(noreplace) %attr(0664,pesign,pesign) %{_sysconfdir}/pki/pesign-rh-test/* %{_libexecdir}/pesign/pesign-authorize +%{_libexecdir}/pesign/pesign-rpmbuild-helper %config(noreplace)/%{_sysconfdir}/pesign/users %config(noreplace)/%{_sysconfdir}/pesign/groups %{_sysconfdir}/popt.d/pesign.popt %{macrosdir}/macros.pesign %{_mandir}/man*/* -%dir %attr(0770, pesign, pesign) %{_localstatedir}/run/%{name} -%ghost %attr(0660, -, -) %{_localstatedir}/run/%{name}/socket -%ghost %attr(0660, -, -) %{_localstatedir}/run/%{name}/pesign.pid +%dir %attr(0770, pesign, pesign) %{_rundir}/%{name} +%ghost %attr(0660, -, -) %{_rundir}/%{name}/socket +%ghost %attr(0660, -, -) %{_rundir}/%{name}/pesign.pid %if 0%{?rhel} >= 7 || 0%{?fedora} >= 17 %{_tmpfilesdir}/pesign.conf %{_unitdir}/pesign.service @@ -178,6 +188,25 @@ exit 0 %{python3_sitelib}/mockbuild/plugins/pesign.* %changelog +* Thu Feb 18 2021 Peter Jones - 113-13 +- Backport a bunch of stuff the upstream development tree. + +* Mon Aug 03 2020 Peter Jones - 113-12 +- Try to make kernel and fwupd both work at the same time. + +* Tue Jul 28 2020 Fedora Release Engineering - 113-11 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Thu Jul 16 2020 Peter Jones - 113-10 +- Synchronize with master + +* Mon Feb 24 2020 Peter Jones - 0.112-30 +- Make sure the patch for -29 is actually in the build in f32, and + synchronize with master. + +* Tue Feb 18 2020 Peter Jones - 0.112-29 +- Rebuild to match OpenSC's token name mangling change. + * Thu Jan 30 2020 Fedora Release Engineering - 0.112-28 - Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild diff --git a/sources b/sources index c2671ea..d0199f7 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -e377e0bc924287ee09356a239c5f51a8 certs.tar.xz -eae1d66e160be744ff310ad7592ae31e pesign-0.112.tar.bz2 +SHA512 (certs.tar.xz) = ddac535c786d1a23074534323c4ce89f907d4f82b19c5d3a9c814b145fbac1599cd2386cf20c28d22aee7d5c4db441f052bab9ee655de756117a0a0bc99b525f +SHA512 (pesign-113.tar.bz2) = 89c5e33bf6ac8f8dc4b65192e5fd4bf1fea285106d1de2a6ea02a8c5090f2ec5976b1d80c60e57f74fa56dc25b174a4dd5682292db44ab9aeab69ea992dfef36