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@gmail.com> --- scripts/makepkg.sh.in | 38 ++++++++++++++++++++-------- scripts/repo-add.sh.in | 63 +++++++++++++++++++++++++++++++++++------------- 2 files changed, 73 insertions(+), 28 deletions(-) diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in index 080e530..f6f9dfe 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. @@ -391,8 +394,8 @@ check_deps() { local ret=0 local pmout pmout=$(run_pacman -T "$@") || ret=$? - set -E - + set -E + if (( ret == 127 )); then #unresolved deps echo "$pmout" elif (( ret )); then @@ -1040,7 +1043,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 @@ -1067,7 +1070,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 @@ -1082,13 +1085,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 @@ -1269,7 +1283,7 @@ check_sanity() { local i for i in 'changelog' 'install'; do - local filelist=$(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE") + local filelist=$(sed -n "s/^[[:space:]]*$i=//p" "$BUILDFILE") local file for file in $filelist; do # evaluate any bash variables used @@ -1557,6 +1571,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 @@ -1592,7 +1607,7 @@ OPT_SHORT="AcCdefFghiLmop:rRsV" OPT_LONG="allsource,asroot,ignorearch,clean,cleancache,nodeps" OPT_LONG+=",noextract,force,forcever:,geninteg,help,holdver" OPT_LONG+=",install,log,nocolor,nobuild,pkg:,rmdeps,repackage,skipinteg" -OPT_LONG+=",source,syncdeps,version,config:" +OPT_LONG+=",source,syncdeps,version,config:,signwithkey" # Pacman Options OPT_LONG+=",noconfirm,noprogressbar" OPT_TEMP="$(parse_options $OPT_SHORT $OPT_LONG "$@" || echo 'PARSE_OPTIONS FAILED')" @@ -1635,6 +1650,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 4ee63d8..ac734aa 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|--signwithkey key]] [-v] <path-to-db> <package|delta> ...\n")" + printf "$(gettext "Usage: repo-remove [-q] [-s [-k|--signwithkey 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}" dblink="${REPO_DB_FILE%.tar.*}" ln -sf "$REPO_DB_FILE" "$dblink" 2>/dev/null || \ ln -f "$REPO_DB_FILE" "$dblink" 2>/dev/null || \ -- 1.7.1.1