/mandos/release

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/release

« back to all changes in this revision

Viewing changes to mandos-keygen

  • Committer: Teddy Hogeborn
  • Date: 2024-09-09 04:24:39 UTC
  • mto: This revision was merged to the branch mainline in revision 410.
  • Revision ID: teddy@recompile.se-20240909042439-j85mr20uli2hnyis
Eliminate compiler warnings

Many programs use nested functions, which now result in a linker
warning about executable stack.  Hide this warning.  Also, rewrite a
loop in the plymouth plugin to avoid warning about signed overflow.
This change also makes the plugin pick the alphabetically first
process entry instead of the last, in case many plymouth processes are
found (which should be unlikely).

* Makefile (plugin-runner, dracut-module/password-agent,
  plugins.d/password-prompt, plugins.d/mandos-client,
  plugins.d/plymouth): New target; set LDFLAGS to add "-Xlinker
  --no-warn-execstack".
* plugins.d/plymouth.c (get_pid): When no pid files are found, and we
  are looking through the process list, go though it from the start
  instead of from the end, i.e. in normal alphabetical order and not
  in reverse order.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/bin/sh -e
2
2
3
 
# Mandos key generator - create a new OpenPGP key for a Mandos client
4
 
5
 
# Copyright © 2008-2017 Teddy Hogeborn
6
 
# Copyright © 2008-2017 Björn Påhlsson
7
 
8
 
# This program is free software: you can redistribute it and/or modify
9
 
# it under the terms of the GNU General Public License as published by
 
3
# Mandos key generator - create new keys for a Mandos client
 
4
 
5
# Copyright © 2008-2019 Teddy Hogeborn
 
6
# Copyright © 2008-2019 Björn Påhlsson
 
7
 
8
# This file is part of Mandos.
 
9
#
 
10
# Mandos is free software: you can redistribute it and/or modify it
 
11
# under the terms of the GNU General Public License as published by
10
12
# the Free Software Foundation, either version 3 of the License, or
11
13
# (at your option) any later version.
12
14
#
13
 
#     This program is distributed in the hope that it will be useful,
14
 
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
#     Mandos is distributed in the hope that it will be useful, but
 
16
#     WITHOUT ANY WARRANTY; without even the implied warranty of
15
17
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
18
#     GNU General Public License for more details.
17
19
18
20
# You should have received a copy of the GNU General Public License
19
 
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
21
# along with Mandos.  If not, see <http://www.gnu.org/licenses/>.
20
22
21
23
# Contact the authors at <mandos@recompile.se>.
22
24
23
25
 
24
 
VERSION="1.7.14"
 
26
VERSION="1.8.16"
25
27
 
26
28
KEYDIR="/etc/keys/mandos"
27
29
KEYTYPE=RSA
32
34
KEYEMAIL=""
33
35
KEYCOMMENT=""
34
36
KEYEXPIRE=0
 
37
TLS_KEYTYPE=ed25519
35
38
FORCE=no
36
39
SSH=yes
37
40
KEYCOMMENT_ORIG="$KEYCOMMENT"
42
45
fi
43
46
 
44
47
# Parse options
45
 
TEMP=`getopt --options vhpF:d:t:l:s:L:n:e:c:x:fS \
46
 
    --longoptions version,help,password,passfile:,dir:,type:,length:,subtype:,sublength:,name:,email:,comment:,expire:,force,no-ssh \
 
48
TEMP=`getopt --options vhpF:d:t:l:s:L:n:e:c:x:T:fS \
 
49
    --longoptions version,help,password,passfile:,dir:,type:,length:,subtype:,sublength:,name:,email:,comment:,expire:,tls-keytype:,force,no-ssh \
