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.
500
483
self.busname = domain + '.Mandos'
501
484
self.main_loop = gobject.MainLoop()
485
self.bus = dbus.SystemBus()
486
mandos_dbus_objc = self.bus.get_object(
487
self.busname, "/", follow_name_owner_changes=True)
488
self.mandos_serv = dbus.Interface(mandos_dbus_objc,
492
mandos_clients = (self.mandos_serv
493
.GetAllClientsWithProperties())
494
except dbus.exceptions.DBusException:
495
mandos_clients = dbus.Dictionary()
498
.connect_to_signal("ClientRemoved",
499
self.find_and_remove_client,
500
dbus_interface=server_interface,
503
.connect_to_signal("ClientAdded",
505
dbus_interface=server_interface,
508
.connect_to_signal("ClientNotFound",
509
self.client_not_found,
510
dbus_interface=server_interface,
512
for path, client in mandos_clients.iteritems():
513
client_proxy_object = self.bus.get_object(self.busname,
515
self.add_client(MandosClientWidget(server_proxy_object
518
=client_proxy_object,
503
528
def client_not_found(self, fingerprint, address):
504
529
self.log_message(("Client with address %s and fingerprint %s"
554
580
#self.log_message("Wrap mode: " + self.log_wrap)
556
582
def find_and_remove_client(self, path, name):
557
"""Find a client by its object path and remove it.
583
"""Find an client from its object path and remove it.
559
585
This is connected to the ClientRemoved signal from the
560
586
Mandos server object."""
562
588
client = self.clients_dict[path]
565
self.log_message("Unknown client %r (%r) removed", name,
592
self.remove_client(client, path)
570
594
def add_new_client(self, path):
571
595
client_proxy_object = self.bus.get_object(self.busname, path)
610
634
"""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
636
self._input_callback_tag = (gobject.io_add_watch
656
637
(sys.stdin.fileno(),