/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-02-09 23:23:26 UTC
  • Revision ID: teddy@recompile.se-20190209232326-z1z2kzpgfixz7iaj
Add support for using raw public keys in TLS (RFC 7250)

Since GnuTLS removed support for OpenPGP keys in TLS (RFC 6091), and
no other library supports it, we have to change the protocol to use
something else.  We choose to use "raw public keys" (RFC 7250).  Since
we still use OpenPGP keys to decrypt the secret password, this means
that each client will have two keys: One OpenPGP key and one TLS
public/private key, and the key ID of the latter key is used to
identify clients instead of the fingerprint of the OpenPGP key.

Note that this code is still compatible with GnuTLS before version
3.6.0 (when OpenPGP key support was removed).  This commit merely adds
support for using raw pulic keys instead with GnuTLS 3.6.6. or later.

* DBUS-API (Signals/ClientNotFound): Change name of first parameter
                                     from "Fingerprint" to "KeyID".
  (Mandos Client Interface/Properties/KeyID): New.
* INSTALL: Document conflict with GnuTLS 3.6.0 (which removed OpenPGP
           key support) up until 3.6.6, when support for raw public
           keys was added.  Also document new dependency of client on
           "gnutls-bin" package (for certtool).
* Makefile (run-client): Depend on TLS key files, and also pass them
                         as arguments to client.
  (keydir/tls-privkey.pem, keydir/tls-pubkey.pem): New.
  (confdir/clients.conf): Add dependency on TLS public key.
  (purge-client): Add removal of TLS key files.
* clients.conf ([foo]/key_id, [bar]/key_id): New.
* debian/control (Source: mandos/Build-Depends): Also allow
                                                 libgnutls30 (>= 3.6.6)
  (Package: mandos/Depends): - '' -
  (Package: mandos/Description): Alter description to match new
                                 design.
  (Package: mandos-client/Description): - '' -
  (Package: mandos-client/Depends): Move "gnutls-bin | openssl" to
                                    here from "Recommends".
* debian/mandos-client.README.Debian: Add --tls-privkey and
                                      --tls-pubkey options to test
                                      command.
* debian/mandos-client.postinst (create_key): Renamed to "create_keys"
                                             (all callers changed),
                                             and also create TLS key.
* debian/mandos-client.postrm (purge): Also remove TLS key files.
* intro.xml (DESCRIPTION): Describe new dual-key design.
* mandos (GnuTLS): Define different functions depending on whether
                   support for raw public keys is detected.
  (Client.key_id): New attribute.
  (ClientDBus.KeyID_dbus_property): New method.
  (ProxyClient.__init__): Take new "key_id" parameter.
  (ClientHandler.handle): Use key IDs when using raw public keys and
                          use fingerprints when using OpenPGP keys.
  (ClientHandler.peer_certificate): Also handle raw public keys.
  (ClientHandler.key_id): New.
  (MandosServer.handle_ipc): Pass key ID over the pipe IPC.  Also
                             check for key ID matches when looking up
                             clients.
  (main): Default GnuTLS priority string depends on whether we are
          using raw public keys or not.  When unpickling clients, set
          key_id if not set in the pickle.
  (main/MandosDBusService.ClientNotFound): Change name of first
                                           parameter from
                                           "Fingerprint" to "KeyID".
* mandos-clients.conf.xml (OPTIONS): Document new "key_id" option.
  (OPTIONS/secret): Mention new key ID matchning.
  (EXPANSION/RUNTIME EXPANSION): Add new "key_id" option.
  (EXAMPLE): - '' -
* mandos-ctl (tablewords, main/keywords): Add new "KeyID" property.
* mandos-keygen: Create TLS key files.  New "--tls-keytype" (-T)
                 option.  Alter help text to be more clear about key
                 types.  When in password mode, also output "key_id"
                 option.
* mandos-keygen.xml (SYNOPSIS): Add new "--tls-keytype" (-T) option.
  (DESCRIPTION): Alter to match new dual-key design.
  (OVERVIEW): - '' -
  (FILES): Add TLS key files.
