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

  • Committer: Teddy Hogeborn
  • Date: 2011-12-31 20:07:11 UTC
  • mfrom: (535.1.9 wireless-network-hook)
  • Revision ID: teddy@recompile.se-20111231200711-6dli3r8drftem57r
Merge new wireless network hook.  Fix bridge network hook to use
hardware addresses instead of interface names.  Implement and document
new "CONNECT" environment variable for network hooks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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/>.
21
21
22
 
# Contact the authors at <mandos@fukt.bsnet.se>.
 
22
# Contact the authors at <mandos@recompile.se>.
23
23
24
24
 
25
 
from __future__ import division, absolute_import, print_function, unicode_literals
 
25
from __future__ import (division, absolute_import, print_function,
 
26
                        unicode_literals)
26
27
 
27
28
import sys
28
29
import os
48
49
logging.getLogger('dbus.proxies').setLevel(logging.CRITICAL)
49
50
 
50
51
# Some useful constants
51
 
domain = 'se.bsnet.fukt'
 
52
domain = 'se.recompile'
52
53
server_interface = domain + '.Mandos'
53
54
client_interface = domain + '.Mandos.Client'
54
 
version = "1.2.3"
 
55
version = "1.4.1"
55
56
 
56
57
# Always run in monochrome mode
57
58
urwid.curses_display.curses.has_colors = lambda : False
86
87
        self.proxy = proxy_object # Mandos Client proxy object
87
88
        
88
89
        self.properties = dict()
89
 
        self.proxy.connect_to_signal("PropertyChanged",
90
 
                                     self.property_changed,
91
 
                                     client_interface,
92
 
                                     byte_arrays=True)
 
90
        self.property_changed_match = (
 
91
            self.proxy.connect_to_signal("PropertyChanged",
 
92
                                         self.property_changed,
 
93
                                         client_interface,
 
94
                                         byte_arrays=True))
93
95
        
94
96
        self.properties.update(
95
97
            self.proxy.GetAll(client_interface,
96
98
                              dbus_interface = dbus.PROPERTIES_IFACE))
97
99
 
98
 
        #XXX This break good super behaviour!
 
100
        #XXX This breaks good super behaviour
99
101
#        super(MandosClientPropertyCache, self).__init__(
100
102
#            *args, **kwargs)
101
103
    
105
107
        """
106
108
        # Update properties dict with new value
107
109
        self.properties[property] = value
 
110
    
 
111
    def delete(self, *args, **kwargs):
 
112
        self.property_changed_match.remove()
 
113
        super(MandosClientPropertyCache, self).__init__(
 
114
            *args, **kwargs)
108
115
 
109
116
 
110
117
class MandosClientWidget(urwid.FlowWidget, MandosClientPropertyCache):
154
161
        if self.need_approval:
155
162
            self.using_timer(True)
156
163
        
157
 
        self.proxy.connect_to_signal("CheckerCompleted",
158
 
                                     self.checker_completed,
159
 
                                     client_interface,
160
 
                                     byte_arrays=True)
161
 
        self.proxy.connect_to_signal("CheckerStarted",
162
 
                                     self.checker_started,
163
 
                                     client_interface,
164
 
                                     byte_arrays=True)
165
 
        self.proxy.connect_to_signal("GotSecret",
166
 
                                     self.got_secret,
167
 
                                     client_interface,
168
 
                                     byte_arrays=True)
169
 
        self.proxy.connect_to_signal("NeedApproval",
170
 
                                     self.need_approval,
171
 
                                     client_interface,
172
 
                                     byte_arrays=True)
173
 
        self.proxy.connect_to_signal("Rejected",
174
 
                                     self.rejected,
175
 
                                     client_interface,
176
 
                                     byte_arrays=True)
 
164
        self.match_objects = (
 
165
            self.proxy.connect_to_signal("CheckerCompleted",
 
166
                                         self.checker_completed,
 
167
                                         client_interface,
 
168
                                         byte_arrays=True),
 
169
            self.proxy.connect_to_signal("CheckerStarted",
 
170
                                         self.checker_started,
 
171
                                         client_interface,
 
172
                                         byte_arrays=True),
 
173
            self.proxy.connect_to_signal("GotSecret",
 
174
                                         self.got_secret,
 
175
                                         client_interface,
 
176
                                         byte_arrays=True),
 
177
            self.proxy.connect_to_signal("NeedApproval",
 
178
                                         self.need_approval,
 
179
                                         client_interface,
 
180
                                         byte_arrays=True),
 
181
            self.proxy.connect_to_signal("Rejected",
 
182
                                         self.rejected,
 
183
                                         client_interface,
 
184
                                         byte_arrays=True))
 
185
        #self.logger('Created client %s' % (self.properties["Name"]))
177
186
    
178
187
    def property_changed(self, property=None, value=None):
179
188
        super(self, MandosClientWidget).property_changed(property,
191
200
        else:
192
201
            self._update_timer_callback_lock -= 1
193
202
        if old == 0 and self._update_timer_callback_lock:
 
203
            # Will update the shown timer value every second
194
204
            self._update_timer_callback_tag = (gobject.timeout_add
195
205
                                               (1000,
196
206
                                                self.update_timer))
232
242
        self.update()
233
243
    
234
244
    def checker_started(self, command):
 
245
        """Server signals that a checker started. This could be useful
 
