Merge remote-tracking branch 'VittGam/master'
authorGuus Sliepen <guus@tinc-vpn.org>
Tue, 21 Mar 2017 20:48:08 +0000 (21:48 +0100)
committerGuus Sliepen <guus@tinc-vpn.org>
Tue, 21 Mar 2017 20:48:08 +0000 (21:48 +0100)
16 files changed:
COPYING
NEWS
README
THANKS
configure.ac
distro/tinc@.service
doc/tinc.conf.5.in
doc/tinc.texi
m4/openssl.m4
src/connection.c
src/connection.h
src/meta.c
src/net_setup.c
src/protocol_auth.c
src/proxy.c
src/tincd.c

diff --git a/COPYING b/COPYING
index 513da31..c7a4498 100644 (file)
--- a/COPYING
+++ b/COPYING
@@ -1,4 +1,4 @@
-Copyright (C) 1998-2016 Ivo Timmermans, Guus Sliepen and others.
+Copyright (C) 1998-2017 Ivo Timmermans, Guus Sliepen and others.
 See the AUTHORS file for a complete list.
 
 This program is free software; you can redistribute it and/or modify it under
diff --git a/NEWS b/NEWS
index 73a4a62..028cc9c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,21 @@
+Version 1.0.32               not released yet
+
+ * Fix segmentation fault when using Cipher = none.
+
+Version 1.0.31               January 15 2017
+
+ * Remove ExecStop in tinc@.service.
+
+Thanks to Élie Bouttier for his contribution to this version of tinc.
+
+Version 1.0.30               October 30 2016
+
+ * Fix troubles connecting to some HTTP proxies.
+
+ * Add mitigations for the Sweet32 attack when using a 64-bit block cipher.
+
+ * Use AES256 and SHA256 as the default encryption and digest algorithms.
+
 Version 1.0.29               October 9 2016
 
  * Fix UDP communication with peers with link-local IPv6 addresses.
diff --git a/README b/README
index e0e5817..3fb92fc 100644 (file)
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
-This is the README file for tinc version 1.0.29. Installation
+This is the README file for tinc version 1.0.31. Installation
 instructions may be found in the INSTALL file.
 
-tinc is Copyright (C) 1998-2016 by:
+tinc is Copyright (C) 1998-2017 by:
 
 Ivo Timmermans,
 Guus Sliepen <guus@tinc-vpn.org>,
@@ -39,6 +39,8 @@ practice and that the default length of the HMAC for packets is too short in
 his opinion. We do not know of a way to exploit these weaknesses, but these
 issues are being addressed in the tinc 1.1 branch.
 
+The Sweet32 attack affects versions of tinc prior to 1.0.30.
+
 Cryptography is a hard thing to get right. We cannot make any
 guarantees. Time, review and feedback are the only things that can
 prove the security of any cryptographic product. If you wish to review
@@ -52,22 +54,25 @@ Some configuration variables have different names now. Most notably "TapDevice"
 should be changed into "Device", and "Device" should be changed into
 "BindToDevice".
 
+
 Compatibility
 -------------
 
-Version 1.0.29 is compatible with 1.0pre8, 1.0 and later, but not with older
-versions of tinc.
+Version 1.0.31 is compatible with 1.0pre8, 1.0 and later, but not with older
+versions of tinc. Note that since version 1.0.30, tinc requires all nodes in
+the VPN to be compiled with a version of LibreSSL or OpenSSL that supports the
+AES256 and SHA256 algorithms.
 
 
 Requirements
 ------------
 
-Since 1.0pre3, we use OpenSSL for all cryptographic functions.  So you
-need to install this library first; grab it from
-http://www.openssl.org/.  You will need version 0.9.7 or later.  If
-this library is not installed on you system, configure will fail.  The
-manual in doc/tinc.texi contains more detailed information on how to
-install this library.
+Since 1.0pre3, we use OpenSSL for all cryptographic functions.  So you need to
+install this library first; grab it from http://www.openssl.org/. You will
+need version 1.0.1 or later with support for AES256 and SHA256 enabled. If
+this library is not installed on you system, configure will fail. The manual
+in doc/tinc.texi contains more detailed information on how to install this
+library. Alternatively, you may also use LibreSSL.
 
 Since 1.0pre6, the zlib library is used for optional compression. You can
 find it at http://www.gzip.org/zlib/. Because of a possible exploit in
