/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-07-29 16:35:53 UTC
  • Revision ID: teddy@recompile.se-20190729163553-1i442i2cbx64c537
Make tests and man page examples match

Make the tests test_manual_page_example[1-5] match exactly what is
written in the manual page, and add comments to manual page as
reminders to keep tests and manual page examples in sync.

* mandos-ctl (Test_commands_from_options.test_manual_page_example_1):
  Remove "--verbose" option, since the manual does not have it as the
  first example, and change assertion to match.
* mandos-ctl.xml (EXAMPLE): Add comments to all examples documenting
  which test function they correspond to.  Also remove unnecessary
  quotes from option arguments in fourth example, and clarify language
  slightly in fifth example.

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
#
115
115
if sys.version_info.major == 2:
116
116
    str = unicode
117
117
 
118
 
version = "1.7.16"
 
118
version = "1.8.4"
119
119
stored_state_file = "clients.pickle"
120
120
 
121
121
logger = logging.getLogger()
275
275
 
276
276
 
277
277
# 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."""
 
278
class avahi(object):
 
279
    """This isn't so much a class as it is a module-like namespace."""
281
280
    IF_UNSPEC = -1               # avahi-common/address.h
282
281
    PROTO_UNSPEC = -1            # avahi-common/address.h
283
282
    PROTO_INET = 0               # avahi-common/address.h
287
286
    DBUS_INTERFACE_SERVER = DBUS_NAME + ".Server"
288
287
    DBUS_PATH_SERVER = "/"
289
288
 
290
 
    def string_array_to_txt_array(self, t):
 
289
    @staticmethod
 
290
    def string_array_to_txt_array(t):
291
291
        return dbus.Array((dbus.ByteArray(s.encode("utf-8"))
292
292
                           for s in t), signature="ay")
293
293
    ENTRY_GROUP_ESTABLISHED = 2  # avahi-common/defs.h
298
298
    SERVER_RUNNING = 2           # avahi-common/defs.h
299
299
    SERVER_COLLISION = 3         # avahi-common/defs.h
300
300
    SERVER_FAILURE = 4           # avahi-common/defs.h
301
 
avahi = Avahi()
302
301
 
303
302
 
304
303
class AvahiError(Exception):
496
495
class AvahiServiceToSyslog(AvahiService):
497
496
    def rename(self, *args, **kwargs):
498
497
        """Add the new name to the syslog messages"""
499
 
        ret = super(AvahiServiceToSyslog, self).rename(self, *args,
500
 
                                                       **kwargs)
 
498
        ret = super(AvahiServiceToSyslog, self).rename(*args, **kwargs)
501
499
        syslogger.setFormatter(logging.Formatter(
502
500
            'Mandos ({}) [%(process)d]: %(levelname)s: %(message)s'
503
501
            .format(self.name)))
505
503
 
506
504
 
507
505
# Pretend that we have a GnuTLS module
508
 
class GnuTLS(object):
509
 
    """This isn't so much a class as it is a module-like namespace.
510
 
    It is instantiated once, and simulates having a GnuTLS module."""
 
506
class gnutls(object):
 
507
    """This isn't so much a class as it is a module-like namespace."""
511
508
 
512
509
    library = ctypes.util.find_library("gnutls")
513
510
    if library is None:
514
511
        library = ctypes.util.find_library("gnutls-deb0")
515
512
    _library = ctypes.cdll.LoadLibrary(library)
516
513
    del library
517
 
    _need_version = b"3.3.0"
518
 
 
519
 
    def __init__(self):
520
 
        # Need to use "self" here, since this method is called before
521
 
        # the assignment to the "gnutls" global variable happens.
522
 
        if self.check_version(self._need_version) is None:
523
 
            raise self.Error("Needs GnuTLS {} or later"
524
 
                             .format(self._need_version))
525
514
 
526
515
    # Unless otherwise indicated, the constants and types below are
527
516
    # all from the gnutls/gnutls.h C header file.
531
520
    E_INTERRUPTED = -52
532
521
    E_AGAIN = -28
533
522
    CRT_OPENPGP = 2
 
523
    CRT_RAWPK = 3
534
524
    CLIENT = 2
535
525
    SHUT_RDWR = 0
536
526
    CRD_CERTIFICATE = 1
537
527
    E_NO_CERTIFICATE_FOUND = -49
 
