Our server pr0vider carried out maintenance on 15 January 2020 but it corrupted some files in the process. If you notice anything out of the ordinary (partial files, pages not loading, that kind of shit) then let us know at:

m_rtkl.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /* Copyright (C) All Rights Reserved
  2. ** Written by Gottem <support@gottem.nl>
  3. ** Website: https://gitgud.malvager.net/Wazakindjes/unrealircd_mods
  4. ** License: https://gitgud.malvager.net/Wazakindjes/unrealircd_mods/raw/master/LICENSE
  5. */
  6. // One include for all cross-platform compatibility thangs
  7. #include "unrealircd.h"
  8. // Command strings
  9. #define MSG_RKLINE "RKLINE"
  10. #define MSG_RZLINE "RZLINE"
  11. // Register command functions
  12. CMD_FUNC(m_rkline);
  13. CMD_FUNC(m_rzline);
  14. // Quality fowod declarations
  15. static int dumpit(aClient *sptr, char **p);
  16. int m_rtkl_main(aClient *cptr, aClient *sptr, int parc, char *parv[], char *cmd, char *operperm);
  17. int hook_tkl_add(aClient *cptr, aClient *sptr, aTKline *tkl, int parc, char *parv[]);
  18. int hook_tkl_del(aClient *cptr, aClient *sptr, aTKline *tkl, int parc, char *parv[]);
  19. int hook_tkl_main(aClient *cptr, aClient *sptr, aTKline *tkl, int parc, char *parv[], char flag);
  20. // Muh globals
  21. static ModuleInfo *rtklMI = NULL; // Store ModuleInfo so we can use it to check for errors in MOD_LOAD
  22. Command *rklineCmd, *rzlineCmd; // Pointers to the commands we're gonna add
  23. Hook *hookTklAdd, *hookTklDel; // Pointers for TKL ADD/DEL hewks ;]
  24. // Help string in case someone does just /RKLINE
  25. static char *rtklhelp[] = {
  26. /* Special characters:
  27. ** \002 = bold -- \x02
  28. ** \037 = underlined -- \x1F
  29. */
  30. "*** \002Help on /RKLINE and /RZLINE\002 ***",
  31. "Both of those commands allow you to remove \037local\037",
  32. "K:Lines and Z:Lines from remote servers. This might be useful",
  33. "if for example a spamfilter triggered a K:Line and you want to",
  34. "remove the ban without reconnecting.",
  35. " ",
  36. "Syntax:",
  37. " \002/RKLINE\002 \037server\037 \037[-]user@host\037 [duration] [reason]",
  38. " \002/RZLINE\002 \037server\037 \037[-]user@IP\037 [duration] [reason]",
  39. " Everything after the \037server\037 arg is the same stuff",
  40. "as for regular K/Z:Lines.",
  41. " ",
  42. "Examples:",
  43. " \002/RKLINE myleaf.dom.tld guest*@* 0 na d00d\002",
  44. " \002/RZLINE myleaf.dom.tld guest*@* 0 na d00d\002",
  45. " Place a ban on all guests",
  46. " \002/RKLINE myleaf.dom.tld -guest*@*\002",
  47. " Remove the same ban",
  48. " ",
  49. "There's no function for listing them in this module, as you can already use",
  50. "\002/stats K <server>\002 for that.",
  51. NULL
  52. };
  53. // Dat dere module header
  54. ModuleHeader MOD_HEADER(m_rtkl) = {
  55. "m_rtkl", // Module name
  56. "$Id: v1.01 2019/01/24 Gottem$", // Version
  57. "Allows privileged opers to remove remote servers' local K/Z:Lines", // Description
  58. "3.2-b8-1", // Modversion, not sure wat do
  59. NULL
  60. };
  61. // Initialisation routine (register hooks, commands and modes or create structs etc)
  62. MOD_INIT(m_rtkl) {
  63. // If command already exists for some reason, bail out
  64. if(CommandExists(MSG_RKLINE)) {
  65. config_error("Command %s already exists", MSG_RKLINE);
  66. return MOD_FAILED;
  67. }
  68. if(CommandExists(MSG_RZLINE)) {
  69. config_error("Command %s already exists", MSG_RZLINE);
  70. return MOD_FAILED;
  71. }
  72. hookTklAdd = HookAdd(modinfo->handle, HOOKTYPE_TKL_ADD, 0, hook_tkl_add);
  73. hookTklDel = HookAdd(modinfo->handle, HOOKTYPE_TKL_DEL, 0, hook_tkl_del);
  74. // Only users may use this module's commands =]
  75. rklineCmd = CommandAdd(modinfo->handle, MSG_RKLINE, m_rkline, MAXPARA, M_USER);
  76. rzlineCmd = CommandAdd(modinfo->handle, MSG_RZLINE, m_rzline, MAXPARA, M_USER);
  77. rtklMI = modinfo; // Store module info yo
  78. return MOD_SUCCESS; // Let MOD_LOAD handle errors
  79. }
  80. // Actually load the module here (also command overrides as they may not exist in MOD_INIT yet)
  81. MOD_LOAD(m_rtkl) {
  82. // Did the module throw an error during initialisation, or is one of the commands/hewks null even?
  83. if(ModuleGetError(rtklMI->handle) != MODERR_NOERROR || !rklineCmd || !rzlineCmd || !hookTklAdd || !hookTklDel) {
  84. // Display error string kek
  85. config_error("A critical error occurred when loading module %s: %s", MOD_HEADER(m_rtkl).name, ModuleGetErrorStr(rtklMI->handle));
  86. return MOD_FAILED; // No good
  87. }
  88. return MOD_SUCCESS; // We good
  89. }
  90. // Called on unload/rehash obv
  91. MOD_UNLOAD(m_rtkl) {
  92. return MOD_SUCCESS; // We good
  93. }
  94. // Dump a NULL-terminated array of strings to user sptr using the numeric rplnum, and then return 0 (taken from DarkFire IRCd)
  95. static int dumpit(aClient *sptr, char **p) {
  96. if(IsServer(sptr)) // Bail out early and silently if it's a server =]
  97. return 0;
  98. for(; *p != NULL; p++)
  99. sendto_one(sptr, ":%s %03d %s :%s", me.name, RPL_TEXT, sptr->name, *p);
  100. // Let user take 8 seconds to read it
  101. sptr->local->since += 8;
  102. return 0;
  103. }
  104. CMD_FUNC(m_rkline) {
  105. /* Gets args: aClient *cptr, aClient *sptr, int parc, char *parv[]
  106. **
  107. ** cptr: Pointer to directly attached client -- if remote user this is the remote server instead
  108. ** sptr: Pointer to user executing command
  109. ** parc: Amount of arguments (also includes the command in the count)
  110. ** parv: Contains the actual args, first one starts at parv[1]
  111. **
  112. ** So "RKLINE test" would result in parc = 2 and parv[1] = "test"
  113. ** Also, parv[0] seems to always be NULL, so better not rely on it fam
  114. */
  115. return m_rtkl_main(cptr, sptr, parc, parv, MSG_RKLINE, "tkl:kline");
  116. }
  117. CMD_FUNC(m_rzline) {
  118. return m_rtkl_main(cptr, sptr, parc, parv, MSG_RZLINE, "tkl:zline");
  119. }
  120. int m_rtkl_main(aClient *cptr, aClient *sptr, int parc, char *parv[], char *cmd, char *operperm) {
  121. int i; // Iterator to shift parv in a bit ;]
  122. aClient *srv; // Server pointer kek
  123. char buf[BUFSIZE];
  124. if(!MyClient(sptr) || !IsPerson(sptr) || IsULine(sptr)) // Only regular local users (well, opers) can use this =]
  125. return 0;
  126. if(!IsOper(sptr) || !ValidatePermissionsForPath(operperm, sptr, NULL, NULL, NULL)) {
  127. sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, sptr->name); // Not gonna happen
  128. return -1; // "Critical" error
  129. }
  130. if(BadPtr(parv[1]) || !stricmp(parv[1], "help") || !stricmp(parv[1], "halp")) // If first argument is a bad pointer or "help", don't proceed
  131. return dumpit(sptr, rtklhelp); // Return help string instead
  132. // Need at least 2 args before we pass it on to the server
  133. if(BadPtr(parv[2])) {
  134. sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, sptr->name, MSG_RKLINE); // Show "needs more parameters" error string
  135. return -1; // "Critical" error
  136. }
  137. if(!(srv = find_server(parv[1], NULL))) {
  138. sendnotice(sptr, "[m_rtkl] Invalid server name: %s (server not found)", parv[1]);
  139. return -1; // "Critical" error
  140. }
  141. memset(buf, '\0', BUFSIZE);
  142. for(i = 2; i < parc && parv[i]; i++) {
  143. if(i == 2) {
  144. ircsnprintf(buf, BUFSIZE, "%s", parv[i]);
  145. if(*parv[i] == '-') // No need to process any more args for deletions =]
  146. break;
  147. }
  148. else
  149. ircsnprintf(buf, BUFSIZE, "%s %s", buf, parv[i]);
  150. }
  151. sendto_snomask_global(SNO_TKL, "*** [m_rtkl] %s (%s@%s) used %s for server %s [args = %s]", sptr->name, sptr->user->username, sptr->user->realhost, cmd, parv[1], buf);
  152. *cmd++; // Skip the R in RKLINE etc =]
  153. sendto_one(srv, ":%s %s %s", sptr->name, cmd, buf);
  154. return 0; // All good
  155. }
  156. int hook_tkl_add(aClient *cptr, aClient *sptr, aTKline *tkl, int parc, char *parv[]) {
  157. return hook_tkl_main(cptr, sptr, tkl, parc, parv, '+');
  158. }
  159. int hook_tkl_del(aClient *cptr, aClient *sptr, aTKline *tkl, int parc, char *parv[]) {
  160. return hook_tkl_main(cptr, sptr, tkl, parc, parv, '-');
  161. }
  162. int hook_tkl_main(aClient *cptr, aClient *sptr, aTKline *tkl, int parc, char *parv[], char flag) {
  163. char *p, *nick; // To get just the nick bit from the full user!ident@host mask lol
  164. aClient *acptr; // Pointer to the client using that nick
  165. if(!sptr || MyClient(sptr) || parc < 6 || BadPtr(parv[5]) || !strchr("zk", *parv[2])) // Only respond to non-local clients and _local_ K/Z:Lines ;];]
  166. return 0; // kbye
  167. nick = strdup(parv[5]);
  168. if(!(p = strrchr(nick, '!'))) // If for some reason the arg is malformed (expecting user!ident@host here), bail the fuck out
  169. return 0;
  170. *p = '\0';
  171. if(!(acptr = find_person(nick, NULL))) // Validate target nick
  172. return 0; // Lolnope
  173. char buf[BUFSIZE]; // Outbut buffer lol
  174. char *timeret; // Time buffer yo
  175. memset(buf, '\0', BUFSIZE); // Just in caes lol
  176. // Let's build that fucking message
  177. ircsnprintf(buf, BUFSIZE, "[m_rtkl] %s", (flag == '+' ? "Added" : "Removed")); // Let's start with the "direction"
  178. // Check if the X:Line is permanent
  179. if(tkl->expire_at == 0)
  180. ircsnprintf(buf, BUFSIZE, "%s permanent", buf); // Append that shit
  181. // Always mention the X:Line type and the user@host mask
  182. ircsnprintf(buf, BUFSIZE, "%s (local) %c:Line for %s@%s", buf, toupper(*parv[2]), tkl->usermask, tkl->hostmask);
  183. // If deleting only...
  184. if(flag == '-') {
  185. timeret = asctime(gmtime((TS *)&tkl->set_at)); // ...get original "set at" time as a char * ...
  186. ircsnprintf(buf, BUFSIZE, "%s set by %s at %s GMT", buf, tkl->setby, timeret); // ...as well as "setby", then append that shit
  187. }
  188. if(tkl->expire_at > 0) { // If the X:Line would've expired (deleting) or will expire at some point (adding) ...
  189. timeret = asctime(gmtime((TS *)&tkl->expire_at)); // ... get that shit too as a char * ...
  190. ircsnprintf(buf, BUFSIZE, "%s (to expire at %s GMT, reason: ", buf, timeret); // ...and append em w/o setby (is not necessary when adding)
  191. }
  192. else // Permanent X:Line, no need for expiration field
  193. ircsnprintf(buf, BUFSIZE, "%s (reason: ", buf); // Open parenthesis group thingy for da raisin
  194. ircsnprintf(buf, BUFSIZE, "%s %s)", buf, tkl->reason); // Actual reason gets appended here lol, w/ closing parenthesis
  195. sendnotice(acptr, buf); // Send that fucking abomination
  196. return 0; // Can't do shit anyways =]
  197. }