* mandos-options.xml (priority): Document new default priority string
                                 when using raw public keys.
* mandos.xml (NETWORK PROTOCOL): Describe new protocol using key ID.
  (BUGS): Remove issue about checking expire times of OpenPGP keys,
          since TLS public keys do not have expiration times.
  (SECURITY/CLIENT): Alter description to match new design.
  (SEE ALSO/GnuTLS): - '' -
  (SEE ALSO): Add reference to RFC 7250, and alter description of when
              RFC 6091 is used.
* overview.xml: Alter text to match new design.
* plugin-runner.xml (EXAMPLE): Add --tls-pubkey and --tls-privkey
                               options to mandos-client options.
* plugins.d/mandos-client.c: Use raw public keys when compiling with
                             supporting GnuTLS versions. Add new
                             "--tls-pubkey" and "--tls-privkey"
                             options (which do nothing if GnuTLS
                             library does not support raw public
                             keys).  Alter text throughout to reflect
                             new design.  Only generate new DH
                             parameters (based on size of OpenPGP key)
                             when using OpenPGP in TLS.  Default
                             GnuTLS priority string depends on whether
                             we are using raw public keys or not.
* plugins.d/mandos-client.xml (SYNOPSIS): Add new "--tls-privkey" (-t)
                                          and "--tls-pubkey" (-T)
                                          options.
  (DESCRIPTION): Describe new dual-key design.
  (OPTIONS): Document new "--tls-privkey" (-t) and "--tls-pubkey" (-T)
             options.
  (OPTIONS/--dh-bits): No longer necessarily depends on OpenPGP key
                       size.
  (FILES): Add default locations for TLS public and private key files.
  (EXAMPLE): Use new --tls-pubkey and --tls-privkey options.
  (SECURITY): Alter wording slightly to reflect new dual-key design.
  (SEE ALSO/GnuTLS): Alter description to match new design.
  (SEE ALSO): Add reference to RFC 7250, and alter description of when
              RFC 6091 is used.

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-2017 Teddy Hogeborn
15
 
# Copyright © 2008-2017 Björn Påhlsson
16
 
#
17
 
# This program is free software: you can redistribute it and/or modify
18
 
# it under the terms of the GNU General Public License as published by
 
14
# Copyright © 2008-2018 Teddy Hogeborn
 
15
# Copyright © 2008-2018 Björn Påhlsson
 
16
#
 
17
# This file is part of Mandos.
 
18
#
 
19
# Mandos is free software: you can redistribute it and/or modify it
 
20
# under the terms of the GNU General Public License as published by
19
21
# the Free Software Foundation, either version 3 of the License, or
20
22
# (at your option) any later version.
21
23
#
22
 
#     This program is distributed in the hope that it will be useful,
23
 
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
 
24
#     Mandos is distributed in the hope that it will be useful, but
 
25
#     WITHOUT ANY WARRANTY; without even the implied warranty of
24
26
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25
27
#     GNU General Public License for more details.
26
28
#
27
29
# You should have received a copy of the GNU General Public License
28
 
# along with this program.  If not, see
29
 
# <http://www.gnu.org/licenses/>.
 
30
# along with Mandos.  If not, see <http://www.gnu.org/licenses/>.
30
31
#
31
32
# Contact the authors at <mandos@recompile.se>.
32
33
#
114
115
if sys.version_info.major == 2:
115
116
    str = unicode
116
117
 
117
 
version = "1.7.15"
 
118
version = "1.7.20"
118
119
stored_state_file = "clients.pickle"
119
120
 
120
121
logger = logging.getLogger()
495
496
class AvahiServiceToSyslog(AvahiService):
496
497
    def rename(self, *args, **kwargs):
497
498
        """Add the new name to the syslog messages"""
498
 
        ret = AvahiService.rename(self, *args, **kwargs)
 
499
        ret = super(AvahiServiceToSyslog, self).rename(*args, **kwargs)
499
500
        syslogger.setFormatter(logging.Formatter(
500
501
            'Mandos ({}) [%(process)d]: %(levelname)s: %(message)s'
501
502
            .format(self.name)))
