/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

  • Committer: Björn Påhlsson
  • Date: 2011-09-18 16:04:23 UTC
  • mfrom: (497 trunk)
  • mto: This revision was merged to the branch mainline in revision 498.
  • Revision ID: belorn@fukt.bsnet.se-20110918160423-x09aoqldw7wqmzia
Merge from teddy.

Show diffs side-by-side

added added

removed removed

Lines of Context:
264
264
        self.server_state_changed(self.server.GetState())
265
265
 
266
266
 
267
 
def _timedelta_to_milliseconds(td):
268
 
    "Convert a datetime.timedelta() to milliseconds"
269
 
    return ((td.days * 24 * 60 * 60 * 1000)
270
 
            + (td.seconds * 1000)
271
 
            + (td.microseconds // 1000))
272
 
        
273
267
class Client(object):
274
268
    """A representation of a client host served by this server.
275
269
    
313
307
                          "created", "enabled", "fingerprint",
314
308
                          "host", "interval", "last_checked_ok",
315
309
                          "last_enabled", "name", "timeout")
316
 
        
 
310
    
 
311
    @staticmethod
 
312
    def _timedelta_to_milliseconds(td):
 
313
        "Convert a datetime.timedelta() to milliseconds"
 
314
        return ((td.days * 24 * 60 * 60 * 1000)
 
315
                + (td.seconds * 1000)
 
316
                + (td.microseconds // 1000))
 
317
    
317
318
    def timeout_milliseconds(self):
318
319
        "Return the 'timeout' attribute in milliseconds"
319
 
        return _timedelta_to_milliseconds(self.timeout)
 
320
        return self._timedelta_to_milliseconds(self.timeout)
320
321
 
321
322
    def extended_timeout_milliseconds(self):
322
323
        "Return the 'extended_timeout' attribute in milliseconds"
323
 
        return _timedelta_to_milliseconds(self.extended_timeout)    
 
324
        return self._timedelta_to_milliseconds(self.extended_timeout)    
324
325
    
325
326
    def interval_milliseconds(self):
326
327
        "Return the 'interval' attribute in milliseconds"
327
 
        return _timedelta_to_milliseconds(self.interval)
 
328
        return self._timedelta_to_milliseconds(self.interval)
328
329
 
329
330
    def approval_delay_milliseconds(self):
330
 
        return _timedelta_to_milliseconds(self.approval_delay)
 
331
        return self._timedelta_to_milliseconds(self.approval_delay)
331
332
    
332
333
    def __init__(self, name = None, disable_hook=None, config=None):
333
334
        """Note: the 'checker' key in 'config' sets the
392
393
            # Already enabled
393
394
            return
394
395
        self.send_changedstate()
 
396
        self.last_enabled = datetime.datetime.utcnow()
395
397
        # Schedule a new checker to be started an 'interval' from now,
396
398
        # and every interval from then on.
397
399
        self.checker_initiator_tag = (gobject.timeout_add
403
405
                                   (self.timeout_milliseconds(),
404
406
                                    self.disable))
405
407
        self.enabled = True
406
 
        self.last_enabled = datetime.datetime.utcnow()
407
408
        # Also start a new checker *right now*.
408
409
        self.start_checker()
409
410
    
462
463
        gobject.source_remove(self.disable_initiator_tag)
463
464
        self.expires = datetime.datetime.utcnow() + timeout
464
465
        self.disable_initiator_tag = (gobject.timeout_add
465
 
                                      (_timedelta_to_milliseconds(timeout),
 
466
                                      (self._timedelta_to_milliseconds(timeout),
466
467
                                       self.disable))
467
468
    
468
469
    def need_approval(self):
750
751
        return xmlstring
751
752
 
752
753
 
753
 
def datetime_to_dbus (dt, variant_level=0):
754
 
    """Convert a UTC datetime.datetime() to a D-Bus type."""
755
 
    if dt is None:
756
 
        return dbus.String("", variant_level = variant_level)
757
 
    return dbus.String(dt.isoformat(),
758
 
                       variant_level=variant_level)
759
 
 
760
754
class ClientDBus(Client, DBusObjectWithProperties):
761
755
    """A Client class using D-Bus
762
756
    
783
777
                                 ("/clients/" + client_object_name))
784
778
        DBusObjectWithProperties.__init__(self, self.bus,
785
779
                                          self.dbus_object_path)
 
780
    def _set_expires(self, value):
 
781
        old_value = getattr(self, "_expires", None)
 
782
        self._expires = value
 
783
        if hasattr(self, "dbus_object_path") and old_value != value:
 
784
            dbus_time = (self._datetime_to_dbus(self._expires,
 
785
                                                variant_level=1))
 
786
            self.PropertyChanged(dbus.String("Expires"),
 
787
                                 dbus_time)
 
788
    expires = property(lambda self: self._expires, _set_expires)
 
789
    del _set_expires
786
790
        
787
 
    def notifychangeproperty(transform_func,
788
 
                             dbus_name, type_func=lambda x: x,
789
 
                             variant_level=1):
790
 
        """ Modify a variable so that its a property that announce its
791
 
        changes to DBus.
792
 
        transform_fun: Function that takes a value and transform it to
793
 
                       DBus type.
794
 
        dbus_name: DBus name of the variable
795
 
        type_func: Function that transform the value before sending it
796
 
                   to DBus
797
 
        variant_level: DBus variant level. default: 1
798
 
        """
799
 
        real_value = [None,]
800
 
        def setter(self, value):
801
 
            old_value = real_value[0]
802
 
            real_value[0] = value
803
 
            if hasattr(self, "dbus_object_path"):
804
 
                if type_func(old_value) != type_func(real_value[0]):
805
 
                    dbus_value = transform_func(type_func(real_value[0]),
806
 
                                                variant_level)
807
 
                    self.PropertyChanged(dbus.String(dbus_name),
808
 
                                         dbus_value)
809
 
 
810
 
        return property(lambda self: real_value[0], setter)
811
 
 
812
 
 
813
 
    expires = notifychangeproperty(datetime_to_dbus, "Expires")
814
 
    approvals_pending = notifychangeproperty(dbus.Boolean,
815
 
                                             "ApprovalPending",
816
 
                                             type_func = bool)
817
 
    enabled = notifychangeproperty(dbus.Boolean, "Enabled")
818
 
    last_enabled = notifychangeproperty(datetime_to_dbus,
819
 
                                        "LastEnabled")
820
 
    checker = notifychangeproperty(dbus.Boolean, "CheckerRunning",
821
 
                                   type_func = lambda checker: checker is not None)
822
 
    last_checked_ok = notifychangeproperty(datetime_to_dbus,
823
 
                                           "LastCheckedOK")
824
 
    last_approval_request = notifychangeproperty(datetime_to_dbus,
825
 
                                                 "LastApprovalRequest")
826
 
    approved_by_default = notifychangeproperty(dbus.Boolean,
827
 
                                               "ApprovedByDefault")
828
 
    approval_delay = notifychangeproperty(dbus.UInt16, "ApprovalDelay",
829
 
                                          type_func = _timedelta_to_milliseconds)
830
 
    approval_duration = notifychangeproperty(dbus.UInt16, "ApprovalDuration",
831
 
                                             type_func = _timedelta_to_milliseconds)
832
 
    host = notifychangeproperty(dbus.String, "Host")
833
 
    timeout = notifychangeproperty(dbus.UInt16, "Timeout",
834
 
                                   type_func = _timedelta_to_milliseconds)
835
 
    extended_timeout = notifychangeproperty(dbus.UInt16, "ExtendedTimeout",
836
 
                                            type_func = _timedelta_to_milliseconds)
837
 
    interval = notifychangeproperty(dbus.UInt16, "Interval",
838
 
                                    type_func = _timedelta_to_milliseconds)
839
 
    checker_command = notifychangeproperty(dbus.String, "Checker")
840
 
    
841
 
    del notifychangeproperty
 
791
    def _get_approvals_pending(self):
 
792
        return self._approvals_pending
 
793
    def _set_approvals_pending(self, value):
 
794
        old_value = self._approvals_pending
 
795
        self._approvals_pending = value
 
796
        bval = bool(value)
 
797
        if (hasattr(self, "dbus_object_path")
 
798
            and bval is not bool(old_value)):
 
799
            dbus_bool = dbus.Boolean(bval, variant_level=1)
 
800
            self.PropertyChanged(dbus.String("ApprovalPending"),
 
801
                                 dbus_bool)
 
802
 
 
803
    approvals_pending = property(_get_approvals_pending,
 
804
                                 _set_approvals_pending)
 
805
    del _get_approvals_pending, _set_approvals_pending
 
806
    
 
807
    @staticmethod
 
808
    def _datetime_to_dbus(dt, variant_level=0):
 
809
        """Convert a UTC datetime.datetime() to a D-Bus type."""
 
810
        if dt is None:
 
811
            return dbus.String("", variant_level = variant_level)
 
812
        return dbus.String(dt.isoformat(),
 
813
                           variant_level=variant_level)
 
814
    
 
815
    def enable(self):
 
816
        oldstate = getattr(self, "enabled", False)
 
817
        r = Client.enable(self)
 
818
        if oldstate != self.enabled:
 
819
            # Emit D-Bus signals
 
820
            self.PropertyChanged(dbus.String("Enabled"),
 
821
                                 dbus.Boolean(True, variant_level=1))
 
822
            self.PropertyChanged(
 
823
                dbus.String("LastEnabled"),
 
824
                self._datetime_to_dbus(self.last_enabled,
 
825
                                       variant_level=1))
 
826
        return r
 
827
    
 
828
    def disable(self, quiet = False):
 
829
        oldstate = getattr(self, "enabled", False)
 
830
        r = Client.disable(self, quiet=quiet)
 
831
        if not quiet and oldstate != self.enabled:
 
832
            # Emit D-Bus signal
 
833
            self.PropertyChanged(dbus.String("Enabled"),
 
834
                                 dbus.Boolean(False, variant_level=1))
 
835
        return r
842
836
    
843
837
    def __del__(self, *args, **kwargs):
844
838
        try:
853
847
                         *args, **kwargs):
854
848
        self.checker_callback_tag = None
855
849
        self.checker = None
 
850
        # Emit D-Bus signal
 
851
        self.PropertyChanged(dbus.String("CheckerRunning"),
 
852
                             dbus.Boolean(False, variant_level=1))
856
853
        if os.WIFEXITED(condition):
857
854
            exitstatus = os.WEXITSTATUS(condition)
858
855
            # Emit D-Bus signal
867
864
        
868
865
        return Client.checker_callback(self, pid, condition, command,
869
866
                                       *args, **kwargs)
870
 
 
 
867
    
 
868
    def checked_ok(self, *args, **kwargs):
 
869
        Client.checked_ok(self, *args, **kwargs)
 
870
        # Emit D-Bus signal
 
871
        self.PropertyChanged(
 
872
            dbus.String("LastCheckedOK"),
 
873
            (self._datetime_to_dbus(self.last_checked_ok,
 
874
                                    variant_level=1)))
 
875
    
 
876
    def need_approval(self, *args, **kwargs):
 
877
        r = Client.need_approval(self, *args, **kwargs)
 
878
        # Emit D-Bus signal
 
879
        self.PropertyChanged(
 
880
            dbus.String("LastApprovalRequest"),
 
881
            (self._datetime_to_dbus(self.last_approval_request,
 
882
                                    variant_level=1)))
 
883
        return r
 
884
    
871
885
    def start_checker(self, *args, **kwargs):
872
886
        old_checker = self.checker
873
887
        if self.checker is not None:
880
894
            and old_checker_pid != self.checker.pid):
881
895
            # Emit D-Bus signal
882
896
            self.CheckerStarted(self.current_checker_command)
 
897
            self.PropertyChanged(
 
898
                dbus.String("CheckerRunning"),
 
899
                dbus.Boolean(True, variant_level=1))
883
900
        return r
884
901
    
 
902
    def stop_checker(self, *args, **kwargs):
 
903
        old_checker = getattr(self, "checker", None)
 
904
        r = Client.stop_checker(self, *args, **kwargs)
 
905
        if (old_checker is not None
 
906
            and getattr(self, "checker", None) is None):
 
907
            self.PropertyChanged(dbus.String("CheckerRunning"),
 
908
                                 dbus.Boolean(False, variant_level=1))
 
909
        return r
 
910
 
885
911
    def _reset_approved(self):
886
912
        self._approved = None
887
913
        return False
889
915
    def approve(self, value=True):
890
916
        self.send_changedstate()
891
917
        self._approved = value
892
 
        gobject.timeout_add(_timedelta_to_milliseconds
 
918
        gobject.timeout_add(self._timedelta_to_milliseconds
893
919
                            (self.approval_duration),
894
920
                            self._reset_approved)
895
921
    
986
1012
    def ApprovedByDefault_dbus_property(self, value=None):
987
1013
        if value is None:       # get
988
1014
            return dbus.Boolean(self.approved_by_default)
 
1015
        old_value = self.approved_by_default
989
1016
        self.approved_by_default = bool(value)
 
1017
        # Emit D-Bus signal
 
1018
        if old_value != self.approved_by_default:
 
1019
            self.PropertyChanged(dbus.String("ApprovedByDefault"),
 
1020
                                 dbus.Boolean(value, variant_level=1))
990
1021
    
991
1022
    # ApprovalDelay - property
992
1023
    @dbus_service_property(_interface, signature="t",
994
1025
    def ApprovalDelay_dbus_property(self, value=None):
995
1026
        if value is None:       # get
996
1027
            return dbus.UInt64(self.approval_delay_milliseconds())
 
1028
        old_value = self.approval_delay
997
1029
        self.approval_delay = datetime.timedelta(0, 0, 0, value)
 
1030
        # Emit D-Bus signal
 
1031
        if old_value != self.approval_delay:
 
1032
            self.PropertyChanged(dbus.String("ApprovalDelay"),
 
1033
                                 dbus.UInt64(value, variant_level=1))
998
1034
    
999
1035
    # ApprovalDuration - property
1000
1036
    @dbus_service_property(_interface, signature="t",
1001
1037
                           access="readwrite")
1002
1038
    def ApprovalDuration_dbus_property(self, value=None):
1003
1039
        if value is None:       # get
1004
 
            return dbus.UInt64(_timedelta_to_milliseconds(
 
1040
            return dbus.UInt64(self._timedelta_to_milliseconds(
1005
1041
                    self.approval_duration))
 
1042
        old_value = self.approval_duration
1006
1043
        self.approval_duration = datetime.timedelta(0, 0, 0, value)
 
1044
        # Emit D-Bus signal
 
1045
        if old_value != self.approval_duration:
 
1046
            self.PropertyChanged(dbus.String("ApprovalDuration"),
 
1047
                                 dbus.UInt64(value, variant_level=1))
1007
1048
    
1008
1049
    # Name - property
1009
1050
    @dbus_service_property(_interface, signature="s", access="read")
1021
1062
    def Host_dbus_property(self, value=None):
1022
1063
        if value is None:       # get
1023
1064
            return dbus.String(self.host)
 
1065
        old_value = self.host
1024
1066
        self.host = value
 
1067
        # Emit D-Bus signal
 
1068
        if old_value != self.host:
 
1069
            self.PropertyChanged(dbus.String("Host"),
 
1070
                                 dbus.String(value, variant_level=1))
1025
1071
    
1026
1072
    # Created - property
1027
1073
    @dbus_service_property(_interface, signature="s", access="read")
1028
1074
    def Created_dbus_property(self):
1029
 
        return dbus.String(datetime_to_dbus(self.created))
 
1075
        return dbus.String(self._datetime_to_dbus(self.created))
1030
1076
    
1031
1077
    # LastEnabled - property
1032
1078
    @dbus_service_property(_interface, signature="s", access="read")
1033
1079
    def LastEnabled_dbus_property(self):
1034
 
        return datetime_to_dbus(self.last_enabled)
 
1080
        return self._datetime_to_dbus(self.last_enabled)
1035
1081
    
1036
1082
    # Enabled - property
1037
1083
    @dbus_service_property(_interface, signature="b",
1051
1097
        if value is not None:
1052
1098
            self.checked_ok()
1053
1099
            return
1054
 
        return datetime_to_dbus(self.last_checked_ok)
 
1100
        return self._datetime_to_dbus(self.last_checked_ok)
1055
1101
    
1056
1102
    # Expires - property
1057
1103
    @dbus_service_property(_interface, signature="s", access="read")
1058
1104
    def Expires_dbus_property(self):
1059
 
        return datetime_to_dbus(self.expires)
 
1105
        return self._datetime_to_dbus(self.expires)
1060
1106
    
1061
1107
    # LastApprovalRequest - property
1062
1108
    @dbus_service_property(_interface, signature="s", access="read")
1063
1109
    def LastApprovalRequest_dbus_property(self):
1064
 
        return datetime_to_dbus(self.last_approval_request)
 
1110
        return self._datetime_to_dbus(self.last_approval_request)
1065
1111
    
1066
1112
    # Timeout - property
1067
1113
    @dbus_service_property(_interface, signature="t",
1069
1115
    def Timeout_dbus_property(self, value=None):
1070
1116
        if value is None:       # get
1071
1117
            return dbus.UInt64(self.timeout_milliseconds())
 
1118
        old_value = self.timeout
1072
1119
        self.timeout = datetime.timedelta(0, 0, 0, value)
 
1120
        # Emit D-Bus signal
 
1121
        if old_value != self.timeout:
 
1122
            self.PropertyChanged(dbus.String("Timeout"),
 
1123
                                 dbus.UInt64(value, variant_level=1))
1073
1124
        if getattr(self, "disable_initiator_tag", None) is None:
1074
1125
            return
1075
1126
        # Reschedule timeout
1097
1148
    def ExtendedTimeout_dbus_property(self, value=None):
1098
1149
        if value is None:       # get
1099
1150
            return dbus.UInt64(self.extended_timeout_milliseconds())
 
1151
        old_value = self.extended_timeout
1100
1152
        self.extended_timeout = datetime.timedelta(0, 0, 0, value)
 
1153
        # Emit D-Bus signal
 
1154
        if old_value != self.extended_timeout:
 
1155
            self.PropertyChanged(dbus.String("ExtendedTimeout"),
 
1156
                                 dbus.UInt64(value, variant_level=1))
1101
1157
 
1102
1158
    # Interval - property
1103
1159
    @dbus_service_property(_interface, signature="t",
1105
1161
    def Interval_dbus_property(self, value=None):
1106
1162
        if value is None:       # get
1107
1163
            return dbus.UInt64(self.interval_milliseconds())
 
1164
        old_value = self.interval
1108
1165
        self.interval = datetime.timedelta(0, 0, 0, value)
 
1166
        # Emit D-Bus signal
 
1167
        if old_value != self.interval:
 
1168
            self.PropertyChanged(dbus.String("Interval"),
 
1169
                                 dbus.UInt64(value, variant_level=1))
1109
1170
        if getattr(self, "checker_initiator_tag", None) is None:
1110
1171
            return
1111
1172
        # Reschedule checker run
1120
1181
    def Checker_dbus_property(self, value=None):
1121
1182
        if value is None:       # get
1122
1183
            return dbus.String(self.checker_command)
 
1184
        old_value = self.checker_command
1123
1185
        self.checker_command = value
 
1186
        # Emit D-Bus signal
 
1187
        if old_value != self.checker_command:
 
1188
            self.PropertyChanged(dbus.String("Checker"),
 
1189
                                 dbus.String(self.checker_command,
 
1190
                                             variant_level=1))
1124
1191
    
1125
1192
    # CheckerRunning - property
1126
1193
    @dbus_service_property(_interface, signature="b",