49
51
if sys.version_info.major == 2:
53
log = logging.getLogger(os.path.basename(sys.argv[0]))
54
logging.basicConfig(level="NOTSET", # Show all messages
55
format="%(message)s") # Show basic log messages
57
logging.captureWarnings(True) # Show warnings via the logging system
59
locale.setlocale(locale.LC_ALL, "")
61
logging.getLogger("dbus.proxies").setLevel(logging.CRITICAL)
54
locale.setlocale(locale.LC_ALL, '')
56
logging.getLogger('dbus.proxies').setLevel(logging.CRITICAL)
63
58
# Some useful constants
64
domain = "se.recompile"
65
server_interface = domain + ".Mandos"
66
client_interface = domain + ".Mandos.Client"
59
domain = 'se.recompile'
60
server_interface = domain + '.Mandos'
61
client_interface = domain + '.Mandos.Client'
70
65
dbus.OBJECT_MANAGER_IFACE
129
124
def __init__(self, server_proxy_object=None, update_hook=None,
130
delete_hook=None, **kwargs):
125
delete_hook=None, logger=None, **kwargs):
131
126
# Called on update
132
127
self.update_hook = update_hook
133
128
# Called on delete
134
129
self.delete_hook = delete_hook
135
130
# Mandos Server proxy object
136
131
self.server_proxy_object = server_proxy_object
138
135
self._update_timer_callback_tag = None
175
173
if flag and self._update_timer_callback_tag is None:
176
174
# Will update the shown timer value every second
177
self._update_timer_callback_tag = (
178
GLib.timeout_add(1000,
179
glib_safely(self.update_timer)))
175
self._update_timer_callback_tag = (GLib.timeout_add
180
178
elif not (flag or self._update_timer_callback_tag is None):
181
179
GLib.source_remove(self._update_timer_callback_tag)
182
180
self._update_timer_callback_tag = None
184
182
def checker_completed(self, exitstatus, condition, command):
185
183
if exitstatus == 0:
186
log.debug('Checker for client %s (command "%s")'
187
" succeeded", self.properties["Name"], command)
184
self.logger('Checker for client {} (command "{}")'
185
' succeeded'.format(self.properties["Name"],
191
190
if os.WIFEXITED(condition):
192
log.info('Checker for client %s (command "%s") failed'
193
" with exit code %d", self.properties["Name"],
194
command, os.WEXITSTATUS(condition))
191
self.logger('Checker for client {} (command "{}") failed'
193
.format(self.properties["Name"], command,
194
os.WEXITSTATUS(condition)))
195
195
elif os.WIFSIGNALED(condition):
196
log.info('Checker for client %s (command "%s") was'
197
" killed by signal %d", self.properties["Name"],
198
command, os.WTERMSIG(condition))
196
self.logger('Checker for client {} (command "{}") was'
197
' killed by signal {}'
198
.format(self.properties["Name"], command,
199
os.WTERMSIG(condition)))
201
202
def checker_started(self, command):
202
203
"""Server signals that a checker started."""
203
log.debug('Client %s started checker "%s"',
204
self.properties["Name"], command)
204
self.logger('Client {} started checker "{}"'
205
.format(self.properties["Name"],
206
208
def got_secret(self):
207
log.info("Client %s received its secret",
208
self.properties["Name"])
209
self.logger('Client {} received its secret'
210
.format(self.properties["Name"]))
210
212
def need_approval(self, timeout, default):
212
message = "Client %s needs approval within %f seconds"
214
message = 'Client {} needs approval within {} seconds'
214
message = "Client %s will get its secret in %f seconds"
215
log.info(message, self.properties["Name"], timeout/1000)
216
message = 'Client {} will get its secret in {} seconds'
217
self.logger(message.format(self.properties["Name"],
217
220
def rejected(self, reason):
218
log.info("Client %s was rejected; reason: %s",
219
self.properties["Name"], reason)
221
self.logger('Client {} was rejected; reason: {}'
222
.format(self.properties["Name"], reason))
221
224
def selectable(self):
222
225
"""Make this a "selectable" widget.
276
279
timer = datetime.timedelta(0)
278
281
expires = (datetime.datetime.strptime
279
(expires, "%Y-%m-%dT%H:%M:%S.%f"))
282
(expires, '%Y-%m-%dT%H:%M:%S.%f'))
280
283
timer = max(expires - datetime.datetime.utcnow(),
281
284
datetime.timedelta())
282
message = ("A checker has failed! Time until client"
285
message = ('A checker has failed! Time until client'
284
287
.format(str(timer).rsplit(".", 1)[0]))
285
288
self.using_timer(True)
403
class UserInterface(object):
411
404
"""This is the entire user interface - the whole screen
412
405
with boxes, lists of client widgets, etc.
414
def __init__(self, max_log_length=1000):
407
def __init__(self, max_log_length=1000, log_level=1):
415
408
DBusGMainLoop(set_as_default=True)
417
410
self.screen = urwid.curses_display.Screen()
463
458
self.log_visible = True
464
459
self.log_wrap = "any"
466
self.loghandler = UILogHandler(self)
469
self.add_log_line(("bold",
470
"Mandos Monitor version " + version))
471
self.add_log_line(("bold", "q: Quit ?: Help"))
462
self.log_message_raw(("bold",
463
"Mandos Monitor version " + version))
464
self.log_message_raw(("bold",
473
self.busname = domain + ".Mandos"
467
self.busname = domain + '.Mandos'
474
468
self.main_loop = GLib.MainLoop()
476
470
def client_not_found(self, key_id, address):
477
log.info("Client with address %s and key ID %s could"
478
" not be found", address, key_id)
471
self.log_message("Client with address {} and key ID {} could"
472
" not be found".format(address, key_id))
480
474
def rebuild(self):
481
475
"""This rebuilds the User Interface.
492
486
self.uilist.append(self.logbox)
493
487
self.topwidget = urwid.Pile(self.uilist)
495
def add_log_line(self, markup):
489
def log_message(self, message, level=1):
490
"""Log message formatted with timestamp"""
491
if level < self.log_level:
493
timestamp = datetime.datetime.now().isoformat()
494
self.log_message_raw("{}: {}".format(timestamp, message),
497
def log_message_raw(self, markup, level=1):
498
"""Add a log message to the log buffer."""
499
if level < self.log_level:
496
501
self.log.append(urwid.Text(markup, wrap=self.log_wrap))
497
502
if self.max_log_length:
498
503
if len(self.log) > self.max_log_length:
499
del self.log[0:(len(self.log) - self.max_log_length)]
504
del self.log[0:len(self.log)-self.max_log_length-1]
500
505
self.logbox.set_focus(len(self.logbox.body.contents)-1,
501
506
coming_from="above")
588
592
mandos_clients = (self.mandos_serv
589
593
.GetAllClientsWithProperties())
590
594
if not mandos_clients:
591
log.warning("Note: Server has no clients.")
595
self.log_message_raw(("bold",
596
"Note: Server has no clients."))
592
597
except dbus.exceptions.DBusException:
593
log.warning("Note: No Mandos server running.")
598
self.log_message_raw(("bold",
599
"Note: No Mandos server running."))
594
600
mandos_clients = dbus.Dictionary()
596
602
(self.mandos_serv
701
707
self.topwidget.set_focus(self.logbox)
704
if log.level < logging.INFO:
705
log.setLevel(logging.INFO)
706
log.info("Verbose mode: Off")
710
if self.log_level == 0:
712
self.log_message("Verbose mode: Off")
708
log.setLevel(logging.NOTSET)
709
log.info("Verbose mode: On")
715
self.log_message("Verbose mode: On")
710
716
# elif (key == "end" or key == "meta >" or key == "G"
711
717
# or key == ">"):
712
718
# pass # xxx end-of-buffer
734
class UILogHandler(logging.Handler):
735
def __init__(self, ui, *args, **kwargs):
737
super(UILogHandler, self).__init__(*args, **kwargs)
739
logging.Formatter("%(asctime)s: %(message)s"))
740
def emit(self, record):
741
msg = self.format(record)
742
if record.levelno > logging.INFO:
744
self.ui.add_log_line(msg)
747
740
ui = UserInterface()
750
743
except KeyboardInterrupt:
751
with warnings.catch_warnings():
752
warnings.filterwarnings("ignore", "", BytesWarning)
755
with warnings.catch_warnings():
756
warnings.filterwarnings("ignore", "", BytesWarning)
745
except Exception as e:
746
ui.log_message(str(e))