]> jfr.im git - irc/quakenet/newserv.git/blob - fakeusers/fakeusers.c
Clean up fakeusers even more.
[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 static fakeuser *fakeuserlist;
38 static DBAPIConn *nofudb;
39
40 static void reconnectfakeuser(void *arg);
41
42 static fakeuser *findfakeuserbynick(char *nick) {
43 fakeuser *fake;
44
45 for (fake = fakeuserlist; fake; fake = fake->next)
46 if (!ircd_strcmp(nick, fake->nick))
47 return fake;
48
49 return NULL;
50 }
51
52 static void fake_free(fakeuser *fake) {
53 fakeuser **pnext;
54
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;
64 }
65 }
66
67 free(fake);
68 }
69
70 static void fake_remove(fakeuser *fake) {
71 nofudb->squery(nofudb, "DELETE FROM ? WHERE nick = ?", "Ts", "fakeusers", fake->nick);
72
73 fake_free(fake);
74 }
75
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);
80
81 fake = findfakeuserbynick(user->nick);
82
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 }
88
89 fake->user = NULL;
90
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 }
102 }
103
104 static void reconnectfakeuser(void *arg) {
105 fakeuser *fake = arg;
106 nick *user;
107
108 if (fake->user)
109 return;
110
111 if ((user = getnickbynick(fake->nick)) && (IsOper(user) || IsService(user) || IsXOper(user)))
112 return;
113
114 fake->user = registerlocaluser(fake->nick, fake->ident, fake->host, fake->realname,
115 NULL, UMODE_INV | UMODE_DEAF, &fakeuser_handler);
116 }
117
118 static fakeuser *fake_add(const char *nick, const char *ident, const char *host, const char *realname) {
119 fakeuser *fake;
120
121 fake = malloc(sizeof(fakeuser));
122
123 if (!fake)
124 return NULL;
125
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);
130
131 fake->user = NULL;
132 fake->lastkill = 0;
133
134 fake->next = fakeuserlist;
135 fakeuserlist = fake;
136
137 scheduleoneshot(time(NULL) + 1, reconnectfakeuser, fake);
138
139 return fake;
140 }
141
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);
146
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);
152
153 return fake;
154 }
155
156 static void fakeusers_load(const DBAPIResult *res, void *arg) {
157 if (!res)
158 return;
159
160 if (!res->success) {
161 Error("fakeuser", ERR_ERROR, "Error loading fakeuser list.");
162 res->clear(res);
163 return;
164 }
165
166 while (res->next(res))
167 fake_add(res->get(res, 0), res->get(res, 1), res->get(res, 2), res->get(res, 3));
168
169 res->clear(res);
170 }
171
172 static int fakeuser_loaddb() {
173 if (!nofudb) {
174 nofudb = dbapi2open(DBAPI2_DEFAULT, "fakeusers");
175
176 if (!nofudb) {
177 Error("fakeuser", ERR_STOP, "Could not connect to database.");
178 return 0;
179 }
180 }
181
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);
189
190 nofudb->query(nofudb, fakeusers_load, NULL,
191 "SELECT nick, ident, host, realname FROM ?", "T", "fakeusers");
192
193 return 1;
194 }
195
196 static int fakeadd(void *source, int cargc, char **cargv) {
197 nick *sender = source;
198 fakeuser *fake;
199 char *nick, *ident, *realname;
200 char host[HOSTLEN + 1];
201
202 if (cargc == 0)
203 return CMD_USAGE;
204
205 fake = findfakeuserbynick(cargv[0]);
206
207 if (fake) {
208 controlreply(sender, "Fake User with nick %s already found", cargv[0]);
209 return CMD_ERROR;
210 }
211
212 nick = cargv[0];
213
214 if (cargc < 4)
215 realname = cargv[0];
216 else
217 realname = cargv[3];
218
219 if (cargc < 3) {
220 strlcpy(host, cargv[0], NICKLEN + 1);
221 strlcat(host, ".fakeusers.quakenet.org", HOSTLEN + 1);
222 } else
223 strlcpy(host, cargv[2], HOSTLEN + 1);
224
225 if (cargc < 2)
226 ident = cargv[0];
227 else
228 ident = cargv[1];
229
230 fake = fake_create(nick, ident, host, realname);
231
232 if (!fake)
233 return CMD_ERROR;
234
235 controlreply(sender, "Added fake user %s", fake->nick);
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);
238
239 scheduleoneshot(time(NULL) + 1, &reconnectfakeuser, fake);
240 return CMD_OK;
241 }
242
243 static int fakelist(void *sender, int cargc, char **cargv) {
244 fakeuser *fake;
245 int fakeusercount = 0;
246
247 for (fake = fakeuserlist; fake; fake = fake->next) {
248 if (!fake->user)
249 controlreply(sender, "%s!%s@%s (%s) - RECONNECTING", fake->nick, fake->ident,
250 fake->host, fake->realname);
251 else
252 controlreply(sender, "%s!%s@%s (%s)", fake->nick, fake->ident,
253 fake->host, fake->realname);
254
255 fakeusercount++;
256 }
257
258 controlreply(sender, "%d fakeusers are currently connected", fakeusercount);
259 return CMD_OK;
260 }
261
262 static int fakekill(void *sender, int cargc, char **cargv) {
263 fakeuser *fake;
264
265 if (cargc == 0)
266 return CMD_USAGE;
267
268 fake = findfakeuserbynick(cargv[0]);
269
270 if (!fake) {
271 controlreply(sender, "No Fake User with nick %s found", cargv[0]);
272 return CMD_ERROR;
273 }
274
275 nofudb->squery(nofudb, "DELETE FROM ? WHERE nick = ?", "Ts", "fakeusers", fake->nick);
276 controlreply(sender, "Killed fake user %s", fake->nick);
277 controlwall(NO_OPER, NL_FAKEUSERS, "Fake user %s!%s@%s (%s) removed by %s/%s", fake->nick, fake->ident,
278 fake->host, fake->realname, ((nick *)sender)->nick, ((nick *)sender)->authname);
279
280 fake_remove(fake);
281 return CMD_OK;
282 }
283
284 void _init() {
285 if (!fakeuser_loaddb()) {
286 Error("fakeuser", ERR_FATAL, "Cannot load database");
287 return;
288 }
289
290 registercontrolhelpcmd("fakeuser", NO_OPER, 4, &fakeadd, "Usage: FAKEUSER nick <ident> <host> <realname>\nCreates a fake user.");
291 registercontrolhelpcmd("fakelist", NO_OPER, 0, &fakelist, "Usage: FAKELIST\nLists all fake users.");
292 registercontrolhelpcmd("fakekill", NO_OPER, 2, &fakekill, "Usage: FAKEKILL nick\nRemoves a fake user");
293 }
294
295 void _fini() {
296 fakeuser *fake, *next;
297
298 for (fake = fakeuserlist; fake; fake = next) {
299 next = fake->next;
300 fake_free(fake);
301 }
302
303 deregistercontrolcmd("fakeuser", &fakeadd);
304 deregistercontrolcmd("fakelist", &fakelist);
305 deregistercontrolcmd("fakekill", &fakekill);
306 }