=== modified file 'TODO'
--- TODO 2012-06-17 14:55:31 +0000
+++ TODO 2012-06-23 00:58:49 +0000
@@ -47,7 +47,6 @@
** TODO [#C] DBusServiceObjectUsingSuper
** TODO [#B] Global enable/disable flag
** TODO [#B] By-client countdown on number of secrets given
-** TODO [#B] Support RFC 3339 time duration syntax
** D-Bus Client method NeedsPassword(50) - Timeout, default disapprove
+ SetPass(u"gazonk", True) -> Approval, persistent
+ Approve(False) -> Close client connection immediately
@@ -80,7 +79,6 @@
* mandos-ctl
*** Handle "no D-Bus server" and/or "no Mandos server found" better
*** [#B] --dump option
-** TODO Support RFC 3339 time duration syntax
* TODO mandos-dispatch
Listens for specified D-Bus signals and spawns shell commands with
=== modified file 'clients.conf'
--- clients.conf 2011-11-26 23:08:17 +0000
+++ clients.conf 2012-06-23 00:58:49 +0000
@@ -4,19 +4,19 @@
# How long until a client is disabled and not be allowed to get the
# data this server holds.
-;timeout = 5m
+;timeout = PT5M
# How often to run the checker to confirm that a client is still up.
# Note: a new checker will not be started if an old one is still
# running. The server will wait for a checker to complete until the
# above "timeout" occurs, at which time the client will be disabled,
# and any running checker killed.
-;interval = 2m
+;interval = PT2M
# Extended timeout is an added timeout that is given once after a
# password has been sent sucessfully to a client. This allows for
# additional delays caused by file system checks and quota checks.
-;extended_timeout = 15m
+;extended_timeout = PT15M
# What command to run as "the checker".
;checker = fping -q -- %%(host)s
@@ -25,10 +25,10 @@
;approved_by_default = True
# How long to wait for approval.
-;approval_delay = 0s
+;approval_delay = PT0S
# How long one approval will last.
-;approval_duration = 1s
+;approval_duration = PT1S
# Whether this client is enabled by default
;enabled = True
@@ -78,10 +78,10 @@
;host = 192.0.2.3
;
;# Parameters from the [DEFAULT] section can be overridden per client.
-;interval = 1m
+;interval = PT1M
;
;# This client requires manual approval before it receives its secret.
;approved_by_default = False
;# Require approval within 30 seconds.
-;approval_delay = 30s
+;approval_delay = PT30S
;####
=== modified file 'mandos'
--- mandos 2012-06-17 22:26:40 +0000
+++ mandos 2012-06-23 00:58:49 +0000
@@ -68,6 +68,7 @@
import binascii
import tempfile
import itertools
+import collections
import dbus
import dbus.service
@@ -446,13 +447,13 @@
"fingerprint", "host", "interval",
"last_approval_request", "last_checked_ok",
"last_enabled", "name", "timeout")
- client_defaults = { "timeout": "5m",
- "extended_timeout": "15m",
- "interval": "2m",
+ client_defaults = { "timeout": "PT5M",
+ "extended_timeout": "PT15M",
+ "interval": "PT2M",
"checker": "fping -q -- %%(host)s",
"host": "",
- "approval_delay": "0s",
- "approval_duration": "1s",
+ "approval_delay": "PT0S",
+ "approval_duration": "PT1S",
"approved_by_default": "True",
"enabled": "True",
}
@@ -2090,6 +2091,105 @@
return True
+def rfc3339_duration_to_delta(duration):
+ """Parse an RFC 3339 "duration" and return a datetime.timedelta
+
+ >>> rfc3339_duration_to_delta("P7D")
+ datetime.timedelta(7)
+ >>> rfc3339_duration_to_delta("PT60S")
+ datetime.timedelta(0, 60)
+ >>> rfc3339_duration_to_delta("PT60M")
+ datetime.timedelta(0, 3600)
+ >>> rfc3339_duration_to_delta("PT24H")
+ datetime.timedelta(1)
+ >>> rfc3339_duration_to_delta("P1W")
+ datetime.timedelta(7)
+ >>> rfc3339_duration_to_delta("PT5M30S")
+ datetime.timedelta(0, 330)
+ >>> rfc3339_duration_to_delta("P1DT3M20S")
+ datetime.timedelta(1, 200)
+ """
+
+ # Parsing an RFC 3339 duration with regular expressions is not
+ # possible - there would have to be multiple places for the same
+ # values, like seconds. The current code, while more esoteric, is
+ # cleaner without depending on a parsing library. If Python had a
+ # built-in library for parsing we would use it, but we'd like to
+ # avoid excessive use of external libraries.
+
+ # New type for defining tokens, syntax, and semantics all-in-one
+ Token = collections.namedtuple("Token",
+ ("regexp", # To match token; if
+ # "value" is not None,
+ # must have a "group"
+ # containing digits
+ "value", # datetime.timedelta or
+ # None
+ "followers")) # Tokens valid after
+ # this token
+ # RFC 3339 "duration" tokens, syntax, and semantics; taken from
+ # the "duration" ABNF definition in RFC 3339, Appendix A.
+ token_end = Token(re.compile(r"$"), None, frozenset())
+ token_second = Token(re.compile(r"(\d+)S"),
+ datetime.timedelta(seconds=1),
+ frozenset((token_end,)))
+ token_minute = Token(re.compile(r"(\d+)M"),
+ datetime.timedelta(minutes=1),
+ frozenset((token_second, token_end)))
+ token_hour = Token(re.compile(r"(\d+)H"),
+ datetime.timedelta(hours=1),
+ frozenset((token_minute, token_end)))
+ token_time = Token(re.compile(r"T"),
+ None,
+ frozenset((token_hour, token_minute,
+ token_second)))
+ token_day = Token(re.compile(r"(\d+)D"),
+ datetime.timedelta(days=1),
+ frozenset((token_time, token_end)))
+ token_month = Token(re.compile(r"(\d+)M"),
+ datetime.timedelta(weeks=4),
+ frozenset((token_day, token_end)))
+ token_year = Token(re.compile(r"(\d+)Y"),
+ datetime.timedelta(weeks=52),
+ frozenset((token_month, token_end)))
+ token_week = Token(re.compile(r"(\d+)W"),
+ datetime.timedelta(weeks=1),
+ frozenset((token_end,)))
+ token_duration = Token(re.compile(r"P"), None,
+ frozenset((token_year, token_month,
+ token_day, token_time,
+ token_week))),
+ # Define starting values
+ value = datetime.timedelta() # Value so far
+ found_token = None
+ followers = frozenset(token_duration,) # Following valid tokens
+ s = duration # String left to parse
+ # Loop until end token is found
+ while found_token is not token_end:
+ # Search for any currently valid tokens
+ for token in followers:
+ match = token.regexp.match(s)
+ if match is not None:
+ # Token found
+ if token.value is not None:
+ # Value found, parse digits
+ factor = int(match.group(1), 10)
+ # Add to value so far
+ value += factor * token.value
+ # Strip token from string
+ s = token.regexp.sub("", s, 1)
+ # Go to found token
+ found_token = token
+ # Set valid next tokens
+ followers = found_token.followers
+ break
+ else:
+ # No currently valid tokens were found
+ raise ValueError("Invalid RFC 3339 duration")
+ # End token found
+ return value
+
+
def string_to_delta(interval):
"""Parse a string and return a datetime.timedelta
@@ -2106,6 +2206,12 @@
>>> string_to_delta('5m 30s')
datetime.timedelta(0, 330)
"""
+
+ try:
+ return rfc3339_duration_to_delta(interval)
+ except ValueError:
+ pass
+
timevalue = datetime.timedelta(0)
for s in interval.split():
try:
=== modified file 'mandos-clients.conf.xml'
--- mandos-clients.conf.xml 2012-05-26 22:48:45 +0000
+++ mandos-clients.conf.xml 2012-06-23 00:58:49 +0000
@@ -3,7 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
/etc/mandos/clients.conf">
-
+
%common;
]>
@@ -335,17 +335,12 @@
option.
- The TIME is specified as a
- space-separated number of values, each of which is a
- number and a one-character suffix. The suffix must be one
- of d, s, m,
- h, and w for days, seconds,
- minutes, hours, and weeks, respectively. The values are
- added together to give the total time value, so all of
- 330s,
- 110s 110s 110s, and
- 5m 30s will give a value
- of five minutes and thirty seconds.
+ The TIME is specified as an RFC
+ 3339 duration; for example
+ P1Y2M3DT4H5M6S meaning
+ one year, two months, three days, four hours, five
+ minutes, and six seconds. Some values can be omitted, see
+ RFC 3339 Appendix A for details.
@@ -465,8 +460,8 @@
[DEFAULT]
-timeout = 5m
-interval = 2m
+timeout = PT5M
+interval = PT2M
checker = fping -q -- %%(host)s
# Client "foo"
@@ -489,15 +484,15 @@
4T2zw4dxS5NswXWU0sVEXxjs6PYxuIiCTL7vdpx8QjBkrPWDrAbcMyBr2O
QlnHIvPzEArRQLo=
host = foo.example.org
-interval = 1m
+interval = PT1M
# Client "bar"
[bar]
fingerprint = 3e393aeaefb84c7e89e2f547b3a107558fca3a27
secfile = /etc/mandos/bar-secret
-timeout = 15m
+timeout = PT15M
approved_by_default = False
-approval_delay = 30s
+approval_delay = PT30S
@@ -516,6 +511,20 @@
fping8
+
+
+
+ RFC 3339: Date and Time on the Internet:
+ Timestamps
+
+
+
+ The time intervals are in the "duration" format, as
+ specified in ABNF in Appendix A of RFC 3339.
+
+
+
+
=== modified file 'mandos-ctl'
--- mandos-ctl 2012-06-22 23:33:56 +0000
+++ mandos-ctl 2012-06-23 00:58:49 +0000
@@ -85,7 +85,7 @@
def rfc3339_duration_to_delta(duration):
- """Parse a RFC 3339 "duration" and return a datetime.timedelta
+ """Parse an RFC 3339 "duration" and return a datetime.timedelta
>>> rfc3339_duration_to_delta("P7D")
datetime.timedelta(7)
@@ -103,10 +103,10 @@
datetime.timedelta(1, 200)
"""
- # Parsing a RFC 3339 duration with regular expressions is not
+ # Parsing an RFC 3339 duration with regular expressions is not
# possible - there would have to be multiple places for the same
- # values, like seconds. This, while more esoteric, is cleaner
- # without depending on a parsing library. If Python had a
+ # values, like seconds. The current code, while more esoteric, is
+ # cleaner without depending on a parsing library. If Python had a
# built-in library for parsing we would use it, but we'd like to
# avoid excessive use of external libraries.