sybilsim.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  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 "benc/serialization/standard/BencMessageReader.h"
  16. #include "benc/serialization/standard/BencMessageWriter.h"
  17. #include "benc/serialization/json/JsonBencSerializer.h"
  18. #include "benc/serialization/BencSerializer.h"
  19. #include "io/ArrayReader.h"
  20. #include "admin/angel/Core.h"
  21. #include "admin/AdminClient.h"
  22. #include "memory/MallocAllocator.h"
  23. #include "memory/Allocator.h"
  24. #include "util/log/FileWriterLog.h"
  25. #include "wire/Message.h"
  26. #include "interface/Interface.h"
  27. #include "util/events/EventBase.h"
  28. #include "crypto/random/Random.h"
  29. #include "crypto/random/libuv/LibuvEntropyProvider.h"
  30. #include "exception/Except.h"
  31. #include "util/events/Timeout.h"
  32. #include "crypto/Key.h"
  33. #include "util/log/Log_impl.h"
  34. #include "io/FileReader.h"
  35. #include "io/ArrayWriter.h"
  36. #include "util/Hex.h"
  37. #include "crypto_scalarmult_curve25519.h"
  38. #include <unistd.h> // isatty()
  39. struct NodeContext {
  40. struct Interface angelIface;
  41. struct Sockaddr* boundAddr;
  42. struct Allocator* alloc;
  43. struct EventBase* base;
  44. uint8_t privateKeyHex[64];
  45. String* publicKey;
  46. struct AdminClient* adminClient;
  47. char* nodeName;
  48. /** Admin socket to bind */
  49. String* bind;
  50. /** Admin password */
  51. String* pass;
  52. /** UDPInterface */
  53. int ifNum;
  54. struct Sockaddr* udpAddr;
  55. struct Log nodeLog;
  56. struct Log* parentLogger;
  57. Identity
  58. };
  59. static uint8_t messageToAngel(struct Message* msg, struct Interface* iface)
  60. {
  61. struct NodeContext* ctx = Identity_check((struct NodeContext*) iface);
  62. if (ctx->boundAddr) { return 0; }
  63. struct Allocator* alloc = Allocator_child(ctx->alloc);
  64. Dict* config = BencMessageReader_read(msg, alloc, NULL);
  65. Dict* admin = Dict_getDict(config, String_CONST("admin"));
  66. String* bind = Dict_getString(admin, String_CONST("bind"));
  67. struct Sockaddr_storage ss;
  68. Assert_true(!Sockaddr_parse(bind->bytes, &ss));
  69. ctx->boundAddr = Sockaddr_clone(&ss.addr, ctx->alloc);
  70. Allocator_free(alloc);
  71. EventBase_endLoop(ctx->base);
  72. return 0;
  73. }
  74. static void sendFirstMessageToCore(void* vcontext)
  75. {
  76. struct NodeContext* ctx = Identity_check((struct NodeContext*) vcontext);
  77. struct Allocator* alloc = Allocator_child(ctx->alloc);
  78. struct Message* msg = Message_new(0, 512, alloc);
  79. Dict* d = Dict_new(alloc);
  80. Dict_putString(d, String_CONST("privateKey"), String_new(ctx->privateKeyHex, alloc), alloc);
  81. Dict* logging = Dict_new(alloc);
  82. {
  83. Dict_putString(logging, String_CONST("logTo"), String_CONST("stdout"), alloc);
  84. }
  85. Dict_putDict(d, String_CONST("logging"), logging, alloc);
  86. Dict* admin = Dict_new(alloc);
  87. {
  88. Dict_putString(admin, String_CONST("bind"), ctx->bind, alloc);
  89. Dict_putString(admin, String_CONST("pass"), ctx->pass, alloc);
  90. }
  91. Dict_putDict(d, String_CONST("admin"), admin, alloc);
  92. BencMessageWriter_write(d, msg, NULL);
  93. Interface_receiveMessage(&ctx->angelIface, msg);
  94. Allocator_free(alloc);
  95. }
  96. struct RPCCall;
  97. typedef void (* RPCCallback)(struct RPCCall* call, struct AdminClient_Result* res);
  98. struct RPCCall
  99. {
  100. String* func;
  101. Dict* args;
  102. struct NodeContext* node;
  103. RPCCallback callback;
  104. };
  105. struct Context
  106. {
  107. struct RPCCall* rpcCalls;
  108. int rpcCallCount;
  109. int nextCall;
  110. struct Allocator* rpcAlloc;
  111. struct Random* rand;
  112. struct EventBase* base;
  113. struct Log* logger;
  114. struct Allocator* alloc;
  115. struct NodeContext** nodes;
  116. Dict* confNodes;
  117. String** names;
  118. Identity
  119. };
  120. static String* getPublicKey(char* privateKeyHex, struct Allocator* alloc)
  121. {
  122. uint8_t privateKey[32];
  123. uint8_t publicKey[32];
  124. Hex_decode(privateKey, 32, privateKeyHex, 65);
  125. crypto_scalarmult_curve25519_base(publicKey, privateKey);
  126. return Key_stringify(publicKey, alloc);
  127. }
  128. static void printLog(struct Log* log,
  129. enum Log_Level logLevel,
  130. const char* file,
  131. int line,
  132. const char* format,
  133. va_list args)
  134. {
  135. struct NodeContext* ctx = Identity_check(
  136. (struct NodeContext*) (((char*)log) - offsetof(struct NodeContext, nodeLog))
  137. );
  138. struct Allocator* alloc = Allocator_child(ctx->alloc);
  139. String* str = String_printf(alloc, "[%s] %s", ctx->nodeName, file);
  140. ctx->parentLogger->print(ctx->parentLogger, logLevel, str->bytes, line, format, args);
  141. Allocator_free(alloc);
  142. }
  143. static struct RPCCall* pushCall(struct Context* ctx)
  144. {
  145. ctx->rpcCalls = Allocator_realloc(ctx->rpcAlloc,
  146. ctx->rpcCalls,
  147. sizeof(struct RPCCall) * (ctx->rpcCallCount+1));
  148. Bits_memset(&ctx->rpcCalls[ctx->rpcCallCount], 0, sizeof(struct RPCCall));
  149. return &ctx->rpcCalls[ctx->rpcCallCount++];
  150. }
  151. static void bindUDPCallback(struct RPCCall* call, struct AdminClient_Result* res)
  152. {
  153. Assert_true(!res->err);
  154. Log_debug(&call->node->nodeLog, "UDPInterface_new() -> [%s]", res->messageBytes);
  155. String* addr = Dict_getString(res->responseDict, String_CONST("bindAddress"));
  156. int64_t* ifNum = Dict_getInt(res->responseDict, String_CONST("interfaceNumber"));
  157. struct Sockaddr_storage ss;
  158. Assert_true(!Sockaddr_parse(addr->bytes, &ss));
  159. call->node->ifNum = *ifNum;
  160. call->node->udpAddr = Sockaddr_clone(&ss.addr, call->node->alloc);
  161. }
  162. static void bindUDP(struct Context* ctx, struct NodeContext* node)
  163. {
  164. struct RPCCall* call = pushCall(ctx);
  165. call->func = String_new("UDPInterface_new", ctx->rpcAlloc);
  166. call->args = Dict_new(ctx->rpcAlloc);
  167. call->node = node;
  168. call->callback = bindUDPCallback;
  169. }
  170. static struct NodeContext* startNode(char* nodeName,
  171. char* privateKeyHex,
  172. Dict* admin,
  173. struct Context* ctx,
  174. struct Except* eh)
  175. {
  176. struct NodeContext* node = Allocator_clone(ctx->alloc, (&(struct NodeContext) {
  177. .angelIface = {
  178. .sendMessage = messageToAngel
  179. },
  180. .alloc = ctx->alloc,
  181. .base = ctx->base,
  182. .nodeLog = {
  183. .print = printLog
  184. },
  185. .parentLogger = ctx->logger,
  186. .nodeName = nodeName
  187. }));
  188. Identity_set(node);
  189. node->bind = Dict_getString(admin, String_CONST("bind"));
  190. if (!node->bind) {
  191. node->bind = String_new("127.0.0.1:0", ctx->alloc);
  192. }
  193. node->pass = Dict_getString(admin, String_CONST("password"));
  194. if (!node->pass) {
  195. node->pass = String_new("x", ctx->alloc);
  196. }
  197. Bits_memcpyConst(node->privateKeyHex, privateKeyHex, 64);
  198. Timeout_setTimeout(sendFirstMessageToCore, node, 0, ctx->base, node->alloc);
  199. Core_init(node->alloc, &node->nodeLog, ctx->base, &node->angelIface, ctx->rand, eh);
  200. // sendFirstMessageToCore causes the core to react causing messageToAngel which ends the loop
  201. EventBase_beginLoop(ctx->base);
  202. node->adminClient = AdminClient_new(node->boundAddr,
  203. node->pass,
  204. ctx->base,
  205. &node->nodeLog,
  206. node->alloc);
  207. node->adminClient->millisecondsToWait = 120000;
  208. bindUDP(ctx, node);
  209. node->publicKey = getPublicKey(privateKeyHex, node->alloc);
  210. return node;
  211. }
  212. static void beginConnectionCallback(struct RPCCall* call, struct AdminClient_Result* res)
  213. {
  214. Assert_true(!res->err);
  215. Log_debug(&call->node->nodeLog, "UDPInterface_beginConnection() -> [%s]", res->messageBytes);
  216. }
  217. static void linkNodes(struct Context* ctx, struct NodeContext* client, struct NodeContext* server)
  218. {
  219. Dict* addPasswordArgs = Dict_new(ctx->rpcAlloc);
  220. String* clientStr = String_printf(ctx->rpcAlloc, "%ld", (long) (uintptr_t) client);
  221. Dict_putString(addPasswordArgs,
  222. String_new("password", ctx->rpcAlloc),
  223. clientStr,
  224. ctx->rpcAlloc);
  225. Dict_putString(addPasswordArgs,
  226. String_new("user", ctx->rpcAlloc),
  227. clientStr,
  228. ctx->rpcAlloc);
  229. struct RPCCall* addPasswordCall = pushCall(ctx);
  230. addPasswordCall->func = String_new("AuthorizedPasswords_add", ctx->rpcAlloc);
  231. addPasswordCall->args = addPasswordArgs;
  232. addPasswordCall->node = server;
  233. // client
  234. Dict* beginConnectionArgs = Dict_new(ctx->rpcAlloc);
  235. Dict_putInt(beginConnectionArgs,
  236. String_new("interfaceNumber", ctx->rpcAlloc),
  237. client->ifNum,
  238. ctx->rpcAlloc);
  239. Dict_putString(beginConnectionArgs,
  240. String_new("password", ctx->rpcAlloc),
  241. clientStr,
  242. ctx->rpcAlloc);
  243. Dict_putString(beginConnectionArgs,
  244. String_new("publicKey", ctx->rpcAlloc),
  245. server->publicKey,
  246. ctx->rpcAlloc);
  247. char* udpAddr = Sockaddr_print(server->udpAddr, ctx->rpcAlloc);
  248. Dict_putString(beginConnectionArgs,
  249. String_new("address", ctx->rpcAlloc),
  250. String_new(udpAddr, ctx->rpcAlloc),
  251. ctx->rpcAlloc);
  252. Log_info(ctx->logger, "Linking [%s] with [%s/%s]",
  253. client->nodeName, server->nodeName, udpAddr);
  254. struct RPCCall* connectCall = pushCall(ctx);
  255. connectCall->func = String_new("UDPInterface_beginConnection", ctx->rpcAlloc);
  256. connectCall->args = beginConnectionArgs;
  257. connectCall->node = client;
  258. connectCall->callback = beginConnectionCallback;
  259. }
  260. static void linkAllNodes(struct Context* ctx)
  261. {
  262. int i = 0;
  263. String* key = NULL;
  264. Dict_forEach(ctx->confNodes, key) {
  265. Dict* val = Dict_getDict(ctx->confNodes, key);
  266. List* connectTo = Dict_getList(val, String_CONST("peers"));
  267. for (int j = 0; j < List_size(connectTo); j++) {
  268. String* server = List_getString(connectTo, j);
  269. Assert_true(server);
  270. for (int k = 0; k < Dict_size(ctx->confNodes); k++) {
  271. if (String_equals(server, ctx->names[k])) {
  272. linkNodes(ctx, ctx->nodes[i], ctx->nodes[k]);
  273. break;
  274. }
  275. }
  276. }
  277. i++;
  278. }
  279. ctx->confNodes = NULL;
  280. }
  281. static void startRpc(void* vcontext);
  282. static void rpcCallback(struct AdminClient_Promise* promise, struct AdminClient_Result* res)
  283. {
  284. struct Context* ctx = promise->userData;
  285. Identity_check(ctx);
  286. struct RPCCall* thisCall = &ctx->rpcCalls[ctx->nextCall];
  287. if (thisCall->callback) {
  288. thisCall->callback(thisCall, res);
  289. }
  290. ctx->nextCall++;
  291. startRpc(ctx);
  292. }
  293. static void startRpc(void* vcontext)
  294. {
  295. struct Context* ctx = vcontext;
  296. Identity_check(ctx);
  297. if (ctx->nextCall >= ctx->rpcCallCount) {
  298. if (ctx->confNodes) {
  299. linkAllNodes(ctx);
  300. }
  301. }
  302. if (ctx->nextCall >= ctx->rpcCallCount) {
  303. Log_info(ctx->logger, "\n\nCompleted setting up simulation\n\n");
  304. Allocator_free(ctx->rpcAlloc);
  305. ctx->rpcAlloc = NULL;
  306. ctx->rpcCalls = NULL;
  307. ctx->rpcCallCount = 0;
  308. return;
  309. }
  310. struct RPCCall* nextCall = &ctx->rpcCalls[ctx->nextCall];
  311. struct AdminClient_Promise* promise = AdminClient_rpcCall(nextCall->func,
  312. nextCall->args,
  313. nextCall->node->adminClient,
  314. ctx->rpcAlloc);
  315. promise->callback = rpcCallback;
  316. promise->userData = ctx;
  317. }
  318. static void letErRip(Dict* config, struct Allocator* alloc)
  319. {
  320. struct Except* eh = NULL;
  321. struct Log* logger = FileWriterLog_new(stdout, alloc);
  322. struct EventBase* base = EventBase_new(alloc);
  323. struct Random* rand = LibuvEntropyProvider_newDefaultRandom(base, logger, eh, alloc);
  324. Allocator_setCanary(alloc, (unsigned long)Random_uint64(rand));
  325. struct Context sctx = {
  326. .rpcAlloc = Allocator_child(alloc),
  327. .logger = logger,
  328. .base = base,
  329. .rand = rand,
  330. .alloc = alloc,
  331. };
  332. struct Context* ctx = &sctx;
  333. Identity_set(ctx);
  334. ctx->confNodes = Dict_getDict(config, String_CONST("nodes"));
  335. ctx->nodes = Allocator_calloc(alloc, sizeof(char*), Dict_size(ctx->confNodes));
  336. ctx->names = Allocator_calloc(alloc, sizeof(String*), Dict_size(ctx->confNodes));
  337. String* key = NULL;
  338. int i = 0;
  339. Dict_forEach(ctx->confNodes, key) {
  340. Dict* val = Dict_getDict(ctx->confNodes, key);
  341. String* privateKeyHex = Dict_getString(val, String_CONST("privateKey"));
  342. Dict* admin = Dict_getDict(val, String_CONST("admin"));
  343. ctx->names[i] = key;
  344. ctx->nodes[i] = startNode(key->bytes, privateKeyHex->bytes, admin, ctx, eh);
  345. i++;
  346. }
  347. // begin the chain of RPC calls which sets up the net
  348. Timeout_setTimeout(startRpc, ctx, 0, base, ctx->rpcAlloc);
  349. EventBase_beginLoop(base);
  350. Allocator_free(alloc);
  351. }
  352. static int usage(char* appName)
  353. {
  354. printf("Example usage: %s < config.json\n"
  355. "Example config:\n"
  356. "{\n"
  357. " \"nodes\": {\n"
  358. " \"alice\": {\n"
  359. " \"privateKey\": "
  360. "\"5e2295679394e5e1db67c238abbc10292ad9b127904394c52cc5fff39383e920\",\n"
  361. " \"peers\": []\n"
  362. " },\n"
  363. " \"bob\": {\n"
  364. " \"privateKey\": "
  365. "\"6569bf3f0d168faa6dfb2912f8ee5ee9b938319e97618fdf06caed73b1aad1cc\",\n"
  366. " \"peers\": [\n"
  367. " \"alice\"\n"
  368. " ]\n"
  369. " }\n"
  370. " }\n"
  371. "}\n", appName);
  372. return 0;
  373. }
  374. int main(int argc, char** argv)
  375. {
  376. Assert_true(argc > 0);
  377. if (isatty(STDIN_FILENO)) {
  378. return usage(argv[0]);
  379. }
  380. struct Allocator* alloc = MallocAllocator_new(1<<30);
  381. struct Reader* stdinReader = FileReader_new(stdin, alloc);
  382. Dict config;
  383. if (JsonBencSerializer_get()->parseDictionary(stdinReader, alloc, &config)) {
  384. fprintf(stderr, "Failed to parse configuration.\n");
  385. return -1;
  386. }
  387. letErRip(&config, alloc);
  388. }