/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 14:28:47 UTC
  • mto: This revision was merged to the branch mainline in revision 497.
  • Revision ID: belorn@fukt.bsnet.se-20110918142847-wx9ru8lxxsc4timi
New feature:
extended timeout given once when password is sent to client

New dbus-API property (Expire):
Time and date when a client will be disabled

New dbus-API property (ExtendedTimeout):
The duration of extended timeout

Changed default values:
Timeout: Changed from 1 hour to 5 minutes
Interval: Changed from 5 minutes to 2 minutes

Show diffs side-by-side

added added

removed removed

Lines of Context:
297
297
    secret:     bytestring; sent verbatim (over TLS) to client
298
298
    timeout:    datetime.timedelta(); How long from last_checked_ok
299
299
                                      until this client is disabled
 
300
    extended_timeout:   extra long timeout when password has been sent
300
301
    runtime_expansions: Allowed attributes for runtime expansion.
 
302
    expire:     datetime.datetime(); time (UTC) when a client will be
 
303
                disabled, or None
301
304
    """
302
305
    
303
306
    runtime_expansions = ("approval_delay", "approval_duration",
315
318
    def timeout_milliseconds(self):
316
319
        "Return the 'timeout' attribute in milliseconds"
317
320
        return self._timedelta_to_milliseconds(self.timeout)
 
321
 
 
322
    def extended_timeout_milliseconds(self):
 
323
        "Return the 'extended_timeout' attribute in milliseconds"
 
324
        return self._timedelta_to_milliseconds(self.extended_timeout)    
318
325
    
319
326
    def interval_milliseconds(self):
320
327
        "Return the 'interval' attribute in milliseconds"
354
361
        self.last_enabled = None
355
362
        self.last_checked_ok = None
356
363
        self.timeout = string_to_delta(config["timeout"])
 
364
        self.extended_timeout = string_to_delta(config["extended_timeout"])
357
365
        self.interval = string_to_delta(config["interval"])
358
366
        self.disable_hook = disable_hook
359
367
        self.checker = None
360
368
        self.checker_initiator_tag = None
361
369
        self.disable_initiator_tag = None
 
370
        self.expires = None
362
371
        self.checker_callback_tag = None
363
372
        self.checker_command = config["checker"]
364
373
        self.current_checker_command = None
391
400
                                      (self.interval_milliseconds(),
392
401
                                       self.start_checker))
393
402
        # Schedule a disable() when 'timeout' has passed
 
403
        self.expires = datetime.datetime.utcnow() + self.timeout
394
404
        self.disable_initiator_tag = (gobject.timeout_add
395
405
                                   (self.timeout_milliseconds(),
396
406
                                    self.disable))
409
419
        if getattr(self, "disable_initiator_tag", False):
410
420
            gobject.source_remove(self.disable_initiator_tag)
411
421
            self.disable_initiator_tag = None
 
422
        self.expires = None
412
423
        if getattr(self, "checker_initiator_tag", False):
413
424
            gobject.source_remove(self.checker_initiator_tag)
414
425
            self.checker_initiator_tag = None
440
451
            logger.warning("Checker for %(name)s crashed?",
441
452
                           vars(self))
442
453
    
443
 
    def checked_ok(self):
 
454
    def checked_ok(self, timeout=None):
444
455
        """Bump up the timeout for this client.
445
456
        
446
457
        This should only be called when the client has been seen,
447
458
        alive and well.