diff --git a/THANKS b/THANKS
index 4be771c..3446041 100644 (file)
--- a/THANKS
+++ b/THANKS
@@ -15,6 +15,7 @@ We would like to thank the following people for their contributions to tinc:
 * David Pflug
 * Delf Eldkraft
 * dnk
+* Élie Bouttier
 * Enrique Zanardi
 * Florent Clairambault
 * Florian Weik
index 3ec5068..4853da7 100644 (file)
@@ -1,7 +1,7 @@
 dnl Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.61)
-AC_INIT([tinc], [1.0.29])
+AC_INIT([tinc], [1.0.31])
 AC_CONFIG_SRCDIR([src/tincd.c])
 AM_INIT_AUTOMAKE([1.11 check-news std-options subdir-objects nostdinc silent-rules -Wall])
 AC_CONFIG_HEADERS([config.h])
index 4bb4d2d..c823fa5 100644 (file)
@@ -8,7 +8,6 @@ Type=simple
 WorkingDirectory=/etc/tinc/%i
 ExecStart=/usr/sbin/tincd -n %i -D
 ExecReload=/usr/sbin/tincd -n %i -kHUP
-ExecStop=/usr/sbin/tincd -n %i -k
 TimeoutStopSec=5
 Restart=always
 RestartSec=60
index e2e206e..40ea1cc 100644 (file)
@@ -1,4 +1,4 @@
-.Dd 2016-04-10
+.Dd 2016-10-29
 .Dt TINC.CONF 5
 .\" Manual page created by:
 .\" Ivo Timmermans
@@ -468,7 +468,7 @@ Multiple
 .Va Address
 variables can be specified, in which case each address will be tried until a working
 connection has been established.
-.It Va Cipher Li = Ar cipher Pq blowfish
+.It Va Cipher Li = Ar cipher Pq aes-256-cbc
 The symmetric cipher algorithm used to encrypt UDP packets.
 Any cipher supported by LibreSSL or OpenSSL is recognised.
 Furthermore, specifying
@@ -483,7 +483,7 @@ Fragmentation Needed or Packet too Big messages are dropped by firewalls.
 This option sets the level of compression used for UDP packets.
 Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib),
 10 (fast lzo) and 11 (best lzo).
-.It Va Digest Li = Ar digest Pq sha1
+.It Va Digest Li = Ar digest Pq sha256
 The digest algorithm used to authenticate UDP packets.
 Any digest supported by LibreSSL or OpenSSL is recognised.
 Furthermore, specifying
index 90cc380..132a1c4 100644 (file)
@@ -1143,7 +1143,7 @@ Multiple Address variables can be specified, in which case each address will be
 tried until a working connection has been established.
 
 @cindex Cipher
-@item Cipher = <@var{cipher}> (blowfish)
+@item Cipher = <@var{cipher}> (aes-256-cbc)
 The symmetric cipher algorithm used to encrypt UDP packets.
 Any cipher supported by LibreSSL or OpenSSL is recognized.
 Furthermore, specifying "none" will turn off packet encryption.
@@ -1162,7 +1162,7 @@ Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib),
 10 (fast lzo) and 11 (best lzo).
 
 @cindex Digest
-@item Digest = <@var{digest}> (sha1)
+@item Digest = <@var{digest}> (sha256)
 The digest algorithm used to authenticate UDP packets.
 Any digest supported by LibreSSL or OpenSSL is recognized.
 Furthermore, specifying "none" will turn off packet authentication.
index bb1f146..adca5f7 100644 (file)
@@ -49,7 +49,7 @@ AC_DEFUN([tinc_OPENSSL],
     [AC_MSG_ERROR([Missing LibreSSL/OpenSSL functionality, make sure you have installed the latest version.]); break],
   )
 
