/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 Hogeborn
  • Date: 2015-08-10 08:25:01 UTC
  • mto: (237.7.594 trunk)
  • mto: This revision was merged to the branch mainline in revision 325.
  • Revision ID: teddy@recompile.se-20150810082501-rb7w2dre1flqiqe2
Refactor D-Bus annotation class out from D-Bus properties class.

* mandos (DBusObjectWithAnnotations): New; factored out D-Bus
                                      annotations code from
                                      DBusObjectWithProperties class.
  (DBusObjectWithProperties): Inherit from DBusObjectWithAnnotations.
  (main/MandosDBusService): - '' -
  (main/MandosDBusService._foo): Removed interface annotation for
                                 "o.f.D.Property.EmitsChangedSignal";
                                 this object has no properties.

Show diffs side-by-side

added added

removed removed

Lines of Context:
395
395
                    logger.error(bad_states[state] + ": %r", error)
396
396
            self.cleanup()
397
397
        elif state == avahi.SERVER_RUNNING:
398
 
            self.add()
 
398
            try:
 
399
                self.add()
 
400
            except dbus.exceptions.DBusException as error:
 
401
                if (error.get_dbus_name()
 
402
                    == "org.freedesktop.Avahi.CollisionError"):
 
403
                    logger.info("Local Zeroconf service name"
 
404
                                " collision.")
 
405
                    return self.rename(remove=False)
 
406
                else:
 
407
                    logger.critical("D-Bus Exception", exc_info=error)
 
408
                    self.cleanup()
 
409
                    os._exit(1)
399
410
        else:
400
411
            if error is None:
401
412
                logger.debug("Unknown state: %r", state)
831
842
                           access="r")
832
843
    def Property_dbus_property(self):
833
844
        return dbus.Boolean(False)
 
845
    
 
846
    See also the DBusObjectWithAnnotations class.
834
847
    """
835
848
    
836
849
    def decorator(func):
858
871
    pass
859
872
 
860
873
 
861
 
class DBusObjectWithProperties(dbus.service.Object):
862
 
    """A D-Bus object with properties.
 
874
class DBusObjectWithAnnotations(dbus.service.Object):
 
875
    """A D-Bus object with annotations.
863
876
    
864
 
    Classes inheriting from this can use the dbus_service_property
865
 
    decorator to expose methods as D-Bus properties.  It exposes the
866
 
    standard Get(), Set(), and GetAll() methods on the D-Bus.
 
877
    Classes inheriting from this can use the dbus_annotations
 
878
    decorator to add annotations to methods or signals.
867
879
    """
868
880
    
869
881
    @staticmethod
885
897
                for name, athing in
886
898
                inspect.getmembers(cls, self._is_dbus_thing(thing)))
887
899
    
 
900
    @dbus.service.method(dbus.INTROSPECTABLE_IFACE,
 
901
                         out_signature = "s",
 
902
                         path_keyword = 'object_path',
 
903
                         connection_keyword = 'connection')
 
904
    def Introspect(self, object_path, connection):
 
905
        """Overloading of standard D-Bus method.
 
906
        
 
907
        Inserts annotation tags on methods and signals.
 
908
        """
 
909
        xmlstring = dbus.service.Object.Introspect(self, object_path,
 
910
                                                   connection)
 
911
        try:
 
912
            document = xml.dom.minidom.parseString(xmlstring)
 
913
            
 
914
            for if_tag in document.getElementsByTagName("interface"):
 
915
                # Add annotation tags
 
916
                for typ in ("method", "signal"):
 
917
                    for tag in if_tag.getElementsByTagName(typ):
 
918
                        annots = dict()
 
919
                        for name, prop in (self.
 
920
                                           _get_all_dbus_things(typ)):
 
921
                            if (name == tag.getAttribute("name")
 
922
                                and prop._dbus_interface
 
923
                                == if_tag.getAttribute("name")):
 
924
                                annots.update(getattr(
 
925
                                    prop, "_dbus_annotations", {}))
 
926
                        for name, value in annots.items():
 
927
                            ann_tag = document.createElement(
 
928
                                "annotation")
 
929
                            ann_tag.setAttribute("name", name)
 
930
                            ann_tag.setAttribute("value", value)
 
931
                            tag.appendChild(ann_tag)
 
932
                # Add interface annotation tags
 
933
                for annotation, value in dict(
 
934
                    itertools.chain.from_iterable(
 
935
                        annotations().items()
 
936
                        for name, annotations
 
937
                        in self._get_all_dbus_things("interface")
 
938
                        if name == if_tag.getAttribute("name")
 
939
                        )).items():
 
940
                    ann_tag = document.createElement("annotation")
 
941
                    ann_tag.setAttribute("name", annotation)
 
942
                    ann_tag.setAttribute("value", value)
 
943
                    if_tag.appendChild(ann_tag)
 
944
                # Fix argument name for the Introspect method itself
 
945
                if (if_tag.getAttribute("name")
 
946
                                == dbus.INTROSPECTABLE_IFACE):
 
947
                    for cn in if_tag.getElementsByTagName("method"):
 
