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