/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

First version of a somewhat complete D-Bus server interface.  Also
change user/group name to "_mandos".

* debian/mandos.postinst: Rename old "mandos" user and group to
                          "_mandos"; create "_mandos" user and group
                          if none exist.
* debian/mandos-client.postinst: - '' -

* initramfs-tools-hook: Try "_mandos" before "mandos" as user and
                        group name.

* mandos (_datetime_to_dbus_struct): New; was previously local.
  (Client.started): Renamed to "last_started".  All users changed.
  (Client.started): New; boolean.
  (Client.dbus_object_path): New.
  (Client.check_command): Renamed to "checker_command".  All users
                          changed.
  (Client.__init__): Set and use "self.dbus_object_path".  Set
                     "self.started".
  (Client.start): Update "self.started".  Emit "self.PropertyChanged"
                  signals for both "started" and "last_started".
  (Client.stop): Update "self.started".  Emit "self.PropertyChanged"
                 signal for "started".
  (Client.checker_callback): Take additional "command" argument.  All
                             callers changed. Emit
                             "self.PropertyChanged" signal.
  (Client.bump_timeout): Emit "self.PropertyChanged" signal for
                         "last_checked_ok".
  (Client.start_checker): Emit "self.PropertyChanged" signal for
                          "checker_running".
  (Client.stop_checker): Emit "self.PropertyChanged" signal for
                         "checker_running".
  (Client.still_valid): Bug fix: use "getattr(self, started, False)"
                        instead of "self.started" in case this client
                        object is so new that the "started" attribute
                        has not been created yet.
  (Client.IntervalChanged, Client.CheckerIsRunning, Client.GetChecker,
  Client.GetCreated, Client.GetFingerprint, Client.GetHost,
  Client.GetInterval, Client.GetName, Client.GetStarted,
  Client.GetTimeout, Client.StateChanged, Client.TimeoutChanged):
  Removed; all callers changed.
  (Client.CheckerCompleted): Add "condition" and "command" arguments.
                             All callers changed.
  (Client.GetAllProperties, Client.PropertyChanged): New.
  (Client.StillValid): Renamed to "IsStillValid".
  (Client.StartChecker): Changed to its own function to avoid the
                         return value from "Client.start_checker()".
  (Client.Stop): Changed to its own function to avoid the return value
                 from "Client.stop()".
  (main): Try "_mandos" before "mandos" as user and group name.
          Removed inner function "remove_from_clients".  New inner
          class "MandosServer".

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-2018 Teddy Hogeborn
6
 
# Copyright © 2008-2018 Björn Påhlsson
 
5
# Copyright © 2008 Teddy Hogeborn
 
6
# Copyright © 2008 Björn Påhlsson
7
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
 
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
12
10
# the Free Software Foundation, either version 3 of the License, or
13
11
# (at your option) any later version.
14
12
#
15
 
#     Mandos is distributed in the hope that it will be useful, but
16
 
#     WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
#     This program is distributed in the hope that it will be useful,
 
14
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
17
15
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
16
#     GNU General Public License for more details.
19
17
20
18
# You should have received a copy of the GNU General Public License
21
 
# along with Mandos.  If not, see <http://www.gnu.org/licenses/>.
 
19
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
20
23
 
# Contact the authors at <mandos@recompile.se>.
 
21
# Contact the authors at <mandos@fukt.bsnet.se>.
24
22
25
23
 
26
 
VERSION="1.7.19"
 
24
VERSION="1.0.2"
27
25
 
28
26
KEYDIR="/etc/keys/mandos"
29
 
KEYTYPE=RSA
30
 
KEYLENGTH=4096
31
 
SUBKEYTYPE=RSA
32
 
SUBKEYLENGTH=4096
 
27
KEYTYPE=DSA
 
28
KEYLENGTH=2048
 
29
SUBKEYTYPE=ELG-E
 
30
SUBKEYLENGTH=2048
33
31
KEYNAME="`hostname --fqdn 2>/dev/null || hostname`"
34
32
KEYEMAIL=""
35
 
KEYCOMMENT=""
 
