/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: 2018-02-22 18:50:12 UTC
  • mto: This revision was merged to the branch mainline in revision 943.
  • Revision ID: teddy@recompile.se-20180222185012-etchk537ast7s1xg
Tags: version-1.7.19-1
* Makefile (version): Change to 1.7.19.
* NEWS (Version 1.7.19): Add new entry.
* debian/changelog (1.7.19-1): - '' -

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-2019 Teddy Hogeborn
15
 
# Copyright © 2008-2019 Björn Påhlsson
 
14
# Copyright © 2008-2018 Teddy Hogeborn
 
15
# Copyright © 2008-2018 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
84
83
from gi.repository import GLib
85
84
from dbus.mainloop.glib import DBusGMainLoop
86
85
import ctypes
88
87
import xml.dom.minidom
89
88
import inspect
90
89
 
91
 
if sys.version_info.major == 2:
92
 
    __metaclass__ = type
93
 
 
94
90
# Try to find the value of SO_BINDTODEVICE:
95
91
try:
96
92
    # This is where SO_BINDTODEVICE is in Python 3.3 (or 3.4?) and
119
115
if sys.version_info.major == 2:
120
116
    str = unicode
121
117
 
122
 
if sys.version_info < (3, 2):
123
 
    configparser.Configparser = configparser.SafeConfigParser
124
 
 
125
 
version = "1.8.7"
 
118
version = "1.7.19"
126
119
stored_state_file = "clients.pickle"
127
120
 
128
121
logger = logging.getLogger()
186
179
    pass
187
180
 
188
181
 
189
 
class PGPEngine:
 
182
class PGPEngine(object):
190
183
    """A simple class for OpenPGP symmetric encryption & decryption"""
191
184
 
192
185
    def __init__(self):
282
275
 
283
276
 
284
277
# Pretend that we have an Avahi module
285
 
class avahi:
286
 
    """This isn't so much a class as it is a module-like namespace."""
 
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."""
287
281
    IF_UNSPEC = -1               # avahi-common/address.h
288
282
    PROTO_UNSPEC = -1            # avahi-common/address.h
289
283
    PROTO_INET = 0               # avahi-common/address.h
293
287
    DBUS_INTERFACE_SERVER = DBUS_NAME + ".Server"
294
288
    DBUS_PATH_SERVER = "/"
295
289
 
296
 
    @staticmethod
297
 
    def string_array_to_txt_array(t):
 
290
    def string_array_to_txt_array(self, t):
298
291
        return dbus.Array((dbus.ByteArray(s.encode("utf-8"))
299
292
                           for s in t), signature="ay")
300
293
    ENTRY_GROUP_ESTABLISHED = 2  # avahi-common/defs.h
305
298
    SERVER_RUNNING = 2           # avahi-common/defs.h
306
299
    SERVER_COLLISION = 3         # avahi-common/defs.h
307
300
    SERVER_FAILURE = 4           # avahi-common/defs.h
 
301
avahi = Avahi()
308
302
 
309
303
 
310
304
class AvahiError(Exception):
322
316
    pass
323
317
 
324
318
 
325
 
class AvahiService:
 
319
class AvahiService(object):
326
320
    """An Avahi (Zeroconf) service.
327
321
 
328
322
    Attributes:
510
504
 
511
505
 
512
506
# Pretend that we have a GnuTLS module
513
 
