From d9a861331f31ac2d492f99af2bb8a12838eac768 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sun, 10 Aug 2014 21:40:19 -0400 Subject: [PATCH] Use DNS server list instead of hard coding domains/keys --- cfg/install.mk | 2 +- misc/DNSservers | 2 + src/dns.c | 128 +++++++++++++++++++++++++++++++++++++++-------- src/misc_tools.c | 19 +++++++ src/misc_tools.h | 3 ++ src/toxic.c | 27 +++++----- 6 files changed, 145 insertions(+), 36 deletions(-) create mode 100644 misc/DNSservers diff --git a/cfg/install.mk b/cfg/install.mk index 1d04404..9cf266d 100644 --- a/cfg/install.mk +++ b/cfg/install.mk @@ -1,7 +1,7 @@ MISC_DIR = ../misc DOC_DIR = ../doc SND_DIR = ../sounds -DATAFILES = DHTnodes toxic.conf.example +DATAFILES = DHTnodes DNSservers toxic.conf.example MANFILES = toxic.1 toxic.conf.5 SNDFILES = ContactLogsIn.wav ContactLogsOut.wav Error.wav IncomingCall.wav SNDFILES += LogIn.wav LogOut.wav NewMessage.wav OutgoingCall.wav diff --git a/misc/DNSservers b/misc/DNSservers new file mode 100644 index 0000000..d82acbe --- /dev/null +++ b/misc/DNSservers @@ -0,0 +1,2 @@ +utox.org d3154f65d28a5b41a05d4ac7e4b39c6b1c233cc857fb365c56e8392737462a12 +toxme.se 5d72c517df6aec54f1e977a6b6f25914ea4cf7277a85027cd9f5196df17e0b13 diff --git a/src/dns.c b/src/dns.c index 154300c..a4ce046 100644 --- a/src/dns.c +++ b/src/dns.c @@ -40,19 +40,21 @@ #include "dns.h" #include "global_commands.h" #include "misc_tools.h" +#include "configdir.h" +#define DNS3_KEY_SIZE 32 #define MAX_DNS_REQST_SIZE 256 -#define NUM_DNS3_SERVERS 2 /* must correspond to number of items in dns3_servers array */ +#define NUM_DNS3_BACKUP_SERVERS 2 /* must correspond to number of items in dns3_servers array */ #define TOX_DNS3_TXT_PREFIX "v=tox3;id=" -#define DNS3_KEY_SZ 32 extern struct _Winthread Winthread; +extern struct _dns3_servers dns3_servers; -/* TODO: process keys from key file instead of hard-coding like a noob */ -static struct dns3_server { +/* Hardcoded backup in case domain list is not loaded */ +static struct dns3_server_backup { const char *name; - char key[DNS3_KEY_SZ]; -} dns3_servers[] = { + char key[DNS3_KEY_SIZE]; +} dns3_servers_backup[] = { { "utox.org", { @@ -84,6 +86,54 @@ static struct _dns_thread { } dns_thread; +#define MAX_DNS_SERVERS 50 +#define MAX_DOMAIN_SIZE 128 +#define MAX_DNS_LINE MAX_DOMAIN_SIZE + DNS3_KEY_SIZE + 2 + +struct _dns3_servers { + bool loaded; + int lines; + char names[MAX_DNS_SERVERS][MAX_DOMAIN_SIZE]; + char keys[MAX_DNS_SERVERS][DNS3_KEY_SIZE]; +} dns3_servers; + +static int load_dns_domainlist(void) +{ + const char *path = PACKAGE_DATADIR "/DNSservers"; + FILE *fp = fopen(path, "r"); + + if (fp == NULL) + return -1; + + char line[MAX_DNS_LINE]; + + while (fgets(line, sizeof(line), fp) && dns3_servers.lines < MAX_DNS_SERVERS) { + if (strlen(line) < (2 * DNS3_KEY_SIZE) + 4) + continue; + + const char *name = strtok(line, " "); + const char *keystr = strtok(NULL, " "); + + if (name == NULL || keystr == NULL) + continue; + + snprintf(dns3_servers.names[dns3_servers.lines], sizeof(dns3_servers.names[dns3_servers.lines]), "%s", name); + int res = hex_string_to_bytes(dns3_servers.keys[dns3_servers.lines], DNS3_KEY_SIZE, keystr, strlen(keystr)); + + if (res == -1) + continue; + + ++dns3_servers.lines; + } + + fclose(fp); + + if (dns3_servers.lines < 1) + return -2; + + return 0; +} + static int dns_error(ToxWindow *self, const char *errmsg) { pthread_mutex_lock(&Winthread.lock); @@ -191,35 +241,61 @@ static int parse_addr(const char *addr, char *namebuf, char *dombuf) return strlen(namebuf); } +/* matches input domain name with domains in list and obtains key. Return 0 on success, -1 on failure */ +static int get_domain_match(char *pubkey, char *domain, const char *inputdomain) +{ + /* check server list first */ + int i; + bool match = false; + + for (i = 0; i < dns3_servers.lines; ++i) { + if (strcmp(dns3_servers.names[i], inputdomain) == 0) { + memcpy(pubkey, dns3_servers.keys[i], DNS3_KEY_SIZE); + snprintf(domain, MAX_DOMAIN_SIZE, "%s", dns3_servers.names[i]); + match = true; + break; + } + } + + /* fall back to hard-coded domains on server list failure */ + if (!match) { + for (i = 0; i < NUM_DNS3_BACKUP_SERVERS; ++i) { + if (strcmp(dns3_servers_backup[i].name, inputdomain) == 0) { + memcpy(pubkey, dns3_servers_backup[i].key, DNS3_KEY_SIZE); + snprintf(domain, MAX_DOMAIN_SIZE, "%s", dns3_servers_backup[i].name); + match = true; + break; + } + } + + if (!match) + return -1; + } + + return 0; +} + /* Does DNS lookup for addr and puts resulting tox id in id_bin. */ void *dns3_lookup_thread(void *data) { ToxWindow *self = t_data.self; - char domain[MAX_STR_SIZE]; + char inputdomain[MAX_STR_SIZE]; char name[MAX_STR_SIZE]; - int namelen = parse_addr(t_data.addr, name, domain); + int namelen = parse_addr(t_data.addr, name, inputdomain); if (namelen == -1) { dns_error(self, "Must be a Tox ID or an address in the form username@domain"); kill_dns_thread(NULL); } - /* get domain name/pub key */ - const char *DNS_pubkey = NULL; - const char *domname = NULL; - int i; + char DNS_pubkey[DNS3_KEY_SIZE]; + char domain[MAX_DOMAIN_SIZE]; - for (i = 0; i < NUM_DNS3_SERVERS; ++i) { - if (strcmp(dns3_servers[i].name, domain) == 0) { - DNS_pubkey = dns3_servers[i].key; - domname = dns3_servers[i].name; - break; - } - } + int match = get_domain_match(DNS_pubkey, domain, inputdomain); - if (domname == NULL) { + if (match == -1) { dns_error(self, "Domain not found."); kill_dns_thread(NULL); } @@ -248,7 +324,7 @@ void *dns3_lookup_thread(void *data) char d_string[MAX_DNS_REQST_SIZE]; /* format string and create dns query */ - snprintf(d_string, sizeof(d_string), "_%s._tox.%s", string, domname); + snprintf(d_string, sizeof(d_string), "_%s._tox.%s", string, domain); int ans_len = res_query(d_string, C_IN, T_TXT, answer, sizeof(answer)); if (ans_len <= 0) { @@ -296,6 +372,16 @@ void dns3_lookup(ToxWindow *self, Tox *m, const char *id_bin, const char *addr, return; } + if (!dns3_servers.loaded) { + dns3_servers.loaded = true; + int ret = load_dns_domainlist(); + + if (ret < 0) { + const char *errmsg = "DNS server list failed to load with error code %d. Falling back to hard-coded list."; + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, errmsg, ret); + } + } + snprintf(t_data.id_bin, sizeof(t_data.id_bin), "%s", id_bin); snprintf(t_data.addr, sizeof(t_data.addr), "%s", addr); snprintf(t_data.msg, sizeof(t_data.msg), "%s", msg); diff --git a/src/misc_tools.c b/src/misc_tools.c index dff2643..aa2e2d6 100644 --- a/src/misc_tools.c +++ b/src/misc_tools.c @@ -124,6 +124,25 @@ char *hex_string_to_bin(const char *hex_string) return val; } +int hex_string_to_bytes(char *buf, int size, const char *keystr, int strsize) +{ + if (size % 2 != 0) + return -1; + + int i, res; + const char *pos = keystr; + + for (i = 0; i < size; ++i) { + res = sscanf(pos, "%2hhx", &buf[i]); + pos += 2; + + if (res == EOF || res < 1) + return -1; + } + + return 0; +} + /* Returns 1 if the string is empty, 0 otherwise */ int string_is_empty(const char *string) { diff --git a/src/misc_tools.h b/src/misc_tools.h index a8f396d..4ba2628 100644 --- a/src/misc_tools.h +++ b/src/misc_tools.h @@ -42,6 +42,9 @@ void host_to_net(uint8_t *num, uint16_t numbytes); /* convert a hex string to binary */ char *hex_string_to_bin(const char *hex_string); +/* convert a hex string to bytes. returns 0 on success, -1 on failure */ +int hex_string_to_bytes(char *buf, int size, const char *keystr, int strsize); + /* get the current unix time */ uint64_t get_unix_time(void); diff --git a/src/toxic.c b/src/toxic.c index 3386d12..b607f87 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -226,10 +226,10 @@ static Tox *init_tox(int ipv4) return m; } -#define MINLINE 50 /* IP: 7 + port: 5 + key: 38 + spaces: 2 = 70. ! (& e.g. tox.im = 6) */ -#define MAXLINE 256 /* Approx max number of chars in a sever line (name + port + key) */ +#define MIN_NODE_LINE 50 /* IP: 7 + port: 5 + key: 38 + spaces: 2 = 70. ! (& e.g. tox.im = 6) */ +#define MAX_NODE_LINE 256 /* Approx max number of chars in a sever line (name + port + key) */ #define MAXNODES 50 -#define NODELEN (MAXLINE - TOX_CLIENT_ID_SIZE - 7) +#define NODELEN (MAX_NODE_LINE - TOX_CLIENT_ID_SIZE - 7) static struct _toxNodes { int lines; @@ -238,7 +238,7 @@ static struct _toxNodes { char keys[MAXNODES][TOX_CLIENT_ID_SIZE]; } toxNodes; -static int nodelist_load(const char *filename) +static int load_nodelist(const char *filename) { if (!filename) return 1; @@ -248,10 +248,10 @@ static int nodelist_load(const char *filename) if (fp == NULL) return 1; - char line[MAXLINE]; + char line[MAX_NODE_LINE]; while (fgets(line, sizeof(line), fp) && toxNodes.lines < MAXNODES) { - if (strlen(line) > MINLINE) { + if (strlen(line) > MIN_NODE_LINE) { const char *name = strtok(line, " "); const char *port = strtok(NULL, " "); const char *key_ascii = strtok(NULL, " "); @@ -272,12 +272,11 @@ static int nodelist_load(const char *filename) } } - if (toxNodes.lines < 1) { - fclose(fp); - return 2; - } - fclose(fp); + + if (toxNodes.lines < 1) + return 1; + return 0; } @@ -313,11 +312,11 @@ int init_connection(Tox *m) int res; if (!arg_opts.nodes_path[0]) - res = nodelist_load(PACKAGE_DATADIR "/DHTnodes"); + res = load_nodelist(PACKAGE_DATADIR "/DHTnodes"); else - res = nodelist_load(arg_opts.nodes_path); + res = load_nodelist(arg_opts.nodes_path); - if (toxNodes.lines < 1) + if (res != 0) return res; res = 3;