config.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. /*
  2. * config.c -- handles:
  3. * botnet config
  4. * cmdpass functions
  5. */
  6. #include "main.h"
  7. #include <sys/stat.h>
  8. #include <sys/types.h>
  9. #include <unistd.h>
  10. #include <fcntl.h>
  11. #include "chan.h"
  12. #include "tandem.h"
  13. #include "modules.h"
  14. #include <net/if.h>
  15. /* not needed?
  16. #include <sys/ioctl.h>
  17. #include <signal.h>
  18. */
  19. #include "stat.h"
  20. #include "bg.h"
  21. extern char botnetnick[];
  22. extern struct userrec *userlist;
  23. extern time_t now;
  24. #ifdef S_AUTH
  25. char authkey[121]; /* This is one of the keys used in the auth hash */
  26. #endif /* S_AUTH */
  27. char cmdprefix[1] = "+"; /* This is the prefix for msg/channel cmds */
  28. struct cfg_entry CFG_MOTD = {
  29. "motd", CFGF_GLOBAL, NULL, NULL,
  30. NULL, NULL, NULL
  31. };
  32. #ifdef S_AUTH
  33. void authkey_describe(struct cfg_entry * entry, int idx) {
  34. dprintf(idx, STR("authkey is used for authing, give to your users if they are to use DCC chat or IRC cmds. (can be bot specific)\n"));
  35. }
  36. void authkey_changed(struct cfg_entry * entry, char * olddata, int * valid) {
  37. if (entry->ldata) {
  38. strncpy0(authkey, (char *) entry->ldata, sizeof authkey);
  39. } else if (entry->gdata) {
  40. strncpy0(authkey, (char *) entry->gdata, sizeof authkey);
  41. }
  42. }
  43. struct cfg_entry CFG_AUTHKEY = {
  44. "authkey", CFGF_LOCAL | CFGF_GLOBAL, NULL, NULL,
  45. authkey_changed, authkey_changed, authkey_describe
  46. };
  47. #endif /* S_AUTH */
  48. void cmdprefix_describe(struct cfg_entry *entry, int idx) {
  49. dprintf(idx, STR("cmdprefix is the prefix used for msg cmds, ie: !op or .op\n"));
  50. }
  51. void cmdprefix_changed(struct cfg_entry * entry, char * olddata, int * valid) {
  52. if (entry->ldata) {
  53. strncpy0(cmdprefix, (char *) entry->ldata, sizeof cmdprefix);
  54. } else if (entry->gdata) {
  55. strncpy0(cmdprefix, (char *) entry->gdata, sizeof cmdprefix);
  56. }
  57. }
  58. struct cfg_entry CFG_CMDPREFIX = {
  59. "cmdprefix", CFGF_LOCAL | CFGF_GLOBAL, NULL, NULL,
  60. cmdprefix_changed, cmdprefix_changed, cmdprefix_describe
  61. };
  62. void misc_describe(struct cfg_entry *cfgent, int idx)
  63. {
  64. int i = 0;
  65. if (!strcmp(cfgent->name, STR("fork-interval"))) {
  66. dprintf(idx, STR("fork-interval is number of seconds in between each fork() call made by the bot, to change process ID and reset cpu usage counters.\n"));
  67. i = 1;
  68. #ifdef S_LASTCHECK
  69. } else if (!strcmp(cfgent->name, STR("login"))) {
  70. dprintf(idx, STR("login sets how to handle someone logging in to the shell\n"));
  71. #endif /* S_LASTCHECK */
  72. #ifdef S_ANTITRACE
  73. } else if (!strcmp(cfgent->name, STR("trace"))) {
  74. dprintf(idx, STR("trace sets how to handle someone tracing/debugging the bot\n"));
  75. #endif /* S_ANTITRACE */
  76. #ifdef S_PROMISC
  77. } else if (!strcmp(cfgent->name, STR("promisc"))) {
  78. dprintf(idx, STR("promisc sets how to handle when a interface is set to promiscuous mode\n"));
  79. #endif /* S_PROMISC */
  80. #ifdef S_PROCESSCHECK
  81. } else if (!strcmp(cfgent->name, STR("bad-process"))) {
  82. dprintf(idx, STR("bad-process sets how to handle when a running process not listed in process-list is detected\n"));
  83. } else if (!strcmp(cfgent->name, STR("process-list"))) {
  84. dprintf(idx, STR("process-list is a comma-separated list of \"expected processes\" running on the bots uid\n"));
  85. i = 1;
  86. #endif /* S_PROCESSCHECK */
  87. #ifdef S_HIJACKCHECK
  88. } else if (!strcmp(cfgent->name, STR("hijack"))) {
  89. dprintf(idx, STR("hijack sets how to handle when a commonly used hijack method attempt is detected. (recommended: die)\n"));
  90. #endif /* S_HIJACKCHECK */
  91. }
  92. if (!i)
  93. dprintf(idx, STR("Valid settings are: nocheck, ignore, warn, die, reject, suicide\n"));
  94. }
  95. void fork_lchanged(struct cfg_entry * cfgent, char * oldval, int * valid) {
  96. if (!cfgent->ldata)
  97. return;
  98. if (atoi(cfgent->ldata)<=0)
  99. *valid=0;
  100. }
  101. void fork_gchanged(struct cfg_entry * cfgent, char * oldval, int * valid) {
  102. if (!cfgent->gdata)
  103. return;
  104. if (atoi(cfgent->gdata)<=0)
  105. *valid=0;
  106. }
  107. void fork_describe(struct cfg_entry * cfgent, int idx) {
  108. dprintf(idx, STR("fork-interval is number of seconds in between each fork() call made by the bot, to change process ID and reset cpu usage counters.\n"));
  109. }
  110. struct cfg_entry CFG_FORKINTERVAL = {
  111. "fork-interval", CFGF_GLOBAL | CFGF_LOCAL, NULL, NULL,
  112. fork_gchanged, fork_lchanged, fork_describe
  113. };
  114. void detect_lchanged(struct cfg_entry * cfgent, char * oldval, int * valid) {
  115. char * p = cfgent->ldata;
  116. if (!p)
  117. *valid=1;
  118. else if (strcmp(p, STR("ignore")) && strcmp(p, STR("die")) && strcmp(p, STR("reject"))
  119. && strcmp(p, STR("suicide")) && strcmp(p, STR("nocheck")) && strcmp(p, STR("warn")))
  120. *valid=0;
  121. }
  122. void detect_gchanged(struct cfg_entry * cfgent, char * oldval, int * valid) {
  123. char * p = (char *) cfgent->ldata;
  124. if (!p)
  125. *valid=1;
  126. else if (strcmp(p, STR("ignore")) && strcmp(p, STR("die")) && strcmp(p, STR("reject"))
  127. && strcmp(p, STR("suicide")) && strcmp(p, STR("nocheck")) && strcmp(p, STR("warn")))
  128. *valid=0;
  129. }
  130. #ifdef S_LASTCHECK
  131. struct cfg_entry CFG_LOGIN = {
  132. "login", CFGF_GLOBAL | CFGF_LOCAL, NULL, NULL,
  133. detect_gchanged, detect_lchanged, misc_describe
  134. };
  135. #endif /* S_LASTCHECK */
  136. #ifdef S_HIJACKCHECK
  137. struct cfg_entry CFG_HIJACK = {
  138. "hijack", CFGF_GLOBAL | CFGF_LOCAL, NULL, NULL,
  139. detect_gchanged, detect_lchanged, misc_describe
  140. };
  141. #endif /* S_HIJACKCHECK */
  142. #ifdef S_ANTITRACE
  143. struct cfg_entry CFG_TRACE = {
  144. "trace", CFGF_GLOBAL | CFGF_LOCAL, NULL, NULL,
  145. detect_gchanged, detect_lchanged, misc_describe
  146. };
  147. #endif /* S_ANTITRACE */
  148. #ifdef S_PROMISC
  149. struct cfg_entry CFG_PROMISC = {
  150. "promisc", CFGF_GLOBAL | CFGF_LOCAL, NULL, NULL,
  151. detect_gchanged, detect_lchanged, misc_describe
  152. };
  153. #endif /* S_PROMISC */
  154. #ifdef S_PROCESSCHECK
  155. struct cfg_entry CFG_BADPROCESS = {
  156. "bad-process", CFGF_GLOBAL | CFGF_LOCAL, NULL, NULL,
  157. detect_gchanged, detect_lchanged, misc_describe
  158. };
  159. struct cfg_entry CFG_PROCESSLIST = {
  160. "process-list", CFGF_GLOBAL | CFGF_LOCAL, NULL, NULL,
  161. NULL, NULL, misc_describe
  162. };
  163. #endif /* S_PROCESSCHECK */
  164. #ifdef S_DCCPASS
  165. struct cmd_pass *cmdpass = NULL;
  166. #endif
  167. /* this is cfg shit from servers/irc/ctcp because hub doesnt load
  168. * these mods */
  169. #ifdef HUB
  170. void servers_describe(struct cfg_entry * entry, int idx) {
  171. dprintf(idx, STR("servers is a comma-separated list of servers the bot will use\n"));
  172. }
  173. void servers_changed(struct cfg_entry * entry, char * olddata, int * valid) {
  174. }
  175. void servers6_describe(struct cfg_entry * entry, int idx) {
  176. dprintf(idx, STR("servers6 is a comma-separated list of servers the bot will use (FOR IPv6)\n"));
  177. }
  178. void servers6_changed(struct cfg_entry * entry, char * olddata, int * valid) {
  179. }
  180. void nick_describe(struct cfg_entry * entry, int idx) {
  181. dprintf(idx, STR("nick is the bots preferred nick when connecting/using .resetnick\n"));
  182. }
  183. void nick_changed(struct cfg_entry * entry, char * olddata, int * valid) {
  184. }
  185. void realname_describe(struct cfg_entry * entry, int idx) {
  186. dprintf(idx, STR("realname is the bots \"real name\" when connecting\n"));
  187. }
  188. void realname_changed(struct cfg_entry * entry, char * olddata, int * valid) {
  189. }
  190. struct cfg_entry CFG_SERVERS = {
  191. "servers", CFGF_LOCAL | CFGF_GLOBAL, NULL, NULL,
  192. servers_changed, servers_changed, servers_describe
  193. };
  194. struct cfg_entry CFG_SERVERS6 = {
  195. "servers6", CFGF_LOCAL | CFGF_GLOBAL, NULL, NULL,
  196. servers6_changed, servers6_changed, servers6_describe
  197. };
  198. struct cfg_entry CFG_NICK = {
  199. "nick", CFGF_LOCAL | CFGF_GLOBAL, NULL, NULL,
  200. nick_changed, nick_changed, nick_describe
  201. };
  202. struct cfg_entry CFG_REALNAME = {
  203. "realname", CFGF_LOCAL | CFGF_GLOBAL, NULL, NULL,
  204. realname_changed, realname_changed, realname_describe
  205. };
  206. void getin_describe(struct cfg_entry *cfgent, int idx)
  207. {
  208. if (!strcmp(cfgent->name, STR("op-bots")))
  209. dprintf(idx, STR("op-bots is number of bots to ask every time a oprequest is to be made\n"));
  210. else if (!strcmp(cfgent->name, STR("in-bots")))
  211. dprintf(idx, STR("in-bots is number of bots to ask every time a inrequest is to be made\n"));
  212. else if (!strcmp(cfgent->name, STR("op-requests")))
  213. dprintf(idx, STR("op-requests (requests:seconds) limits how often the bot will ask for ops\n"));
  214. else if (!strcmp(cfgent->name, STR("lag-threshold")))
  215. dprintf(idx, STR("lag-threshold is maximum acceptable server lag for the bot to send/honor requests\n"));
  216. else if (!strcmp(cfgent->name, STR("op-time-slack")))
  217. dprintf(idx, STR("op-time-slack is number of seconds a opcookies encoded time value can be off from the bots current time\n"));
  218. else if (!strcmp(cfgent->name, STR("lock-threshold")))
  219. dprintf(idx, STR("Format H:L. When at least H hubs but L or less leafs are linked, lock all channels\n"));
  220. else if (!strcmp(cfgent->name, STR("kill-threshold")))
  221. dprintf(idx, STR("When more than kill-threshold bots have been killed/k-lined the last minute, channels are locked\n"));
  222. else if (!strcmp(cfgent->name, STR("fight-threshold")))
  223. dprintf(idx, STR("When more than fight-threshold ops/deops/kicks/bans/unbans altogether have happened on a channel in one minute, the channel is locked\n"));
  224. else {
  225. dprintf(idx, STR("No description for %s ???\n"), cfgent->name);
  226. putlog(LOG_ERRORS, "*", STR("getin_describe() called with unknown config entry %s"), cfgent->name);
  227. }
  228. }
  229. void getin_changed(struct cfg_entry *cfgent, char *oldval, int *valid)
  230. {
  231. int i;
  232. if (!cfgent->gdata)
  233. return;
  234. *valid = 0;
  235. if (!strcmp(cfgent->name, STR("op-requests"))) {
  236. int L,
  237. R;
  238. char *value = cfgent->gdata;
  239. L = atoi(value);
  240. value = strchr(value, ':');
  241. if (!value)
  242. return;
  243. value++;
  244. R = atoi(value);
  245. if ((R >= 60) || (R <= 3) || (L < 1) || (L > R))
  246. return;
  247. *valid = 1;
  248. return;
  249. }
  250. if (!strcmp(cfgent->name, STR("lock-threshold"))) {
  251. int L,
  252. R;
  253. char *value = cfgent->gdata;
  254. L = atoi(value);
  255. value = strchr(value, ':');
  256. if (!value)
  257. return;
  258. value++;
  259. R = atoi(value);
  260. if ((R >= 1000) || (R < 0) || (L < 0) || (L > 100))
  261. return;
  262. *valid = 1;
  263. return;
  264. }
  265. i = atoi(cfgent->gdata);
  266. if (!strcmp(cfgent->name, STR("op-bots"))) {
  267. if ((i < 1) || (i > 10))
  268. return;
  269. } else if (!strcmp(cfgent->name, STR("invite-bots"))) {
  270. if ((i < 1) || (i > 10))
  271. return;
  272. } else if (!strcmp(cfgent->name, STR("key-bots"))) {
  273. if ((i < 1) || (i > 10))
  274. return;
  275. } else if (!strcmp(cfgent->name, STR("limit-bots"))) {
  276. if ((i < 1) || (i > 10))
  277. return;
  278. } else if (!strcmp(cfgent->name, STR("unban-bots"))) {
  279. if ((i < 1) || (i > 10))
  280. return;
  281. } else if (!strcmp(cfgent->name, STR("lag-threshold"))) {
  282. if ((i < 3) || (i > 60))
  283. return;
  284. } else if (!strcmp(cfgent->name, STR("fight-threshold"))) {
  285. if (i && ((i < 50) || (i > 1000)))
  286. return;
  287. } else if (!strcmp(cfgent->name, STR("kill-threshold"))) {
  288. if ((i < 0) || (i >= 200))
  289. return;
  290. } else if (!strcmp(cfgent->name, STR("op-time-slack"))) {
  291. if ((i < 30) || (i > 1200))
  292. return;
  293. }
  294. *valid = 1;
  295. return;
  296. }
  297. struct cfg_entry CFG_OPBOTS = {
  298. "op-bots", CFGF_GLOBAL, NULL, NULL,
  299. getin_changed, NULL, getin_describe
  300. };
  301. struct cfg_entry CFG_INBOTS = {
  302. "in-bots", CFGF_GLOBAL, NULL, NULL,
  303. getin_changed, NULL, getin_describe
  304. };
  305. struct cfg_entry CFG_LAGTHRESHOLD = {
  306. "lag-threshold", CFGF_GLOBAL, NULL, NULL,
  307. getin_changed, NULL, getin_describe
  308. };
  309. struct cfg_entry CFG_OPREQUESTS = {
  310. "op-requests", CFGF_GLOBAL, NULL, NULL,
  311. getin_changed, NULL, getin_describe
  312. };
  313. struct cfg_entry CFG_OPTIMESLACK = {
  314. "op-time-slack", CFGF_GLOBAL, NULL, NULL,
  315. getin_changed, NULL, getin_describe
  316. };
  317. #ifdef G_AUTOLOCK
  318. struct cfg_entry CFG_LOCKTHRESHOLD = {
  319. "lock-threshold", CFGF_GLOBAL, NULL, NULL,
  320. getin_changed, NULL, getin_describe
  321. };
  322. struct cfg_entry CFG_KILLTHRESHOLD = {
  323. "kill-threshold", CFGF_GLOBAL, NULL, NULL,
  324. getin_changed, NULL, getin_describe
  325. };
  326. struct cfg_entry CFG_FIGHTTHRESHOLD = {
  327. "fight-threshold", CFGF_GLOBAL, NULL, NULL,
  328. getin_changed, NULL, getin_describe
  329. };
  330. #endif /* G_AUTOLOCK */
  331. #endif /* HUB */
  332. int cfg_count=0;
  333. struct cfg_entry ** cfg = NULL;
  334. int cfg_noshare=0;
  335. /* Expected memory usage
  336. */
  337. int expmem_config()
  338. {
  339. #ifdef S_DCCPASS
  340. struct cmd_pass *cp = NULL;
  341. #endif /* S_DCCPASS */
  342. int tot = 0, i;
  343. for (i=0;i<cfg_count;i++) {
  344. tot += sizeof(void *);
  345. if (cfg[i]->gdata)
  346. tot += strlen(cfg[i]->gdata) + 1;
  347. if (cfg[i]->ldata)
  348. tot += strlen(cfg[i]->ldata) + 1;
  349. }
  350. #ifdef S_DCCPASS
  351. for (cp=cmdpass;cp;cp=cp->next) {
  352. tot += sizeof(struct cmd_pass) + strlen(cp->name)+1;
  353. }
  354. #endif /* S_DCCPASS */
  355. return tot;
  356. }
  357. void init_config()
  358. {
  359. #ifdef S_AUTH
  360. add_cfg(&CFG_AUTHKEY);
  361. #endif /* S_AUTH */
  362. add_cfg(&CFG_MOTD);
  363. add_cfg(&CFG_FORKINTERVAL);
  364. #ifdef S_LASTCHECK
  365. add_cfg(&CFG_LOGIN);
  366. #endif /* S_LASTCHECK */
  367. #ifdef S_HIJACKCHECK
  368. add_cfg(&CFG_HIJACK);
  369. #endif /* S_HIJACKCHECK */
  370. #ifdef S_ANTITRACE
  371. add_cfg(&CFG_TRACE);
  372. #endif /* S_ANTITRACE */
  373. #ifdef S_PROMISC
  374. add_cfg(&CFG_PROMISC);
  375. #endif /* S_PROMISC */
  376. #ifdef S_PROCESSCHECK
  377. add_cfg(&CFG_BADPROCESS);
  378. add_cfg(&CFG_PROCESSLIST);
  379. #endif /* S_PROCESSCHECK */
  380. #ifdef HUB
  381. add_cfg(&CFG_NICK);
  382. add_cfg(&CFG_SERVERS);
  383. add_cfg(&CFG_SERVERS6);
  384. add_cfg(&CFG_REALNAME);
  385. set_cfg_str(NULL, STR("realname"), "A deranged product of evil coders");
  386. add_cfg(&CFG_OPBOTS);
  387. add_cfg(&CFG_INBOTS);
  388. add_cfg(&CFG_LAGTHRESHOLD);
  389. add_cfg(&CFG_OPREQUESTS);
  390. add_cfg(&CFG_OPTIMESLACK);
  391. #ifdef G_AUTOLOCK
  392. add_cfg(&CFG_LOCKTHRESHOLD);
  393. add_cfg(&CFG_KILLTHRESHOLD);
  394. add_cfg(&CFG_FIGHTTHRESHOLD);
  395. #endif /* G_AUTOLOCK */
  396. #endif /* HUB */
  397. }
  398. #ifdef S_DCCPASS
  399. int check_cmd_pass(char *cmd, char *pass)
  400. {
  401. struct cmd_pass *cp;
  402. for (cp = cmdpass; cp; cp = cp->next)
  403. if (!egg_strcasecmp(cmd, cp->name)) {
  404. char tmp[32];
  405. encrypt_pass(pass, tmp);
  406. if (!strcmp(tmp, cp->pass))
  407. return 1;
  408. return 0;
  409. }
  410. return 0;
  411. }
  412. int has_cmd_pass(char *cmd)
  413. {
  414. struct cmd_pass *cp;
  415. for (cp = cmdpass; cp; cp = cp->next)
  416. if (!egg_strcasecmp(cmd, cp->name))
  417. return 1;
  418. return 0;
  419. }
  420. void set_cmd_pass(char *ln, int shareit)
  421. {
  422. struct cmd_pass *cp;
  423. char *cmd;
  424. cmd = newsplit(&ln);
  425. for (cp = cmdpass; cp; cp = cp->next)
  426. if (!strcmp(cmd, cp->name))
  427. break;
  428. if (cp)
  429. if (ln[0]) {
  430. /* change */
  431. strcpy(cp->pass, ln);
  432. if (shareit)
  433. botnet_send_cmdpass(-1, cp->name, cp->pass);
  434. } else {
  435. if (cp == cmdpass)
  436. cmdpass = cp->next;
  437. else {
  438. struct cmd_pass *cp2;
  439. cp2 = cmdpass;
  440. while (cp2->next != cp)
  441. cp2 = cp2->next;
  442. cp2->next = cp->next;
  443. }
  444. if (shareit)
  445. botnet_send_cmdpass(-1, cp->name, "");
  446. nfree(cp->name);
  447. nfree(cp);
  448. } else if (ln[0]) {
  449. /* create */
  450. cp = nmalloc(sizeof(struct cmd_pass));
  451. cp->next = cmdpass;
  452. cmdpass = cp;
  453. cp->name = nmalloc(strlen(cmd) + 1);
  454. strcpy(cp->name, cmd);
  455. strcpy(cp->pass, ln);
  456. if (shareit)
  457. botnet_send_cmdpass(-1, cp->name, cp->pass);
  458. }
  459. }
  460. #endif /* S_DCCPAS */
  461. struct cfg_entry *check_can_set_cfg(char *target, char *entryname)
  462. {
  463. int i;
  464. struct userrec *u;
  465. struct cfg_entry *entry = NULL;
  466. for (i = 0; i < cfg_count; i++)
  467. if (!strcmp(cfg[i]->name, entryname)) {
  468. entry = cfg[i];
  469. break;
  470. }
  471. if (!entry)
  472. return 0;
  473. if (target) {
  474. if (!(entry->flags & CFGF_LOCAL))
  475. return 0;
  476. if (!(u = get_user_by_handle(userlist, target)))
  477. return 0;
  478. if (!(u->flags & USER_BOT))
  479. return 0;
  480. } else {
  481. if (!(entry->flags & CFGF_GLOBAL))
  482. return 0;
  483. }
  484. return entry;
  485. }
  486. void set_cfg_str(char *target, char *entryname, char *data)
  487. {
  488. struct cfg_entry *entry;
  489. if (!(entry = check_can_set_cfg(target, entryname)))
  490. return;
  491. if (data && !strcmp(data, "-"))
  492. data = NULL;
  493. if (data && (strlen(data) >= 1024))
  494. data[1023] = 0;
  495. if (target) {
  496. struct userrec *u = get_user_by_handle(userlist, target);
  497. struct xtra_key *xk;
  498. char *olddata = entry->ldata;
  499. if (u && !strcmp(botnetnick, u->handle)) {
  500. if (data) {
  501. entry->ldata = nmalloc(strlen(data) + 1);
  502. strcpy(entry->ldata, data);
  503. } else
  504. entry->ldata = NULL;
  505. if (entry->localchanged) {
  506. int valid = 1;
  507. entry->localchanged(entry, olddata, &valid);
  508. if (!valid) {
  509. if (entry->ldata)
  510. nfree(entry->ldata);
  511. entry->ldata = olddata;
  512. data = olddata;
  513. olddata = NULL;
  514. }
  515. }
  516. }
  517. xk = nmalloc(sizeof(struct xtra_key));
  518. egg_bzero(xk, sizeof(struct xtra_key));
  519. xk->key = nmalloc(strlen(entry->name) + 1);
  520. strcpy(xk->key, entry->name);
  521. if (data) {
  522. xk->data = nmalloc(strlen(data) + 1);
  523. strcpy(xk->data, data);
  524. }
  525. set_user(&USERENTRY_CONFIG, u, xk);
  526. if (olddata)
  527. nfree(olddata);
  528. } else {
  529. char *olddata = entry->gdata;
  530. if (data) {
  531. entry->gdata = nmalloc(strlen(data) + 1);
  532. strcpy(entry->gdata, data);
  533. } else
  534. entry->gdata = NULL;
  535. if (entry->globalchanged) {
  536. int valid = 1;
  537. entry->globalchanged(entry, olddata, &valid);
  538. if (!valid) {
  539. if (entry->gdata)
  540. nfree(entry->gdata);
  541. entry->gdata = olddata;
  542. olddata = NULL;
  543. }
  544. }
  545. if (!cfg_noshare)
  546. botnet_send_cfg_broad(-1, entry);
  547. if (olddata)
  548. nfree(olddata);
  549. }
  550. }
  551. void userfile_cfg_line(char *ln)
  552. {
  553. char *name;
  554. int i;
  555. struct cfg_entry *cfgent = NULL;
  556. name = newsplit(&ln);
  557. for (i = 0; !cfgent && (i < cfg_count); i++)
  558. if (!strcmp(cfg[i]->name, name))
  559. cfgent = cfg[i];
  560. if (cfgent) {
  561. set_cfg_str(NULL, cfgent->name, ln[0] ? ln : NULL);
  562. } else
  563. putlog(LOG_ERRORS, "*", STR("Unrecognized config entry %s in userfile"), name);
  564. }
  565. void got_config_share(int idx, char *ln)
  566. {
  567. char *name;
  568. int i;
  569. struct cfg_entry *cfgent = NULL;
  570. cfg_noshare++;
  571. name = newsplit(&ln);
  572. for (i = 0; !cfgent && (i < cfg_count); i++)
  573. if (!strcmp(cfg[i]->name, name))
  574. cfgent = cfg[i];
  575. if (cfgent) {
  576. set_cfg_str(NULL, cfgent->name, ln[0] ? ln : NULL);
  577. botnet_send_cfg_broad(idx, cfgent);
  578. } else
  579. putlog(LOG_ERRORS, "*", STR("Unrecognized config entry %s in userfile"), name);
  580. cfg_noshare--;
  581. }
  582. void add_cfg(struct cfg_entry *entry)
  583. {
  584. cfg = (void *) nrealloc(cfg, sizeof(void *) * (cfg_count + 1));
  585. cfg[cfg_count] = entry;
  586. cfg_count++;
  587. entry->ldata = NULL;
  588. entry->gdata = NULL;
  589. }
  590. void trigger_cfg_changed()
  591. {
  592. int i;
  593. struct userrec *u;
  594. struct xtra_key *xk;
  595. u = get_user_by_handle(userlist, botnetnick);
  596. for (i = 0; i < cfg_count; i++) {
  597. if (cfg[i]->flags & CFGF_LOCAL) {
  598. xk = get_user(&USERENTRY_CONFIG, u);
  599. while (xk && strcmp(xk->key, cfg[i]->name))
  600. xk = xk->next;
  601. if (xk) {
  602. putlog(LOG_DEBUG, "*", STR("trigger_cfg_changed for %s"), cfg[i]->name ? cfg[i]->name : "(null)");
  603. if (!strcmp(cfg[i]->name, xk->key ? xk->key : "")) {
  604. set_cfg_str(botnetnick, cfg[i]->name, xk->data);
  605. }
  606. }
  607. }
  608. }
  609. }