class gnutls:
514
 
    """This isn't so much a class as it is a module-like namespace."""
 
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."""
515
510
 
516
511
    library = ctypes.util.find_library("gnutls")
517
512
    if library is None:
518
513
        library = ctypes.util.find_library("gnutls-deb0")
519
514
    _library = ctypes.cdll.LoadLibrary(library)
520
515
    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))
521
524
 
522
525
    # Unless otherwise indicated, the constants and types below are
523
526
    # all from the gnutls/gnutls.h C header file.
527
530
    E_INTERRUPTED = -52
528
531
    E_AGAIN = -28
529
532
    CRT_OPENPGP = 2
530
 
    CRT_RAWPK = 3
531
533
    CLIENT = 2
532
534
    SHUT_RDWR = 0
533
535
    CRD_CERTIFICATE = 1
534
536
    E_NO_CERTIFICATE_FOUND = -49
535
 
    X509_FMT_DER = 0
536
 
    NO_TICKETS = 1<<10
537
 
    ENABLE_RAWPK = 1<<18
538
 
    CTYPE_PEERS = 3
539
 
    KEYID_USE_SHA256 = 1        # gnutls/x509.h
540
537
    OPENPGP_FMT_RAW = 0         # gnutls/openpgp.h
541
538
 
542
539
    # Types
565
562
 
566
563
    # Exceptions
567
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.
568
569
        def __init__(self, message=None, code=None, args=()):
569
570
            # Default usage is by a message string, but if a return
570
571
            # code is passed, convert it to a string with
571
572
            # gnutls.strerror()
572
573
            self.code = code
573
574
            if message is None and code is not None:
574
 
                message = gnutls.strerror(code)
575
 
            return super(gnutls.Error, self).__init__(
 
575
                message = GnuTLS.strerror(code)
 
576
            return super(GnuTLS.Error, self).__init__(
576
577
                message, *args)
577
578
 
578
579
    class CertificateSecurityError(Error):
579
580
        pass
580
581
 
581
582
    # Classes
582
 
    class Credentials:
 
583
    class Credentials(object):
583
584
        def __init__(self):
584
585
            self._c_object = gnutls.certificate_credentials_t()
585
586
            gnutls.certificate_allocate_credentials(
589
590
        def __del__(self):
590
591
            gnutls.certificate_free_credentials(self._c_object)
591
592
 
592
 
    class ClientSession:
 
593
    class ClientSession(object):
593
594
        def __init__(self, socket, credentials=None):
594
595
            self._c_object = gnutls.session_t()
595
 
            gnutls_flags = gnutls.CLIENT
596
 
            if gnutls.check_version(b"3.5.6"):
597
 
                gnutls_flags |= gnutls.NO_TICKETS
598
 
            if gnutls.has_rawpk:
599
 
                gnutls_flags |= gnutls.ENABLE_RAWPK
600
 
            gnutls.init(ctypes.byref(self._c_object), gnutls_flags)
601
 
            del gnutls_flags
 
596
            gnutls.init(ctypes.byref(self._c_object), gnutls.CLIENT)
602
597
            gnutls.set_default_priority(self._c_object)
603
598
            gnutls.transport_set_ptr(self._c_object, socket.fileno())
604
599
            gnutls.handshake_set_private_extensions(self._c_object,
736
731
    check_version.argtypes = [ctypes.c_char_p]
737
732
    check_version.restype = ctypes.c_char_p
738
733
 
739
 
    _need_version = b"3.3.0"
740
 
    if check_version(_need_version) is None:
741
 
        raise self.Error("Needs GnuTLS {} or later"
742
 
                         .format(_need_version))
743
 
 
744
 
    _tls_rawpk_version = b"3.6.6"
745
 
    has_rawpk = bool(check_version(_tls_rawpk_version))
746
 
 
747
 
    if has_rawpk:
748
 
        # Types
749
 
        class pubkey_st(ctypes.Structure):
750
 
            _fields = []
751
 
        pubkey_t = ctypes.POINTER(pubkey_st)
752
 
 
753
 
        x509_crt_fmt_t = ctypes.c_int
754
 
 
755
 
        # All the function declarations below are from gnutls/abstract.h
756
 
        pubkey_init = _library.gnutls_pubkey_init
757
 
        pubkey_init.argtypes = [ctypes.POINTER(pubkey_t)]
758
 
        pubkey_init.restype = _error_code
759
 
 
760
 
        pubkey_import = _library.gnutls_pubkey_import
761
 
        pubkey_import.argtypes = [pubkey_t, ctypes.POINTER(datum_t),
762
 
                                  x509_crt_fmt_t]
763
 
        pubkey_import.restype = _error_code
764
 
 
765
 
        pubkey_get_key_id = _library.gnutls_pubkey_get_key_id
766
 
        pubkey_get_key_id.argtypes = [pubkey_t, ctypes.c_int,
767
 
                                      ctypes.POINTER(ctypes.c_ubyte),
768
 
                                      ctypes.POINTER(ctypes.c_size_t)]
769
 
        pubkey_get_key_id.restype = _error_code
770
 
 
771
 
        pubkey_deinit = _library.gnutls_pubkey_deinit
772
 
        pubkey_deinit.argtypes = [pubkey_t]
773
 
        pubkey_deinit.restype = None
774
 
    else:
775
 
        # All the function declarations below are from gnutls/openpgp.h
776
 
 
777
 
        openpgp_crt_init = _library.gnutls_openpgp_crt_init
778
 
        openpgp_crt_init.argtypes = [ctypes.POINTER(openpgp_crt_t)]
779
 
        openpgp_crt_init.restype = _error_code
780
 
 
781
 
        openpgp_crt_import = _library.gnutls_openpgp_crt_import
782
 
        openpgp_crt_import.argtypes = [openpgp_crt_t,
783
 
                                       ctypes.POINTER(datum_t),
784
 
                                       openpgp_crt_fmt_t]
785
 
        openpgp_crt_import.restype = _error_code
786
 
 
787
 
        openpgp_crt_verify_self = _library.gnutls_openpgp_crt_verify_self
788
 
        openpgp_crt_verify_self.argtypes = [openpgp_crt_t, ctypes.c_uint,
789
 
                                            ctypes.POINTER(ctypes.c_uint)]
790
 
        openpgp_crt_verify_self.restype = _error_code
791
 
 
792
 
        openpgp_crt_deinit = _library.gnutls_openpgp_crt_deinit
793
 
        openpgp_crt_deinit.argtypes = [openpgp_crt_t]
794
 
        openpgp_crt_deinit.restype = None
795
 
 
796
 
        openpgp_crt_get_fingerprint = (
797
 
            _library.gnutls_openpgp_crt_get_fingerprint)
798
 
        openpgp_crt_get_fingerprint.argtypes = [openpgp_crt_t,
799
 
                                                ctypes.c_void_p,
800
 
                                                ctypes.POINTER(
801
 
                                                    ctypes.c_size_t)]
802
 
        openpgp_crt_get_fingerprint.restype = _error_code
803
 
 
804
 
    if check_version(b"3.6.4"):
805
 
        certificate_type_get2 = _library.gnutls_certificate_type_get2
806
 
        certificate_type_get2.argtypes = [session_t, ctypes.c_int]
807
 
        certificate_type_get2.restype = _error_code
 
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
808
762
 
809
763
    # Remove non-public functions
810
764
    del _error_code, _retry_on_error
 
765
# Create the global "gnutls" object, simulating a module
 
766
gnutls = GnuTLS()
811
767
 
812
768
 
813
769
def call_pipe(connection,       # : multiprocessing.Connection
821
777
    connection.close()
822
778
 
823
779
 
824
 
class Client:
 
780
class Client(object):
825
781
    """A representation of a client host served by this server.
