/mandos/release

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/release

« back to all changes in this revision

Viewing changes to mandos

  • Committer: Teddy Hogeborn
  • Date: 2022-04-23 20:39:28 UTC
  • mto: This revision was merged to the branch mainline in revision 406.
  • Revision ID: teddy@recompile.se-20220423203928-q2ngppp3pt7cfv4x
Makefile: Add comment about phase out of -lpthread

* Makefile (dracut-module/password-agent): Add comment about -lpthread
  being unnecessary in GNU C library 2.34 and later.

Show diffs side-by-side

added added

removed removed

Lines of Context:
189
189
        facility=logging.handlers.SysLogHandler.LOG_DAEMON,
190
190
        address="/dev/log"))
191
191
    syslogger.setFormatter(logging.Formatter
192
 
                           ("Mandos [%(process)d]: %(levelname)s:"
193
 
                            " %(message)s"))
 
192
                           ('Mandos [%(process)d]: %(levelname)s:'
 
193
                            ' %(message)s'))
194
194
    logger.addHandler(syslogger)
195
195
 
196
196
    if debug:
197
197
        console = logging.StreamHandler()
198
 
        console.setFormatter(logging.Formatter("%(asctime)s %(name)s"
199
 
                                               " [%(process)d]:"
200
 
                                               " %(levelname)s:"
201
 
                                               " %(message)s"))
 
198
        console.setFormatter(logging.Formatter('%(asctime)s %(name)s'
 
199
                                               ' [%(process)d]:'
 
200
                                               ' %(levelname)s:'
 
201
                                               ' %(message)s'))
202
202
        logger.addHandler(console)
203
203
    logger.setLevel(level)
204
204
 
224
224
        except OSError as e:
225
225
            if e.errno != errno.ENOENT:
226
226
                raise
227
 
        self.gnupgargs = ["--batch",
228
 
                          "--homedir", self.tempdir,
229
 
                          "--force-mdc",
230
 
                          "--quiet"]
 
227
        self.gnupgargs = ['--batch',
 
228
                          '--homedir', self.tempdir,
 
229
                          '--force-mdc',
 
230
                          '--quiet']
231
231
        # Only GPG version 1 has the --no-use-agent option.
232
232
        if self.gpg == b"gpg" or self.gpg.endswith(b"/gpg"):
233
233
            self.gnupgargs.append("--no-use-agent")
272
272
                dir=self.tempdir) as passfile:
273
273
            passfile.write(passphrase)
274
274
            passfile.flush()
