msgcmds.c 15 KB

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