sense the system to use gpg1 when installed
[myplc.git] / plc.d / gpg
index 23a1860..b947995 100755 (executable)
--- a/plc.d/gpg
+++ b/plc.d/gpg
@@ -1,35 +1,46 @@
 #!/bin/bash
 #
-# priority: 500
+# priority: 400
 #
 # Generate GPG keys
 #
 # Mark Huang <mlhuang@cs.princeton.edu>
 # Copyright (C) 2006 The Trustees of Princeton University
 #
-# $Id: gpg,v 1.3 2006/05/08 18:16:33 mlhuang Exp $
-#
 
 # Source function library and configuration
 . /etc/plc.d/functions
 . /etc/planetlab/plc_config
 
-case "$1" in
-    start)
-       if [ ! -f $PLC_ROOT_GPG_KEY_PUB -o ! -f $PLC_ROOT_GPG_KEY ] ; then
-           # Generate new GPG keyring
-           MESSAGE=$"Generating GPG keys"
-           dialog "$MESSAGE"
+### IMPORTANT NOTE 2020 - feb
+# when moving to fedora31 I run into this
+# https://fedoraproject.org/wiki/Changes/GnuPG2_as_default_GPG_implementation
+# which breaks the whole system for us because
+# * gnupg2 key generation function won't work as expected
+# * but with much wider impact, it turns out that private keys
+#   are now stored in a completely different way, and this will affect
+#   the way that particular location (typically /etc/planetlab/secring.gpg)
+#   is both
+#   * configured (as $PLC_ROOT_GPG_KEY) 
+#   * and passed around (see the PLC.GPG module and its gpg_sign() function)
+# 
+# so for now it looks MUCH EASIER to just get fedora to install gnupg1 
+# instead of (or on top of) gnupg, and use gpg1 when available
+# below is a leftover of the beginning of a code adaptation
+# to gnupg2, that should work fine (took some time to get right actually)
+# but this is currently unused 
 
-           mkdir -p $(dirname $PLC_ROOT_GPG_KEY_PUB)
-           mkdir -p $(dirname $PLC_ROOT_GPG_KEY)
+# for now we run only with gpg1, but on recent systems it means 
+# we need to invoke explicitly gpg1
+type gpg1 >& /dev/null && GPG=gpg1 || GPG=gpg
 
-           # Temporarily replace /dev/random with /dev/urandom to
-           # avoid running out of entropy.
-           rm -f /dev/random
-           mknod /dev/random c 1 9
-           gpg --homedir=/root --no-tty --yes \
-               --batch --gen-key <<EOF
+# this is more for when we support both
+# the default gpg command is version 1 up to f29, version 2 starts with f31 
+GPG_MAJOR_VERSION=$($GPG --version | grep '^gpg' | cut -d' ' -f 3 | cut -d. -f1)
+
+function generate_key_v1() {
+       local homedir=$1
+       $GPG --homedir=$homedir --no-permission-warning --batch --no-tty --yes --gen-key << EOF
 Key-Type: DSA
 Key-Length: 1024
 Subkey-Type: ELG-E
@@ -42,54 +53,147 @@ Expire-Date: 0
 %secring $PLC_ROOT_GPG_KEY
 %commit
 EOF
-           check
-           rm -f /dev/random
-           mknod /dev/random c 1 8
-           chmod 644 $PLC_ROOT_GPG_KEY_PUB
-           chmod 600 $PLC_ROOT_GPG_KEY
+}
+
+# this code should work allright as far as key generation, but as explained above
+# moving to gnupg2 requires a lot more work all over the place...
+function generate_key_v2() {
+       >&2 echo "it appears you have GPGv2 installed, myPLC is not ready for that !"
+       return 1
+
+       local homedir=$1
+       $GPG --homedir=$homedir --generate-key --batch << EOF
+Key-Type: DSA
+Key-Length: 1024
+Subkey-Type: ELG-E
+Subkey-Length: 1024
+Name-Real: $PLC_NAME Central
+Name-Comment: http://$PLC_WWW_HOST/
+Name-Email: $PLC_MAIL_SUPPORT_ADDRESS
+Expire-Date: 0
+%pubring $PLC_ROOT_GPG_KEY_PUB
+%no-protection
+%commit
+EOF
+}
 
