/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-2014 Teddy Hogeborn
6
 
# Copyright © 2008-2014 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
18
17
# You should have received a copy of the GNU General Public License
19
18
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
19
21
 
# Contact the authors at <mandos@recompile.se>.
 
20
# Contact the authors at <mandos@fukt.bsnet.se>.
22
21
23
22
 
24
 
VERSION="1.6.5"
 
23
VERSION="1.0"
25
24
 
26
 
KEYDIR="/etc/keys/mandos"
27
 
KEYTYPE=RSA
28
 
KEYLENGTH=4096
29
 
SUBKEYTYPE=RSA
30
 
SUBKEYLENGTH=4096
31
 
KEYNAME="`hostname --fqdn 2>/dev/null || hostname`"
 
25
KEYDIR="/etc/mandos"
 
26
KEYTYPE=DSA
 
27
KEYLENGTH=2048
 
28
SUBKEYTYPE=ELG-E
 
29
SUBKEYLENGTH=2048
 
30
KEYNAME="`hostname --fqdn`"
32
31
KEYEMAIL=""
33
 
KEYCOMMENT=""
 
32
KEYCOMMENT="Mandos client key"
34
33
KEYEXPIRE=0
35
34
FORCE=no
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
61
55
  -h, --help            Show this help message and exit
62
56
  -d DIR, --dir DIR     Target directory for key files
63
 
  -t TYPE, --type TYPE  Key type.  Default is RSA.
 
57
  -t TYPE, --type TYPE  Key type.  Default is DSA.
64
58
  -l BITS, --length BITS
65
 
                        Key length in bits.  Default is 4096.
 
59
                        Key length in bits.  Default is 2048.
66
60
  -s TYPE, --subtype TYPE
67
 
                        Subkey type.  Default is RSA.
 
61
                        Subkey type.  Default is ELG-E.
68
62
  -L BITS, --sublength BITS
69
 
                        Subkey length in bits.  Default is 4096.
 
63
                        Subkey length in bits.  Default is 2048.
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
74
 
                        Comment field for key.  The default is empty.
 
67
  -c COMMENT, --comment COMMENT
 
68
                        Comment field for key.  The default value is
 
69
                        "Mandos client key".
75
70
  -x TIME, --expire TIME
76
71
                        Key expire time.  Default is no expiration.
77
72
                        See gpg(1) for syntax.
78
 
  -f, --force           Force overwriting old key files.
 
73
  -f, --force           Force overwriting old keys.
79
74
 
80
75
Password creation options:
81
 
  -p, --password        Create an encrypted password using the key in
82
 
                        the key directory.  All options other than
83
 
                        --dir and --name are ignored.
84
 
  -F FILE, --passfile FILE
85
 
                        Encrypt a password from FILE using the key in
86
 
                        the key directory.  All options other than
87
 
                        --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.
88
79
EOF
89
80
}
90
81
 
92
83
while :; do
93
84
    case "$1" in
94
85
        -p|--password) mode=password; shift;;
95
 
        -F|--passfile) mode=password; PASSFILE="$2"; shift 2;;
96
86
        -d|--dir) KEYDIR="$2"; shift 2;;
97
87
        -t|--type) KEYTYPE="$2"; shift 2;;
98
88
        -s|--subtype) SUBKEYTYPE="$2"; shift 2;;
118
108
PUBKEYFILE="$KEYDIR/pubkey.txt"
119
109
 
120
110
# Check for some invalid values
121
 
if [ ! -d "$KEYDIR" ]; then
 
111
if [ -d "$KEYDIR" ]; then :; else
122
112
    echo "$KEYDIR not a directory" >&2
123
113
    exit 1
124
114
fi
125
 
if [ ! -r "$KEYDIR" ]; then
126
 
    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
127
122
    exit 1
128
123
fi
129
124
 
130
125
if [ "$mode" = keygen ]; then
131
 
    if [ ! -w "$KEYDIR" ]; then
132
 
        echo "Directory $KEYDIR not writeable" >&2
133
 
        exit 1
134
 
    fi
135
126
    if [ -z "$KEYTYPE" ]; then
136
127
        echo "Empty key type" >&2