47
50
    --name "$0" -- "$@"`
48
51
 
49
52
help(){
61
64
  -v, --version         Show program's version number and exit
62
65
  -h, --help            Show this help message and exit
63
66
  -d DIR, --dir DIR     Target directory for key files
64
 
  -t TYPE, --type TYPE  Key type.  Default is RSA.
 
67
  -t TYPE, --type TYPE  OpenPGP key type.  Default is RSA.
65
68
  -l BITS, --length BITS
66
 
                        Key length in bits.  Default is 4096.
 
69
                        OpenPGP key length in bits.  Default is 4096.
67
70
  -s TYPE, --subtype TYPE
68
 
                        Subkey type.  Default is RSA.
 
71
                        OpenPGP subkey type.  Default is RSA.
69
72
  -L BITS, --sublength BITS
70
 
                        Subkey length in bits.  Default is 4096.
 
73
                        OpenPGP subkey length in bits.  Default 4096.
71
74
  -n NAME, --name NAME  Name of key.  Default is the FQDN.
72
75
  -e ADDRESS, --email ADDRESS
73
 
                        Email address of key.  Default is empty.
 
76
                        Email address of OpenPGP key.  Default empty.
74
77
  -c TEXT, --comment TEXT
75
 
                        Comment field for key.  The default is empty.
 
78
                        Comment field for OpenPGP key.  Default empty.
76
79
  -x TIME, --expire TIME
77
 
                        Key expire time.  Default is no expiration.
 
80
                        OpenPGP key expire time.  Default is none.
78
81
                        See gpg(1) for syntax.
 
82
  -T TYPE, --tls-keytype TYPE
 
83
                        TLS key type.  Default is ed25519.
79
84
  -f, --force           Force overwriting old key files.
80
85
 
81
86
Password creation options:
104
109
        -e|--email) KEYEMAIL="$2"; shift 2;;
105
110
        -c|--comment) KEYCOMMENT="$2"; shift 2;;
106
111
        -x|--expire) KEYEXPIRE="$2"; shift 2;;
 
112
        -T|--tls-keytype) TLS_KEYTYPE="$2"; shift 2;;
107
113
        -f|--force) FORCE=yes; shift;;
108
114
        -S|--no-ssh) SSH=no; shift;;
109
115
        -v|--version) echo "$0 $VERSION"; exit;;
119
125
 
120
126
SECKEYFILE="$KEYDIR/seckey.txt"
121
127
PUBKEYFILE="$KEYDIR/pubkey.txt"
 
128
TLS_PRIVKEYFILE="$KEYDIR/tls-privkey.pem"
 
129
TLS_PUBKEYFILE="$KEYDIR/tls-pubkey.pem"
122
130
 
123
131
# Check for some invalid values
124
132
if [ ! -d "$KEYDIR" ]; then
139
147
        echo "Empty key type" >&2
140
148
        exit 1
141
149
    fi
142
 
    
 
150
 
143
151
    if [ -z "$KEYNAME" ]; then
144
152
        echo "Empty key name" >&2
145
153
        exit 1
146
154
    fi
147
 
    
 
155
 
148
156
    if [ -z "$KEYLENGTH" ] || [ "$KEYLENGTH" -lt 512 ]; then
149
157
        echo "Invalid key length" >&2
150
158
        exit 1
151
159
    fi
152
 
    
 
160
 
153
161
    if [ -z "$KEYEXPIRE" ]; then
154
162
        echo "Empty key expiration" >&2
155
163
        exit 1
156
164
    fi
157
 
    
 
165
 
158
166
    # Make FORCE be 0 or 1
159
167
    case "$FORCE" in
160
168
        [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]) FORCE=1;;
161
169
        [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|*) FORCE=0;;
162
170
    esac
163
 
    
164
 
    if [ \( -e "$SECKEYFILE" -o -e "$PUBKEYFILE" \) \
165
 
        -a "$FORCE" -eq 0 ]; then
 
171
 
 
172
    if { [ -e "$SECKEYFILE" ] || [ -e "$PUBKEYFILE" ] \
 
173
             || [ -e "$TLS_PRIVKEYFILE" ] \
 
174
             || [ -e "$TLS_PUBKEYFILE" ]; } \
 
175
        && [ "$FORCE" -eq 0 ]; then
166
176
        echo "Refusing to overwrite old key files; use --force" >&2
167
177
        exit 1
168
178
    fi
169
 
    
 
179
 
170
180
    # Set lines for GnuPG batch file
171
181
    if [ -n "$KEYCOMMENT" ]; then
172
182
        KEYCOMMENTLINE="Name-Comment: $KEYCOMMENT"
174
184
    if [ -n "$KEYEMAIL" ]; then
175
185
        KEYEMAILLINE="Name-Email: $KEYEMAIL"
176
186
    fi
177
 
    
 
187
 
178
188
    # Create temporary gpg batch file
179
189
    BATCHFILE="`mktemp -t mandos-keygen-batch.XXXXXXXXXX`"
 
190
    TLS_PRIVKEYTMP="`mktemp -t mandos-keygen-privkey.XXXXXXXXXX`"
180
191
fi
181
192
 
182
193
if [ "$mode" = password ]; then
191
202
trap "
192
203
set +e; \
193
204
test -n \"$SECFILE\" && shred --remove \"$SECFILE\"; \
 
205
test -n \"$TLS_PRIVKEYTMP\" && shred --remove \"$TLS_PRIVKEYTMP\"; \
194
206
shred --remove \"$RINGDIR\"/sec* 2>/dev/null;
195
207
test -n \"$BATCHFILE\" && rm --force \"$BATCHFILE\"; \
196
208
rm --recursive --force \"$RINGDIR\";
221
233
        %no-protection
222
234
        %commit
223
235
        EOF
224
 
    
 
236
 
225
237
    if tty --quiet; then
226
238
        cat <<-EOF
227
239
        Note: Due to entropy requirements, key generation could take
231
243
        echo -n "Started: "
232
244
        date
233
245
    fi
234
 
    
 
246
 
 
247
    # Generate TLS private key
 
248
    if certtool --generate-privkey --password='' \
 
249
                --outfile "$TLS_PRIVKEYTMP" --sec-param ultra \
 
250
                --key-type="$TLS_KEYTYPE" --pkcs8 --no-text 2>/dev/null; then
 
251
        
 
252
        # Backup any old key files
 
253
        if cp --backup=numbered --force "$TLS_PRIVKEYFILE" "$TLS_PRIVKEYFILE" \
 
254
              2>/dev/null; then
 
255
            shred --remove "$TLS_PRIVKEYFILE" 2>/dev/null || :
 
256
        fi
 
257
        if cp --backup=numbered --force "$TLS_PUBKEYFILE" "$TLS_PUBKEYFILE" \
 
258
              2>/dev/null; then
 
259
            rm --force "$TLS_PUBKEYFILE"
 
260
        fi
 
261
        cp --archive "$TLS_PRIVKEYTMP" "$TLS_PRIVKEYFILE"
 
262
        shred --remove "$TLS_PRIVKEYTMP" 2>/dev/null || :
 
263
 
 
264
        ## TLS public key
 
265
 
 
266
        # First try certtool from GnuTLS
 
267
        if ! certtool --password='' --load-privkey="$TLS_PRIVKEYFILE" \
 
268
             --outfile="$TLS_PUBKEYFILE" --pubkey-info --no-text \
 
269
             2>/dev/null; then
 
270
            # Otherwise try OpenSSL
 
271
            if ! openssl pkey -in "$TLS_PRIVKEYFILE" \
 
272
                 -out "$TLS_PUBKEYFILE" -pubout; then
 
273
                rm --force "$TLS_PUBKEYFILE"
 
274
                # None of the commands succeded; give up
 
275
                return 1
 
276
            fi
 
277
        fi
 
278
    fi
 
279
 
235
280
    # Make sure trustdb.gpg exists;
236
281
    # this is a workaround for Debian bug #737128
237
282
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
242
287
        --homedir "$RINGDIR" --trust-model always \
243
288
        --gen-key "$BATCHFILE"
244
289
    rm --force "$BATCHFILE"
245
 
    
 
290
 
246
291
    if tty --quiet; then
247
292
        echo -n "Finished: "
248
293
        date
249
294
    fi
250
 
    
 
295
 
251
296
    # Backup any old key files
252
297
    if cp --backup=numbered --force "$SECKEYFILE" "$SECKEYFILE" \
253
298
        2>/dev/null; then
254
 
        shred --remove "$SECKEYFILE"
 
299
        shred --remove "$SECKEYFILE" 2>/dev/null || :
255
300
    fi
256
301
    if cp --backup=numbered --force "$PUBKEYFILE" "$PUBKEYFILE" \
257
302
        2>/dev/null; then
258
303
        rm --force "$PUBKEYFILE"
259
304
    fi
260
 
    
 
305
 
261
306
    FILECOMMENT="Mandos client key for $KEYNAME"
262
307
    if [ "$KEYCOMMENT" != "$KEYCOMMENT_ORIG" ]; then
263
308
        FILECOMMENT="$FILECOMMENT ($KEYCOMMENT)"
264
309
    fi
265
 
    
 
310
 
266
311
    if [ -n "$KEYEMAIL" ]; then
267
312
        FILECOMMENT="$FILECOMMENT <$KEYEMAIL>"
268
313
    fi
269
 
    
 
314
 
270
315
    # Export key from key rings to key files
271
316
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
272
317
        --homedir "$RINGDIR" --armor --export-options export-minimal \
278
323
fi
279
324
 
280
325
if [ "$mode" = password ]; then
281
 
    
 
326
 
282
327
    # Make SSH be 0 or 1
283
328
    case "$SSH" in
284
329
        [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]) SSH=1;;
285
330
        [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|*) SSH=0;;
286
331
    esac
287
 
    
 
332
 
288
333
    if [ $SSH -eq 1 ]; then
289
334
        for ssh_keytype in ecdsa-sha2-nistp256 ed25519 rsa; do
290
335
            set +e
291
336
            ssh_fingerprint="`ssh-keyscan -t $ssh_keytype localhost 2>/dev/null`"
 
337
            err=$?
292
338
            set -e
293
 
            if [ $? -ne 0 ]; then
 
339
            if [ $err -ne 0 ]; then
294
340
                ssh_fingerprint=""
295
341
                continue
296
342
            fi
300
346
            fi
301
347
        done
302
348
    fi
303
 
    
 
349
 
304
350
    # Import key into temporary key rings
305
351
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
306
352
        --homedir "$RINGDIR" --trust-model always --armor \
308
354
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
309
355
        --homedir "$RINGDIR" --trust-model always --armor \
310
356
        --import "$PUBKEYFILE"
311
 
    
 
357
 
312
358
    # Get fingerprint of key
313
359
    FINGERPRINT="`gpg --quiet --batch --no-tty --no-options \
