servmsg.c 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697
  1. #ifdef LEAF
  2. /*
  3. * servmsg.c -- part of server.mod
  4. *
  5. */
  6. #ifdef S_NODELAY
  7. #include <netinet/tcp.h>
  8. #endif
  9. char cursrvname[120]="";
  10. static time_t last_ctcp = (time_t) 0L;
  11. static int count_ctcp = 0;
  12. static char altnick_char = 0;
  13. /* We try to change to a preferred unique nick here. We always first try the
  14. * specified alternate nick. If that failes, we repeatedly modify the nick
  15. * until it gets accepted.
  16. *
  17. * sent nick:
  18. * "<altnick><c>"
  19. * ^--- additional count character: 1-9^-_\\[]`a-z
  20. * ^--------- given, alternate nick
  21. *
  22. * The last added character is always saved in altnick_char. At the very first
  23. * attempt (were altnick_char is 0), we try the alternate nick without any
  24. * additions.
  25. *
  26. * fixed by guppy (1999/02/24) and Fabian (1999/11/26)
  27. */
  28. static int gotfake433(char *from)
  29. {
  30. int l = strlen(botname) - 1;
  31. char *oknicks = "-_\\`^[]{}";
  32. Context;
  33. /* First run? */
  34. if (altnick_char == 0) {
  35. Context;
  36. altnick_char = oknicks[0];
  37. Context;
  38. if (l + 1 == NICKMAX) {
  39. Context;
  40. botname[l] = altnick_char;
  41. } else {
  42. Context;
  43. botname[++l] = altnick_char;
  44. botname[l + 1] = 0;
  45. }
  46. } else {
  47. char *p = strchr(oknicks, altnick_char);
  48. Context;
  49. p++;
  50. Context;
  51. if (!*p) {
  52. Context;
  53. altnick_char = 'a' + random() % 26;
  54. } else {
  55. Context;
  56. altnick_char = (*p);
  57. }
  58. Context;
  59. botname[l] = altnick_char;
  60. }
  61. putlog(LOG_SERV, "*", IRC_BOTNICKINUSE, botname);
  62. Context;
  63. dprintf(DP_MODE, "NICK %s\n", botname);
  64. Context;
  65. return 0;
  66. }
  67. /* Check for tcl-bound msg command, return 1 if found
  68. *
  69. * msg: proc-name <nick> <user@host> <handle> <args...>
  70. */
  71. static int check_tcl_msg(char *cmd, char *nick, char *uhost,
  72. struct userrec *u, char *args)
  73. {
  74. struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
  75. char *hand = u ? u->handle : "*";
  76. int x;
  77. get_user_flagrec(u, &fr, NULL);
  78. Tcl_SetVar(interp, "_msg1", nick, 0);
  79. Tcl_SetVar(interp, "_msg2", uhost, 0);
  80. Tcl_SetVar(interp, "_msg3", hand, 0);
  81. Tcl_SetVar(interp, "_msg4", args, 0);
  82. x = check_tcl_bind(H_msg, cmd, &fr, " $_msg1 $_msg2 $_msg3 $_msg4",
  83. MATCH_EXACT | BIND_HAS_BUILTINS | BIND_USE_ATTR);
  84. if (x == BIND_EXEC_LOG)
  85. putlog(LOG_CMDS, "*", "(%s!%s) !%s! %s %s", nick, uhost, hand,
  86. cmd, args);
  87. return ((x == BIND_MATCHED) || (x == BIND_EXECUTED) || (x == BIND_EXEC_LOG));
  88. }
  89. static int check_tcl_msgc(char *cmd, char *nick, char *uhost,
  90. struct userrec *u, char *args)
  91. {
  92. struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
  93. char *hand = u ? u->handle : "*";
  94. int x;
  95. get_user_flagrec(u, &fr, NULL);
  96. Tcl_SetVar(interp, "_msgc1", nick, 0);
  97. Tcl_SetVar(interp, "_msgc2", uhost, 0);
  98. Tcl_SetVar(interp, "_msgc3", hand, 0);
  99. Tcl_SetVar(interp, "_msgc4", args, 0);
  100. Tcl_SetVar(interp, "_msgc5", NULL, 0);
  101. x = check_tcl_bind(H_msgc, cmd, &fr, " $_msgc1 $_msgc2 $_msgc3 $_msgc4 $_msgc5",
  102. MATCH_EXACT | BIND_HAS_BUILTINS | BIND_USE_ATTR);
  103. if (x == BIND_EXEC_LOG)
  104. putlog(LOG_CMDS, "*", "(%s!%s) !%s! %s%s %s", nick, uhost, hand, cmdprefix,
  105. cmd, args);
  106. return ((x == BIND_MATCHED) || (x == BIND_EXECUTED) || (x == BIND_EXEC_LOG));
  107. }
  108. static void check_tcl_notc(char *nick, char *uhost, struct userrec *u,
  109. char *dest, char *arg)
  110. {
  111. struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
  112. get_user_flagrec(u, &fr, NULL);
  113. Tcl_SetVar(interp, "_notc1", nick, 0);
  114. Tcl_SetVar(interp, "_notc2", uhost, 0);
  115. Tcl_SetVar(interp, "_notc3", u ? u->handle : "*", 0);
  116. Tcl_SetVar(interp, "_notc4", arg, 0);
  117. Tcl_SetVar(interp, "_notc5", dest, 0);
  118. check_tcl_bind(H_notc, arg, &fr, " $_notc1 $_notc2 $_notc3 $_notc4 $_notc5",
  119. MATCH_MASK | BIND_USE_ATTR | BIND_STACKABLE);
  120. }
  121. static void check_tcl_msgm(char *cmd, char *nick, char *uhost,
  122. struct userrec *u, char *arg)
  123. {
  124. struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
  125. char args[1024];
  126. if (arg[0])
  127. simple_sprintf(args, "%s %s", cmd, arg);
  128. else
  129. strcpy(args, cmd);
  130. get_user_flagrec(u, &fr, NULL);
  131. Tcl_SetVar(interp, "_msgm1", nick, 0);
  132. Tcl_SetVar(interp, "_msgm2", uhost, 0);
  133. Tcl_SetVar(interp, "_msgm3", u ? u->handle : "*", 0);
  134. Tcl_SetVar(interp, "_msgm4", args, 0);
  135. check_tcl_bind(H_msgm, args, &fr, " $_msgm1 $_msgm2 $_msgm3 $_msgm4",
  136. MATCH_MASK | BIND_USE_ATTR | BIND_STACKABLE);
  137. }
  138. /* Return 1 if processed.
  139. */
  140. static int check_tcl_raw(char *from, char *code, char *msg)
  141. {
  142. int x;
  143. Context;
  144. Tcl_SetVar(interp, "_raw1", from, 0);
  145. Tcl_SetVar(interp, "_raw2", code, 0);
  146. Tcl_SetVar(interp, "_raw3", msg, 0);
  147. x = check_tcl_bind(H_raw, code, 0, " $_raw1 $_raw2 $_raw3",
  148. MATCH_EXACT | BIND_STACKABLE | BIND_WANTRET);
  149. return (x == BIND_EXEC_LOG);
  150. }
  151. static int check_tcl_ctcpr(char *nick, char *uhost, struct userrec *u,
  152. char *dest, char *keyword, char *args,
  153. p_tcl_bind_list table)
  154. {
  155. struct flag_record fr = {FR_GLOBAL | FR_CHAN | FR_ANYWH, 0, 0, 0, 0, 0};
  156. int x;
  157. get_user_flagrec(u, &fr, NULL);
  158. Tcl_SetVar(interp, "_ctcpr1", nick, 0);
  159. Tcl_SetVar(interp, "_ctcpr2", uhost, 0);
  160. Tcl_SetVar(interp, "_ctcpr3", u ? u->handle : "*", 0);
  161. Tcl_SetVar(interp, "_ctcpr4", dest, 0);
  162. Tcl_SetVar(interp, "_ctcpr5", keyword, 0);
  163. Tcl_SetVar(interp, "_ctcpr6", args, 0);
  164. x = check_tcl_bind(table, keyword, &fr,
  165. " $_ctcpr1 $_ctcpr2 $_ctcpr3 $_ctcpr4 $_ctcpr5 $_ctcpr6",
  166. MATCH_MASK | BIND_USE_ATTR | BIND_STACKABLE |
  167. ((table == H_ctcp) ? BIND_WANTRET : 0));
  168. return (x == BIND_EXEC_LOG) || (table == H_ctcr);
  169. }
  170. static int check_tcl_wall(char *from, char *msg)
  171. {
  172. int x;
  173. Tcl_SetVar(interp, "_wall1", from, 0);
  174. Tcl_SetVar(interp, "_wall2", msg, 0);
  175. x = check_tcl_bind(H_wall, msg, 0, " $_wall1 $_wall2",
  176. MATCH_MASK | BIND_STACKABLE);
  177. if (x == BIND_EXEC_LOG) {
  178. putlog(LOG_WALL, "*", "!%s! %s", from, msg);
  179. return 1;
  180. } else
  181. return 0;
  182. }
  183. static int check_tcl_flud(char *nick, char *uhost, struct userrec *u,
  184. char *ftype, char *chname)
  185. {
  186. int x;
  187. Tcl_SetVar(interp, "_flud1", nick, 0);
  188. Tcl_SetVar(interp, "_flud2", uhost, 0);
  189. Tcl_SetVar(interp, "_flud3", u ? u->handle : "*", 0);
  190. Tcl_SetVar(interp, "_flud4", ftype, 0);
  191. Tcl_SetVar(interp, "_flud5", chname, 0);
  192. x = check_tcl_bind(H_flud, ftype, 0,
  193. " $_flud1 $_flud2 $_flud3 $_flud4 $_flud5",
  194. MATCH_MASK | BIND_STACKABLE | BIND_WANTRET);
  195. return (x == BIND_EXEC_LOG);
  196. }
  197. static int match_my_nick(char *nick)
  198. {
  199. if (!rfc_casecmp(nick, botname))
  200. return 1;
  201. return 0;
  202. }
  203. /* 001: welcome to IRC (use it to fix the server name)
  204. */
  205. static int got001(char *from, char *msg)
  206. {
  207. struct server_list *x;
  208. int i, servidx = findanyidx(serv);
  209. struct chanset_t *chan;
  210. /* Ok...param #1 of 001 = what server thinks my nick is */
  211. server_online = now;
  212. fixcolon(msg);
  213. strncpyz(botname, msg, NICKLEN);
  214. altnick_char = 0;
  215. strncpy0(cursrvname, from, sizeof(cursrvname));
  216. dprintf(DP_SERVER, "WHOIS %s\n", botname); /* get user@host */
  217. /* Call Tcl init-server */
  218. if (initserver[0])
  219. do_tcl("init-server", initserver);
  220. check_tcl_event("init-server");
  221. x = serverlist;
  222. if (x == NULL)
  223. return 0; /* Uh, no server list */
  224. /* Only join if the IRC module is loaded. */
  225. if (module_find("irc", 0, 0))
  226. for (chan = chanset; chan; chan = chan->next) {
  227. chan->status &= ~(CHAN_ACTIVE | CHAN_PEND);
  228. if (!channel_inactive(chan))
  229. dprintf(DP_SERVER, "JOIN %s %s\n",
  230. (chan->name[0]) ? chan->name : chan->dname,
  231. chan->channel.key[0] ? chan->channel.key : chan->key_prot);
  232. }
  233. if (egg_strcasecmp(from, dcc[servidx].host)) {
  234. putlog(LOG_MISC, "*", "(%s claims to be %s; updating server list)",
  235. dcc[servidx].host, from);
  236. for (i = curserv; i > 0 && x != NULL; i--)
  237. x = x->next;
  238. if (x == NULL) {
  239. putlog(LOG_MISC, "*", "Invalid server list!");
  240. return 0;
  241. }
  242. if (x->realname)
  243. nfree(x->realname);
  244. if (strict_servernames == 1) {
  245. x->realname = NULL;
  246. if (x->name)
  247. nfree(x->name);
  248. x->name = nmalloc(strlen(from) + 1);
  249. strcpy(x->name, from);
  250. } else {
  251. x->realname = nmalloc(strlen(from) + 1);
  252. strcpy(x->realname, from);
  253. }
  254. }
  255. return 0;
  256. }
  257. /* Got 442: not on channel
  258. */
  259. static int got442(char *from, char *msg)
  260. {
  261. char *chname;
  262. struct chanset_t *chan;
  263. struct server_list *x;
  264. int i;
  265. for (x = serverlist, i = 0; x; x = x->next, i++)
  266. if (i == curserv) {
  267. if (egg_strcasecmp(from, x->realname ? x->realname : x->name))
  268. return 0;
  269. break;
  270. }
  271. newsplit(&msg);
  272. chname = newsplit(&msg);
  273. chan = findchan(chname);
  274. if (chan)
  275. if (!channel_inactive(chan)) {
  276. module_entry *me = module_find("channels", 0, 0);
  277. putlog(LOG_MISC, chname, IRC_SERVNOTONCHAN, chname);
  278. if (me && me->funcs)
  279. (me->funcs[CHANNEL_CLEAR])(chan, 1);
  280. chan->status &= ~CHAN_ACTIVE;
  281. dprintf(DP_MODE, "JOIN %s %s\n", chan->name,
  282. chan->channel.key[0] ? chan->channel.key : chan->key_prot);
  283. }
  284. return 0;
  285. }
  286. /* Close the current server connection.
  287. */
  288. static void nuke_server(char *reason)
  289. {
  290. if (serv >= 0) {
  291. int servidx = findanyidx(serv);
  292. if (reason && (servidx > 0))
  293. dprintf(servidx, "QUIT :%s\n", reason);
  294. disconnect_server(servidx);
  295. lostdcc(servidx);
  296. }
  297. }
  298. static char ctcp_reply[1024] = "";
  299. static int lastmsgs[FLOOD_GLOBAL_MAX];
  300. static char lastmsghost[FLOOD_GLOBAL_MAX][81];
  301. static time_t lastmsgtime[FLOOD_GLOBAL_MAX];
  302. /* Do on NICK, PRIVMSG, NOTICE and JOIN.
  303. */
  304. static int detect_flood(char *floodnick, char *floodhost, char *from, int which)
  305. {
  306. char *p, ftype[10], h[1024];
  307. struct userrec *u;
  308. int thr = 0, lapse = 0, atr;
  309. u = get_user_by_host(from);
  310. atr = u ? u->flags : 0;
  311. if (atr & (USER_BOT))
  312. return 0;
  313. if (isauthed(floodhost) > -1)
  314. return 0;
  315. /* Determine how many are necessary to make a flood */
  316. switch (which) {
  317. case FLOOD_PRIVMSG:
  318. case FLOOD_NOTICE:
  319. thr = flud_thr;
  320. lapse = flud_time;
  321. strcpy(ftype, "msg");
  322. break;
  323. case FLOOD_CTCP:
  324. thr = flud_ctcp_thr;
  325. lapse = flud_ctcp_time;
  326. strcpy(ftype, "ctcp");
  327. break;
  328. }
  329. if ((thr == 0) || (lapse == 0))
  330. return 0; /* No flood protection */
  331. /* Okay, make sure i'm not flood-checking myself */
  332. if (match_my_nick(floodnick))
  333. return 0;
  334. if (!egg_strcasecmp(floodhost, botuserhost))
  335. return 0; /* My user@host (?) */
  336. p = strchr(floodhost, '@');
  337. if (p) {
  338. p++;
  339. if (egg_strcasecmp(lastmsghost[which], p)) { /* New */
  340. strcpy(lastmsghost[which], p);
  341. lastmsgtime[which] = now;
  342. lastmsgs[which] = 0;
  343. return 0;
  344. }
  345. } else
  346. return 0; /* Uh... whatever. */
  347. if (lastmsgtime[which] < now - lapse) {
  348. /* Flood timer expired, reset it */
  349. lastmsgtime[which] = now;
  350. lastmsgs[which] = 0;
  351. return 0;
  352. }
  353. lastmsgs[which]++;
  354. if (lastmsgs[which] >= thr) { /* FLOOD */
  355. /* Reset counters */
  356. lastmsgs[which] = 0;
  357. lastmsgtime[which] = 0;
  358. lastmsghost[which][0] = 0;
  359. u = get_user_by_host(from);
  360. if (check_tcl_flud(floodnick, floodhost, u, ftype, "*"))
  361. return 0;
  362. /* Private msg */
  363. simple_sprintf(h, "*!*@%s", p);
  364. putlog(LOG_MISC, "*", IRC_FLOODIGNORE1, p);
  365. addignore(h, botnetnick, (which == FLOOD_CTCP) ? "CTCP flood" :
  366. "MSG/NOTICE flood", now + (60 * ignore_time));
  367. }
  368. return 0;
  369. }
  370. /* Check for more than 8 control characters in a line.
  371. * This could indicate: beep flood CTCP avalanche.
  372. */
  373. static int detect_avalanche(char *msg)
  374. {
  375. int count = 0;
  376. unsigned char *p;
  377. for (p = (unsigned char *) msg; (*p) && (count < 8); p++)
  378. if ((*p == 7) || (*p == 1))
  379. count++;
  380. if (count >= 8)
  381. return 1;
  382. else
  383. return 0;
  384. }
  385. /* Got a private message.
  386. */
  387. static int gotmsg(char *from, char *msg)
  388. {
  389. char *to, buf[UHOSTLEN], *nick, ctcpbuf[512], *uhost = buf, *ctcp;
  390. char *p, *p1, *code;
  391. struct userrec *u;
  392. int ctcp_count = 0, i;
  393. int ignoring = 0;
  394. if (msg[0] && ((strchr(CHANMETA, *msg) != NULL) ||
  395. (*msg == '@'))) /* Notice to a channel, not handled here */
  396. return 0;
  397. ignoring = match_ignore(from);
  398. to = newsplit(&msg);
  399. fixcolon(msg);
  400. /* Only check if flood-ctcp is active */
  401. strcpy(uhost, from);
  402. nick = splitnick(&uhost);
  403. if (flud_ctcp_thr && detect_avalanche(msg)) {
  404. if (!ignoring) {
  405. putlog(LOG_MODES, "*", "Avalanche from %s - ignoring", from);
  406. p = strchr(uhost, '@');
  407. if (p != NULL)
  408. p++;
  409. else
  410. p = uhost;
  411. simple_sprintf(ctcpbuf, "*!*@%s", p);
  412. addignore(ctcpbuf, botnetnick, "ctcp avalanche",
  413. now + (60 * ignore_time));
  414. }
  415. }
  416. /* Check for CTCP: */
  417. ctcp_reply[0] = 0;
  418. p = strchr(msg, 1);
  419. while ((p != NULL) && (*p)) {
  420. p++;
  421. p1 = p;
  422. while ((*p != 1) && (*p != 0))
  423. p++;
  424. if (*p == 1) {
  425. *p = 0;
  426. ctcp = strcpy(ctcpbuf, p1);
  427. strcpy(p1 - 1, p + 1);
  428. if (!ignoring)
  429. detect_flood(nick, uhost, from,
  430. strncmp(ctcp, "ACTION ", 7) ? FLOOD_CTCP : FLOOD_PRIVMSG);
  431. /* Respond to the first answer_ctcp */
  432. p = strchr(msg, 1);
  433. if (ctcp_count < answer_ctcp) {
  434. ctcp_count++;
  435. if (ctcp[0] != ' ') {
  436. code = newsplit(&ctcp);
  437. if ((to[0] == '$') || strchr(to, '.')) {
  438. if (!ignoring)
  439. /* Don't interpret */
  440. putlog(LOG_PUBLIC, to, "CTCP %s: %s from %s (%s) to %s",
  441. code, ctcp, nick, uhost, to);
  442. } else {
  443. u = get_user_by_host(from);
  444. if (!ignoring || trigger_on_ignore) {
  445. if (!check_tcl_ctcp(nick, uhost, u, to, code, ctcp) &&
  446. !ignoring) {
  447. if ((lowercase_ctcp && !egg_strcasecmp(code, "DCC")) ||
  448. (!lowercase_ctcp && !strcmp(code, "DCC"))) {
  449. /* If it gets this far unhandled, it means that
  450. * the user is totally unknown.
  451. */
  452. code = newsplit(&ctcp);
  453. if (!strcmp(code, "CHAT")) {
  454. if (!quiet_reject) {
  455. if (u)
  456. dprintf(DP_HELP, "NOTICE %s :%s\n", nick,
  457. "I'm not accepting call at the moment.");
  458. else
  459. dprintf(DP_HELP, "NOTICE %s :%s\n",
  460. nick, DCC_NOSTRANGERS);
  461. }
  462. putlog(LOG_MISC, "*", "%s: %s",
  463. DCC_REFUSED, from);
  464. } else
  465. putlog(LOG_MISC, "*", "Refused DCC %s: %s",
  466. code, from);
  467. }
  468. }
  469. if (!strcmp(code, "ACTION")) {
  470. putlog(LOG_MSGS, "*", "Action to %s: %s %s",
  471. to, nick, ctcp);
  472. } else {
  473. putlog(LOG_MSGS, "*", "CTCP %s: %s from %s (%s)",
  474. code, ctcp, nick, uhost);
  475. } /* I love a good close cascade ;) */
  476. }
  477. }
  478. }
  479. }
  480. }
  481. }
  482. /* Send out possible ctcp responses */
  483. if (ctcp_reply[0]) {
  484. if (ctcp_mode != 2) {
  485. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, ctcp_reply);
  486. } else {
  487. if (now - last_ctcp > flud_ctcp_time) {
  488. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, ctcp_reply);
  489. count_ctcp = 1;
  490. } else if (count_ctcp < flud_ctcp_thr) {
  491. dprintf(DP_HELP, "NOTICE %s :%s\n", nick, ctcp_reply);
  492. count_ctcp++;
  493. }
  494. last_ctcp = now;
  495. }
  496. }
  497. if (msg[0]) {
  498. if ((to[0] == '$') || (strchr(to, '.') != NULL)) {
  499. /* Msg from oper */
  500. if (!ignoring) {
  501. detect_flood(nick, uhost, from, FLOOD_PRIVMSG);
  502. /* Do not interpret as command */
  503. putlog(LOG_MSGS | LOG_SERV, "*", "[%s!%s to %s] %s",nick, uhost, to, msg);
  504. }
  505. } else {
  506. char *code;
  507. struct userrec *u;
  508. detect_flood(nick, uhost, from, FLOOD_PRIVMSG);
  509. u = get_user_by_host(from);
  510. code = newsplit(&msg);
  511. rmspace(msg);
  512. Context;
  513. i = isauthed(uhost);
  514. /* is it a cmd? */
  515. Context;
  516. if (i > -1 && auth[i].authed && code[0] == cmdprefix[0] && code[1]) {
  517. code++;
  518. Context;
  519. u = auth[i].user;
  520. if (check_tcl_msgc(code, nick, uhost, u, msg))
  521. auth[i].atime = now;
  522. else
  523. putlog(LOG_MSGS, "*", "[%s] %s %s", from, code, msg);
  524. } else if ((code[0] != cmdprefix[0] || !code[1] || i == -1 || !(auth[i].authed))) {
  525. Context;
  526. if (!ignoring || trigger_on_ignore)
  527. check_tcl_msgm(code, nick, uhost, u, msg);
  528. if (!ignoring)
  529. if (!check_tcl_msg(code, nick, uhost, u, msg))
  530. putlog(LOG_MSGS, "*", "[%s] %s %s", from, code, msg);
  531. }
  532. }
  533. }
  534. return 0;
  535. }
  536. /* Got a private notice.
  537. */
  538. static int gotnotice(char *from, char *msg)
  539. {
  540. char *to, *nick, ctcpbuf[512], *p, *p1, buf[512], *uhost = buf, *ctcp;
  541. struct userrec *u;
  542. int ignoring;
  543. if (msg[0] && ((strchr(CHANMETA, *msg) != NULL) ||
  544. (*msg == '@'))) /* Notice to a channel, not handled here */
  545. return 0;
  546. ignoring = match_ignore(from);
  547. to = newsplit(&msg);
  548. fixcolon(msg);
  549. strcpy(uhost, from);
  550. nick = splitnick(&uhost);
  551. if (flud_ctcp_thr && detect_avalanche(msg)) {
  552. /* Discard -- kick user if it was to the channel */
  553. if (!ignoring)
  554. putlog(LOG_MODES, "*", "Avalanche from %s", from);
  555. return 0;
  556. }
  557. /* Check for CTCP: */
  558. p = strchr(msg, 1);
  559. while ((p != NULL) && (*p)) {
  560. p++;
  561. p1 = p;
  562. while ((*p != 1) && (*p != 0))
  563. p++;
  564. if (*p == 1) {
  565. *p = 0;
  566. ctcp = strcpy(ctcpbuf, p1);
  567. strcpy(p1 - 1, p + 1);
  568. if (!ignoring)
  569. detect_flood(nick, uhost, from, FLOOD_CTCP);
  570. p = strchr(msg, 1);
  571. if (ctcp[0] != ' ') {
  572. char *code = newsplit(&ctcp);
  573. if ((to[0] == '$') || strchr(to, '.')) {
  574. if (!ignoring)
  575. putlog(LOG_PUBLIC, "*",
  576. "CTCP reply %s: %s from %s (%s) to %s", code, ctcp,
  577. nick, uhost, to);
  578. } else {
  579. u = get_user_by_host(from);
  580. if (!ignoring || trigger_on_ignore) {
  581. check_tcl_ctcr(nick, uhost, u, to, code, ctcp);
  582. if (!ignoring)
  583. /* Who cares? */
  584. putlog(LOG_MSGS, "*",
  585. "CTCP reply %s: %s from %s (%s) to %s",
  586. code, ctcp, nick, uhost, to);
  587. }
  588. }
  589. }
  590. }
  591. }
  592. if (msg[0]) {
  593. if (((to[0] == '$') || strchr(to, '.')) && !ignoring) {
  594. detect_flood(nick, uhost, from, FLOOD_NOTICE);
  595. putlog(LOG_MSGS | LOG_SERV, "*", "-%s (%s) to %s- %s",
  596. nick, uhost, to, msg);
  597. } else {
  598. /* Server notice? */
  599. if ((nick[0] == 0) || (uhost[0] == 0)) {
  600. /* Hidden `250' connection count message from server */
  601. if (strncmp(msg, "Highest connection count:", 25))
  602. putlog(LOG_SERV, "*", "-NOTICE- %s", msg);
  603. } else {
  604. detect_flood(nick, uhost, from, FLOOD_NOTICE);
  605. u = get_user_by_host(from);
  606. if (!ignoring || trigger_on_ignore)
  607. check_tcl_notc(nick, uhost, u, botname, msg);
  608. if (!ignoring)
  609. putlog(LOG_MSGS, "*", "-%s (%s)- %s", nick, uhost, msg);
  610. }
  611. }
  612. }
  613. return 0;
  614. }
  615. /* got 251: lusers
  616. * <server> 251 <to> :there are 2258 users and 805 invisible on 127 servers
  617. */
  618. static int got251(char *from, char *msg)
  619. {
  620. int i;
  621. char *servs;
  622. if (min_servs == 0)
  623. return 0; /* No minimum limit on servers */
  624. newsplit(&msg);
  625. fixcolon(msg); /* NOTE!!! If servlimit is not set or is 0 */
  626. for (i = 0; i < 8; i++)
  627. newsplit(&msg); /* lusers IS NOT SENT AT ALL!! */
  628. servs = newsplit(&msg);
  629. if (strncmp(msg, "servers", 7))
  630. return 0; /* Was invalid format */
  631. while (*servs && (*servs < 32))
  632. servs++; /* I've seen some lame nets put bolds &
  633. * stuff in here :/ */
  634. i = atoi(servs);
  635. if (i < min_servs) {
  636. putlog(LOG_SERV, "*", IRC_AUTOJUMP, min_servs, i);
  637. nuke_server(IRC_CHANGINGSERV);
  638. }
  639. return 0;
  640. }
  641. /* WALLOPS: oper's nuisance
  642. */
  643. static int gotwall(char *from, char *msg)
  644. {
  645. char *nick;
  646. int r;
  647. fixcolon(msg);
  648. r = check_tcl_wall(from, msg);
  649. if (r == 0) {
  650. /* Following is not needed at all, but we'll keep it for compatibility sak$
  651. * so not to confuse possible scripts that are parsing log files.
  652. */
  653. if (strchr(from, '!')) {
  654. nick = splitnick(&from);
  655. putlog(LOG_WALL, "*", "!%s(%s)! %s", nick, from, msg);
  656. } else
  657. putlog(LOG_WALL, "*", "!%s! %s", from, msg);
  658. }
  659. return 0;
  660. }
  661. static void server_10secondly()
  662. {
  663. char *alt;
  664. if (!server_online)
  665. return;
  666. if (keepnick) {
  667. /* NOTE: now that botname can but upto NICKLEN bytes long,
  668. * check that it's not just a truncation of the full nick.
  669. */
  670. if (strncmp(botname, origbotname, strlen(botname))) {
  671. /* See if my nickname is in use and if if my nick is right. */
  672. alt = get_altbotnick();
  673. if (alt[0] && egg_strcasecmp (botname, alt))
  674. dprintf(DP_SERVER, "ISON :%s %s %s\n", botname, origbotname, alt);
  675. else
  676. dprintf(DP_SERVER, "ISON :%s %s\n", botname, origbotname);
  677. }
  678. }
  679. }
  680. /* Called once a minute... but if we're the only one on the
  681. * channel, we only wanna send out "lusers" once every 5 mins.
  682. */
  683. static void minutely_checks()
  684. {
  685. static int count = 4;
  686. int ok = 0;
  687. struct chanset_t *chan;
  688. /* Only check if we have already successfully logged in. */
  689. if (!server_online)
  690. return;
  691. if (min_servs == 0)
  692. return;
  693. for (chan = chanset; chan; chan = chan->next)
  694. if (channel_active(chan) && chan->channel.members == 1) {
  695. ok = 1;
  696. break;
  697. }
  698. if (!ok)
  699. return;
  700. count++;
  701. if (count >= 5) {
  702. dprintf(DP_SERVER, "LUSERS\n");
  703. count = 0;
  704. }
  705. }
  706. /* Pong from server.
  707. */
  708. static int gotpong(char *from, char *msg)
  709. {
  710. newsplit(&msg);
  711. fixcolon(msg); /* Scrap server name */
  712. server_lag = now - my_atoul(msg);
  713. if (server_lag > 99999) {
  714. /* IRCnet lagmeter support by drummer */
  715. server_lag = now - lastpingtime;
  716. }
  717. return 0;
  718. }
  719. /* This is a reply on ISON :<current> <orig> [<alt>]
  720. */
  721. static void got303(char *from, char *msg)
  722. {
  723. char *tmp, *alt;
  724. int ison_orig = 0, ison_alt = 0;
  725. if (!keepnick ||
  726. !strncmp(botname, origbotname, strlen(botname))) {
  727. return;
  728. }
  729. newsplit(&msg);
  730. fixcolon(msg);
  731. alt = get_altbotnick();
  732. tmp = newsplit(&msg);
  733. if (tmp[0] && !rfc_casecmp(botname, tmp)) {
  734. while ((tmp = newsplit(&msg))[0]) { /* no, it's NOT == */
  735. if (!rfc_casecmp(tmp, origbotname))
  736. ison_orig = 1;
  737. else if (alt[0] && !rfc_casecmp(tmp, alt))
  738. ison_alt = 1;
  739. }
  740. if (!ison_orig) {
  741. if (!nick_juped)
  742. putlog(LOG_MISC, "*", IRC_GETORIGNICK, origbotname);
  743. dprintf(DP_SERVER, "NICK %s\n", origbotname);
  744. } else if (alt[0] && !ison_alt && rfc_casecmp(botname, alt)) {
  745. putlog(LOG_MISC, "*", IRC_GETALTNICK, alt);
  746. dprintf(DP_SERVER, "NICK %s\n", alt);
  747. }
  748. }
  749. }
  750. /* 432 : Bad nickname
  751. */
  752. static int got432(char *from, char *msg)
  753. {
  754. char *erroneus;
  755. newsplit(&msg);
  756. erroneus = newsplit(&msg);
  757. if (server_online)
  758. putlog(LOG_MISC, "*", "NICK IS INVALID: %s (keeping '%s').", erroneus,
  759. botname);
  760. else {
  761. putlog(LOG_MISC, "*", IRC_BADBOTNICK);
  762. if (!keepnick) {
  763. makepass(erroneus);
  764. erroneus[NICKMAX] = 0;
  765. dprintf(DP_MODE, "NICK %s\n", erroneus);
  766. }
  767. return 0;
  768. }
  769. return 0;
  770. }
  771. /* 433 : Nickname in use
  772. * Change nicks till we're acceptable or we give up
  773. */
  774. static int got433(char *from, char *msg)
  775. {
  776. char *tmp;
  777. Context;
  778. if (server_online) {
  779. /* We are online and have a nickname, we'll keep it */
  780. newsplit(&msg);
  781. tmp = newsplit(&msg);
  782. putlog(LOG_MISC, "*", "NICK IN USE: %s (keeping '%s').", tmp, botname);
  783. nick_juped = 0;
  784. return 0;
  785. }
  786. Context;
  787. gotfake433(from);
  788. Context;
  789. return 0;
  790. }
  791. /* 437 : Nickname juped (IRCnet)
  792. */
  793. static int got437(char *from, char *msg)
  794. {
  795. char *s;
  796. struct chanset_t *chan;
  797. newsplit(&msg);
  798. s = newsplit(&msg);
  799. if (s[0] && (strchr(CHANMETA, s[0]) != NULL)) {
  800. chan = findchan(s);
  801. if (chan) {
  802. if (chan->status & CHAN_ACTIVE) {
  803. putlog(LOG_MISC, "*", IRC_CANTCHANGENICK, s);
  804. } else {
  805. if (!channel_juped(chan)) {
  806. putlog(LOG_MISC, "*", IRC_CHANNELJUPED, s);
  807. chan->status |= CHAN_JUPED;
  808. }
  809. }
  810. }
  811. } else if (server_online) {
  812. if (!nick_juped)
  813. putlog(LOG_MISC, "*", "NICK IS JUPED: %s (keeping '%s').", s, botname);
  814. if (!rfc_casecmp(s, origbotname))
  815. nick_juped = 1;
  816. } else {
  817. putlog(LOG_MISC, "*", "%s: %s", IRC_BOTNICKJUPED, s);
  818. gotfake433(from);
  819. }
  820. return 0;
  821. }
  822. /* 438 : Nick change too fast
  823. */
  824. static int got438(char *from, char *msg)
  825. {
  826. newsplit(&msg);
  827. newsplit(&msg);
  828. fixcolon(msg);
  829. putlog(LOG_MISC, "*", "%s", msg);
  830. return 0;
  831. }
  832. static int got451(char *from, char *msg)
  833. {
  834. /* Usually if we get this then we really messed up somewhere
  835. * or this is a non-standard server, so we log it and kill the socket
  836. * hoping the next server will work :) -poptix
  837. */
  838. /* Um, this does occur on a lagged anti-spoof server connection if the
  839. * (minutely) sending of joins occurs before the bot does its ping reply.
  840. * Probably should do something about it some time - beldin
  841. */
  842. putlog(LOG_MISC, "*", IRC_NOTREGISTERED1, from);
  843. nuke_server(IRC_NOTREGISTERED2);
  844. return 0;
  845. }
  846. /* Got error notice
  847. */
  848. static int goterror(char *from, char *msg)
  849. {
  850. /* FIXME: fixcolon doesn't do what we need here, this is a temp fix
  851. * fixcolon(msg);
  852. */
  853. if (msg[0] == ':')
  854. msg++;
  855. putlog(LOG_SERV, "*", "-ERROR from server- %s", msg);
  856. if (serverror_quit) {
  857. putlog(LOG_SERV, "*", "Disconnecting from server.");
  858. nuke_server("Bah, stupid error messages.");
  859. }
  860. return 1;
  861. }
  862. /* Got nick change.
  863. */
  864. static int gotnick(char *from, char *msg)
  865. {
  866. char *nick, *alt = get_altbotnick();
  867. struct userrec *u;
  868. u = get_user_by_host(from);
  869. nick = splitnick(&from);
  870. fixcolon(msg);
  871. check_queues(nick, msg);
  872. if (match_my_nick(nick)) {
  873. /* Regained nick! */
  874. strncpyz(botname, msg, NICKLEN);
  875. altnick_char = 0;
  876. if (!strcmp(msg, origbotname)) {
  877. putlog(LOG_SERV | LOG_MISC, "*", "Regained nickname '%s'.", msg);
  878. nick_juped = 0;
  879. } else if (alt[0] && !strcmp(msg, alt))
  880. putlog(LOG_SERV | LOG_MISC, "*", "Regained alternate nickname '%s'.",
  881. msg);
  882. else if (keepnick && strcmp(nick, msg)) {
  883. putlog(LOG_SERV | LOG_MISC, "*", "Nickname changed to '%s'???", msg);
  884. if (!rfc_casecmp(nick, origbotname)) {
  885. putlog(LOG_MISC, "*", IRC_GETORIGNICK, origbotname);
  886. dprintf(DP_SERVER, "NICK %s\n", origbotname);
  887. } else if (alt[0] && !rfc_casecmp(nick, alt)
  888. && egg_strcasecmp(botname, origbotname)) {
  889. putlog(LOG_MISC, "*", IRC_GETALTNICK, alt);
  890. dprintf(DP_SERVER, "NICK %s\n", alt);
  891. }
  892. } else
  893. putlog(LOG_SERV | LOG_MISC, "*", "Nickname changed to '%s'???", msg);
  894. } else if ((keepnick) && (rfc_casecmp(nick, msg))) {
  895. /* Only do the below if there was actual nick change, case doesn't count */
  896. if (!rfc_casecmp(nick, origbotname)) {
  897. putlog(LOG_MISC, "*", IRC_GETORIGNICK, origbotname);
  898. dprintf(DP_SERVER, "NICK %s\n", origbotname);
  899. } else if (alt[0] && !rfc_casecmp(nick, alt) &&
  900. egg_strcasecmp(botname, origbotname)) {
  901. putlog(LOG_MISC, "*", IRC_GETALTNICK, altnick);
  902. dprintf(DP_SERVER, "NICK %s\n", altnick);
  903. }
  904. }
  905. return 0;
  906. }
  907. static int gotmode(char *from, char *msg)
  908. {
  909. char *ch;
  910. Context;
  911. ch = newsplit(&msg);
  912. /* Usermode changes? */
  913. if (strchr(CHANMETA, ch[0]) == NULL) {
  914. if (match_my_nick(ch) && check_mode_r) {
  915. /* umode +r? - D0H dalnet uses it to mean something different */
  916. fixcolon(msg);
  917. if ((msg[0] == '+') && strchr(msg, 'r')) {
  918. int servidx = findanyidx(serv);
  919. putlog(LOG_MISC | LOG_JOIN, "*",
  920. "%s has me i-lined (jumping)", dcc[servidx].host);
  921. nuke_server("i-lines suck");
  922. }
  923. }
  924. }
  925. return 0;
  926. }
  927. static void disconnect_server(int idx)
  928. {
  929. if (server_online > 0)
  930. check_tcl_event("disconnect-server");
  931. server_online = 0;
  932. if (dcc[idx].sock >= 0)
  933. killsock(dcc[idx].sock);
  934. dcc[idx].sock = (-1);
  935. serv = (-1);
  936. botuserhost[0] = 0;
  937. }
  938. static void eof_server(int idx)
  939. {
  940. int i = 0;
  941. putlog(LOG_SERV, "*", "%s %s", IRC_DISCONNECTED, dcc[idx].host);
  942. if (ischanhub() && auth_total > 0) {
  943. putlog(LOG_DEBUG, "*", "Removing %d auth entries.", auth_total);
  944. for (i = 0; i < auth_total; i++)
  945. removeauth(i);
  946. }
  947. disconnect_server(idx);
  948. lostdcc(idx);
  949. }
  950. static void display_server(int idx, char *buf)
  951. {
  952. sprintf(buf, "%s (lag: %d)", trying_server ? "conn" : "serv",
  953. server_lag);
  954. }
  955. static void connect_server(void);
  956. static void kill_server(int idx, void *x)
  957. {
  958. module_entry *me;
  959. disconnect_server(idx);
  960. if ((me = module_find("channels", 0, 0)) && me->funcs) {
  961. struct chanset_t *chan;
  962. for (chan = chanset; chan; chan = chan->next)
  963. (me->funcs[CHANNEL_CLEAR]) (chan, 1);
  964. }
  965. /* A new server connection will be automatically initiated in
  966. about 2 seconds. */
  967. }
  968. static void timeout_server(int idx)
  969. {
  970. putlog(LOG_SERV, "*", "Timeout: connect to %s", dcc[idx].host);
  971. disconnect_server(idx);
  972. lostdcc(idx);
  973. }
  974. static void server_activity(int idx, char *msg, int len);
  975. static struct dcc_table SERVER_SOCKET =
  976. {
  977. "SERVER",
  978. 0,
  979. eof_server,
  980. server_activity,
  981. NULL,
  982. timeout_server,
  983. display_server,
  984. NULL,
  985. kill_server,
  986. NULL
  987. };
  988. int isop(char *mode)
  989. {
  990. int state = 0,
  991. cnt = 0;
  992. char *p;
  993. p = mode;
  994. while ((*p) && (*p != ' ')) {
  995. if (*p == '-')
  996. state = 1;
  997. else if (*p == '+')
  998. state = 0;
  999. else if ((!state) && (*p == 'o'))
  1000. cnt++;
  1001. p++;
  1002. }
  1003. return (cnt >= 1);
  1004. }
  1005. int ismdop(char *mode)
  1006. {
  1007. int state = 0,
  1008. cnt = 0;
  1009. char *p;
  1010. p = mode;
  1011. while ((*p) && (*p != ' ')) {
  1012. if (*p == '-')
  1013. state = 1;
  1014. else if (*p == '+')
  1015. state = 0;
  1016. else if ((state) && (*p == 'o'))
  1017. cnt++;
  1018. p++;
  1019. }
  1020. return (cnt >= 3);
  1021. }
  1022. /*
  1023. void got_rsn(char *botnick, char *code, char *par) {
  1024. if (strcmp(origbotname, botname)) {
  1025. randuse = 0;
  1026. dprintf(DP_MODE, STR("NICK %s\n"), origbotname);
  1027. }
  1028. }
  1029. void got_rn(char *botnick, char *code, char *par) {
  1030. int l = (rand() % 4) + 6, i;
  1031. char newnick[NICKLEN+1];
  1032. for (i=0;i<l;i++)
  1033. newnick[i]=(rand() % 2) * 32 + 65 + rand() % 26;
  1034. newnick[l]=0;
  1035. randuse = 1;
  1036. //havealt = 1;
  1037. dprintf(DP_MODE, STR("NICK %s\n"), newnick);
  1038. }
  1039. */
  1040. static void server_activity(int idx, char *msg, int len)
  1041. {
  1042. char *from, *code, tmp[1024];
  1043. char sign = '+';
  1044. Context;
  1045. if (trying_server) {
  1046. strcpy(dcc[idx].nick, "(server)");
  1047. putlog(LOG_SERV, "*", "Connected to %s", dcc[idx].host);
  1048. trying_server = 0;
  1049. SERVER_SOCKET.timeout_val = 0;
  1050. }
  1051. Context;
  1052. waiting_for_awake = 0;
  1053. from = "";
  1054. if (msg[0] == ':') {
  1055. msg++;
  1056. from = newsplit(&msg);
  1057. }
  1058. code = newsplit(&msg);
  1059. /* check MODEs now, we're in a rush */
  1060. Context;
  1061. if (!strcmp(code, STR("MODE")) && (msg[0] == '#') && strchr(from, '!')) {
  1062. /* It's MODE #chan by a user */
  1063. char *modes[5] = { NULL, NULL, NULL, NULL, NULL };
  1064. char *nfrom,
  1065. *hfrom;
  1066. int i;
  1067. struct userrec *ufrom = NULL;
  1068. struct chanset_t *chan = NULL;
  1069. char work[1024],
  1070. *wptr,
  1071. *p;
  1072. memberlist *m;
  1073. int modecnt = 0,
  1074. ops = 0,
  1075. deops = 0,
  1076. bans = 0,
  1077. unbans = 0;
  1078. /* Split up the mode: #chan modes param param param param */
  1079. strncpy0(work, msg, sizeof(work));
  1080. wptr = work;
  1081. Context;
  1082. p = newsplit(&wptr);
  1083. chan = findchan(p);
  1084. p = newsplit(&wptr);
  1085. while (*p) {
  1086. char *mp;
  1087. if (*p == '+')
  1088. sign = '+';
  1089. else if (*p == '-')
  1090. sign = '-';
  1091. else if (strchr(STR("oblkvIe"), p[0])) {
  1092. mp = newsplit(&wptr);
  1093. if (strchr("ob", p[0])) {
  1094. /* Just want o's and b's */
  1095. modes[modecnt] = nmalloc(strlen(mp) + 4);
  1096. sprintf(modes[modecnt], STR("%c%c %s"), sign, p[0], mp);
  1097. modecnt++;
  1098. if (p[0] == 'o') {
  1099. if (sign == '+')
  1100. ops++;
  1101. else
  1102. deops++;
  1103. }
  1104. if (p[0] == 'b') {
  1105. if (sign == '+')
  1106. bans++;
  1107. else
  1108. unbans++;
  1109. }
  1110. }
  1111. } else if (strchr(STR("pstnmi"), p[0])) {
  1112. } else {
  1113. /* hrmm... what modechar did i forget? */
  1114. putlog(LOG_ERRORS, "*", STR("Forgotten modechar: %c"), p[0]);
  1115. }
  1116. p++;
  1117. }
  1118. Context;
  1119. ufrom = get_user_by_host(from);
  1120. /* Split up from */
  1121. strncpy0(work, from, sizeof(work));
  1122. p = strchr(work, '!');
  1123. *p++ = 0;
  1124. nfrom = work;
  1125. hfrom = p;
  1126. /* Now we got modes[], chan, ufrom, nfrom, hfrom, and count of each relevant mode */
  1127. // check for mdop
  1128. if ((chan) && (deops >= 3)) {
  1129. if ((!ufrom) || (!(ufrom->flags & USER_BOT))) {
  1130. if (ROLE_KICK_MDOP) {
  1131. m=ismember(chan, nfrom);
  1132. if (!m || !chan_sentkick(m)) {
  1133. sprintf(tmp, STR("KICK %s %s :%s%s\n"), chan->name, nfrom, kickprefix, kickreason(KICK_MASSDEOP));
  1134. tputs(serv, tmp, strlen(tmp));
  1135. if (m)
  1136. m->flags |= SENTKICK;
  1137. }
  1138. }
  1139. }
  1140. }
  1141. //check for mop
  1142. if (chan && (ops >= 3)) {
  1143. if (channel_nomop(chan)) {
  1144. if ((!ufrom) || (!(ufrom->flags & USER_BOT))) {
  1145. if (ROLE_KICK_MDOP) {
  1146. m=ismember(chan, nfrom);
  1147. if (!m || !chan_sentkick(m)) {
  1148. sprintf(tmp, STR("KICK %s %s :%s%s\n"), chan->name, nfrom, kickprefix, kickreason(KICK_MANUALOP));
  1149. tputs(serv, tmp, strlen(tmp));
  1150. if (m)
  1151. m->flags |= SENTKICK;
  1152. }
  1153. }
  1154. }
  1155. }
  1156. }
  1157. if (chan && ops && (ufrom) && (ufrom->flags & USER_BOT)
  1158. && (!channel_fastop(chan))
  1159. && (!channel_take(chan))
  1160. ) {
  1161. int isbadop = 0;
  1162. if ((modecnt != 2) || (strncmp(modes[0], "+o", 2))
  1163. || (strncmp(modes[1], "-b", 2)))
  1164. isbadop = 1;
  1165. else {
  1166. char enccookie[25],
  1167. plaincookie[25],
  1168. key[NICKLEN + 20],
  1169. goodcookie[25];
  1170. /* -b *!*@[...] */
  1171. strncpy0(enccookie, (char *) &(modes[1][8]), sizeof(enccookie));
  1172. p = enccookie + strlen(enccookie) - 1;
  1173. // *p = 0;
  1174. // while (p - enccookie < 24) {
  1175. // *p++ = '.';
  1176. // *p = 0;
  1177. // }
  1178. strcpy(key, nfrom);
  1179. strcat(key, netpass);
  1180. //putlog(LOG_DEBUG, "*", "Decrypting cookie: %s with key %s", enccookie, key);
  1181. p = decrypt_string(key, enccookie);
  1182. //putlog(LOG_DEBUG, "*", "Decrypted cookie: %s", p);
  1183. Context;
  1184. strncpy0(plaincookie, p, sizeof(plaincookie));
  1185. nfree(p);
  1186. /*
  1187. last 6 digits of time
  1188. last 5 chars of nick
  1189. last 5 regular chars of chan
  1190. */
  1191. makeplaincookie(chan->dname, (char *) (modes[0] + 3), goodcookie);
  1192. // putlog(LOG_DEBUG, "*", "cookie from %s: %s should be: %s", nfrom, plaincookie, goodcookie);
  1193. if (strncmp((char *) &plaincookie[6], (char *) &goodcookie[6], 5))
  1194. isbadop = 2;
  1195. else if (strncmp((char *) &plaincookie[11], (char *) &goodcookie[11], 5))
  1196. isbadop = 3;
  1197. else {
  1198. char tmp[20];
  1199. long optime;
  1200. int off;
  1201. sprintf(tmp, STR("%010li"), (now + timesync));
  1202. strncpy0((char *) &tmp[4], plaincookie, 7);
  1203. optime = atol(tmp);
  1204. off = (now + timesync - optime);
  1205. if (abs(off) > op_time_slack) {
  1206. // isbadop = 4;
  1207. putlog(LOG_ERRORS, "*", "%s opped with bad ts (not punishing.): %li was off by %li", nfrom, optime, off);
  1208. }
  1209. }
  1210. }
  1211. if (isbadop) {
  1212. char trg[NICKLEN + 1] = "";
  1213. int n,
  1214. i;
  1215. memberlist *m;
  1216. Context;
  1217. switch (role) {
  1218. case 0:
  1219. break;
  1220. case 1:
  1221. /* Kick opper */
  1222. m=ismember(chan, nfrom);
  1223. if (!m || !chan_sentkick(m)) {
  1224. sprintf(tmp, STR("KICK %s %s :%s%s\n"), chan->name, nfrom, kickprefix, kickreason(KICK_BADOP));
  1225. tputs(serv, tmp, strlen(tmp));
  1226. if (m)
  1227. m->flags |= SENTKICK;
  1228. }
  1229. sprintf(tmp, STR("%s MODE %s"), from, msg);
  1230. deflag_user(ufrom, DEFLAG_BADCOOKIE, tmp, chan);
  1231. break;
  1232. default:
  1233. n = role - 1;
  1234. i = 0;
  1235. while ((i < 5) && (n > 0)) {
  1236. if (modes[i] && !strncmp(modes[i], "+o", 2))
  1237. n--;
  1238. if (n)
  1239. i++;
  1240. }
  1241. if (!n) {
  1242. strcpy(trg, (char *) &modes[i][3]);
  1243. m = ismember(chan, trg);
  1244. if (m) {
  1245. if (!(m->flags & CHANOP)) {
  1246. if (!chan_sentkick(m)) {
  1247. sprintf(tmp, STR("KICK %s %s :%s%s\n"), chan->name, trg, kickprefix, kickreason(KICK_BADOPPED));
  1248. tputs(serv, tmp, strlen(tmp));
  1249. m->flags |= SENTKICK;
  1250. }
  1251. }
  1252. }
  1253. }
  1254. }
  1255. if (isbadop == 1)
  1256. putlog(LOG_WARN, "*", STR("Missing cookie: %s MODE %s"), from, msg);
  1257. else if (isbadop == 2)
  1258. putlog(LOG_WARN, "*", STR("Invalid cookie (bad nick): %s MODE %s"), from, msg);
  1259. else if (isbadop == 3)
  1260. putlog(LOG_WARN, "*", STR("Invalid cookie (bad chan): %s MODE %s"), from, msg);
  1261. else if (isbadop == 4)
  1262. putlog(LOG_WARN, "*", STR("Invalid cookie (bad time): %s MODE %s"), from, msg);
  1263. } else
  1264. putlog(LOG_DEBUG, "@", STR("Good op: %s"), msg);
  1265. }
  1266. if ((ops) && chan && !channel_manop(chan) && (ufrom)
  1267. && !(ufrom->flags & USER_BOT)) {
  1268. char trg[NICKLEN + 1] = "";
  1269. int n,
  1270. i;
  1271. memberlist *m;
  1272. switch (role) {
  1273. case 0:
  1274. break;
  1275. case 1:
  1276. /* Kick opper */
  1277. m = ismember(chan, nfrom);
  1278. if (!m || !chan_sentkick(m)) {
  1279. sprintf(tmp, STR("KICK %s %s :%s%s\n"), chan->name, nfrom, kickprefix, kickreason(KICK_MANUALOP));
  1280. tputs(serv, tmp, strlen(tmp));
  1281. if (m)
  1282. m->flags |= SENTKICK;
  1283. }
  1284. sprintf(tmp, STR("%s MODE %s"), from, msg);
  1285. deflag_user(ufrom, DEFLAG_MANUALOP, tmp, chan);
  1286. break;
  1287. default:
  1288. n = role - 1;
  1289. i = 0;
  1290. while ((i < 5) && (n > 0)) {
  1291. if (modes[i] && !strncmp(modes[i], "+o", 2))
  1292. n--;
  1293. if (n)
  1294. i++;
  1295. }
  1296. if (!n) {
  1297. strcpy(trg, (char *) &modes[i][3]);
  1298. m = ismember(chan, trg);
  1299. if (m) {
  1300. if (!(m->flags & CHANOP) && (rfc_casecmp(botname, trg))) {
  1301. if (!chan_sentkick(m)) {
  1302. sprintf(tmp, STR("KICK %s %s :%s%s\n"), chan->name, trg, kickprefix, kickreason(KICK_MANUALOPPED));
  1303. tputs(serv, tmp, strlen(tmp));
  1304. m->flags |= SENTKICK;
  1305. }
  1306. }
  1307. } else {
  1308. sprintf(tmp, STR("KICK %s %s :%s%s\n"), chan->name, trg, kickprefix, kickreason(KICK_MANUALOPPED));
  1309. tputs(serv, tmp, strlen(tmp));
  1310. }
  1311. }
  1312. }
  1313. }
  1314. for (i = 0; i < 5; i++)
  1315. if (modes[i])
  1316. nfree(modes[i]);
  1317. }
  1318. if (use_console_r) {
  1319. if (!strcmp(code, "PRIVMSG") ||
  1320. !strcmp(code, "NOTICE")) {
  1321. if (!match_ignore(from))
  1322. putlog(LOG_RAW, "@", "[@] %s %s %s", from, code, msg);
  1323. } else
  1324. putlog(LOG_RAW, "@", "[@] %s %s %s", from, code, msg);
  1325. }
  1326. /* This has GOT to go into the raw binding table, * merely because this
  1327. * is less effecient.
  1328. */
  1329. check_tcl_raw(from, code, msg);
  1330. }
  1331. static int gotping(char *from, char *msg)
  1332. {
  1333. fixcolon(msg);
  1334. dprintf(DP_MODE, "PONG :%s\n", msg);
  1335. return 0;
  1336. }
  1337. static int gotkick(char *from, char *msg)
  1338. {
  1339. char *nick;
  1340. nick = from;
  1341. if (rfc_casecmp(nick, botname))
  1342. /* Not my kick, I don't need to bother about it. */
  1343. return 0;
  1344. if (use_penalties) {
  1345. last_time += 2;
  1346. if (debug_output)
  1347. putlog(LOG_SRVOUT, "*", "adding 2secs penalty (successful kick)");
  1348. }
  1349. return 0;
  1350. }
  1351. /* Another sec penalty if bot did a whois on another server.
  1352. */
  1353. static int whoispenalty(char *from, char *msg)
  1354. {
  1355. struct server_list *x = serverlist;
  1356. int i, ii;
  1357. if (x && use_penalties) {
  1358. i = ii = 0;
  1359. for (; x; x = x->next) {
  1360. if (i == curserv) {
  1361. if ((strict_servernames == 1) || !x->realname) {
  1362. if (strcmp(x->name, from))
  1363. ii = 1;
  1364. } else {
  1365. if (strcmp(x->realname, from))
  1366. ii = 1;
  1367. }
  1368. }
  1369. i++;
  1370. }
  1371. if (ii) {
  1372. last_time += 1;
  1373. if (debug_output)
  1374. putlog(LOG_SRVOUT, "*", "adding 1sec penalty (remote whois)");
  1375. }
  1376. }
  1377. return 0;
  1378. }
  1379. static int got311(char *from, char *msg)
  1380. {
  1381. char *n1, *n2, *u, *h;
  1382. n1 = newsplit(&msg);
  1383. n2 = newsplit(&msg);
  1384. u = newsplit(&msg);
  1385. h = newsplit(&msg);
  1386. if (!n1 || !n2 || !u || !h)
  1387. return 0;
  1388. if (match_my_nick(n2))
  1389. egg_snprintf(botuserhost, sizeof botuserhost, "%s@%s", u, h);
  1390. return 0;
  1391. }
  1392. static cmd_t my_raw_binds[] =
  1393. {
  1394. {"PRIVMSG", "", (Function) gotmsg, NULL},
  1395. {"NOTICE", "", (Function) gotnotice, NULL},
  1396. {"MODE", "", (Function) gotmode, NULL},
  1397. {"PING", "", (Function) gotping, NULL},
  1398. {"PONG", "", (Function) gotpong, NULL},
  1399. {"WALLOPS", "", (Function) gotwall, NULL},
  1400. {"001", "", (Function) got001, NULL},
  1401. {"251", "", (Function) got251, NULL},
  1402. {"303", "", (Function) got303, NULL},
  1403. {"432", "", (Function) got432, NULL},
  1404. {"433", "", (Function) got433, NULL},
  1405. {"437", "", (Function) got437, NULL},
  1406. {"438", "", (Function) got438, NULL},
  1407. {"451", "", (Function) got451, NULL},
  1408. {"442", "", (Function) got442, NULL},
  1409. {"NICK", "", (Function) gotnick, NULL},
  1410. {"ERROR", "", (Function) goterror, NULL},
  1411. /* ircu2.10.10 has a bug when a client is throttled ERROR is sent wrong */
  1412. {"ERROR:", "", (Function) goterror, NULL},
  1413. {"KICK", "", (Function) gotkick, NULL},
  1414. {"318", "", (Function) whoispenalty, NULL},
  1415. {"311", "", (Function) got311, NULL},
  1416. {NULL, NULL, NULL, NULL}
  1417. };
  1418. static void server_resolve_success(int);
  1419. static void server_resolve_failure(int);
  1420. /* Hook up to a server
  1421. */
  1422. static void connect_server(void)
  1423. {
  1424. char pass[121], botserver[UHOSTLEN];
  1425. static int oldserv = -1;
  1426. int servidx;
  1427. unsigned int botserverport = 0;
  1428. waiting_for_awake = 0;
  1429. trying_server = now;
  1430. empty_msgq();
  1431. /* Start up the counter (always reset it if "never-give-up" is on) */
  1432. if ((oldserv < 0) || (never_give_up))
  1433. oldserv = curserv;
  1434. if (newserverport) { /* Jump to specified server */
  1435. curserv = (-1); /* Reset server list */
  1436. strcpy(botserver, newserver);
  1437. botserverport = newserverport;
  1438. strcpy(pass, newserverpass);
  1439. newserver[0] = 0;
  1440. newserverport = 0;
  1441. newserverpass[0] = 0;
  1442. oldserv = (-1);
  1443. } else
  1444. pass[0] = 0;
  1445. if (!cycle_time) {
  1446. struct chanset_t *chan;
  1447. struct server_list *x = serverlist;
  1448. if (!x) {
  1449. // putlog(LOG_SERV, "*", "No servers in server list");
  1450. // cycle_time = 10;
  1451. return;
  1452. }
  1453. servidx = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
  1454. if (servidx < 0) {
  1455. putlog(LOG_SERV, "*",
  1456. "NO MORE DCC CONNECTIONS -- Can't create server connection.");
  1457. return;
  1458. }
  1459. if (connectserver[0]) /* drummer */
  1460. do_tcl("connect-server", connectserver);
  1461. check_tcl_event("connect-server");
  1462. next_server(&curserv, botserver, &botserverport, pass);
  1463. putlog(LOG_SERV, "*", "%s %s:%d", IRC_SERVERTRY, botserver, botserverport);
  1464. dcc[servidx].port = botserverport;
  1465. strcpy(dcc[servidx].nick, "(server)");
  1466. strncpyz(dcc[servidx].host, botserver, UHOSTLEN);
  1467. botuserhost[0] = 0;
  1468. nick_juped = 0;
  1469. for (chan = chanset; chan; chan = chan->next)
  1470. chan->status &= ~CHAN_JUPED;
  1471. dcc[servidx].timeval = now;
  1472. dcc[servidx].sock = -1;
  1473. dcc[servidx].u.dns->host = get_data_ptr(strlen(dcc[servidx].host) + 1);
  1474. strcpy(dcc[servidx].u.dns->host, dcc[servidx].host);
  1475. dcc[servidx].u.dns->cbuf = get_data_ptr(strlen(pass) + 1);
  1476. strcpy(dcc[servidx].u.dns->cbuf, pass);
  1477. dcc[servidx].u.dns->dns_success = server_resolve_success;
  1478. dcc[servidx].u.dns->dns_failure = server_resolve_failure;
  1479. dcc[servidx].u.dns->dns_type = RES_IPBYHOST;
  1480. dcc[servidx].u.dns->type = &SERVER_SOCKET;
  1481. if (server_cycle_wait)
  1482. /* Back to 1st server & set wait time.
  1483. * Note: Put it here, just in case the server quits on us quickly
  1484. */
  1485. cycle_time = server_cycle_wait;
  1486. else
  1487. cycle_time = 0;
  1488. /* I'm resolving... don't start another server connect request */
  1489. resolvserv = 1;
  1490. /* Resolve the hostname. */
  1491. #ifdef USE_IPV6
  1492. server_resolve_success(servidx);
  1493. #else
  1494. dcc_dnsipbyhost(dcc[servidx].host);
  1495. #endif /* USE_IPV6 */
  1496. }
  1497. }
  1498. static void server_resolve_failure(int servidx)
  1499. {
  1500. serv = -1;
  1501. resolvserv = 0;
  1502. putlog(LOG_SERV, "*", "%s %s (%s)", IRC_FAILEDCONNECT, dcc[servidx].host,
  1503. IRC_DNSFAILED);
  1504. lostdcc(servidx);
  1505. }
  1506. static void server_resolve_success(int servidx)
  1507. {
  1508. int oldserv = dcc[servidx].u.dns->ibuf;
  1509. #ifdef S_NODELAY
  1510. int i = 0;
  1511. #endif
  1512. char s[121], pass[121];
  1513. resolvserv = 0;
  1514. dcc[servidx].addr = dcc[servidx].u.dns->ip;
  1515. strcpy(pass, dcc[servidx].u.dns->cbuf);
  1516. changeover_dcc(servidx, &SERVER_SOCKET, 0);
  1517. #ifdef USE_IPV6
  1518. serv = open_telnet(dcc[servidx].host, dcc[servidx].port);
  1519. #else
  1520. serv = open_telnet(iptostr(htonl(dcc[servidx].addr)), dcc[servidx].port);
  1521. #endif /* USE_IPV6 */
  1522. if (serv < 0) {
  1523. neterror(s);
  1524. putlog(LOG_SERV, "*", "%s %s (%s)", IRC_FAILEDCONNECT, dcc[servidx].host,
  1525. s);
  1526. lostdcc(servidx);
  1527. if (oldserv == curserv && !never_give_up)
  1528. fatal("NO SERVERS WILL ACCEPT MY CONNECTION.", 0);
  1529. } else {
  1530. dcc[servidx].sock = serv;
  1531. #ifdef HAVE_SSL
  1532. if (!ssl_link(dcc[servidx].sock, CONNECT_SSL)) {
  1533. dcc[servidx].ssl = 0;
  1534. putlog(LOG_SERV, "*", "SSL for '%s' failed", dcc[servidx].host);
  1535. } else {
  1536. putlog(LOG_SERV, "*", "SSL for '%s' successful", dcc[servidx].host);
  1537. dcc[servidx].ssl = 1;
  1538. }
  1539. #else
  1540. dcc[servidx].ssl = 0;
  1541. #endif /* HAVE_SSL */
  1542. #ifdef S_NODELAY
  1543. i = 1;
  1544. setsockopt(serv, 6, TCP_NODELAY, &i, sizeof(i));
  1545. #endif /* S_NODELAY */
  1546. /* Queue standard login */
  1547. dcc[servidx].timeval = now;
  1548. SERVER_SOCKET.timeout_val = &server_timeout;
  1549. /* Another server may have truncated it, so use the original */
  1550. strcpy(botname, origbotname);
  1551. /* Start alternate nicks from the beginning */
  1552. altnick_char = 0;
  1553. if (pass[0])
  1554. dprintf(DP_MODE, "PASS %s\n", pass);
  1555. dprintf(DP_MODE, "NICK %s\n", botname);
  1556. dprintf(DP_MODE, "USER %s . . :%s\n", botuser, botrealname);
  1557. /* Wait for async result now */
  1558. }
  1559. }
  1560. #endif