137
128
        exit 1
146
137
        echo "Invalid key length" >&2
147
138
        exit 1
148
139
    fi
149
 
    
 
140
 
150
141
    if [ -z "$KEYEXPIRE" ]; then
151
142
        echo "Empty key expiration" >&2
152
143
        exit 1
158
149
        [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|*) FORCE=0;;
159
150
    esac
160
151
    
161
 
    if [ \( -e "$SECKEYFILE" -o -e "$PUBKEYFILE" \) \
162
 
        -a "$FORCE" -eq 0 ]; then
 
152
    if { [ -e "$SECKEYFILE" ] || [ -e "$PUBKEYFILE" ]; } \
 
153
        && [ "$FORCE" -eq 0 ]; then
163
154
        echo "Refusing to overwrite old key files; use --force" >&2
164
155
        exit 1
165
156
    fi
171
162
    if [ -n "$KEYEMAIL" ]; then
172
163
        KEYEMAILLINE="Name-Email: $KEYEMAIL"
173
164
    fi
174
 
    
 
165
 
175
166
    # Create temporary gpg batch file
176
 
    BATCHFILE="`mktemp -t mandos-keygen-batch.XXXXXXXXXX`"
 
167
    BATCHFILE="`mktemp -t mandos-gpg-batch.XXXXXXXXXX`"
177
168
fi
178
169
 
179
170
if [ "$mode" = password ]; then
180
171
    # Create temporary encrypted password file
181
 
    SECFILE="`mktemp -t mandos-keygen-secfile.XXXXXXXXXX`"
182
 
fi
183
 
 
184
 
# Create temporary key ring directory
185
 
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
186
186
 
187
187
# Remove temporary files on exit
188
188
trap "
189
189
set +e; \
190
 
test -n \"$SECFILE\" && shred --remove \"$SECFILE\"; \
191
 
shred --remove \"$RINGDIR\"/sec*;
192
 
test -n \"$BATCHFILE\" && rm --force \"$BATCHFILE\"; \
193
 
rm --recursive --force \"$RINGDIR\";
194
 
tty --quiet && stty echo; \
 
190
rm --force $PUBRING ${PUBRING}~ $BATCHFILE $TRUSTDB; \
 
191
shred --remove $SECRING $SECFILE; \
 
192
stty echo; \
195
193
" EXIT
196
194
 
197
 
set -e
198
 
 
199
 
umask 077
 
195
umask 027
200
196
 
201
197
if [ "$mode" = keygen ]; then
202
198
    # Create batch file for GnuPG
203
199
    cat >"$BATCHFILE" <<-EOF
204
200
        Key-Type: $KEYTYPE
205
201
        Key-Length: $KEYLENGTH
206
 
        Key-Usage: sign,auth
 
202
        #Key-Usage: encrypt,sign,auth
207
203
        Subkey-Type: $SUBKEYTYPE
208
204
        Subkey-Length: $SUBKEYLENGTH
209
 
        Subkey-Usage: encrypt
 
205
        #Subkey-Usage: encrypt,sign,auth
210
206
        Name-Real: $KEYNAME
211
207
        $KEYCOMMENTLINE
212
208
        $KEYEMAILLINE
213
209
        Expire-Date: $KEYEXPIRE
214
210
        #Preferences: <string>
215
211
        #Handle: <no-spaces>
216
 
        #%pubring pubring.gpg
217
 
        #%secring secring.gpg
 
212
        %pubring $PUBRING
 
213
        %secring $SECRING
218
214
        %commit
219
215
        EOF
220
216
    
221
 
    if tty --quiet; then
222
 
        cat <<-EOF
223
 
        Note: Due to entropy requirements, key generation could take
224
 
        anything from a few minutes to SEVERAL HOURS.  Please be
225
 
        patient and/or supply the system with more entropy if needed.
226
 
        EOF
227
 
        echo -n "Started: "
228
 
        date
229
 
    fi
230
 
    
231
 
    # Make sure trustdb.gpg exists;
232
 
    # this is a workaround for Debian bug #737128
233
 
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
234
 
        --homedir "$RINGDIR" \