33
KEYCOMMENT="Mandos client key"
36
34
KEYEXPIRE=0
37
35
FORCE=no
38
 
SSH=yes
39
36
KEYCOMMENT_ORIG="$KEYCOMMENT"
40
37
mode=keygen
41
38
 
44
41
fi
45
42
 
46
43
# Parse options
47
 
TEMP=`getopt --options vhpF:d:t:l:s:L:n:e:c:x:fS \
48
 
    --longoptions version,help,password,passfile:,dir:,type:,length:,subtype:,sublength:,name:,email:,comment:,expire:,force,no-ssh \
 
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 \
49
46
    --name "$0" -- "$@"`
50
47
 
51
48
help(){
52
 
basename="`basename "$0"`"
 
49
basename="`basename $0`"
53
50
cat <<EOF
54
51
Usage: $basename [ -v | --version ]
55
52
       $basename [ -h | --help ]
63
60
  -v, --version         Show program's version number and exit
64
61
  -h, --help            Show this help message and exit
65
62
  -d DIR, --dir DIR     Target directory for key files
66
 
  -t TYPE, --type TYPE  Key type.  Default is RSA.
 
63
  -t TYPE, --type TYPE  Key type.  Default is DSA.
67
64
  -l BITS, --length BITS
68
 
                        Key length in bits.  Default is 4096.
 
65
                        Key length in bits.  Default is 2048.
69
66
  -s TYPE, --subtype TYPE
70
 
                        Subkey type.  Default is RSA.
 
67
                        Subkey type.  Default is ELG-E.
71
68
  -L BITS, --sublength BITS
72
 
                        Subkey length in bits.  Default is 4096.
 
69
                        Subkey length in bits.  Default is 2048.
73
70
  -n NAME, --name NAME  Name of key.  Default is the FQDN.
74
71
  -e ADDRESS, --email ADDRESS
75
72
                        Email address of key.  Default is empty.
76
73
  -c TEXT, --comment TEXT
77
 
                        Comment field for key.  The default is empty.
 
74
                        Comment field for key.  The default value is
 
75
                        "Mandos client key".
78
76
  -x TIME, --expire TIME
79
77
                        Key expire time.  Default is no expiration.
80
78
                        See gpg(1) for syntax.
88
86
                        Encrypt a password from FILE using the key in
89
87
                        the key directory.  All options other than
90
88
                        --dir and --name are ignored.
91
 
  -S, --no-ssh          Don't get SSH key or set "checker" option.
92
89
EOF
93
90
}
94
91
 
107
104
        -c|--comment) KEYCOMMENT="$2"; shift 2;;
108
105
        -x|--expire) KEYEXPIRE="$2"; shift 2;;
109
106
        -f|--force) FORCE=yes; shift;;
110
 
        -S|--no-ssh) SSH=no; shift;;
111
107
        -v|--version) echo "$0 $VERSION"; exit;;
112
108
        -h|--help) help; exit;;
113
109
        --) shift; break;;
115
111
    esac
116
112
done
117
113
if [ "$#" -gt 0 ]; then
118
 
    echo "Unknown arguments: '$*'" >&2
 
114
    echo "Unknown arguments: '$@'" >&2
119
115
    exit 1
120
116
fi
121
117
 
151
147
        echo "Invalid key length" >&2
152
148
        exit 1
153
149
    fi
154
 
    
 
150
 
155
151
    if [ -z "$KEYEXPIRE" ]; then
156
152
        echo "Empty key expiration" >&2
157
153
        exit 1
163
159
        [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|*) FORCE=0;;
164
160
    esac
165
161
    
166
 
    if { [ -e "$SECKEYFILE" ] || [ -e "$PUBKEYFILE" ]; } \
167
 
        && [ "$FORCE" -eq 0 ]; then
 
162
    if [ \( -e "$SECKEYFILE" -o -e "$PUBKEYFILE" \) \
 
163
        -a "$FORCE" -eq 0 ]; then
168
164
        echo "Refusing to overwrite old key files; use --force" >&2
169
165
        exit 1
170
166
    fi
176
172
    if [ -n "$KEYEMAIL" ]; then
177
173
        KEYEMAILLINE="Name-Email: $KEYEMAIL"