826
782
 
827
783
    Attributes:
828
784
    approved:   bool(); 'None' if not yet approved/disapproved
829
785
    approval_delay: datetime.timedelta(); Time to wait for approval
830
786
    approval_duration: datetime.timedelta(); Duration of one approval
831
 
    checker: multiprocessing.Process(); a running checker process used
832
 
             to see if the client lives. 'None' if no process is
833
 
             running.
 
787
    checker:    subprocess.Popen(); a running checker process used
 
788
                                    to see if the client lives.
 
789
                                    'None' if no process is running.
834
790
    checker_callback_tag: a GLib event source tag, or None
835
791
    checker_command: string; External command which is run to check
836
792
                     if client lives.  %() expansions are done at
844
800
    disable_initiator_tag: a GLib event source tag, or None
845
801
    enabled:    bool()
846
802
    fingerprint: string (40 or 32 hexadecimal digits); used to
847
 
                 uniquely identify an OpenPGP client
848
 
    key_id: string (64 hexadecimal digits); used to uniquely identify
849
 
            a client using raw public keys
 
803
                 uniquely identify the client
850
804
    host:       string; available for use by the checker command
851
805
    interval:   datetime.timedelta(); How often to start a new checker
852
806
    last_approval_request: datetime.datetime(); (UTC) or None