235
 
        --import-ownertrust < /dev/null
236
217
    # Generate a new key in the key rings
237
 
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
238
 
        --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" \
239
221
        --gen-key "$BATCHFILE"
240
222
    rm --force "$BATCHFILE"
241
 
    
242
 
    if tty --quiet; then
243
 
        echo -n "Finished: "
244
 
        date
245
 
    fi
246
 
    
 
223
 
247
224
    # Backup any old key files
248
225
    if cp --backup=numbered --force "$SECKEYFILE" "$SECKEYFILE" \
249
226
        2>/dev/null; then
263
240
        FILECOMMENT="$FILECOMMENT <$KEYEMAIL>"
264
241
    fi
265
242
    
266
 
    # Export key from key rings to key files
267
 
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
268
 
        --homedir "$RINGDIR" --armor --export-options export-minimal \
269
 
        --comment "$FILECOMMENT" --output "$SECKEYFILE" \
270
 
        --export-secret-keys
271
 
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
272
 
        --homedir "$RINGDIR" --armor --export-options export-minimal \
273
 
        --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
274
254
fi
275
255
 
276
256
if [ "$mode" = password ]; then
277
 
    # Import key into temporary key rings
278
 
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
279
 
        --homedir "$RINGDIR" --trust-model always --armor \
280
 
        --import "$SECKEYFILE"
281
 
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
282
 
        --homedir "$RINGDIR" --trust-model always --armor \
283
 
        --import "$PUBKEYFILE"
284
 
    
 
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
 
285
269
    # Get fingerprint of key
286
 
    FINGERPRINT="`gpg --quiet --batch --no-tty --no-options \
287
 
        --enable-dsa2 --homedir \"$RINGDIR\" --trust-model always \
288
 
        --fingerprint --with-colons \
289
 
        | sed --quiet \
290
 
        --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}'`"
291
276
    
292
277
    test -n "$FINGERPRINT"
293
278
    
294
279
    FILECOMMENT="Encrypted password for a Mandos client"
295
280
    
296
 
    while [ ! -s "$SECFILE" ]; do
297
 
        if [ -n "$PASSFILE" ]; then
298
 
            cat "$PASSFILE"
299
 
        else
300
 
            tty --quiet && stty -echo
301
 
            echo -n "Enter passphrase: " >&2
302
 
            read first
303
 
            tty --quiet && echo >&2
304
 
            echo -n "Repeat passphrase: " >&2
305
 
            read second
306
 
            if tty --quiet; then
307
 
                echo >&2
308
 
                stty echo
309
 
            fi
310
 
            if [ "$first" != "$second" ]; then
311
 
                echo "Passphrase mismatch" >&2
312
 
                touch "$RINGDIR"/mismatch
313
 
            else
314
 
                echo -n "$first"
315
 
            fi
316
 
        fi | gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
317
 
            --homedir "$RINGDIR" --trust-model always --armor \
318
 
            --encrypt --sign --recipient "$FINGERPRINT" --comment \
319
 
            "$FILECOMMENT" > "$SECFILE"
320
 
        if [ -e "$RINGDIR"/mismatch ]; then
321
 
            rm --force "$RINGDIR"/mismatch
322
 
            if tty --quiet; then
323
 
                > "$SECFILE"
324
 
            else
325
 
                exit 1
326
 
            fi
327
 
        fi
328
 
    done
 
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" \
 
290
        > "$SECFILE"
 
291
    echo >&2
 
292
    stty echo
329
293
    
330
294
    cat <<-EOF
331
295
        [$KEYNAME]
332
296
        host = $KEYNAME
333
297
        fingerprint = $FINGERPRINT
334
298
        secret =
335
 
        EOF
336
 
    sed --quiet --expression='
 
299
EOF
 
300
    sed -n -e '
337
301
        /^-----BEGIN PGP MESSAGE-----$/,/^-----END PGP MESSAGE-----$/{
338
302
            /^$/,${
339
303
                # Remove 24-bit Radix-64 checksum
352
316
    shred --remove "$SECFILE"
353
317
fi
354
318
# Remove the key rings
355
 
shred --remove "$RINGDIR"/sec*
356
 
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