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

  • Committer: Teddy Hogeborn
  • Date: 2016-07-03 03:32:28 UTC
  • Revision ID: teddy@recompile.se-20160703033228-cafpnnfs53kdg52g
Change all http:// URLs to https:// wherever possible.

* INSTALL (Prerequisites/Libraries/Mandos Server): Change "http://" to
  "https://" wherever possible.
* Makefile (FORTIFY): - '' -
* mandos.xml (SEE ALSO): - '' -
* plugin-runner.c (main): - '' -
* plugins.d/mandos-client.c (start_mandos_communication): - '' -
* plugins.d/mandos-client.xml (SEE ALSO): - '' -

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-2015 Teddy Hogeborn
7
 
# Copyright © 2008-2015 Björn Påhlsson
 
6
# Copyright © 2008-2016 Teddy Hogeborn
 
7
# Copyright © 2008-2016 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
39
39
import os
40
40
import collections
41
41
import doctest
 
42
import json
42
43
 
43
44
import dbus
44
45
 
64
65
    "ApprovalDelay": "Approval Delay",
65
66
    "ApprovalDuration": "Approval Duration",
66
67
    "Checker": "Checker",
67
 
    "ExtendedTimeout": "Extended Timeout"
 
68
    "ExtendedTimeout": "Extended Timeout",
 
69
    "Expires": "Expires",
 
70
    "LastCheckerStatus": "Last Checker Status",
68
71
}
69
72
defaultkeywords = ("Name", "Enabled", "Timeout", "LastCheckedOK")
70
73
domain = "se.recompile"
72
75
server_path = "/"
73
76
server_interface = domain + ".Mandos"
74
77
client_interface = domain + ".Mandos.Client"
75
 
version = "1.6.9"
76
 
 
 
78
version = "1.7.10"
 
79
 
 
80
 
 
81
try:
 
82
    dbus.OBJECT_MANAGER_IFACE
 
83
except AttributeError:
 
84
    dbus.OBJECT_MANAGER_IFACE = "org.freedesktop.DBus.ObjectManager"
77
85
 
78
86
def milliseconds_to_string(ms):
79
87
    td = datetime.timedelta(0, 0, 0, ms)
111
119
    # avoid excessive use of external libraries.
112
120
    
113
121
    # New type for defining tokens, syntax, and semantics all-in-one
114
 
    Token = collections.namedtuple("Token",
115
 
                                   ("regexp", # To match token; if
116
 
                                              # "value" is not None,
117
 
                                              # must have a "group"
118
 
                                              # containing digits
119
 
                                    "value",  # datetime.timedelta or
120
 
                                              # None
121
 
                                    "followers")) # Tokens valid after
122
 
                                                  # this token
 
122
    Token = collections.namedtuple("Token", (
 
123
        "regexp",  # To match token; if "value" is not None, must have
 
124
                   # a "group" containing digits
 
125
        "value",   # datetime.timedelta or None
 
126
        "followers"))           # Tokens valid after this token
123
127
    # RFC 3339 "duration" tokens, syntax, and semantics; taken from
124
128
    # the "duration" ABNF definition in RFC 3339, Appendix A.
125
129
    token_end = Token(re.compile(r"$"), None, frozenset())
178
182
                break
179
183
        else:
180
184
            # No currently valid tokens were found
181
 
            raise ValueError("Invalid RFC 3339 duration")
 
185
            raise ValueError("Invalid RFC 3339 duration: {!r}"
 
186
                             .format(duration))
182
187
    # End token found
183
188
    return value
184
189
 
186
191
def string_to_delta(interval):
187
192
    """Parse a string and return a datetime.timedelta
188
193
    
189
 
    >>> string_to_delta("7d")
 
194
    >>> string_to_delta('7d')
190
195
    datetime.timedelta(7)
191
 
    >>> string_to_delta("60s")
 
196
    >>> string_to_delta('60s')
192
197
    datetime.timedelta(0, 60)
193
 
    >>> string_to_delta("60m")
 
198
    >>> string_to_delta('60m')
194
199
    datetime.timedelta(0, 3600)
195
 
    >>> string_to_delta("24h")
 
200
    >>> string_to_delta('24h')
196
201
    datetime.timedelta(1)
197
 
    >>> string_to_delta("1w")
 
202
    >>> string_to_delta('1w')
198
203
    datetime.timedelta(7)
199
 
    >>> string_to_delta("5m 30s")
 
204
    >>> string_to_delta('5m 30s')
200
205
    datetime.timedelta(0, 330)
201
206
    """
