/mandos/release

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/release

« back to all changes in this revision

Viewing changes to mandos

  • Committer: teddy at bsnet
  • Date: 2010-08-16 19:00:59 UTC
  • mto: (237.2.183 mandos-local)
  • mto: This revision was merged to the branch mainline in revision 270.
  • Revision ID: teddy@fukt.bsnet.se-20100816190059-69vvi27up95cgbbl
* Makefile (run-server, run-client): Add notices about harmless error
                                     messages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
67
67
from dbus.mainloop.glib import DBusGMainLoop
68
68
import ctypes
69
69
import ctypes.util
70
 
import xml.dom.minidom
71
 
import inspect
72
70
 
73
71
try:
74
72
    SO_BINDTODEVICE = socket.SO_BINDTODEVICE
176
174
                                    self.server.EntryGroupNew()),
177
175
                avahi.DBUS_INTERFACE_ENTRY_GROUP)
178
176
            self.group.connect_to_signal('StateChanged',
179
 
                                         self
180
 
                                         .entry_group_state_changed)
 
177
                                         self.entry_group_state_changed)
181
178
        logger.debug(u"Adding Zeroconf service '%s' of type '%s' ...",
182
179
                     self.name, self.type)
183
180
        self.group.AddService(
249
246
                                    to see if the client lives.
250
247
                                    'None' if no process is running.
251
248
    checker_initiator_tag: a gobject event source tag, or None
252
 
    disable_initiator_tag: - '' -
 
249
    disable_initiator_tag:    - '' -
253
250
    checker_callback_tag:  - '' -
254
251
    checker_command: string; External command which is run to check if
255
252
                     client lives.  %() expansions are done at
259
256
    """
260
257
    
261
258
    @staticmethod
262
 
    def _timedelta_to_milliseconds(td):
263
 
        "Convert a datetime.timedelta() to milliseconds"
264
 
        return ((td.days * 24 * 60 * 60 * 1000)
265
 
                + (td.seconds * 1000)
266
 
                + (td.microseconds // 1000))
 
259
    def _datetime_to_milliseconds(dt):
 
260
        "Convert a datetime.datetime() to milliseconds"
 
261
        return ((dt.days * 24 * 60 * 60 * 1000)
 
262
                + (dt.seconds * 1000)
 
263
                + (dt.microseconds // 1000))
267
264
    
268
265
    def timeout_milliseconds(self):
269
266
        "Return the 'timeout' attribute in milliseconds"
270
 
        return self._timedelta_to_milliseconds(self.timeout)
 
267
        return self._datetime_to_milliseconds(self.timeout)
271
268
    
272
269
    def interval_milliseconds(self):
273
270
        "Return the 'interval' attribute in milliseconds"
274
 
        return self._timedelta_to_milliseconds(self.interval)
 
271
        return self._datetime_to_milliseconds(self.interval)
275
272
    
276
273
    def __init__(self, name = None, disable_hook=None, config=None):
277
274
        """Note: the 'checker' key in 'config' sets the
292
289
        elif u"secfile" in config:
293
290
            with closing(open(os.path.expanduser
294
291
                              (os.path.expandvars
295
 
                               (config[u"secfile"])),
296
 
                              "rb")) as secfile:
 
292
                               (config[u"secfile"])))) as secfile:
297
293
                self.secret = secfile.read()
298
294
        else:
