Found by AddressSanitizer and Valgrind.
#include "utils.h" /* for cp */
#include "xalloc.h"
-splay_tree_t *config_tree;
+splay_tree_t *config_tree = NULL;
int pinginterval = 0; /* seconds between pings */
int pingtimeout = 0; /* seconds to wait for response */
scan_for_hostname(tinc_conf, &hostname, &port);
}
+ free(name);
+ name = NULL;
+
if(hostname) {
goto done;
}
if(!f) {
fprintf(stderr, "Could not write %s: %s\n", filename, strerror(errno));
+ free(key);
return 1;
}
if(!ecdsa_write_pem_private_key(key, f)) {
fprintf(stderr, "Could not write ECDSA private key\n");
fclose(f);
+ free(key);
return 1;
}
sha512(fingerprint, strlen(fingerprint), hash);
b64encode_urlsafe(hash, hash, 18);
+ free(key);
+
// Create a random cookie for this invitation.
char cookie[25];
randomize(cookie, 18);
sha512(buf, sizeof(buf), cookiehash);
b64encode_urlsafe(cookiehash, cookiehash, 18);
+ free(fingerprint);
+
b64encode_urlsafe(cookie, cookie, 18);
// Create a file containing the details of the invitation.
struct addrinfo *ai = str2addrinfo(address, port, SOCK_STREAM);
if(!ai) {
+ free(b64key);
return 1;
}
if(!aip) {
freeaddrinfo(ai);
+ free(b64key);
return 1;
}
}
}
freeaddrinfo(ai);
+ ai = NULL;
+ aip = NULL;
+
+ free(b64key);
+ b64key = NULL;
// Check if the hash of the key he gave us matches the hash in the URL.
char *fingerprint = line + 2;
logger(DEBUG_ALWAYS, LOG_INFO, "Both netname and configuration directory given, using the latter...");
}
+ free(identname);
+
if(netname) {
xasprintf(&identname, "tinc.%s", netname);
} else {
if(fp) {
if(!ecdsa_write_pem_private_key(key, fp)) {
fprintf(stderr, "Could not write ECDSA private key\n");
+ free(key);
return 1;
}
fclose(fp);
} else {
fprintf(stderr, "Could not open '%s' for writing: %s\n", argv[1], strerror(errno));
+ free(key);
return 1;
}
fprintf(stderr, "Could not write ECDSA public key\n");
}
+ free(key);
fclose(fp);
+ return 0;
} else {
fprintf(stderr, "Could not open '%s' for writing: %s\n", argv[2], strerror(errno));
+ free(key);
return 1;
}
-
- return 0;
}
int packetloss = 0;
int r;
int option_index = 0;
- ecdsa_t *mykey = NULL, *hiskey = NULL;
bool quit = false;
while((r = getopt_long(argc, argv, "dqrstwL:W:v46", long_options, &option_index)) != EOF) {
if(sock < 0) {
fprintf(stderr, "Could not create socket: %s\n", sockstrerror(sockerrno));
+ freeaddrinfo(ai);
return 1;
}
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one));
if(initiator) {
- if(connect(sock, ai->ai_addr, ai->ai_addrlen)) {
+ int res = connect(sock, ai->ai_addr, ai->ai_addrlen);
+
+ freeaddrinfo(ai);
+ ai = NULL;
+
+ if(res) {
fprintf(stderr, "Could not connect to peer: %s\n", sockstrerror(sockerrno));
return 1;
}
fprintf(stderr, "Connected\n");
} else {
- if(bind(sock, ai->ai_addr, ai->ai_addrlen)) {
+ int res = bind(sock, ai->ai_addr, ai->ai_addrlen);
+
+ freeaddrinfo(ai);
+ ai = NULL;
+
+ if(res) {
fprintf(stderr, "Could not bind socket: %s\n", sockstrerror(sockerrno));
return 1;
}
return 1;
}
+ ecdsa_t *mykey = NULL;
+
if(!(mykey = ecdsa_read_pem_private_key(fp))) {
return 1;
}
if(!fp) {
fprintf(stderr, "Could not open %s: %s\n", argv[2], strerror(errno));
+ free(mykey);
return 1;
}
+ ecdsa_t *hiskey = NULL;
+
if(!(hiskey = ecdsa_read_pem_public_key(fp))) {
+ free(mykey);
return 1;
}
sptps_t s;
if(!sptps_start(&s, &sock, initiator, datagram, mykey, hiskey, "sptps_test", 10, send_data, receive_record)) {
+ free(mykey);
+ free(hiskey);
return 1;
}
if(in < 0) {
fprintf(stderr, "Could not init stdin reader thread\n");
+ free(mykey);
+ free(hiskey);
return 1;
}
}
FD_SET(sock, &fds);
if(select(max_fd + 1, &fds, NULL, NULL, NULL) <= 0) {
+ free(mykey);
+ free(hiskey);
return 1;
}
if(len < 0) {
fprintf(stderr, "Could not read from stdin: %s\n", strerror(errno));
+ free(mykey);
+ free(hiskey);
return 1;
}
sptps_send_record(&s, 0, buf, len);
}
} else if(!sptps_send_record(&s, buf[0] == '!' ? 1 : 0, buf, (len == 1 && buf[0] == '\n') ? 0 : buf[0] == '*' ? sizeof(buf) : (size_t)len)) {
+ free(mykey);
+ free(hiskey);
return 1;
}
}
if(len < 0) {
fprintf(stderr, "Could not read from socket: %s\n", sockstrerror(sockerrno));
+ free(mykey);
+ free(hiskey);
return 1;
}
if(!done) {
if(!datagram) {
+ free(mykey);
+ free(hiskey);
return 1;
}
}
}
}
- if(!sptps_stop(&s)) {
+ bool stopped = sptps_stop(&s);
+
+ free(mykey);
+ free(hiskey);
+
+ if(!stopped) {
return 1;
}
break;
case 'c': /* config file */
+ free(confbase);
confbase = xstrdup(optarg);
confbasegiven = true;
break;
case 'n': /* net name given */
+ free(netname);
netname = xstrdup(optarg);
break;
break;
case 3: /* open control socket here */
+ free(pidfilename);
pidfilename = xstrdup(optarg);
break;
case '?': /* wrong options */
usage(true);
+ free_names();
return false;
default:
if(netname && (strpbrk(netname, "\\/") || *netname == '.')) {
fprintf(stderr, "Invalid character in netname!\n");
+ free_names();
return false;
}
#endif
+ char *default_c = "tincd";
+
if(slash++) {
xasprintf(&c, "%.*stincd", (int)(slash - program_name), program_name);
} else {
- c = "tincd";
+ c = default_c;
}
int nargc = 0;
#ifdef HAVE_MINGW
int status = spawnvp(_P_WAIT, c, nargv);
+ free(nargv);
+
+ if(c != default_c) {
+ free(c);
+ }
+
if(status == -1) {
fprintf(stderr, "Error starting %s: %s\n", c, strerror(errno));
return 1;
if(socketpair(AF_UNIX, SOCK_STREAM, 0, pfd)) {
fprintf(stderr, "Could not create umbilical socket: %s\n", strerror(errno));
free(nargv);
+
+ if(c != default_c) {
+ free(c);
+ }
+
return 1;
}
if(pid == -1) {
fprintf(stderr, "Could not fork: %s\n", strerror(errno));
free(nargv);
+
+ if(c != default_c) {
+ free(c);
+ }
+
return 1;
}
signal(SIGINT, SIG_DFL);
#endif
- if(failure || result != pid || !WIFEXITED(status) || WEXITSTATUS(status)) {
+ bool failed = failure || result != pid || !WIFEXITED(status) || WEXITSTATUS(status);
+
+ if(failed) {
fprintf(stderr, "Error starting %s\n", c);
- return 1;
}
- return 0;
+ if(c != default_c) {
+ free(c);
+ }
+
+ return failed ? EXIT_FAILURE : EXIT_SUCCESS;
#endif
}
if(node && !check_id(node)) {
fprintf(stderr, "Invalid name for node.\n");
+
+ if(node != line) {
+ free(node);
+ }
+
return 1;
}
fprintf(stderr, "Warning: %s is not a known configuration variable!\n", variable);
} else {
fprintf(stderr, "%s: is not a known configuration variable! Use --force to use it anyway.\n", variable);
+
+ if(node && node != line) {
+ free(node);
+ }
+
return 1;
}
}
if(node) {
snprintf(filename, sizeof(filename), "%s" SLASH "%s", hosts_dir, node);
+
+ if(node != line) {
+ free(node);
+ node = NULL;
+ }
} else {
snprintf(filename, sizeof(filename), "%s", tinc_conf);
}
break;
case 'c': /* config file */
+ free(confbase);
confbase = xstrdup(optarg);
break;
case 'L': /* no detach */
#ifndef HAVE_MLOCKALL
logger(DEBUG_ALWAYS, LOG_ERR, "The %s option is not supported on this platform.", argv[optind - 1]);
- return false;
+ goto exit_fail;
#else
do_mlock = true;
break;
break;
case 'n': /* net name given */
+ free(netname);
netname = xstrdup(optarg);
break;
cfg = parse_config_line(optarg, NULL, ++lineno);
if(!cfg) {
- return false;
+ goto exit_fail;
}
list_insert_tail(cmdline_conf, cfg);
case 'R':
case 'U':
logger(DEBUG_ALWAYS, LOG_ERR, "The %s option is not supported on this platform.", argv[optind - 1]);
- return false;
+ goto exit_fail;
#else
case 'R': /* chroot to NETNAME dir */
}
if(optarg) {
+ free(logfilename);
logfilename = xstrdup(optarg);
}
break;
case 5: /* open control socket here */
+ free(pidfilename);
pidfilename = xstrdup(optarg);
break;
case '?': /* wrong options */
usage(true);
- return false;
+ goto exit_fail;
default:
break;
if(optind < argc) {
fprintf(stderr, "%s: unrecognized argument '%s'\n", argv[0], argv[optind]);
usage(true);
- return false;
+ goto exit_fail;
}
if(!netname && (netname = getenv("NETNAME"))) {
if(netname && !check_netname(netname, false)) {
fprintf(stderr, "Invalid character in netname!\n");
- return false;
+ goto exit_fail;
}
if(netname && !check_netname(netname, true)) {
}
return true;
+
+exit_fail:
+ free_names();
+ free(cmdline_conf);
+ cmdline_conf = NULL;
+ return false;
}
static bool drop_privs(void) {
# define setpriority(level) (setpriority(PRIO_PROCESS, 0, (level)))
#endif
+static void cleanup() {
+ if(config_tree) {
+ exit_configuration(&config_tree);
+ }
+
+ free(cmdline_conf);
+ free_names();
+}
+
int main(int argc, char **argv) {
program_name = argv[0];
}
make_names(true);
+ atexit(cleanup);
+
chdir(confbase);
#ifdef HAVE_MINGW
crypto_exit();
- exit_configuration(&config_tree);
- free(cmdline_conf);
- free_names();
-
return status;
}