chanprog.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968
  1. /*
  2. * Copyright (C) 1997 Robey Pointer
  3. * Copyright (C) 1999 - 2002 Eggheads Development Team
  4. * Copyright (C) 2002 - 2010 Bryan Drewery
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. */
  20. /*
  21. * chanprog.c -- handles:
  22. * rmspace()
  23. * maintaining the server list
  24. * revenge punishment
  25. * timers, utimers
  26. * telling the current programmed settings
  27. * initializing a lot of stuff and loading the tcl scripts
  28. *
  29. */
  30. #include "common.h"
  31. #include "chanprog.h"
  32. #include "settings.h"
  33. #include "src/mod/irc.mod/irc.h"
  34. #include "src/mod/channels.mod/channels.h"
  35. #include "src/mod/server.mod/server.h"
  36. #include "src/mod/share.mod/share.h"
  37. #include "rfc1459.h"
  38. #include "net.h"
  39. #include "misc.h"
  40. #include "users.h"
  41. #include "botnet.h"
  42. #include "userrec.h"
  43. #include "main.h"
  44. #include "debug.h"
  45. #include "set.h"
  46. #include "dccutil.h"
  47. #include "botmsg.h"
  48. #if HAVE_GETRUSAGE
  49. #include <sys/resource.h>
  50. #if HAVE_SYS_RUSAGE_H
  51. #include <sys/rusage.h>
  52. #endif
  53. #endif
  54. #include <sys/utsname.h>
  55. #include <bdlib/src/Array.h>
  56. #include <bdlib/src/String.h>
  57. char *def_chanset = "+enforcebans +dynamicbans +userbans -bitch +cycle -inactive +userexempts -dynamicexempts +userinvites -dynamicinvites -nodesynch -closed -take -voice -private -fastop +meankicks ban-type 3 protect-backup 1 groups { main }";
  58. struct chanset_t *chanset = NULL; /* Channel list */
  59. struct chanset_t *chanset_default = NULL; /* Default channel list */
  60. char admin[121] = ""; /* Admin info */
  61. char origbotnick[HANDLEN + 1] = ""; /* from -B (placed into conf.bot->nick .. for backup when conf is cleared */
  62. char origbotname[NICKLEN] = ""; /* Nick to regain */
  63. char jupenick[NICKLEN] = "";
  64. char botname[NICKLEN] = ""; /* IRC nickname */
  65. in_port_t my_port = 0;
  66. int reset_chans = 0;
  67. bool cookies_disabled = 0;
  68. char s2_4[3] = "",s1_6[3] = "",s1_11[3] = "";
  69. /* Remove leading and trailing whitespaces.
  70. */
  71. void rmspace(char *s)
  72. {
  73. if (!s || !*s)
  74. return;
  75. register char *p = NULL, *q = NULL;
  76. /* Remove trailing whitespaces. */
  77. for (q = s + strlen(s) - 1; q >= s && egg_isspace(*q); q--)
  78. ;
  79. *(q + 1) = 0;
  80. /* Remove leading whitespaces. */
  81. for (p = s; egg_isspace(*p); p++)
  82. ;
  83. if (p != s)
  84. memmove(s, p, q - p + 2);
  85. }
  86. /* Returns memberfields if the nick is in the member list.
  87. */
  88. memberlist *ismember(struct chanset_t *chan, const char *nick)
  89. {
  90. register memberlist *x = NULL;
  91. if (chan && nick && nick[0])
  92. for (x = chan->channel.member; x && x->nick[0]; x = x->next)
  93. if (!rfc_casecmp(x->nick, nick))
  94. return x;
  95. return NULL;
  96. }
  97. /* Find a chanset by channel name as the server knows it (ie !ABCDEchannel)
  98. */
  99. struct chanset_t *findchan(const char *name)
  100. {
  101. register struct chanset_t *chan = NULL;
  102. for (chan = chanset; chan; chan = chan->next)
  103. if (chan->name[0] && !rfc_casecmp(chan->name, name))
  104. return chan;
  105. return NULL;
  106. }
  107. /* Find a chanset by display name (ie !channel)
  108. */
  109. struct chanset_t *findchan_by_dname(const char *name)
  110. {
  111. register struct chanset_t *chan = NULL;
  112. for (chan = chanset; chan; chan = chan->next)
  113. if (!rfc_casecmp(chan->dname, name))
  114. return chan;
  115. return NULL;
  116. }
  117. /*
  118. * "caching" functions
  119. */
  120. /* Shortcut for get_user_by_host -- might have user record in one
  121. * of the channel caches.
  122. */
  123. struct userrec *check_chanlist(const char *host)
  124. {
  125. char *nick = NULL, *uhost = NULL, buf[UHOSTLEN] = "";
  126. register memberlist *m = NULL;
  127. register struct chanset_t *chan = NULL;
  128. strlcpy(buf, host, sizeof buf);
  129. uhost = buf;
  130. nick = splitnick(&uhost);
  131. for (chan = chanset; chan; chan = chan->next)
  132. for (m = chan->channel.member; m && m->nick[0]; m = m->next)
  133. if (!rfc_casecmp(nick, m->nick) && !strcasecmp(uhost, m->userhost))
  134. return m->user;
  135. return NULL;
  136. }
  137. /* Shortcut for get_user_by_handle -- might have user record in channels
  138. */
  139. struct userrec *check_chanlist_hand(const char *hand)
  140. {
  141. register struct chanset_t *chan = NULL;
  142. register memberlist *m = NULL;
  143. for (chan = chanset; chan; chan = chan->next)
  144. for (m = chan->channel.member; m && m->nick[0]; m = m->next)
  145. if (m->user && !strcasecmp(m->user->handle, hand))
  146. return m->user;
  147. return NULL;
  148. }
  149. /* Clear the user pointers in the chanlists.
  150. *
  151. * Necessary when a hostmask is added/removed, a user is added or a new
  152. * userfile is loaded.
  153. */
  154. void clear_chanlist(void)
  155. {
  156. register memberlist *m = NULL;
  157. register struct chanset_t *chan = NULL;
  158. for (chan = chanset; chan; chan = chan->next)
  159. for (m = chan->channel.member; m && m->nick[0]; m = m->next) {
  160. m->user = NULL;
  161. m->tried_getuser = 0;
  162. }
  163. }
  164. /* Clear the user pointer of a specific nick in the chanlists.
  165. *
  166. * Necessary when a hostmask is added/removed, a nick changes, etc.
  167. * Does not completely invalidate the channel cache like clear_chanlist().
  168. */
  169. void clear_chanlist_member(const char *nick)
  170. {
  171. register memberlist *m = NULL;
  172. register struct chanset_t *chan = NULL;
  173. for (chan = chanset; chan; chan = chan->next)
  174. for (m = chan->channel.member; m && m->nick[0]; m = m->next)
  175. if (!rfc_casecmp(m->nick, nick)) {
  176. m->user = NULL;
  177. m->tried_getuser = 0;
  178. break;
  179. }
  180. }
  181. /* If this user@host is in a channel, set it (it was null)
  182. */
  183. void set_chanlist(const char *host, struct userrec *rec)
  184. {
  185. char *nick = NULL, *uhost = NULL, buf[UHOSTLEN] = "";
  186. register memberlist *m = NULL;
  187. register struct chanset_t *chan = NULL;
  188. strlcpy(buf, host, sizeof buf);
  189. uhost = buf;
  190. nick = splitnick(&uhost);
  191. for (chan = chanset; chan; chan = chan->next)
  192. for (m = chan->channel.member; m && m->nick[0]; m = m->next)
  193. if (!rfc_casecmp(nick, m->nick) && !strcasecmp(uhost, m->userhost))
  194. m->user = rec;
  195. }
  196. /* 0 marks all channels
  197. * 1 removes marked channels
  198. * 2 unmarks all channels
  199. */
  200. void checkchans(int which)
  201. {
  202. struct chanset_t *chan = NULL, *chan_next = NULL;
  203. if (which == 0 || which == 2) {
  204. for (chan = chanset; chan; chan = chan->next) {
  205. if (which == 0) {
  206. chan->status |= CHAN_FLAGGED;
  207. } else if (which == 2) {
  208. chan->status &= ~CHAN_FLAGGED;
  209. }
  210. }
  211. } else if (which == 1) {
  212. for (chan = chanset; chan; chan = chan_next) {
  213. chan_next = chan->next;
  214. if (chan->status & CHAN_FLAGGED) {
  215. putlog(LOG_MISC, "*", "No longer supporting channel %s", chan->dname);
  216. remove_channel(chan);
  217. }
  218. }
  219. }
  220. }
  221. void tell_verbose_uptime(int idx)
  222. {
  223. char s[256] = "", s1[121] = "", s2[81] = "", outbuf[501] = "";
  224. time_t total, hr, min;
  225. #if HAVE_GETRUSAGE
  226. struct rusage ru;
  227. #else
  228. # if HAVE_CLOCK
  229. clock_t cl;
  230. # endif
  231. #endif /* HAVE_GETRUSAGE */
  232. daysdur(now, online_since, s, sizeof(s));
  233. if (backgrd)
  234. strlcpy(s1, "background", sizeof(s1));
  235. else {
  236. if (term_z)
  237. strlcpy(s1, "terminal mode", sizeof(s1));
  238. else
  239. strlcpy(s1, "log dump mode", sizeof(s1));
  240. }
  241. simple_snprintf(outbuf, sizeof(outbuf), "Online for %s", s);
  242. if (restart_time) {
  243. daysdur(now, restart_time, s, sizeof(s));
  244. size_t olen = strlen(outbuf);
  245. simple_snprintf(&outbuf[olen], sizeof(outbuf) - olen, " (%s %s)", restart_was_update ? "updated" : "restarted", s);
  246. }
  247. #if HAVE_GETRUSAGE
  248. getrusage(RUSAGE_SELF, &ru);
  249. total = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
  250. hr = (int) (total / 60);
  251. min = (int) (total - (hr * 60));
  252. egg_snprintf(s2, sizeof(s2), "CPU %02d:%02d (load avg %3.1f%%)", (int) hr, (int) min, 100.0 * ((float) total / (float) (now - online_since)));
  253. #else
  254. # if HAVE_CLOCK
  255. cl = (clock() / CLOCKS_PER_SEC);
  256. hr = (int) (cl / 60);
  257. min = (int) (cl - (hr * 60));
  258. egg_snprintf(s2, sizeof(s2), "CPU %02d:%02d (load avg %3.1f%%)", (int) hr, (int) min, 100.0 * ((float) cl / (float) (now - online_since)));
  259. # else
  260. simple_snprintf(s2, sizeof(s2), "CPU ???");
  261. # endif
  262. #endif /* HAVE_GETRUSAGE */
  263. dprintf(idx, "%s (%s) %s cache hit %4.1f%%\n",
  264. outbuf, s1, s2,
  265. 100.0 * ((float) cache_hit) / ((float) (cache_hit + cache_miss)));
  266. }
  267. /* Dump status info out to dcc
  268. */
  269. void tell_verbose_status(int idx)
  270. {
  271. char *vers_t = NULL, *uni_t = NULL;
  272. int i;
  273. struct utsname un;
  274. if (!uname(&un) < 0) {
  275. vers_t = " ";
  276. uni_t = "*unknown*";
  277. } else {
  278. vers_t = un.release;
  279. uni_t = un.sysname;
  280. }
  281. i = count_users(userlist);
  282. dprintf(idx, "I am %s, running %s: %d user%s\n", conf.bot->nick, ver, i, i == 1 ? "" : "s");
  283. dprintf(idx, "my user: %s\n", conf.bot->u->handle);
  284. if (conf.bot->localhub)
  285. dprintf(idx, "I am a localhub.\n");
  286. if (conf.bot->hub && isupdatehub())
  287. dprintf(idx, "I am an update hub.\n");
  288. tell_verbose_uptime(idx);
  289. if (admin[0])
  290. dprintf(idx, "Admin: %s\n", admin);
  291. dprintf(idx, "OS: %s %s\n", uni_t, vers_t);
  292. dprintf(idx, "Running from: %s\n", binname);
  293. dprintf(idx, "uid: %s (%d) pid: %lu homedir: %s\n", conf.username, conf.uid, (unsigned long) mypid, conf.homedir);
  294. if (tempdir[0])
  295. dprintf(idx, "Tempdir : %s\n", tempdir);
  296. if (conf.datadir)
  297. dprintf(idx, "Datadir : %s\n", conf.datadir);
  298. }
  299. /* Show all internal state variables
  300. */
  301. void tell_settings(int idx)
  302. {
  303. char s[1024] = "";
  304. struct flag_record fr = {FR_GLOBAL, 0, 0, 0 };
  305. dprintf(idx, "Botnet Nickname: %s\n", conf.bot->nick);
  306. if (conf.bot->hub)
  307. dprintf(idx, "Userfile: %s \n", userfile);
  308. dprintf(idx, "Directories:\n");
  309. dprintf(idx, " Temp : %s\n", tempdir);
  310. fr.global = default_flags;
  311. build_flags(s, &fr, NULL);
  312. dprintf(idx, "New users get flags [%s]\n", s);
  313. if (conf.bot->hub && owner[0])
  314. dprintf(idx, "Permanent owner(s): %s\n", owner);
  315. dprintf(idx, "Ignores last %d mins\n", ignore_time);
  316. }
  317. void reaffirm_owners()
  318. {
  319. /* Make sure perm owners are +a */
  320. if (owner[0]) {
  321. char *q = owner, *p = strchr(q, ','), s[121] = "";
  322. struct userrec *u = NULL;
  323. while (p) {
  324. strlcpy(s, q, (p - q) + 1);
  325. rmspace(s);
  326. u = get_user_by_handle(userlist, s);
  327. if (u)
  328. u->flags = sanity_check(u->flags | USER_ADMIN, 0);
  329. q = p + 1;
  330. p = strchr(q, ',');
  331. }
  332. strlcpy(s, q, sizeof(s));
  333. rmspace(s);
  334. u = get_user_by_handle(userlist, s);
  335. if (u)
  336. u->flags = sanity_check(u->flags | USER_ADMIN, 0);
  337. }
  338. }
  339. bool is_hub(const char* nick) {
  340. for (size_t idx = 0; idx < conf.hubs.length(); ++idx) {
  341. bd::String hub(conf.hubs[idx]);
  342. if (!strncasecmp(nick, newsplit(hub).c_str(), HANDLEN)) {
  343. return true;
  344. }
  345. }
  346. return false;
  347. }
  348. void load_internal_users()
  349. {
  350. char *p = NULL, *ln = NULL, *hand = NULL, *pass = NULL, *q = NULL;
  351. char *hosts = NULL, buf[2048] = "", tmp[51] = "";
  352. int i;
  353. struct userrec *u = NULL;
  354. /* hubs */
  355. for (size_t idx = 0; idx < conf.hubs.length(); ++idx) {
  356. bd::Array<bd::String> params(static_cast<bd::String>(conf.hubs[idx]).split(' '));
  357. bd::String handle(params[0]);
  358. if (!get_user_by_handle(userlist, const_cast<char*>(handle.c_str()))) {
  359. bd::String address(params[1]);
  360. in_port_t port = atoi(static_cast<bd::String>(params[2]).c_str());
  361. unsigned short hublevel = params.length() == 4 ? atoi(static_cast<bd::String>(params[3]).c_str()) : (idx + 1);
  362. userlist = adduser(userlist, handle.c_str(), "none", "-", USER_OP, 1);
  363. u = get_user_by_handle(userlist, const_cast<char*>(handle.c_str()));
  364. simple_snprintf(tmp, sizeof(tmp), "%li [internal]", (long)now);
  365. set_user(&USERENTRY_ADDED, u, tmp);
  366. struct bot_addr *bi = (struct bot_addr *) my_calloc(1, sizeof(struct bot_addr));
  367. bi->address = strdup(address.c_str());
  368. bi->telnet_port = bi->relay_port = port;
  369. bi->hublevel = hublevel;
  370. if (conf.bot->hub && (!bi->hublevel) && (!strcasecmp(handle.c_str(), conf.bot->nick))) {
  371. bi->hublevel = 99;
  372. }
  373. bi->uplink = (char *) my_calloc(1, 1);
  374. set_user(&USERENTRY_BOTADDR, u, bi);
  375. /* set_user(&USERENTRY_PASS, get_user_by_handle(userlist, handle.c_str()), SALT2); */
  376. }
  377. }
  378. /* perm owners */
  379. owner[0] = 0;
  380. strlcpy(buf, settings.owners, sizeof(buf));
  381. p = buf;
  382. while (p) {
  383. ln = p;
  384. p = strchr(p, ',');
  385. if (p)
  386. *p++ = 0;
  387. hand = ln;
  388. pass = NULL;
  389. hosts = NULL;
  390. for (i = 0; ln; i++) {
  391. switch (i) {
  392. case 0:
  393. hand = ln;
  394. break;
  395. case 1:
  396. pass = ln;
  397. if (ln && (ln = strchr(ln, ' ')))
  398. *ln++ = 0;
  399. hosts = ln;
  400. if (owner[0])
  401. strlcat(owner, ",", 121);
  402. strlcat(owner, hand, 121);
  403. if (!get_user_by_handle(userlist, hand)) {
  404. userlist = adduser(userlist, hand, "none", "-", USER_ADMIN | USER_OWNER | USER_MASTER | USER_OP | USER_PARTY | USER_HUBA | USER_CHUBA, 0);
  405. u = get_user_by_handle(userlist, hand);
  406. set_user(&USERENTRY_PASS, u, pass);
  407. simple_snprintf(tmp, sizeof(tmp), "%li [internal]", (long)now);
  408. set_user(&USERENTRY_ADDED, u, tmp);
  409. while (hosts) {
  410. char x[1024] = "";
  411. if ((ln = strchr(ln, ' ')))
  412. *ln++ = 0;
  413. if ((q = strchr(hosts, '!'))) { /* skip over nick they provided ... */
  414. q++;
  415. if (*q == '*' || *q == '?') /* ... and any '*' or '?' */
  416. q++;
  417. hosts = q;
  418. }
  419. simple_snprintf(x, sizeof(x), "-telnet!%s", hosts);
  420. set_user(&USERENTRY_HOSTS, u, x);
  421. hosts = ln;
  422. }
  423. }
  424. break;
  425. default:
  426. break;
  427. }
  428. if (ln && (ln = strchr(ln, ' ')))
  429. *ln++ = 0;
  430. }
  431. }
  432. // Add HQ in if needed
  433. if (!backgrd && term_z) {
  434. strlcat(owner, ",HQ", sizeof(owner));
  435. }
  436. }
  437. static struct userrec* add_bot_userlist(char* bot) {
  438. struct userrec *u = NULL;
  439. if (!(u = get_user_by_handle(userlist, bot))) {
  440. /* I need to be on the userlist... doh. */
  441. userlist = adduser(userlist, bot, "none", "-", USER_OP, 1);
  442. u = get_user_by_handle(userlist, bot);
  443. struct bot_addr *bi = (struct bot_addr *) my_calloc(1, sizeof(struct bot_addr));
  444. bi->uplink = (char *) my_calloc(1, 1);
  445. bi->address = (char *) my_calloc(1, 1);
  446. bi->telnet_port = 3333;
  447. bi->relay_port = 3333;
  448. bi->hublevel = 999;
  449. set_user(&USERENTRY_BOTADDR, u, bi);
  450. }
  451. return u;
  452. }
  453. void add_myself_to_userlist() {
  454. conf.bot->u = add_bot_userlist(conf.bot->nick);
  455. }
  456. void add_child_bots() {
  457. conf_bot* bot = conf.bots->next; //Skip myself
  458. if (bot && bot->nick) {
  459. for (; bot && bot->nick; bot = bot->next) {
  460. add_bot_userlist(bot->nick);
  461. }
  462. }
  463. }
  464. void add_localhub() {
  465. add_bot_userlist(conf.localhub);
  466. }
  467. void rehash_ip() {
  468. /* cache our ip on load instead of every 30 seconds */
  469. char *ip4 = NULL, *ip6 = NULL;
  470. if (cached_ip) {
  471. ip4 = strdup(myipstr(AF_INET));
  472. ip6 = strdup(myipstr(AF_INET6));
  473. }
  474. cache_my_ip();
  475. sdprintf("ip4: %s", myipstr(AF_INET));
  476. sdprintf("ip6: %s", myipstr(AF_INET6));
  477. /* Check if our ip changed during a rehash */
  478. if (ip4) {
  479. if (strcmp(ip4, myipstr(AF_INET)) || strcmp(ip6, myipstr(AF_INET6))) {
  480. if (tands > 0) {
  481. botnet_send_chat(-1, conf.bot->nick, "IP changed.");
  482. botnet_send_bye("IP changed.");
  483. }
  484. fatal("brb", 1);
  485. }
  486. free(ip4);
  487. free(ip6);
  488. }
  489. if (conf.bot->hub) {
  490. struct bot_addr *bi = (struct bot_addr *) get_user(&USERENTRY_BOTADDR, conf.bot->u);
  491. listen_all(bi->telnet_port, 0, 1);
  492. my_port = bi->telnet_port;
  493. } else if (conf.bot->localhub) {
  494. // If not listening on the domain socket, open it up
  495. bool listening = 0;
  496. for (int i = 0; i < dcc_total; i++) {
  497. if (dcc[i].type && (dcc[i].type == &DCC_TELNET) && (!strcmp(dcc[i].host, conf.localhub_socket)) && (!strcmp(dcc[i].nick, "(unix_domain"))) {
  498. listening = 1;
  499. break;
  500. }
  501. }
  502. if (!listening) {
  503. // Listen on the unix domain socket
  504. in_port_t port;
  505. int i = open_listen_addr_by_af(conf.localhub_socket, &port, AF_UNIX);
  506. if (i < 0) {
  507. putlog(LOG_ERRORS, "*", "Can't listen on %s - %s", conf.localhub_socket, i == -1 ? "it's taken." : "couldn't assign file.");
  508. } else {
  509. /* now setup dcc entry */
  510. int idx = new_dcc(&DCC_TELNET, 0);
  511. dcc[idx].addr = 0L;
  512. strlcpy(dcc[idx].host, conf.localhub_socket, sizeof(dcc[idx].host));
  513. dcc[idx].port = 0;
  514. dcc[idx].sock = i;
  515. dcc[idx].timeval = now;
  516. strlcpy(dcc[idx].nick, "(unix_domain)", sizeof(dcc[idx].nick));
  517. putlog(LOG_DEBUG, "*", "Listening on telnet %s", conf.localhub_socket);
  518. }
  519. }
  520. }
  521. }
  522. void chanprog()
  523. {
  524. struct utsname un;
  525. sdprintf("I am: %s", conf.bot->nick);
  526. /* Add the 'default' virtual channel.
  527. The flags will be overwritten when the userfile is loaded,
  528. but if there is no userfile yet, or no 'default' channel,
  529. then it will take on the properties of 'def_chanset',
  530. and then later save this to the userfile.
  531. */
  532. channel_add(NULL, "default", def_chanset, 1);
  533. if (conf.bot->hub) {
  534. simple_snprintf(userfile, 121, "%s/.u", dirname(binname));
  535. loading = 1;
  536. checkchans(0);
  537. readuserfile(userfile, &userlist);
  538. checkchans(1);
  539. var_parse_my_botset();
  540. loading = 0;
  541. }
  542. load_internal_users();
  543. add_myself_to_userlist();
  544. if (conf.bot->localhub)
  545. add_child_bots();
  546. else if (!conf.bot->hub)
  547. add_localhub();
  548. rehash_ip();
  549. /* set our shell info */
  550. uname(&un);
  551. set_user(&USERENTRY_OS, conf.bot->u, un.sysname);
  552. set_user(&USERENTRY_USERNAME, conf.bot->u, conf.username);
  553. set_user(&USERENTRY_NODENAME, conf.bot->u, un.nodename);
  554. set_user(&USERENTRY_ARCH, conf.bot->u, un.machine);
  555. set_user(&USERENTRY_OSVER, conf.bot->u, un.release);
  556. var_parse_my_botset();
  557. /* We should be safe now */
  558. reaffirm_owners();
  559. }
  560. /* Reload the user file from disk
  561. */
  562. void reload()
  563. {
  564. FILE *f = fopen(userfile, "r");
  565. if (f == NULL) {
  566. putlog(LOG_MISC, "*", "Can't reload user file!");
  567. return;
  568. }
  569. fclose(f);
  570. noshare = 1;
  571. clear_userlist(userlist);
  572. noshare = 0;
  573. userlist = NULL;
  574. loading = 1;
  575. checkchans(0);
  576. if (!readuserfile(userfile, &userlist))
  577. fatal("User file is missing!", 0);
  578. /* ensure we did not lose our internal users */
  579. load_internal_users();
  580. /* make sure I am added and conf.bot->u is set */
  581. add_myself_to_userlist();
  582. if (conf.bot->localhub)
  583. add_child_bots();
  584. else if (!conf.bot->hub)
  585. add_localhub();
  586. /* Make sure no removed users/bots are still connected. */
  587. check_stale_dcc_users();
  588. for (tand_t* bot = tandbot; bot; bot = bot->next)
  589. bot->u = get_user_by_handle(userlist, bot->bot);
  590. /* I don't think these will ever be called anyway. */
  591. if (!conf.bot->hub) {
  592. Auth::FillUsers();
  593. check_hostmask();
  594. }
  595. checkchans(1);
  596. loading = 0;
  597. var_parse_my_botset();
  598. reaffirm_owners();
  599. hook_read_userfile();
  600. }
  601. void setup_HQ(int n) {
  602. dcc[n].addr = iptolong(getmyip());
  603. dcc[n].sock = STDOUT;
  604. dcc[n].timeval = now;
  605. dcc[n].u.chat->con_flags = conmask | LOG_ALL;
  606. dcc[n].u.chat->strip_flags = STRIP_ALL;
  607. dcc[n].status = STAT_ECHO;
  608. strlcpy(dcc[n].nick, STR("HQ"), sizeof(dcc[n].nick));
  609. strlcpy(dcc[n].host, STR("llama@console"), sizeof(dcc[n].host));
  610. dcc[n].user = get_user_by_handle(userlist, dcc[n].nick);
  611. /* Make sure there's an innocuous HQ user if needed */
  612. if (!dcc[n].user) {
  613. userlist = adduser(userlist, dcc[n].nick, "none", "-", USER_ADMIN | USER_OWNER | USER_MASTER | USER_VOICE | USER_OP | USER_PARTY | USER_CHUBA | USER_HUBA, 0);
  614. dcc[n].user = get_user_by_handle(userlist, dcc[n].nick);
  615. }
  616. }
  617. /* Oddly enough, written by proton (Emech's coder)
  618. */
  619. int isowner(char *name)
  620. {
  621. if (!owner[0])
  622. return (0);
  623. if (!name || !name[0])
  624. return (0);
  625. char *pa = owner, *pb = owner;
  626. size_t nl = strlen(name), pl;
  627. while (1) {
  628. while (1) {
  629. if ((*pb == 0) || (*pb == ',') || (*pb == ' '))
  630. break;
  631. pb++;
  632. }
  633. pl = pb - pa;
  634. if (pl == nl && !strncasecmp(pa, name, nl))
  635. return (1);
  636. while (1) {
  637. if ((*pb == 0) || ((*pb != ',') && (*pb != ' ')))
  638. break;
  639. pb++;
  640. }
  641. if (*pb == 0)
  642. return (0);
  643. pa = pb;
  644. }
  645. }
  646. bool bot_shouldjoin(struct userrec* u, struct flag_record* fr, struct chanset_t* chan, bool ignore_inactive)
  647. {
  648. // If restarting, keep this channel.
  649. if (restarting && (reset_chans == 2) && (channel_active(chan) || channel_pending(chan))) return 1;
  650. /* If the bot is restarting (and hasn't finished getting the userfile for the first time) DO NOT JOIN channels - breaks +B/+backup */
  651. if (restarting || loading) return 0;
  652. // No user record, can't make any safe assumptions really
  653. if (!u) return 0;
  654. #ifdef DEBUG
  655. /* Force debugging bots to only join 3 channels */
  656. if (!strncmp(u->handle, "wtest", 5)) {
  657. if (!strcmp(chan->dname, "#skynet") ||
  658. !strcmp(chan->dname, "#bryan") ||
  659. !strcmp(chan->dname, "#wraith-devel"))
  660. return 1;
  661. else
  662. return 0;
  663. }
  664. #endif
  665. // Is this bot in the groups that this channel has?
  666. const char *botgroups = u == conf.bot->u ? groups : var_get_bot_data(u, "groups");
  667. bd::Array<bd::String> my_groupsArray(bd::String(botgroups).split(','));
  668. bool group_match = 0;
  669. if (chan->groups && chan->groups->length()) {
  670. for (size_t i = 0; i < my_groupsArray.length(); ++i) {
  671. if (chan->groups->find(my_groupsArray[i]) != chan->groups->npos) {
  672. group_match = 1;
  673. break;
  674. }
  675. }
  676. }
  677. // Ignore +inactive during cmd_slowjoin to ensure that +backup bots join
  678. return (!glob_kick(*fr) && !chan_kick(*fr) && // Not being kicked
  679. ((ignore_inactive || !channel_inactive(chan)) && // Not inactive
  680. ((channel_backup(chan) && (glob_backup(*fr) || chan_backup(*fr) || group_match)) || // Is +backup and I'm a backup bot or my group matches
  681. (!channel_backup(chan) && !glob_backup(*fr) && !chan_backup(*fr) && group_match))) // is -backup and I am not a backup bot and my group matches
  682. );
  683. }
  684. bool shouldjoin(struct chanset_t *chan)
  685. {
  686. struct flag_record fr = { FR_CHAN|FR_GLOBAL|FR_BOT, 0, 0, 0 };
  687. get_user_flagrec(conf.bot->u, &fr, chan->dname, chan);
  688. return bot_shouldjoin(conf.bot->u, &fr, chan);
  689. }
  690. /* do_chanset() set (options) on (chan)
  691. * USES DO_LOCAL|DO_NET bits.
  692. */
  693. int do_chanset(char *result, struct chanset_t *chan, const char *options, int flags)
  694. {
  695. int ret = OK;
  696. if (flags & DO_NET) {
  697. size_t bufsiz = 0;
  698. /* malloc(options,chan,'cset ',' ',+ 1) */
  699. if (chan)
  700. bufsiz = strlen(options) + strlen(chan->dname) + 5 + 1 + 1;
  701. else
  702. bufsiz = strlen(options) + 1 + 5 + 1 + 1;
  703. char *buf = (char*) my_calloc(1, bufsiz);
  704. strlcat(buf, "cset ", bufsiz);
  705. if (chan)
  706. strlcat(buf, chan->dname, bufsiz);
  707. else
  708. strlcat(buf, "*", bufsiz);
  709. strlcat(buf, " ", bufsiz);
  710. strlcat(buf, options, bufsiz);
  711. putlog(LOG_DEBUG, "*", "sending out cset: %s", buf);
  712. putallbots(buf);
  713. free(buf);
  714. }
  715. if (flags & DO_LOCAL) {
  716. bool cmd = (flags & CMD);
  717. struct chanset_t *ch = NULL;
  718. int all = chan ? 0 : 1;
  719. if (chan)
  720. ch = chan;
  721. else
  722. ch = chanset_default; //First iteration changes default, then move on to all chans
  723. while (ch) {
  724. const char **item = NULL;
  725. int items = 0;
  726. if (SplitList(result, options, &items, &item) == OK) {
  727. ret = channel_modify(result, ch, items, (char **) item, cmd);
  728. } else
  729. ret = ERROR;
  730. free(item);
  731. if (all) {
  732. if (ret == ERROR) /* just bail if there was an error, no sense in trying more */
  733. return ret;
  734. if (ch == chanset_default)
  735. ch = chanset;
  736. else
  737. ch = ch->next;
  738. } else {
  739. ch = NULL;
  740. }
  741. }
  742. }
  743. return ret;
  744. }
  745. char *
  746. samechans(const char *nick, const char *delim)
  747. {
  748. static char ret[1024] = "";
  749. struct chanset_t *chan = NULL;
  750. ret[0] = 0; /* may be filled from last time */
  751. for (chan = chanset; chan; chan = chan->next) {
  752. if (ismember(chan, nick)) {
  753. strlcat(ret, chan->dname, sizeof(ret));
  754. strlcat(ret, delim, sizeof(ret));
  755. }
  756. }
  757. return ret;
  758. }
  759. struct chanset_t* find_common_opped_chan(bd::String nick) {
  760. for (struct chanset_t* chan = chanset; chan; chan = chan->next) {
  761. if (channel_active(chan) && (me_op(chan) || me_voice(chan))) {
  762. if (ismember(chan, nick.c_str()))
  763. return chan;
  764. }
  765. }
  766. return NULL;
  767. }
  768. void privmsg(bd::String target, bd::String msg, int idx) {
  769. struct chanset_t* chan = NULL;
  770. if (have_cprivmsg && !strchr(CHANMETA, target[0]))
  771. chan = find_common_opped_chan(target);
  772. bool cleartextPrefix = (msg(0, 3) == "+p ");
  773. // Encrypt with FiSH?
  774. if (!strchr(CHANMETA, target[0]) && !cleartextPrefix && FishKeys.contains(target) && FishKeys[target]->sharedKey.length()) {
  775. msg = "+OK " + egg_bf_encrypt(msg, FishKeys[target]->sharedKey);
  776. }
  777. if (cleartextPrefix) {
  778. msg += static_cast<size_t>(3);
  779. }
  780. if (chan)
  781. dprintf(idx, "CPRIVMSG %s %s :%s\n", target.c_str(), chan->name, msg.c_str());
  782. else
  783. dprintf(idx, "PRIVMSG %s :%s\n", target.c_str(), msg.c_str());
  784. }
  785. void notice(bd::String target, bd::String msg, int idx) {
  786. struct chanset_t* chan = NULL;
  787. if (have_cnotice && !strchr(CHANMETA, target[0]))
  788. chan = find_common_opped_chan(target);
  789. if (chan)
  790. dprintf(idx, "CNOTICE %s %s :%s\n", target.c_str(), chan->name, msg.c_str());
  791. else
  792. dprintf(idx, "NOTICE %s :%s\n", target.c_str(), msg.c_str());
  793. }
  794. void check_removed_server(bool jump_no_match) {
  795. if (server_online) {
  796. int found_server = 0;
  797. for (struct server_list *n = serverlist; n; n = n->next) {
  798. // Check if server list contains a match to the 'real server name' we're connected to
  799. // ie, irc.sucks.net -> irc.servercentral.net (expected (dcc) -> real (cursrvname))
  800. if (((n->port && n->port == curservport) || (!n->port && default_port == curservport)) &&
  801. !strcmp(n->name, cursrvname)) {
  802. found_server = 1;
  803. break;
  804. // Check if server list contains a match to the 'expected server name' we're connected to
  805. // ie, irc.sucks.net -> irc.servercentral.net (expected (dcc) -> real (cursrvname))
  806. } else if (servidx != -1 && ((n->port && n->port == dcc[servidx].port) || (!n->port && default_port == dcc[servidx].port)) &&
  807. !strcmp(n->name, dcc[servidx].host)) {
  808. found_server = 2;
  809. break;
  810. }
  811. }
  812. if (!found_server) {
  813. if (jump_no_match) {
  814. // Current server not found in new list, jump!
  815. putlog(LOG_SERV, "*", "Server removed from list, jumping!");
  816. nuke_server("server removed");
  817. cycle_time = 0;
  818. }
  819. } else {
  820. // Update current server in list.
  821. curserv = -1;
  822. next_server(&curserv, found_server == 1 ? cursrvname : dcc[servidx].host, &curservport, NULL);
  823. }
  824. }
  825. }
  826. void keyx(const bd::String &target) {
  827. bd::String myPublicKeyB64, myPrivateKey, sharedKey;
  828. DH1080_gen(myPrivateKey, myPublicKeyB64);
  829. putlog(LOG_MSGS, "*", "[FiSH] Initiating DH1080 key-exchange with %s - sending my public key", target.c_str());
  830. notice(target, "DH1080_INIT " + myPublicKeyB64, DP_HELP);
  831. fish_data_t* fishData = new fish_data_t;
  832. fishData->myPublicKeyB64 = myPublicKeyB64;
  833. fishData->myPrivateKey = myPrivateKey;
  834. fishData->timestamp = now;
  835. FishKeys[target] = fishData;
  836. }