-  AC_CHECK_DECL([OpenSSL_add_all_algorithms], ,
+  AC_CHECK_DECLS([OpenSSL_add_all_algorithms, EVP_aes_256_cfb], ,
     [AC_MSG_ERROR([Missing LibreSSL/OpenSSL functionality, make sure you have installed the latest version.]); break],
     [#include <openssl/evp.h>]
   )
index fd7ae84..d27e6fd 100644 (file)
@@ -1,6 +1,6 @@
 /*
     connection.c -- connection list management
-    Copyright (C) 2000-2012 Guus Sliepen <guus@tinc-vpn.org>,
+    Copyright (C) 2000-2016 Guus Sliepen <guus@tinc-vpn.org>,
                   2000-2005 Ivo Timmermans
                   2008      Max Rijevski <maksuf@gmail.com>
 
@@ -91,6 +91,8 @@ void free_connection_partially(connection_t *c) {
        c->outbufstart = 0;
        c->last_ping_time = 0;
        c->last_flushed_time = 0;
+       c->inbudget = 0;
+       c->outbudget = 0;
 
        if(c->inctx) {
                EVP_CIPHER_CTX_cleanup(c->inctx);
index 877601f..099d9d3 100644 (file)
@@ -1,6 +1,6 @@
 /*
     connection.h -- header for connection.c
-    Copyright (C) 2000-2012 Guus Sliepen <guus@tinc-vpn.org>,
+    Copyright (C) 2000-2016 Guus Sliepen <guus@tinc-vpn.org>,
                   2000-2005 Ivo Timmermans
 
     This program is free software; you can redistribute it and/or modify
@@ -41,7 +41,8 @@ typedef struct connection_status_t {
        unsigned int encryptout:1;                      /* 1 if we can encrypt outgoing traffic */
        unsigned int decryptin:1;                       /* 1 if we have to decrypt incoming traffic */
        unsigned int mst:1;                             /* 1 if this connection is part of a minimum spanning tree */
-       unsigned int unused:23;
+       unsigned int proxy_passed:1;                    /* 1 if we are connecting via a proxy and we have finished talking with it */
+       unsigned int unused:22;
 } connection_status_t;
 
 #include "edge.h"
@@ -70,6 +71,8 @@ typedef struct connection_t {
        const EVP_CIPHER *outcipher;    /* Cipher we will use to send data to him */
        EVP_CIPHER_CTX *inctx;          /* Context of encrypted meta data that will come from him to us */
        EVP_CIPHER_CTX *outctx;         /* Context of encrypted meta data that will be sent from us to him */
+       uint64_t inbudget;              /* Encrypted bytes send budget */
+       uint64_t outbudget;             /* Encrypted bytes receive budget */
        char *inkey;                            /* His symmetric meta key + iv */
        char *outkey;                           /* Our symmetric meta key + iv */
        int inkeylength;                        /* Length of his key + iv */
index 06ab96e..09c063d 100644 (file)
@@ -1,6 +1,6 @@
 /*
     meta.c -- handle the meta communication
-    Copyright (C) 2000-2015 Guus Sliepen <guus@tinc-vpn.org>,
+    Copyright (C) 2000-2016 Guus Sliepen <guus@tinc-vpn.org>,
                   2000-2005 Ivo Timmermans
                   2006      Scott Lamb <slamb@slamb.org>
 
@@ -62,6 +62,14 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
 
        /* Add our data to buffer */
        if(c->status.encryptout) {
+               /* Check encryption limits */
+               if(length > c->outbudget) {
+                       ifdebug(META) logger(LOG_ERR, "Byte limit exceeded for encryption to %s (%s)", c->name, c->hostname);
+                       return false;
+               } else {
+                       c->outbudget -= length;
+               }
+
                result = EVP_EncryptUpdate(c->outctx, (unsigned char *)c->outbuf + c->outbufstart + c->outbuflen,
                                &outlen, (unsigned char *)buffer, length);
                if(!result || outlen < length) {
@@ -175,6 +183,14 @@ bool receive_meta(connection_t *c) {
                /* Decrypt */
 
                if(c->status.decryptin && !decrypted) {
+                       /* Check decryption limits */
+                       if(lenin > c->inbudget) {
+                               ifdebug(META) logger(LOG_ERR, "Byte limit exceeded for decryption from %s (%s)", c->name, c->hostname);
+                               return false;
+                       } else {
+                               c->inbudget -= lenin;
+                       }
+
                        result = EVP_DecryptUpdate(c->inctx, (unsigned char *)inbuf, &lenout, (unsigned char *)c->buffer + oldlen, lenin);
                        if(!result || lenout != lenin) {
                                logger(LOG_ERR, "Error while decrypting metadata from %s (%s): %s",
index 6c50f9d..2371f7e 100644 (file)
@@ -1,7 +1,7 @@
 /*
     net_setup.c -- Setup.
     Copyright (C) 1998-2005 Ivo Timmermans,
-                  2000-2016 Guus Sliepen <guus@tinc-vpn.org>
+                  2000-2017 Guus Sliepen <guus@tinc-vpn.org>
                   2006      Scott Lamb <slamb@slamb.org>
                   2010      Brandon Black <blblack@gmail.com>
 
@@ -650,14 +650,28 @@ static bool setup_myself(void) {
                }
                free(cipher);
        } else
-               myself->incipher = EVP_bf_cbc();
+               myself->incipher = EVP_aes_256_cbc();
 
        if(myself->incipher)
                myself->inkeylength = EVP_CIPHER_key_length(myself->incipher) + EVP_CIPHER_iv_length(myself->incipher);
        else
                myself->inkeylength = 1;
 
-       myself->connection->outcipher = EVP_bf_ofb();
+       /* We need to use a stream mode for the meta protocol. Use AES for this,
+          but try to match the key size with the one from the cipher selected
+          by Cipher.
+
+          If Cipher is set to none, still use a low level of encryption for the
+          meta protocol.
+       */
+
+       int keylen = myself->incipher ? EVP_CIPHER_key_length(myself->incipher) : 0;
+       if(keylen <= 16)
+               myself->connection->outcipher = EVP_aes_128_cfb();
+       else if(keylen <= 24)
+               myself->connection->outcipher = EVP_aes_192_cfb();
+       else
+               myself->connection->outcipher = EVP_aes_256_cfb();
 
        if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime))
                keylifetime = 3600;
@@ -681,9 +695,9 @@ static bool setup_myself(void) {
 
                free(digest);
        } else
-               myself->indigest = EVP_sha1();
+               myself->indigest = EVP_sha256();
 
-       myself->connection->outdigest = EVP_sha1();
+       myself->connection->outdigest = EVP_sha256();
 
        if(get_config_int(lookup_config(config_tree, "MACLength"), &myself->inmaclength)) {
                if(myself->indigest) {
index 13dae1d..8288847 100644 (file)
@@ -41,9 +41,8 @@
 #include "xalloc.h"
 
 bool send_id(connection_t *c) {
-       if(proxytype && c->outgoing)
-               if(!send_proxyrequest(c))
-                       return false;
+       if(proxytype && c->outgoing && !c->status.proxy_passed)
+               return send_proxyrequest(c);
 
        return send_request(c, "%d %s %d", ID, myself->connection->name,
                                                myself->connection->protocol_version);
@@ -114,6 +113,21 @@ bool id_h(connection_t *c) {
        return send_metakey(c);
 }
 
+static uint64_t byte_budget(const EVP_CIPHER *cipher) {
+       /* Hopefully some failsafe way to calculate the maximum amount of bytes to
+          send/receive with a given cipher before we might run into birthday paradox
+          attacks. Because we might use different modes, the block size of the mode
+          might be 1 byte. In that case, use the IV length. Ensure the whole thing
+          is limited to what can be represented with a 64 bits integer.
+        */
+
+       int ivlen = EVP_CIPHER_iv_length(cipher);
+       int blklen = EVP_CIPHER_block_size(cipher);
+       int len = blklen > 1 ? blklen : ivlen > 1 ? ivlen : 8;
+       int bits = len * 4 - 1;
+       return bits < 64 ? UINT64_C(1) << bits : UINT64_MAX;
+}
+
 bool send_metakey(connection_t *c) {
        bool x;
 
@@ -196,6 +210,7 @@ bool send_metakey(connection_t *c) {
                        return false;
                }
 
+               c->outbudget = byte_budget(c->outcipher);
                c->status.encryptout = true;
        }
 
@@ -274,6 +289,7 @@ bool metakey_h(connection_t *c) {
                        return false;
                }
 
+               c->inbudget = byte_budget(c->incipher);
                c->status.decryptin = true;
        } else {
                c->incipher = NULL;
index e30c1fb..5268272 100644 (file)
@@ -1,6 +1,6 @@
 /*
     proxy.c -- Proxy handling functions.
-    Copyright (C) 2015 Guus Sliepen <guus@tinc-vpn.org>
+    Copyright (C) 2015-2016 Guus Sliepen <guus@tinc-vpn.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -194,6 +194,8 @@ int receive_proxy_meta(connection_t *c, int start, int lenin) {
 
                        ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Proxy request granted");
                        c->allow_request = ID;
+                       c->status.proxy_passed = true;
+                       send_id(c);
                        return 8;
                } else {
                        logger(LOG_ERR, "Proxy request rejected");
@@ -249,6 +251,8 @@ int receive_proxy_meta(connection_t *c, int start, int lenin) {
                } else {
                        ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Proxy request granted");
                        c->allow_request = ID;
+                       c->status.proxy_passed = true;
+                       send_id(c);
                        return replen;
                }
 
@@ -256,7 +260,12 @@ int receive_proxy_meta(connection_t *c, int start, int lenin) {
                char *p = memchr(c->buffer, '\n', c->buflen);
                if(!p || p - c->buffer >= c->buflen)
                        return 0;
-               p = memchr(p + 1, '\n', c->buflen - (p + 1 - c->buffer));
+
+               while((p = memchr(p + 1, '\n', c->buflen - (p + 1 - c->buffer)))) {
+                       if(p > c->buffer + 3 && !memcmp(p - 3, "\r\n\r\n", 4))
+                               break;
+               }
+
                if(!p)
                        return 0;
 
@@ -270,8 +279,12 @@ int receive_proxy_meta(connection_t *c, int start, int lenin) {
                                logger(LOG_DEBUG, "Proxy request granted");
                                replen = p  + 1 - c->buffer;
                                c->allow_request = ID;
+                               c->status.proxy_passed = true;
+                               send_id(c);
                                return replen;
                        } else {
+                               p = memchr(c->buffer, '\n', c->buflen);
+                               p[-1] = 0;
                                logger(LOG_ERR, "Proxy request rejected: %s", c->buffer + 9);
                                return false;
                        }
index aaf40e2..22fb726 100644 (file)
@@ -1,7 +1,7 @@
 /*
     tincd.c -- the main file for tincd
     Copyright (C) 1998-2005 Ivo Timmermans
-                  2000-2016 Guus Sliepen <guus@tinc-vpn.org>
+                  2000-2017 Guus Sliepen <guus@tinc-vpn.org>
                   2008      Max Rijevski <maksuf@gmail.com>
                   2009      Michael Tokarev <mjt@tls.msk.ru>
                   2010      Julien Muchembled <jm@jmuchemb.eu>
@@ -583,7 +583,7 @@ int main(int argc, char **argv) {
 
        if(show_version) {
                printf("%s version %s\n", PACKAGE, VERSION);
-               printf("Copyright (C) 1998-2016 Ivo Timmermans, Guus Sliepen and others.\n"
+               printf("Copyright (C) 1998-2017 Ivo Timmermans, Guus Sliepen and others.\n"
                                "See the AUTHORS file for a complete list.\n\n"
                                "tinc comes with ABSOLUTELY NO WARRANTY.  This is free software,\n"
                                "and you are welcome to redistribute it under certain conditions;\n"