/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

* init.d-mandos (Required-Start, Required-Stop): Bug fix: Added
                 "$syslog", thanks to Petter Reinholdtsen
                 <pere@hungry.com> (Debian bug #546928).

* initramfs-tools-script: Removed erroneous comment.

* plugins.d/askpass-fifo.c: Removed TEMP_FAILURE_RETRY since it is
                            not needed.

* plugins.d/mandos-client.c (main): Bug fix: Initialize
                                    "old_sigterm_action".

* plugins.d/splashy.c (main): Bug fix: really check return value from
                              "sigaddset".  Fix some warnings on
                              64-bit systems.

* plugins.d/usplash.c (termination_handler, main): Save received
                                                   signal and
                                                   re-raise it on
                                                   exit.
  (usplash_write): Do not close FIFO, instead, take an additional file
                   descriptor pointer to it and open only when needed
                   (all callers changed).  Abort immediately on EINTR.
                   Bug fix:  Add NUL byte on single-word commands.
                   Ignore "interrupted_by_signal".
  (makeprompt, find_usplash): New; broken out from "main()".
  (find_usplash): Bug fix: close /proc/<pid>/cmdline FD on error.
  (main): Reorganized to jump to a new "failure" label on any error.
          Bug fix: check return values from sigaddset.
          New variable "usplash_accessed" to flag if usplash(8) needs
          to be killed and restarted.  Removed the "an_error_occured"
          variable.

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
79
77
        SO_BINDTODEVICE = None
80
78
 
81
79
 
82
 
version = "1.0.14"
 
80
version = "1.0.11"
83
81
 
84
82
logger = logging.Logger(u'mandos')
85
83
syslogger = (logging.handlers.SysLogHandler
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, quiet=quiet)
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
    """
1280
1049
        cmd, args = cmdline.rstrip(u"\r\n").split(None, 1)
1281
1050
        
1282
1051
        if cmd == u"NOTFOUND":
1283
 
            fpr, address = args.split(None, 1)
1284
 
            logger.warning(u"Client not found for fingerprint: %s, ad"
1285
 
                           u"dress: %s", fpr, address)
 
1052
            logger.warning(u"Client not found for fingerprint: %s",
 
1053
                           args)
1286
1054
            if self.use_dbus:
1287
1055
                # Emit D-Bus signal
1288
 
                mandos_dbus_service.ClientNotFound(fpr, address)
 
1056
                mandos_dbus_service.ClientNotFound(args)
1289
1057
        elif cmd == u"INVALID":
1290
1058
            for client in self.clients:
1291
1059
                if client.name == args:
1303
1071
                    client.checked_ok()
1304
1072
                    if self.use_dbus:
1305
1073
                        # Emit D-Bus signal
1306
 
                        client.GotSecret()
 
1074
                        client.ReceivedSecret()
1307
1075
                    break
1308
1076
            else:
1309
1077
                logger.error(u"Sending secret to unknown client %s",
1347
1115
            elif suffix == u"w":
1348
1116
                delta = datetime.timedelta(0, 0, 0, 0, 0, 0, value)
1349
1117
            else:
1350
 
                raise ValueError(u"Unknown suffix %r" % suffix)
1351
 
        except (ValueError, IndexError), e:
1352
 
            raise ValueError(e.message)
 
1118
                raise ValueError
 
1119
        except (ValueError, IndexError):
 
1120
            raise ValueError
1353
1121
        timevalue += delta
1354
1122
    return timevalue
1355
1123
 
1394
1162
        null = os.open(os.path.devnull, os.O_NOCTTY | os.O_RDWR)
1395
1163
        if not stat.S_ISCHR(os.fstat(null).st_mode):
1396
1164
            raise OSError(errno.ENODEV,
1397
 
                          u"%s not a character device"
1398
 
                          % os.path.devnull)
 
1165
                          u"/dev/null not a character device")
1399
1166
        os.dup2(null, sys.stdin.fileno())
1400
1167
        os.dup2(null, sys.stdout.fileno())
1401
1168
        os.dup2(null, sys.stderr.fileno())
1405
1172
 
1406
1173
def main():
1407
1174
    
1408
 
    ##################################################################
 
1175
    ######################################################################
1409
1176
    # Parsing of options, both command line and config file
1410
1177
    
1411
1178
    parser = optparse.OptionParser(version = "%%prog %s" % version)
1568
1335
    bus = dbus.SystemBus()
1569
1336
    # End of Avahi example code
1570
1337
    if use_dbus:
1571
 
        try:
1572
 
            bus_name = dbus.service.BusName(u"se.bsnet.fukt.Mandos",
1573
 
                                            bus, do_not_queue=True)
1574
 
        except dbus.exceptions.NameExistsException, e:
1575
 
            logger.error(unicode(e) + u", disabling D-Bus")
1576
 
            use_dbus = False
1577
 
            server_settings[u"use_dbus"] = False
1578
 
            tcp_server.use_dbus = False
 
1338
        bus_name = dbus.service.BusName(u"se.bsnet.fukt.Mandos", bus)
1579
1339
    protocol = avahi.PROTO_INET6 if use_ipv6 else avahi.PROTO_INET
1580
1340
    service = AvahiService(name = server_settings[u"servicename"],
1581
1341
                           servicetype = u"_mandos._tcp",
1619
1379
        pass
1620
1380
    del pidfilename
1621
1381
    
 
1382
    def cleanup():
 
1383
        "Cleanup function; run on exit"
 
1384
        service.cleanup()
 
1385
        
 
1386
        while tcp_server.clients:
 
1387
            client = tcp_server.clients.pop()
 
1388
            client.disable_hook = None
 
1389
            client.disable()
 
1390
    
 
1391
    atexit.register(cleanup)
 
1392
    
1622
1393
    if not debug:
1623
1394
        signal.signal(signal.SIGINT, signal.SIG_IGN)
1624
1395
    signal.signal(signal.SIGHUP, lambda signum, frame: sys.exit())
1636
1407
                "D-Bus signal"
1637
1408
                pass
1638
1409
            
1639
 
            @dbus.service.signal(_interface, signature=u"ss")
1640
 
            def ClientNotFound(self, fingerprint, address):
 
1410
            @dbus.service.signal(_interface, signature=u"s")
 
1411
            def ClientNotFound(self, fingerprint):
1641
1412
                "D-Bus signal"
1642
1413
                pass
1643
1414
            
1657
1428
            def GetAllClientsWithProperties(self):
1658
1429
                "D-Bus method"
1659
1430
                return dbus.Dictionary(
1660
 
                    ((c.dbus_object_path, c.GetAll(u""))
 
1431
                    ((c.dbus_object_path, c.GetAllProperties())
1661
1432
                     for c in tcp_server.clients),
1662
1433
                    signature=u"oa{sv}")
1663
1434
            
1669
1440
                        tcp_server.clients.remove(c)
1670
1441
                        c.remove_from_connection()
1671
1442
                        # Don't signal anything except ClientRemoved
1672
 
                        c.disable(quiet=True)
 
1443
                        c.disable(signal=False)
1673
1444
                        # Emit D-Bus signal
1674
1445
                        self.ClientRemoved(object_path, c.name)
1675
1446
                        return
1676
 
                raise KeyError(object_path)
 
1447
                raise KeyError
1677
1448
            
1678
1449
            del _interface
1679
1450
        
1680
1451
        mandos_dbus_service = MandosDBusService()
1681
1452
    
1682
 
    def cleanup():
1683
 
        "Cleanup function; run on exit"
1684
 
        service.cleanup()
1685
 
        
1686
 
        while tcp_server.clients:
1687
 
            client = tcp_server.clients.pop()
1688
 
            if use_dbus:
1689
 
                client.remove_from_connection()
1690
 
            client.disable_hook = None
1691
 
            # Don't signal anything except ClientRemoved
1692
 
            client.disable(quiet=True)
1693
 
            if use_dbus:
1694
 
                # Emit D-Bus signal
1695
 
                mandos_dbus_service.ClientRemoved(client.dbus_object_path,
1696
 
                                                  client.name)
1697
 
    
1698
 
    atexit.register(cleanup)
1699
 
    
1700
1453
    for client in tcp_server.clients:
1701
1454
        if use_dbus:
1702
1455
            # Emit D-Bus signal
1703
1456
            mandos_dbus_service.ClientAdded(client.dbus_object_path,
1704
 
                                            client.GetAll(u""))
 
1457
                                            client.GetAllProperties())
1705
1458
        client.enable()
1706
1459
    
1707
1460
    tcp_server.enable()
1725
1478
            service.activate()
1726
1479
        except dbus.exceptions.DBusException, error:
1727
1480
            logger.critical(u"DBusException: %s", error)
1728
 
            cleanup()
1729
1481
            sys.exit(1)
1730
1482
        # End of Avahi example code
1731
1483
        
1738
1490
        main_loop.run()
1739
1491
    except AvahiError, error:
1740
1492
        logger.critical(u"AvahiError: %s", error)
1741
 
        cleanup()
1742
1493
        sys.exit(1)
1743
1494
    except KeyboardInterrupt:
1744
1495
        if debug:
1745
1496
            print >> sys.stderr
1746
1497
        logger.debug(u"Server received KeyboardInterrupt")
1747
1498
    logger.debug(u"Server exiting")
1748
 
    # Must run before the D-Bus bus name gets deregistered
1749
 
    cleanup()
1750
1499
 
1751
1500
if __name__ == '__main__':
1752
1501
    main()