]> jfr.im git - irc/quakenet/newserv.git/blame - fakeusers/fakeusers.c
FAKEUSER: more tidyup
[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 38
8bbe812b
P
39static void fakeuser_cleanup();
40static int fakeuser_loaddb();
41static void fakeusers_load(const DBAPIResult *res, void *arg);
42static void fakeuser_handler(nick *user, int command, void **params);
43static int fakeadd(void *sender, int cargc, char **cargv);
44static int fakelist(void *sender, int cargc, char **cargv);
45static int fakekill(void *sender, int cargc, char **cargv);
46static void schedulefakeuser(void *arg);
47static fakeuser *findfakeuserbynick(char *nick);
48static void fake_remove(char *nickname);
49static fakeuser *fake_add(fakeuser *details);
8ac0e8a7 50
6c5439b1
P
51static DBAPIConn *nofudb;
52
e0f6f3b8 53void fakeuser_cleanup() {
8ac0e8a7 54 fakeuser *fake;
8ac0e8a7 55 void *next;
e0f6f3b8
P
56
57 for (fake = fakeuserlist; fake; fake = next) {
8ac0e8a7
CP
58 deregisterlocaluser(fake->user, "Signing off");
59 next = fake->next;
60 free(fake);
61 }
e0f6f3b8 62
8ac0e8a7 63 fakeuserlist = NULL;
8ac0e8a7
CP
64}
65
e0f6f3b8 66int fakeuser_loaddb() {
6c5439b1 67 if (!nofudb) {
6189af13 68 nofudb = dbapi2open(DBAPI2_DEFAULT, "fakeusers");
e0f6f3b8
P
69
70 if (!nofudb) {
6c5439b1
P
71 Error("fakeuser", ERR_STOP, "Could not connect to database.");
72 return 0;
73 }
74 }
75
e0f6f3b8
P
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);
6c5439b1
P
83
84 nofudb->query(nofudb, fakeusers_load, NULL,
e0f6f3b8 85 "SELECT nick, ident, host, realname FROM ?", "T", "fakeusers");
6c5439b1 86
8ac0e8a7
CP
87 return 1;
88}
89
6c5439b1 90void fakeusers_load(const DBAPIResult *res, void *arg) {
57eb978d 91 fakeuser fakeuser;
8ac0e8a7 92
e0f6f3b8 93 if (!res)
6c5439b1
P
94 return;
95
e0f6f3b8 96 if (!res->success) {
6c5439b1
P
97 Error("fakeuser", ERR_ERROR, "Error loading fakeuser list.");
98 res->clear(res);
8ac0e8a7
CP
99 return;
100 }
8ac0e8a7 101
e0f6f3b8 102 while (res->next(res)) {
57eb978d
P
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);
8ac0e8a7 108 }
e0f6f3b8
P
109
110 scheduleoneshot(time(NULL) + 1, schedulefakeuser, NULL);
6c5439b1 111 res->clear(res);
8ac0e8a7
CP
112}
113
e0f6f3b8 114nick *register_fakeuseronnet(fakeuser *details) {
8ac0e8a7 115 nick *user;
e0f6f3b8 116
15167802 117 if ((user = getnickbynick(details->nick)) && (IsOper(user) || IsService(user) || IsXOper(user))) {
8ac0e8a7
CP
118 return NULL;
119 }
120
8ac0e8a7 121 return registerlocaluser(details->nick, details->ident, details->host, details->realname,
e0f6f3b8 122 NULL, UMODE_INV | UMODE_DEAF, &fakeuser_handler);
8ac0e8a7
CP
123}
124
e0f6f3b8 125fakeuser *fake_add(fakeuser *details) {
57eb978d 126 fakeuser *newfake;
8ac0e8a7 127
8ac0e8a7 128 newfake = malloc(sizeof(fakeuser));
e0f6f3b8
P
129
130 if (!newfake) {
8ac0e8a7
CP
131 return NULL;
132 }
8ac0e8a7 133
57eb978d 134 memcpy(newfake, details, sizeof(fakeuser));
8ac0e8a7 135
57eb978d
P
136 newfake->user = NULL;
137 newfake->lastkill = 0;
8ac0e8a7 138
57eb978d
P
139 newfake->next = fakeuserlist;
140 fakeuserlist = newfake;
141 return newfake;
8ac0e8a7
CP
142}
143
57eb978d
P
144void fake_remove(char *nickname) {
145 fakeuser *fake, *prev;
8ac0e8a7 146
e0f6f3b8
P
147 for (fake = fakeuserlist; fake; fake = fake->next) {
148 if (!ircd_strcmp(nickname, fake->nick)) {
149 if (fake == fakeuserlist)
150 fakeuserlist = fake->next;
57eb978d 151 else
e0f6f3b8
P
152 prev->next = fake->next;
153
8bbe812b
P
154 if(fake->user)
155 deregisterlocaluser(fake->user, "Signing off");
156
57eb978d
P
157 free(fake);
158 return;
8ac0e8a7 159 }
e0f6f3b8
P
160
161 prev = fake;
8ac0e8a7 162 }
8ac0e8a7
CP
163}
164
e0f6f3b8
P
165void fakeuser_handler(nick *user, int command, void **params) {
166 if (command == LU_KILLED) {
8ac0e8a7
CP
167 fakeuser *item;
168 time_t timenow = time(NULL);
169
57eb978d 170 item = findfakeuserbynick(user->nick);
e0f6f3b8
P
171
172 if (!item) {
15167802 173 controlwall(NO_OPER, NL_FAKEUSERS, "Error: A fakeuser was killed, but wasn't found in the list");
6189af13 174 Error("fakeuser", ERR_ERROR, "A fakeuser was killed, but wasn't found in the list");
8ac0e8a7 175 return;
15167802 176 }
8ac0e8a7 177
57eb978d 178 item->user = NULL;
8ac0e8a7 179
57eb978d
P
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);
8ac0e8a7
CP
184 return;
185 }
e0f6f3b8 186
57eb978d 187 item->lastkill = timenow;
8ac0e8a7 188
57eb978d 189 scheduleoneshot(time(NULL) + KILL_WAIT, schedulefakeuser, item);
8ac0e8a7
CP
190 }
191}
192
e0f6f3b8 193int fakeadd(void *sender, int cargc, char **cargv) {
57eb978d
P
194 fakeuser newfake;
195 fakeuser *fake;
8ac0e8a7
CP
196
197 if (cargc == 0)
198 return CMD_USAGE;
57eb978d
P
199
200 fake = findfakeuserbynick(cargv[0]);
e0f6f3b8
P
201
202 if (fake) {
57eb978d
P
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);
e0f6f3b8 208
8ac0e8a7 209 if (cargc < 4)
57eb978d 210 strlcpy(newfake.realname, cargv[0], REALLEN + 1);
8ac0e8a7 211 else
57eb978d 212 strlcpy(newfake.realname, cargv[3], REALLEN + 1);
e0f6f3b8
P
213
214 if (cargc < 3) {
57eb978d
P
215 strlcpy(newfake.host, cargv[0], NICKLEN + 1);
216 strlcat(newfake.host, ".fakeusers.quakenet.org", HOSTLEN + 1);
e0f6f3b8 217 } else
57eb978d 218 strlcpy(newfake.host, cargv[2], HOSTLEN + 1);
e0f6f3b8 219
8ac0e8a7 220 if (cargc < 2)
57eb978d 221 strlcpy(newfake.ident, cargv[0], USERLEN + 1);
8ac0e8a7 222 else
57eb978d 223 strlcpy(newfake.ident, cargv[1], USERLEN + 1);
8ac0e8a7 224
57eb978d 225 fake = fake_add(&newfake);
e0f6f3b8
P
226
227 if (!fake) {
8ac0e8a7
CP
228 return CMD_ERROR;
229 }
57eb978d
P
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,
e0f6f3b8 234 fake->host, fake->realname, ((nick *)sender)->nick, ((nick *)sender)->authname);
57eb978d
P
235
236 scheduleoneshot(time(NULL) + 1, schedulefakeuser, fake);
8ac0e8a7
CP
237 return CMD_OK;
238}
239
e0f6f3b8 240int fakelist(void *sender, int cargc, char **cargv) {
8ac0e8a7 241 fakeuser *fake;
e0f6f3b8
P
242 int fakeusercount = 0;
243
244 for (fake = fakeuserlist; fake; fake = fake->next) {
245 if (!fake->user)
8bbe812b 246 controlreply(sender, "%s!%s@%s (%s) - RECONNECTING", fake->nick, fake->ident,
57eb978d 247 fake->host, fake->realname);
8ac0e8a7 248 else
57eb978d
P
249 controlreply(sender, "%s!%s@%s (%s)", fake->nick, fake->ident,
250 fake->host, fake->realname);
251
252 fakeusercount++;
8ac0e8a7 253 }
e0f6f3b8 254
57eb978d 255 controlreply(sender, "%d fakeusers are currently connected", fakeusercount);
8ac0e8a7
CP
256 return CMD_OK;
257}
258
e0f6f3b8 259int fakekill(void *sender, int cargc, char **cargv) {
8ac0e8a7 260 fakeuser *fake;
e0f6f3b8 261
8ac0e8a7
CP
262 if (cargc == 0)
263 return CMD_USAGE;
57eb978d
P
264
265 fake = findfakeuserbynick(cargv[0]);
e0f6f3b8
P
266
267 if (!fake) {
57eb978d
P
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,
e0f6f3b8 275 fake->host, fake->realname, ((nick *)sender)->nick, ((nick *)sender)->authname);
57eb978d 276
57eb978d
P
277 fake_remove(cargv[0]);
278 return CMD_OK;
279}
280
281void schedulefakeuser(void *arg) {
282 fakeuser *fake;
e0f6f3b8 283
8bbe812b
P
284 for (fake = fakeuserlist; fake; fake = fake->next)
285 if (!fake->user)
e0f6f3b8 286 fake->user = register_fakeuseronnet(fake);
8ac0e8a7
CP
287}
288
e0f6f3b8 289fakeuser *findfakeuserbynick(char *nick) {
8ac0e8a7 290 fakeuser *fake;
e0f6f3b8 291
8bbe812b
P
292 for (fake = fakeuserlist; fake; fake = fake->next)
293 if (!ircd_strcmp(nick, fake->nick))
57eb978d 294 return fake;
e0f6f3b8 295
57eb978d 296 return NULL;
8ac0e8a7 297}
8bbe812b
P
298
299void _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
310void _fini() {
311 fakeuser_cleanup();
312 deleteallschedules(schedulefakeuser);
313 deregistercontrolcmd("fakeuser", &fakeadd);
314 deregistercontrolcmd("fakelist", &fakelist);
315 deregistercontrolcmd("fakekill", &fakekill);
316}