870
824
    """
871
825
 
872
826
    runtime_expansions = ("approval_delay", "approval_duration",
873
 
                          "created", "enabled", "expires", "key_id",
 
827
                          "created", "enabled", "expires",
874
828
                          "fingerprint", "host", "interval",
875
829
                          "last_approval_request", "last_checked_ok",
876
830
                          "last_enabled", "name", "timeout")
906
860
            client["enabled"] = config.getboolean(client_name,
907
861
                                                  "enabled")
908
862
 
909
 
            # Uppercase and remove spaces from key_id and fingerprint
910
 
            # for later comparison purposes with return value from the
911
 
            # key_id() and fingerprint() functions
912
 
            client["key_id"] = (section.get("key_id", "").upper()
913
 
                                .replace(" ", ""))
 
863
            # Uppercase and remove spaces from fingerprint for later
 
864
            # comparison purposes with return value from the
 
865
            # fingerprint() function
914
866
            client["fingerprint"] = (section["fingerprint"].upper()
915
867
                                     .replace(" ", ""))
916
868
            if "secret" in section:
960
912
            self.expires = None
961
913
 
962
914
        logger.debug("Creating client %r", self.name)
963
 
        logger.debug("  Key ID: %s", self.key_id)
964
915
        logger.debug("  Fingerprint: %s", self.fingerprint)
965
916
        self.created = settings.get("created",
966
917
                                    datetime.datetime.utcnow())
1043
994
    def checker_callback(self, source, condition, connection,
1044
995
                         command):
1045
996
        """The checker has completed, so take appropriate actions."""
 
997
        self.checker_callback_tag = None
 
998
        self.checker = None
1046
999
        # Read return code from connection (see call_pipe)
1047
1000
        returncode = connection.recv()
1048
1001
        connection.close()
1049
 
        self.checker.join()
1050
 
        self.checker_callback_tag = None
1051
 
        self.checker = None
1052
1002
 
1053
1003
        if returncode >= 0:
1054
1004
            self.last_checker_status = returncode
2049
1999
    def Name_dbus_property(self):
2050
2000
        return dbus.String(self.name)
2051
2001
 
2052
 
    # KeyID - property
2053
 
    @dbus_annotations(
2054
 
        {"org.freedesktop.DBus.Property.EmitsChangedSignal": "const"})
2055
 
    @dbus_service_property(_interface, signature="s", access="read")
2056
 
    def KeyID_dbus_property(self):
2057
 
        return dbus.String(self.key_id)
2058
 
 
2059
2002
    # Fingerprint - property
2060
2003
    @dbus_annotations(
2061
2004
        {"org.freedesktop.DBus.Property.EmitsChangedSignal": "const"})
2216
2159
    del _interface
2217
2160
 
2218
2161
 
2219
 
class ProxyClient:
2220
 
    def __init__(self, child_pipe, key_id, fpr, address):
 
2162
class ProxyClient(object):
 
2163
    def __init__(self, child_pipe, fpr, address):
2221
2164
        self._pipe = child_pipe
2222
 
        self._pipe.send(('init', key_id, fpr, address))
 
2165
        self._pipe.send(('init', fpr, address))
2223
2166
        if not self._pipe.recv():
2224
 
            raise KeyError(key_id or fpr)
 
2167
            raise KeyError(fpr)
2225
2168
 
2226
2169
    def __getattribute__(self, name):
2227
2170
        if name == '_pipe':
2294
2237
 
2295
2238
            approval_required = False
2296
2239
            try:
2297
 
                if gnutls.has_rawpk:
2298
 
                    fpr = b""
2299
 
                    try:
2300
 
                        key_id = self.key_id(
2301
 
                            self.peer_certificate(session))
2302
 
                    except (TypeError, gnutls.Error) as error:
2303
 
                        logger.warning("Bad certificate: %s", error)
2304
 
                        return
2305
 
                    logger.debug("Key ID: %s", key_id)
2306
 
 
2307
 
                else:
2308
 
                    key_id = b""
2309
 
                    try:
2310
 
                        fpr = self.fingerprint(
2311
 
                            self.peer_certificate(session))
2312
 
                    except (TypeError, gnutls.Error) as error:
2313
 
                        logger.warning("Bad certificate: %s", error)
2314
 
                        return
2315
 
                    logger.debug("Fingerprint: %s", fpr)
2316
 
 
2317
 
                try:
2318
 
                    client = ProxyClient(child_pipe, key_id, fpr,
 
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,
2319
2250
                                         self.client_address)
2320
2251
                except KeyError:
2321
2252
                    return
2398
2329
 
2399
2330
    @staticmethod
2400
2331
    def peer_certificate(session):
2401
 
        "Return the peer's certificate as a bytestring"
2402
 
        try:
2403
 
            cert_type = gnutls.certificate_type_get2(session._c_object,
2404
 
                                                     gnutls.CTYPE_PEERS)
2405
 
        except AttributeError:
2406
 
            cert_type = gnutls.certificate_type_get(session._c_object)
2407
 
        if gnutls.has_rawpk:
2408
 
            valid_cert_types = frozenset((gnutls.CRT_RAWPK,))
2409
 
        else:
2410
 
            valid_cert_types = frozenset((gnutls.CRT_OPENPGP,))
2411
 
        # If not a valid certificate type...
2412
 
        if cert_type not in valid_cert_types:
2413
 
            logger.info("Cert type %r not in %r", cert_type,
2414
 
                        valid_cert_types)
 
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):
2415
2336
            # ...return invalid data
2416
2337
            return b""
2417
2338
        list_size = ctypes.c_uint(1)
2425
2346
        return ctypes.string_at(cert.data, cert.size)
2426
2347
 
2427
2348
    @staticmethod
2428
 
    def key_id(certificate):
2429
 
        "Convert a certificate bytestring to a hexdigit key ID"
2430
 
        # New GnuTLS "datum" with the public key
2431
 
        datum = gnutls.datum_t(
2432
 
            ctypes.cast(ctypes.c_char_p(certificate),
2433
 
                        ctypes.POINTER(ctypes.c_ubyte)),
2434
 
            ctypes.c_uint(len(certificate)))
2435
 
        # XXX all these need to be created in the gnutls "module"
2436
 
        # New empty GnuTLS certificate
2437
 
        pubkey = gnutls.pubkey_t()
2438
 
        gnutls.pubkey_init(ctypes.byref(pubkey))
2439
 
        # Import the raw public key into the certificate
2440
 
        gnutls.pubkey_import(pubkey,
2441
 
                             ctypes.byref(datum),
2442
 
                             gnutls.X509_FMT_DER)
2443
 
        # New buffer for the key ID
2444
 
        buf = ctypes.create_string_buffer(32)
2445
 
        buf_len = ctypes.c_size_t(len(buf))
2446
 
        # Get the key ID from the raw public key into the buffer
2447
 
        gnutls.pubkey_get_key_id(pubkey,
2448
 
                                 gnutls.KEYID_USE_SHA256,
2449
 
                                 ctypes.cast(ctypes.byref(buf),
2450
 
                                             ctypes.POINTER(ctypes.c_ubyte)),
2451
 
                                 ctypes.byref(buf_len))
2452
 
        # Deinit the certificate
2453
 
        gnutls.pubkey_deinit(pubkey)
2454
 
 
2455
 
        # Convert the buffer to a Python bytestring
2456
 
        key_id = ctypes.string_at(buf, buf_len.value)
2457
 
        # Convert the bytestring to hexadecimal notation
2458
 
        hex_key_id = binascii.hexlify(key_id).upper()
2459
 
        return hex_key_id
2460
 
 
2461
 
    @staticmethod
2462
2349
    def fingerprint(openpgp):
2463
2350
        "Convert an OpenPGP bytestring to a hexdigit fingerprint"
2464
2351
        # New GnuTLS "datum" with the OpenPGP public key
2478
2365
                                       ctypes.byref(crtverify))
2479
2366
        if crtverify.value != 0:
2480
2367
            gnutls.openpgp_crt_deinit(crt)
2481
 
            raise gnutls.CertificateSecurityError(code
2482
 
                                                  =crtverify.value)
 
2368
            raise gnutls.CertificateSecurityError("Verify failed")
2483
2369
        # New buffer for the fingerprint
2484
2370
        buf = ctypes.create_string_buffer(20)
2485
2371
        buf_len = ctypes.c_size_t()
2495
2381
        return hex_fpr
2496
2382
 
2497
2383
 
2498
 
class MultiprocessingMixIn:
 
2384
class MultiprocessingMixIn(object):
2499
2385
    """Like socketserver.ThreadingMixIn, but with multiprocessing"""
2500
2386
 
2501
2387
    def sub_process_main(self, request, address):
2513
2399
        return proc
2514
2400
 
2515
2401
 
2516
 
class MultiprocessingMixInWithPipe(MultiprocessingMixIn):
 
2402
class MultiprocessingMixInWithPipe(MultiprocessingMixIn, object):
2517
2403
    """ adds a pipe to the MixIn """
2518
2404
 
2519
2405
    def process_request(self, request, client_address):
2534
2420
 
2535
2421
 
2536
2422
class IPv6_TCPServer(MultiprocessingMixInWithPipe,
2537
 
                     socketserver.TCPServer):
 
2423
                     socketserver.TCPServer, object):
2538
2424
    """IPv6-capable TCP server.  Accepts 'None' as address and/or port
