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