344
343
for key in self.keywords})
346
## Classes for commands.
348
# Abstract classes first
349
class Command(object):
350
"""Abstract class for commands"""
351
def run(self, clients):
352
"""Normal commands should implement run_on_one_client(), but
353
commands which want to operate on all clients at the same time
354
can override this run() method instead."""
355
for client in clients:
356
self.run_on_one_client(client)
358
class PrintCmd(Command):
359
"""Abstract class for commands printing client details"""
360
all_keywords = ("Name", "Enabled", "Timeout", "LastCheckedOK",
361
"Created", "Interval", "Host", "KeyID",
362
"Fingerprint", "CheckerRunning", "LastEnabled",
363
"ApprovalPending", "ApprovedByDefault",
364
"LastApprovalRequest", "ApprovalDelay",
365
"ApprovalDuration", "Checker", "ExtendedTimeout",
366
"Expires", "LastCheckerStatus")
367
def run(self, clients):
368
print(self.output(clients))
370
class PropertyCmd(Command):
371
"""Abstract class for Actions for setting one client property"""
372
def run_on_one_client(self, client):
373
"""Set the Client's D-Bus property"""
374
client.Set(client_interface, self.property, self.value_to_set,
375
dbus_interface=dbus.PROPERTIES_IFACE)
377
class ValueArgumentMixIn(object):
378
"""Mixin class for commands taking a value as argument"""
379
def __init__(self, value):
380
self.value_to_set = value
382
class MillisecondsValueArgumentMixIn(ValueArgumentMixIn):
383
"""Mixin class for commands taking a value argument as
386
def value_to_set(self):
389
def value_to_set(self, value):
390
"""When setting, convert value to a datetime.timedelta"""
391
self._vts = string_to_delta(value).total_seconds() * 1000
393
# Actual (non-abstract) command classes
395
class PrintTableCmd(PrintCmd):
396
def __init__(self, verbose=False):
397
self.verbose = verbose
398
def output(self, clients):
400
keywords = self.all_keywords
402
keywords = ("Name", "Enabled", "Timeout", "LastCheckedOK")
403
return str(TableOfClients(clients.values(), keywords))
405
class DumpJSONCmd(PrintCmd):
406
def output(self, clients):
407
data = {client["Name"]:
408
{key: self.dbus_boolean_to_bool(client[key])
409
for key in self.all_keywords}
410
for client in clients.values()}
411
return json.dumps(data, indent=4, separators=(',', ': '))
413
def dbus_boolean_to_bool(value):
414
if isinstance(value, dbus.Boolean):
418
class IsEnabledCmd(Command):
419
def run_on_one_client(self, client):
420
if self.is_enabled(client):
423
def is_enabled(self, client):
424
return client.Get(client_interface, "Enabled",
425
dbus_interface=dbus.PROPERTIES_IFACE)
427
class RemoveCmd(Command):
428
def __init__(self, mandos):
430
def run_on_one_client(self, client):
431
self.mandos.RemoveClient(client.__dbus_object_path__)
433
class ApproveCmd(Command):
434
def run_on_one_client(self, client):
435
client.Approve(dbus.Boolean(True),
436
dbus_interface=client_interface)
438
class DenyCmd(Command):
439
def run_on_one_client(self, client):
440
client.Approve(dbus.Boolean(False),
441
dbus_interface=client_interface)
443
class EnableCmd(PropertyCmd):
445
value_to_set = dbus.Boolean(True)
447
class DisableCmd(PropertyCmd):
449
value_to_set = dbus.Boolean(False)
451
class BumpTimeoutCmd(PropertyCmd):
452
property = "LastCheckedOK"
455
class StartCheckerCmd(PropertyCmd):
456
property = "CheckerRunning"
457
value_to_set = dbus.Boolean(True)
459
class StopCheckerCmd(PropertyCmd):
460
property = "CheckerRunning"
461
value_to_set = dbus.Boolean(False)
463
class ApproveByDefaultCmd(PropertyCmd):
464
property = "ApprovedByDefault"
465
value_to_set = dbus.Boolean(True)
467
class DenyByDefaultCmd(PropertyCmd):
468
property = "ApprovedByDefault"
469
value_to_set = dbus.Boolean(False)
471
class SetCheckerCmd(PropertyCmd, ValueArgumentMixIn):
474
class SetHostCmd(PropertyCmd, ValueArgumentMixIn):
477
class SetSecretCmd(PropertyCmd, ValueArgumentMixIn):
480
class SetTimeoutCmd(PropertyCmd, MillisecondsValueArgumentMixIn):
483
class SetExtendedTimeoutCmd(PropertyCmd,
484
MillisecondsValueArgumentMixIn):
485
property = "ExtendedTimeout"
487
class SetIntervalCmd(PropertyCmd, MillisecondsValueArgumentMixIn):
488
property = "Interval"
490
class SetApprovalDelayCmd(PropertyCmd,
491
MillisecondsValueArgumentMixIn):
492
property = "ApprovalDelay"
494
class SetApprovalDurationCmd(PropertyCmd,
495
MillisecondsValueArgumentMixIn):
496
property = "ApprovalDuration"
347
498
def has_actions(options):
348
499
return any((options.enable,
455
606
mandos_serv_object_manager = dbus.Interface(
456
607
mandos_dbus_objc, dbus_interface=dbus.OBJECT_MANAGER_IFACE)
611
if options.dump_json:
612
commands.append(DumpJSONCmd())
615
commands.append(EnableCmd())
618
commands.append(DisableCmd())
620
if options.bump_timeout:
621
commands.append(BumpTimeoutCmd(options.bump_timeout))
623
if options.start_checker:
624
commands.append(StartCheckerCmd())
626
if options.stop_checker:
627
commands.append(StopCheckerCmd())
629
if options.is_enabled:
630
commands.append(IsEnabledCmd())
633
commands.append(RemoveCmd(mandos_serv))
635
if options.checker is not None:
636
commands.append(SetCheckerCmd())
638
if options.timeout is not None:
639
commands.append(SetTimeoutCmd(options.timeout))
641
if options.extended_timeout:
643
SetExtendedTimeoutCmd(options.extended_timeout))
645
if options.interval is not None:
646
command.append(SetIntervalCmd(options.interval))
648
if options.approved_by_default is not None:
649
if options.approved_by_default:
650
command.append(ApproveByDefaultCmd())
652
command.append(DenyByDefaultCmd())
654
if options.approval_delay is not None:
655
command.append(SetApprovalDelayCmd(options.approval_delay))
657
if options.approval_duration is not None:
659
SetApprovalDurationCmd(options.approval_duration))
661
if options.host is not None:
662
command.append(SetHostCmd(options.host))
664
if options.secret is not None:
665
command.append(SetSecretCmd(options.secret))
668
commands.append(ApproveCmd())
671
commands.append(DenyCmd())
673
# If no command option has been given, show table of clients,
674
# optionally verbosely
676
commands.append(PrintTableCmd(verbose=options.verbose))
458
678
# block stderr since dbus library prints to stderr
459
679
null = os.open(os.path.devnull, os.O_RDWR)
460
680
stderrcopy = os.dup(sys.stderr.fileno())
493
713
log.critical("Client not found on server: %r", name)
496
if not has_actions(options) and clients:
497
if options.verbose or options.dump_json:
498
keywords = ("Name", "Enabled", "Timeout", "LastCheckedOK",
499
"Created", "Interval", "Host", "KeyID",
500
"Fingerprint", "CheckerRunning",
501
"LastEnabled", "ApprovalPending",
502
"ApprovedByDefault", "LastApprovalRequest",
503
"ApprovalDelay", "ApprovalDuration",
504
"Checker", "ExtendedTimeout", "Expires",
507
keywords = defaultkeywords
509
if options.dump_json:
510
json.dump({client["Name"]: {key:
512
if isinstance(client[key],
516
for client in clients.values()},
517
fp=sys.stdout, indent=4,
518
separators=(',', ': '))
521
print(TableOfClients(clients.values(), keywords))
523
# Process each client in the list by all selected options
524
for client in clients:
526
def set_client_prop(prop, value):
527
"""Set a Client D-Bus property"""
528
client.Set(client_interface, prop, value,
529
dbus_interface=dbus.PROPERTIES_IFACE)
531
def set_client_prop_ms(prop, value):
532
"""Set a Client D-Bus property, converted
533
from a string to milliseconds."""
534
set_client_prop(prop,
535
string_to_delta(value).total_seconds()
539
mandos_serv.RemoveClient(client.__dbus_object_path__)
541
set_client_prop("Enabled", dbus.Boolean(True))
543
set_client_prop("Enabled", dbus.Boolean(False))
544
if options.bump_timeout:
545
set_client_prop("LastCheckedOK", "")
546
if options.start_checker:
547
set_client_prop("CheckerRunning", dbus.Boolean(True))
548
if options.stop_checker:
549
set_client_prop("CheckerRunning", dbus.Boolean(False))
550
if options.is_enabled:
551
if client.Get(client_interface, "Enabled",
552
dbus_interface=dbus.PROPERTIES_IFACE):
556
if options.checker is not None:
557
set_client_prop("Checker", options.checker)
558
if options.host is not None:
559
set_client_prop("Host", options.host)
560
if options.interval is not None:
561
set_client_prop_ms("Interval", options.interval)
562
if options.approval_delay is not None:
563
set_client_prop_ms("ApprovalDelay",
564
options.approval_delay)
565
if options.approval_duration is not None:
566
set_client_prop_ms("ApprovalDuration",
567
options.approval_duration)
568
if options.timeout is not None:
569
set_client_prop_ms("Timeout", options.timeout)
570
if options.extended_timeout is not None:
571
set_client_prop_ms("ExtendedTimeout",
572
options.extended_timeout)
573
if options.secret is not None:
574
set_client_prop("Secret",
575
dbus.ByteArray(options.secret.read()))
576
if options.approved_by_default is not None:
577
set_client_prop("ApprovedByDefault",
579
.approved_by_default))
581
client.Approve(dbus.Boolean(True),
582
dbus_interface=client_interface)
584
client.Approve(dbus.Boolean(False),
585
dbus_interface=client_interface)
716
# Run all commands on clients
717
for command in commands:
588
721
class Test_milliseconds_to_string(unittest.TestCase):