178
174
    fi
179
 
    
 
175
 
180
176
    # Create temporary gpg batch file
181
177
    BATCHFILE="`mktemp -t mandos-keygen-batch.XXXXXXXXXX`"
182
178
fi
193
189
trap "
194
190
set +e; \
195
191
test -n \"$SECFILE\" && shred --remove \"$SECFILE\"; \
196
 
shred --remove \"$RINGDIR\"/sec* 2>/dev/null;
 
192
shred --remove \"$RINGDIR\"/sec*;
197
193
test -n \"$BATCHFILE\" && rm --force \"$BATCHFILE\"; \
198
194
rm --recursive --force \"$RINGDIR\";
199
 
tty --quiet && stty echo; \
 
195
stty echo; \
200
196
" EXIT
201
197
 
202
 
set -e
203
 
 
204
198
umask 077
205
199
 
206
200
if [ "$mode" = keygen ]; then
208
202
    cat >"$BATCHFILE" <<-EOF
209
203
        Key-Type: $KEYTYPE
210
204
        Key-Length: $KEYLENGTH
211
 
        Key-Usage: sign,auth
 
205
        #Key-Usage: encrypt,sign,auth
212
206
        Subkey-Type: $SUBKEYTYPE
213
207
        Subkey-Length: $SUBKEYLENGTH
214
 
        Subkey-Usage: encrypt
 
208
        #Subkey-Usage: encrypt,sign,auth
215
209
        Name-Real: $KEYNAME
216
210
        $KEYCOMMENTLINE
217
211
        $KEYEMAILLINE
220
214
        #Handle: <no-spaces>
221
215
        #%pubring pubring.gpg
222
216
        #%secring secring.gpg
223
 
        %no-protection
224
217
        %commit
225
218
        EOF
226
219
    
227
 
    if tty --quiet; then
228
 
        cat <<-EOF
229
 
        Note: Due to entropy requirements, key generation could take
230
 
        anything from a few minutes to SEVERAL HOURS.  Please be
231
 
        patient and/or supply the system with more entropy if needed.
232
 
        EOF
233
 
        echo -n "Started: "
234
 
        date
235
 
    fi
236
 
    
237
 
    # Make sure trustdb.gpg exists;
238
 
    # this is a workaround for Debian bug #737128
239
 
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
240
 
        --homedir "$RINGDIR" \
241
 
        --import-ownertrust < /dev/null
242
220
    # Generate a new key in the key rings
243
221
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
244
222
        --homedir "$RINGDIR" --trust-model always \
245
223
        --gen-key "$BATCHFILE"
246
224
    rm --force "$BATCHFILE"
247
225
    
248
 
    if tty --quiet; then
249
 
        echo -n "Finished: "
250
 
        date
251
 
    fi
252
 
    
253
226
    # Backup any old key files
254
227
    if cp --backup=numbered --force "$SECKEYFILE" "$SECKEYFILE" \
255
228
        2>/dev/null; then
280
253
fi
281
254
 
282
255
if [ "$mode" = password ]; then
283
 
    
284
 
    # Make SSH be 0 or 1
285
 
    case "$SSH" in
286
 
        [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]) SSH=1;;
287
 
        [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|*) SSH=0;;
288
 
    esac
289
 
    
290
 
    if [ $SSH -eq 1 ]; then
291
 
        for ssh_keytype in ecdsa-sha2-nistp256 ed25519 rsa; do
292
 
            set +e
293
 
            ssh_fingerprint="`ssh-keyscan -t $ssh_keytype localhost 2>/dev/null`"
294
 
            err=$?
295
 
            set -e
296
 
            if [ $err -ne 0 ]; then
297
 
                ssh_fingerprint=""
298
 
                continue
299
 
            fi
300
 
            if [ -n "$ssh_fingerprint" ]; then
301
 
                ssh_fingerprint="${ssh_fingerprint#localhost }"
302
 
                break
303
 
            fi
304
 
        done
305
 
    fi
306
 
    
307
256
    # Import key into temporary key rings
308
257
    gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
309
258
        --homedir "$RINGDIR" --trust-model always --armor \
