=== modified file 'DBUS-API' --- DBUS-API 2011-03-17 18:14:34 +0000 +++ DBUS-API 2011-09-18 15:59:05 +0000 @@ -86,15 +86,17 @@ | CheckerRunning (c) | b | Read/Write | N/A | | Created (d) | s | Read | N/A | | Enabled (e) | b | Read/Write | N/A | + | Expires (f) | s | Read | N/A | + | ExtendedTimeout (a) | t | Read/Write | extended_timeout | | Fingerprint | s | Read | fingerprint | | Host | s | Read/Write | host | | Interval (a) | t | Read/Write | interval | - | LastApprovalRequest (f) | s | Read | N/A | - | LastCheckedOK (g) | s | Read/Write | N/A | - | LastEnabled (h) | s | Read | N/A | + | LastApprovalRequest (g) | s | Read | N/A | + | LastCheckedOK (h) | s | Read/Write | N/A | + | LastEnabled (i) | s | Read | N/A | | Name | s | Read | (Section name) | | ObjectPath | o | Read | N/A | - | Secret (i) | ay | Write | secret (or secfile) | + | Secret (j) | ay | Write | secret (or secfile) | | Timeout (a) | t | Read/Write | timeout | a) Represented as milliseconds. @@ -109,20 +111,23 @@ e) Setting this property is equivalent to calling Enable() or Disable(). - f) The time of the last approval request, as an RFC 3339 string, or - an empty string if this has not happened. - - g) The last time a checker was successful, as an RFC 3339 string, - or an empty string if this has not happened. Setting this - property is equivalent to calling CheckedOK(), i.e. the current - time is set, regardless of the string sent. Please always use - an empty string when setting this property, to allow for - possible future expansion. - - h) The last time this client was enabled, as an RFC 3339 string, or - an empty string if this has not happened. - - i) A raw byte array, not hexadecimal digits. + f) The date and time this client will be disabled, as an RFC 3339 + string, or an empty string if this has not happened. + + g) The date and time of the last approval request, as an RFC 3339 + string, or an empty string if this has not happened. + + h) The date and time a checker was last successful, as an RFC 3339 + string, or an empty string if this has not happened. Setting + this property is equivalent to calling CheckedOK(), i.e. the + current time is set, regardless of the string sent. Please + always use an empty string when setting this property, to allow + for possible future expansion. + + i) The date and time this client was last enabled, as an RFC 3339 + string, or an empty string if this has not happened. + + j) A raw byte array, not hexadecimal digits. ** Signals *** CheckerCompleted(n: Exitcode, x: Waitstatus, s: Command) === modified file 'README' --- README 2011-08-08 21:12:37 +0000 +++ README 2011-09-18 14:28:47 +0000 @@ -3,7 +3,7 @@ This information previously in this file has been moved to the intro(8mandos) manual page. Go to the above URL, or run this command: - make intro.8mandos && man -l intro.8mandos + man 8mandos intro In short, this is the Mandos system; it allows computers to have encrypted root file systems and at the same time be capable of remote === modified file 'TODO' --- TODO 2011-08-17 22:46:35 +0000 +++ TODO 2011-09-18 14:28:47 +0000 @@ -38,6 +38,7 @@ ** TODO [#B] Use openat() * mandos (server) +** TODO [#A] Make all attributes properties! ** TODO [#B] Log level :BUGS: ** TODO Persistent state :BUGS: /var/lib/mandos/* === modified file 'mandos' --- mandos 2011-07-27 17:58:27 +0000 +++ mandos 2011-09-18 15:59:05 +0000 @@ -297,7 +297,10 @@ secret: bytestring; sent verbatim (over TLS) to client timeout: datetime.timedelta(); How long from last_checked_ok until this client is disabled + extended_timeout: extra long timeout when password has been sent runtime_expansions: Allowed attributes for runtime expansion. + expires: datetime.datetime(); time (UTC) when a client will be + disabled, or None """ runtime_expansions = ("approval_delay", "approval_duration", @@ -315,6 +318,10 @@ def timeout_milliseconds(self): "Return the 'timeout' attribute in milliseconds" return self._timedelta_to_milliseconds(self.timeout) + + def extended_timeout_milliseconds(self): + "Return the 'extended_timeout' attribute in milliseconds" + return self._timedelta_to_milliseconds(self.extended_timeout) def interval_milliseconds(self): "Return the 'interval' attribute in milliseconds" @@ -354,11 +361,13 @@ self.last_enabled = None self.last_checked_ok = None self.timeout = string_to_delta(config["timeout"]) + self.extended_timeout = string_to_delta(config["extended_timeout"]) self.interval = string_to_delta(config["interval"]) self.disable_hook = disable_hook self.checker = None self.checker_initiator_tag = None self.disable_initiator_tag = None + self.expires = None self.checker_callback_tag = None self.checker_command = config["checker"] self.current_checker_command = None @@ -391,6 +400,7 @@ (self.interval_milliseconds(), self.start_checker)) # Schedule a disable() when 'timeout' has passed + self.expires = datetime.datetime.utcnow() + self.timeout self.disable_initiator_tag = (gobject.timeout_add (self.timeout_milliseconds(), self.disable)) @@ -409,6 +419,7 @@ if getattr(self, "disable_initiator_tag", False): gobject.source_remove(self.disable_initiator_tag) self.disable_initiator_tag = None + self.expires = None if getattr(self, "checker_initiator_tag", False): gobject.source_remove(self.checker_initiator_tag) self.checker_initiator_tag = None @@ -440,16 +451,19 @@ logger.warning("Checker for %(name)s crashed?", vars(self)) - def checked_ok(self): + def checked_ok(self, timeout=None): """Bump up the timeout for this client. This should only be called when the client has been seen, alive and well. """ + if timeout is None: + timeout = self.timeout self.last_checked_ok = datetime.datetime.utcnow() gobject.source_remove(self.disable_initiator_tag) + self.expires = datetime.datetime.utcnow() + timeout self.disable_initiator_tag = (gobject.timeout_add - (self.timeout_milliseconds(), + (self._timedelta_to_milliseconds(timeout), self.disable)) def need_approval(self): @@ -763,6 +777,16 @@ ("/clients/" + client_object_name)) DBusObjectWithProperties.__init__(self, self.bus, self.dbus_object_path) + def _set_expires(self, value): + old_value = getattr(self, "_expires", None) + self._expires = value + if hasattr(self, "dbus_object_path") and old_value != value: + dbus_time = (self._datetime_to_dbus(self._expires, + variant_level=1)) + self.PropertyChanged(dbus.String("Expires"), + dbus_time) + expires = property(lambda self: self._expires, _set_expires) + del _set_expires def _get_approvals_pending(self): return self._approvals_pending @@ -783,6 +807,8 @@ @staticmethod def _datetime_to_dbus(dt, variant_level=0): """Convert a UTC datetime.datetime() to a D-Bus type.""" + if dt is None: + return dbus.String("", variant_level = variant_level) return dbus.String(dt.isoformat(), variant_level=variant_level) @@ -986,10 +1012,12 @@ def ApprovedByDefault_dbus_property(self, value=None): if value is None: # get return dbus.Boolean(self.approved_by_default) + old_value = self.approved_by_default self.approved_by_default = bool(value) # Emit D-Bus signal - self.PropertyChanged(dbus.String("ApprovedByDefault"), - dbus.Boolean(value, variant_level=1)) + if old_value != self.approved_by_default: + self.PropertyChanged(dbus.String("ApprovedByDefault"), + dbus.Boolean(value, variant_level=1)) # ApprovalDelay - property @dbus_service_property(_interface, signature="t", @@ -997,10 +1025,12 @@ def ApprovalDelay_dbus_property(self, value=None): if value is None: # get return dbus.UInt64(self.approval_delay_milliseconds()) + old_value = self.approval_delay self.approval_delay = datetime.timedelta(0, 0, 0, value) # Emit D-Bus signal - self.PropertyChanged(dbus.String("ApprovalDelay"), - dbus.UInt64(value, variant_level=1)) + if old_value != self.approval_delay: + self.PropertyChanged(dbus.String("ApprovalDelay"), + dbus.UInt64(value, variant_level=1)) # ApprovalDuration - property @dbus_service_property(_interface, signature="t", @@ -1009,10 +1039,12 @@ if value is None: # get return dbus.UInt64(self._timedelta_to_milliseconds( self.approval_duration)) + old_value = self.approval_duration self.approval_duration = datetime.timedelta(0, 0, 0, value) # Emit D-Bus signal - self.PropertyChanged(dbus.String("ApprovalDuration"), - dbus.UInt64(value, variant_level=1)) + if old_value != self.approval_duration: + self.PropertyChanged(dbus.String("ApprovalDuration"), + dbus.UInt64(value, variant_level=1)) # Name - property @dbus_service_property(_interface, signature="s", access="read") @@ -1030,10 +1062,12 @@ def Host_dbus_property(self, value=None): if value is None: # get return dbus.String(self.host) + old_value = self.host self.host = value # Emit D-Bus signal - self.PropertyChanged(dbus.String("Host"), - dbus.String(value, variant_level=1)) + if old_value != self.host: + self.PropertyChanged(dbus.String("Host"), + dbus.String(value, variant_level=1)) # Created - property @dbus_service_property(_interface, signature="s", access="read") @@ -1043,9 +1077,7 @@ # LastEnabled - property @dbus_service_property(_interface, signature="s", access="read") def LastEnabled_dbus_property(self): - if self.last_enabled is None: - return dbus.String("") - return dbus.String(self._datetime_to_dbus(self.last_enabled)) + return self._datetime_to_dbus(self.last_enabled) # Enabled - property @dbus_service_property(_interface, signature="b", @@ -1065,19 +1097,17 @@ if value is not None: self.checked_ok() return - if self.last_checked_ok is None: - return dbus.String("") - return dbus.String(self._datetime_to_dbus(self - .last_checked_ok)) + return self._datetime_to_dbus(self.last_checked_ok) + + # Expires - property + @dbus_service_property(_interface, signature="s", access="read") + def Expires_dbus_property(self): + return self._datetime_to_dbus(self.expires) # LastApprovalRequest - property @dbus_service_property(_interface, signature="s", access="read") def LastApprovalRequest_dbus_property(self): - if self.last_approval_request is None: - return dbus.String("") - return dbus.String(self. - _datetime_to_dbus(self - .last_approval_request)) + return self._datetime_to_dbus(self.last_approval_request) # Timeout - property @dbus_service_property(_interface, signature="t", @@ -1085,15 +1115,18 @@ def Timeout_dbus_property(self, value=None): if value is None: # get return dbus.UInt64(self.timeout_milliseconds()) + old_value = self.timeout self.timeout = datetime.timedelta(0, 0, 0, value) # Emit D-Bus signal - self.PropertyChanged(dbus.String("Timeout"), - dbus.UInt64(value, variant_level=1)) + if old_value != self.timeout: + self.PropertyChanged(dbus.String("Timeout"), + dbus.UInt64(value, variant_level=1)) if getattr(self, "disable_initiator_tag", None) is None: return # Reschedule timeout gobject.source_remove(self.disable_initiator_tag) self.disable_initiator_tag = None + self.expires = None time_to_die = (self. _timedelta_to_milliseconds((self .last_checked_ok @@ -1104,19 +1137,36 @@ # The timeout has passed self.disable() else: + self.expires = (datetime.datetime.utcnow() + + datetime.timedelta(milliseconds = time_to_die)) self.disable_initiator_tag = (gobject.timeout_add (time_to_die, self.disable)) - + + # ExtendedTimeout - property + @dbus_service_property(_interface, signature="t", + access="readwrite") + def ExtendedTimeout_dbus_property(self, value=None): + if value is None: # get + return dbus.UInt64(self.extended_timeout_milliseconds()) + old_value = self.extended_timeout + self.extended_timeout = datetime.timedelta(0, 0, 0, value) + # Emit D-Bus signal + if old_value != self.extended_timeout: + self.PropertyChanged(dbus.String("ExtendedTimeout"), + dbus.UInt64(value, variant_level=1)) + # Interval - property @dbus_service_property(_interface, signature="t", access="readwrite") def Interval_dbus_property(self, value=None): if value is None: # get return dbus.UInt64(self.interval_milliseconds()) + old_value = self.interval self.interval = datetime.timedelta(0, 0, 0, value) # Emit D-Bus signal - self.PropertyChanged(dbus.String("Interval"), - dbus.UInt64(value, variant_level=1)) + if old_value != self.interval: + self.PropertyChanged(dbus.String("Interval"), + dbus.UInt64(value, variant_level=1)) if getattr(self, "checker_initiator_tag", None) is None: return # Reschedule checker run @@ -1131,11 +1181,13 @@ def Checker_dbus_property(self, value=None): if value is None: # get return dbus.String(self.checker_command) + old_value = self.checker_command self.checker_command = value # Emit D-Bus signal - self.PropertyChanged(dbus.String("Checker"), - dbus.String(self.checker_command, - variant_level=1)) + if old_value != self.checker_command: + self.PropertyChanged(dbus.String("Checker"), + dbus.String(self.checker_command, + variant_level=1)) # CheckerRunning - property @dbus_service_property(_interface, signature="b", @@ -1329,7 +1381,7 @@ logger.info("Sending secret to %s", client.name) # bump the timeout as if seen - client.checked_ok() + client.checked_ok(client.extended_timeout) if self.server.use_dbus: # Emit D-Bus signal client.GotSecret() @@ -1796,8 +1848,9 @@ % server_settings["servicename"])) # Parse config file with clients - client_defaults = { "timeout": "1h", - "interval": "5m", + client_defaults = { "timeout": "5m", + "extended_timeout": "15m", + "interval": "2m", "checker": "fping -q -- %%(host)s", "host": "", "approval_delay": "0s", === modified file 'mandos-clients.conf.xml' --- mandos-clients.conf.xml 2011-08-08 21:12:37 +0000 +++ mandos-clients.conf.xml 2011-09-18 14:28:47 +0000 @@ -229,7 +229,7 @@ will wait for a checker to complete until the below timeout occurs, at which time the client will be disabled, and any running checker - killed. The default interval is 5 minutes. + killed. The default interval is 2 minutes. The format of TIME is the same @@ -302,7 +302,7 @@ The timeout is how long the server will wait (for either a successful checker run or a client receiving its secret) until a client is disabled and not allowed to get the data - this server holds. By default Mandos will use 1 hour. + this server holds. By default Mandos will use 5 minutes. The TIME is specified as a @@ -319,6 +319,29 @@ + + + + + + This option is optional. + + + Extended timeout is an added timeout that is given once + after a password has been sent sucessfully to a client. + The timeout is by default longer than the normal timeout, + and is used for handling the extra long downtime while a + matchine is booting up. Time to take into consideration + when changing this value is system file checks and quota + checks. The default value is 15 minutes. + + + The format of TIME is the same + as for timeout above. + + + @@ -420,8 +443,8 @@ [DEFAULT] -timeout = 1h -interval = 5m +timeout = 5m +interval = 2m checker = fping -q -- %%(host)s # Client "foo" === modified file 'mandos-ctl' --- mandos-ctl 2011-07-27 17:58:27 +0000 +++ mandos-ctl 2011-09-18 14:28:47 +0000 @@ -52,6 +52,7 @@ "ApprovalDelay": "Approval Delay", "ApprovalDuration": "Approval Duration", "Checker": "Checker", + "ExtendedTimeout" : "Extended Timeout" } defaultkeywords = ("Name", "Enabled", "Timeout", "LastCheckedOK") domain = "se.bsnet.fukt" @@ -149,6 +150,7 @@ options.remove, options.checker is not None, options.timeout is not None, + options.extended_timeout is not None, options.interval is not None, options.approved_by_default is not None, options.approval_delay is not None, @@ -185,6 +187,8 @@ help="Set checker command for client") parser.add_argument("-t", "--timeout", help="Set timeout for client") + parser.add_argument("--extended-timeout", + help="Set extended timeout for client") parser.add_argument("-i", "--interval", help="Set checker interval for client") parser.add_argument("--approve-by-default", action="store_true", @@ -270,7 +274,8 @@ "LastEnabled", "ApprovalPending", "ApprovedByDefault", "LastApprovalRequest", "ApprovalDelay", - "ApprovalDuration", "Checker") + "ApprovalDuration", "Checker", + "ExtendedTimeout") else: keywords = defaultkeywords @@ -325,6 +330,11 @@ timedelta_to_milliseconds (string_to_delta(options.timeout)), dbus_interface=dbus.PROPERTIES_IFACE) + if options.extended_timeout: + client.Set(client_interface, "ExtendedTimeout", + timedelta_to_milliseconds + (string_to_delta(options.extended_timeout)), + dbus_interface=dbus.PROPERTIES_IFACE) if options.secret: client.Set(client_interface, "Secret", dbus.ByteArray(open(options.secret, === modified file 'mandos-ctl.xml' --- mandos-ctl.xml 2011-08-08 21:12:37 +0000 +++ mandos-ctl.xml 2011-09-18 14:28:47 +0000 @@ -95,6 +95,11 @@ + + + +