From cea5f1fe04865f49efec0cdbfafc7db69c152adf Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Tue, 20 Oct 2015 22:47:11 -0400 Subject: [PATCH 01/14] Fix avatar size limit and fix comment --- misc/toxic.conf.example | 2 +- src/toxic.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/misc/toxic.conf.example b/misc/toxic.conf.example index a4bf7fd..070796a 100644 --- a/misc/toxic.conf.example +++ b/misc/toxic.conf.example @@ -66,7 +66,7 @@ tox = { // Path for downloaded files // download_path="/home/USERNAME/Downloads/"; - // Path for your avatar (file must be a .png and cannot exceed 16.3 KiB) + // Path for your avatar (file must be a .png and cannot exceed 64 KiB) // avatar_path="/home/USERNAME/Pictures/youravatar.png"; // Path for chatlogs diff --git a/src/toxic.c b/src/toxic.c index 0a0c302..6dcf558 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -1077,7 +1077,6 @@ static void parse_args(int argc, char *argv[]) } /* Looks for an old default profile data file and blocklist, and renames them to the new default names. - * Saves the old data files under the names "toxic_data.old" and "toxic_data_blocklist.old". * * Returns 0 on success. * Returns -1 on failure. From 6b97df26157099ea76b64482b0cef1dfeaee88f3 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Thu, 22 Oct 2015 19:44:05 -0400 Subject: [PATCH 02/14] Add command to change the Tox ID nospam value --- src/chat.c | 5 +++-- src/execute.c | 1 + src/global_commands.c | 9 +++++++++ src/global_commands.h | 1 + src/groupchat.c | 5 +++-- src/help.c | 5 +++-- src/prompt.c | 5 +++-- 7 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/chat.c b/src/chat.c index 97ab127..1d2a419 100644 --- a/src/chat.c +++ b/src/chat.c @@ -63,9 +63,9 @@ static void kill_infobox(ToxWindow *self); #endif /* AUDIO */ #ifdef AUDIO -#define AC_NUM_CHAT_COMMANDS 27 +#define AC_NUM_CHAT_COMMANDS 28 #else -#define AC_NUM_CHAT_COMMANDS 20 +#define AC_NUM_CHAT_COMMANDS 21 #endif /* AUDIO */ /* Array of chat command names used for tab completion. */ @@ -86,6 +86,7 @@ static const char chat_cmd_list[AC_NUM_CHAT_COMMANDS][MAX_CMDNAME_SIZE] = { { "/myid" }, { "/nick" }, { "/note" }, + { "/nospam" }, { "/quit" }, { "/savefile" }, { "/sendfile" }, diff --git a/src/execute.c b/src/execute.c index 9e83a83..aedd5bc 100644 --- a/src/execute.c +++ b/src/execute.c @@ -53,6 +53,7 @@ static struct cmd_func global_commands[] = { { "/myid", cmd_myid }, { "/nick", cmd_nick }, { "/note", cmd_note }, + { "/nospam", cmd_nospam }, { "/q", cmd_quit }, { "/quit", cmd_quit }, { "/requests", cmd_requests }, diff --git a/src/global_commands.c b/src/global_commands.c index 1ce3b21..8f67b34 100644 --- a/src/global_commands.c +++ b/src/global_commands.c @@ -484,6 +484,15 @@ void cmd_note(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MA prompt_update_statusmessage(prompt, m, msg); } +void cmd_nospam(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) +{ + uint32_t nospam = rand(); /* should be random enough */ + tox_self_set_nospam(m, nospam); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Your Tox ID has been changed to:"); + cmd_myid(window, self, m, 0, NULL); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Any services that relied on your old ID will need to be updated manually."); +} + void cmd_prompt_help(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]) { help_init_menu(self); diff --git a/src/global_commands.h b/src/global_commands.h index 277f0f1..85dccaa 100644 --- a/src/global_commands.h +++ b/src/global_commands.h @@ -37,6 +37,7 @@ void cmd_log(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]) void cmd_myid(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_nick(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_note(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); +void cmd_nospam(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_prompt_help(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_quit(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); void cmd_requests(WINDOW *, ToxWindow *, Tox *, int argc, char (*argv)[MAX_STR_SIZE]); diff --git a/src/groupchat.c b/src/groupchat.c index ce568d8..7d80b57 100644 --- a/src/groupchat.c +++ b/src/groupchat.c @@ -70,9 +70,9 @@ extern struct user_settings *user_settings; extern struct Winthread Winthread; #ifdef AUDIO -#define AC_NUM_GROUP_COMMANDS 22 +#define AC_NUM_GROUP_COMMANDS 23 #else -#define AC_NUM_GROUP_COMMANDS 18 +#define AC_NUM_GROUP_COMMANDS 19 #endif /* AUDIO */ /* Array of groupchat command names used for tab completion. */ @@ -91,6 +91,7 @@ static const char group_cmd_list[AC_NUM_GROUP_COMMANDS][MAX_CMDNAME_SIZE] = { { "/myid" }, { "/nick" }, { "/note" }, + { "/nospam" }, { "/quit" }, { "/requests" }, { "/status" }, diff --git a/src/help.c b/src/help.c index 8989c11..87eb76d 100644 --- a/src/help.c +++ b/src/help.c @@ -151,6 +151,7 @@ static void help_draw_global(ToxWindow *self) wprintw(win, " /status : Set status with optional note\n"); wprintw(win, " /note : Set a personal note\n"); wprintw(win, " /nick : Set your nickname\n"); + wprintw(win, " /nospam : Change part of your Tox ID to stop spam\n"); wprintw(win, " /log or : Enable/disable logging\n"); wprintw(win, " /group : Create a group chat where type: text | audio\n"); wprintw(win, " /myid : Print your Tox ID\n"); @@ -292,9 +293,9 @@ void help_onKey(ToxWindow *self, wint_t key) case 'g': #ifdef AUDIO - help_init_window(self, 24, 80); + help_init_window(self, 25, 80); #else - help_init_window(self, 20, 80); + help_init_window(self, 21, 80); #endif self->help->type = HELP_GLOBAL; break; diff --git a/src/prompt.c b/src/prompt.c index 872481b..eb91169 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -51,9 +51,9 @@ extern FriendsList Friends; FriendRequests FrndRequests; #ifdef AUDIO -#define AC_NUM_GLOB_COMMANDS 18 +#define AC_NUM_GLOB_COMMANDS 19 #else -#define AC_NUM_GLOB_COMMANDS 16 +#define AC_NUM_GLOB_COMMANDS 17 #endif /* AUDIO */ /* Array of global command names used for tab completion. */ @@ -71,6 +71,7 @@ static const char glob_cmd_list[AC_NUM_GLOB_COMMANDS][MAX_CMDNAME_SIZE] = { { "/myid" }, { "/nick" }, { "/note" }, + { "/nospam" }, { "/quit" }, { "/requests" }, { "/status" }, From 7af9327b3739d2b05a21b1911f0c6355e915739b Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Thu, 22 Oct 2015 19:55:48 -0400 Subject: [PATCH 03/14] Add note about logs not being encrypted --- src/global_commands.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/global_commands.c b/src/global_commands.c index 8f67b34..134a854 100644 --- a/src/global_commands.c +++ b/src/global_commands.c @@ -370,9 +370,9 @@ void cmd_log(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX if (argc == 0) { if (log->log_on) - msg = "Logging for this window is ON. Type \"/log off\" to disable."; + msg = "Logging for this window is ON; type \"/log off\" to disable. (Logs are not encrypted)"; else - msg = "Logging for this window is OFF. Type \"/log on\" to enable."; + msg = "Logging for this window is OFF; type \"/log on\" to enable."; line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, msg); return; From 941ac1d951209fd77b05014c48a4c6b19d13f7c3 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Fri, 23 Oct 2015 04:40:33 -0400 Subject: [PATCH 04/14] Update DHTnodes --- misc/DHTnodes | 8 -------- 1 file changed, 8 deletions(-) diff --git a/misc/DHTnodes b/misc/DHTnodes index 705f56a..aa6a4ec 100644 --- a/misc/DHTnodes +++ b/misc/DHTnodes @@ -1,25 +1,17 @@ -192.254.75.102 33445 951C88B7E75C867418ACDB5D273821372BB5BD652740BCDF623A4FA293E75D2F 144.76.60.215 33445 04119E835DF3E78BACF0F84235B300546AF8B936F035185E2A8E9E0A67C8924F 23.226.230.47 33445 A09162D68618E742FFBCA1C2C70385E6679604B2D80EA6E84AD0996A1AC8A074 -178.62.125.224 33445 10B20C49ACBD968D7C80F2E8438F92EA51F189F4E70CFBBB2C2C8C799E97F03E 178.21.112.187 33445 4B2C19E924972CB9B57732FB172F8A8604DE13EEDA2A6234E348983344B23057 195.154.119.113 33445 E398A69646B8CEACA9F0B84F553726C1C49270558C57DF5F3C368F05A7D71354 192.210.149.121 33445 F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67 -76.191.23.96 33445 93574A3FAB7D612FEA29FD8D67D3DD10DFD07A075A5D62E8AF3DD9F5D0932E11 46.38.239.179 33445 F5A1A38EFB6BD3C2C8AF8B10D85F0F89E931704D349F1D0720C3C4059AF2440A 178.62.250.138 33445 788236D34978D1D5BD822F0A5BEBD2C53C64CC31CD3149350EE27D4D9A2F9B6B -78.225.128.39 33445 7A2306BFBA665E5480AE59B31E116BE9C04DCEFE04D9FE25082316FA34B4DA0C 130.133.110.14 33445 461FA3776EF0FA655F1A05477DF1B3B614F7D6B124F7DB1DD4FE3C08B03B640F 104.167.101.29 33445 5918AC3C06955962A75AD7DF4F80A5D7C34F7DB9E1498D2E0495DE35B3FE8A57 -195.154.109.148 33445 391C96CB67AE893D4782B8E4495EB9D89CF1031F48460C06075AA8CE76D50A21 -192.3.173.88 33445 3E1FFDEB667BFF549F619EC6737834762124F50A89C8D0DBF1DDF64A2DD6CD1B 205.185.116.116 33445 A179B09749AC826FF01F37A9613F6B57118AE014D4196A0E1105A98F93A54702 198.98.51.198 33445 1D5A5F2F5D6233058BF0259B09622FB40B482E4FA0931EB8FD3AB8E7BF7DAF6F 80.232.246.79 33445 A7A060D553B017D9D8F038E265C7AFB6C70BAAC55070197F9C007432D0038E0F 108.61.165.198 33445 8E7D0B859922EF569298B4D261A8CCB5FEA14FB91ED412A7603A585A25698832 212.71.252.109 33445 C4CEB8C7AC607C6B374E2E782B3C00EA3A63B80D4910B8649CCACDD19F260819 194.249.212.109 33445 3CEE1F054081E7A011234883BC4FC39F661A55B73637A5AC293DDF1251D9432B -194.249.212.109 443 3CEE1F054081E7A011234883BC4FC39F661A55B73637A5AC293DDF1251D9432B -103.38.216.87 33445 601AEE6FC8C17E8CD8F8F1FFC4D4AD84E59A73BE451F037194E7A404E3795320 185.25.116.107 33445 DA4E4ED4B697F2E9B000EEFE3A34B554ACD3F45F5C96EAEA2516DD7FF9AF7B43 192.99.168.140 33445 6A4D0607A296838434A6A7DDF99F50EF9D60A2C510BBF31FE538A25CB6B4652F From 928f25bd89e7dccf577cd9b7659f87ba36fc3729 Mon Sep 17 00:00:00 2001 From: JFreegman Date: Fri, 23 Oct 2015 20:34:08 -0400 Subject: [PATCH 05/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f4bbaee..524e6ca 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Toxic [![Build Status](https://travis-ci.org/Tox/toxic.png?branch=master)](https://travis-ci.org/Tox/toxic) +# Toxic [![Build Status](https://travis-ci.org/Jfreegman/toxic.png?branch=master)](https://travis-ci.org/Jfreegman/toxic) Toxic is a [Tox](https://tox.chat)-based instant messenging client which formerly resided in the [Tox core repository](https://github.com/irungentoo/toxcore), and is now available as a standalone application. [![Toxic Screenshot](https://i.imgur.com/san99Z2.png "Home Screen")](https://i.imgur.com/san99Z2.png) From f7e48d294e32cfc8e3803d31a869abb02a05989a Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Fri, 23 Oct 2015 20:35:15 -0400 Subject: [PATCH 06/14] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 524e6ca..a735f69 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Toxic [![Build Status](https://travis-ci.org/Jfreegman/toxic.png?branch=master)](https://travis-ci.org/Jfreegman/toxic) +# Toxic [![Build Status](https://travis-ci.org/JFreegman/toxic.png?branch=master)](https://travis-ci.org/JFreegman/toxic) Toxic is a [Tox](https://tox.chat)-based instant messenging client which formerly resided in the [Tox core repository](https://github.com/irungentoo/toxcore), and is now available as a standalone application. [![Toxic Screenshot](https://i.imgur.com/san99Z2.png "Home Screen")](https://i.imgur.com/san99Z2.png) From 8584feab80cfef00a51fdffa3e0092c5c6d63c9b Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Wed, 28 Oct 2015 17:14:17 -0400 Subject: [PATCH 07/14] Replace DNS-based username lookups with HTTPS & drop utox.org support --- INSTALL.md | 25 +- Makefile | 4 +- cfg/global_vars.mk | 2 +- cfg/systems/Darwin.mk | 2 +- cfg/systems/Linux.mk | 2 +- doc/toxic.1 | 8 +- doc/toxic.1.asc | 4 +- misc/{DNSservers => nameservers} | 1 - src/dns.c | 391 ------------------------------- src/global_commands.c | 6 +- src/name_lookup.c | 391 +++++++++++++++++++++++++++++++ src/{dns.h => name_lookup.h} | 23 +- src/toxic.c | 28 ++- src/windows.h | 2 +- 14 files changed, 452 insertions(+), 437 deletions(-) rename misc/{DNSservers => nameservers} (50%) delete mode 100644 src/dns.c create mode 100644 src/name_lookup.c rename src/{dns.h => name_lookup.h} (59%) diff --git a/INSTALL.md b/INSTALL.md index 4e96a30..12d9749 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -9,17 +9,18 @@ ## Dependencies -| Name | Needed by | Debian package | -|------------------------------------------------------|----------------------------|------------------| -| [Tox Core](https://github.com/irungentoo/toxcore) | BASE | *None* | -| [NCurses](https://www.gnu.org/software/ncurses) | BASE | libncursesw5-dev | -| [LibConfig](http://www.hyperrealm.com/libconfig) | BASE | libconfig-dev | -| [GNUmake](https://www.gnu.org/software/make) | BASE | make | -| [Tox Core AV](https://github.com/irungentoo/toxcore) | AUDIO | *None* | -| [OpenAL](http://openal.org) | AUDIO, SOUND NOTIFICATIONS | libopenal-dev | -| [OpenALUT](http://openal.org) | SOUND NOTIFICATIONS | libalut-dev | -| [LibNotify](https://developer.gnome.org/libnotify) | DESKTOP NOTIFICATIONS | libnotify-dev | -| [AsciiDoc](http://asciidoc.org/index.html) | DOCUMENTATION1 | asciidoc | +| Name | Needed by | Debian package | +|------------------------------------------------------|----------------------------|---------------------| +| [Tox Core](https://github.com/irungentoo/toxcore) | BASE | *None* | +| [NCurses](https://www.gnu.org/software/ncurses) | BASE | libncursesw5-dev | +| [LibConfig](http://www.hyperrealm.com/libconfig) | BASE | libconfig-dev | +| [GNUmake](https://www.gnu.org/software/make) | BASE | make | +| [libcurl](http://curl.haxx.se/) | BASE | libcurl4-openssl-dev| +| [Tox Core AV](https://github.com/irungentoo/toxcore) | AUDIO | *None* | +| [OpenAL](http://openal.org) | AUDIO, SOUND NOTIFICATIONS | libopenal-dev | +| [OpenALUT](http://openal.org) | SOUND NOTIFICATIONS | libalut-dev | +| [LibNotify](https://developer.gnome.org/libnotify) | DESKTOP NOTIFICATIONS | libnotify-dev | +| [AsciiDoc](http://asciidoc.org/index.html) | DOCUMENTATION1 | asciidoc | 1: see [Documentation](#docs) @@ -31,7 +32,7 @@ brew install https://raw.githubusercontent.com/Tox/homebrew-tox/master/Formula/l brew install https://raw.githubusercontent.com/Homebrew/homebrew-x11/master/libnotify.rb ``` -You can omit `libnotify` if you intend to build without desktop notifications enabled. +You can omit `libnotify` if you intend to build without desktop notifications enabled. ## Compiling diff --git a/Makefile b/Makefile index 392b257..1de0582 100644 --- a/Makefile +++ b/Makefile @@ -11,10 +11,10 @@ CFLAGS += '-DPACKAGE_DATADIR="$(abspath $(DATADIR))"' CFLAGS += $(USER_CFLAGS) LDFLAGS = $(USER_LDFLAGS) -OBJ = chat.o chat_commands.o configdir.o dns.o execute.o file_transfers.o notify.o +OBJ = chat.o chat_commands.o configdir.o execute.o file_transfers.o notify.o OBJ += friendlist.o global_commands.o groupchat.o line_info.o input.o help.o autocomplete.o OBJ += log.o misc_tools.o prompt.o settings.o toxic.o toxic_strings.o windows.o message_queue.o -OBJ += group_commands.o term_mplex.o avatars.o +OBJ += group_commands.o term_mplex.o avatars.o name_lookup.o # Check on wich system we are running UNAME_S = $(shell uname -s) diff --git a/cfg/global_vars.mk b/cfg/global_vars.mk index a62d277..de60c24 100644 --- a/cfg/global_vars.mk +++ b/cfg/global_vars.mk @@ -16,7 +16,7 @@ MISC_DIR = $(BASE_DIR)/misc # Project files MANFILES = toxic.1 toxic.conf.5 -DATAFILES = DHTnodes DNSservers toxic.conf.example +DATAFILES = DHTnodes nameservers toxic.conf.example DESKFILE = toxic.desktop SNDFILES = ToxicContactOnline.wav ToxicContactOffline.wav ToxicError.wav SNDFILES += ToxicRecvMessage.wav ToxicOutgoingCall.wav ToxicIncomingCall.wav diff --git a/cfg/systems/Darwin.mk b/cfg/systems/Darwin.mk index f33a4be..1fc579b 100644 --- a/cfg/systems/Darwin.mk +++ b/cfg/systems/Darwin.mk @@ -6,5 +6,5 @@ PKG_CONFIG_PATH = $(shell export PKG_CONFIG_PATH=/usr/lib/pkgconfig:/usr/local/o LIBS := $(filter-out ncursesw, $(LIBS)) # OS X ships a usable, recent version of ncurses, but calls it ncurses not ncursesw. -LDFLAGS += -lncurses -lalut -ltoxav -ltoxcore -ltoxdns -lresolv -lconfig -ltoxencryptsave -g +LDFLAGS += -lncurses -lalut -ltoxav -ltoxcore -lcurl -lconfig -ltoxencryptsave -g CFLAGS += -I/usr/local/opt/freealut/include/AL -I/usr/local/opt/glib/include/glib-2.0 -g diff --git a/cfg/systems/Linux.mk b/cfg/systems/Linux.mk index 9a67614..6bd4075 100644 --- a/cfg/systems/Linux.mk +++ b/cfg/systems/Linux.mk @@ -1,4 +1,4 @@ # Specials options for linux systems CFLAGS += -LDFLAGS += -ldl -lresolv -lrt +LDFLAGS += -ldl -lrt -lcurl MANDIR = $(PREFIX)/share/man diff --git a/doc/toxic.1 b/doc/toxic.1 index af74931..79d06a5 100644 --- a/doc/toxic.1 +++ b/doc/toxic.1 @@ -2,12 +2,12 @@ .\" Title: toxic .\" Author: [see the "AUTHORS" section] .\" Generator: DocBook XSL Stylesheets v1.78.1 -.\" Date: 2015-03-28 +.\" Date: 2015-07-08 .\" Manual: Toxic Manual .\" Source: toxic __VERSION__ .\" Language: English .\" -.TH "TOXIC" "1" "2015\-03\-28" "toxic __VERSION__" "Toxic Manual" +.TH "TOXIC" "1" "2015\-07\-08" "toxic __VERSION__" "Toxic Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -101,9 +101,9 @@ Use a SOCKS5 proxy: Requires [IP] [port] Use a HTTP proxy: Requires [IP] [port] .RE .PP -\-r, \-\-dnslist +\-r, \-\-namelist .RS 4 -Use specified DNSservers file +Use specified nameservers list .RE .PP \-t, \-\-force\-tcp diff --git a/doc/toxic.1.asc b/doc/toxic.1.asc index 4950c6b..8384091 100644 --- a/doc/toxic.1.asc +++ b/doc/toxic.1.asc @@ -53,8 +53,8 @@ OPTIONS -P, --HTTP-proxy:: Use a HTTP proxy: Requires [IP] [port] --r, --dnslist:: - Use specified DNSservers file +-r, --namelist:: + Use specified nameservers list -t, --force-tcp:: Force TCP connection (use this with proxies) diff --git a/misc/DNSservers b/misc/nameservers similarity index 50% rename from misc/DNSservers rename to misc/nameservers index 379637d..94f6aab 100644 --- a/misc/DNSservers +++ b/misc/nameservers @@ -1,3 +1,2 @@ -utox.org d3154f65d28a5b41a05d4ac7e4b39c6b1c233cc857fb365c56e8392737462a12 toxme.io 1A39E7A5D5FA9CF155C751570A32E625698A60A55F6D88028F949F66144F4F25 diff --git a/src/dns.c b/src/dns.c deleted file mode 100644 index c5457a7..0000000 --- a/src/dns.c +++ /dev/null @@ -1,391 +0,0 @@ -/* dns.c - * - * - * Copyright (C) 2014 Toxic All Rights Reserved. - * - * This file is part of Toxic. - * - * Toxic is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Toxic is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Toxic. If not, see . - * - */ - -#include -#include -#include /* for u_char */ -#include -#include - -#ifdef __APPLE__ - #include -#else - #include -#endif /* ifdef __APPLE__ */ - -#include - -#include "toxic.h" -#include "windows.h" -#include "line_info.h" -#include "dns.h" -#include "global_commands.h" -#include "misc_tools.h" -#include "configdir.h" - -#define DNS3_KEY_SIZE 32 -#define MAX_DNS_REQST_SIZE 255 -#define TOX_DNS3_TXT_PREFIX "v=tox3;id=" - -extern struct Winthread Winthread; -extern struct dns3_servers dns3_servers; -extern struct arg_opts arg_opts; - -static struct thread_data { - ToxWindow *self; - char id_bin[TOX_ADDRESS_SIZE]; - char addr[MAX_STR_SIZE]; - char msg[MAX_STR_SIZE]; - uint8_t busy; - Tox *m; -} t_data; - -static struct dns_thread { - pthread_t tid; - pthread_attr_t attr; -} dns_thread; - - -#define MAX_DNS_SERVERS 50 -#define MAX_DOMAIN_SIZE 32 -#define MAX_DNS_LINE MAX_DOMAIN_SIZE + (DNS3_KEY_SIZE * 2) + 3 - -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(const char *path) -{ - 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) { - int linelen = strlen(line); - - if (linelen < DNS3_KEY_SIZE * 2 + 5) - continue; - - if (line[linelen - 1] == '\n') - line[--linelen] = '\0'; - - const char *name = strtok(line, " "); - const char *keystr = strtok(NULL, " "); - - if (name == NULL || keystr == NULL) - continue; - - if (strlen(keystr) != DNS3_KEY_SIZE * 2) - 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); - - 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); - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "User lookup failed: %s", errmsg); - pthread_mutex_unlock(&Winthread.lock); - - return -1; -} - -static void killdns_thread(void *dns_obj) -{ - if (dns_obj) - tox_dns3_kill(dns_obj); - - memset(&t_data, 0, sizeof(struct thread_data)); - pthread_attr_destroy(&dns_thread.attr); - pthread_exit(NULL); -} - -/* puts TXT from dns response in buf. Returns length of TXT on success, -1 on fail.*/ -static int parse_dns_response(ToxWindow *self, u_char *answer, int ans_len, char *buf) -{ - uint8_t *ans_pt = answer + sizeof(HEADER); - uint8_t *ans_end = answer + ans_len; - char exp_ans[PACKETSZ]; - - int len = dn_expand(answer, ans_end, ans_pt, exp_ans, sizeof(exp_ans)); - - if (len == -1) - return dns_error(self, "dn_expand failed."); - - ans_pt += len; - - if (ans_pt > ans_end - 4) - return dns_error(self, "DNS reply was too short."); - - int type; - GETSHORT(type, ans_pt); - - if (type != T_TXT) - return dns_error(self, "Broken DNS reply."); - - - ans_pt += INT16SZ; /* class */ - uint32_t size = 0; - - /* recurse through CNAME rr's */ - do { - ans_pt += size; - len = dn_expand(answer, ans_end, ans_pt, exp_ans, sizeof(exp_ans)); - - if (len == -1) - return dns_error(self, "Second dn_expand failed."); - - ans_pt += len; - - if (ans_pt > ans_end - 10) - return dns_error(self, "DNS reply was too short."); - - GETSHORT(type, ans_pt); - ans_pt += INT16SZ; - ans_pt += 4; - GETSHORT(size, ans_pt); - - if (ans_pt + size < answer || ans_pt + size > ans_end) - return dns_error(self, "RR overflow."); - - } while (type == T_CNAME); - - if (type != T_TXT) - return dns_error(self, "DNS response failed."); - - uint32_t txt_len = *ans_pt; - - if (!size || txt_len >= size || !txt_len) - return dns_error(self, "No record found."); - - if (txt_len > MAX_DNS_REQST_SIZE) - return dns_error(self, "Invalid DNS response."); - - ans_pt++; - ans_pt[txt_len] = '\0'; - memcpy(buf, ans_pt, txt_len + 1); - - return txt_len; -} - -/* Takes address addr in the form "username@domain", puts the username in namebuf, - and the domain in dombuf. - - return length of username on success, -1 on failure */ -static int parse_addr(const char *addr, char *namebuf, size_t namebuf_sz, char *dombuf, size_t dombuf_sz) -{ - if (strlen(addr) >= MAX_STR_SIZE) - return -1; - - char tmpaddr[MAX_STR_SIZE]; - char *tmpname = NULL; - char *tmpdom = NULL; - - snprintf(tmpaddr, sizeof(tmpaddr), "%s", addr); - tmpname = strtok(tmpaddr, "@"); - tmpdom = strtok(NULL, ""); - - if (tmpname == NULL || tmpdom == NULL) - return -1; - - str_to_lower(tmpdom); - snprintf(namebuf, namebuf_sz, "%s", tmpname); - snprintf(dombuf, dombuf_sz, "%s", tmpdom); - - 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) -{ - int i; - - 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]); - return 0; - } - } - - return -1; -} - -/* 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 inputdomain[MAX_STR_SIZE]; - char name[MAX_STR_SIZE]; - - int namelen = parse_addr(t_data.addr, name, sizeof(name), inputdomain, sizeof(inputdomain)); - - if (namelen == -1) { - dns_error(self, "Must be a Tox ID or an address in the form username@domain"); - killdns_thread(NULL); - } - - char DNS_pubkey[DNS3_KEY_SIZE]; - char domain[MAX_DOMAIN_SIZE]; - - int match = get_domain_match(DNS_pubkey, domain, inputdomain); - - if (match == -1) { - dns_error(self, "Domain not found."); - killdns_thread(NULL); - } - - void *dns_obj = tox_dns3_new((uint8_t *) DNS_pubkey); - - if (dns_obj == NULL) { - dns_error(self, "Core failed to create DNS object."); - killdns_thread(NULL); - } - - char string[MAX_DNS_REQST_SIZE + 1]; - uint32_t request_id; - - int str_len = tox_generate_dns3_string(dns_obj, (uint8_t *) string, sizeof(string), &request_id, - (uint8_t *) name, namelen); - - if (str_len == -1) { - dns_error(self, "Core failed to generate DNS3 string."); - killdns_thread(dns_obj); - } - - string[str_len] = '\0'; - - u_char answer[PACKETSZ]; - char d_string[MAX_DOMAIN_SIZE + MAX_DNS_REQST_SIZE + 10]; - - /* format string and create dns query */ - 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) { - dns_error(self, "DNS query failed."); - killdns_thread(dns_obj); - } - - char ans_id[MAX_DNS_REQST_SIZE + 1]; - - /* extract TXT from DNS response */ - if (parse_dns_response(self, answer, ans_len, ans_id) == -1) - killdns_thread(dns_obj); - - char encrypted_id[MAX_DNS_REQST_SIZE + 1]; - int prfx_len = strlen(TOX_DNS3_TXT_PREFIX); - - /* extract the encrypted ID from TXT response */ - if (strncmp(ans_id, TOX_DNS3_TXT_PREFIX, prfx_len) != 0) { - dns_error(self, "Bad DNS3 TXT response."); - killdns_thread(dns_obj); - } - - memcpy(encrypted_id, ans_id + prfx_len, ans_len - prfx_len); - - if (tox_decrypt_dns3_TXT(dns_obj, (uint8_t *) t_data.id_bin, (uint8_t *) encrypted_id, - strlen(encrypted_id), request_id) == -1) { - dns_error(self, "Core failed to decrypt DNS response."); - killdns_thread(dns_obj); - } - - pthread_mutex_lock(&Winthread.lock); - cmd_add_helper(self, t_data.m, t_data.id_bin, t_data.msg); - pthread_mutex_unlock(&Winthread.lock); - - killdns_thread(dns_obj); - return 0; -} - -/* creates new thread for dns3 lookup. Only allows one lookup at a time. */ -void dns3_lookup(ToxWindow *self, Tox *m, const char *id_bin, const char *addr, const char *msg) -{ - if (arg_opts.proxy_type != TOX_PROXY_TYPE_NONE && arg_opts.force_tcp) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "DNS lookups are disabled."); - return; - } - - if (t_data.busy) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Please wait for previous user lookup to finish."); - return; - } - - if (!dns3_servers.loaded) { - const char *path = arg_opts.dns_path[0] ? arg_opts.dns_path : PACKAGE_DATADIR "/DNSservers"; - dns3_servers.loaded = true; - int ret = load_dns_domainlist(path); - - 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); - t_data.self = self; - t_data.m = m; - t_data.busy = 1; - - if (pthread_attr_init(&dns_thread.attr) != 0) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, "Error: DNS thread attr failed to init"); - memset(&t_data, 0, sizeof(struct thread_data)); - return; - } - - if (pthread_attr_setdetachstate(&dns_thread.attr, PTHREAD_CREATE_DETACHED) != 0) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, "Error: DNS thread attr failed to set"); - pthread_attr_destroy(&dns_thread.attr); - memset(&t_data, 0, sizeof(struct thread_data)); - return; - } - - if (pthread_create(&dns_thread.tid, &dns_thread.attr, dns3_lookup_thread, NULL) != 0) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, "Error: DNS thread failed to init"); - pthread_attr_destroy(&dns_thread.attr); - memset(&t_data, 0, sizeof(struct thread_data)); - return; - } -} diff --git a/src/global_commands.c b/src/global_commands.c index 134a854..a15bc69 100644 --- a/src/global_commands.c +++ b/src/global_commands.c @@ -30,12 +30,12 @@ #include "friendlist.h" #include "log.h" #include "line_info.h" -#include "dns.h" #include "groupchat.h" #include "prompt.h" #include "help.h" #include "term_mplex.h" #include "avatars.h" +#include "name_lookup.h" extern char *DATA_FILE; extern ToxWindow *prompt; @@ -192,8 +192,8 @@ void cmd_add(WINDOW *window, ToxWindow *self, Tox *m, int argc, char (*argv)[MAX } cmd_add_helper(self, m, id_bin, msg); - } else { /* assume id is a username@domain address and do DNS lookup */ - dns3_lookup(self, m, id_bin, id, msg); + } else { /* assume id is a username@domain address and do http name server lookup */ + name_lookup(self, m, id_bin, id, msg); } } diff --git a/src/name_lookup.c b/src/name_lookup.c new file mode 100644 index 0000000..5fdd21a --- /dev/null +++ b/src/name_lookup.c @@ -0,0 +1,391 @@ +/* name_lookup.c + * + * + * Copyright (C) 2015 Toxic All Rights Reserved. + * + * This file is part of Toxic. + * + * Toxic is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Toxic is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Toxic. If not, see . + * + */ + +#include +#include +#include /* for u_char */ +#include + +#include "toxic.h" +#include "windows.h" +#include "line_info.h" +#include "global_commands.h" +#include "misc_tools.h" +#include "configdir.h" + +extern struct arg_opts arg_opts; +extern struct Winthread Winthread;; + +#define NAMESERVER_API_PATH "api" +#define SERVER_KEY_SIZE 32 +#define MAX_SERVERS 50 +#define MAX_DOMAIN_SIZE 32 +#define MAX_SERVER_LINE MAX_DOMAIN_SIZE + (SERVER_KEY_SIZE * 2) + 3 + +struct Nameservers { + int lines; + char names[MAX_SERVERS][MAX_DOMAIN_SIZE]; + char keys[MAX_SERVERS][SERVER_KEY_SIZE]; +} Nameservers; + +static struct thread_data { + Tox *m; + ToxWindow *self; + char id_bin[TOX_ADDRESS_SIZE]; + char addr[MAX_STR_SIZE]; + char msg[MAX_STR_SIZE]; + bool busy; + bool disabled; +} t_data; + +static struct lookup_thread { + pthread_t tid; + pthread_attr_t attr; +} lookup_thread; + +static int lookup_error(ToxWindow *self, const char *errmsg) +{ + pthread_mutex_lock(&Winthread.lock); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "name lookup failed: %s", errmsg); + pthread_mutex_unlock(&Winthread.lock); + + return -1; +} + +static void kill_lookup_thread(void) +{ + memset(&t_data, 0, sizeof(struct thread_data)); + pthread_attr_destroy(&lookup_thread.attr); + pthread_exit(NULL); +} + +/* Attempts to load the nameserver list pointed at by path into the Nameservers structure. + * + * Returns 0 on success. + * -1 is reserved. + * Returns -2 if the supplied path does not exist. + * Returns -3 if the list does not contain any valid entries. + */ +static int load_nameserver_list(const char *path) +{ + FILE *fp = fopen(path, "r"); + + if (fp == NULL) + return -2; + + char line[MAX_SERVER_LINE]; + + while (fgets(line, sizeof(line), fp) && Nameservers.lines < MAX_SERVERS) { + int linelen = strlen(line); + + if (linelen < SERVER_KEY_SIZE * 2 + 5) + continue; + + if (line[linelen - 1] == '\n') + line[--linelen] = '\0'; + + const char *name = strtok(line, " "); + const char *keystr = strtok(NULL, " "); + + if (name == NULL || keystr == NULL) + continue; + + if (strlen(keystr) != SERVER_KEY_SIZE * 2) + continue; + + snprintf(Nameservers.names[Nameservers.lines], sizeof(Nameservers.names[Nameservers.lines]), "%s", name); + int res = hex_string_to_bytes(Nameservers.keys[Nameservers.lines], SERVER_KEY_SIZE, keystr); + + if (res == -1) + continue; + + ++Nameservers.lines; + } + + fclose(fp); + + if (Nameservers.lines < 1) + return -3; + + return 0; +} + +/* Takes address addr in the form "username@domain", puts the username in namebuf, + * and the domain in dombuf. + * + * Returns 0 on success. + * Returns -1 on failure + */ +static int parse_addr(const char *addr, char *namebuf, size_t namebuf_sz, char *dombuf, size_t dombuf_sz) +{ + if (strlen(addr) >= (MAX_STR_SIZE - strlen(NAMESERVER_API_PATH))) + return -1; + + char tmpaddr[MAX_STR_SIZE]; + char *tmpname = NULL; + char *tmpdom = NULL; + + snprintf(tmpaddr, sizeof(tmpaddr), "%s", addr); + tmpname = strtok(tmpaddr, "@"); + tmpdom = strtok(NULL, ""); + + if (tmpname == NULL || tmpdom == NULL) + return -1; + + str_to_lower(tmpdom); + snprintf(namebuf, namebuf_sz, "%s", tmpname); + snprintf(dombuf, dombuf_sz, "%s", tmpdom); + + return 0; +} + +/* matches input domain name with domains in list and obtains key. + * Turns out_domain into the full domain we need to make a POST request. + * + * Return true on match. + * Returns false on no match. + */ +static bool get_domain_match(char *pubkey, char *out_domain, size_t out_domain_size, const char *inputdomain) +{ + int i; + + for (i = 0; i < Nameservers.lines; ++i) { + if (strcmp(Nameservers.names[i], inputdomain) == 0) { + memcpy(pubkey, Nameservers.keys[i], SERVER_KEY_SIZE); + snprintf(out_domain, out_domain_size, "https://%s/%s", Nameservers.names[i], NAMESERVER_API_PATH); + return true; + } + } + + return false; +} + +#define MAX_RECV_LOOKUP_DATA_SIZE 1024 + +/* Holds raw data received from name server */ +struct Recv_Data { + char data[MAX_RECV_LOOKUP_DATA_SIZE]; + size_t size; +}; + +size_t write_lookup_data(void *data, size_t size, size_t nmemb, void *user_pointer) +{ + struct Recv_Data *recv_data = (struct Recv_Data *) user_pointer; + size_t real_size = size * nmemb; + + if (real_size > MAX_RECV_LOOKUP_DATA_SIZE) + return 0; + + memcpy(&recv_data->data, data, real_size); + recv_data->size = real_size; + recv_data->data[real_size] = 0; + + return real_size; +} + +/* Converts Tox ID string contained in recv_data to binary format and puts it in thread's ID buffer. + * + * Returns 0 on success. + * Returns -1 on failure. + */ +#define ID_PREFIX "\"tox_id\": \"" +static int process_response(struct Recv_Data *recv_data) +{ + size_t prefix_size = strlen(ID_PREFIX); + + if (recv_data->size < TOX_ADDRESS_SIZE * 2 + prefix_size) + return -1; + + const char *IDstart = strstr(recv_data->data, ID_PREFIX); + + if (IDstart == NULL) + return -1; + + if (strlen(IDstart) < TOX_ADDRESS_SIZE * 2 + prefix_size) + return -1; + + char ID_string[TOX_ADDRESS_SIZE * 2 + 1]; + memcpy(ID_string, IDstart + prefix_size, TOX_ADDRESS_SIZE * 2); + ID_string[TOX_ADDRESS_SIZE * 2] = 0; + + if (hex_string_to_bin(ID_string, strlen(ID_string), t_data.id_bin, sizeof(t_data.id_bin)) == -1) + return -1; + + return 0; +} + +void *lookup_thread_func(void *data) +{ + ToxWindow *self = t_data.self; + + char input_domain[MAX_STR_SIZE]; + char name[MAX_STR_SIZE]; + + if (parse_addr(t_data.addr, name, sizeof(name), input_domain, sizeof(input_domain)) == -1) { + lookup_error(self, "Input must be a 76 character Tox ID or an address in the form: username@domain"); + kill_lookup_thread(); + } + + char nameserver_key[SERVER_KEY_SIZE]; + char real_domain[MAX_DOMAIN_SIZE]; + + if (!get_domain_match(nameserver_key, real_domain, sizeof(real_domain), input_domain)) { + if (!strcasecmp(input_domain, "utox.org")) + lookup_error(self, "utox.org uses deprecated DNS-based lookups and is no longer supported by Toxic"); + else + lookup_error(self, "Name server domain not found."); + + kill_lookup_thread(); + } + + CURL *c_handle = curl_easy_init(); + + if (!c_handle) { + lookup_error(self, "curl handler error"); + kill_lookup_thread(); + } + + struct Recv_Data recv_data; + memset(&recv_data, 0, sizeof(struct Recv_Data)); + + char post_data[MAX_STR_SIZE]; + snprintf(post_data, sizeof(post_data), "{\"action\": 3, \"name\": \"%s\"}", name); + + struct curl_slist *headers = NULL; + + headers = curl_slist_append(headers, "Content-Type: application/json"); + headers = curl_slist_append(headers, "charsets: utf-8"); + + curl_easy_setopt(c_handle, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(c_handle, CURLOPT_URL, real_domain); + curl_easy_setopt(c_handle, CURLOPT_WRITEFUNCTION, write_lookup_data); + curl_easy_setopt(c_handle, CURLOPT_WRITEDATA, (void *) &recv_data); + curl_easy_setopt(c_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); + curl_easy_setopt(c_handle, CURLOPT_POSTFIELDS, post_data); + + if (curl_easy_setopt(c_handle, CURLOPT_USE_SSL, CURLUSESSL_ALL) != CURLE_OK) { + lookup_error(self, "Failed to enable TLS."); + goto on_exit; + } + + if (curl_easy_setopt(c_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2) != CURLE_OK) { + lookup_error(self, "TLSv1.2 could not be set."); + goto on_exit; + } + + if (curl_easy_perform(c_handle) != CURLE_OK) { + lookup_error(self, "curl lookup error."); + goto on_exit; + } + + if (process_response(&recv_data) == -1) { + lookup_error(self, "parsing error."); + goto on_exit; + } + + pthread_mutex_lock(&Winthread.lock); + cmd_add_helper(self, t_data.m, t_data.id_bin, t_data.msg); + pthread_mutex_unlock(&Winthread.lock); + +on_exit: + curl_slist_free_all(headers); + curl_easy_cleanup(c_handle); + kill_lookup_thread(); + + return 0; +} + +void name_lookup(ToxWindow *self, Tox *m, const char *id_bin, const char *addr, const char *message) +{ + if (t_data.disabled) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "name lookups are disabled."); + return; + } + + if (arg_opts.proxy_type != TOX_PROXY_TYPE_NONE && arg_opts.force_tcp) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "name lookups are disabled."); + return; + } + + if (t_data.busy) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Please wait for previous name lookup to finish."); + return; + } + + 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", message); + t_data.self = self; + t_data.m = m; + t_data.busy = true; + + if (pthread_attr_init(&lookup_thread.attr) != 0) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, "Error: lookup thread attr failed to init"); + memset(&t_data, 0, sizeof(struct thread_data)); + return; + } + + if (pthread_attr_setdetachstate(&lookup_thread.attr, PTHREAD_CREATE_DETACHED) != 0) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, "Error: lookup thread attr failed to set"); + pthread_attr_destroy(&lookup_thread.attr); + memset(&t_data, 0, sizeof(struct thread_data)); + return; + } + + if (pthread_create(&lookup_thread.tid, &lookup_thread.attr, lookup_thread_func, NULL) != 0) { + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, RED, "Error: lookup thread failed to init"); + pthread_attr_destroy(&lookup_thread.attr); + memset(&t_data, 0, sizeof(struct thread_data)); + return; + } +} + +/* Initializes http based name lookups. Note: This function must be called only once before additional + * threads are spawned. + * + * Returns 0 on success. + * Returns -1 if curl failed to init. + * Returns -2 if the nameserver list cannot be found. + * Returns -3 if the nameserver list does not contain any valid entries. + */ +int name_lookup_init(void) +{ + if (curl_global_init(CURL_GLOBAL_ALL) != 0) { + t_data.disabled = true; + return -1; + } + + const char *path = arg_opts.nameserver_path[0] ? arg_opts.nameserver_path : PACKAGE_DATADIR "/nameservers"; + int ret = load_nameserver_list(path); + + if (ret != 0) { + t_data.disabled = true; + return ret; + } + + return 0; +} + +void name_lookup_cleanup(void) +{ + curl_global_cleanup(); +} diff --git a/src/dns.h b/src/name_lookup.h similarity index 59% rename from src/dns.h rename to src/name_lookup.h index 9e6852e..c1419d8 100644 --- a/src/dns.h +++ b/src/name_lookup.h @@ -1,7 +1,7 @@ -/* dns.c +/* name_lookup.h * * - * Copyright (C) 2014 Toxic All Rights Reserved. + * Copyright (C) 2015 Toxic All Rights Reserved. * * This file is part of Toxic. * @@ -20,13 +20,18 @@ * */ -/* Does DNS lookup for addr and puts resulting tox id in id_bin. - Return 0 on success, -1 on failure. */ +#ifndef NAME_LOOKUP +#define NAME_LOOKUP -#ifndef DNS_H -#define DNS_H +/* Initializes http based name lookups. Note: This function must be called only once before additional + * threads are spawned. + * + * Returns 0 on success. + * Returns -1 on failure. + */ +int name_lookup_init(void); +void name_lookup_cleanup(void); -/* creates new thread for dns3 lookup. Only allows one lookup at a time. */ -void dns3_lookup(ToxWindow *self, Tox *m, const char *id_bin, const char *addr, const char *msg); +int name_lookup(ToxWindow *self, Tox *m, const char *id_bin, const char *addr, const char *message); -#endif /* #define DNS_H */ +#endif /* NAME_LOOKUP */ diff --git a/src/toxic.c b/src/toxic.c index 6dcf558..4bfc647 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -58,6 +58,7 @@ #include "message_queue.h" #include "execute.h" #include "term_mplex.h" +#include "name_lookup.h" #ifdef X11 #include "xtra.h" @@ -155,6 +156,7 @@ void exit_toxic_success(Tox *m) free_global_data(); tox_kill(m); endwin(); + name_lookup_cleanup(); #ifdef X11 /* We have to terminate xtra last coz reasons @@ -904,7 +906,7 @@ static void print_usage(void) fprintf(stderr, " -o, --noconnect Do not connect to the DHT network\n"); fprintf(stderr, " -p, --SOCKS5-proxy Use SOCKS5 proxy: Requires [IP] [port]\n"); fprintf(stderr, " -P, --HTTP-proxy Use HTTP proxy: Requires [IP] [port]\n"); - fprintf(stderr, " -r, --dnslist Use specified DNSservers file\n"); + fprintf(stderr, " -r, --namelist Use specified name lookup server list\n"); fprintf(stderr, " -t, --force-tcp Force toxic to use a TCP connection (use with proxies)\n"); fprintf(stderr, " -T, --tcp-server Act as a TCP relay server: Requires [port]\n"); fprintf(stderr, " -u, --unencrypt-data Unencrypt an encrypted data file\n"); @@ -932,7 +934,7 @@ static void parse_args(int argc, char *argv[]) {"nodes", required_argument, 0, 'n'}, {"help", no_argument, 0, 'h'}, {"noconnect", no_argument, 0, 'o'}, - {"dnslist", required_argument, 0, 'r'}, + {"namelist", required_argument, 0, 'r'}, {"force-tcp", no_argument, 0, 't'}, {"tcp-server", required_argument, 0, 'T'}, {"SOCKS5-proxy", required_argument, 0, 'p'}, @@ -1044,10 +1046,10 @@ static void parse_args(int argc, char *argv[]) break; case 'r': - snprintf(arg_opts.dns_path, sizeof(arg_opts.dns_path), "%s", optarg); + snprintf(arg_opts.nameserver_path, sizeof(arg_opts.nameserver_path), "%s", optarg); - if (!file_exists(arg_opts.dns_path)) - queue_init_message("DNSservers file not found"); + if (!file_exists(arg_opts.nameserver_path)) + queue_init_message("nameserver list not found"); break; @@ -1222,7 +1224,18 @@ int main(int argc, char **argv) exit_toxic_err("failed in main", FATALERR_MEMORY); const char *p = arg_opts.config_path[0] ? arg_opts.config_path : NULL; - int settings_err = settings_load(user_settings, p); + + if (settings_load(user_settings, p) == -1) + queue_init_message("Failed to load user settings"); + + int nameserver_ret = name_lookup_init(); + + if (nameserver_ret == -1) + queue_init_message("curl failed to initialize; name lookup service is disabled."); + else if (nameserver_ret == -2) + queue_init_message("Name lookup server list could not be found."); + else if (nameserver_ret == -3) + queue_init_message("Name lookup server list does not contain any valid entries."); #ifdef X11 if (init_xtra(DnD_callback) == -1) @@ -1271,9 +1284,6 @@ int main(int argc, char **argv) init_notify(60, 3000); - if (settings_err == -1) - queue_init_message("Failed to load user settings"); - /* screen/tmux auto-away timer */ if (init_mplex_away_timer(m) == -1) queue_init_message("Failed to init mplex auto-away."); diff --git a/src/windows.h b/src/windows.h index 21e90bf..fded1e8 100644 --- a/src/windows.h +++ b/src/windows.h @@ -90,7 +90,7 @@ struct arg_opts { bool encrypt_data; bool unencrypt_data; - char dns_path[MAX_STR_SIZE]; + char nameserver_path[MAX_STR_SIZE]; char config_path[MAX_STR_SIZE]; char nodes_path[MAX_STR_SIZE]; From fea317ee24e2b8612945525407f6f30451224d13 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Wed, 28 Oct 2015 21:46:21 -0400 Subject: [PATCH 08/14] Remove travis script. Goodbye old friend --- .travis.yml | 52 ---------------------------------------------------- 1 file changed, 52 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index fb0f5e9..0000000 --- a/.travis.yml +++ /dev/null @@ -1,52 +0,0 @@ -language: c -compiler: - - gcc - - clang - -before_script: - # Installing yasm (needed for compiling vpx) and openal - - sudo apt-get -yq install yasm libopenal-dev libconfig-dev libalut-dev libnotify-dev clang llvm-dev - # Installing libsodium, needed for toxcore - - git clone https://github.com/jedisct1/libsodium.git libsodium - - cd libsodium - - git checkout tags/1.0.3 > /dev/null - - ./autogen.sh > /dev/null - - ./configure > /dev/null - - make check -j2 || make check || exit 1 > /dev/null - - sudo make install > /dev/null - - cd .. - # Installing libopus, needed for audio encoding/decoding - - wget http://downloads.xiph.org/releases/opus/opus-1.1.tar.gz - - tar xzf opus-1.1.tar.gz > /dev/null - - cd opus-1.1 - - ./configure > /dev/null - - make -j2 || make || exit 1 > /dev/null - - sudo make install > /dev/null - - cd .. - # Installing vpx - - git clone https://chromium.googlesource.com/webm/libvpx libvpx - - cd libvpx - - ./configure --enable-shared > /dev/null - - make -j2 || make || exit 1 > /dev/null - - sudo make install > /dev/null - - cd .. - # Creating libraries links and updating cache - - sudo ldconfig > /dev/null - # Installing toxcore - - git clone https://github.com/irungentoo/toxcore.git toxcore - - cd toxcore - - autoreconf -i - - ./configure --disable-tests --disable-ntox --disable-daemon --enable-av - - make -j2 || make || exit 1 - - sudo make install - - cd .. -script: - - make -j2 || make || exit 1 -notifications: - email: false - - irc: - channels: - - "chat.freenode.net#tox-dev" - on_success: always - on_failure: always From 368a1465ec3345c71d6d4edca03f4f9b038f571c Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Thu, 29 Oct 2015 15:13:42 -0400 Subject: [PATCH 09/14] Use a specified TLS cipher list for https name lookups --- README.md | 1 - src/name_lookup.c | 15 ++++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a735f69..da5d8b5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ -# Toxic [![Build Status](https://travis-ci.org/JFreegman/toxic.png?branch=master)](https://travis-ci.org/JFreegman/toxic) Toxic is a [Tox](https://tox.chat)-based instant messenging client which formerly resided in the [Tox core repository](https://github.com/irungentoo/toxcore), and is now available as a standalone application. [![Toxic Screenshot](https://i.imgur.com/san99Z2.png "Home Screen")](https://i.imgur.com/san99Z2.png) diff --git a/src/name_lookup.c b/src/name_lookup.c index 5fdd21a..9de8ac2 100644 --- a/src/name_lookup.c +++ b/src/name_lookup.c @@ -41,6 +41,9 @@ extern struct Winthread Winthread;; #define MAX_DOMAIN_SIZE 32 #define MAX_SERVER_LINE MAX_DOMAIN_SIZE + (SERVER_KEY_SIZE * 2) + 3 +/* List based on Mozilla's recommended configurations for modern browsers */ +#define TLS_CIPHER_SUITE_LIST "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK" + struct Nameservers { int lines; char names[MAX_SERVERS][MAX_DOMAIN_SIZE]; @@ -282,8 +285,9 @@ void *lookup_thread_func(void *data) curl_easy_setopt(c_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); curl_easy_setopt(c_handle, CURLOPT_POSTFIELDS, post_data); + if (curl_easy_setopt(c_handle, CURLOPT_USE_SSL, CURLUSESSL_ALL) != CURLE_OK) { - lookup_error(self, "Failed to enable TLS."); + lookup_error(self, "TLS could not be enabled."); goto on_exit; } @@ -292,13 +296,18 @@ void *lookup_thread_func(void *data) goto on_exit; } + if (curl_easy_setopt(c_handle, CURLOPT_SSL_CIPHER_LIST, TLS_CIPHER_SUITE_LIST) != CURLE_OK) { + lookup_error(self, "Failed to set TLS cipher list."); + goto on_exit; + } + if (curl_easy_perform(c_handle) != CURLE_OK) { - lookup_error(self, "curl lookup error."); + lookup_error(self, "https lookup error."); goto on_exit; } if (process_response(&recv_data) == -1) { - lookup_error(self, "parsing error."); + lookup_error(self, "Name lookup failed."); goto on_exit; } From 2b4b8c02890adf0f23396772c18ab2174dec455c Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Thu, 29 Oct 2015 20:16:35 -0400 Subject: [PATCH 10/14] Add more descriptive curl errors --- src/name_lookup.c | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/src/name_lookup.c b/src/name_lookup.c index 9de8ac2..781571f 100644 --- a/src/name_lookup.c +++ b/src/name_lookup.c @@ -65,10 +65,17 @@ static struct lookup_thread { pthread_attr_t attr; } lookup_thread; -static int lookup_error(ToxWindow *self, const char *errmsg) +static int lookup_error(ToxWindow *self, const char *errmsg, ...) { + char frmt_msg[MAX_STR_SIZE]; + + va_list args; + va_start(args, errmsg); + vsnprintf(frmt_msg, sizeof(frmt_msg), errmsg, args); + va_end(args); + pthread_mutex_lock(&Winthread.lock); - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "name lookup failed: %s", errmsg); + line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "name lookup failed: %s", frmt_msg); pthread_mutex_unlock(&Winthread.lock); return -1; @@ -285,24 +292,31 @@ void *lookup_thread_func(void *data) curl_easy_setopt(c_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); curl_easy_setopt(c_handle, CURLOPT_POSTFIELDS, post_data); + int ret = curl_easy_setopt(c_handle, CURLOPT_USE_SSL, CURLUSESSL_ALL); - if (curl_easy_setopt(c_handle, CURLOPT_USE_SSL, CURLUSESSL_ALL) != CURLE_OK) { - lookup_error(self, "TLS could not be enabled."); + if (ret != CURLE_OK) { + lookup_error(self, "TLS could not be enabled (libcurl error %d)", ret); goto on_exit; } - if (curl_easy_setopt(c_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2) != CURLE_OK) { - lookup_error(self, "TLSv1.2 could not be set."); + ret = curl_easy_setopt(c_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); + + if (ret != CURLE_OK) { + lookup_error(self, "TLSv1.2 could not be set (libcurl error %d)", ret); goto on_exit; } - if (curl_easy_setopt(c_handle, CURLOPT_SSL_CIPHER_LIST, TLS_CIPHER_SUITE_LIST) != CURLE_OK) { - lookup_error(self, "Failed to set TLS cipher list."); + ret = curl_easy_setopt(c_handle, CURLOPT_SSL_CIPHER_LIST, TLS_CIPHER_SUITE_LIST); + + if (ret != CURLE_OK) { + lookup_error(self, "Failed to set TLS cipher list (libcurl error %d)", ret); goto on_exit; } - if (curl_easy_perform(c_handle) != CURLE_OK) { - lookup_error(self, "https lookup error."); + ret = curl_easy_perform(c_handle); + + if (ret != CURLE_OK) { + lookup_error(self, "https lookup error (libcurl error %d)", ret); goto on_exit; } From 7cf9c37aeff2c9f5a263f17da045854a41655a0c Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Thu, 29 Oct 2015 20:35:31 -0400 Subject: [PATCH 11/14] Handle case where system doesn't support any of the specified TLS cipher suites --- src/name_lookup.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/name_lookup.c b/src/name_lookup.c index 781571f..198e531 100644 --- a/src/name_lookup.c +++ b/src/name_lookup.c @@ -316,8 +316,16 @@ void *lookup_thread_func(void *data) ret = curl_easy_perform(c_handle); if (ret != CURLE_OK) { - lookup_error(self, "https lookup error (libcurl error %d)", ret); - goto on_exit; + /* If system doesn't support any of the specified ciphers suites, fall back to default */ + if (ret == CURLE_SSL_CIPHER) { + curl_easy_setopt(c_handle, CURLOPT_SSL_CIPHER_LIST, NULL); + ret = curl_easy_perform(c_handle); + } + + if (ret != CURLE_OK) { + lookup_error(self, "https lookup error (libcurl error %d)", ret); + goto on_exit; + } } if (process_response(&recv_data) == -1) { From 36963a5b385a6e1c5f8cddc12bbb981c980bac51 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Fri, 30 Oct 2015 00:10:38 -0400 Subject: [PATCH 12/14] rm redundant error message --- src/name_lookup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/name_lookup.c b/src/name_lookup.c index 198e531..4f259e2 100644 --- a/src/name_lookup.c +++ b/src/name_lookup.c @@ -329,7 +329,7 @@ void *lookup_thread_func(void *data) } if (process_response(&recv_data) == -1) { - lookup_error(self, "Name lookup failed."); + lookup_error(self, ""); goto on_exit; } From 9751cfc407660d8efc0caa255f6d446b7b2b67ef Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Sun, 1 Nov 2015 21:34:42 -0500 Subject: [PATCH 13/14] Force name lookups through proxy set by client --- src/name_lookup.c | 53 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/src/name_lookup.c b/src/name_lookup.c index 4f259e2..f982946 100644 --- a/src/name_lookup.c +++ b/src/name_lookup.c @@ -243,6 +243,47 @@ static int process_response(struct Recv_Data *recv_data) return 0; } +/* Sets proxy info for given CURL handler. + * + * Returns 0 on success or if no proxy is set by the client. + * Returns -1 on failure. + */ +static int set_lookup_proxy(ToxWindow *self, CURL *c_handle, const char *proxy_address, uint16_t port, uint8_t proxy_type) +{ + if (proxy_type == TOX_PROXY_TYPE_NONE) + return 0; + + if (proxy_address == NULL || port == 0) { + lookup_error(self, "Unknkown proxy error"); + return -1; + } + + int ret = curl_easy_setopt(c_handle, CURLOPT_PROXYPORT, (long) port); + + if (ret != CURLE_OK) { + lookup_error(self, "Failed to set proxy port (libcurl error %d)", ret); + return -1; + } + + long int type = proxy_type == TOX_PROXY_TYPE_SOCKS5 ? CURLPROXY_SOCKS5 : CURLPROXY_HTTP; + + ret = curl_easy_setopt(c_handle, CURLOPT_PROXYTYPE, type); + + if (ret != CURLE_OK) { + lookup_error(self, "Failed to set proxy type (libcurl error %d)", ret); + return -1; + } + + ret = curl_easy_setopt(c_handle, CURLOPT_PROXY, proxy_address); + + if (ret != CURLE_OK) { + lookup_error(self, "Failed to set proxy (libcurl error %d)", ret); + return -1; + } + + return 0; +} + void *lookup_thread_func(void *data) { ToxWindow *self = t_data.self; @@ -292,6 +333,9 @@ void *lookup_thread_func(void *data) curl_easy_setopt(c_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); curl_easy_setopt(c_handle, CURLOPT_POSTFIELDS, post_data); + if (set_lookup_proxy(self, c_handle, arg_opts.proxy_address, arg_opts.proxy_port, arg_opts.proxy_type) == -1) + goto on_exit; + int ret = curl_easy_setopt(c_handle, CURLOPT_USE_SSL, CURLUSESSL_ALL); if (ret != CURLE_OK) { @@ -323,13 +367,13 @@ void *lookup_thread_func(void *data) } if (ret != CURLE_OK) { - lookup_error(self, "https lookup error (libcurl error %d)", ret); + lookup_error(self, "HTTPS lookup error (libcurl error %d)", ret); goto on_exit; } } if (process_response(&recv_data) == -1) { - lookup_error(self, ""); + lookup_error(self, "Bad response."); goto on_exit; } @@ -352,11 +396,6 @@ void name_lookup(ToxWindow *self, Tox *m, const char *id_bin, const char *addr, return; } - if (arg_opts.proxy_type != TOX_PROXY_TYPE_NONE && arg_opts.force_tcp) { - line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "name lookups are disabled."); - return; - } - if (t_data.busy) { line_info_add(self, NULL, NULL, NULL, SYS_MSG, 0, 0, "Please wait for previous name lookup to finish."); return; From e02cf1bb7dde04853d9668d99cf9c8ad6f62af9a Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Mon, 2 Nov 2015 02:01:17 -0500 Subject: [PATCH 14/14] Use proxy for DNS requests when type is SOCKS5 --- src/name_lookup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/name_lookup.c b/src/name_lookup.c index f982946..464e206 100644 --- a/src/name_lookup.c +++ b/src/name_lookup.c @@ -254,7 +254,7 @@ static int set_lookup_proxy(ToxWindow *self, CURL *c_handle, const char *proxy_a return 0; if (proxy_address == NULL || port == 0) { - lookup_error(self, "Unknkown proxy error"); + lookup_error(self, "Unknown proxy error"); return -1; } @@ -265,7 +265,7 @@ static int set_lookup_proxy(ToxWindow *self, CURL *c_handle, const char *proxy_a return -1; } - long int type = proxy_type == TOX_PROXY_TYPE_SOCKS5 ? CURLPROXY_SOCKS5 : CURLPROXY_HTTP; + long int type = proxy_type == TOX_PROXY_TYPE_SOCKS5 ? CURLPROXY_SOCKS5_HOSTNAME : CURLPROXY_HTTP; ret = curl_easy_setopt(c_handle, CURLOPT_PROXYTYPE, type);