Configurator.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  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. #define string_strrchr
  16. #define string_strlen
  17. #include "admin/AdminClient.h"
  18. #include "admin/Configurator.h"
  19. #include "benc/String.h"
  20. #include "util/platform/libc/string.h"
  21. #include "benc/Dict.h"
  22. #include "benc/Int.h"
  23. #include "benc/List.h"
  24. #include "memory/Allocator.h"
  25. #include "util/events/Event.h"
  26. #include "util/Bits.h"
  27. #include "util/log/Log.h"
  28. #include "util/platform/Sockaddr.h"
  29. #include <stdlib.h>
  30. #include <stdbool.h>
  31. struct Context
  32. {
  33. struct Log* logger;
  34. struct Allocator* alloc;
  35. struct AdminClient* client;
  36. struct Allocator* currentReqAlloc;
  37. struct AdminClient_Result* currentResult;
  38. struct EventBase* base;
  39. };
  40. static void rpcCallback(struct AdminClient_Promise* p, struct AdminClient_Result* res)
  41. {
  42. struct Context* ctx = p->userData;
  43. Allocator_adopt(ctx->alloc, p->alloc);
  44. ctx->currentResult = res;
  45. EventBase_endLoop(ctx->base);
  46. }
  47. static void die(struct AdminClient_Result* res, struct Context* ctx, struct Allocator* alloc)
  48. {
  49. Log_keys(ctx->logger, "message bytes = [%s]", res->messageBytes);
  50. #ifndef Log_KEYS
  51. Log_critical(ctx->logger, "enable Log_LEVEL=KEYS to see message content.");
  52. #endif
  53. Dict d = NULL;
  54. struct AdminClient_Promise* exitPromise =
  55. AdminClient_rpcCall(String_CONST("Core_exit"), &d, ctx->client, alloc);
  56. exitPromise->callback = rpcCallback;
  57. exitPromise->userData = ctx;
  58. EventBase_beginLoop(ctx->base);
  59. if (ctx->currentResult->err) {
  60. Log_critical(ctx->logger, "Failed to stop the core.");
  61. }
  62. Log_critical(ctx->logger, "Aborting.");
  63. exit(1);
  64. }
  65. static int rpcCall0(String* function,
  66. Dict* args,
  67. struct Context* ctx,
  68. struct Allocator* alloc,
  69. bool exitIfError)
  70. {
  71. ctx->currentReqAlloc = Allocator_child(alloc);
  72. ctx->currentResult = NULL;
  73. struct AdminClient_Promise* promise = AdminClient_rpcCall(function, args, ctx->client, alloc);
  74. promise->callback = rpcCallback;
  75. promise->userData = ctx;
  76. EventBase_beginLoop(ctx->base);
  77. struct AdminClient_Result* res = ctx->currentResult;
  78. Assert_always(res);
  79. if (res->err) {
  80. Log_critical(ctx->logger,
  81. "Failed to make function call [%s], error: [%s]",
  82. AdminClient_errorString(res->err),
  83. function->bytes);
  84. die(res, ctx, alloc);
  85. }
  86. String* error = Dict_getString(res->responseDict, String_CONST("error"));
  87. int ret = 0;
  88. if (error && !String_equals(error, String_CONST("none"))) {
  89. if (exitIfError) {
  90. Log_critical(ctx->logger,
  91. "Got error [%s] calling [%s]",
  92. error->bytes,
  93. function->bytes);
  94. die(res, ctx, alloc);
  95. }
  96. Log_warn(ctx->logger, "Got error [%s] calling [%s], ignoring.",
  97. error->bytes, function->bytes);
  98. ret = 1;
  99. }
  100. Allocator_free(ctx->currentReqAlloc);
  101. ctx->currentReqAlloc = NULL;
  102. return ret;
  103. }
  104. static void rpcCall(String* function, Dict* args, struct Context* ctx, struct Allocator* alloc)
  105. {
  106. rpcCall0(function, args, ctx, alloc, true);
  107. }
  108. static void authorizedPasswords(List* list, struct Context* ctx)
  109. {
  110. uint32_t count = List_size(list);
  111. for (uint32_t i = 0; i < count; i++) {
  112. Dict* d = List_getDict(list, i);
  113. Log_info(ctx->logger, "Checking authorized password %d.", i);
  114. if (!d) {
  115. Log_critical(ctx->logger, "Not a dictionary type %d.", i);
  116. exit(-1);
  117. }
  118. String* passwd = Dict_getString(d, String_CONST("password"));
  119. if (!passwd) {
  120. Log_critical(ctx->logger, "Must specify a password %d.", i);
  121. exit(-1);
  122. }
  123. }
  124. for (uint32_t i = 0; i < count; i++) {
  125. struct Allocator* child = Allocator_child(ctx->alloc);
  126. Dict* d = List_getDict(list, i);
  127. String* passwd = Dict_getString(d, String_CONST("password"));
  128. String* user = Dict_getString(d, String_CONST("user"));
  129. if (!user) {
  130. user = String_printf(child, "password [%d]", i);
  131. }
  132. Log_info(ctx->logger, "Adding authorized password #[%d] for user [%s].", i, user->bytes);
  133. Dict args = Dict_CONST(
  134. String_CONST("authType"), Int_OBJ(1), Dict_CONST(
  135. String_CONST("password"), String_OBJ(passwd), Dict_CONST(
  136. String_CONST("user"), String_OBJ(user), NULL
  137. )));
  138. rpcCall(String_CONST("AuthorizedPasswords_add"), &args, ctx, child);
  139. Allocator_free(child);
  140. }
  141. }
  142. static void dns(Dict* dns, struct Context* ctx, struct Except* eh)
  143. {
  144. List* servers = Dict_getList(dns, String_CONST("servers"));
  145. int count = List_size(servers);
  146. for (int i = 0; i < count; i++) {
  147. String* server = List_getString(servers, i);
  148. if (!server) {
  149. Except_throw(eh, "dns.servers[%d] is not a string", i);
  150. }
  151. Dict* d = Dict_new(ctx->alloc);
  152. Dict_putString(d, String_CONST("addr"), server, ctx->alloc);
  153. rpcCall(String_CONST("RainflyClient_addServer"), d, ctx, ctx->alloc);
  154. }
  155. List* keys = Dict_getList(dns, String_CONST("keys"));
  156. count = List_size(keys);
  157. for (int i = 0; i < count; i++) {
  158. String* key = List_getString(keys, i);
  159. if (!key) {
  160. Except_throw(eh, "dns.keys[%d] is not a string", i);
  161. }
  162. Dict* d = Dict_new(ctx->alloc);
  163. Dict_putString(d, String_CONST("ident"), key, ctx->alloc);
  164. rpcCall(String_CONST("RainflyClient_addKey"), d, ctx, ctx->alloc);
  165. }
  166. int64_t* minSigs = Dict_getInt(dns, String_CONST("minSignatures"));
  167. if (minSigs) {
  168. Dict* d = Dict_new(ctx->alloc);
  169. Dict_putInt(d, String_CONST("count"), *minSigs, ctx->alloc);
  170. rpcCall(String_CONST("RainflyClient_minSignatures"), d, ctx, ctx->alloc);
  171. }
  172. }
  173. static void udpInterface(Dict* config, struct Context* ctx)
  174. {
  175. List* ifaces = Dict_getList(config, String_CONST("UDPInterface"));
  176. if (!ifaces) {
  177. ifaces = List_addDict(ifaces,
  178. Dict_getDict(config, String_CONST("UDPInterface")), ctx->alloc);
  179. }
  180. uint32_t count = List_size(ifaces);
  181. for (uint32_t i = 0; i < count; i++) {
  182. Dict *udp = List_getDict(ifaces, i);
  183. if (!udp) {
  184. continue;
  185. }
  186. // Setup the interface.
  187. String* bindStr = Dict_getString(udp, String_CONST("bind"));
  188. Dict* d = Dict_new(ctx->alloc);
  189. if (bindStr) {
  190. Dict_putString(d, String_CONST("bindAddress"), bindStr, ctx->alloc);
  191. }
  192. rpcCall(String_CONST("UDPInterface_new"), d, ctx, ctx->alloc);
  193. // Make the connections.
  194. Dict* connectTo = Dict_getDict(udp, String_CONST("connectTo"));
  195. if (connectTo) {
  196. struct Dict_Entry* entry = *connectTo;
  197. struct Allocator* perCallAlloc = Allocator_child(ctx->alloc);
  198. while (entry != NULL) {
  199. String* key = (String*) entry->key;
  200. if (entry->val->type != Object_DICT) {
  201. Log_critical(ctx->logger, "interfaces.UDPInterface.connectTo: entry [%s] "
  202. "is not a dictionary type.", key->bytes);
  203. exit(-1);
  204. }
  205. Dict* value = entry->val->as.dictionary;
  206. Log_keys(ctx->logger, "Attempting to connect to node [%s].", key->bytes);
  207. key = String_clone(key, perCallAlloc);
  208. char* lastColon = strrchr(key->bytes, ':');
  209. if (!Sockaddr_parse(key->bytes, NULL)) {
  210. // it's a sockaddr, fall through
  211. } else if (lastColon) {
  212. // try it as a hostname.
  213. int port = atoi(lastColon+1);
  214. if (!port) {
  215. Log_critical(ctx->logger, "Couldn't get port number from [%s]", key->bytes);
  216. exit(-1);
  217. }
  218. *lastColon = '\0';
  219. struct Sockaddr* adr = Sockaddr_fromName(key->bytes, perCallAlloc);
  220. if (adr != NULL) {
  221. Sockaddr_setPort(adr, port);
  222. key = String_new(Sockaddr_print(adr, perCallAlloc), perCallAlloc);
  223. } else {
  224. Log_warn(ctx->logger, "Failed to lookup hostname [%s]", key->bytes);
  225. entry = entry->next;
  226. continue;
  227. }
  228. }
  229. Dict_putString(value, String_CONST("address"), key, perCallAlloc);
  230. rpcCall(String_CONST("UDPInterface_beginConnection"), value, ctx, perCallAlloc);
  231. entry = entry->next;
  232. }
  233. Allocator_free(perCallAlloc);
  234. }
  235. }
  236. }
  237. static void tunInterface(Dict* ifaceConf, struct Allocator* tempAlloc, struct Context* ctx)
  238. {
  239. String* ifaceType = Dict_getString(ifaceConf, String_CONST("type"));
  240. if (!String_equals(ifaceType, String_CONST("TUNInterface"))) {
  241. return;
  242. }
  243. // Setup the interface.
  244. String* device = Dict_getString(ifaceConf, String_CONST("tunDevice"));
  245. Dict* args = Dict_new(tempAlloc);
  246. if (device) {
  247. Dict_putString(args, String_CONST("desiredTunName"), device, tempAlloc);
  248. }
  249. rpcCall0(String_CONST("Core_initTunnel"), args, ctx, tempAlloc, false);
  250. }
  251. static void ipTunnel(Dict* ifaceConf, struct Allocator* tempAlloc, struct Context* ctx)
  252. {
  253. List* incoming = Dict_getList(ifaceConf, String_CONST("allowedConnections"));
  254. Dict* d;
  255. for (int i = 0; (d = List_getDict(incoming, i)) != NULL; i++) {
  256. String* key = Dict_getString(d, String_CONST("publicKey"));
  257. String* ip4 = Dict_getString(d, String_CONST("ip4Address"));
  258. String* ip6 = Dict_getString(d, String_CONST("ip6Address"));
  259. if (!key) {
  260. Log_critical(ctx->logger, "In router.ipTunnel.allowedConnections[%d]"
  261. "'publicKey' required.", i);
  262. exit(1);
  263. }
  264. if (!ip4 && !ip6) {
  265. Log_critical(ctx->logger, "In router.ipTunnel.allowedConnections[%d]"
  266. "either ip4Address or ip6Address required.", i);
  267. exit(1);
  268. }
  269. Log_debug(ctx->logger, "Allowing IpTunnel connections from [%s]", key->bytes);
  270. Dict_putString(d, String_CONST("publicKeyOfAuthorizedNode"), key, tempAlloc);
  271. rpcCall0(String_CONST("IpTunnel_allowConnection"), d, ctx, tempAlloc, true);
  272. }
  273. List* outgoing = Dict_getList(ifaceConf, String_CONST("outgoingConnections"));
  274. String* s;
  275. for (int i = 0; (s = List_getString(outgoing, i)) != NULL; i++) {
  276. Log_debug(ctx->logger, "Initiating IpTunnel connection to [%s]", s->bytes);
  277. Dict requestDict =
  278. Dict_CONST(String_CONST("publicKeyOfNodeToConnectTo"), String_OBJ(s), NULL);
  279. rpcCall0(String_CONST("IpTunnel_connectTo"), &requestDict, ctx, tempAlloc, true);
  280. }
  281. }
  282. static void routerConfig(Dict* routerConf, struct Allocator* tempAlloc, struct Context* ctx)
  283. {
  284. tunInterface(Dict_getDict(routerConf, String_CONST("interface")), tempAlloc, ctx);
  285. ipTunnel(Dict_getDict(routerConf, String_CONST("ipTunnel")), tempAlloc, ctx);
  286. }
  287. #ifdef HAS_ETH_INTERFACE
  288. static void ethInterface(Dict* config, struct Context* ctx)
  289. {
  290. List* ifaces = Dict_getList(config, String_CONST("ETHInterface"));
  291. if (!ifaces) {
  292. ifaces = List_addDict(ifaces,
  293. Dict_getDict(config, String_CONST("ETHInterface")), ctx->alloc);
  294. }
  295. uint32_t count = List_size(ifaces);
  296. for (uint32_t i = 0; i < count; i++) {
  297. Dict *eth = List_getDict(ifaces, i);
  298. if (!eth) {
  299. continue;
  300. }
  301. // Setup the interface.
  302. String* deviceStr = Dict_getString(eth, String_CONST("bind"));
  303. Log_info(ctx->logger, "Setting up ETHInterface [%d].", i);
  304. Dict* d = Dict_new(ctx->alloc);
  305. if (deviceStr) {
  306. Log_info(ctx->logger, "Binding to device [%s].", deviceStr->bytes);
  307. Dict_putString(d, String_CONST("bindDevice"), deviceStr, ctx->alloc);
  308. }
  309. if (rpcCall0(String_CONST("ETHInterface_new"), d, ctx, ctx->alloc, false)) {
  310. Log_warn(ctx->logger, "Failed to create ETHInterface.");
  311. continue;
  312. }
  313. // Make the connections.
  314. Dict* connectTo = Dict_getDict(eth, String_CONST("connectTo"));
  315. if (connectTo) {
  316. Log_info(ctx->logger, "ETHInterface should connect to a specific node.");
  317. struct Dict_Entry* entry = *connectTo;
  318. while (entry != NULL) {
  319. String* key = (String*) entry->key;
  320. if (entry->val->type != Object_DICT) {
  321. Log_critical(ctx->logger, "interfaces.ETHInterface.connectTo: entry [%s] "
  322. "is not a dictionary type.", key->bytes);
  323. exit(-1);
  324. }
  325. Dict* value = entry->val->as.dictionary;
  326. Log_keys(ctx->logger, "Attempting to connect to node [%s].", key->bytes);
  327. struct Allocator* perCallAlloc = Allocator_child(ctx->alloc);
  328. // Turn the dict from the config into our RPC args dict by filling in all
  329. // the arguments,
  330. Dict_putString(value, String_CONST("macAddress"), key, perCallAlloc);
  331. Dict_putInt(value, String_CONST("interfaceNumber"), i, perCallAlloc);
  332. rpcCall(String_CONST("ETHInterface_beginConnection"), value, ctx, perCallAlloc);
  333. Allocator_free(perCallAlloc);
  334. entry = entry->next;
  335. }
  336. }
  337. int64_t* beaconP = Dict_getInt(eth, String_CONST("beacon"));
  338. if (beaconP) {
  339. int64_t beacon = *beaconP;
  340. if (beacon > 3 || beacon < 0) {
  341. Log_error(ctx->logger, "interfaces.ETHInterface.beacon may only be 0, 1,or 2");
  342. } else {
  343. // We can cast beacon to an int here because we know it's small enough
  344. Log_info(ctx->logger, "Setting beacon mode on ETHInterface to [%d].", (int) beacon);
  345. Dict d = Dict_CONST(String_CONST("interfaceNumber"), Int_OBJ(i),
  346. Dict_CONST(String_CONST("state"), Int_OBJ(beacon), NULL));
  347. rpcCall(String_CONST("ETHInterface_beacon"), &d, ctx, ctx->alloc);
  348. }
  349. }
  350. }
  351. }
  352. #endif
  353. static void security(List* securityConf, struct Allocator* tempAlloc, struct Context* ctx)
  354. {
  355. Dict* d = Dict_new(tempAlloc);
  356. Dict_putString(d, String_CONST("user"), String_CONST("nobody"), tempAlloc);
  357. // it's ok if this fails
  358. rpcCall0(String_CONST("Security_setUser"), d, ctx, tempAlloc, false);
  359. d = Dict_new(tempAlloc);
  360. rpcCall(String_CONST("Security_dropPermissions"), d, ctx, tempAlloc);
  361. }
  362. void Configurator_config(Dict* config,
  363. struct Sockaddr* sockAddr,
  364. String* adminPassword,
  365. struct EventBase* eventBase,
  366. struct Log* logger,
  367. struct Allocator* alloc)
  368. {
  369. struct Except* eh = NULL;
  370. struct Allocator* tempAlloc = Allocator_child(alloc);
  371. struct AdminClient* client =
  372. AdminClient_new(sockAddr, adminPassword, eventBase, logger, tempAlloc);
  373. struct Context ctx = {
  374. .logger = logger,
  375. .alloc = tempAlloc,
  376. .client = client,
  377. .base = eventBase,
  378. };
  379. List* authedPasswords = Dict_getList(config, String_CONST("authorizedPasswords"));
  380. if (authedPasswords) {
  381. authorizedPasswords(authedPasswords, &ctx);
  382. }
  383. Dict* ifaces = Dict_getDict(config, String_CONST("interfaces"));
  384. udpInterface(ifaces, &ctx);
  385. #ifdef HAS_ETH_INTERFACE
  386. ethInterface(ifaces, &ctx);
  387. #endif
  388. Dict* routerConf = Dict_getDict(config, String_CONST("router"));
  389. routerConfig(routerConf, tempAlloc, &ctx);
  390. List* securityList = Dict_getList(config, String_CONST("security"));
  391. security(securityList, tempAlloc, &ctx);
  392. Dict* dnsConf = Dict_getDict(config, String_CONST("dns"));
  393. dns(dnsConf, &ctx, eh);
  394. Allocator_free(tempAlloc);
  395. }