Similar to old style key exchange requests, keep track of whether a key
exchange is already in progress and how long it took. If no key is known yet
or if key exchange takes too long, (re)start a new key exchange.
Most fields should be zero when reusing a connection. In particular, when an
outgoing connection to a node which is reachable on more than one address is
made, the second connection to that node will have status.encryptout set but
outctx will be NULL, causing a NULL pointer dereference when
EVP_EncryptUpdate() is called in send_meta() when it shouldn't.
When starting tincd, tincctl now strips non-options from the command line, and
sets argv[0] to the name of the tincd command instead of copying its own
command name.
When stopping a running tincd, tincctl now waits for it to terminate.
Internally, tinc maintains a directed graph of the meta connections between
nodes. However, this causes graphviz to draw two lines between nodes, which is
not always desirable. The "dump graph" command now defaults to dumping an
undirected graph, the "dump digraph" command will dump a directed graph.
This new setting allows choosing a custom script interpreter used for the various tinc callbacks.
If none is specified, the script itself is called as executable (as before).
This is particularly useful when storing tinc configuration and script on a mount point with no-exec attribute.
Commented non-existing functions in android NDK.
Prefix scripts execution with shell binary to allow execution on no-exec mount points.
Everyything is currently hard coded, while it should use pre-compiler variables...
When two nodes which support SPTPS want to send packets to each other, they now
always use SPTPS. The node initiating the SPTPS session send the first SPTPS
packet via an extended REQ_KEY messages. All other handshake messages are sent
using ANS_KEY messages. This ensures that intermediate nodes using an older
version of tinc can still help with NAT traversal. After the authentication
phase is over, SPTPS packets are sent via UDP, or are encapsulated in extended
REQ_KEY messages instead of PACKET messages.
Otherwise, the call to daemon() could close filedescriptors in use by libevent
itself; for example if it uses kqueue or epoll instead of a select() or poll()
backend.
In retry() the function do_outgoing_connection() is called, which can delete
items from the connection_tree, so when walking the tree we must first save the
pointer to the next item.
The used remote protocol can change between two reconnects, aka if
the remote side has enabled/disabled for example their ExperimentalProtocols
setting.
Proxy type "exec" can be used to have an external script or binary set
up an outgoing connection. Standard input and output will be used to
exchange data with the external command. The variables REMOTEADDRESS and
REMOTEPORT are set to the intended destination address and port.
When the Proxy option is used, outgoing connections will be made via the
specified proxy. There is no support for authentication methods or for having
the proxy forward incoming connections, and there is no attempt to proxy UDP.
When the "Broadcast = direct" option is used, broadcast packets are not sent
and forwarded via the Minimum Spanning Tree to all nodes, but are sent directly
to all nodes that can be reached in one hop.
One use for this is to allow running ad-hoc routing protocols, such as OLSR, on
top of tinc.
Most likeley the error is that there just is no valid key inside the used
host file, and in this case errno just contains a random value from the
last previously failed call.
When the Name starts with a $, the rest will be interpreted as the name of an
environment variable containing the real Name. When Name is $HOST, but this
environment variable does not exist, gethostname() will be used to set the
Name. In both cases, illegal characters will be converted to underscores.
If the LISTEN_FDS environment variable is set and tinc is run in the
foreground, tinc will use filedescriptors 3 to 3 + LISTEN_FDS for its listening
TCP sockets. For now, tinc will create matching listening UDP sockets itself.
There is no dependency on systemd or on libsystemd-daemon.
DeviceType = multicast allows one to specify a multicast address and port with
a Device statement. Tinc will then read/send packets to that multicast group
instead of to a tun/tap device. This allows interaction with UML, QEMU and KVM
instances that are listening on the same group.
When making outgoing connections, tinc goes through the list of Addresses and
tries all of them until one succeeds. However, before it would consider
establishing a TCP connection a success, even when the authentication failed.
This would be a problem if the first Address would point to a hostname and port
combination that belongs to the wrong tinc node, or perhaps even to a non-tinc
service, causing tinc to endlessly try this Address instead of moving to the
next one.
Problem found by Delf Eldkraft.
* Everything is identical except the headers of the records.
* Instead of sending explicit message length and having an implicit sequence
number, datagram mode has an implicit message length and an explicit sequence
number.
* The sequence number is used to set the most significant bytes of the counter.
Seeking in files and rewriting parts of them does not seem to work properly on
Windows. Instead, when old RSA keys are found when generating new ones, the
file containing the old keys is copied to a temporary file where the changes
are made, and that file is renamed back to the original filename. On Windows,
we cannot atomically replace files with a rename(), so we need to move the
original file out of the way first. If anything fails, the new code will warn
that the user has to solve the problem by hand.
This allows tincctl to receive log messages from a running tincd,
independent of what is logged to syslog or to file. Tincctl can receive
debug messages with an arbitrary level.
This allows administrators who frequently want to work with one tinc
network to omit the -n option. Since the NETNAME variable is set by
tincd when executing scripts, this makes it slightly easier to use
tincctl from within scripts.
The Broadcast option can be used to cause tinc to drop all broadcast and
multicast packets. This option might be expanded in the future to selectively
allow only some broadcast packet types.
The code introduced in commit 41a05f59ba is not
needed anymore, since tinc has been able to handle UDP packets from a different
source address than those of the TCP packets since 1.0.10. When using multiple
BindToAddress statements, this code does not make sense anymore, we do want the
kernel to choose the source address on its own.
Tinc will now, by default, decrement the TTL field of incoming IPv4 and IPv6
packets, before forwarding them to the virtual network device or to another
node. Packets with a TTL value of zero will be dropped, and an ICMP Time
Exceeded message will be sent back.
This behaviour can be disabled using the DecrementTTL option.
Scripts called by tinc would inherit its open filedescriptors. This could
be a problem if other long-running daemons are started from those scripts,
if those daemons would not close all filedescriptors before going into the
background.
Problem found and solution suggested by Nick Hibma.
Apart from the platform specific tun/tap driver, link with the dummy and
raw_socket devices, and optionally with support for UML and VDE devices.
At runtime, the DeviceType option can be used to select which driver to
use.
* Exchange nonce and ECDH public key first, calculate the ECDSA signature
over the complete key exchange.
* Make an explicit distinction between client and server in the signatures.
* Add more comments and replace some magic numbers by #defines.
Thanks to Erik Tews for very helpful hints and comments!
In case the config file could not be opened a new but unitialized RSA structure
would be returned, causing a segmentation fault later on. This would only
happen in the case that the config file could be opened before, but not when
read_rsa_public_key() was called. This situation could occur when the --user
option was used, and the config files were not readable by the specified user.
Probably due to a merge, the try_harder() function had duplicated the
rate-limiting code for detecting the sender node based on the HMAC of the
packet. This prevented this detection from running at all. The function is now
identical again to that in the 1.0 branch.
sometimes argv[0] will have directory-less name (when the
command is started by shell searching in $PATH for example).
For tincctl start we want the same rules to run tincd as for
tincctl itself (having full path is better but if shell does
not provide one we've no other choice). Previous code tried
to run ./tincd in this case, which is obviously wrong.
This is a fix for the previous commit.
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
For tincctl start, run tincd from dirname($0) not SBINDIR -
this allows painless alternative directory installation and
running from build directory too.
Also while at it, pass the rest of command line to tincd, not
only options before "start" argument. This way it's possible
to pass options to tincd like this:
tincctl -n net start -- -d 1 -R -U tincuser ...
And also add missing newline at the end of error message there.
Signed-Off-By: Michael Tokarev <mjt@tls.msk.ru>
Encryption and authentication of the meta connection is spread out over
meta.c and protocol_auth.c. The new protocol was added there as well,
leading to spaghetti code. To improve things, the new protocol will now
be implemented in sptps.[ch].
The goal is to have a very simplified version of TLS. There is a record
layer, and there are only two record types: application data and
handshake messages. The handshake message contains a random nonce, an
ephemeral ECDH public key, and an ECDSA signature over the former. After
the ECDH public keys are exchanged, a shared secret is calculated, and a
TLS style PRF is used to generate the key material for the cipher and
HMAC algorithm, and further communication is encrypted and authenticated.
A lot of the simplicity comes from the fact that both sides must have
each other's public keys in advance, and there are no options to choose.
There will be one fixed cipher suite, and both peers always authenticate
each other. (Inspiration taken from Ian Grigg's hypotheses[0].)
There might be some compromise in the future, to enable or disable
encryption, authentication and compression, but there will be no choice
of algorithms. This will allow SPTPS to be built with a few embedded
crypto algorithms instead of linking with huge crypto libraries.
The API is also kept simple. There is a start and a stop function. All
data necessary to make the connection work is passed in the start
function. Instead having both send- and receive-record functions, there
is a send-record function and a receive-data function. The latter will
pass protocol data received from the peer to the SPTPS implementation,
which will in turn call a receive-record callback function when
necessary. This hides all the handshaking from the application, and is
completely independent from any event loop or socket characteristics.
[0] http://iang.org/ssl/hn_hypotheses_in_secure_protocol_design.html
This is mainly important for Windows, where the select() call in the
main thread is not being woken up when the tapreader thread calls
route(), causing a delay of up to 1 second before the output buffer is
flushed. This would cause bad performance when UDP communication is not
possible.