msgcmds.cc 15 KB

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