2539
2425
 
2540
2426
    Attributes:
2613
2499
                    raise
2614
2500
        # Only bind(2) the socket if we really need to.
2615
2501
        if self.server_address[0] or self.server_address[1]:
2616
 
            if self.server_address[1]:
2617
 
                self.allow_reuse_address = True
2618
2502
            if not self.server_address[0]:
2619
2503
                if self.address_family == socket.AF_INET6:
2620
2504
                    any_address = "::"  # in6addr_any
2694
2578
        command = request[0]
2695
2579
 
2696
2580
        if command == 'init':
2697
 
            key_id = request[1].decode("ascii")
2698
 
            fpr = request[2].decode("ascii")
2699
 
            address = request[3]
 
2581
            fpr = request[1].decode("ascii")
 
2582
            address = request[2]
2700
2583
 
2701
2584
            for c in self.clients.values():
2702
 
                if key_id == "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855":
2703
 
                    continue
2704
 
                if key_id and c.key_id == key_id:
2705
 
                    client = c
2706
 
                    break
2707
 
                if fpr and c.fingerprint == fpr:
 
2585
                if c.fingerprint == fpr:
2708
2586
                    client = c
2709
2587
                    break
2710
2588
            else:
2711
 
                logger.info("Client not found for key ID: %s, address"
2712
 
                            ": %s", key_id or fpr, address)
 
