binary.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  1. /* I hereby release this into the Public Domain - Bryan Drewery */
  2. /*
  3. * binary.c -- handles:
  4. * misc update functions
  5. * md5 hash verifying
  6. *
  7. */
  8. #include "common.h"
  9. #include "binary.h"
  10. #include "settings.h"
  11. #include "crypt.h"
  12. #include "shell.h"
  13. #include "misc.h"
  14. #include "main.h"
  15. #include "misc_file.h"
  16. #include "tandem.h"
  17. #include "botnet.h"
  18. #include "userrec.h"
  19. #include <sys/wait.h>
  20. #include <sys/types.h>
  21. #include <sys/mman.h>
  22. #include <signal.h>
  23. #include <sys/stat.h>
  24. #include <fcntl.h>
  25. #include <termios.h>
  26. settings_t settings = {
  27. SETTINGS_HEADER,
  28. /* -- STATIC -- */
  29. "", "", "", "", "", "", "", "", "", "",
  30. /* -- DYNAMIC -- */
  31. "", "", "", "", "", "", "", "", "", "", "",
  32. /* -- PADDING */
  33. ""
  34. };
  35. static void edpack(settings_t *, const char *, int);
  36. #ifdef DEBUG
  37. static void tellconfig(settings_t *);
  38. #endif
  39. #define PACK_ENC 1
  40. #define PACK_DEC 2
  41. int checked_bin_buf = 0;
  42. #define MMAP_LOOP(_offset, _block_len, _total, _len) \
  43. for ((_offset) = 0; \
  44. (_offset) < (_total); \
  45. (_offset) += (_block_len), \
  46. (_len) = ((_total) - (_offset)) < (_block_len) ? \
  47. ((_total) - (_offset)) : \
  48. (_block_len) \
  49. )
  50. #define MMAP_READ(_map, _dest, _offset, _len) \
  51. memcpy((_dest), &(_map)[(_offset)], (_len)); \
  52. (_offset) += (_len);
  53. static char *
  54. bin_checksum(const char *fname, int todo)
  55. {
  56. MD5_CTX ctx;
  57. static char hash[MD5_HASH_LENGTH + 1] = "";
  58. unsigned char md5out[MD5_HASH_LENGTH + 1] = "", buf[PREFIXLEN + 1] = "";
  59. int fd = -1;
  60. size_t len = 0, offset = 0, size = 0, newpos = 0;
  61. unsigned char *map = NULL, *outmap = NULL;
  62. char *fname_bak = NULL;
  63. Tempfile *newbin = NULL;
  64. MD5_Init(&ctx);
  65. ++checked_bin_buf;
  66. hash[0] = 0;
  67. fixmod(fname);
  68. if (todo == GET_CHECKSUM) {
  69. fd = open(fname, O_RDONLY);
  70. if (fd == -1) werr(ERR_BINSTAT);
  71. size = lseek(fd, 0, SEEK_END);
  72. map = (unsigned char*) mmap(0, size, PROT_READ, MAP_SHARED, fd, 0);
  73. if ((void*)map == MAP_FAILED) goto fatal;
  74. MMAP_LOOP(offset, sizeof(buf) - 1, size, len) {
  75. if (!memcmp(&map[offset], &settings.prefix, PREFIXLEN))
  76. break;
  77. }
  78. MD5_Update(&ctx, map, offset);
  79. /* Hash everything after the packdata too */
  80. offset += sizeof(settings_t);
  81. MD5_Update(&ctx, &map[offset], size - offset);
  82. MD5_Final(md5out, &ctx);
  83. btoh(md5out, MD5_DIGEST_LENGTH, hash, sizeof(hash));
  84. OPENSSL_cleanse(&ctx, sizeof(ctx));
  85. munmap(map, size);
  86. close(fd);
  87. }
  88. if (todo == GET_CONF) {
  89. fd = open(fname, O_RDONLY);
  90. if (fd == -1) werr(ERR_BINSTAT);
  91. size = lseek(fd, 0, SEEK_END);
  92. map = (unsigned char*) mmap(0, size, PROT_READ, MAP_SHARED, fd, 0);
  93. if ((void*)map == MAP_FAILED) goto fatal;
  94. /* Find the packdata */
  95. MMAP_LOOP(offset, sizeof(buf) - 1, size, len) {
  96. if (!memcmp(&map[offset], &settings.prefix, PREFIXLEN))
  97. break;
  98. }
  99. MD5_Update(&ctx, map, offset);
  100. /* Hash everything after the packdata too */
  101. MD5_Update(&ctx, &map[offset + sizeof(settings_t)], size - (offset + sizeof(settings_t)));
  102. MD5_Final(md5out, &ctx);
  103. btoh(md5out, MD5_DIGEST_LENGTH, hash, sizeof(hash));
  104. OPENSSL_cleanse(&ctx, sizeof(ctx));
  105. settings_t newsettings;
  106. /* Read the settings struct into newsettings */
  107. MMAP_READ(map, &newsettings, offset, sizeof(settings));
  108. /* Decrypt the new data */
  109. edpack(&newsettings, hash, PACK_DEC);
  110. OPENSSL_cleanse(hash, sizeof(hash));
  111. /* Copy over only the dynamic data, leaving the pack config static */
  112. memcpy(&settings.bots, &newsettings.bots, SIZE_CONF);
  113. OPENSSL_cleanse(&newsettings, sizeof(settings_t));
  114. munmap(map, size);
  115. close(fd);
  116. return ".";
  117. }
  118. if (todo & WRITE_CHECKSUM) {
  119. newbin = new Tempfile("bin", 0);
  120. size = strlen(fname) + 2;
  121. fname_bak = (char *) my_calloc(1, size);
  122. simple_snprintf(fname_bak, size, "%s~", fname);
  123. fd = open(fname, O_RDONLY);
  124. if (fd == -1) werr(ERR_BINSTAT);
  125. size = lseek(fd, 0, SEEK_END);
  126. map = (unsigned char*) mmap(0, size, PROT_READ, MAP_SHARED, fd, 0);
  127. if ((void*)map == MAP_FAILED) goto fatal;
  128. /* Find settings struct in original binary */
  129. MMAP_LOOP(offset, sizeof(buf) - 1, size, len) {
  130. if (!memcmp(&map[offset], &settings.prefix, PREFIXLEN))
  131. break;
  132. }
  133. MD5_Update(&ctx, map, offset);
  134. /* Hash everything after the packdata too */
  135. MD5_Update(&ctx, &map[offset + sizeof(settings_t)], size - (offset + sizeof(settings_t)));
  136. MD5_Final(md5out, &ctx);
  137. btoh(md5out, MD5_DIGEST_LENGTH, hash, sizeof(hash));
  138. OPENSSL_cleanse(&ctx, sizeof(ctx));
  139. strlcpy(settings.hash, hash, sizeof(settings.hash));
  140. /* encrypt the entire struct with the hash (including hash) */
  141. edpack(&settings, hash, PACK_ENC);
  142. //Don't clear hash if requested during the write.
  143. if (!(todo & GET_CHECKSUM))
  144. OPENSSL_cleanse(hash, sizeof(hash));
  145. /* Copy everything up to this point into the new binary (including the settings header/prefix) */
  146. outmap = (unsigned char*) mmap(0, size, PROT_WRITE, MAP_SHARED, newbin->fd, 0);
  147. if ((void*)outmap == MAP_FAILED) goto fatal;
  148. if (lseek(newbin->fd, size - 1, SEEK_SET) == -1) goto fatal;
  149. if (write(newbin->fd, "", 1) != 1) goto fatal;
  150. offset += PREFIXLEN;
  151. memcpy(outmap, map, offset);
  152. newpos = offset;
  153. if (todo & WRITE_PACK) {
  154. /* Now copy in our encrypted settings struct */
  155. memcpy(&outmap[newpos], &settings.hash, SIZE_PACK);
  156. #ifdef DEBUG
  157. sdprintf(STR("writing pack: %d\n"), SIZE_PACK);
  158. #endif
  159. } else {
  160. /* Just copy the original pack data to the new binary */
  161. memcpy(&outmap[newpos], &map[offset], SIZE_PACK);
  162. }
  163. offset += SIZE_PACK;
  164. newpos += SIZE_PACK;
  165. if (todo & WRITE_CONF) {
  166. /* Copy in the encrypted conf data */
  167. memcpy(&outmap[newpos], &settings.bots, SIZE_CONF);
  168. #ifdef DEBUG
  169. sdprintf(STR("writing conf: %d\n"), SIZE_CONF);
  170. #endif
  171. } else {
  172. /* Just copy the original conf data to the new binary */
  173. memcpy(&outmap[newpos], &map[offset], SIZE_CONF);
  174. }
  175. newpos += SIZE_CONF;
  176. offset += SIZE_CONF;
  177. /* Write the rest of the binary */
  178. memcpy(&outmap[newpos], &map[offset], size - offset);
  179. newpos += size - offset;
  180. offset += size - offset;
  181. munmap(map, size);
  182. close(fd);
  183. munmap(outmap, size);
  184. newbin->my_close();
  185. if (size != newpos) {
  186. delete newbin;
  187. fatal(STR("Binary corrupted"), 0);
  188. }
  189. if (movefile(fname, fname_bak)) {
  190. printf(STR("Failed to move file (%s -> %s): %s\n"), fname, fname_bak, strerror(errno));
  191. delete newbin;
  192. fatal("", 0);
  193. }
  194. if (movefile(newbin->file, fname)) {
  195. printf(STR("Failed to move file (%s -> %s): %s\n"), newbin->file, fname, strerror(errno));
  196. delete newbin;
  197. fatal("", 0);
  198. }
  199. fixmod(fname);
  200. unlink(fname_bak);
  201. delete newbin;
  202. return hash;
  203. fatal:
  204. if ((void*)map != MAP_FAILED)
  205. munmap(map, size);
  206. if (fd != -1)
  207. close(fd);
  208. if ((void*)outmap != MAP_FAILED)
  209. munmap(outmap, size);
  210. delete newbin;
  211. werr(ERR_BINSTAT);
  212. }
  213. return hash;
  214. }
  215. static int
  216. features_find(const char *buffer)
  217. {
  218. if (!strcasecmp(buffer, STR("no_take")))
  219. return FEATURE_NO_TAKE;
  220. else if (!strcasecmp(buffer, STR("no_mdop")))
  221. return FEATURE_NO_MDOP;
  222. return 0;
  223. }
  224. /* It is desirable to use this bit on systems that have it.
  225. The only bit of terminal state we want to twiddle is echoing, which is
  226. done in software; there is no need to change the state of the terminal
  227. hardware. */
  228. #ifndef TCSASOFT
  229. # define TCSASOFT 0
  230. #endif
  231. typedef struct line_list {
  232. struct line_list* next;
  233. int line;
  234. } line_list_t;
  235. static int
  236. readcfg(const char *cfgfile, bool read_stdin)
  237. {
  238. FILE *f = NULL;
  239. struct termios s, t;
  240. bool tty_changed = false;
  241. line_list_t *error_list = NULL, *error_line = NULL;
  242. if (read_stdin) {
  243. f = stdin;
  244. setbuf(stdin, NULL);
  245. setbuf(stdout, NULL);
  246. /* Taken from libc: getpass.c */
  247. /* Turn echoing off if it is on now. */
  248. if (tcgetattr (fileno (stdin), &t) == 0) {
  249. s = t;
  250. t.c_lflag &= ~(ECHO | ISIG);
  251. tty_changed = (tcsetattr (fileno (stdin), TCSAFLUSH | TCSASOFT, &t) == 0);
  252. }
  253. printf(STR("// Paste in your PACKCONFIG. Reference http://wraith.botpack.net/wiki/PackConfig\n"));
  254. printf(STR("// Press <enter> if it gets hung up. If that doesn't work hit ^D (CTRL+d)\n"));
  255. fflush(stdout);
  256. } else {
  257. if ((f = fopen(cfgfile, "r")) == NULL) {
  258. fprintf(stderr, STR("Error: Can't open '%s' for reading\n"), cfgfile);
  259. exit(1);
  260. }
  261. }
  262. char *buffer = NULL, *p = NULL;
  263. int skip = 0, line = 0, feature = 0;
  264. bool error = 0;
  265. #define ADD_ERROR \
  266. error_line = (line_list_t *) my_calloc(1, sizeof(line_list_t)); \
  267. error_line->line = line; \
  268. error_line->next = NULL; \
  269. list_append((struct list_type **) &(error_list), (struct list_type *) error_line); \
  270. error = 1;
  271. settings.salt1[0] = settings.salt2[0] = 0;
  272. if (!read_stdin)
  273. printf(STR("Reading '%s' "), cfgfile);
  274. while ((!feof(f)) && ((buffer = step_thru_file(f)) != NULL)) {
  275. if (tty_changed) {
  276. printf(".");
  277. fflush(stdout);
  278. }
  279. ++line;
  280. if ((*buffer)) {
  281. if (strchr(buffer, '\n'))
  282. *(char *) strchr(buffer, '\n') = 0;
  283. if ((skipline(buffer, &skip)))
  284. continue;
  285. if ((strchr(buffer, '<') || strchr(buffer, '>')) && !strstr(buffer, "SALT")) {
  286. ADD_ERROR
  287. }
  288. p = strchr(buffer, ' ');
  289. while (p && (strchr(LISTSEPERATORS, p[0])))
  290. *p++ = 0;
  291. if (p) {
  292. size_t p_len = strlen(trim(p));
  293. if (!strcasecmp(buffer, STR("packname"))) {
  294. strlcpy(settings.packname, trim(p), sizeof settings.packname);
  295. } else if (!strcasecmp(buffer, STR("shellhash"))) {
  296. if (p_len != 40 && p_len != 47) {
  297. fprintf(stderr, STR("\nSHELLHASH should be a SHA1 hash or salted-SHA1 hash.\n"));
  298. ADD_ERROR
  299. }
  300. strlcpy(settings.shellhash, trim(p), sizeof settings.shellhash);
  301. } else if (!strcasecmp(buffer, STR("dccprefix"))) {
  302. strlcpy(settings.dcc_prefix, trim(p), 2);
  303. } else if (!strcasecmp(buffer, STR("owner"))) {
  304. strlcat(settings.owners, trim(p), sizeof(settings.owners));
  305. strlcat(settings.owners, ",", sizeof(settings.owners));
  306. } else if (!strcasecmp(buffer, STR("owneremail"))) {
  307. strlcat(settings.owneremail, trim(p), sizeof(settings.owneremail));
  308. strlcat(settings.owneremail, ",", sizeof(settings.owneremail));
  309. } else if (!strcasecmp(buffer, STR("hub"))) {
  310. strlcat(settings.hubs, trim(p), sizeof(settings.hubs));
  311. strlcat(settings.hubs, ",", sizeof(settings.hubs));
  312. } else if (!strcasecmp(buffer, STR("salt1"))) {
  313. strlcat(settings.salt1, trim(p), sizeof(settings.salt1));
  314. } else if (!strcasecmp(buffer, STR("salt2"))) {
  315. strlcat(settings.salt2, trim(p), sizeof(settings.salt2));
  316. if (read_stdin) break;
  317. }
  318. } else { /* SINGLE DIRECTIVES */
  319. if ((feature = features_find(buffer))) {
  320. int features = atol(settings.features);
  321. features |= feature;
  322. simple_snprintf(settings.features, sizeof(settings.features), "%d", features);
  323. }
  324. }
  325. }
  326. buffer = NULL;
  327. }
  328. if (f && !read_stdin) {
  329. fclose(f);
  330. } else if (read_stdin && tty_changed) {
  331. /* Restore the original setting. */
  332. tcsetattr (fileno (stdin), TCSAFLUSH | TCSASOFT, &s);
  333. }
  334. if (error) {
  335. printf("\n");
  336. fprintf(stderr, STR("Error: Look at your configuration again and remove any <>\n"));
  337. for (error_line = error_list; error_line; error_line = error_line->next)
  338. fprintf(stderr, STR("Line %d\n"), error_line->line);
  339. exit(1);
  340. }
  341. /* Was the entire pack read in? */
  342. if (!settings.salt1[0] || !settings.salt2[0]) {
  343. printf("\n");
  344. fprintf(stderr, STR("Missing SALTS\n"));
  345. exit(1);
  346. }
  347. if (!read_stdin) printf(STR(" Success\n"));
  348. else printf("\n");
  349. return 1;
  350. }
  351. static void edpack(settings_t *incfg, const char *in_hash, int what)
  352. {
  353. char *tmp = NULL, *hash = (char *) in_hash, nhash[51] = "";
  354. unsigned char *(*enc_dec_string)(const char *, unsigned char *, size_t *);
  355. size_t len = 0;
  356. if (what == PACK_ENC)
  357. enc_dec_string = aes_encrypt_ecb_binary;
  358. else
  359. enc_dec_string = aes_decrypt_ecb_binary;
  360. #define dofield(_field) do { \
  361. if (_field) { \
  362. len = sizeof(_field) - 1; \
  363. tmp = (char *) enc_dec_string(hash, (unsigned char *) _field, &len); \
  364. if (what == PACK_ENC) \
  365. memcpy(_field, tmp, len); \
  366. else \
  367. simple_snprintf(_field, sizeof(_field), "%s", tmp); \
  368. OPENSSL_cleanse(tmp, len); \
  369. free(tmp); \
  370. } \
  371. } while (0)
  372. #define dohash(_field) do { \
  373. if (what == PACK_ENC) \
  374. strlcat(nhash, _field, sizeof(nhash)); \
  375. dofield(_field); \
  376. if (what == PACK_DEC) \
  377. strlcat(nhash, _field, sizeof(nhash)); \
  378. } while (0)
  379. #define update_hash() do { \
  380. MD5(NULL); \
  381. hash = MD5(nhash); \
  382. OPENSSL_cleanse(nhash, sizeof(nhash)); \
  383. nhash[0] = 0; \
  384. } while (0)
  385. /* -- STATIC -- */
  386. dohash(incfg->hash);
  387. dohash(incfg->packname);
  388. update_hash();
  389. dohash(incfg->shellhash);
  390. update_hash();
  391. dofield(incfg->dcc_prefix);
  392. dofield(incfg->features);
  393. dofield(incfg->owners);
  394. dofield(incfg->owneremail);
  395. dofield(incfg->hubs);
  396. dohash(incfg->salt1);
  397. dohash(incfg->salt2);
  398. update_hash();
  399. /* -- DYNAMIC -- */
  400. dofield(incfg->bots);
  401. dofield(incfg->uid);
  402. dofield(incfg->autocron);
  403. dofield(incfg->watcher);
  404. dofield(incfg->username);
  405. dofield(incfg->datadir);
  406. dofield(incfg->homedir);
  407. dofield(incfg->binpath);
  408. dofield(incfg->binname);
  409. dofield(incfg->portmin);
  410. dofield(incfg->portmax);
  411. OPENSSL_cleanse(nhash, sizeof(nhash));
  412. #undef dofield
  413. #undef dohash
  414. #undef update_hash
  415. }
  416. #ifdef DEBUG
  417. static void
  418. tellconfig(settings_t *incfg)
  419. {
  420. #define dofield(_field) printf("%s: %s\n", #_field, _field);
  421. // -- STATIC --
  422. dofield(incfg->hash);
  423. dofield(incfg->packname);
  424. dofield(incfg->shellhash);
  425. dofield(incfg->dcc_prefix);
  426. dofield(incfg->features);
  427. dofield(incfg->owners);
  428. dofield(incfg->owneremail);
  429. dofield(incfg->hubs);
  430. // dofield(incfg->salt1);
  431. // dofield(incfg->salt2);
  432. // -- DYNAMIC --
  433. dofield(incfg->bots);
  434. dofield(incfg->uid);
  435. dofield(incfg->autocron);
  436. dofield(incfg->watcher);
  437. dofield(incfg->username);
  438. dofield(incfg->datadir);
  439. dofield(incfg->homedir);
  440. dofield(incfg->binpath);
  441. dofield(incfg->binname);
  442. dofield(incfg->portmin);
  443. dofield(incfg->portmax);
  444. #undef dofield
  445. }
  446. #endif
  447. void
  448. check_sum(const char *fname, const char *cfgfile, bool read_stdin)
  449. {
  450. if (!settings.hash[0]) {
  451. if (!cfgfile && !read_stdin)
  452. fatal(STR("Binary not initialized."), 0);
  453. readcfg(cfgfile, read_stdin);
  454. // tellconfig(&settings);
  455. if (bin_checksum(fname, WRITE_CHECKSUM|WRITE_CONF|WRITE_PACK))
  456. printf(STR("* Wrote settings to binary.\n"));
  457. exit(0);
  458. } else {
  459. char *hash = bin_checksum(fname, GET_CHECKSUM);
  460. // tellconfig(&settings);
  461. edpack(&settings, hash, PACK_DEC);
  462. INIT_SALTS;
  463. OPENSSL_cleanse(settings.salt1, sizeof(settings.salt1));
  464. OPENSSL_cleanse(settings.salt2, sizeof(settings.salt2));
  465. #ifdef DEBUG
  466. tellconfig(&settings);
  467. #endif
  468. int n = strcmp(settings.hash, hash);
  469. OPENSSL_cleanse(settings.hash, sizeof(settings.hash));
  470. OPENSSL_cleanse(hash, strlen(hash));
  471. if (n) {
  472. OPENSSL_cleanse(&settings, sizeof(settings_t));
  473. CLEAR_SALTS;
  474. }
  475. }
  476. }
  477. bool check_bin_initialized(const char *fname)
  478. {
  479. int i = 0;
  480. size_t len = strlen(shell_escape(fname)) + 3 + 1;
  481. char *path = (char *) my_calloc(1, len);
  482. simple_snprintf(path, len, STR("%s -p"), shell_escape(fname));
  483. i = system(path);
  484. free(path);
  485. if (i != -1 && WEXITSTATUS(i) == 4)
  486. return 1;
  487. return 0;
  488. }
  489. bool check_bin_compat(const char *fname)
  490. {
  491. size_t len = strlen(shell_escape(fname)) + 3 + 1;
  492. char *path = (char *) my_calloc(1, len);
  493. char *out = NULL;
  494. simple_snprintf(path, len, STR("%s -3"), shell_escape(fname));
  495. if (shell_exec(path, NULL, &out, NULL)) {
  496. if (out) {
  497. char *buf = out;
  498. size_t settings_ver = atoi(newsplit(&buf)), settings_len = atoi(newsplit(&buf));
  499. if (settings_ver == SETTINGS_VER && settings_len == sizeof(settings_t)) {
  500. free(path);
  501. free(out);
  502. return 1;
  503. }
  504. free(out);
  505. }
  506. }
  507. free(path);
  508. return 0;
  509. }
  510. void write_settings(const char *fname, int die, bool doconf, int initialized)
  511. {
  512. char *hash = NULL;
  513. int bits = WRITE_CHECKSUM;
  514. /* see if the binary is already initialized or not */
  515. if (initialized == -1)
  516. initialized = check_bin_initialized(fname);
  517. /* only write pack data if the binary is uninitialized
  518. * otherwise, assume it has similar/correct/updated pack data
  519. */
  520. if (!initialized)
  521. bits |= WRITE_PACK;
  522. if (doconf)
  523. bits |= WRITE_CONF;
  524. /* only bother writing anything if we have pack or doconf, checksum is worthless to write out */
  525. if (bits & (WRITE_PACK|WRITE_CONF)) {
  526. // Also get the checksum
  527. if (die == -1)
  528. bits |= GET_CHECKSUM;
  529. const char salt1[] = SALT1;
  530. const char salt2[] = SALT2;
  531. strlcpy(settings.salt1, salt1, sizeof(settings.salt1));
  532. strlcpy(settings.salt2, salt2, sizeof(settings.salt2));
  533. if ((hash = bin_checksum(fname, bits))) {
  534. printf(STR("* Wrote %ssettings to: %s.\n"), ((bits & WRITE_PACK) && !(bits & WRITE_CONF)) ? "pack " :
  535. ((bits & WRITE_CONF) && !(bits & WRITE_PACK)) ? "conf " :
  536. ((bits & WRITE_PACK) && (bits & WRITE_CONF)) ? "pack/conf " :
  537. "",
  538. fname);
  539. if (die == -1) { /* only bother decrypting if we aren't about to exit */
  540. edpack(&settings, hash, PACK_DEC);
  541. INIT_SALTS;
  542. OPENSSL_cleanse(hash, strlen(hash));
  543. }
  544. }
  545. if (die == -1) {
  546. OPENSSL_cleanse(settings.salt1, sizeof(settings.salt1));
  547. OPENSSL_cleanse(settings.salt2, sizeof(settings.salt2));
  548. }
  549. }
  550. if (die >= 0)
  551. exit(die);
  552. }
  553. static void
  554. clear_settings(void)
  555. {
  556. // memset(&settings.bots, 0, sizeof(settings_t) - SIZE_PACK - PREFIXLEN);
  557. memset(&settings.bots, 0, SIZE_CONF);
  558. }
  559. void conf_to_bin(conf_t *in, bool move, int die)
  560. {
  561. conf_bot *bot = NULL;
  562. char *newbin = NULL;
  563. clear_settings();
  564. sdprintf("converting conf to bin\n");
  565. simple_snprintf(settings.uid, sizeof(settings.uid), "%d", in->uid);
  566. simple_snprintf(settings.watcher, sizeof(settings.watcher), "%d", in->watcher);
  567. simple_snprintf(settings.autocron, sizeof(settings.autocron), "%d", in->autocron);
  568. simple_snprintf(settings.portmin, sizeof(settings.portmin), "%d", in->portmin);
  569. simple_snprintf(settings.portmax, sizeof(settings.portmax), "%d", in->portmax);
  570. strlcpy(settings.binname, in->binname, sizeof(settings.binname));
  571. if (in->username)
  572. strlcpy(settings.username, in->username, sizeof(settings.username));
  573. strlcpy(settings.datadir, in->datadir, sizeof(settings.datadir));
  574. if (in->homedir)
  575. strlcpy(settings.homedir, in->homedir, sizeof(settings.homedir));
  576. strlcpy(settings.binpath, in->binpath, sizeof(settings.binpath));
  577. for (bot = in->bots; bot && bot->nick; bot = bot->next) {
  578. simple_snprintf(settings.bots, sizeof(settings.bots), STR("%s%s%s %s %s%s %s,"),
  579. settings.bots && settings.bots[0] ? settings.bots : "",
  580. bot->disabled ? "/" : "",
  581. bot->nick,
  582. bot->net.ip ? bot->net.ip : "*",
  583. bot->net.host6 ? "+" : "",
  584. bot->net.host ? bot->net.host : (bot->net.host6 ? bot->net.host6 : "*"),
  585. bot->net.ip6 ? bot->net.ip6 : "");
  586. }
  587. #ifndef CYGWIN_HACKS
  588. if (move)
  589. newbin = move_bin(in->binpath, in->binname, 0);
  590. else
  591. #endif /* !CYGWIN_HACKS */
  592. newbin = binname;
  593. // tellconfig(&settings);
  594. write_settings(newbin, -1, 1);
  595. if (die >= 0)
  596. exit(die);
  597. }
  598. void reload_bin_data() {
  599. if (bin_checksum(binname, GET_CONF)) {
  600. putlog(LOG_MISC, "*", STR("Rehashed config data from binary."));
  601. conf_bot *oldbots = NULL, *oldbot = NULL;
  602. bool was_localhub = conf.bot->localhub ? 1 : 0;
  603. /* save the old bots list */
  604. if (conf.bots)
  605. oldbots = conf_bots_dup(conf.bots);
  606. /* Save the old conf.bot */
  607. oldbot = (conf_bot *) my_calloc(1, sizeof(conf_bot));
  608. conf_bot_dup(oldbot, conf.bot);
  609. /* free up our current conf struct */
  610. free_conf();
  611. /* Fill conf[] with binary data from settings[] */
  612. bin_to_conf();
  613. /* fill up conf.bot using origbotname */
  614. fill_conf_bot(0); /* 0 to avoid exiting if conf.bot cannot be filled */
  615. if (was_localhub) {
  616. /* add any new bots not in userfile */
  617. conf_add_userlist_bots();
  618. /* deluser removed bots from conf */
  619. if (oldbots)
  620. deluser_removed_bots(oldbots, conf.bots);
  621. }
  622. if (conf.bot && conf.bot->disabled) {
  623. if (tands > 0) {
  624. botnet_send_chat(-1, conf.bot->nick, STR("Bot disabled in binary."));
  625. botnet_send_bye(STR("Bot disabled in binary."));
  626. }
  627. if (server_online)
  628. nuke_server(STR("bbl"));
  629. werr(ERR_BOTDISABLED);
  630. } else if (!conf.bot) {
  631. conf.bot = oldbot;
  632. if (tands > 0) {
  633. botnet_send_chat(-1, conf.bot->nick, STR("Bot removed from binary."));
  634. botnet_send_bye(STR("Bot removed from binary."));
  635. }
  636. if (server_online)
  637. nuke_server(STR("it's been good, cya"));
  638. werr(ERR_BADBOT);
  639. }
  640. /* The bot nick changed! (case) */
  641. if (strcmp(conf.bot->nick, oldbot->nick)) {
  642. change_handle(conf.bot->u, conf.bot->nick);
  643. // var_set_by_name(conf.bot->nick, "nick", conf.bot->nick);
  644. // var_set_userentry(conf.bot->nick, "nick", conf.bot->nick);
  645. }
  646. free_bot(oldbot);
  647. if (oldbots)
  648. free_conf_bots(oldbots);
  649. if (!conf.bot->localhub)
  650. free_conf_bots(conf.bots);
  651. }
  652. }