314
263
    
315
264
    # Get fingerprint of key
316
265
    FINGERPRINT="`gpg --quiet --batch --no-tty --no-options \
317
 
        --enable-dsa2 --homedir "$RINGDIR" --trust-model always \
 
266
        --enable-dsa2 --homedir \"$RINGDIR\" --trust-model always \
318
267
        --fingerprint --with-colons \
319
268
        | sed --quiet \
320
269
        --expression='/^fpr:/{s/^fpr:.*:\\([0-9A-Z]*\\):\$/\\1/p;q}'`"
323
272
    
324
273
    FILECOMMENT="Encrypted password for a Mandos client"
325
274
    
326
 
    while [ ! -s "$SECFILE" ]; do
327
 
        if [ -n "$PASSFILE" ]; then
328
 
            cat "$PASSFILE"
 
275
    if [ -n "$PASSFILE" ]; then
 
276
        cat "$PASSFILE"
 
277
    else
 
278
        stty -echo
 
279
        echo -n "Enter passphrase: " >&2
 
280
        first="$(head --lines=1 | tr --delete '\n')"
 
281
        echo -n -e "\nRepeat passphrase: " >&2
 
282
        second="$(head --lines=1 | tr --delete '\n')"
 
283
        echo >&2
 
284
        stty echo
 
285
        if [ "$first" != "$second" ]; then
 
286
            echo -e "Passphrase mismatch" >&2
 
287
            false
329
288
        else
330
 
            tty --quiet && stty -echo
331
 
            echo -n "Enter passphrase: " >/dev/tty
332
 
            read -r first
333
 
            tty --quiet && echo >&2
334
 
            echo -n "Repeat passphrase: " >/dev/tty
335
 
            read -r second
336
 
            if tty --quiet; then
337
 
                echo >&2
338
 
                stty echo
339
 
            fi
340
 
            if [ "$first" != "$second" ]; then
341
 
                echo "Passphrase mismatch" >&2
342
 
                touch "$RINGDIR"/mismatch
343
 
            else
344
 
                echo -n "$first"
345
 
            fi
346
 
        fi | gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
347
 
            --homedir "$RINGDIR" --trust-model always --armor \
348
 
            --encrypt --sign --recipient "$FINGERPRINT" --comment \
349
 
            "$FILECOMMENT" > "$SECFILE"
350
 
        if [ -e "$RINGDIR"/mismatch ]; then
351
 
            rm --force "$RINGDIR"/mismatch
352
 
            if tty --quiet; then
353
 
                > "$SECFILE"
354
 
            else
355
 
                exit 1
356
 
            fi
 
289
            echo -n "$first"
357
290
        fi
358
 
    done
 
291
    fi | gpg --quiet --batch --no-tty --no-options --enable-dsa2 \
 
292
        --homedir "$RINGDIR" --trust-model always --armor --encrypt \
 
293
        --sign --recipient "$FINGERPRINT" --comment "$FILECOMMENT" \
 
294
        > "$SECFILE"
 
295
    status="${PIPESTATUS[0]}"
 
296
    if [ "$status" -ne 0 ]; then
 
297
        exit "$status"
 
298
    fi
359
299
    
360
300
    cat <<-EOF
361
301
        [$KEYNAME]
372
312
                /^[^-]/s/^/    /p
373
313
            }
374
314
        }' < "$SECFILE"
375
 
    if [ -n "$ssh_fingerprint" ]; then
376
 
        echo 'checker = ssh-keyscan -t '"$ssh_keytype"' %%(host)s 2>/dev/null | grep --fixed-strings --line-regexp --quiet --regexp=%%(host)s" %(ssh_fingerprint)s"'
377
 
        echo "ssh_fingerprint = ${ssh_fingerprint}"
378
 
    fi
379
315
fi
380
316
 
381
317
trap - EXIT
386
322
    shred --remove "$SECFILE"
387
323
fi
388
324
# Remove the key rings
389
 
shred --remove "$RINGDIR"/sec* 2>/dev/null
 
325
shred --remove "$RINGDIR"/sec*
390
326
rm --recursive --force "$RINGDIR"