2589
                logger.info("Client not found for fingerprint: %s, ad"
 
2590
                            "dress: %s", fpr, address)
2713
2591
                if self.use_dbus:
2714
2592
                    # Emit D-Bus signal
2715
 
                    mandos_dbus_service.ClientNotFound(key_id or fpr,
 
2593
                    mandos_dbus_service.ClientNotFound(fpr,
2716
2594
                                                       address[0])
2717
2595
                parent_pipe.send(False)
2718
2596
                return False
2981
2859
        sys.exit(os.EX_OK if fail_count == 0 else 1)
2982
2860
 
2983
2861
    # Default values for config file for server-global settings
2984
 
    if gnutls.has_rawpk:
2985
 
        priority = ("SECURE128:!CTYPE-X.509:+CTYPE-RAWPK:!RSA"
2986
 
                    ":!VERS-ALL:+VERS-TLS1.3:%PROFILE_ULTRA")
2987
 
    else:
2988
 
        priority = ("SECURE256:!CTYPE-X.509:+CTYPE-OPENPGP:!RSA"
2989
 
                    ":+SIGN-DSA-SHA256")
2990
2862
    server_defaults = {"interface": "",
2991
2863
                       "address": "",
2992
2864
                       "port": "",
2993
2865
                       "debug": "False",
2994
 
                       "priority": priority,
 
2866
                       "priority":
 
2867
                       "SECURE256:!CTYPE-X.509:+CTYPE-OPENPGP:!RSA"
 
2868
                       ":+SIGN-DSA-SHA256",
2995
2869
                       "servicename": "Mandos",
2996
2870
                       "use_dbus": "True",
2997
2871
                       "use_ipv6": "True",
3002
2876
                       "foreground": "False",
3003
2877
                       "zeroconf": "True",
3004
2878
                       }
3005
 
    del priority
3006
2879
 
3007
2880
    # Parse config file for server-global settings
3008
 
    server_config = configparser.ConfigParser(server_defaults)
 
2881
    server_config = configparser.SafeConfigParser(server_defaults)
3009
2882
    del server_defaults
3010
2883
    server_config.read(os.path.join(options.configdir, "mandos.conf"))
3011
 
    # Convert the ConfigParser object to a dict
 
2884
    # Convert the SafeConfigParser object to a dict
3012
2885
    server_settings = server_config.defaults()
3013
2886
    # Use the appropriate methods on the non-string config options
3014
2887
    for option in ("debug", "use_dbus", "use_ipv6", "restore",
3086
2959
                                  server_settings["servicename"])))