528
    X509_FMT_DER = 0
 
529
    NO_TICKETS = 1<<10
 
530
    ENABLE_RAWPK = 1<<18
 
531
    CTYPE_PEERS = 3
 
532
    KEYID_USE_SHA256 = 1        # gnutls/x509.h
538
533
    OPENPGP_FMT_RAW = 0         # gnutls/openpgp.h
539
534
 
540
535
    # Types
563
558
 
564
559
    # Exceptions
565
560
    class Error(Exception):
566
 
        # We need to use the class name "GnuTLS" here, since this
567
 
        # exception might be raised from within GnuTLS.__init__,
568
 
        # which is called before the assignment to the "gnutls"
569
 
        # global variable has happened.
570
561
        def __init__(self, message=None, code=None, args=()):
571
562
            # Default usage is by a message string, but if a return
572
563
            # code is passed, convert it to a string with
573
564
            # gnutls.strerror()
574
565
            self.code = code
575
566
            if message is None and code is not None:
576
 
                message = GnuTLS.strerror(code)
577
 
            return super(GnuTLS.Error, self).__init__(
 
567
                message = gnutls.strerror(code)
 
568
            return super(gnutls.Error, self).__init__(
578
569
                message, *args)
579
570
 
580
571
    class CertificateSecurityError(Error):
594
585
    class ClientSession(object):
595
586
        def __init__(self, socket, credentials=None):
596
587
            self._c_object = gnutls.session_t()
597
 
            gnutls.init(ctypes.byref(self._c_object), gnutls.CLIENT)
 
588
            gnutls_flags = gnutls.CLIENT
 
589
            if gnutls.check_version(b"3.5.6"):
 
590
                gnutls_flags |= gnutls.NO_TICKETS
 
591
            if gnutls.has_rawpk:
 
592
                gnutls_flags |= gnutls.ENABLE_RAWPK
 
593
            gnutls.init(ctypes.byref(self._c_object), gnutls_flags)
 
594
            del gnutls_flags
598
595
            gnutls.set_default_priority(self._c_object)
599
596
            gnutls.transport_set_ptr(self._c_object, socket.fileno())
600
597
            gnutls.handshake_set_private_extensions(self._c_object,
732
729
    check_version.argtypes = [ctypes.c_char_p]
733
730
    check_version.restype = ctypes.c_char_p
734
731
 
735
 
    # All the function declarations below are from gnutls/openpgp.h
736
 
 
737
 
    openpgp_crt_init = _library.gnutls_openpgp_crt_init
738
 
    openpgp_crt_init.argtypes = [ctypes.POINTER(openpgp_crt_t)]
739
 
    openpgp_crt_init.restype = _error_code
740
 
 
741
 
    openpgp_crt_import = _library.gnutls_openpgp_crt_import
742
 
    openpgp_crt_import.argtypes = [openpgp_crt_t,
743
 
                                   ctypes.POINTER(datum_t),
744
 
                                   openpgp_crt_fmt_t]
745
 
    openpgp_crt_import.restype = _error_code
746
 
 
747
 
    openpgp_crt_verify_self = _library.gnutls_openpgp_crt_verify_self
748
 
    openpgp_crt_verify_self.argtypes = [openpgp_crt_t, ctypes.c_uint,
749
 
                                        ctypes.POINTER(ctypes.c_uint)]
750
 
    openpgp_crt_verify_self.restype = _error_code
751
 
 
752
 
    openpgp_crt_deinit = _library.gnutls_openpgp_crt_deinit
753
 
    openpgp_crt_deinit.argtypes = [openpgp_crt_t]
754
 
    openpgp_crt_deinit.restype = None
755
 
 
756
 
    openpgp_crt_get_fingerprint = (
757
 
        _library.gnutls_openpgp_crt_get_fingerprint)
758
 
    openpgp_crt_get_fingerprint.argtypes = [openpgp_crt_t,
759
 
                                            ctypes.c_void_p,
760
 
                                            ctypes.POINTER(
761
 
                                                ctypes.c_size_t)]
762
 
    openpgp_crt_get_fingerprint.restype = _error_code
 
732
    _need_version = b"3.3.0"
 
733
    if check_version(_need_version) is None:
 
734
        raise self.Error("Needs GnuTLS {} or later"
 
735
                         .format(_need_version))
 
736
 
 
737
    _tls_rawpk_version = b"3.6.6"
 
738
    has_rawpk = bool(check_version(_tls_rawpk_version))
 
739
 
 
740
    if has_rawpk:
 
741
        # Types
 
742
        class pubkey_st(ctypes.Structure):
 
743
            _fields = []
 
744
        pubkey_t = ctypes.POINTER(pubkey_st)
 
745
 
 
746
        x509_crt_fmt_t = ctypes.c_int
 
747
 
 
748
        # All the function declarations below are from gnutls/abstract.h
 
749
        pubkey_init = _library.gnutls_pubkey_init
 
750
        pubkey_init.argtypes = [ctypes.POINTER(pubkey_t)]
 
751
        pubkey_init.restype = _error_code
 
752
 
 
753
        pubkey_import = _library.gnutls_pubkey_import
 
754
        pubkey_import.argtypes = [pubkey_t, ctypes.POINTER(datum_t),
 
755
                                  x509_crt_fmt_t]
 
756
        pubkey_import.restype = _error_code
 
757
 
 
758
        pubkey_get_key_id = _library.gnutls_pubkey_get_key_id
 
759
        pubkey_get_key_id.argtypes = [pubkey_t, ctypes.c_int,
 
760
                                      ctypes.POINTER(ctypes.c_ubyte),
 
761
                                      ctypes.POINTER(ctypes.c_size_t)]
 
762
        pubkey_get_key_id.restype = _error_code
 
763
 
 
764
        pubkey_deinit = _library.gnutls_pubkey_deinit
 
765
        pubkey_deinit.argtypes = [pubkey_t]
 
766
        pubkey_deinit.restype = None
 
767
    else:
 
768
        # All the function declarations below are from gnutls/openpgp.h
 
769
 
 
770
        openpgp_crt_init = _library.gnutls_openpgp_crt_init
 
771
        openpgp_crt_init.argtypes = [ctypes.POINTER(openpgp_crt_t)]
 
772
        openpgp_crt_init.restype = _error_code
 
773
 
 
774
        openpgp_crt_import = _library.gnutls_openpgp_crt_import
 
775
        openpgp_crt_import.argtypes = [openpgp_crt_t,
 
776
                                       ctypes.POINTER(datum_t),
 
777
                                       openpgp_crt_fmt_t]
 
778
        openpgp_crt_import.restype = _error_code
 
779
 
 
780
        openpgp_crt_verify_self = _library.gnutls_openpgp_crt_verify_self
 
781
        openpgp_crt_verify_self.argtypes = [openpgp_crt_t, ctypes.c_uint,
 
782
                                            ctypes.POINTER(ctypes.c_uint)]
 
783
        openpgp_crt_verify_self.restype = _error_code
 
784
 
 
785
        openpgp_crt_deinit = _library.gnutls_openpgp_crt_deinit
 
786
        openpgp_crt_deinit.argtypes = [openpgp_crt_t]
 
787
        openpgp_crt_deinit.restype = None
 
788
 
 
789
        openpgp_crt_get_fingerprint = (
 
790
            _library.gnutls_openpgp_crt_get_fingerprint)
 
791
        openpgp_crt_get_fingerprint.argtypes = [openpgp_crt_t,
 
792
                                                ctypes.c_void_p,
 
793
                                                ctypes.POINTER(
 
794
                                                    ctypes.c_size_t)]
 
795
        openpgp_crt_get_fingerprint.restype = _error_code
 
796
 
 
797
    if check_version(b"3.6.4"):
 
798
        certificate_type_get2 = _library.gnutls_certificate_type_get2
 
799
        certificate_type_get2.argtypes = [session_t, ctypes.c_int]
 
800
        certificate_type_get2.restype = _error_code
763
801
 
764
802
    # Remove non-public functions
765
803
    del _error_code, _retry_on_error
766
 
# Create the global "gnutls" object, simulating a module
767
 
gnutls = GnuTLS()
768
804
 
769
805
 
770
806
def call_pipe(connection,       # : multiprocessing.Connection
801
837
    disable_initiator_tag: a GLib event source tag, or None
802
838
    enabled:    bool()
803
839
    fingerprint: string (40 or 32 hexadecimal digits); used to
804
 
                 uniquely identify the client
 
840
                 uniquely identify an OpenPGP client
 
841
    key_id: string (64 hexadecimal digits); used to uniquely identify
 
842
            a client using raw public keys
805
843
    host:       string; available for use by the checker command
806
844
    interval:   datetime.timedelta(); How often to start a new checker
807
845
    last_approval_request: datetime.datetime(); (UTC) or None
825
863
    """
826
864
 
827
865
    runtime_expansions = ("approval_delay", "approval_duration",
828
 
                          "created", "enabled", "expires",
 
866
                          "created", "enabled", "expires", "key_id",
829
867
                          "fingerprint", "host", "interval",
830
868
                          "last_approval_request", "last_checked_ok",
831
869
                          "last_enabled", "name", "timeout")
861
899
            client["enabled"] = config.getboolean(client_name,
862
900
                                                  "enabled")
863
901
 
864
 
            # Uppercase and remove spaces from fingerprint for later
865
 
            # comparison purposes with return value from the
866
 
            # fingerprint() function
 
902
            # Uppercase and remove spaces from key_id and fingerprint
 
903
            # for later comparison purposes with return value from the
 
904
            # key_id() and fingerprint() functions
 
905
            client["key_id"] = (section.get("key_id", "").upper()
 
906
                                .replace(" ", ""))
867
907
            client["fingerprint"] = (section["fingerprint"].upper()
868
908
                                     .replace(" ", ""))
869
909
            if "secret" in section:
913
953
            self.expires = None
914
954
 
915
955
        logger.debug("Creating client %r", self.name)
 
956
        logger.debug("  Key ID: %s", self.key_id)
916
957
        logger.debug("  Fingerprint: %s", self.fingerprint)
917
958
        self.created = settings.get("created",
918
959
                                    datetime.datetime.utcnow())
2000
2041
    def Name_dbus_property(self):
2001
2042
        return dbus.String(self.name)
2002
2043
 
 
2044
    # KeyID - property
 
2045
    @dbus_annotations(
 
2046
        {"org.freedesktop.DBus.Property.EmitsChangedSignal": "const"})
 
2047
    @dbus_service_property(_interface, signature="s", access="read")
 
2048
    def KeyID_dbus_property(self):
 
2049
        return dbus.String(self.key_id)
 
2050
 
2003
2051
    # Fingerprint - property
2004
2052
    @dbus_annotations(
2005
2053
        {"org.freedesktop.DBus.Property.EmitsChangedSignal": "const"})
2161
2209
 
2162
2210
 
2163
2211
class ProxyClient(object):
2164
 
    def __init__(self, child_pipe, fpr, address):
 
2212
    def __init__(self, child_pipe, key_id, fpr, address):
2165
2213
        self._pipe = child_pipe
2166
 
        self._pipe.send(('init', fpr, address))
 
2214
        self._pipe.send(('init', key_id, fpr, address))
2167
2215
        if not self._pipe.recv():
2168
 
            raise KeyError(fpr)
 
2216
            raise KeyError(key_id or fpr)
2169
2217
 
2170
2218
    def __getattribute__(self, name):
2171
2219
        if name == '_pipe':
2238
2286
 
2239
2287
            approval_required = False
2240
2288
            try:
2241
 
                try:
2242
 
                    fpr = self.fingerprint(
2243
 
                        self.peer_certificate(session))
2244
 
                except (TypeError, gnutls.Error) as error:
2245
 
                    logger.warning("Bad certificate: %s", error)
2246
 
                    return
2247
 
                logger.debug("Fingerprint: %s", fpr)
2248
 
 
2249
 
                try:
2250
 
                    client = ProxyClient(child_pipe, fpr,
 
2289
                if gnutls.has_rawpk:
 
2290
                    fpr = b""
 
2291
                    try:
 
2292
                        key_id = self.key_id(
 
2293
                            self.peer_certificate(session))
 
2294
                    except (TypeError, gnutls.Error) as error:
 
2295
                        logger.warning("Bad certificate: %s", error)
 
2296
                        return
 
2297
                    logger.debug("Key ID: %s", key_id)
 
2298
 
 
2299
                else:
 
2300
                    key_id = b""
 
2301
                    try:
 
2302
                        fpr = self.fingerprint(
 
2303
                            self.peer_certificate(session))
 
2304
                    except (TypeError, gnutls.Error) as error:
 
2305
                        logger.warning("Bad certificate: %s", error)
 
2306
                        return
 
2307
                    logger.debug("Fingerprint: %s", fpr)
 
2308
 
 
2309
                try:
 
2310
                    client = ProxyClient(child_pipe, key_id, fpr,
2251
2311
                                         self.client_address)
2252
2312
                except KeyError:
2253
2313
                    return
2330
2390
 
2331
2391
    @staticmethod
2332
2392
    def peer_certificate(session):
2333
 
        "Return the peer's OpenPGP certificate as a bytestring"
2334
 
        # If not an OpenPGP certificate...
2335
 
        if (gnutls.certificate_type_get(session._c_object)
2336
 
            != gnutls.CRT_OPENPGP):
 
2393
        "Return the peer's certificate as a bytestring"
 
2394
        try:
 
2395
            cert_type = gnutls.certificate_type_get2(session._c_object,
 
2396
                                                     gnutls.CTYPE_PEERS)
 
2397
        except AttributeError:
 
2398
            cert_type = gnutls.certificate_type_get(session._c_object)
 
2399
        if gnutls.has_rawpk:
 
2400
            valid_cert_types = frozenset((gnutls.CRT_RAWPK,))
 
2401
        else:
 
2402
            valid_cert_types = frozenset((gnutls.CRT_OPENPGP,))
 
2403
        # If not a valid certificate type...
 
2404
        if cert_type not in valid_cert_types:
 
2405
            logger.info("Cert type %r not in %r", cert_type,
 
2406
                        valid_cert_types)
2337
2407
            # ...return invalid data
2338
2408
            return b""
2339
2409
        list_size = ctypes.c_uint(1)
2347
2417
        return ctypes.string_at(cert.data, cert.size)
2348
2418
 
2349
2419
    @staticmethod
 
2420
    def key_id(certificate):
 
2421
        "Convert a certificate bytestring to a hexdigit key ID"
 
2422
        # New GnuTLS "datum" with the public key
 
2423
        datum = gnutls.datum_t(
 
2424
            ctypes.cast(ctypes.c_char_p(certificate),
 
2425
                        ctypes.POINTER(ctypes.c_ubyte)),
 
2426
            ctypes.c_uint(len(certificate)))
 
2427
        # XXX all these need to be created in the gnutls "module"
 
2428
        # New empty GnuTLS certificate
 
2429
        pubkey = gnutls.pubkey_t()
 
2430
        gnutls.pubkey_init(ctypes.byref(pubkey))
 
2431
        # Import the raw public key into the certificate
 
2432
        gnutls.pubkey_import(pubkey,
 
2433
                             ctypes.byref(datum),
 
2434
                             gnutls.X509_FMT_DER)
 
2435
        # New buffer for the key ID
 
2436
        buf = ctypes.create_string_buffer(32)
 
2437
        buf_len = ctypes.c_size_t(len(buf))
 
2438
        # Get the key ID from the raw public key into the buffer
 
2439
        gnutls.pubkey_get_key_id(pubkey,
 
2440
                                 gnutls.KEYID_USE_SHA256,
 
2441
                                 ctypes.cast(ctypes.byref(buf),
 
2442
                                             ctypes.POINTER(ctypes.c_ubyte)),
 
2443
                                 ctypes.byref(buf_len))
 
2444
        # Deinit the certificate
 
2445
        gnutls.pubkey_deinit(pubkey)
 
2446
 
 
2447
        # Convert the buffer to a Python bytestring
 
2448
        key_id = ctypes.string_at(buf, buf_len.value)
 
2449
        # Convert the bytestring to hexadecimal notation
 
2450
        hex_key_id = binascii.hexlify(key_id).upper()
 
2451
        return hex_key_id
 
2452
 
 
2453
    @staticmethod
2350
2454
    def fingerprint(openpgp):
2351
2455
        "Convert an OpenPGP bytestring to a hexdigit fingerprint"
2352
2456
        # New GnuTLS "datum" with the OpenPGP public key
2366
2470
                                       ctypes.byref(crtverify))
2367
2471
        if crtverify.value != 0:
2368
2472
            gnutls.openpgp_crt_deinit(crt)
2369
 
            raise gnutls.CertificateSecurityError("Verify failed")
 
2473
            raise gnutls.CertificateSecurityError(code
 
2474
                                                  =crtverify.value)
2370
2475
        # New buffer for the fingerprint
2371
2476
        buf = ctypes.create_string_buffer(20)
2372
2477
        buf_len = ctypes.c_size_t()
2500
2605
                    raise
2501
2606
        # Only bind(2) the socket if we really need to.
2502
2607
        if self.server_address[0] or self.server_address[1]:
 
2608
            if self.server_address[1]:
 
2609
                self.allow_reuse_address = True
2503
2610
            if not self.server_address[0]:
2504
2611
                if self.address_family == socket.AF_INET6:
2505
2612
                    any_address = "::"  # in6addr_any
2579
2686
        command = request[0]
2580
2687
 
2581
2688
        if command == 'init':
2582
 
            fpr = request[1].decode("ascii")
2583
 
            address = request[2]
 
2689
            key_id = request[1].decode("ascii")
 
2690
            fpr = request[2].decode("ascii")
 
2691
            address = request[3]
2584
2692
 
2585
2693
            for c in self.clients.values():
2586
 
                if c.fingerprint == fpr:
 
2694
                if key_id == "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855":
 
2695
                    continue
 
2696
                if key_id and c.key_id == key_id:
 
2697
                    client = c
 
2698
                    break
 
2699
                if fpr and c.fingerprint == fpr:
2587
2700
                    client = c
2588
2701
                    break
2589
2702
            else:
2590
 
                logger.info("Client not found for fingerprint: %s, ad"
2591
 
                            "dress: %s", fpr, address)
 
2703
                logger.info("Client not found for key ID: %s, address"
 
2704
                            ": %s", key_id or fpr, address)
2592
2705
                if self.use_dbus:
2593
2706
                    # Emit D-Bus signal
2594
 
                    mandos_dbus_service.ClientNotFound(fpr,
 
2707
                    mandos_dbus_service.ClientNotFound(key_id or fpr,
2595
2708
                                                       address[0])
2596
2709
                parent_pipe.send(False)
2597
2710
                return False
2860
2973
        sys.exit(os.EX_OK if fail_count == 0 else 1)
2861
2974
 
2862
2975
    # Default values for config file for server-global settings
 
2976
    if gnutls.has_rawpk:
 
2977
        priority = ("SECURE128:!CTYPE-X.509:+CTYPE-RAWPK:!RSA"
 
2978
                    ":!VERS-ALL:+VERS-TLS1.3:%PROFILE_ULTRA")
 
2979
    else:
 
2980
        priority = ("SECURE256:!CTYPE-X.509:+CTYPE-OPENPGP:!RSA"
 
2981
                    ":+SIGN-DSA-SHA256")
2863
2982
    server_defaults = {"interface": "",
2864
2983
                       "address": "",
2865
2984
                       "port": "",
2866
2985
                       "debug": "False",
2867
 
                       "priority":
2868
 
                       "SECURE256:!CTYPE-X.509:+CTYPE-OPENPGP:!RSA"
2869
 
                       ":+SIGN-DSA-SHA256",
 
2986
                       "priority": priority,
2870
2987
                       "servicename": "Mandos",
2871
2988
                       "use_dbus": "True",
2872
2989
                       "use_ipv6": "True",
2877
2994
                       "foreground": "False",
2878
2995
                       "zeroconf": "True",
2879
2996
                       }
 
2997
    del priority
2880
2998
 
2881
2999
    # Parse config file for server-global settings
2882
3000
    server_config = configparser.SafeConfigParser(server_defaults)
3126
3244
                        for k in ("name", "host"):
3127
3245
                            if isinstance(value[k], bytes):
3128
3246
                                value[k] = value[k].decode("utf-8")
 
3247
                        if "key_id" not in value:
 
3248
                            value["key_id"] = ""
 
3249
                        elif "fingerprint" not in value:
 
3250
                            value["fingerprint"] = ""
3129
3251
                    #  old_client_settings
3130
3252
                    # .keys()
3131
3253
                    old_client_settings = {
3268
3390
                pass
3269
3391
 
3270
3392
            @dbus.service.signal(_interface, signature="ss")
3271
 
            def ClientNotFound(self, fingerprint, address):
 
3393
            def ClientNotFound(self, key_id, address):
3272
3394
                "D-Bus signal"
3273
3395
                pass
3274
3396