/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-04-09 20:37:18 UTC
  • mfrom: (237.4.114 release)
  • Revision ID: teddy@recompile.se-20190409203718-2h1z7km2g9kozxaw
Merge from release branch

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
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.8.4"
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:
 
278
class avahi(object):
286
279
    """This isn't so much a class as it is a module-like namespace."""
287
280
    IF_UNSPEC = -1               # avahi-common/address.h
288
281
    PROTO_UNSPEC = -1            # avahi-common/address.h
322
315
    pass
323
316
 
324
317
 
325
 
class AvahiService:
 
318
class AvahiService(object):
326
319
    """An Avahi (Zeroconf) service.
327
320
 
328
321
    Attributes:
510
503
 
511
504
 
512
505
# Pretend that we have a GnuTLS module
513
 
class gnutls:
 
506
class gnutls(object):
514
507
    """This isn't so much a class as it is a module-like namespace."""
515
508
 
516
509
    library = ctypes.util.find_library("gnutls")
579
572
        pass
580
573
 
581
574
    # Classes
582
 
    class Credentials:
 
575
    class Credentials(object):
583
576
        def __init__(self):
584
577
            self._c_object = gnutls.certificate_credentials_t()
585
578
            gnutls.certificate_allocate_credentials(
589
582
        def __del__(self):
590
583
            gnutls.certificate_free_credentials(self._c_object)
591
584
 
592
 
    class ClientSession:
 
585
    class ClientSession(object):
593
586
        def __init__(self, socket, credentials=None):
594
587
            self._c_object = gnutls.session_t()
595
588
            gnutls_flags = gnutls.CLIENT
596
 
            if gnutls.check_version(b"3.5.6"):
 
589
            if gnutls.check_version("3.5.6"):
597
590
                gnutls_flags |= gnutls.NO_TICKETS
598
591
            if gnutls.has_rawpk:
599
592
                gnutls_flags |= gnutls.ENABLE_RAWPK
801
794
                                                    ctypes.c_size_t)]
802
795
        openpgp_crt_get_fingerprint.restype = _error_code
803
796
 
804
 
    if check_version(b"3.6.4"):
 
797
    if check_version("3.6.4"):
805
798
        certificate_type_get2 = _library.gnutls_certificate_type_get2
806
799
        certificate_type_get2.argtypes = [session_t, ctypes.c_int]
807
800
        certificate_type_get2.restype = _error_code
821
814
    connection.close()
822
815
 
823
816
 
824
 
class Client:
 
817
class Client(object):
825
818
    """A representation of a client host served by this server.
826
819
 
827
820
    Attributes:
828
821
    approved:   bool(); 'None' if not yet approved/disapproved
829
822
    approval_delay: datetime.timedelta(); Time to wait for approval
830
823
    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.
 
824
    checker:    subprocess.Popen(); a running checker process used
 
825
                                    to see if the client lives.
 
826
                                    'None' if no process is running.
834
827
    checker_callback_tag: a GLib event source tag, or None
835
828
    checker_command: string; External command which is run to check
836
829
                     if client lives.  %() expansions are done at
1043
1036
    def checker_callback(self, source, condition, connection,
1044
1037
                         command):
1045
1038
        """The checker has completed, so take appropriate actions."""
 
1039
        self.checker_callback_tag = None
 
1040
        self.checker = None
1046
1041
        # Read return code from connection (see call_pipe)
1047
1042
        returncode = connection.recv()
1048
1043
        connection.close()
1049
 
        self.checker.join()
1050
 
        self.checker_callback_tag = None
1051
 
        self.checker = None
1052
1044
 
1053
1045
        if returncode >= 0:
1054
1046
            self.last_checker_status = returncode
2216
2208
    del _interface
2217
2209
 
2218
2210
 
2219
 
class ProxyClient:
 
2211
class ProxyClient(object):
2220
2212
    def __init__(self, child_pipe, key_id, fpr, address):
2221
2213
        self._pipe = child_pipe
2222
2214
        self._pipe.send(('init', key_id, fpr, address))
2295
2287
            approval_required = False
2296
2288
            try:
2297
2289
                if gnutls.has_rawpk:
2298
 
                    fpr = b""
 
2290
                    fpr = ""
2299
2291
                    try:
2300
2292
                        key_id = self.key_id(
2301
2293
                            self.peer_certificate(session))
2305
2297
                    logger.debug("Key ID: %s", key_id)
2306
2298
 
2307
2299
                else:
2308
 
                    key_id = b""
 
2300
                    key_id = ""
2309
2301
                    try:
2310
2302
                        fpr = self.fingerprint(
2311
2303
                            self.peer_certificate(session))
2495
2487
        return hex_fpr
2496
2488
 
2497
2489
 
2498
 
class MultiprocessingMixIn:
 
2490
class MultiprocessingMixIn(object):
2499
2491
    """Like socketserver.ThreadingMixIn, but with multiprocessing"""
2500
2492
 
2501
2493
    def sub_process_main(self, request, address):
2513
2505
        return proc
2514
2506
 
2515
2507
 
2516
 
class MultiprocessingMixInWithPipe(MultiprocessingMixIn):
 
2508
class MultiprocessingMixInWithPipe(MultiprocessingMixIn, object):
2517
2509
    """ adds a pipe to the MixIn """
2518
2510
 
2519
2511
    def process_request(self, request, client_address):
2534
2526
 
2535
2527
 
2536
2528
class IPv6_TCPServer(MultiprocessingMixInWithPipe,
2537
 
                     socketserver.TCPServer):
 
2529
                     socketserver.TCPServer, object):
2538
2530
    """IPv6-capable TCP server.  Accepts 'None' as address and/or port
