/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-ctl

  • Committer: Teddy Hogeborn
  • Date: 2015-03-10 18:03:38 UTC
  • mto: (237.7.304 trunk)
  • mto: This revision was merged to the branch mainline in revision 325.
  • Revision ID: teddy@recompile.se-20150310180338-pcxw6r2qmw9k6br9
Add ":!RSA" to GnuTLS priority string, to disallow non-DHE kx.

If Mandos was somehow made to use a non-ephemeral Diffie-Hellman key
exchange algorithm in the TLS handshake, any saved network traffic
could then be decrypted later if the Mandos client key was obtained.
By default, Mandos uses ephemeral DH key exchanges which does not have
this problem, but a non-ephemeral key exchange algorithm was still
enabled by default.  The simplest solution is to simply turn that off,
which ensures that Mandos will always use ephemeral DH key exchanges.

There is a "PFS" priority string specifier, but we can't use it because:

1. Security-wise, it is a mix between "NORMAL" and "SECURE128" - it
   enables a lot more algorithms than "SECURE256".

2. It is only available since GnuTLS 3.2.4.

Thanks to Andreas Fischer <af@bantuX.org> for reporting this issue.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
4
4
# Mandos Monitor - Control and monitor the Mandos server
5
5
6
 
# Copyright © 2008-2012 Teddy Hogeborn
7
 
# Copyright © 2008-2012 Björn Påhlsson
 
6
# Copyright © 2008-2014 Teddy Hogeborn
 
7
# Copyright © 2008-2014 Björn Påhlsson
8
8
9
9
# This program is free software: you can redistribute it and/or modify
10
10
# it under the terms of the GNU General Public License as published by
26
26
from __future__ import (division, absolute_import, print_function,
27
27
                        unicode_literals)
28
28
 
29
 
from future_builtins import *
 
29
try:
 
30
    from future_builtins import *
 
31
except ImportError:
 
32
    pass
30
33
 
31
34
import sys
32
35
import argparse
39
42
 
40
43
import dbus
41
44
 
 
45
if sys.version_info.major == 2:
 
46
    str = unicode
 
47
 
42
48
locale.setlocale(locale.LC_ALL, "")
43
49
 
44
50
tablewords = {
66
72
server_path = "/"
67
73
server_interface = domain + ".Mandos"
68
74
client_interface = domain + ".Mandos.Client"
69
 
version = "1.6.1"
70
 
 
71
 
def timedelta_to_milliseconds(td):
72
 
    """Convert a datetime.timedelta object to milliseconds"""
73
 
    return ((td.days * 24 * 60 * 60 * 1000)
74
 
            + (td.seconds * 1000)
75
 
            + (td.microseconds // 1000))
 
75
version = "1.6.9"
76
76
 
77
77
def milliseconds_to_string(ms):
78
78
    td = datetime.timedelta(0, 0, 0, ms)
79
79
    return ("{days}{hours:02}:{minutes:02}:{seconds:02}"
80
 
            .format(days = "{0}T".format(td.days) if td.days else "",
 
80
            .format(days = "{}T".format(td.days) if td.days else "",
81
81
                    hours = td.seconds // 3600,
82
82
                    minutes = (td.seconds % 3600) // 60,
83
83
                    seconds = td.seconds % 60,
151
151
    token_duration = Token(re.compile(r"P"), None,
152
152
                           frozenset((token_year, token_month,
153
153
                                      token_day, token_time,
154
 
                                      token_week))),
 
154
                                      token_week)))
155
155
    # Define starting values
156
156
    value = datetime.timedelta() # Value so far
157
157
    found_token = None
158
 
    followers = frozenset(token_duration,) # Following valid tokens
 
158
    followers = frozenset((token_duration,)) # Following valid tokens
159
159
    s = duration                # String left to parse
160
160
    # Loop until end token is found
161
161
    while found_token is not token_end:
230
230
        if keyword in ("Timeout", "Interval", "ApprovalDelay",
231
231
                       "ApprovalDuration", "ExtendedTimeout"):
232
232
            return milliseconds_to_string(value)
233
 
        return unicode(value)
 
233
        return str(value)
234
234
    
235
235
    # Create format string to print table rows
236
236
    format_string = " ".join("{{{key}:{width}}}".format(
243
243
    # Print header line
244
244
    print(format_string.format(**tablewords))
245
245
    for client in clients:
246
 
        print(format_string.format(**dict((key,
 
246
        print(format_string.format(**{ key:
247
247
                                           valuetostring(client[key],
248
 
                                                         key))
249
 
                                          for key in keywords)))
 
248
                                                         key)
 
249
                                       for key in keywords }))
250
250
 
251
251
def has_actions(options):
252
252
    return any((options.enable,
271
271
def main():
272
272
    parser = argparse.ArgumentParser()
273
273
    parser.add_argument("--version", action="version",
274
 
                        version = "%(prog)s {0}".format(version),
 
274
                        version = "%(prog)s {}".format(version),
275
275
                        help="show version number and exit")
276
276
    parser.add_argument("-a", "--all", action="store_true",
277
277
                        help="Select all clients")
310
310
    parser.add_argument("--approval-duration",
311
311
                        help="Set duration of one client approval")
312
312
    parser.add_argument("-H", "--host", help="Set host for client")
313
 
    parser.add_argument("-s", "--secret", type=file,
 
313
    parser.add_argument("-s", "--secret",
 
314
                        type=argparse.FileType(mode="rb"),
314
315
                        help="Set password blob (file) for client")
315
316
    parser.add_argument("-A", "--approve", action="store_true",
316
317
                        help="Approve any current client request")
331
332
 
332
333
    if options.check:
333
334
        fail_count, test_count = doctest.testmod()
334
 
        sys.exit(0 if fail_count == 0 else 1)
 
335
        sys.exit(os.EX_OK if fail_count == 0 else 1)
335
336
    
336
337
    try:
337
338
        bus = dbus.SystemBus()
365
366
    clients={}
366
367
    
367
368
    if options.all or not options.client:
368
 
        clients = dict((bus.get_object(busname, path), properties)
369
 
                       for path, properties in
370
 
                       mandos_clients.iteritems())
 
369
        clients = { bus.get_object(busname, path): properties
 
370
                    for path, properties in mandos_clients.items() }
371
371
    else:
372
372
        for name in options.client:
373
 
            for path, client in mandos_clients.iteritems():
 
373
            for path, client in mandos_clients.items():
374
374
                if client["Name"] == name:
375
375
                    client_objc = bus.get_object(busname, path)
376
376
                    clients[client_objc] = client
377
377
                    break
378
378
            else:
379
 
                print("Client not found on server: {0!r}"
 
379
                print("Client not found on server: {!r}"
380
380
                      .format(name), file=sys.stderr)
381
381
                sys.exit(1)
382
382
    
405
405
                """Set a Client D-Bus property, converted
406
406
                from a string to milliseconds."""
407
407
                set_client_prop(prop,
408
 
                                timedelta_to_milliseconds
409
 
                                (string_to_delta(value)))
 
408
                                string_to_delta(value).total_seconds()
 
409
                                * 1000)
410
410
            if options.remove:
411
411
                mandos_serv.RemoveClient(client.__dbus_object_path__)
412
412
            if options.enable: