/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-ctl

  • Committer: Teddy Hogeborn
  • Date: 2019-07-27 10:11:45 UTC
  • Revision ID: teddy@recompile.se-20190727101145-jnpbpf8220gldbcd
Add dracut(8) support

Add support for the dracut(8) system for generating initramfs image
files; dracut is an alternative to the "initramfs-tools" package.

* .bzrignore (dracut-module/password-agent): Ignore new binary file.
* dracut-module: New directory for the dracut module.
* INSTALL (Prerequisites/Libraries/Mandos Client): Add dracut as an
                                                   alternative to
                                                   initramfs-tools,
                                                   and also add GLib.
* Makefile (DRACUTMODULE, GLIB_CFLAGS, GLIB_LIBS): New.
  (CPROGS): Add "dracut-module/password-agent".
  (DOCS): Add "dracut-module/password-agent.8mandos".
  (dracut-module/password-agent.8mandos): New.
  (dracut-module/password-agent.8mandos.xhtml): - '' -
  (dracut-module/password-agent): - '' -
  (check): Add command to run tests of password-agent(8mandos).
  (install-client-nokey): Also install the dracut module directory,
                          its files, and the password-agent(8mandos)
                          manual page.
  (install-client): To update the initramfs image file, run
                    update-initramfs or dracut depending on what is
                    installed.
  (uninstall-client): - '' - and also uninstall the the files in the
                      dracut module directory, that directory itself,
                      and the password-agent(8mandos) manual page.
* debian/control (Build-Depends): Add "libglib2.0-dev (>=2.40)".
  (Package: mandos-client/Depends): Add "dracut (>= 044+241-3)" as an
                                    alternative dependency to
                                    initramfs-tools.
  (Package: mandos-client/Conflicts): New; set to
                                      "dracut-config-generic".
  (debian/mandos-client.README.Debian): Document alternative commands
                                        to update the initramfs image
                                        for when dracut is used.
* debian/mandos-client.postinst (update_initramfs): Use alternative
                                                    commands to update
                                                    the initramfs
                                                    image for when
                                                    dracut is used.
* debian/tests/control (password-agent, password-agent-suid): Add two
                                                              new tests.
* dracut-module/ask-password-mandos.path: New.
* dracut-module/ask-password-mandos.service: - '' -
* dracut-module/cmdline-mandos.sh: - '' -
* dracut-module/module-setup.sh: - '' -
* dracut-module/password-agent.c: - '' -
* dracut-module/password-agent.xml: - '' -
* initramfs-unpack: Use the dracut "skipcpio" command, if available.
                    Also be more flexible and try hard to detect where
                    compressed data starts.
* plugins.d/mandos-client.xml (SECURITY): Be more precise that the
                                          mandos-client binary might
                                          not always be setuid, but
                                          that the program assumes
                                          that it has been started
                                          that way.
* plugins.d/password-prompt.c: Add new "--prompt" option.
  (conflict_detection): First try to detect the new PID file of
                        plymouth.
  (main): Define and use new "prompt" variable.
* plugins.d/password-prompt.xml (SYNOPSIS): Show new --prompt option.
  (DESCRIPTION): Describe new behavior of looking for plymouth PID
                 file.
  (OPTIONS): Document new "--prompt" option.
  (ENVIRONMENT): Clarify that the CRYPTTAB_SOURCE and CRYPTTAB_NAME
                 environment variables are not used if the --prompt
                 option is used.  Remove unnecessarily specific
                 details about where the CRYPTTAB_SOURCE and
                 CRYPTTAB_NAME comes from, since this can now be
                 either initramfs-tools or dracut.
  (SEE ALSO): Remove superfluous crypttab(5) reference, and add commas
              to separate the other references.
* plugins.d/plymouth.c: Add new "--prompt" and "--debug" options.
  (debug): New global flag.
  (fprintf_plus): New function, used for debug output.
  (exec_and_wait): Add extra "const" to "argv" argument.
  (main): Define and use new "prompt" variable.  Add debug output.
  (main/options, main/parse_opt): New; used to parse options.
* plugins.d/plymouth.xml (SYNOPSIS): Show new options.
  (OPTIONS): Document new options.
  (ENVIRONMENT): Clarify that the cryptsource and crypttarget
                 environment variables are not used if the --prompt
                 option is used.  Remove unnecessarily specific
                 details about where the cryptsource and crypttarget
                 comes from, since this can now be either
                 initramfs-tools or dracut.
  (EXAMPLE): Add an example using an option.
  (SEE ALSO): Remove superfluous crypttab(5) reference.
* plugins.d/splashy.xml (ENVIRONMENT): Clarify that the cryptsource
                                       and crypttarget environment
                                       variables are not used if the
                                       --prompt option is used.
                                       Remove unnecessarily specific
                                       details about where the
                                       cryptsource and crypttarget
                                       comes from, since this can now
                                       be either initramfs-tools or
                                       dracut.
  (SEE ALSO): Remove superfluous crypttab(5) reference.
* plugins.d/usplash.xml (ENVIRONMENT): Clarify that the cryptsource
                                       and crypttarget environment
                                       variables are not used if the
                                       --prompt option is used.
                                       Remove unnecessarily specific
                                       details about where the
                                       cryptsource and crypttarget
                                       comes from, since this can now
                                       be either initramfs-tools or
                                       dracut.
  (SEE ALSO): Remove superfluous crypttab(5) reference.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/python
2
 
# -*- after-save-hook: (lambda () (let ((command (if (fboundp 'file-local-name) (file-local-name (buffer-file-name)) (or (file-remote-p (buffer-file-name) 'localname) (buffer-file-name))))) (if (= (progn (if (get-buffer "*Test*") (kill-buffer "*Test*")) (process-file-shell-command (format "%s --check" (shell-quote-argument command)) nil "*Test*")) 0) (let ((w (get-buffer-window "*Test*"))) (if w (delete-window w))) (progn (with-current-buffer "*Test*" (compilation-mode)) (display-buffer "*Test*" '(display-buffer-in-side-window)))))); coding: utf-8 -*-
 
2
# -*- after-save-hook: (lambda () (let ((command (if (fboundp 'file-local-name) (file-local-name (buffer-file-name)) (or (file-remote-p (buffer-file-name) 'localname) (buffer-file-name))))) (if (= (progn (if (get-buffer "*Test*") (kill-buffer "*Test*")) (process-file-shell-command (format "%s --test" (shell-quote-argument command)) nil "*Test*")) 0) (let ((w (get-buffer-window "*Test*"))) (if w (delete-window w))) (progn (with-current-buffer "*Test*" (compilation-mode)) (display-buffer "*Test*" '(display-buffer-in-side-window)))))); coding: utf-8 -*-
3
3
#
4
4
# Mandos Monitor - Control and monitor the Mandos server
5
5
#
46
46
import tempfile
47
47
import contextlib
48
48
 
49
 
if sys.version_info.major == 2:
50
 
    __metaclass__ = type
51
 
 
52
49
try:
53
50
    import pydbus
54
51
    import gi
56
53
except ImportError:
57
54
    import dbus as dbus_python
58
55
    pydbus = None
59
 
    class gi:
 
56
    class gi(object):
60
57
        """Dummy gi module, for the tests"""
61
 
        class repository:
62
 
            class GLib:
 
58
        class repository(object):
 
59
            class GLib(object):
63
60
                class Error(Exception):
64
61
                    pass
65
62
 
81
78
 
82
79
locale.setlocale(locale.LC_ALL, "")
83
80
 
84
 
version = "1.8.8"
 
81
version = "1.8.4"
85
82
 
86
83
 
87
84
def main():
253
250
def rfc3339_duration_to_delta(duration):
254
251
    """Parse an RFC 3339 "duration" and return a datetime.timedelta
255
252
 
256
 
    >>> rfc3339_duration_to_delta("P7D") == datetime.timedelta(7)
257
 
    True
258
 
    >>> rfc3339_duration_to_delta("PT60S") == datetime.timedelta(0, 60)
259
 
    True
260
 
    >>> rfc3339_duration_to_delta("PT60M") == datetime.timedelta(hours=1)
261
 
    True
262
 
    >>> # 60 months
263
 
    >>> rfc3339_duration_to_delta("P60M") == datetime.timedelta(1680)
264
 
    True
265
 
    >>> rfc3339_duration_to_delta("PT24H") == datetime.timedelta(1)
266
 
    True
267
 
    >>> rfc3339_duration_to_delta("P1W") == datetime.timedelta(7)
268
 
    True
269
 
    >>> rfc3339_duration_to_delta("PT5M30S") == datetime.timedelta(0, 330)
270
 
    True
271
 
    >>> rfc3339_duration_to_delta("P1DT3M20S") == datetime.timedelta(1, 200)
272
 
    True
 
253
    >>> rfc3339_duration_to_delta("P7D")
 
254
    datetime.timedelta(7)
 
255
    >>> rfc3339_duration_to_delta("PT60S")
 
256
    datetime.timedelta(0, 60)
 
257
    >>> rfc3339_duration_to_delta("PT60M")
 
258
    datetime.timedelta(0, 3600)
 
259
    >>> rfc3339_duration_to_delta("P60M")
 
260
    datetime.timedelta(1680)
 
261
    >>> rfc3339_duration_to_delta("PT24H")
 
262
    datetime.timedelta(1)
 
263
    >>> rfc3339_duration_to_delta("P1W")
 
264
    datetime.timedelta(7)
 
265
    >>> rfc3339_duration_to_delta("PT5M30S")
 
266
    datetime.timedelta(0, 330)
 
267
    >>> rfc3339_duration_to_delta("P1DT3M20S")
 
268
    datetime.timedelta(1, 200)
273
269
    >>> # Can not be empty:
274
270
    >>> rfc3339_duration_to_delta("")
275
271
    Traceback (most recent call last):
385
381
    """Parse an interval string as documented by Mandos before 1.6.1,
386
382
    and return a datetime.timedelta
387
383
 
388
 
    >>> parse_pre_1_6_1_interval('7d') == datetime.timedelta(days=7)
389
 
    True
390
 
    >>> parse_pre_1_6_1_interval('60s') == datetime.timedelta(0, 60)
391
 
    True
392
 
    >>> parse_pre_1_6_1_interval('60m') == datetime.timedelta(hours=1)
393
 
    True
394
 
    >>> parse_pre_1_6_1_interval('24h') == datetime.timedelta(days=1)
395
 
    True
396
 
    >>> parse_pre_1_6_1_interval('1w') == datetime.timedelta(days=7)
397
 
    True
398
 
    >>> parse_pre_1_6_1_interval('5m 30s') == datetime.timedelta(0, 330)
399
 
    True
400
 
    >>> parse_pre_1_6_1_interval('') == datetime.timedelta(0)
401
 
    True
 
384
    >>> parse_pre_1_6_1_interval('7d')
 
385
    datetime.timedelta(7)
 
386
    >>> parse_pre_1_6_1_interval('60s')
 
387
    datetime.timedelta(0, 60)
 
388
    >>> parse_pre_1_6_1_interval('60m')
 
389
    datetime.timedelta(0, 3600)
 
390
    >>> parse_pre_1_6_1_interval('24h')
 
391
    datetime.timedelta(1)
 
392
    >>> parse_pre_1_6_1_interval('1w')
 
393
    datetime.timedelta(7)
 
394
    >>> parse_pre_1_6_1_interval('5m 30s')
 
395
    datetime.timedelta(0, 330)
 
396
    >>> parse_pre_1_6_1_interval('')
 
397
    datetime.timedelta(0)
402
398
    >>> # Ignore unknown characters, allow any order and repetitions
403
 
    >>> parse_pre_1_6_1_interval('2dxy7zz11y3m5m') == datetime.timedelta(2, 480, 18000)
404
 
    True
 
399
    >>> parse_pre_1_6_1_interval('2dxy7zz11y3m5m')
 
400
    datetime.timedelta(2, 480, 18000)
405
401
 
406
402
    """
407
403
 
470
466
        parser.error("--remove can only be combined with --deny")
471
467
 
472
468
 
473
 
class dbus:
 
469
class dbus(object):
474
470
 
475
 
    class SystemBus:
 
471
    class SystemBus(object):
476
472
 
477
473
        object_manager_iface = "org.freedesktop.DBus.ObjectManager"
478
474
        def get_managed_objects(self, busname, objectpath):
524
520
        pass
525
521
 
526
522
 
527
 
class dbus_python_adapter:
 
523
class dbus_python_adapter(object):
528
524
 
529
525
    class SystemBus(dbus.MandosBus):
530
526
        """Use dbus-python"""
584
580
                                     self.client_interface, key,
585
581
                                     value)
586
582
 
587
 
    class SilenceLogger:
 
583
    class SilenceLogger(object):
588
584
        "Simple context manager to silence a particular logger"
589
585
        def __init__(self, loggername):
590
586
            self.logger = logging.getLogger(loggername)
619
615
                return new_object
620
616
 
621
617
 
622
 
class pydbus_adapter:
 
618
class pydbus_adapter(object):
623
619
    class SystemBus(dbus.MandosBus):
624
620
        def __init__(self, module=pydbus):
625
621
            self.pydbus = module
715
711
    return commands
716
712
 
717
713
 
718
 
class command:
 
714
class command(object):
719
715
    """A namespace for command classes"""
720
716
 
721
 
    class Base:
 
717
    class Base(object):
722
718
        """Abstract base class for commands"""
723
719
        def run(self, clients, bus=None):
724
720
            """Normal commands should implement run_on_one_client(),
787
783
                keywords = self.all_keywords
788
784
            print(self.TableOfClients(clients.values(), keywords))
789
785
 
790
 
        class TableOfClients:
 
786
        class TableOfClients(object):
791
787
            tableheaders = {
792
788
                "Name": "Name",
793
789
                "Enabled": "Enabled",
1024
1020
                                                     "output"))
1025
1021
 
1026
1022
 
1027
 
class Unique:
 
1023
class Unique(object):
1028
1024
    """Class for objects which exist only to be unique objects, since
1029
1025
unittest.mock.sentinel only exists in Python 3.3"""
1030
1026
 
1314
1310
class Test_dbus_python_adapter_SystemBus(TestCaseWithAssertLogs):
1315
1311
 
1316
1312
    def MockDBusPython_func(self, func):
1317
 
        class mock_dbus_python:
 
1313
        class mock_dbus_python(object):
1318
1314
            """mock dbus-python module"""
1319
 
            class exceptions:
 
1315
            class exceptions(object):
1320
1316
                """Pseudo-namespace"""
1321
1317
                class DBusException(Exception):
1322
1318
                    pass
1323
 
            class SystemBus:
 
1319
            class SystemBus(object):
1324
1320
                @staticmethod
1325
1321
                def get_object(busname, objectpath):
1326
1322
                    DBusObject = collections.namedtuple(
1340
1336
                                    dbus_interface=dbus_interface)
1341
1337
                    return DBusObject(methodname=method,
1342
1338
                                      Set=set_property)
1343
 
            class Boolean:
 
1339
            class Boolean(object):
1344
1340
                def __init__(self, value):
1345
1341
                    self.value = bool(value)
1346
1342
                def __bool__(self):
1558
1554
            self.call_method(bus, "methodname", "busname",
1559
1555
                             "objectpath", "interface")
1560
1556
 
1561
 
    class fake_dbus_python_raises_exception_on_connect:
 
1557
    class fake_dbus_python_raises_exception_on_connect(object):
1562
1558
        """fake dbus-python module"""
1563
 
        class exceptions:
 
1559
        class exceptions(object):
1564
1560
            """Pseudo-namespace"""
1565
1561
            class DBusException(Exception):
1566
1562
                pass
1574
1570
 
1575
1571
 
1576
1572
class Test_dbus_python_adapter_CachingBus(unittest.TestCase):
1577
 
    class mock_dbus_python:
 
1573
    class mock_dbus_python(object):
1578
1574
        """mock dbus-python modules"""
1579
 
        class SystemBus:
 
1575
        class SystemBus(object):
1580
1576
            @staticmethod
1581
1577
            def get_object(busname, objectpath):
1582
1578
                return Unique()
1628
1624
class Test_pydbus_adapter_SystemBus(TestCaseWithAssertLogs):
1629
1625
 
1630
1626
    def Stub_pydbus_func(self, func):
1631
 
        class stub_pydbus:
 
1627
        class stub_pydbus(object):
1632
1628
            """stub pydbus module"""
1633
 
            class SystemBus:
 
1629
            class SystemBus(object):
1634
1630
                @staticmethod
1635
1631
                def get(busname, objectpath):
1636
1632
                    DBusObject = collections.namedtuple(
1682
1678
            self.call_method(bus, "methodname", "busname",
1683
1679
                             "objectpath", "interface")
1684
1680
 
1685
 
    class fake_pydbus_raises_exception_on_connect:
 
1681
    class fake_pydbus_raises_exception_on_connect(object):
1686
1682
        """fake dbus-python module"""
1687
1683
        @classmethod
1688
1684
        def SystemBus(cls):
1692
1688
            return Bus(get=get)
1693
1689
 
1694
1690
    def test_set_property_uses_setattr(self):
1695
 
        class Object:
 
1691
        class Object(object):
1696
1692
            pass
1697
1693
        obj = Object()
1698
 
        class pydbus_spy:
1699
 
            class SystemBus:
 
1694
        class pydbus_spy(object):
 
1695
            class SystemBus(object):
1700
1696
                @staticmethod
1701
1697
                def get(busname, objectpath):
1702
1698
                    return {"interface": obj}
1709
1705
    def test_get_suppresses_xml_deprecation_warning(self):
1710
1706
        if sys.version_info.major >= 3:
1711
1707
            return
1712
 
        class stub_pydbus_get:
1713
 
            class SystemBus:
 
1708
        class stub_pydbus_get(object):
 
1709
            class SystemBus(object):
1714
1710
                @staticmethod
1715
1711
                def get(busname, objectpath):
1716
1712
                    warnings.warn_explicit(
1724
1720
 
1725
1721
 
1726
1722
class Test_pydbus_adapter_CachingBus(unittest.TestCase):
1727
 
    class stub_pydbus:
 
1723
    class stub_pydbus(object):
1728
1724
        """stub pydbus module"""
1729
 
        class SystemBus:
 
1725
        class SystemBus(object):
1730
1726
            @staticmethod
1731
1727
            def get(busname, objectpath):
1732
1728
                return Unique()
2005
2001
 
2006
2002
 
2007
2003
    def test_manual_page_example_1(self):
2008
 
        self.assert_command_from_args("",
 
2004
        self.assert_command_from_args("--verbose".split(),
2009
2005
                                      command.PrintTable,
2010
2006
                                      clients=[],
2011
 
                                      verbose=False)
 
2007
                                      verbose=True)
2012
2008
 
2013
2009
    def test_manual_page_example_2(self):
2014
2010
        self.assert_command_from_args(