/mandos/trunk

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

« back to all changes in this revision

Viewing changes to mandos-keygen

  • Committer: Teddy Hogeborn
  • Date: 2008-08-29 05:53:59 UTC
  • Revision ID: teddy@fukt.bsnet.se-20080829055359-wkdasnyxtylmnxus
* mandos.xml (EXAMPLE): Replaced all occurences of command name with
                        "&COMMANDNAME;".

* plugins.d/password-prompt.c (main): Improved some documentation
                                      strings.  Do perror() of
                                      tcgetattr() fails.  Add debug
                                      output if interrupted by signal.
                                      Loop over write() instead of
                                      using fwrite() when outputting
                                      password.  Add debug output if
                                      getline() returns 0, unless it
                                      was caused by a signal.  Add
                                      exit status code to debug
                                      output.

* plugins.d/password-prompt.xml: Changed all single quotes to double
                                 quotes for consistency.  Removed
                                 <?xml-stylesheet>.
  (ENTITY TIMESTAMP): New.  Automatically updated by Emacs time-stamp
                      by using Emacs local variables.
  (/refentry/refentryinfo/title): Changed to "Mandos Manual".
  (/refentry/refentryinfo/productname): Changed to "Mandos".
  (/refentry/refentryinfo/date): New; set to "&TIMESTAMP;".
  (/refentry/refentryinfo/copyright): Split copyright holders.
  (/refentry/refnamediv/refpurpose): Improved wording.
  (SYNOPSIS): Fix to use correct markup.  Add short options.
  (DESCRIPTION, OPTIONS): Improved wording.
  (OPTIONS): Improved wording.  Use more correct markup.  Document
             short options.
  (EXIT STATUS): Add text.
  (ENVIRONMENT): Document use of "cryptsource" and "crypttarget".
  (FILES): REMOVED.
  (BUGS): Add text.
  (EXAMPLE): Added some examples.
  (SECURITY): Added text.
  (SEE ALSO): Remove reference to mandos(8).  Add reference to
              crypttab(5).

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
3
3
# Mandos key generator - create a new OpenPGP key for a Mandos client
4
4
5
 
# Copyright © 2008,2009 Teddy Hogeborn
6
 
# Copyright © 2008,2009 Björn Påhlsson
 
5
# Copyright © 2007-2008 Teddy Hogeborn & Björn Påhlsson
7
6
8
7
# This program is free software: you can redistribute it and/or modify
9
8
# it under the terms of the GNU General Public License as published by
21
20
# Contact the authors at <mandos@fukt.bsnet.se>.
22
21
23
22
 
24
 
VERSION="1.0.14"
 
23
VERSION="1.0"
25
24
 
26
 
KEYDIR="/etc/keys/mandos"
 
25
KEYDIR="/etc/mandos"
27
26
KEYTYPE=DSA
28
27
KEYLENGTH=2048
29
28
SUBKEYTYPE=ELG-E
30
29
SUBKEYLENGTH=2048
31
 
KEYNAME="`hostname --fqdn 2>/dev/null || hostname`"
 
30
KEYNAME="`hostname --fqdn`"
32
31
KEYEMAIL=""
33
32
KEYCOMMENT="Mandos client key"
34
33
KEYEXPIRE=0
36
35
KEYCOMMENT_ORIG="$KEYCOMMENT"
37
36
mode=keygen
38
37
 
39
 
if [ ! -d "$KEYDIR" ]; then
40
 
    KEYDIR="/etc/mandos/keys"
41
 
fi
42
 
 
43
38
# Parse options
44
 
TEMP=`getopt --options vhpF:d:t:l:s:L:n:e:c:x:f \
45
 
    --longoptions version,help,password,passfile:,dir:,type:,length:,subtype:,sublength:,name:,email:,comment:,expire:,force \
 
39
TEMP=`getopt --options vhd:t:l:n:e:c:x:f \
 
40
    --longoptions version,help,password,dir:,type:,length:,subtype:,sublength:,name:,email:,comment:,expire:,force \
