/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-07-20 06:33:48 UTC
  • Revision ID: teddy@fukt.bsnet.se-20080720063348-jscgy5p0itrgvlo8
* mandos-clients.conf ([foo]): Uncommented.
  ([foo]/secret): New.
  ([foo]/secfile): Commented out.
  ([foo]/checker): Changed to "fping -q -- %%(fqdn)s".
  ([foo]/timeout): New.

* server.py: New modeline for Python and Emacs.  Set a logging format.
  (Client.__init__): Bug fix: Choose either the value from the options
                     object or pass the argument through string_to_delta
                     for both "timeout" and "interval".
  (Client.checker_callback): Bug fix: Do not log spurious "Checker for
                             <foo> failed" messages.
  (Client.start_checker): Moved "Starting checker" log message down to
                          just before actually starting the subprocess.
                          Do not redirect the subprocesses' stdout to a
                          pipe.
  (peer_certificate, fingerprint): Added docstrings.
  (entry_group_state_changed): Call "killme()" instead of
                               "main_loop.quit()".
  (daemon, killme): New functions.
  (exitstatus, main_loop_started): New global variables.
  (__main__): Removed the "--cert", "--key", "--ca", and "--crl"
              options.  Removed the sleep command from the default
              checker.  Add a console logger in debug mode.  Call
              "killme()" instead of "main_loop.quit()" when there are no
              more clients.  Call "daemon()" if not in debug mode.
              Register "cleanup()" to run at exit.  Ignore some
              signals.  Catch DBusException to detect another running
              server and exit cleanly.  Exit with "exitstatus".
  (cleanup): New function.

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/keys/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 TEXT, --comment TEXT
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
 
                        --dir 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
112
 
    echo "$KEYDIR not a directory" >&2
113
 
    exit 1
114
 
fi
115
 
if [ ! -r "$KEYDIR" ]; then
116
 
    echo "Directory $KEYDIR not readable" >&2
117
 
    exit 1
118
 
fi
119
 
 
120
 
if [ "$mode" = keygen ]; then
121
 
    if [ ! -w "$KEYDIR" ]; then
122
 
        echo "Directory $KEYDIR not writeable" >&2
123
 
        exit 1
124
 
    fi
125
 
    if [ -z "$KEYTYPE" ]; then
126
 
        echo "Empty key type" >&2
127
 
        exit 1
128
 
    fi
129
 
    
130
 
    if [ -z "$KEYNAME" ]; then
131
 
        echo "Empty key name" >&2
132
 
        exit 1
133
 
    fi
134
 
    
135
 
    if [ -z "$KEYLENGTH" ] || [ "$KEYLENGTH" -lt 512 ]; then
136
 
        echo "Invalid key length" >&2
137
 
        exit 1
138
 
    fi
139
 
 
140
 
    if [ -z "$KEYEXPIRE" ]; then
141
 
        echo "Empty key expiration" >&2
142
 
        exit 1
143
 
    fi
144
 
    
145
 
    # Make FORCE be 0 or 1
146
 
    case "$FORCE" in
147
 
        [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]) FORCE=1;;
148
 
        [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|*) FORCE=0;;
149
 
    esac
150
 
    
151
 
    if [ \( -e "$SECKEYFILE" -o -e "$PUBKEYFILE" \) \
152
 
        -a "$FORCE" -eq 0 ]; then
153
 
        echo "Refusing to overwrite old key files; use --force" >&2
154
 
        exit 1
155
 
    fi
156
 
    
157
 
    # Set lines for GnuPG batch file
158
 
    if [ -n "$KEYCOMMENT" ]; then
159
 
        KEYCOMMENTLINE="Name-Comment: $KEYCOMMENT"
160
 
    fi
161
 
    if [ -n "$KEYEMAIL" ]; then
162
 
        KEYEMAILLINE="Name-Email: $KEYEMAIL"
163
 
    fi
164
 
 
165
 
    # Create temporary gpg batch file
166
 
    BATCHFILE="`mktemp -t mandos-keygen-batch.XXXXXXXXXX`"
167
 
fi
168
 
 
169
 
if [ "$mode" = password ]; then
170
 
    # Create temporary encrypted password file
171
 
    SECFILE="`mktemp -t mandos-keygen-secfile.XXXXXXXXXX`"
172
 
fi
173
 
 
174
 
# Create temporary key ring directory
175
 
RINGDIR="`mktemp -d -t mandos-keygen-keyrings.XXXXXXXXXX`"
176
 
 
177
 
# Remove temporary files on exit
178
 
trap "
179
 
set +e; \
180
 
test -n \"$SECFILE\" && shred --remove \"$SECFILE\"; \
181
 
shred --remove \"$RINGDIR\"/sec*;
182
 
test -n \"$BATCHFILE\" && rm --force \"$BATCHFILE\"; \
183
 
rm --recursive --force \"$RINGDIR\";
184
 
stty echo; \
185
 
" EXIT
186
 
 
187
 
umask 077
188
 
 
189
 
if [ "$mode" = keygen ]; then
190
 
    # Create batch file for GnuPG
