1
0

sybilsim.c 15 KB

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