-           result "$MESSAGE"
+# Be verbose
+set -x
+
+case "$1" in
+    start)
+       # Make temporary GPG home directory
+       homedir=$(mktemp -d /tmp/gpg.XXXXXX)
+
+       # in case a previous gpg invocation failed in some weird way
+       # and left behind a zero length gpg key (pub or priv).
+       if [ -f $PLC_ROOT_GPG_KEY_PUB -a ! -s $PLC_ROOT_GPG_KEY_PUB ] ; then
+           rm -f $PLC_ROOT_GPG_KEY_PUB 
+       fi
+       if [ -f $PLC_ROOT_GPG_KEY -a ! -s $PLC_ROOT_GPG_KEY ] ; then
+           rm -f $PLC_ROOT_GPG_KEY
+       fi
+
+       if [ ! -f $PLC_ROOT_GPG_KEY_PUB -o ! -f $PLC_ROOT_GPG_KEY ] ; then
+           # Generate new GPG keyring
+           MESSAGE=$"Generating GPG keys"
+           dialog "$MESSAGE"
+
+           mkdir -p $(dirname $PLC_ROOT_GPG_KEY_PUB)
+           mkdir -p $(dirname $PLC_ROOT_GPG_KEY)
+
+           # Temporarily replace /dev/random with /dev/urandom to
+           # avoid running out of entropy.
+           # (1 9 is /dev/urandom, 1 8 is /dev/random)
+           #
+           # a former version of this was rm'ing /dev/random and re-creating it afterwards
+           # however in 1.0.4 libvirt won't allow the use of mknod at all, so let's work around that
+           # by moving things around instead
+           #
+           # if we find this file it's probably that a previous run has failed..
+           [ -f /dev/random.preserve ] && { echo "Unexpected file /dev/random.preserve - exiting" ; exit 1; }
+           mv -f /dev/random /dev/random.preserve
+           # doesn't hurt to check 
+           check
+           ln -s /dev/urandom /dev/random
+           # again 
+           check
+               if [ "$GPG_MAJOR_VERSION" == 1 ]; then
+                       generate_key_v1 $homedir
+               else
+                       generate_key_v2 $homedir
+               fi
+           check
+           mv -f /dev/random.preserve /dev/random
+           check
        else
            # Update GPG UID
            MESSAGE=$"Updating GPG keys"
            dialog "$MESSAGE"
 
-           # Get the current GPG fingerprint
-           fingerprint=$PLC_MAIL_SUPPORT_ADDRESS
-           (
-               IFS=:
-               while read -a fields ; do
-                   if [ "${fields[0]}" = "pub" ] ; then
-                       fingerprint=${fields[4]}
-                       break
-                   fi
-               done < <(
-                   gpg --homedir=/root --no-tty --yes \
-                       --no-default-keyring --keyring $PLC_ROOT_GPG_KEY_PUB --secret-keyring $PLC_ROOT_GPG_KEY \
-                       --list-public-keys --with-colons
-                   check
-               )
+           # Get the current GPG fingerprint and comment
+           OLDIFS=$IFS
+           IFS=:
+           while read -a fields ; do
+               if [ "${fields[0]}" = "pub" ] ; then
+                   fingerprint=${fields[4]}
+                   break
+               fi
+           done < <(
+               $GPG --homedir=$homedir --no-permission-warning --batch --no-tty --yes \
+                   --no-default-keyring \
+                   --secret-keyring=$PLC_ROOT_GPG_KEY \
+                   --keyring=$PLC_ROOT_GPG_KEY_PUB \
+                   --list-public-keys --with-colons
+               check
            )
+           IFS=$OLDIFS
 
-           # GPG UIDs cannot and should not normally be changed, but
-           # since we do not certify signatures, we can effectively
-           # change it by adding a new one and deleting the old one.
-           gpg --homedir=/root --no-tty --yes \
-               --no-default-keyring --keyring $PLC_ROOT_GPG_KEY_PUB --secret-keyring $PLC_ROOT_GPG_KEY \
+           # Add a new UID if appropriate. GPG will detect and merge duplicates.
+           $GPG --homedir=$homedir --no-permission-warning --batch --no-tty --yes \
+               --no-default-keyring \
+               --secret-keyring=$PLC_ROOT_GPG_KEY \
+               --keyring=$PLC_ROOT_GPG_KEY_PUB \
                --command-fd 0 --status-fd 1 --edit-key $fingerprint <<EOF
 adduid
 $PLC_NAME Central
 $PLC_MAIL_SUPPORT_ADDRESS
 http://$PLC_WWW_HOST/
-uid 1
-deluid
-y
 save
 EOF
            check
+       fi
 
-           result "$MESSAGE"
+       # Install the key in the RPM database
+       mkdir -p /etc/pki/rpm-gpg
+       $GPG --homedir=$homedir --no-permission-warning --batch --no-tty --yes \
+           --no-default-keyring \
+           --secret-keyring=$PLC_ROOT_GPG_KEY \
+           --keyring=$PLC_ROOT_GPG_KEY_PUB \
+           --export --armor >"/etc/pki/rpm-gpg/RPM-GPG-KEY-$PLC_NAME"
+       check
+       if rpm -q gpg-pubkey ; then
+           rpm --allmatches -e gpg-pubkey
+           check
        fi
+       # starting with rpm-4.6, this fails when run a second time
+       # it would be complex to do this properly based on the filename, 
+       # as /etc/pki/rpm-gpg/ typically has many symlinks to the same file
+       # see also http://fedoranews.org/tchung/gpg/
+       # so just ignore the result
+       rpm --import /etc/pki/rpm-gpg/* || :
+       check
+
+       # Make GPG key readable by apache so that the API can sign peer requests
+       chown apache $PLC_ROOT_GPG_KEY
+       chmod 644 $PLC_ROOT_GPG_KEY_PUB
+       chmod 600 $PLC_ROOT_GPG_KEY
+       check
+
+       # Cleanup
+       rm -rf $homedir
+
+       result "$MESSAGE"
        ;;
 esac