msgcmds.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  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. * msgcmds.c -- part of irc.mod
  22. * all commands entered via /MSG
  23. *
  24. */
  25. #include "src/core_binds.h"
  26. static int msg_bewm(char *nick, char *host, struct userrec *u, char *par)
  27. {
  28. struct chanset_t *chan = NULL;
  29. if (!homechan[0] || !(chan = findchan_by_dname(homechan)))
  30. return BIND_RET_BREAK;
  31. if (!channel_active(chan))
  32. return BIND_RET_BREAK;
  33. if (match_my_nick(nick))
  34. return BIND_RET_BREAK;
  35. bd::String msg;
  36. if (!u) {
  37. msg = bd::String::printf(STR("---- (%s!%s) attempted to gain secure invite, but is not a recognized user."), nick, host);
  38. privmsg(chan->name, msg, DP_SERVER);
  39. putlog(LOG_CMDS, "*", STR("(%s!%s) !*! BEWM"), nick, host);
  40. return BIND_RET_BREAK;
  41. }
  42. if (u->bot)
  43. return BIND_RET_BREAK;
  44. struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  45. get_user_flagrec(u, &fr, chan->dname, chan);
  46. if (!chk_op(fr, chan)) {
  47. putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! !BEWM"), nick, host, u->handle);
  48. msg = bd::String::printf(STR("---- %s (%s!%s) attempted to gain secure invite, but is missing a flag."), u->handle, nick, host);
  49. privmsg(chan->name, msg, DP_SERVER);
  50. return BIND_RET_BREAK;
  51. }
  52. msg = bd::String::printf("\001ACTION has invited \002%s\002 (%s!%s) to %s.\001", u->handle, nick, host, chan->dname);
  53. privmsg(chan->name, msg, DP_SERVER);
  54. cache_invite(chan, nick, host, u->handle, 0, 0);
  55. putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! BEWM"), nick, host, u->handle);
  56. return BIND_RET_BREAK;
  57. }
  58. static int msg_pass(char *nick, char *host, struct userrec *u, char *par)
  59. {
  60. char *old = NULL, *mynew = NULL;
  61. if (match_my_nick(nick))
  62. return BIND_RET_BREAK;
  63. if (!u) {
  64. putlog(LOG_CMDS, "*", "(%s!%s) !*! PASS", nick, host);
  65. return BIND_RET_BREAK;
  66. }
  67. if (u->bot)
  68. return BIND_RET_BREAK;
  69. if (!par[0]) {
  70. notice(nick, u_pass_match(u, "-") ? "You don't have a password set." : "You have a password set.", DP_HELP);
  71. putlog(LOG_CMDS, "*", "(%s!%s) !%s! PASS?", nick, host, u->handle);
  72. return BIND_RET_BREAK;
  73. }
  74. old = newsplit(&par);
  75. if (!u_pass_match(u, "-") && !par[0]) {
  76. putlog(LOG_CMDS, "*", "(%s!%s) !%s! $b!$bPASS...", nick, host, u->handle);
  77. notice(nick, "You already have a password set.", DP_HELP);
  78. return BIND_RET_BREAK;
  79. }
  80. if (par[0]) {
  81. if (!u_pass_match(u, old)) {
  82. putlog(LOG_CMDS, "*", "(%s!%s) !%s! $b!$bPASS...", nick, host, u->handle);
  83. notice(nick, "Incorrect password.", DP_HELP);
  84. return BIND_RET_BREAK;
  85. }
  86. mynew = newsplit(&par);
  87. } else {
  88. mynew = old;
  89. }
  90. if (strlen(mynew) > MAXPASSLEN)
  91. mynew[MAXPASSLEN] = 0;
  92. if (!goodpass(mynew, 0, nick)) {
  93. putlog(LOG_CMDS, "*", "(%s!%s) !%s! $b!$bPASS...", nick, host, u->handle);
  94. return BIND_RET_BREAK;
  95. }
  96. putlog(LOG_CMDS, "*", "(%s!%s) !%s! PASS", nick, host, u->handle);
  97. set_user(&USERENTRY_PASS, u, mynew);
  98. bd::String msg;
  99. msg = bd::String::printf("%s '%s'.", mynew == old ? "Password set to:" : "Password changed to:", mynew);
  100. notice(nick, msg, DP_HELP);
  101. return BIND_RET_BREAK;
  102. }
  103. static int msg_op(char *nick, char *host, struct userrec *u, char *par)
  104. {
  105. struct chanset_t *chan = NULL;
  106. char *pass = NULL;
  107. struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  108. if (match_my_nick(nick))
  109. return BIND_RET_BREAK;
  110. pass = newsplit(&par);
  111. bd::String msg;
  112. if (homechan[0]) {
  113. struct chanset_t *hchan = NULL;
  114. hchan = findchan_by_dname(homechan);
  115. if (hchan && channel_active(hchan) && !ismember(hchan, nick)) {
  116. putlog(LOG_CMDS, "*", "(%s!%s) !*! failed OP %s (not in %s)", nick, host, par, homechan);
  117. if (par[0])
  118. msg = bd::String::printf("---- (%s!%s) attempted to OP for %s but is not currently in %s.", nick, host, par, homechan);
  119. else
  120. msg = bd::String::printf("---- (%s!%s) attempted to OP but is not currently in %s.", nick, host, homechan);
  121. privmsg(homechan, msg, DP_SERVER);
  122. return BIND_RET_BREAK;
  123. }
  124. }
  125. if (u_pass_match(u, pass)) {
  126. if (!u_pass_match(u, "-")) {
  127. if (par[0]) {
  128. chan = findchan_by_dname(par);
  129. if (chan && channel_active(chan)) {
  130. get_user_flagrec(u, &fr, par, chan);
  131. if (chk_op(fr, chan)) {
  132. if (do_op(nick, chan, 0, 1)) {
  133. stats_add(u, 0, 1);
  134. putlog(LOG_CMDS, "*", "(%s!%s) !%s! OP %s", nick, host, u->handle, par);
  135. if (manop_warn && chan->manop) {
  136. msg = bd::String::printf("%s is currently set to punish for manual op.", chan->dname);
  137. notice(nick, msg, DP_HELP);
  138. }
  139. }
  140. }
  141. return BIND_RET_BREAK;
  142. }
  143. } else {
  144. int stats = 0;
  145. for (chan = chanset; chan; chan = chan->next) {
  146. get_user_flagrec(u, &fr, chan->dname, chan);
  147. if (chk_op(fr, chan)) {
  148. if (do_op(nick, chan, 0, 1)) {
  149. stats++;
  150. if (manop_warn && chan->manop) {
  151. msg = bd::String::printf("%s is currently set to punish for manual op.", chan->dname);
  152. notice(nick, msg, DP_HELP);
  153. }
  154. }
  155. }
  156. }
  157. putlog(LOG_CMDS, "*", "(%s!%s) !%s! OP", nick, host, u->handle);
  158. if (stats)
  159. stats_add(u, 0, 1);
  160. return BIND_RET_BREAK;
  161. }
  162. }
  163. }
  164. putlog(LOG_CMDS, "*", "(%s!%s) !*! failed OP", nick, host);
  165. return BIND_RET_BREAK;
  166. }
  167. static int msg_ident(char *nick, char *host, struct userrec *u, char *par)
  168. {
  169. char s[UHOSTLEN] = "", s1[UHOSTLEN] = "", *pass = NULL, who[HANDLEN + 1] = "";
  170. struct userrec *u2 = NULL;
  171. if (match_my_nick(nick) || (u && u->bot))
  172. return BIND_RET_BREAK;
  173. pass = newsplit(&par);
  174. if (!par[0])
  175. strlcpy(who, nick, sizeof(who));
  176. else {
  177. strlcpy(who, par, sizeof(who));
  178. }
  179. bd::String msg;
  180. u2 = get_user_by_handle(userlist, who);
  181. if (u2 && rfc_casecmp(who, origbotname) && !u2->bot) {
  182. /* This could be used as detection... */
  183. if (u_pass_match(u2, "-")) {
  184. putlog(LOG_CMDS, "*", "(%s!%s) !*! IDENT %s", nick, host, who);
  185. } else if (!u_pass_match(u2, pass)) {
  186. putlog(LOG_CMDS, "*", "(%s!%s) !*! failed IDENT %s", nick, host, who);
  187. return BIND_RET_BREAK;
  188. } else if (u == u2) {
  189. notice(nick, "I recognize you there.", DP_HELP);
  190. return BIND_RET_BREAK;
  191. } else if (u) {
  192. msg = bd::String::printf("You're not %s, you're %s.", who, u->handle);
  193. notice(nick, msg, DP_HELP);
  194. return BIND_RET_BREAK;
  195. } else {
  196. putlog(LOG_CMDS, "*", "(%s!%s) !*! IDENT %s", nick, host, who);
  197. simple_snprintf(s, sizeof s, "%s!%s", nick, host);
  198. maskaddr(s, s1, 0); /* *!user@host */
  199. msg = bd::String::printf("Added hostmask: %s", s1);
  200. notice(nick, msg, DP_HELP);
  201. addhost_by_handle(who, s1);
  202. check_this_user(who, 0, NULL);
  203. return BIND_RET_BREAK;
  204. }
  205. }
  206. putlog(LOG_CMDS, "*", "(%s!%s) !*! failed IDENT %s", nick, host, who);
  207. return BIND_RET_BREAK;
  208. }
  209. static int msg_invite(char *nick, char *host, struct userrec *u, char *par)
  210. {
  211. char *pass = NULL;
  212. struct chanset_t *chan = NULL;
  213. struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0 };
  214. if (match_my_nick(nick))
  215. return BIND_RET_BREAK;
  216. pass = newsplit(&par);
  217. if (u_pass_match(u, pass) && !u_pass_match(u, "-")) {
  218. if (par[0] == '*') {
  219. for (chan = chanset; chan; chan = chan->next) {
  220. get_user_flagrec(u, &fr, chan->dname, chan);
  221. if (chk_op(fr, chan) && (chan->channel.mode & CHANINV)) {
  222. cache_invite(chan, nick, host, u->handle, 0, 0);
  223. }
  224. }
  225. putlog(LOG_CMDS, "*", "(%s!%s) !%s! INVITE ALL", nick, host, u->handle);
  226. return BIND_RET_BREAK;
  227. }
  228. bd::String msg;
  229. if (!(chan = findchan_by_dname(par))) {
  230. msg = bd::String::printf("Usage: /MSG %s %s <pass> <channel>", botname, msginvite);
  231. notice(nick, msg, DP_HELP);
  232. return BIND_RET_BREAK;
  233. }
  234. if (!channel_active(chan)) {
  235. msg = bd::String::printf("%s: Not on that channel right now.", par);
  236. notice(nick, msg, DP_HELP);
  237. return BIND_RET_BREAK;
  238. }
  239. /* We need to check access here also (dw 991002) */
  240. get_user_flagrec(u, &fr, par, chan);
  241. if (chk_op(fr, chan)) {
  242. cache_invite(chan, nick, host, u->handle, 0, 0);
  243. putlog(LOG_CMDS, "*", "(%s!%s) !%s! INVITE %s", nick, host, u->handle, par);
  244. return BIND_RET_BREAK;
  245. }
  246. }
  247. putlog(LOG_CMDS, "*", "(%s!%s) !%s! failed INVITE %s", nick, host, (u ? u->handle : "*"), par);
  248. return BIND_RET_BREAK;
  249. }
  250. static void logc(const char *cmd, Auth *a, char *chname, char *par)
  251. {
  252. if (chname && chname[0])
  253. putlog(LOG_CMDS, "*", "(%s!%s) !%s! %s %c%s %s", a->nick, a->host, a->handle, chname, auth_prefix[0], cmd, par ? par : "");
  254. else
  255. putlog(LOG_CMDS, "*", "(%s!%s) !%s! %c%s %s", a->nick, a->host, a->handle, auth_prefix[0], cmd, par ? par : "");
  256. }
  257. #define LOGC(cmd) logc(cmd, a, chname, par)
  258. static int msg_authstart(char *nick, char *host, struct userrec *u, char *par)
  259. {
  260. if (!u)
  261. return 0;
  262. if (match_my_nick(nick))
  263. return BIND_RET_BREAK;
  264. if (u && u->bot)
  265. return BIND_RET_BREAK;
  266. if (!ischanhub()) {
  267. putlog(LOG_WARN, "*", STR("(%s!%s) !%s! Attempted AUTH? (I'm not a chathub (+c))"), nick, host, u->handle);
  268. return BIND_RET_BREAK;
  269. }
  270. putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! AUTH?"), nick, host, u->handle);
  271. Auth *auth = Auth::Find(host);
  272. if (auth) {
  273. if (auth->Authed()) {
  274. notice(nick, "You are already authed.", DP_HELP);
  275. return 0;
  276. }
  277. } else
  278. auth = new Auth(nick, host, u);
  279. /* Send "auth." if they are recognized, otherwise "auth!" */
  280. auth->Status(AUTH_PASS);
  281. bd::String msg;
  282. msg = bd::String::printf(STR("auth%s %s"), u ? "." : "!", conf.bot->nick);
  283. privmsg(nick, msg, DP_HELP);
  284. return BIND_RET_BREAK;
  285. }
  286. static void
  287. AuthFinish(Auth *auth)
  288. {
  289. putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! +AUTH"), auth->nick, auth->host, auth->handle);
  290. auth->Done();
  291. bd::String msg;
  292. msg = bd::String::printf(STR("You are now authorized for cmds, see %chelp"), auth_prefix[0]);
  293. notice(auth->nick, msg, DP_HELP);
  294. }
  295. static int msg_auth(char *nick, char *host, struct userrec *u, char *par)
  296. {
  297. char *pass = NULL;
  298. if (match_my_nick(nick))
  299. return BIND_RET_BREAK;
  300. if (u && u->bot)
  301. return BIND_RET_BREAK;
  302. Auth *auth = Auth::Find(host);
  303. if (!auth || auth->Status() != AUTH_PASS)
  304. return BIND_RET_BREAK;
  305. pass = newsplit(&par);
  306. if (u_pass_match(u, pass) && !u_pass_match(u, "-")) {
  307. auth->user = u;
  308. if (strlen(auth_key) && get_user(&USERENTRY_SECPASS, u)) {
  309. putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! AUTH"), nick, host, u->handle);
  310. auth->Status(AUTH_HASH);
  311. auth->MakeHash();
  312. bd::String msg;
  313. msg = bd::String::printf(STR("-Auth %s %s"), auth->rand, conf.bot->nick);
  314. privmsg(nick, msg, DP_HELP);
  315. } else {
  316. /* no auth_key and/or no SECPASS for the user, don't require a hash auth */
  317. AuthFinish(auth);
  318. }
  319. } else {
  320. putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! failed AUTH"), nick, host, u->handle);
  321. delete auth;
  322. }
  323. return BIND_RET_BREAK;
  324. }
  325. static int msg_pls_auth(char *nick, char *host, struct userrec *u, char *par)
  326. {
  327. if (strlen(auth_key) && get_user(&USERENTRY_SECPASS, u)) {
  328. if (match_my_nick(nick))
  329. return BIND_RET_BREAK;
  330. if (u && u->bot)
  331. return BIND_RET_BREAK;
  332. Auth *auth = Auth::Find(host);
  333. if (!auth || auth->Status() != AUTH_HASH)
  334. return BIND_RET_BREAK;
  335. if (!strcmp(auth->hash, par)) { /* good hash! */
  336. AuthFinish(auth);
  337. } else { /* bad hash! */
  338. char s[300] = "";
  339. putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! failed +AUTH"), nick, host, u->handle);
  340. notice(nick, STR("Invalid hash."), DP_HELP);
  341. simple_snprintf(s, sizeof(s), "*!%s", host);
  342. addignore(s, origbotname, STR("Invalid auth hash."), now + (60 * ignore_time));
  343. delete auth;
  344. }
  345. return BIND_RET_BREAK;
  346. }
  347. return BIND_RET_LOG;
  348. }
  349. static int msg_unauth(char *nick, char *host, struct userrec *u, char *par)
  350. {
  351. if (match_my_nick(nick))
  352. return BIND_RET_BREAK;
  353. if (u && u->bot)
  354. return BIND_RET_BREAK;
  355. Auth *auth = Auth::Find(host);
  356. if (!auth)
  357. return BIND_RET_BREAK;
  358. delete auth;
  359. notice(nick, STR("You are now unauthorized."), DP_HELP);
  360. putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! UNAUTH"), nick, host, u->handle);
  361. return BIND_RET_BREAK;
  362. }
  363. static int msg_release(char *nick, char *host, struct userrec *u, char *par)
  364. {
  365. char *pass = NULL;
  366. if (match_my_nick(nick))
  367. return BIND_RET_BREAK;
  368. if (u && u->bot)
  369. return BIND_RET_BREAK;
  370. pass = newsplit(&par);
  371. if (u && u_pass_match(u, pass) && !u_pass_match(u, "-")) {
  372. struct flag_record fr = {FR_GLOBAL, 0, 0, 0 };
  373. get_user_flagrec(u, &fr, NULL);
  374. if (glob_master(fr)) {
  375. putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! RELEASE"), nick, host, u->handle);
  376. egg_timeval_t howlong;
  377. howlong.sec = 5;
  378. howlong.usec = 0;
  379. timer_create(&howlong, "Release jupenick", (Function) release_nick);
  380. // release_nick();
  381. } else
  382. putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! failed RELEASE (User it not +m)"), nick, host, u->handle);
  383. } else
  384. putlog(LOG_CMDS, "*", STR("(%s!%s) !%s! failed RELEASE"), nick, host, u ? u->handle : "*");
  385. return BIND_RET_BREAK;
  386. }
  387. /* MSG COMMANDS
  388. *
  389. * Function call should be:
  390. * int msg_cmd("handle","nick","user@host","params");
  391. *
  392. * The function is responsible for any logging. Return 1 if successful,
  393. * 0 if not.
  394. */
  395. static cmd_t C_msg[] =
  396. {
  397. {"auth?", "", (Function) msg_authstart, NULL, LEAF},
  398. {"auth", "", (Function) msg_auth, NULL, LEAF},
  399. {"+auth", "", (Function) msg_pls_auth, NULL, LEAF},
  400. {"unauth", "", (Function) msg_unauth, NULL, LEAF},
  401. {"ident", "", (Function) msg_ident, NULL, LEAF},
  402. {"invite", "", (Function) msg_invite, NULL, LEAF},
  403. {"op", "", (Function) msg_op, NULL, LEAF},
  404. {"pass", "", (Function) msg_pass, NULL, LEAF},
  405. {"release", "", (Function) msg_release, NULL, LEAF},
  406. {"bewm", "", (Function) msg_bewm, NULL, LEAF},
  407. {NULL, NULL, NULL, NULL, 0}
  408. };