From: Guus Sliepen Date: Tue, 21 Mar 2017 20:48:08 +0000 (+0100) Subject: Merge remote-tracking branch 'VittGam/master' X-Git-Tag: release-1.0.32~11 X-Git-Url: https://git.tinc-vpn.org/git/browse?a=commitdiff_plain;h=07ace0b6481efcc0a058aab7b90b95edd31709da;hp=1e2485a1c0c5b7497d1384d719a2d2a2dc8757ce;p=tinc Merge remote-tracking branch 'VittGam/master' --- diff --git a/COPYING b/COPYING index 513da315..c7a4498a 100644 --- 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 73a4a622..028cc9cd 100644 --- 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 e0e5817f..3fb92fcc 100644 --- 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 , @@ -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 4be771cd..3446041b 100644 --- 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 diff --git a/configure.ac b/configure.ac index 3ec50683..4853da7f 100644 --- a/configure.ac +++ b/configure.ac @@ -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]) diff --git a/distro/tinc@.service b/distro/tinc@.service index 4bb4d2dd..c823fa5a 100644 --- a/distro/tinc@.service +++ b/distro/tinc@.service @@ -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 diff --git a/doc/tinc.conf.5.in b/doc/tinc.conf.5.in index e2e206e1..40ea1cc7 100644 --- a/doc/tinc.conf.5.in +++ b/doc/tinc.conf.5.in @@ -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 diff --git a/doc/tinc.texi b/doc/tinc.texi index 90cc380c..132a1c42 100644 --- a/doc/tinc.texi +++ b/doc/tinc.texi @@ -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. diff --git a/m4/openssl.m4 b/m4/openssl.m4 index bb1f1465..adca5f7a 100644 --- a/m4/openssl.m4 +++ b/m4/openssl.m4 @@ -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 ] ) diff --git a/src/connection.c b/src/connection.c index fd7ae843..d27e6fd3 100644 --- a/src/connection.c +++ b/src/connection.c @@ -1,6 +1,6 @@ /* connection.c -- connection list management - Copyright (C) 2000-2012 Guus Sliepen , + Copyright (C) 2000-2016 Guus Sliepen , 2000-2005 Ivo Timmermans 2008 Max Rijevski @@ -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); diff --git a/src/connection.h b/src/connection.h index 877601fe..099d9d3b 100644 --- a/src/connection.h +++ b/src/connection.h @@ -1,6 +1,6 @@ /* connection.h -- header for connection.c - Copyright (C) 2000-2012 Guus Sliepen , + Copyright (C) 2000-2016 Guus Sliepen , 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 */ diff --git a/src/meta.c b/src/meta.c index 06ab96e4..09c063d3 100644 --- a/src/meta.c +++ b/src/meta.c @@ -1,6 +1,6 @@ /* meta.c -- handle the meta communication - Copyright (C) 2000-2015 Guus Sliepen , + Copyright (C) 2000-2016 Guus Sliepen , 2000-2005 Ivo Timmermans 2006 Scott Lamb @@ -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", diff --git a/src/net_setup.c b/src/net_setup.c index 6c50f9d8..2371f7ee 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -1,7 +1,7 @@ /* net_setup.c -- Setup. Copyright (C) 1998-2005 Ivo Timmermans, - 2000-2016 Guus Sliepen + 2000-2017 Guus Sliepen 2006 Scott Lamb 2010 Brandon Black @@ -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) { diff --git a/src/protocol_auth.c b/src/protocol_auth.c index 13dae1d3..8288847e 100644 --- a/src/protocol_auth.c +++ b/src/protocol_auth.c @@ -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; diff --git a/src/proxy.c b/src/proxy.c index e30c1fb0..52682721 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -1,6 +1,6 @@ /* proxy.c -- Proxy handling functions. - Copyright (C) 2015 Guus Sliepen + Copyright (C) 2015-2016 Guus Sliepen 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; } diff --git a/src/tincd.c b/src/tincd.c index aaf40e28..22fb726a 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -1,7 +1,7 @@ /* tincd.c -- the main file for tincd Copyright (C) 1998-2005 Ivo Timmermans - 2000-2016 Guus Sliepen + 2000-2017 Guus Sliepen 2008 Max Rijevski 2009 Michael Tokarev 2010 Julien Muchembled @@ -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"