275
 
            proc = subprocess.Popen([self.gpg, "--symmetric",
276
 
                                     "--passphrase-file",
 
275
            proc = subprocess.Popen([self.gpg, '--symmetric',
 
276
                                     '--passphrase-file',
277
277
                                     passfile.name]
278
278
                                    + self.gnupgargs,
279
279
                                    stdin=subprocess.PIPE,
290
290
                dir=self.tempdir) as passfile:
291
291
            passfile.write(passphrase)
292
292
            passfile.flush()
293
 
            proc = subprocess.Popen([self.gpg, "--decrypt",
294
 
                                     "--passphrase-file",
 
293
            proc = subprocess.Popen([self.gpg, '--decrypt',
 
294
                                     '--passphrase-file',
295
295
                                     passfile.name]
296
296
                                    + self.gnupgargs,
297
297
                                    stdin=subprocess.PIPE,
350
350
    Attributes:
351
351
    interface: integer; avahi.IF_UNSPEC or an interface index.
352
352
               Used to optionally bind to the specified interface.
353
 
    name: string; Example: "Mandos"
354
 
    type: string; Example: "_mandos._tcp".
 
353
    name: string; Example: 'Mandos'
 
354
    type: string; Example: '_mandos._tcp'.
355
355
     See <https://www.iana.org/assignments/service-names-port-numbers>
356
356
    port: integer; what port to announce
357
357
    TXT: list of strings; TXT record for the service
435
435
                avahi.DBUS_INTERFACE_ENTRY_GROUP)
436
436
        self.entry_group_state_changed_match = (
437
437
            self.group.connect_to_signal(
438
 
                "StateChanged", self.entry_group_state_changed))
 
438
                'StateChanged', self.entry_group_state_changed))
439
439
        logger.debug("Adding Zeroconf service '%s' of type '%s' ...",
440
440
                     self.name, self.type)
441
441
        self.group.AddService(
527
527
        ret = super(AvahiServiceToSyslog, self).rename(*args,
528
528
                                                       **kwargs)
529
529
        syslogger.setFormatter(logging.Formatter(
530
 
            "Mandos ({}) [%(process)d]: %(levelname)s: %(message)s"
 
530
            'Mandos ({}) [%(process)d]: %(levelname)s: %(message)s'
531
531
            .format(self.name)))
532
532
        return ret
533
533
 
574
574
    certificate_type_t = ctypes.c_int
575
575
 
576
576
    class datum_t(ctypes.Structure):
577
 
        _fields_ = [("data", ctypes.POINTER(ctypes.c_ubyte)),
578
 
                    ("size", ctypes.c_uint)]
 
577
        _fields_ = [('data', ctypes.POINTER(ctypes.c_ubyte)),
 
578
                    ('size', ctypes.c_uint)]
579
579
 
580
580
    class _openpgp_crt_int(ctypes.Structure):
581
581
        _fields_ = []
676
676
    # Error handling functions
677
677
    def _error_code(result):
678
678
        """A function to raise exceptions on errors, suitable
679
 
        for the "restype" attribute on ctypes functions"""
 
679
        for the 'restype' attribute on ctypes functions"""
680
680
        if result >= gnutls.E_SUCCESS:
681
681
            return result
682
682
        if result == gnutls.E_NO_CERTIFICATE_FOUND:
686
686
    def _retry_on_error(result, func, arguments,
687
687
                        _error_code=_error_code):
688
688
        """A function to retry on some errors, suitable
689
 
        for the "errcheck" attribute on ctypes functions"""
 
689
        for the 'errcheck' attribute on ctypes functions"""
690
690
        while result < gnutls.E_SUCCESS:
691
691
            if result not in (gnutls.E_INTERRUPTED, gnutls.E_AGAIN):
692
692
                return _error_code(result)
876
876
    """A representation of a client host served by this server.
877
877
 
878
878
    Attributes:
879
 
    approved:   bool(); None if not yet approved/disapproved
 
879
    approved:   bool(); 'None' if not yet approved/disapproved
880
880
    approval_delay: datetime.timedelta(); Time to wait for approval
881
881
    approval_duration: datetime.timedelta(); Duration of one approval
882
882
    checker: multiprocessing.Process(); a running checker process used
883
 
             to see if the client lives. None if no process is
 
883
             to see if the client lives. 'None' if no process is
884
884
             running.
885
885
    checker_callback_tag: a GLib event source tag, or None
886
886
    checker_command: string; External command which is run to check
1242
1242
        func._dbus_name = func.__name__
1243
1243
        if func._dbus_name.endswith("_dbus_property"):
1244
1244
            func._dbus_name = func._dbus_name[:-14]
1245
 
        func._dbus_get_args_options = {"byte_arrays": byte_arrays}
 
1245
        func._dbus_get_args_options = {'byte_arrays': byte_arrays}
1246
1246
        return func
1247
1247
 
1248
1248
    return decorator
1337
1337
 
1338
1338
    @dbus.service.method(dbus.INTROSPECTABLE_IFACE,
1339
1339
                         out_signature="s",
1340
 
                         path_keyword="object_path",
1341
 
                         connection_keyword="connection")
 
1340
                         path_keyword='object_path',
 
1341
                         connection_keyword='connection')
1342
1342
    def Introspect(self, object_path, connection):
1343
1343
        """Overloading of standard D-Bus method.
1344
1344
 
1497
1497
 
1498
1498
    @dbus.service.method(dbus.INTROSPECTABLE_IFACE,
1499
1499
                         out_signature="s",
1500
 
                         path_keyword="object_path",
1501
 
                         connection_keyword="connection")
 
1500
                         path_keyword='object_path',
 
1501
                         connection_keyword='connection')
1502
1502
    def Introspect(self, object_path, connection):
1503
1503
        """Overloading of standard D-Bus method.
1504
1504
 
1599
1599
 
1600
1600
    @dbus.service.method(dbus.INTROSPECTABLE_IFACE,
1601
1601
                         out_signature="s",
1602
 
                         path_keyword="object_path",
1603
 
                         connection_keyword="connection")
 
1602
                         path_keyword='object_path',
 
1603
                         connection_keyword='connection')
1604
1604
    def Introspect(self, object_path, connection):
1605
1605
        """Overloading of standard D-Bus method.
1606
1606
 
2272
2272
class ProxyClient:
2273
2273
    def __init__(self, child_pipe, key_id, fpr, address):
2274
2274
        self._pipe = child_pipe
2275
 
        self._pipe.send(("init", key_id, fpr, address))
 
2275
        self._pipe.send(('init', key_id, fpr, address))
2276
2276
        if not self._pipe.recv():
2277
2277
            raise KeyError(key_id or fpr)
2278
2278
 
2279
2279
    def __getattribute__(self, name):
2280
 
        if name == "_pipe":
 
2280
        if name == '_pipe':
2281
2281
            return super(ProxyClient, self).__getattribute__(name)
2282
 
        self._pipe.send(("getattr", name))
 
2282
        self._pipe.send(('getattr', name))
2283
2283
        data = self._pipe.recv()
2284
 
        if data[0] == "data":
 
2284
        if data[0] == 'data':
2285
2285
            return data[1]
2286
 
        if data[0] == "function":
 
2286
        if data[0] == 'function':
2287
2287
 
2288
2288
            def func(*args, **kwargs):
2289
 
                self._pipe.send(("funcall", name, args, kwargs))
 
2289
                self._pipe.send(('funcall', name, args, kwargs))
2290
2290
                return self._pipe.recv()[1]
2291
2291
 
2292
2292
            return func
2293
2293
 
2294
2294
    def __setattr__(self, name, value):
2295
 
        if name == "_pipe":
 
2295
        if name == '_pipe':
2296
2296
            return super(ProxyClient, self).__setattr__(name, value)
2297
 
        self._pipe.send(("setattr", name, value))
 
2297
        self._pipe.send(('setattr', name, value))
2298
2298
 
2299
2299
 
2300
2300
class ClientHandler(socketserver.BaseRequestHandler, object):
2312
2312
 
2313
2313
            session = gnutls.ClientSession(self.request)
2314
2314
 
2315
 
            # priority = ":".join(("NONE", "+VERS-TLS1.1",
 
2315
            # priority = ':'.join(("NONE", "+VERS-TLS1.1",
2316
2316
            #                       "+AES-256-CBC", "+SHA1",
2317
2317
            #                       "+COMP-NULL", "+CTYPE-OPENPGP",
2318
2318
            #                       "+DHE-DSS"))
2590
2590
 
2591
2591
class IPv6_TCPServer(MultiprocessingMixInWithPipe,
2592
2592
                     socketserver.TCPServer):
2593
 
    """IPv6-capable TCP server.  Accepts None as address and/or port
 
2593
    """IPv6-capable TCP server.  Accepts 'None' as address and/or port
2594
2594
 
2595
2595
    Attributes:
2596
2596
        enabled:        Boolean; whether this server is activated yet
2748
2748
        request = parent_pipe.recv()
2749
2749
        command = request[0]
2750
2750
 
2751
 
        if command == "init":
 
2751
        if command == 'init':
2752
2752
            key_id = request[1].decode("ascii")
2753
2753
            fpr = request[2].decode("ascii")
2754
2754
            address = request[3]
2784
2784
            # remove the old hook in favor of the new above hook on
2785
2785
            # same fileno
2786
2786
            return False
2787
 
        if command == "funcall":
 
2787
        if command == 'funcall':
2788
2788
            funcname = request[1]
2789
2789
            args = request[2]
2790
2790
            kwargs = request[3]
2791
2791
 
2792
 
            parent_pipe.send(("data", getattr(client_object,
 
2792
            parent_pipe.send(('data', getattr(client_object,
2793
2793
                                              funcname)(*args,
2794
2794
                                                        **kwargs)))
2795
2795
 
2796
 
        if command == "getattr":
 
2796
        if command == 'getattr':
2797
2797
            attrname = request[1]
2798
2798
            if isinstance(client_object.__getattribute__(attrname),
2799
2799
                          collections.abc.Callable):
2800
 
                parent_pipe.send(("function", ))
 
2800
                parent_pipe.send(('function', ))
2801
2801
            else:
2802
2802
                parent_pipe.send((
2803
 
                    "data", client_object.__getattribute__(attrname)))
 
2803
                    'data', client_object.__getattribute__(attrname)))
2804
2804
 
2805
 
        if command == "setattr":
 
2805
        if command == 'setattr':
2806
2806
            attrname = request[1]
2807
2807
            value = request[2]
2808
2808
            setattr(client_object, attrname, value)
2914
2914
def string_to_delta(interval):
2915
2915
    """Parse a string and return a datetime.timedelta
2916
2916
 
2917
 
    >>> string_to_delta("7d") == datetime.timedelta(7)
2918
 
    True
2919
 
    >>> string_to_delta("60s") == datetime.timedelta(0, 60)
2920
 
    True
2921
 
    >>> string_to_delta("60m") == datetime.timedelta(0, 3600)
2922
 
    True
2923
 
    >>> string_to_delta("24h") == datetime.timedelta(1)
2924
 
    True
2925
 
    >>> string_to_delta("1w") == datetime.timedelta(7)
2926
 
    True
2927
 
    >>> string_to_delta("5m 30s") == datetime.timedelta(0, 330)
 
2917
    >>> string_to_delta('7d') == datetime.timedelta(7)
 
2918
    True
 
2919
    >>> string_to_delta('60s') == datetime.timedelta(0, 60)
 
2920
    True
 
2921
    >>> string_to_delta('60m') == datetime.timedelta(0, 3600)
 
2922
    True
 
2923
    >>> string_to_delta('24h') == datetime.timedelta(1)
 
2924
    True
 
2925
    >>> string_to_delta('1w') == datetime.timedelta(7)
 
2926
    True
 
2927
    >>> string_to_delta('5m 30s') == datetime.timedelta(0, 330)
2928
2928
    True
2929
2929
    """
2930
2930
 
3134
3134
 
3135
3135
    if server_settings["servicename"] != "Mandos":
3136
3136
        syslogger.setFormatter(
3137
 
            logging.Formatter("Mandos ({}) [%(process)d]:"
3138
 
                              " %(levelname)s: %(message)s".format(
 
3137
            logging.Formatter('Mandos ({}) [%(process)d]:'
 
3138
                              ' %(levelname)s: %(message)s'.format(
3139
3139
                                  server_settings["servicename"])))
3140
3140
 
3141
3141
    # Parse config file with clients
3584
3584
 
3585
3585
        try:
3586
3586
            with tempfile.NamedTemporaryFile(
3587
 
                    mode="wb",
 
3587
                    mode='wb',
3588
3588
                    suffix=".pickle",
3589
 
                    prefix="clients-",
 
3589
                    prefix='clients-',
3590
3590
                    dir=os.path.dirname(stored_state_path),
3591
3591
                    delete=False) as stored_state:
3592
3592
                pickle.dump((clients, client_settings), stored_state,
3679
3679
 
3680
3680
def should_only_run_tests():
3681
3681
    parser = argparse.ArgumentParser(add_help=False)
3682
 
    parser.add_argument("--check", action="store_true")
 
3682
    parser.add_argument("--check", action='store_true')
3683
3683
    args, unknown_args = parser.parse_known_args()
3684
3684
    run_tests = args.check
3685
3685
    if run_tests:
3693
3693
    tests.addTests(doctest.DocTestSuite())
3694
3694
    return tests
3695
3695
 
3696
 
if __name__ == "__main__":
 
3696
if __name__ == '__main__':
3697
3697
    try:
3698
3698
        if should_only_run_tests():
3699
3699
            # Call using ./mandos --check [--verbose]