binary.cc 25 KB

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