948
                        if cn.getAttribute("name") == "Introspect":
 
949
                            for arg in cn.getElementsByTagName("arg"):
 
950
                                if (arg.getAttribute("direction")
 
951
                                    == "out"):
 
952
                                    arg.setAttribute("name",
 
953
                                                     "xml_data")
 
954
            xmlstring = document.toxml("utf-8")
 
955
            document.unlink()
 
956
        except (AttributeError, xml.dom.DOMException,
 
957
                xml.parsers.expat.ExpatError) as error:
 
958
            logger.error("Failed to override Introspection method",
 
959
                         exc_info=error)
 
960
        return xmlstring
 
961
 
 
962
 
 
963
class DBusObjectWithProperties(DBusObjectWithAnnotations):
 
964
    """A D-Bus object with properties.
 
965
    
 
966
    Classes inheriting from this can use the dbus_service_property
 
967
    decorator to expose methods as D-Bus properties.  It exposes the
 
968
    standard Get(), Set(), and GetAll() methods on the D-Bus.
 
969
    """
 
970
    
888
971
    def _get_dbus_property(self, interface_name, property_name):
889
972
        """Returns a bound method if one exists which is a D-Bus
890
973
        property with the specified name and interface.
975
1058
        
976
1059
        Inserts property tags and interface annotation tags.
977
1060
        """
978
 
        xmlstring = dbus.service.Object.Introspect(self, object_path,
979
 
                                                   connection)
 
1061
        xmlstring = DBusObjectWithAnnotations.Introspect(self,
 
1062
                                                         object_path,
 
1063
                                                         connection)
980
1064
        try:
981
1065
            document = xml.dom.minidom.parseString(xmlstring)
982
1066
            
995
1079
                            if prop._dbus_interface
996
1080
                            == if_tag.getAttribute("name")):
997
1081
                    if_tag.appendChild(tag)
998
 
                # Add annotation tags
999
 
                for typ in ("method", "signal", "property"):
1000
 
                    for tag in if_tag.getElementsByTagName(typ):
1001
 
                        annots = dict()
1002
 
                        for name, prop in (self.
1003
 
                                           _get_all_dbus_things(typ)):
1004
 
                            if (name == tag.getAttribute("name")
1005
 
                                and prop._dbus_interface
1006
 
                                == if_tag.getAttribute("name")):
1007
 
                                annots.update(getattr(
1008
 
                                    prop, "_dbus_annotations", {}))
1009
 
                        for name, value in annots.items():
1010
 
                            ann_tag = document.createElement(
1011
 
                                "annotation")
1012
 
                            ann_tag.setAttribute("name", name)
1013
 
                            ann_tag.setAttribute("value", value)
1014
 
                            tag.appendChild(ann_tag)
1015
 
                # Add interface annotation tags
1016
 
                for annotation, value in dict(
1017
 
                    itertools.chain.from_iterable(
1018
 
                        annotations().items()
1019
 
                        for name, annotations
1020
 
                        in self._get_all_dbus_things("interface")
1021
 
                        if name == if_tag.getAttribute("name")
1022
 
                        )).items():
1023
 
                    ann_tag = document.createElement("annotation")
1024
 
                    ann_tag.setAttribute("name", annotation)
1025
 
                    ann_tag.setAttribute("value", value)
1026
 
                    if_tag.appendChild(ann_tag)
 
1082
                # Add annotation tags for properties
 
1083
                for tag in if_tag.getElementsByTagName("property"):
 
1084
                    annots = dict()
 
1085
                    for name, prop in self._get_all_dbus_things(
 
1086
                            "property"):
 
1087
                        if (name == tag.getAttribute("name")
 
1088
                            and prop._dbus_interface
 
1089
                            == if_tag.getAttribute("name")):
 
1090
                            annots.update(getattr(
 
1091
                                prop, "_dbus_annotations", {}))
 
1092
                    for name, value in annots.items():
 
1093
                        ann_tag = document.createElement(
 
1094
                            "annotation")
 
1095
                        ann_tag.setAttribute("name", name)
 
1096
                        ann_tag.setAttribute("value", value)
 
1097
                        tag.appendChild(ann_tag)
1027
1098
                # Add the names to the return values for the
1028
1099
                # "org.freedesktop.DBus.Properties" methods
1029
1100
                if (if_tag.getAttribute("name")
1365
1436
        if exitstatus >= 0:
1366
1437
            # Emit D-Bus signal
1367
1438
            self.CheckerCompleted(dbus.Int16(exitstatus),
1368
 
                                  dbus.Int64(0),
 
1439
                                  # This is specific to GNU libC
 
1440
                                  dbus.Int64(exitstatus << 8),
1369
1441
                                  dbus.String(command))
1370
1442
        else:
1371
1443
            # Emit D-Bus signal
1372
1444
            self.CheckerCompleted(dbus.Int16(-1),
1373
1445
                                  dbus.Int64(
1374
 
                                      self.last_checker_signal),
 
1446
                                      # This is specific to GNU libC
 
1447
                                      (exitstatus << 8)
 
1448
                                      | self.last_checker_signal),
1375
1449
                                  dbus.String(command))
