X-Git-Url: https://tinc-vpn.org/git/browse?p=tinc;a=blobdiff_plain;f=src%2Finvitation.c;h=749870458e61a7ec9f3292af831c9d2401bc6d05;hp=7a6a91b7465401e14e099b9a3f58fe2adfd57ef2;hb=5dec1c25713a19c49fcbb885200184a9682ef175;hpb=ced4c1a327b321a6d73028a3a15b41b0be64d910 diff --git a/src/invitation.c b/src/invitation.c index 7a6a91b7..74987045 100644 --- a/src/invitation.c +++ b/src/invitation.c @@ -32,16 +32,12 @@ #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,19 +79,19 @@ 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"); - 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; } @@ -111,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); @@ -142,7 +145,7 @@ again: if(!rstrip(line)) { if(hostname) - goto done; + goto save; else goto again; } @@ -157,7 +160,7 @@ again: free(hostname); hostname = xstrdup(line); -done: +save: if(filename) { FILE *f = fopen(filename, "a"); if(f) { @@ -166,10 +169,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) { @@ -348,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) @@ -362,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); @@ -476,6 +494,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 +515,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 +656,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 +675,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,13 +686,37 @@ ask_netname: ecdsa_free(key); rsa_free(rsa); - fprintf(stderr, "Invitation succesfully accepted.\n"); - shutdown(sock, SHUT_RDWR); - success = true; + check_port(name); + +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; } + static bool invitation_send(void *handle, uint8_t type, const char *data, size_t len) { while(len) { int result = send(sock, data, len, 0); @@ -716,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; } @@ -733,9 +768,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 +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)