246
           to log in the future. """
235
247
        #self.logger('Client %s started checker "%s"'
236
248
        #            % (self.properties["Name"], unicode(command)))
237
249
        pass
305
317
                message = "Denial in %s. (a)pprove?"
306
318
            message = message % unicode(timer).rsplit(".", 1)[0]
307
319
        elif self.last_checker_failed:
308
 
            timeout = datetime.timedelta(milliseconds
309
 
                                         = self.properties
310
 
                                         ["Timeout"])
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)
 
320
            # When checker has failed, print a timer until client expires
 
321
            expires = self.properties["Expires"]
 
322
            if expires == "":
 
323
                timer = datetime.timedelta(0)
 
324
            else:
 
325
                expires = datetime.datetime.strptime(expires,
 
326
                                                     '%Y-%m-%dT%H:%M:%S.%f')
 
327
                timer = expires - datetime.datetime.utcnow()
316
328
            message = ('A checker has failed! Time until client'
317
329
                       ' gets disabled: %s'
318
330
                           % unicode(timer).rsplit(".", 1)[0])
337
349
            self.update_hook()
338
350
    
339
351
    def update_timer(self):
340
 
        "called by gobject"
 
352
        """called by gobject. Will indefinitely loop until
 
353
        gobject.source_remove() on tag is called"""
341
354
        self.update()
342
355
        return True             # Keep calling this
343
356
    
344
 
    def delete(self):
 
357
    def delete(self, *args, **kwargs):
345
358
        if self._update_timer_callback_tag is not None:
346
359
            gobject.source_remove(self._update_timer_callback_tag)
347
360
            self._update_timer_callback_tag = None
 
361
        for match in self.match_objects:
 
362
            match.remove()
 
363
        self.match_objects = ()
348
364
        if self.delete_hook is not None:
349
365
            self.delete_hook(self)
 
366
        return super(MandosClientWidget, self).delete(*args, **kwargs)
350
367
    
351
368
    def render(self, maxcolrow, focus=False):
352
369
        """Render differently if we have focus.
358
375
        """Handle keys.
359
376
        This overrides the method from urwid.FlowWidget"""
360
377
        if key == "+":
361
 
            self.proxy.Enable(dbus_interface = client_interface)
 
378
            self.proxy.Enable(dbus_interface = client_interface,
 
379
                              ignore_reply=True)
362
380
        elif key == "-":
363
 
            self.proxy.Disable(dbus_interface = client_interface)
 
381
            self.proxy.Disable(dbus_interface = client_interface,
 
382
                               ignore_reply=True)
364
383
        elif key == "a":
365
384
            self.proxy.Approve(dbus.Boolean(True, variant_level=1),
366
 
                               dbus_interface = client_interface)
 
385
                               dbus_interface = client_interface,
 
386
                               ignore_reply=True)
367
387
        elif key == "d":
368
388
            self.proxy.Approve(dbus.Boolean(False, variant_level=1),
369
 
                                  dbus_interface = client_interface)
 
389
                                  dbus_interface = client_interface,
 
390
                               ignore_reply=True)
370
391
        elif key == "R" or key == "_" or key == "ctrl k":
371
392
            self.server_proxy_object.RemoveClient(self.proxy
372
 
                                                  .object_path)
 
393
                                                  .object_path,
 
394
                                                  ignore_reply=True)
373
395
        elif key == "s":
374
 
            self.proxy.StartChecker(dbus_interface = client_interface)
 
396
            self.proxy.StartChecker(dbus_interface = client_interface,
 
397
                                    ignore_reply=True)
375
398
        elif key == "S":
376
 
            self.proxy.StopChecker(dbus_interface = client_interface)
 
399
            self.proxy.StopChecker(dbus_interface = client_interface,
 
400
                                   ignore_reply=True)
377
401
        elif key == "C":
378
 
            self.proxy.CheckedOK(dbus_interface = client_interface)
 
402
            self.proxy.CheckedOK(dbus_interface = client_interface,
 
403
                                 ignore_reply=True)
379
404
        # xxx
380
405
#         elif key == "p" or key == "=":
381
406
#             self.proxy.pause()
474
499
        