46
41
    --name "$0" -- "$@"`
47
42
 
48
43
help(){
54
49
       $basename [ OPTIONS ]
55
50
   Encrypted password creation:
56
51
       $basename { -p | --password } [ --name NAME ] [ --dir DIR]
57
 
       $basename { -F | --passfile } FILE [ --name NAME ] [ --dir DIR]
58
52
 
59
53
Key creation options:
60
54
  -v, --version         Show program's version number and exit
70
64
  -n NAME, --name NAME  Name of key.  Default is the FQDN.
71
65
  -e ADDRESS, --email ADDRESS
72
66
                        Email address of key.  Default is empty.
73
 
  -c TEXT, --comment TEXT
 
67
  -c COMMENT, --comment COMMENT
74
68
                        Comment field for key.  The default value is
75
69
                        "Mandos client key".
76
70
  -x TIME, --expire TIME
77
71
                        Key expire time.  Default is no expiration.
78
72
                        See gpg(1) for syntax.
79
 
  -f, --force           Force overwriting old key files.
 
73
  -f, --force           Force overwriting old keys.
80
74
 
81
75
Password creation options:
82
 
  -p, --password        Create an encrypted password using the key in
83
 
                        the key directory.  All options other than
84
 
                        --dir and --name are ignored.
85
 
  -F FILE, --passfile FILE
86
 
                        Encrypt a password from FILE using the key in
87
 
                        the key directory.  All options other than
88
 
                        --dir and --name are ignored.
 
76
  -p, --password        Create an encrypted password using the keys in
 
77
                        the key directory.  All options other than
 
78
                        --keydir and --name are ignored.
89
79
EOF
90
80
}
91
81
 
93
83
while :; do
94
84
    case "$1" in
95
85
        -p|--password) mode=password; shift;;
96
 
        -F|--passfile) mode=password; PASSFILE="$2"; shift 2;;
97
86
        -d|--dir) KEYDIR="$2"; shift 2;;
98
87
        -t|--type) KEYTYPE="$2"; shift 2;;
99
88
        -s|--subtype) SUBKEYTYPE="$2"; shift 2;;
119
108
PUBKEYFILE="$KEYDIR/pubkey.txt"
120
109
 
121
110
# Check for some invalid values
122
 
if [ ! -d "$KEYDIR" ]; then
 
111
if [ -d "$KEYDIR" ]; then :; else
123
112
    echo "$KEYDIR not a directory" >&2
124
113
    exit 1
125
114
fi
126
 
if [ ! -r "$KEYDIR" ]; then
127
 
    echo "Directory $KEYDIR not readable" >&2
 
115
if [ -w "$KEYDIR" ]; then :; else
 
116
    echo "Directory $KEYDIR not writeable" >&2
 
117
    exit 1
 
118
fi
 
119
 
 
120
if [ "$mode" = password -a -e "$KEYDIR/trustdb.gpg.lock" ]; then
 
121
    echo "Key directory has locked trustdb; aborting." >&2
128
122
    exit 1
129
123
fi
130
124
 
131
125
if [ "$mode" = keygen ]; then
132
 
    if [ ! -w "$KEYDIR" ]; then
133
 
        echo "Directory $KEYDIR not writeable" >&2
134
 
        exit 1
135
 
    fi
136
126
    if [ -z "$KEYTYPE" ]; then
137
127
        echo "Empty key type" >&2
138
128
        exit 1
147
137
        echo "Invalid key length" >&2
148
138
        exit 1
149
139
    fi
150
 
    
 
140
 
151
141
    if [ -z "$KEYEXPIRE" ]; then
152
142
        echo "Empty key expiration" >&2
153
143
        exit 1
159
149
        [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|*) FORCE=0;;
160
150
    esac
161
151
    
162
 
    if [ \( -e "$SECKEYFILE" -o -e "$PUBKEYFILE" \) \
163
 
        -a "$FORCE" -eq 0 ]; then
 
152
    if { [ -e "$SECKEYFILE" ] || [ -e "$PUBKEYFILE" ]; } \
 
153
        && [ "$FORCE" -eq 0 ]; then
164
154
        echo "Refusing to overwrite old key files; use --force" >&2
165
155
        exit 1
166
156
    fi
172
162
    if [ -n "$KEYEMAIL" ]; then
173
163
        KEYEMAILLINE="Name-Email: $KEYEMAIL"
174
164
    fi
175
 
    
 
165
 
176
166
    # Create temporary gpg batch file
177
 
    BATCHFILE="`mktemp -t mandos-keygen-batch.XXXXXXXXXX`"
 
167
    BATCHFILE="`mktemp -t mandos-gpg-batch.XXXXXXXXXX`"
178
168
fi
179
169
 
180
170
if [ "$mode" = password ]; then
181
171
    # Create temporary encrypted password file
182
 
    SECFILE="`mktemp -t mandos-keygen-secfile.XXXXXXXXXX`"
183
 
fi
184
 
 
185
 
# Create temporary key ring directory
186
 
RINGDIR="`mktemp -d -t mandos-keygen-keyrings.XXXXXXXXXX`"
 
172
    SECFILE="`mktemp -t mandos-gpg-secfile.XXXXXXXXXX`"
 
173
fi
 
174
 
 
175
# Create temporary key rings
 
176
SECRING="`mktemp -t mandos-gpg-secring.XXXXXXXXXX`"
 
177
PUBRING="`mktemp -t mandos-gpg-pubring.XXXXXXXXXX`"
 
178
 
 
179
if [ "$mode" = password ]; then
 
180
    # If a trustdb.gpg file does not already exist, schedule it for
 
181
    # deletion when we are done.
 
182
    if ! [ -e "$KEYDIR/trustdb.gpg" ]; then
 
183
        TRUSTDB="$KEYDIR/trustdb.gpg"
 
184
    fi
 
185
fi
187
186
 
188
187
# Remove temporary files on exit
189
188
trap "
190
189
set +e; \
191
 
test -n \"$SECFILE\" && shred --remove \"$SECFILE\"; \
192
 
shred --remove \"$RINGDIR\"/sec*;
193
 
test -n \"$BATCHFILE\" && rm --force \"$BATCHFILE\"; \
194
 
rm --recursive --force \"$RINGDIR\";
 
190
rm --force $PUBRING ${PUBRING}~ $BATCHFILE $TRUSTDB; \
 
191
shred --remove $SECRING $SECFILE; \
195
192
stty echo; \
196
193
" EXIT
197
194
 
198
 
umask 077
 
195
umask 027
199
196
 
200
197
if [ "$mode" = keygen ]; then
201
198
    # Create batch file for GnuPG
212
209
        Expire-Date: $KEYEXPIRE
213
210
        #Preferences: <string>
214
211
        #Handle: <no-spaces>
215
 
        #%pubring pubring.gpg
216
 
        #%secring secring.gpg
 
212
        %pubring $PUBRING
 
213
        %secring $SECRING
217
214
        %commit
218
215
        EOF
219
216
    
220
 
    if tty --quiet; then
221
 
        cat <<-EOF
222
 
        Note: Due to entropy requirements, key generation could take
223
 
        anything from a few minutes to SEVERAL HOURS.  Please be
224
 
        patient and/or supply the system with more entropy if needed.
225
 
        EOF
226
 
        echo -n "Started: "
227
 
        date
228
 
    fi
229
 
    
230
217
    # Generate a new key in the key rings
231
 
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
232
 
        --homedir "$RINGDIR" --trust-model always \
 
218
    gpg --no-random-seed-file --quiet --batch --no-tty \
 
219
        --no-default-keyring --no-options --enable-dsa2 \
 
220
        --secret-keyring "$SECRING" --keyring "$PUBRING" \
233
221
        --gen-key "$BATCHFILE"
234
222
    rm --force "$BATCHFILE"
235
 
    
236
 
    if tty --quiet; then
237
 
        echo -n "Finished: "
238
 
        date
239
 
    fi
240
 
    
 
223
 
241
224
    # Backup any old key files
242
225
    if cp --backup=numbered --force "$SECKEYFILE" "$SECKEYFILE" \
243
226
        2>/dev/null; then
257
240
        FILECOMMENT="$FILECOMMENT <$KEYEMAIL>"
258
241
    fi
259
242
    
260
 
    # Export key from key rings to key files
261
 
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
262
 
        --homedir "$RINGDIR" --armor --export-options export-minimal \
263
 
        --comment "$FILECOMMENT" --output "$SECKEYFILE" \
264
 
        --export-secret-keys
265
 
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
266
 
        --homedir "$RINGDIR" --armor --export-options export-minimal \
267
 
        --comment "$FILECOMMENT" --output "$PUBKEYFILE" --export
 
243
    # Export keys from key rings to key files
 
244
    gpg --no-random-seed-file --quiet --batch --no-tty --armor \
 
245
        --no-default-keyring --no-options --enable-dsa2 \
 
246
        --secret-keyring "$SECRING" --keyring "$PUBRING" \
 
247
        --export-options export-minimal --comment "$FILECOMMENT" \
 
248
        --output "$SECKEYFILE" --export-secret-keys
 
249
    gpg --no-random-seed-file --quiet --batch --no-tty --armor \
 
250
        --no-default-keyring --no-options --enable-dsa2 \
 
251
        --secret-keyring "$SECRING" --keyring "$PUBRING" \
 
252
        --export-options export-minimal --comment "$FILECOMMENT" \
 
253
        --output "$PUBKEYFILE" --export
268
254
fi
269
255
 
270
256
if [ "$mode" = password ]; then
271
 
    # Import key into temporary key rings
272
 
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
273
 
        --homedir "$RINGDIR" --trust-model always --armor \
274
 
        --import "$SECKEYFILE"
275
 
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
276
 
        --homedir "$RINGDIR" --trust-model always --armor \
277
 
        --import "$PUBKEYFILE"
278
 
    
 
257
    # Import keys into temporary key rings
 
258
    gpg --no-random-seed-file --quiet --batch --no-tty --armor \
 
259
        --no-default-keyring --no-options --enable-dsa2 \
 
260
        --homedir "$KEYDIR" --no-permission-warning \
 
261
        --secret-keyring "$SECRING" --keyring "$PUBRING" \
 
262
        --trust-model always --import "$SECKEYFILE"
 
263
    gpg --no-random-seed-file --quiet --batch --no-tty --armor \
 
264
        --no-default-keyring --no-options --enable-dsa2 \
 
265
        --homedir "$KEYDIR" --no-permission-warning \
 
266
        --secret-keyring "$SECRING" --keyring "$PUBRING" \
 
267
        --trust-model always --import "$PUBKEYFILE"
 
268
 
279
269
    # Get fingerprint of key
280
 
    FINGERPRINT="`gpg --quiet --batch --no-tty --no-options \
