cfg.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. /*
  2. * config.c -- handles:
  3. * botnet config
  4. * cmdpass functions
  5. */
  6. #include "common.h"
  7. #include "cfg.h"
  8. #include "cmds.h"
  9. #include "userrec.h"
  10. #include "auth.h"
  11. #include "misc.h"
  12. #include "users.h"
  13. #include "dccutil.h"
  14. #include "botmsg.h"
  15. #include <sys/stat.h>
  16. #include <sys/types.h>
  17. #include <unistd.h>
  18. #include <fcntl.h>
  19. #include "chan.h"
  20. #include "tandem.h"
  21. #include "src/mod/channels.mod/channels.h"
  22. #include "src/mod/ctcp.mod/ctcp.h"
  23. #include "src/chanprog.h"
  24. #include "src/mod/server.mod/server.h"
  25. #include "botnet.h"
  26. #include <net/if.h>
  27. #include "stat.h"
  28. int cfg_count = 0;
  29. bool cfg_noshare = 0;
  30. struct cfg_entry **cfg = NULL;
  31. char cmdprefix = '+'; /* This is the prefix for msg/channel cmds */
  32. struct cmd_pass *cmdpass = NULL;
  33. static void chanset_describe(struct cfg_entry * entry, int idx) {
  34. dprintf(idx, STR("chanset is a list of default options for when a channel is added. Same format as .chanset.\n"));
  35. }
  36. static void chanset_changed(struct cfg_entry *entry, int *valid) {
  37. if (entry->ldata)
  38. strlcpy(cfg_glob_chanset, (char *) entry->ldata, 512);
  39. else if (entry->gdata)
  40. strlcpy(cfg_glob_chanset, (char *) entry->gdata, 512);
  41. }
  42. struct cfg_entry CFG_CHANSET = {
  43. "chanset", CFGF_LOCAL | CFGF_GLOBAL | CFGF_LEAF, NULL, NULL,
  44. chanset_changed, chanset_changed, chanset_describe
  45. };
  46. static void servport_describe(struct cfg_entry * entry, int idx) {
  47. dprintf(idx, STR("servport is the default port to use for server connections.\n"));
  48. }
  49. static void servport_changed(struct cfg_entry *entry, int *valid) {
  50. if (entry->ldata)
  51. default_port = atoi(entry->ldata);
  52. else if (entry->gdata)
  53. default_port = atoi(entry->gdata);
  54. }
  55. struct cfg_entry CFG_SERVPORT = {
  56. "servport", CFGF_LOCAL | CFGF_GLOBAL | CFGF_LEAF, NULL, NULL,
  57. servport_changed, servport_changed, servport_describe
  58. };
  59. static void authkey_describe(struct cfg_entry *entry, int idx) {
  60. dprintf(idx,
  61. 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"));
  62. }
  63. struct cfg_entry CFG_AUTHKEY = {
  64. "authkey", CFGF_LOCAL | CFGF_GLOBAL, NULL, NULL,
  65. NULL, NULL, authkey_describe
  66. };
  67. static void msgcmds_describe(struct cfg_entry *entry, int idx) {
  68. if (entry == &CFG_MSGOP)
  69. dprintf(idx, STR("msgop defines the cmd for opping via msging the bot (leave blank to disable)\n"));
  70. else if (entry == &CFG_MSGPASS)
  71. dprintf(idx, STR("msgpass defines the cmd for setting a pass via msging the bot (leave blank to disable)\n"));
  72. else if (entry == &CFG_MSGINVITE)
  73. dprintf(idx, STR("msginvite defines the cmd for requesting invite via msging the bot (leave blank to disable)\n"));
  74. else if (entry == &CFG_MSGIDENT)
  75. dprintf(idx, STR("msgident defines the cmd for identing via msging the bot (leave blank to disable)\n"));
  76. }
  77. struct cfg_entry CFG_MSGOP = {
  78. "msgop", CFGF_LOCAL | CFGF_GLOBAL, NULL, NULL,
  79. NULL, NULL, msgcmds_describe
  80. };
  81. struct cfg_entry CFG_MSGPASS = {
  82. "msgpass", CFGF_LOCAL | CFGF_GLOBAL, NULL, NULL,
  83. NULL, NULL, msgcmds_describe
  84. };
  85. struct cfg_entry CFG_MSGINVITE = {
  86. "msginvite", CFGF_LOCAL | CFGF_GLOBAL, NULL, NULL,
  87. NULL, NULL, msgcmds_describe
  88. };
  89. struct cfg_entry CFG_MSGIDENT = {
  90. "msgident", CFGF_LOCAL | CFGF_GLOBAL, NULL, NULL,
  91. NULL, NULL, msgcmds_describe
  92. };
  93. static void cmdprefix_describe(struct cfg_entry *entry, int idx) {
  94. dprintf(idx, STR("cmdprefix is the prefix character used for msg cmds, ie: !op or .op\n"));
  95. }
  96. static void cmdprefix_changed(struct cfg_entry *entry, int *valid) {
  97. if (entry->ldata)
  98. cmdprefix = entry->ldata[0];
  99. else if (entry->gdata)
  100. cmdprefix = entry->gdata[0];
  101. }
  102. struct cfg_entry CFG_CMDPREFIX = {
  103. "cmdprefix", CFGF_LOCAL | CFGF_GLOBAL | CFGF_LEAF, NULL, NULL,
  104. cmdprefix_changed, cmdprefix_changed, cmdprefix_describe
  105. };
  106. int deflag_translate(const char *buf)
  107. {
  108. int num = atoi(buf);
  109. if (egg_isdigit(num))
  110. return num;
  111. if (!egg_strcasecmp(buf, "ignore"))
  112. return P_IGNORE;
  113. else if (!egg_strcasecmp(buf, "deop"))
  114. return P_DEOP;
  115. else if (!egg_strcasecmp(buf, "kick"))
  116. return P_KICK;
  117. else if (!egg_strcasecmp(buf, "delete") || !egg_strcasecmp(buf, "remove"))
  118. return P_DELETE;
  119. return P_IGNORE;
  120. }
  121. void deflag_user(struct userrec *u, int why, char *msg, struct chanset_t *chan)
  122. {
  123. if (!u)
  124. return;
  125. char tmp[256] = "", tmp2[1024] = "";
  126. struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  127. int which = 0;
  128. switch (why) {
  129. case DEFLAG_BADCOOKIE:
  130. strcpy(tmp, "Bad op cookie");
  131. which = chan->bad_cookie;
  132. break;
  133. case DEFLAG_MANUALOP:
  134. strcpy(tmp, STR("Manual op in -manop channel"));
  135. which = chan->manop;
  136. break;
  137. #ifdef G_MEAN
  138. case DEFLAG_MEAN_DEOP:
  139. strcpy(tmp, STR("Deopped bot in +mean channel"));
  140. ent = &CFG_MEANDEOP;
  141. break;
  142. case DEFLAG_MEAN_KICK:
  143. strcpy(tmp, STR("Kicked bot in +mean channel"));
  144. ent = &CFG_MEANDEOP;
  145. break;
  146. case DEFLAG_MEAN_BAN:
  147. strcpy(tmp, STR("Banned bot in +mean channel"));
  148. ent = &CFG_MEANDEOP;
  149. break;
  150. #endif /* G_MEAN */
  151. case DEFLAG_MDOP:
  152. strcpy(tmp, "Mass deop");
  153. which = chan->mdop;
  154. break;
  155. case DEFLAG_MOP:
  156. strcpy(tmp, "Mass op");
  157. which = chan->mop;
  158. break;
  159. default:
  160. sprintf(tmp, "Reason #%i", why);
  161. }
  162. if (which == P_DEOP) {
  163. putlog(LOG_WARN, "*", "Setting %s +d (%s): %s", u->handle, tmp, msg);
  164. sprintf(tmp2, "+d: %s (%s)", tmp, msg);
  165. set_user(&USERENTRY_COMMENT, u, tmp2);
  166. get_user_flagrec(u, &fr, chan->dname);
  167. fr.global = USER_DEOP;
  168. fr.chan = USER_DEOP;
  169. set_user_flagrec(u, &fr, chan->dname);
  170. } else if (which == P_KICK) {
  171. putlog(LOG_WARN, "*", "Setting %s +dk (%s): %s", u->handle, tmp, msg);
  172. sprintf(tmp2, "+dk: %s (%s)", tmp, msg);
  173. set_user(&USERENTRY_COMMENT, u, tmp2);
  174. get_user_flagrec(u, &fr, chan->dname);
  175. fr.global = USER_DEOP | USER_KICK;
  176. fr.chan = USER_DEOP | USER_KICK;
  177. set_user_flagrec(u, &fr, chan->dname);
  178. } else if (which == P_DELETE) {
  179. putlog(LOG_WARN, "*", "Deleting %s (%s): %s", u->handle, tmp, msg);
  180. deluser(u->handle);
  181. } else {
  182. putlog(LOG_WARN, "*", "No user flag effects for %s (%s): %s", u->handle, tmp, msg);
  183. sprintf(tmp2, "Warning: %s (%s)", tmp, msg);
  184. set_user(&USERENTRY_COMMENT, u, tmp2);
  185. }
  186. }
  187. static void misc_describe(struct cfg_entry *cfgent, int idx)
  188. {
  189. int i = 0;
  190. if (!strcmp(cfgent->name, "fork-interval")) {
  191. 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"));
  192. i = 1;
  193. } else if (!strcmp(cfgent->name, "login")) {
  194. dprintf(idx, STR("login sets how to handle someone logging in to the shell\n"));
  195. } else if (!strcmp(cfgent->name, "trace")) {
  196. dprintf(idx, STR("trace sets how to handle someone tracing/debugging the bot\n"));
  197. } else if (!strcmp(cfgent->name, "promisc")) {
  198. dprintf(idx, STR("promisc sets how to handle when a interface is set to promiscuous mode\n"));
  199. } else if (!strcmp(cfgent->name, "bad-process")) {
  200. dprintf(idx, STR("bad-process sets how to handle when a running process not listed in process-list is detected\n"));
  201. } else if (!strcmp(cfgent->name, "process-list")) {
  202. dprintf(idx, STR("process-list is a comma-separated list of \"expected processes\" running on the bots uid\n"));
  203. i = 1;
  204. } else if (!strcmp(cfgent->name, "hijack")) {
  205. dprintf(idx, STR("hijack sets how to handle when a commonly used hijack method attempt is detected. (recommended: die)\n"));
  206. }
  207. if (!i)
  208. dprintf(idx, "Valid settings are: ignore, warn, die, reject, suicide\n");
  209. }
  210. static void fork_lchanged(struct cfg_entry * cfgent, int * valid) {
  211. if (!cfgent->ldata)
  212. return;
  213. if (atoi(cfgent->ldata) <= 0)
  214. *valid = 0;
  215. }
  216. static void fork_gchanged(struct cfg_entry * cfgent, int * valid) {
  217. if (!cfgent->gdata)
  218. return;
  219. if (atoi(cfgent->gdata) <= 0)
  220. *valid = 0;
  221. }
  222. static void fork_describe(struct cfg_entry * cfgent, int idx) {
  223. 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"));
  224. }
  225. struct cfg_entry CFG_FORKINTERVAL = {
  226. "fork-interval", CFGF_GLOBAL | CFGF_LOCAL, NULL, NULL,
  227. fork_gchanged, fork_lchanged, fork_describe
  228. };
  229. static void detect_lchanged(struct cfg_entry * cfgent, int * valid) {
  230. char *p = NULL;
  231. if (!(p = (char *) cfgent->ldata))
  232. *valid = 1;
  233. else if (strcmp(p, "ignore") && strcmp(p, "die") && strcmp(p, "reject") && strcmp(p, "suicide") && strcmp(p, "warn"))
  234. *valid = 0;
  235. }
  236. static void detect_gchanged(struct cfg_entry * cfgent, int * valid) {
  237. char *p = (char *) cfgent->ldata;
  238. if (!p)
  239. *valid=1;
  240. else if (strcmp(p, "ignore") && strcmp(p, "die") && strcmp(p, "reject") && strcmp(p, "suicide") && strcmp(p, "warn"))
  241. *valid=0;
  242. }
  243. struct cfg_entry CFG_LOGIN = {
  244. "login", CFGF_GLOBAL | CFGF_LOCAL, NULL, NULL,
  245. detect_gchanged, detect_lchanged, misc_describe
  246. };
  247. struct cfg_entry CFG_HIJACK = {
  248. "hijack", CFGF_GLOBAL | CFGF_LOCAL, NULL, NULL,
  249. detect_gchanged, detect_lchanged, misc_describe
  250. };
  251. struct cfg_entry CFG_TRACE = {
  252. "trace", CFGF_GLOBAL | CFGF_LOCAL, NULL, NULL,
  253. detect_gchanged, detect_lchanged, misc_describe
  254. };
  255. struct cfg_entry CFG_PROMISC = {
  256. "promisc", CFGF_GLOBAL | CFGF_LOCAL, NULL, NULL,
  257. detect_gchanged, detect_lchanged, misc_describe
  258. };
  259. struct cfg_entry CFG_BADPROCESS = {
  260. "bad-process", CFGF_GLOBAL | CFGF_LOCAL, NULL, NULL,
  261. detect_gchanged, detect_lchanged, misc_describe
  262. };
  263. struct cfg_entry CFG_PROCESSLIST = {
  264. "process-list", CFGF_GLOBAL | CFGF_LOCAL, NULL, NULL,
  265. NULL, NULL, misc_describe
  266. };
  267. static void servers_changed(struct cfg_entry * entry, int * valid) {
  268. if (!strcmp(entry->name, "servers")) {
  269. if (conf.bot->net.host6 || conf.bot->net.ip6) /* we want to use the servers6 entry. */
  270. return;
  271. } else if (!strcmp(entry->name, "servers6")) {
  272. if (!conf.bot->net.host6 && !conf.bot->net.ip6) /* we probably want to use the normal server list.. */
  273. return;
  274. }
  275. char *slist = NULL, *p = NULL;
  276. slist = (char *) (entry->ldata ? entry->ldata : (entry->gdata ? entry->gdata : ""));
  277. if (serverlist) {
  278. clearq(serverlist);
  279. serverlist = NULL;
  280. }
  281. shuffle(slist, ",");
  282. p = strdup(slist);
  283. add_server(p);
  284. free(p);
  285. }
  286. static void servers_describe(struct cfg_entry * entry, int idx) {
  287. if (!strcmp(entry->name, "servers"))
  288. dprintf(idx, STR("servers is a comma-separated list of servers the bot will use\n"));
  289. else
  290. dprintf(idx, STR("servers6 is a comma-separated list of servers the bot will use (FOR IPv6)\n"));
  291. }
  292. struct cfg_entry CFG_SERVERS = {
  293. "servers", CFGF_LOCAL | CFGF_GLOBAL | CFGF_LEAF, NULL, NULL,
  294. servers_changed, servers_changed, servers_describe
  295. };
  296. struct cfg_entry CFG_SERVERS6 = {
  297. "servers6", CFGF_LOCAL | CFGF_GLOBAL | CFGF_LEAF, NULL, NULL,
  298. servers_changed, servers_changed, servers_describe
  299. };
  300. static void nick_changed(struct cfg_entry * entry, int * valid) {
  301. char *p = NULL;
  302. if (entry->ldata)
  303. p = entry->ldata;
  304. else if (entry->gdata)
  305. p = entry->gdata;
  306. else
  307. p = NULL;
  308. if (p && p[0])
  309. strlcpy(origbotname, p, NICKLEN + 1);
  310. else
  311. strlcpy(origbotname, conf.bot->nick, NICKLEN + 1);
  312. if (server_online)
  313. dprintf(DP_SERVER, "NICK %s\n", origbotname);
  314. }
  315. static void nick_describe(struct cfg_entry * entry, int idx) {
  316. dprintf(idx, STR("nick is the bots preferred nick when connecting/using .resetnick\n"));
  317. }
  318. struct cfg_entry CFG_NICK = {
  319. "nick", CFGF_LOCAL | CFGF_GLOBAL | CFGF_LEAF, NULL, NULL,
  320. nick_changed, nick_changed, nick_describe
  321. };
  322. static void realname_describe(struct cfg_entry * entry, int idx) {
  323. dprintf(idx, STR("realname is the bots \"real name\" when connecting\n"));
  324. }
  325. static void realname_changed(struct cfg_entry * entry, int * valid) {
  326. if (entry->ldata)
  327. strlcpy(botrealname, (char *) entry->ldata, 121);
  328. else if (entry->gdata)
  329. strlcpy(botrealname, (char *) entry->gdata, 121);
  330. }
  331. struct cfg_entry CFG_REALNAME = {
  332. "realname", CFGF_LOCAL | CFGF_GLOBAL | CFGF_LEAF, NULL, NULL,
  333. realname_changed, realname_changed, realname_describe
  334. };
  335. static void dccauth_describe(struct cfg_entry *cfgent, int idx)
  336. {
  337. dprintf(idx, STR("dccauth is boolean (0 or 1). Set to use auth checking on dcc/telnet login.\n"));
  338. }
  339. struct cfg_entry CFG_DCCAUTH = {
  340. "dccauth", CFGF_GLOBAL | CFGF_LOCAL, NULL, NULL,
  341. NULL, NULL, dccauth_describe
  342. };
  343. static void getin_describe(struct cfg_entry *cfgent, int idx)
  344. {
  345. if (!strcmp(cfgent->name, "op-bots"))
  346. dprintf(idx, STR("op-bots is number of bots to ask every time a oprequest is to be made\n"));
  347. else if (!strcmp(cfgent->name, "in-bots"))
  348. dprintf(idx, STR("in-bots is number of bots to ask every time a inrequest is to be made\n"));
  349. else if (!strcmp(cfgent->name, "op-requests"))
  350. dprintf(idx, STR("op-requests (requests:seconds) limits how often the bot will ask for ops\n"));
  351. else if (!strcmp(cfgent->name, "lag-threshold"))
  352. dprintf(idx, STR("lag-threshold is maximum acceptable server lag for the bot to send/honor requests\n"));
  353. else if (!strcmp(cfgent->name, "op-time-slack"))
  354. dprintf(idx, STR("op-time-slack is number of seconds a opcookies encoded time value can be off from the bots current time\n"));
  355. else if (!strcmp(cfgent->name, "close-threshold"))
  356. dprintf(idx, STR("Format H:L. When at least H hubs but L or less leafs are linked, close all channels\n"));
  357. else if (!strcmp(cfgent->name, "kill-threshold"))
  358. dprintf(idx, STR("When more than kill-threshold bots have been killed/k-lined the last minute, channels are locked\n"));
  359. else if (!strcmp(cfgent->name, "fight-threshold"))
  360. 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"));
  361. else {
  362. dprintf(idx, STR("No description for %s ???\n"), cfgent->name);
  363. putlog(LOG_ERRORS, "*", STR("getin_describe() called with unknown config entry %s"), cfgent->name);
  364. }
  365. }
  366. static void getin_changed(struct cfg_entry *cfgent, int *valid)
  367. {
  368. if (!cfgent->gdata)
  369. return;
  370. *valid = 0;
  371. if (!strcmp(cfgent->name, "op-requests")) {
  372. int L,
  373. R;
  374. char *value = cfgent->gdata;
  375. L = atoi(value);
  376. value = strchr(value, ':');
  377. if (!value)
  378. return;
  379. value++;
  380. R = atoi(value);
  381. if ((R >= 60) || (R <= 3) || (L < 1) || (L > R))
  382. return;
  383. *valid = 1;
  384. return;
  385. }
  386. if (!strcmp(cfgent->name, "close-threshold")) {
  387. int L, R;
  388. char *value = NULL;
  389. value = cfgent->gdata;
  390. L = atoi(value);
  391. value = strchr(value, ':');
  392. if (!value)
  393. return;
  394. value++;
  395. R = atoi(value);
  396. if ((R >= 1000) || (R < 0) || (L < 0) || (L > 100))
  397. return;
  398. *valid = 1;
  399. return;
  400. }
  401. int i = atoi(cfgent->gdata);
  402. if (!strcmp(cfgent->name, "op-bots")) {
  403. if ((i < 1) || (i > 10))
  404. return;
  405. } else if (!strcmp(cfgent->name, "invite-bots")) {
  406. if ((i < 1) || (i > 10))
  407. return;
  408. } else if (!strcmp(cfgent->name, "key-bots")) {
  409. if ((i < 1) || (i > 10))
  410. return;
  411. } else if (!strcmp(cfgent->name, "limit-bots")) {
  412. if ((i < 1) || (i > 10))
  413. return;
  414. } else if (!strcmp(cfgent->name, "unban-bots")) {
  415. if ((i < 1) || (i > 10))
  416. return;
  417. } else if (!strcmp(cfgent->name, "lag-threshold")) {
  418. if ((i < 3) || (i > 60))
  419. return;
  420. } else if (!strcmp(cfgent->name, "fight-threshold")) {
  421. if (i && ((i < 50) || (i > 1000)))
  422. return;
  423. } else if (!strcmp(cfgent->name, "kill-threshold")) {
  424. if ((i < 0) || (i >= 200))
  425. return;
  426. } else if (!strcmp(cfgent->name, "op-time-slack")) {
  427. if ((i < 30) || (i > 1200))
  428. return;
  429. }
  430. *valid = 1;
  431. return;
  432. }
  433. struct cfg_entry CFG_OPBOTS = {
  434. "op-bots", CFGF_GLOBAL, NULL, NULL,
  435. getin_changed, NULL, getin_describe
  436. };
  437. struct cfg_entry CFG_FIGHTTHRESHOLD = {
  438. "fight-threshold", CFGF_GLOBAL, NULL, NULL,
  439. getin_changed, NULL, getin_describe
  440. };
  441. struct cfg_entry CFG_CLOSETHRESHOLD = {
  442. "close-threshold", CFGF_GLOBAL, NULL, NULL,
  443. getin_changed, NULL, getin_describe
  444. };
  445. struct cfg_entry CFG_KILLTHRESHOLD = {
  446. "kill-threshold", CFGF_GLOBAL, NULL, NULL,
  447. getin_changed, NULL, getin_describe
  448. };
  449. struct cfg_entry CFG_INBOTS = {
  450. "in-bots", CFGF_GLOBAL, NULL, NULL,
  451. getin_changed, NULL, getin_describe
  452. };
  453. struct cfg_entry CFG_LAGTHRESHOLD = {
  454. "lag-threshold", CFGF_GLOBAL, NULL, NULL,
  455. getin_changed, NULL, getin_describe
  456. };
  457. struct cfg_entry CFG_OPREQUESTS = {
  458. "op-requests", CFGF_GLOBAL, NULL, NULL,
  459. getin_changed, NULL, getin_describe
  460. };
  461. void add_cfg(struct cfg_entry *entry)
  462. {
  463. cfg = (struct cfg_entry **) my_realloc(cfg, sizeof(void *) * (cfg_count + 1));
  464. cfg[cfg_count] = entry;
  465. cfg_count++;
  466. entry->ldata = NULL;
  467. entry->gdata = NULL;
  468. }
  469. static struct cfg_entry *check_can_set_cfg(char *target, char *entryname)
  470. {
  471. struct cfg_entry *entry = NULL;
  472. for (int i = 0; i < cfg_count; i++)
  473. if (!strcmp(cfg[i]->name, entryname)) {
  474. entry = cfg[i];
  475. break;
  476. }
  477. if (!entry)
  478. return 0;
  479. struct userrec *u = NULL;
  480. if (target) {
  481. if (!(entry->flags & CFGF_LOCAL))
  482. return 0;
  483. if (!(u = get_user_by_handle(userlist, target)))
  484. return 0;
  485. if (!u->bot)
  486. return 0;
  487. } else {
  488. if (!(entry->flags & CFGF_GLOBAL))
  489. return 0;
  490. }
  491. return entry;
  492. }
  493. void set_cfg_str(char *target, char *entryname, char *data)
  494. {
  495. struct cfg_entry *entry = NULL;
  496. bool dochange = 0;
  497. if (!(entry = check_can_set_cfg(target, entryname)))
  498. return;
  499. if (!(entry->flags & (CFGF_HUB|CFGF_LEAF)) ||
  500. (conf.bot->hub && entry->flags & CFGF_HUB) || (!conf.bot->hub && entry->flags & CFGF_LEAF))
  501. dochange = 1;
  502. if (data && !strcmp(data, "-"))
  503. data = NULL;
  504. if (data && (strlen(data) >= 1024))
  505. data[1023] = 0;
  506. if (target) {
  507. struct userrec *u = get_user_by_handle(userlist, target);
  508. struct xtra_key *xk = NULL;
  509. char *olddata = entry->ldata;
  510. if (u && !strcmp(conf.bot->nick, u->handle)) {
  511. if (data) {
  512. entry->ldata = strdup(data);
  513. } else
  514. entry->ldata = NULL;
  515. if (dochange && entry->localchanged) {
  516. int valid = 1;
  517. /* entry->localchanged(entry, olddata, &valid); */
  518. entry->localchanged(entry, &valid);
  519. if (!valid) {
  520. if (entry->ldata)
  521. free(entry->ldata);
  522. entry->ldata = olddata;
  523. data = olddata;
  524. olddata = NULL;
  525. }
  526. }
  527. }
  528. xk = (struct xtra_key *) my_calloc(1, sizeof(struct xtra_key));
  529. xk->key = strdup(entry->name);
  530. if (data) {
  531. xk->data = strdup(data);
  532. }
  533. set_user(&USERENTRY_CONFIG, u, xk);
  534. if (olddata)
  535. free(olddata);
  536. } else {
  537. char *olddata = entry->gdata;
  538. if (data) {
  539. entry->gdata = strdup(data);
  540. } else
  541. entry->gdata = NULL;
  542. if (dochange && entry->globalchanged) {
  543. int valid = 1;
  544. /* entry->globalchanged(entry, olddata, &valid); */
  545. entry->globalchanged(entry, &valid);
  546. if (!valid) {
  547. if (entry->gdata)
  548. free(entry->gdata);
  549. entry->gdata = olddata;
  550. olddata = NULL;
  551. }
  552. }
  553. if (!cfg_noshare)
  554. botnet_send_cfg_broad(-1, entry);
  555. if (olddata)
  556. free(olddata);
  557. }
  558. }
  559. struct cfg_entry CFG_MOTD = {
  560. "motd", CFGF_GLOBAL, NULL, NULL,
  561. NULL, NULL, NULL
  562. };
  563. void init_cfg()
  564. {
  565. add_cfg(&CFG_AUTHKEY);
  566. add_cfg(&CFG_BADPROCESS);
  567. add_cfg(&CFG_DCCAUTH);
  568. add_cfg(&CFG_CHANSET);
  569. add_cfg(&CFG_CLOAK_SCRIPT);
  570. add_cfg(&CFG_CLOSETHRESHOLD);
  571. add_cfg(&CFG_CMDPREFIX);
  572. add_cfg(&CFG_FIGHTTHRESHOLD);
  573. add_cfg(&CFG_FORKINTERVAL);
  574. add_cfg(&CFG_HIJACK);
  575. add_cfg(&CFG_INBOTS);
  576. add_cfg(&CFG_KILLTHRESHOLD);
  577. add_cfg(&CFG_LAGTHRESHOLD);
  578. add_cfg(&CFG_LOGIN);
  579. add_cfg(&CFG_MOTD);
  580. #ifdef G_MEAN
  581. add_cfg(&CFG_MEANBAN);
  582. add_cfg(&CFG_MEANDEOP);
  583. add_cfg(&CFG_MEANKICK);
  584. #endif /* G_MEAN */
  585. add_cfg(&CFG_MSGIDENT);
  586. add_cfg(&CFG_MSGINVITE);
  587. add_cfg(&CFG_MSGOP);
  588. add_cfg(&CFG_MSGPASS);
  589. add_cfg(&CFG_NICK);
  590. add_cfg(&CFG_OPBOTS);
  591. add_cfg(&CFG_OPREQUESTS);
  592. add_cfg(&CFG_PROCESSLIST);
  593. add_cfg(&CFG_PROMISC);
  594. add_cfg(&CFG_REALNAME);
  595. add_cfg(&CFG_SERVERS);
  596. add_cfg(&CFG_SERVERS6);
  597. add_cfg(&CFG_SERVPORT);
  598. add_cfg(&CFG_TRACE);
  599. }
  600. int check_cmd_pass(const char *cmd, char *pass)
  601. {
  602. if (check_master_hash(NULL, pass))
  603. return 1;
  604. struct cmd_pass *cp = NULL;
  605. for (cp = cmdpass; cp; cp = cp->next)
  606. if (!egg_strcasecmp(cmd, cp->name)) {
  607. char tmp[32] = "";
  608. encrypt_pass(pass, tmp);
  609. if (!strcmp(tmp, cp->pass))
  610. return 1;
  611. return 0;
  612. }
  613. return 0;
  614. }
  615. int has_cmd_pass(const char *cmd)
  616. {
  617. struct cmd_pass *cp = NULL;
  618. for (cp = cmdpass; cp; cp = cp->next)
  619. if (!egg_strcasecmp(cmd, cp->name))
  620. return 1;
  621. return 0;
  622. }
  623. void set_cmd_pass(char *ln, int shareit)
  624. {
  625. struct cmd_pass *cp = NULL;
  626. char *cmd = NULL;
  627. cmd = newsplit(&ln);
  628. for (cp = cmdpass; cp; cp = cp->next)
  629. if (!strcmp(cmd, cp->name))
  630. break;
  631. if (cp)
  632. if (ln[0]) {
  633. /* change */
  634. strcpy(cp->pass, ln);
  635. if (shareit)
  636. botnet_send_cmdpass(-1, cp->name, cp->pass);
  637. } else {
  638. if (cp == cmdpass)
  639. cmdpass = cp->next;
  640. else {
  641. struct cmd_pass *cp2;
  642. cp2 = cmdpass;
  643. while (cp2->next != cp)
  644. cp2 = cp2->next;
  645. cp2->next = cp->next;
  646. }
  647. if (shareit)
  648. botnet_send_cmdpass(-1, cp->name, "");
  649. free(cp->name);
  650. free(cp);
  651. } else if (ln[0]) {
  652. /* create */
  653. cp = (struct cmd_pass *) my_calloc(1, sizeof(struct cmd_pass));
  654. cp->next = cmdpass;
  655. cmdpass = cp;
  656. cp->name = strdup(cmd);
  657. strcpy(cp->pass, ln);
  658. if (shareit)
  659. botnet_send_cmdpass(-1, cp->name, cp->pass);
  660. }
  661. }
  662. void userfile_cfg_line(char *ln)
  663. {
  664. char *name = NULL;
  665. int i;
  666. struct cfg_entry *cfgent = NULL;
  667. name = newsplit(&ln);
  668. for (i = 0; !cfgent && (i < cfg_count); i++)
  669. if (!strcmp(cfg[i]->name, name))
  670. cfgent = cfg[i];
  671. if (cfgent) {
  672. /* if we are a leaf, dont share the cfg line. */
  673. if (bot_hublevel(conf.bot->u) == 999)
  674. cfg_noshare = 1;
  675. set_cfg_str(NULL, cfgent->name, (ln && ln[0]) ? ln : NULL);
  676. /* regardless of leaf/hub it is safe to set this to 0 */
  677. cfg_noshare = 0;
  678. } else
  679. putlog(LOG_ERRORS, "*", "Unrecognized config entry %s in userfile", name);
  680. }
  681. void got_config_share(int idx, char *ln, int broad)
  682. {
  683. char *name = NULL;
  684. int i;
  685. struct cfg_entry *cfgent = NULL;
  686. cfg_noshare = 1;
  687. name = newsplit(&ln);
  688. for (i = 0; !cfgent && (i < cfg_count); i++)
  689. if (!strcmp(cfg[i]->name, name))
  690. cfgent = cfg[i];
  691. if (cfgent) {
  692. set_cfg_str(NULL, cfgent->name, (ln && ln[0]) ? ln : NULL);
  693. if (broad)
  694. botnet_send_cfg_broad(idx, cfgent);
  695. } else
  696. putlog(LOG_ERRORS, "*", "Unrecognized config entry %s in userfile", name);
  697. cfg_noshare = 0;
  698. }
  699. void trigger_cfg_changed()
  700. {
  701. int i;
  702. struct xtra_key *xk = NULL;
  703. for (i = 0; i < cfg_count; i++) {
  704. if (cfg[i]->flags & CFGF_LOCAL) {
  705. xk = (struct xtra_key *) get_user(&USERENTRY_CONFIG, conf.bot->u);
  706. while (xk && strcmp(xk->key, cfg[i]->name))
  707. xk = xk->next;
  708. if (xk) {
  709. putlog(LOG_DEBUG, "*", "trigger_cfg_changed for %s", cfg[i]->name ? cfg[i]->name : "(null)");
  710. if (!strcmp(cfg[i]->name, xk->key ? xk->key : "")) {
  711. set_cfg_str(conf.bot->nick, cfg[i]->name, xk->data);
  712. }
  713. }
  714. }
  715. }
  716. }