a first move towards adopting gpgv2
[myplc.git] / plc.d / gpg
1 #!/bin/bash
2 #
3 # priority: 400
4 #
5 # Generate GPG keys
6 #
7 # Mark Huang <mlhuang@cs.princeton.edu>
8 # Copyright (C) 2006 The Trustees of Princeton University
9 #
10
11 # Source function library and configuration
12 . /etc/plc.d/functions
13 . /etc/planetlab/plc_config
14
15 ### IMPORTANT NOTE 2020 - feb
16 # when moving to fedora31 I run into this
17 # https://fedoraproject.org/wiki/Changes/GnuPG2_as_default_GPG_implementation
18 # which breaks the whole system for us because
19 # * gnupg2 key generation function won't work as expected
20 # * but with much wider impact, it turns out that private keys
21 #   are now stored in a completely different way, and this will affect
22 #   the way that particular location (typically /etc/planetlab/secring.gpg)
23 #   is both
24 #   * configured (as $PLC_ROOT_GPG_KEY) 
25 #   * and passed around (see the PLC.GPG module and its gpg_sign() function)
26
27 # so for now it looks MUCH EASIER to just get fedora to install gnupg1 
28 # instead of (or on top of) gnupg, and use gpg1 when available
29 # below is a leftover of the beginning of a code adaptation
30 # to gnupg2, that should work fine (took some time to get right actually)
31 # but this is currently unused 
32
33 # the default gpg command is version 1 up to f29, version 2 starts with f31 
34 # that could be more for when we support both
35 GPG_MAJOR_VERSION=$(gpg --version | grep '^gpg' | cut -d' ' -f 3 | cut -d. -f1)
36
37 function generate_key_v1() {
38         local homedir=$1
39         gpg --homedir=$homedir --no-permission-warning --batch --no-tty --yes --gen-key << EOF
40 Key-Type: DSA
41 Key-Length: 1024
42 Subkey-Type: ELG-E
43 Subkey-Length: 1024
44 Name-Real: $PLC_NAME Central
45 Name-Comment: http://$PLC_WWW_HOST/
46 Name-Email: $PLC_MAIL_SUPPORT_ADDRESS
47 Expire-Date: 0
48 %pubring $PLC_ROOT_GPG_KEY_PUB
49 %secring $PLC_ROOT_GPG_KEY
50 %commit
51 EOF
52 }
53
54 # this code should work allright as far as key generation, but as explained above
55 # moving to gnupg2 requires a lot more work all over the place...
56 function generate_key_v2() {
57         >&2 echo "it appears you have GPGv2 installed, myPLC is not ready for that !"
58         return 1
59
60         local homedir=$1
61         gpg --homedir=$homedir --generate-key --batch << EOF
62 Key-Type: DSA
63 Key-Length: 1024
64 Subkey-Type: ELG-E
65 Subkey-Length: 1024
66 Name-Real: $PLC_NAME Central
67 Name-Comment: http://$PLC_WWW_HOST/
68 Name-Email: $PLC_MAIL_SUPPORT_ADDRESS
69 Expire-Date: 0
70 %pubring $PLC_ROOT_GPG_KEY_PUB
71 %no-protection
72 %commit
73 EOF
74 }
75
76 # Be verbose
77 set -x
78
79 case "$1" in
80     start)
81         # Make temporary GPG home directory
82         homedir=$(mktemp -d /tmp/gpg.XXXXXX)
83
84         # in case a previous gpg invocation failed in some weird way
85         # and left behind a zero length gpg key (pub or priv).
86         if [ -f $PLC_ROOT_GPG_KEY_PUB -a ! -s $PLC_ROOT_GPG_KEY_PUB ] ; then
87             rm -f $PLC_ROOT_GPG_KEY_PUB 
88         fi
89         if [ -f $PLC_ROOT_GPG_KEY -a ! -s $PLC_ROOT_GPG_KEY ] ; then
90             rm -f $PLC_ROOT_GPG_KEY
91         fi
92
93         if [ ! -f $PLC_ROOT_GPG_KEY_PUB -o ! -f $PLC_ROOT_GPG_KEY ] ; then
94             # Generate new GPG keyring
95             MESSAGE=$"Generating GPG keys"
96             dialog "$MESSAGE"
97
98             mkdir -p $(dirname $PLC_ROOT_GPG_KEY_PUB)
99             mkdir -p $(dirname $PLC_ROOT_GPG_KEY)
100
101             # Temporarily replace /dev/random with /dev/urandom to
102             # avoid running out of entropy.
103             # (1 9 is /dev/urandom, 1 8 is /dev/random)
104             #
105             # a former version of this was rm'ing /dev/random and re-creating it afterwards
106             # however in 1.0.4 libvirt won't allow the use of mknod at all, so let's work around that
107             # by moving things around instead
108             #
109             # if we find this file it's probably that a previous run has failed..
110             [ -f /dev/random.preserve ] && { echo "Unexpected file /dev/random.preserve - exiting" ; exit 1; }
111             mv -f /dev/random /dev/random.preserve
112             # doesn't hurt to check 
113             check
114             ln -s /dev/urandom /dev/random
115             # again 
116             check
117                 if [ "$GPG_MAJOR_VERSION" == 1 ]; then
118                         generate_key_v1 $homedir
119                 else
120                         generate_key_v2 $homedir
121                 fi
122             check
123             mv -f /dev/random.preserve /dev/random
124             check
125         else
126             # Update GPG UID
127             MESSAGE=$"Updating GPG keys"
128             dialog "$MESSAGE"
129
130             # Get the current GPG fingerprint and comment
131             OLDIFS=$IFS
132             IFS=:
133             while read -a fields ; do
134                 if [ "${fields[0]}" = "pub" ] ; then
135                     fingerprint=${fields[4]}
136                     break
137                 fi
138             done < <(
139                 gpg --homedir=$homedir --no-permission-warning --batch --no-tty --yes \
140                     --no-default-keyring \
141                     --secret-keyring=$PLC_ROOT_GPG_KEY \
142                     --keyring=$PLC_ROOT_GPG_KEY_PUB \
143                     --list-public-keys --with-colons
144                 check
145             )
146             IFS=$OLDIFS
147
148             # Add a new UID if appropriate. GPG will detect and merge duplicates.
149             gpg --homedir=$homedir --no-permission-warning --batch --no-tty --yes \
150                 --no-default-keyring \
151                 --secret-keyring=$PLC_ROOT_GPG_KEY \
152                 --keyring=$PLC_ROOT_GPG_KEY_PUB \
153                 --command-fd 0 --status-fd 1 --edit-key $fingerprint <<EOF
154 adduid
155 $PLC_NAME Central
156 $PLC_MAIL_SUPPORT_ADDRESS
157 http://$PLC_WWW_HOST/
158 save
159 EOF
160             check
161         fi
162
163         # Install the key in the RPM database
164         mkdir -p /etc/pki/rpm-gpg
165         gpg --homedir=$homedir --no-permission-warning --batch --no-tty --yes \
166             --no-default-keyring \
167             --secret-keyring=$PLC_ROOT_GPG_KEY \
168             --keyring=$PLC_ROOT_GPG_KEY_PUB \
169             --export --armor >"/etc/pki/rpm-gpg/RPM-GPG-KEY-$PLC_NAME"
170         check
171         if rpm -q gpg-pubkey ; then
172             rpm --allmatches -e gpg-pubkey
173             check
174         fi
175         # starting with rpm-4.6, this fails when run a second time
176         # it would be complex to do this properly based on the filename, 
177         # as /etc/pki/rpm-gpg/ typically has many symlinks to the same file
178         # see also http://fedoranews.org/tchung/gpg/
179         # so just ignore the result
180         rpm --import /etc/pki/rpm-gpg/* || :
181         check
182
183         # Make GPG key readable by apache so that the API can sign peer requests
184         chown apache $PLC_ROOT_GPG_KEY
185         chmod 644 $PLC_ROOT_GPG_KEY_PUB
186         chmod 600 $PLC_ROOT_GPG_KEY
187         check
188
189         # Cleanup
190         rm -rf $homedir
191
192         result "$MESSAGE"
193         ;;
194 esac
195
196 exit $ERRORS