AdminClient.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  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 "admin/AdminClient.h"
  16. #include "benc/serialization/BencSerializer.h"
  17. #include "benc/serialization/standard/StandardBencSerializer.h"
  18. #include "benc/serialization/cloner/Cloner.h"
  19. #include "interface/addressable/AddrInterface.h"
  20. #include "interface/addressable/UDPAddrInterface.h"
  21. #include "exception/Except.h"
  22. #include "io/ArrayReader.h"
  23. #include "io/ArrayWriter.h"
  24. #include "io/Reader.h"
  25. #include "io/Writer.h"
  26. #include "util/Bits.h"
  27. #include "util/platform/libc/strlen.h"
  28. #include "util/Endian.h"
  29. #include "util/Hex.h"
  30. #include "util/events/Timeout.h"
  31. #include "util/Identity.h"
  32. #include "wire/Message.h"
  33. #include <crypto_hash_sha256.h>
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. struct Request;
  37. typedef void (* AdminClient_RespHandler)(struct Request* req);
  38. struct Request
  39. {
  40. struct AdminClient_Result res;
  41. struct AdminClient_Promise* promise;
  42. AdminClient_RespHandler callback;
  43. struct Context* ctx;
  44. struct Allocator* alloc;
  45. /** Need a special allocator for the timeout so it can be axed before the request is complete */
  46. struct Allocator* timeoutAlloc;
  47. struct Timeout* timeout;
  48. Dict* requestMessage;
  49. /** the handle in the ctx->outstandingRequests map */
  50. uint32_t handle;
  51. Identity
  52. };
  53. #define Map_NAME OfRequestByHandle
  54. #define Map_ENABLE_HANDLES
  55. #define Map_VALUE_TYPE struct Request*
  56. #include "util/Map.h"
  57. struct Context
  58. {
  59. struct AdminClient pub;
  60. struct EventBase* eventBase;
  61. struct AddrInterface* addrIface;
  62. struct Sockaddr* targetAddr;
  63. struct Log* logger;
  64. String* password;
  65. struct Map_OfRequestByHandle outstandingRequests;
  66. struct Allocator* alloc;
  67. Identity
  68. };
  69. static int calculateAuth(Dict* message,
  70. String* password,
  71. String* cookieStr,
  72. struct Allocator* alloc)
  73. {
  74. // Calculate the hash of the password.
  75. String* hashHex = String_newBinary(NULL, 64, alloc);
  76. uint8_t passAndCookie[64];
  77. uint32_t cookie = (cookieStr != NULL) ? strtoll(cookieStr->bytes, NULL, 10) : 0;
  78. snprintf((char*) passAndCookie, 64, "%s%u", password->bytes, cookie);
  79. uint8_t hash[32];
  80. crypto_hash_sha256(hash, passAndCookie, strlen((char*) passAndCookie));
  81. Hex_encode((uint8_t*)hashHex->bytes, 64, hash, 32);
  82. Dict_putString(message, String_new("hash", alloc), hashHex, alloc);
  83. Dict_putString(message, String_new("cookie", alloc), cookieStr, alloc);
  84. // serialize the message with the password hash
  85. uint8_t buffer[AdminClient_MAX_MESSAGE_SIZE];
  86. struct Writer* writer = ArrayWriter_new(buffer, AdminClient_MAX_MESSAGE_SIZE, alloc);
  87. if (StandardBencSerializer_get()->serializeDictionary(writer, message)) {
  88. return -1;
  89. }
  90. int length = writer->bytesWritten;
  91. // calculate the hash of the message with the password hash
  92. crypto_hash_sha256(hash, buffer, length);
  93. // swap the hash of the message with the password hash into the location
  94. // where the password hash was.
  95. Hex_encode((uint8_t*)hashHex->bytes, 64, hash, 32);
  96. return 0;
  97. }
  98. static void done(struct Request* req, enum AdminClient_Error err)
  99. {
  100. req->res.err = err;
  101. req->callback(req);
  102. Allocator_free(req->timeoutAlloc);
  103. }
  104. static void timeout(void* vreq)
  105. {
  106. done((struct Request*) vreq, AdminClient_Error_TIMEOUT);
  107. }
  108. static uint8_t receiveMessage(struct Message* msg, struct Interface* iface)
  109. {
  110. struct Context* ctx = Identity_check((struct Context*) iface->receiverContext);
  111. struct Sockaddr_storage source;
  112. Message_pop(msg, &source, ctx->targetAddr->addrLen, NULL);
  113. if (Bits_memcmp(&source, ctx->targetAddr, ctx->targetAddr->addrLen)) {
  114. Log_info(ctx->logger, "Got spurious message from [%s], expecting messages from [%s]",
  115. Sockaddr_print(&source.addr, msg->alloc),
  116. Sockaddr_print(ctx->targetAddr, msg->alloc));
  117. return 0;
  118. }
  119. // we don't yet know with which message this data belongs,
  120. // the message alloc lives the length of the message reception.
  121. struct Allocator* alloc = Allocator_child(msg->alloc);
  122. struct Reader* reader = ArrayReader_new(msg->bytes, msg->length, alloc);
  123. Dict* d = Dict_new(alloc);
  124. if (StandardBencSerializer_get()->parseDictionary(reader, alloc, d)) { return 0; }
  125. String* txid = Dict_getString(d, String_CONST("txid"));
  126. if (!txid || txid->len != 8) { return 0; }
  127. // look up the result
  128. uint32_t handle = ~0u;
  129. Hex_decode((uint8_t*)&handle, 4, txid->bytes, 8);
  130. int idx = Map_OfRequestByHandle_indexForHandle(handle, &ctx->outstandingRequests);
  131. if (idx < 0) { return 0; }
  132. struct Request* req = ctx->outstandingRequests.values[idx];
  133. // now this data will outlive the life of the message.
  134. Allocator_adopt(req->promise->alloc, alloc);
  135. req->res.responseDict = d;
  136. int len =
  137. (msg->length > AdminClient_MAX_MESSAGE_SIZE) ? AdminClient_MAX_MESSAGE_SIZE : msg->length;
  138. Bits_memset(req->res.messageBytes, 0, AdminClient_MAX_MESSAGE_SIZE);
  139. Bits_memcpy(req->res.messageBytes, msg->bytes, len);
  140. done(req, AdminClient_Error_NONE);
  141. return 0;
  142. }
  143. static int requestOnFree(struct Allocator_OnFreeJob* job)
  144. {
  145. struct Request* req = Identity_check((struct Request*) job->userData);
  146. int idx = Map_OfRequestByHandle_indexForHandle(req->handle, &req->ctx->outstandingRequests);
  147. if (idx > -1) {
  148. Map_OfRequestByHandle_remove(idx, &req->ctx->outstandingRequests);
  149. }
  150. return 0;
  151. }
  152. static struct Request* sendRaw(Dict* messageDict,
  153. struct AdminClient_Promise* promise,
  154. struct Context* ctx,
  155. String* cookie,
  156. AdminClient_RespHandler callback)
  157. {
  158. struct Allocator* reqAlloc = Allocator_child(promise->alloc);
  159. struct Request* req = Allocator_clone(reqAlloc, (&(struct Request) {
  160. .alloc = reqAlloc,
  161. .ctx = ctx,
  162. .promise = promise
  163. }));
  164. Identity_set(req);
  165. int idx = Map_OfRequestByHandle_put(&req, &ctx->outstandingRequests);
  166. req->handle = ctx->outstandingRequests.handles[idx];
  167. String* id = String_newBinary(NULL, 8, req->alloc);
  168. Hex_encode(id->bytes, 8, (int8_t*) &req->handle, 4);
  169. Dict_putString(messageDict, String_CONST("txid"), id, req->alloc);
  170. if (cookie) {
  171. Assert_always(!calculateAuth(messageDict, ctx->password, cookie, req->alloc));
  172. }
  173. struct Writer* writer =
  174. ArrayWriter_new(req->res.messageBytes, AdminClient_MAX_MESSAGE_SIZE, req->alloc);
  175. if (StandardBencSerializer_get()->serializeDictionary(writer, messageDict)) {
  176. done(req, AdminClient_Error_SERIALIZATION_FAILED);
  177. return NULL;
  178. }
  179. req->timeoutAlloc = Allocator_child(req->alloc);
  180. req->timeout = Timeout_setTimeout(timeout,
  181. req,
  182. ctx->pub.millisecondsToWait,
  183. ctx->eventBase,
  184. req->timeoutAlloc);
  185. Allocator_onFree(req->timeoutAlloc, requestOnFree, req);
  186. req->callback = callback;
  187. struct Message m = {
  188. .bytes = req->res.messageBytes,
  189. .padding = AdminClient_Result_PADDING_SIZE,
  190. .length = writer->bytesWritten
  191. };
  192. Message_push(&m, ctx->targetAddr, ctx->targetAddr->addrLen, NULL);
  193. struct Allocator* child = Allocator_child(req->alloc);
  194. struct Message* msg = Message_clone(&m, child);
  195. Interface_sendMessage(&ctx->addrIface->generic, msg);
  196. Allocator_free(child);
  197. return req;
  198. }
  199. static void requestCallback(struct Request* req)
  200. {
  201. if (req->promise->callback) {
  202. req->promise->callback(req->promise, &req->res);
  203. }
  204. Allocator_free(req->promise->alloc);
  205. }
  206. static void cookieCallback(struct Request* req)
  207. {
  208. if (req->res.err) {
  209. requestCallback(req);
  210. return;
  211. }
  212. String* cookie = Dict_getString(req->res.responseDict, String_CONST("cookie"));
  213. if (!cookie) {
  214. req->res.err = AdminClient_Error_NO_COOKIE;
  215. requestCallback(req);
  216. return;
  217. }
  218. Dict* message = req->requestMessage;
  219. sendRaw(message, req->promise, req->ctx, cookie, requestCallback);
  220. Allocator_free(req->alloc);
  221. }
  222. static struct AdminClient_Promise* doCall(Dict* message,
  223. struct Context* ctx,
  224. struct Allocator* alloc)
  225. {
  226. struct Allocator* promiseAlloc = Allocator_child(alloc);
  227. struct AdminClient_Promise* promise =
  228. Allocator_calloc(promiseAlloc, sizeof(struct AdminClient_Promise), 1);
  229. promise->alloc = promiseAlloc;
  230. Dict gc = Dict_CONST(String_CONST("q"), String_OBJ(String_CONST("cookie")), NULL);
  231. struct Request* req = sendRaw(&gc, promise, ctx, NULL, cookieCallback);
  232. req->requestMessage = Cloner_cloneDict(message, promiseAlloc);
  233. return promise;
  234. }
  235. struct AdminClient_Promise* AdminClient_rpcCall(String* function,
  236. Dict* args,
  237. struct AdminClient* client,
  238. struct Allocator* alloc)
  239. {
  240. struct Context* ctx = Identity_check((struct Context*) client);
  241. Dict a = (args) ? *args : NULL;
  242. Dict message = Dict_CONST(
  243. String_CONST("q"), String_OBJ(String_CONST("auth")), Dict_CONST(
  244. String_CONST("aq"), String_OBJ(function), Dict_CONST(
  245. String_CONST("args"), Dict_OBJ(&a), NULL
  246. )));
  247. return doCall(&message, ctx, alloc);
  248. }
  249. char* AdminClient_errorString(enum AdminClient_Error err)
  250. {
  251. switch (err) {
  252. case AdminClient_Error_NONE:
  253. return "Success";
  254. case AdminClient_Error_OVERLONG_RESPONSE:
  255. return "Overlong resonse message";
  256. case AdminClient_Error_ERROR_READING_FROM_SOCKET:
  257. return "Error reading from socket, check errno.";
  258. case AdminClient_Error_SOCKET_NOT_READY:
  259. return "Socket not ready for reading";
  260. case AdminClient_Error_DESERIALIZATION_FAILED:
  261. return "Failed to deserialize response";
  262. case AdminClient_Error_SERIALIZATION_FAILED:
  263. return "Failed to serialize request";
  264. case AdminClient_Error_TIMEOUT:
  265. return "Timed out waiting for a response";
  266. case AdminClient_Error_NO_COOKIE:
  267. return "Cookie request returned with no cookie";
  268. default:
  269. return "Internal error";
  270. };
  271. }
  272. struct AdminClient* AdminClient_new(struct Sockaddr* connectToAddress,
  273. String* adminPassword,
  274. struct EventBase* eventBase,
  275. struct Log* logger,
  276. struct Allocator* alloc)
  277. {
  278. struct Context* context = Allocator_clone(alloc, (&(struct Context) {
  279. .eventBase = eventBase,
  280. .logger = logger,
  281. .password = adminPassword,
  282. .pub = {
  283. .millisecondsToWait = 5000,
  284. },
  285. .outstandingRequests = {
  286. .allocator = alloc
  287. },
  288. .alloc = alloc
  289. }));
  290. Identity_set(context);
  291. context->targetAddr = Sockaddr_clone(connectToAddress, alloc);
  292. if (Sockaddr_getFamily(context->targetAddr) == Sockaddr_AF_INET) {
  293. uint8_t* addrBytes;
  294. int len = Sockaddr_getAddress(context->targetAddr, &addrBytes);
  295. if (Bits_isZero(addrBytes, len)) {
  296. // 127.0.0.1
  297. uint32_t loopback = Endian_hostToBigEndian32(0x7f000001);
  298. Bits_memcpyConst(addrBytes, &loopback, 4);
  299. }
  300. }
  301. Log_debug(logger, "Connecting to [%s]", Sockaddr_print(context->targetAddr, alloc));
  302. context->addrIface = UDPAddrInterface_new(eventBase, NULL, alloc, NULL, logger);
  303. context->addrIface->generic.receiveMessage = receiveMessage;
  304. context->addrIface->generic.receiverContext = context;
  305. return &context->pub;
  306. }