[pacman-dev] [PATCH 6/6] Parameter to select key to sign

Denis A. Altoé Falqueto denisfalqueto at gmail.com
Wed Jul 7 13:43:57 EDT 2010


There is a possibility of another key being used, instead of
the user's default. For exemple, the pacman-keyring package
will be signed by a master key, because it needs to be trusted
explicitly by the user before the installation of that package.
So, the parameter --signwithkey will be used to supply an
id of a key that will be used to sign a database or package.

Signed-off-by: Denis A. Altoé Falqueto <denisfalqueto at gmail.com>
---
 scripts/makepkg.sh.in  |   32 ++++++++++++++++++------
 scripts/repo-add.sh.in |   63 +++++++++++++++++++++++++++++++++++-------------
 2 files changed, 70 insertions(+), 25 deletions(-)

diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in
index 223bf12..cb25312 100644
--- a/scripts/makepkg.sh.in
+++ b/scripts/makepkg.sh.in
@@ -28,7 +28,7 @@
 # makepkg uses quite a few external programs during its execution. You
 # need to have at least the following installed for makepkg to function:
 #   bsdtar (libarchive), bzip2, coreutils, fakeroot, find (findutils),
-#   gettext, grep, gzip, openssl, sed, tput (ncurses), xz
+#   gettext, grep, gzip, openssl, sed, tput (ncurses), xz, gpg

 # gettext initialization
 export TEXTDOMAIN='pacman'
@@ -43,6 +43,8 @@ BUILDSCRIPT='@BUILDSCRIPT@'
 startdir="$PWD"
 srcdir="$startdir/src"
 pkgdir="$startdir/pkg"
+GPG="gpg2"
+SIG_EXT=".sig"

 packaging_options=('strip' 'docs' 'libtool' 'emptydirs' 'zipman' 'purge')
 other_options=('ccache' 'distcc' 'makeflags' 'force')
@@ -74,6 +76,7 @@ BUILDFUNC=0
 PKGFUNC=0
 SPLITPKG=0
 PKGLIST=""
+SIGNKEY=""

 # Forces the pkgver of the current PKGBUILD. Used by the fakeroot call
 # when dealing with svn/cvs/etc PKGBUILDs.
@@ -1028,7 +1031,7 @@ create_package() {
 	local ret=0

 	[[ -f $pkg_file ]] && rm -f "$pkg_file"
-	[[ -f $pkg_file.sig ]] && rm -f "$pkg_file.sig"
+	[[ -f ${pkg_file}${SIG_EXT} ]] && rm -f "${pkg_file}${SIG_EXT}"

 	# when fileglobbing, we want * in an empty directory to expand to
 	# the null string rather than itself
@@ -1055,7 +1058,7 @@ create_package() {
 	if (( ! ret )) && [[ "$PKGDEST" != "${startdir}" ]]; then
 		ln -sf "${pkg_file}" "${pkg_file/$PKGDEST/$startdir}"
 		ret=$?
-		[[ -f $pkg_file.sig ]] && ln -sf "$pkg_file.sig"
"${pkg_file/$PKGDEST/$startdir}.sig"
+		[[ -f ${pkg_file}${SIG_EXT} ]] && ln -sf "${pkg_file}${SIG_EXT}"
"${pkg_file/$PKGDEST/$startdir}${SIG_EXT}"
 	fi

 	if (( ret )); then
@@ -1070,13 +1073,24 @@ create_signature() {
 	local ret=0
 	local filename="$1"
 	msg "$(gettext "Signing package...")"
-	if [ ! $(type -p "gpg") ]; then
-		error "$(gettext "Cannot find the gpg binary! Is gnupg installed?")"
+	if [[ ! $(type -p "${GPG}") ]]; then
+		error "$(gettext "Cannot find the ${GPG} binary! Is gnupg installed?")"
 		exit 1 # $E_MISSING_PROGRAM
 	fi
-	gpg --detach-sign --use-agent "$filename" || ret=$?
+
+	# Check if SIGNKEY is valid.
+	local SIGNWITHKEY=""
+	if [[ "${SIGNKEY}" ]]; then
+		if ! ${GPG} --list-key "${SIGNKEY}" 1>/dev/null 2>&1; then
+			error "$(gettext "The key ${SIGNKEY} doesn\'t exist.")"
+			exit 1
+		fi
+		SIGNWITHKEY="-u ${SIGNKEY}"
+	fi
+	# The signature will be generated directly in ascii-friendly format
+	${GPG} --detach-sign ${SIGNWITHKEY} "$filename" || ret=$?
 	if (( ! ret )); then
-		msg2 "$(gettext "Created signature file %s.")" "$filename.sig"
+		msg2 "$(gettext "Created signature file %s.")" "${filename}${SIG_EXT}"
 	else
 		warning "$(gettext "Failed to sign package file.")"
 	fi
@@ -1522,6 +1536,7 @@ usage() {
 	echo "$(gettext "  --pkg <list>     Only build listed packages from
a split package")"
 	echo "$(gettext "  --skipinteg      Do not fail when integrity
checks are missing")"
 	echo "$(gettext "  --source         Generate a source-only tarball
without downloaded sources")"
+	echo "$(gettext "  --signwithkey    Selects an specific key to use
for signing")"
 	echo
 	echo "$(gettext "These options can be passed to pacman:")"
 	echo
@@ -1557,7 +1572,7 @@ OPT_SHORT="AcCdefFghiLmop:rRsV"
 OPT_LONG="allsource,asroot,ignorearch,clean,cleancache,nodeps"
 OPT_LONG="$OPT_LONG,noextract,force,forcever:,geninteg,help,holdver"
 OPT_LONG="$OPT_LONG,install,log,nocolor,nobuild,pkg:,rmdeps,repackage,skipinteg"
-OPT_LONG="$OPT_LONG,source,syncdeps,version,config:"
+OPT_LONG="$OPT_LONG,source,syncdeps,version,config:,signwithkey"
 # Pacman Options
 OPT_LONG="$OPT_LONG,noconfirm,noprogressbar"
 OPT_TEMP="$(parse_options $OPT_SHORT $OPT_LONG "$@" || echo
'PARSE_OPTIONS FAILED')"
@@ -1600,6 +1615,7 @@ while true; do
 		--skipinteg)      SKIPINTEG=1 ;;
 		--source)         SOURCEONLY=1 ;;
 		-s|--syncdeps)    DEP_BIN=1 ;;
