=== modified file '.bzrignore'
--- .bzrignore 2008-10-03 09:32:30 +0000
+++ .bzrignore 2010-09-30 06:24:20 +0000
@@ -2,8 +2,6 @@
*.8
*.8mandos
confdir
-debian/po/messages.mo
-debian/po/templates.pot
keydir
man
plugin-runner
@@ -12,3 +10,4 @@
plugins.d/password-prompt
plugins.d/splashy
plugins.d/usplash
+plugins.d/plymouth
=== modified file 'DBUS-API'
--- DBUS-API 2010-09-12 03:00:40 +0000
+++ DBUS-API 2010-09-26 18:32:58 +0000
@@ -76,25 +76,26 @@
"clients.conf", in which case they are fully documented in
mandos-clients.conf(5).
- | Name | Type | Access | clients.conf |
- |----------------------+------+------------+---------------------|
- | ApprovedByDefault | b | Read/Write | approved_by_default |
- | ApprovalDelay (a) | t | Read/Write | approval_delay |
- | ApprovalDuration (a) | t | Read/Write | approval_duration |
- | ApprovalPending (b) | b | Read | N/A |
- | Checker | s | Read/Write | checker |
- | CheckerRunning (c) | b | Read/Write | N/A |
- | Created (d) | s | Read | N/A |
- | Enabled (e) | b | Read/Write | N/A |
- | Fingerprint | s | Read | fingerprint |
- | Host | s | Read/Write | host |
- | Interval (a) | t | Read/Write | interval |
- | LastCheckedOK (f) | s | Read/Write | N/A |
- | LastEnabled (g) | s | Read | N/A |
- | Name | s | Read | (Section name) |
- | ObjectPath | o | Read | N/A |
- | Secret (h) | ay | Write | secret (or secfile) |
- | Timeout (a) | t | Read/Write | timeout |
+ | Name | Type | Access | clients.conf |
+ |-------------------------+------+------------+---------------------|
+ | ApprovedByDefault | b | Read/Write | approved_by_default |
+ | ApprovalDelay (a) | t | Read/Write | approval_delay |
+ | ApprovalDuration (a) | t | Read/Write | approval_duration |
+ | ApprovalPending (b) | b | Read | N/A |
+ | Checker | s | Read/Write | checker |
+ | CheckerRunning (c) | b | Read/Write | N/A |
+ | Created (d) | s | Read | N/A |
+ | Enabled (e) | b | Read/Write | N/A |
+ | 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 |
+ | Name | s | Read | (Section name) |
+ | ObjectPath | o | Read | N/A |
+ | Secret (i) | ay | Write | secret (or secfile) |
+ | Timeout (a) | t | Read/Write | timeout |
a) Represented as milliseconds.
@@ -108,17 +109,20 @@
e) Setting this property is equivalent to calling Enable() or
Disable().
- f) The last time a checker was successful, as a RFC 3339 string, or
+ f) The time of the last approval request, as a RFC 3339 string, or
+ an empty string if this has not happened.
+
+ g) The last time a checker was successful, as a 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.
- g) The last time this client was enabled, as a RFC 3339 string, or
+ h) The last time this client was enabled, as a RFC 3339 string, or
an empty string if this has not happened.
- h) A raw byte array, not hexadecimal digits.
+ i) A raw byte array, not hexadecimal digits.
** Signals
*** CheckerCompleted(n: Exitcode, x: Waitstatus, s: Command)
@@ -143,5 +147,26 @@
*** Rejected(s: Reason)
This client was not given its secret for a specified Reason.
+* Copyright
+
+ Copyright © 2010 Teddy Hogeborn
+ Copyright © 2010 Björn Påhlsson
+
+** License:
+
+ This program is free software: you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see
+ .
+
#+STARTUP: showall
=== modified file 'Makefile'
--- Makefile 2010-09-21 19:16:41 +0000
+++ Makefile 2010-09-28 18:57:31 +0000
@@ -23,7 +23,7 @@
OPTIMIZE=-Os
LANGUAGE=-std=gnu99
htmldir=man
-version=1.0.14
+version=1.2
SED=sed
## Use these settings for a traditional /usr/local install
@@ -87,12 +87,12 @@
plugins.d/plymouth
CPROGS=plugin-runner $(PLUGINS)
PROGS=mandos mandos-keygen mandos-ctl mandos-monitor $(CPROGS)
-DOCS=mandos.8 plugin-runner.8mandos mandos-keygen.8 \
- mandos-monitor.8 mandos-ctl.8 \
+DOCS=mandos.8 mandos-keygen.8 mandos-monitor.8 mandos-ctl.8 \
+ mandos.conf.5 mandos-clients.conf.5 plugin-runner.8mandos \
plugins.d/mandos-client.8mandos \
- plugins.d/password-prompt.8mandos mandos.conf.5 \
- plugins.d/usplash.8mandos plugins.d/splashy.8mandos \
- plugins.d/askpass-fifo.8mandos mandos-clients.conf.5
+ plugins.d/password-prompt.8mandos plugins.d/usplash.8mandos \
+ plugins.d/splashy.8mandos plugins.d/askpass-fifo.8mandos \
+ plugins.d/plymouth.8mandos
htmldocs=$(addsuffix .xhtml,$(DOCS))
@@ -300,6 +300,10 @@
fi
gzip --best --to-stdout mandos.8 \
> $(MANDIR)/man8/mandos.8.gz
+ gzip --best --to-stdout mandos-monitor.8 \
+ > $(MANDIR)/man8/mandos-monitor.8.gz
+ gzip --best --to-stdout mandos-ctl.8 \
+ > $(MANDIR)/man8/mandos-ctl.8.gz
gzip --best --to-stdout mandos.conf.5 \
> $(MANDIR)/man5/mandos.conf.5.gz
gzip --best --to-stdout mandos-clients.conf.5 \
@@ -346,16 +350,18 @@
> $(MANDIR)/man8/mandos-keygen.8.gz
gzip --best --to-stdout plugin-runner.8mandos \
> $(MANDIR)/man8/plugin-runner.8mandos.gz
+ gzip --best --to-stdout plugins.d/mandos-client.8mandos \
+ > $(MANDIR)/man8/mandos-client.8mandos.gz
gzip --best --to-stdout plugins.d/password-prompt.8mandos \
> $(MANDIR)/man8/password-prompt.8mandos.gz
- gzip --best --to-stdout plugins.d/mandos-client.8mandos \
- > $(MANDIR)/man8/mandos-client.8mandos.gz
gzip --best --to-stdout plugins.d/usplash.8mandos \
> $(MANDIR)/man8/usplash.8mandos.gz
gzip --best --to-stdout plugins.d/splashy.8mandos \
> $(MANDIR)/man8/splashy.8mandos.gz
gzip --best --to-stdout plugins.d/askpass-fifo.8mandos \
> $(MANDIR)/man8/askpass-fifo.8mandos.gz
+ gzip --best --to-stdout plugins.d/plymouth.8mandos \
+ > $(MANDIR)/man8/plymouth.8mandos.gz
install-client: install-client-nokey
# Post-installation stuff
@@ -370,6 +376,8 @@
$(PREFIX)/sbin/mandos-ctl \
$(PREFIX)/sbin/mandos-monitor \
$(MANDIR)/man8/mandos.8.gz \
+ $(MANDIR)/man8/mandos-monitor.8.gz \
+ $(MANDIR)/man8/mandos-ctl.8.gz \
$(MANDIR)/man5/mandos.conf.5.gz \
$(MANDIR)/man5/mandos-clients.conf.5.gz
update-rc.d -f mandos remove
@@ -391,13 +399,14 @@
$(INITRAMFSTOOLS)/hooks/mandos \
$(INITRAMFSTOOLS)/conf-hooks.d/mandos \
$(INITRAMFSTOOLS)/scripts/init-premount/mandos \
+ $(MANDIR)/man8/mandos-keygen.8.gz \
$(MANDIR)/man8/plugin-runner.8mandos.gz \
- $(MANDIR)/man8/mandos-keygen.8.gz \
+ $(MANDIR)/man8/mandos-client.8mandos.gz
$(MANDIR)/man8/password-prompt.8mandos.gz \
$(MANDIR)/man8/usplash.8mandos.gz \
$(MANDIR)/man8/splashy.8mandos.gz \
$(MANDIR)/man8/askpass-fifo.8mandos.gz \
- $(MANDIR)/man8/mandos-client.8mandos.gz
+ $(MANDIR)/man8/plymouth.8mandos.gz \
-rmdir $(PREFIX)/lib/mandos/plugins.d $(CONFDIR)/plugins.d \
$(PREFIX)/lib/mandos $(CONFDIR) $(KEYDIR)
update-initramfs -k all -u
=== modified file 'NEWS'
--- NEWS 2010-09-09 18:16:14 +0000
+++ NEWS 2010-09-28 18:57:31 +0000
@@ -1,6 +1,33 @@
This NEWS file records noteworthy changes, very tersely.
See the manual for detailed information.
+Version 1.2 (2010-09-28)
+* Client:
+** New "plymouth" plugin to ask for a password using the Plymouth
+ graphical boot system.
+** The Mandos client now automatically chooses a network interface if
+ the DEVICE setting in /etc/initramfs-tools/initramfs.conf is set to
+ the empty string. This is also the new default instead of "eth0".
+** The Mandos client --connect option now loops indefinitely until a
+ password is received from the specified server.
+** Bug fix: Quote directory correctly in mandos-keygen with --password
+** Bug fix: don't use "echo -e" in mandos-keygen; unsupported by dash.
+* Server:
+** Terminology change: clients are now "ENABLED" or "DISABLED", not
+ "valid" or "invalid".
+** New D-Bus API; see the file "DBUS-API".
+** New control utilities using the new D-Bus API:
+ + mandos-ctl A command-line based utility
+ + mandos-monitor A text-based GUI interface
+** New feature: manual interactive approval or denying of clients on a
+ case-by-case basis.
+** New --debuglevel option to control logging
+** Will not write PID file if --debug is passed
+** Bug fix: Avoid race conditions with short "interval" values or
+ fast checkers.
+** Bug fix: Don't try to bind to a network interface when none is
+ specified
+
Version 1.0.14 (2009-10-25)
Enable building without -pie and -fPIE if BROKEN_PIE is set.
=== modified file 'README'
--- README 2009-11-03 00:12:35 +0000
+++ README 2010-09-26 18:32:58 +0000
@@ -144,7 +144,9 @@
plugins to run, all competing to be the first to find a password and
provide it to the plugin runner.
- Three additional plugins are provided:
+ Four additional plugins are provided:
+ * plymouth(8mandos)
+ This prompts for a password when using plymouth(8).
* usplash(8mandos)
This prompts for a password when using usplash(8).
* splashy(8mandos)
@@ -160,8 +162,8 @@
* Copyright
- Copyright © 2008,2009 Teddy Hogeborn
- Copyright © 2008,2009 Björn Påhlsson
+ Copyright © 2008-2010 Teddy Hogeborn
+ Copyright © 2008-2010 Björn Påhlsson
** License:
=== modified file 'TODO'
--- TODO 2010-09-21 19:16:41 +0000
+++ TODO 2010-09-26 18:32:58 +0000
@@ -2,10 +2,6 @@
* Use _attribute_((nonnull)) wherever possible.
-* Release critical
-** mandos-ctl.xml
-*** More examples
-
* mandos-client
** TODO [#B] use scandir(3) instead of readdir(3)
** TODO [#B] Prefix all debug output with "Mandos plugin " + program_invocation_short_name
@@ -85,6 +81,8 @@
** TODO make clients to a dict!
** TODO [#A] Limit approval_delay to max gnutls/tls timeout value
** TODO [#B] break the wait on approval_delay if connection dies
+** TODO Generate Client.runtime_expansions from client options + extra
+** TODO Allow %%(checker)s as a runtime expansion
* mandos.xml
** Add mandos contact info in manual pages
@@ -105,6 +103,7 @@
*** Properties popup
** Nicer crashes. Stack traces Messes up shell.
*** Print a nice "We are sorry" message, save stack trace to log.
+** Show timeout countdown for approval
* mandos-keygen
** TODO Loop until passwords match when run interactively
=== modified file 'common.ent'
--- common.ent 2010-09-09 18:16:14 +0000
+++ common.ent 2010-09-28 18:57:31 +0000
@@ -1,3 +1,3 @@
-
+
=== modified file 'debian/changelog'
--- debian/changelog 2010-09-09 18:16:14 +0000
+++ debian/changelog 2010-09-28 18:57:31 +0000
@@ -1,3 +1,22 @@
+mandos (1.2-1) unstable; urgency=low
+
+ * New upstream release.
+ * Makefile (LINK_FORTIFY_LD): Remove "-fPIE". (Closes: #557076)
+ * debian/control: Add gnupg dependency to "mandos-client" and removed it
+ from "mandos". Added dependency on "python-urwid" "mandos" since the
+ new "mandos-monitor" utility needs it, and on "python (>=2.6) |
+ python-multiprocessing" since the Mandos server now uses it.
+ * debian/rules: Set BROKEN_PIE on mips and mipsel if a known buggy
+ version of binutils is used.
+ * debian/mandos.docs: Also install "/usr/share/doc/mandos/DBUS-API".
+ * debian/mandos.dirs: Added "etc/dbus-1/system.d".
+ * debian/mandos-client.README.Debian: Update info about DEVICE setting
+ of initramfs.conf.
+ * debian/mandos-client.README.Debian: Remove warning about --connect not
+ looping, since it now does.
+
+ -- Teddy Hogeborn Tue, 28 Sep 2010 20:46:11 +0200
+
mandos (1.0.14-1) unstable; urgency=low (HIGH on mips and mipsel)
* New upstream release.
=== modified file 'debian/control'
--- debian/control 2010-09-09 22:26:35 +0000
+++ debian/control 2010-10-01 18:40:55 +0000
@@ -7,7 +7,7 @@
Build-Depends: debhelper (>= 7), docbook-xml, docbook-xsl,
libavahi-core-dev, libgpgme11-dev, libgnutls-dev, xsltproc,
pkg-config
-Standards-Version: 3.8.3
+Standards-Version: 3.9.1
Vcs-Bzr: http://ftp.fukt.bsnet.se/pub/mandos/trunk
Vcs-Browser: http://bzr.fukt.bsnet.se/loggerhead/mandos/trunk/files
Homepage: http://www.fukt.bsnet.se/mandos
@@ -16,7 +16,7 @@
Architecture: all
Depends: ${misc:Depends}, python (>=2.5), python-gnutls, python-dbus,
python-avahi, python-gobject, avahi-daemon, adduser,
- python-urwid
+ python-urwid, python (>=2.6) | python-multiprocessing
Recommends: fping
Description: a server giving encrypted passwords to Mandos clients
This is the server part of the Mandos system, which allows
=== modified file 'debian/copyright'
--- debian/copyright 2009-01-04 21:54:55 +0000
+++ debian/copyright 2010-09-26 18:32:58 +0000
@@ -5,8 +5,8 @@
Upstream-Source:
Files: *
-Copyright: Copyright © 2008,2009 Teddy Hogeborn
-Copyright: Copyright © 2008,2009 Björn Påhlsson
+Copyright: Copyright © 2008-2010 Teddy Hogeborn
+Copyright: Copyright © 2008-2010 Björn Påhlsson
License: GPL-3+
This program is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
=== modified file 'debian/mandos-client.README.Debian'
--- debian/mandos-client.README.Debian 2009-09-08 06:28:20 +0000
+++ debian/mandos-client.README.Debian 2010-09-27 17:53:53 +0000
@@ -1,9 +1,11 @@
* Choose the Client Network Interface
- You MUST make sure that the correct network interface is specified
- in the DEVICE setting in the "/etc/initramfs-tools/initramfs.conf"
- file. *If* this is changed, it will be necessary to update the
- initrd image by running the command
+ Please make sure that the correct network interface is specified in
+ the DEVICE setting in the "/etc/initramfs-tools/initramfs.conf"
+ file. If the setting is empty, the interface will be autodetected
+ at boot time, which may not be correct. *If* the DEVICE setting is
+ changed, it will be necessary to update the initrd image by running
+ the command
update-initramfs -k all -u
@@ -74,9 +76,6 @@
instead of using ZeroConf. The syntax for doing this is
"mandos=connect::".
- Warning: this will cause the client to make exactly one attempt at
- connecting, and then fail if it does not succeed.
-
For very advanced users, it it possible to specify simply
"mandos=connect" on the kernel command line to make the system only
set up the network (using the data in the "ip=" option) and not pass
@@ -84,4 +83,4 @@
work, "--options-for=mandos-client:--connect=:" needs
to be manually added to the file "/etc/mandos/plugin-runner.conf".
- -- Teddy Hogeborn , Tue, 8 Sep 2009 08:25:58 +0200
+ -- Teddy Hogeborn , Mon, 27 Sep 2010 19:53:21 +0200
=== modified file 'mandos'
--- mandos 2010-09-12 18:23:40 +0000
+++ mandos 2010-09-28 18:57:31 +0000
@@ -11,8 +11,8 @@
# "AvahiService" class, and some lines in "main".
#
# Everything else is
-# Copyright © 2008,2009 Teddy Hogeborn
-# Copyright © 2008,2009 Björn Påhlsson
+# Copyright © 2008-2010 Teddy Hogeborn
+# Copyright © 2008-2010 Björn Påhlsson
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -81,7 +81,7 @@
SO_BINDTODEVICE = None
-version = "1.0.14"
+version = "1.2"
#logger = logging.getLogger(u'mandos')
logger = logging.Logger(u'mandos')
@@ -240,36 +240,43 @@
"""A representation of a client host served by this server.
Attributes:
- name: string; from the config file, used in log messages and
- D-Bus identifiers
+ _approved: bool(); 'None' if not yet approved/disapproved
+ approval_delay: datetime.timedelta(); Time to wait for approval
+ approval_duration: datetime.timedelta(); Duration of one approval
+ checker: subprocess.Popen(); a running checker process used
+ to see if the client lives.
+ 'None' if no process is running.
+ checker_callback_tag: a gobject event source tag, or None
+ checker_command: string; External command which is run to check
+ if client lives. %() expansions are done at
+ runtime with vars(self) as dict, so that for
+ instance %(name)s can be used in the command.
+ checker_initiator_tag: a gobject event source tag, or None
+ created: datetime.datetime(); (UTC) object creation
+ current_checker_command: string; current running checker_command
+ disable_hook: If set, called by disable() as disable_hook(self)
+ disable_initiator_tag: a gobject event source tag, or None
+ enabled: bool()
fingerprint: string (40 or 32 hexadecimal digits); used to
uniquely identify the client
- secret: bytestring; sent verbatim (over TLS) to client
host: string; available for use by the checker command
- created: datetime.datetime(); (UTC) object creation
+ interval: datetime.timedelta(); How often to start a new checker
+ last_approval_request: datetime.datetime(); (UTC) or None
+ last_checked_ok: datetime.datetime(); (UTC) or None
last_enabled: datetime.datetime(); (UTC)
- enabled: bool()
- last_checked_ok: datetime.datetime(); (UTC) or None
+ name: string; from the config file, used in log messages and
+ D-Bus identifiers
+ secret: bytestring; sent verbatim (over TLS) to client
timeout: datetime.timedelta(); How long from last_checked_ok
until this client is disabled
- interval: datetime.timedelta(); How often to start a new checker
- disable_hook: If set, called by disable() as disable_hook(self)
- checker: subprocess.Popen(); a running checker process used
- to see if the client lives.
- 'None' if no process is running.
- checker_initiator_tag: a gobject event source tag, or None
- disable_initiator_tag: - '' -
- checker_callback_tag: - '' -
- checker_command: string; External command which is run to check if
- client lives. %() expansions are done at
- runtime with vars(self) as dict, so that for
- instance %(name)s can be used in the command.
- current_checker_command: string; current running checker_command
- approval_delay: datetime.timedelta(); Time to wait for approval
- _approved: bool(); 'None' if not yet approved/disapproved
- approval_duration: datetime.timedelta(); Duration of one approval
+ runtime_expansions: Allowed attributes for runtime expansion.
"""
+ runtime_expansions = (u"approval_delay", u"approval_duration",
+ u"created", u"enabled", u"fingerprint",
+ u"host", u"interval", u"last_checked_ok",
+ u"last_enabled", u"name", u"timeout")
+
@staticmethod
def _timedelta_to_milliseconds(td):
"Convert a datetime.timedelta() to milliseconds"
@@ -315,6 +322,7 @@
self.host = config.get(u"host", u"")
self.created = datetime.datetime.utcnow()
self.enabled = False
+ self.last_approval_request = None
self.last_enabled = None
self.last_checked_ok = None
self.timeout = string_to_delta(config[u"timeout"])
@@ -416,6 +424,9 @@
(self.timeout_milliseconds(),
self.disable))
+ def need_approval(self):
+ self.last_approval_request = datetime.datetime.utcnow()
+
def start_checker(self):
"""Start a new checker subprocess if one is not running.
@@ -450,12 +461,14 @@
command = self.checker_command % self.host
except TypeError:
# Escape attributes for the shell
- escaped_attrs = dict((key,
- re.escape(unicode(str(val),
- errors=
- u'replace')))
- for key, val in
- vars(self).iteritems())
+ escaped_attrs = dict(
+ (attr,
+ re.escape(unicode(str(getattr(self, attr, u"")),
+ errors=
+ u'replace')))
+ for attr in
+ self.runtime_expansions)
+
try:
command = self.checker_command % escaped_attrs
except TypeError, error:
@@ -703,6 +716,10 @@
dbus_object_path: dbus.ObjectPath
bus: dbus.SystemBus()
"""
+
+ runtime_expansions = (Client.runtime_expansions
+ + (u"dbus_object_path",))
+
# dbus.service.Object doesn't use super(), so we can't either.
def __init__(self, bus = None, *args, **kwargs):
@@ -711,9 +728,11 @@
Client.__init__(self, *args, **kwargs)
# Only now, when this client is initialized, can it show up on
# the D-Bus
+ client_object_name = unicode(self.name).translate(
+ {ord(u"."): ord(u"_"),
+ ord(u"-"): ord(u"_")})
self.dbus_object_path = (dbus.ObjectPath
- (u"/clients/"
- + self.name.replace(u".", u"_")))
+ (u"/clients/" + client_object_name))
DBusObjectWithProperties.__init__(self, self.bus,
self.dbus_object_path)
@@ -801,6 +820,15 @@
variant_level=1)))
return r
+ def need_approval(self, *args, **kwargs):
+ r = Client.need_approval(self, *args, **kwargs)
+ # Emit D-Bus signal
+ self.PropertyChanged(
+ dbus.String(u"LastApprovalRequest"),
+ (self._datetime_to_dbus(self.last_approval_request,
+ variant_level=1)))
+ return r
+
def start_checker(self, *args, **kwargs):
old_checker = self.checker
if self.checker is not None:
@@ -881,15 +909,15 @@
@dbus.service.signal(_interface, signature=u"tb")
def NeedApproval(self, timeout, default):
"D-Bus signal"
- pass
+ return self.need_approval()
## Methods
-
+
# Approve - method
@dbus.service.method(_interface, in_signature=u"b")
def Approve(self, value):
self.approve(value)
-
+
# CheckedOK - method
@dbus.service.method(_interface)
def CheckedOK(self):
@@ -1015,6 +1043,15 @@
return dbus.String(self._datetime_to_dbus(self
.last_checked_ok))
+ # LastApprovalRequest - property
+ @dbus_service_property(_interface, signature=u"s", access=u"read")
+ def LastApprovalRequest_dbus_property(self):
+ if self.last_approval_request is None:
+ return dbus.String(u"")
+ return dbus.String(self.
+ _datetime_to_dbus(self
+ .last_approval_request))
+
# Timeout - property
@dbus_service_property(_interface, signature=u"t",
access=u"readwrite")
@@ -1508,7 +1545,7 @@
u"dress: %s", fpr, address)
if self.use_dbus:
# Emit D-Bus signal
- mandos_dbus_service.ClientNotFound(fpr, address)
+ mandos_dbus_service.ClientNotFound(fpr, address[0])
parent_pipe.send(False)
return False
@@ -1647,7 +1684,7 @@
parser.add_option("--debug", action=u"store_true",
help=u"Debug mode; run in foreground and log to"
u" terminal")
- parser.add_option("--debuglevel", type=u"string", metavar="Level",
+ parser.add_option("--debuglevel", type=u"string", metavar="LEVEL",
help=u"Debug level for stdout output")
parser.add_option("--priority", type=u"string", help=u"GnuTLS"
u" priority string (see GnuTLS documentation)")
@@ -1751,11 +1788,12 @@
gnutls_priority=
server_settings[u"priority"],
use_dbus=use_dbus)
- pidfilename = u"/var/run/mandos.pid"
- try:
- pidfile = open(pidfilename, u"w")
- except IOError:
- logger.error(u"Could not open file %r", pidfilename)
+ if not debug:
+ pidfilename = u"/var/run/mandos.pid"
+ try:
+ pidfile = open(pidfilename, u"w")
+ except IOError:
+ logger.error(u"Could not open file %r", pidfilename)
try:
uid = pwd.getpwnam(u"_mandos").pw_uid
@@ -1863,21 +1901,22 @@
if not tcp_server.clients:
logger.warning(u"No clients defined")
- try:
- with pidfile:
- pid = os.getpid()
- pidfile.write(str(pid) + "\n")
- del pidfile
- except IOError:
- logger.error(u"Could not write to file %r with PID %d",
- pidfilename, pid)
- except NameError:
- # "pidfile" was never created
- pass
- del pidfilename
-
if not debug:
+ try:
+ with pidfile:
+ pid = os.getpid()
+ pidfile.write(str(pid) + "\n")
+ del pidfile
+ except IOError:
+ logger.error(u"Could not write to file %r with PID %d",
+ pidfilename, pid)
+ except NameError:
+ # "pidfile" was never created
+ pass
+ del pidfilename
+
signal.signal(signal.SIGINT, signal.SIG_IGN)
+
signal.signal(signal.SIGHUP, lambda signum, frame: sys.exit())
signal.signal(signal.SIGTERM, lambda signum, frame: sys.exit())
=== modified file 'mandos-clients.conf.xml'
--- mandos-clients.conf.xml 2010-09-12 03:00:40 +0000
+++ mandos-clients.conf.xml 2010-09-27 18:57:12 +0000
@@ -3,7 +3,7 @@
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
/etc/mandos/clients.conf">
-
+
%common;
]>
@@ -34,6 +34,7 @@
2008
2009
+ 2010
Teddy Hogeborn
Björn Påhlsson
@@ -100,53 +101,53 @@
- timeout = TIME
-
-
- This option is optional .
-
-
- 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.
-
-
- 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.
-
-
-
-
-
- interval = TIME
-
-
- This option is optional .
-
-
- 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. The default interval is 5 minutes.
-
-
- The format of TIME is the same
- as for timeout above.
+ approval_delay = TIME
+
+
+ This option is optional .
+
+
+ How long to wait for external approval before resorting to
+ use the approved_by_default value. The
+ default is 0s
, i.e. not to wait.
+
+
+ The format of TIME is the same
+ as for timeout below.
+
+
+
+
+
+ approval_duration = TIME
+
+
+ This option is optional .
+
+
+ How long an external approval lasts. The default is 1
+ second.
+
+
+ The format of TIME is the same
+ as for timeout below.
+
+
+
+
+
+ approved_by_default = { 1 | yes | true | on | 0 | no | false | off }
+
+
+ Whether to approve a client by default after
+ the approval_delay . The default
+ is True
.
@@ -196,6 +197,70 @@
+ host = STRING
+
+
+ This option is optional , but highly
+ recommended unless the
+ checker option is modified to a
+ non-standard value without %%(host)s
in it.
+
+
+ Host name for this client. This is not used by the server
+ directly, but can be, and is by default, used by the
+ checker. See the checker option.
+
+
+
+
+
+ interval = TIME
+
+
+ This option is optional .
+
+
+ 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 below
+ timeout
occurs, at which
+ time the client will be disabled, and any running checker
+ killed. The default interval is 5 minutes.
+
+
+ The format of TIME is the same
+ as for timeout below.
+
+
+
+
+
+ secfile = FILENAME
+
+
+ This option is only used if secret is not
+ specified, in which case this option is
+ required .
+
+
+ Similar to the secret , except the secret
+ data is in an external file. The contents of the file
+ should not be base64-encoded, but
+ will be sent to clients verbatim.
+
+
+ File names of the form ~user/foo/bar
+ and $ENVVAR /foo/bar
+ are supported.
+
+
+
+
+
secret = BASE64_ENCODED_DATA
@@ -226,94 +291,30 @@
- secfile = FILENAME
-
-
- This option is only used if secret is not
- specified, in which case this option is
- required .
-
-
- Similar to the secret , except the secret
- data is in an external file. The contents of the file
- should not be base64-encoded, but
- will be sent to clients verbatim.
-
-
- File names of the form ~user/foo/bar
- and $ENVVAR /foo/bar
- are supported.
-
-
-
-
-
- host = STRING
-
-
- This option is optional , but highly
- recommended unless the
- checker option is modified to a
- non-standard value without %%(host)s
in it.
-
-
- Host name for this client. This is not used by the server
- directly, but can be, and is by default, used by the
- checker. See the checker option.
-
-
-
-
-
- approved_by_default = { 1 | yes | true | on | 0 | no | false | off }
-
-
- Whether to approve a client by default after
- the approval_delay . The default
- is True
.
-
-
-
-
-
- approval_delay = timeout = TIME
This option is optional .
- How long to wait for external approval before resorting to
- use the approved_by_default value. The
- default is 0s
, i.e. not to wait.
-
-
- The format of TIME is the same
- as for timeout above.
-
-
-
-
-
- approval_duration = TIME
-
-
- This option is optional .
-
-
- How long an external approval lasts. The default is 1
- second.
-
-
- The format of TIME is the same
- as for timeout above.
+ 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.
+
+
+ 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.
@@ -356,10 +357,28 @@
%%(foo )s
will be replaced by the value of the attribute
foo of the internal
- Client
object. See the
- source code for details, and let the authors know of any
- attributes that are useful so they may be preserved to any new
- versions of this software.
+ Client
object in the
+ Mandos server. The currently allowed values for
+ foo are:
+ approval_delay
,
+ approval_duration
,
+ created
,
+ enabled
,
+ fingerprint
,
+ host
,
+ interval
,
+ last_approval_request
,
+ last_checked_ok
,
+ last_enabled
,
+ name
,
+ timeout
, and, if using
+ D-Bus, dbus_object_path
.
+ See the source code for details. Currently, none of these attributes
+ except host
are guaranteed
+ to be valid in future versions. Therefore, please
+ let the authors know of any attributes that are useful so they
+ may be preserved to any new versions of this software.
Note that this means that, in order to include an actual
=== modified file 'mandos-ctl'
--- mandos-ctl 2010-09-12 18:23:40 +0000
+++ mandos-ctl 2010-09-28 18:57:31 +0000
@@ -1,5 +1,26 @@
#!/usr/bin/python
# -*- mode: python; coding: utf-8 -*-
+#
+# Mandos Monitor - Control and monitor the Mandos server
+#
+# Copyright © 2008-2010 Teddy Hogeborn
+# Copyright © 2008-2010 Björn Påhlsson
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# Contact the authors at .
+#
from __future__ import division
import sys
@@ -17,12 +38,17 @@
'Enabled': u'Enabled',
'Timeout': u'Timeout',
'LastCheckedOK': u'Last Successful Check',
+ 'LastApprovalRequest': u'Last Approval Request',
'Created': u'Created',
'Interval': u'Interval',
'Host': u'Host',
'Fingerprint': u'Fingerprint',
'CheckerRunning': u'Check Is Running',
'LastEnabled': u'Last Enabled',
+ 'ApprovalPending': u'Approval Is Pending',
+ 'ApprovedByDefault': u'Approved By Default',
+ 'ApprovalDelay': u"Approval Delay",
+ 'ApprovalDuration': u"Approval Duration",
'Checker': u'Checker',
}
defaultkeywords = ('Name', 'Enabled', 'Timeout', 'LastCheckedOK')
@@ -31,7 +57,7 @@
server_path = '/'
server_interface = domain + '.Mandos'
client_interface = domain + '.Mandos.Client'
-version = "1.0.14"
+version = "1.2"
def timedelta_to_milliseconds(td):
"Convert a datetime.timedelta object to milliseconds"
@@ -93,7 +119,8 @@
def valuetostring(value, keyword):
if type(value) is dbus.Boolean:
return u"Yes" if value else u"No"
- if keyword in (u"timeout", u"interval"):
+ if keyword in (u"Timeout", u"Interval", u"ApprovalDelay",
+ u"ApprovalDuration"):
return milliseconds_to_string(value)
return unicode(value)
@@ -110,6 +137,7 @@
for client in clients:
print format_string % tuple(valuetostring(client[key], key)
for key in keywords)
+
def has_actions(options):
return any((options.enable,
options.disable,
@@ -121,6 +149,9 @@
options.checker is not None,
options.timeout is not None,
options.interval is not None,
+ options.approved_by_default is not None,
+ options.approval_delay is not None,
+ options.approval_duration is not None,
options.host is not None,
options.secret is not None,
options.approve,
@@ -152,6 +183,16 @@
help="Set timeout for client")
parser.add_option("-i", "--interval", type="string",
help="Set checker interval for client")
+ parser.add_option("--approve-by-default", action="store_true",
+ dest=u"approved_by_default",
+ help="Set client to be approved by default")
+ parser.add_option("--deny-by-default", action="store_false",
+ dest=u"approved_by_default",
+ help="Set client to be denied by default")
+ parser.add_option("--approval-delay", type="string",
+ help="Set delay before client approve/deny")
+ parser.add_option("--approval-duration", type="string",
+ help="Set duration of one client approval")
parser.add_option("-H", "--host", type="string",
help="Set host for client")
parser.add_option("-s", "--secret", type="string",
@@ -161,14 +202,15 @@
parser.add_option("-D", "--deny", action="store_true",
help="Deny any current client request")
options, client_names = parser.parse_args()
-
+
if has_actions(options) and not client_names and not options.all:
- parser.error('Options requires clients names or --all.')
+ parser.error('Options require clients names or --all.')
if options.verbose and has_actions(options):
- parser.error('Verbose option can only be used alone or with --all.')
+ parser.error('--verbose can only be used alone or with'
+ ' --all.')
if options.all and not has_actions(options):
- parser.error('--all requires an action')
-
+ parser.error('--all requires an action.')
+
try:
bus = dbus.SystemBus()
mandos_dbus_objc = bus.get_object(busname, server_path)
@@ -195,17 +237,19 @@
print >> sys.stderr, "Access denied: Accessing mandos server through dbus."
sys.exit(1)
- # Compile list of clients to process
- clients=[]
-
+ # Compile dict of (clients: properties) to process
+ clients={}
+
if options.all or not client_names:
- clients = (bus.get_object(busname, path) for path in mandos_clients.iterkeys())
+ clients = dict((bus.get_object(busname, path), properties)
+ for path, properties in
+ mandos_clients.iteritems())
else:
for name in client_names:
for path, client in mandos_clients.iteritems():
if client['Name'] == name:
client_objc = bus.get_object(busname, path)
- clients.append(client_objc)
+ clients[client_objc] = client
break
else:
print >> sys.stderr, "Client not found on server: %r" % name
@@ -213,13 +257,17 @@
if not has_actions(options) and clients:
if options.verbose:
- keywords = ('Name', 'Enabled', 'Timeout', 'LastCheckedOK',
- 'Created', 'Interval', 'Host', 'Fingerprint',
- 'CheckerRunning', 'LastEnabled', 'Checker')
+ keywords = ('Name', 'Enabled', 'Timeout',
+ 'LastCheckedOK', 'Created', 'Interval',
+ 'Host', 'Fingerprint', 'CheckerRunning',
+ 'LastEnabled', 'ApprovalPending',
+ 'ApprovedByDefault',
+ 'LastApprovalRequest', 'ApprovalDelay',
+ 'ApprovalDuration', 'Checker')
else:
keywords = defaultkeywords
-
- print_clients(mandos_clients.values(), keywords)
+
+ print_clients(clients.values(), keywords)
else:
# Process each client in the list by all selected options
for client in clients:
@@ -251,19 +299,39 @@
timedelta_to_milliseconds
(string_to_delta(options.interval)),
dbus_interface=dbus.PROPERTIES_IFACE)
+ if options.approval_delay:
+ client.Set(client_interface, u"ApprovalDelay",
+ timedelta_to_milliseconds
+ (string_to_delta(options.
+ approval_delay)),
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ if options.approval_duration:
+ client.Set(client_interface, u"ApprovalDuration",
+ timedelta_to_milliseconds
+ (string_to_delta(options.
+ approval_duration)),
+ dbus_interface=dbus.PROPERTIES_IFACE)
if options.timeout:
client.Set(client_interface, u"Timeout",
- timedelta_to_milliseconds(string_to_delta
- (options.timeout)),
+ timedelta_to_milliseconds
+ (string_to_delta(options.timeout)),
dbus_interface=dbus.PROPERTIES_IFACE)
if options.secret:
client.Set(client_interface, u"Secret",
- dbus.ByteArray(open(options.secret, u'rb').read()),
+ dbus.ByteArray(open(options.secret,
+ u'rb').read()),
+ dbus_interface=dbus.PROPERTIES_IFACE)
+ if options.approved_by_default is not None:
+ client.Set(client_interface, u"ApprovedByDefault",
+ dbus.Boolean(options
+ .approved_by_default),
dbus_interface=dbus.PROPERTIES_IFACE)
if options.approve:
- client.Approve(dbus.Boolean(True), dbus_interface=client_interface)
- if options.deny:
- client.Approve(dbus.Boolean(False), dbus_interface=client_interface)
+ client.Approve(dbus.Boolean(True),
+ dbus_interface=client_interface)
+ elif options.deny:
+ client.Approve(dbus.Boolean(False),
+ dbus_interface=client_interface)
if __name__ == '__main__':
main()
=== modified file 'mandos-ctl.xml'
--- mandos-ctl.xml 2010-09-21 19:16:41 +0000
+++ mandos-ctl.xml 2010-09-25 23:52:17 +0000
@@ -2,7 +2,7 @@
-
+
%common;
]>
@@ -101,6 +101,30 @@
+ --approve-by-default
+
+ --deny-by-default
+
+
+
+ --approval-delay
+ TIME
+
+
+
+ --approval-duration
+ TIME
+
+
+
+ --interval
+ TIME
+ -i
+ TIME
+
+
+
--host
STRING
-H
@@ -273,8 +297,8 @@
Set the checker option of the specified
client(s); see mandos-client.conf 5 .
+ >mandos-clients.conf5 .
@@ -288,8 +312,8 @@
Set the timeout option of the specified
client(s); see mandos-client.conf 5 .
+ >mandos-clients.conf5 .
@@ -301,10 +325,51 @@
TIME
- Set the interval option of the specified
- client(s); see mandos-client.conf 5 .
+ Set the interval option of the
+ specified client(s); see mandos-clients.conf 5 .
+
+
+
+
+
+ --approve-by-default
+ --deny-by-default
+
+
+ Set the approved_by_default option of
+ the specified client(s) to True or
+ False , respectively; see
+ mandos-clients.conf 5 .
+
+
+
+
+
+ --approval-delay
+ TIME
+
+
+ Set the approval_delay option of the
+ specified client(s); see mandos-clients.conf 5 .
+
+
+
+
+
+ --approval-duration
+ TIME
+
+
+ Set the approval_duration option of the
+ specified client(s); see mandos-clients.conf 5 .
@@ -318,8 +383,8 @@
Set the host option of the specified
client(s); see mandos-client.conf 5 .
+ >mandos-clients.conf5 .
@@ -333,8 +398,8 @@
Set the secfile option of the specified
client(s); see mandos-client.conf 5 .
+ >mandos-clients.conf5 .
@@ -422,22 +487,56 @@
EXAMPLE
- List all clients with some of their settings:
+ To list all clients:
&COMMANDNAME;
-
-
- Show all settings for the clients named foo
and
- bar
:
-
-
-
-
-&COMMANDNAME; --verbose foo bar
-
+
+
+
+ To list all settings for the clients
+ named foo1.example.org
and foo2.example.org
:
+
+
+
+
+&COMMANDNAME; --verbose foo1.example.org foo2.example.org
+
+
+
+
+
+
+ To enable all clients:
+
+
+ &COMMANDNAME; --enable --all
+
+
+
+
+
+ To change timeout and interval value for the clients
+ named foo1.example.org
and foo2.example.org
:
+
+
+
+
+&COMMANDNAME; --timeout="5m" --interval="1m" foo1.example.org foo2.example.org
+
+
+
+
+
+
+ To approve all clients currently waiting for it:
+
+
+ &COMMANDNAME; --approve --all
=== modified file 'mandos-keygen'
--- mandos-keygen 2010-09-13 06:19:45 +0000
+++ mandos-keygen 2010-10-01 18:40:55 +0000
@@ -2,8 +2,8 @@
#
# Mandos key generator - create a new OpenPGP key for a Mandos client
#
-# Copyright © 2008,2009 Teddy Hogeborn
-# Copyright © 2008,2009 Björn Påhlsson
+# Copyright © 2008-2010 Teddy Hogeborn
+# Copyright © 2008-2010 Björn Påhlsson
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@
# Contact the authors at .
#
-VERSION="1.0.14"
+VERSION="1.2"
KEYDIR="/etc/keys/mandos"
KEYTYPE=DSA
@@ -195,6 +195,8 @@
stty echo; \
" EXIT
+set -e
+
umask 077
if [ "$mode" = keygen ]; then
=== modified file 'mandos-monitor'
--- mandos-monitor 2010-09-14 18:22:03 +0000
+++ mandos-monitor 2010-09-28 18:57:31 +0000
@@ -1,5 +1,26 @@
#!/usr/bin/python
# -*- mode: python; coding: utf-8 -*-
+#
+# Mandos Monitor - Control and monitor the Mandos server
+#
+# Copyright © 2009,2010 Teddy Hogeborn
+# Copyright © 2009,2010 Björn Påhlsson
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# Contact the authors at .
+#
from __future__ import division, absolute_import, with_statement
@@ -30,7 +51,7 @@
domain = 'se.bsnet.fukt'
server_interface = domain + '.Mandos'
client_interface = domain + '.Mandos.Client'
-version = "1.0.15"
+version = "1.2"
# Always run in monochrome mode
urwid.curses_display.curses.has_colors = lambda : False
@@ -102,6 +123,7 @@
self.logger = logger
self._update_timer_callback_tag = None
+ self._update_timer_callback_lock = 0
self.last_checker_failed = False
# The widget shown normally
@@ -113,6 +135,25 @@
*args, **kwargs)
self.update()
self.opened = False
+
+ last_checked_ok = isoformat_to_datetime(self.properties
+ [u"LastCheckedOK"])
+ if last_checked_ok is None:
+ self.last_checker_failed = True
+ else:
+ self.last_checker_failed = ((datetime.datetime.utcnow()
+ - last_checked_ok)
+ > datetime.timedelta
+ (milliseconds=
+ self.properties
+ [u"Interval"]))
+
+ if self.last_checker_failed:
+ self.using_timer(True)
+
+ if self.need_approval:
+ self.using_timer(True)
+
self.proxy.connect_to_signal(u"CheckerCompleted",
self.checker_completed,
client_interface,
@@ -133,28 +174,35 @@
self.rejected,
client_interface,
byte_arrays=True)
- last_checked_ok = isoformat_to_datetime(self.properties
- [u"LastCheckedOK"])
- if last_checked_ok is None:
- self.last_checker_failed = True
+
+ def property_changed(self, property=None, value=None):
+ super(self, MandosClientWidget).property_changed(property,
+ value)
+ if property == u"ApprovalPending":
+ using_timer(bool(value))
+
+ def using_timer(self, flag):
+ """Call this method with True or False when timer should be
+ activated or deactivated.
+ """
+ old = self._update_timer_callback_lock
+ if flag:
+ self._update_timer_callback_lock += 1
else:
- self.last_checker_failed = ((datetime.datetime.utcnow()
- - last_checked_ok)
- > datetime.timedelta
- (milliseconds=
- self.properties
- [u"Interval"]))
- if self.last_checker_failed:
+ self._update_timer_callback_lock -= 1
+ if old == 0 and self._update_timer_callback_lock:
self._update_timer_callback_tag = (gobject.timeout_add
(1000,
self.update_timer))
+ elif old and self._update_timer_callback_lock == 0:
+ gobject.source_remove(self._update_timer_callback_tag)
+ self._update_timer_callback_tag = None
def checker_completed(self, exitstatus, condition, command):
if exitstatus == 0:
if self.last_checker_failed:
self.last_checker_failed = False
- gobject.source_remove(self._update_timer_callback_tag)
- self._update_timer_callback_tag = None
+ self.using_timer(False)
#self.logger(u'Checker for client %s (command "%s")'
# u' was successful'
# % (self.properties[u"Name"], command))
@@ -163,9 +211,7 @@
# Checker failed
if not self.last_checker_failed:
self.last_checker_failed = True
- self._update_timer_callback_tag = (gobject.timeout_add
- (1000,
- self.update_timer))
+ self.using_timer(True)
if os.WIFEXITED(condition):
self.logger(u'Checker for client %s (command "%s")'
u' failed with exit code %s'
@@ -202,6 +248,7 @@
message = u'Client %s will get its secret in %s seconds'
self.logger(message
% (self.properties[u"Name"], timeout/1000))
+ self.using_timer(True)
def rejected(self, reason):
self.logger(u'Client %s was rejected; reason: %s'
@@ -242,10 +289,21 @@
if not self.properties[u"Enabled"]:
message = u"DISABLED"
elif self.properties[u"ApprovalPending"]:
+ timeout = datetime.timedelta(milliseconds
+ = self.properties
+ [u"ApprovalDelay"])
+ last_approval_request = isoformat_to_datetime(
+ self.properties[u"LastApprovalRequest"])
+ if last_approval_request is not None:
+ timer = timeout - (datetime.datetime.utcnow()
+ - last_approval_request)
+ else:
+ timer = datetime.timedelta()
if self.properties[u"ApprovedByDefault"]:
- message = u"Connection established to client. (d)eny?"
+ message = u"Approval in %s. (d)eny?"
else:
- message = u"Seeks approval to send secret. (a)pprove?"
+ message = u"Denial in %s. (a)pprove?"
+ message = message % unicode(timer).rsplit(".", 1)[0]
elif self.last_checker_failed:
timeout = datetime.timedelta(milliseconds
= self.properties
@@ -256,7 +314,7 @@
self.properties[u"LastEnabled"]))
timer = timeout - (datetime.datetime.utcnow() - last_ok)
message = (u'A checker has failed! Time until client'
- u' gets diabled: %s'
+ u' gets disabled: %s'
% unicode(timer).rsplit(".", 1)[0])
else:
message = u"enabled"
@@ -309,7 +367,7 @@
elif key == u"d":
self.proxy.Approve(dbus.Boolean(False, variant_level=1),
dbus_interface = client_interface)
- elif key == u"r" or key == u"_" or key == u"ctrl k":
+ elif key == u"R" or key == u"_" or key == u"ctrl k":
self.server_proxy_object.RemoveClient(self.proxy
.object_path)
elif key == u"s":
@@ -628,7 +686,7 @@
.join((u"Clients:",
u"+: Enable",
u"-: Disable",
- u"r: Remove",
+ u"R: Remove",
u"s: Start new checker",
u"S: Stop checker",
u"C: Checker OK",
=== modified file 'mandos-monitor.xml'
--- mandos-monitor.xml 2010-09-14 18:22:03 +0000
+++ mandos-monitor.xml 2010-09-30 06:24:20 +0000
@@ -167,7 +167,7 @@
Deny client
- r, _, Ctrl-K
+ R, _, Ctrl-K
Remove client
=== modified file 'mandos.lsm'
--- mandos.lsm 2010-09-14 18:22:03 +0000
+++ mandos.lsm 2010-09-28 18:57:31 +0000
@@ -1,7 +1,7 @@
Begin4
Title: Mandos
-Version: 1.0.14
-Entered-date: 2010-09-14
+Version: 1.2
+Entered-date: 2010-09-28
Description: The Mandos system allows computers to have encrypted
root file systems and at the same time be capable of remote and/or
unattended reboots.
@@ -12,9 +12,9 @@
Maintained-by: teddy@fukt.bsnet.se (Teddy Hogeborn),
belorn@fukt.bsnet.se (Björn Påhlsson)
Primary-site: http://www.fukt.bsnet.se/mandos
- 103K mandos_1.0.14.orig.tar.gz
+ 132K mandos_1.2.orig.tar.gz
Alternate-site: ftp://ftp.fukt.bsnet.se/pub/mandos
- 103K mandos_1.0.14.orig.tar.gz
+ 132K mandos_1.2.orig.tar.gz
Platforms: Requires GCC, GNU libC, Avahi, GnuPG, Python 2.5, and
various other libraries. While made for Debian GNU/Linux, it is
probably portable to other distributions, but not other Unixes.
=== modified file 'mandos.xml'
--- mandos.xml 2010-09-12 03:00:40 +0000
+++ mandos.xml 2010-09-27 17:39:03 +0000
@@ -2,7 +2,7 @@
-
+
%common;
]>
@@ -33,6 +33,7 @@
2008
2009
+ 2010
Teddy Hogeborn
Björn Påhlsson
@@ -86,6 +87,9 @@
--debug
+ --debuglevel
+ LEVEL
+
--no-dbus
--no-ipv6
@@ -194,6 +198,24 @@
+ --debuglevel
+ LEVEL
+
+
+ Set the debugging log level.
+ LEVEL is a string, one of
+ CRITICAL
,
+ ERROR
,
+ WARNING
,
+ INFO
, or
+ DEBUG
, in order of
+ increasing verbosity. The default level is
+ WARNING
.
+
+
+
+
+
--priority
PRIORITY
@@ -338,6 +360,26 @@
+
+ APPROVAL
+
+ The server can be configured to require manual approval for a
+ client before it is sent its secret. The delay to wait for such
+ approval and the default action (approve or deny) can be
+ configured both globally and per client; see
+ mandos-clients.conf
+ 5 . By default all clients
+ will be approved immediately without delay.
+
+
+ This can be used to deny a client its secret if not manually
+ approved within a specified time. It can also be used to make
+ the server delay before giving a client its secret, allowing
+ optional manual denying of this specific client.
+
+
+
+
LOGGING
@@ -418,8 +460,8 @@
/var/run/mandos.pid
- The file containing the process id of
- &COMMANDNAME; .
+ The file containing the process id of the
+ &COMMANDNAME; process started last.
=== modified file 'plugin-runner.c'
--- plugin-runner.c 2010-09-09 22:06:10 +0000
+++ plugin-runner.c 2010-09-26 21:27:28 +0000
@@ -2,8 +2,8 @@
/*
* Mandos plugin runner - Run Mandos plugins
*
- * Copyright © 2008,2009 Teddy Hogeborn
- * Copyright © 2008,2009 Björn Påhlsson
+ * Copyright © 2008-2010 Teddy Hogeborn
+ * Copyright © 2008-2010 Björn Påhlsson
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
=== modified file 'plugins.d/askpass-fifo.c'
--- plugins.d/askpass-fifo.c 2010-09-07 16:48:58 +0000
+++ plugins.d/askpass-fifo.c 2010-09-26 18:32:58 +0000
@@ -2,8 +2,8 @@
/*
* Askpass-FIFO - Read a password from a FIFO and output it
*
- * Copyright © 2008,2009 Teddy Hogeborn
- * Copyright © 2008,2009 Björn Påhlsson
+ * Copyright © 2008-2010 Teddy Hogeborn
+ * Copyright © 2008-2010 Björn Påhlsson
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
=== modified file 'plugins.d/mandos-client.c'
--- plugins.d/mandos-client.c 2010-09-12 18:12:11 +0000
+++ plugins.d/mandos-client.c 2010-09-26 21:27:28 +0000
@@ -9,8 +9,8 @@
* "browse_callback", and parts of "main".
*
* Everything else is
- * Copyright © 2008,2009 Teddy Hogeborn
- * Copyright © 2008,2009 Björn Påhlsson
+ * Copyright © 2008-2010 Teddy Hogeborn
+ * Copyright © 2008-2010 Björn Påhlsson
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
=== modified file 'plugins.d/mandos-client.xml'
--- plugins.d/mandos-client.xml 2010-08-10 19:08:24 +0000
+++ plugins.d/mandos-client.xml 2010-09-26 18:32:58 +0000
@@ -2,7 +2,7 @@
-
+
%common;
]>
=== modified file 'plugins.d/password-prompt.c'
--- plugins.d/password-prompt.c 2010-09-07 16:48:58 +0000
+++ plugins.d/password-prompt.c 2010-09-26 18:32:58 +0000
@@ -2,8 +2,8 @@
/*
* Password-prompt - Read a password from the terminal and print it
*
- * Copyright © 2008,2009 Teddy Hogeborn
- * Copyright © 2008,2009 Björn Påhlsson
+ * Copyright © 2008-2010 Teddy Hogeborn
+ * Copyright © 2008-2010 Björn Påhlsson
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
=== modified file 'plugins.d/plymouth.c'
--- plugins.d/plymouth.c 2010-09-15 17:21:04 +0000
+++ plugins.d/plymouth.c 2010-09-26 18:32:58 +0000
@@ -1,3 +1,27 @@
+/* -*- coding: utf-8 -*- */
+/*
+ * Usplash - Read a password from usplash and output it
+ *
+ * Copyright © 2010 Teddy Hogeborn
+ * Copyright © 2010 Björn Påhlsson
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see
+ * .
+ *
+ * Contact the authors at .
+ */
+
#define _GNU_SOURCE /* asprintf(), TEMP_FAILURE_RETRY() */
#include /* sig_atomic_t, struct sigaction,
sigemptyset(), sigaddset(), SIGINT,
@@ -6,14 +30,15 @@
#include /* bool, false, true */
#include /* open(), O_RDONLY */
#include /* and, or, not*/
-#include /* size_t, ssize_t, pid_t, struct dirent,
- waitpid() */
+#include /* size_t, ssize_t, pid_t, struct
+ dirent, waitpid() */
#include /* waitpid() */
#include /* NULL */
#include /* strchr(), memcmp() */
-#include /* asprintf(), perror(), fopen(), fscanf() */
-#include /* close(), readlink(), read(), fork()
- setsid(), chdir(), dup2()
+#include /* asprintf(), perror(), fopen(),
+ fscanf() */
+#include /* close(), readlink(), read(),
+ fork(), setsid(), chdir(), dup2(),
STDERR_FILENO, execv(), access() */
#include /* free(), EXIT_FAILURE, realloc(),
EXIT_SUCCESS, malloc(), _exit(),
@@ -21,7 +46,7 @@
#include /* scandir(), alphasort() */
#include /* intmax_t, strtoumax(), SCNuMAX */
#include /* struct stat, lstat() */
-#include /* EX_OSERR */
+#include /* EX_OSERR, EX_UNAVAILABLE */
#include /* error() */
#include /* TEMP_FAILURE_RETRY */
#include /* argz_count(), argz_extract() */
@@ -30,9 +55,12 @@
const char plymouth_pid[] = "/dev/.initramfs/plymouth.pid";
const char plymouth_path[] = "/bin/plymouth";
const char plymouthd_path[] = "/sbin/plymouthd";
-const char *plymouthd_default_argv[] = {"/sbin/plymouthd", "--mode=boot",
+const char *plymouthd_default_argv[] = {"/sbin/plymouthd",
+ "--mode=boot",
"--attach-to-session",
- "--pid-file=/dev/.initramfs/plymouth.pid",
+ "--pid-file="
+ "/dev/.initramfs/"
+ "plymouth.pid",
NULL };
static void termination_handler(__attribute__((unused))int signum){
@@ -123,7 +151,7 @@
if (tmp == NULL){
error(0, errno, "realloc");
free(new_argv);
- _exit(EXIT_FAILURE);
+ _exit(EX_OSERR);
}
new_argv = (char **)tmp;
new_argv[i] = strdup(argv[i]);
@@ -149,7 +177,7 @@
error(0, errno, "waitpid");
return false;
}
- if(WIFEXITED(status) and WEXITSTATUS(status) == 0){
+ if(WIFEXITED(status) and (WEXITSTATUS(status) == 0)){
return true;
}
return false;
@@ -163,7 +191,8 @@
errno = 0;
maxvalue = strtoumax(proc_entry->d_name, &tmp, 10);
- if(errno != 0 or *tmp != '\0' or maxvalue != (uintmax_t)((pid_t)maxvalue)){
+ if(errno != 0 or *tmp != '\0'
+ or maxvalue != (uintmax_t)((pid_t)maxvalue)){
return 0;
}
}
@@ -174,7 +203,7 @@
error(0, errno, "asprintf");
return 0;
}
-
+
struct stat exe_stat;
ret = lstat(exe_link, &exe_stat);
if(ret == -1){
@@ -191,7 +220,7 @@
free(exe_link);
return 0;
}
-
+
ssize_t sret = readlink(exe_link, exe_target, sizeof(exe_target));
free(exe_link);
if((sret != (ssize_t)sizeof(plymouth_path)-1) or
@@ -308,92 +337,95 @@
/* test -x /bin/plymouth */
ret = access(plymouth_path, X_OK);
if(ret == -1){
- exit(EXIT_FAILURE);
+ /* Plymouth is probably not installed. Don't print an error
+ message, just exit. */
+ exit(EX_UNAVAILABLE);
}
-
+
{ /* Add signal handlers */
struct sigaction old_action,
new_action = { .sa_handler = termination_handler,
.sa_flags = 0 };
sigemptyset(&new_action.sa_mask);
- for(int *sig = (int[]){ SIGINT, SIGHUP, SIGTERM, 0 }; *sig != 0; sig++){
+ for(int *sig = (int[]){ SIGINT, SIGHUP, SIGTERM, 0 };
+ *sig != 0; sig++){
ret = sigaddset(&new_action.sa_mask, *sig);
if(ret == -1){
- error(0, errno, "sigaddset");
- exit(EX_OSERR);
+ error(EX_OSERR, errno, "sigaddset");
}
ret = sigaction(*sig, NULL, &old_action);
if(ret == -1){
- error(0, errno, "sigaction");
- exit(EX_OSERR);
+ error(EX_OSERR, errno, "sigaction");
}
if(old_action.sa_handler != SIG_IGN){
ret = sigaction(*sig, &new_action, NULL);
if(ret == -1){
- error(0, errno, "sigaction");
- exit(EX_OSERR);
+ error(EX_OSERR, errno, "sigaction");
}
}
}
}
-
+
/* plymouth --ping */
bret = exec_and_wait(&plymouth_command_pid, plymouth_path,
- (const char *[]){ (const char *)plymouth_path, (const char *)"--ping", (const char *)NULL},
+ (const char *[])
+ { plymouth_path, "--ping", NULL },
true, false);
if(not bret){
if(interrupted_by_signal){
kill_and_wait(plymouth_command_pid);
+ exit(EXIT_FAILURE);
}
- exit(EXIT_FAILURE);
+ /* Plymouth is probably not running. Don't print an error
+ message, just exit. */
+ exit(EX_UNAVAILABLE);
}
prompt = makeprompt();
ret = asprintf(&prompt_arg, "--prompt=%s", prompt);
free(prompt);
if(ret == -1){
- error(0, errno, "asprintf");
- exit(EXIT_FAILURE);
+ error(EX_OSERR, errno, "asprintf");
}
/* plymouth ask-for-password --prompt="$prompt" */
- bret = exec_and_wait(&plymouth_command_pid, plymouth_path,
- (const char *[]){plymouth_path, "ask-for-password", prompt_arg, NULL},
+ bret = exec_and_wait(&plymouth_command_pid,
+ plymouth_path, (const char *[])
+ { plymouth_path, "ask-for-password",
+ prompt_arg, NULL },
true, false);
free(prompt_arg);
- if(not bret){
- if(interrupted_by_signal){
- kill_and_wait(plymouth_command_pid);
- } else {
- exit(EXIT_FAILURE);
- }
- }
-
if(bret){
exit(EXIT_SUCCESS);
}
+ if(not interrupted_by_signal){
+ /* exec_and_wait failed for some other reason */
+ exit(EXIT_FAILURE);
+ }
+ kill_and_wait(plymouth_command_pid);
- const char **plymouthd_argv = NULL;
+ const char **plymouthd_argv;
pid_t pid = get_pid();
if(pid == 0){
error(0, 0, "plymouthd pid not found");
+ plymouthd_argv = plymouthd_default_argv;
} else {
plymouthd_argv = getargv(pid);
}
- if(plymouthd_argv == NULL){
- plymouthd_argv = plymouthd_default_argv;
- }
- bret = exec_and_wait(NULL, plymouth_path,
- (const char *[]){plymouth_path, "quit", NULL}, false, false);
- if(not bret){
- exit(EXIT_FAILURE);
- }
- bret = exec_and_wait(NULL, plymouthd_path, plymouthd_argv, false, true);
- if(not bret){
- exit(EXIT_FAILURE);
- }
- exec_and_wait(NULL, plymouth_path,
- (const char *[]){ plymouth_path, "show-splash", NULL }, false, false);
+ bret = exec_and_wait(NULL, plymouth_path, (const char *[])
+ { plymouth_path, "quit", NULL },
+ false, false);
+ if(not bret){
+ exit(EXIT_FAILURE);
+ }
+ bret = exec_and_wait(NULL, plymouthd_path, plymouthd_argv,
+ false, true);
+ if(not bret){
+ exit(EXIT_FAILURE);
+ }
+ exec_and_wait(NULL, plymouth_path, (const char *[])
+ { plymouth_path, "show-splash", NULL },
+ false, false);
exit(EXIT_FAILURE);
}
=== added file 'plugins.d/plymouth.xml'
--- plugins.d/plymouth.xml 1970-01-01 00:00:00 +0000
+++ plugins.d/plymouth.xml 2010-09-26 18:32:58 +0000
@@ -0,0 +1,278 @@
+
+
+
+
+%common;
+]>
+
+
+
+ Mandos Manual
+
+ Mandos
+ &version;
+ &TIMESTAMP;
+
+
+ Björn
+ Påhlsson
+
+ belorn@fukt.bsnet.se
+
+
+
+ Teddy
+ Hogeborn
+
+ teddy@fukt.bsnet.se
+
+
+
+
+ 2010
+ Teddy Hogeborn
+ Björn Påhlsson
+
+
+
+
+
+ &COMMANDNAME;
+ 8mandos
+
+
+
+ &COMMANDNAME;
+ Mandos plugin to use plymouth to get a
+ password.
+
+
+
+
+ &COMMANDNAME;
+
+
+
+
+ DESCRIPTION
+
+ This program prompts for a password using
+ plymouth 8
+ and outputs any given password to standard
+ output. If no plymouth 8
+ process can be found, this program will immediately exit with an
+ exit code indicating failure.
+
+
+ This program is not very useful on its own. This program is
+ really meant to run as a plugin in the Mandos client-side system, where it is used as a
+ fallback and alternative to retrieving passwords from a
+ Mandos server.
+
+
+ If this program is killed (presumably by
+ plugin-runner
+ 8mandos because some other
+ plugin provided the password), it cannot tell
+ plymouth 8
+ to abort requesting a password, because
+ plymouth
+ 8 does not support this.
+ Therefore, this program will then kill the
+ running plymouth
+ 8 process and start a
+ new one using the same command line
+ arguments as the old one was using.
+
+
+
+
+ OPTIONS
+
+ This program takes no options.
+
+
+
+
+ EXIT STATUS
+
+ If exit status is 0, the output from the program is the password
+ as it was read. Otherwise, if exit status is other than 0, the
+ program was interrupted or encountered an error, and any output
+ so far could be corrupt and/or truncated, and should therefore
+ be ignored.
+
+
+
+
+ ENVIRONMENT
+
+
+ cryptsource
+ crypttarget
+
+
+ If set, these environment variables will be assumed to
+ contain the source device name and the target device
+ mapper name, respectively, and will be shown as part of
+ the prompt.
+
+
+ These variables will normally be inherited from
+ plugin-runner
+ 8mandos , which will
+ normally have inherited them from
+ /scripts/local-top/cryptroot in the
+ initial RAM disk environment, which will
+ have set them from parsing kernel arguments and
+ /conf/conf.d/cryptroot (also in the
+ initial RAM disk environment), which in turn will have been
+ created when the initial RAM disk image was created by
+ /usr/share/initramfs-tools/hooks/cryptroot , by
+ extracting the information of the root file system from
+ /etc/crypttab .
+
+
+ This behavior is meant to exactly mirror the behavior of
+ askpass , the default password prompter.
+
+
+
+
+
+
+
+ FILES
+
+
+ /bin/plymouth
+
+
+ This is the command run to retrieve a password from
+ plymouth
+ 8 .
+
+
+
+
+ /proc
+
+
+ To find the running plymouth 8
+ , this directory will be searched for
+ numeric entries which will be assumed to be directories.
+ In all those directories, the exe and
+ cmdline entries will be used to
+ determine the name of the running binary, effective user
+ and group ID , and the command line
+ arguments. See proc 5
+ .
+
+
+
+
+ /sbin/plymouthd
+
+
+ This is the name of the binary which will be searched for
+ in the process list. See plymouth 8
+ .
+
+
+
+
+
+
+
+ BUGS
+
+ Killing the plymouth 8
+ daemon and starting a new one is ugly, but necessary as long as
+ it does not support aborting a password request.
+
+
+
+
+ EXAMPLE
+
+ Note that normally, this program will not be invoked directly,
+ but instead started by the Mandos plugin-runner 8mandos
+ .
+
+
+
+ This program takes no options.
+
+
+ &COMMANDNAME;
+
+
+
+
+
+ SECURITY
+
+ If this program is killed by a signal, it will kill the process
+ ID which at the start of this program was
+ determined to run plymouth 8
+ as root (see also ). There is a very
+ slight risk that, in the time between those events, that process
+ ID was freed and then taken up by another
+ process; the wrong process would then be killed. Now, this
+ program can only be killed by the user who started it; see
+ plugin-runner
+ 8mandos . This program
+ should therefore be started by a completely separate
+ non-privileged user, and no other programs should be allowed to
+ run as that special user. This means that it is not recommended
+ to use the user "nobody" to start this program, as other
+ possibly less trusted programs could be running as "nobody", and
+ they would then be able to kill this program, triggering the
+ killing of the process ID which may or may not
+ be plymouth
+ 8 .
+
+
+ The only other thing that could be considered worthy of note is
+ this: This program is meant to be run by
+ plugin-runner 8mandos , and will, when run
+ standalone, outside, in a normal environment, immediately output
+ on its standard output any presumably secret password it just
+ received. Therefore, when running this program standalone
+ (which should never normally be done), take care not to type in
+ any real secret password by force of habit, since it would then
+ immediately be shown as output.
+
+
+
+
+ SEE ALSO
+
+ crypttab
+ 5 ,
+ plugin-runner
+ 8mandos ,
+ proc
+ 5 ,
+ plymouth
+ 8
+
+
+
+
+
+
+
+
=== modified file 'plugins.d/splashy.c'
--- plugins.d/splashy.c 2010-09-07 16:48:58 +0000
+++ plugins.d/splashy.c 2010-09-26 18:32:58 +0000
@@ -2,8 +2,8 @@
/*
* Splashy - Read a password from splashy and output it
*
- * Copyright © 2008,2009 Teddy Hogeborn
- * Copyright © 2008,2009 Björn Påhlsson
+ * Copyright © 2008-2010 Teddy Hogeborn
+ * Copyright © 2008-2010 Björn Påhlsson
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
=== modified file 'plugins.d/usplash.c'
--- plugins.d/usplash.c 2010-09-15 17:21:04 +0000
+++ plugins.d/usplash.c 2010-09-26 18:32:58 +0000
@@ -2,8 +2,8 @@
/*
* Usplash - Read a password from usplash and output it
*
- * Copyright © 2008,2009 Teddy Hogeborn
- * Copyright © 2008,2009 Björn Påhlsson
+ * Copyright © 2008-2010 Teddy Hogeborn
+ * Copyright © 2008-2010 Björn Påhlsson
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as