513
514
    _library = ctypes.cdll.LoadLibrary(library)
514
515
    del library
515
516
    _need_version = b"3.3.0"
 
517
    _tls_rawpk_version = b"3.6.6"
516
518
 
517
519
    def __init__(self):
518
520
        # Need to use "self" here, since this method is called before
529
531
    E_INTERRUPTED = -52
530
532
    E_AGAIN = -28
531
533
    CRT_OPENPGP = 2
 
534
    CRT_RAWPK = 3
532
535
    CLIENT = 2
533
536
    SHUT_RDWR = 0
534
537
    CRD_CERTIFICATE = 1
535
538
    E_NO_CERTIFICATE_FOUND = -49
 
539
    X509_FMT_DER = 0
 
540
    NO_TICKETS = 1<<10
 
541
    ENABLE_RAWPK = 1<<18
 
542
    CTYPE_PEERS = 3
 
543
    KEYID_USE_SHA256 = 1        # gnutls/x509.h
536
544
    OPENPGP_FMT_RAW = 0         # gnutls/openpgp.h
537
545
 
538
546
    # Types
592
600
    class ClientSession(object):
593
601
        def __init__(self, socket, credentials=None):
594
602
            self._c_object = gnutls.session_t()
595
 
            gnutls.init(ctypes.byref(self._c_object), gnutls.CLIENT)
 
603
            gnutls_flags = gnutls.CLIENT
 
604
            if gnutls.check_version("3.5.6"):
 
605
                gnutls_flags |= gnutls.NO_TICKETS
 
606
            if gnutls.has_rawpk:
 
607
                gnutls_flags |= gnutls.ENABLE_RAWPK
 
608
            gnutls.init(ctypes.byref(self._c_object), gnutls_flags)
 
609
            del gnutls_flags
596
610
            gnutls.set_default_priority(self._c_object)
597
611
            gnutls.transport_set_ptr(self._c_object, socket.fileno())
