/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:
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.20"
 
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
 
    _tls_rawpk_version = b"3.6.6"
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
518
 
526
519
    # Unless otherwise indicated, the constants and types below are
527
520
    # all from the gnutls/gnutls.h C header file.
569
562
 
570
563
    # Exceptions
571
564
    class Error(Exception):
572
 
        # We need to use the class name "GnuTLS" here, since this
573
 
        # exception might be raised from within GnuTLS.__init__,
574
 
        # which is called before the assignment to the "gnutls"
575
 
        # global variable has happened.
576
565
        def __init__(self, message=None, code=None, args=()):
577
566
            # Default usage is by a message string, but if a return
578
567
            # code is passed, convert it to a string with
579
568
            # gnutls.strerror()
580
569
            self.code = code
581
570
            if message is None and code is not None:
582
 
                message = GnuTLS.strerror(code)
583
 
            return super(GnuTLS.Error, self).__init__(
 
571
                message = gnutls.strerror(code)
 
572
            return super(gnutls.Error, self).__init__(
584
573
                message, *args)
585
574
 
586
575
    class CertificateSecurityError(Error):
601
590
        def __init__(self, socket, credentials=None):
602
591
            self._c_object = gnutls.session_t()
603
592
            gnutls_flags = gnutls.CLIENT
604
 
            if gnutls.check_version("3.5.6"):
 
593
            if gnutls.check_version(b"3.5.6"):
605
594
                gnutls_flags |= gnutls.NO_TICKETS
606
595
            if gnutls.has_rawpk:
607
596
                gnutls_flags |= gnutls.ENABLE_RAWPK
744
733
    check_version.argtypes = [ctypes.c_char_p]
745
734
    check_version.restype = ctypes.c_char_p
746
735
 
 
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"
747
742
    has_rawpk = bool(check_version(_tls_rawpk_version))
748
743
 
749
744
    if has_rawpk:
803
798
                                                    ctypes.c_size_t)]
804
799
        openpgp_crt_get_fingerprint.restype = _error_code
805
800
 
806
 
    if check_version("3.6.4"):
 
801
    if check_version(b"3.6.4"):
807
802
        certificate_type_get2 = _library.gnutls_certificate_type_get2
808
803
        certificate_type_get2.argtypes = [session_t, ctypes.c_int]
809
804
        certificate_type_get2.restype = _error_code
810
805
 
811
806
    # Remove non-public functions
812
807
    del _error_code, _retry_on_error
813
 
# Create the global "gnutls" object, simulating a module
814
 
gnutls = GnuTLS()
815
808
 
816
809
 
817
810
def call_pipe(connection,       # : multiprocessing.Connection
832
825
    approved:   bool(); 'None' if not yet approved/disapproved
833
826
    approval_delay: datetime.timedelta(); Time to wait for approval
834
827
    approval_duration: datetime.timedelta(); Duration of one approval
835
 
    checker:    subprocess.Popen(); a running checker process used
836
 
                                    to see if the client lives.
837
 
                                    '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.
838
831
    checker_callback_tag: a GLib event source tag, or None
839
832
    checker_command: string; External command which is run to check
840
833
                     if client lives.  %() expansions are done at
1047
1040
    def checker_callback(self, source, condition, connection,
1048
1041
                         command):
1049
1042
        """The checker has completed, so take appropriate actions."""
1050
 
        self.checker_callback_tag = None
1051
 
        self.checker = None
1052
1043
        # Read return code from connection (see call_pipe)
1053
1044
        returncode = connection.recv()
1054
1045
        connection.close()
 
1046
        self.checker.join()
 
1047
        self.checker_callback_tag = None
 
1048
        self.checker = None
1055
1049
 
1056
1050
        if returncode >= 0:
1057
1051
            self.last_checker_status = returncode
2298
2292
            approval_required = False
2299
2293
            try:
2300
2294
                if gnutls.has_rawpk:
2301
 
                    fpr = ""
 
2295
                    fpr = b""
2302
2296
                    try:
2303
2297
                        key_id = self.key_id(
2304
2298
                            self.peer_certificate(session))
2308
2302
                    logger.debug("Key ID: %s", key_id)
2309
2303
 
2310
2304
                else:
2311
 
                    key_id = ""
 
2305
                    key_id = b""
2312
2306
                    try:
2313
2307
                        fpr = self.fingerprint(
2314
2308
                            self.peer_certificate(session))
2616
2610
                    raise
2617
2611
        # Only bind(2) the socket if we really need to.
2618
2612
        if self.server_address[0] or self.server_address[1]:
 
2613
            if self.server_address[1]:
 
2614
                self.allow_reuse_address = True
2619
2615
            if not self.server_address[0]:
2620
2616
                if self.address_family == socket.AF_INET6:
2621
2617
                    any_address = "::"  # in6addr_any
2700
2696
            address = request[3]
2701
2697
 
2702
2698
            for c in self.clients.values():
 
2699
                if key_id == "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855":
 
2700
                    continue
2703
2701
                if key_id and c.key_id == key_id:
2704
2702
                    client = c
2705
2703
                    break
3004
3002
    del priority
3005
3003
 
3006
3004
    # Parse config file for server-global settings
3007
 
    server_config = configparser.SafeConfigParser(server_defaults)
 
3005
    server_config = configparser.ConfigParser(server_defaults)
3008
3006
    del server_defaults
3009
3007
    server_config.read(os.path.join(options.configdir, "mandos.conf"))
3010
 
    # Convert the SafeConfigParser object to a dict
 
3008
    # Convert the ConfigParser object to a dict
3011
3009
    server_settings = server_config.defaults()
3012
3010
    # Use the appropriate methods on the non-string config options
3013
3011
    for option in ("debug", "use_dbus", "use_ipv6", "restore",
3085
3083
                                  server_settings["servicename"])))
3086
3084
 
3087
3085
    # Parse config file with clients
3088
 
    client_config = configparser.SafeConfigParser(Client
3089
 
                                                  .client_defaults)
 
3086
    client_config = configparser.ConfigParser(Client.client_defaults)
3090
3087
    client_config.read(os.path.join(server_settings["configdir"],
3091
3088
                                    "clients.conf"))
3092
3089
 
3163
3160
        # Close all input and output, do double fork, etc.
3164
3161
        daemon()
3165
3162
 
3166
 
    # multiprocessing will use threads, so before we use GLib we need
3167
 
    # to inform GLib that threads will be used.
3168
 
    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()
3169
3167
 
3170
3168
    global main_loop
3171
3169
    # From the Avahi example code
3251
3249
                        for k in ("name", "host"):
3252
3250
                            if isinstance(value[k], bytes):
3253
3251
                                value[k] = value[k].decode("utf-8")
3254
 
                        if not value.has_key("key_id"):
 
3252
                        if "key_id" not in value:
3255
3253
                            value["key_id"] = ""
3256
 
                        elif not value.has_key("fingerprint"):
 
3254
                        elif "fingerprint" not in value:
3257
3255
                            value["fingerprint"] = ""
3258
3256
                    #  old_client_settings
3259
3257
                    # .keys()