project('tinc', 'c',
- version: run_command('./src/git_tag.sh', check: true).stdout().strip(),
+ version: '1.18pre',
license: 'GPL-2.0-or-later',
meson_version: '>=0.51',
default_options: [
dir_run_state = get_option('runstatedir')
opt_crypto = get_option('crypto')
opt_curses = get_option('curses')
+opt_debug = get_option('debug')
opt_docs = get_option('docs')
opt_harden = get_option('hardening')
opt_jumbograms = get_option('jumbograms')
cc = meson.get_compiler('c')
os_name = host_machine.system()
+cpu_family = host_machine.cpu_family()
cc_name = cc.get_id()
cc_defs = ['-D_GNU_SOURCE']
static = opt_static.enabled()
endif
-if static
+if static and cc_name != 'msvc'
ld_flags += '-static'
endif
if opt_harden
- cc_flags += [
- '-D_FORTIFY_SOURCE=2',
- '-fwrapv',
- '-fno-strict-overflow',
- '-Wreturn-type',
- '-Wold-style-definition',
- '-Wmissing-declarations',
- '-Wmissing-prototypes',
- '-Wstrict-prototypes',
- '-Wredundant-decls',
- '-Wbad-function-cast',
- '-Wwrite-strings',
- '-fdiagnostics-show-option',
- '-fstrict-aliasing',
- '-Wmissing-noreturn',
- ]
- if cc_name == 'clang'
- cc_flags += '-Qunused-arguments'
- endif
- ld_flags += ['-Wl,-z,relro', '-Wl,-z,now']
- if os_name == 'windows'
- ld_flags += ['-Wl,--dynamicbase', '-Wl,--nxcompat']
+ if cc_name == 'msvc'
+ # Most of these flags are already ON by default in the latest version of MSVC.
+ # Add anyway in case someone is building using an old toolchain.
+ cc_flags += ['/guard:cf', '/GS']
+ ld_flags += [
+ '/guard:cf',
+ '/NXCOMPAT',
+ '/DYNAMICBASE',
+ cpu_family.endswith('64') ? '/HIGHENTROPYVA' : '/SAFESEH',
+ ]
+ else
+ cc_flags += [
+ '-D_FORTIFY_SOURCE=2',
+ '-fwrapv',
+ '-fno-strict-overflow',
+ '-Wreturn-type',
+ '-Wold-style-definition',
+ '-Wmissing-declarations',
+ '-Wmissing-prototypes',
+ '-Wstrict-prototypes',
+ '-Wredundant-decls',
+ '-Wbad-function-cast',
+ '-Wwrite-strings',
+ '-fdiagnostics-show-option',
+ '-fstrict-aliasing',
+ '-Wmissing-noreturn',
+ ]
+ if cc_name == 'clang'
+ cc_flags += '-Qunused-arguments'
+ endif
+ ld_flags += ['-Wl,-z,relro', '-Wl,-z,now']
+ if os_name == 'windows'
+ ld_flags += ['-Wl,--dynamicbase', '-Wl,--nxcompat']
+ endif
endif
endif
return 0;
}
#endif
+
+bool sleep_millis(unsigned int ms) {
+#ifdef _MSC_VER
+ Sleep(ms);
+ return true;
+#else
+ return !usleep(ms * 1000);
+#endif
+}
#define MAX(a,b) (((a)>(b))?(a):(b))
#endif
-#endif
+#ifdef _MSC_VER
+
+#define __attribute(args)
+#define __attribute__(args)
+
+#define PATH_MAX MAX_PATH
+#define strcasecmp _stricmp
+#define strncasecmp _strnicmp
+#define __const const
+
+typedef int mode_t;
+typedef int pid_t;
+typedef SSIZE_T ssize_t;
+
+static const int STDIN_FILENO = 0;
+static const int F_OK = 0;
+static const int X_OK = 0;
+static const int W_OK = 2;
+static const int R_OK = 4;
+
+#else // _MSC_VER
+
+#endif // _MSC_VER
+
+extern bool sleep_millis(unsigned int ms);
+
+#endif // TINC_DROPIN_H
Not a compatible replacement for <stdint.h>, do not blindly use it as such.
*/
-#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined(__WATCOMC__) && (defined(_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_) || defined(__UINT_FAST64_TYPE__)) )) && !defined(FIXEDINT_H_INCLUDED)
+#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined(_MSC_VER) && _MSC_VER >= 1600) || (defined(__WATCOMC__) && (defined(_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_) || defined(__UINT_FAST64_TYPE__)) )) && !defined(FIXEDINT_H_INCLUDED)
#include <stdint.h>
#define FIXEDINT_H_INCLUDED
uint8_t ether_dhost[ETH_ALEN];
uint8_t ether_shost[ETH_ALEN];
uint16_t ether_type;
-} __attribute__((__gcc_struct__)) __attribute((__packed__));
+};
#endif
#ifndef HAVE_STRUCT_ARPHDR
uint8_t ar_hln;
uint8_t ar_pln;
uint16_t ar_op;
-} __attribute__((__gcc_struct__)) __attribute((__packed__));
+};
#define ARPOP_REQUEST 1
#define ARPOP_REPLY 2
uint8_t arp_spa[4];
uint8_t arp_tha[ETH_ALEN];
uint8_t arp_tpa[4];
-} __attribute__((__gcc_struct__)) __attribute((__packed__));
+};
#define arp_hrd ea_hdr.ar_hrd
#define arp_pro ea_hdr.ar_pro
#define arp_hln ea_hdr.ar_hln
++total_vars;
}
- int count[total_vars];
- memset(count, 0, sizeof(count));
+ const size_t countlen = total_vars * sizeof(int);
+ int *count = alloca(countlen);
+ memset(count, 0, countlen);
for splay_each(config_t, conf, &config) {
int var_type = 0;
+++ /dev/null
-#!/bin/sh
-
-git describe --always --tags --match='release-*' "$@" | sed 's/release-//'
#define WINVER 0x0600
#define _WIN32_WINNT 0x0600
#define WIN32_LEAN_AND_MEAN
+#define _CRT_SECURE_NO_WARNINGS
+#define _CRT_NONSTDC_NO_WARNINGS
#endif
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
+#endif
#include <limits.h>
#include <math.h>
#include <time.h>
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#elif defined(HAVE_NETBSD)
+#define alloca(size) __builtin_alloca(size)
+#endif
+
#ifdef HAVE_MINGW
+#ifdef HAVE_W32API_H
#include <w32api.h>
+#endif
+
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
+
+#ifdef _MSC_VER
+#include <io.h>
+#include <process.h>
+#include <direct.h>
#endif
+#endif // HAVE_MINGW
#ifdef HAVE_TERMIOS_H
#include <termios.h>
#ifdef HAVE_DIRENT_H
#include <dirent.h>
+#elif defined(_MSC_VER)
+#include "dirent.h"
#endif
/* SunOS really wants sys/socket.h BEFORE net/if.h,
configure_file(output: 'config.h', configuration: cdata)
src_lib_common += vcs_tag(
- command: './git_tag.sh',
+ command: ['git', 'describe', '--always', '--tags', '--match=release-*'],
fallback: 'unknown',
input: '../version_git.h.in',
output: 'version_git.h',
randomize(cookie, 18);
// Create a filename that doesn't reveal the cookie itself
- uint8_t buf[18 + strlen(fingerprint)];
+ const size_t buflen = 18 + strlen(fingerprint);
+ uint8_t *buf = alloca(buflen);
+
char cookiehash[64];
memcpy(buf, cookie, 18);
- memcpy(buf + 18, fingerprint, sizeof(buf) - 18);
- sha512(buf, sizeof(buf), cookiehash);
+ memcpy(buf + 18, fingerprint, buflen - 18);
+ sha512(buf, buflen, cookiehash);
b64encode_tinc_urlsafe(cookiehash, cookiehash, 18);
free(fingerprint);
static size_t datalen;
static bool success = false;
-static char *get_line(const char **data) {
+static char *get_line(char *line, size_t linelen, const char **data) {
if(!data || !*data) {
return NULL;
}
return NULL;
}
- static char line[1024];
const char *end = strchr(*data, '\n');
size_t len = end ? (size_t)(end - *data) : strlen(*data);
- if(len >= sizeof(line)) {
+ if(len >= linelen) {
fprintf(stderr, "Maximum line length exceeded!\n");
return NULL;
}
}
static char *get_value(const char *data, const char *var) {
- char *line = get_line(&data);
+ static char buf[1024];
+
+ char *line = get_line(buf, sizeof(buf), &data);
if(!line) {
return NULL;
}
static bool finalize_join(void) {
- const char *temp_name = get_value(data, "Name");
+ const char *name = get_value(data, "Name");
- if(!temp_name) {
+ if(!name) {
fprintf(stderr, "No Name found in invitation!\n");
return false;
}
- size_t len = strlen(temp_name);
- char name[len + 1];
- memcpy(name, temp_name, len);
- name[len] = 0;
-
if(!check_id(name)) {
fprintf(stderr, "Invalid Name found in invitation!\n");
return false;
const char *p = data;
char *l, *value;
- while((l = get_line(&p))) {
+ static char line[1024];
+
+ while((l = get_line(line, sizeof(line), &p))) {
// Ignore comments
if(*l == '#') {
continue;
return false;
}
- while((l = get_line(&p))) {
+ while((l = get_line(line, sizeof(line), &p))) {
if(!strcmp(l, "#---------------------------------------------------------------#")) {
continue;
}
uint8_t ip_p;
uint16_t ip_sum;
struct in_addr ip_src, ip_dst;
-} __attribute__((__gcc_struct__)) __attribute((__packed__));
+};
#endif
#ifndef IP_OFFMASK
#define icmp_radv icmp_dun.id_radv
#define icmp_mask icmp_dun.id_mask
#define icmp_data icmp_dun.id_data
-} __attribute__((__gcc_struct__)) __attribute((__packed__));
+};
#endif
#endif
} ip6_ctlun;
struct in6_addr ip6_src;
struct in6_addr ip6_dst;
-} __attribute__((__gcc_struct__)) __attribute((__packed__));
+};
#define ip6_vfc ip6_ctlun.ip6_un2_vfc
#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow
#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen
uint16_t icmp6_un_data16[2];
uint8_t icmp6_un_data8[4];
} icmp6_dataun;
-} __attribute__((__gcc_struct__)) __attribute((__packed__));
+};
#define ICMP6_DST_UNREACH_NOROUTE 0
#define ICMP6_DST_UNREACH 1
#define ICMP6_PACKET_TOO_BIG 2
struct nd_neighbor_solicit {
struct icmp6_hdr nd_ns_hdr;
struct in6_addr nd_ns_target;
-} __attribute__((__gcc_struct__)) __attribute((__packed__));
+};
#define ND_OPT_SOURCE_LINKADDR 1
#define ND_OPT_TARGET_LINKADDR 2
#define nd_ns_type nd_ns_hdr.icmp6_type
struct nd_opt_hdr {
uint8_t nd_opt_type;
uint8_t nd_opt_len;
-} __attribute__((__gcc_struct__)) __attribute((__packed__));
+};
#endif
#endif
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include "system.h"
+
typedef enum debug_t {
DEBUG_UNSET = -1, /* Used by tinc as the default debug level. */
DEBUG_NOTHING = 0, /* Quiet mode, only show starting/stopping of the daemon */
endforeach
check_headers = [
+ 'alloca.h',
'arpa/inet.h',
'arpa/nameser.h',
'dirent.h',
'sys/types.h',
'sys/wait.h',
'syslog.h',
+ 'string.h',
'termios.h',
+ 'unistd.h',
]
# 'struct msghdr' misses some required fields
-win_common_libs = ['ws2_32', 'iphlpapi', 'winpthread']
+check_headers += 'w32api.h'
-if opt_harden
+win_common_libs = ['ws2_32', 'iphlpapi', 'threads']
+
+if opt_harden and cc_name != 'msvc'
win_common_libs += 'ssp'
endif
foreach libname : win_common_libs
- deps_common += cc.find_library(libname)
+ dep = dependency(libname, required: false)
+ if not dep.found()
+ dep = cc.find_library(libname)
+ endif
+ deps_common += dep
endforeach
src_tincd += files('device.c')
if(contradicting_del_edge > 100 && contradicting_add_edge > 100) {
logger(DEBUG_ALWAYS, LOG_WARNING, "Possible node with same Name as us! Sleeping %d seconds.", sleeptime);
- nanosleep(&(struct timespec) {
- sleeptime, 0
- }, NULL);
+ sleep_millis(sleeptime * 1000);
sleeptime *= 2;
if(sleeptime < 0) {
if(type == SPTPS_HANDSHAKE || tcponly || (!direct && !relay_supported) || (type != PKT_PROBE && origlen > relay->minmtu)) {
if(type != SPTPS_HANDSHAKE && (to->nexthop->connection->options >> 24) >= 7) {
- uint8_t buf[len + sizeof(to->id) + sizeof(from->id)];
+ const size_t buflen = len + sizeof(to->id) + sizeof(from->id);
+ uint8_t *buf = alloca(buflen);
uint8_t *buf_ptr = buf;
memcpy(buf_ptr, &to->id, sizeof(to->id));
buf_ptr += sizeof(to->id);
buf_ptr += sizeof(from->id);
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));
+ return send_sptps_tcppacket(to->nexthop->connection, buf, buflen);
}
- char buf[B64_SIZE(len)];
+ char *buf = alloca(B64_SIZE(len));
b64encode_tinc(data, buf, len);
/* If this is a handshake packet, use ANS_KEY instead of REQ_KEY, for two reasons:
overhead += sizeof(to->id) + sizeof(from->id);
}
- char buf[len + overhead];
+ char *buf = alloca(len + overhead);
char *buf_ptr = buf;
if(relay_supported) {
myself->in_bytes += packet.len;
route(myself, &packet);
} else {
- usleep(errors * 50000);
+ sleep_millis(errors * 50);
errors++;
if(errors > 10) {
static const size_t blklen = 128;
static bool hmac_sha512(const uint8_t *key, size_t keylen, const uint8_t *msg, size_t msglen, uint8_t *out) {
- uint8_t tmp[blklen + mdlen];
+ const size_t tmplen = blklen + mdlen;
+ uint8_t *tmp = alloca(tmplen);
sha512_context md;
if(keylen <= blklen) {
// opad
memxor(tmp, 0x36 ^ 0x5c, blklen);
- if(sha512(tmp, sizeof(tmp), out) != 0) {
+ if(sha512(tmp, tmplen, out) != 0) {
return false;
}
It consists of the previous HMAC result plus the seed.
*/
- uint8_t data[mdlen + seedlen];
+ const size_t datalen = mdlen + seedlen;
+ uint8_t *data = alloca(datalen);
memset(data, 0, mdlen);
memcpy(data + mdlen, seed, seedlen);
- uint8_t hash[mdlen];
+ uint8_t *hash = alloca(mdlen);
while(outlen > 0) {
/* Inner HMAC */
- if(!hmac_sha512(secret, secretlen, data, sizeof(data), data)) {
+ if(!hmac_sha512(secret, secretlen, data, datalen, data)) {
return false;
}
/* Outer HMAC */
if(outlen >= mdlen) {
- if(!hmac_sha512(secret, secretlen, data, sizeof(data), out)) {
+ if(!hmac_sha512(secret, secretlen, data, datalen, out)) {
return false;
}
out += mdlen;
outlen -= mdlen;
} else {
- if(!hmac_sha512(secret, secretlen, data, sizeof(data), hash)) {
+ if(!hmac_sha512(secret, secretlen, data, datalen, hash)) {
return false;
}
bool digest_create(digest_t *digest, const void *indata, size_t inlen, void *outdata) {
size_t len = EVP_MD_size(digest->digest);
- unsigned char tmpdata[len];
+ unsigned char *tmpdata = alloca(len);
if(digest->hmac_ctx) {
bool ok;
ok = mac_ctx
&& EVP_MAC_update(mac_ctx, indata, inlen)
- && EVP_MAC_final(mac_ctx, tmpdata, NULL, sizeof(tmpdata));
+ && EVP_MAC_final(mac_ctx, tmpdata, NULL, len);
EVP_MAC_CTX_free(mac_ctx);
#endif
bool digest_verify(digest_t *digest, const void *indata, size_t inlen, const void *cmpdata) {
size_t len = digest->maclength;
- unsigned char outdata[len];
+ unsigned char *outdata = alloca(len);
return digest_create(digest, indata, inlen, outdata) && !memcmp(cmpdata, outdata, digest->maclength);
}
It consists of the previous HMAC result plus the seed.
*/
- char data[len + seedlen];
+ char *data = alloca(len + seedlen);
memset(data, 0, len);
memcpy(data + len, seed, seedlen);
- uint8_t hash[len];
+ uint8_t *hash = alloca(len);
while(outlen > 0) {
/* Inner HMAC */
// Create a temporary newline-terminated copy of the request
size_t len = strlen(request);
- char tmp[len + 1];
+ const size_t tmplen = len + 1;
+ char *tmp = alloca(tmplen);
memcpy(tmp, request, len);
tmp[len] = '\n';
- broadcast_meta(from, tmp, sizeof(tmp));
+ broadcast_meta(from, tmp, tmplen);
}
bool receive_request(connection_t *c, const char *request) {
return false;
}
- uint8_t s4req[9 + (proxyuser ? strlen(proxyuser) : 0)];
+ const size_t s4reqlen = 9 + (proxyuser ? strlen(proxyuser) : 0);
+ uint8_t *s4req = alloca(s4reqlen);
s4req[0] = 4;
s4req[1] = 1;
memcpy(s4req + 2, &c->address.in.sin_port, 2);
memcpy(s4req + 8, proxyuser, strlen(proxyuser));
}
- s4req[sizeof(s4req) - 1] = 0;
+ s4req[s4reqlen - 1] = 0;
c->tcplen = 8;
- return send_meta(c, s4req, sizeof(s4req));
+ return send_meta(c, s4req, s4reqlen);
}
case PROXY_SOCKS5: {
len += 3 + strlen(proxyuser) + strlen(proxypass);
}
- uint8_t s5req[len];
+ uint8_t *s5req = alloca(len);
+
size_t i = 0;
s5req[i++] = 5;
s5req[i++] = 1;
abort();
}
- return send_meta(c, s5req, sizeof(s5req));
+ return send_meta(c, s5req, len);
}
case PROXY_SOCKS4A:
// Recover the filename from the cookie and the key
char *fingerprint = ecdsa_get_base64_public_key(invitation_key);
- char hashbuf[18 + strlen(fingerprint)];
+ const size_t hashbuflen = 18 + strlen(fingerprint);
+ char *hashbuf = alloca(hashbuflen);
char cookie[64];
memcpy(hashbuf, data, 18);
- memcpy(hashbuf + 18, fingerprint, sizeof(hashbuf) - 18);
- sha512(hashbuf, sizeof(hashbuf), cookie);
+ memcpy(hashbuf + 18, fingerprint, hashbuflen - 18);
+ sha512(hashbuf, hashbuflen, cookie);
b64encode_tinc_urlsafe(cookie, cookie, 18);
free(fingerprint);
if(c->protocol_minor >= 2) {
c->allow_request = ACK;
- char label[25 + strlen(myself->name) + strlen(c->name)];
+
+ const size_t labellen = 25 + strlen(myself->name) + strlen(c->name);
+ char *label = alloca(labellen);
if(c->outgoing) {
- snprintf(label, sizeof(label), "tinc TCP key expansion %s %s", myself->name, c->name);
+ snprintf(label, labellen, "tinc TCP key expansion %s %s", myself->name, c->name);
} else {
- snprintf(label, sizeof(label), "tinc TCP key expansion %s %s", c->name, myself->name);
+ snprintf(label, labellen, "tinc TCP key expansion %s %s", c->name, myself->name);
}
- return sptps_start(&c->sptps, c, c->outgoing, false, myself->connection->ecdsa, c->ecdsa, label, sizeof(label), send_meta_sptps, receive_meta_sptps);
+ return sptps_start(&c->sptps, c, c->outgoing, false, myself->connection->ecdsa, c->ecdsa, label, labellen, send_meta_sptps, receive_meta_sptps);
} else {
return send_metakey(c);
}
}
const size_t len = rsa_size(c->rsa);
- char key[len];
- char enckey[len];
- char hexkey[2 * len + 1];
+ char *key = alloca(len);
+ char *enckey = alloca(len);
+ char *hexkey = alloca(2 * len + 1);
/* Create a random key */
char hexkey[MAX_STRING_SIZE];
int cipher, digest, maclength, compression;
const size_t len = rsa_size(myself->connection->rsa);
- char enckey[len];
- char key[len];
+ char *enckey = alloca(len);
+ char *key = alloca(len);
if(sscanf(request, "%*d %d %d %d %d " MAX_STRING, &cipher, &digest, &maclength, &compression, hexkey) != 5) {
logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "METAKEY", c->name, c->hostname);
/* Convert the challenge from hexadecimal back to binary */
- size_t inlen = hex2bin(hexkey, enckey, sizeof(enckey));
+ size_t inlen = hex2bin(hexkey, enckey, len);
/* Check if the length of the meta key is all right */
bool send_challenge(connection_t *c) {
const size_t len = rsa_size(c->rsa);
- char buffer[len * 2 + 1];
+ char *buffer = alloca(len * 2 + 1);
c->hischallenge = xrealloc(c->hischallenge, len);
bool send_chal_reply(connection_t *c) {
const size_t len = rsa_size(myself->connection->rsa);
size_t digestlen = digest_length(&c->indigest);
- char digest[digestlen * 2 + 1];
+ char *digest = alloca(digestlen * 2 + 1);
/* Calculate the hash from the challenge we received */
node_t *to = handle;
to->sptps.send_data = send_sptps_data_myself;
- char buf[B64_SIZE(len)];
+ char *buf = alloca(B64_SIZE(len));
b64encode_tinc(data, buf, len);
return send_request(to->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, to->name, REQ_KEY, buf);
return true;
}
- char label[25 + strlen(myself->name) + strlen(to->name)];
- snprintf(label, sizeof(label), "tinc UDP key expansion %s %s", myself->name, to->name);
+ const size_t labellen = 25 + strlen(myself->name) + strlen(to->name);
+ char *label = alloca(labellen);
+ snprintf(label, labellen, "tinc UDP key expansion %s %s", myself->name, to->name);
+
sptps_stop(&to->sptps);
to->status.validkey = false;
to->status.waitingforkey = true;
to->last_req_key = now.tv_sec;
to->incompression = myself->incompression;
- return sptps_start(&to->sptps, to, true, true, myself->connection->ecdsa, to->ecdsa, label, sizeof(label), send_initial_sptps_data, receive_sptps_record);
+ return sptps_start(&to->sptps, to, true, true, myself->connection->ecdsa, to->ecdsa, label, labellen, send_initial_sptps_data, receive_sptps_record);
}
return send_request(to->nexthop->connection, "%d %s %s", REQ_KEY, myself->name, to->name);
return true;
}
- char label[25 + strlen(from->name) + strlen(myself->name)];
- snprintf(label, sizeof(label), "tinc UDP key expansion %s %s", from->name, myself->name);
+ const size_t labellen = 25 + strlen(from->name) + strlen(myself->name);
+ char *label = alloca(labellen);
+ snprintf(label, labellen, "tinc UDP key expansion %s %s", from->name, myself->name);
sptps_stop(&from->sptps);
from->status.validkey = false;
from->status.waitingforkey = true;
from->last_req_key = now.tv_sec;
- sptps_start(&from->sptps, from, false, true, myself->connection->ecdsa, from->ecdsa, label, sizeof(label), send_sptps_data_myself, receive_sptps_record);
+ sptps_start(&from->sptps, from, false, true, myself->connection->ecdsa, from->ecdsa, label, labellen, send_sptps_data_myself, receive_sptps_record);
sptps_receive_data(&from->sptps, buf, len);
send_mtu_info(myself, from, MTU);
return true;
return false;
#else
size_t keylen = myself->incipher ? cipher_keylength(myself->incipher) : 1;
- char key[keylen * 2 + 1];
+ char *key = alloca(keylen * 2 + 1);
randomize(key, keylen);
/* SPTPS or old-style key exchange? */
if(from->status.sptps) {
- uint8_t buf[strlen(key)];
- size_t len = b64decode_tinc(key, buf, strlen(key));
+ const size_t buflen = strlen(key);
+ uint8_t *buf = alloca(buflen);
+ size_t len = b64decode_tinc(key, buf, buflen);
if(!len || !sptps_receive_data(&from->sptps, buf, len)) {
/* Uh-oh. It might be that the tunnel is stuck in some corrupted state,
len++;
#endif
#endif
- char var[len + 1];
+ char *var = alloca(len + 1);
strncpy(var, p, len);
var[len] = 0;
#ifdef HAVE_UNSETENV
size_t pathlen = strlen(pathext);
size_t scriptlen = strlen(scriptname);
- char fullname[scriptlen + pathlen + 1];
+
+ const size_t fullnamelen = scriptlen + pathlen + 1;
+ char *fullname = alloca(fullnamelen);
char *ext = fullname + scriptlen;
- strncpy(fullname, scriptname, sizeof(fullname));
+ strncpy(fullname, scriptname, fullnamelen);
const char *p = pathext;
bool found = false;
// Send a record (datagram version, accepts all record types, handles encryption and authentication).
static bool send_record_priv_datagram(sptps_t *s, uint8_t type, const void *data, uint16_t len) {
- uint8_t buffer[len + 21UL];
+ uint8_t *buffer = alloca(len + 21UL);
// Create header with sequence number, length and record type
uint32_t seqno = s->outseqno++;
return send_record_priv_datagram(s, type, data, len);
}
- uint8_t buffer[len + 19UL];
+ uint8_t *buffer = alloca(len + 19UL);
// Create header with sequence number, length and record type
uint32_t seqno = s->outseqno++;
size_t siglen = ecdsa_size(s->mykey);
// Concatenate both KEX messages, plus tag indicating if it is from the connection originator, plus label
- uint8_t msg[(1 + 32 + keylen) * 2 + 1 + s->labellen];
- uint8_t sig[siglen];
+ const size_t msglen = (1 + 32 + keylen) * 2 + 1 + s->labellen;
+ uint8_t *msg = alloca(msglen);
+ uint8_t *sig = alloca(siglen);
msg[0] = s->initiator;
memcpy(msg + 1, s->mykex, 1 + 32 + keylen);
memcpy(msg + 1 + 2 * (33 + keylen), s->label, s->labellen);
// Sign the result.
- if(!ecdsa_sign(s->mykey, msg, sizeof(msg), sig)) {
+ if(!ecdsa_sign(s->mykey, msg, msglen, sig)) {
return error(s, EINVAL, "Failed to sign SIG record");
}
// Send the SIG exchange record.
- return send_record_priv(s, SPTPS_HANDSHAKE, sig, sizeof(sig));
+ return send_record_priv(s, SPTPS_HANDSHAKE, sig, siglen);
}
// Generate key material from the shared secret created from the ECDHE key exchange.
}
// Create the HMAC seed, which is "key expansion" + session label + server nonce + client nonce
- uint8_t seed[s->labellen + 64 + 13];
+ uint8_t *seed = alloca(s->labellen + 64 + 13);
memcpy(seed, "key expansion", 13);
if(s->initiator) {
}
// Concatenate both KEX messages, plus tag indicating if it is from the connection originator
- uint8_t msg[(1 + 32 + keylen) * 2 + 1 + s->labellen];
+ const size_t msglen = (1 + 32 + keylen) * 2 + 1 + s->labellen;
+ uint8_t *msg = alloca(msglen);
msg[0] = !s->initiator;
memcpy(msg + 1, s->hiskex, 1 + 32 + keylen);
memcpy(msg + 1 + 2 * (33 + keylen), s->label, s->labellen);
// Verify signature.
- if(!ecdsa_verify(s->hiskey, msg, sizeof(msg), data)) {
+ if(!ecdsa_verify(s->hiskey, msg, msglen, data)) {
return error(s, EIO, "Failed to verify SIG record");
}
return false;
}
- uint8_t buffer[len];
+ uint8_t *buffer = alloca(len);
size_t outlen;
return chacha_poly1305_decrypt(s->incipher, seqno, data + 4, len - 4, buffer, &outlen);
}
// Decrypt
- uint8_t buffer[len];
+ uint8_t *buffer = alloca(len);
size_t outlen;
if(!chacha_poly1305_decrypt(s->incipher, seqno, data, len, buffer, &outlen)) {
#include "system.h"
-#include <getopt.h>
-
#ifdef HAVE_READLINE
#include "readline/readline.h"
#include "readline/history.h"
time_t now = time(NULL);
if(now < refresh_time) {
- nanosleep(&(struct timespec) {
- refresh_time - now, 0
- }, NULL);
+ sleep_millis((refresh_time - now) * 1000);
}
}
-subdir('integration')
+if cc_name != 'msvc'
+ subdir('integration')
+endif
+
subdir('unit')