191
 
    cat >"$BATCHFILE" <<-EOF
192
 
        Key-Type: $KEYTYPE
193
 
        Key-Length: $KEYLENGTH
194
 
        #Key-Usage: encrypt,sign,auth
195
 
        Subkey-Type: $SUBKEYTYPE
196
 
        Subkey-Length: $SUBKEYLENGTH
197
 
        #Subkey-Usage: encrypt,sign,auth
198
 
        Name-Real: $KEYNAME
199
 
        $KEYCOMMENTLINE
200
 
        $KEYEMAILLINE
201
 
        Expire-Date: $KEYEXPIRE
202
 
        #Preferences: <string>
203
 
        #Handle: <no-spaces>
204
 
        #%pubring pubring.gpg
205
 
        #%secring secring.gpg
206
 
        %commit
207
 
        EOF
208
 
    
209
 
    # Generate a new key in the key rings
210
 
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
211
 
        --homedir "$RINGDIR" --trust-model always \
212
 
        --gen-key "$BATCHFILE"
213
 
    rm --force "$BATCHFILE"
214
 
    
215
 
    # Backup any old key files
216
 
    if cp --backup=numbered --force "$SECKEYFILE" "$SECKEYFILE" \
217
 
        2>/dev/null; then
218
 
        shred --remove "$SECKEYFILE"
219
 
    fi
220
 
    if cp --backup=numbered --force "$PUBKEYFILE" "$PUBKEYFILE" \
221
 
        2>/dev/null; then
222
 
        rm --force "$PUBKEYFILE"
223
 
    fi
224
 
    
225
 
    FILECOMMENT="Mandos client key for $KEYNAME"
226
 
    if [ "$KEYCOMMENT" != "$KEYCOMMENT_ORIG" ]; then
227
 
        FILECOMMENT="$FILECOMMENT ($KEYCOMMENT)"
228
 
    fi
229
 
    
230
 
    if [ -n "$KEYEMAIL" ]; then
231
 
        FILECOMMENT="$FILECOMMENT <$KEYEMAIL>"
232
 
    fi
233
 
    
234
 
    # Export keys from key rings to key files
235
 
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
236
 
        --homedir "$RINGDIR" --armor --export-options export-minimal \
237
 
        --comment "$FILECOMMENT" --output "$SECKEYFILE" \
238
 
        --export-secret-keys
239
 
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
240
 
        --homedir "$RINGDIR" --armor --export-options export-minimal \
241
 
        --comment "$FILECOMMENT" --output "$PUBKEYFILE" --export
242
 
fi
243
 
 
244
 
if [ "$mode" = password ]; then
245
 
    # Import keys into temporary key rings
246
 
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
247
 
        --homedir "$RINGDIR" --trust-model always --armor \
248
 
        --import "$SECKEYFILE"
249
 
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
250
 
        --homedir "$RINGDIR" --trust-model always --armor \
251
 
        --import "$PUBKEYFILE"
252
 
    
253
 
    # Get fingerprint of key
254
 
    FINGERPRINT="`gpg --quiet --batch --no-tty --no-options \
255
 
        --enable-dsa2 --homedir \"$RINGDIR\" --trust-model always \
256
 
        --fingerprint --with-colons \
257
 
        | sed --quiet \
258
 
        --expression='/^fpr:/{s/^fpr:.*:\\([0-9A-Z]*\\):\$/\\1/p;q}'`"
259
 
    
260
 
    test -n "$FINGERPRINT"
261
 
    
262
 
    FILECOMMENT="Encrypted password for a Mandos client"
263
 
    
264
 
    stty -echo
265
 
    echo -n "Enter passphrase: " >&2
266
 
    head --lines=1 | tr --delete '\n' \
267
 
        | gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
268
 
        --homedir "$RINGDIR" --trust-model always --armor --encrypt \
269
 
        --recipient "$FINGERPRINT" --comment "$FILECOMMENT" \
270
 
        > "$SECFILE"
271
 
    echo >&2
272
 
    stty echo
273
 
    
274
 
    cat <<-EOF
275
 
        [$KEYNAME]
276
 
        host = $KEYNAME
277
 
        fingerprint = $FINGERPRINT
278
 
        secret =
279
 
EOF
280
 
    sed --quiet --expression='
281
 
        /^-----BEGIN PGP MESSAGE-----$/,/^-----END PGP MESSAGE-----$/{
282
 
            /^$/,${
283
 
                # Remove 24-bit Radix-64 checksum
284
 
                s/=....$//
285
 
                # Indent four spaces
286
 
                /^[^-]/s/^/    /p
287
 
            }
288
 
        }' < "$SECFILE"
289
 
fi
290
 
 
291
 
trap - EXIT
292
 
 
293
 
set +e
294
 
# Remove the password file, if any
295
 
if [ -n "$SECFILE" ]; then
296
 
    shred --remove "$SECFILE"
297
 
fi
298
 
# Remove the key rings
299
 
shred --remove "$RINGDIR"/sec*
300
 
rm --recursive --force "$RINGDIR"