From a009f11c0c628ddf279819dedef2e75f0f0d0359 Mon Sep 17 00:00:00 2001 From: Jfreegman Date: Tue, 20 Sep 2016 00:00:09 -0400 Subject: [PATCH] Automatically update DHT nodeslist List is now automatically fetched from nodes.tox.chat and placed in the user config directory. The list is updated once every 30 days, and will attempt to detect problems and re-fetch the list if necessary. Also fixed a couple file descriptor leaks and cleaned some things up. --- Makefile | 8 +- cfg/global_vars.mk | 2 +- doc/toxic.1 | 12 +-- doc/toxic.1.asc | 8 +- misc/DHTnodes | 1 - src/bootstrap.c | 249 ++++++++++++++++++++++++++++++++++++++++----- src/bootstrap.h | 11 +- src/configdir.c | 8 +- src/configdir.h | 15 +++ src/curl_util.c | 93 +++++++++++++++++ src/curl_util.h | 50 +++++++++ src/name_lookup.c | 86 ++-------------- src/name_lookup.h | 3 +- src/toxic.c | 36 +++---- src/windows.h | 2 +- 15 files changed, 440 insertions(+), 144 deletions(-) delete mode 100644 misc/DHTnodes create mode 100644 src/curl_util.c create mode 100644 src/curl_util.h diff --git a/Makefile b/Makefile index abb09ff..9c55ae6 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 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 name_lookup.o qr_code.o bootstrap.o +OBJ = autocomplete.o avatars.o bootstrap.o chat.o chat_commands.o configdir.o curl_util.o execute.o +OBJ += file_transfers.o friendlist.o global_commands.o group_commands.o groupchat.o help.o input.o +OBJ += line_info.o log.o message_queue.o misc_tools.o name_lookup.o notify.o prompt.o qr_code.o settings.o +OBJ += term_mplex.o toxic.o toxic_strings.o windows.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 2fa9723..0503b90 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 nameservers toxic.conf.example +DATAFILES = nameservers toxic.conf.example DESKFILE = toxic.desktop SNDFILES = ToxicContactOnline.wav ToxicContactOffline.wav ToxicError.wav SNDFILES += ToxicRecvMessage.wav ToxicOutgoingCall.wav ToxicIncomingCall.wav diff --git a/doc/toxic.1 b/doc/toxic.1 index 9878cb1..a5c72eb 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-12-07 +.\" Date: 2016-04-25 .\" Manual: Toxic Manual .\" Source: toxic __VERSION__ .\" Language: English .\" -.TH "TOXIC" "1" "2015\-12\-07" "toxic __VERSION__" "Toxic Manual" +.TH "TOXIC" "1" "2016\-04\-25" "toxic __VERSION__" "Toxic Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -82,8 +82,7 @@ Show help message .RS 4 Use specified \fInodes\-file\fR -for DHT bootstrap nodes, instead of -\fI__DATADIR__/DHTnodes\fR +for DHT bootstrap nodes, instead of the default .RE .PP \-o, \-\-noconnect @@ -122,9 +121,10 @@ Unencrypt a data file\&. A warning will appear if this option is used with a dat .RE .SH "FILES" .PP -__DATADIR__/DHTnodes +~/\&.config/tox/DHTnodes .RS 4 -Default list of DHT bootstrap nodes\&. +Default location for list of DHT bootstrap nodes (list obtained at +https://nodes\&.tox\&.chat)\&. This list is automatically updated every 30 days\&. .RE .PP ~/\&.config/tox/toxic_profile\&.tox diff --git a/doc/toxic.1.asc b/doc/toxic.1.asc index 20d3c00..b97af86 100644 --- a/doc/toxic.1.asc +++ b/doc/toxic.1.asc @@ -41,8 +41,7 @@ OPTIONS Show help message -n, --nodes nodes-file:: - Use specified 'nodes-file' for DHT bootstrap nodes, instead of - '{datadir}/DHTnodes' + Use specified 'nodes-file' for DHT bootstrap nodes, instead of the default -o, --noconnect:: Do not connect to the DHT network @@ -68,8 +67,9 @@ OPTIONS FILES ----- -{datadir}/DHTnodes:: - Default list of DHT bootstrap nodes. +~/.config/tox/DHTnodes:: + Default location for list of DHT bootstrap nodes (list obtained at https://nodes.tox.chat). + This list is automatically updated every 30 days. ~/.config/tox/toxic_profile.tox:: Savestate which contains your personal info (nickname, Tox ID, contacts, diff --git a/misc/DHTnodes b/misc/DHTnodes deleted file mode 100644 index bdaefc6..0000000 --- a/misc/DHTnodes +++ /dev/null @@ -1 +0,0 @@ -{"last_scan":1474137109,"nodes":[{"ipv4":"tox.zodiaclabs.org","ipv6":"v6.tox.zodiaclabs.org","port":33445,"tcp_ports":[33445,3389],"public_key":"A09162D68618E742FFBCA1C2C70385E6679604B2D80EA6E84AD0996A1AC8A074","maintainer":"stal","location":"US","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"I am the bone of my code;\nNIH is my body and str8c is my blood.\nI have overflowed a thousand buffers.\nUnknown to SIGSEGV, nor to abort();\nHave withstood pain to create fast programs;\nYet my code will always be unsafe.\nSo as I pray, rock solid straight C.","last_ping":1474137098},{"ipv4":"biribiri.org","ipv6":"-","port":33445,"tcp_ports":[33445,3389],"public_key":"F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67","maintainer":"nurupo","location":"US","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Welcome, stranger #3783. I'm up for 1d 14h 23m 12s, running since Sep 16 04:08:25 UTC. If I get outdated, please ping my maintainer at nurupo.contributions@gmail.com","last_ping":1474137098},{"ipv4":"178.62.250.138","ipv6":"2a03:b0c0:2:d0::16:1","port":33445,"tcp_ports":[3389,33445],"public_key":"788236D34978D1D5BD822F0A5BEBD2C53C64CC31CD3149350EE27D4D9A2F9B6B","maintainer":"Impyy","location":"NL","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Impy's kickin' bootstrap node","last_ping":1474137097},{"ipv4":"130.133.110.14","ipv6":"2001:6f8:1c3c:babe::14:1","port":33445,"tcp_ports":[33445],"public_key":"461FA3776EF0FA655F1A05477DF1B3B614F7D6B124F7DB1DD4FE3C08B03B640F","maintainer":"Manolis","location":"DE","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Spline tox bootstrap node","last_ping":1474137101},{"ipv4":"205.185.116.116","ipv6":"-","port":33445,"tcp_ports":[3389,33445],"public_key":"A179B09749AC826FF01F37A9613F6B57118AE014D4196A0E1105A98F93A54702","maintainer":"Busindre","location":"US","status_udp":true,"status_tcp":true,"version":"2014101200","motd":"tox-bootstrapd","last_ping":1474137098},{"ipv4":"198.98.51.198","ipv6":"2605:6400:1:fed5:22:45af:ec10:f329","port":33445,"tcp_ports":[33445,3389,443],"public_key":"1D5A5F2F5D6233058BF0259B09622FB40B482E4FA0931EB8FD3AB8E7BF7DAF6F","maintainer":"Busindre","location":"US","status_udp":true,"status_tcp":true,"version":"2014101200","motd":"tox-bootstrapd","last_ping":1474137098},{"ipv4":"139.162.217.110","ipv6":"-","port":33445,"tcp_ports":[33445,3389],"public_key":"0EEBE6304F4B3F6549F39A87FBB45751929F4833BA6AC5F35B6DFA79D01B4523","maintainer":"Kr9r0x","location":"GB","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"tox-bootstrapd","last_ping":1474137097},{"ipv4":"194.249.212.109","ipv6":"2001:1470:fbfe::109","port":33445,"tcp_ports":[3389,443,33445],"public_key":"3CEE1F054081E7A011234883BC4FC39F661A55B73637A5AC293DDF1251D9432B","maintainer":"fluke571","location":"SI","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"tox-bootstrapd","last_ping":1474137098},{"ipv4":"185.25.116.107","ipv6":"2a00:7a60:0:746b::3","port":33445,"tcp_ports":[33445,3389],"public_key":"DA4E4ED4B697F2E9B000EEFE3A34B554ACD3F45F5C96EAEA2516DD7FF9AF7B43","maintainer":"MAH69K","location":"UA","status_udp":true,"status_tcp":true,"version":"","motd":"","last_ping":1474137102},{"ipv4":"192.99.168.140","ipv6":"-","port":33445,"tcp_ports":[33445,3389],"public_key":"6A4D0607A296838434A6A7DDF99F50EF9D60A2C510BBF31FE538A25CB6B4652F","maintainer":"WIeschie","location":"CA","status_udp":true,"status_tcp":true,"version":"2014101200","motd":"tox-bootstrapd","last_ping":1474137098},{"ipv4":"95.215.46.114","ipv6":"2a02:7aa0:1619::bdbd:17b8","port":33445,"tcp_ports":[33445,3389],"public_key":"5823FB947FF24CF83DDFAC3F3BAA18F96EA2018B16CC08429CB97FA502F40C23","maintainer":"Rotkaermota","location":"SE","status_udp":true,"status_tcp":true,"version":"","motd":"","last_ping":1474137102},{"ipv4":"5.189.176.217","ipv6":"2a02:c200:1:10:3:1:605:1337","port":5190,"tcp_ports":[33445,5190,3389],"public_key":"2B2137E094F743AC8BD44652C55F41DFACC502F125E99E4FE24D40537489E32F","maintainer":"tastytea","location":"DE","status_udp":true,"status_tcp":true,"version":"","motd":"","last_ping":1474137101},{"ipv4":"148.251.23.146","ipv6":"2a01:4f8:201:8493::2","port":2306,"tcp_ports":[33445,2306],"public_key":"7AED21F94D82B05774F697B209628CD5A9AD17E0C073D9329076A4C28ED28147","maintainer":"pucetox","location":"DE","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"by pucetox,\n sync your nodes here tox.0x10k.com/bootstrapd-conf , \n for communication: 1D1C0B992DEB6D7F18561176F7F5E572BCC7F2BA5CFA7E9E437B9134122CE96D906A6119F9D2","last_ping":1474137097},{"ipv4":"104.223.122.15","ipv6":"2607:ff48:aa81:800::35eb:1","port":33445,"tcp_ports":[3389,33445],"public_key":"0FB96EEBFB1650DDB52E70CF773DDFCABE25A95CC3BB50FC251082E4B63EF82A","maintainer":"ru_maniac","location":"US","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"tox id for queries and general info: EBD2A7B649ABB10ED9F47E5113F04000F39D46F087CEB62FCCE1069471FD6915256D197F2A97","last_ping":1474137098},{"ipv4":"tox.verdict.gg","ipv6":"-","port":33445,"tcp_ports":[33445,3389],"public_key":"1C5293AEF2114717547B39DA8EA6F1E331E5E358B35F9B6B5F19317911C5F976","maintainer":"Deliran","location":"DE","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Since 2015","last_ping":1474137098},{"ipv4":"d4rk4.ru","ipv6":"-","port":1813,"tcp_ports":[1813],"public_key":"53737F6D47FA6BD2808F378E339AF45BF86F39B64E79D6D491C53A1D522E7039","maintainer":"D4rk4","location":"RU","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"TOX ID: 35EDC07AEB18B163E07EE33F6CDDA63969F394FF6A617CEAB22A7EBBEAAAF854C0EDFBD46898","last_ping":1474137102},{"ipv4":"81.4.110.149","ipv6":"2a00:d880:3:2::8bdc:f19","port":33445,"tcp_ports":[33445,3389],"public_key":"9E7BD4793FFECA7F32238FA2361040C09025ED3333744483CA6F3039BFF0211E","maintainer":"tibietigni","location":"NL","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Tibietigni.com node. Tox_id for communication: D36CC0B702621F48FDBC540A57124A744E5133C932E65ACCEBCABF2586A02455171717175989","last_ping":1474137097},{"ipv4":"95.31.20.151","ipv6":"-","port":33445,"tcp_ports":[3389],"public_key":"9CA69BB74DE7C056D1CC6B16AB8A0A38725C0349D187D8996766958584D39340","maintainer":"IgorNovgorodov","location":"RU","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"happy-new-year","last_ping":1474137101},{"ipv4":"51.254.84.212","ipv6":"2001:41d0:a:1a3b::18","port":33445,"tcp_ports":[3389,33445],"public_key":"AEC204B9A4501412D5F0BB67D9C81B5DB3EE6ADA64122D32A3E9B093D544327D","maintainer":"a68366","location":"FR","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Since 26.12.2015","last_ping":1474137097},{"ipv4":"5.135.59.163","ipv6":"-","port":33445,"tcp_ports":[3389,33445],"public_key":"2D320F971EF2CA18004416C2AAE7BA52BF7949DB34EA8E2E21AF67BD367BE211","maintainer":"Skey","location":"FR","status_udp":true,"status_tcp":true,"version":"2014101200","motd":"tox-bootstrapd","last_ping":1474137097},{"ipv4":"185.58.206.164","ipv6":"2a02:f680:1:1100::3313","port":33445,"tcp_ports":[3389,33445],"public_key":"24156472041E5F220D1FA11D9DF32F7AD697D59845701CDD7BE7D1785EB9DB39","maintainer":"ru_maniac","location":"RU","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"please note: running on iphy's fork!\nmore info on the matter: goo.gl/Gz5KhK \u0026 goo.gl/i2TZJr\n\ntox id for queries and general info: EBD2A7B649ABB10ED9F47E5113F04000F39D46F087CEB62FCCE1069471FD6915256D197F2A97","last_ping":1474137098},{"ipv4":"128.199.199.197","ipv6":"2400:6180:0:d0::17a:a001","port":33445,"tcp_ports":[3389,33445],"public_key":"B05C8869DBB4EDDD308F43C1A974A20A725A36EACCA123862FDE9945BF9D3E09","maintainer":"wiiaam","location":"SG","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"apt-get install antox","last_ping":1474137098},{"ipv4":"bootybay.club","ipv6":"-","port":33445,"tcp_ports":[3389,33445],"public_key":"0CB9D8D636F8E3D71CF44A3019408A846B7BEDFA2810853355DB58C0A36BFE38","maintainer":"AssPirate","location":"AU","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"tox-bootstrapd","last_ping":1474137098},{"ipv4":"91.121.66.124","ipv6":"2001:41d0:1:757c::1","port":33445,"tcp_ports":[33445],"public_key":"4E3F7D37295664BBD0741B6DBCB6431D6CD77FC4105338C2FC31567BF5C8224A","maintainer":"h4nt3r","location":"FR","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"tox id for queries and general info: 3BC3C6875508A2EC86BE3E35E4FA9155E444CFA96671AE7D7D0D2585A0A5FA38E071A5E463E5","last_ping":1474137097},{"ipv4":"195.93.190.6","ipv6":"2a01:d0:ffff:a8a::2","port":33445,"tcp_ports":[33445],"public_key":"FB4CE0DDEFEED45F26917053E5D24BDDA0FA0A3D83A672A9DA2375928B37023D","maintainer":"strngr","location":"UA","status_udp":true,"status_tcp":true,"version":"","motd":"","last_ping":1474137105},{"ipv4":"loki.uplinklabs.net","ipv6":"loki.uplinklabs.net","port":33445,"tcp_ports":[3389,33445],"public_key":"1A56EA3EDF5DF4C0AEABBF3C2E4E603890F87E983CAC8A0D532A335F2C6E3E1F","maintainer":"AbacusAvenger","location":"US","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"tox-bootstrapd","last_ping":1474137098},{"ipv4":"95.215.44.78","ipv6":"2a02:7aa0:1619::c6fe:d0cb","port":33445,"tcp_ports":[33445,3389],"public_key":"672DBE27B4ADB9D5FB105A6BB648B2F8FDB89B3323486A7A21968316E012023C","maintainer":"HooinKyoma","location":"SE","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Thanx to Hooin Kyoma","last_ping":1474137098},{"ipv4":"tox.ntp.moscow","ipv6":"tox.ntp.moscow","port":33445,"tcp_ports":[33445,3389],"public_key":"80EF8660D9C5ACE1577BAB031375A0F08284CBFD9F810A857955DCC87377FC4D","maintainer":"abbat","location":"RU","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"tox-easy-bootstrap","last_ping":1474137098},{"ipv4":"146.185.136.123","ipv6":"2a03:b0c0:0:1010::389:1","port":33445,"tcp_ports":[33445,443,3389],"public_key":"09993FAF174DFFDC515B398A2EFC5639C4E6D7B736FC864F89786B50EAF88C1A","maintainer":"LittleVulpix","location":"NL","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"LittleTox - your friendly neighbourhood tox node from the land of windmills!","last_ping":1474137097},{"ipv4":"163.172.136.118","ipv6":"2001:bc8:4400:2100::1c:50f","port":33445,"tcp_ports":[33445,3389],"public_key":"2C289F9F37C20D09DA83565588BF496FAB3764853FA38141817A72E3F18ACA0B","maintainer":"LittleVulpix","location":"FR","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"LittleTox - your friendly neighbourhood tox node!","last_ping":1474137097},{"ipv4":"37.97.185.116","ipv6":"-","port":33445,"tcp_ports":[33445],"public_key":"E59A0E71ADA20D35BD1B0957059D7EF7E7792B3D680AE25C6F4DBBA09114D165","maintainer":"Yani","location":"NL","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Yani's node of pleasure and leisure","last_ping":1474137097},{"ipv4":"193.124.186.205","ipv6":"2a02:f680:1:1100::542a","port":5228,"tcp_ports":[443,3389,33445],"public_key":"9906D65F2A4751068A59D30505C5FC8AE1A95E0843AE9372EAFA3BAB6AC16C2C","maintainer":"Cactus","location":"RU","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"tox-bootstrapd","last_ping":1474137098},{"ipv4":"80.87.193.193","ipv6":"2a01:230:2:6::46a8","port":33445,"tcp_ports":[33445,3389],"public_key":"B38255EE4B054924F6D79A5E6E5889EC94B6ADF6FE9906F97A3D01E3D083223A","maintainer":"linxon","location":"RU","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Free Linxon's TOX Bootstrap node","last_ping":1474137098},{"ipv4":"initramfs.io","ipv6":"-","port":33445,"tcp_ports":[33445,3389],"public_key":"3F0A45A268367C1BEA652F258C85F4A66DA76BCAA667A49E770BCC4917AB6A25","maintainer":"initramfs","location":"TW","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"initramfs' Tox DHT Node","last_ping":1474137099},{"ipv4":"tox.neverlocate.me","ipv6":"-","port":33445,"tcp_ports":[33445],"public_key":"49183DBF0E865713154069D1C7C7A2732ED78CF32C4D76AF5304FE31C5FEB81A","maintainer":"brandon","location":"US","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"tox-bootstrapd","last_ping":1474137102},{"ipv4":"shigure.eve.moe","ipv6":"shigure.eve.moe","port":33445,"tcp_ports":[3389,33445],"public_key":"1A480A53FAF2CBBFCC382D786C43E69EEE23F22C7C23A7CFEB6180A373E23E54","maintainer":"EveNeko","location":"GB","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"tox-bootstrapd@shigure.eve.moe","last_ping":1474137098},{"ipv4":"tox.deadteam.org","ipv6":"tox.deadteam.org","port":33445,"tcp_ports":[33445],"public_key":"C7D284129E83877D63591F14B3F658D77FF9BA9BA7293AEB2BDFBFE1A803AF47","maintainer":"DeadTeam","location":"DE","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Vive le TOX","last_ping":1474137101},{"ipv4":"prok.pw","ipv6":"-","port":33445,"tcp_ports":[3389,33445],"public_key":"69C3FEBB977687B64FA0213BDEB89A43463BB48DED288150CFFB6429EFF82436","maintainer":"Prototik","location":"RU","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Have a nice chatting!","last_ping":1474137098},{"ipv4":"maggie.prok.pw","ipv6":"maggie.prok.pw","port":33445,"tcp_ports":[33445,3389],"public_key":"B75583B6D967DB8AD7C6D3B6F9318194BCC79B2FEF18F69E2DF275B779E7AA30","maintainer":"Prototik","location":"DE","status_udp":true,"status_tcp":true,"version":"2016010100","motd":"Maggie wants a pacifier","last_ping":1474137101},{"ipv4":"108.61.165.198","ipv6":"2001:19f0:5000:8121:5054:ff:fe1c:9ded","port":33445,"tcp_ports":[],"public_key":"8E7D0B859922EF569298B4D261A8CCB5FEA14FB91ED412A7603A585A25698832","maintainer":"ray65536","location":"NL","status_udp":true,"status_tcp":false,"version":"2016010100","motd":"Ray's Tox Node","last_ping":1474137101},{"ipv4":"92.54.84.70","ipv6":"-","port":33445,"tcp_ports":[],"public_key":"5625A62618CB4FCA70E147A71B29695F38CC65FF0CBD68AD46254585BE564802","maintainer":"t3mp","location":"RU","status_udp":true,"status_tcp":false,"version":"2016010100","motd":"tox-bootstrapd","last_ping":1474137102},{"ipv4":"srv1.ricin.im","ipv6":"-","port":1337,"tcp_ports":[],"public_key":"3651DAB570D7F60381F87B19D6935EE7F5FE01308DCE71C4B69993150C6A903C","maintainer":"Ricin.im","location":"FR","status_udp":true,"status_tcp":false,"version":"2016010100","motd":"Ricin.im Tox node. Enjoy babes \u003c3","last_ping":1474137101},{"ipv4":"46.101.197.175","ipv6":"2a03:b0c0:3:d0::ac:5001","port":443,"tcp_ports":[443,33445,3389],"public_key":"CD133B521159541FB1D326DE9850F5E56A6C724B5B8E5EB5CD8D950408E95707","maintainer":"clearmartin","location":"DE","status_udp":false,"status_tcp":true,"version":"","motd":"","last_ping":1474137105},{"ipv4":"toxnode.nek0.net","ipv6":"toxnode.nek0.net","port":33445,"tcp_ports":[3389,33445],"public_key":"20965721D32CE50C3E837DD75B33908B33037E6225110BFF209277AEAF3F9639","maintainer":"Phsm","location":"UA","status_udp":false,"status_tcp":true,"version":"","motd":"","last_ping":1474137107},{"ipv4":"sorunome.de","ipv6":"sorunome.de","port":33445,"tcp_ports":[33445,3389],"public_key":"02807CF4F8BB8FB390CC3794BDF1E8449E9A8392C5D3F2200019DA9F1E812E46","maintainer":"Sorunome","location":"DE","status_udp":false,"status_tcp":true,"version":"","motd":"","last_ping":1474137105},{"ipv4":"hibiki.eve.moe","ipv6":"hibiki.eve.moe","port":33445,"tcp_ports":[33445],"public_key":"D3EB45181B343C2C222A5BCF72B760638E15ED87904625AAD351C594EEFAE03E","maintainer":"EveNeko","location":"US","status_udp":false,"status_tcp":true,"version":"","motd":"","last_ping":1474137098},{"ipv4":"46.229.52.198","ipv6":"-","port":33445,"tcp_ports":[33445],"public_key":"813C8F4187833EF0655B10F7752141A352248462A567529A38B6BBF73E979307","maintainer":"Stranger","location":"UA","status_udp":false,"status_tcp":true,"version":"","motd":"","last_ping":1474137109},{"ipv4":"144.76.60.215","ipv6":"2a01:4f8:191:64d6::1","port":33445,"tcp_ports":[],"public_key":"04119E835DF3E78BACF0F84235B300546AF8B936F035185E2A8E9E0A67C8924F","maintainer":"sonOfRa","location":"DE","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"195.154.119.113","ipv6":"2001:bc8:3698:101::1","port":33445,"tcp_ports":[],"public_key":"E398A69646B8CEACA9F0B84F553726C1C49270558C57DF5F3C368F05A7D71354","maintainer":"Munrek","location":"FR","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"46.38.239.179","ipv6":"-","port":33445,"tcp_ports":[],"public_key":"F5A1A38EFB6BD3C2C8AF8B10D85F0F89E931704D349F1D0720C3C4059AF2440A","maintainer":"MartinSchröder","location":"DE","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"104.167.101.29","ipv6":"-","port":33445,"tcp_ports":[],"public_key":"5918AC3C06955962A75AD7DF4F80A5D7C34F7DB9E1498D2E0495DE35B3FE8A57","maintainer":"noisykeyboard","location":"CA","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"80.232.246.79","ipv6":"-","port":33445,"tcp_ports":[],"public_key":"CF6CECA0A14A31717CC8501DA51BE27742B70746956E6676FF423A529F91ED5D","maintainer":"fUNKIAM","location":"LV","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"104.233.104.126","ipv6":"-","port":33445,"tcp_ports":[],"public_key":"EDEE8F2E839A57820DE3DA4156D88350E53D4161447068A3457EE8F59F362414","maintainer":"wildermesser","location":"CA","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"home.vikingmakt.com.br","ipv6":"-","port":33445,"tcp_ports":[],"public_key":"188E072676404ED833A4E947DC1D223DF8EFEBE5F5258573A236573688FB9761","maintainer":"umgeher","location":"BR","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"188.244.38.183","ipv6":"2001:470:de00:2:20c:29ff:fe68:354f","port":33445,"tcp_ports":[],"public_key":"15A0F9684E2423F9F46CFA5A50B562AE42525580D840CC50E518192BF333EE38","maintainer":"gem","location":"RU","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"mrflibble.c4.ee","ipv6":"2a02:16e0:0:12::4","port":33445,"tcp_ports":[],"public_key":"FAAB17014F42F7F20949F61E55F66A73C230876812A9737F5F6D2DCE4D9E4207","maintainer":"mrflibble","location":"GB","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"82.211.31.116","ipv6":"-","port":33445,"tcp_ports":[],"public_key":"AF97B76392A6474AF2FD269220FDCF4127D86A42EF3A242DF53A40A268A2CD7C","maintainer":"Net.Verified","location":"RU","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"tox1.privacydragon.me","ipv6":"-","port":33445,"tcp_ports":[],"public_key":"31910C0497D347FF160D6F3A6C0E317BAFA71E8E03BC4CBB2A185C9D4FB8B31E","maintainer":"PrivacyDragon","location":"US","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"zawertun.net","ipv6":"-","port":33445,"tcp_ports":[],"public_key":"5521952892FBD5C185DF7180DB4DEF69D7844DEEE79B1F75A634ED9DF656756E","maintainer":"ZaWertun","location":"NL","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"87.98.168.93","ipv6":"-","port":33445,"tcp_ports":[],"public_key":"C3F6C06A624FAE086DA94604A7838DB495769807EC055FADA36EBF2D4484FB33","maintainer":"_kinka_","location":"ES","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"185.61.253.189","ipv6":"2a04:ee00:0:9:20c:29ff:fe27:ad96","port":33445,"tcp_ports":[],"public_key":"73EEBCB4CBBE56BF0E0F01881DDD88C6B250BAE92CF487BE3FBE02FD830CE200","maintainer":"MAXL-SPB","location":"RU","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"109.75.40.105","ipv6":"2001:470:70d6::1","port":33445,"tcp_ports":[],"public_key":"2B9CD794424FD579044EC2FC5252B23DF8B4AAF239C25074F70B1090C3F8C83A","maintainer":"nek","location":"AM","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0},{"ipv4":"185.120.34.64","ipv6":"2a06:8ec0:1:bb::3862","port":33445,"tcp_ports":[],"public_key":"728925473812C7AAC482BE7250BCCAD0B8CB9F737BF3D42ABD34459C1768F854","maintainer":"Kostik","location":"GB","status_udp":false,"status_tcp":false,"version":"","motd":"","last_ping":0}]} diff --git a/src/bootstrap.c b/src/bootstrap.c index 0e2e1ed..244ecc1 100644 --- a/src/bootstrap.c +++ b/src/bootstrap.c @@ -23,23 +23,40 @@ #include #include #include +#include +#include #include #include "line_info.h" #include "windows.h" #include "misc_tools.h" +#include "configdir.h" +#include "curl_util.h" extern struct arg_opts arg_opts; +/* URL that we get the JSON encoded nodes list from. */ +#define NODES_LIST_URL "https://nodes.tox.chat/json" + +#define DEFAULT_NODES_FILENAME "DHTnodes" /* Time to wait between bootstrap attempts */ #define TRY_BOOTSTRAP_INTERVAL 5 +/* Number of nodes to bootstrap to per try */ +#define NUM_BOOTSTRAP_NODES 5 + +/* How often we should update the nodeslist file. */ +#define NODELIST_UPDATE_TIMEOUT (60*24*30) + #define IPv4_MAX_SIZE 64 #define PORT_MAX_SIZE 5 +#define LAST_SCAN_JSON_VALUE "\"last_scan\":" +#define LAST_SCAN_JSON_VALUE_LEN (sizeof(LAST_SCAN_JSON_VALUE) - 1) + #define IPV4_JSON_VALUE "\"ipv4\":\"" #define IPV4_JSON_VALUE_LEN (sizeof(IPV4_JSON_VALUE) - 1) @@ -62,24 +79,198 @@ static struct toxNodes { char keys[MAXNODES][TOX_PUBLIC_KEY_SIZE]; } toxNodes; -/* Load the DHT nodelist to memory from json formatted nodes file obtained at https://nodes.tox.chat/json. + +/* Return true if nodeslist pointed to by fp needs to be updated. + * This will be the case if the file is empty, has an invalid format, + * or if the file is older than the given timeout. + */ +static bool nodeslist_needs_update(const char *nodes_path) +{ + FILE *fp = fopen(nodes_path, "r+"); + + if (fp == NULL) { + return false; + } + + /* last_scan value should be at beginning of file */ + char line[LAST_SCAN_JSON_VALUE_LEN + 32]; + + if (fgets(line, sizeof(line), fp) == NULL) { + fclose(fp); + return true; + } + + fclose(fp); + + const char *last_scan_val = strstr(line, LAST_SCAN_JSON_VALUE); + + if (last_scan_val == NULL) { + return true; + } + + last_scan_val += LAST_SCAN_JSON_VALUE_LEN; + long long int last_scan = strtoll(last_scan_val, NULL, 10); + + if (timed_out(last_scan, NODELIST_UPDATE_TIMEOUT)) { + return true; + } + + return false; +} + +/* Fetches the JSON encoded DHT nodeslist from NODES_LIST_URL. * * Return 0 on success. - * Return -1 if nodelist file cannot be opened. - * Return -2 if nodelist file cannot be parsed. - * Return -3 if nodelist file does not contain any valid node entries. + * Return -1 on failure. */ -int load_DHT_nodelist(void) +static int curl_fetch_nodes_JSON(struct Recv_Data *recv_data) { - const char *filename = !arg_opts.nodes_path[0] ? PACKAGE_DATADIR "/DHTnodes" : arg_opts.nodes_path; - FILE *fp = fopen(filename, "r"); + CURL *c_handle = curl_easy_init(); - if (fp == NULL) + if (c_handle == NULL) { return -1; + } + + 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, NODES_LIST_URL); + curl_easy_setopt(c_handle, CURLOPT_WRITEFUNCTION, write_lookup_data); + curl_easy_setopt(c_handle, CURLOPT_WRITEDATA, recv_data); + curl_easy_setopt(c_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); + curl_easy_setopt(c_handle, CURLOPT_HTTPGET, 1L); + + int proxy_ret = set_curl_proxy(c_handle, arg_opts.proxy_address, arg_opts.proxy_port, arg_opts.proxy_type); + + if (proxy_ret != 0) { + fprintf(stderr, "set_curl_proxy() failed with error %d\n", proxy_ret); + return -1; + } + + int ret = curl_easy_setopt(c_handle, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2); + + if (ret != CURLE_OK) { + fprintf(stderr, "TLSv1.2 could not be set (libcurl error %d)", ret); + return -1; + } + + ret = curl_easy_setopt(c_handle, CURLOPT_SSL_CIPHER_LIST, TLS_CIPHER_SUITE_LIST); + + if (ret != CURLE_OK) { + fprintf(stderr, "Failed to set TLS cipher list (libcurl error %d)", ret); + return -1; + } + + ret = curl_easy_perform(c_handle); + + if (ret != CURLE_OK) { + /* 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) { + fprintf(stderr, "HTTPS lookup error (libcurl error %d)\n", ret); + return -1; + } + } + + return 0; +} + +/* Attempts to update the DHT nodeslist. + * + * Return 1 if list was updated successfully. + * Return 0 if list does not need to be updated. + * Return -1 if file cannot be opened. + * Return -2 if http lookup failed. + * Return -3 if http reponse was empty. + * Return -4 if data could not be written to disk. + */ +static int update_DHT_nodeslist(const char *nodes_path) +{ + if (!nodeslist_needs_update(nodes_path)) { + return 0; + } + + FILE *fp = fopen(nodes_path, "r+"); + + if (fp == NULL) { + return -1; + } + + struct Recv_Data recv_data; + memset(&recv_data, 0, sizeof(struct Recv_Data)); + + if (curl_fetch_nodes_JSON(&recv_data) == -1) { + fclose(fp); + return -2; + } + + if (recv_data.length == 0) { + fclose(fp); + return -3; + } + + if (fwrite(recv_data.data, recv_data.length, 1, fp) != 1) { + fclose(fp); + return -4; + } + + fclose(fp); + return 1; +} + +static void get_nodeslist_path(char *buf, size_t buf_size) +{ + char *config_dir = NULL; + + if (arg_opts.nodes_path[0]) { + snprintf(buf, buf_size, "%s", arg_opts.nodes_path); + } else if ((config_dir = get_user_config_dir()) != NULL) { + snprintf(buf, buf_size, "%s%s%s", config_dir, CONFIGDIR, DEFAULT_NODES_FILENAME); + free(config_dir); + } else { + snprintf(buf, buf_size, "%s", DEFAULT_NODES_FILENAME); + } +} + +/* Load the DHT nodeslist to memory from json encoded nodes file obtained at NODES_LIST_URL. + * TODO: Parse json using a proper library? + * + * Return 0 on success. + * Return -1 if nodeslist file cannot be opened or created. + * Return -2 if nodeslist file cannot be parsed. + * Return -3 if nodeslist file does not contain any valid node entries. + */ +int load_DHT_nodeslist(void) +{ + char nodes_path[PATH_MAX]; + get_nodeslist_path(nodes_path, sizeof(nodes_path)); + + FILE *fp = NULL; + + if (!file_exists(nodes_path)) { + if ((fp = fopen(nodes_path, "w+")) == NULL) { + return -1; + } + } else if ((fp = fopen(nodes_path, "r+")) == NULL) { + return -1; + } + + int update_err = update_DHT_nodeslist(nodes_path); + + if (update_err < 0) { + fprintf(stderr, "update_DHT_nodeslist() failed with error %d\n", update_err); + } char line[MAX_NODELIST_SIZE]; if (fgets(line, sizeof(line), fp) == NULL) { + fclose(fp); return -2; } @@ -124,8 +315,9 @@ int load_DHT_nodelist(void) long int port = strtol(port_string, NULL, 10); - if (port <= 0 || port > MAX_PORT_RANGE) + if (port <= 0 || port > MAX_PORT_RANGE) { continue; + } /* Extract key */ const char *key_start = strstr(port_start, KEY_JSON_VALUE); @@ -145,7 +337,7 @@ int load_DHT_nodelist(void) memcpy(key_string, key_start, TOX_PUBLIC_KEY_SIZE * 2); key_string[TOX_PUBLIC_KEY_SIZE * 2] = 0; - /* Add IP-Port-Key to nodes list */ + /* Add entry to nodes list */ snprintf(toxNodes.nodes[toxNodes.lines], sizeof(toxNodes.nodes[toxNodes.lines]), "%s", ipv4_string); toxNodes.ports[toxNodes.lines] = port; @@ -155,34 +347,45 @@ int load_DHT_nodelist(void) toxNodes.lines++; } - fclose(fp); - - if (toxNodes.lines == 0) + /* If nodeslist does not contain any valid entries we set the last_scan value + * to 0 so that it will fetch a new list the next time this function is called. + */ + if (toxNodes.lines == 0) { + const char *s = "{\"last_scan\":0}"; + rewind(fp); + fwrite(s, strlen(s), 1, fp); // Not much we can do if it fails + fclose(fp); return -3; + } + fclose(fp); return 0; } -/* Connects to a random DHT node listed in the DHTnodes file. */ +/* Connects to NUM_BOOTSTRAP_NODES random DHT nodes listed in the DHTnodes file. */ static void DHT_bootstrap(Tox *m) { if (toxNodes.lines == 0) { return; } - size_t node = rand() % toxNodes.lines; + size_t i; - TOX_ERR_BOOTSTRAP err; - tox_bootstrap(m, toxNodes.nodes[node], toxNodes.ports[node], (uint8_t *) toxNodes.keys[node], &err); + for (i = 0; i < NUM_BOOTSTRAP_NODES; ++i) { + size_t node = rand() % toxNodes.lines; - if (err != TOX_ERR_BOOTSTRAP_OK) { - fprintf(stderr, "Failed to bootstrap %s:%d\n", toxNodes.nodes[node], toxNodes.ports[node]); - } + TOX_ERR_BOOTSTRAP err; + tox_bootstrap(m, toxNodes.nodes[node], toxNodes.ports[node], (uint8_t *) toxNodes.keys[node], &err); - tox_add_tcp_relay(m, toxNodes.nodes[node], toxNodes.ports[node], (uint8_t *) toxNodes.keys[node], &err); + if (err != TOX_ERR_BOOTSTRAP_OK) { + fprintf(stderr, "Failed to bootstrap %s:%d\n", toxNodes.nodes[node], toxNodes.ports[node]); + } - if (err != TOX_ERR_BOOTSTRAP_OK) { - fprintf(stderr, "Failed to add TCP relay %s:%d\n", toxNodes.nodes[node], toxNodes.ports[node]); + tox_add_tcp_relay(m, toxNodes.nodes[node], toxNodes.ports[node], (uint8_t *) toxNodes.keys[node], &err); + + if (err != TOX_ERR_BOOTSTRAP_OK) { + fprintf(stderr, "Failed to add TCP relay %s:%d\n", toxNodes.nodes[node], toxNodes.ports[node]); + } } } diff --git a/src/bootstrap.h b/src/bootstrap.h index e3dfab5..0159d3d 100644 --- a/src/bootstrap.h +++ b/src/bootstrap.h @@ -23,11 +23,12 @@ /* Manages connection to the Tox DHT network. */ void do_tox_connection(Tox *m); -/* Load the DHT nodelist to memory from json formatted nodes file obtained attempts https://nodes.tox.chat/json. +/* Load the DHT nodeslist to memory from json encoded nodes file obtained at NODES_LIST_URL. + * TODO: Parse json using a proper library? * * Return 0 on success. - * Return -1 if nodelist file cannot be opened. - * Return -2 if nodelist file cannot be parsed. - * Return -3 if nodelist file does not contain any valid node entries. + * Return -1 if nodeslist file cannot be opened or created. + * Return -2 if nodeslist file cannot be parsed. + * Return -3 if nodeslist file does not contain any valid node entries. */ -int load_DHT_nodelist(void); +int load_DHT_nodeslist(void); diff --git a/src/configdir.c b/src/configdir.c index d1e5f8d..ee97af3 100644 --- a/src/configdir.c +++ b/src/configdir.c @@ -33,7 +33,7 @@ #include "configdir.h" #include "misc_tools.h" -/* get the user's home directory */ +/* get the user's home directory. */ void get_home_dir(char *home, int size) { struct passwd pwd; @@ -102,8 +102,10 @@ char *get_user_config_dir(void) return user_config_dir; } -/* - * Creates the config and chatlog directories. +/* Creates the config and chatlog directories. + * + * Returns 0 on success. + * Returns -1 on failure. */ int create_user_config_dirs(char *path) { diff --git a/src/configdir.h b/src/configdir.h index 69abffd..a5317c3 100644 --- a/src/configdir.h +++ b/src/configdir.h @@ -34,8 +34,23 @@ #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) #endif +/** + * @brief Get the user's config directory. + * + * This is without a trailing slash. Resulting string must be freed. + * + * @return The users config dir or NULL on error. + */ char *get_user_config_dir(void); + +/* get the user's home directory. */ void get_home_dir(char *home, int size); + +/* Creates the config and chatlog directories. + * + * Returns 0 on success. + * Returns -1 on failure. + */ int create_user_config_dirs(char *path); #endif /* #define CONFIGDIR_H */ diff --git a/src/curl_util.c b/src/curl_util.c new file mode 100644 index 0000000..5ab2944 --- /dev/null +++ b/src/curl_util.c @@ -0,0 +1,93 @@ +/* curl_util.c + * + * + * Copyright (C) 2016 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 +#include + +#include "curl_util.h" + +/* Sets proxy info for given CURL handler. + * + * Returns 0 on success or if no proxy is set by the client. + * Returns -1 if proxy info is invalid. + * Returns an int > 0 on curl error (see: https://curl.haxx.se/libcurl/c/libcurl-errors.html) + */ +int set_curl_proxy(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) { + return -1; + } + + int ret = curl_easy_setopt(c_handle, CURLOPT_PROXYPORT, (long) port); + + if (ret != CURLE_OK) { + return ret; + } + + long int type = proxy_type == TOX_PROXY_TYPE_SOCKS5 ? CURLPROXY_SOCKS5_HOSTNAME : CURLPROXY_HTTP; + + ret = curl_easy_setopt(c_handle, CURLOPT_PROXYTYPE, type); + + if (ret != CURLE_OK) { + return ret; + } + + ret = curl_easy_setopt(c_handle, CURLOPT_PROXY, proxy_address); + + if (ret != CURLE_OK) { + return ret; + } + + return 0; +} + +/* Callback function for CURL to write received data. + * + * This function will append data from an http request to the data buffer + * until the request is complete or the buffer is full. Buffer will be null terminated. + * + * Returns number of bytes received from http request on success (don't change this). + * Returns 0 if data exceeds buffer 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 length = size * nmemb; + size_t total_size = length + recv_data->length; + + if (total_size > MAX_RECV_CURL_DATA_SIZE) { + return 0; + } + + memcpy(recv_data->data + recv_data->length, data, length); + recv_data->data[total_size] = '\0'; + recv_data->length += length; + + return length; +} diff --git a/src/curl_util.h b/src/curl_util.h new file mode 100644 index 0000000..b6b67f1 --- /dev/null +++ b/src/curl_util.h @@ -0,0 +1,50 @@ +/* curl_util.h + * + * + * Copyright (C) 2016 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 . + * + */ + +/* 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" + +/* Max size of an http response that we can store in Recv_Data */ +#define MAX_RECV_CURL_DATA_SIZE 32767 + +/* Holds data received from curl lookup */ +struct Recv_Data { + char data[MAX_RECV_CURL_DATA_SIZE + 1]; /* Data received from curl write data callback */ + size_t length; /* Total number of bytes written to data buffer (doesn't include null) */ +}; + +/* Sets proxy info for given CURL handler. + * + * Returns 0 on success or if no proxy is set by the client. + * Returns -1 if proxy info is invalid. + * Returns an int > 0 on curl error (see: https://curl.haxx.se/libcurl/c/libcurl-errors.html) + */ +int set_curl_proxy(CURL *c_handle, const char *proxy_address, uint16_t port, uint8_t proxy_type); + +/* Callback function for CURL to write received data. + * + * This function will append data from an http request to the data buffer + * until the request is complete or the buffer is full. Buffer will be null terminated. + * + * Returns size of bytes written to the data buffer. + */ +size_t write_lookup_data(void *data, size_t size, size_t nmemb, void *user_pointer); diff --git a/src/name_lookup.c b/src/name_lookup.c index 3fc7e36..863e9aa 100644 --- a/src/name_lookup.c +++ b/src/name_lookup.c @@ -22,7 +22,6 @@ #include #include -#include /* for u_char */ #include #include "toxic.h" @@ -31,6 +30,7 @@ #include "global_commands.h" #include "misc_tools.h" #include "configdir.h" +#include "curl_util.h" extern struct arg_opts arg_opts; extern struct Winthread Winthread;; @@ -41,9 +41,6 @@ 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]; @@ -189,29 +186,6 @@ static bool get_domain_match(char *pubkey, char *out_domain, size_t out_domain_s 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. @@ -222,7 +196,7 @@ 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) + if (recv_data->length < TOX_ADDRESS_SIZE * 2 + prefix_size) return -1; const char *IDstart = strstr(recv_data->data, ID_PREFIX); @@ -243,47 +217,6 @@ 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, "Unknown 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_HOSTNAME : 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; @@ -333,8 +266,12 @@ 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) + int proxy_ret = set_curl_proxy(c_handle, arg_opts.proxy_address, arg_opts.proxy_port, arg_opts.proxy_type); + + if (proxy_ret != 0) { + lookup_error(self, "Failed to set proxy (error %d)\n"); goto on_exit; + } int ret = curl_easy_setopt(c_handle, CURLOPT_USE_SSL, CURLUSESSL_ALL); @@ -437,9 +374,9 @@ void name_lookup(ToxWindow *self, Tox *m, const char *id_bin, const char *addr, * 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) +int name_lookup_init(int curl_init_status) { - if (curl_global_init(CURL_GLOBAL_ALL) != 0) { + if (curl_init_status != 0) { t_data.disabled = true; return -1; } @@ -454,8 +391,3 @@ int name_lookup_init(void) return 0; } - -void name_lookup_cleanup(void) -{ - curl_global_cleanup(); -} diff --git a/src/name_lookup.h b/src/name_lookup.h index c1419d8..e9b8ed4 100644 --- a/src/name_lookup.h +++ b/src/name_lookup.h @@ -29,8 +29,7 @@ * Returns 0 on success. * Returns -1 on failure. */ -int name_lookup_init(void); -void name_lookup_cleanup(void); +int name_lookup_init(int curl_init_status); int name_lookup(ToxWindow *self, Tox *m, const char *id_bin, const char *addr, const char *message); diff --git a/src/toxic.c b/src/toxic.c index ab56f5c..2691656 100644 --- a/src/toxic.c +++ b/src/toxic.c @@ -41,6 +41,7 @@ #include #include +#include #include #include @@ -164,7 +165,7 @@ void exit_toxic_success(Tox *m) free_global_data(); tox_kill(m); endwin(); - name_lookup_cleanup(); + curl_global_cleanup(); #ifdef X11 /* We have to terminate xtra last coz reasons @@ -455,6 +456,7 @@ int store_data(Tox *m, const char *path) char *data = malloc(data_len * sizeof(char)); if (data == NULL) { + fclose(fp); return -1; } @@ -465,6 +467,7 @@ int store_data(Tox *m, const char *path) char *enc_data = malloc(enc_len * sizeof(char)); if (enc_data == NULL) { + fclose(fp); free(data); return -1; } @@ -580,14 +583,14 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, TOX_ERR_NEW if (len == 0) { fclose(fp); - exit_toxic_err("failed in load_toxic", FATALERR_FILEOP); + exit_toxic_err("failed in load_tox", FATALERR_FILEOP); } char data[len]; if (fread(data, sizeof(data), 1, fp) != 1) { fclose(fp); - exit_toxic_err("failed in load_toxic", FATALERR_FILEOP); + exit_toxic_err("failed in load_tox", FATALERR_FILEOP); } bool is_encrypted = tox_is_data_encrypted((uint8_t *) data); @@ -595,7 +598,7 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, TOX_ERR_NEW /* attempt to encrypt an already encrypted data file */ if (arg_opts.encrypt_data && is_encrypted) { fclose(fp); - exit_toxic_err("failed in load_toxic", FATALERR_ENCRYPT); + exit_toxic_err("failed in load_tox", FATALERR_ENCRYPT); } if (arg_opts.unencrypt_data && is_encrypted) @@ -681,7 +684,7 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, TOX_ERR_NEW fclose(fp); } else { /* Data file does not/should not exist */ if (file_exists(data_path)) - exit_toxic_err("failed in load_toxic", FATALERR_FILEOP); + exit_toxic_err("failed in load_tox", FATALERR_FILEOP); tox_opts->savedata_type = TOX_SAVEDATA_TYPE_NONE; @@ -691,7 +694,7 @@ static Tox *load_tox(char *data_path, struct Tox_Options *tox_opts, TOX_ERR_NEW return NULL; if (store_data(m, data_path) == -1) - exit_toxic_err("failed in load_toxic", FATALERR_FILEOP); + exit_toxic_err("failed in load_tox", FATALERR_FILEOP); } return m; @@ -920,10 +923,6 @@ static void parse_args(int argc, char *argv[]) case 'n': snprintf(arg_opts.nodes_path, sizeof(arg_opts.nodes_path), "%s", optarg); - - if (!file_exists(arg_opts.nodes_path)) - queue_init_message("DHTnodes file not found"); - break; case 'o': @@ -1092,6 +1091,7 @@ void DnD_callback(const char* asdv, DropType dt) int main(int argc, char **argv) { + update_unix_time(); parse_args(argc, argv); /* Use the -b flag to enable stderr */ @@ -1125,16 +1125,12 @@ int main(int argc, char **argv) const char *p = arg_opts.config_path[0] ? arg_opts.config_path : NULL; - if (settings_load(user_settings, p) == -1) + if (settings_load(user_settings, p) == -1) { queue_init_message("Failed to load user settings"); - - int nodelist_ret = load_DHT_nodelist(); - - if (nodelist_ret != 0) { - queue_init_message("DHT nodelist failed to load (error %d). You can still connect manually with the /connect command.", nodelist_ret); } - int nameserver_ret = name_lookup_init(); + int curl_init = curl_global_init(CURL_GLOBAL_ALL); + int nameserver_ret = name_lookup_init(curl_init); if (nameserver_ret == -1) { queue_init_message("curl failed to initialize; name lookup service is disabled."); @@ -1144,6 +1140,12 @@ int main(int argc, char **argv) queue_init_message("Name lookup server list does not contain any valid entries."); } + int nodeslist_ret = load_DHT_nodeslist(); + + if (nodeslist_ret != 0) { + queue_init_message("DHT nodeslist failed to load (error %d)\n", nodeslist_ret); + } + #ifdef X11 if (init_xtra(DnD_callback) == -1) queue_init_message("X failed to initialize"); diff --git a/src/windows.h b/src/windows.h index c2a0760..21f1386 100644 --- a/src/windows.h +++ b/src/windows.h @@ -153,7 +153,7 @@ struct ToxWindow { #ifdef VIDEO int video_device_selection[2]; /* -1 if not set, if set uses these selections instead of primary video device */ - + #endif /* VIDEO */ #endif /* AUDIO */