Allocate temporary filenames on the stack.

This gets rid of xasprintf() in a number of places, and removes the need
to free() the temporary strings. A few potential memory leaks have been
fixed.
This commit is contained in:
Guus Sliepen 2015-05-20 00:55:00 +02:00
parent 58e8f598f3
commit 3ccdf50beb
6 changed files with 103 additions and 141 deletions

View file

@ -4,7 +4,7 @@
1998-2005 Ivo Timmermans 1998-2005 Ivo Timmermans
2000 Cris van Pelt 2000 Cris van Pelt
2010-2011 Julien Muchembled <jm@jmuchemb.eu> 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> 2013 Florent Clairambault <florent@clairambault.fr>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
@ -368,19 +368,19 @@ void read_config_options(splay_tree_t *config_tree, const char *prefix) {
} }
bool read_server_config(void) { bool read_server_config(void) {
char *fname; char fname[PATH_MAX];
bool x; bool x;
read_config_options(config_tree, NULL); read_config_options(config_tree, NULL);
xasprintf(&fname, "%s" SLASH "tinc.conf", confbase); snprintf(fname, sizeof fname, "%s" SLASH "tinc.conf", confbase);
errno = 0; errno = 0;
x = read_config_file(config_tree, fname); x = read_config_file(config_tree, fname);
// We will try to read the conf files in the "conf.d" dir // We will try to read the conf files in the "conf.d" dir
if (x) { if (x) {
char * dname; char dname[PATH_MAX];
xasprintf(&dname, "%s" SLASH "conf.d", confbase); snprintf(dname, sizeof dname, "%s" SLASH "conf.d", confbase);
DIR *dir = opendir (dname); DIR *dir = opendir (dname);
// If we can find this dir // If we can find this dir
if (dir) { if (dir) {
@ -390,51 +390,44 @@ bool read_server_config(void) {
size_t l = strlen(ep->d_name); size_t l = strlen(ep->d_name);
// And we try to read the ones that end with ".conf" // And we try to read the ones that end with ".conf"
if (l > 5 && !strcmp(".conf", & ep->d_name[ l - 5 ])) { if (l > 5 && !strcmp(".conf", & ep->d_name[ l - 5 ])) {
free(fname); snprintf(fname, sizeof fname, "%s" SLASH "%s", dname, ep->d_name);
xasprintf(&fname, "%s" SLASH "%s", dname, ep->d_name);
x = read_config_file(config_tree, fname); x = read_config_file(config_tree, fname);
} }
} }
closedir (dir); closedir (dir);
} }
free(dname);
} }
if(!x && errno) if(!x && errno)
logger(DEBUG_ALWAYS, LOG_ERR, "Failed to read `%s': %s", fname, strerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "Failed to read `%s': %s", fname, strerror(errno));
free(fname);
return x; return x;
} }
bool read_host_config(splay_tree_t *config_tree, const char *name) { bool read_host_config(splay_tree_t *config_tree, const char *name) {
char *fname; char fname[PATH_MAX];
bool x; bool x;
read_config_options(config_tree, name); 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); x = read_config_file(config_tree, fname);
free(fname);
return x; return x;
} }
bool append_config_file(const char *name, const char *key, const char *value) { bool append_config_file(const char *name, const char *key, const char *value) {
char *fname; char fname[PATH_MAX];
xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, name); snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
FILE *fp = fopen(fname, "a"); FILE *fp = fopen(fname, "a");
if(!fp) { if(!fp) {
logger(DEBUG_ALWAYS, LOG_ERR, "Cannot open config file %s: %s", fname, strerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "Cannot open config file %s: %s", fname, strerror(errno));
} else { return false;
fprintf(fp, "\n# The following line was automatically added by tinc\n%s = %s\n", key, value);
fclose(fp);
} }
free(fname); fprintf(fp, "\n# The following line was automatically added by tinc\n%s = %s\n", key, value);
fclose(fp);
return fp != NULL; return true;
} }

View file

@ -1,6 +1,6 @@
/* /*
invitation.c -- Create and accept invitations 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 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 it under the terms of the GNU General Public License as published by
@ -84,11 +84,11 @@ char *get_my_hostname() {
char *port = NULL; char *port = NULL;
char *hostport = NULL; char *hostport = NULL;
char *name = get_my_name(false); char *name = get_my_name(false);
char *filename = NULL; char filename[PATH_MAX];
// Use first Address statement in own host config file // Use first Address statement in own host config file
if(check_id(name)) { 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(filename, &hostname, &port);
scan_for_hostname(tinc_conf, &hostname, &port); scan_for_hostname(tinc_conf, &hostname, &port);
} }
@ -207,7 +207,6 @@ done:
free(hostname); free(hostname);
free(port); free(port);
free(filename);
return hostport; return hostport;
} }
@ -243,14 +242,12 @@ int cmd_invite(int argc, char *argv[]) {
return 1; return 1;
// Ensure no host configuration file with that name exists // Ensure no host configuration file with that name exists
char *filename = NULL; char filename[PATH_MAX];
xasprintf(&filename, "%s" SLASH "hosts" SLASH "%s", confbase, argv[1]); snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", confbase, argv[1]);
if(!access(filename, F_OK)) { if(!access(filename, F_OK)) {
free(filename);
fprintf(stderr, "A host config file for %s already exists!\n", argv[1]); fprintf(stderr, "A host config file for %s already exists!\n", argv[1]);
return 1; return 1;
} }
free(filename);
// If a daemon is running, ensure no other nodes know about this name // If a daemon is running, ensure no other nodes know about this name
bool found = false; bool found = false;
@ -272,10 +269,9 @@ int cmd_invite(int argc, char *argv[]) {
} }
} }
xasprintf(&filename, "%s" SLASH "invitations", confbase); snprintf(filename, sizeof filename, "%s" SLASH "invitations", confbase);
if(mkdir(filename, 0700) && errno != EEXIST) { if(mkdir(filename, 0700) && errno != EEXIST) {
fprintf(stderr, "Could not create directory %s: %s\n", filename, strerror(errno)); fprintf(stderr, "Could not create directory %s: %s\n", filename, strerror(errno));
free(filename);
return 1; return 1;
} }
@ -283,7 +279,6 @@ int cmd_invite(int argc, char *argv[]) {
DIR *dir = opendir(filename); DIR *dir = opendir(filename);
if(!dir) { if(!dir) {
fprintf(stderr, "Could not read directory %s: %s\n", filename, strerror(errno)); fprintf(stderr, "Could not read directory %s: %s\n", filename, strerror(errno));
free(filename);
return 1; return 1;
} }
@ -295,9 +290,9 @@ int cmd_invite(int argc, char *argv[]) {
while((ent = readdir(dir))) { while((ent = readdir(dir))) {
if(strlen(ent->d_name) != 24) if(strlen(ent->d_name) != 24)
continue; continue;
char *invname; char invname[PATH_MAX];
struct stat st; 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(!stat(invname, &st)) {
if(deadline < st.st_mtime) if(deadline < st.st_mtime)
count++; count++;
@ -307,21 +302,17 @@ int cmd_invite(int argc, char *argv[]) {
fprintf(stderr, "Could not stat %s: %s\n", invname, strerror(errno)); fprintf(stderr, "Could not stat %s: %s\n", invname, strerror(errno));
errno = 0; errno = 0;
} }
free(invname);
} }
closedir(dir);
if(errno) { if(errno) {
fprintf(stderr, "Error while reading directory %s: %s\n", filename, strerror(errno)); fprintf(stderr, "Error while reading directory %s: %s\n", filename, strerror(errno));
closedir(dir);
free(filename);
return 1; return 1;
} }
closedir(dir);
free(filename);
ecdsa_t *key; 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. // Remove the key if there are no outstanding invitations.
if(!count) if(!count)
@ -332,19 +323,15 @@ int cmd_invite(int argc, char *argv[]) {
if(!f) { if(!f) {
if(errno != ENOENT) { if(errno != ENOENT) {
fprintf(stderr, "Could not read %s: %s\n", filename, strerror(errno)); fprintf(stderr, "Could not read %s: %s\n", filename, strerror(errno));
free(filename);
return 1; return 1;
} }
key = ecdsa_generate(); key = ecdsa_generate();
if(!key) { if(!key)
free(filename);
return 1; return 1;
}
f = fopen(filename, "w"); f = fopen(filename, "w");
if(!f) { if(!f) {
fprintf(stderr, "Could not write %s: %s\n", filename, strerror(errno)); fprintf(stderr, "Could not write %s: %s\n", filename, strerror(errno));
free(filename);
return 1; return 1;
} }
chmod(filename, 0600); chmod(filename, 0600);
@ -360,7 +347,6 @@ int cmd_invite(int argc, char *argv[]) {
fprintf(stderr, "Could not read private key from %s\n", filename); fprintf(stderr, "Could not read private key from %s\n", filename);
} }
free(filename);
if(!key) if(!key)
return 1; return 1;
@ -385,11 +371,10 @@ int cmd_invite(int argc, char *argv[]) {
b64encode_urlsafe(cookie, cookie, 18); b64encode_urlsafe(cookie, cookie, 18);
// Create a file containing the details of the invitation. // 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); int ifd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
if(!ifd) { if(!ifd) {
fprintf(stderr, "Could not create invitation file %s: %s\n", filename, strerror(errno)); fprintf(stderr, "Could not create invitation file %s: %s\n", filename, strerror(errno));
free(filename);
return 1; return 1;
} }
f = fdopen(ifd, "w"); f = fdopen(ifd, "w");
@ -424,11 +409,10 @@ int cmd_invite(int argc, char *argv[]) {
fprintf(f, "#---------------------------------------------------------------#\n"); fprintf(f, "#---------------------------------------------------------------#\n");
fprintf(f, "Name = %s\n", myname); fprintf(f, "Name = %s\n", myname);
char *filename2; char filename2[PATH_MAX];
xasprintf(&filename2, "%s" SLASH "hosts" SLASH "%s", confbase, myname); snprintf(filename2, sizeof filename2, "%s" SLASH "hosts" SLASH "%s", confbase, myname);
fcopy(f, filename2); fcopy(f, filename2);
fclose(f); fclose(f);
free(filename2);
// Create an URL from the local address, key hash and cookie // Create an URL from the local address, key hash and cookie
char *url; char *url;
@ -447,7 +431,6 @@ int cmd_invite(int argc, char *argv[]) {
puts(url); puts(url);
free(url); free(url);
free(filename);
free(address); free(address);
return 0; return 0;
@ -606,8 +589,8 @@ make_names:
fprintf(f, "Name = %s\n", name); fprintf(f, "Name = %s\n", name);
char *filename; char filename[PATH_MAX];
xasprintf(&filename, "%s" SLASH "%s", hosts_dir, name); snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, name);
FILE *fh = fopen(filename, "w"); FILE *fh = fopen(filename, "w");
if(!fh) { if(!fh) {
fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno)); fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno));
@ -668,7 +651,6 @@ make_names:
} }
fclose(f); fclose(f);
free(filename);
while(l && !strcasecmp(l, "Name")) { while(l && !strcasecmp(l, "Name")) {
if(!check_id(value)) { if(!check_id(value)) {
@ -681,7 +663,7 @@ make_names:
return false; return false;
} }
xasprintf(&filename, "%s" SLASH "%s", hosts_dir, value); snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, value);
f = fopen(filename, "w"); f = fopen(filename, "w");
if(!f) { if(!f) {
@ -709,7 +691,6 @@ make_names:
} }
fclose(f); fclose(f);
free(filename);
} }
// Generate our key and send a copy to the server // Generate our key and send a copy to the server
@ -721,7 +702,7 @@ make_names:
if(!b64key) if(!b64key)
return false; 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); f = fopenmask(filename, "w", 0600);
if(!ecdsa_write_pem_private_key(key, f)) { if(!ecdsa_write_pem_private_key(key, f)) {
@ -741,7 +722,7 @@ make_names:
#ifndef DISABLE_LEGACY #ifndef DISABLE_LEGACY
rsa_t *rsa = rsa_generate(2048, 0x1001); 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); f = fopenmask(filename, "w", 0600);
rsa_write_pem_private_key(rsa, f); rsa_write_pem_private_key(rsa, f);
@ -767,15 +748,13 @@ ask_netname:
line[strlen(line) - 1] = 0; line[strlen(line) - 1] = 0;
char *newbase; char newbase[PATH_MAX];
xasprintf(&newbase, CONFDIR SLASH "tinc" SLASH "%s", line); snprintf(newbase, sizeof newbase, CONFDIR SLASH "tinc" SLASH "%s", line);
if(rename(confbase, newbase)) { if(rename(confbase, newbase)) {
fprintf(stderr, "Error trying to rename %s to %s: %s\n", confbase, newbase, strerror(errno)); fprintf(stderr, "Error trying to rename %s to %s: %s\n", confbase, newbase, strerror(errno));
free(newbase);
goto ask_netname; goto ask_netname;
} }
free(newbase);
netname = line; netname = line;
make_names(); make_names();
} }

View file

@ -1,7 +1,7 @@
/* /*
net.c -- most of the network code net.c -- most of the network code
Copyright (C) 1998-2005 Ivo Timmermans, 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> 2006 Scott Lamb <slamb@slamb.org>
2011 Loïc Grenié <loic.grenie@gmail.com> 2011 Loïc Grenié <loic.grenie@gmail.com>
@ -314,7 +314,7 @@ static void sigalrm_handler(void *data) {
#endif #endif
int reload_configuration(void) { int reload_configuration(void) {
char *fname = NULL; char fname[PATH_MAX];
/* Reread our own configuration file */ /* Reread our own configuration file */
@ -328,9 +328,8 @@ int reload_configuration(void) {
read_config_options(config_tree, NULL); 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); read_config_file(config_tree, fname);
free(fname);
/* Parse some options that are allowed to be changed while tinc is running */ /* Parse some options that are allowed to be changed while tinc is running */
@ -407,13 +406,12 @@ int reload_configuration(void) {
if(c->status.control) if(c->status.control)
continue; 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; struct stat s;
if(stat(fname, &s) || s.st_mtime > last_config_check) { 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); logger(DEBUG_CONNECTIONS, LOG_INFO, "Host config file of %s has been changed", c->name);
terminate_connection(c, c->edge); terminate_connection(c, c->edge);
} }
free(fname);
} }
last_config_check = now.tv_sec; last_config_check = now.tv_sec;

View file

@ -1,7 +1,7 @@
/* /*
net_setup.c -- Setup. net_setup.c -- Setup.
Copyright (C) 1998-2005 Ivo Timmermans, 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> 2006 Scott Lamb <slamb@slamb.org>
2010 Brandon Black <blblack@gmail.com> 2010 Brandon Black <blblack@gmail.com>
@ -226,14 +226,14 @@ static bool read_ecdsa_private_key(void) {
static bool read_invitation_key(void) { static bool read_invitation_key(void) {
FILE *fp; FILE *fp;
char *fname; char fname[PATH_MAX];
if(invitation_key) { if(invitation_key) {
ecdsa_free(invitation_key); ecdsa_free(invitation_key);
invitation_key = NULL; 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"); fp = fopen(fname, "r");
@ -244,7 +244,6 @@ static bool read_invitation_key(void) {
logger(DEBUG_ALWAYS, LOG_ERR, "Reading Ed25519 private key file `%s' failed", fname); logger(DEBUG_ALWAYS, LOG_ERR, "Reading Ed25519 private key file `%s' failed", fname);
} }
free(fname);
return invitation_key; return invitation_key;
} }
@ -327,13 +326,12 @@ void regenerate_key(void) {
void load_all_subnets(void) { void load_all_subnets(void) {
DIR *dir; DIR *dir;
struct dirent *ent; 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); dir = opendir(dname);
if(!dir) { if(!dir) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", dname, strerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", dname, strerror(errno));
free(dname);
return; return;
} }
@ -380,13 +378,12 @@ void load_all_subnets(void) {
void load_all_nodes(void) { void load_all_nodes(void) {
DIR *dir; DIR *dir;
struct dirent *ent; 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); dir = opendir(dname);
if(!dir) { if(!dir) {
logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", dname, strerror(errno)); logger(DEBUG_ALWAYS, LOG_ERR, "Could not open %s: %s", dname, strerror(errno));
free(dname);
return; return;
} }

View file

@ -1,7 +1,7 @@
/* /*
script.c -- call an external script script.c -- call an external script
Copyright (C) 1999-2005 Ivo Timmermans, 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 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 it under the terms of the GNU General Public License as published by
@ -28,10 +28,10 @@
bool execute_script(const char *name, char **envp) { bool execute_script(const char *name, char **envp) {
#ifdef HAVE_SYSTEM #ifdef HAVE_SYSTEM
char *scriptname; char scriptname[PATH_MAX];
char *command; 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 */ /* First check if there is a script */
@ -57,17 +57,13 @@ bool execute_script(const char *name, char **envp) {
break; break;
p = q; p = q;
} }
if(!found) { if(!found)
free(scriptname);
return true; return true;
}
} else } else
#endif #endif
if(access(scriptname, F_OK)) { if(access(scriptname, F_OK))
free(scriptname);
return true; return true;
}
logger(DEBUG_STATUS, LOG_INFO, "Executing script %s", name); logger(DEBUG_STATUS, LOG_INFO, "Executing script %s", name);
@ -86,7 +82,6 @@ bool execute_script(const char *name, char **envp) {
int status = system(command); int status = system(command);
free(command); free(command);
free(scriptname);
/* Unset environment */ /* Unset environment */

View file

@ -376,7 +376,7 @@ static FILE *ask_and_open(const char *filename, const char *what, const char *mo
static bool ed25519_keygen(bool ask) { static bool ed25519_keygen(bool ask) {
ecdsa_t *key; ecdsa_t *key;
FILE *f; FILE *f;
char *pubname, *privname; char fname[PATH_MAX];
fprintf(stderr, "Generating Ed25519 keypair:\n"); fprintf(stderr, "Generating Ed25519 keypair:\n");
@ -386,41 +386,42 @@ static bool ed25519_keygen(bool ask) {
} else } else
fprintf(stderr, "Done.\n"); fprintf(stderr, "Done.\n");
xasprintf(&privname, "%s" SLASH "ed25519_key.priv", confbase); snprintf(fname, sizeof fname, "%s" SLASH "ed25519_key.priv", confbase);
f = ask_and_open(privname, "private Ed25519 key", "a", ask, 0600); f = ask_and_open(fname, "private Ed25519 key", "a", ask, 0600);
free(privname);
if(!f) if(!f)
return false; goto error;
if(!ecdsa_write_pem_private_key(key, f)) { if(!ecdsa_write_pem_private_key(key, f)) {
fprintf(stderr, "Error writing private key!\n"); fprintf(stderr, "Error writing private key!\n");
ecdsa_free(key); goto error;
fclose(f);
return false;
} }
fclose(f); fclose(f);
if(name) if(name)
xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, name); snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
else 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); f = ask_and_open(fname, "public Ed25519 key", "a", ask, 0666);
free(pubname);
if(!f) if(!f)
return false; return false;
char *pubkey = ecdsa_get_base64_public_key(key); char *pubkey = ecdsa_get_base64_public_key(key);
fprintf(f, "Ed25519PublicKey = %s\n", pubkey); fprintf(f, "Ed25519PublicKey = %s\n", pubkey);
free(pubkey);
fclose(f); fclose(f);
ecdsa_free(key); ecdsa_free(key);
return true; return true;
error:
if(f)
fclose(f);
ecdsa_free(key);
return false;
} }
#ifndef DISABLE_LEGACY #ifndef DISABLE_LEGACY
@ -431,7 +432,7 @@ static bool ed25519_keygen(bool ask) {
static bool rsa_keygen(int bits, bool ask) { static bool rsa_keygen(int bits, bool ask) {
rsa_t *key; rsa_t *key;
FILE *f; FILE *f;
char *pubname, *privname; char fname[PATH_MAX];
// Make sure the key size is a multiple of 8 bits. // Make sure the key size is a multiple of 8 bits.
bits &= ~0x7; bits &= ~0x7;
@ -450,44 +451,44 @@ static bool rsa_keygen(int bits, bool ask) {
} else } else
fprintf(stderr, "Done.\n"); fprintf(stderr, "Done.\n");
xasprintf(&privname, "%s" SLASH "rsa_key.priv", confbase); snprintf(fname, sizeof fname, "%s" SLASH "rsa_key.priv", confbase);
f = ask_and_open(privname, "private RSA key", "a", ask, 0600); f = ask_and_open(fname, "private RSA key", "a", ask, 0600);
free(privname);
if(!f) if(!f)
return false; goto error;
if(!rsa_write_pem_private_key(key, f)) { if(!rsa_write_pem_private_key(key, f)) {
fprintf(stderr, "Error writing private key!\n"); fprintf(stderr, "Error writing private key!\n");
fclose(f); goto error;
rsa_free(key);
return false;
} }
fclose(f); fclose(f);
if(name) if(name)
xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, name); snprintf(fname, sizeof fname, "%s" SLASH "hosts" SLASH "%s", confbase, name);
else 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); f = ask_and_open(fname, "public RSA key", "a", ask, 0666);
free(pubname);
if(!f) if(!f)
return false; goto error;
if(!rsa_write_pem_public_key(key, f)) { if(!rsa_write_pem_public_key(key, f)) {
fprintf(stderr, "Error writing public key!\n"); fprintf(stderr, "Error writing public key!\n");
fclose(f); goto error;
rsa_free(key);
return false;
} }
fclose(f); fclose(f);
rsa_free(key); rsa_free(key);
return true; return true;
error:
if(f)
fclose(f);
rsa_free(key);
return false;
} }
#endif #endif
@ -1597,11 +1598,11 @@ static int cmd_config(int argc, char *argv[]) {
} }
// Open the right configuration file. // Open the right configuration file.
char *filename; char filename[PATH_MAX];
if(node) if(node)
xasprintf(&filename, "%s" SLASH "%s", hosts_dir, node); snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, node);
else else
filename = tinc_conf; snprintf(filename, sizeof filename, "%s", tinc_conf);
FILE *f = fopen(filename, "r"); FILE *f = fopen(filename, "r");
if(!f) { if(!f) {
@ -1609,11 +1610,11 @@ static int cmd_config(int argc, char *argv[]) {
return 1; return 1;
} }
char *tmpfile = NULL; char tmpfile[PATH_MAX];
FILE *tf = NULL; FILE *tf = NULL;
if(action >= -1) { if(action >= -1) {
xasprintf(&tmpfile, "%s.config.tmp", filename); snprintf(tmpfile, sizeof tmpfile, "%s.config.tmp", filename);
tf = fopen(tmpfile, "w"); tf = fopen(tmpfile, "w");
if(!tf) { if(!tf) {
fprintf(stderr, "Could not open temporary file %s: %s\n", tmpfile, strerror(errno)); fprintf(stderr, "Could not open temporary file %s: %s\n", tmpfile, strerror(errno));
@ -1799,11 +1800,11 @@ int check_port(char *name) {
for(int i = 0; i < 100; i++) { for(int i = 0; i < 100; i++) {
int port = 0x1000 + (rand() & 0x7fff); int port = 0x1000 + (rand() & 0x7fff);
if(try_bind(port)) { if(try_bind(port)) {
char *filename; char filename[PATH_MAX];
xasprintf(&filename, "%s" SLASH "hosts" SLASH "%s", confbase, name); snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", confbase, name);
FILE *f = fopen(filename, "a"); FILE *f = fopen(filename, "a");
free(filename);
if(!f) { if(!f) {
fprintf(stderr, "Could not open %s: %s\n", filename, strerror(errno));
fprintf(stderr, "Please change tinc's Port manually.\n"); fprintf(stderr, "Please change tinc's Port manually.\n");
return 0; return 0;
} }
@ -1894,8 +1895,8 @@ static int cmd_init(int argc, char *argv[]) {
check_port(name); check_port(name);
#ifndef HAVE_MINGW #ifndef HAVE_MINGW
char *filename; char filename[PATH_MAX];
xasprintf(&filename, "%s" SLASH "tinc-up", confbase); snprintf(filename, sizeof filename, "%s" SLASH "tinc-up", confbase);
if(access(filename, F_OK)) { if(access(filename, F_OK)) {
FILE *f = fopenmask(filename, "w", 0777); FILE *f = fopenmask(filename, "w", 0777);
if(!f) { if(!f) {
@ -2005,12 +2006,12 @@ static int cmd_edit(int argc, char *argv[]) {
return 1; return 1;
} }
char *filename = NULL; char filename[PATH_MAX] = "";
if(strncmp(argv[1], "hosts" SLASH, 6)) { if(strncmp(argv[1], "hosts" SLASH, 6)) {
for(int i = 0; conffiles[i]; i++) { for(int i = 0; conffiles[i]; i++) {
if(!strcmp(argv[1], conffiles[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; break;
} }
} }
@ -2018,8 +2019,8 @@ static int cmd_edit(int argc, char *argv[]) {
argv[1] += 6; argv[1] += 6;
} }
if(!filename) { if(!*filename) {
xasprintf(&filename, "%s" SLASH "%s", hosts_dir, argv[1]); snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, argv[1]);
char *dash = strchr(argv[1], '-'); char *dash = strchr(argv[1], '-');
if(dash) { if(dash) {
*dash++ = 0; *dash++ = 0;
@ -2037,6 +2038,7 @@ static int cmd_edit(int argc, char *argv[]) {
xasprintf(&command, "edit \"%s\"", filename); xasprintf(&command, "edit \"%s\"", filename);
#endif #endif
int result = system(command); int result = system(command);
free(command);
if(result) if(result)
return result; return result;
@ -2048,8 +2050,8 @@ static int cmd_edit(int argc, char *argv[]) {
} }
static int export(const char *name, FILE *out) { static int export(const char *name, FILE *out) {
char *filename; char filename[PATH_MAX];
xasprintf(&filename, "%s" SLASH "%s", hosts_dir, name); snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, name);
FILE *in = fopen(filename, "r"); FILE *in = fopen(filename, "r");
if(!in) { if(!in) {
fprintf(stderr, "Could not open configuration file %s: %s\n", filename, strerror(errno)); fprintf(stderr, "Could not open configuration file %s: %s\n", filename, strerror(errno));
@ -2136,7 +2138,7 @@ static int cmd_import(int argc, char *argv[]) {
char buf[4096]; char buf[4096];
char name[4096]; char name[4096];
char *filename = NULL; char filename[PATH_MAX] = "";
int count = 0; int count = 0;
bool firstline = true; bool firstline = true;
@ -2152,8 +2154,7 @@ static int cmd_import(int argc, char *argv[]) {
if(out) if(out)
fclose(out); fclose(out);
free(filename); snprintf(filename, sizeof filename, "%s" SLASH "%s", hosts_dir, name);
xasprintf(&filename, "%s" SLASH "%s", hosts_dir, name);
if(!force && !access(filename, F_OK)) { if(!force && !access(filename, F_OK)) {
fprintf(stderr, "Host configuration file %s already exists, skipping.\n", filename); fprintf(stderr, "Host configuration file %s already exists, skipping.\n", filename);
@ -2259,11 +2260,10 @@ static int cmd_network(int argc, char *argv[]) {
continue; continue;
} }
char *fname; char fname[PATH_MAX];
xasprintf(&fname, "%s/%s/tinc.conf", confdir, ent->d_name); snprintf(fname, sizeof fname, "%s/%s/tinc.conf", confdir, ent->d_name);
if(!access(fname, R_OK)) if(!access(fname, R_OK))
printf("%s\n", ent->d_name); printf("%s\n", ent->d_name);
free(fname);
} }
closedir(dir); closedir(dir);