+		--signwithkey)    shift; SIGNKEY=$1 ;;

 		-h|--help)        usage; exit 0 ;; # E_OK
 		-V|--version)     version; exit 0 ;; # E_OK
diff --git a/scripts/repo-add.sh.in b/scripts/repo-add.sh.in
index 9b04be9..28966c8 100644
--- a/scripts/repo-add.sh.in
+++ b/scripts/repo-add.sh.in
@@ -26,6 +26,8 @@ export TEXTDOMAINDIR='@localedir@'

 myver='@PACKAGE_VERSION@'
 confdir='@sysconfdir@'
+GPG="gpg2"
+SIG_EXT=".sig"

 QUIET=0
 SIGN=0
@@ -62,8 +64,8 @@ error() {
 # print usage instructions
 usage() {
 	printf "repo-add, repo-remove (pacman) %s\n\n" "$myver"
-	printf "$(gettext "Usage: repo-add [-q] [-s] [-v] <path-to-db>
<package|delta> ...\n")"
-	printf "$(gettext "Usage: repo-remove [-q] <path-to-db>
<packagename|delta> ...\n\n")"
+	printf "$(gettext "Usage: repo-add [-q] [-s [-k key]] [-v]
<path-to-db> <package|delta> ...\n")"
+	printf "$(gettext "Usage: repo-remove [-q] [-s [-k key]]
<path-to-db> <packagename|delta> ...\n\n")"
 	printf "$(gettext "\
 repo-add will update a package database by reading a package file.\n\
 Multiple packages to add can be specified on the command line.\n\n")"
@@ -185,13 +187,24 @@ create_signature() {
 	local dbfile="$1"
 	local ret=0
 	msg "$(gettext "Signing database...")"
-	if [ ! $(type -p "gpg") ]; then
-		error "$(gettext "Cannot find the gpg binary! Is gnupg installed?")"
+	if [ ! $(type -p "${GPG}") ]; then
+		error "$(gettext "Cannot find the ${GPG} binary! Is gnupg installed?")"
 		exit 1 # $E_MISSING_PROGRAM
 	fi
-	gpg --detach-sign --use-agent "$dbfile" || ret=$?
+
+	# Check if SIGNKEY is valid.
+	local SIGNWITHKEY=""
+	if [[ "${SIGNKEY}" ]]; then
+		if ! "${GPG}" --list-key "${SIGNKEY}" 1>/dev/null 2>&1; then
+			error "$(gettext "The key ${SIGNKEY} doesnn't exist.")"
+			exit 1
+		fi
+		SIGNWITHKEY="-u ${SIGNKEY}"
+	fi
+	echo "${GPG} --detach-sign ${SIGNWITHKEY} $dbfile"
+	${GPG} --detach-sign ${SIGNWITHKEY} "$dbfile" || ret=$?
 	if (( ! ret )); then
-		msg2 "$(gettext "Created signature file %s.")" "$dbfile.sig"
+		msg2 "$(gettext "Created signature file %s.")" "${dbfile}${SIG_EXT}"
 	else
 		warning "$(gettext "Failed to sign package database.")"
 	fi
@@ -203,15 +216,15 @@ verify_signature() {
 	local dbfile="$1"
 	local ret=0
 	msg "$(gettext "Verifying database signature...")"
-	if [ ! $(type -p "gpg") ]; then
-		error "$(gettext "Cannot find the gpg binary! Is gnupg installed?")"
+	if [ ! $(type -p "${GPG}") ]; then
+		error "$(gettext "Cannot find the ${GPG} binary! Is gnupg installed?")"
 		exit 1 # $E_MISSING_PROGRAM
 	fi
-	if [[ ! -f $dbfile.sig ]]; then
+	if [[ ! -f ${dbfile}${SIG_EXT} ]]; then
 		warning "$(gettext "No existing signature found, skipping verification.")"
 		return
 	fi
-	gpg --verify "$dbfile.sig" || ret=$?
+	${GPG} --verify "${dbfile}${SIG_EXT}" || ret=$?
 	if (( ! ret )); then
 		msg2 "$(gettext "Database signature file verified.")"
 	else
@@ -298,9 +311,9 @@ db_write_entry()
 	echo -e "%MD5SUM%\n$md5sum\n" >>desc

 	# add base64'd PGP signature
-	if [[ -f $startdir/$pkgfile.sig ]]; then
+	if [[ -f $startdir/$pkgfile${SIG_EXT} ]]; then
 		echo -e "%PGPSIG%" >>desc
-		echo -e "$(openssl base64 -in "$startdir/$pkgfile.sig" | tr -d
'\n')\n" >>desc
+		echo -e "$(openssl enc -base64 -in "$startdir/$pkgfile${SIG_EXT}")\n" >>desc
 	fi

 	[[ -n $url ]] && echo -e "%URL%\n$url\n" >>desc
@@ -492,10 +505,24 @@ trap 'trap_exit "$(gettext "An unknown error has
occured. Exiting...")"' ERR

 success=0
 # parse arguments
-for arg in "$@"; do
+while [[ $# > 0 ]] ; do
+	arg="$1"
 	case "$arg" in
 		-q|--quiet) QUIET=1;;
-		-s|--sign) SIGN=1;;
+		-s|--sign)
+			SIGN=1
+			# The signature will be made, even if there are no operations
+			success=1
+			;;
+		-k|--signwithkey)
+			shift
+			SIGNKEY="$1"
+			# Check if key really exists
+			if ! ${GPG} --list-key ${SIGNKEY} 1> /dev/null 2>&1; then
+				error "$(gettext "Cannot find key $SIGNKEY.")"
+				exit 1
+			fi
+			;;
 		-v|--verify) VERIFY=1;;
 		*)
 			if [[ -z $REPO_DB_FILE ]]; then
