Let a server explicitly send a notification when the invitation protocol succeeded.
[tinc] / src / invitation.c
index e5085ce..7498704 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() {
@@ -90,12 +84,14 @@ char *get_my_hostname() {
 
        // If that doesn't work, guess externally visible hostname
        fprintf(stderr, "Trying to discover externally visible hostname...\n");
-       struct addrinfo *ai = str2addrinfo("ifconfig.me", "80", SOCK_STREAM);
-       static const char request[] = "GET /host HTTP/1.0\r\n\r\n";
-       if(ai) {
-               int s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+       struct addrinfo *ai = str2addrinfo("tinc-vpn.org", "80", SOCK_STREAM);
+       struct addrinfo *aip = ai;
+       static const char request[] = "GET http://tinc-vpn.org/host.cgi HTTP/1.0\r\n\r\n";
+
+       while(aip) {
+               int s = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
                if(s >= 0) {
-                       if(connect(s, ai->ai_addr, ai->ai_addrlen)) {
+                       if(connect(s, aip->ai_addr, aip->ai_addrlen)) {
                                closesocket(s);
                                s = -1;
                        }
@@ -112,14 +108,20 @@ char *get_my_hostname() {
                                        hostname = xstrdup(p + 1);
                        }
                        closesocket(s);
+                       if(hostname)
+                               break;
                }
-               freeaddrinfo(ai);
+               aip = aip->ai_next;
+               continue;
        }
 
+       if(ai)
+               freeaddrinfo(ai);
+
        // Check that the hostname is reasonable
        if(hostname) {
                for(char *p = hostname; *p; p++) {
-                       if(isalnum(*p) || *p == '-' || *p == '.')
+                       if(isalnum(*p) || *p == '-' || *p == '.' || *p == ':')
                                continue;
                        // If not, forget it.
                        free(hostname);
@@ -362,6 +364,9 @@ int cmd_invite(int argc, char *argv[]) {
        if(!f)
                abort();
 
+       // Get the local address
+       char *address = get_my_hostname();
+
        // Fill in the details.
        fprintf(f, "Name = %s\n", argv[1]);
        if(netname)
@@ -376,7 +381,6 @@ int cmd_invite(int argc, char *argv[]) {
        fclose(f);
 
        // Create an URL from the local address, key hash and cookie
-       char *address = get_my_hostname();
        printf("%s/%s%s\n", address, hash, cookie);
        free(filename);
        free(address);
@@ -519,12 +523,12 @@ make_names:
                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;
        }
@@ -652,12 +656,7 @@ make_names:
                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");
@@ -676,12 +675,7 @@ make_names:
 
        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);
@@ -694,10 +688,6 @@ make_names:
 
        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: ");
@@ -726,6 +716,7 @@ ask_netname:
        return true;
 }
 
+
 static bool invitation_send(void *handle, uint8_t type, const char *data, size_t len) {
        while(len) {
                int result = send(sock, data, len, 0);
@@ -754,6 +745,12 @@ static bool invitation_receive(void *handle, uint8_t type, const char *msg, uint
                case 1:
                        return finalize_join();
 
+               case 2:
+                       fprintf(stderr, "Invitation succesfully accepted.\n");
+                       shutdown(sock, SHUT_RDWR);
+                       success = true;
+                       break;
+
                default:
                        return false;
        }
@@ -772,7 +769,12 @@ int cmd_join(int argc, char *argv[]) {
        }
 
        // Make sure confbase exists and is accessible.
-       if(mkdir(confbase, 0755) && errno != EEXIST) {
+       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;
        }
@@ -886,7 +888,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)