299
295
            raise TypeError(u"No secret or secfile for client %s"
325
321
        self.checker_initiator_tag = (gobject.timeout_add
326
322
                                      (self.interval_milliseconds(),
327
323
                                       self.start_checker))
 
324
        # Also start a new checker *right now*.
 
325
        self.start_checker()
328
326
        # Schedule a disable() when 'timeout' has passed
329
327
        self.disable_initiator_tag = (gobject.timeout_add
330
328
                                   (self.timeout_milliseconds(),
331
329
                                    self.disable))
332
330
        self.enabled = True
333
 
        # Also start a new checker *right now*.
334
 
        self.start_checker()
335
331
    
336
 
    def disable(self, quiet=True):
 
332
    def disable(self):
337
333
        """Disable this client."""
338
334
        if not getattr(self, "enabled", False):
339
335
            return False
340
 
        if not quiet:
341
 
            logger.info(u"Disabling client %s", self.name)
 
336
        logger.info(u"Disabling client %s", self.name)
342
337
        if getattr(self, u"disable_initiator_tag", False):
343
338
            gobject.source_remove(self.disable_initiator_tag)
344
339
            self.disable_initiator_tag = None
400
395
        # is as it should be.
401
396
        
402
397
        # If a checker exists, make sure it is not a zombie
403
 
        try:
 
398
        if self.checker is not None:
404
399
            pid, status = os.waitpid(self.checker.pid, os.WNOHANG)
405
 
        except (AttributeError, OSError), error:
406
 
            if (isinstance(error, OSError)
407
 
                and error.errno != errno.ECHILD):
408
 
                raise error
409
 
        else:
410
400
            if pid:
411
401
                logger.warning(u"Checker was a zombie")
412
402
                gobject.source_remove(self.checker_callback_tag)
468
458
        logger.debug(u"Stopping checker for %(name)s", vars(self))
469
459
        try:
470
460
            os.kill(self.checker.pid, signal.SIGTERM)
471
 
            #time.sleep(0.5)
 
461
            #os.sleep(0.5)
472
462
            #if self.checker.poll() is None:
473
463
            #    os.kill(self.checker.pid, signal.SIGKILL)
474
464
        except OSError, error:
487
477
            return now < (self.last_checked_ok + self.timeout)
488
478
 
489
479
 
490
 
def dbus_service_property(dbus_interface, signature=u"v",
491
 
                          access=u"readwrite", byte_arrays=False):
492
 
    """Decorators for marking methods of a DBusObjectWithProperties to
493
 
    become properties on the D-Bus.
494
 
    
495
 
    The decorated method will be called with no arguments by "Get"
496
 
    and with one argument by "Set".
497
 
    
498
 
    The parameters, where they are supported, are the same as
499
 
    dbus.service.method, except there is only "signature", since the
500
 
    type from Get() and the type sent to Set() is the same.
501
 
    """
502
 
    def decorator(func):
503
 
        func._dbus_is_property = True
504
 
        func._dbus_interface = dbus_interface
505
 
        func._dbus_signature = signature
506
 
        func._dbus_access = access
507
 
        func._dbus_name = func.__name__
508
 
        if func._dbus_name.endswith(u"_dbus_property"):
509
 
            func._dbus_name = func._dbus_name[:-14]
510
 
        func._dbus_get_args_options = {u'byte_arrays': byte_arrays }
511
 
        return func
512
 
    return decorator
513
 
 
514
 
 
515
 
class DBusPropertyException(dbus.exceptions.DBusException):
516
 
    """A base class for D-Bus property-related exceptions
517
 
    """
518
 
    def __unicode__(self):
519
 
        return unicode(str(self))
520
 
 
521
 
 
522
 
class DBusPropertyAccessException(DBusPropertyException):
523
 
    """A property's access permissions disallows an operation.
524
 
    """
525
 
    pass
526
 
 
527
 
 
528
 
class DBusPropertyNotFound(DBusPropertyException):
529
 
    """An attempt was made to access a non-existing property.
530
 
    """
531
 
    pass
532
 
 
533
 
 
534
 
class DBusObjectWithProperties(dbus.service.Object):
535
 
    """A D-Bus object with properties.
536
 
 
537
 
    Classes inheriting from this can use the dbus_service_property
538
 
    decorator to expose methods as D-Bus properties.  It exposes the
539
 
    standard Get(), Set(), and GetAll() methods on the D-Bus.
540
 
    """
541
 
    
542
 
    @staticmethod
543
 
    def _is_dbus_property(obj):
544
 
        return getattr(obj, u"_dbus_is_property", False)
545
 
    
546
 
    def _get_all_dbus_properties(self):
547
 
        """Returns a generator of (name, attribute) pairs
548
 
        """
549
 
        return ((prop._dbus_name, prop)
550
 
                for name, prop in
551
 
                inspect.getmembers(self, self._is_dbus_property))
552
 
    
553
 
    def _get_dbus_property(self, interface_name, property_name):
554
 
        """Returns a bound method if one exists which is a D-Bus
555
 
        property with the specified name and interface.
556
 
        """
557
 
        for name in (property_name,
558
 
                     property_name + u"_dbus_property"):
559
 
            prop = getattr(self, name, None)
560
 
            if (prop is None
561
 
                or not self._is_dbus_property(prop)
562
 
                or prop._dbus_name != property_name
563
 
                or (interface_name and prop._dbus_interface
564
 
                    and interface_name != prop._dbus_interface)):
565
 
                continue
566
 
            return prop
567
 
        # No such property
568
 
        raise DBusPropertyNotFound(self.dbus_object_path + u":"
569
 
                                   + interface_name + u"."
570
 
                                   + property_name)
571
 
    
572
 
    @dbus.service.method(dbus.PROPERTIES_IFACE, in_signature=u"ss",
573
 
                         out_signature=u"v")
574
 
    def Get(self, interface_name, property_name):
575
 
        """Standard D-Bus property Get() method, see D-Bus standard.
576
 
        """
577
 
        prop = self._get_dbus_property(interface_name, property_name)
578
 
        if prop._dbus_access == u"write":
579
 
            raise DBusPropertyAccessException(property_name)
580
 
        value = prop()
581
 
        if not hasattr(value, u"variant_level"):
582
 
            return value
583
 
        return type(value)(value, variant_level=value.variant_level+1)
584
 
    
585
 
    @dbus.service.method(dbus.PROPERTIES_IFACE, in_signature=u"ssv")
586
 
    def Set(self, interface_name, property_name, value):
587
 
        """Standard D-Bus property Set() method, see D-Bus standard.
588
 
        """
589
 
        prop = self._get_dbus_property(interface_name, property_name)
590
 
        if prop._dbus_access == u"read":
591
 
            raise DBusPropertyAccessException(property_name)
592
 
        if prop._dbus_get_args_options[u"byte_arrays"]:
593
 
            value = dbus.ByteArray(''.join(unichr(byte)
594
 
                                           for byte in value))
595
 
        prop(value)
596
 
    
597
 
    @dbus.service.method(dbus.PROPERTIES_IFACE, in_signature=u"s",
598
 
                         out_signature=u"a{sv}")
599
 
    def GetAll(self, interface_name):
600
 
        """Standard D-Bus property GetAll() method, see D-Bus
601
 
        standard.
602
 
 
603
 
        Note: Will not include properties with access="write".
604
 
        """
605
 
        all = {}
606
 
        for name, prop in self._get_all_dbus_properties():
607
 
            if (interface_name
608
 
                and interface_name != prop._dbus_interface):
609
 
                # Interface non-empty but did not match
610
 
                continue
611
 
            # Ignore write-only properties
612
 
            if prop._dbus_access == u"write":
613
 
                continue
614
 
            value = prop()
615
 
            if not hasattr(value, u"variant_level"):
616
 
                all[name] = value
617
 
                continue
618
 
            all[name] = type(value)(value, variant_level=
619
 
                                    value.variant_level+1)
620
 
        return dbus.Dictionary(all, signature=u"sv")
621
 
    
622
 
    @dbus.service.method(dbus.INTROSPECTABLE_IFACE,
623
 
                         out_signature=u"s",
624
 
                         path_keyword='object_path',
625
 
                         connection_keyword='connection')
626
 
    def Introspect(self, object_path, connection):
627
 
        """Standard D-Bus method, overloaded to insert property tags.
628
 
        """
629
 
        xmlstring = dbus.service.Object.Introspect(self, object_path,
630
 
                                                   connection)
631
 
        try:
632
 
            document = xml.dom.minidom.parseString(xmlstring)
633
 
            def make_tag(document, name, prop):
634
 
                e = document.createElement(u"property")
635
 
                e.setAttribute(u"name", name)
636
 
                e.setAttribute(u"type", prop._dbus_signature)
637
 
                e.setAttribute(u"access", prop._dbus_access)
638
 
                return e
639
 
            for if_tag in document.getElementsByTagName(u"interface"):
640
 
                for tag in (make_tag(document, name, prop)
641
 
                            for name, prop
642
 
                            in self._get_all_dbus_properties()
643
 
                            if prop._dbus_interface
644
 
                            == if_tag.getAttribute(u"name")):
645
 
                    if_tag.appendChild(tag)
646
 
                # Add the names to the return values for the
647
 
                # "org.freedesktop.DBus.Properties" methods
648
 
                if (if_tag.getAttribute(u"name")
649
 
                    == u"org.freedesktop.DBus.Properties"):
650
 
                    for cn in if_tag.getElementsByTagName(u"method"):
651
 
                        if cn.getAttribute(u"name") == u"Get":
652
 
                            for arg in cn.getElementsByTagName(u"arg"):
653
 
                                if (arg.getAttribute(u"direction")
654
 
                                    == u"out"):
655
 
                                    arg.setAttribute(u"name", u"value")
656
 
                        elif cn.getAttribute(u"name") == u"GetAll":
657
 
                            for arg in cn.getElementsByTagName(u"arg"):
658
 
                                if (arg.getAttribute(u"direction")
659
 
                                    == u"out"):
660
 
                                    arg.setAttribute(u"name", u"props")
661
 
            xmlstring = document.toxml(u"utf-8")
662
 
            document.unlink()
663
 
        except (AttributeError, xml.dom.DOMException,
664
 
                xml.parsers.expat.ExpatError), error:
665
 
            logger.error(u"Failed to override Introspection method",
666
 
                         error)
667
 
        return xmlstring
668
 
 
669
 
 
670
 
class ClientDBus(Client, DBusObjectWithProperties):
 
480
class ClientDBus(Client, dbus.service.Object):
671
481
    """A Client class using D-Bus
672
482
    
673
483
    Attributes:
684
494
        self.dbus_object_path = (dbus.ObjectPath
685
495
                                 (u"/clients/"
686
496
                                  + self.name.replace(u".", u"_")))
687
 
        DBusObjectWithProperties.__init__(self, self.bus,
688
 
                                          self.dbus_object_path)
 
497
        dbus.service.Object.__init__(self, self.bus,
 
498
                                     self.dbus_object_path)
689
499
    
690
500
    @staticmethod
691
501
    def _datetime_to_dbus(dt, variant_level=0):
706
516
                                       variant_level=1))
707
517
        return r
708
518
    
709
 
    def disable(self, quiet = False):
 
519
    def disable(self, signal = True):
710
520
        oldstate = getattr(self, u"enabled", False)
711
 
        r = Client.disable(self, log=signal)
712
 
        if not quiet and oldstate != self.enabled:
 
521
        r = Client.disable(self)
 
522
        if signal and oldstate != self.enabled:
713
523
            # Emit D-Bus signal
714
524
            self.PropertyChanged(dbus.String(u"enabled"),
715
525
                                 dbus.Boolean(False, variant_level=1))
720
530
            self.remove_from_connection()
721
531
        except LookupError:
722
532
            pass
723
 
        if hasattr(DBusObjectWithProperties, u"__del__"):
724
 
            DBusObjectWithProperties.__del__(self, *args, **kwargs)
 
533
        if hasattr(dbus.service.Object, u"__del__"):
 
534
            dbus.service.Object.__del__(self, *args, **kwargs)
725
535
        Client.__del__(self, *args, **kwargs)
726
536
    
727
537
    def checker_callback(self, pid, condition, command,
801
611
        "D-Bus signal"
802
612
        pass
803
613
    
 
614
    # GetAllProperties - method
 
615
    @dbus.service.method(_interface, out_signature=u"a{sv}")
 
616
    def GetAllProperties(self):
 
617
        "D-Bus method"
 
618
        return dbus.Dictionary({
 
619
                dbus.String(u"name"):
 
620
                    dbus.String(self.name, variant_level=1),
 
621
                dbus.String(u"fingerprint"):
 
622
                    dbus.String(self.fingerprint, variant_level=1),
 
623
                dbus.String(u"host"):
 
624
                    dbus.String(self.host, variant_level=1),
 
625
                dbus.String(u"created"):
 
626
                    self._datetime_to_dbus(self.created,
 
627
                                           variant_level=1),
 
628
                dbus.String(u"last_enabled"):
 
629
                    (self._datetime_to_dbus(self.last_enabled,
 
630
                                            variant_level=1)
 
631
                     if self.last_enabled is not None
 
632
                     else dbus.Boolean(False, variant_level=1)),
 
633
                dbus.String(u"enabled"):
 
634
                    dbus.Boolean(self.enabled, variant_level=1),
 
635
                dbus.String(u"last_checked_ok"):
 
636
                    (self._datetime_to_dbus(self.last_checked_ok,
 
637
                                            variant_level=1)
 
638
                     if self.last_checked_ok is not None
 
639
                     else dbus.Boolean (False, variant_level=1)),
 
640
                dbus.String(u"timeout"):
 
641
                    dbus.UInt64(self.timeout_milliseconds(),
 
642
                                variant_level=1),
 
643
                dbus.String(u"interval"):
 
644
                    dbus.UInt64(self.interval_milliseconds(),
 
645
                                variant_level=1),
 
646
                dbus.String(u"checker"):
 
647
                    dbus.String(self.checker_command,
 
648
                                variant_level=1),
 
649
                dbus.String(u"checker_running"):
 
650
                    dbus.Boolean(self.checker is not None,
 
651
                                 variant_level=1),
 
652
                dbus.String(u"object_path"):
 
653
                    dbus.ObjectPath(self.dbus_object_path,
 
654
                                    variant_level=1)
 
655
                }, signature=u"sv")
 
656
    
 
657
    # IsStillValid - method
 
658
    @dbus.service.method(_interface, out_signature=u"b")
 
659
    def IsStillValid(self):
 
660
        return self.still_valid()
 
661
    
804
662
    # PropertyChanged - signal
805
663
    @dbus.service.signal(_interface, signature=u"sv")
806
664
    def PropertyChanged(self, property, value):
807
665
        "D-Bus signal"
808
666
        pass
809
667
    
810
 
    # GotSecret - signal
 
668
    # ReceivedSecret - signal
811
669
    @dbus.service.signal(_interface)
812
 
    def GotSecret(self):
 
670
    def ReceivedSecret(self):
813
671
        "D-Bus signal"
814
672
        pass
815
673
    
819
677
        "D-Bus signal"
820
678
        pass
821
679
    
 
680
    # SetChecker - method
 
681
    @dbus.service.method(_interface, in_signature=u"s")
 
682
    def SetChecker(self, checker):
 
683
        "D-Bus setter method"
 
684
        self.checker_command = checker
 
685
        # Emit D-Bus signal
 
686
        self.PropertyChanged(dbus.String(u"checker"),
 
687
                             dbus.String(self.checker_command,
 
688
                                         variant_level=1))
 
689
    
 
690
    # SetHost - method
 
691
    @dbus.service.method(_interface, in_signature=u"s")
 
692
    def SetHost(self, host):
 
693
        "D-Bus setter method"
 
694
        self.host = host
 
695
        # Emit D-Bus signal
 
696
        self.PropertyChanged(dbus.String(u"host"),
 
697
                             dbus.String(self.host, variant_level=1))
 
698
    
 
699
    # SetInterval - method
 
700
    @dbus.service.method(_interface, in_signature=u"t")
 
701
    def SetInterval(self, milliseconds):
 
702
        self.interval = datetime.timedelta(0, 0, 0, milliseconds)
 
703
        # Emit D-Bus signal
 
704
        self.PropertyChanged(dbus.String(u"interval"),
 
705
                             (dbus.UInt64(self.interval_milliseconds(),
 
706
                                          variant_level=1)))
 
707
    
 
708
    # SetSecret - method
 
709
    @dbus.service.method(_interface, in_signature=u"ay",
 
710
                         byte_arrays=True)
 
711
    def SetSecret(self, secret):
 
712
        "D-Bus setter method"
 
713
        self.secret = str(secret)
 
714
    
 
715
    # SetTimeout - method
 
716
    @dbus.service.method(_interface, in_signature=u"t")
 
717
    def SetTimeout(self, milliseconds):
 
718
        self.timeout = datetime.timedelta(0, 0, 0, milliseconds)
 
719
        # Emit D-Bus signal
 
720
        self.PropertyChanged(dbus.String(u"timeout"),
 
721
                             (dbus.UInt64(self.timeout_milliseconds(),
 
722
                                          variant_level=1)))
 
723
    
822
724
    # Enable - method
823
725
    @dbus.service.method(_interface)
824
726
    def Enable(self):
842
744
    def StopChecker(self):
843
745
        self.stop_checker()
844
746
    
845
 
    # name - property
846
 
    @dbus_service_property(_interface, signature=u"s", access=u"read")
847
 
    def name_dbus_property(self):
848
 
        return dbus.String(self.name)
849
 
    
850
 
    # fingerprint - property
851
 
    @dbus_service_property(_interface, signature=u"s", access=u"read")
852
 
    def fingerprint_dbus_property(self):
853
 
        return dbus.String(self.fingerprint)
854
 
    
855
 
    # host - property
856
 
    @dbus_service_property(_interface, signature=u"s",
857
 
                           access=u"readwrite")
858
 
    def host_dbus_property(self, value=None):
859
 
        if value is None:       # get
860
 
            return dbus.String(self.host)
861
 
        self.host = value
862
 
        # Emit D-Bus signal
863
 
        self.PropertyChanged(dbus.String(u"host"),
864
 
                             dbus.String(value, variant_level=1))
865
 
    
866
 
    # created - property
867
 
    @dbus_service_property(_interface, signature=u"s", access=u"read")
868
 
    def created_dbus_property(self):
869
 
        return dbus.String(self._datetime_to_dbus(self.created))
870
 
    
871
 
    # last_enabled - property
872
 
    @dbus_service_property(_interface, signature=u"s", access=u"read")
873
 
    def last_enabled_dbus_property(self):
874
 
        if self.last_enabled is None:
875
 
            return dbus.String(u"")
876
 
        return dbus.String(self._datetime_to_dbus(self.last_enabled))
877
 
    
878
 
    # enabled - property
879
 
    @dbus_service_property(_interface, signature=u"b",
880
 
                           access=u"readwrite")
881
 
    def enabled_dbus_property(self, value=None):
882
 
        if value is None:       # get
883
 
            return dbus.Boolean(self.enabled)
884
 
        if value:
885
 
            self.enable()
886
 
        else:
887
 
            self.disable()
888
 
    
889
 
    # last_checked_ok - property
890
 
    @dbus_service_property(_interface, signature=u"s",
891
 
                           access=u"readwrite")
892
 
    def last_checked_ok_dbus_property(self, value=None):
893
 
        if value is not None:
894
 
            self.checked_ok()
895
 
            return
896
 
        if self.last_checked_ok is None:
897
 
            return dbus.String(u"")
898
 
        return dbus.String(self._datetime_to_dbus(self
899
 
                                                  .last_checked_ok))
900
 
    
901
 
    # timeout - property
902
 
    @dbus_service_property(_interface, signature=u"t",
903
 
                           access=u"readwrite")
904
 
    def timeout_dbus_property(self, value=None):
905
 
        if value is None:       # get
906
 
            return dbus.UInt64(self.timeout_milliseconds())
907
 
        self.timeout = datetime.timedelta(0, 0, 0, value)
908
 
        # Emit D-Bus signal
909
 
        self.PropertyChanged(dbus.String(u"timeout"),
910
 
                             dbus.UInt64(value, variant_level=1))
911
 
        if getattr(self, u"disable_initiator_tag", None) is None:
912
 
            return
913
 
        # Reschedule timeout
914
 
        gobject.source_remove(self.disable_initiator_tag)
915
 
        self.disable_initiator_tag = None
916
 
        time_to_die = (self.
917
 
                       _timedelta_to_milliseconds((self
918
 
                                                   .last_checked_ok
919
 
                                                   + self.timeout)
920
 
                                                  - datetime.datetime
921
 
                                                  .utcnow()))
922
 
        if time_to_die <= 0:
923
 
            # The timeout has passed
924
 
            self.disable()
925
 
        else:
926
 
            self.disable_initiator_tag = (gobject.timeout_add
927
 
                                          (time_to_die, self.disable))
928
 
    
929
 
    # interval - property
930
 
    @dbus_service_property(_interface, signature=u"t",
931
 
                           access=u"readwrite")
932
 
    def interval_dbus_property(self, value=None):
933
 
        if value is None:       # get
934
 
            return dbus.UInt64(self.interval_milliseconds())
935
 
        self.interval = datetime.timedelta(0, 0, 0, value)
936
 
        # Emit D-Bus signal
937
 
        self.PropertyChanged(dbus.String(u"interval"),
938
 
                             dbus.UInt64(value, variant_level=1))
939
 
        if getattr(self, u"checker_initiator_tag", None) is None:
940
 
            return
941
 
        # Reschedule checker run
942
 
        gobject.source_remove(self.checker_initiator_tag)
943
 
        self.checker_initiator_tag = (gobject.timeout_add
944
 
                                      (value, self.start_checker))
945
 
        self.start_checker()    # Start one now, too
946
 
 
947
 
    # checker - property
948
 
    @dbus_service_property(_interface, signature=u"s",
949
 
                           access=u"readwrite")
950
 
    def checker_dbus_property(self, value=None):
951
 
        if value is None:       # get
952
 
            return dbus.String(self.checker_command)
953
 
        self.checker_command = value
954
 
        # Emit D-Bus signal
955
 
        self.PropertyChanged(dbus.String(u"checker"),
956
 
                             dbus.String(self.checker_command,
957
 
                                         variant_level=1))
958
 
    
959
 
    # checker_running - property
960
 
    @dbus_service_property(_interface, signature=u"b",
961
 
                           access=u"readwrite")
962
 
    def checker_running_dbus_property(self, value=None):
963
 
        if value is None:       # get
964
 
            return dbus.Boolean(self.checker is not None)
965
 
        if value:
966
 
            self.start_checker()
967
 
        else:
968
 
            self.stop_checker()
969
 
    
970
 
    # object_path - property
971
 
    @dbus_service_property(_interface, signature=u"o", access=u"read")
972
 
    def object_path_dbus_property(self):
973
 
        return self.dbus_object_path # is already a dbus.ObjectPath
974
 
    
975
 
    # secret = property
976
 
    @dbus_service_property(_interface, signature=u"ay",
977
 
                           access=u"write", byte_arrays=True)
978
 
    def secret_dbus_property(self, value):
979
 
        self.secret = str(value)
980
 
    
981
747
    del _interface
982
748
 
983
749
 
1217
983
        clients:        set of Client objects
1218
984
        gnutls_priority GnuTLS priority string
1219
985
        use_dbus:       Boolean; to emit D-Bus signals or not
 
986
        clients:        set of Client objects
 
987
        gnutls_priority GnuTLS priority string
 
988
        use_dbus:       Boolean; to emit D-Bus signals or not
1220
989
    
1221
990
    Assumes a gobject.MainLoop event loop.
1222
991
    """
1302
1071
                    client.checked_ok()
1303
1072
                    if self.use_dbus:
1304
1073
                        # Emit D-Bus signal
1305
 
                        client.GotSecret()
 
1074
                        client.ReceivedSecret()
1306
1075
                    break
1307
1076
            else:
1308
1077
                logger.error(u"Sending secret to unknown client %s",
1346
1115
            elif suffix == u"w":
1347
1116
                delta = datetime.timedelta(0, 0, 0, 0, 0, 0, value)
1348
1117
            else:
1349
 
                raise ValueError(u"Unknown suffix %r" % suffix)
1350
 
        except (ValueError, IndexError), e:
1351
 
            raise ValueError(e.message)
 
1118
                raise ValueError
 
1119
        except (ValueError, IndexError):
 
1120
            raise ValueError
1352
1121
        timevalue += delta
1353
1122
    return timevalue
1354
1123
 
1393
1162
        null = os.open(os.path.devnull, os.O_NOCTTY | os.O_RDWR)
1394
1163
        if not stat.S_ISCHR(os.fstat(null).st_mode):
1395
1164
            raise OSError(errno.ENODEV,
1396
 
                          u"%s not a character device"
1397
 
                          % os.path.devnull)
 
1165
                          u"/dev/null not a character device")
1398
1166
        os.dup2(null, sys.stdin.fileno())
1399
1167
        os.dup2(null, sys.stdout.fileno())
1400
1168
        os.dup2(null, sys.stderr.fileno())
1404
1172
 
1405
1173
def main():
1406
1174
    
1407
 
    ##################################################################
 
1175
    ######################################################################
1408
1176
    # Parsing of options, both command line and config file
1409
1177
    
1410
1178
    parser = optparse.OptionParser(version = "%%prog %s" % version)
1428
1196
                      help=u"Directory to search for configuration"
1429
1197
                      u" files")
