From 6c16b978fd33f3611e9f7aaf4f9c44bce1679485 Mon Sep 17 00:00:00 2001
From: Peter Jones <pjones@redhat.com>
Date: Mon, 6 Jul 2020 13:54:35 -0400
Subject: [PATCH] Move most of macros.pesign to pesign-rpmbuild-helper
Signed-off-by: Peter Jones <pjones@redhat.com>
---
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 74327ba13f3..a7ca89159c6 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)
@@ -49,6 +49,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 \
@@ -94,6 +99,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..2e984b4eeb3 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 <input ca cert filename> # 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.26.2