4
4
# Mandos Monitor - Control and monitor the Mandos server
6
# Copyright © 2009-2012 Teddy Hogeborn
7
# Copyright © 2009-2012 Björn Påhlsson
6
# Copyright © 2009-2011 Teddy Hogeborn
7
# Copyright © 2009-2011 Björn Påhlsson
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
19
19
# You should have received a copy of the GNU General Public License
20
20
# along with this program. If not, see <http://www.gnu.org/licenses/>.
22
# Contact the authors at <mandos@recompile.se>.
22
# Contact the authors at <mandos@fukt.bsnet.se>.
25
from __future__ import (division, absolute_import, print_function,
25
from __future__ import division, absolute_import, print_function, unicode_literals
49
48
logging.getLogger('dbus.proxies').setLevel(logging.CRITICAL)
51
50
# Some useful constants
52
domain = 'se.recompile'
51
domain = 'se.bsnet.fukt'
53
52
server_interface = domain + '.Mandos'
54
53
client_interface = domain + '.Mandos.Client'
57
56
# Always run in monochrome mode
58
57
urwid.curses_display.curses.has_colors = lambda : False
87
86
self.proxy = proxy_object # Mandos Client proxy object
89
88
self.properties = dict()
90
self.property_changed_match = (
91
self.proxy.connect_to_signal("PropertyChanged",
92
self.property_changed,
89
self.proxy.connect_to_signal("PropertyChanged",
90
self.property_changed,
96
94
self.properties.update(
97
95
self.proxy.GetAll(client_interface,
98
96
dbus_interface = dbus.PROPERTIES_IFACE))
100
#XXX This breaks good super behaviour
98
#XXX This break good super behaviour!
101
99
# super(MandosClientPropertyCache, self).__init__(
102
100
# *args, **kwargs)
108
106
# Update properties dict with new value
109
107
self.properties[property] = value
111
def delete(self, *args, **kwargs):
112
self.property_changed_match.remove()
113
super(MandosClientPropertyCache, self).__init__(
117
110
class MandosClientWidget(urwid.FlowWidget, MandosClientPropertyCache):
161
154
if self.need_approval:
162
155
self.using_timer(True)
164
self.match_objects = (
165
self.proxy.connect_to_signal("CheckerCompleted",
166
self.checker_completed,
169
self.proxy.connect_to_signal("CheckerStarted",
170
self.checker_started,
173
self.proxy.connect_to_signal("GotSecret",
177
self.proxy.connect_to_signal("NeedApproval",
181
self.proxy.connect_to_signal("Rejected",
185
#self.logger('Created client %s' % (self.properties["Name"]))
157
self.proxy.connect_to_signal("CheckerCompleted",
158
self.checker_completed,
161
self.proxy.connect_to_signal("CheckerStarted",
162
self.checker_started,
165
self.proxy.connect_to_signal("GotSecret",
169
self.proxy.connect_to_signal("NeedApproval",
173
self.proxy.connect_to_signal("Rejected",
187
178
def property_changed(self, property=None, value=None):
188
179
super(self, MandosClientWidget).property_changed(property,
244
234
def checker_started(self, command):
245
"""Server signals that a checker started. This could be useful
246
to log in the future. """
247
235
#self.logger('Client %s started checker "%s"'
248
236
# % (self.properties["Name"], unicode(command)))
317
305
message = "Denial in %s. (a)pprove?"
318
306
message = message % unicode(timer).rsplit(".", 1)[0]
319
307
elif self.last_checker_failed:
320
# When checker has failed, print a timer until client expires
321
expires = self.properties["Expires"]
323
timer = datetime.timedelta(0)
325
expires = datetime.datetime.strptime(expires,
326
'%Y-%m-%dT%H:%M:%S.%f')
327
timer = expires - datetime.datetime.utcnow()
308
timeout = datetime.timedelta(milliseconds
311
last_ok = isoformat_to_datetime(
312
max((self.properties["LastCheckedOK"]
313
or self.properties["Created"]),
314
self.properties["LastEnabled"]))
315
timer = timeout - (datetime.datetime.utcnow() - last_ok)
328
316
message = ('A checker has failed! Time until client'
329
317
' gets disabled: %s'
330
318
% unicode(timer).rsplit(".", 1)[0])
349
337
self.update_hook()
351
339
def update_timer(self):
352
"""called by gobject. Will indefinitely loop until
353
gobject.source_remove() on tag is called"""
355
342
return True # Keep calling this
357
def delete(self, *args, **kwargs):
358
345
if self._update_timer_callback_tag is not None:
359
346
gobject.source_remove(self._update_timer_callback_tag)
360
347
self._update_timer_callback_tag = None
361
for match in self.match_objects:
363
self.match_objects = ()
364
348
if self.delete_hook is not None:
365
349
self.delete_hook(self)
366
return super(MandosClientWidget, self).delete(*args, **kwargs)
368
351
def render(self, maxcolrow, focus=False):
369
352
"""Render differently if we have focus.
376
359
This overrides the method from urwid.FlowWidget"""
378
self.proxy.Enable(dbus_interface = client_interface,
361
self.proxy.Enable(dbus_interface = client_interface)
381
self.proxy.Disable(dbus_interface = client_interface,
363
self.proxy.Disable(dbus_interface = client_interface)
384
365
self.proxy.Approve(dbus.Boolean(True, variant_level=1),
385
dbus_interface = client_interface,
366
dbus_interface = client_interface)
388
368
self.proxy.Approve(dbus.Boolean(False, variant_level=1),
389
dbus_interface = client_interface,
369
dbus_interface = client_interface)
391
370
elif key == "R" or key == "_" or key == "ctrl k":
392
371
self.server_proxy_object.RemoveClient(self.proxy
396
self.proxy.StartChecker(dbus_interface = client_interface,
374
self.proxy.StartChecker(dbus_interface = client_interface)
399
self.proxy.StopChecker(dbus_interface = client_interface,
376
self.proxy.StopChecker(dbus_interface = client_interface)
402
self.proxy.CheckedOK(dbus_interface = client_interface,
378
self.proxy.CheckedOK(dbus_interface = client_interface)
405
380
# elif key == "p" or key == "=":
406
381
# self.proxy.pause()
500
475
self.busname = domain + '.Mandos'
501
476
self.main_loop = gobject.MainLoop()
477
self.bus = dbus.SystemBus()
478
mandos_dbus_objc = self.bus.get_object(
479
self.busname, "/", follow_name_owner_changes=True)
480
self.mandos_serv = dbus.Interface(mandos_dbus_objc,
484
mandos_clients = (self.mandos_serv
485
.GetAllClientsWithProperties())
486
except dbus.exceptions.DBusException:
487
mandos_clients = dbus.Dictionary()
490
.connect_to_signal("ClientRemoved",
491
self.find_and_remove_client,
492
dbus_interface=server_interface,
495
.connect_to_signal("ClientAdded",
497
dbus_interface=server_interface,
500
.connect_to_signal("ClientNotFound",
501
self.client_not_found,
502
dbus_interface=server_interface,
504
for path, client in mandos_clients.iteritems():
505
client_proxy_object = self.bus.get_object(self.busname,
507
self.add_client(MandosClientWidget(server_proxy_object
510
=client_proxy_object,
503
520
def client_not_found(self, fingerprint, address):
504
521
self.log_message(("Client with address %s and fingerprint %s"
554
572
#self.log_message("Wrap mode: " + self.log_wrap)
556
574
def find_and_remove_client(self, path, name):
557
"""Find a client by its object path and remove it.
575
"""Find an client from its object path and remove it.
559
577
This is connected to the ClientRemoved signal from the
560
578
Mandos server object."""
562
580
client = self.clients_dict[path]
565
self.log_message("Unknown client %r (%r) removed", name,
584
self.remove_client(client, path)
570
586
def add_new_client(self, path):
571
587
client_proxy_object = self.bus.get_object(self.busname, path)
610
626
"""Start the main loop and exit when it's done."""
611
self.bus = dbus.SystemBus()
612
mandos_dbus_objc = self.bus.get_object(
613
self.busname, "/", follow_name_owner_changes=True)
614
self.mandos_serv = dbus.Interface(mandos_dbus_objc,
618
mandos_clients = (self.mandos_serv
619
.GetAllClientsWithProperties())
620
except dbus.exceptions.DBusException:
621
mandos_clients = dbus.Dictionary()
624
.connect_to_signal("ClientRemoved",
625
self.find_and_remove_client,
626
dbus_interface=server_interface,
629
.connect_to_signal("ClientAdded",
631
dbus_interface=server_interface,
634
.connect_to_signal("ClientNotFound",
635
self.client_not_found,
636
dbus_interface=server_interface,
638
for path, client in mandos_clients.iteritems():
639
client_proxy_object = self.bus.get_object(self.busname,
641
self.add_client(MandosClientWidget(server_proxy_object
644
=client_proxy_object,
655
628
self._input_callback_tag = (gobject.io_add_watch
656
629
(sys.stdin.fileno(),