1998-2005 Ivo Timmermans
2000 Cris van Pelt
2010-2011 Julien Muchembled <jm@jmuchemb.eu>
- 2000-2013 Guus Sliepen <guus@tinc-vpn.org>
+ 2000-2015 Guus Sliepen <guus@tinc-vpn.org>
2013 Florent Clairambault <florent@clairambault.fr>
This program is free software; you can redistribute it and/or modify
}
bool read_server_config(void) {
- char *fname;
+ char fname[PATH_MAX];
bool x;
read_config_options(config_tree, NULL);
- xasprintf(&fname, "%s" SLASH "tinc.conf", confbase);
+ snprintf(fname, sizeof fname, "%s" SLASH "tinc.conf", confbase);
errno = 0;
x = read_config_file(config_tree, fname);
// We will try to read the conf files in the "conf.d" dir
if (x) {
- char * dname;
- xasprintf(&dname, "%s" SLASH "conf.d", confbase);
+ char dname[PATH_MAX];
+ snprintf(dname, sizeof dname, "%s" SLASH "conf.d", confbase);
DIR *dir = opendir (dname);
// If we can find this dir
if (dir) {
size_t l = strlen(ep->d_name);
// And we try to read the ones that end with ".conf"
if (l > 5 && !strcmp(".conf", & ep->d_name[ l - 5 ])) {
- free(fname);
- xasprintf(&fname, "%s" SLASH "%s", dname, ep->d_name);
+ snprintf(fname, sizeof fname, "%s" SLASH "%s", dname, ep->d_name);
x = read_config_file(config_tree, fname);
}
}
closedir (dir);
}
- free(dname);
}
if(!x && errno)
logger(DEBUG_ALWAYS, LOG_ERR, "Failed to read `%s': %s", fname, strerror(errno));
- free(fname);
-
return x;
}
bool read_host_config(splay_tree_t *config_tree, const char *name) {
- char *fname;
+ char fname[PATH_MAX];
bool x;
read_config_options(config_tree, name);
- xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
+ snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
x = read_config_file(config_tree, fname);
- free(fname);
return x;
}
bool append_config_file(const char *name, const char *key, const char *value) {
- char *fname;
- xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
+ char fname[PATH_MAX];
+ snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
FILE *fp = fopen(fname, "a");
if(!fp) {
logger(DEBUG_ALWAYS, LOG_ERR, "Cannot open config file %s: %s", fname, strerror(errno));
- } else {
- fprintf(fp, "\n# The following line was automatically added by tinc\n%s = %s\n", key, value);
- fclose(fp);
+ return false;
}
- free(fname);
-
- return fp != NULL;
+ fprintf(fp, "\n# The following line was automatically added by tinc\n%s = %s\n", key, value);
+ fclose(fp);
+ return true;
}
/*
invitation.c -- Create and accept invitations
- Copyright (C) 2013-2014 Guus Sliepen <guus@tinc-vpn.org>
+ Copyright (C) 2013-2015 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
char *port = NULL;
char *hostport = NULL;
char *name = get_my_name(false);
- char *filename = NULL;
+ char filename[PATH_MAX];
// Use first Address statement in own host config file
if(check_id(name)) {
- xasprintf(&filename, "%s" SLASH "hosts" SLASH "%s", confbase, name);
+ snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", confbase, name);
scan_for_hostname(filename, &hostname, &port);
scan_for_hostname(tinc_conf, &hostname, &port);
}
free(hostname);
free(port);
- free(filename);
return hostport;
}
return 1;
// Ensure no host configuration file with that name exists
- char *filename = NULL;
- xasprintf(&filename, "%s" SLASH "hosts" SLASH "%s", confbase, argv[1]);
+ char filename[PATH_MAX];
+ snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", confbase, argv[1]);
if(!access(filename, F_OK)) {
- free(filename);
fprintf(stderr, "A host config file for %s already exists!\n", argv[1]);
return 1;
}
- free(filename);
// If a daemon is running, ensure no other nodes know about this name
bool found = false;
}
}
- xasprintf(&filename, "%s" SLASH "invitations", confbase);
+ snprintf(filename, sizeof filename, "%s" SLASH "invitations", confbase);
if(mkdir(filename, 0700) && errno != EEXIST) {
fprintf(stderr, "Could not create directory %s: %s\n", filename, strerror(errno));
- free(filename);
return 1;
}
DIR *dir = opendir(filename);
if(!dir) {
fprintf(stderr, "Could not read directory %s: %s\n", filename, strerror(errno));
- free(filename);
return 1;
}
while((ent = readdir(dir))) {
if(strlen(ent->d_name) != 24)
continue;
- char *invname;
+ char invname[PATH_MAX];
struct stat st;
- xasprintf(&invname, "%s" SLASH "%s", filename, ent->d_name);
+ snprintf(invname, sizeof invname, "%s" SLASH "%s", filename, ent->d_name);
if(!stat(invname, &st)) {
if(deadline < st.st_mtime)
count++;
fprintf(stderr, "Could not stat %s: %s\n", invname, strerror(errno));
errno = 0;
}
- free(invname);
}
+ closedir(dir);
+
if(errno) {
fprintf(stderr, "Error while reading directory %s: %s\n", filename, strerror(errno));
- closedir(dir);
- free(filename);
return 1;
}
- closedir(dir);
- free(filename);
-
ecdsa_t *key;
- xasprintf(&filename, "%s" SLASH "invitations" SLASH "ed25519_key.priv", confbase);
+ snprintf(filename, sizeof filename, "%s" SLASH "invitations" SLASH "ed25519_key.priv", confbase);
// Remove the key if there are no outstanding invitations.
if(!count)
if(!f) {
if(errno != ENOENT) {
fprintf(stderr, "Could not read %s: %s\n", filename, strerror(errno));
- free(filename);
return 1;
}
key = ecdsa_generate();
- if(!key) {
- free(filename);
+ if(!key)
return 1;
- }
f = fopen(filename, "w");
if(!f) {
fprintf(stderr, "Could not write %s: %s\n", filename, strerror(errno));
- free(filename);
return 1;
}
chmod(filename, 0600);
fprintf(stderr, "Could not read private key from %s\n", filename);
}
- free(filename);
if(!key)
return 1;
b64encode_urlsafe(cookie, cookie, 18);
// Create a file containing the details of the invitation.
- xasprintf(&filename, "%s" SLASH "invitations" SLASH "%s", confbase, cookiehash);
+ snprintf(filename, sizeof filename, "%s" SLASH "invitations" SLASH "%s", confbase, cookiehash);
int ifd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
if(!ifd) {
fprintf(stderr, "Could not create invitation file %s: %s\n", filename, strerror(errno));
- free(filename);
return 1;
}
f = fdopen(ifd, "w");
fprintf(f, "#---------------------------------------------------------------#\n");
fprintf(f, "Name = %s\n", myname);
- char *filename2;
- xasprintf(&filename2, "%s" SLASH "hosts" SLASH "%s", confbase, myname);
+ char filename2[PATH_MAX];
+ snprintf(filename2, sizeof filename2, "%s" SLASH "hosts" SLASH "%s", confbase, myname);
fcopy(f, filename2);
fclose(f);
- free(filename2);
// Create an URL from the local address, key hash and cookie
char *url;
puts(url);
free(url);
- free(filename);
free(address);
return 0;
fprintf(f, "Name = %s\n", name);
- char *filename;
- xasprintf(&filename, "%s" SLASH "%s", hosts_dir, name);
+ char filename[PATH_MAX];
+ snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, name);
FILE *fh = fopen(filename, "w");
if(!fh) {
fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno));
}
fclose(f);
- free(filename);
while(l && !strcasecmp(l, "Name")) {
if(!check_id(value)) {
return false;
}
- xasprintf(&filename, "%s" SLASH "%s", hosts_dir, value);
+ snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, value);
f = fopen(filename, "w");
if(!f) {
}
fclose(f);
- free(filename);
}
// Generate our key and send a copy to the server
if(!b64key)
return false;
- xasprintf(&filename, "%s" SLASH "ed25519_key.priv", confbase);
+ snprintf(filename, sizeof filename, "%s" SLASH "ed25519_key.priv", confbase);
f = fopenmask(filename, "w", 0600);
if(!ecdsa_write_pem_private_key(key, f)) {
#ifndef DISABLE_LEGACY
rsa_t *rsa = rsa_generate(2048, 0x1001);
- xasprintf(&filename, "%s" SLASH "rsa_key.priv", confbase);
+ snprintf(filename, sizeof filename, "%s" SLASH "rsa_key.priv", confbase);
f = fopenmask(filename, "w", 0600);
rsa_write_pem_private_key(rsa, f);
line[strlen(line) - 1] = 0;
- char *newbase;
- xasprintf(&newbase, CONFDIR SLASH "tinc" SLASH "%s", line);
+ char newbase[PATH_MAX];
+ snprintf(newbase, sizeof newbase, CONFDIR SLASH "tinc" SLASH "%s", line);
if(rename(confbase, newbase)) {
fprintf(stderr, "Error trying to rename %s to %s: %s\n", confbase, newbase, strerror(errno));
- free(newbase);
goto ask_netname;
}
- free(newbase);
netname = line;
make_names();
}
/*
net.c -- most of the network code
Copyright (C) 1998-2005 Ivo Timmermans,
- 2000-2013 Guus Sliepen <guus@tinc-vpn.org>
+ 2000-2015 Guus Sliepen <guus@tinc-vpn.org>
2006 Scott Lamb <slamb@slamb.org>
2011 Loïc Grenié <loic.grenie@gmail.com>
#endif
int reload_configuration(void) {
- char *fname = NULL;
+ char fname[PATH_MAX];
/* Reread our own configuration file */
read_config_options(config_tree, NULL);
- xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, myself->name);
+ snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, myself->name);
read_config_file(config_tree, fname);
- free(fname);
/* Parse some options that are allowed to be changed while tinc is running */
if(c->status.control)
continue;
- xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name);
+ snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name);
struct stat s;
if(stat(fname, &s) || s.st_mtime > last_config_check) {
logger(DEBUG_CONNECTIONS, LOG_INFO, "Host config file of %s has been changed", c->name);
terminate_connection(c, c->edge);
}
- free(fname);
}
last_config_check = now.tv_sec;
/*
net_setup.c -- Setup.
Copyright (C) 1998-2005 Ivo Timmermans,
- 2000-2014 Guus Sliepen <guus@tinc-vpn.org>
+ 2000-2015 Guus Sliepen <guus@tinc-vpn.org>
2006 Scott Lamb <slamb@slamb.org>
2010 Brandon Black <blblack@gmail.com>
static bool read_invitation_key(void) {
FILE *fp;
- char *fname;
+ char fname[PATH_MAX];
if(invitation_key) {
ecdsa_free(invitation_key);
invitation_key = NULL;
}
- xasprintf(&fname, "%s" SLASH "invitations" SLASH "ed25519_key.priv", confbase);
+ snprintf(fname, sizeof fname, "%s" SLASH "invitations" SLASH "ed25519_key.priv", confbase);
fp = fopen(fname, "r");
logger(DEBUG_ALWAYS, LOG_ERR, "Reading Ed25519 private key file `%s' failed", fname);
}
- free(fname);
return invitation_key;
}
void load_all_subnets(void) {
DIR *dir;
struct dirent *ent;
- char *dname;
+ char dname[PATH_MAX];
- xasprintf(&dname, "%s" SLASH "hosts", confbase);
+ 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));
- free(dname);
return;
}
void load_all_nodes(void) {
DIR *dir;
struct dirent *ent;
- char *dname;
+ char dname[PATH_MAX];
- xasprintf(&dname, "%s" SLASH "hosts", confbase);
+ 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));
- free(dname);
return;
}
/*
script.c -- call an external script
Copyright (C) 1999-2005 Ivo Timmermans,
- 2000-2013 Guus Sliepen <guus@tinc-vpn.org>
+ 2000-2015 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
bool execute_script(const char *name, char **envp) {
#ifdef HAVE_SYSTEM
- char *scriptname;
+ char scriptname[PATH_MAX];
char *command;
- xasprintf(&scriptname, "%s" SLASH "%s%s", confbase, name, scriptextension);
+ snprintf(scriptname, sizeof scriptname, "%s" SLASH "%s%s", confbase, name, scriptextension);
/* First check if there is a script */
break;
p = q;
}
- if(!found) {
- free(scriptname);
+ if(!found)
return true;
- }
} else
#endif
- if(access(scriptname, F_OK)) {
- free(scriptname);
+ if(access(scriptname, F_OK))
return true;
- }
logger(DEBUG_STATUS, LOG_INFO, "Executing script %s", name);
int status = system(command);
free(command);
- free(scriptname);
/* Unset environment */
static bool ed25519_keygen(bool ask) {
ecdsa_t *key;
FILE *f;
- char *pubname, *privname;
+ char fname[PATH_MAX];
fprintf(stderr, "Generating Ed25519 keypair:\n");
} else
fprintf(stderr, "Done.\n");
- xasprintf(&privname, "%s" SLASH "ed25519_key.priv", confbase);
- f = ask_and_open(privname, "private Ed25519 key", "a", ask, 0600);
- free(privname);
+ snprintf(fname, sizeof fname, "%s" SLASH "ed25519_key.priv", confbase);
+ f = ask_and_open(fname, "private Ed25519 key", "a", ask, 0600);
if(!f)
- return false;
+ goto error;
if(!ecdsa_write_pem_private_key(key, f)) {
fprintf(stderr, "Error writing private key!\n");
- ecdsa_free(key);
- fclose(f);
- return false;
+ goto error;
}
fclose(f);
if(name)
- xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
+ snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
else
- xasprintf(&pubname, "%s" SLASH "ed25519_key.pub", confbase);
+ snprintf(fname, sizeof fname, "%s" SLASH "ed25519_key.pub", confbase);
- f = ask_and_open(pubname, "public Ed25519 key", "a", ask, 0666);
- free(pubname);
+ f = ask_and_open(fname, "public Ed25519 key", "a", ask, 0666);
if(!f)
return false;
char *pubkey = ecdsa_get_base64_public_key(key);
fprintf(f, "Ed25519PublicKey = %s\n", pubkey);
- free(pubkey);
fclose(f);
ecdsa_free(key);
return true;
+
+error:
+ if(f)
+ fclose(f);
+ ecdsa_free(key);
+ return false;
}
#ifndef DISABLE_LEGACY
static bool rsa_keygen(int bits, bool ask) {
rsa_t *key;
FILE *f;
- char *pubname, *privname;
+ char fname[PATH_MAX];
// Make sure the key size is a multiple of 8 bits.
bits &= ~0x7;
} else
fprintf(stderr, "Done.\n");
- xasprintf(&privname, "%s" SLASH "rsa_key.priv", confbase);
- f = ask_and_open(privname, "private RSA key", "a", ask, 0600);
- free(privname);
+ snprintf(fname, sizeof fname, "%s" SLASH "rsa_key.priv", confbase);
+ f = ask_and_open(fname, "private RSA key", "a", ask, 0600);
if(!f)
- return false;
+ goto error;
if(!rsa_write_pem_private_key(key, f)) {
fprintf(stderr, "Error writing private key!\n");
- fclose(f);
- rsa_free(key);
- return false;
+ goto error;
}
fclose(f);
if(name)
- xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
+ snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
else
- xasprintf(&pubname, "%s" SLASH "rsa_key.pub", confbase);
+ snprintf(fname, sizeof fname, "%s" SLASH "rsa_key.pub", confbase);
- f = ask_and_open(pubname, "public RSA key", "a", ask, 0666);
- free(pubname);
+ f = ask_and_open(fname, "public RSA key", "a", ask, 0666);
if(!f)
- return false;
+ goto error;
if(!rsa_write_pem_public_key(key, f)) {
fprintf(stderr, "Error writing public key!\n");
- fclose(f);
- rsa_free(key);
- return false;
+ goto error;
}
fclose(f);
rsa_free(key);
return true;
+
+error:
+ if(f)
+ fclose(f);
+ rsa_free(key);
+ return false;
}
#endif
}
// Open the right configuration file.
- char *filename;
+ char filename[PATH_MAX];
if(node)
- xasprintf(&filename, "%s" SLASH "%s", hosts_dir, node);
+ snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, node);
else
- filename = tinc_conf;
+ snprintf(filename, sizeof filename, "%s", tinc_conf);
FILE *f = fopen(filename, "r");
if(!f) {
return 1;
}
- char *tmpfile = NULL;
+ char tmpfile[PATH_MAX];
FILE *tf = NULL;
if(action >= -1) {
- xasprintf(&tmpfile, "%s.config.tmp", filename);
+ snprintf(tmpfile, sizeof tmpfile, "%s.config.tmp", filename);
tf = fopen(tmpfile, "w");
if(!tf) {
fprintf(stderr, "Could not open temporary file %s: %s\n", tmpfile, strerror(errno));
for(int i = 0; i < 100; i++) {
int port = 0x1000 + (rand() & 0x7fff);
if(try_bind(port)) {
- char *filename;
- xasprintf(&filename, "%s" SLASH "hosts" SLASH "%s", confbase, name);
+ char filename[PATH_MAX];
+ snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", confbase, name);
FILE *f = fopen(filename, "a");
- free(filename);
if(!f) {
+ fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
fprintf(stderr, "Please change tinc's Port manually.\n");
return 0;
}
check_port(name);
#ifndef HAVE_MINGW
- char *filename;
- xasprintf(&filename, "%s" SLASH "tinc-up", confbase);
+ char filename[PATH_MAX];
+ snprintf(filename, sizeof filename, "%s" SLASH "tinc-up", confbase);
if(access(filename, F_OK)) {
FILE *f = fopenmask(filename, "w", 0777);
if(!f) {
return 1;
}
- char *filename = NULL;
+ char filename[PATH_MAX] = "";
if(strncmp(argv[1], "hosts" SLASH, 6)) {
for(int i = 0; conffiles[i]; i++) {
if(!strcmp(argv[1], conffiles[i])) {
- xasprintf(&filename, "%s" SLASH "%s", confbase, argv[1]);
+ snprintf(filename, sizeof filename, "%s" SLASH "%s", confbase, argv[1]);
break;
}
}
argv[1] += 6;
}
- if(!filename) {
- xasprintf(&filename, "%s" SLASH "%s", hosts_dir, argv[1]);
+ if(!*filename) {
+ snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, argv[1]);
char *dash = strchr(argv[1], '-');
if(dash) {
*dash++ = 0;
xasprintf(&command, "edit \"%s\"", filename);
#endif
int result = system(command);
+ free(command);
if(result)
return result;
}
static int export(const char *name, FILE *out) {
- char *filename;
- xasprintf(&filename, "%s" SLASH "%s", hosts_dir, name);
+ char filename[PATH_MAX];
+ snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, name);
FILE *in = fopen(filename, "r");
if(!in) {
fprintf(stderr, "Could not open configuration file %s: %s\n", filename, strerror(errno));
char buf[4096];
char name[4096];
- char *filename = NULL;
+ char filename[PATH_MAX] = "";
int count = 0;
bool firstline = true;
if(out)
fclose(out);
- free(filename);
- xasprintf(&filename, "%s" SLASH "%s", hosts_dir, name);
+ snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, name);
if(!force && !access(filename, F_OK)) {
fprintf(stderr, "Host configuration file %s already exists, skipping.\n", filename);
continue;
}
- char *fname;
- xasprintf(&fname, "%s/%s/tinc.conf", confdir, ent->d_name);
+ char fname[PATH_MAX];
+ snprintf(fname, sizeof fname, "%s/%s/tinc.conf", confdir, ent->d_name);
if(!access(fname, R_OK))
printf("%s\n", ent->d_name);
- free(fname);
}
closedir(dir);