#include "crypto.h"
#include "ecdsa.h"
#include "ecdsagen.h"
+#include "ifconfig.h"
#include "invitation.h"
#include "names.h"
#include "netutl.h"
#include "rsagen.h"
#include "script.h"
#include "sptps.h"
+#include "subnet.h"
#include "tincctl.h"
#include "utils.h"
#include "xalloc.h"
char *port = NULL;
char *hostport = NULL;
char *name = get_my_name(false);
- char filename[PATH_MAX];
+ char filename[PATH_MAX] = {0};
// Use first Address statement in own host config file
if(check_id(name)) {
hostname = xstrdup(line);
save:
- if(filename) {
+ if(*filename) {
FILE *f = fopen(filename, "a");
if(f) {
fprintf(f, "\nAddress = %s\n", hostname);
return 1;
}
chmod(filename, 0600);
- ecdsa_write_pem_private_key(key, f);
+ if(!ecdsa_write_pem_private_key(key, f)) {
+ fprintf(stderr, "Could not write ECDSA private key\n");
+ fclose(f);
+ return 1;
+ }
fclose(f);
if(connect_tincd(false))
// Fill in the details.
fprintf(f, "Name = %s\n", argv[1]);
- if(netname)
+ if(check_netname(netname, true))
fprintf(f, "NetName = %s\n", netname);
fprintf(f, "ConnectTo = %s\n", myname);
}
if(!check_id(name)) {
- fprintf(stderr, "Invalid Name found in invitation: %s!\n", name);
+ fprintf(stderr, "Invalid Name found in invitation!\n");
return false;
}
- if(!netname)
+ if(!netname) {
netname = grep(data, "NetName");
+ if(netname && !check_netname(netname, true)) {
+ fprintf(stderr, "Unsafe NetName found in invitation!\n");
+ return false;
+ }
+ }
bool ask_netname = false;
char temp_netname[32];
return false;
}
+ snprintf(filename, sizeof filename, "%s" SLASH "tinc-up.invitation", confbase);
+ FILE *fup = fopen(filename, "w");
+ if(!fup) {
+ fprintf(stderr, "Could not create file %s: %s\n", filename, strerror(errno));
+ fclose(f);
+ fclose(fh);
+ return false;
+ }
+
+ ifconfig_header(fup);
+
// Filter first chunk on approved keywords, split between tinc.conf and hosts/Name
+ // Generate a tinc-up script from Ifconfig and Route keywords.
// Other chunks go unfiltered to their respective host config files
const char *p = data;
char *l, *value;
break;
}
+ // Handle Ifconfig and Route statements
+ if(!found) {
+ if(!strcasecmp(l, "Ifconfig")) {
+ if(!strcasecmp(value, "dhcp"))
+ ifconfig_dhcp(fup);
+ else if(!strcasecmp(value, "dhcp6"))
+ ifconfig_dhcp6(fup);
+ else if(!strcasecmp(value, "slaac"))
+ ifconfig_slaac(fup);
+ else
+ ifconfig_address(fup, value);
+ continue;
+ } else if(!strcasecmp(l, "Route")) {
+ ifconfig_route(fup, value);
+ continue;
+ }
+ }
+
// Ignore unknown and unsafe variables
if(!found) {
fprintf(stderr, "Ignoring unknown variable '%s' in invitation.\n", l);
}
fclose(f);
+ bool valid_tinc_up = ifconfig_footer(fup);
+ fclose(fup);
while(l && !strcasecmp(l, "Name")) {
if(!check_id(value)) {
snprintf(filename, sizeof filename, "%s" SLASH "ed25519_key.priv", confbase);
f = fopenmask(filename, "w", 0600);
+ if(!f)
+ return false;
if(!ecdsa_write_pem_private_key(key, f)) {
fprintf(stderr, "Error writing private key!\n");
snprintf(filename, sizeof filename, "%s" SLASH "rsa_key.priv", confbase);
f = fopenmask(filename, "w", 0600);
- rsa_write_pem_private_key(rsa, f);
+ if(!f || !rsa_write_pem_private_key(rsa, f)) {
+ fprintf(stderr, "Could not write private RSA key\n");
+ } else if(!rsa_write_pem_public_key(rsa, fh)) {
+ fprintf(stderr, "Could not write public RSA key\n");
+ }
+
fclose(f);
- rsa_write_pem_public_key(rsa, fh);
fclose(fh);
rsa_free(rsa);
make_names(false);
}
+ char filename2[PATH_MAX];
+ snprintf(filename, sizeof filename, "%s" SLASH "tinc-up.invitation", confbase);
+ snprintf(filename2, sizeof filename2, "%s" SLASH "tinc-up", confbase);
+
+ if(valid_tinc_up) {
+ if(tty) {
+ FILE *fup = fopen(filename, "r");
+ if(fup) {
+ fprintf(stderr, "\nPlease review the following tinc-up script:\n\n");
+
+ char buf[MAXSIZE];
+ while(fgets(buf, sizeof buf, fup))
+ fputs(buf, stderr);
+ fclose(fup);
+
+ int response = 0;
+ do {
+ fprintf(stderr, "\nDo you want to use this script [y]es/[n]o/[e]dit? ");
+ response = tolower(getchar());
+ } while(!strchr("yne", response));
+
+ fprintf(stderr, "\n");
+
+ if(response == 'e') {
+ char *command;
+#ifndef HAVE_MINGW
+ xasprintf(&command, "\"%s\" \"%s\"", getenv("VISUAL") ?: getenv("EDITOR") ?: "vi", filename);
+#else
+ xasprintf(&command, "edit \"%s\"", filename);
+#endif
+ if(system(command))
+ response = 'n';
+ else
+ response = 'y';
+ free(command);
+ }
+
+ if(response == 'y') {
+ rename(filename, filename2);
+ chmod(filename2, 0755);
+ fprintf(stderr, "tinc-up enabled.\n");
+ } else {
+ fprintf(stderr, "tinc-up has been left disabled.\n");
+ }
+ }
+ } else {
+ fprintf(stderr, "A tinc-up script was generated, but has been left disabled.\n");
+ }
+ } else {
+ // A placeholder was generated.
+ rename(filename, filename2);
+ chmod(filename2, 0755);
+ }
+
fprintf(stderr, "Configuration stored in: %s\n", confbase);
return true;