binary.c 24 KB

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