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