/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: 2015-10-04 13:44:03 UTC
  • Revision ID: teddy@recompile.se-20151004134403-jn72bwgbw3aocllk
* initramfs-tools-hook: Don't try to chmod symlinks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/python
 
1
#!/usr/bin/python2.7
2
2
# -*- mode: python; coding: utf-8 -*-
3
3
4
4
# Mandos server - give out binary blobs to connecting clients.
11
11
# "AvahiService" class, and some lines in "main".
12
12
13
13
# Everything else is
14
 
# Copyright © 2008-2016 Teddy Hogeborn
15
 
# Copyright © 2008-2016 Björn Påhlsson
 
14
# Copyright © 2008-2015 Teddy Hogeborn
 
15
# Copyright © 2008-2015 Björn Påhlsson
16
16
17
17
# This program is free software: you can redistribute it and/or modify
18
18
# it under the terms of the GNU General Public License as published by
44
44
import argparse
45
45
import datetime
46
46
import errno
 
47
import gnutls.crypto
 
48
import gnutls.connection
 
49
import gnutls.errors
 
50
import gnutls.library.functions
 
51
import gnutls.library.constants
 
52
import gnutls.library.types
47
53
try:
48
54
    import ConfigParser as configparser
49
55
except ImportError:
77
83
import dbus
78
84
import dbus.service
79
85
try:
80
 
    from gi.repository import GObject
 
86
    import gobject
81
87
except ImportError:
82
 
    import gobject as GObject
 
88
    from gi.repository import GObject as gobject
83
89
import avahi
84
90
from dbus.mainloop.glib import DBusGMainLoop
85
91
import ctypes
98
104
if sys.version_info.major == 2:
99
105
    str = unicode
100
106
 
101
 
version = "1.7.3"
 
107
version = "1.7.0"
102
108
stored_state_file = "clients.pickle"
103
109
 
104
110
logger = logging.getLogger()
151
157
    
152
158
    def __init__(self):
153
159
        self.tempdir = tempfile.mkdtemp(prefix="mandos-")
154
 
        self.gpg = "gpg"
155
 
        try:
156
 
            output = subprocess.check_output(["gpgconf"])
157
 
            for line in output.splitlines():
158
 
                name, text, path = line.split(":")
159
 
                if name == "gpg":
160
 
                    self.gpg = path
161
 
                    break
162
 
        except OSError as e:
163
 
            if e.errno != errno.ENOENT:
164
 
                raise
165
160
        self.gnupgargs = ['--batch',
166
 
                          '--homedir', self.tempdir,
 
161
                          '--home', self.tempdir,
167
162
                          '--force-mdc',
168
163
                          '--quiet',
169
164
                          '--no-use-agent']
208
203
                dir=self.tempdir) as passfile:
209
204
            passfile.write(passphrase)
210
205
            passfile.flush()
