Fix crash on Windows when a socket is available for both write and read.
Currently, if both write and read events fire at the same time on a
socket, the Windows-specific event loop will call both the write and
read callbacks, in that order. Problem is, the write callback could have
deleted the io handle, which makes the next call to the write callback a
use-after-free typically resulting in a hard crash.
In practice, this issue is triggered quite easily by putting the
computer to sleep, which basically freezes the tinc process. When the
computer wakes up and the process resumes, all TCP connections are
suddenly gone; as a result, the following sequence of events might
appear in the logs:
Metadata socket read error for node1 (1.2.3.4 port 655): (10054) An existing connection was forcibly closed by the remote host.
Closing connection with node1 (1.2.3.4 port 655)
Sending DEL_EDGE to everyone (BROADCAST): 13 4bf6 mynode node1
Sending 43 bytes of metadata to node2 (5.6.7.8 port 655)
Could not send 10891 bytes of data to node2 (5.6.7.8 port 655): (10054) An existing connection was forcibly closed by the remote host.a
Closing connection with node2 (5.6.7.8 port 655)
<CRASH>
In this example the crash occurs because the socket to node2 was
signaled for reading *in addition* to writing, but since the connection
was terminated, the attempt to call the read callback crashed the
process.
This commit fixes the problem by not even attempting to fire the write
callback when the write event on the socket is signaled - instead, we
just rely on the part of the event loop that simulates level-triggered
write events. Arguably that's even cleaner and faster, because the code
being removed was technically redundant - we have to go through that
write check loop anyway.
Guus Sliepen [Sun, 30 Oct 2016 14:17:52 +0000 (15:17 +0100)]
Use AES256 and SHA256 by default for the legacy protocol.
At the start of the decade, there were still distributions that shipped
with versions of OpenSSL that did not support these algorithms. By now
everyone should support them. The old defaults were Blowfish and SHA1,
both of which are not considered secure anymore.
The meta-protocol now always uses AES in CFB mode, but the key length
will adapt to the one specified by the Cipher option. The digest for the
meta-protocol is hardcoded to SHA256.
Guus Sliepen [Sun, 5 Jun 2016 12:47:21 +0000 (14:47 +0200)]
Preserve IPv6 scope_id in edges.
When creating an edge after authenticating a peer, we copy the
address used for the TCP connection, but change the port to that used
for UDP. But the way we did it discarded the scope_id for IPv6
addresses. This prevented UDP communication from working correctly when
connecting to a peer on the same LAN using an IPv6 link-local address.
Thanks to Rafał Leśniak for pointing out this issue.
thorkill [Thu, 19 May 2016 13:48:15 +0000 (15:48 +0200)]
Prevent tincd from sending packets to unexpecting nodes
Make tincd recognize when it was asleep and close connections to it's
peers. This happens when e.g. RoadWarrior has been suspended for
"longer" time period. After resume, it will start to communicate
with it's peers using the contextes it had before suspend.
On the other side, the nodes closed the connections since PingTimeout
and/or TCP connection went down.
Sending data to such unaware (sptps mostly) nodes will cause
havoc in the logs. Misleading the developers to wrong assumptions
that something is wrong with sptps.
Guus Sliepen [Sun, 1 May 2016 10:07:44 +0000 (12:07 +0200)]
Revert "Remove tinc.service, it is not necessary."
This reverts commit 0b6f84f96eeed20a0d771fedb72c0e19941adb7e. Although
systemd does automatically provide a "tinc.slice" when there is only a
tinc@.service template, it doesn't quite work the same way as
tinc.service.
Thanks to Alexander Ried for pointing out that if you have
tinc@.service template, systemd will provide a default slice containing
all instances of that template. So "systemctl start tinc" will still do
what we want it to do.
It doesn't do anything except give a confusing error message that we are
closing the connection to ourself. Replace it with connection_del().
This also fixes a double free.
Handle special characters in sptps_test only if the --special option is given.
sptps_test treats lines starting with #, ^ and $ specially, in order to
test the SPTPS protocol. However, this should only be done if explicitly
requested, otherwise it can unexpectedly fail.
When passing a NetName via an invitation, we don't allow any characters
that are unsafe (either because they could cause shells to expand things,
or because they are not allowed on some filesystems).
Also, warn when tinc is started with unsafe netnames.
This adds the ability for an invitation to provision an invitee with a
tinc-up script. This is quite strictly controlled; only address configuration
and routes are supported by adding "Ifconfig" and "Route" statements to
the invitation file. The "tinc join" command will generate a tinc-up script
from those statements, and will ask before enabling the tinc-up script.
Fix generation of version_git.h for some versions of BSD make.
In order to support VPATH builds, we have to use ${srcdir}/version.c as
the target for the rule that depends on the generation of version_git.h.
When not doing a VPATH build, ${srcdir} expands to ".", so the target
will be "./version.c". However, on some BSDs, make does not understand
that "./version.c" is the same as "version.c", and therefore it doesn't
trigger generating version_git.h when trying to build version.o. (It
works fine if you do a VPATH build, and OpenBSD's make does the right
thing in all cases.)
The trick is to have version.c depend on ${srcdir}/version.c. Of course,
Linux's make knows this is nonsense and will complain about a circular
dependency, so add this rule only on BSD platforms.
Guus Sliepen [Sun, 1 Nov 2015 20:07:56 +0000 (21:07 +0100)]
Update "now" after connect() when making outgoing connections.
It could be that address resolution takes a long time, don't let that
count against a connection. This is especially important when using a
nameserver from the VPN.
Guus Sliepen [Sun, 3 May 2015 18:06:12 +0000 (20:06 +0200)]
Never call putenv() with data on the stack.
Even though we are using putenv() here to remove items from the
environment, there is no guarantee that putenv() doesn't add the
argument to the environment anyway. In that case, we have to make sure
that it doesn't go away. We also don't want a memory leak, so keep a
list of things we unputenv()ed around, so we can reuse things.
Thanks to Poul-Henning Kamp for pointing out this problem.
Guus Sliepen [Sat, 27 Feb 2016 13:46:01 +0000 (14:46 +0100)]
Add warnings for bad combinations of Device and Interface.
On Linux, the name of the tun/tap interface can be set freely. However,
on most other operating systems, tinc cannot change the name of the
interface. In those situations, it is possible to specify a Device and
an Interface that conflict with each other. On BSD, this can cause
$INTERFACE to be set incorrectly, on Windows, this results in a
potentially unreliable way in which a TAP-Win32 interface is selected.
Fix source IP address for ICMP unreachable packets generated by tinc.
Try to send ICMP unreachable replies from an address assigned to the
local machine, instead of the destination address of the original
packet.
The address is found by looking up the route towards the sender of
the packet that generated the error; in usual configurations, this
is the tinc interface.
This also fixes the traceroute display in mtr when using the
DecrementTTL option.