]> jfr.im git - irc/quakenet/newserv.git/blame - fakeusers/fakeusers.c
FAKEUSERS: astyle -A2 -s2 -f -p -k3 -S -U -H -n
[irc/quakenet/newserv.git] / fakeusers / fakeusers.c
CommitLineData
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 22MODULE_VERSION("");
87698d77 23
8ac0e8a7
CP
24#define KILL_WAIT 10
25#define KILL_TIME 60
26
27typedef 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
CP
36
37fakeuser *fakeuserlist = NULL;
8ac0e8a7
CP
38
39void fakeuser_cleanup();
40int fakeuser_loaddb();
6c5439b1 41void fakeusers_load(const DBAPIResult *res, void *arg);
8ac0e8a7
CP
42void fakeuser_handler(nick *user, int command, void **params);
43int fakeadd(void *sender, int cargc, char **cargv);
44int fakelist(void *sender, int cargc, char **cargv);
45int fakekill(void *sender, int cargc, char **cargv);
57eb978d 46void schedulefakeuser(void *arg);
e0f6f3b8 47fakeuser *findfakeuserbynick(char *nick);
57eb978d
P
48void fake_remove(char *nickname);
49fakeuser *fake_add(fakeuser *details);
8ac0e8a7 50
6c5439b1
P
51static DBAPIConn *nofudb;
52
8ac0e8a7 53void _init() {
e0f6f3b8 54 if (!fakeuser_loaddb()) {
6189af13 55 Error("fakeuser", ERR_FATAL, "Cannot load database");
8ac0e8a7
CP
56 return;
57 }
e0f6f3b8 58
8ac0e8a7
CP
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");
57eb978d 62
8ac0e8a7
CP
63}
64
65void _fini() {
66 fakeuser_cleanup();
57eb978d 67 deleteallschedules(schedulefakeuser);
8ac0e8a7
CP
68 deregistercontrolcmd("fakeuser", &fakeadd);
69 deregistercontrolcmd("fakelist", &fakelist);
70 deregistercontrolcmd("fakekill", &fakekill);
71}
72
e0f6f3b8 73void fakeuser_cleanup() {
8ac0e8a7 74 fakeuser *fake;
8ac0e8a7 75 void *next;
e0f6f3b8
P
76
77 for (fake = fakeuserlist; fake; fake = next) {
8ac0e8a7
CP
78 deregisterlocaluser(fake->user, "Signing off");
79 next = fake->next;
80 free(fake);
81 }
e0f6f3b8 82
8ac0e8a7 83 fakeuserlist = NULL;
8ac0e8a7
CP
84}
85
e0f6f3b8 86int fakeuser_loaddb() {
6c5439b1 87 if (!nofudb) {
6189af13 88 nofudb = dbapi2open(DBAPI2_DEFAULT, "fakeusers");
e0f6f3b8
P
89
90 if (!nofudb) {
6c5439b1
P
91 Error("fakeuser", ERR_STOP, "Could not connect to database.");
92 return 0;
93 }
94 }
95
e0f6f3b8
P
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);
6c5439b1
P
103
104 nofudb->query(nofudb, fakeusers_load, NULL,
e0f6f3b8 105 "SELECT nick, ident, host, realname FROM ?", "T", "fakeusers");
6c5439b1 106
8ac0e8a7
CP
107 return 1;
108}
109
6c5439b1 110void fakeusers_load(const DBAPIResult *res, void *arg) {
57eb978d 111 fakeuser fakeuser;
8ac0e8a7 112
e0f6f3b8 113 if (!res)
6c5439b1
P
114 return;
115
e0f6f3b8 116 if (!res->success) {
6c5439b1
P
117 Error("fakeuser", ERR_ERROR, "Error loading fakeuser list.");
118 res->clear(res);
8ac0e8a7
CP
119 return;
120 }
8ac0e8a7 121
e0f6f3b8 122 while (res->next(res)) {
57eb978d
P
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);
8ac0e8a7 128 }
e0f6f3b8
P
129
130 scheduleoneshot(time(NULL) + 1, schedulefakeuser, NULL);
6c5439b1 131 res->clear(res);
8ac0e8a7
CP
132}
133
e0f6f3b8 134fakeuser *getdetails(nick *user) {
57eb978d
P
135 fakeuser *details;
136 details = malloc(sizeof(fakeuser));
e0f6f3b8 137
8ac0e8a7
CP
138 if (!details)
139 return NULL;
e0f6f3b8 140
8ac0e8a7
CP
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
e0f6f3b8 149nick *register_fakeuseronnet(fakeuser *details) {
8ac0e8a7 150 nick *user;
e0f6f3b8 151
15167802 152 if ((user = getnickbynick(details->nick)) && (IsOper(user) || IsService(user) || IsXOper(user))) {
8ac0e8a7
CP
153 return NULL;
154 }
155
8ac0e8a7 156 return registerlocaluser(details->nick, details->ident, details->host, details->realname,
e0f6f3b8 157 NULL, UMODE_INV | UMODE_DEAF, &fakeuser_handler);
8ac0e8a7
CP
158}
159
e0f6f3b8 160fakeuser *fake_add(fakeuser *details) {
57eb978d 161 fakeuser *newfake;
8ac0e8a7 162
8ac0e8a7 163 newfake = malloc(sizeof(fakeuser));
e0f6f3b8
P
164
165 if (!newfake) {
8ac0e8a7
CP
166 return NULL;
167 }
8ac0e8a7 168
57eb978d 169 memcpy(newfake, details, sizeof(fakeuser));
8ac0e8a7 170
57eb978d
P
171 newfake->user = NULL;
172 newfake->lastkill = 0;
8ac0e8a7 173
57eb978d
P
174 newfake->next = fakeuserlist;
175 fakeuserlist = newfake;
176 return newfake;
8ac0e8a7
CP
177}
178
57eb978d
P
179void fake_remove(char *nickname) {
180 fakeuser *fake, *prev;
8ac0e8a7 181
e0f6f3b8
P
182 for (fake = fakeuserlist; fake; fake = fake->next) {
183 if (!ircd_strcmp(nickname, fake->nick)) {
184 if (fake == fakeuserlist)
185 fakeuserlist = fake->next;
57eb978d 186 else
e0f6f3b8
P
187 prev->next = fake->next;
188
57eb978d
P
189 free(fake);
190 return;
8ac0e8a7 191 }
e0f6f3b8
P
192
193 prev = fake;
8ac0e8a7 194 }
8ac0e8a7
CP
195}
196
e0f6f3b8
P
197void fakeuser_handler(nick *user, int command, void **params) {
198 if (command == LU_KILLED) {
8ac0e8a7
CP
199 fakeuser *item;
200 time_t timenow = time(NULL);
201
57eb978d 202 item = findfakeuserbynick(user->nick);
e0f6f3b8
P
203
204 if (!item) {
15167802 205 controlwall(NO_OPER, NL_FAKEUSERS, "Error: A fakeuser was killed, but wasn't found in the list");
6189af13 206 Error("fakeuser", ERR_ERROR, "A fakeuser was killed, but wasn't found in the list");
8ac0e8a7 207 return;
15167802 208 }
8ac0e8a7 209
57eb978d 210 item->user = NULL;
8ac0e8a7 211
57eb978d
P
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);
8ac0e8a7
CP
216 return;
217 }
e0f6f3b8 218
57eb978d 219 item->lastkill = timenow;
8ac0e8a7 220
57eb978d 221 scheduleoneshot(time(NULL) + KILL_WAIT, schedulefakeuser, item);
8ac0e8a7
CP
222 }
223}
224
e0f6f3b8 225int fakeadd(void *sender, int cargc, char **cargv) {
57eb978d
P
226 fakeuser newfake;
227 fakeuser *fake;
8ac0e8a7
CP
228
229 if (cargc == 0)
230 return CMD_USAGE;
57eb978d
P
231
232 fake = findfakeuserbynick(cargv[0]);
e0f6f3b8
P
233
234 if (fake) {
57eb978d
P
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);
e0f6f3b8 240
8ac0e8a7 241 if (cargc < 4)
57eb978d 242 strlcpy(newfake.realname, cargv[0], REALLEN + 1);
8ac0e8a7 243 else
57eb978d 244 strlcpy(newfake.realname, cargv[3], REALLEN + 1);
e0f6f3b8
P
245
246 if (cargc < 3) {
57eb978d
P
247 strlcpy(newfake.host, cargv[0], NICKLEN + 1);
248 strlcat(newfake.host, ".fakeusers.quakenet.org", HOSTLEN + 1);
e0f6f3b8 249 } else
57eb978d 250 strlcpy(newfake.host, cargv[2], HOSTLEN + 1);
e0f6f3b8 251
8ac0e8a7 252 if (cargc < 2)
57eb978d 253 strlcpy(newfake.ident, cargv[0], USERLEN + 1);
8ac0e8a7 254 else
57eb978d 255 strlcpy(newfake.ident, cargv[1], USERLEN + 1);
8ac0e8a7 256
57eb978d 257 fake = fake_add(&newfake);
e0f6f3b8
P
258
259 if (!fake) {
8ac0e8a7
CP
260 return CMD_ERROR;
261 }
57eb978d
P
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,
e0f6f3b8 266 fake->host, fake->realname, ((nick *)sender)->nick, ((nick *)sender)->authname);
57eb978d
P
267
268 scheduleoneshot(time(NULL) + 1, schedulefakeuser, fake);
8ac0e8a7
CP
269 return CMD_OK;
270}
271
e0f6f3b8 272int fakelist(void *sender, int cargc, char **cargv) {
8ac0e8a7 273 fakeuser *fake;
e0f6f3b8
P
274 int fakeusercount = 0;
275
276 for (fake = fakeuserlist; fake; fake = fake->next) {
277 if (!fake->user)
57eb978d
P
278 controlreply(sender, "%s!%s@%s (%s) %s - RECONNECTING", fake->nick, fake->ident,
279 fake->host, fake->realname);
8ac0e8a7 280 else
57eb978d
P
281 controlreply(sender, "%s!%s@%s (%s)", fake->nick, fake->ident,
282 fake->host, fake->realname);
283
284 fakeusercount++;
8ac0e8a7 285 }
e0f6f3b8 286
57eb978d 287 controlreply(sender, "%d fakeusers are currently connected", fakeusercount);
8ac0e8a7
CP
288 return CMD_OK;
289}
290
e0f6f3b8 291int fakekill(void *sender, int cargc, char **cargv) {
8ac0e8a7 292 fakeuser *fake;
e0f6f3b8 293
8ac0e8a7
CP
294 if (cargc == 0)
295 return CMD_USAGE;
57eb978d
P
296
297 fake = findfakeuserbynick(cargv[0]);
e0f6f3b8
P
298
299 if (!fake) {
57eb978d
P
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,
e0f6f3b8 307 fake->host, fake->realname, ((nick *)sender)->nick, ((nick *)sender)->authname);
57eb978d 308
e0f6f3b8 309 if (fake->user) {
8ac0e8a7
CP
310 if (cargc > 1)
311 deregisterlocaluser(fake->user, cargv[1]);
312 else
313 deregisterlocaluser(fake->user, "Signing off");
8ac0e8a7 314 }
57eb978d
P
315
316 fake_remove(cargv[0]);
317 return CMD_OK;
318}
319
320void schedulefakeuser(void *arg) {
321 fakeuser *fake;
e0f6f3b8
P
322
323 for (fake = fakeuserlist; fake; fake = fake->next) {
324 if (!fake->user) {
325 fake->user = register_fakeuseronnet(fake);
57eb978d 326 }
8ac0e8a7 327 }
8ac0e8a7
CP
328}
329
e0f6f3b8 330fakeuser *findfakeuserbynick(char *nick) {
8ac0e8a7 331 fakeuser *fake;
e0f6f3b8
P
332
333 for (fake = fakeuserlist; fake; fake = fake->next) {
334 if (!ircd_strcmp(nick, fake->nick)) {
57eb978d
P
335 return fake;
336 }
8ac0e8a7 337 }
e0f6f3b8 338
57eb978d 339 return NULL;
8ac0e8a7 340}