202
207
    
278
283
                        help="Select all clients")
279
284
    parser.add_argument("-v", "--verbose", action="store_true",
280
285
                        help="Print all fields")
 
286
    parser.add_argument("-j", "--dump-json", action="store_true",
 
287
                        help="Dump client data in JSON format")
281
288
    parser.add_argument("-e", "--enable", action="store_true",
282
289
                        help="Enable client")
283
290
    parser.add_argument("-d", "--disable", action="store_true",
326
333
    if has_actions(options) and not (options.client or options.all):
327
334
        parser.error("Options require clients names or --all.")
328
335
    if options.verbose and has_actions(options):
329
 
        parser.error("--verbose can only be used alone or with"
330
 
                     " --all.")
 
336
        parser.error("--verbose can only be used alone.")
 
337
    if options.dump_json and (options.verbose or has_actions(options)):
 
338
        parser.error("--dump-json can only be used alone.")
331
339
    if options.all and not has_actions(options):
332
340
        parser.error("--all requires an action.")
333
 
 
 
341
    
334
342
    if options.check:
335
343
        fail_count, test_count = doctest.testmod()
336
344
        sys.exit(os.EX_OK if fail_count == 0 else 1)
344
352
    
345
353
    mandos_serv = dbus.Interface(mandos_dbus_objc,
346
354
                                 dbus_interface = server_interface)
 
355
    mandos_serv_object_manager = dbus.Interface(
 
356
        mandos_dbus_objc, dbus_interface = dbus.OBJECT_MANAGER_IFACE)
347
357
    
348
358
    #block stderr since dbus library prints to stderr
349
359
    null = os.open(os.path.devnull, os.O_RDWR)
352
362
    os.close(null)
353
363
    try:
354
364
        try:
355
 
            mandos_clients = mandos_serv.GetAllClientsWithProperties()
 
365
            mandos_clients = { path: ifs_and_props[client_interface]
 
366
                               for path, ifs_and_props in
 
367
                               mandos_serv_object_manager
 
368
                               .GetManagedObjects().items()
 
369
                               if client_interface in ifs_and_props }
356
370
        finally:
357
371
            #restore stderr
358
372
            os.dup2(stderrcopy, sys.stderr.fileno())
359
373
            os.close(stderrcopy)
360
 
    except dbus.exceptions.DBusException:
361
 
        print("Access denied: Accessing mandos server through dbus.",
362
 
              file=sys.stderr)
 
374
    except dbus.exceptions.DBusException as e:
 
375
        print("Access denied: Accessing mandos server through D-Bus: {}"
 
376
              .format(e), file=sys.stderr)
363
377
        sys.exit(1)
364
378
    
365
379
    # Compile dict of (clients: properties) to process
381
395
                sys.exit(1)
382
396
    
383
397
    if not has_actions(options) and clients:
384
 
        if options.verbose:
 
398
        if options.verbose or options.dump_json:
385
399
            keywords = ("Name", "Enabled", "Timeout", "LastCheckedOK",
386
400
                        "Created", "Interval", "Host", "Fingerprint",
387
401
                        "CheckerRunning", "LastEnabled",
388
402
                        "ApprovalPending", "ApprovedByDefault",
389
403
                        "LastApprovalRequest", "ApprovalDelay",
390
404
                        "ApprovalDuration", "Checker",
391
 
                        "ExtendedTimeout")
 
405
                        "ExtendedTimeout", "Expires",
 
406
                        "LastCheckerStatus")
392
407
        else:
393
408
            keywords = defaultkeywords
394
409
        
395
 
        print_clients(clients.values(), keywords)
 
410
        if options.dump_json:
 
411
            json.dump({client["Name"]: {key:
 
412
                                        bool(client[key])
 
413
                                        if isinstance(client[key],
 
414
                                                      dbus.Boolean)
 
415
                                        else client[key]
 
416
                                        for key in keywords }
 
417
                       for client in clients.values() },
 
418
                      fp = sys.stdout, indent = 4,
 
419
                      separators = (',', ': '))
 
420
            print()
 
421
        else:
 
422
            print_clients(clients.values(), keywords)
396
423
    else:
397
424
        # Process each client in the list by all selected options
398
425
        for client in clients: