Don't force a .bat extension for scripts under Windows.
[tinc] / src / invitation.c
index 7a6a91b..a590450 100644 (file)
 #include "utils.h"
 #include "xalloc.h"
 
-#ifdef HAVE_MINGW
-#define SCRIPTEXTENSION ".bat"
-#else
-#define SCRIPTEXTENSION ""
-#endif
-
 int addressfamily = AF_UNSPEC;
 
 char *get_my_hostname() {
        char *hostname = NULL;
+       char *port = NULL;
+       char *hostport = NULL;
        char *name = get_my_name(false);
        char *filename = NULL;
 
@@ -61,20 +57,21 @@ char *get_my_hostname() {
                                if(*q == '=')
                                        q += 1 + strspn(q + 1, "\t ");
                                *p = 0;
-                               if(strcasecmp(line, "Address"))
-                                       continue;
                                p = q + strcspn(q, "\t ");
                                if(*p)
                                        *p++ = 0;
                                p += strspn(p, "\t ");
                                p[strcspn(p, "\t ")] = 0;
+                               if(!port && !strcasecmp(line, "Port")) {
+                                       port = xstrdup(q);
+                                       continue;
+                               }
+                               if(strcasecmp(line, "Address"))
+                                       continue;
+                               hostname = xstrdup(q);
                                if(*p) {
-                                       if(strchr(q, ':'))
-                                               xasprintf(&hostname, "[%s]:%s", q, p);
-                                       else
-                                               xasprintf(&hostname, "%s:%s", q, p);
-                               } else {
-                                       hostname = xstrdup(q);
+                                       free(port);
+                                       port = xstrdup(p);
                                }
                                break;
                        }
@@ -82,10 +79,8 @@ char *get_my_hostname() {
                }
        }
 
-       if(hostname) {
-               free(filename);
-               return hostname;
-       }
+       if(hostname)
+               goto done;
 
        // If that doesn't work, guess externally visible hostname
        fprintf(stderr, "Trying to discover externally visible hostname...\n");
@@ -142,7 +137,7 @@ again:
 
        if(!rstrip(line)) {
                if(hostname)
-                       goto done;
+                       goto save;
                else
                        goto again;
        }
@@ -157,7 +152,7 @@ again:
        free(hostname);
        hostname = xstrdup(line);
 
-done:
+save:
        if(filename) {
                FILE *f = fopen(filename, "a");
                if(f) {
@@ -166,10 +161,23 @@ done:
                } else {
                        fprintf(stderr, "Could not append Address to %s: %s\n", filename, strerror(errno));
                }
-               free(filename);
        }
 
-       return hostname;
+done:
+       if(port) {
+               if(strchr(hostname, ':'))
+                       xasprintf(&hostport, "[%s]:%s", hostname, port);
+               else
+                       xasprintf(&hostport, "%s:%s", hostname, port);
+       } else {
+               hostport = hostname;
+               hostname = NULL;
+       }
+
+       free(hostname);
+       free(port);
+       free(filename);
+       return hostport;
 }
 
 static bool fcopy(FILE *out, const char *filename) {
@@ -476,6 +484,9 @@ static bool finalize_join(void) {
        if(!netname)
                netname = grep(data, "NetName");
 
+       bool ask_netname = false;
+       char temp_netname[32];
+
 make_names:
        if(!confbasegiven) {
                free(confbase);
@@ -494,26 +505,20 @@ make_names:
                fprintf(stderr, "Configuration file %s already exists!\n", tinc_conf);
                if(!tty || confbasegiven)
                        return false;
-ask_netname:
-               fprintf(stderr, "Enter a new netname: ");
-               if(!fgets(line, sizeof line, stdin)) {
-                       fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno));
-                       return false;
-               }
-               if(!*line || *line == '\n')
-                       goto ask_netname;
 
-               line[strlen(line) - 1] = 0;
-               netname = line;
+               // Generate a random netname, ask for a better one later.
+               ask_netname = true;
+               snprintf(temp_netname, sizeof temp_netname, "join_%x", rand());
+               netname = temp_netname;
                goto make_names;
        }       
 
-       if(mkdir(confbase, 0755) && errno != EEXIST) {
+       if(mkdir(confbase, 0777) && errno != EEXIST) {
                fprintf(stderr, "Could not create directory %s: %s\n", confbase, strerror(errno));
                return false;
        }
 
-       if(mkdir(hosts_dir, 0755) && errno != EEXIST) {
+       if(mkdir(hosts_dir, 0777) && errno != EEXIST) {
                fprintf(stderr, "Could not create directory %s: %s\n", hosts_dir, strerror(errno));
                return false;
        }
@@ -641,12 +646,7 @@ ask_netname:
                return false;
 
        xasprintf(&filename, "%s" SLASH "ecdsa_key.priv", confbase);
-       f = fopen(filename, "w");
-
-#ifdef HAVE_FCHMOD
-       /* Make it unreadable for others. */
-       fchmod(fileno(f), 0600);
-#endif
+       f = fopenmask(filename, "w", 0600);
 
        if(!ecdsa_write_pem_private_key(key, f)) {
                fprintf(stderr, "Error writing private key!\n");
@@ -665,12 +665,7 @@ ask_netname:
 
        rsa_t *rsa = rsa_generate(2048, 0x1001);
        xasprintf(&filename, "%s" SLASH "rsa_key.priv", confbase);
-       f = fopen(filename, "w");
-
-#ifdef HAVE_FCHMOD
-       /* Make it unreadable for others. */
-       fchmod(fileno(f), 0600);
-#endif
+       f = fopenmask(filename, "w", 0600);
 
        rsa_write_pem_private_key(rsa, f);
        fclose(f);
@@ -681,10 +676,37 @@ ask_netname:
        ecdsa_free(key);
        rsa_free(rsa);
 
+       check_port(name);
+
        fprintf(stderr, "Invitation succesfully accepted.\n");
        shutdown(sock, SHUT_RDWR);
        success = true;
 
+ask_netname:
+       if(ask_netname) {
+               fprintf(stderr, "Enter a new netname: ");
+               if(!fgets(line, sizeof line, stdin)) {
+                       fprintf(stderr, "Error while reading stdin: %s\n", strerror(errno));
+                       return false;
+               }
+               if(!*line || *line == '\n')
+                       goto ask_netname;
+
+               line[strlen(line) - 1] = 0;
+
+               char *newbase;
+               xasprintf(&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();
+       }
+
        return true;
 }
 
@@ -733,9 +755,25 @@ int cmd_join(int argc, char *argv[]) {
                return 1;
        }
 
-       // Make sure confdir exists.
-       if(mkdir(confdir, 0755) && errno != EEXIST) {
-               fprintf(stderr, "Could not create directory %s: %s\n", CONFDIR, strerror(errno));
+       // Make sure confbase exists and is accessible.
+       if(strcmp(confdir, confbase) && mkdir(confdir, 0755) && errno != EEXIST) {
+               fprintf(stderr, "Could not create directory %s: %s\n", confdir, strerror(errno));
+               return 1;
+       }
+
+       if(mkdir(confbase, 0777) && errno != EEXIST) {
+               fprintf(stderr, "Could not create directory %s: %s\n", confbase, strerror(errno));
+               return 1;
+       }
+
+       if(access(confbase, R_OK | W_OK | X_OK)) {
+               fprintf(stderr, "No permission to write in directory %s: %s\n", confbase, strerror(errno));
+               return 1;
+       }
+
+       // If a netname or explicit configuration directory is specified, check for an existing tinc.conf.
+       if((netname || confbasegiven) && !access(tinc_conf, F_OK)) {
+               fprintf(stderr, "Configuration file %s already exists!\n", tinc_conf);
                return 1;
        }
 
@@ -837,7 +875,7 @@ int cmd_join(int argc, char *argv[]) {
                return 1;
        }
 
-       // Check if the hash of the key he have us matches the hash in the URL.
+       // Check if the hash of the key he gave us matches the hash in the URL.
        char *fingerprint = line + 2;
        digest_t *digest = digest_open_by_name("sha256", 18);
        if(!digest)