/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

  • Committer: Teddy Hogeborn
  • Date: 2019-08-05 21:14:05 UTC
  • Revision ID: teddy@recompile.se-20190805211405-9m6hecekaihpttz9
Override lintian warnings about upgrading from old versions

There are some really things which are imperative that we fix in case
someone were to upgrade from a really old version.  We want to keep
these fixes in the postinst maintainer scripts, even though lintian
complains about such old upgrades not being supported by Debian in
general.  We prefer the code being there, for the sake of the users.

* debian/mandos-client.lintian-overrides
  (maintainer-script-supports-ancient-package-version): New.
  debian/mandos.lintian-overrides
  (maintainer-script-supports-ancient-package-version): - '' -

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
# "AvahiService" class, and some lines in "main".
12
12
#
13
13
# Everything else is
14
 
# Copyright © 2008-2018 Teddy Hogeborn
15
 
# Copyright © 2008-2018 Björn Påhlsson
 
14
# Copyright © 2008-2019 Teddy Hogeborn
 
15
# Copyright © 2008-2019 Björn Påhlsson
16
16
#
17
17
# This file is part of Mandos.
18
18
#
80
80
 
81
81
import dbus
82
82
import dbus.service
 
83
import gi
83
84
from gi.repository import GLib
84
85
from dbus.mainloop.glib import DBusGMainLoop
85
86
import ctypes
115
116
if sys.version_info.major == 2:
116
117
    str = unicode
117
118
 
118
 
version = "1.7.18"
 
119
if sys.version_info < (3, 2):
 
120
    configparser.Configparser = configparser.SafeConfigParser
 
121
 
 
122
version = "1.8.6"
119
123
stored_state_file = "clients.pickle"
120
124
 
121
125
logger = logging.getLogger()
275
279
 
276
280
 
277
281
# Pretend that we have an Avahi module
278
 
class Avahi(object):
279
 
    """This isn't so much a class as it is a module-like namespace.
280
 
    It is instantiated once, and simulates having an Avahi module."""
 
282
class avahi(object):
 
283
    """This isn't so much a class as it is a module-like namespace."""
281
284
    IF_UNSPEC = -1               # avahi-common/address.h
282
285
    PROTO_UNSPEC = -1            # avahi-common/address.h
283
286
    PROTO_INET = 0               # avahi-common/address.h
287
290
    DBUS_INTERFACE_SERVER = DBUS_NAME + ".Server"
288
291
    DBUS_PATH_SERVER = "/"
289
292
 
290
 
    def string_array_to_txt_array(self, t):
 
293
    @staticmethod
 
294
    def string_array_to_txt_array(t):
291
295
        return dbus.Array((dbus.ByteArray(s.encode("utf-8"))
292
296
                           for s in t), signature="ay")
293
297
    ENTRY_GROUP_ESTABLISHED = 2  # avahi-common/defs.h
298
302
    SERVER_RUNNING = 2           # avahi-common/defs.h
299
303
    SERVER_COLLISION = 3         # avahi-common/defs.h
300
304
    SERVER_FAILURE = 4           # avahi-common/defs.h
301
 
avahi = Avahi()
302
305
 
303
306
 
304
307
class AvahiError(Exception):
504
507
 
505
508
 
506
509
# Pretend that we have a GnuTLS module
507
 
class GnuTLS(object):
508
 
    """This isn't so much a class as it is a module-like namespace.
509
 
    It is instantiated once, and simulates having a GnuTLS module."""
 
510
class gnutls(object):
 
511
    """This isn't so much a class as it is a module-like namespace."""
510
512
 
511
513
    library = ctypes.util.find_library("gnutls")
512
514
    if library is None:
513
515
        library = ctypes.util.find_library("gnutls-deb0")
514
516
    _library = ctypes.cdll.LoadLibrary(library)
515
517
    del library
516
 
    _need_version = b"3.3.0"
517
 
 
518
 
    def __init__(self):
519
 
        # Need to use "self" here, since this method is called before
520
 
        # the assignment to the "gnutls" global variable happens.
521
 
        if self.check_version(self._need_version) is None:
522
 
            raise self.Error("Needs GnuTLS {} or later"
523
 
                             .format(self._need_version))