3087
2960
 
3088
2961
    # Parse config file with clients
3089
 
    client_config = configparser.ConfigParser(Client.client_defaults)
 
2962
    client_config = configparser.SafeConfigParser(Client
 
2963
                                                  .client_defaults)
3090
2964
    client_config.read(os.path.join(server_settings["configdir"],
3091
2965
                                    "clients.conf"))
3092
2966
 
3163
3037
        # Close all input and output, do double fork, etc.
3164
3038
        daemon()
3165
3039
 
3166
 
    if gi.version_info < (3, 10, 2):
3167
 
        # multiprocessing will use threads, so before we use GLib we
3168
 
        # need to inform GLib that threads will be used.
3169
 
        GLib.threads_init()
 
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()
3170
3043
 
3171
3044
    global main_loop
3172
3045
    # From the Avahi example code
3252
3125
                        for k in ("name", "host"):
3253
3126
                            if isinstance(value[k], bytes):
3254
3127
                                value[k] = value[k].decode("utf-8")
3255
 
                        if "key_id" not in value:
3256
 
                            value["key_id"] = ""
3257
 
                        elif "fingerprint" not in value:
3258
 
                            value["fingerprint"] = ""
3259
3128
                    #  old_client_settings
3260
3129
                    # .keys()
3261
3130
                    old_client_settings = {
3398
3267
                pass
3399
3268
 
3400
3269
            @dbus.service.signal(_interface, signature="ss")
3401
 
            def ClientNotFound(self, key_id, address):
 
3270
            def ClientNotFound(self, fingerprint, address):
3402
3271
                "D-Bus signal"
3403
3272
                pass
3404
3273