1430
1198
    parser.add_option("--no-dbus", action=u"store_false",
1431
 
                      dest=u"use_dbus", help=u"Do not provide D-Bus"
1432
 
                      u" system bus interface")
 
1199
                      dest=u"use_dbus",
 
1200
                      help=optparse.SUPPRESS_HELP) # XXX: Not done yet
1433
1201
    parser.add_option("--no-ipv6", action=u"store_false",
1434
1202
                      dest=u"use_ipv6", help=u"Do not use IPv6")
1435
1203
    options = parser.parse_args()[0]
1487
1255
    # For convenience
1488
1256
    debug = server_settings[u"debug"]
1489
1257
    use_dbus = server_settings[u"use_dbus"]
 
1258
    use_dbus = False            # XXX: Not done yet
1490
1259
    use_ipv6 = server_settings[u"use_ipv6"]
1491
1260
    
1492
1261
    if not debug:
1567
1336
    bus = dbus.SystemBus()
1568
1337
    # End of Avahi example code
1569
1338
    if use_dbus:
1570
 
        try:
1571
 
            bus_name = dbus.service.BusName(u"se.bsnet.fukt.Mandos",
1572
 
                                            bus, do_not_queue=True)
1573
 
        except dbus.exceptions.NameExistsException, e:
1574
 
            logger.error(unicode(e) + u", disabling D-Bus")