314
360
        --enable-dsa2 --homedir "$RINGDIR" --trust-model always \
315
361
        --fingerprint --with-colons \
316
362
        | sed --quiet \
317
363
        --expression='/^fpr:/{s/^fpr:.*:\\([0-9A-Z]*\\):\$/\\1/p;q}'`"
318
 
    
 
364
 
319
365
    test -n "$FINGERPRINT"
320
 
    
 
366
 
 
367
    if [ -r "$TLS_PUBKEYFILE" ]; then
 
368
       KEY_ID="$(certtool --key-id --hash=sha256 \
 
369
                       --infile="$TLS_PUBKEYFILE" 2>/dev/null || :)"
 
370
 
 
371
       if [ -z "$KEY_ID" ]; then
 
372
           KEY_ID=$(openssl pkey -pubin -in "$TLS_PUBKEYFILE" \
 
373
                            -outform der \
 
374
                        | openssl sha256 \
 
375
                        | sed --expression='s/^.*[^[:xdigit:]]//')
 
376
       fi
 
377
       test -n "$KEY_ID"
 
378
    fi
 
379
 
321
380
    FILECOMMENT="Encrypted password for a Mandos client"
322
 
    
 
381
 
323
382
    while [ ! -s "$SECFILE" ]; do
324
383
        if [ -n "$PASSFILE" ]; then
325
 
            cat "$PASSFILE"
 
384
            cat -- "$PASSFILE"
326
385
        else
327
386
            tty --quiet && stty -echo
328
387
            echo -n "Enter passphrase: " >/dev/tty
338
397
                echo "Passphrase mismatch" >&2
339
398
                touch "$RINGDIR"/mismatch
340
399
            else
341
 
                echo -n "$first"
 
400
                printf "%s" "$first"
342
401
            fi
343
402
        fi | gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
344
403
            --homedir "$RINGDIR" --trust-model always --armor \
353
412
            fi
354
413
        fi
355
414
    done
356
 
    
 
415
 
357
416
    cat <<-EOF
358
417
        [$KEYNAME]
359
418
        host = $KEYNAME
 
419
        EOF
 
420
    if [ -n "$KEY_ID" ]; then
 
421
        echo "key_id = $KEY_ID"
 
422
    fi
 
423
    cat <<-EOF
360
424
        fingerprint = $FINGERPRINT
361
425
        secret =
362
426
        EOF
380
444
set +e
381
445
# Remove the password file, if any
382
446
if [ -n "$SECFILE" ]; then
383
 
    shred --remove "$SECFILE"
 
447
    shred --remove "$SECFILE" 2>/dev/null
384
448
fi
385
449
# Remove the key rings
386
450
shred --remove "$RINGDIR"/sec* 2>/dev/null