2539
2531
 
2540
2532
    Attributes:
2613
2605
                    raise
2614
2606
        # Only bind(2) the socket if we really need to.
2615
2607
        if self.server_address[0] or self.server_address[1]:
2616
 
            if self.server_address[1]:
2617
 
                self.allow_reuse_address = True
2618
2608
            if not self.server_address[0]:
2619
2609
                if self.address_family == socket.AF_INET6:
2620
2610
                    any_address = "::"  # in6addr_any
3005
2995
    del priority
3006
2996
 
3007
2997
    # Parse config file for server-global settings
3008
 
    server_config = configparser.ConfigParser(server_defaults)
 
2998
    server_config = configparser.SafeConfigParser(server_defaults)
3009
2999
    del server_defaults
3010
3000
    server_config.read(os.path.join(options.configdir, "mandos.conf"))
3011
 
    # Convert the ConfigParser object to a dict
 
3001
    # Convert the SafeConfigParser object to a dict
3012
3002
    server_settings = server_config.defaults()
3013
3003
    # Use the appropriate methods on the non-string config options
3014
3004
    for option in ("debug", "use_dbus", "use_ipv6", "restore",
3086
3076
                                  server_settings["servicename"])))
3087
3077
 
3088
3078
    # Parse config file with clients
3089
 
    client_config = configparser.ConfigParser(Client.client_defaults)
 
3079
    client_config = configparser.SafeConfigParser(Client
 
3080
                                                  .client_defaults)
3090
3081
    client_config.read(os.path.join(server_settings["configdir"],
3091
3082
                                    "clients.conf"))
3092
3083
 
3163
3154
        # Close all input and output, do double fork, etc.
3164
3155
        daemon()
3165
3156
 
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()
 
3157
    # multiprocessing will use threads, so before we use GLib we need
 
3158
    # to inform GLib that threads will be used.
 
3159
    GLib.threads_init()
3170
3160
 
3171
3161
    global main_loop
3172
3162
    # From the Avahi example code
3252
3242
                        for k in ("name", "host"):
3253
3243
                            if isinstance(value[k], bytes):
3254
3244
                                value[k] = value[k].decode("utf-8")
3255
 
                        if "key_id" not in value:
 
3245
                        if not value.has_key("key_id"):
3256
3246
                            value["key_id"] = ""
3257
 
                        elif "fingerprint" not in value:
 
3247
                        elif not value.has_key("fingerprint"):
3258
3248
                            value["fingerprint"] = ""
3259
3249
                    #  old_client_settings
3260
3250
                    # .keys()