448
459
        """
 
460
        if timeout is None:
 
461
            timeout = self.timeout
449
462
        self.last_checked_ok = datetime.datetime.utcnow()
450
463
        gobject.source_remove(self.disable_initiator_tag)
 
464
        self.expires = datetime.datetime.utcnow() + timeout
451
465
        self.disable_initiator_tag = (gobject.timeout_add
452
 
                                      (self.timeout_milliseconds(),
 
466
                                      (self._timedelta_to_milliseconds(timeout),
453
467
                                       self.disable))
454
468
    
455
469
    def need_approval(self):
763
777
                                 ("/clients/" + client_object_name))
764
778
        DBusObjectWithProperties.__init__(self, self.bus,
765
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
766
790
        
767
791
    def _get_approvals_pending(self):
768
792
        return self._approvals_pending
783
807
    @staticmethod
784
808
    def _datetime_to_dbus(dt, variant_level=0):
785
809
        """Convert a UTC datetime.datetime() to a D-Bus type."""
 
810
        if dt is None:
 
811
            return dbus.String("", variant_level = variant_level)
786
812
        return dbus.String(dt.isoformat(),
787
813
                           variant_level=variant_level)
788
814
    
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)
990
1017
        # Emit D-Bus signal
991
 
        self.PropertyChanged(dbus.String("ApprovedByDefault"),
992
 
                             dbus.Boolean(value, variant_level=1))
 
1018
        if old_value != self.approved_by_default:
 
1019
            self.PropertyChanged(dbus.String("ApprovedByDefault"),
 
1020
                                 dbus.Boolean(value, variant_level=1))
993
1021
    
994
1022
    # ApprovalDelay - property
995
1023
    @dbus_service_property(_interface, signature="t",
997
1025
    def ApprovalDelay_dbus_property(self, value=None):
998
1026
        if value is None:       # get
999
1027
            return dbus.UInt64(self.approval_delay_milliseconds())
 
1028
        old_value = self.approval_delay
1000
1029
        self.approval_delay = datetime.timedelta(0, 0, 0, value)
1001
1030
        # Emit D-Bus signal
1002
 
        self.PropertyChanged(dbus.String("ApprovalDelay"),
1003
 
                             dbus.UInt64(value, variant_level=1))
 
1031
        if old_value != self.approval_delay:
 
1032
            self.PropertyChanged(dbus.String("ApprovalDelay"),
 
1033
                                 dbus.UInt64(value, variant_level=1))
1004
1034
    
1005
1035
    # ApprovalDuration - property
1006
1036
    @dbus_service_property(_interface, signature="t",
1009
1039
        if value is None:       # get
1010
1040
            return dbus.UInt64(self._timedelta_to_milliseconds(
1011
1041
                    self.approval_duration))
 
1042
        old_value = self.approval_duration
1012
1043
        self.approval_duration = datetime.timedelta(0, 0, 0, value)
1013
1044
        # Emit D-Bus signal
1014
 
        self.PropertyChanged(dbus.String("ApprovalDuration"),
1015
 
                             dbus.UInt64(value, variant_level=1))
 
1045
        if old_value != self.approval_duration:
 
1046
            self.PropertyChanged(dbus.String("ApprovalDuration"),
 
1047
                                 dbus.UInt64(value, variant_level=1))
1016
1048
    
1017
1049
    # Name - property
1018
1050
    @dbus_service_property(_interface, signature="s", access="read")
1030
1062
    def Host_dbus_property(self, value=None):
1031
1063
        if value is None:       # get
1032
1064
            return dbus.String(self.host)
 
1065
        old_value = self.host
1033
1066
        self.host = value
1034
1067
        # Emit D-Bus signal
1035
 
        self.PropertyChanged(dbus.String("Host"),
1036
 
                             dbus.String(value, variant_level=1))
 
1068
        if old_value != self.host:
 
1069
            self.PropertyChanged(dbus.String("Host"),
 
1070
                                 dbus.String(value, variant_level=1))
1037
1071
    
1038
1072
    # Created - property
1039
1073
    @dbus_service_property(_interface, signature="s", access="read")
1043
1077
    # LastEnabled - property
1044
1078
    @dbus_service_property(_interface, signature="s", access="read")
1045
1079
    def LastEnabled_dbus_property(self):
1046
 
        if self.last_enabled is None:
1047
 
            return dbus.String("")
1048
 
        return dbus.String(self._datetime_to_dbus(self.last_enabled))
 
1080
        return self._datetime_to_dbus(self.last_enabled)
1049
1081
    
1050
1082
    # Enabled - property
1051
1083
    @dbus_service_property(_interface, signature="b",
1065
1097
        if value is not None:
1066
1098
            self.checked_ok()
1067
1099
            return
1068
 
        if self.last_checked_ok is None:
1069
 
            return dbus.String("")
1070
 
        return dbus.String(self._datetime_to_dbus(self
1071
 
                                                  .last_checked_ok))
 
1100
        return self._datetime_to_dbus(self.last_checked_ok)
 
1101
    
 
1102
    # Expires - property
 
1103
    @dbus_service_property(_interface, signature="s", access="read")
 
1104
    def Expires_dbus_property(self):
 
1105
        return self._datetime_to_dbus(self.expires)
1072
1106
    
1073
1107
    # LastApprovalRequest - property
1074
1108
    @dbus_service_property(_interface, signature="s", access="read")
1075
1109
    def LastApprovalRequest_dbus_property(self):
1076
 
        if self.last_approval_request is None:
1077
 
            return dbus.String("")
1078
 
        return dbus.String(self.
1079
 
                           _datetime_to_dbus(self
1080
 
                                             .last_approval_request))
 
1110
        return self._datetime_to_dbus(self.last_approval_request)
1081
1111
    
1082
1112
    # Timeout - property
1083
1113
    @dbus_service_property(_interface, signature="t",
1085
1115
    def Timeout_dbus_property(self, value=None):
1086
1116
        if value is None:       # get
1087
1117
            return dbus.UInt64(self.timeout_milliseconds())
 
1118
        old_value = self.timeout
1088
1119
        self.timeout = datetime.timedelta(0, 0, 0, value)
1089
1120
        # Emit D-Bus signal
1090
 
        self.PropertyChanged(dbus.String("Timeout"),
1091
 
                             dbus.UInt64(value, variant_level=1))
 
1121
        if old_value != self.timeout:
 
1122
            self.PropertyChanged(dbus.String("Timeout"),
 
1123
                                 dbus.UInt64(value, variant_level=1))
1092
1124
        if getattr(self, "disable_initiator_tag", None) is None:
1093
1125
            return
1094
1126
        # Reschedule timeout
1095
1127
        gobject.source_remove(self.disable_initiator_tag)
1096
1128
        self.disable_initiator_tag = None
 
1129
        self.expires = None
1097
1130
        time_to_die = (self.
1098
1131
                       _timedelta_to_milliseconds((self
1099
1132
                                                   .last_checked_ok
1104
1137
            # The timeout has passed
1105
1138
            self.disable()
1106
1139
        else:
 
1140
            self.expires = (datetime.datetime.utcnow()
 
1141
                            + datetime.timedelta(milliseconds = time_to_die))
1107
1142
            self.disable_initiator_tag = (gobject.timeout_add
1108
1143
                                          (time_to_die, self.disable))
1109
 
    
 
1144
 
 
1145
    # ExtendedTimeout - property
 
1146
    @dbus_service_property(_interface, signature="t",
 
1147
                           access="readwrite")
 
1148
    def ExtendedTimeout_dbus_property(self, value=None):
 
1149
        if value is None:       # get
 
1150
            return dbus.UInt64(self.extended_timeout_milliseconds())
 
1151
        old_value = self.extended_timeout
 
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))
 
1157
 
1110
1158
    # Interval - property
1111
1159
    @dbus_service_property(_interface, signature="t",
1112
1160
                           access="readwrite")
1113
1161
    def Interval_dbus_property(self, value=None):
1114
1162
        if value is None:       # get
1115
1163
            return dbus.UInt64(self.interval_milliseconds())
 
1164
        old_value = self.interval
1116
1165
        self.interval = datetime.timedelta(0, 0, 0, value)
1117
1166
        # Emit D-Bus signal
1118
 
        self.PropertyChanged(dbus.String("Interval"),
1119
 
                             dbus.UInt64(value, variant_level=1))
 
1167
        if old_value != self.interval:
 
1168
            self.PropertyChanged(dbus.String("Interval"),
 
1169
                                 dbus.UInt64(value, variant_level=1))
1120
1170
        if getattr(self, "checker_initiator_tag", None) is None:
1121
1171
            return
1122
1172
        # Reschedule checker run
1131
1181
    def Checker_dbus_property(self, value=None):
1132
1182
        if value is None:       # get
1133
1183
            return dbus.String(self.checker_command)
 
1184
        old_value = self.checker_command
1134
1185
        self.checker_command = value
1135
1186
        # Emit D-Bus signal
1136
 
        self.PropertyChanged(dbus.String("Checker"),
1137
 
                             dbus.String(self.checker_command,
1138
 
                                         variant_level=1))
 
1187
        if old_value != self.checker_command:
 
1188
            self.PropertyChanged(dbus.String("Checker"),
 
1189
                                 dbus.String(self.checker_command,
 
1190
                                             variant_level=1))
1139
1191
    
1140
1192
    # CheckerRunning - property
1141
1193
    @dbus_service_property(_interface, signature="b",
1329
1381
 
1330
1382
                logger.info("Sending secret to %s", client.name)
1331
1383
                # bump the timeout as if seen
1332
 
                client.checked_ok()
 
1384
                client.checked_ok(client.extended_timeout)
1333
1385
                if self.server.use_dbus:
1334
1386
                    # Emit D-Bus signal
1335
1387
                    client.GotSecret()
1796
1848
                                % server_settings["servicename"]))
1797
1849
    
1798
1850
    # Parse config file with clients
1799
 
    client_defaults = { "timeout": "1h",
1800
 
                        "interval": "5m",
 
1851
    client_defaults = { "timeout": "5m",
 
1852
                        "extended_timeout": "15m",
 
1853
                        "interval": "2m",
1801
1854
                        "checker": "fping -q -- %%(host)s",
1802
1855
                        "host": "",
1803
1856
                        "approval_delay": "0s",