/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: 2016-02-28 03:01:43 UTC
  • Revision ID: teddy@recompile.se-20160228030143-i6w90r7wzkvlx9kq
Stop using python-gnutls.  Use GnuTLS 3.3 or later directly.

* INSTALL: Document dependency on GnuTLS 3.3 and remove dependency on
          Python-GnuTLS.

* debian/control (Source: mandos/Build-Depends): Add (>= 3.3.0) to
                                                 "libgnutls28-dev" and
                                                 "gnutls-dev".
  (Source: mandos/Build-Depends-Indep): Remove "python2.7-gnutls".
  (Package: mandos/Depends): Remove "python-gnutls" and
                             "python2.7-gnutls", add "libgnutls28-dev
                             (>= 3.3.0) | libgnutls30 (>= 3.3.0)"
* mandos: Remove imports of "gnutls" and all submodules.
  (GnuTLS, gnutls): New; simulate a "gnutls" module.  Change all
                    callers to match new shorter names.

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
151
151
    
152
152
    def __init__(self):
153
153
        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
154
        self.gnupgargs = ['--batch',
166
 
                          '--homedir', self.tempdir,
 
155
                          '--home', self.tempdir,
167
156
                          '--force-mdc',
168
157
                          '--quiet',
169
158
                          '--no-use-agent']
208
197
                dir=self.tempdir) as passfile:
209
198
            passfile.write(passphrase)
210
199
            passfile.flush()
211
 
            proc = subprocess.Popen([self.gpg, '--symmetric',
 
200
            proc = subprocess.Popen(['gpg', '--symmetric',
212
201
                                     '--passphrase-file',
213
202
                                     passfile.name]
214
203
                                    + self.gnupgargs,
226
215
                dir = self.tempdir) as passfile:
227
216
            passfile.write(passphrase)
228
217
            passfile.flush()
229
 
            proc = subprocess.Popen([self.gpg, '--decrypt',
 
218
            proc = subprocess.Popen(['gpg', '--decrypt',
230
219
                                     '--passphrase-file',
231
220
                                     passfile.name]
232
221
                                    + self.gnupgargs,
461
450
    
462
451
    # Constants
463
452
    E_SUCCESS = 0
464
 
    E_INTERRUPTED = -52
465
 
    E_AGAIN = -28
466
453
    CRT_OPENPGP = 2
467
454
    CLIENT = 2
468
455
    SHUT_RDWR = 0
496
483
        # We need to use the class name "GnuTLS" here, since this
497
484
        # exception might be raised from within GnuTLS.__init__,
498
485
        # which is called before the assignment to the "gnutls"
499
 
        # global variable has happened.
 
486
        # global variable happens.
500
487
        def __init__(self, message = None, code = None, args=()):
501
488
            # Default usage is by a message string, but if a return
502
489
            # code is passed, convert it to a string with
503
490
            # gnutls.strerror()
504
 
            self.code = code
505
491
            if message is None and code is not None:
506
492
                message = GnuTLS.strerror(code)
507
493
            return super(GnuTLS.Error, self).__init__(
545
531
        
546
532
        def send(self, data):
547
533
            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)
 
534
            if not data:
 
535
                return 0
 
536
            return gnutls.record_send(self._c_object, data, len(data))
553
537
        
554
538
        def bye(self):
555
539
            return gnutls.bye(self._c_object, gnutls.SHUT_RDWR)
556
540
    
557
 
    # Error handling functions
 
541
    # Error handling function
558
542
    def _error_code(result):
559
543
        """A function to raise exceptions on errors, suitable
560
544
        for the 'restype' attribute on ctypes functions"""
564
548
            raise gnutls.CertificateSecurityError(code = result)
565
549
        raise gnutls.Error(code = result)
566
550
    
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
551
    # Unless otherwise indicated, the function declarations below are
577
552
    # all from the gnutls/gnutls.h C header file.
578
553
    
594
569
    record_send.argtypes = [session_t, ctypes.c_void_p,
595
570
                            ctypes.c_size_t]
596
571
    record_send.restype = ctypes.c_ssize_t
597
 
    record_send.errcheck = _retry_on_error
598
572
    
599
573
    certificate_allocate_credentials = (
600
574
        _library.gnutls_certificate_allocate_credentials)
646
620
    handshake = _library.gnutls_handshake
647
621
    handshake.argtypes = [session_t]
648
622
    handshake.restype = _error_code
649
 
    handshake.errcheck = _retry_on_error
650
623
    
651
624
    transport_set_ptr = _library.gnutls_transport_set_ptr
652
625
    transport_set_ptr.argtypes = [session_t, transport_ptr_t]
655
628
    bye = _library.gnutls_bye
656
629
    bye.argtypes = [session_t, close_request_t]
657
630
    bye.restype = _error_code
658
 
    bye.errcheck = _retry_on_error
659
631
    
660
632
    check_version = _library.gnutls_check_version
661
633
    check_version.argtypes = [ctypes.c_char_p]
690
662
                                                ctypes.c_size_t)]
691
663
    openpgp_crt_get_fingerprint.restype = _error_code
692
664
    
693
 
    # Remove non-public functions
694
 
    del _error_code, _retry_on_error
 
665
    # Remove non-public function
 
666
    del _error_code
695
667
# Create the global "gnutls" object, simulating a module
696
668
gnutls = GnuTLS()
697
669
 
2243
2215
                    else:
2244
2216
                        delay -= time2 - time
2245
2217
                
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
 
2218
                sent_size = 0
 
2219
                while sent_size < len(client.secret):
 
2220
                    try:
 
2221
                        sent = session.send(client.secret[sent_size:])
 
2222
                    except gnutls.Error as error:
 
2223
                        logger.warning("gnutls send failed",
 
2224
                                       exc_info=error)
 
2225
                        return
 
2226
                    logger.debug("Sent: %d, remaining: %d", sent,
 
2227
                                 len(client.secret) - (sent_size
 
2228
                                                       + sent))
 
2229
                    sent_size += sent
2252
2230
                
2253
2231
                logger.info("Sending secret to %s", client.name)
2254
2232
                # bump the timeout using extended_timeout