]> jfr.im git - irc/quakenet/newserv.git/blame - trojanscan/trojanscan.c
Add malloc checking to lua/nterfacer/trojanscan.
[irc/quakenet/newserv.git] / trojanscan / trojanscan.c
CommitLineData
c86edd1d 1/*
378cf1b9 2 * Trojanscan version 2
c86edd1d 3 *
8f619fe4 4 * Trojanscan copyright (C) Chris Porter 2002-2007
c86edd1d
Q
5 * Newserv bits copyright (C) David Mansell 2002-2003
6 *
378cf1b9
CP
7 * TODO: CHECK::
8 * - Poke splidge about +r'ing bots, potential problems:
1fe41720 9 * - users might whine about T clone stealing account
378cf1b9
CP
10 * - would have to steal one already in use, so if trojans start using /msg q whois they'll see
11 * (though they have to be authed for this, they could use a clone of their own however)
c86edd1d
Q
12 */
13
14#include "trojanscan.h"
707e6470 15#include "../lib/strlfunc.h"
87698d77 16#include "../lib/version.h"
669e39ad 17#include "../core/nsmalloc.h"
87698d77 18
93917ccd
CP
19#define tmalloc(x) nsmalloc(POOL_TROJANSCAN, x)
20#define tfree(x) nsfree(POOL_TROJANSCAN, x)
21
8f619fe4 22MODULE_VERSION(TROJANSCAN_VERSION);
c86edd1d 23
cba071ec 24void trojanscan_phrasematch(channel *chp, nick *sender, trojanscan_phrases *phrase, char messagetype, char *matchbuf);
8f619fe4 25char *trojanscan_sanitise(char *input);
ef8d695d 26void trojanscan_refresh_settings(void);
a0c2b0da 27static void trojanscan_part_watch(int hook, void *arg);
9bf89af0 28static void trojanscan_connect_nick(void *);
8f619fe4 29
1e614cc2 30#define TROJANSCAN_SETTING_SIZE 256
8f619fe4
CP
31#define TROJANSCAN_MAX_SETTINGS 50
32
33static struct {
34 char setting[TROJANSCAN_SETTING_SIZE];
35 char value[TROJANSCAN_SETTING_SIZE];
36} trojanscan_settings[TROJANSCAN_MAX_SETTINGS];
37
38static int settingcount = 0;
39static char *versionreply;
a0c2b0da 40static int hooksregistered = 0;
9bf89af0 41static void *trojanscan_connect_nick_schedule;
cba071ec 42
c86edd1d
Q
43void _init() {
44 trojanscan_cmds = newcommandtree();
45
46 addcommandtotree(trojanscan_cmds, "showcommands", TROJANSCAN_ACL_UNAUTHED, 0, &trojanscan_showcommands);
47 addcommandtotree(trojanscan_cmds, "help", TROJANSCAN_ACL_UNAUTHED, 1, &trojanscan_help);
48 addcommandtotree(trojanscan_cmds, "hello", TROJANSCAN_ACL_UNAUTHED | TROJANSCAN_ACL_OPER, 1, &trojanscan_hello);
49
50 addcommandtotree(trojanscan_cmds, "join", TROJANSCAN_ACL_STAFF, 1, &trojanscan_userjoin);
51 addcommandtotree(trojanscan_cmds, "chanlist", TROJANSCAN_ACL_STAFF, 0, &trojanscan_chanlist);
52 addcommandtotree(trojanscan_cmds, "whois", TROJANSCAN_ACL_STAFF, 1, &trojanscan_whois);
53
54 addcommandtotree(trojanscan_cmds, "changelev", TROJANSCAN_ACL_STAFF | TROJANSCAN_ACL_OPER, 2, &trojanscan_changelev);
55 addcommandtotree(trojanscan_cmds, "deluser", TROJANSCAN_ACL_TEAMLEADER | TROJANSCAN_ACL_OPER, 2, &trojanscan_deluser);
b558d631 56 addcommandtotree(trojanscan_cmds, "mew", TROJANSCAN_ACL_STAFF, 2, &trojanscan_mew);
c86edd1d
Q
57 addcommandtotree(trojanscan_cmds, "status", TROJANSCAN_ACL_STAFF | TROJANSCAN_ACL_OPER, 0, &trojanscan_status);
58 addcommandtotree(trojanscan_cmds, "listusers", TROJANSCAN_ACL_TEAMLEADER, 0, &trojanscan_listusers);
59
60 addcommandtotree(trojanscan_cmds, "rehash", TROJANSCAN_ACL_WEBSITE, 0, &trojanscan_rehash);
61
4c9499c7 62 addcommandtotree(trojanscan_cmds, "cat", TROJANSCAN_ACL_OPER, 1, &trojanscan_cat);
c86edd1d
Q
63
64 addcommandtotree(trojanscan_cmds, "reschedule", TROJANSCAN_ACL_DEVELOPER | TROJANSCAN_ACL_OPER, 0, &trojanscan_reschedule);
65
66 srand((int)time(NULL));
67
68 trojanscan_connect_schedule = scheduleoneshot(time(NULL) + 1, &trojanscan_connect, NULL);
69}
70
71void _fini(void) {
72 int i;
73 struct trojanscan_realchannels *rp = trojanscan_realchanlist, *oldrp;
74 struct trojanscan_rejoinlist *rj = trojanscan_schedulerejoins, *oldrj;
75
76 if (trojanscan_nick)
77 deregisterlocaluser(trojanscan_nick, NULL);
78
79 if (trojanscan_connect_schedule)
80 deleteschedule(trojanscan_connect_schedule, &trojanscan_connect, NULL);
81
9bf89af0
CP
82 if (trojanscan_connect_nick_schedule)
83 deleteschedule(trojanscan_connect_nick_schedule, &trojanscan_connect_nick, NULL);
84
c86edd1d
Q
85 if(trojanscan_schedule)
86 deleteschedule(trojanscan_schedule, &trojanscan_dojoin, NULL);
87
88 if(trojanscan_poolschedule)
89 deleteschedule(trojanscan_poolschedule, &trojanscan_repool, NULL);
90
91 if(trojanscan_cloneschedule)
92 deleteschedule(trojanscan_poolschedule, &trojanscan_registerclones, NULL);
93
a0c2b0da
CP
94 if(hooksregistered)
95 deregisterhook(HOOK_CHANNEL_PART, trojanscan_part_watch);
96
c86edd1d
Q
97 while(rp) {
98 deleteschedule(rp->schedule, &trojanscan_dopart, (void *)rp);
99 oldrp = rp;
100 rp = rp->next;
93917ccd 101 tfree(oldrp);
c86edd1d
Q
102 }
103
104 while(rj) {
105 deleteschedule(rj->schedule, &trojanscan_rejoin_channel, (void *)rj);
106 freesstring(rj->channel);
107 oldrj = rj;
108 rj = rj->next;
93917ccd 109 tfree(oldrj);
c86edd1d
Q
110 }
111
112 if(trojanscan_initialschedule)
113 deleteschedule(trojanscan_initialschedule, &trojanscan_fill_channels, NULL);
114
115 deleteschedule(trojanscan_rehashschedule, &trojanscan_rehash_schedule, NULL);
116
117 for (i=0;i<TROJANSCAN_CLONE_TOTAL;i++)
118 if(trojanscan_swarm[i].clone) {
119 deregisterlocaluser(trojanscan_swarm[i].clone, NULL);
21ec3379 120 derefnode(iptree, trojanscan_swarm[i].fakeipnode);
c86edd1d
Q
121 trojanscan_swarm[i].clone = NULL;
122 }
123 trojanscan_free_database();
124 trojanscan_free_channels();
125
126 for (i=0;i<trojanscan_hostpoolsize;i++)
127 freesstring(trojanscan_hostpool[i]);
128
129 for (i=0;i<trojanscan_tailpoolsize;i++)
130 freesstring(trojanscan_tailpool[i]);
131 trojanscan_database_close();
f8d5cfcf
CP
132
133 nscheckfreeall(POOL_TROJANSCAN);
c86edd1d
Q
134}
135
9bf89af0 136static void trojanscan_connect_nick(void *arg) {
c86edd1d 137 sstring *mnick, *myident, *myhost, *myrealname, *myauthname;
c86edd1d 138 channel *cp;
9bf89af0
CP
139
140 mnick = getcopyconfigitem("trojanscan", "nick", "T", NICKLEN);
141 myident = getcopyconfigitem("trojanscan", "ident", "trojanscan", NICKLEN);
142 myhost = getcopyconfigitem("trojanscan", "hostname", "trojanscan.slug.netsplit.net", HOSTLEN);
143 myrealname = getcopyconfigitem("trojanscan", "realname", "Trojanscan v" TROJANSCAN_VERSION, REALLEN);
144 myauthname = getcopyconfigitem("trojanscan", "authname", "T", ACCOUNTLEN);
145
146 trojanscan_nick = registerlocaluser(mnick->content, myident->content, myhost->content, myrealname->content, myauthname->content, UMODE_SERVICE | UMODE_DEAF |
147 UMODE_OPER | UMODE_INV |
148 UMODE_ACCOUNT,
149 &trojanscan_handlemessages);
150 freesstring(mnick);
151 freesstring(myident);
152 freesstring(myhost);
153 freesstring(myrealname);
154 freesstring(myauthname);
155
156 cp = findchannel(TROJANSCAN_OPERCHANNEL);
157 if (!cp) {
158 localcreatechannel(trojanscan_nick, TROJANSCAN_OPERCHANNEL);
159 } else {
160 if(!localjoinchannel(trojanscan_nick, cp))
161 localgetops(trojanscan_nick, cp);
162 }
163
164 cp = findchannel(TROJANSCAN_CHANNEL);
165 if (!cp) {
166 localcreatechannel(trojanscan_nick, TROJANSCAN_CHANNEL);
167 } else {
168 if(!localjoinchannel(trojanscan_nick, cp))
169 localgetops(trojanscan_nick, cp);
170 }
171
172#ifdef TROJANSCAN_PEONCHANNEL
173 cp = findchannel(TROJANSCAN_PEONCHANNEL);
174 if (!cp) {
175 localcreatechannel(trojanscan_nick, TROJANSCAN_PEONCHANNEL);
176 } else {
177 if(!localjoinchannel(trojanscan_nick, cp))
178 localgetops(trojanscan_nick, cp);
179 }
180#endif
181}
182
183void trojanscan_connect(void *arg) {
184 sstring *dbhost, *dbuser, *dbpass, *db, *dbport, *temp;
c86edd1d
Q
185 int length, i;
186 char buf[10];
187
188 trojanscan_connect_schedule = NULL;
189
190 for(i=0;i<TROJANSCAN_CLONE_TOTAL;i++)
191 trojanscan_swarm[i].index = i; /* sure this could be done with pointer arithmetic... */
192
193 trojanscan_hostpoolsize = 0;
194 trojanscan_tailpoolsize = 0;
195 trojanscan_hostmode = 0;
196 trojanscan_poolschedule = NULL;
197 trojanscan_cloneschedule = NULL;
198 trojanscan_realchanlist = NULL;
199 trojanscan_database.glines = 0;
200 trojanscan_database.detections = 0;
201
c86edd1d
Q
202 dbhost = getcopyconfigitem("trojanscan", "dbhost", "localhost", HOSTLEN);
203 dbuser = getcopyconfigitem("trojanscan", "dbuser", "", NICKLEN);
204 dbpass = getcopyconfigitem("trojanscan", "dbpass", "", REALLEN);
205 db = getcopyconfigitem("trojanscan", "db", "", NICKLEN);
206
207 dbport = getcopyconfigitem("trojanscan", "dbport", "3306", ACCOUNTLEN);
208
209 length = snprintf(buf, sizeof(buf) - 1, "%d", TROJANSCAN_DEFAULT_MAXCHANS);
210 temp = getcopyconfigitem("trojanscan", "maxchans", buf, length);
211
212 trojanscan_maxchans = atoi(temp->content);
213 freesstring(temp);
214
215 length = snprintf(buf, sizeof(buf) - 1, "%d", TROJANSCAN_DEFAULT_CYCLETIME);
216 temp = getcopyconfigitem("trojanscan", "cycletime", buf, length);
217
218 trojanscan_cycletime = atoi(temp->content);
219 freesstring(temp);
220
221 length = snprintf(buf, sizeof(buf) - 1, "%d", TROJANSCAN_DEFAULT_PARTTIME);
222 temp = getcopyconfigitem("trojanscan", "parttime", buf, length);
223 trojanscan_part_time = atoi(temp->content);
224 freesstring(temp);
225
226 length = snprintf(buf, sizeof(buf) - 1, "%d", TROJANSCAN_DEFAULT_MAXUSERS);
227 temp = getcopyconfigitem("trojanscan", "maxusers", buf, length);
228 trojanscan_maxusers = atoi(temp->content);
229 freesstring(temp);
230
36efd3fc
CP
231 length = snprintf(buf, sizeof(buf) - 1, "%d", TROJANSCAN_MINIMUM_HOSTS_BEFORE_POOL);
232 temp = getcopyconfigitem("trojanscan", "minpoolhosts", buf, length);
233 trojanscan_min_hosts = atoi(temp->content);
234 freesstring(temp);
235
c86edd1d 236 if ((trojanscan_cycletime / trojanscan_maxchans) < 1) {
1fe41720
CP
237 Error("trojanscan", ERR_FATAL, "Cycletime / maxchans < 1, increase cycletime or decrease maxchans else cycling breaks.");
238 return; /* PPA: module failed to load */
c86edd1d
Q
239 }
240
241 length = snprintf(buf, sizeof(buf) - 1, "%d", TROJANSCAN_DEFAULT_MINIMUM_CHANNEL_SIZE);
242 temp = getcopyconfigitem("trojanscan", "minchansize", buf, length);
243 trojanscan_minchansize = atoi(temp->content);
244 freesstring(temp);
245
9bf89af0 246 trojanscan_connect_nick(NULL);
c86edd1d
Q
247
248 if (trojanscan_database_connect(dbhost->content, dbuser->content, dbpass->content, db->content, atoi(dbport->content)) < 0) {
249 Error("trojanscan", ERR_FATAL, "Cannot connect to database host!");
1fe41720 250 return; /* PPA: module failed to load */
c86edd1d
Q
251 }
252
b558d631 253 trojanscan_database_query("CREATE TABLE phrases (id INT(10) PRIMARY KEY AUTO_INCREMENT, wormid INT(10) NOT NULL, phrase TEXT NOT NULL, priority INT(10) DEFAULT 0 NOT NULL, dateadded int(10), disabled BOOL DEFAULT 0 NOT NULL)");
4986ec37 254 trojanscan_database_query("CREATE TABLE worms (id INT(10) PRIMARY KEY AUTO_INCREMENT, wormname TEXT NOT NULL, glinetype INT DEFAULT 0, data text, hitmsgs BOOL DEFAULT 1, hitchans BOOL DEFAULT 0, epidemic BOOL DEFAULT 0, privinfo text)");
c86edd1d
Q
255 trojanscan_database_query("CREATE TABLE logs (id INT(10) PRIMARY KEY AUTO_INCREMENT, userid INT(10) NOT NULL, act TEXT NOT NULL, description TEXT NOT NULL, ts TIMESTAMP)");
256 trojanscan_database_query("CREATE TABLE channels (id INT(10) PRIMARY KEY AUTO_INCREMENT, channel VARCHAR(%d) NOT NULL, exempt BOOL DEFAULT 0)", CHANNELLEN);
257 trojanscan_database_query("CREATE TABLE users (id INT(10) PRIMARY KEY AUTO_INCREMENT, authname VARCHAR(%d) NOT NULL, authlevel TINYINT(4) NOT NULL)", ACCOUNTLEN);
258 trojanscan_database_query("CREATE TABLE hits (id INT(10) PRIMARY KEY AUTO_INCREMENT, nickname VARCHAR(%d) NOT NULL, ident VARCHAR(%d) NOT NULL, host VARCHAR(%d) NOT NULL, phrase INT(10) NOT NULL, ts TIMESTAMP, messagetype VARCHAR(1) NOT NULL DEFAULT 'm', glined BOOL DEFAULT 1)", NICKLEN, USERLEN, HOSTLEN);
1e614cc2 259 trojanscan_database_query("CREATE TABLE settings (id INT(10) PRIMARY KEY AUTO_INCREMENT, setting VARCHAR(255) NOT NULL UNIQUE, value VARCHAR(255) NOT NULL)");
c86edd1d
Q
260 trojanscan_database_query("CREATE TABLE wwwlogs (id INT(10) PRIMARY KEY AUTO_INCREMENT, authid INT(10) NOT NULL, ip VARCHAR(15), action TEXT, ts TIMESTAMP)");
261 trojanscan_database_query("CREATE TABLE unknownlog (id INT(10) PRIMARY KEY AUTO_INCREMENT, data TEXT, user VARCHAR(%d) NOT NULL, ts TIMESTAMP)", NICKLEN+USERLEN+HOSTLEN+3);
262
8f619fe4 263 trojanscan_database_query("DELETE FROM settings WHERE setting = 'rehash' OR setting = 'changed'");
c86edd1d
Q
264 trojanscan_database_query("INSERT INTO settings (setting, value) VALUES ('rehash','0')");
265 trojanscan_database_query("INSERT INTO settings (setting, value) VALUES ('changed','0')");
8f619fe4
CP
266
267 /* assumption: constants aren't supplied by someone evil */
268 trojanscan_database_query("INSERT INTO settings (setting, value) VALUES ('versionreply','" TROJANSCAN_DEFAULT_VERSION_REPLY "')");
c86edd1d 269
1e614cc2 270 trojanscan_refresh_settings();
c86edd1d
Q
271 trojanscan_read_database(1);
272
c86edd1d
Q
273 freesstring(dbhost);
274 freesstring(dbuser);
275 freesstring(dbpass);
276 freesstring(db);
277 freesstring(dbport);
278 trojanscan_registerclones(NULL);
279
c86edd1d
Q
280 trojanscan_rehashschedule = scheduleoneshot(time(NULL) + 60, &trojanscan_rehash_schedule, NULL);
281
a0c2b0da
CP
282 registerhook(HOOK_CHANNEL_PART, trojanscan_part_watch);
283 hooksregistered = 1;
c86edd1d
Q
284}
285
8f619fe4
CP
286char *trojanscan_get_setting(char *setting) {
287 int i;
288
289 for(i=0;i<settingcount;i++)
290 if(!strcmp(trojanscan_settings[i].setting, setting))
291 return trojanscan_settings[i].value;
292
293 return NULL;
294}
295
296void trojanscan_refresh_settings(void) {
297 trojanscan_database_res *res;
298 trojanscan_database_row sqlrow;
299 int i = 0;
300
301 if(trojanscan_database_query("SELECT setting, value FROM settings"))
302 return;
303
304 if(!(res = trojanscan_database_store_result(&trojanscan_sql)))
305 return;
306
307 if (trojanscan_database_num_rows(res) <= 0)
308 return;
309
310 while((sqlrow = trojanscan_database_fetch_row(res))) {
311 strlcpy(trojanscan_settings[i].setting, sqlrow[0], TROJANSCAN_SETTING_SIZE);
312 strlcpy(trojanscan_settings[i].value, sqlrow[1], TROJANSCAN_SETTING_SIZE);
313
314 trojanscan_sanitise(trojanscan_settings[i].value);
315
316 if(++i == TROJANSCAN_MAX_SETTINGS)
317 break;
318 }
319
320 settingcount = i;
321
322 trojanscan_database_free_result(res);
323
324 /* optimisation hack */
325 versionreply = trojanscan_get_setting("versionreply");
326}
327
c86edd1d 328void trojanscan_rehash_schedule(void *arg) {
8f619fe4 329 char *v;
da2d09ce
CP
330 trojanscan_rehashschedule = scheduleoneshot(time(NULL) + 60, &trojanscan_rehash_schedule, NULL);
331
8f619fe4
CP
332 trojanscan_refresh_settings();
333
334 v = trojanscan_get_setting("rehash");
335 if(v && v[0] == '1') {
336 trojanscan_mainchanmsg("n: rehash initiated by website. . .");
337 trojanscan_read_database(0);
338 }
c86edd1d
Q
339}
340
341void trojanscan_free_database(void) {
342 int i;
343 for(i=0;i<trojanscan_database.total_channels;i++)
344 freesstring(trojanscan_database.channels[i].name);
93917ccd 345 tfree(trojanscan_database.channels);
f0ca73a3 346 for(i=0;i<trojanscan_database.total_phrases;i++) {
08d42cf7
CP
347 if (trojanscan_database.phrases[i].phrase)
348 pcre_free(trojanscan_database.phrases[i].phrase);
349 if (trojanscan_database.phrases[i].hint)
350 pcre_free(trojanscan_database.phrases[i].hint);
f0ca73a3 351 }
93917ccd 352 tfree(trojanscan_database.phrases);
c86edd1d
Q
353 for(i=0;i<trojanscan_database.total_worms;i++)
354 freesstring(trojanscan_database.worms[i].name);
93917ccd 355 tfree(trojanscan_database.worms);
c86edd1d
Q
356 trojanscan_database.total_channels = 0;
357 trojanscan_database.total_phrases = 0;
358 trojanscan_database.total_worms = 0;
359
360}
361
8f619fe4
CP
362char *trojanscan_sanitise(char *input) {
363 char *p;
364
365 for(p=input;*p;p++)
366 if(*p == '\r' || *p == '\n')
367 *p = '!';
368
369 return input;
370}
371
c86edd1d
Q
372sstring *trojanscan_getsstring(char *string, int length) {
373 int i;
374
375 for(i=0;i<length;i++) {
376 if ((string[i] == '\r') || (string[i] == '\n')) {
377 Error("trojanscan", ERR_WARNING, "Error reading %s at position %d, set to ERROR!", string, i+1);
378 return getsstring("ERROR", sizeof("ERROR"));
379 }
380 }
381
382 return getsstring(string, length);
383}
384
385int trojanscan_strip_codes(char *buf, size_t max, char *original) {
386 int i, j, length = TROJANSCAN_MMIN(strlen(original), max-1);
387 char *p2 = original, *p3, flag = 0;
388 p3 = buf;
389 for(i=0;i<length+1;i++) {
390 switch (*p2) {
391 case '\002':
392 case '\017':
393 case '\026':
394 case '\037':
395 break;
396 case '\003':
397 for(j=0;j<6;j++) {
398 if ((i + 1) > length)
399 break;
400 if ((j == 4) && flag)
401 break;
402 p2++;
403 i++;
404 if ((j == 0) && (!((*p2 >= '0') && (*p2 <= '9'))))
405 break;
406 if (j == 1) {
407
408 if (*p2 == ',') {
409 if ((i + 1) > length)
410 break;
411 if (!((*(p2 + 1) >= '0') && (*(p2 + 1) <= '9')))
412 break;
413 flag = 1;
414 } else if ((*p2 >= '0') && (*p2 <= '9')) {
415 flag = 0;
416 } else {
417 break;
418 }
419 }
420 if (j == 2) {
421 if (flag) {
422 if (!((*p2 >= '0') && (*p2 <= '9')))
423 break;
424 } else {
425 if (*p2 != ',') {
426 break;
427 } else {
428 if ((i + 1) > length)
429 break;
430 if (!((*(p2 + 1) >= '0') && (*(p2 + 1) <= '9')))
431 break;
432 }
433 }
434 }
435 if ((j == 3) && (!((*p2 >= '0') && (*p2 <= '9'))))
436 break;
437 if ((j == 4) && (!((*p2 >= '0') && (*p2 <= '9'))))
438 break;
439 }
440 p2--;
441 i--;
442 break;
443
444 default:
445 *p3 = *p2;
446 p3++;
447 break;
448 }
449 p2++;
450 }
451 return p3 - buf;
452}
453
454struct trojanscan_worms *trojanscan_find_worm_by_id(int id) {
455 int i;
456 for(i=0;i<trojanscan_database.total_worms;i++)
457 if ((trojanscan_database.worms[i].id == id))
458 return &trojanscan_database.worms[i];
459 return NULL;
460}
461
462void trojanscan_read_database(int first_time) {
463 const char *error;
464 int erroroffset, i, tempresult;
465
466 trojanscan_database_res *res;
467 trojanscan_database_row sqlrow;
468
469 if (!first_time) {
470 trojanscan_free_database();
471 } else {
472 trojanscan_database.total_channels = 0;
473 trojanscan_database.total_phrases = 0;
474 trojanscan_database.total_worms = 0;
475 }
476
477 if (!(trojanscan_database_query("SELECT channel, exempt FROM channels"))) {
478 if ((res = trojanscan_database_store_result(&trojanscan_sql))) {
479 trojanscan_database.total_channels = trojanscan_database_num_rows(res);
480 if (trojanscan_database.total_channels > 0) {
93917ccd 481 if ((trojanscan_database.channels = (trojanscan_channels *)tmalloc(sizeof(trojanscan_channels) * trojanscan_database.total_channels))) {
c86edd1d
Q
482 if ((trojanscan_database.total_channels>0) && trojanscan_database.channels) {
483 i = 0;
484 while((sqlrow = trojanscan_database_fetch_row(res))) {
8f619fe4 485 trojanscan_database.channels[i].name = trojanscan_getsstring(trojanscan_sanitise(sqlrow[0]), strlen(sqlrow[0]));
c86edd1d
Q
486 trojanscan_database.channels[i].exempt = (sqlrow[1][0] == '1');
487 i++;
488 }
489 }
490 }
491 }
492 trojanscan_database_free_result(res);
493 }
494 }
495
378cf1b9 496 if (!(trojanscan_database_query("SELECT id, wormname, glinetype, length(data), hitmsgs, hitchans, epidemic FROM worms"))) {
c86edd1d
Q
497 if ((res = trojanscan_database_store_result(&trojanscan_sql))) {
498 trojanscan_database.total_worms = trojanscan_database_num_rows(res);
499 if (trojanscan_database.total_worms > 0) {
93917ccd 500 if ((trojanscan_database.worms = (trojanscan_worms *)tmalloc(sizeof(trojanscan_worms) * trojanscan_database.total_worms))) {
c86edd1d
Q
501 i = 0;
502 while((sqlrow = trojanscan_database_fetch_row(res))) {
503 trojanscan_database.worms[i].id = atoi(sqlrow[0]);
8f619fe4 504 trojanscan_database.worms[i].name = trojanscan_getsstring(trojanscan_sanitise(sqlrow[1]), strlen(sqlrow[1]));
c86edd1d
Q
505 tempresult = atoi(sqlrow[2]);
506 trojanscan_database.worms[i].glineuser = (tempresult == 0);
507 trojanscan_database.worms[i].glinehost = (tempresult == 1);
508 trojanscan_database.worms[i].monitor = (tempresult == 2);
509 if(sqlrow[3]) {
510 trojanscan_database.worms[i].datalen = ((atoi(sqlrow[3]) == 0) ? 0 : 1);
511 } else {
512 trojanscan_database.worms[i].datalen = 0;
513 }
514
515 trojanscan_database.worms[i].hitpriv = (atoi(sqlrow[4]) == 1);
516 trojanscan_database.worms[i].hitchans = (atoi(sqlrow[5]) == 1);
378cf1b9 517 trojanscan_database.worms[i].epidemic = (atoi(sqlrow[6]) == 1);
c86edd1d
Q
518
519 i++;
520 }
521 }
522 }
523 trojanscan_database_free_result(res);
524 }
525 }
526
b558d631 527 if (!(trojanscan_database_query("SELECT id, phrase, wormid FROM phrases WHERE disabled = 0 ORDER BY priority DESC"))) {
c86edd1d
Q
528 if ((res = trojanscan_database_store_result(&trojanscan_sql))) {
529 trojanscan_database.total_phrases = trojanscan_database_num_rows(res);
530 if (trojanscan_database.total_phrases > 0) {
93917ccd 531 if ((trojanscan_database.phrases = (trojanscan_phrases *)tmalloc(sizeof(trojanscan_phrases) * trojanscan_database.total_phrases))) {
c86edd1d
Q
532 i = 0;
533 while((sqlrow = trojanscan_database_fetch_row(res))) {
534 trojanscan_database.phrases[i].id = atoi(sqlrow[0]);
535 trojanscan_database.phrases[i].worm = trojanscan_find_worm_by_id(atoi(sqlrow[2]));
536 if (!(trojanscan_database.phrases[i].phrase = pcre_compile(sqlrow[1], PCRE_CASELESS, &error, &erroroffset, NULL))) {
537 Error("trojanscan", ERR_WARNING, "Error compiling expression %s at offset %d: %s", sqlrow[1], erroroffset, error);
538 } else {
08d42cf7
CP
539 trojanscan_database.phrases[i].hint = pcre_study(trojanscan_database.phrases[i].phrase, 0, &error);
540 if (error) {
c86edd1d 541 Error("trojanscan", ERR_WARNING, "Error studying expression %s: %s", sqlrow[1], error);
08d42cf7 542 pcre_free(trojanscan_database.phrases[i].phrase);
c86edd1d
Q
543 trojanscan_database.phrases[i].phrase = NULL;
544 }
545 }
546 i++;
547 }
548 }
549 }
550 trojanscan_database_free_result(res);
551 }
552 }
553
554 trojanscan_database_query("UPDATE settings SET value = '0' where setting = 'rehash'");
c86edd1d
Q
555}
556
557void trojanscan_log(nick *np, char *event, char *details, ...) {
558 int nickid = 0;
559 char eevent[TROJANSCAN_QUERY_TEMP_BUF_SIZE], edetails[TROJANSCAN_QUERY_TEMP_BUF_SIZE], buf[513];
560 va_list va;
561
562 va_start(va, details);
563 vsnprintf(buf, sizeof(buf) - 1, details, va);
564 va_end(va);
565
566 if (np)
567 if (IsAccount(np))
568 nickid = trojanscan_user_id_by_authname(np->authname);
569
570 trojanscan_database_escape_string(eevent, event, strlen(event));
571 trojanscan_database_escape_string(edetails, buf, strlen(buf));
572 trojanscan_database_query("INSERT INTO logs (userid, act, description) VALUES ('%d', '%s', '%s')", nickid, eevent, edetails);
573}
574
575void trojanscan_generateclone(void *arg) {
c8fdcfa5 576 int i, loops = 0, modes = UMODE_XOPER | UMODE_INV;
c86edd1d 577 char c_nick[NICKLEN+1], c_ident[USERLEN+1], c_host[HOSTLEN+1], c_real[REALLEN+1];
21ec3379 578 patricia_node_t *fakeip;
c86edd1d 579
c3db6f7e 580 i = (int)((long)arg);
378cf1b9 581
c86edd1d
Q
582 /* PPA: unlikely to be infinite */
583 do {
56099b38
CP
584 c_nick[0] = '\0';
585 if (!loops && trojanscan_hostmode) /* only have one go at this */
c86edd1d 586 trojanscan_generatenick(c_nick, NICKLEN);
56099b38 587 if(!c_nick[0])
c86edd1d 588 trojanscan_gennick(c_nick, trojanscan_minmaxrand(7, TROJANSCAN_MMIN(13, NICKLEN)));
56099b38
CP
589 loops++;
590 } while ((getnickbynick(c_nick) != NULL));
c86edd1d
Q
591
592 trojanscan_generateident(c_ident, USERLEN);
56099b38 593 if(!c_ident[0])
c86edd1d
Q
594 trojanscan_genident(c_ident, trojanscan_minmaxrand(4, TROJANSCAN_MMIN(8, USERLEN)));
595
596 if(trojanscan_hostmode) {
2e9a528b 597 trojanscan_generatehost(c_host, HOSTLEN, &fakeip);
56099b38 598 if(!c_host[0])
2e9a528b 599 trojanscan_genhost(c_host, HOSTLEN, &fakeip);
c86edd1d 600 } else {
2e9a528b 601 trojanscan_genhost(c_host, HOSTLEN, &fakeip);
c86edd1d
Q
602 }
603
604 trojanscan_generaterealname(c_real, REALLEN);
56099b38 605 if(!c_real[0])
c86edd1d
Q
606 trojanscan_genreal(c_real, trojanscan_minmaxrand(15, TROJANSCAN_MMIN(50, REALLEN)));
607
c86edd1d 608 trojanscan_swarm[i].clone = registerlocaluser(c_nick, c_ident, c_host, c_real, NULL, modes, &trojanscan_clonehandlemessages);
21ec3379 609 trojanscan_swarm[i].fakeipnode = fakeip;
2e9a528b 610
36efd3fc
CP
611 if(trojanscan_swarm[i].clone && !trojanscan_swarm_created) {
612 nick *np = trojanscan_selectuser();
613 if(np) /* select a 'random' sign on time for whois generation */
614 trojanscan_swarm[i].clone->timestamp = np->timestamp;
615 }
c86edd1d
Q
616 trojanscan_swarm[i].remaining = trojanscan_minmaxrand(5, 100);
617
618 trojanscan_swarm[i].sitting = 0;
619
620}
621
622void trojanscan_free_channels(void) {
623 int i;
624 if(trojanscan_chans) {
625 for(i=0;i<trojanscan_activechans;i++)
378cf1b9 626 freesstring(trojanscan_chans[i].channel);
93917ccd 627 tfree(trojanscan_chans);
c86edd1d
Q
628 trojanscan_chans = NULL;
629 trojanscan_activechans = 0;
630 }
631}
632
633void trojanscan_repool(void *arg) {
634 if (trojanscan_generatepool() < TROJANSCAN_MINPOOLSIZE) {
635 trojanscan_hostmode = 0;
636 return;
637 } else {
638 trojanscan_hostmode = 1;
639 trojanscan_poolschedule = scheduleoneshot(time(NULL) + TROJANSCAN_POOL_REGENERATION, &trojanscan_repool, NULL);
640 }
641}
642
643void trojanscan_registerclones(void *arg) {
644 unsigned int i;
645
646 if (trojanscan_generatepool() < TROJANSCAN_MINPOOLSIZE) {
647 trojanscan_hostmode = 0;
648 trojanscan_cloneschedule = scheduleoneshot(time(NULL) + 10, &trojanscan_registerclones, NULL);
649 return;
650 } else {
651 trojanscan_hostmode = 1;
652 trojanscan_poolschedule = scheduleoneshot(time(NULL) + TROJANSCAN_POOL_REGENERATION, &trojanscan_repool, NULL);
653 trojanscan_cloneschedule = NULL;
654 }
655
656 for (i=0;i<TROJANSCAN_CLONE_TOTAL;i++)
c3db6f7e 657 trojanscan_generateclone((void *)((long)i));
c86edd1d
Q
658 trojanscan_mainchanmsg("n: swarm (%d clones) created.", TROJANSCAN_CLONE_TOTAL);
659 trojanscan_swarm_created = 1;
72a4a767 660
d1a3e67a 661 trojanscan_initialschedule = scheduleoneshot(time(NULL) + 60, &trojanscan_fill_channels, NULL);
c86edd1d
Q
662}
663
664int trojanscan_status(void *sender, int cargc, char **cargv) {
665 nick *np = (nick *)sender;
666 trojanscan_log(np, "status", "");
667 trojanscan_reply(np, "Channels in schedule: %d", trojanscan_activechans);
668 trojanscan_reply(np, "Channels in database: %d", trojanscan_database.total_channels);
669 trojanscan_reply(np, "Phrases: %d", trojanscan_database.total_phrases);
670 trojanscan_reply(np, "Worms: %d", trojanscan_database.total_worms);
671 trojanscan_reply(np, "Detections: %d", trojanscan_database.detections);
672 trojanscan_reply(np, "Glines: %d", trojanscan_database.glines);
673 trojanscan_reply(np, "Host/tail pool size: %d", TROJANSCAN_POOLSIZE);
674 trojanscan_reply(np, "Cycletime: %d", trojanscan_cycletime);
675 trojanscan_reply(np, "Clones: %d", TROJANSCAN_CLONE_TOTAL);
676 return CMD_OK;
677}
678
679int trojanscan_chanlist(void *sender, int cargc, char **cargv) {
680 int i;
681 nick *np = (nick *)sender;
31f37482 682 char buf[CHANNELLEN * 2 + 20];
c86edd1d 683 trojanscan_reply(np, "Channel list (%d total):", trojanscan_activechans);
31f37482
CP
684 buf[0] = '\0';
685
686 for(i=0;i<trojanscan_activechans;i++) {
687 if(trojanscan_chans[i].channel->length + 3 > sizeof(buf) - strlen(buf)) {
688 trojanscan_reply(np, "%s", buf);
689 buf[0] = '\0';
690 }
691
692 /* if splidge sees this I'm going to die */
693 strlcat(buf, trojanscan_chans[i].channel->content, sizeof(buf));
694 strlcat(buf, " ", sizeof(buf));
695 }
696 if(buf[0])
697 trojanscan_reply(np, "%s", buf);
698
c86edd1d
Q
699 trojanscan_reply(np, "Done.");
700 return CMD_OK;
701}
702
703int trojanscan_whois(void *sender, int cargc, char **cargv) {
704 char *tochange;
705 nick *np = (nick *)sender, *np2;
706 int templevel;
707
708 if (cargc < 1) {
709 trojanscan_reply(np, "Not enough parameters.");
710 return CMD_ERROR;
711 }
712
713 if (cargv[0][0] == '#') {
714 tochange = cargv[0] + 1;
715 } else {
716 int i;
717 np2 = getnickbynick(cargv[0]);
718 if (!np2) {
719 trojanscan_reply(np, "That nickname is not on the network.");
720 return CMD_ERROR;
721 }
722 for(i=0;i<TROJANSCAN_CLONE_TOTAL;i++) {
1fe41720 723 if(trojanscan_swarm[i].clone->nick && !ircd_strcmp(trojanscan_swarm[i].clone->nick, np2->nick)) {
c86edd1d 724 trojanscan_reply(np, "Nickname : %s", np2->nick);
31f37482 725 trojanscan_reply(np, "Swarm : yes", trojanscan_swarm[i].clone->nick);
c86edd1d
Q
726 return CMD_OK;
727 }
728 }
729 if (!IsAccount(np2)) {
730 trojanscan_reply(np, "User is not authed.");
731 return CMD_OK;
732 }
733 tochange = np2->authname;
734 }
735
736 templevel = trojanscan_user_level_by_authname(tochange);
737 if (templevel == -1) {
738 trojanscan_reply(np, "User does not exist.");
739 } else {
740 union trojanscan_userlevel flags;
741 flags.number = templevel;
742 trojanscan_reply(np, "Authname : %s", tochange);
743 trojanscan_reply(np, "Flags : +" TROJANSCAN_FLAG_MASK, TrojanscanFlagsInfo(flags));
744 }
745
746 return CMD_OK;
747}
748
749void trojanscan_privmsg_chan_or_nick(channel *cp, nick *np, char *message, ...) {
750 char buf[513];
751 va_list va;
752
753 if (!trojanscan_nick)
754 return;
755
756 va_start(va, message);
757 vsnprintf(buf, sizeof(buf) - 1, message, va);
758 va_end(va);
759
760 if (cp) {
761 sendmessagetochannel(trojanscan_nick, cp, buf);
762 } else {
763 sendmessagetouser(trojanscan_nick, np, buf);
764 }
765
766}
767
768int trojanscan_mew(void *sender, int cargc, char **cargv) {
769 nick *np = (nick *)sender, *np2 = NULL;
770 channel *cp = NULL;
771
772 if (cargc < 2) {
773 trojanscan_reply(np, "Not enough paramaters.");
774 return CMD_ERROR;
775 }
776
777 if(cargv[0][0] == '#') {
778 if (!(cp = findchannel(cargv[0]))) {
779 trojanscan_reply(np, "Channel not found.");
780 return CMD_ERROR;
781 }
782 trojanscan_log(np, "mew", "%s %s", cp->index->name->content, cargv[1]);
783 } else {
784 if (!(np2 = getnickbynick(cargv[0]))) {
785 trojanscan_reply(np, "Nickname is not present on the network.");
786 return CMD_ERROR;
787 }
788 trojanscan_log(np, "mew", "%s %s", np2->nick, cargv[1]);
789 }
790
791 trojanscan_privmsg_chan_or_nick(cp, np2, "\001ACTION mews hopefully at %s\001", cargv[1]);
792
793 if (cp) {
794 trojanscan_reply(np, "Mewed at %s in %s.", cargv[1], cp->index->name->content);
795 } else {
796 trojanscan_reply(np, "Mewed at %s at %s.", cargv[1], np2->nick);
797 }
b558d631
CP
798
799 if(!IsOper(np))
800 trojanscan_mainchanmsg("n: mew: %s %s (%s/%s)", cargv[1], cp?cp->index->name->content:np2->nick, np->nick, np->authname);
801
c86edd1d
Q
802 return CMD_OK;
803}
804
805int trojanscan_cat(void *sender, int cargc, char **cargv) {
806 nick *np = (nick *)sender, *np2 = NULL;
807 channel *cp = NULL;
808 FILE *cat;
809 char buf[513], *p;
810
811 if (cargc < 1) {
812 trojanscan_reply(np, "Not enough paramaters.");
813 return CMD_ERROR;
814 }
815
816 if(cargv[0][0] == '#') {
817 if (!(cp = findchannel(cargv[0]))) {
818 trojanscan_reply(np, "Channel not found.");
819 return CMD_ERROR;
820 }
821 trojanscan_log(np, "cat", cp->index->name->content);
822 } else {
823 if (!(np2 = getnickbynick(cargv[0]))) {
824 trojanscan_reply(np, "Nickname is not present on the network.");
825 return CMD_ERROR;
826 }
827 trojanscan_log(np, "cat", np2->nick);
828 }
829
830 if ((!(cat = fopen(TROJANSCAN_CAT, "r")))) {
831 trojanscan_reply(np, "Unable to open cat!");
832 return CMD_ERROR;
833 }
834
c86edd1d
Q
835 while (fgets(buf, sizeof(buf) - 1, cat)) {
836 if ((p = strchr(buf, '\n'))) {
837 *p = '\0';
838 trojanscan_privmsg_chan_or_nick(cp, np2, "%s", buf);
839 } else if (feof(cat)) {
840 trojanscan_privmsg_chan_or_nick(cp, np2, "%s", buf);
841 }
842 }
843
844 fclose(cat);
845
846 if (cp) {
847 trojanscan_reply(np, "Spammed cat in %s.", cp->index->name->content);
848 } else {
849 trojanscan_reply(np, "Spammed cat at %s.", np2->nick);
850 }
851
852 return CMD_OK;
853}
854
855int trojanscan_reschedule(void *sender, int cargc, char **cargv) {
856 nick *np = (nick *)sender;
857 trojanscan_log(np, "reschedule", "");
858 trojanscan_fill_channels(NULL);
859
860 trojanscan_reply(np, "Rescheduled.");
861 return CMD_OK;
862}
863
864int trojanscan_listusers(void *sender, int cargc, char **cargv) {
865 nick *np = (nick *)sender;
866
867 trojanscan_log(np, "listusers", "");
868
869 trojanscan_reply(np, "User list:");
870
871 if (!(trojanscan_database_query("SELECT authname, authlevel FROM users ORDER BY authlevel DESC, authname"))) {
872 trojanscan_database_res *res;
873 if ((res = trojanscan_database_store_result(&trojanscan_sql))) {
874 if (trojanscan_database_num_rows(res)) {
875 trojanscan_database_row sqlrow;
876 union trojanscan_userlevel flags;
877 while((sqlrow = trojanscan_database_fetch_row(res))) {
878 flags.number = atoi(sqlrow[1]);
879 trojanscan_reply(np, "%s +" TROJANSCAN_FLAG_MASK, sqlrow[0], TrojanscanIsDeveloper(flags) ? "d" : "", TrojanscanIsTeamLeader(flags) ? "t" : "", TrojanscanIsStaff(flags) ? "s" : "", TrojanscanIsWebsite(flags) ? "w" : "", TrojanscanIsCat(flags) ? "c" : "");
880 }
881 }
882 trojanscan_database_free_result(res);
883 }
884 }
885
886 trojanscan_reply(np, "Done.");
887 return CMD_OK;
888}
889
890int trojanscan_help(void *sender, int cargc, char **cargv) {
891 nick *np = (nick *)sender;
892
893 if (cargc == 0) {
894 trojanscan_reply(np, "Not enough parameters.");
895 return CMD_ERROR;
896 }
897
898 if (!strcasecmp("help", cargv[0])) {
899 trojanscan_reply(np, "Syntax: help <command name>");
900 trojanscan_reply(np, "Gives help on commands.");
901 } else if (!strcasecmp("status", cargv[0])) {
902 trojanscan_reply(np, "Syntax: status");
903 trojanscan_reply(np, "Gives statistical information about the bot.");
904 } else if (!strcasecmp("join", cargv[0])) {
905 trojanscan_reply(np, "Syntax: join <#channel>");
906 trojanscan_reply(np, "Orders a clone to join supplied channel.");
907 } else if (!strcasecmp("showcommands", cargv[0])) {
908 trojanscan_reply(np, "Syntax: showcommands");
909 trojanscan_reply(np, "Pretty obvious.");
910 } else if (!strcasecmp("hello", cargv[0])) {
911 trojanscan_reply(np, "Syntax: hello ?nickname?");
912 trojanscan_reply(np, "Creates a new user.");
913 } else if (!strcasecmp("rehash", cargv[0])) {
914 trojanscan_reply(np, "Syntax: rehash");
915 trojanscan_reply(np, "Reloads bot database.");
916 } else if (!strcasecmp("changelev", cargv[0])) {
917 trojanscan_reply(np, "Syntax: changelev <nickname or #authname> <flags>");
918 trojanscan_reply(np, "Changes access flags of selected user to supplied input.");
919 trojanscan_reply(np, "+d -> developer");
920 trojanscan_reply(np, "+t -> team leader");
921 trojanscan_reply(np, "+s -> staff");
922 trojanscan_reply(np, "+w -> web management");
923 trojanscan_reply(np, "+c -> cat access");
924 } else if (!strcasecmp("deluser", cargv[0])) {
925 trojanscan_reply(np, "Syntax: deluser <nickname or #authname>");
926 trojanscan_reply(np, "Deletes selected user from my database.");
927 } else if (!strcasecmp("mew", cargv[0])) {
928 trojanscan_reply(np, "Syntax: mew <#channel or nickname> <nickname>");
929 trojanscan_reply(np, "Gracefully mews at target in selected channel or query.");
930 } else if (!strcasecmp("cat", cargv[0])) {
931 trojanscan_reply(np, "Syntax: cat <#channel or nickname>");
932 trojanscan_reply(np, "Shows the almightly cat.");
933 } else if (!strcasecmp("reschedule", cargv[0])) {
934 trojanscan_reply(np, "Syntax: reschedule");
935 trojanscan_reply(np, "Recalculates bots schedule.");
936 } else if (!strcasecmp("chanlist", cargv[0])) {
937 trojanscan_reply(np, "Syntax: chanlist");
938 trojanscan_reply(np, "Displays bots current channel list.");
939 } else if (!strcasecmp("whois", cargv[0])) {
940 trojanscan_reply(np, "Syntax: whois <nickname or #authname>");
941 trojanscan_reply(np, "Displays information on given user.");
942 } else if (!strcasecmp("whois", cargv[0])) {
943 trojanscan_reply(np, "Syntax: listusers <flags>");
944 trojanscan_reply(np, "Displays users with listusersing flags.");
945 } else {
946 trojanscan_reply(np, "Command not found.");
947 return CMD_ERROR;
948 }
949
950 return CMD_OK;
951}
952
953int trojanscan_hello(void *sender, int cargc, char **cargv) {
954 nick *np = (nick *)sender, *toadd;
955 char eaccount[TROJANSCAN_QUERY_TEMP_BUF_SIZE];
956 int level = 0;
957
958 if (cargc > 0) {
959 toadd = getnickbynick(cargv[0]);
960 if (!toadd) {
961 trojanscan_reply(np, "That nickname is not on the network.");
962 return CMD_ERROR;
963 }
964 if (!IsAccount(toadd)) {
965 trojanscan_reply(np, "That user is not authed with the network.");
966 return CMD_ERROR;
967 }
968 } else {
969 if (!IsAccount(np)) {
970 trojanscan_reply(np, "You are not authed with the network, auth before creating your user.");
971 return CMD_ERROR;
972 }
973 toadd = np;
974 }
975
976 if (trojanscan_user_level_by_authname(toadd->authname)!=-1) {
977 trojanscan_reply(np, "Authname (%s) is already on file.", toadd->authname);
978 return CMD_ERROR;
979 }
980
981 trojanscan_log(np, "hello", toadd->authname);
982
983 if (!(trojanscan_database_query("SELECT id FROM users LIMIT 1"))) {
984 trojanscan_database_res *res;
985 if ((res = trojanscan_database_store_result(&trojanscan_sql))) {
986 if (trojanscan_database_num_rows(res) == 0)
987 level = TROJANSCAN_ACL_DEVELOPER | TROJANSCAN_ACL_STAFF | TROJANSCAN_ACL_WEBSITE | TROJANSCAN_ACL_CAT;
988 trojanscan_database_free_result(res);
989 }
990 }
991
992 trojanscan_database_escape_string(eaccount, toadd->authname, strlen(toadd->authname));
993 trojanscan_database_query("INSERT INTO users (authname, authlevel) VALUES ('%s', %d)", eaccount, level);
994 trojanscan_reply(np, "Account added to database, account %s%s.", toadd->authname, level>0?" (first user so developer access)":"");
995
996 return CMD_OK;
997}
998
999int trojanscan_user_level_by_authname(char *authname) {
1000 int result = -1, sl = strlen(authname);
1001 char eaccount[TROJANSCAN_QUERY_TEMP_BUF_SIZE];
1002
1003 trojanscan_database_escape_string(eaccount, authname, sl);
1004 if (!(trojanscan_database_query("SELECT authlevel, authname FROM users WHERE authname = '%s'", eaccount))) {
1005 trojanscan_database_res *res;
1006 if ((res = trojanscan_database_store_result(&trojanscan_sql))) {
1007 if (trojanscan_database_num_rows(res) > 0) {
1008 trojanscan_database_row sqlrow = trojanscan_database_fetch_row(res);
1009 result = atoi(sqlrow[0]);
707e6470 1010 strlcpy(authname, sqlrow[1], sl + 1);
c86edd1d
Q
1011 }
1012 trojanscan_database_free_result(res);
1013 }
1014 }
1015 return result;
1016}
1017
1018int trojanscan_user_id_by_authname(char *authname) {
1019 int result = 0;
1020 char eaccount[TROJANSCAN_QUERY_TEMP_BUF_SIZE];
1021
1022 trojanscan_database_escape_string(eaccount, authname, strlen(authname));
1023 if (!(trojanscan_database_query("SELECT id FROM users WHERE authname = '%s'", eaccount))) {
1024 trojanscan_database_res *res;
1025 if ((res = trojanscan_database_store_result(&trojanscan_sql))) {
1026 if (trojanscan_database_num_rows(res) > 0) {
1027 trojanscan_database_row sqlrow = trojanscan_database_fetch_row(res);
1028 result = atoi(sqlrow[0]);
1029 }
1030 trojanscan_database_free_result(res);
1031 }
1032 }
1033 return result;
1034}
1035
1036struct trojanscan_clones *trojanscan_selectclone(char type) {
1037 struct trojanscan_clones *rc;
1038 int randomclone, hits = 0, minlimit, maxlimit;
1039
1040 if(type == TROJANSCAN_WATCH_CLONES) {
1041 minlimit = TROJANSCAN_CLONE_MAX;
378cf1b9 1042 maxlimit = minlimit + TROJANSCAN_WATCHCLONE_MAX - 1;
c86edd1d
Q
1043 } else {
1044 minlimit = 0;
1045 maxlimit = TROJANSCAN_CLONE_MAX - 1;
1046 }
1047
1048 do {
1049 randomclone = trojanscan_minmaxrand(minlimit, maxlimit);
1050 if (hits++ > 200)
1051 return NULL;
1052 rc = &trojanscan_swarm[randomclone];
1053 if ((type == TROJANSCAN_NORMAL_CLONES) && (rc->sitting == 0) && (rc->remaining == 0))
1054 break;
1055
1056 } while (rc->remaining == 0);
1057
1058 if(type == TROJANSCAN_NORMAL_CLONES) {
1059 if ((rc->sitting == 0) && (rc->remaining == 0)) {
1060 if ((!rc->remaining) && (!rc->sitting)) {
1061 if (rc->clone) {
1062 deregisterlocaluser(rc->clone, NULL);
21ec3379 1063 derefnode(iptree, rc->fakeipnode);
c86edd1d
Q
1064 rc->clone = NULL;
1065 }
c3db6f7e 1066 trojanscan_generateclone((void *)((long)rc->index));
c86edd1d
Q
1067 }
1068 }
c86edd1d
Q
1069 }
1070
1071 return rc;
1072
1073}
1074
2e9a528b
P
1075/* hack hack hack */
1076int trojanscan_nickbanned(trojanscan_clones *np, channel *cp) {
1077 int ret;
21ec3379 1078 patricia_node_t *realipnode = np->clone->ipnode;
2e9a528b 1079
21ec3379 1080 np->clone->ipnode = np->fakeipnode;
2e9a528b
P
1081
1082 ret = nickbanned(np->clone, cp);
1083
21ec3379 1084 np->clone->ipnode = realipnode;
2e9a528b
P
1085
1086 return ret;
1087}
1088
c86edd1d
Q
1089struct trojanscan_realchannels *trojanscan_allocaterc(char *chan) {
1090 struct trojanscan_realchannels *rc;
1091 struct trojanscan_clones *clonep;
1092 channel *cp;
378cf1b9 1093 int attempts_left = 10;
c86edd1d
Q
1094
1095 if (!chan) {
1096 trojanscan_errorcode = 1; /* sorry splidge ;( */
1097 return NULL;
1098 }
1099
1100 if(chan[0] != '#') {
1101 trojanscan_errorcode = 2;
1102 return NULL;
1103 }
1104
1105 if (strlen(chan) > 1) {
1106 if(strrchr(chan, ',')) {
1107 trojanscan_errorcode = 3;
1108 return NULL;
1109 }
1110
1111 if(strrchr(chan, ' ')) {
1112 trojanscan_errorcode = 4;
1113 return NULL;
1114 }
1115 }
1116
1117 cp = findchannel(chan);
1118 if (!cp) {
1119 trojanscan_errorcode = 5;
1120 return NULL;
1121 }
378cf1b9
CP
1122
1123 do {
1124 clonep = trojanscan_selectclone(TROJANSCAN_NORMAL_CLONES);
1125 if (!clonep) {
1126 trojanscan_errorcode = 6;
1127 return NULL;
1128 }
2e9a528b 1129 if(!trojanscan_nickbanned(clonep, cp))
378cf1b9
CP
1130 break;
1131 } while (--attempts_left > 0);
1132
1133 if (!attempts_left) {
1134 trojanscan_errorcode = 7;
c86edd1d
Q
1135 return NULL;
1136 }
378cf1b9 1137
93917ccd 1138 rc = (struct trojanscan_realchannels *)tmalloc(sizeof(struct trojanscan_realchannels));
c86edd1d
Q
1139
1140 rc->next = NULL;
1141 rc->clone = clonep;
1142 rc->chan = cp;
1143 rc->donotpart = 0;
1144 rc->kickedout = 0;
1145 return rc;
1146}
1147
1148void trojanscan_join(struct trojanscan_realchannels *rc) {
1149 struct trojanscan_realchannels *rp = trojanscan_realchanlist;
1150
1151 if (rc->clone && rc->clone->clone) {
1152 if (!localjoinchannel(rc->clone->clone, rc->chan)) {
31f37482
CP
1153 rc->clone->remaining--;
1154 rc->clone->sitting++;
c86edd1d
Q
1155 if (trojanscan_minmaxrand(1, TROJANSCAN_NICKCHANGE_ODDS)%TROJANSCAN_NICKCHANGE_ODDS == 0)
1156 trojanscan_donickchange((void *)rc->clone);
1157
1158 rc->schedule = scheduleoneshot(time(NULL)+trojanscan_part_time, &trojanscan_dopart, (void *)rc);
1159
1160 if (rp) {
1161 for(;rp->next;rp=rp->next);
1162 rp->next = rc;
1163 } else {
1164 trojanscan_realchanlist = rc;
1165 }
1166 }
1167 }
1168
1169}
1170
1171int trojanscan_userjoin(void *sender, int cargc, char **cargv) {
1172 nick *np = (nick *)sender;
1173 struct trojanscan_realchannels *rc;
1174
1175 if (cargc < 1) {
1176 trojanscan_reply(np, "Not enough paramaters");
1177 return CMD_ERROR;
1178 }
1179
1180 if (!trojanscan_swarm_created) {
1181 trojanscan_reply(np, "My swarm is currently empty.");
1182 return CMD_OK;
1183 }
1184
1185 if((rc = trojanscan_allocaterc(cargv[0]))) {
1186 trojanscan_log(np, "join", cargv[0]);
1187 trojanscan_join(rc);
1188 trojanscan_reply(np, "Clone has joined channel.");
1189 if(!IsOper(np))
1190 trojanscan_mainchanmsg("n: join: %s (%s/%s)", cargv[0], np->nick, np->authname);
1191 } else {
1192 if (trojanscan_errorcode == 5) {
1193 trojanscan_reply(np, "Not joining empty channel, check you entered the correct channel name.");
1194 } else {
1195 trojanscan_reply(np, "Clone could not join channel (error code %d)!", trojanscan_errorcode);
1196 }
1197 }
1198 return CMD_OK;
1199}
1200
1201int trojanscan_rehash(void *sender, int cargc, char **cargv) {
1202 nick *np = (void *)sender;
1e614cc2 1203 trojanscan_refresh_settings();
c86edd1d
Q
1204 trojanscan_read_database(0);
1205 trojanscan_log(np, "rehash", "");
1206 trojanscan_reply(np, "Done.");
1207 return CMD_OK;
1208}
1209
1210int trojanscan_changelev(void *sender, int cargc, char **cargv) {
1211 nick *np = (nick *)sender, *np2;
1212 int templevel;
1213 char eaccount[TROJANSCAN_QUERY_TEMP_BUF_SIZE], *tochange, *p, mode = 1, error = 0, clast = 0, specialcase;
1214 union trojanscan_userlevel flags1, flags2;
1215
1216 if (cargc < 2) {
1217 trojanscan_reply(np, "Not enough parameters.");
1218 return CMD_ERROR;
1219 }
1220
1221 templevel = trojanscan_user_level_by_authname(np->authname);
1222
1223 if (templevel == -1) {
1224 trojanscan_reply(np, "You do not have an account.");
1225 return CMD_ERROR;
1226 }
1227
1228 flags1.number = templevel;
1229
1230 if (cargv[0][0] == '#') {
1231 tochange = cargv[0] + 1;
1232 } else {
1233 np2 = getnickbynick(cargv[0]);
1234 if (!np2) {
1235 trojanscan_reply(np, "That nickname is not on the network.");
1236 return CMD_ERROR;
1237 }
1238 if (!IsAccount(np2)) {
1239 trojanscan_reply(np, "That user is not authed with the network.");
1240 return CMD_ERROR;
1241 }
1242 tochange = np2->authname;
1243 }
1244
1245 templevel = trojanscan_user_level_by_authname(tochange);
1246
1247 if (templevel == -1) {
1248 trojanscan_reply(np, "User does not exist.");
1249 return CMD_ERROR;
1250 }
1251
1252 flags2.number = templevel;
1253
1254 if (!ircd_strcmp(np->authname, tochange)) {
1255 specialcase = 1;
1256 } else {
1257 specialcase = 0;
1258 }
1259
1260 for (p=cargv[1];*p;p++) {
1261 switch (*p) {
1262 case '+':
1263 case '-':
1264 mode = (*p == '+');
1265 break;
1266 case 'd':
1267 if (!TrojanscanIsDeveloper(flags1))
1268 clast = 1;
1269 flags2.values.developer = mode;
1270 break;
1271 case 't':
1272 if (!TrojanscanIsDeveloper(flags1))
1273 clast = 1;
1274 flags2.values.teamleader = mode;
1275 break;
1276 case 's':
1277 if (!TrojanscanIsLeastTeamLeader(flags1))
1278 clast = 1;
1279 flags2.values.staff = mode;
1280 break;
1281 case 'w':
1282 if (!TrojanscanIsDeveloper(flags1))
1283 clast = 1;
1284 flags2.values.website = mode;
1285 break;
1286 case 'c':
1287 if (!TrojanscanIsDeveloper(flags1))
1288 clast = 1;
1289 flags2.values.cat = mode;
1290 break;
1291 default:
1292 error = 1;
1293 goto last;
1294 break;
1295 }
1296 if (clast == 1) {
1297 if (specialcase && !mode) { /* allow user to remove their own flags */
1298 clast = 0;
1299 } else {
1300 goto last;
1301 }
1302 }
1303 }
1304
1305 last:
1306 if (*p) {
1307 if (error) {
1308 trojanscan_reply(np, "Unknown mode: %c%c.", mode?'+':'-', *p);
1309 } else {
1310 trojanscan_reply(np, "You have insufficient privilidges to add/remove one or more flags specified.");
1311 }
1312 return CMD_ERROR;
1313 }
1314
1315 trojanscan_log(np, "changelev", "%s %s", tochange, cargv[1]);
1316 trojanscan_database_escape_string(eaccount, tochange, strlen(tochange));
1317 trojanscan_database_query("UPDATE users SET authlevel = %d WHERE authname = '%s'", flags2.number, eaccount);
1318
1319 trojanscan_reply(np, "Flags changed.");
1320
1321 return CMD_OK;
1322}
1323
1324int trojanscan_deluser(void *sender, int cargc, char **cargv) {
1325 nick *np = (nick *)sender, *to;
1326 int templevel;
1327 char eaccount[TROJANSCAN_QUERY_TEMP_BUF_SIZE], *account;
1328 union trojanscan_userlevel flags1, flags2;
1329
1330 if (cargc < 1) {
1331 trojanscan_reply(np, "Not enough parameters.");
1332 return CMD_ERROR;
1333 }
1334
1335 if (cargv[0][0] == '#') {
1336 account = cargv[0] + 1;
1337 } else {
1338 to = getnickbynick(cargv[0]);
1339 if (!to) {
1340 trojanscan_reply(np, "That nickname is not on the network.");
1341 return CMD_ERROR;
1342 }
1343 if (!IsAccount(to)) {
1344 trojanscan_reply(np, "That user is not authed with the network.");
1345 return CMD_ERROR;
1346 }
1347 account = to->authname;
1348 }
1349
1350 flags1.number = trojanscan_user_level_by_authname(np->authname);
1351 templevel = trojanscan_user_level_by_authname(account);
1352
1353 if (templevel == -1) {
1354 trojanscan_reply(np, "Auth %s does not exist.", account);
1355 return CMD_ERROR;
1356 }
1357
1358 flags2.number = templevel;
1359
1360 if (!TrojanscanIsDeveloper(flags1) && TrojanscanIsLeastTeamLeader(flags2)) {
1361 trojanscan_reply(np, "Your cannot delete %s as his/her flags equal or surpass your own.", account);
1362 return CMD_ERROR;
1363 }
1364
1365 trojanscan_log(np, "deluser", account);
1366 trojanscan_database_escape_string(eaccount, account, strlen(account));
1367 trojanscan_database_query("DELETE FROM users WHERE authname = '%s'", eaccount);
1368 trojanscan_reply(np, "User deleted.");
1369
1370 return CMD_OK;
1371}
1372
1373int trojanscan_add_ll(struct trojanscan_prechannels **head, struct trojanscan_prechannels *newitem) {
1374 struct trojanscan_prechannels *position, *lastitem = NULL, *location = NULL;
1375 if (!*head) {
1376 *head = newitem;
1377 newitem->next = NULL;
1378 if (newitem->exempt) {
1379 return 0;
1380 } else {
1381 return 1;
1382 }
1383 }
1384 /* if its exempt, we don't give a monkeys where it is... */
1385 if (newitem->exempt) {
1386 newitem->next = *head;
1387 *head = newitem;
1388 return 0;
1389 }
1390
1391 for(position=*head;position;lastitem=position,position=position->next) {
1392 if (!ircd_strcmp(position->name->content, newitem->name->content)) {
93917ccd 1393 tfree(newitem);
c86edd1d
Q
1394 return 0;
1395 }
1396 if (!location && (position->size < newitem->size)) {
1397 if (!lastitem) {
1398 location = *head;
1399 } else {
1400 location = lastitem;
1401 }
1402 }
1403 }
1404 if (!location) {
1405 newitem->next = NULL;
1406 lastitem->next = newitem;
1407 } else {
1408 newitem->next = location->next;
1409 location->next = newitem;
1410 }
1411 if(newitem->exempt) {
1412 return 0;
1413 } else {
1414 return 1;
1415 }
1416}
1417
1418void trojanscan_watch_clone_update(struct trojanscan_prechannels *hp, int count) {
378cf1b9 1419 int i, j, marked;
c86edd1d 1420 struct trojanscan_prechannels *lp;
1fbb1306 1421 struct trojanscan_templist *markedlist = NULL;
378cf1b9 1422
c86edd1d 1423 if(count > 0) {
70ad3da9 1424 markedlist = (struct trojanscan_templist *)tmalloc(count * sizeof(struct trojanscan_templist));
c86edd1d
Q
1425 if (!markedlist)
1426 return;
93917ccd 1427 memset(markedlist, 0, sizeof(struct trojanscan_templist) * count);
c86edd1d
Q
1428 }
1429
1430 for(i=0;i<trojanscan_activechans;i++) {
1431 marked = 0;
1fbb1306
CP
1432 if(markedlist) {
1433 for(lp=hp,j=0;j<count&&lp;j++,lp=lp->next) {
1434 if(!markedlist[j].active && !lp->exempt && !ircd_strcmp(lp->name->content, trojanscan_chans[i].channel->content)) { /* we're already on the channel */
1435 if(trojanscan_chans[i].watch_clone) {
1436 markedlist[j].active = 1;
1437 markedlist[j].watch_clone = trojanscan_chans[i].watch_clone;
1438 lp->watch_clone = trojanscan_chans[i].watch_clone;
1439 }
1440 marked = 1;
1441 break;
378cf1b9 1442 }
c86edd1d
Q
1443 }
1444 }
378cf1b9
CP
1445 if(!marked && trojanscan_chans[i].watch_clone) {
1446 channel *cp = findchannel(trojanscan_chans[i].channel->content);
1447 if(cp)
334b567e 1448 localpartchannel(trojanscan_chans[i].watch_clone->clone, cp, NULL);
c86edd1d
Q
1449 }
1450 }
1451
1fbb1306
CP
1452 if(!markedlist)
1453 return;
1454
c86edd1d 1455 for(j=0,lp=hp;j<count&&lp;j++,lp=lp->next) {
378cf1b9
CP
1456 if((!markedlist[j].active || !markedlist[j].watch_clone) && !lp->exempt) {
1457 channel *cp = findchannel(lp->name->content);
1458 if(cp) {
1459 int attempts = 10;
1460 do {
1461 lp->watch_clone = trojanscan_selectclone(TROJANSCAN_WATCH_CLONES);
1462 if(!lp->watch_clone)
1463 break;
2e9a528b 1464 if(!trojanscan_nickbanned(lp->watch_clone, cp)) {
1fe41720
CP
1465 if(localjoinchannel(lp->watch_clone->clone, cp))
1466 lp->watch_clone = NULL;
378cf1b9
CP
1467 break;
1468 }
1469 } while(--attempts > 0);
1470 if(!attempts)
1471 lp->watch_clone = NULL;
1472
1473 }
c86edd1d 1474 }
c86edd1d
Q
1475 }
1476
93917ccd 1477 tfree(markedlist);
c86edd1d
Q
1478}
1479
1480void trojanscan_fill_channels(void *arg) {
1481 struct trojanscan_prechannels *head = NULL, *lp, *last = NULL;
1482 int i, count, tempctime = 0;
1483
1484 chanindex *chn;
1485
1486 for (count=i=0;i<trojanscan_database.total_channels;i++) {
93917ccd 1487 lp = (trojanscan_prechannels *)tmalloc(sizeof(trojanscan_prechannels));
c86edd1d
Q
1488 lp->name = trojanscan_database.channels[i].name;
1489 lp->size = 65535;
1490 lp->exempt = trojanscan_database.channels[i].exempt;
378cf1b9 1491 lp->watch_clone = NULL;
c86edd1d
Q
1492 if (trojanscan_add_ll(&head, lp))
1493 count++;
1494 }
1495
1496 for (i=0;i<CHANNELHASHSIZE;i++) {
1497 for(chn=chantable[i];chn;chn=chn->next) {
0d182ada 1498 if (chn->channel && !IsKey(chn->channel) && !IsInviteOnly(chn->channel) && !IsRegOnly(chn->channel) && (chn->channel->users->totalusers >= trojanscan_minchansize)) {
93917ccd 1499 lp = (trojanscan_prechannels *)tmalloc(sizeof(trojanscan_prechannels));
c86edd1d
Q
1500 lp->name = chn->name;
1501 lp->size = chn->channel->users->totalusers;
1502 lp->exempt = 0;
378cf1b9 1503 lp->watch_clone = NULL;
c86edd1d
Q
1504 if (trojanscan_add_ll(&head, lp))
1505 count++;
1506 }
1507 }
1508 }
1509
1510 count = TROJANSCAN_MMIN(count, trojanscan_maxchans);
1511
378cf1b9 1512 trojanscan_watch_clone_update(head, count);
c86edd1d
Q
1513
1514 trojanscan_free_channels();
93917ccd
CP
1515 trojanscan_chans = (struct trojanscan_inchannel *)tmalloc(count * sizeof(struct trojanscan_inchannel));
1516 memset(trojanscan_chans, 0, count * sizeof(struct trojanscan_inchannel));
c86edd1d
Q
1517 trojanscan_activechans = count;
1518 i = 0;
378cf1b9 1519
c86edd1d 1520 for(lp=head;lp;last=lp,lp=lp->next) {
378cf1b9
CP
1521 if (!(lp->exempt) && (i < count)) {
1522 trojanscan_chans[i].channel = getsstring(lp->name->content, lp->name->length);
1523 trojanscan_chans[i++].watch_clone = lp->watch_clone;
1524 }
c86edd1d 1525 if (last)
93917ccd 1526 tfree(last);
c86edd1d
Q
1527 }
1528
1529 if (last)
93917ccd 1530 tfree(last);
c86edd1d
Q
1531
1532 if (trojanscan_activechans > 0) {
1533 tempctime = trojanscan_cycletime / trojanscan_activechans;
1534 } else {
1535 tempctime = 60;
1536 trojanscan_mainchanmsg("d: just escaped a divide by zero error (no activechans!), rescheduling in 60 seconds");
1537 }
1538
1539 if(trojanscan_schedule)
1540 deleteschedule(trojanscan_schedule, &trojanscan_dojoin, NULL);
1541
1542 trojanscan_channumber = 0;
1543
1544 trojanscan_schedule = schedulerecurring(time(NULL) + tempctime, trojanscan_activechans + 1, tempctime, trojanscan_dojoin, NULL);
1545
1546}
1547
1548void trojanscan_dojoin(void *arg) {
1549 struct trojanscan_realchannels *rc;
1550 if (trojanscan_channumber >= trojanscan_activechans) {
1551 trojanscan_schedule = NULL;
1552 trojanscan_fill_channels(NULL);
1553 } else {
378cf1b9 1554 if ((rc = trojanscan_allocaterc(trojanscan_chans[trojanscan_channumber++].channel->content)))
c86edd1d
Q
1555 trojanscan_join(rc);
1556 }
1557}
1558
1559
1560void trojanscan_dopart(void *arg) {
1561 struct trojanscan_realchannels *rc = (struct trojanscan_realchannels *)arg, *rp, *past = NULL;
1562
1563 if (rc->kickedout) { /* there's a join scheduled, wait for it (reschedule) */
1564 rc->schedule = scheduleoneshot(time(NULL)+5, &trojanscan_dopart, (void *)rc);
1565 return;
1566 }
1567
31f37482 1568 if (rc->clone->clone && (!(rc->donotpart)))
334b567e 1569 localpartchannel(rc->clone->clone, rc->chan, NULL);
31f37482 1570
c86edd1d
Q
1571 rc->clone->sitting--;
1572
1573 for(rp=trojanscan_realchanlist;rp;rp=rp->next) {
1574 if (rp == rc) {
1575 if (!past) {
1576 trojanscan_realchanlist = rp->next;
1577 } else {
1578 past->next = rp->next;
1579 }
93917ccd 1580 tfree(rp);
c86edd1d
Q
1581 break;
1582 }
1583 past = rp;
1584 }
1585
1586}
1587
1588void trojanscan_donickchange(void *arg) { /* just incase I choose to make this schedule at some point */
1589 struct trojanscan_clones *clone = (trojanscan_clones *)arg;
1590 if (clone && clone->clone) {
1591 char c_nick[NICKLEN+1];
1592 int loops = 0;
1593 /* PPA: unlikely to be infinite */
1594 do {
1595 if ((loops++ < 10) && trojanscan_hostmode) {
1596 trojanscan_generatenick(c_nick, NICKLEN);
1597 } else {
1598 trojanscan_gennick(c_nick, trojanscan_minmaxrand(7, TROJANSCAN_MMIN(13, NICKLEN)));
1599 }
b98ba21f 1600 } while (c_nick[0] && (getnickbynick(c_nick) != NULL));
c86edd1d
Q
1601
1602 renamelocaluser(clone->clone, c_nick);
1603 }
1604
1605}
1606
1607int trojanscan_keysort(const void *v1, const void *v2) {
1608 return ((*(trojanscan_prechannels **)v2)->size - (*(trojanscan_prechannels **)v1)->size);
1609}
1610
1611int trojanscan_showcommands(void *sender, int cargc, char **cargv) {
1612 nick *np = (nick *)sender;
1613 Command *cmdlist[100];
1614 int i, n;
1615 char level = 0;
1616
1617 n = getcommandlist(trojanscan_cmds, cmdlist, 100);
1618
1619 trojanscan_reply(np, "The following commands are registered at present:");
1620
1621 for(i=0;i<n;i++) {
1622 if (cmdlist[i]->level & TROJANSCAN_ACL_STAFF) {
1623 level = 's';
1624 } else if (cmdlist[i]->level & TROJANSCAN_ACL_DEVELOPER) {
1625 level = 'd';
1626 } else if (cmdlist[i]->level & TROJANSCAN_ACL_TEAMLEADER) {
1627 level = 't';
1628 } else if (cmdlist[i]->level & TROJANSCAN_ACL_CAT) {
1629 level = 'c';
1630 } else if (cmdlist[i]->level & TROJANSCAN_ACL_WEBSITE) {
1631 level = 'w';
1632 } else if (cmdlist[i]->level & TROJANSCAN_ACL_UNAUTHED) {
1633 level = 0;
1634 }
1635 if (level) {
1636 trojanscan_reply(np, "%s (+%c)", cmdlist[i]->command->content, level);
1637 } else {
1638 trojanscan_reply(np, "%s", cmdlist[i]->command->content);
1639 }
1640 }
1641 trojanscan_reply(np, "End of list.");
1642 return CMD_OK;
1643}
1644
1645void trojanscan_handlemessages(nick *target, int messagetype, void **args) {
1646 Command *cmd;
1647 char *cargv[50];
1648 int cargc, templevel;
1649 nick *sender;
1650 union trojanscan_userlevel level;
1651
1652 switch(messagetype) {
1653 case LU_PRIVMSG:
1654 case LU_SECUREMSG:
1655 /* If it's a message, first arg is nick and second is message */
1656 sender = (nick *)args[0];
1657
1658 if(strncmp(TROJANSCAN_VERSION_DETECT, args[1], sizeof(TROJANSCAN_VERSION_DETECT)-1)==0) {
1659 char p = ((char *)args[1])[sizeof(TROJANSCAN_VERSION_DETECT)-1];
1660 if((p == ' ') || (p == '\0') || (p == 1)) {
1661 trojanscan_reply(sender, "\001VERSION Trojanscan (or Tigger) Newserv module version %s by Chris Porter (slug), Newserv by David Mansell (splidge). Compiled " __DATE__ " " __TIME__ ".\001", TROJANSCAN_VERSION);
1662 return;
1663 }
1664 }
1665
1666 /* Split the line into params */
1667 cargc = splitline((char *)args[1], cargv, 50, 0);
b98ba21f 1668 if(cargc == 0 || !cargv[0])
99174f6c 1669 return;
c86edd1d
Q
1670
1671 cmd=findcommandintree(trojanscan_cmds, cargv[0], 1);
1672 if (!cmd) {
1673 trojanscan_reply(sender, "Unknown command.");
1674 return;
1675 }
1676
1677 if ((cmd->level & TROJANSCAN_ACL_OPER) && !IsOper(sender)) {
1678 trojanscan_reply(sender, "You need to be opered to use this command.");
1679 return;
1680 }
1681
1682 /* bit grim code... */
1683
1684 if (!(cmd->level & TROJANSCAN_ACL_UNAUTHED)) {
1685 if (!IsAccount(sender)) {
1686 trojanscan_reply(sender, "You must be authed with the network to access this command!");
1687 return;
1688 }
1689 templevel = trojanscan_user_level_by_authname(sender->authname);
1690
1691 if (templevel == -1) {
1692 trojanscan_reply(sender, "You do not have an account.");
1693 return;
1694 }
1695
1696 level.number = templevel;
1697
1698 if ((cmd->level & TROJANSCAN_ACL_DEVELOPER) && !TrojanscanIsDeveloper(level)) {
1699 trojanscan_reply(sender, "Access denied.");
1700 return;
1701 }
1702 if ((cmd->level & TROJANSCAN_ACL_TEAMLEADER) && !TrojanscanIsLeastTeamLeader(level)) {
1703 trojanscan_reply(sender, "Access denied.");
1704 return;
1705 }
1706 if ((cmd->level & TROJANSCAN_ACL_STAFF) && !TrojanscanIsLeastStaff(level)) {
1707 trojanscan_reply(sender, "Access denied.");
1708 return;
1709 }
1710 if ((cmd->level & TROJANSCAN_ACL_CAT) && !TrojanscanIsCat(level)) {
1711 trojanscan_reply(sender, "Access denied.");
1712 return;
1713 }
1714 if ((cmd->level & TROJANSCAN_ACL_WEBSITE) && !TrojanscanIsLeastWebsite(level)) {
1715 trojanscan_reply(sender, "Access denied.");
1716 return;
1717 }
1718 }
1719
1720 /* Check the maxargs */
1721 if (cmd->maxparams<(cargc-1)) {
1722 /* We need to do some rejoining */
1723 rejoinline(cargv[cmd->maxparams], cargc-(cmd->maxparams));
1724 cargc = (cmd->maxparams) + 1;
1725 }
1726
1727 (cmd->handler)((void *)sender, cargc - 1, &(cargv[1]));
1728 break;
1729
1730 case LU_KILLED:
1731 /* someone killed me? Bastards */
9bf89af0 1732 trojanscan_connect_nick_schedule = scheduleoneshot(time(NULL) + 1, &trojanscan_connect_nick, NULL);
c86edd1d
Q
1733 trojanscan_nick = NULL;
1734 break;
1735
1736 default:
1737 break;
1738 }
1739}
1740
a0c2b0da
CP
1741static char trojanscan_getmtfromhooktype(int input) {
1742 switch(input) {
1743 case HOOK_CHANNEL_PART: return 'P';
1744 default: return '?';
1745 }
1746}
1747
c86edd1d
Q
1748char trojanscan_getmtfrommessagetype(int input) {
1749 switch(input) {
1750 case LU_PRIVMSG: return 'm';
1751 case LU_PRIVNOTICE: return 'n';
1752 case LU_SECUREMSG: return 's';
1753 case LU_CHANMSG: return 'M';
1754 case LU_CHANNOTICE: return 'N';
1755 default: return '?';
1756 }
1757}
1758
a0c2b0da
CP
1759static void trojanscan_process(nick *sender, channel *cp, char mt, char *pretext) {
1760 char text[513];
1761 unsigned int len;
1762 unsigned int i;
1763 struct trojanscan_worms *worm;
1764 int vector[30], detected = 0;
1765
1766 trojanscan_strip_codes(text, sizeof(text) - 1, pretext);
1767
1768 len = strlen(text);
1769
1770 for(i=0;i<trojanscan_database.total_phrases;i++) {
1771 if (
1772 (
1773 (worm = trojanscan_database.phrases[i].worm)
1774 ) &&
1775 (
1776 (
1777 (
1778 (mt == 'm') || (mt == 's') || (mt == 'n')
1779 ) &&
1780 (
1781 (trojanscan_database.phrases[i].worm->hitpriv)
1782 )
1783 ) ||
1784 (
1785 (
1786 (mt == 'M') || (mt == 'N') || (mt == 'P')
1787 ) &&
1788 (
1789 (trojanscan_database.phrases[i].worm->hitchans)
1790 )
1791 )
1792 ) &&
1793 (trojanscan_database.phrases[i].phrase)
1794 ) {
1795 int pre = pcre_exec(trojanscan_database.phrases[i].phrase, trojanscan_database.phrases[i].hint, text, len, 0, 0, vector, 30);
1796 if(pre >= 0) {
1797 char matchbuf[513];
1798 matchbuf[0] = 0;
1799 matchbuf[512] = 0; /* hmm */
1800
1801 if(pre > 1)
1802 if(pcre_copy_substring(text, vector, pre, 1, matchbuf, sizeof(matchbuf) - 1) <= 0)
1803 matchbuf[0] = 0;
1804
1805 trojanscan_phrasematch(cp, sender, &trojanscan_database.phrases[i], mt, matchbuf);
1806
1807 detected = 1;
1808 break;
1809 }
1810 }
1811 }
1812 if (!detected && (mt != 'N') && (mt != 'M')) {
1813 char etext[TROJANSCAN_QUERY_TEMP_BUF_SIZE], enick[TROJANSCAN_QUERY_TEMP_BUF_SIZE], eident[TROJANSCAN_QUERY_TEMP_BUF_SIZE], ehost[TROJANSCAN_QUERY_TEMP_BUF_SIZE];
1814 trojanscan_database_escape_string(etext, text, len);
1815 trojanscan_database_escape_string(enick, sender->nick, strlen(sender->nick));
1816 trojanscan_database_escape_string(eident, sender->ident, strlen(sender->ident));
1817 trojanscan_database_escape_string(ehost, sender->host->name->content, sender->host->name->length);
1818 trojanscan_database_query("INSERT INTO unknownlog (data, user) VALUES ('%s','%s!%s@%s')", etext, enick, eident, ehost);
1819 }
1820}
1821
c86edd1d 1822void trojanscan_clonehandlemessages(nick *target, int messagetype, void **args) {
a0c2b0da 1823 char *pretext = NULL;
c86edd1d
Q
1824 nick *sender;
1825 struct trojanscan_realchannels *rp;
1826 struct trojanscan_rejoinlist *rj;
c86edd1d 1827 char mt = trojanscan_getmtfrommessagetype(messagetype);
378cf1b9 1828 char *channel_name;
a0c2b0da
CP
1829 channel *cp = NULL;
1830 int i;
378cf1b9 1831
c86edd1d
Q
1832 switch(messagetype) {
1833 case LU_PRIVMSG:
1834 case LU_SECUREMSG:
1835 case LU_PRIVNOTICE:
1836
1837 pretext = (char *)args[1];
1838
1839 case LU_CHANMSG:
1840 case LU_CHANNOTICE:
c86edd1d 1841 sender = (nick *)args[0];
a0c2b0da 1842
c86edd1d
Q
1843 if (strlen(sender->nick) < 2)
1844 break;
1845
a0c2b0da 1846 if (!pretext) {
c86edd1d 1847 pretext = (char *)args[2];
a0c2b0da
CP
1848 cp = args[1];
1849 }
c86edd1d
Q
1850
1851 if(strncmp(TROJANSCAN_VERSION_DETECT, pretext, sizeof(TROJANSCAN_VERSION_DETECT)-1)==0) {
1852 char p = pretext[sizeof(TROJANSCAN_VERSION_DETECT)-1];
1853 if((p == ' ') || (p == '\0') || (p == 1)) {
1854 int staff = 0;
1855 if (IsOper(sender)) {
1856 staff = 1;
1857 } else {
1858 if (IsAccount(sender)) {
1859 int templevel = trojanscan_user_level_by_authname(sender->authname);
1860 if (templevel != -1) {
1861 union trojanscan_userlevel level;
1862 level.number = templevel;
1863 if (TrojanscanIsLeastStaff(level))
1864 staff = 1;
1865 }
1866 }
1867 }
1868 if (staff) {
1fe41720
CP
1869 if(trojanscan_nick) {
1870 sendnoticetouser(target, sender, "\001VERSION T clone, check T for confirmation.\001");
1871 sendnoticetouser(trojanscan_nick, sender, "\001VERSION %s is part of my swarm.\001", target->nick);
1872 } else {
1873 sendnoticetouser(target, sender, "\001VERSION T clone, though since T is currently gone you'll have to version me again in a minute for confirmation.\001");
1874 }
c86edd1d 1875 } else {
8f619fe4 1876 sendnoticetouser(target, sender, "\001VERSION %s\001", versionreply);
c86edd1d
Q
1877 }
1878
1879 return;
1880 }
1881 }
1882
a0c2b0da 1883 trojanscan_process(sender, cp, mt, pretext);
c86edd1d
Q
1884 break;
1885 case LU_KILLED:
1886 /* someone killed me? Bastards */
378cf1b9 1887
c86edd1d 1888 /* PPA: we do NOT rejoin channels at this moment in time, it is possible to do this though */
378cf1b9 1889 for (i=0;i<TROJANSCAN_CLONE_TOTAL;i++) {
c86edd1d 1890 if (trojanscan_swarm[i].clone == target) {
c86edd1d 1891
c3db6f7e 1892 scheduleoneshot(time(NULL)+1, &trojanscan_generateclone, (void *)((long)i));
1fe41720 1893 if(i >= TROJANSCAN_CLONE_MAX) {
378cf1b9
CP
1894 int j;
1895 for(j=0;j<trojanscan_activechans;j++)
1896 if(trojanscan_chans[j].watch_clone == &trojanscan_swarm[i])
1897 trojanscan_chans[j].watch_clone = NULL;
1898 } else {
1899 for(rp=trojanscan_realchanlist;rp;rp=rp->next)
1900 if ((rp->clone == &(trojanscan_swarm[i])))
1901 rp->donotpart = 1;
1902 }
1fbd040c 1903 derefnode(iptree, trojanscan_swarm[i].fakeipnode);
c86edd1d
Q
1904 trojanscan_swarm[i].clone = NULL;
1905 trojanscan_swarm[i].remaining = 0; /* bah */
1906 break;
1907 }
1908 }
1909 break;
1910
1911 case LU_KICKED:
378cf1b9
CP
1912 channel_name = ((channel *)args[1])->index->name->content;
1913 for (i=0;i<trojanscan_activechans;i++) {
1914 if (!trojanscan_chans[i].watch_clone)
1915 continue;
1916 if ((trojanscan_chans[i].watch_clone->clone == target) && (!strcmp(trojanscan_chans[i].channel->content, channel_name)))
1917 break;
1918 }
1919 if(i != trojanscan_activechans) {
1920 int j;
1921 for(j=0;j<TROJANSCAN_CLONE_TOTAL;j++) {
1922 if(&trojanscan_swarm[j] == trojanscan_chans[i].watch_clone) {
1923 trojanscan_chans[i].watch_clone = NULL;
c86edd1d
Q
1924 break;
1925 }
c86edd1d 1926 }
378cf1b9
CP
1927 } else {
1928 /*
1929 trojanscan_mainchanmsg("k: %s on %s by %s", target->nick, ((channel *)args[1])->index->name->content, (((nick *)args[0])->nick)?(((nick *)args[0])->nick):"(server)");
1930 */
93917ccd 1931 rj = (struct trojanscan_rejoinlist *)tmalloc(sizeof(struct trojanscan_rejoinlist));
378cf1b9
CP
1932 if (rj) {
1933 rj->rp = NULL;
1934 for(rp=trojanscan_realchanlist;rp;rp=rp->next)
1935 if ((rp->clone->clone == target) && (rp->chan == args[1])) {
1936 rp->kickedout++;
1937 rj->rp = rp;
1938 break;
1939 }
1940 if(!rj->rp) {
93917ccd 1941 tfree(rj);
378cf1b9
CP
1942 return;
1943 }
c86edd1d 1944
378cf1b9
CP
1945 rj->channel = getsstring(((channel *)args[1])->index->name->content, ((channel *)args[1])->index->name->length);
1946 if(!rj->channel) {
1947 trojanscan_mainchanmsg("d: unable to allocate memory for channel: %s upon rejoin", ((channel *)args[1])->index->name->content);
93917ccd 1948 tfree(rj);
378cf1b9
CP
1949 return;
1950 }
c86edd1d 1951
2e9a528b 1952 rj->clone = rp->clone;
378cf1b9
CP
1953 rj->next = trojanscan_schedulerejoins;
1954 trojanscan_schedulerejoins = rj;
c86edd1d 1955
378cf1b9
CP
1956 rj->schedule = scheduleoneshot(time(NULL)+1, &trojanscan_rejoin_channel, (void *)rj);
1957 }
1958 }
1959 break;
c86edd1d
Q
1960 default:
1961 break;
1962 }
1963}
1964
a0c2b0da
CP
1965static void trojanscan_part_watch(int hook, void *arg) {
1966 void **arglist = (void **)arg;
1967 channel *cp = (channel *)arglist[0];
1968 nick *np = arglist[1];
1969 char *reason = arglist[2];
1970
1971 if(!cp || !np || !reason || (*reason == '\0'))
1972 return;
1973
1974 trojanscan_process(np, cp, trojanscan_getmtfromhooktype(hook), reason);
1975}
1976
82c1a763
CP
1977static int trojanscan_hostcount(nick *sender, int hostmode, char *mask, int masklen) {
1978 int usercount = 0, j;
1979 nick *np = NULL; /* sigh at warnings */
1980
1981 if(hostmode)
1982 for (j=0;j<NICKHASHSIZE;j++)
1983 for (np=nicktable[j];np;np=np->next)
1984 if (np->ipnode==sender->ipnode)
1985 usercount++;
1986
1987 if(usercount > TROJANSCAN_MAX_HOST_GLINE) {
1988 hostmode = 0;
1989 usercount = 0;
1990 }
1991
1992 if(!hostmode)
1993 for (j=0;j<NICKHASHSIZE;j++)
1994 for (np=nicktable[j];np;np=np->next)
1995 if (np->ipnode==sender->ipnode && !ircd_strcmp(np->ident, sender->ident))
1996 usercount++;
1997
1998 if(mask)
1999 snprintf(mask, masklen, "%s@%s", hostmode?"*":sender->ident, IPtostr(sender->p_ipaddr));
2000
2001 return usercount;
2002}
2003
cba071ec
CP
2004void trojanscan_phrasematch(channel *chp, nick *sender, trojanscan_phrases *phrase, char messagetype, char *matchbuf) {
2005 char glinemask[HOSTLEN + USERLEN + NICKLEN + 4], enick[TROJANSCAN_QUERY_TEMP_BUF_SIZE], eident[TROJANSCAN_QUERY_TEMP_BUF_SIZE], ehost[TROJANSCAN_QUERY_TEMP_BUF_SIZE];
82c1a763
CP
2006 unsigned int frequency;
2007 int glining = 0, usercount;
cba071ec
CP
2008 struct trojanscan_worms *worm = phrase->worm;
2009
cba071ec
CP
2010 trojanscan_database.detections++;
2011
54db53be 2012 usercount = 0;
cba071ec 2013 if (worm->monitor) {
cba071ec 2014 usercount = -1;
82c1a763
CP
2015 } else if(worm->glinehost || worm->glineuser) {
2016 glining = 1;
2017
2018 usercount = trojanscan_hostcount(sender, worm->glinehost, glinemask, sizeof(glinemask));
cba071ec
CP
2019 }
2020
2021 if (!usercount) {
2022 trojanscan_mainchanmsg("w: user %s!%s@%s triggered infection monitor, yet no hosts found at stage 2 -- worm: %s", sender->nick, sender->ident, sender->host->name->content, worm->name->content);
2023 return;
2024 }
2025
2026 if (glining && (usercount > trojanscan_maxusers)) {
2027 trojanscan_mainchanmsg("w: not glining %s!%s@%s due to too many users (%d) with mask: *!%s -- worm: %s)", sender->nick, sender->ident, sender->host->name->content, usercount, glinemask, worm->name->content);
2028 return;
2029 }
2030
2031 if (glining && !worm->datalen) {
2032 trojanscan_mainchanmsg("w: not glining %s!%s@%s due to too lack of removal data with mask: *!%s (%d users) -- worm: %s)", sender->nick, sender->ident, sender->host->name->content, glinemask, usercount, worm->name->content);
2033 return;
2034 }
2035
2036 trojanscan_database_escape_string(enick, sender->nick, strlen(sender->nick));
2037 trojanscan_database_escape_string(eident, sender->ident, strlen(sender->ident));
2038 trojanscan_database_escape_string(ehost, sender->host->name->content, sender->host->name->length);
2039
2040 frequency = 1;
2041
2042 if (!(trojanscan_database_query("SELECT COUNT(*) FROM hits WHERE glined = %d AND host = '%s'", glining, ehost))) {
2043 trojanscan_database_res *res;
2044 if ((res = trojanscan_database_store_result(&trojanscan_sql))) {
2045 trojanscan_database_row sqlrow;
2046 if ((trojanscan_database_num_rows(res) > 0) && (sqlrow = trojanscan_database_fetch_row(res)))
2047 frequency = atoi(sqlrow[0]) + 1;
2048 trojanscan_database_free_result(res);
2049 }
2050 }
2051
2052 if (!glining) {
a0c2b0da 2053 trojanscan_mainchanmsg("m: t: %c u: %s!%s@%s%s%s w: %s p: %d %s%s", messagetype, sender->nick, sender->ident, sender->host->name->content, messagetype=='N'||messagetype=='M'||messagetype=='P'?" #: ":"", messagetype=='N'||messagetype=='M'||messagetype=='P'?chp->index->name->content:"", worm->name->content, phrase->id, matchbuf[0]?" --: ":"", matchbuf[0]?matchbuf:"");
cba071ec 2054#ifdef TROJANSCAN_PEONCHANNEL
a0c2b0da 2055 trojanscan_peonchanmsg("m: t: %c u: %s!%s@%s%s%s%s w: %s %s%s", messagetype, sender->nick, sender->ident, (IsHideHost(sender)&&IsAccount(sender))?sender->authname:sender->host->name->content, (IsHideHost(sender)&&IsAccount(sender))?"."HIS_HIDDENHOST:"", messagetype=='N'||messagetype=='M'||messagetype=='P'?" #: ":"", messagetype=='N'||messagetype=='M'||messagetype=='P'?chp->index->name->content:"", worm->name->content, matchbuf[0]?" --: ":"", matchbuf[0]?matchbuf:"");
cba071ec
CP
2056#endif
2057 } else {
2058 int glinetime = TROJANSCAN_FIRST_OFFENSE * frequency * (worm->epidemic?TROJANSCAN_EPIDEMIC_MULTIPLIER:1);
2059 if(glinetime > 7 * 24)
2060 glinetime = 7 * 24; /* can't set glines over 7 days with normal non U:lined glines */
2061
2062 trojanscan_database_query("INSERT INTO hits (nickname, ident, host, phrase, messagetype, glined) VALUES ('%s', '%s', '%s', %d, '%c', %d)", enick, eident, ehost, phrase->id, messagetype, glining);
2063 trojanscan_database.glines++;
2064
2065 irc_send("%s GL * +%s %d :You (%s!%s@%s) are infected with a trojan (%s/%d), see %s%d for details - banned for %d hours\r\n", mynumeric->content, glinemask, glinetime * 3600, sender->nick, sender->ident, sender->host->name->content, worm->name->content, phrase->id, TROJANSCAN_URL_PREFIX, worm->id, glinetime);
2066
a0c2b0da 2067 trojanscan_mainchanmsg("g: *!%s t: %c u: %s!%s@%s%s%s c: %d w: %s%s p: %d f: %d", glinemask, messagetype, sender->nick, sender->ident, sender->host->name->content, messagetype=='N'||messagetype=='M'||messagetype=='P'?" #: ":"", messagetype=='N'||messagetype=='M'||messagetype=='P'?chp->index->name->content:"", usercount, worm->name->content, worm->epidemic?"(E)":"", phrase->id, frequency);
cba071ec
CP
2068 }
2069}
2070
c86edd1d
Q
2071void trojanscan_rejoin_channel(void *arg) {
2072 struct trojanscan_rejoinlist *rj2, *lrj, *rj = (struct trojanscan_rejoinlist *)arg;
c86edd1d
Q
2073
2074 channel *cp = findchannel(rj->channel->content);
2075 freesstring(rj->channel);
2076
2077 if (rj->rp) {
2078 rj->rp->kickedout--;
2079 if (!cp) {
2080 rj->rp->donotpart = 1; /* we were the last user on the channel, so we need to be VERY careful freeing it */
2081 } else {
2082 if(!rj->rp->donotpart && !rj->rp->kickedout) { /* check we're allowed to join channels (not killed), and we're the last one to join */
2e9a528b 2083 if (trojanscan_nickbanned(rj->clone, cp)) {
c86edd1d
Q
2084 rj->rp->donotpart = 1;
2085 } else {
2e9a528b 2086 localjoinchannel(rj->clone->clone, cp);
c86edd1d
Q
2087 }
2088 }
2089 }
2090 }
2091
2092 rj2 = trojanscan_schedulerejoins;
2093 lrj = NULL;
2094
2095 if (rj2 == rj) {
2096 trojanscan_schedulerejoins = rj->next;
93917ccd 2097 tfree(rj);
c86edd1d
Q
2098 } else {
2099 for(rj2=trojanscan_schedulerejoins;rj2;lrj=rj2,rj2=rj2->next) {
2100 if (rj2 == rj) {
2101 lrj->next = rj2->next;
93917ccd 2102 tfree(rj);
c86edd1d
Q
2103 break;
2104 }
2105 }
2106 }
2107
2108}
2109
2110void trojanscan_reply(nick *target, char *message, ... ) {
2111 char buf[513];
2112 va_list va;
2113
2114 if (!trojanscan_nick)
2115 return;
2116
2117 va_start(va, message);
2118 vsnprintf(buf, sizeof(buf) - 1, message, va);
2119 va_end(va);
2120
2121 sendnoticetouser(trojanscan_nick, target, "%s", buf);
2122}
2123
2124
2125void trojanscan_mainchanmsg(char *message, ...) {
2126 char buf[513];
2127 va_list va;
2128 channel *cp;
2129
2130 if (!trojanscan_nick)
2131 return;
2132 if (!(cp = findchannel(TROJANSCAN_CHANNEL)))
2133 return;
2134
2135 va_start(va, message);
2136 vsnprintf(buf, sizeof(buf) - 1, message, va);
2137 va_end(va);
2138
2139 sendmessagetochannel(trojanscan_nick, cp, "%s", buf);
2140}
2141
e3448309 2142#ifdef TROJANSCAN_PEONCHANNEL
e261c2c9
CP
2143void trojanscan_peonchanmsg(char *message, ...) {
2144 char buf[513];
2145 va_list va;
2146 channel *cp;
2147
2148 if (!trojanscan_nick)
2149 return;
2150 if (!(cp = findchannel(TROJANSCAN_PEONCHANNEL)))
2151 return;
2152
2153 va_start(va, message);
2154 vsnprintf(buf, sizeof(buf) - 1, message, va);
2155 va_end(va);
2156
2157 sendmessagetochannel(trojanscan_nick, cp, "%s", buf);
2158}
e3448309 2159#endif
e261c2c9 2160
c86edd1d
Q
2161int trojanscan_minmaxrand(float min, float max) {
2162 return (int)((max-min+1)*rand()/(RAND_MAX+min))+min;
2163}
2164
2165char *trojanscan_iptostr(char *buf, int buflen, unsigned int ip) {
2166 snprintf(buf, buflen, "%d.%d.%d.%d", ip >> 24, (ip >> 16) & 255, (ip >> 8) & 255, ip & 255);
2167 return buf;
2168}
2169
2170char trojanscan_genchar(int ty) {
2171 /* hostname and realname characters*/
2172 if (!ty) {
2173 if (!(trojanscan_minmaxrand(0, 40) % 10)) {
2174 return trojanscan_minmaxrand(48, 57);
2175 } else {
2176 return trojanscan_minmaxrand(97, 122);
2177 }
2178 /* ident characters - without numbers*/
2179 } else if (ty == 1) {
2180 return trojanscan_minmaxrand(97, 122);
2181 /* ident characters - with numbers*/
2182 } else if (ty == 2) {
2183 ty = trojanscan_minmaxrand(97, 125);
2184 if (ty > 122) return trojanscan_minmaxrand(48, 57);
2185 return ty;
2186 /* nick characters - with and without numbers*/
2187 } else if (ty == 3 || ty == 4) {
2188 if (!(trojanscan_minmaxrand(0, 59) % 16)) {
2189 char weirdos[6] = { '\\', '|', '[', '{', ']', '}' };
2190 return weirdos[trojanscan_minmaxrand(0, 5)];
2191 }
2192 if (ty == 4) {
2193 ty = trojanscan_minmaxrand(65, 93);
2194 if (ty > 90) return trojanscan_minmaxrand(48, 57);
2195 } else {
2196 ty = trojanscan_minmaxrand(65, 90);
2197 }
2198 if (!(trojanscan_minmaxrand(0, 40) % 8)) return ty;
2199 return ty + 32;
2200 /* moron check */
2201 } else {
2202 return ' ';
2203 }
2204}
2205
2206void trojanscan_gennick(char *ptc, char size) {
2207 int i;
2208 for (i=0;i<size;i++) {
2209 if (i == 0) {
2210 ptc[i] = trojanscan_genchar(3);
2211 } else {
2212 ptc[i] = trojanscan_genchar(4);
2213 }
2214 }
2215 ptc[i] = '\0';
2216}
2217
2218void trojanscan_genident(char *ptc, char size) {
2219 int i;
2220 for (i=0;i<size;i++) {
2221 if (i == 0) {
2222 ptc[i] = trojanscan_genchar(1);
2223 } else {
2224 ptc[i] = trojanscan_genchar(2);
2225 }
2226 }
2227 ptc[i] = '\0';
2228}
2229
21ec3379 2230void trojanscan_genhost(char *ptc, char size, patricia_node_t **fakeipnode) {
c86edd1d 2231 int dots = trojanscan_minmaxrand(2, 5), i, dotexist = 0, cur;
21ec3379
P
2232 struct irc_in_addr ipaddress;
2233
c86edd1d
Q
2234 while (!dotexist) {
2235 for (i=0;i<size;i++) {
2236 ptc[i] = trojanscan_genchar(0);
2237 if ((i > 5) && (i < (size-4))) {
2238 if ((ptc[i-1] != '.') && (ptc[i-1] != '-')) {
2239 cur = trojanscan_minmaxrand(1,size / dots);
2240 if (cur < 3) {
2241 if (cur == 1) {
2242 ptc[i] = '.';
2243 dotexist = 1;
2244 } else {
2245 ptc[i] = '-';
2246 }
2247 }
2248 }
2249 }
2250 }
2251 }
2252 ptc[i] = '\0';
2e9a528b 2253
21ec3379 2254 memset(&ipaddress, 0, sizeof(ipaddress));
c426783d 2255 ((unsigned short *)(ipaddress.in6_16))[5] = 65535;
21ec3379
P
2256 ((unsigned short *)(ipaddress.in6_16))[6] = trojanscan_minmaxrand(0, 65535);
2257 ((unsigned short *)(ipaddress.in6_16))[7] = trojanscan_minmaxrand(0, 65535);
2258
2259 *fakeipnode = refnode(iptree, &ipaddress, PATRICIA_MAXBITS);
c86edd1d
Q
2260}
2261
2262void trojanscan_genreal(char *ptc, char size) {
2263 int spaces = trojanscan_minmaxrand(2, 4), i;
2264 for (i=0;i<size;i++) {
2265 ptc[i] = trojanscan_genchar(0);
2266 if ((i > 5) && (i < (size-4))) {
2267 if (ptc[i-1] != ' ') {
2268 if (trojanscan_minmaxrand(1,size / spaces) == 1) ptc[i] = ' ';
2269 }
2270 }
2271 }
2272 ptc[i] = '\0';
2273}
2274
2275int trojanscan_is_not_octet(char *begin, int length) {
2276 int i;
2277 if(length > 3)
2278 return 0;
2279 for(i=0;i<length;i++) {
2280 if (!((*begin >= '0') && (*begin <= '9')))
2281 return 0;
2282 begin++;
2283 }
2284 return 1;
2285}
2286
2287int trojanscan_generatepool(void) {
2288 int i, k = 0, j = 0, loops = 0;
2289 char *p, *pp;
2290 nick *np;
2291
2292 for (i=0;i<NICKHASHSIZE;i++)
2293 for (np=nicktable[i];np;np=np->next)
2294 j++;
2295
36efd3fc 2296 if(j < trojanscan_min_hosts)
c86edd1d 2297 return 0;
378cf1b9
CP
2298
2299 if(TROJANSCAN_HOST_MODE == TROJANSCAN_STEAL_HOST)
2300 return TROJANSCAN_MINPOOLSIZE;
c86edd1d
Q
2301
2302 i = 0;
2303 do {
2304 for (j=trojanscan_minmaxrand(0, NICKHASHSIZE-1);j<NICKHASHSIZE;j++) {
2305 if (nicktable[j]) {
2306 for(p=nicktable[j]->host->name->content, pp=p;*p;) {
2307 if (*++p == '.') {
2308 if (!trojanscan_is_not_octet(pp, p-pp)) {
2309 if (i < TROJANSCAN_POOLSIZE) {
2310 if (i < trojanscan_hostpoolsize)
2311 freesstring(trojanscan_hostpool[i]);
2312 trojanscan_hostpool[i] = getsstring(pp, p-pp);
2313 i++;
2314 } else {
2315 if (k >= TROJANSCAN_POOLSIZE)
2316 break;
2317 }
2318 }
2319 pp=++p;
2320 }
2321 }
2322 if (!trojanscan_is_not_octet(pp, p-pp)) {
2323 if (k < TROJANSCAN_POOLSIZE) {
2324 if (k < trojanscan_tailpoolsize)
2325 freesstring(trojanscan_tailpool[k]);
2326 trojanscan_tailpool[k] = getsstring(pp, p-pp);
2327 k++;
2328 } else {
2329 if (i >= TROJANSCAN_POOLSIZE)
2330 break;
2331 }
2332 }
2333 }
2334 }
2335 loops++;
2336 } while ((loops < 5) && ((i < TROJANSCAN_POOLSIZE) || (k < TROJANSCAN_POOLSIZE)));
2337
2338 trojanscan_hostpoolsize = i;
2339 trojanscan_tailpoolsize = k;
2340 return i;
2341}
2342
c8fdcfa5 2343nick *trojanscan_selectuser(void) {
56099b38 2344 int target = trojanscan_minmaxrand(0, 500), loops = 150, j;
c8fdcfa5
CP
2345 nick *np;
2346 do {
2347 for (j=trojanscan_minmaxrand(0, NICKHASHSIZE-1);j<NICKHASHSIZE;j++)
2348 for(np=nicktable[j];np;np=np->next)
2349 if (!--target)
2350 return np;
2351 } while(--loops > 0);
2352 return NULL;
2353}
2354
707e6470
CP
2355host *trojanscan_selecthost(void) {
2356 int target = trojanscan_minmaxrand(0, 500), loops = 150, j;
2357 host *hp;
2358 do {
2359 for (j=trojanscan_minmaxrand(0, HOSTHASHSIZE-1);j<HOSTHASHSIZE;j++)
2360 for(hp=hosttable[j];hp;hp=hp->next)
2361 if (!--target)
2362 return hp;
2363 } while(--loops > 0);
2364
2365 return NULL;
2366}
2367
21ec3379
P
2368void trojanscan_generatehost(char *buf, int maxsize, patricia_node_t **fakeip) {
2369 struct irc_in_addr ipaddress;
2370
378cf1b9 2371 if(TROJANSCAN_HOST_MODE == TROJANSCAN_STEAL_HOST) {
707e6470 2372 host *hp;
c8fdcfa5 2373 int loops = 20;
2e9a528b 2374
c8fdcfa5 2375 buf[0] = '\0';
2e9a528b 2376
378cf1b9 2377 do {
707e6470
CP
2378 hp = trojanscan_selecthost();
2379 if(hp && (hp->clonecount <= TROJANSCAN_MAX_CLONE_COUNT) && !trojanscan_isip(hp->name->content)) {
2380 strlcpy(buf, hp->name->content, maxsize + 1);
2381 if(hp->nicks) {
21ec3379
P
2382 *fakeip = hp->nicks->ipnode;
2383 patricia_ref_prefix(hp->nicks->ipnode->prefix);
707e6470 2384 } else {
21ec3379 2385 memset(&ipaddress, 0, sizeof(ipaddress));
c426783d 2386 ((unsigned short *)(ipaddress.in6_16))[5] = 65535;
21ec3379
P
2387 ((unsigned short *)(ipaddress.in6_16))[6] = trojanscan_minmaxrand(0, 65535);
2388 ((unsigned short *)(ipaddress.in6_16))[7] = trojanscan_minmaxrand(0, 65535);
2389
2390 *fakeip = refnode(iptree, &ipaddress, PATRICIA_MAXBITS);
707e6470 2391 }
c8fdcfa5 2392 break;
378cf1b9 2393 }
c8fdcfa5 2394 } while(--loops > 0);
378cf1b9
CP
2395 } else {
2396 char *cpos;
2397 int pieces = trojanscan_minmaxrand(2, 4), totallen = 0, a = 0, i;
93917ccd
CP
2398 int *choices = tmalloc(sizeof(int) * (pieces + 1));
2399 int *lengths = tmalloc(sizeof(int) * (pieces + 1));
378cf1b9
CP
2400
2401 choices[pieces] = trojanscan_minmaxrand(0, trojanscan_tailpoolsize-1);
2402 lengths[pieces] = strlen(trojanscan_tailpool[choices[pieces]]->content) + 1;
2403 totallen += lengths[pieces];
2404
2405 for (i=0;i<pieces;i++) {
2406 choices[i] = trojanscan_minmaxrand(0, trojanscan_hostpoolsize-1);
2407 lengths[i] = strlen(trojanscan_hostpool[choices[i]]->content) + 1;
2408 if (totallen+lengths[i] > maxsize) {
2409 choices[i] = choices[pieces];
2410 lengths[i] = lengths[pieces];
2411 pieces-=(pieces-i);
2412 break;
2413 }
2414 totallen += lengths[i];
2415 }
2416
2417 for (i=0;i<pieces;i++) {
2418 for (cpos=trojanscan_hostpool[choices[i]]->content; *cpos;)
2419 buf[a++] = *cpos++;
2420 buf[a++] = '.';
c86edd1d 2421 }
c86edd1d 2422
378cf1b9 2423 for (cpos=trojanscan_tailpool[choices[i]]->content; *cpos;) {
c86edd1d 2424 buf[a++] = *cpos++;
378cf1b9 2425 }
c86edd1d 2426
378cf1b9 2427 buf[a] = '\0';
93917ccd
CP
2428 tfree(choices);
2429 tfree(lengths);
2e9a528b 2430
21ec3379 2431 memset(&ipaddress, 0, sizeof(ipaddress));
c426783d 2432 ((unsigned short *)(ipaddress.in6_16))[5] = 65535;
21ec3379
P
2433 ((unsigned short *)(ipaddress.in6_16))[6] = trojanscan_minmaxrand(0, 65535);
2434 ((unsigned short *)(ipaddress.in6_16))[7] = trojanscan_minmaxrand(0, 65535);
2435
2436 *fakeip = refnode(iptree, &ipaddress, PATRICIA_MAXBITS);
c86edd1d 2437 }
c86edd1d
Q
2438}
2439
2440void trojanscan_generatenick(char *buf, int maxsize) {
56099b38 2441 int bits = trojanscan_minmaxrand(2, 3), loops = 0, wanttocopy, len = 0, i, d = 0, newmaxsize = maxsize - trojanscan_minmaxrand(0, 7);
c8fdcfa5 2442 nick *np;
56099b38
CP
2443
2444 if(newmaxsize > 2)
2445 maxsize = newmaxsize;
2446
c86edd1d 2447 do {
c8fdcfa5
CP
2448 np = trojanscan_selectuser();
2449 if(np) {
56099b38 2450 wanttocopy = trojanscan_minmaxrand(1, (strlen(np->nick) / 2) + 3);
c8fdcfa5
CP
2451 for(i=0;((i<wanttocopy) && (len<maxsize));i++)
2452 buf[len++] = np->nick[i];
2453 if(++d > bits) {
2454 buf[len] = '\0';
2455 return;
c86edd1d
Q
2456 }
2457 }
c8fdcfa5 2458 } while (++loops < 10);
c86edd1d
Q
2459 buf[0] = '\0';
2460}
2461
2462void trojanscan_generateident(char *buf, int maxsize) {
c8fdcfa5 2463 nick *np = trojanscan_selectuser();
c86edd1d 2464 buf[0] = '\0';
c8fdcfa5 2465 if(np)
707e6470 2466 strlcpy(buf, np->ident, maxsize + 1);
c86edd1d
Q
2467}
2468
2469void trojanscan_generaterealname(char *buf, int maxsize) {
c8fdcfa5 2470 nick *np = trojanscan_selectuser();
c86edd1d 2471 buf[0] = '\0';
c8fdcfa5 2472 if(np)
707e6470 2473 strlcpy(buf, np->realname->name->content, maxsize + 1);
c86edd1d
Q
2474}
2475
2476void trojanscan_database_close(void) {
2477 mysql_close(&trojanscan_sql);
2478}
2479
2480int trojanscan_database_connect(char *dbhost, char *dbuser, char *dbpass, char *db, unsigned int port) {
2481 mysql_init(&trojanscan_sql);
2482 if (!mysql_real_connect(&trojanscan_sql, dbhost, dbuser, dbpass, db, port, NULL, 0))
2483 return -1;
2484 return 0;
2485}
2486
2487void trojanscan_database_escape_string(char *dest, char *source, size_t length) {
2488 mysql_escape_string(dest, source, length);
2489}
2490
2491int trojanscan_database_query(char *format, ...) {
2492 char trojanscan_sqlquery[TROJANSCAN_QUERY_BUF_SIZE];
2493 va_list va;
2494
2495 va_start(va, format);
2496 vsnprintf(trojanscan_sqlquery, sizeof(trojanscan_sqlquery) - 1, format, va);
2497 va_end(va);
2498 return mysql_query(&trojanscan_sql, trojanscan_sqlquery);
2499}
2500
2501int trojanscan_database_num_rows(trojanscan_database_res *res) {
2502 return mysql_num_rows(res);
2503}
2504
2505trojanscan_database_res *trojanscan_database_store_result() {
2506 return mysql_store_result(&trojanscan_sql);
2507}
2508
2509trojanscan_database_row trojanscan_database_fetch_row(trojanscan_database_res *res) {
2510 return mysql_fetch_row(res);
2511}
2512
2513void trojanscan_database_free_result(trojanscan_database_res *res) {
2514 mysql_free_result(res);
2515}
2516
9bbffb1f
CP
2517int trojanscan_isip(char *host) {
2518 char *p = host, components = 0, length = 0;
2519
2520 for(;*p;p++) {
2521 if(*p == '.') {
2522 if(((!length) || (length = 0)) || (++components > 3))
2523 return 0;
2524 } else {
2525 if ((++length > 3) || !isdigit(*p))
2526 return 0;
2527 }
2528 }
2529 return components == 3;
2530}
2531