1376
1450
        return ret
1377
1451
    
1454
1528
        self.checked_ok()
1455
1529
    
1456
1530
    # Enable - method
 
1531
    @dbus_annotations({"org.freedesktop.DBus.Deprecated": "true"})
1457
1532
    @dbus.service.method(_interface)
1458
1533
    def Enable(self):
1459
1534
        "D-Bus method"
1460
1535
        self.enable()
1461
1536
    
1462
1537
    # StartChecker - method
 
1538
    @dbus_annotations({"org.freedesktop.DBus.Deprecated": "true"})
1463
1539
    @dbus.service.method(_interface)
1464
1540
    def StartChecker(self):
1465
1541
        "D-Bus method"
1466
1542
        self.start_checker()
1467
1543
    
1468
1544
    # Disable - method
 
1545
    @dbus_annotations({"org.freedesktop.DBus.Deprecated": "true"})
1469
1546
    @dbus.service.method(_interface)
1470
1547
    def Disable(self):
1471
1548
        "D-Bus method"
1472
1549
        self.disable()
1473
1550
    
1474
1551
    # StopChecker - method
 
1552
    @dbus_annotations({"org.freedesktop.DBus.Deprecated": "true"})
1475
1553
    @dbus.service.method(_interface)
1476
1554
    def StopChecker(self):
1477
1555
        self.stop_checker()
1513
1591
        self.approval_duration = datetime.timedelta(0, 0, 0, value)
1514
1592
    
1515
1593
    # Name - property
 
1594
    @dbus_annotations(
 
1595
        {"org.freedesktop.DBus.Property.EmitsChangedSignal": "const"})
1516
1596
    @dbus_service_property(_interface, signature="s", access="read")
1517
1597
    def Name_dbus_property(self):
1518
1598
        return dbus.String(self.name)
1519
1599
    
1520
1600
    # Fingerprint - property
 
1601
    @dbus_annotations(
 
1602
        {"org.freedesktop.DBus.Property.EmitsChangedSignal": "const"})
1521
1603
    @dbus_service_property(_interface, signature="s", access="read")
1522
1604
    def Fingerprint_dbus_property(self):
1523
1605
        return dbus.String(self.fingerprint)
1532
1614
        self.host = str(value)
1533
1615
    
1534
1616
    # Created - property
 
1617
    @dbus_annotations(
 
1618
        {"org.freedesktop.DBus.Property.EmitsChangedSignal": "const"})
1535
1619
    @dbus_service_property(_interface, signature="s", access="read")
1536
1620
    def Created_dbus_property(self):
1537
1621
        return datetime_to_dbus(self.created)
1652
1736
            self.stop_checker()
1653
1737
    
1654
1738
    # ObjectPath - property
 
1739
    @dbus_annotations(
 
1740
        {"org.freedesktop.DBus.Property.EmitsChangedSignal": "const",
 
1741
         "org.freedesktop.DBus.Deprecated": "true"})
1655
1742
    @dbus_service_property(_interface, signature="o", access="read")
1656
1743
    def ObjectPath_dbus_property(self):
1657
1744
        return self.dbus_object_path # is already a dbus.ObjectPath
1658
1745
    
1659
1746
    # Secret = property
 
1747
    @dbus_annotations(
 
1748
        {"org.freedesktop.DBus.Property.EmitsChangedSignal":
 
1749
         "invalidates"})
1660
1750
    @dbus_service_property(_interface,
1661
1751
                           signature="ay",
1662
1752
                           access="write",
2386
2476
                        "debug": "False",
2387
2477
                        "priority":
2388
2478
                        "SECURE256:!CTYPE-X.509:+CTYPE-OPENPGP:!RSA"
2389
 
                        ":+SIGN-RSA-SHA224:+SIGN-RSA-RMD160",
 
2479
                        ":+SIGN-DSA-SHA256",
2390
2480
                        "servicename": "Mandos",
2391
2481
                        "use_dbus": "True",
2392
2482
                        "use_ipv6": "True",
2723
2813
        
2724
2814
        @alternate_dbus_interfaces(
2725
2815
            { "se.recompile.Mandos": "se.bsnet.fukt.Mandos" })
2726
 
        class MandosDBusService(DBusObjectWithProperties):
 
2816
        class MandosDBusService(DBusObjectWithAnnotations):
2727
2817
            """A D-Bus proxy object"""
2728
2818
            
2729
2819
            def __init__(self):
2731
2821
            
2732
2822
            _interface = "se.recompile.Mandos"
2733
2823
            
2734
 
            @dbus_interface_annotations(_interface)
2735
 
            def _foo(self):
2736
 
                return {
2737
 
                    "org.freedesktop.DBus.Property.EmitsChangedSignal":
2738
 
                    "false" }
2739
 
            
2740
2824
            @dbus.service.signal(_interface, signature="o")
2741
2825
            def ClientAdded(self, objpath):
2742
2826
                "D-Bus signal"