Import Upstream version 1.1~pre14-16-g15b868e

This commit is contained in:
Guus Sliepen 2019-08-26 13:44:52 +02:00
parent aa10d88732
commit 87cef22421
41 changed files with 783 additions and 256 deletions

View file

@ -196,8 +196,11 @@ sbin_PROGRAMS = tincd$(EXEEXT) tinc$(EXEEXT) sptps_test$(EXEEXT) \
subdir = src
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/attribute.m4 \
$(top_srcdir)/m4/ax_append_flag.m4 \
$(top_srcdir)/m4/ax_cflags_warn_all.m4 \
$(top_srcdir)/m4/ax_check_compile_flag.m4 \
$(top_srcdir)/m4/ax_check_link_flag.m4 \
$(top_srcdir)/m4/ax_require_defined.m4 \
$(top_srcdir)/m4/curses.m4 $(top_srcdir)/m4/libgcrypt.m4 \
$(top_srcdir)/m4/lzo.m4 $(top_srcdir)/m4/miniupnpc.m4 \
$(top_srcdir)/m4/openssl.m4 $(top_srcdir)/m4/readline.m4 \

View file

@ -349,13 +349,13 @@ static bool read_packet(vpn_packet_t *packet) {
case DEVICE_TYPE_UTUN:
case DEVICE_TYPE_TUNIFHEAD: {
if((inlen = read(device_fd, packet->data + 10, MTU - 10)) <= 0) {
if((inlen = read(device_fd, DATA(packet) + 10, MTU - 10)) <= 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while reading from %s %s: %s", device_info,
device, strerror(errno));
return false;
}
switch (packet->data[14] >> 4) {
switch (DATA(packet)[14] >> 4) {
case 4:
DATA(packet)[12] = 0x08;
DATA(packet)[13] = 0x00;
@ -369,7 +369,7 @@ static bool read_packet(vpn_packet_t *packet) {
default:
logger(DEBUG_TRAFFIC, LOG_ERR,
"Unknown IP version %d while reading packet from %s %s",
packet->data[14] >> 4, device_info, device);
DATA(packet)[14] >> 4, device_info, device);
return false;
}
@ -430,9 +430,9 @@ static bool write_packet(vpn_packet_t *packet) {
return false;
}
memcpy(packet->data + 10, &type, sizeof type);
memcpy(DATA(packet) + 10, &type, sizeof type);
if(write(device_fd, packet->data + 10, packet->len - 10) < 0) {
if(write(device_fd, DATA(packet) + 10, packet->len - 10) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Can't write to %s %s: %s", device_info, device,
strerror(errno));
return false;

View file

@ -87,7 +87,7 @@ static void tun_error(char *format, ...)
{
va_list vl;
va_start(vl, format);
vsnprintf(tunemu_error, ERROR_BUFFER_SIZE, format, vl);
vsnprintf(tunemu_error, sizeof tunemu_error, format, vl);
va_end(vl);
}

View file

@ -106,6 +106,7 @@ int vasprintf(char **buf, const char *fmt, va_list ap) {
va_copy(aq, ap);
status = vsnprintf(*buf, len, fmt, aq);
buf[len - 1] = 0;
va_end(aq);
if(status >= 0)

View file

@ -110,20 +110,22 @@ void logger(int level, int priority, const char *format, ...) {
va_start(ap, format);
int len = vsnprintf(message, sizeof message, format, ap);
message[sizeof message - 1] = 0;
va_end(ap);
if(len > 0 && len < sizeof message && message[len - 1] == '\n')
if(len > 0 && len < sizeof message - 1 && message[len - 1] == '\n')
message[len - 1] = 0;
real_logger(level, priority, message);
}
static void sptps_logger(sptps_t *s, int s_errno, const char *format, va_list ap) {
char message[1024] = "";
char message[1024];
size_t msglen = sizeof message;
int len = vsnprintf(message, msglen, format, ap);
if(len > 0 && len < sizeof message) {
message[sizeof message - 1] = 0;
if(len > 0 && len < sizeof message - 1) {
if(message[len - 1] == '\n')
message[--len] = 0;

147
src/net.c
View file

@ -42,6 +42,7 @@ static int sleeptime = 10;
time_t last_config_check = 0;
static timeout_t pingtimer;
static timeout_t periodictimer;
static struct timeval last_periodic_run_time;
/* Purge edges and subnets of unreachable nodes. Use carefully. */
@ -93,29 +94,31 @@ void purge(void) {
void terminate_connection(connection_t *c, bool report) {
logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Closing connection with %s (%s)", c->name, c->hostname);
if(c->node && c->node->connection == c)
c->node->connection = NULL;
if(c->node) {
if(c->node->connection == c)
c->node->connection = NULL;
if(c->edge) {
if(report && !tunnelserver)
send_del_edge(everyone, c->edge);
if(c->edge) {
if(report && !tunnelserver)
send_del_edge(everyone, c->edge);
edge_del(c->edge);
c->edge = NULL;
edge_del(c->edge);
c->edge = NULL;
/* Run MST and SSSP algorithms */
/* Run MST and SSSP algorithms */
graph();
graph();
/* If the node is not reachable anymore but we remember it had an edge to us, clean it up */
/* If the node is not reachable anymore but we remember it had an edge to us, clean it up */
if(report && !c->node->status.reachable) {
edge_t *e;
e = lookup_edge(c->node, myself);
if(e) {
if(!tunnelserver)
send_del_edge(everyone, e);
edge_del(e);
if(report && !c->node->status.reachable) {
edge_t *e;
e = lookup_edge(c->node, myself);
if(e) {
if(!tunnelserver)
send_del_edge(everyone, e);
edge_del(e);
}
}
}
}
@ -144,30 +147,76 @@ void terminate_connection(connection_t *c, bool report) {
and close the connection.
*/
static void timeout_handler(void *data) {
bool close_all_connections = false;
/*
timeout_handler will start after 30 seconds from start of tincd
hold information about the elapsed time since last time the handler
has been run
*/
long sleep_time = now.tv_sec - last_periodic_run_time.tv_sec;
/*
It seems that finding sane default value is harder than expected
Since we send every second a UDP packet to make holepunching work
And default UDP state expire on firewalls is between 15-30 seconds
we drop all connections after 60 Seconds - UDPDiscoveryTimeout=30
by default
*/
if (sleep_time > 2 * udp_discovery_timeout) {
logger(DEBUG_ALWAYS, LOG_ERR, "Awaking from dead after %ld seconds of sleep", sleep_time);
/*
Do not send any packets to tinc after we wake up.
The other node probably closed our connection but we still
are holding context information to them. This may happen on
laptops or any other hardware which can be suspended for some time.
Sending any data to node that wasn't expecting it will produce
annoying and misleading errors on the other side about failed signature
verification and or about missing sptps context
*/
close_all_connections = true;
}
last_periodic_run_time = now;
for list_each(connection_t, c, connection_list) {
// control connections (eg. tinc ctl) do not have any timeout
if(c->status.control)
continue;
if(c->last_ping_time + pingtimeout <= now.tv_sec) {
if(c->edge) {
try_tx(c->node, false);
if(c->status.pinged) {
logger(DEBUG_CONNECTIONS, LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds", c->name, c->hostname, (long)(now.tv_sec - c->last_ping_time));
} else if(c->last_ping_time + pinginterval <= now.tv_sec) {
send_ping(c);
continue;
} else {
continue;
}
} else {
if(c->status.connecting)
logger(DEBUG_CONNECTIONS, LOG_WARNING, "Timeout while connecting to %s (%s)", c->name, c->hostname);
else
logger(DEBUG_CONNECTIONS, LOG_WARNING, "Timeout from %s (%s) during authentication", c->name, c->hostname);
}
if(close_all_connections) {
logger(DEBUG_ALWAYS, LOG_ERR, "Forcing connection close after sleep time %s (%s)", c->name, c->hostname);
terminate_connection(c, c->edge);
continue;
}
// Bail out early if we haven't reached the ping timeout for this node yet
if(c->last_ping_time + pingtimeout > now.tv_sec)
continue;
// timeout during connection establishing
if(!c->edge) {
if(c->status.connecting)
logger(DEBUG_CONNECTIONS, LOG_WARNING, "Timeout while connecting to %s (%s)", c->name, c->hostname);
else
logger(DEBUG_CONNECTIONS, LOG_WARNING, "Timeout from %s (%s) during authentication", c->name, c->hostname);
terminate_connection(c, c->edge);
continue;
}
// helps in UDP holepunching
try_tx(c->node, false);
// timeout during ping
if(c->status.pinged) {
logger(DEBUG_CONNECTIONS, LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds", c->name, c->hostname, (long)now.tv_sec - c->last_ping_time);
terminate_connection(c, c->edge);
continue;
}
// check whether we need to send a new ping
if(c->last_ping_time + pinginterval <= now.tv_sec)
send_ping(c);
}
timeout_set(data, &(struct timeval){1, rand() % 100000});
@ -210,19 +259,25 @@ static void periodic_handler(void *data) {
and we are not already trying to make one, create an
outgoing connection to this node.
*/
int r = rand() % (node_tree->count - 1);
int i = 0;
int count = 0;
for splay_each(node_t, n, node_tree) {
if(n == myself || n->connection || !(n->status.has_address || n->status.reachable))
continue;
count++;
}
if(!count)
goto end;
int r = rand() % count;
for splay_each(node_t, n, node_tree) {
if(n == myself)
if(n == myself || n->connection || !(n->status.has_address || n->status.reachable))
continue;
if(i++ != r)
if(r--)
continue;
if(n->connection)
break;
bool found = false;
for list_each(outgoing_t, outgoing, outgoing_list) {
@ -239,6 +294,7 @@ static void periodic_handler(void *data) {
list_insert_tail(outgoing_list, outgoing);
setup_outgoing_connection(outgoing);
}
break;
}
} else if(nc > 3) {
@ -287,6 +343,7 @@ static void periodic_handler(void *data) {
}
}
end:
timeout_set(data, &(struct timeval){5, rand() % 100000});
}
@ -344,9 +401,14 @@ int reload_configuration(void) {
for splay_each(subnet_t, subnet, subnet_tree)
if (subnet->owner)
subnet->expires = 1;
}
load_all_subnets();
for splay_each(node_t, n, node_tree)
n->status.has_address = false;
load_all_nodes();
if(strictsubnets) {
for splay_each(subnet_t, subnet, subnet_tree) {
if (!subnet->owner)
continue;
@ -444,6 +506,7 @@ void retry(void) {
this is where it all happens...
*/
int main_loop(void) {
last_periodic_run_time = now;
timeout_add(&pingtimer, timeout_handler, &pingtimer, &(struct timeval){pingtimeout, rand() % 100000});
timeout_add(&periodictimer, periodic_handler, &periodictimer, &(struct timeval){0, 0});

View file

@ -217,7 +217,6 @@ extern void regenerate_key(void);
extern void purge(void);
extern void retry(void);
extern int reload_configuration(void);
extern void load_all_subnets(void);
extern void load_all_nodes(void);
extern void try_tx(struct node_t *n, bool);

View file

@ -355,16 +355,16 @@ static bool receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
if(seqno != n->received_seqno + 1) {
if(seqno >= n->received_seqno + replaywin * 8) {
if(n->farfuture++ < replaywin >> 2) {
logger(DEBUG_ALWAYS, LOG_WARNING, "Packet from %s (%s) is %d seqs in the future, dropped (%u)",
logger(DEBUG_TRAFFIC, LOG_WARNING, "Packet from %s (%s) is %d seqs in the future, dropped (%u)",
n->name, n->hostname, seqno - n->received_seqno - 1, n->farfuture);
return false;
}
logger(DEBUG_ALWAYS, LOG_WARNING, "Lost %d packets from %s (%s)",
logger(DEBUG_TRAFFIC, LOG_WARNING, "Lost %d packets from %s (%s)",
seqno - n->received_seqno - 1, n->name, n->hostname);
memset(n->late, 0, replaywin);
} else if (seqno <= n->received_seqno) {
if((n->received_seqno >= replaywin * 8 && seqno <= n->received_seqno - replaywin * 8) || !(n->late[(seqno / 8) % replaywin] & (1 << seqno % 8))) {
logger(DEBUG_ALWAYS, LOG_WARNING, "Got late or replayed packet from %s (%s), seqno %d, last received %d",
logger(DEBUG_TRAFFIC, LOG_WARNING, "Got late or replayed packet from %s (%s), seqno %d, last received %d",
n->name, n->hostname, seqno, n->received_seqno);
return false;
}
@ -436,7 +436,7 @@ void receive_tcppacket(connection_t *c, const char *buffer, int len) {
bool receive_tcppacket_sptps(connection_t *c, const char *data, int len) {
if (len < sizeof(node_id_t) + sizeof(node_id_t)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Got too short TCP SPTPS packet from %s (%s)", c->name, c->hostname);
logger(DEBUG_PROTOCOL, LOG_ERR, "Got too short TCP SPTPS packet from %s (%s)", c->name, c->hostname);
return false;
}
@ -499,7 +499,7 @@ static void send_sptps_packet(node_t *n, vpn_packet_t *origpkt) {
uint8_t type = 0;
int offset = 0;
if(!(DATA(origpkt)[12] | DATA(origpkt)[13])) {
if((!(DATA(origpkt)[12] | DATA(origpkt)[13])) && (n->sptps.outstate)) {
sptps_send_record(&n->sptps, PKT_PROBE, (char *)DATA(origpkt), origpkt->len);
return;
}
@ -767,7 +767,7 @@ bool send_sptps_data(node_t *to, node_t *from, int type, const void *data, size_
char buf[len + sizeof to->id + sizeof from->id]; char* buf_ptr = buf;
memcpy(buf_ptr, &to->id, sizeof to->id); buf_ptr += sizeof to->id;
memcpy(buf_ptr, &from->id, sizeof from->id); buf_ptr += sizeof from->id;
memcpy(buf_ptr, data, len); buf_ptr += len;
memcpy(buf_ptr, data, len);
logger(DEBUG_TRAFFIC, LOG_INFO, "Sending packet from %s (%s) to %s (%s) via %s (%s) (TCP)", from->name, from->hostname, to->name, to->hostname, to->nexthop->name, to->nexthop->hostname);
return send_sptps_tcppacket(to->nexthop->connection, buf, sizeof buf);
}

View file

@ -324,62 +324,6 @@ void regenerate_key(void) {
n->status.validkey_in = false;
}
/*
Read Subnets from all host config files
*/
void load_all_subnets(void) {
DIR *dir;
struct dirent *ent;
char dname[PATH_MAX];
snprintf(dname, sizeof dname, "%s" SLASH "hosts", confbase);
dir = opendir(dname);
if(!dir) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", dname, strerror(errno));
return;
}
while((ent = readdir(dir))) {
if(!check_id(ent->d_name))
continue;
node_t *n = lookup_node(ent->d_name);
#ifdef _DIRENT_HAVE_D_TYPE
//if(ent->d_type != DT_REG)
// continue;
#endif
splay_tree_t *config_tree;
init_configuration(&config_tree);
read_config_options(config_tree, ent->d_name);
read_host_config(config_tree, ent->d_name);
if(!n) {
n = new_node();
n->name = xstrdup(ent->d_name);
node_add(n);
}
for(config_t *cfg = lookup_config(config_tree, "Subnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
subnet_t *s, *s2;
if(!get_config_subnet(cfg, &s))
continue;
if((s2 = lookup_subnet(n, s))) {
s2->expires = -1;
free(s);
} else {
subnet_add(n, s);
}
}
exit_configuration(&config_tree);
}
closedir(dir);
}
void load_all_nodes(void) {
DIR *dir;
struct dirent *ent;
@ -397,18 +341,43 @@ void load_all_nodes(void) {
continue;
node_t *n = lookup_node(ent->d_name);
if(n)
continue;
n = new_node();
n->name = xstrdup(ent->d_name);
node_add(n);
splay_tree_t *config_tree;
init_configuration(&config_tree);
read_config_options(config_tree, ent->d_name);
read_host_config(config_tree, ent->d_name);
if(!n) {
n = new_node();
n->name = xstrdup(ent->d_name);
node_add(n);
}
if(strictsubnets) {
for(config_t *cfg = lookup_config(config_tree, "Subnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
subnet_t *s, *s2;
if(!get_config_subnet(cfg, &s))
continue;
if((s2 = lookup_subnet(n, s))) {
s2->expires = -1;
free(s);
} else {
subnet_add(n, s);
}
}
}
if(lookup_config(config_tree, "Address"))
n->status.has_address = true;
exit_configuration(&config_tree);
}
closedir(dir);
}
char *get_name(void) {
char *name = NULL;
char *returned_name;
@ -707,7 +676,7 @@ static bool add_listen_address(char *address, bool bindto) {
int udp_fd = setup_vpn_in_socket((sockaddr_t *) aip->ai_addr);
if(tcp_fd < 0) {
if(udp_fd < 0) {
close(tcp_fd);
continue;
}
@ -947,10 +916,7 @@ static bool setup_myself(void) {
graph();
if(strictsubnets)
load_all_subnets();
else if(autoconnect)
load_all_nodes();
load_all_nodes();
/* Open device */

View file

@ -534,6 +534,8 @@ begin:
} else if(proxytype == PROXY_EXEC) {
result = 0;
} else {
if(!proxyai)
abort();
result = connect(c->socket, proxyai->ai_addr, proxyai->ai_addrlen);
freeaddrinfo(proxyai);
}

View file

@ -234,3 +234,22 @@ void sockaddrunmap(sockaddr_t *sa) {
sa->in.sin_family = AF_INET;
}
}
void sockaddr_setport(sockaddr_t *sa, const char *port) {
uint16_t portnum = htons(atoi(port));
if(!portnum)
return;
switch(sa->sa.sa_family) {
case AF_INET:
sa->in.sin_port = portnum;
break;
case AF_INET6:
sa->in6.sin6_port = portnum;
break;
case AF_UNKNOWN:
free(sa->unknown.port);
sa->unknown.port = xstrdup(port);
default:
return;
}
}

View file

@ -34,5 +34,6 @@ extern int sockaddrcmp_noport(const sockaddr_t *, const sockaddr_t *);
extern void sockaddrunmap(sockaddr_t *);
extern void sockaddrfree(sockaddr_t *);
extern void sockaddrcpy(sockaddr_t *, const sockaddr_t *);
extern void sockaddr_setport(sockaddr_t *, const char *);
#endif /* __TINC_NETUTL_H__ */

View file

@ -40,7 +40,8 @@ typedef struct node_status_t {
unsigned int send_locally:1; /* 1 if the next UDP packet should be sent on the local network */
unsigned int udppacket:1; /* 1 if the most recently received packet was UDP */
unsigned int validkey_in:1; /* 1 if we have sent a valid key to him */
unsigned int unused:21;
unsigned int has_address:1; /* 1 if we know an external address for this node */
unsigned int unused:20;
} node_status_t;
typedef struct node_t {

View file

@ -28,14 +28,16 @@
#include "../xalloc.h"
struct cipher {
EVP_CIPHER_CTX ctx;
EVP_CIPHER_CTX *ctx;
const EVP_CIPHER *cipher;
};
static cipher_t *cipher_open(const EVP_CIPHER *evp_cipher) {
cipher_t *cipher = xzalloc(sizeof *cipher);
cipher->cipher = evp_cipher;
EVP_CIPHER_CTX_init(&cipher->ctx);
cipher->ctx = EVP_CIPHER_CTX_new();
if(!cipher->ctx)
abort();
return cipher;
}
@ -68,7 +70,7 @@ void cipher_close(cipher_t *cipher) {
if(!cipher)
return;
EVP_CIPHER_CTX_cleanup(&cipher->ctx);
EVP_CIPHER_CTX_free(cipher->ctx);
free(cipher);
}
@ -76,23 +78,23 @@ size_t cipher_keylength(const cipher_t *cipher) {
if(!cipher || !cipher->cipher)
return 0;
return cipher->cipher->key_len + cipher->cipher->iv_len;
return EVP_CIPHER_key_length(cipher->cipher) + EVP_CIPHER_iv_length(cipher->cipher);
}
size_t cipher_blocksize(const cipher_t *cipher) {
if(!cipher || !cipher->cipher)
return 1;
return cipher->cipher->block_size;
return EVP_CIPHER_block_size(cipher->cipher);
}
bool cipher_set_key(cipher_t *cipher, void *key, bool encrypt) {
bool result;
if(encrypt)
result = EVP_EncryptInit_ex(&cipher->ctx, cipher->cipher, NULL, (unsigned char *)key, (unsigned char *)key + cipher->cipher->key_len);
result = EVP_EncryptInit_ex(cipher->ctx, cipher->cipher, NULL, (unsigned char *)key, (unsigned char *)key + EVP_CIPHER_key_length(cipher->cipher));
else
result = EVP_DecryptInit_ex(&cipher->ctx, cipher->cipher, NULL, (unsigned char *)key, (unsigned char *)key + cipher->cipher->key_len);
result = EVP_DecryptInit_ex(cipher->ctx, cipher->cipher, NULL, (unsigned char *)key, (unsigned char *)key + EVP_CIPHER_key_length(cipher->cipher));
if(result)
return true;
@ -105,9 +107,9 @@ bool cipher_set_key_from_rsa(cipher_t *cipher, void *key, size_t len, bool encry
bool result;
if(encrypt)
result = EVP_EncryptInit_ex(&cipher->ctx, cipher->cipher, NULL, (unsigned char *)key + len - cipher->cipher->key_len, (unsigned char *)key + len - cipher->cipher->iv_len - cipher->cipher->key_len);
result = EVP_EncryptInit_ex(cipher->ctx, cipher->cipher, NULL, (unsigned char *)key + len - EVP_CIPHER_key_length(cipher->cipher), (unsigned char *)key + len - EVP_CIPHER_iv_length(cipher->cipher) - EVP_CIPHER_key_length(cipher->cipher));
else
result = EVP_DecryptInit_ex(&cipher->ctx, cipher->cipher, NULL, (unsigned char *)key + len - cipher->cipher->key_len, (unsigned char *)key + len - cipher->cipher->iv_len - cipher->cipher->key_len);
result = EVP_DecryptInit_ex(cipher->ctx, cipher->cipher, NULL, (unsigned char *)key + len - EVP_CIPHER_key_length(cipher->cipher), (unsigned char *)key + len - EVP_CIPHER_iv_length(cipher->cipher) - EVP_CIPHER_key_length(cipher->cipher));
if(result)
return true;
@ -119,15 +121,15 @@ bool cipher_set_key_from_rsa(cipher_t *cipher, void *key, size_t len, bool encry
bool cipher_encrypt(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) {
if(oneshot) {
int len, pad;
if(EVP_EncryptInit_ex(&cipher->ctx, NULL, NULL, NULL, NULL)
&& EVP_EncryptUpdate(&cipher->ctx, (unsigned char *)outdata, &len, indata, inlen)
&& EVP_EncryptFinal(&cipher->ctx, (unsigned char *)outdata + len, &pad)) {
if(EVP_EncryptInit_ex(cipher->ctx, NULL, NULL, NULL, NULL)
&& EVP_EncryptUpdate(cipher->ctx, (unsigned char *)outdata, &len, indata, inlen)
&& EVP_EncryptFinal(cipher->ctx, (unsigned char *)outdata + len, &pad)) {
if(outlen) *outlen = len + pad;
return true;
}
} else {
int len;
if(EVP_EncryptUpdate(&cipher->ctx, outdata, &len, indata, inlen)) {
if(EVP_EncryptUpdate(cipher->ctx, outdata, &len, indata, inlen)) {
if(outlen) *outlen = len;
return true;
}
@ -140,15 +142,15 @@ bool cipher_encrypt(cipher_t *cipher, const void *indata, size_t inlen, void *ou
bool cipher_decrypt(cipher_t *cipher, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool oneshot) {
if(oneshot) {
int len, pad;
if(EVP_DecryptInit_ex(&cipher->ctx, NULL, NULL, NULL, NULL)
&& EVP_DecryptUpdate(&cipher->ctx, (unsigned char *)outdata, &len, indata, inlen)
&& EVP_DecryptFinal(&cipher->ctx, (unsigned char *)outdata + len, &pad)) {
if(EVP_DecryptInit_ex(cipher->ctx, NULL, NULL, NULL, NULL)
&& EVP_DecryptUpdate(cipher->ctx, (unsigned char *)outdata, &len, indata, inlen)
&& EVP_DecryptFinal(cipher->ctx, (unsigned char *)outdata + len, &pad)) {
if(outlen) *outlen = len + pad;
return true;
}
} else {
int len;
if(EVP_EncryptUpdate(&cipher->ctx, outdata, &len, indata, inlen)) {
if(EVP_EncryptUpdate(cipher->ctx, outdata, &len, indata, inlen)) {
if(outlen) *outlen = len;
return true;
}
@ -162,9 +164,9 @@ int cipher_get_nid(const cipher_t *cipher) {
if(!cipher || !cipher->cipher)
return 0;
return cipher->cipher->nid;
return EVP_CIPHER_nid(cipher->cipher);
}
bool cipher_active(const cipher_t *cipher) {
return cipher && cipher->cipher && cipher->cipher->nid != 0;
return cipher && cipher->cipher && EVP_CIPHER_nid(cipher->cipher) != 0;
}

View file

@ -93,14 +93,19 @@ bool digest_create(digest_t *digest, const void *indata, size_t inlen, void *out
return false;
}
} else {
EVP_MD_CTX ctx;
EVP_MD_CTX *ctx = EVP_MD_CTX_create();
if(!ctx)
abort();
if(!EVP_DigestInit(&ctx, digest->digest)
|| !EVP_DigestUpdate(&ctx, indata, inlen)
|| !EVP_DigestFinal(&ctx, tmpdata, NULL)) {
if(!EVP_DigestInit(ctx, digest->digest)
|| !EVP_DigestUpdate(ctx, indata, inlen)
|| !EVP_DigestFinal(ctx, tmpdata, NULL)) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "Error creating digest: %s", ERR_error_string(ERR_get_error(), NULL));
EVP_MD_CTX_destroy(ctx);
return false;
}
EVP_MD_CTX_destroy(ctx);
}
memcpy(outdata, tmpdata, digest->maclength);
@ -118,14 +123,14 @@ int digest_get_nid(const digest_t *digest) {
if(!digest || !digest->digest)
return 0;
return digest->digest->type;
return EVP_MD_type(digest->digest);
}
size_t digest_keylength(const digest_t *digest) {
if(!digest || !digest->digest)
return 0;
return digest->digest->md_size;
return EVP_MD_size(digest->digest);
}
size_t digest_length(const digest_t *digest) {
@ -136,5 +141,5 @@ size_t digest_length(const digest_t *digest) {
}
bool digest_active(const digest_t *digest) {
return digest && digest->digest && digest->digest->type != 0;
return digest && digest->digest && EVP_MD_type(digest->digest) != 0;
}

View file

@ -30,28 +30,51 @@ typedef RSA rsa_t;
// Set RSA keys
#ifndef HAVE_RSA_SET0_KEY
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) {
BN_free(r->n); r->n = n;
BN_free(r->e); r->e = e;
BN_free(r->d); r->d = d;
return 1;
}
#endif
rsa_t *rsa_set_hex_public_key(char *n, char *e) {
BIGNUM *bn_n = NULL;
BIGNUM *bn_e = NULL;
if(BN_hex2bn(&bn_n, n) != strlen(n) || BN_hex2bn(&bn_e, e) != strlen(e)) {
BN_free(bn_e);
BN_free(bn_n);
return false;
}
rsa_t *rsa = RSA_new();
if(!rsa)
return NULL;
if(BN_hex2bn(&rsa->n, n) != strlen(n) || BN_hex2bn(&rsa->e, e) != strlen(e)) {
RSA_free(rsa);
return false;
}
RSA_set0_key(rsa, bn_n, bn_e, NULL);
return rsa;
}
rsa_t *rsa_set_hex_private_key(char *n, char *e, char *d) {
BIGNUM *bn_n = NULL;
BIGNUM *bn_e = NULL;
BIGNUM *bn_d = NULL;
if(BN_hex2bn(&bn_n, n) != strlen(n) || BN_hex2bn(&bn_e, e) != strlen(e) || BN_hex2bn(&bn_d, d) != strlen(d)) {
BN_free(bn_d);
BN_free(bn_e);
BN_free(bn_n);
return false;
}
rsa_t *rsa = RSA_new();
if(!rsa)
return NULL;
if(BN_hex2bn(&rsa->n, n) != strlen(n) || BN_hex2bn(&rsa->e, e) != strlen(e) || BN_hex2bn(&rsa->d, d) != strlen(d)) {
RSA_free(rsa);
return false;
}
RSA_set0_key(rsa, bn_n, bn_e, bn_d);
return rsa;
}

View file

@ -27,10 +27,11 @@ typedef RSA rsa_t;
#include "../logger.h"
#include "../rsagen.h"
#include "../xalloc.h"
/* This function prettyprints the key generation process */
static void indicator(int a, int b, void *p) {
static int indicator(int a, int b, BN_GENCB *cb) {
switch (a) {
case 0:
fprintf(stderr, ".");
@ -62,12 +63,45 @@ static void indicator(int a, int b, void *p) {
default:
fprintf(stderr, "?");
}
return 1;
}
// Generate RSA key
#ifndef HAVE_BN_GENCB_NEW
BN_GENCB *BN_GENCB_new(void) {
return xzalloc(sizeof(BN_GENCB));
}
void BN_GENCB_free(BN_GENCB *cb) {
free(cb);
}
#endif
rsa_t *rsa_generate(size_t bits, unsigned long exponent) {
return RSA_generate_key(bits, exponent, indicator, NULL);
BIGNUM *bn_e = BN_new();
rsa_t *rsa = RSA_new();
BN_GENCB *cb = BN_GENCB_new();
if(!bn_e || !rsa || !cb)
abort();
BN_set_word(bn_e, exponent);
BN_GENCB_set(cb, indicator, NULL);
int result = RSA_generate_key_ex(rsa, bits, bn_e, cb);
BN_GENCB_free(cb);
BN_free(bn_e);
if(!result) {
fprintf(stderr, "Error during key generation!\n");
RSA_free(rsa);
return NULL;
}
return rsa;
}
// Write PEM RSA keys

View file

@ -72,10 +72,11 @@ bool send_request(connection_t *c, const char *format, ...) {
input buffer anyway */
va_start(args, format);
len = vsnprintf(request, MAXBUFSIZE, format, args);
len = vsnprintf(request, sizeof request, format, args);
request[sizeof request - 1] = 0;
va_end(args);
if(len < 0 || len > MAXBUFSIZE - 1) {
if(len < 0 || len > sizeof request - 1) {
logger(DEBUG_ALWAYS, LOG_ERR, "Output buffer overflow while sending request to %s (%s)",
c->name, c->hostname);
return false;

View file

@ -790,7 +790,6 @@ bool ack_h(connection_t *c, const char *request) {
return upgrade_h(c, request);
char hisport[MAX_STRING_SIZE];
char *hisaddress;
int weight, mtu;
uint32_t options;
node_t *n;
@ -867,19 +866,14 @@ bool ack_h(connection_t *c, const char *request) {
c->edge = new_edge();
c->edge->from = myself;
c->edge->to = n;
sockaddr2str(&c->address, &hisaddress, NULL);
c->edge->address = str2sockaddr(hisaddress, hisport);
free(hisaddress);
sockaddrcpy(&c->edge->address, &c->address);
sockaddr_setport(&c->edge->address, hisport);
sockaddr_t local_sa;
socklen_t local_salen = sizeof local_sa;
if (getsockname(c->socket, &local_sa.sa, &local_salen) < 0)
logger(DEBUG_ALWAYS, LOG_WARNING, "Could not get local socket address for connection with %s", c->name);
else {
char *local_address;
sockaddr2str(&local_sa, &local_address, NULL);
c->edge->local_address = str2sockaddr(local_address, myport);
free(local_address);
}
else
sockaddr_setport(&local_sa, myport);
c->edge->weight = (weight + c->estimated_weight) / 2;
c->edge->connection = c;
c->edge->options = c->options;

View file

@ -547,8 +547,6 @@ size_t sptps_receive_data(sptps_t *s, const void *data, size_t len) {
memcpy(s->inbuf + s->buflen, data, toread);
total_read += toread;
s->buflen += toread;
len -= toread;
data += toread;
// If we don't have a whole record, exit.
if(s->buflen < s->reclen + (s->instate ? 19UL : 3UL))

View file

@ -560,6 +560,7 @@ bool sendline(int fd, char *format, ...) {
va_start(ap, format);
blen = vsnprintf(buffer, sizeof buffer, format, ap);
buffer[sizeof buffer - 1] = 0;
va_end(ap);
if(blen < 1 || blen >= sizeof buffer)
@ -718,6 +719,13 @@ bool connect_tincd(bool verbose) {
}
fclose(f);
if ((pid == 0) || (kill(pid, 0) && (errno == ESRCH))) {
fprintf(stderr, "Could not find tincd running at pid %d\n", pid);
/* clean up the stale socket and pid file */
unlink(pidfilename);
unlink(unixsocketname);
return false;
}
#ifndef HAVE_MINGW
struct sockaddr_un sa;
@ -878,7 +886,7 @@ static int cmd_start(int argc, char *argv[]) {
if(!pid) {
close(pfd[0]);
char buf[100] = "";
char buf[100];
snprintf(buf, sizeof buf, "%d", pfd[1]);
setenv("TINC_UMBILICAL", buf, true);
exit(execvp(c, nargv));
@ -1384,7 +1392,7 @@ static int cmd_pid(int argc, char *argv[]) {
return 1;
}
if(!connect_tincd(true) && !pid)
if(!connect_tincd(true) || !pid)
return 1;
printf("%d\n", pid);
@ -2513,6 +2521,7 @@ static int cmd_verify(int argc, char *argv[]) {
char *newline = memchr(data, '\n', len);
if(!newline || (newline - data > MAX_STRING_SIZE - 1)) {
fprintf(stderr, "Invalid input\n");
free(data);
return 1;
}
@ -2525,11 +2534,13 @@ static int cmd_verify(int argc, char *argv[]) {
if(sscanf(data, "Signature = %s %ld %s", signer, &t, sig) != 3 || strlen(sig) != 86 || !t || !check_id(signer)) {
fprintf(stderr, "Invalid input\n");
free(data);
return 1;
}
if(node && strcmp(node, signer)) {
fprintf(stderr, "Signature is not made by %s\n", node);
free(data);
return 1;
}
@ -2823,8 +2834,10 @@ static int cmd_shell(int argc, char *argv[]) {
if(nargc == argc)
continue;
if(!strcasecmp(nargv[argc], "exit") || !strcasecmp(nargv[argc], "quit"))
if(!strcasecmp(nargv[argc], "exit") || !strcasecmp(nargv[argc], "quit")) {
free(nargv);
return result;
}
bool found = false;