X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Flibmeshlink.c;h=c05d17813a3fbe6e63bee1062222e712f83c5c6d;hb=3113556aba931142a93384ebd9ba43c842761561;hp=04e3141561b4aa1d582562872de17278d82d69f9;hpb=bdfa996a1b6f1f50f69b2ecad259b50756f44bf7;p=meshlink diff --git a/src/libmeshlink.c b/src/libmeshlink.c index 04e31415..c05d1781 100644 --- a/src/libmeshlink.c +++ b/src/libmeshlink.c @@ -18,7 +18,180 @@ */ #include "libmeshlink.h" +#include "crypto.h" +#include "ecdsagen.h" +char *hosts_dir = NULL; +static char *name = NULL; + +/* + Generate a public/private ECDSA keypair, and ask for a file to store + them in. +*/ +bool ecdsa_keygen(bool ask) { + ecdsa_t *key; + FILE *f; + char *pubname, *privname; + + fprintf(stderr, "Generating ECDSA keypair:\n"); + + if(!(key = ecdsa_generate())) { + fprintf(stderr, "Error during key generation!\n"); + return false; + } else + fprintf(stderr, "Done.\n"); + + xasprintf(&privname, "%s" SLASH "ecdsa_key.priv", confbase); + //f = ask_and_open(privname, "private ECDSA key", "a", ask, 0600); //this function is not ported to lib because makes no sense + free(privname); + + if(!f) + return false; + + if(!ecdsa_write_pem_private_key(key, f)) { + fprintf(stderr, "Error writing private key!\n"); + ecdsa_free(key); + fclose(f); + return false; + } + + fclose(f); + + if(name) + xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, name); + else + xasprintf(&pubname, "%s" SLASH "ecdsa_key.pub", confbase); + + //f = ask_and_open(pubname, "public ECDSA key", "a", ask, 0666); + free(pubname); + + if(!f) + return false; + + char *pubkey = ecdsa_get_base64_public_key(key); + fprintf(f, "ECDSAPublicKey = %s\n", pubkey); + free(pubkey); + + fclose(f); + ecdsa_free(key); + + return true; +} + +/* + Generate a public/private RSA keypair, and ask for a file to store + them in. +*/ +bool rsa_keygen(int bits, bool ask) { + rsa_t *key; + FILE *f; + char *pubname, *privname; + + fprintf(stderr, "Generating %d bits keys:\n", bits); + + if(!(key = rsa_generate(bits, 0x10001))) { + fprintf(stderr, "Error during key generation!\n"); + return false; + } else + fprintf(stderr, "Done.\n"); + + xasprintf(&privname, "%s" SLASH "rsa_key.priv", confbase); + //f = ask_and_open(privname, "private RSA key", "a", ask, 0600); + free(privname); + + if(!f) + return false; + + if(!rsa_write_pem_private_key(key, f)) { + fprintf(stderr, "Error writing private key!\n"); + fclose(f); + rsa_free(key); + return false; + } + + fclose(f); + + if(name) + xasprintf(&pubname, "%s" SLASH "hosts" SLASH "%s", confbase, name); + else + xasprintf(&pubname, "%s" SLASH "rsa_key.pub", confbase); + + //f = ask_and_open(pubname, "public RSA key", "a", ask, 0666); + free(pubname); + + if(!f) + return false; + + if(!rsa_write_pem_public_key(key, f)) { + fprintf(stderr, "Error writing public key!\n"); + fclose(f); + rsa_free(key); + return false; + } + + fclose(f); + rsa_free(key); + + return true; +} + +static bool try_bind(int port) { + struct addrinfo *ai = NULL; + struct addrinfo hint = { + .ai_flags = AI_PASSIVE, + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + .ai_protocol = IPPROTO_TCP, + }; + + char portstr[16]; + snprintf(portstr, sizeof portstr, "%d", port); + + if(getaddrinfo(NULL, portstr, &hint, &ai) || !ai) + return false; + + while(ai) { + int fd = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP); + if(!fd) + return false; + int result = bind(fd, ai->ai_addr, ai->ai_addrlen); + closesocket(fd); + if(result) + return false; + ai = ai->ai_next; + } + + return true; +} + +int check_port(char *name) { + if(try_bind(655)) + return 655; + + fprintf(stderr, "Warning: could not bind to port 655. "); + + for(int i = 0; i < 100; i++) { + int port = 0x1000 + (rand() & 0x7fff); + if(try_bind(port)) { + char *filename; + xasprintf(&filename, "%s" SLASH "hosts" SLASH "%s", confbase, name); + FILE *f = fopen(filename, "a"); + free(filename); + if(!f) { + fprintf(stderr, "Please change tinc's Port manually.\n"); + return 0; + } + + fprintf(f, "Port = %d\n", port); + fclose(f); + fprintf(stderr, "Tinc will instead listen on port %d.\n", port); + return port; + } + } + + fprintf(stderr, "Please change tinc's Port manually.\n"); + return 0; +} //tinc_setup() should basically do what cmd_init() from src/tincctl.c does, except it doesn't have to generate a tinc-up script. bool tinc_setup(const char* tinc_conf, const char* name) { if(!access(tinc_conf, F_OK)) {