Andreas Rammhold [Thu, 28 Feb 2019 19:38:14 +0000 (20:38 +0100)]
fix: use EVP_DecryptUpdate while decrypting
With OpenSSL versions 1.0.2r & 1.1.1b there were changes in regards to
how OpenSSL treats misuse of Encrypt/Decrypt EVP methods in the opposite
case. E.g. using the encrypt methods in a decrypt context. OpenSSL now
returns an error in these situations. [1]
Since tinc used the EVP_EncryptUpdate function in the cipher_decrypt
function the new sanity check was triggered causing tinc to be unusable
with said OpenSSL versions.
Guus Sliepen [Tue, 18 Dec 2018 16:44:08 +0000 (17:44 +0100)]
Prevent large amounts of UDP probes being sent consecutively.
We cannot reset udp_ping_sent to zero when we receive a valid reply to
an UDP probe, because that would cause a new one to be sent immediately
in try_udp(). Instead, add a bit to node_status_t to keep track of whether we
have a UDP probe that's waiting for a reply.
Thanks to Ronny Nilsson for spotting the source of the problem.
Guus Sliepen [Mon, 22 Oct 2018 18:31:37 +0000 (20:31 +0200)]
Attempt to make the test suite work with Windows executables.
The test suite still assumes a POSIX shell to run the tests, but now handles
the case when the executables themselves are (cross-)compiled for Windows,
with a .exe extension. Also, DOS line endings must be converted to UNIX
line endings in some cases.
Some tests now pass on Linux+Wine, but others do not, mainly due to Wine
not handling services very well.
Guus Sliepen [Thu, 18 Oct 2018 15:17:20 +0000 (17:17 +0200)]
Make more variables safe for use in invitations.
When writing one's own invitation files, more variables are now accepted
by the invitee. The goal is to allow anything that doesn't interfere
with the existing network configuration of the invitee and that doesn't
cause any unexpected behaviour, such as starting running commands.
Guus Sliepen [Thu, 18 Oct 2018 14:10:32 +0000 (16:10 +0200)]
Use the onlink flag when adding routes on Linux.
As reported by iczero, adding gateway routes on Linux can fail if the
gateway address is not reachable yet, either because the interface is
down, or if the gateway address is not inside any route that already is
added or is being added to that interface. By adding the onlink flag,
iproute2 will just add the route without questions.
iczero [Wed, 17 Oct 2018 05:58:52 +0000 (22:58 -0700)]
Fix tinc-up generation on windows
- use `%INTERFACE%` instead of `$INTERFACE` on windows
- correct typo in `netsh interface` (was `netsh inetface`)
- remove `static` when setting ipv6 address
Guus Sliepen [Mon, 8 Oct 2018 19:27:08 +0000 (21:27 +0200)]
Fix the compiler attribute test to work with Clang.
Clang doesn't like the __nonnull__ attribute being applied to functions
that don't take pointer arguments, and this causes errors when running
the configure script.
Prevent oracle attacks in the legacy protocol (CVE-2018-16737, CVE-2018-16738)
The legacy authentication protocol allows an oracle attack that could
potentially be exploited. This commit contains several mitigations:
- Connections are no longer closed immediately on error, but put in
a "tarpit".
- The authentication protocol now requires a valid CHAL_REPLY from the
initiator of a connection before sending a CHAL_REPLY of its own.
- Reduce the amount of connections per second accepted.
- Null ciphers or digests are no longer allowed in METAKEYs.
- Connections that claim to have the same name as the local node are
rejected.
Just to be on the safe side:
- The new protocol now requires a valid SIG from the initiator of a
connection before sending a SIG of its own.
Guus Sliepen [Tue, 12 Jun 2018 17:47:02 +0000 (19:47 +0200)]
Remove the wxPython GUI.
This GUI is missing a lot of functionality, and won't be part of an 1.1.0
release. Therefore, it's being removed, and might be brought back after
1.1.0.
Running the "del Port" command when no Port is set returns an error. But
it is not necessary anyway since the later "set Port" command will
overwrite it.
Guus Sliepen [Fri, 30 Mar 2018 09:50:40 +0000 (11:50 +0200)]
Prevent an infinite loop in get_recent_address().
When a node is offline, but we still have edges to it that have the same
address as we already have in our address cache, an infinite loop would
happen in get_recent_address(), because we forgot to advance the pointer
in the list of known addresses, and kept looking at the same one over
and over.
Thanks to Sven-Haegar Koch for spotting the bug and providing
diagnostics.
Todd C. Miller [Tue, 27 Feb 2018 21:20:46 +0000 (14:20 -0700)]
Call WSAWaitForMultipleEvents() in a loop until we have checked all events.
WSAWaitForMultipleEvents() only returns the index of the first event that is read. We need to call WSAWaitForMultipleEvents() repeatedly to check if other events are also ready. Otherwise, a single busy event (such as the TAP device) can starve the other events.
Guus Sliepen [Tue, 27 Feb 2018 20:08:57 +0000 (21:08 +0100)]
Work around a GCC bug that causes inet_checksum() to give wrong results.
Valgrind reports the following bug:
==24877== Conditional jump or move depends on uninitialised value(s)
==24877== at 0x12283E: inet_checksum (route.c:80)
==24877== by 0x12283E: route_ipv6_unreachable (route.c:315)
==24877== by 0x1236AC: route_ipv6 (route.c:751)
==24877== by 0x1236AC: route (route.c:1160)
==24877== by 0x113DE0: receive_tcppacket (net_packet.c:493)
==24877== by 0x1119D4: receive_meta (meta.c:315)
==24877== by 0x113288: handle_meta_connection_data (net.c:287)
==24877== by 0x11A091: handle_meta_io (net_socket.c:491)
==24877== by 0x10FB0C: event_loop (event.c:370)
==24877== by 0x11362E: main_loop (net.c:489)
==24877== by 0x10CACA: main (tincd.c:551)
Clearing the variable pseudo in route_ipv6_unreachable removes this error,
but the resulting checksum is still bad. If one instead adds a dummy
write that depends on checksum, the error goes away and the checksum is
correct.
Guus Sliepen [Mon, 26 Feb 2018 21:19:43 +0000 (22:19 +0100)]
Unconditionally remove timeouts from the queue before calling the callback.
We are going to unlink the timeout from the splay tree anyway, so do it
unconditionally before the callback, instead of waiting until after the
callback to check whether or not to remove it based on its expiration
time.
Todd C. Miller [Thu, 22 Feb 2018 21:27:37 +0000 (14:27 -0700)]
In device_handle_read() we need to reset the read event on error or
it will keep firing. This is easy to reproduce by suspending the
machine while tinc is running.
Todd C. Miller [Wed, 21 Feb 2018 03:18:38 +0000 (20:18 -0700)]
Fix heap corruption on Windows exposed by the use-after free fix.
reset_address_cache() could call free_known_addresses() on a struct
addrinfo * that was returned by getaddrinfo(). It seems safest to just
make a copy of the addresses returned by getaddrinfo() so we can always
use free_known_addresses() instead of trying to determine whether or
not we need to use freeaddrinfo().
Guus Sliepen [Sun, 18 Feb 2018 15:51:06 +0000 (16:51 +0100)]
Reduce memory allocations due to HMAC() and EVP_MD_*().
HMAC() allocates a temporary buffer on the heap each time it is called.
Similarly, we called EVP_MD_CTX_create() every time we wanted to
calculate a hash. Use HMAC_CTX and EVP_MD_CTX variables to store the
state so no (re)allocations are necessary. HMAC() was called for every
legacy packet sent and received.
Guus Sliepen [Sun, 18 Feb 2018 14:38:12 +0000 (15:38 +0100)]
Reduce memory allocations due to zlib's uncompress().
Everytime uncompress() is called, zlib allocates some buffer on the heap
and frees it again. When compression is enabled, this is the biggest source
of memory allocations in tinc. Instead of using this function, use
inflate(), which can store its state in a z_stream variable, which avoids
(re)allocating memory for every packet received.
Guus Sliepen [Sun, 18 Feb 2018 14:33:36 +0000 (15:33 +0100)]
Add code coverage testing support.
Allows configure to be run with the --enable-code-coverage flag, allowing
one to run make check-code-coverage, which runs the test suite and produces
a code coverage report.
Todd C. Miller [Fri, 16 Feb 2018 21:17:39 +0000 (14:17 -0700)]
Fix a use-after-free bug in get_recent_address() and two related issues.
1) The sockaddr_t * returned may be part of memory freed by the call to
freeaddrinfo().
2) The sockaddr_t * returned from a recently seen address not in the
cache was cast from struct addrinfo *ai, not the struct sockaddr *
inside of it.
3) In do_outgoing_connection(), when filling in the address in the
connection_t, there is a buffer overflow (read, not write) if
the sa returned by get_recent_address() didn't come from the
cache of recently seen addresses. That is, it was really a
struct sockaddr * and not a sockaddr_t *. This last was
found by building tinc with address sanitizer.
Todd C. Miller [Wed, 31 Jan 2018 21:55:20 +0000 (14:55 -0700)]
In device_issue_read() there is no need to reset Offset and OffsetHigh
to 0; they are only used for seekable files (not sockets).
Reset the write event before the call to WriteFile(). This is
consistent with how the read event is reset before ReadFile().
Clear device_write_packet.len() if WriteFile() fails with an error
other than ERROR_IO_PENDING; otherwise write_packet() will call
GetOverlappedResult() the next time it is run even though there is
no write in progress.
Todd C. Miller [Tue, 23 Jan 2018 22:57:58 +0000 (15:57 -0700)]
WSAEVENT is a pointer, so we cannot simply return the different of two
events in io_compare(), which returns an int. This can return the wrong
result for 64-bit executables.
Etienne Dechamps [Wed, 17 Jan 2018 19:37:53 +0000 (19:37 +0000)]
Move ResetEvent() call before ReadFile().
Commit 313a752 changed the Windows device code such that ResetEvent() is
called on the read OVERLAPPED structure before GetOverlappedResult(), as
opposed to before ReadFile(). In [1] Guus pointed out that this doesn't
make a ton of sense, and I agree with him; it must have been an
oversight on my part when I wrote this code.
Surprisingly, none of this makes any difference in my testing, at least
with the standard TAP 9.0.0.9 driver. Nevertheless, this code is
probably wrong and fixing it will make me sleep better at night.
Guus Sliepen [Fri, 5 Jan 2018 21:49:30 +0000 (22:49 +0100)]
Add a cache of recently seen addresses.
This maintains a cache file for each host we have communicated with, either
via TCP or UDP. The cache is used when trying to make outgoing connections,
and is updated whenever a successful TCP or UDP connection is established.
Up to 8 addresses are stored in the cache.
Currently, the cache is stored in /etc/tinc/NETNAME/cache. The directory
has to be manually created to opt in to this feature for now.