524
518
 
525
519
    # Unless otherwise indicated, the constants and types below are
526
520
    # all from the gnutls/gnutls.h C header file.
530
524
    E_INTERRUPTED = -52
531
525
    E_AGAIN = -28
532
526
    CRT_OPENPGP = 2
 
527
    CRT_RAWPK = 3
533
528
    CLIENT = 2
534
529
    SHUT_RDWR = 0
535
530
    CRD_CERTIFICATE = 1
536
531
    E_NO_CERTIFICATE_FOUND = -49
 
532
    X509_FMT_DER = 0
 
533
    NO_TICKETS = 1<<10
 
534
    ENABLE_RAWPK = 1<<18
 
535
    CTYPE_PEERS = 3
 
536
    KEYID_USE_SHA256 = 1        # gnutls/x509.h
537
537
    OPENPGP_FMT_RAW = 0         # gnutls/openpgp.h
538
538
 
539
539
    # Types
562
562
 
563
563
    # Exceptions
564
564
    class Error(Exception):
565
 
        # We need to use the class name "GnuTLS" here, since this
566
 
        # exception might be raised from within GnuTLS.__init__,
567
 
        # which is called before the assignment to the "gnutls"
568
 
        # global variable has happened.
569
565
        def __init__(self, message=None, code=None, args=()):
570
566
            # Default usage is by a message string, but if a return
571
567
            # code is passed, convert it to a string with
572
568
            # gnutls.strerror()
573
569
            self.code = code
574
570
            if message is None and code is not None:
575
 
                message = GnuTLS.strerror(code)