281
 
        --enable-dsa2 --homedir \"$RINGDIR\" --trust-model always \
282
 
        --fingerprint --with-colons \
283
 
        | sed --quiet \
284
 
        --expression='/^fpr:/{s/^fpr:.*:\\([0-9A-Z]*\\):\$/\\1/p;q}'`"
 
270
    FINGERPRINT="`gpg --no-random-seed-file --quiet --batch --no-tty \
 
271
        --armor --no-default-keyring --no-options --enable-dsa2 \
 
272
        --homedir \"$KEYDIR\" --no-permission-warning \
 
273
        --secret-keyring \"$SECRING\" --keyring \"$PUBRING\" \
 
274
        --trust-model always --fingerprint --with-colons \
 
275
        | sed -n -e '/^fpr:/{s/^fpr:.*:\\([0-9A-Z]*\\):\$/\\1/p;q}'`"
285
276
    
286
277
    test -n "$FINGERPRINT"
287
278
    
288
279
    FILECOMMENT="Encrypted password for a Mandos client"
289
280
    
290
 
    if [ -n "$PASSFILE" ]; then
291
 
        cat "$PASSFILE"
292
 
    else
293
 
        stty -echo
294
 
        echo -n "Enter passphrase: " >&2
295
 
        first="$(head --lines=1 | tr --delete '\n')"
296
 
        echo -n -e "\nRepeat passphrase: " >&2
297
 
        second="$(head --lines=1 | tr --delete '\n')"
298
 
        echo >&2
299
 
        stty echo
300
 
        if [ "$first" != "$second" ]; then
301
 
            echo -e "Passphrase mismatch" >&2
302
 
            touch "$RINGDIR"/mismatch
303
 
        else
304
 
            echo -n "$first"
305
 
        fi
306
 
    fi | gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
307
 
        --homedir "$RINGDIR" --trust-model always --armor --encrypt \
308
 
        --sign --recipient "$FINGERPRINT" --comment "$FILECOMMENT" \
 
281
    stty -echo
 
282
    echo -n "Enter passphrase: " >&2
 
283
    sed -e '1q' \
 
284
        | gpg --no-random-seed-file --batch --no-tty --armor \
 
285
        --no-default-keyring --no-options --enable-dsa2 \
 
286
        --homedir "$KEYDIR" --no-permission-warning \
 
287
        --secret-keyring "$SECRING" --keyring "$PUBRING" \
 
288
        --trust-model always --encrypt --recipient "$FINGERPRINT" \
 
289
        --comment "$FILECOMMENT" \
309
290
        > "$SECFILE"
310
 
    if [ -e "$RINGDIR"/mismatch ]; then
311
 
        rm --force "$RINGDIR"/mismatch
312
 
        exit 1
313
 
    fi
 
291
    echo >&2
 
292
    stty echo
314
293
    
315
294
    cat <<-EOF
316
295
        [$KEYNAME]
317
296
        host = $KEYNAME
318
297
        fingerprint = $FINGERPRINT
319
298
        secret =
320
 
        EOF
321
 
    sed --quiet --expression='
 
299
EOF
 
300
    sed -n -e '
322
301
        /^-----BEGIN PGP MESSAGE-----$/,/^-----END PGP MESSAGE-----$/{
323
302
            /^$/,${
324
303
                # Remove 24-bit Radix-64 checksum
337
316
    shred --remove "$SECFILE"
338
317
fi
339
318
# Remove the key rings
340
 
shred --remove "$RINGDIR"/sec*
341
 
rm --recursive --force "$RINGDIR"
 
319
shred --remove "$SECRING"
 
320
rm --force "$PUBRING" "${PUBRING}~"
 
321
# Remove the trustdb, if one did not exist when we started
 
322
if [ -n "$TRUSTDB" ]; then
 
323
    rm --force "$TRUSTDB"
 
324
fi