211
 
            proc = subprocess.Popen([self.gpg, '--symmetric',
 
206
            proc = subprocess.Popen(['gpg', '--symmetric',
212
207
                                     '--passphrase-file',
213
208
                                     passfile.name]
214
209
                                    + self.gnupgargs,
226
221
                dir = self.tempdir) as passfile:
227
222
            passfile.write(passphrase)
228
223
            passfile.flush()
229
 
            proc = subprocess.Popen([self.gpg, '--decrypt',
 
224
            proc = subprocess.Popen(['gpg', '--decrypt',
230
225
                                     '--passphrase-file',
231
226
                                     passfile.name]
232
227
                                    + self.gnupgargs,
440
435
            .format(self.name)))
441
436
        return ret
442
437
 
443
 
# Pretend that we have a GnuTLS module
444
 
class GnuTLS(object):
445
 
    """This isn't so much a class as it is a module-like namespace.
446
 
    It is instantiated once, and simulates having a GnuTLS module."""
447
 
    
448
 
    _library = ctypes.cdll.LoadLibrary(
449
 
        ctypes.util.find_library("gnutls"))
450
 
    _need_version = "3.3.0"
451
 
    def __init__(self):
452
 
        # Need to use class name "GnuTLS" here, since this method is
453
 
        # called before the assignment to the "gnutls" global variable
454
 
        # happens.
455
 
        if GnuTLS.check_version(self._need_version) is None:
456
 
            raise GnuTLS.Error("Needs GnuTLS {} or later"
457
 
                               .format(self._need_version))
458
 
    
459
 
    # Unless otherwise indicated, the constants and types below are
460
 
    # all from the gnutls/gnutls.h C header file.
461
 
    
462
 
    # Constants
463
 
    E_SUCCESS = 0
464
 
    E_INTERRUPTED = -52
465
 
    E_AGAIN = -28
466
 
    CRT_OPENPGP = 2
467
 
    CLIENT = 2
468
 
    SHUT_RDWR = 0
469
 
    CRD_CERTIFICATE = 1
470
 
    E_NO_CERTIFICATE_FOUND = -49
471
 
    OPENPGP_FMT_RAW = 0         # gnutls/openpgp.h
472
 
    
473
 
    # Types
474
 
    class session_int(ctypes.Structure):
475
 
        _fields_ = []
476
 
    session_t = ctypes.POINTER(session_int)
477
 
    class certificate_credentials_st(ctypes.Structure):
478
 
        _fields_ = []
479
 
    certificate_credentials_t = ctypes.POINTER(
480
 
        certificate_credentials_st)
481
 
    certificate_type_t = ctypes.c_int
482
 
    class datum_t(ctypes.Structure):
483
 
        _fields_ = [('data', ctypes.POINTER(ctypes.c_ubyte)),
484
 
                    ('size', ctypes.c_uint)]
485
 
    class openpgp_crt_int(ctypes.Structure):
486
 
        _fields_ = []
487
 
    openpgp_crt_t = ctypes.POINTER(openpgp_crt_int)
488
 
    openpgp_crt_fmt_t = ctypes.c_int # gnutls/openpgp.h
489
 
    log_func = ctypes.CFUNCTYPE(None, ctypes.c_int, ctypes.c_char_p)
490
 
    credentials_type_t = ctypes.c_int # 
491
 
    transport_ptr_t = ctypes.c_void_p
492
 
    close_request_t = ctypes.c_int
493
 
    
494
 
    # Exceptions
495
 
    class Error(Exception):
496
 
        # We need to use the class name "GnuTLS" here, since this
497
 
        # exception might be raised from within GnuTLS.__init__,
498
 
        # which is called before the assignment to the "gnutls"
499
 
        # global variable has happened.
500
 
        def __init__(self, message = None, code = None, args=()):
501
 
            # Default usage is by a message string, but if a return
502
 
            # code is passed, convert it to a string with
503
 
            # gnutls.strerror()
504
 
            self.code = code
505
 
            if message is None and code is not None:
506
 
                message = GnuTLS.strerror(code)
507
 
            return super(GnuTLS.Error, self).__init__(
508
 
                message, *args)
509
 
    
510
 
    class CertificateSecurityError(Error):
511
 
        pass
512
 
    
513
 
    # Classes
514
 
    class Credentials(object):
515
 
        def __init__(self):
516
 
            self._c_object = gnutls.certificate_credentials_t()
517
 
            gnutls.certificate_allocate_credentials(
518
 
                ctypes.byref(self._c_object))
519
 
            self.type = gnutls.CRD_CERTIFICATE
520
 
        
521
 
        def __del__(self):
522
 
            gnutls.certificate_free_credentials(self._c_object)
523
 
    
524
 
    class ClientSession(object):
525
 
        def __init__(self, socket, credentials = None):
526
 
            self._c_object = gnutls.session_t()
527
 
            gnutls.init(ctypes.byref(self._c_object), gnutls.CLIENT)
528
 
            gnutls.set_default_priority(self._c_object)
529
 
            gnutls.transport_set_ptr(self._c_object, socket.fileno())
530
 
            gnutls.handshake_set_private_extensions(self._c_object,
531
 
                                                    True)
532
 
            self.socket = socket
533
 
            if credentials is None:
534
 
                credentials = gnutls.Credentials()
535
 
            gnutls.credentials_set(self._c_object, credentials.type,
536
 
                                   ctypes.cast(credentials._c_object,
537
 
                                               ctypes.c_void_p))
538
 
            self.credentials = credentials
539
 
        
540
 
        def __del__(self):
541
 
            gnutls.deinit(self._c_object)
542
 
        
543
 
        def handshake(self):
544
 
            return gnutls.handshake(self._c_object)
545
 
        
546
 
        def send(self, data):
547
 
            data = bytes(data)
548
 
            data_len = len(data)
549
 
            while data_len > 0:
550
 
                data_len -= gnutls.record_send(self._c_object,
551
 
                                               data[-data_len:],
552
 
                                               data_len)
553
 
        
554
 
        def bye(self):
555
 
            return gnutls.bye(self._c_object, gnutls.SHUT_RDWR)
556
 
    
557
 
    # Error handling functions
558
 
    def _error_code(result):
559
 
        """A function to raise exceptions on errors, suitable
560
 
        for the 'restype' attribute on ctypes functions"""
561
 
        if result >= 0:
562
 
            return result
563
 
        if result == gnutls.E_NO_CERTIFICATE_FOUND:
564
 
            raise gnutls.CertificateSecurityError(code = result)
565
 
        raise gnutls.Error(code = result)
566
 
    
567
 
    def _retry_on_error(result, func, arguments):
568
 
        """A function to retry on some errors, suitable
569
 
        for the 'errcheck' attribute on ctypes functions"""
570
 
        while result < 0:
571
 
            if result not in (gnutls.E_INTERRUPTED, gnutls.E_AGAIN):
572
 
                return _error_code(result)
573
 
            result = func(*arguments)
574
 
        return result
575
 
    
576
 
    # Unless otherwise indicated, the function declarations below are
577
 
    # all from the gnutls/gnutls.h C header file.
578
 
    
579
 
    # Functions
580
 
    priority_set_direct = _library.gnutls_priority_set_direct
581
 
    priority_set_direct.argtypes = [session_t, ctypes.c_char_p,
582
 
                                    ctypes.POINTER(ctypes.c_char_p)]
583
 
    priority_set_direct.restype = _error_code
584
 
    
585
 
    init = _library.gnutls_init
586
 
    init.argtypes = [ctypes.POINTER(session_t), ctypes.c_int]
587
 
    init.restype = _error_code
588
 
    
589
 
    set_default_priority = _library.gnutls_set_default_priority
590
 
    set_default_priority.argtypes = [session_t]
591
 
    set_default_priority.restype = _error_code
592
 
    
593
 
    record_send = _library.gnutls_record_send
594
 
    record_send.argtypes = [session_t, ctypes.c_void_p,
595
 
                            ctypes.c_size_t]
596
 
    record_send.restype = ctypes.c_ssize_t
597
 
    record_send.errcheck = _retry_on_error
598
 
    
599
 
    certificate_allocate_credentials = (
600
 
        _library.gnutls_certificate_allocate_credentials)
601
 
    certificate_allocate_credentials.argtypes = [
602
 
        ctypes.POINTER(certificate_credentials_t)]
603
 
    certificate_allocate_credentials.restype = _error_code
604
 
    
605
 
    certificate_free_credentials = (
606
 
        _library.gnutls_certificate_free_credentials)
607
 
    certificate_free_credentials.argtypes = [certificate_credentials_t]
608
 
    certificate_free_credentials.restype = None
609
 
    
610
 
    handshake_set_private_extensions = (
611
 
        _library.gnutls_handshake_set_private_extensions)
612
 
    handshake_set_private_extensions.argtypes = [session_t,
613
 
                                                 ctypes.c_int]
614
 
    handshake_set_private_extensions.restype = None
615
 
    
616
 
    credentials_set = _library.gnutls_credentials_set
617
 
    credentials_set.argtypes = [session_t, credentials_type_t,
618
 
                                ctypes.c_void_p]
619
 
    credentials_set.restype = _error_code
620
 
    
621
 
    strerror = _library.gnutls_strerror
622
 
    strerror.argtypes = [ctypes.c_int]
623
 
    strerror.restype = ctypes.c_char_p
624
 
    
625
 
    certificate_type_get = _library.gnutls_certificate_type_get
626
 
    certificate_type_get.argtypes = [session_t]
627
 
    certificate_type_get.restype = _error_code
628
 
    
629
 
    certificate_get_peers = _library.gnutls_certificate_get_peers
630
 
    certificate_get_peers.argtypes = [session_t,
631
 
                                      ctypes.POINTER(ctypes.c_uint)]
632
 
    certificate_get_peers.restype = ctypes.POINTER(datum_t)
633
 
    
634
 
    global_set_log_level = _library.gnutls_global_set_log_level
635
 
    global_set_log_level.argtypes = [ctypes.c_int]
636
 
    global_set_log_level.restype = None
637
 
    
638
 
    global_set_log_function = _library.gnutls_global_set_log_function
639
 
    global_set_log_function.argtypes = [log_func]
640
 
    global_set_log_function.restype = None
641
 
    
642
 
    deinit = _library.gnutls_deinit
643
 
    deinit.argtypes = [session_t]
644
 
    deinit.restype = None
645
 
    
646
 
    handshake = _library.gnutls_handshake
647
 
    handshake.argtypes = [session_t]
648
 
    handshake.restype = _error_code
649
 
    handshake.errcheck = _retry_on_error
650
 
    
651
 
    transport_set_ptr = _library.gnutls_transport_set_ptr
652
 
    transport_set_ptr.argtypes = [session_t, transport_ptr_t]
653
 
    transport_set_ptr.restype = None
654
 
    
655
 
    bye = _library.gnutls_bye
656
 
    bye.argtypes = [session_t, close_request_t]
657
 
    bye.restype = _error_code
658
 
    bye.errcheck = _retry_on_error
659
 
    
660
 
    check_version = _library.gnutls_check_version
661
 
    check_version.argtypes = [ctypes.c_char_p]
662
 
    check_version.restype = ctypes.c_char_p
663
 
    
664
 
    # All the function declarations below are from gnutls/openpgp.h
665
 
    
666
 
    openpgp_crt_init = _library.gnutls_openpgp_crt_init
667
 
    openpgp_crt_init.argtypes = [ctypes.POINTER(openpgp_crt_t)]
668
 
    openpgp_crt_init.restype = _error_code
669
 
    
670
 
    openpgp_crt_import = _library.gnutls_openpgp_crt_import
671
 
    openpgp_crt_import.argtypes = [openpgp_crt_t,
672
 
                                   ctypes.POINTER(datum_t),
673
 
                                   openpgp_crt_fmt_t]
674
 
    openpgp_crt_import.restype = _error_code
675
 
    
676
 
    openpgp_crt_verify_self = _library.gnutls_openpgp_crt_verify_self
677
 
    openpgp_crt_verify_self.argtypes = [openpgp_crt_t, ctypes.c_uint,
678
 
                                        ctypes.POINTER(ctypes.c_uint)]
679
 
    openpgp_crt_verify_self.restype = _error_code
680
 
    
681
 
    openpgp_crt_deinit = _library.gnutls_openpgp_crt_deinit
682
 
    openpgp_crt_deinit.argtypes = [openpgp_crt_t]
683
 
    openpgp_crt_deinit.restype = None
684
 
    
685
 
    openpgp_crt_get_fingerprint = (
686
 
        _library.gnutls_openpgp_crt_get_fingerprint)
687
 
    openpgp_crt_get_fingerprint.argtypes = [openpgp_crt_t,
688
 
                                            ctypes.c_void_p,
689
 
                                            ctypes.POINTER(
690
 
                                                ctypes.c_size_t)]
691
 
    openpgp_crt_get_fingerprint.restype = _error_code
692
 
    
693
 
    # Remove non-public functions
694
 
    del _error_code, _retry_on_error
695
 
# Create the global "gnutls" object, simulating a module
696
 
gnutls = GnuTLS()
697
 
 
698
438
def call_pipe(connection,       # : multiprocessing.Connection
699
439
              func, *args, **kwargs):
700
440
    """This function is meant to be called by multiprocessing.Process
715
455
    checker:    subprocess.Popen(); a running checker process used
716
456
                                    to see if the client lives.
717
457
                                    'None' if no process is running.
718
 
    checker_callback_tag: a GObject event source tag, or None
 
458
    checker_callback_tag: a gobject event source tag, or None
719
459
    checker_command: string; External command which is run to check
720
460
                     if client lives.  %() expansions are done at
721
461
                     runtime with vars(self) as dict, so that for
722
462
                     instance %(name)s can be used in the command.
723
 
    checker_initiator_tag: a GObject event source tag, or None
 
463
    checker_initiator_tag: a gobject event source tag, or None
724
464
    created:    datetime.datetime(); (UTC) object creation
725
465
    client_structure: Object describing what attributes a client has
726
466
                      and is used for storing the client at exit
727
467
    current_checker_command: string; current running checker_command
728
 
    disable_initiator_tag: a GObject event source tag, or None
 
468
    disable_initiator_tag: a gobject event source tag, or None
729
469
    enabled:    bool()
730
470
    fingerprint: string (40 or 32 hexadecimal digits); used to
731
471
                 uniquely identify the client
885
625
        if not quiet:
886
626
            logger.info("Disabling client %s", self.name)
887
627
        if getattr(self, "disable_initiator_tag", None) is not None:
888
 
            GObject.source_remove(self.disable_initiator_tag)
 
628
            gobject.source_remove(self.disable_initiator_tag)
889
629
            self.disable_initiator_tag = None
890
630
        self.expires = None
891
631
        if getattr(self, "checker_initiator_tag", None) is not None:
892
 
            GObject.source_remove(self.checker_initiator_tag)
 
632
            gobject.source_remove(self.checker_initiator_tag)
893
633
            self.checker_initiator_tag = None
894
634
        self.stop_checker()
895
635
        self.enabled = False
896
636
        if not quiet:
897
637
            self.send_changedstate()
898
 
        # Do not run this again if called by a GObject.timeout_add
 
638
        # Do not run this again if called by a gobject.timeout_add
899
639
        return False
900
640
    
901
641
    def __del__(self):
905
645
        # Schedule a new checker to be started an 'interval' from now,
906
646
        # and every interval from then on.
907
647
        if self.checker_initiator_tag is not None:
908
 
            GObject.source_remove(self.checker_initiator_tag)
909
 
        self.checker_initiator_tag = GObject.timeout_add(
 
648
            gobject.source_remove(self.checker_initiator_tag)
 
649
        self.checker_initiator_tag = gobject.timeout_add(
910
650
            int(self.interval.total_seconds() * 1000),
911
651
            self.start_checker)
912
652
        # Schedule a disable() when 'timeout' has passed
913
653
        if self.disable_initiator_tag is not None:
914
 
            GObject.source_remove(self.disable_initiator_tag)
915
 
        self.disable_initiator_tag = GObject.timeout_add(
 
654
            gobject.source_remove(self.disable_initiator_tag)
 
655
        self.disable_initiator_tag = gobject.timeout_add(
916
656
            int(self.timeout.total_seconds() * 1000), self.disable)
917
657
        # Also start a new checker *right now*.
918
658
        self.start_checker()
954
694
        if timeout is None:
955
695
            timeout = self.timeout
956
696
        if self.disable_initiator_tag is not None:
957
 
            GObject.source_remove(self.disable_initiator_tag)
 
697
            gobject.source_remove(self.disable_initiator_tag)
958
698
            self.disable_initiator_tag = None
959
699
        if getattr(self, "enabled", False):
960
 
            self.disable_initiator_tag = GObject.timeout_add(
 
700
            self.disable_initiator_tag = gobject.timeout_add(
961
701
                int(timeout.total_seconds() * 1000), self.disable)
962
702
            self.expires = datetime.datetime.utcnow() + timeout
963
703
    
1018
758
                args = (pipe[1], subprocess.call, command),
1019
759
                kwargs = popen_args)
1020
760
            self.checker.start()
1021
 
            self.checker_callback_tag = GObject.io_add_watch(
1022
 
                pipe[0].fileno(), GObject.IO_IN,
 
761
            self.checker_callback_tag = gobject.io_add_watch(
 
762
                pipe[0].fileno(), gobject.IO_IN,
1023
763
                self.checker_callback, pipe[0], command)
1024
 
        # Re-run this periodically if run by GObject.timeout_add
 
764
        # Re-run this periodically if run by gobject.timeout_add
1025
765
        return True
1026
766
    
1027
767
    def stop_checker(self):
1028
768
        """Force the checker process, if any, to stop."""
1029
769
        if self.checker_callback_tag:
1030
 
            GObject.source_remove(self.checker_callback_tag)
 
770
            gobject.source_remove(self.checker_callback_tag)
1031
771
            self.checker_callback_tag = None
1032
772
        if getattr(self, "checker", None) is None:
1033
773
            return
1807
1547
    
1808
1548
    def approve(self, value=True):
1809
1549
        self.approved = value
1810
 
        GObject.timeout_add(int(self.approval_duration.total_seconds()
 
1550
        gobject.timeout_add(int(self.approval_duration.total_seconds()
1811
1551
                                * 1000), self._reset_approved)
1812
1552
        self.send_changedstate()
1813
1553
    
2024
1764
                if (getattr(self, "disable_initiator_tag", None)
2025
1765
                    is None):
2026
1766
                    return
2027
 
                GObject.source_remove(self.disable_initiator_tag)
2028
 
                self.disable_initiator_tag = GObject.timeout_add(
 
1767
                gobject.source_remove(self.disable_initiator_tag)
 
1768
                self.disable_initiator_tag = gobject.timeout_add(
2029
1769
                    int((self.expires - now).total_seconds() * 1000),
2030
1770
                    self.disable)
2031
1771
    
2051
1791
            return
2052
1792
        if self.enabled:
2053
1793
            # Reschedule checker run
2054
 
            GObject.source_remove(self.checker_initiator_tag)
2055
 
            self.checker_initiator_tag = GObject.timeout_add(
 
1794
            gobject.source_remove(self.checker_initiator_tag)
 
1795
            self.checker_initiator_tag = gobject.timeout_add(
2056
1796
                value, self.start_checker)
2057
1797
            self.start_checker() # Start one now, too
2058
1798
    
2140
1880
            logger.debug("Pipe FD: %d",
2141
1881
                         self.server.child_pipe.fileno())
2142
1882
            
2143
 
            session = gnutls.ClientSession(self.request)
 
1883
            session = gnutls.connection.ClientSession(
 
1884
                self.request, gnutls.connection .X509Credentials())
 
1885
            
 
1886
            # Note: gnutls.connection.X509Credentials is really a
 
1887
            # generic GnuTLS certificate credentials object so long as
 
1888
            # no X.509 keys are added to it.  Therefore, we can use it
 
1889
            # here despite using OpenPGP certificates.
2144
1890
            
2145
1891
            #priority = ':'.join(("NONE", "+VERS-TLS1.1",
2146
1892
            #                      "+AES-256-CBC", "+SHA1",
2150
1896
            priority = self.server.gnutls_priority
2151
1897
            if priority is None:
2152
1898
                priority = "NORMAL"
2153
 
            gnutls.priority_set_direct(session._c_object, priority,
2154
 
                                       None)
 
1899
            gnutls.library.functions.gnutls_priority_set_direct(
 
1900
                session._c_object, priority, None)
2155
1901
            
2156
1902
            # Start communication using the Mandos protocol
2157
1903
            # Get protocol number
2167
1913
            # Start GnuTLS connection
2168
1914
            try:
2169
1915
                session.handshake()
2170
 
            except gnutls.Error as error:
 
1916
            except gnutls.errors.GNUTLSError as error:
2171
1917
                logger.warning("Handshake failed: %s", error)
2172
1918
                # Do not run session.bye() here: the session is not
2173
1919
                # established.  Just abandon the request.
2179
1925
                try:
2180
1926
                    fpr = self.fingerprint(
2181
1927
                        self.peer_certificate(session))
2182
 
                except (TypeError, gnutls.Error) as error:
 
1928
                except (TypeError,
 
1929
                        gnutls.errors.GNUTLSError) as error:
2183
1930
                    logger.warning("Bad certificate: %s", error)
2184
1931
                    return
2185
1932
                logger.debug("Fingerprint: %s", fpr)
2243
1990
                    else:
2244
1991
                        delay -= time2 - time
2245
1992
                
2246
 
                try:
2247
 
                    session.send(client.secret)
2248
 
                except gnutls.Error as error:
2249
 
                    logger.warning("gnutls send failed",
2250
 
                                   exc_info = error)
2251
 
                    return
 
1993
                sent_size = 0
 
1994
                while sent_size < len(client.secret):
 
1995
                    try:
 
1996
                        sent = session.send(client.secret[sent_size:])
 
1997
                    except gnutls.errors.GNUTLSError as error:
 
1998
                        logger.warning("gnutls send failed",
 
1999
                                       exc_info=error)
 
2000
                        return
 
2001
                    logger.debug("Sent: %d, remaining: %d", sent,
 
2002
                                 len(client.secret) - (sent_size
 
2003
                                                       + sent))
 
2004
                    sent_size += sent
2252
2005
                
2253
2006
                logger.info("Sending secret to %s", client.name)
2254
2007
                # bump the timeout using extended_timeout
2262
2015
                    client.approvals_pending -= 1
2263
2016
                try:
2264
2017
                    session.bye()
2265
 
                except gnutls.Error as error:
 
2018
                except gnutls.errors.GNUTLSError as error:
2266
2019
                    logger.warning("GnuTLS bye failed",
2267
2020
                                   exc_info=error)
2268
2021
    
2270
2023
    def peer_certificate(session):
2271
2024
        "Return the peer's OpenPGP certificate as a bytestring"
2272
2025
        # If not an OpenPGP certificate...
2273
 
        if (gnutls.certificate_type_get(session._c_object)
2274
 
            != gnutls.CRT_OPENPGP):
2275
 
            # ...return invalid data
2276
 
            return b""
 
2026
        if (gnutls.library.functions.gnutls_certificate_type_get(
 
2027
                session._c_object)
 
2028
            != gnutls.library.constants.GNUTLS_CRT_OPENPGP):
 
2029
            # ...do the normal thing
 
2030
            return session.peer_certificate
2277
2031
        list_size = ctypes.c_uint(1)
2278
 
        cert_list = (gnutls.certificate_get_peers
 
2032
        cert_list = (gnutls.library.functions
 
2033
                     .gnutls_certificate_get_peers
2279
2034
                     (session._c_object, ctypes.byref(list_size)))
2280
2035
        if not bool(cert_list) and list_size.value != 0:
2281
 
            raise gnutls.Error("error getting peer certificate")
 
2036
            raise gnutls.errors.GNUTLSError("error getting peer"
 
2037
                                            " certificate")
2282
2038
        if list_size.value == 0:
2283
2039
            return None
2284
2040
        cert = cert_list[0]
2288
2044
    def fingerprint(openpgp):
2289
2045
        "Convert an OpenPGP bytestring to a hexdigit fingerprint"
2290
2046
        # New GnuTLS "datum" with the OpenPGP public key
2291
 
        datum = gnutls.datum_t(
 
2047
        datum = gnutls.library.types.gnutls_datum_t(
2292
2048
            ctypes.cast(ctypes.c_char_p(openpgp),
2293
2049
                        ctypes.POINTER(ctypes.c_ubyte)),
2294
2050
            ctypes.c_uint(len(openpgp)))
2295
2051
        # New empty GnuTLS certificate
2296
 
        crt = gnutls.openpgp_crt_t()
2297
 
        gnutls.openpgp_crt_init(ctypes.byref(crt))
 
2052
        crt = gnutls.library.types.gnutls_openpgp_crt_t()
 
2053
        gnutls.library.functions.gnutls_openpgp_crt_init(
 
2054
            ctypes.byref(crt))
2298
2055
        # Import the OpenPGP public key into the certificate
2299
 
        gnutls.openpgp_crt_import(crt, ctypes.byref(datum),
2300
 
                                  gnutls.OPENPGP_FMT_RAW)
 
2056
        gnutls.library.functions.gnutls_openpgp_crt_import(
 
2057
            crt, ctypes.byref(datum),
 
2058
            gnutls.library.constants.GNUTLS_OPENPGP_FMT_RAW)
2301
2059
        # Verify the self signature in the key
2302
2060
        crtverify = ctypes.c_uint()
2303
 
        gnutls.openpgp_crt_verify_self(crt, 0,
2304
 
                                       ctypes.byref(crtverify))
 
2061
        gnutls.library.functions.gnutls_openpgp_crt_verify_self(
 
2062
            crt, 0, ctypes.byref(crtverify))
2305
2063
        if crtverify.value != 0:
2306
 
            gnutls.openpgp_crt_deinit(crt)
2307
 
            raise gnutls.CertificateSecurityError("Verify failed")
 
2064
            gnutls.library.functions.gnutls_openpgp_crt_deinit(crt)
 
2065
            raise gnutls.errors.CertificateSecurityError(
 
2066
                "Verify failed")
2308
2067
        # New buffer for the fingerprint
2309
2068
        buf = ctypes.create_string_buffer(20)
2310
2069
        buf_len = ctypes.c_size_t()
2311
2070
        # Get the fingerprint from the certificate into the buffer
2312
 
        gnutls.openpgp_crt_get_fingerprint(crt, ctypes.byref(buf),
2313
 
                                           ctypes.byref(buf_len))
 
2071
        gnutls.library.functions.gnutls_openpgp_crt_get_fingerprint(
 
2072
            crt, ctypes.byref(buf), ctypes.byref(buf_len))
2314
2073
        # Deinit the certificate
2315
 
        gnutls.openpgp_crt_deinit(crt)
 
2074
        gnutls.library.functions.gnutls_openpgp_crt_deinit(crt)
2316
2075
        # Convert the buffer to a Python bytestring
2317
2076
        fpr = ctypes.string_at(buf, buf_len.value)
2318
2077
        # Convert the bytestring to hexadecimal notation
2462
2221
        gnutls_priority GnuTLS priority string
2463
2222
        use_dbus:       Boolean; to emit D-Bus signals or not
2464
2223
    
2465
 
    Assumes a GObject.MainLoop event loop.
 
2224
    Assumes a gobject.MainLoop event loop.
2466
2225
    """
2467
2226
    
2468
2227
    def __init__(self, server_address, RequestHandlerClass,
2493
2252
    
2494
2253
    def add_pipe(self, parent_pipe, proc):
2495
2254
        # Call "handle_ipc" for both data and EOF events
2496
 
        GObject.io_add_watch(
 
2255
        gobject.io_add_watch(
2497
2256
            parent_pipe.fileno(),
2498
 
            GObject.IO_IN | GObject.IO_HUP,
 
2257
            gobject.IO_IN | gobject.IO_HUP,
2499
2258
            functools.partial(self.handle_ipc,
2500
2259
                              parent_pipe = parent_pipe,
2501
2260
                              proc = proc))
2505
2264
                   proc = None,
2506
2265
                   client_object=None):
2507
2266
        # error, or the other end of multiprocessing.Pipe has closed
2508
 
        if condition & (GObject.IO_ERR | GObject.IO_HUP):
 
2267
        if condition & (gobject.IO_ERR | gobject.IO_HUP):
2509
2268
            # Wait for other process to exit
2510
2269
            proc.join()
2511
2270
            return False
2532
2291
                parent_pipe.send(False)
2533
2292
                return False
2534
2293
            
2535
 
            GObject.io_add_watch(
 
2294
            gobject.io_add_watch(
2536
2295
                parent_pipe.fileno(),
2537
 
                GObject.IO_IN | GObject.IO_HUP,
 
2296
                gobject.IO_IN | gobject.IO_HUP,
2538
2297
                functools.partial(self.handle_ipc,
2539
2298
                                  parent_pipe = parent_pipe,
2540
2299
                                  proc = proc,
2922
2681
            logger.error("Could not open file %r", pidfilename,
2923
2682
                         exc_info=e)
2924
2683
    
2925
 
    for name, group in (("_mandos", "_mandos"),
2926
 
                        ("mandos", "mandos"),
2927
 
                        ("nobody", "nogroup")):
 
2684
    for name in ("_mandos", "mandos", "nobody"):
2928
2685
        try:
2929
2686
            uid = pwd.getpwnam(name).pw_uid
2930
 
            gid = pwd.getpwnam(group).pw_gid
 
2687
            gid = pwd.getpwnam(name).pw_gid
2931
2688
            break
2932
2689
        except KeyError:
2933
2690
            continue
2946
2703
        
2947
2704
        # "Use a log level over 10 to enable all debugging options."
2948
2705
        # - GnuTLS manual
2949
 
        gnutls.global_set_log_level(11)
 
2706
        gnutls.library.functions.gnutls_global_set_log_level(11)
2950
2707
        
2951
 
        @gnutls.log_func
 
2708
        @gnutls.library.types.gnutls_log_func
2952
2709
        def debug_gnutls(level, string):
2953
2710
            logger.debug("GnuTLS: %s", string[:-1])
2954
2711
        
2955
 
        gnutls.global_set_log_function(debug_gnutls)
 
2712
        gnutls.library.functions.gnutls_global_set_log_function(
 
2713
            debug_gnutls)
2956
2714
        
2957
2715
        # Redirect stdin so all checkers get /dev/null
2958
2716
        null = os.open(os.devnull, os.O_NOCTTY | os.O_RDWR)
2965
2723
        # Close all input and output, do double fork, etc.
2966
2724
        daemon()
2967
2725
    
2968
 
    # multiprocessing will use threads, so before we use GObject we
2969
 
    # need to inform GObject that threads will be used.
2970
 
    GObject.threads_init()
 
2726
    # multiprocessing will use threads, so before we use gobject we
 
2727
    # need to inform gobject that threads will be used.
 
2728
    gobject.threads_init()
2971
2729
    
2972
2730
    global main_loop
2973
2731
    # From the Avahi example code
2974
2732
    DBusGMainLoop(set_as_default=True)
2975
 
    main_loop = GObject.MainLoop()
 
2733
    main_loop = gobject.MainLoop()
2976
2734
    bus = dbus.SystemBus()
2977
2735
    # End of Avahi example code
2978
2736
    if use_dbus:
3306
3064
            # Don't signal the disabling
3307
3065
            client.disable(quiet=True)
3308
3066
            # Emit D-Bus signal for removal
3309
 
            if use_dbus:
3310
 
                mandos_dbus_service.client_removed_signal(client)
 
3067
            mandos_dbus_service.client_removed_signal(client)
3311
3068
        client_settings.clear()
3312
3069
    
3313
3070
    atexit.register(cleanup)
3347
3104
                sys.exit(1)
3348
3105
            # End of Avahi example code
3349
3106
        
3350
 
        GObject.io_add_watch(tcp_server.fileno(), GObject.IO_IN,
 
3107
        gobject.io_add_watch(tcp_server.fileno(), gobject.IO_IN,
3351
3108
                             lambda *args, **kwargs:
3352
3109
                             (tcp_server.handle_request
3353
3110
                              (*args[2:], **kwargs) or True))