update.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. /*
  2. * update.c -- part of update.mod
  3. *
  4. */
  5. #define MODULE_NAME "update"
  6. #define MAKING_update
  7. #include "src/mod/module.h"
  8. #include <netinet/in.h>
  9. #include <arpa/inet.h>
  10. #include <sys/stat.h>
  11. #include <pwd.h>
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #include <unistd.h>
  15. #include "transfer.mod/transfer.h"
  16. #include "compress.mod/compress.h"
  17. static Function *global = NULL, *transfer_funcs = NULL, *compress_funcs = NULL,
  18. *uncompress_funcs = NULL;
  19. /* Prototypes */
  20. static void start_sending_binary(int);
  21. static void cancel_user_xfer(int, void *);
  22. #include "update.h"
  23. #ifdef HUB
  24. int bupdating = 0;
  25. #endif /* HUB */
  26. #ifdef LEAF
  27. int updated = 0;
  28. #endif /* LEAF */
  29. /*
  30. * Botnet commands
  31. */
  32. static void update_ufno(int idx, char *par)
  33. {
  34. putlog(LOG_BOTS, "*", "binary file rejected by %s: %s",
  35. dcc[idx].nick, par);
  36. dcc[idx].status &= ~STAT_OFFEREDU;
  37. }
  38. static void update_ufyes(int idx, char *par)
  39. {
  40. if (dcc[idx].status & STAT_OFFEREDU) {
  41. start_sending_binary(idx);
  42. }
  43. }
  44. static void update_fileq(int idx, char *par)
  45. {
  46. if (dcc[idx].status & STAT_GETTINGU) return;
  47. #ifdef LEAF
  48. if (updated) return;
  49. if (localhub) {
  50. #else
  51. if (!isupdatehub()) {
  52. #endif /* LEAF */
  53. dprintf(idx, "sb uy\n");
  54. } else if (isupdatehub()) {
  55. dprintf(idx, "sb un I am the update hub, NOT YOU.\n");
  56. }
  57. }
  58. /* us <ip> <port> <length>
  59. */
  60. static void update_ufsend(int idx, char *par)
  61. {
  62. char *ip=NULL, *port;
  63. char s[1024];
  64. int i, sock;
  65. FILE *f;
  66. putlog(LOG_BOTS, "*", "Downloading updated binary from %s", dcc[idx].nick);
  67. #ifdef HUB
  68. egg_snprintf(s, sizeof s, "%s.update.%s.hub", tempdir, botnetnick);
  69. #else
  70. egg_snprintf(s, sizeof s, "%s.update.%s.leaf", tempdir, botnetnick);
  71. #endif
  72. unlink(s); //make sure there isnt already a new binary here..
  73. if (dcc_total == max_dcc) {
  74. putlog(LOG_MISC, "*", "NO MORE DCC CONNECTIONS -- can't grab new binary");
  75. dprintf(idx, "sb e I can't open a DCC to you; I'm full.\n");
  76. zapfbot(idx);
  77. } else if (!(f = fopen(s, "wb"))) {
  78. putlog(LOG_MISC, "*", "CAN'T WRITE BINARY DOWNLOAD FILE!");
  79. zapfbot(idx);
  80. } else {
  81. ip = newsplit(&par);
  82. port = newsplit(&par);
  83. #ifdef USE_IPV6
  84. sock = getsock(SOCK_BINARY, hostprotocol(ip)); /* Don't buffer this -> mark binary. */
  85. #else
  86. sock = getsock(SOCK_BINARY); /* Don't buffer this -> mark binary. */
  87. #endif /* USE_IPV6 */
  88. if (sock < 0 || open_telnet_dcc(sock, ip, port) < 0) {
  89. killsock(sock);
  90. putlog(LOG_BOTS, "*", "Asynchronous connection failed!");
  91. dprintf(idx, "sb e Can't connect to you!\n");
  92. zapfbot(idx);
  93. } else {
  94. putlog(LOG_DEBUG, "*", "Connecting to %s:%s for new binary.", ip, port);
  95. i = new_dcc(&DCC_FORK_SEND, sizeof(struct xfer_info));
  96. dcc[i].addr = my_atoul(ip);
  97. dcc[i].port = atoi(port);
  98. strcpy(dcc[i].nick, "*binary");
  99. dcc[i].u.xfer->filename = nmalloc(strlen(s) + 1);
  100. strcpy(dcc[i].u.xfer->filename, s);
  101. dcc[i].u.xfer->origname = dcc[i].u.xfer->filename;
  102. dcc[i].u.xfer->length = atoi(par);
  103. dcc[i].u.xfer->f = f;
  104. dcc[i].sock = sock;
  105. strcpy(dcc[i].host, dcc[idx].nick);
  106. dcc[idx].status |= STAT_GETTINGU;
  107. }
  108. }
  109. }
  110. static void update_version(int idx, char *par)
  111. {
  112. /* Cleanup any share flags */
  113. #ifdef HUB
  114. if (bupdating) return;
  115. dcc[idx].status &= ~(STAT_GETTINGU | STAT_SENDINGU | STAT_OFFEREDU);
  116. if ((dcc[idx].u.bot->bts < buildts) && (isupdatehub())) {
  117. dprintf(idx, "sb u?\n");
  118. dcc[idx].status |= STAT_OFFEREDU;
  119. }
  120. #endif
  121. }
  122. /* Note: these MUST be sorted. */
  123. static botcmd_t C_update[] =
  124. {
  125. {"u?", (Function) update_fileq},
  126. {"un", (Function) update_ufno},
  127. {"us", (Function) update_ufsend},
  128. {"uy", (Function) update_ufyes},
  129. {"v", (Function) update_version},
  130. {NULL, NULL}
  131. };
  132. static void got_nu(char *botnick, char *code, char *par)
  133. {
  134. /* needupdate? curver */
  135. time_t newts;
  136. #ifdef LEAF
  137. tand_t *bot;
  138. struct bot_addr *bi,
  139. *obi;
  140. struct userrec *u1;
  141. bot = tandbot;
  142. if (!strcmp(bot->bot, botnick)) //dont listen to our uplink.. use normal upate system..
  143. return;
  144. if (!localhub)
  145. return;
  146. if (localhub && updated)
  147. return;
  148. #endif /* LEAF */
  149. if (!par[0]) return;
  150. newts = atoi(newsplit(&par));
  151. if (newts > buildts) {
  152. #ifdef LEAF
  153. u1 = get_user_by_handle(userlist, botnetnick);
  154. obi = get_user(&USERENTRY_BOTADDR, u1);
  155. bi = user_malloc(sizeof(struct bot_addr));
  156. bi->uplink = user_malloc(strlen(botnick) + 1);
  157. strcpy(bi->uplink, botnick);
  158. bi->address = user_malloc(strlen(obi->address) + 1);
  159. strcpy(bi->address, obi->address);
  160. bi->telnet_port = obi->telnet_port;
  161. bi->relay_port = obi->relay_port;
  162. bi->hublevel = obi->hublevel;
  163. set_user(&USERENTRY_BOTADDR, u1, bi);
  164. /* Change our uplink to them */
  165. //let cont_link restructure us..
  166. putlog(LOG_MISC, "*", "Changed uplink to %s for update.", botnick);
  167. botunlink(-2, bot->bot, "Restructure for update.");
  168. usleep(1000 * 500);
  169. botlink("", -3, botnick);
  170. #else
  171. putlog(LOG_MISC, "*", "I need to be updated with %lu", newts);
  172. #endif /* LEAF */
  173. }
  174. }
  175. static cmd_t update_bot[] = {
  176. {"nu?", "", (Function) got_nu, NULL}, //need update?
  177. {0, 0, 0, 0}
  178. };
  179. static void updatein_mod(int idx, char *msg)
  180. {
  181. char *code;
  182. int f, i;
  183. code = newsplit(&msg);
  184. for (f = 0, i = 0; C_update[i].name && !f; i++) {
  185. int y = egg_strcasecmp(code, C_update[i].name);
  186. if (!y)
  187. /* Found a match */
  188. (C_update[i].func)(idx, msg);
  189. if (y < 0)
  190. f = 1;
  191. }
  192. }
  193. static void finish_update(int idx)
  194. {
  195. //module_entry *me;
  196. struct passwd *pw;
  197. uid_t id;
  198. char buf[1024];
  199. char *buf2;
  200. int i, j = -1;
  201. id = geteuid();
  202. pw = getpwuid(id);
  203. for (i = 0; i < dcc_total; i++)
  204. if (!egg_strcasecmp(dcc[i].nick, dcc[idx].host) &&
  205. (dcc[i].type->flags & DCT_BOT))
  206. j = i;
  207. if (j == -1)
  208. return;
  209. /* NO
  210. ic = 0;
  211. next:;
  212. ic++;
  213. if (ic > 5) {
  214. putlog(LOG_MISC, "*", "COULD NOT UNCOMPRESS BINARY");
  215. return;
  216. }
  217. result = 0;
  218. result = is_compressedfile(dcc[idx].u.xfer->filename);
  219. if (result == COMPF_COMPRESSED) {
  220. uncompress_file(dcc[idx].u.xfer->filename);
  221. usleep(1000 * 500);
  222. result = is_compressedfile(dcc[idx].u.xfer->filename);
  223. if (result == COMPF_COMPRESSED)
  224. goto next;
  225. }
  226. */
  227. sprintf(buf, "%s%s", pw->pw_dir, strrchr(dcc[idx].u.xfer->filename, '/'));
  228. movefile(dcc[idx].u.xfer->filename, buf);
  229. chmod(buf, S_IRUSR | S_IWUSR | S_IXUSR);
  230. sprintf(buf, "%s", strrchr(buf, '/'));
  231. buf2 = buf;
  232. buf2++;
  233. putlog(LOG_MISC, "*", "Updating with binary: %s", buf2);
  234. Context;
  235. if (updatebin(0, buf2, 1))
  236. putlog(LOG_MISC, "*", "Failed to update to new binary..");
  237. #ifdef LEAF
  238. else
  239. updated = 1;
  240. #endif
  241. }
  242. static void start_sending_binary(int idx)
  243. {
  244. //module_entry *me;
  245. #ifdef HUB
  246. char update_file[1024];
  247. char buf2[1024], buf3[1024];
  248. struct stat sb;
  249. int i = 1;
  250. dcc[idx].status &= ~STAT_OFFEREDU;
  251. if (bupdating) return;
  252. bupdating = 1;
  253. dcc[idx].status |= STAT_SENDINGU;
  254. putlog(LOG_BOTS, "*", "Sending binary send request to %s",dcc[idx].nick);
  255. if (!strcmp("*", dcc[idx].u.bot->sysname)) {
  256. putlog(LOG_MISC, "*", "Cannot update \002%s\002 automatically, uname not returning os name.", dcc[idx].nick);
  257. return;
  258. }
  259. if (bot_hublevel(dcc[idx].user) == 999) { //send them the leaf binary..
  260. sprintf(buf2, "leaf");
  261. } else {
  262. sprintf(buf2, "hub");
  263. }
  264. sprintf(update_file, "%s.%s.%d", buf2,dcc[idx].u.bot->sysname, egg_numver);
  265. if (stat(update_file, &sb)) {
  266. putlog(LOG_MISC, "*", "Need to update \002%s\002 with %s, but it cannot be accessed", dcc[idx].nick, update_file);
  267. return;
  268. }
  269. sprintf(buf3, "%s.%s", tempdir, update_file);
  270. unlink(buf3);
  271. copyfile(update_file, buf3);
  272. /* NO
  273. ic = 0;
  274. next:;
  275. ic++;
  276. if (ic > 5) {
  277. putlog(LOG_MISC, "*", "COULD NOT COMPRESS BINARY");
  278. goto end;
  279. }
  280. result = 0;
  281. result = is_compressedfile(buf3);
  282. if (result == COMPF_UNCOMPRESSED) {
  283. compress_file(buf3, 9);
  284. usleep(1000 * 500);
  285. }
  286. result = is_compressedfile(buf3);
  287. if (result == COMPF_UNCOMPRESSED)
  288. goto next;
  289. end:;
  290. */
  291. if ((i = raw_dcc_send(buf3, "*binary", "(binary)", buf3)) > 0) {
  292. putlog(LOG_BOTS, "*", "%s -- can't send new binary",
  293. i == DCCSEND_FULL ? "NO MORE DCC CONNECTIONS" :
  294. i == DCCSEND_NOSOCK ? "CAN'T OPEN A LISTENING SOCKET" :
  295. i == DCCSEND_BADFN ? "BAD FILE" :
  296. i == DCCSEND_FEMPTY ? "EMPTY FILE" : "UNKNOWN REASON!");
  297. dcc[idx].status &= ~(STAT_SENDINGU);
  298. } else {
  299. dcc[idx].status |= STAT_SENDINGU;
  300. i = dcc_total - 1;
  301. strcpy(dcc[i].host, dcc[idx].nick); /* Store bot's nick */
  302. dprintf(idx, "sb us %lu %d %lu\n",
  303. iptolong(natip[0] ? (IP) inet_addr(natip) : getmyip()),
  304. dcc[i].port, dcc[i].u.xfer->length);
  305. }
  306. #endif
  307. }
  308. static void (*def_dcc_bot_kill) (int, void *) = 0;
  309. static void cancel_user_xfer(int idx, void *x)
  310. {
  311. int i, j, k = 0;
  312. if (idx < 0) {
  313. idx = -idx;
  314. k = 1;
  315. updatebot(-1, dcc[idx].nick, '-', 0);
  316. }
  317. if (dcc[idx].status & STAT_SHARE) {
  318. if (dcc[idx].status & STAT_GETTINGU) {
  319. j = 0;
  320. for (i = 0; i < dcc_total; i++)
  321. if (!egg_strcasecmp(dcc[i].host, dcc[idx].nick) &&
  322. ((dcc[i].type->flags & (DCT_FILETRAN | DCT_FILESEND)) ==
  323. (DCT_FILETRAN | DCT_FILESEND)))
  324. j = i;
  325. if (j != 0) {
  326. killsock(dcc[j].sock);
  327. unlink(dcc[j].u.xfer->filename);
  328. lostdcc(j);
  329. }
  330. putlog(LOG_BOTS, "*", "(Userlist download aborted.)");
  331. }
  332. if (dcc[idx].status & STAT_SENDINGU) {
  333. j = 0;
  334. for (i = 0; i < dcc_total; i++)
  335. if ((!egg_strcasecmp(dcc[i].host, dcc[idx].nick)) &&
  336. ((dcc[i].type->flags & (DCT_FILETRAN | DCT_FILESEND))
  337. == DCT_FILETRAN))
  338. j = i;
  339. if (j != 0) {
  340. killsock(dcc[j].sock);
  341. unlink(dcc[j].u.xfer->filename);
  342. lostdcc(j);
  343. }
  344. putlog(LOG_BOTS, "*", "(Userlist transmit aborted.)");
  345. }
  346. }
  347. if (!k)
  348. def_dcc_bot_kill(idx, x);
  349. }
  350. #ifdef HUB
  351. int cnt = 0;
  352. static void check_updates()
  353. {
  354. int i;
  355. char buf[1024];
  356. if (!isupdatehub()) return;
  357. cnt++;
  358. if ((cnt > 5) && bupdating) bupdating = 0; //2 minutes should be plenty.
  359. if (bupdating) return;
  360. cnt = 0;
  361. for (i = 0; i < dcc_total; i++) {
  362. if (dcc[i].type->flags & DCT_BOT && (dcc[i].status & STAT_SHARE) &&
  363. !(dcc[i].status & STAT_SENDINGU) && !(dcc[i].status & STAT_OFFEREDU) &&
  364. !(dcc[i].status & STAT_UPDATED)) { //only offer binary to bots that are sharing
  365. dcc[i].status &= ~(STAT_GETTINGU | STAT_SENDINGU |
  366. STAT_OFFEREDU);
  367. if ((dcc[i].u.bot->bts < buildts) && (isupdatehub())) {
  368. dprintf(i, "sb u?\n");
  369. dcc[i].status |= STAT_OFFEREDU;
  370. }
  371. }
  372. }
  373. //send out notice to update remote bots ...
  374. sprintf(buf, "nu? %lu", buildts);
  375. putallbots(buf);
  376. }
  377. #endif
  378. static int update_expmem()
  379. {
  380. int tot = 0;
  381. return tot;
  382. }
  383. static void update_report(int idx, int details)
  384. {
  385. int i, j;
  386. if (details) {
  387. dprintf(idx, " update module, using %d bytes.\n", update_expmem());
  388. for (i = 0; i < dcc_total; i++)
  389. if (dcc[i].type == &DCC_BOT) {
  390. if (dcc[i].status & STAT_GETTINGU) {
  391. int ok = 0;
  392. for (j = 0; j < dcc_total; j++)
  393. if (((dcc[j].type->flags & (DCT_FILETRAN | DCT_FILESEND))
  394. == (DCT_FILETRAN | DCT_FILESEND)) &&
  395. !egg_strcasecmp(dcc[j].host, dcc[i].nick)) {
  396. dprintf(idx, "Downloading binary from %s (%d%% done)\n",
  397. dcc[i].nick,
  398. (int) (100.0 * ((float) dcc[j].status) /
  399. ((float) dcc[j].u.xfer->length)));
  400. ok = 1;
  401. break;
  402. }
  403. if (!ok)
  404. dprintf(idx, "Download binary from %s (negotiating "
  405. "botentries)\n", dcc[i].nick);
  406. } else if (dcc[i].status & STAT_SENDINGU) {
  407. for (j = 0; j < dcc_total; j++) {
  408. if (((dcc[j].type->flags & (DCT_FILETRAN | DCT_FILESEND))
  409. == DCT_FILETRAN)
  410. && !egg_strcasecmp(dcc[j].host, dcc[i].nick)) {
  411. if (dcc[j].type == &DCC_GET)
  412. dprintf(idx, "Sending binary to %s (%d%% done)\n",
  413. dcc[i].nick,
  414. (int) (100.0 * ((float) dcc[j].status) /
  415. ((float) dcc[j].u.xfer->length)));
  416. else
  417. dprintf(idx,
  418. "Sending binary to %s (waiting for connect)\n",
  419. dcc[i].nick);
  420. }
  421. }
  422. }
  423. }
  424. }
  425. }
  426. EXPORT_SCOPE char *update_start();
  427. static Function update_table[] =
  428. {
  429. /* 0 - 3 */
  430. (Function) update_start,
  431. (Function) NULL,
  432. (Function) update_expmem,
  433. (Function) update_report,
  434. /* 4 - 7 */
  435. (Function) finish_update,
  436. #ifdef HUB
  437. (Function) & bupdating
  438. #else
  439. (Function) 0
  440. #endif /* HUB */
  441. };
  442. char *update_start(Function *global_funcs)
  443. {
  444. global = global_funcs;
  445. module_register(MODULE_NAME, update_table, 2, 3);
  446. if (!(transfer_funcs = module_depend(MODULE_NAME, "transfer", 2, 0))) {
  447. module_undepend(MODULE_NAME);
  448. return "This module requires transfer module 2.0 or later.";
  449. }
  450. if (!(compress_funcs = module_depend(MODULE_NAME, "compress", 0, 0))) {
  451. module_undepend(MODULE_NAME);
  452. return "This module requires the compression.";
  453. }
  454. if (!(uncompress_funcs = module_depend(MODULE_NAME, "compress", 0, 0))) {
  455. module_undepend(MODULE_NAME);
  456. return "This module requires the compression.";
  457. }
  458. add_builtins(H_bot, update_bot);
  459. #ifdef HUB
  460. add_hook(HOOK_30SECONDLY, (Function) check_updates);
  461. #endif
  462. add_hook(HOOK_SHAREUPDATEIN, (Function) updatein_mod);
  463. def_dcc_bot_kill = DCC_BOT.kill;
  464. DCC_BOT.kill = cancel_user_xfer;
  465. return NULL;
  466. }