/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:
 
1
#!/bin/sh -e
 
2
 
3
# Mandos key generator - create a new OpenPGP key for a Mandos client
 
4
 
5
# Copyright © 2007-2008 Teddy Hogeborn & Björn Påhlsson
 
6
 
7
# This program is free software: you can redistribute it and/or modify
 
8
# it under the terms of the GNU General Public License as published by
 
9
# the Free Software Foundation, either version 3 of the License, or
 
10
# (at your option) any later version.
 
11
#
 
12
#     This program is distributed in the hope that it will be useful,
 
13
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
#     GNU General Public License for more details.
 
16
 
17
# You should have received a copy of the GNU General Public License
 
18
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
19
 
20
# Contact the authors at <mandos@fukt.bsnet.se>.
 
21
 
22
 
 
23
VERSION="1.0"
 
24
 
 
25
KEYDIR="/etc/mandos"
 
26
KEYTYPE=DSA
 
27
KEYLENGTH=2048
 
28
SUBKEYTYPE=ELG-E
 
29
SUBKEYLENGTH=2048
 
30
KEYNAME="`hostname --fqdn`"
 
31
KEYEMAIL=""
 
32
KEYCOMMENT="Mandos client key"
 
33
KEYEXPIRE=0
 
34
FORCE=no
 
35
KEYCOMMENT_ORIG="$KEYCOMMENT"
 
36
mode=keygen
 
37
 
 
38
# Parse options
 
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 \
 