475
500
        self.busname = domain + '.Mandos'
476
501
        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,
481
 
                                          dbus_interface
482
 
                                          = server_interface)
483
 
        try:
484
 
            mandos_clients = (self.mandos_serv
485
 
                              .GetAllClientsWithProperties())
486
 
        except dbus.exceptions.DBusException:
487
 
            mandos_clients = dbus.Dictionary()
488
 
        
489
 
        (self.mandos_serv
490
 
         .connect_to_signal("ClientRemoved",
491
 
                            self.find_and_remove_client,
492
 
                            dbus_interface=server_interface,
493
 
                            byte_arrays=True))
494
 
        (self.mandos_serv
495
 
         .connect_to_signal("ClientAdded",
496
 
                            self.add_new_client,
497
 
                            dbus_interface=server_interface,
498
 
                            byte_arrays=True))
499
 
        (self.mandos_serv
500
 
         .connect_to_signal("ClientNotFound",
501
 
                            self.client_not_found,
502
 
                            dbus_interface=server_interface,
503
 
                            byte_arrays=True))
504
 
        for path, client in mandos_clients.iteritems():
505
 
            client_proxy_object = self.bus.get_object(self.busname,
506
 
                                                      path)
507
 
            self.add_client(MandosClientWidget(server_proxy_object
508
 
                                               =self.mandos_serv,
509
 
                                               proxy_object
510
 
                                               =client_proxy_object,
511
 
                                               properties=client,
512
 
                                               update_hook
513
 
                                               =self.refresh,
514
 
                                               delete_hook
515
 
                                               =self.remove_client,
516
 
                                               logger
517
 
                                               =self.log_message),
518
 
                            path=path)
519
502
    
520
503
    def client_not_found(self, fingerprint, address):
521
504
        self.log_message(("Client with address %s and fingerprint %s"
536
519
                                                     self.divider)))
537
520
        if self.log_visible:
538
521
            self.uilist.append(self.logbox)
539
 
            pass
540
522
        self.topwidget = urwid.Pile(self.uilist)
541
523
    
542
524
    def log_message(self, message):
572
554
        #self.log_message("Wrap mode: " + self.log_wrap)
573
555
    
574
556
    def find_and_remove_client(self, path, name):
575
 
        """Find an client from its object path and remove it.
 
557
        """Find a client by its object path and remove it.
576
558
        
577
559
        This is connected to the ClientRemoved signal from the
578
560
        Mandos server object."""
580
562
            client = self.clients_dict[path]
581
563
        except KeyError:
582
564
            # not found?
 
565
            self.log_message("Unknown client %r (%r) removed", name,
 
566
                             path)
583
567
            return
584
 
        self.remove_client(client, path)
 
568
        client.delete()
585
569
    
586
570
    def add_new_client(self, path):
587
571
        client_proxy_object = self.bus.get_object(self.busname, path)
624
608
    
625
609
    def run(self):
626
610
        """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,
 
615
                                          dbus_interface
 
616
                                          = server_interface)
 
617
        try:
 
618
            mandos_clients = (self.mandos_serv
 
619
                              .GetAllClientsWithProperties())
 
620
        except dbus.exceptions.DBusException:
 
621
            mandos_clients = dbus.Dictionary()
 
622
        
 
623
        (self.mandos_serv
 
624
         .connect_to_signal("ClientRemoved",
 
625
                            self.find_and_remove_client,
 
626
                            dbus_interface=server_interface,
 
627
                            byte_arrays=True))
 
628
        (self.mandos_serv
 
629
         .connect_to_signal("ClientAdded",
 
630
                            self.add_new_client,
 
631
                            dbus_interface=server_interface,
 
632
                            byte_arrays=True))
 
633
        (self.mandos_serv
 
634
         .connect_to_signal("ClientNotFound",
 
635
                            self.client_not_found,
 
636
                            dbus_interface=server_interface,
 
637
                            byte_arrays=True))
 
638
        for path, client in mandos_clients.iteritems():
 
639
            client_proxy_object = self.bus.get_object(self.busname,
 
640
                                                      path)
 
641
            self.add_client(MandosClientWidget(server_proxy_object
 
642
                                               =self.mandos_serv,
 
643
                                               proxy_object
 
644
                                               =client_proxy_object,
 
645
                                               properties=client,
 
646
                                               update_hook
 
647
                                               =self.refresh,
 
648
                                               delete_hook
 
649
                                               =self.remove_client,
 
650
                                               logger
 
651
                                               =self.log_message),
 
652
                            path=path)
 
653
 
627
654
        self.refresh()
628
655
        self._input_callback_tag = (gobject.io_add_watch
629
656
                                    (sys.stdin.fileno(),