]>
Commit | Line | Data |
---|---|---|
8ac0e8a7 CP |
1 | /* |
2 | * NOperserv Fakeuser module | |
3 | * | |
4 | * Allows fakeusers to be added so as to block nicks, for example. | |
5 | * | |
6 | * Copyright (c) Tim Gordon 2006. | |
7 | */ | |
8 | ||
9 | #include "../core/schedule.h" | |
10 | #include "../localuser/localuser.h" | |
11 | #include "../localuser/localuserchannel.h" | |
12 | #include "../irc/irc_config.h" | |
13 | #include "../lib/irc_string.h" | |
14 | #include "../control/control.h" | |
15 | #include "../channel/channel.h" | |
6c5439b1 | 16 | #include "../dbapi2/dbapi2.h" |
8ac0e8a7 | 17 | #include "../lib/strlfunc.h" |
87698d77 | 18 | #include "../lib/version.h" |
8ac0e8a7 CP |
19 | #include <string.h> |
20 | #include <stdlib.h> | |
8ac0e8a7 | 21 | |
70b0a4e5 | 22 | MODULE_VERSION(""); |
87698d77 | 23 | |
8ac0e8a7 CP |
24 | #define KILL_WAIT 10 |
25 | #define KILL_TIME 60 | |
26 | ||
27 | typedef struct fakeuser { | |
8ac0e8a7 CP |
28 | char nick[NICKLEN + 1]; |
29 | char ident[USERLEN + 1]; | |
30 | char host[HOSTLEN + 1]; | |
31 | char realname[REALLEN + 1]; | |
57eb978d | 32 | nick *user; |
8ac0e8a7 | 33 | time_t lastkill; |
57eb978d P |
34 | struct fakeuser *next; |
35 | } fakeuser; | |
8ac0e8a7 | 36 | |
710f0af8 | 37 | static fakeuser *fakeuserlist; |
6c5439b1 P |
38 | static DBAPIConn *nofudb; |
39 | ||
710f0af8 GB |
40 | static void reconnectfakeuser(void *arg); |
41 | ||
42 | static fakeuser *findfakeuserbynick(char *nick) { | |
8ac0e8a7 | 43 | fakeuser *fake; |
e0f6f3b8 | 44 | |
710f0af8 GB |
45 | for (fake = fakeuserlist; fake; fake = fake->next) |
46 | if (!ircd_strcmp(nick, fake->nick)) | |
47 | return fake; | |
e0f6f3b8 | 48 | |
710f0af8 | 49 | return NULL; |
8ac0e8a7 CP |
50 | } |
51 | ||
710f0af8 GB |
52 | static void fake_free(fakeuser *fake) { |
53 | fakeuser **pnext; | |
e0f6f3b8 | 54 | |
710f0af8 GB |
55 | if (fake->user) |
56 | deregisterlocaluser(fake->user, "Signing off"); | |
57 | ||
58 | deleteschedule(NULL, &reconnectfakeuser, fake); | |
59 | ||
60 | for (pnext = &fakeuserlist; *pnext; pnext = &((*pnext)->next)) { | |
61 | if (*pnext == fake) { | |
62 | *pnext = fake->next; | |
63 | break; | |
6c5439b1 P |
64 | } |
65 | } | |
66 | ||
710f0af8 GB |
67 | free(fake); |
68 | } | |
6c5439b1 | 69 | |
710f0af8 GB |
70 | static void fake_remove(fakeuser *fake) { |
71 | nofudb->squery(nofudb, "DELETE FROM ? WHERE nick = ?", "Ts", "fakeusers", fake->nick); | |
72 | ||
73 | fake_free(fake); | |
8ac0e8a7 CP |
74 | } |
75 | ||
710f0af8 GB |
76 | static void fakeuser_handler(nick *user, int command, void **params) { |
77 | if (command == LU_KILLED) { | |
78 | fakeuser *fake; | |
79 | time_t timenow = time(NULL); | |
8ac0e8a7 | 80 | |
710f0af8 | 81 | fake = findfakeuserbynick(user->nick); |
6c5439b1 | 82 | |
710f0af8 GB |
83 | if (!fake) { |
84 | controlwall(NO_OPER, NL_FAKEUSERS, "Error: A fakeuser was killed, but wasn't found in the list"); | |
85 | Error("fakeuser", ERR_ERROR, "A fakeuser was killed, but wasn't found in the list"); | |
86 | return; | |
87 | } | |
8ac0e8a7 | 88 | |
710f0af8 | 89 | fake->user = NULL; |
e0f6f3b8 | 90 | |
710f0af8 GB |
91 | if (timenow - fake->lastkill < KILL_TIME) { |
92 | controlwall(NO_OPER, NL_FAKEUSERS, "Fake user %s!%s@%s (%s) KILL'ed twice under in %d seconds. Removing.", | |
93 | fake->nick, fake->ident, fake->host, fake->realname, KILL_TIME); | |
94 | fake_remove(fake); | |
95 | return; | |
96 | } | |
97 | ||
98 | fake->lastkill = timenow; | |
99 | ||
100 | scheduleoneshot(time(NULL) + KILL_WAIT, &reconnectfakeuser, fake); | |
101 | } | |
8ac0e8a7 CP |
102 | } |
103 | ||
710f0af8 GB |
104 | static void reconnectfakeuser(void *arg) { |
105 | fakeuser *fake = arg; | |
8ac0e8a7 | 106 | nick *user; |
710f0af8 GB |
107 | |
108 | if (fake->user) | |
109 | return; | |
e0f6f3b8 | 110 | |
710f0af8 GB |
111 | if ((user = getnickbynick(fake->nick)) && (IsOper(user) || IsService(user) || IsXOper(user))) |
112 | return; | |
8ac0e8a7 | 113 | |
710f0af8 GB |
114 | fake->user = registerlocaluser(fake->nick, fake->ident, fake->host, fake->realname, |
115 | NULL, UMODE_INV | UMODE_DEAF, &fakeuser_handler); | |
8ac0e8a7 CP |
116 | } |
117 | ||
710f0af8 GB |
118 | static fakeuser *fake_add(const char *nick, const char *ident, const char *host, const char *realname) { |
119 | fakeuser *fake; | |
8ac0e8a7 | 120 | |
710f0af8 | 121 | fake = malloc(sizeof(fakeuser)); |
e0f6f3b8 | 122 | |
710f0af8 | 123 | if (!fake) |
8ac0e8a7 | 124 | return NULL; |
8ac0e8a7 | 125 | |
710f0af8 GB |
126 | strlcpy(fake->nick, nick, NICKLEN + 1); |
127 | strlcpy(fake->ident, ident, USERLEN + 1); | |
128 | strlcpy(fake->host, host, HOSTLEN + 1); | |
129 | strlcpy(fake->realname, realname, REALLEN + 1); | |
8ac0e8a7 | 130 | |
710f0af8 GB |
131 | fake->user = NULL; |
132 | fake->lastkill = 0; | |
8ac0e8a7 | 133 | |
710f0af8 GB |
134 | fake->next = fakeuserlist; |
135 | fakeuserlist = fake; | |
136 | ||
137 | scheduleoneshot(time(NULL) + 1, reconnectfakeuser, fake); | |
138 | ||
139 | return fake; | |
8ac0e8a7 CP |
140 | } |
141 | ||
710f0af8 GB |
142 | static fakeuser *fake_create(const char *nick, const char *ident, const char *host, const char *realname) { |
143 | fakeuser *fake; | |
144 | ||
145 | fake = fake_add(nick, ident, host, realname); | |
8ac0e8a7 | 146 | |
710f0af8 GB |
147 | if (!fake) |
148 | return NULL; | |
149 | ||
150 | nofudb->squery(nofudb, "INSERT INTO ? (nick, ident, host, realname) VALUES (?,?,?,?)", "Tssss", "fakeusers", | |
151 | fake->nick, fake->ident, fake->host, fake->realname); | |
e0f6f3b8 | 152 | |
710f0af8 GB |
153 | return fake; |
154 | } | |
8bbe812b | 155 | |
710f0af8 GB |
156 | static void fakeusers_load(const DBAPIResult *res, void *arg) { |
157 | if (!res) | |
158 | return; | |
e0f6f3b8 | 159 | |
710f0af8 GB |
160 | if (!res->success) { |
161 | Error("fakeuser", ERR_ERROR, "Error loading fakeuser list."); | |
162 | res->clear(res); | |
163 | return; | |
8ac0e8a7 | 164 | } |
8ac0e8a7 | 165 | |
710f0af8 GB |
166 | while (res->next(res)) |
167 | fake_add(res->get(res, 0), res->get(res, 1), res->get(res, 2), res->get(res, 3)); | |
e0f6f3b8 | 168 | |
710f0af8 GB |
169 | res->clear(res); |
170 | } | |
8ac0e8a7 | 171 | |
710f0af8 GB |
172 | static int fakeuser_loaddb() { |
173 | if (!nofudb) { | |
174 | nofudb = dbapi2open(DBAPI2_DEFAULT, "fakeusers"); | |
8ac0e8a7 | 175 | |
710f0af8 GB |
176 | if (!nofudb) { |
177 | Error("fakeuser", ERR_STOP, "Could not connect to database."); | |
178 | return 0; | |
8ac0e8a7 | 179 | } |
710f0af8 | 180 | } |
e0f6f3b8 | 181 | |
710f0af8 GB |
182 | nofudb->createtable(nofudb, NULL, NULL, |
183 | "CREATE TABLE ? (" | |
184 | "nick VARCHAR(?) NOT NULL," | |
185 | "ident VARCHAR(?) NOT NULL," | |
186 | "host VARCHAR(?) NOT NULL," | |
187 | "realname VARCHAR(?) NOT NULL," | |
188 | "PRIMARY KEY (nick))", "Tdddd", "fakeusers", NICKLEN, USERLEN, HOSTLEN, REALLEN); | |
8ac0e8a7 | 189 | |
710f0af8 GB |
190 | nofudb->query(nofudb, fakeusers_load, NULL, |
191 | "SELECT nick, ident, host, realname FROM ?", "T", "fakeusers"); | |
192 | ||
193 | return 1; | |
8ac0e8a7 CP |
194 | } |
195 | ||
710f0af8 GB |
196 | static int fakeadd(void *source, int cargc, char **cargv) { |
197 | nick *sender = source; | |
57eb978d | 198 | fakeuser *fake; |
710f0af8 GB |
199 | char *nick, *ident, *realname; |
200 | char host[HOSTLEN + 1]; | |
8ac0e8a7 CP |
201 | |
202 | if (cargc == 0) | |
203 | return CMD_USAGE; | |
57eb978d P |
204 | |
205 | fake = findfakeuserbynick(cargv[0]); | |
e0f6f3b8 P |
206 | |
207 | if (fake) { | |
57eb978d P |
208 | controlreply(sender, "Fake User with nick %s already found", cargv[0]); |
209 | return CMD_ERROR; | |
210 | } | |
211 | ||
710f0af8 | 212 | nick = cargv[0]; |
e0f6f3b8 | 213 | |
8ac0e8a7 | 214 | if (cargc < 4) |
710f0af8 | 215 | realname = cargv[0]; |
8ac0e8a7 | 216 | else |
710f0af8 | 217 | realname = cargv[3]; |
e0f6f3b8 P |
218 | |
219 | if (cargc < 3) { | |
710f0af8 GB |
220 | strlcpy(host, cargv[0], NICKLEN + 1); |
221 | strlcat(host, ".fakeusers.quakenet.org", HOSTLEN + 1); | |
e0f6f3b8 | 222 | } else |
710f0af8 | 223 | strlcpy(host, cargv[2], HOSTLEN + 1); |
e0f6f3b8 | 224 | |
8ac0e8a7 | 225 | if (cargc < 2) |
710f0af8 | 226 | ident = cargv[0]; |
8ac0e8a7 | 227 | else |
710f0af8 | 228 | ident = cargv[1]; |
8ac0e8a7 | 229 | |
710f0af8 | 230 | fake = fake_create(nick, ident, host, realname); |
e0f6f3b8 | 231 | |
710f0af8 | 232 | if (!fake) |
8ac0e8a7 | 233 | return CMD_ERROR; |
57eb978d | 234 | |
57eb978d | 235 | controlreply(sender, "Added fake user %s", fake->nick); |
710f0af8 GB |
236 | controlwall(NO_OPER, NL_FAKEUSERS, "%s added fake user: %s!%s@%s (%s)", controlid(sender), |
237 | fake->nick, fake->ident, fake->host, fake->realname); | |
57eb978d | 238 | |
710f0af8 | 239 | scheduleoneshot(time(NULL) + 1, &reconnectfakeuser, fake); |
836d332e | 240 | |
8ac0e8a7 CP |
241 | return CMD_OK; |
242 | } | |
243 | ||
710f0af8 | 244 | static int fakelist(void *sender, int cargc, char **cargv) { |
8ac0e8a7 | 245 | fakeuser *fake; |
e0f6f3b8 P |
246 | int fakeusercount = 0; |
247 | ||
248 | for (fake = fakeuserlist; fake; fake = fake->next) { | |
249 | if (!fake->user) | |
8bbe812b | 250 | controlreply(sender, "%s!%s@%s (%s) - RECONNECTING", fake->nick, fake->ident, |
57eb978d | 251 | fake->host, fake->realname); |
8ac0e8a7 | 252 | else |
57eb978d P |
253 | controlreply(sender, "%s!%s@%s (%s)", fake->nick, fake->ident, |
254 | fake->host, fake->realname); | |
255 | ||
256 | fakeusercount++; | |
8ac0e8a7 | 257 | } |
e0f6f3b8 | 258 | |
57eb978d | 259 | controlreply(sender, "%d fakeusers are currently connected", fakeusercount); |
836d332e | 260 | |
8ac0e8a7 CP |
261 | return CMD_OK; |
262 | } | |
263 | ||
710f0af8 | 264 | static int fakekill(void *sender, int cargc, char **cargv) { |
8ac0e8a7 | 265 | fakeuser *fake; |
e0f6f3b8 | 266 | |
8ac0e8a7 CP |
267 | if (cargc == 0) |
268 | return CMD_USAGE; | |
57eb978d P |
269 | |
270 | fake = findfakeuserbynick(cargv[0]); | |
e0f6f3b8 P |
271 | |
272 | if (!fake) { | |
57eb978d P |
273 | controlreply(sender, "No Fake User with nick %s found", cargv[0]); |
274 | return CMD_ERROR; | |
275 | } | |
276 | ||
57eb978d P |
277 | controlreply(sender, "Killed fake user %s", fake->nick); |
278 | controlwall(NO_OPER, NL_FAKEUSERS, "Fake user %s!%s@%s (%s) removed by %s/%s", fake->nick, fake->ident, | |
e0f6f3b8 | 279 | fake->host, fake->realname, ((nick *)sender)->nick, ((nick *)sender)->authname); |
57eb978d | 280 | |
710f0af8 | 281 | fake_remove(fake); |
836d332e | 282 | |
57eb978d P |
283 | return CMD_OK; |
284 | } | |
285 | ||
8bbe812b P |
286 | void _init() { |
287 | if (!fakeuser_loaddb()) { | |
288 | Error("fakeuser", ERR_FATAL, "Cannot load database"); | |
289 | return; | |
290 | } | |
291 | ||
292 | registercontrolhelpcmd("fakeuser", NO_OPER, 4, &fakeadd, "Usage: FAKEUSER nick <ident> <host> <realname>\nCreates a fake user."); | |
293 | registercontrolhelpcmd("fakelist", NO_OPER, 0, &fakelist, "Usage: FAKELIST\nLists all fake users."); | |
294 | registercontrolhelpcmd("fakekill", NO_OPER, 2, &fakekill, "Usage: FAKEKILL nick\nRemoves a fake user"); | |
295 | } | |
296 | ||
297 | void _fini() { | |
710f0af8 GB |
298 | fakeuser *fake, *next; |
299 | ||
300 | for (fake = fakeuserlist; fake; fake = next) { | |
301 | next = fake->next; | |
302 | fake_free(fake); | |
303 | } | |
304 | ||
8bbe812b P |
305 | deregistercontrolcmd("fakeuser", &fakeadd); |
306 | deregistercontrolcmd("fakelist", &fakelist); | |
307 | deregistercontrolcmd("fakekill", &fakekill); | |
308 | } |