576
 
            return super(GnuTLS.Error, self).__init__(
 
571
                message = gnutls.strerror(code)
 
572
            return super(gnutls.Error, self).__init__(
577
573
                message, *args)
578
574
 
579
575
    class CertificateSecurityError(Error):
593
589
    class ClientSession(object):
594
590
        def __init__(self, socket, credentials=None):
595
591
            self._c_object = gnutls.session_t()
596
 
            gnutls.init(ctypes.byref(self._c_object), gnutls.CLIENT)
 
592
            gnutls_flags = gnutls.CLIENT
 
593
            if gnutls.check_version(b"3.5.6"):
 
594
                gnutls_flags |= gnutls.NO_TICKETS
 
595
            if gnutls.has_rawpk:
 
596
                gnutls_flags |= gnutls.ENABLE_RAWPK
 
597
            gnutls.init(ctypes.byref(self._c_object), gnutls_flags)
 
598
            del gnutls_flags
597
599
            gnutls.set_default_priority(self._c_object)
598
600
            gnutls.transport_set_ptr(self._c_object, socket.fileno())
599
601
            gnutls.handshake_set_private_extensions(self._c_object,
731
733
    check_version.argtypes = [ctypes.c_char_p]
732
734
    check_version.restype = ctypes.c_char_p
733
735
 
734
 
    # All the function declarations below are from gnutls/openpgp.h
735
 
 
736
 
    openpgp_crt_init = _library.gnutls_openpgp_crt_init
737
 
    openpgp_crt_init.argtypes = [ctypes.POINTER(openpgp_crt_t)]
738
 
    openpgp_crt_init.restype = _error_code
739
 
 
740
 
    openpgp_crt_import = _library.gnutls_openpgp_crt_import
741
 
    openpgp_crt_import.argtypes = [openpgp_crt_t,
742
 
                                   ctypes.POINTER(datum_t),
743
 
                                   openpgp_crt_fmt_t]
744
 
    openpgp_crt_import.restype = _error_code
745
 
 
746
 
    openpgp_crt_verify_self = _library.gnutls_openpgp_crt_verify_self
747
 
    openpgp_crt_verify_self.argtypes = [openpgp_crt_t, ctypes.c_uint,
748
 
                                        ctypes.POINTER(ctypes.c_uint)]
749
 
    openpgp_crt_verify_self.restype = _error_code
750
 
 
751
 
    openpgp_crt_deinit = _library.gnutls_openpgp_crt_deinit
752
 
    openpgp_crt_deinit.argtypes = [openpgp_crt_t]
753
 
    openpgp_crt_deinit.restype = None
754
 
 
755
 
    openpgp_crt_get_fingerprint = (
756
 
        _library.gnutls_openpgp_crt_get_fingerprint)
757
 
    openpgp_crt_get_fingerprint.argtypes = [openpgp_crt_t,
758
 
                                            ctypes.c_void_p,
759
 
                                            ctypes.POINTER(
760
 
                                                ctypes.c_size_t)]
761
 
    openpgp_crt_get_fingerprint.restype = _error_code
 
736
    _need_version = b"3.3.0"
 
737
    if check_version(_need_version) is None:
 
738
        raise self.Error("Needs GnuTLS {} or later"
 
739
                         .format(_need_version))
 
740
 
 
741
    _tls_rawpk_version = b"3.6.6"
 
742
    has_rawpk = bool(check_version(_tls_rawpk_version))
 
743
 
 
744
    if has_rawpk:
 
745
        # Types
 
746
        class pubkey_st(ctypes.Structure):
 
747
            _fields = []
 
748
        pubkey_t = ctypes.POINTER(pubkey_st)
 
749
 
 
750
        x509_crt_fmt_t = ctypes.c_int
 
751
 
 
752
        # All the function declarations below are from gnutls/abstract.h
 
753
        pubkey_init = _library.gnutls_pubkey_init
 
754
        pubkey_init.argtypes = [ctypes.POINTER(pubkey_t)]
 
755
        pubkey_init.restype = _error_code
 
756
 
 
757
        pubkey_import = _library.gnutls_pubkey_import
 
758
        pubkey_import.argtypes = [pubkey_t, ctypes.POINTER(datum_t),
 
759
                                  x509_crt_fmt_t]
 
760
        pubkey_import.restype = _error_code
 
761
 
 
762
        pubkey_get_key_id = _library.gnutls_pubkey_get_key_id
 
763
        pubkey_get_key_id.argtypes = [pubkey_t, ctypes.c_int,
 
764
                                      ctypes.POINTER(ctypes.c_ubyte),
 
765
                                      ctypes.POINTER(ctypes.c_size_t)]
 
766
        pubkey_get_key_id.restype = _error_code
 
767
 
 
768
        pubkey_deinit = _library.gnutls_pubkey_deinit
 
769
        pubkey_deinit.argtypes = [pubkey_t]
 
770
        pubkey_deinit.restype = None
 
771
    else:
 
772
        # All the function declarations below are from gnutls/openpgp.h
 
773
 
 
774
        openpgp_crt_init = _library.gnutls_openpgp_crt_init
 
775
        openpgp_crt_init.argtypes = [ctypes.POINTER(openpgp_crt_t)]
 
776
        openpgp_crt_init.restype = _error_code
 
777
 
 
778
        openpgp_crt_import = _library.gnutls_openpgp_crt_import
 
779
        openpgp_crt_import.argtypes = [openpgp_crt_t,
 
780
                                       ctypes.POINTER(datum_t),
 
781
                                       openpgp_crt_fmt_t]
 
782
        openpgp_crt_import.restype = _error_code
 
783
 
 
784
        openpgp_crt_verify_self = _library.gnutls_openpgp_crt_verify_self
 
785
        openpgp_crt_verify_self.argtypes = [openpgp_crt_t, ctypes.c_uint,
 
786
                                            ctypes.POINTER(ctypes.c_uint)]
 
787
        openpgp_crt_verify_self.restype = _error_code
 
788
 
 
789
        openpgp_crt_deinit = _library.gnutls_openpgp_crt_deinit
 
790
        openpgp_crt_deinit.argtypes = [openpgp_crt_t]
 
791
        openpgp_crt_deinit.restype = None
 
792
 
 
793
        openpgp_crt_get_fingerprint = (
 
794
            _library.gnutls_openpgp_crt_get_fingerprint)
 
795
        openpgp_crt_get_fingerprint.argtypes = [openpgp_crt_t,
 
796
                                                ctypes.c_void_p,
 
797
                                                ctypes.POINTER(
 
798
                                                    ctypes.c_size_t)]
 
799
        openpgp_crt_get_fingerprint.restype = _error_code
 
800
 
 
801
    if check_version(b"3.6.4"):
 
802
        certificate_type_get2 = _library.gnutls_certificate_type_get2
 
803
        certificate_type_get2.argtypes = [session_t, ctypes.c_int]
 
804
        certificate_type_get2.restype = _error_code
762
805
 
763
806
    # Remove non-public functions
764
807
    del _error_code, _retry_on_error
765
 
# Create the global "gnutls" object, simulating a module
766
 
gnutls = GnuTLS()
767
808
 
768
809
 
769
810
def call_pipe(connection,       # : multiprocessing.Connection
784
825
    approved:   bool(); 'None' if not yet approved/disapproved
785
826
    approval_delay: datetime.timedelta(); Time to wait for approval
786
827
    approval_duration: datetime.timedelta(); Duration of one approval
787
 
    checker:    subprocess.Popen(); a running checker process used
788
 
                                    to see if the client lives.
789
 
                                    'None' if no process is running.
 
828
    checker: multiprocessing.Process(); a running checker process used
 
829
             to see if the client lives. 'None' if no process is
 
830
             running.
790
831
    checker_callback_tag: a GLib event source tag, or None
791
832
    checker_command: string; External command which is run to check
792
833
                     if client lives.  %() expansions are done at
800
841
    disable_initiator_tag: a GLib event source tag, or None
801
842
    enabled:    bool()
802
843
    fingerprint: string (40 or 32 hexadecimal digits); used to
803
 
                 uniquely identify the client
 
844
                 uniquely identify an OpenPGP client
 
845
    key_id: string (64 hexadecimal digits); used to uniquely identify
 
846
            a client using raw public keys
804
847
    host:       string; available for use by the checker command
805
848
    interval:   datetime.timedelta(); How often to start a new checker
806
849
    last_approval_request: datetime.datetime(); (UTC) or None
824
867
    """
825
868
 
826
869
    runtime_expansions = ("approval_delay", "approval_duration",
827
 
                          "created", "enabled", "expires",
 
870
                          "created", "enabled", "expires", "key_id",
828
871
                          "fingerprint", "host", "interval",
829
872
                          "last_approval_request", "last_checked_ok",
830
873
                          "last_enabled", "name", "timeout")
860
903
            client["enabled"] = config.getboolean(client_name,
861
904
                                                  "enabled")
862
905
 
863
 
            # Uppercase and remove spaces from fingerprint for later
864
 
            # comparison purposes with return value from the
865
 
            # fingerprint() function
 
906
            # Uppercase and remove spaces from key_id and fingerprint
 
907
            # for later comparison purposes with return value from the
 
908
            # key_id() and fingerprint() functions
 
909
            client["key_id"] = (section.get("key_id", "").upper()
 
910
                                .replace(" ", ""))
866
911
            client["fingerprint"] = (section["fingerprint"].upper()
867
912
                                     .replace(" ", ""))
868
913
            if "secret" in section:
912
957
            self.expires = None
913
958
 
914
959
        logger.debug("Creating client %r", self.name)
 
960
        logger.debug("  Key ID: %s", self.key_id)
915
961
        logger.debug("  Fingerprint: %s", self.fingerprint)
916
962
        self.created = settings.get("created",
917
963
                                    datetime.datetime.utcnow())
994
1040
    def checker_callback(self, source, condition, connection,
995
1041
                         command):
996
1042
        """The checker has completed, so take appropriate actions."""
997
 
        self.checker_callback_tag = None
998
 
        self.checker = None
999
1043
        # Read return code from connection (see call_pipe)
1000
1044
        returncode = connection.recv()
1001
1045
        connection.close()
 
1046
        self.checker.join()
 
1047
        self.checker_callback_tag = None
 
1048
        self.checker = None
1002
1049
 
1003
1050
        if returncode >= 0:
1004
1051
            self.last_checker_status = returncode
1999
2046
    def Name_dbus_property(self):
2000
2047
        return dbus.String(self.name)
2001
2048
 
 
2049
    # KeyID - property
 
2050
    @dbus_annotations(
 
2051
        {"org.freedesktop.DBus.Property.EmitsChangedSignal": "const"})
 
2052
    @dbus_service_property(_interface, signature="s", access="read")
 
2053
    def KeyID_dbus_property(self):
 
2054
        return dbus.String(self.key_id)
 
2055
 
2002
2056
    # Fingerprint - property
2003
2057
    @dbus_annotations(
2004
2058
        {"org.freedesktop.DBus.Property.EmitsChangedSignal": "const"})
2160
2214
 
2161
2215
 
2162
2216
class ProxyClient(object):
2163
 
    def __init__(self, child_pipe, fpr, address):
 
2217
    def __init__(self, child_pipe, key_id, fpr, address):
2164
2218
        self._pipe = child_pipe
2165
 
        self._pipe.send(('init', fpr, address))
 
2219
        self._pipe.send(('init', key_id, fpr, address))
2166
2220
        if not self._pipe.recv():
2167
 
            raise KeyError(fpr)
 
2221
            raise KeyError(key_id or fpr)
2168
2222
 
2169
2223
    def __getattribute__(self, name):
2170
2224
        if name == '_pipe':
2237
2291
 
2238
2292
            approval_required = False
2239
2293
            try:
2240
 
                try:
2241
 
                    fpr = self.fingerprint(
2242
 
                        self.peer_certificate(session))
2243
 
                except (TypeError, gnutls.Error) as error:
2244
 
                    logger.warning("Bad certificate: %s", error)
2245
 
                    return
2246
 
                logger.debug("Fingerprint: %s", fpr)
2247
 
 
2248
 
                try:
2249
 
                    client = ProxyClient(child_pipe, fpr,
 
2294
                if gnutls.has_rawpk:
 
2295
                    fpr = b""
 
2296
                    try:
 
2297
                        key_id = self.key_id(
 
2298
                            self.peer_certificate(session))
 
2299
                    except (TypeError, gnutls.Error) as error:
 
2300
                        logger.warning("Bad certificate: %s", error)
 
2301
                        return
 
2302
                    logger.debug("Key ID: %s", key_id)
 
2303
 
 
2304
                else:
 
2305
                    key_id = b""
 
2306
                    try:
 
2307
                        fpr = self.fingerprint(
 
2308
                            self.peer_certificate(session))
 
2309
                    except (TypeError, gnutls.Error) as error:
 
2310
                        logger.warning("Bad certificate: %s", error)
 
2311
                        return
 
2312
                    logger.debug("Fingerprint: %s", fpr)
 
2313
 
 
2314
                try:
 
2315
                    client = ProxyClient(child_pipe, key_id, fpr,
2250
2316
                                         self.client_address)
2251
2317
                except KeyError:
2252
2318
                    return
2329
2395
 
2330
2396
    @staticmethod
2331
2397
    def peer_certificate(session):
2332
 
        "Return the peer's OpenPGP certificate as a bytestring"
2333
 
        # If not an OpenPGP certificate...
2334
 
        if (gnutls.certificate_type_get(session._c_object)
2335
 
            != gnutls.CRT_OPENPGP):
 
2398
        "Return the peer's certificate as a bytestring"
 
2399
        try:
 
2400
            cert_type = gnutls.certificate_type_get2(session._c_object,
 
2401
                                                     gnutls.CTYPE_PEERS)
 
2402
        except AttributeError:
 
2403
            cert_type = gnutls.certificate_type_get(session._c_object)
 
2404
        if gnutls.has_rawpk:
 
2405
            valid_cert_types = frozenset((gnutls.CRT_RAWPK,))
 
2406
        else:
 
2407
            valid_cert_types = frozenset((gnutls.CRT_OPENPGP,))
 
2408
        # If not a valid certificate type...
 
2409
        if cert_type not in valid_cert_types:
 
2410
            logger.info("Cert type %r not in %r", cert_type,
 
2411
                        valid_cert_types)
2336
2412
            # ...return invalid data
2337
2413
            return b""
2338
2414
        list_size = ctypes.c_uint(1)
2346
2422
        return ctypes.string_at(cert.data, cert.size)
2347
2423
 
2348
2424
    @staticmethod
 
2425
    def key_id(certificate):
 
2426
        "Convert a certificate bytestring to a hexdigit key ID"
 
2427
        # New GnuTLS "datum" with the public key
 
2428
        datum = gnutls.datum_t(
 
2429
            ctypes.cast(ctypes.c_char_p(certificate),
 
2430
                        ctypes.POINTER(ctypes.c_ubyte)),
 
2431
            ctypes.c_uint(len(certificate)))
 
2432
        # XXX all these need to be created in the gnutls "module"
 
2433
        # New empty GnuTLS certificate
 
2434
        pubkey = gnutls.pubkey_t()
 
2435
        gnutls.pubkey_init(ctypes.byref(pubkey))
 
2436
        # Import the raw public key into the certificate
 
2437
        gnutls.pubkey_import(pubkey,
 
2438
                             ctypes.byref(datum),
 
2439
                             gnutls.X509_FMT_DER)
 
2440
        # New buffer for the key ID
 
2441
        buf = ctypes.create_string_buffer(32)
 
2442
        buf_len = ctypes.c_size_t(len(buf))
 
2443
        # Get the key ID from the raw public key into the buffer
 
2444
        gnutls.pubkey_get_key_id(pubkey,
 
2445
                                 gnutls.KEYID_USE_SHA256,
 
2446
                                 ctypes.cast(ctypes.byref(buf),
 
2447
                                             ctypes.POINTER(ctypes.c_ubyte)),
 
2448
                                 ctypes.byref(buf_len))
 
2449
        # Deinit the certificate
 
2450
        gnutls.pubkey_deinit(pubkey)
 
2451
 
 
2452
        # Convert the buffer to a Python bytestring
 
2453
        key_id = ctypes.string_at(buf, buf_len.value)
 
2454
        # Convert the bytestring to hexadecimal notation
 
2455
        hex_key_id = binascii.hexlify(key_id).upper()
 
2456
        return hex_key_id
 
2457
 
 
2458
    @staticmethod
2349
2459
    def fingerprint(openpgp):
2350
2460
        "Convert an OpenPGP bytestring to a hexdigit fingerprint"
2351
2461
        # New GnuTLS "datum" with the OpenPGP public key
2365
2475
                                       ctypes.byref(crtverify))
2366
2476
        if crtverify.value != 0:
2367
2477
            gnutls.openpgp_crt_deinit(crt)
2368
 
            raise gnutls.CertificateSecurityError("Verify failed")
 
2478
            raise gnutls.CertificateSecurityError(code
 
2479
                                                  =crtverify.value)
2369
2480
        # New buffer for the fingerprint
2370
2481
        buf = ctypes.create_string_buffer(20)
2371
2482
        buf_len = ctypes.c_size_t()
2499
2610
                    raise
2500
2611
        # Only bind(2) the socket if we really need to.
2501
2612
        if self.server_address[0] or self.server_address[1]:
 
2613
            if self.server_address[1]:
 
2614
                self.allow_reuse_address = True
2502
2615
            if not self.server_address[0]:
2503
2616
                if self.address_family == socket.AF_INET6:
2504
2617
                    any_address = "::"  # in6addr_any
2578
2691
        command = request[0]
2579
2692
 
2580
2693
        if command == 'init':
2581
 
            fpr = request[1].decode("ascii")
2582
 
            address = request[2]
 
2694
            key_id = request[1].decode("ascii")
 
2695
            fpr = request[2].decode("ascii")
 
2696
            address = request[3]
2583
2697
 
2584
2698
            for c in self.clients.values():
2585
 
                if c.fingerprint == fpr:
 
2699
                if key_id == "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855":
 
2700
                    continue
 
2701
                if key_id and c.key_id == key_id:
 
2702
                    client = c
 
2703
                    break
 
2704
                if fpr and c.fingerprint == fpr:
2586
2705
                    client = c
2587
2706
                    break
2588
2707
            else:
2589
 
                logger.info("Client not found for fingerprint: %s, ad"
2590
 
                            "dress: %s", fpr, address)
 
2708
                logger.info("Client not found for key ID: %s, address"
 
2709
                            ": %s", key_id or fpr, address)
2591
2710
                if self.use_dbus:
2592
2711
                    # Emit D-Bus signal
2593
 
                    mandos_dbus_service.ClientNotFound(fpr,
 
2712
                    mandos_dbus_service.ClientNotFound(key_id or fpr,
2594
2713
                                                       address[0])
2595
2714
                parent_pipe.send(False)
2596
2715
                return False
2859
2978
        sys.exit(os.EX_OK if fail_count == 0 else 1)
2860
2979
 
2861
2980
    # Default values for config file for server-global settings
 
2981
    if gnutls.has_rawpk:
 
2982
        priority = ("SECURE128:!CTYPE-X.509:+CTYPE-RAWPK:!RSA"
 
2983
                    ":!VERS-ALL:+VERS-TLS1.3:%PROFILE_ULTRA")
 
2984
    else:
 
2985
        priority = ("SECURE256:!CTYPE-X.509:+CTYPE-OPENPGP:!RSA"
 
2986
                    ":+SIGN-DSA-SHA256")
2862
2987
    server_defaults = {"interface": "",
2863
2988
                       "address": "",
2864
2989
                       "port": "",
2865
2990
                       "debug": "False",
2866
 
                       "priority":
2867
 
                       "SECURE256:!CTYPE-X.509:+CTYPE-OPENPGP:!RSA"
2868
 
                       ":+SIGN-DSA-SHA256",
 
2991
                       "priority": priority,
2869
2992
                       "servicename": "Mandos",
2870
2993
                       "use_dbus": "True",
2871
2994
                       "use_ipv6": "True",
2876
2999
                       "foreground": "False",
2877
3000
                       "zeroconf": "True",
2878
3001
                       }
 
3002
    del priority
2879
3003
 
2880
3004
    # Parse config file for server-global settings
2881
 
    server_config = configparser.SafeConfigParser(server_defaults)
 
3005
    server_config = configparser.ConfigParser(server_defaults)
2882
3006
    del server_defaults
2883
3007
    server_config.read(os.path.join(options.configdir, "mandos.conf"))
2884
 
    # Convert the SafeConfigParser object to a dict
 
3008
    # Convert the ConfigParser object to a dict
2885
3009
    server_settings = server_config.defaults()
2886
3010
    # Use the appropriate methods on the non-string config options
2887
3011
    for option in ("debug", "use_dbus", "use_ipv6", "restore",
2959
3083
                                  server_settings["servicename"])))
2960
3084
 
2961
3085
    # Parse config file with clients
2962
 
    client_config = configparser.SafeConfigParser(Client
2963
 
                                                  .client_defaults)
 
3086
    client_config = configparser.ConfigParser(Client.client_defaults)
2964
3087
    client_config.read(os.path.join(server_settings["configdir"],
2965
3088
                                    "clients.conf"))
2966
3089
 
3037
3160
        # Close all input and output, do double fork, etc.
3038
3161
        daemon()
3039
3162
 
3040
 
    # multiprocessing will use threads, so before we use GLib we need
3041
 
    # to inform GLib that threads will be used.
3042
 
    GLib.threads_init()
 
3163
    if gi.version_info < (3, 10, 2):
 
3164
        # multiprocessing will use threads, so before we use GLib we
 
3165
        # need to inform GLib that threads will be used.
 
3166
        GLib.threads_init()
3043
3167
 
3044
3168
    global main_loop
3045
3169
    # From the Avahi example code
3125
3249
                        for k in ("name", "host"):
3126
3250
                            if isinstance(value[k], bytes):
3127
3251
                                value[k] = value[k].decode("utf-8")
 
3252
                        if "key_id" not in value:
 
3253
                            value["key_id"] = ""
 
3254
                        elif "fingerprint" not in value:
 
3255
                            value["fingerprint"] = ""
3128
3256
                    #  old_client_settings
3129
3257
                    # .keys()
3130
3258
                    old_client_settings = {
3267
3395
                pass
3268
3396
 
3269
3397
            @dbus.service.signal(_interface, signature="ss")
3270
 
            def ClientNotFound(self, fingerprint, address):
 
3398
            def ClientNotFound(self, key_id, address):
3271
3399
                "D-Bus signal"
3272
3400
                pass
3273
3401