1575
 
            use_dbus = False
1576
 
            server_settings[u"use_dbus"] = False
1577
 
            tcp_server.use_dbus = False
 
1339
        bus_name = dbus.service.BusName(u"se.bsnet.fukt.Mandos", bus)
1578
1340
    protocol = avahi.PROTO_INET6 if use_ipv6 else avahi.PROTO_INET
1579
1341
    service = AvahiService(name = server_settings[u"servicename"],
1580
1342
                           servicetype = u"_mandos._tcp",
1618
1380
        pass
1619
1381
    del pidfilename
1620
1382
    
 
1383
    def cleanup():
 
1384
        "Cleanup function; run on exit"
 
1385
        service.cleanup()
 
1386
        
 
1387
        while tcp_server.clients:
 
1388
            client = tcp_server.clients.pop()
 
1389
            client.disable_hook = None
 
1390
            client.disable()
 
1391
    
 
1392
    atexit.register(cleanup)
 
1393
    
1621
1394
    if not debug:
1622
1395
        signal.signal(signal.SIGINT, signal.SIG_IGN)
1623
1396
    signal.signal(signal.SIGHUP, lambda signum, frame: sys.exit())
1656
1429
            def GetAllClientsWithProperties(self):
1657
1430
                "D-Bus method"
1658
1431
                return dbus.Dictionary(
1659
 
                    ((c.dbus_object_path, c.GetAll(u""))
 
1432
                    ((c.dbus_object_path, c.GetAllProperties())
1660
1433
                     for c in tcp_server.clients),
1661
1434
                    signature=u"oa{sv}")
1662
1435
            
1668
1441
                        tcp_server.clients.remove(c)
1669
1442
                        c.remove_from_connection()
1670
1443
                        # Don't signal anything except ClientRemoved
1671
 
                        c.disable(quiet=True)
 
1444
                        c.disable(signal=False)
1672
1445
                        # Emit D-Bus signal
1673
1446
                        self.ClientRemoved(object_path, c.name)
1674
1447
                        return
1675
 
                raise KeyError(object_path)
 
1448
                raise KeyError
1676
1449
            
1677
1450
            del _interface
1678
1451
        
1679
1452
        mandos_dbus_service = MandosDBusService()
1680
1453
    
1681
 
    def cleanup():
1682
 
        "Cleanup function; run on exit"
1683
 
        service.cleanup()
1684
 
        
1685
 
        while tcp_server.clients:
1686
 
            client = tcp_server.clients.pop()
1687
 
            if use_dbus:
1688
 
                client.remove_from_connection()
1689
 
            client.disable_hook = None
1690
 
            # Don't signal anything except ClientRemoved
1691
 
            client.disable(quiet=True)
1692
 
            if use_dbus:
1693
 
                # Emit D-Bus signal
1694
 
                mandos_dbus_service.ClientRemoved(client.dbus_object_path,
1695
 
                                                  client.name)
1696
 
    
1697
 
    atexit.register(cleanup)
1698
 
    
1699
1454
    for client in tcp_server.clients:
1700
1455
        if use_dbus:
1701
1456
            # Emit D-Bus signal
1702
1457
            mandos_dbus_service.ClientAdded(client.dbus_object_path,
1703
 
                                            client.GetAll(u""))
 
1458
                                            client.GetAllProperties())
1704
1459
        client.enable()
1705
1460
    
1706
1461
    tcp_server.enable()
1724
1479
            service.activate()
1725
1480
        except dbus.exceptions.DBusException, error:
1726
1481
            logger.critical(u"DBusException: %s", error)
1727
 
            cleanup()
1728
1482
            sys.exit(1)
1729
1483
        # End of Avahi example code
1730
1484
        
1737
1491
        main_loop.run()
1738
1492
    except AvahiError, error:
1739
1493
        logger.critical(u"AvahiError: %s", error)
1740
 
        cleanup()
1741
1494
        sys.exit(1)
1742
1495
    except KeyboardInterrupt:
1743
1496
        if debug:
1744
1497
            print >> sys.stderr
1745
1498
        logger.debug(u"Server received KeyboardInterrupt")
1746
1499
    logger.debug(u"Server exiting")
1747
 
    # Must run before the D-Bus bus name gets deregistered
1748
 
    cleanup()
1749
1500
 
1750
1501
if __name__ == '__main__':
1751
1502
    main()