598
612
            gnutls.handshake_set_private_extensions(self._c_object,
730
744
    check_version.argtypes = [ctypes.c_char_p]
731
745
    check_version.restype = ctypes.c_char_p
732
746
 
733
 
    # All the function declarations below are from gnutls/openpgp.h
734
 
 
735
 
    openpgp_crt_init = _library.gnutls_openpgp_crt_init
736
 
    openpgp_crt_init.argtypes = [ctypes.POINTER(openpgp_crt_t)]
737
 
    openpgp_crt_init.restype = _error_code
738
 
 
739
 
    openpgp_crt_import = _library.gnutls_openpgp_crt_import
740
 
    openpgp_crt_import.argtypes = [openpgp_crt_t,
741
 
                                   ctypes.POINTER(datum_t),
742
 
                                   openpgp_crt_fmt_t]
743
 
    openpgp_crt_import.restype = _error_code
744
 
 
745
 
    openpgp_crt_verify_self = _library.gnutls_openpgp_crt_verify_self
746
 
    openpgp_crt_verify_self.argtypes = [openpgp_crt_t, ctypes.c_uint,
747
 
                                        ctypes.POINTER(ctypes.c_uint)]
748
 
    openpgp_crt_verify_self.restype = _error_code
749
 
 
750
 
    openpgp_crt_deinit = _library.gnutls_openpgp_crt_deinit
751
 
    openpgp_crt_deinit.argtypes = [openpgp_crt_t]
752
 
    openpgp_crt_deinit.restype = None
753
 
 
754
 
    openpgp_crt_get_fingerprint = (
755
 
        _library.gnutls_openpgp_crt_get_fingerprint)
756
 
    openpgp_crt_get_fingerprint.argtypes = [openpgp_crt_t,
757
 
                                            ctypes.c_void_p,
758
 
                                            ctypes.POINTER(
759
 
                                                ctypes.c_size_t)]
760
 
    openpgp_crt_get_fingerprint.restype = _error_code
 
747
    has_rawpk = bool(check_version(_tls_rawpk_version))
 
748
 
 
749
    if has_rawpk:
 
750
        # Types
 
751
        class pubkey_st(ctypes.Structure):
 
752
            _fields = []
 
753
        pubkey_t = ctypes.POINTER(pubkey_st)
 
754
 
 
755
        x509_crt_fmt_t = ctypes.c_int
 
756
 
 
757
        # All the function declarations below are from gnutls/abstract.h
 
758
        pubkey_init = _library.gnutls_pubkey_init
 
759
        pubkey_init.argtypes = [ctypes.POINTER(pubkey_t)]
 
760
        pubkey_init.restype = _error_code
 
761
 
 
762
        pubkey_import = _library.gnutls_pubkey_import
 
763
        pubkey_import.argtypes = [pubkey_t, ctypes.POINTER(datum_t),
 
764
                                  x509_crt_fmt_t]
 
765
        pubkey_import.restype = _error_code
 
766
 
 
767
        pubkey_get_key_id = _library.gnutls_pubkey_get_key_id
 
768
        pubkey_get_key_id.argtypes = [pubkey_t, ctypes.c_int,
 
769
                                      ctypes.POINTER(ctypes.c_ubyte),
 
770
                                      ctypes.POINTER(ctypes.c_size_t)]
 
771
        pubkey_get_key_id.restype = _error_code
 
772
 
 
773
        pubkey_deinit = _library.gnutls_pubkey_deinit
 
774
        pubkey_deinit.argtypes = [pubkey_t]
 
775
        pubkey_deinit.restype = None
 
776
    else:
 
777
        # All the function declarations below are from gnutls/openpgp.h
 
778
 
 
779
        openpgp_crt_init = _library.gnutls_openpgp_crt_init
 
780
        openpgp_crt_init.argtypes = [ctypes.POINTER(openpgp_crt_t)]
 
781
        openpgp_crt_init.restype = _error_code
 
782
 
 
783
        openpgp_crt_import = _library.gnutls_openpgp_crt_import
 
784
        openpgp_crt_import.argtypes = [openpgp_crt_t,
 
785
                                       ctypes.POINTER(datum_t),
 
786
                                       openpgp_crt_fmt_t]
 
787
        openpgp_crt_import.restype = _error_code
 
788
 
 
789
        openpgp_crt_verify_self = _library.gnutls_openpgp_crt_verify_self
 
790
        openpgp_crt_verify_self.argtypes = [openpgp_crt_t, ctypes.c_uint,
 
791
                                            ctypes.POINTER(ctypes.c_uint)]
 
792
        openpgp_crt_verify_self.restype = _error_code
 
793
 
 
794
        openpgp_crt_deinit = _library.gnutls_openpgp_crt_deinit
 
795
        openpgp_crt_deinit.argtypes = [openpgp_crt_t]
 
796
        openpgp_crt_deinit.restype = None
 
797
 
 
798
        openpgp_crt_get_fingerprint = (
 
799
            _library.gnutls_openpgp_crt_get_fingerprint)
 
800
        openpgp_crt_get_fingerprint.argtypes = [openpgp_crt_t,
 
801
                                                ctypes.c_void_p,
 
802
                                                ctypes.POINTER(
 
803
                                                    ctypes.c_size_t)]
 
804
        openpgp_crt_get_fingerprint.restype = _error_code
 
805
 
 
806
    if check_version("3.6.4"):
 
807
        certificate_type_get2 = _library.gnutls_certificate_type_get2
 
808
        certificate_type_get2.argtypes = [session_t, ctypes.c_int]
 
809
        certificate_type_get2.restype = _error_code
761
810
 
762
811
    # Remove non-public functions
763
812
    del _error_code, _retry_on_error
799
848
    disable_initiator_tag: a GLib event source tag, or None
800
849
    enabled:    bool()
801
850
    fingerprint: string (40 or 32 hexadecimal digits); used to
802
 
                 uniquely identify the client
 
851
                 uniquely identify an OpenPGP client
 
852
    key_id: string (64 hexadecimal digits); used to uniquely identify
 
853
            a client using raw public keys
803
854
    host:       string; available for use by the checker command
804
855
    interval:   datetime.timedelta(); How often to start a new checker
805
856
    last_approval_request: datetime.datetime(); (UTC) or None
823
874
    """
824
875
 
825
876
    runtime_expansions = ("approval_delay", "approval_duration",
826
 
                          "created", "enabled", "expires",
 
877
                          "created", "enabled", "expires", "key_id",
827
878
                          "fingerprint", "host", "interval",
828
879
                          "last_approval_request", "last_checked_ok",
829
880
                          "last_enabled", "name", "timeout")
859
910
            client["enabled"] = config.getboolean(client_name,
860
911
                                                  "enabled")
861
912
 
862
 
            # Uppercase and remove spaces from fingerprint for later
863
 
            # comparison purposes with return value from the
864
 
            # fingerprint() function
 
913
            # Uppercase and remove spaces from key_id and fingerprint
 
914
            # for later comparison purposes with return value from the
 
915
            # key_id() and fingerprint() functions
 
916
            client["key_id"] = (section.get("key_id", "").upper()
 
917
                                .replace(" ", ""))
865
918
            client["fingerprint"] = (section["fingerprint"].upper()
866
919
                                     .replace(" ", ""))
867
920
            if "secret" in section:
911
964
            self.expires = None
912
965
 
913
966
        logger.debug("Creating client %r", self.name)
 
967
        logger.debug("  Key ID: %s", self.key_id)
914
968
        logger.debug("  Fingerprint: %s", self.fingerprint)
915
969
        self.created = settings.get("created",
916
970
                                    datetime.datetime.utcnow())
1998
2052
    def Name_dbus_property(self):
1999
2053
        return dbus.String(self.name)
2000
2054
 
 
2055
    # KeyID - property
 
2056
    @dbus_annotations(
 
2057
        {"org.freedesktop.DBus.Property.EmitsChangedSignal": "const"})
 
2058
    @dbus_service_property(_interface, signature="s", access="read")
 
2059
    def KeyID_dbus_property(self):
 
2060
        return dbus.String(self.key_id)
 
2061
 
2001
2062
    # Fingerprint - property
2002
2063
    @dbus_annotations(
2003
2064
        {"org.freedesktop.DBus.Property.EmitsChangedSignal": "const"})
2159
2220
 
2160
2221
 
2161
2222
class ProxyClient(object):
2162
 
    def __init__(self, child_pipe, fpr, address):
 
2223
    def __init__(self, child_pipe, key_id, fpr, address):
2163
2224
        self._pipe = child_pipe
2164
 
        self._pipe.send(('init', fpr, address))
 
2225
        self._pipe.send(('init', key_id, fpr, address))
2165
2226
        if not self._pipe.recv():
2166
 
            raise KeyError(fpr)
 
2227
            raise KeyError(key_id or fpr)
2167
2228
 
2168
2229
    def __getattribute__(self, name):
2169
2230
        if name == '_pipe':
2236
2297
 
2237
2298
            approval_required = False
2238
2299
            try:
2239
 
                try:
2240
 
                    fpr = self.fingerprint(
2241
 
                        self.peer_certificate(session))
2242
 
                except (TypeError, gnutls.Error) as error:
2243
 
                    logger.warning("Bad certificate: %s", error)
2244
 
                    return
2245
 
                logger.debug("Fingerprint: %s", fpr)
2246
 
 
2247
 
                try:
2248
 
                    client = ProxyClient(child_pipe, fpr,
 
2300
                if gnutls.has_rawpk:
 
2301
                    fpr = ""
 
2302
                    try:
 
2303
                        key_id = self.key_id(
 
2304
                            self.peer_certificate(session))
 
2305
                    except (TypeError, gnutls.Error) as error:
 
2306
                        logger.warning("Bad certificate: %s", error)
 
2307
                        return
 
2308
                    logger.debug("Key ID: %s", key_id)
 
2309
 
 
2310
                else:
 
2311
                    key_id = ""
 
2312
                    try:
 
2313
                        fpr = self.fingerprint(
 
2314
                            self.peer_certificate(session))
 
2315
                    except (TypeError, gnutls.Error) as error:
 
2316
                        logger.warning("Bad certificate: %s", error)
 
2317
                        return
 
2318
                    logger.debug("Fingerprint: %s", fpr)
 
2319
 
 
2320
                try:
 
2321
                    client = ProxyClient(child_pipe, key_id, fpr,
2249
2322
                                         self.client_address)
2250
2323
                except KeyError:
2251
2324
                    return
2328
2401
 
2329
2402
    @staticmethod
2330
2403
    def peer_certificate(session):
2331
 
        "Return the peer's OpenPGP certificate as a bytestring"
2332
 
        # If not an OpenPGP certificate...
2333
 
        if (gnutls.certificate_type_get(session._c_object)
2334
 
            != gnutls.CRT_OPENPGP):
 
2404
        "Return the peer's certificate as a bytestring"
 
2405
        try:
 
2406
            cert_type = gnutls.certificate_type_get2(session._c_object,
 
2407
                                                     gnutls.CTYPE_PEERS)
 
2408
        except AttributeError:
 
2409
            cert_type = gnutls.certificate_type_get(session._c_object)
 
2410
        if gnutls.has_rawpk:
 
2411
            valid_cert_types = frozenset((gnutls.CRT_RAWPK,))
 
2412
        else:
 
2413
            valid_cert_types = frozenset((gnutls.CRT_OPENPGP,))
 
2414
        # If not a valid certificate type...
 
2415
        if cert_type not in valid_cert_types:
 
2416
            logger.info("Cert type %r not in %r", cert_type,
 
2417
                        valid_cert_types)
2335
2418
            # ...return invalid data
2336
2419
            return b""
2337
2420
        list_size = ctypes.c_uint(1)
2345
2428
        return ctypes.string_at(cert.data, cert.size)
2346
2429
 
2347
2430
    @staticmethod
 
2431
    def key_id(certificate):
 
2432
        "Convert a certificate bytestring to a hexdigit key ID"
 
2433
        # New GnuTLS "datum" with the public key
 
2434
        datum = gnutls.datum_t(
 
2435
            ctypes.cast(ctypes.c_char_p(certificate),
 
2436
                        ctypes.POINTER(ctypes.c_ubyte)),
 
2437
            ctypes.c_uint(len(certificate)))
 
2438
        # XXX all these need to be created in the gnutls "module"
 
2439
        # New empty GnuTLS certificate
 
2440
        pubkey = gnutls.pubkey_t()
 
2441
        gnutls.pubkey_init(ctypes.byref(pubkey))
 
2442
        # Import the raw public key into the certificate
 
2443
        gnutls.pubkey_import(pubkey,
 
2444
                             ctypes.byref(datum),
 
2445
                             gnutls.X509_FMT_DER)
 
2446
        # New buffer for the key ID
 
2447
        buf = ctypes.create_string_buffer(32)
 
2448
        buf_len = ctypes.c_size_t(len(buf))
 
2449
        # Get the key ID from the raw public key into the buffer
 
2450
        gnutls.pubkey_get_key_id(pubkey,
 
2451
                                 gnutls.KEYID_USE_SHA256,
 
2452
                                 ctypes.cast(ctypes.byref(buf),
 
2453
                                             ctypes.POINTER(ctypes.c_ubyte)),
 
2454
                                 ctypes.byref(buf_len))
 
2455
        # Deinit the certificate
 
2456
        gnutls.pubkey_deinit(pubkey)
 
2457
 
 
2458
        # Convert the buffer to a Python bytestring
 
2459
        key_id = ctypes.string_at(buf, buf_len.value)
 
2460
        # Convert the bytestring to hexadecimal notation
 
2461
        hex_key_id = binascii.hexlify(key_id).upper()
 
2462
        return hex_key_id
 
2463
 
 
2464
    @staticmethod
2348
2465
    def fingerprint(openpgp):
2349
2466
        "Convert an OpenPGP bytestring to a hexdigit fingerprint"
2350
2467
        # New GnuTLS "datum" with the OpenPGP public key
2364
2481
                                       ctypes.byref(crtverify))
2365
2482
        if crtverify.value != 0:
2366
2483
            gnutls.openpgp_crt_deinit(crt)
2367
 
            raise gnutls.CertificateSecurityError("Verify failed")
 
2484
            raise gnutls.CertificateSecurityError(code
 
2485
                                                  =crtverify.value)
2368
2486
        # New buffer for the fingerprint
2369
2487
        buf = ctypes.create_string_buffer(20)
2370
2488
        buf_len = ctypes.c_size_t()
2577
2695
        command = request[0]
2578
2696
 
2579
2697
        if command == 'init':
2580
 
            fpr = request[1]
2581
 
            address = request[2]
 
2698
            key_id = request[1].decode("ascii")
 
2699
            fpr = request[2].decode("ascii")
 
2700
            address = request[3]
2582
2701
 
2583
2702
            for c in self.clients.values():
2584
 
                if c.fingerprint == fpr:
 
2703
                if key_id and c.key_id == key_id:
 
2704
                    client = c
 
2705
                    break
 
2706
                if fpr and c.fingerprint == fpr:
2585
2707
                    client = c
2586
2708
                    break
2587
2709
            else:
2588
 
                logger.info("Client not found for fingerprint: %s, ad"
2589
 
                            "dress: %s", fpr, address)
 
2710
                logger.info("Client not found for key ID: %s, address"
 
2711
                            ": %s", key_id or fpr, address)
2590
2712
                if self.use_dbus:
2591
2713
                    # Emit D-Bus signal
2592
 
                    mandos_dbus_service.ClientNotFound(fpr,
 
2714
                    mandos_dbus_service.ClientNotFound(key_id or fpr,
2593
2715
                                                       address[0])
2594
2716
                parent_pipe.send(False)
2595
2717
                return False
2858
2980
        sys.exit(os.EX_OK if fail_count == 0 else 1)
2859
2981
 
2860
2982
    # Default values for config file for server-global settings
 
2983
    if gnutls.has_rawpk:
 
2984
        priority = ("SECURE128:!CTYPE-X.509:+CTYPE-RAWPK:!RSA"
 
2985
                    ":!VERS-ALL:+VERS-TLS1.3:%PROFILE_ULTRA")
 
2986
    else:
 
2987
        priority = ("SECURE256:!CTYPE-X.509:+CTYPE-OPENPGP:!RSA"
 
2988
                    ":+SIGN-DSA-SHA256")
2861
2989
    server_defaults = {"interface": "",
2862
2990
                       "address": "",
2863
2991
                       "port": "",
2864
2992
                       "debug": "False",
2865
 
                       "priority":
2866
 
                       "SECURE256:!CTYPE-X.509:+CTYPE-OPENPGP:!RSA"
2867
 
                       ":+SIGN-DSA-SHA256",
 
2993
                       "priority": priority,
2868
2994
                       "servicename": "Mandos",
2869
2995
                       "use_dbus": "True",
2870
2996
                       "use_ipv6": "True",
2875
3001
                       "foreground": "False",
2876
3002
                       "zeroconf": "True",
2877
3003
                       }
 
3004
    del priority
2878
3005
 
2879
3006
    # Parse config file for server-global settings
2880
3007
    server_config = configparser.SafeConfigParser(server_defaults)
3124
3251
                        for k in ("name", "host"):
3125
3252
                            if isinstance(value[k], bytes):
3126
3253
                                value[k] = value[k].decode("utf-8")
 
3254
                        if not value.has_key("key_id"):
 
3255
                            value["key_id"] = ""
 
3256
                        elif not value.has_key("fingerprint"):
 
3257
                            value["fingerprint"] = ""
3127
3258
                    #  old_client_settings
3128
3259
                    # .keys()
3129
3260
                    old_client_settings = {
3266
3397
                pass
3267
3398
 
3268
3399
            @dbus.service.signal(_interface, signature="ss")
3269
 
            def ClientNotFound(self, fingerprint, address):
 
3400
            def ClientNotFound(self, key_id, address):
3270
3401
                "D-Bus signal"
3271
3402
                pass
3272
3403