41
    --name "$0" -- "$@"`
 
42
 
 
43
help(){
 
44
basename="`basename $0`"
 
45
cat <<EOF
 
46
Usage: $basename [ -v | --version ]
 
47
       $basename [ -h | --help ]
 
48
   Key creation:
 
49
       $basename [ OPTIONS ]
 
50
   Encrypted password creation:
 
51
       $basename { -p | --password } [ --name NAME ] [ --dir DIR]
 
52
 
 
53
Key creation options:
 
54
  -v, --version         Show program's version number and exit
 
55
  -h, --help            Show this help message and exit
 
56
  -d DIR, --dir DIR     Target directory for key files
 
57
  -t TYPE, --type TYPE  Key type.  Default is DSA.
 
58
  -l BITS, --length BITS
 
59
                        Key length in bits.  Default is 2048.
 
60
  -s TYPE, --subtype TYPE
 
61
                        Subkey type.  Default is ELG-E.
 
62
  -L BITS, --sublength BITS
 
63
                        Subkey length in bits.  Default is 2048.
 
64
  -n NAME, --name NAME  Name of key.  Default is the FQDN.
 
65
  -e ADDRESS, --email ADDRESS
 
66
                        Email address of key.  Default is empty.
 
67
  -c COMMENT, --comment COMMENT
 
68
                        Comment field for key.  The default value is
 
69
                        "Mandos client key".
 
70
  -x TIME, --expire TIME
 
71
                        Key expire time.  Default is no expiration.
 
72
                        See gpg(1) for syntax.
 
73
  -f, --force           Force overwriting old keys.
 
74
 
 
75
Password creation options:
 
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.
 
79
EOF
 
80
}
 
81
 
 
82
eval set -- "$TEMP"
 
83
while :; do
 
84
    case "$1" in
 
85
        -p|--password) mode=password; shift;;
 
86
        -d|--dir) KEYDIR="$2"; shift 2;;
 
87
        -t|--type) KEYTYPE="$2"; shift 2;;
 
88
        -s|--subtype) SUBKEYTYPE="$2"; shift 2;;
 
89
        -l|--length) KEYLENGTH="$2"; shift 2;;
 
90
        -L|--sublength) SUBKEYLENGTH="$2"; shift 2;;
 
91
        -n|--name) KEYNAME="$2"; shift 2;;
 
92
        -e|--email) KEYEMAIL="$2"; shift 2;;
 
93
        -c|--comment) KEYCOMMENT="$2"; shift 2;;
 
94
        -x|--expire) KEYEXPIRE="$2"; shift 2;;
 
95
        -f|--force) FORCE=yes; shift;;
 
96
        -v|--version) echo "$0 $VERSION"; exit;;
 
97
        -h|--help) help; exit;;
 
98
        --) shift; break;;
 
99
        *) echo "Internal error" >&2; exit 1;;
 
100
    esac
 
101
done
 
102
if [ "$#" -gt 0 ]; then
 
103
    echo "Unknown arguments: '$@'" >&2
 
104
    exit 1
 
105
fi
 
106
 
 
107
SECKEYFILE="$KEYDIR/seckey.txt"
 
108
PUBKEYFILE="$KEYDIR/pubkey.txt"
 
109
 
 
110
# Check for some invalid values
 
111
if [ -d "$KEYDIR" ]; then :; else
 
112
    echo "$KEYDIR not a directory" >&2
 
113
    exit 1
 
114
fi
 
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
 
122
    exit 1
 
123
fi
 
124
 
 
125
if [ "$mode" = keygen ]; then
 
126
    if [ -z "$KEYTYPE" ]; then
 
127
        echo "Empty key type" >&2
 
128
        exit 1
 
129
    fi
 
130
    
 
131
    if [ -z "$KEYNAME" ]; then
 
132
        echo "Empty key name" >&2
 
133
        exit 1
 
134
    fi
 
135
    
 
136
    if [ -z "$KEYLENGTH" ] || [ "$KEYLENGTH" -lt 512 ]; then
 
137
        echo "Invalid key length" >&2
 
138
        exit 1
 
139
    fi
 
140
 
 
141
    if [ -z "$KEYEXPIRE" ]; then
 
142
        echo "Empty key expiration" >&2
 
143
        exit 1
 
144
    fi
 
145
    
 
146
    # Make FORCE be 0 or 1
 
147
    case "$FORCE" in
 
148
        [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]) FORCE=1;;
 
149
        [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|*) FORCE=0;;
 
150
    esac
 
151
    
 
152
    if { [ -e "$SECKEYFILE" ] || [ -e "$PUBKEYFILE" ]; } \
 
153
        && [ "$FORCE" -eq 0 ]; then
 
154
        echo "Refusing to overwrite old key files; use --force" >&2
 
155
        exit 1
 
156
    fi
 
157
    
 
158
    # Set lines for GnuPG batch file
 
159
    if [ -n "$KEYCOMMENT" ]; then
 
160
        KEYCOMMENTLINE="Name-Comment: $KEYCOMMENT"
 
161
    fi
 
162
    if [ -n "$KEYEMAIL" ]; then
 
163
        KEYEMAILLINE="Name-Email: $KEYEMAIL"
 
164
    fi
 
165
 
 
166
    # Create temporary gpg batch file
 
167
    BATCHFILE="`mktemp -t mandos-gpg-batch.XXXXXXXXXX`"
 
168
fi
 
169
 
 
170
if [ "$mode" = password ]; then
 
171
    # Create temporary encrypted password file
 
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
 
 
187
# Remove temporary files on exit
 
188
trap "
 
189
set +e; \
 
190
rm --force $PUBRING ${PUBRING}~ $BATCHFILE $TRUSTDB; \
 
191
shred --remove $SECRING $SECFILE; \
 
192
stty echo; \
 
193
" EXIT
 
194
 
 
195
umask 027
 
196
 
 
197
if [ "$mode" = keygen ]; then
 
198
    # Create batch file for GnuPG
 
199
    cat >"$BATCHFILE" <<-EOF
 
200
        Key-Type: $KEYTYPE
 
201
        Key-Length: $KEYLENGTH
 
202
        #Key-Usage: encrypt,sign,auth
 
203
        Subkey-Type: $SUBKEYTYPE
 
204
        Subkey-Length: $SUBKEYLENGTH
 
205
        #Subkey-Usage: encrypt,sign,auth
 
206
        Name-Real: $KEYNAME
 
207
        $KEYCOMMENTLINE
 
208
        $KEYEMAILLINE
 
209
        Expire-Date: $KEYEXPIRE
 
210
        #Preferences: <string>
 
211
        #Handle: <no-spaces>
 
212
        %pubring $PUBRING
 
213
        %secring $SECRING
 
214
        %commit
 
215
        EOF
 
216
    
 
217
    # Generate a new key in the key rings
 
218
    gpg --no-random-seed-file --quiet --batch --no-tty \
 
219
        --no-default-keyring --no-options --enable-dsa2 \
 
220
        --secret-keyring "$SECRING" --keyring "$PUBRING" \
 
221
        --gen-key "$BATCHFILE"
 
222
    rm --force "$BATCHFILE"
 
223
 
 
224
    # Backup any old key files
 
225
    if cp --backup=numbered --force "$SECKEYFILE" "$SECKEYFILE" \
 
226
        2>/dev/null; then
 
227
        shred --remove "$SECKEYFILE"
 
228
    fi
 
229
    if cp --backup=numbered --force "$PUBKEYFILE" "$PUBKEYFILE" \
 
230
        2>/dev/null; then
 
231
        rm --force "$PUBKEYFILE"
 
232
    fi
 
233
    
 
234
    FILECOMMENT="Mandos client key for $KEYNAME"
 
235
    if [ "$KEYCOMMENT" != "$KEYCOMMENT_ORIG" ]; then
 
236
        FILECOMMENT="$FILECOMMENT ($KEYCOMMENT)"
 
237
    fi
 
238
    
 
239
    if [ -n "$KEYEMAIL" ]; then
 
240
        FILECOMMENT="$FILECOMMENT <$KEYEMAIL>"
 
241
    fi
 
242
    
 
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
 
254
fi
 
255
 
 
256
if [ "$mode" = password ]; then
 
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
 
 
269
    # Get fingerprint of key
 
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}'`"
 
276
    
 
277
    test -n "$FINGERPRINT"
 
278
    
 
279
    FILECOMMENT="Encrypted password for a Mandos client"
 
280
    
 
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
 
293
    
 
294
    cat <<-EOF
 
295
        [$KEYNAME]
 
296
        host = $KEYNAME
 
297
        fingerprint = $FINGERPRINT
 
298
        secret =
 
299
EOF
 
300
    sed -n -e '
 
301
        /^-----BEGIN PGP MESSAGE-----$/,/^-----END PGP MESSAGE-----$/{
 
302
            /^$/,${
 
303
                # Remove 24-bit Radix-64 checksum
 
304
                s/=....$//
 
305
                # Indent four spaces
 
306
                /^[^-]/s/^/    /p
 
307
            }
 
308
        }' < "$SECFILE"
 
309
fi
 
310
 
 
311
trap - EXIT
 
312
 
 
313
set +e
 
314
# Remove the password file, if any
 
315
if [ -n "$SECFILE" ]; then
 
316
    shred --remove "$SECFILE"
 
317
fi
 
318
# Remove the key rings
 
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