@@ -510,6 +537,7 @@ for arg in "$@"; do
 			fi
 			;;
 	esac
+	shift
 done

 # if at least one operation was a success, re-zip database
@@ -529,18 +557,19 @@ if (( success )); then
 	cd "$tmpdir"
 	if [[ -n $(ls) ]]; then
 		bsdtar -c${TAR_OPT}f "$filename" *
-		create_signature "$filename"
 	else
 		# we have no packages remaining? zip up some emptyness
 		warning "$(gettext "No packages remain, creating empty database.")"
 		bsdtar -c${TAR_OPT}f "$filename" -T /dev/null
 	fi
+	# The signature must be dealt with in both cases, empty repo or not.
+	create_signature "$filename"
 	cd "$startdir"

 	[[ -f $REPO_DB_FILE ]] && mv -f "$REPO_DB_FILE" "${REPO_DB_FILE}.old"
-	[[ -f $REPO_DB_FILE.sig ]] && rm -f "$REPO_DB_FILE.sig"
+	[[ -f $REPO_DB_FILE${SIG_EXT} ]] && rm -f "$REPO_DB_FILE${SIG_EXT}"
 	[[ -f $tmpdir/$filename ]] && mv "$tmpdir/$filename" "$REPO_DB_FILE"
-	[[ -f $tmpdir/$filename.sig ]] && mv "$tmpdir/$filename.sig"
"$REPO_DB_FILE.sig"
+	[[ -f $tmpdir/$filename${SIG_EXT} ]] && mv
"$tmpdir/$filename${SIG_EXT}" "$REPO_DB_FILE${SIG_EXT}"
 	ln -sf "$REPO_DB_FILE" "${REPO_DB_FILE%.tar.*}"
 else
 	msg "$(gettext "No packages modified, nothing to do.")"
-- 
1.7.1


More information about the pacman-dev mailing list