RainflyClient.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include "interface/RainflyClient.h"
  16. #include "benc/String.h"
  17. #include "benc/serialization/BencSerializer.h"
  18. #include "benc/serialization/json/JsonBencSerializer.h"
  19. #include "crypto/random/Random.h"
  20. #include "io/ArrayReader.h"
  21. #include "util/events/Timeout.h"
  22. #include "util/Assert.h"
  23. #include "wire/Message.h"
  24. #include "wire/Error.h"
  25. #include <crypto_sign_ed25519.h>
  26. struct RainflyClient_Key
  27. {
  28. uint8_t bytes[32];
  29. };
  30. Assert_compileTime(sizeof(struct RainflyClient_Key) == 32);
  31. struct RainflyClient_Sig
  32. {
  33. uint8_t bytes[64];
  34. };
  35. Assert_compileTime(sizeof(struct RainflyClient_Sig) == 64);
  36. struct RainflyClient_Lookup_pvt;
  37. struct RainflyClient_Lookup_pvt
  38. {
  39. struct RainflyClient_Lookup pub;
  40. uint32_t cookie;
  41. int server;
  42. int triedServers;
  43. /** The index in hotKeys of the first key pushed to the request. */
  44. int firstKey;
  45. struct RainflyClient_pvt* ctx;
  46. struct Timeout* tryNextTimeout;
  47. struct RainflyClient_Lookup_pvt* next;
  48. Identity
  49. };
  50. struct RainflyClient_pvt
  51. {
  52. struct RainflyClient pub;
  53. struct Interface* iface;
  54. struct Log* logger;
  55. struct EventBase* eventBase;
  56. struct Allocator* alloc;
  57. struct Random* rand;
  58. /** My address. */
  59. struct Sockaddr* addr;
  60. int serverCount;
  61. struct Sockaddr** servers;
  62. int keyCount;
  63. struct RainflyClient_Key* keys;
  64. /** Bitmap of available hot keys. */
  65. uint64_t keyMap;
  66. struct RainflyClient_Key* hotKeys;
  67. struct Timeout* hotKeysTimeout;
  68. struct RainflyClient_Lookup_pvt* lookups;
  69. Identity
  70. };
  71. enum RequestType
  72. {
  73. RequestType_PING = 0x00,
  74. RequestType_HOT_KEYS = 0x01,
  75. RequestType_LOOKUP = 0x02
  76. };
  77. static String** readNames(struct Message* msg, int count, struct Allocator* alloc)
  78. {
  79. String** out = Allocator_calloc(alloc, sizeof(uintptr_t), count+1);
  80. int totalLen = 0;
  81. for (int i = 0; i < count; i++) {
  82. if (msg->length < 1) {
  83. return NULL;
  84. }
  85. int len = Message_pop8(msg, NULL);
  86. out[i] = String_newBinary(NULL, len, alloc);
  87. Message_pop(msg, out[i]->bytes, len, NULL);
  88. totalLen += len + 1;
  89. }
  90. while (totalLen++ % 8) {
  91. if (Message_pop8(msg, NULL)) {
  92. return NULL;
  93. }
  94. }
  95. return out;
  96. }
  97. static void writeNames(struct Message* msg, String** names)
  98. {
  99. int totalLength = 0;
  100. int i;
  101. for (i = 0; names && names[i]; ++i) {
  102. totalLength += names[i]->len + 1;
  103. }
  104. while (totalLength++ % 8) {
  105. Message_push8(msg, 0, NULL);
  106. }
  107. while (--i >= 0) {
  108. Message_push(msg, names[i]->bytes, names[i]->len, NULL);
  109. Message_push8(msg, names[i]->len, NULL);
  110. }
  111. }
  112. static int compare(String* a, String* b)
  113. {
  114. if (a->len != b->len) {
  115. return (a->len > b->len) ? 1 : -1;
  116. }
  117. for (int i = 0; i < (int)a->len; i++) {
  118. if (a->bytes[i] != b->bytes[i]) {
  119. return ((uint8_t)a->bytes[i]) > ((uint8_t)b->bytes[i]) ? 1 : -1;
  120. }
  121. }
  122. return 0;
  123. }
  124. static void handleLookupReply(struct Message* msg, struct RainflyClient_pvt* ctx)
  125. {
  126. Log_debug(ctx->logger, "lookup reply!");
  127. if (msg->length < 10) {
  128. Log_debug(ctx->logger, "runt");
  129. return;
  130. }
  131. uint32_t cookie = Message_pop8(msg, NULL);
  132. cookie <<= 16;
  133. cookie |= Message_pop16(msg, NULL);
  134. uint32_t height = Message_pop32(msg, NULL);
  135. String** namesAndValue = readNames(msg, 3, msg->alloc);
  136. if (!namesAndValue) {
  137. Log_debug(ctx->logger, "runt");
  138. return;
  139. }
  140. int count = msg->length / 64;
  141. if (msg->length != (count * 64)) {
  142. Log_debug(ctx->logger, "invalid message size");
  143. return;
  144. }
  145. struct RainflyClient_Sig* sigs = Allocator_malloc(msg->alloc, msg->length);
  146. for (int i = count-1; i >= 0; i--) {
  147. Message_pop(msg, sigs[i].bytes, 64, NULL);
  148. }
  149. Message_shift(msg, -msg->length, NULL);
  150. writeNames(msg, namesAndValue);
  151. Message_push32(msg, height, NULL);
  152. // find the matching lookup
  153. struct RainflyClient_Lookup_pvt* lookup = ctx->lookups;
  154. while (lookup && lookup->cookie != cookie) {
  155. lookup = lookup->next;
  156. }
  157. if (!lookup) {
  158. Log_debug(ctx->logger, "Response to unasked question");
  159. return;
  160. }
  161. enum RainflyClient_ResponseCode code = RainflyClient_ResponseCode_NO_ERROR;
  162. String* domain = lookup->pub.domain;
  163. if (!String_equals(namesAndValue[0], domain)) {
  164. if (compare(namesAndValue[0], namesAndValue[1]) == 1) {
  165. // they returned the last entry in the set
  166. // it must fall outside of range
  167. if (compare(domain, namesAndValue[0]) != 1 && compare(namesAndValue[1], domain) != 1) {
  168. Log_debug(ctx->logger, "Invalid NXDOMAIN with last entry [%s] -> [%s] req: [%s]",
  169. namesAndValue[0]->bytes, namesAndValue[1]->bytes, domain->bytes);
  170. return;
  171. }
  172. } else if (compare(domain, namesAndValue[0]) != 1
  173. || compare(namesAndValue[1], domain) != 1)
  174. {
  175. Log_debug(ctx->logger, "Invalid NXDOMAIN, domain not in range [%s] -> [%s] req: [%s]",
  176. namesAndValue[0]->bytes, namesAndValue[1]->bytes, domain->bytes);
  177. return;
  178. }
  179. Log_debug(ctx->logger, "Domain [%s] Nonexistant [%s] -> [%s]",
  180. domain->bytes, namesAndValue[0]->bytes, namesAndValue[1]->bytes);
  181. code = RainflyClient_ResponseCode_NXDOMAIN;
  182. }
  183. int validSigs = 0;
  184. uint8_t* scratch = Allocator_malloc(msg->alloc, msg->length + 64);
  185. for (int i = 0; i < count; i++) {
  186. unsigned long long x = 32;
  187. Message_push(msg, sigs[i].bytes, 64, NULL);
  188. uint8_t* key = ctx->hotKeys[(lookup->firstKey + i) % ctx->keyCount].bytes;
  189. if (!crypto_sign_ed25519_open(scratch, &x, msg->bytes, msg->length, key)
  190. && (int)x == msg->length - 64)
  191. {
  192. Log_debug(ctx->logger, "valid signature [%d] on [%s]", i, namesAndValue[0]->bytes);
  193. validSigs++;
  194. } else if (Bits_isZero(sigs[i].bytes, 64)) {
  195. Log_debug(ctx->logger, "unknown signature [%d] on [%s]", i, namesAndValue[0]->bytes);
  196. } else {
  197. Log_debug(ctx->logger, "invalid signature [%d] on [%s]", i, namesAndValue[0]->bytes);
  198. }
  199. Message_shift(msg, -64, NULL);
  200. }
  201. if (validSigs < ctx->pub.minSignatures) {
  202. Log_debug(ctx->logger, "Not enough signatures");
  203. return;
  204. }
  205. struct Reader* r = ArrayReader_new(namesAndValue[2]->bytes, namesAndValue[2]->len, msg->alloc);
  206. Dict d;
  207. if (JsonBencSerializer_get()->parseDictionary(r, msg->alloc, &d)) {
  208. Log_debug(ctx->logger, "Error parsing json");
  209. if (!code) {
  210. code = RainflyClient_ResponseCode_SERVER_ERROR;
  211. }
  212. }
  213. if (lookup->pub.onReply) {
  214. lookup->pub.onReply(&lookup->pub, &d, code);
  215. }
  216. Allocator_free(lookup->pub.alloc);
  217. }
  218. static void handleHotKeysReply(struct Message* msg, struct RainflyClient_pvt* ctx)
  219. {
  220. Log_debug(ctx->logger, "hotkeys reply");
  221. if (msg->length < 7) {
  222. Log_debug(ctx->logger, "runt");
  223. return;
  224. }
  225. uint8_t keyCount = Message_pop8(msg, NULL);
  226. uint16_t start = Message_pop16(msg, NULL);
  227. if (keyCount > ctx->keyCount) {
  228. Log_debug(ctx->logger, "keycount too high");
  229. return;
  230. }
  231. if (start > keyCount) {
  232. Log_debug(ctx->logger, "start too high");
  233. return;
  234. }
  235. uint32_t bitField = Message_pop32(msg, NULL);
  236. if ((Bits_popCountx32(bitField) * (64+32)) != msg->length) {
  237. Log_debug(ctx->logger, "incorrect message size");
  238. return;
  239. }
  240. uint32_t i = start;
  241. do {
  242. i = (i - 1) % keyCount;
  243. if (!(bitField & 1)) {
  244. Log_debug(ctx->logger, "missing signature [%d]", i);
  245. bitField >>= 1;
  246. continue;
  247. }
  248. bitField >>= 1;
  249. // This needs to be 96 bytes otherwise crypto_sign_ed25519_open() will buffer overflow.
  250. // We only use the first 32
  251. uint8_t hotKey[96];
  252. uint8_t sig[96];
  253. Message_pop(msg, sig, 96, NULL);
  254. unsigned long long x = 32;
  255. if (!crypto_sign_ed25519_open(hotKey, &x, sig, 96, ctx->keys[i].bytes) && x == 32) {
  256. Log_debug(ctx->logger, "valid signature [%d]", i);
  257. Bits_memcpyConst(ctx->hotKeys[i].bytes, hotKey, 32);
  258. ctx->keyMap |= (1 << i);
  259. } else {
  260. Log_debug(ctx->logger, "invalid signature [%d]", i);
  261. }
  262. } while (i != start);
  263. }
  264. static uint8_t receiveMessage(struct Message* msg, struct Interface* iface)
  265. {
  266. struct RainflyClient_pvt* ctx =
  267. Identity_check((struct RainflyClient_pvt*)iface->receiverContext);
  268. if (msg->length < ctx->addr->addrLen + 4) {
  269. Log_debug(ctx->logger, "runt");
  270. return Error_NONE;
  271. }
  272. Message_shift(msg, -ctx->addr->addrLen, NULL);
  273. uint8_t operation = Message_pop8(msg, NULL);
  274. if (!(operation & (1<<7))) {
  275. Log_debug(ctx->logger, "query");
  276. }
  277. operation &= ((1<<7)-1);
  278. Log_debug(ctx->logger, "Got a reply [%d]", operation);
  279. switch (operation) {
  280. case RequestType_PING: return Error_NONE;
  281. case RequestType_HOT_KEYS: handleHotKeysReply(msg, ctx); return Error_NONE;
  282. case RequestType_LOOKUP: handleLookupReply(msg, ctx); return Error_NONE;
  283. default: Log_debug(ctx->logger, "Got a message with unrecognized type [%d]", operation);
  284. }
  285. return Error_NONE;
  286. }
  287. static void sendHotKeysRequest(void* vRainflyClient)
  288. {
  289. struct RainflyClient_pvt* ctx = Identity_check((struct RainflyClient_pvt*)vRainflyClient);
  290. int time;
  291. if (Bits_popCountx32(ctx->keyMap) < ctx->pub.minSignatures && ctx->keyCount) {
  292. time = Random_uint32(ctx->rand) % 5000;
  293. } else {
  294. time = (Random_uint32(ctx->rand) % 600000) + 120000;
  295. }
  296. Timeout_resetTimeout(ctx->hotKeysTimeout, time);
  297. if (!ctx->keyCount) {
  298. Log_debug(ctx->logger, "No keys to try");
  299. return;
  300. }
  301. if (!ctx->serverCount) {
  302. Log_debug(ctx->logger, "No servers to try");
  303. return;
  304. }
  305. struct Allocator* alloc = Allocator_child(ctx->alloc);
  306. struct Message* msg = Message_new(0, 1536, alloc);
  307. int start = Random_uint32(ctx->rand) % ctx->keyCount;
  308. int j = 0;
  309. int i = start;
  310. do {
  311. Message_push(msg, ctx->keys[i].bytes, 32, NULL);
  312. i = (i + 1) % ctx->keyCount;
  313. } while (i != start && ++j < 10);
  314. // only 24 bits of space to put some information so put the beginning key and the current
  315. // number of keys so we can reconstruct which keys we sent when we get the response.
  316. Message_push16(msg, start, NULL);
  317. Message_push8(msg, ctx->keyCount, NULL);
  318. Message_push8(msg, RequestType_HOT_KEYS, NULL);
  319. int server = Random_uint32(ctx->rand) % ctx->serverCount;
  320. Message_push(msg, ctx->servers[server], ctx->addr->addrLen, NULL);
  321. Log_debug(ctx->logger, "Sending hotkeys request to [%s]",
  322. Sockaddr_print(ctx->servers[server], alloc));
  323. Interface_sendMessage(ctx->iface, msg);
  324. Allocator_free(alloc);
  325. }
  326. static int lookupOnFree(struct Allocator_OnFreeJob* onFree)
  327. {
  328. struct RainflyClient_Lookup_pvt* lookup =
  329. Identity_check((struct RainflyClient_Lookup_pvt*)onFree->userData);
  330. struct RainflyClient_Lookup_pvt* l = lookup->ctx->lookups;
  331. if (l == lookup) {
  332. lookup->ctx->lookups = lookup->next;
  333. return 0;
  334. }
  335. while (l->next != lookup) {
  336. l = l->next;
  337. }
  338. l->next = lookup->next;
  339. return 0;
  340. }
  341. static void tryNextServer(void* vLookup)
  342. {
  343. struct RainflyClient_Lookup_pvt* lookup =
  344. Identity_check((struct RainflyClient_Lookup_pvt*)vLookup);
  345. struct RainflyClient_pvt* ctx = Identity_check((struct RainflyClient_pvt*)lookup->ctx);
  346. if (lookup->triedServers++ > ctx->pub.maxTries) {
  347. if (lookup->pub.onReply) {
  348. lookup->pub.onReply(&lookup->pub, NULL, RainflyClient_ResponseCode_SERVER_ERROR);
  349. }
  350. Allocator_free(lookup->pub.alloc);
  351. return;
  352. }
  353. struct Allocator* alloc = Allocator_child(lookup->pub.alloc);
  354. struct Message* msg = Message_new(0, 1536, alloc);
  355. int start = lookup->firstKey = Random_uint32(ctx->rand) % ctx->keyCount;
  356. int j = 0;
  357. int i = start;
  358. do {
  359. Message_push(msg, ctx->hotKeys[i].bytes, 32, NULL);
  360. i = (i + 1) % ctx->keyCount;
  361. } while (i != start && ++j < 10);
  362. Log_debug(ctx->logger, "looking up [%s]", lookup->pub.domain->bytes);
  363. writeNames(msg, (String*[]) { lookup->pub.domain, NULL });
  364. uint32_t typeAndIdent = lookup->cookie | (RequestType_LOOKUP << 24);
  365. Message_push32(msg, typeAndIdent, NULL);
  366. int server = lookup->server++ % ctx->serverCount;
  367. Message_push(msg, ctx->servers[server], ctx->addr->addrLen, NULL);
  368. Log_debug(ctx->logger, "Sending lookup request to [%s]",
  369. Sockaddr_print(ctx->servers[server], alloc));
  370. Interface_sendMessage(ctx->iface, msg);
  371. Allocator_free(alloc);
  372. }
  373. ////////////////////
  374. struct RainflyClient_Lookup* RainflyClient_lookup(struct RainflyClient* client, String* domain)
  375. {
  376. struct RainflyClient_pvt* ctx = Identity_check((struct RainflyClient_pvt*)client);
  377. if (!ctx->keyCount || ctx->keyCount < ctx->pub.minSignatures) {
  378. Log_debug(ctx->logger, "Not enough keys to get required signatues");
  379. return NULL;
  380. }
  381. if (!ctx->serverCount) {
  382. Log_debug(ctx->logger, "No servers to try");
  383. return NULL;
  384. }
  385. struct Allocator* alloc = Allocator_child(ctx->alloc);
  386. struct RainflyClient_Lookup_pvt* out =
  387. Allocator_calloc(alloc, sizeof(struct RainflyClient_Lookup_pvt), 1);
  388. out->pub.alloc = alloc;
  389. out->next = ctx->lookups;
  390. if (out->next) {
  391. out->cookie = out->next->cookie++ & 0x00ffffff;
  392. }
  393. ctx->lookups = out;
  394. out->ctx = ctx;
  395. Identity_set(out);
  396. out->pub.domain = String_newBinary(NULL, domain->len+2, alloc);
  397. Bits_memcpy(&out->pub.domain->bytes[2], domain->bytes, domain->len);
  398. out->pub.domain->bytes[0] = 'h';
  399. out->pub.domain->bytes[1] = '/';
  400. out->server = Random_uint32(ctx->rand) % ctx->serverCount;
  401. out->tryNextTimeout = Timeout_setTimeout(tryNextServer, out, 3000, ctx->eventBase, alloc);
  402. Allocator_onFree(alloc, lookupOnFree, out);
  403. tryNextServer(out);
  404. return &out->pub;
  405. }
  406. int RainflyClient_addKey(struct RainflyClient* client, uint8_t key[32])
  407. {
  408. struct RainflyClient_pvt* ctx = Identity_check((struct RainflyClient_pvt*)client);
  409. if (ctx->keyCount > 63) {
  410. return RainflyClient_addKey_TOO_MANY_KEYS;
  411. }
  412. ctx->keyCount++;
  413. ctx->keys = Allocator_realloc(ctx->alloc, ctx->keys, ctx->keyCount * 32);
  414. ctx->hotKeys = Allocator_realloc(ctx->alloc, ctx->hotKeys, ctx->keyCount * 32);
  415. Bits_memcpyConst(&ctx->keys[ctx->keyCount-1], key, 32);
  416. return 0;
  417. }
  418. int RainflyClient_addServer(struct RainflyClient* client, struct Sockaddr* addr)
  419. {
  420. struct RainflyClient_pvt* ctx = Identity_check((struct RainflyClient_pvt*)client);
  421. if (addr->addrLen != ctx->addr->addrLen
  422. || Sockaddr_getFamily(addr) != Sockaddr_getFamily(ctx->addr))
  423. {
  424. return RainflyClient_addServer_WRONG_ADDRESS_TYPE;
  425. }
  426. ctx->serverCount++;
  427. ctx->servers =
  428. Allocator_realloc(ctx->alloc, ctx->servers, ctx->serverCount * sizeof(uintptr_t));
  429. ctx->servers[ctx->serverCount-1] = Sockaddr_clone(addr, ctx->alloc);
  430. return 0;
  431. }
  432. struct RainflyClient* RainflyClient_new(struct AddrInterface* iface,
  433. struct EventBase* base,
  434. struct Random* rand,
  435. struct Log* logger)
  436. {
  437. struct RainflyClient_pvt* ctx =
  438. Allocator_clone(iface->generic.allocator, (&(struct RainflyClient_pvt) {
  439. .pub = {
  440. .minSignatures = RainflyClient_DEFAULT_MIN_SIGNATURES,
  441. .maxTries = RainflyClient_DEFAULT_MAX_TRIES,
  442. },
  443. .iface = &iface->generic,
  444. .logger = logger,
  445. .addr = iface->addr,
  446. .alloc = iface->generic.allocator,
  447. .rand = rand,
  448. .eventBase = base,
  449. }));
  450. Identity_set(ctx);
  451. ctx->hotKeysTimeout = Timeout_setInterval(sendHotKeysRequest, ctx, 1000, base, ctx->alloc);
  452. iface->generic.receiveMessage = receiveMessage;
  453. iface->generic.receiverContext = ctx;
  454. return &ctx->pub;
  455. }