4 * Trojanscan copyright (C) Chris Porter 2002-2009
5 * Newserv bits copyright (C) David Mansell 2002-2003
8 * - Poke splidge about +r'ing bots, potential problems:
9 * - users might whine about T clone stealing account
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)
14 #include "trojanscan.h"
15 #include "../lib/strlfunc.h"
16 #include "../lib/version.h"
17 #include "../core/nsmalloc.h"
18 #include "../glines/glines.h"
19 #include "../patrol/patrol.h"
22 #define tmalloc(x) nsmalloc(POOL_TROJANSCAN, x)
23 #define tfree(x) nsfree(POOL_TROJANSCAN, x)
25 MODULE_VERSION(TROJANSCAN_VERSION
);
27 void trojanscan_phrasematch(channel
*chp
, nick
*sender
, trojanscan_phrases
*phrase
, char messagetype
, char *matchbuf
);
28 char *trojanscan_sanitise(char *input
);
29 void trojanscan_refresh_settings(void);
30 static void trojanscan_part_watch(int hook
, void *arg
);
31 static void trojanscan_connect_nick(void *);
33 #define TROJANSCAN_SETTING_SIZE 256
34 #define TROJANSCAN_MAX_SETTINGS 50
37 char setting
[TROJANSCAN_SETTING_SIZE
];
38 char value
[TROJANSCAN_SETTING_SIZE
];
39 } trojanscan_settings
[TROJANSCAN_MAX_SETTINGS
];
41 static int settingcount
= 0;
42 static char *versionreply
;
43 static int hooksregistered
= 0;
44 static void *trojanscan_connect_nick_schedule
;
46 static void *db_ping_schedule
;
49 trojanscan_cmds
= newcommandtree();
51 addcommandtotree(trojanscan_cmds
, "showcommands", TROJANSCAN_ACL_UNAUTHED
, 0, &trojanscan_showcommands
);
52 addcommandtotree(trojanscan_cmds
, "help", TROJANSCAN_ACL_UNAUTHED
, 1, &trojanscan_help
);
53 addcommandtotree(trojanscan_cmds
, "hello", TROJANSCAN_ACL_UNAUTHED
| TROJANSCAN_ACL_OPER
, 1, &trojanscan_hello
);
55 addcommandtotree(trojanscan_cmds
, "join", TROJANSCAN_ACL_STAFF
, 1, &trojanscan_userjoin
);
56 addcommandtotree(trojanscan_cmds
, "chanlist", TROJANSCAN_ACL_STAFF
, 0, &trojanscan_chanlist
);
57 addcommandtotree(trojanscan_cmds
, "whois", TROJANSCAN_ACL_STAFF
, 1, &trojanscan_whois
);
59 addcommandtotree(trojanscan_cmds
, "changelev", TROJANSCAN_ACL_STAFF
| TROJANSCAN_ACL_OPER
, 2, &trojanscan_changelev
);
60 addcommandtotree(trojanscan_cmds
, "deluser", TROJANSCAN_ACL_TEAMLEADER
| TROJANSCAN_ACL_OPER
, 2, &trojanscan_deluser
);
61 addcommandtotree(trojanscan_cmds
, "mew", TROJANSCAN_ACL_STAFF
, 2, &trojanscan_mew
);
62 addcommandtotree(trojanscan_cmds
, "status", TROJANSCAN_ACL_STAFF
| TROJANSCAN_ACL_OPER
, 0, &trojanscan_status
);
63 addcommandtotree(trojanscan_cmds
, "listusers", TROJANSCAN_ACL_TEAMLEADER
, 0, &trojanscan_listusers
);
65 addcommandtotree(trojanscan_cmds
, "rehash", TROJANSCAN_ACL_WEBSITE
, 0, &trojanscan_rehash
);
67 addcommandtotree(trojanscan_cmds
, "cat", TROJANSCAN_ACL_OPER
, 1, &trojanscan_cat
);
69 addcommandtotree(trojanscan_cmds
, "reschedule", TROJANSCAN_ACL_DEVELOPER
| TROJANSCAN_ACL_OPER
, 0, &trojanscan_reschedule
);
71 srand((int)time(NULL
));
73 trojanscan_connect_schedule
= scheduleoneshot(time(NULL
) + 1, &trojanscan_connect
, NULL
);
78 struct trojanscan_realchannels
*rp
= trojanscan_realchanlist
, *oldrp
;
79 struct trojanscan_rejoinlist
*rj
= trojanscan_schedulerejoins
, *oldrj
;
82 deregisterlocaluser(trojanscan_nick
, NULL
);
84 if (trojanscan_connect_schedule
)
85 deleteschedule(trojanscan_connect_schedule
, &trojanscan_connect
, NULL
);
87 if (trojanscan_connect_nick_schedule
)
88 deleteschedule(trojanscan_connect_nick_schedule
, &trojanscan_connect_nick
, NULL
);
90 if(trojanscan_schedule
)
91 deleteschedule(trojanscan_schedule
, &trojanscan_dojoin
, NULL
);
93 if(trojanscan_cloneschedule
)
94 deleteschedule(trojanscan_cloneschedule
, &trojanscan_registerclones
, NULL
);
97 deregisterhook(HOOK_CHANNEL_PART
, trojanscan_part_watch
);
100 deleteschedule(rp
->schedule
, &trojanscan_dopart
, (void *)rp
);
107 deleteschedule(rj
->schedule
, &trojanscan_rejoin_channel
, (void *)rj
);
108 freesstring(rj
->channel
);
114 if(trojanscan_initialschedule
)
115 deleteschedule(trojanscan_initialschedule
, &trojanscan_fill_channels
, NULL
);
117 deleteschedule(trojanscan_rehashschedule
, &trojanscan_rehash_schedule
, NULL
);
119 for (i
=0;i
<TROJANSCAN_CLONE_TOTAL
;i
++)
120 if(trojanscan_swarm
[i
].clone
) {
121 deregisterlocaluser(trojanscan_swarm
[i
].clone
, NULL
);
122 trojanscan_swarm
[i
].clone
= NULL
;
124 trojanscan_free_database();
125 trojanscan_free_channels();
127 trojanscan_database_close();
129 deletecommandfromtree(trojanscan_cmds
, "showcommands", &trojanscan_showcommands
);
130 deletecommandfromtree(trojanscan_cmds
, "help", &trojanscan_help
);
131 deletecommandfromtree(trojanscan_cmds
, "hello", &trojanscan_hello
);
132 deletecommandfromtree(trojanscan_cmds
, "join", &trojanscan_userjoin
);
133 deletecommandfromtree(trojanscan_cmds
, "chanlist", &trojanscan_chanlist
);
134 deletecommandfromtree(trojanscan_cmds
, "whois", &trojanscan_whois
);
135 deletecommandfromtree(trojanscan_cmds
, "changelev", &trojanscan_changelev
);
136 deletecommandfromtree(trojanscan_cmds
, "deluser", &trojanscan_deluser
);
137 deletecommandfromtree(trojanscan_cmds
, "mew", &trojanscan_mew
);
138 deletecommandfromtree(trojanscan_cmds
, "status", &trojanscan_status
);
139 deletecommandfromtree(trojanscan_cmds
, "listusers", &trojanscan_listusers
);
140 deletecommandfromtree(trojanscan_cmds
, "rehash", &trojanscan_rehash
);
141 deletecommandfromtree(trojanscan_cmds
, "cat", &trojanscan_cat
);
142 deletecommandfromtree(trojanscan_cmds
, "reschedule", &trojanscan_reschedule
);
144 destroycommandtree(trojanscan_cmds
);
145 nscheckfreeall(POOL_TROJANSCAN
);
148 static void trojanscan_connect_nick(void *arg
) {
149 sstring
*mnick
, *myident
, *myhost
, *myrealname
, *myauthname
;
152 mnick
= getcopyconfigitem("trojanscan", "nick", "T", NICKLEN
);
153 myident
= getcopyconfigitem("trojanscan", "ident", "trojanscan", NICKLEN
);
154 myhost
= getcopyconfigitem("trojanscan", "hostname", "trojanscan.quakenet.org", HOSTLEN
);
155 myrealname
= getcopyconfigitem("trojanscan", "realname", "Trojanscan v" TROJANSCAN_VERSION
, REALLEN
);
156 myauthname
= getcopyconfigitem("trojanscan", "authname", "T", ACCOUNTLEN
);
158 trojanscan_nick
= registerlocaluser(mnick
->content
, myident
->content
, myhost
->content
, myrealname
->content
, myauthname
->content
, UMODE_SERVICE
| UMODE_DEAF
|
159 UMODE_OPER
| UMODE_INV
|
161 &trojanscan_handlemessages
);
163 freesstring(myident
);
165 freesstring(myrealname
);
166 freesstring(myauthname
);
168 cp
= findchannel(TROJANSCAN_OPERCHANNEL
);
170 localcreatechannel(trojanscan_nick
, TROJANSCAN_OPERCHANNEL
);
172 if(!localjoinchannel(trojanscan_nick
, cp
))
173 localgetops(trojanscan_nick
, cp
);
176 cp
= findchannel(TROJANSCAN_CHANNEL
);
178 localcreatechannel(trojanscan_nick
, TROJANSCAN_CHANNEL
);
180 if(!localjoinchannel(trojanscan_nick
, cp
))
181 localgetops(trojanscan_nick
, cp
);
184 #ifdef TROJANSCAN_PEONCHANNEL
185 cp
= findchannel(TROJANSCAN_PEONCHANNEL
);
187 localcreatechannel(trojanscan_nick
, TROJANSCAN_PEONCHANNEL
);
189 if(!localjoinchannel(trojanscan_nick
, cp
))
190 localgetops(trojanscan_nick
, cp
);
195 void trojanscan_connect(void *arg
) {
196 sstring
*dbhost
, *dbuser
, *dbpass
, *db
, *dbport
, *temp
;
200 trojanscan_connect_schedule
= NULL
;
202 for(i
=0;i
<TROJANSCAN_CLONE_TOTAL
;i
++)
203 trojanscan_swarm
[i
].index
= i
; /* sure this could be done with pointer arithmetic... */
205 trojanscan_cloneschedule
= NULL
;
206 trojanscan_realchanlist
= NULL
;
207 trojanscan_database
.glines
= 0;
208 trojanscan_database
.detections
= 0;
210 dbhost
= getcopyconfigitem("trojanscan", "dbhost", "localhost", 100);
211 dbuser
= getcopyconfigitem("trojanscan", "dbuser", "moo", 100);
212 dbpass
= getcopyconfigitem("trojanscan", "dbpass", "changeme", 100);
213 db
= getcopyconfigitem("trojanscan", "db", "moo", 100);
215 dbport
= getcopyconfigitem("trojanscan", "dbport", "3306", 10);
217 length
= snprintf(buf
, sizeof(buf
) - 1, "%d", TROJANSCAN_DEFAULT_MAXCHANS
);
218 temp
= getcopyconfigitem("trojanscan", "maxchans", buf
, length
);
220 trojanscan_maxchans
= atoi(temp
->content
);
223 length
= snprintf(buf
, sizeof(buf
) - 1, "%d", TROJANSCAN_DEFAULT_CYCLETIME
);
224 temp
= getcopyconfigitem("trojanscan", "cycletime", buf
, length
);
226 trojanscan_cycletime
= atoi(temp
->content
);
229 length
= snprintf(buf
, sizeof(buf
) - 1, "%d", TROJANSCAN_DEFAULT_PARTTIME
);
230 temp
= getcopyconfigitem("trojanscan", "parttime", buf
, length
);
231 trojanscan_part_time
= atoi(temp
->content
);
234 length
= snprintf(buf
, sizeof(buf
) - 1, "%d", TROJANSCAN_DEFAULT_MAXUSERS
);
235 temp
= getcopyconfigitem("trojanscan", "maxusers", buf
, length
);
236 trojanscan_maxusers
= atoi(temp
->content
);
239 if ((trojanscan_cycletime
/ trojanscan_maxchans
) < 1) {
240 Error("trojanscan", ERR_FATAL
, "Cycletime / maxchans < 1, increase cycletime or decrease maxchans else cycling breaks.");
246 return; /* PPA: module failed to load */
249 length
= snprintf(buf
, sizeof(buf
) - 1, "%d", TROJANSCAN_DEFAULT_MINIMUM_CHANNEL_SIZE
);
250 temp
= getcopyconfigitem("trojanscan", "minchansize", buf
, length
);
251 trojanscan_minchansize
= atoi(temp
->content
);
254 trojanscan_connect_nick(NULL
);
256 if (trojanscan_database_connect(dbhost
->content
, dbuser
->content
, dbpass
->content
, db
->content
, atoi(dbport
->content
)) < 0) {
257 Error("trojanscan", ERR_FATAL
, "Cannot connect to database host!");
263 return; /* PPA: module failed to load */
266 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)");
267 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)");
268 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)");
269 trojanscan_database_query("CREATE TABLE channels (id INT(10) PRIMARY KEY AUTO_INCREMENT, channel VARCHAR(%d) NOT NULL, exempt BOOL DEFAULT 0)", CHANNELLEN
);
270 trojanscan_database_query("CREATE TABLE users (id INT(10) PRIMARY KEY AUTO_INCREMENT, authname VARCHAR(%d) NOT NULL, authlevel TINYINT(4) NOT NULL)", ACCOUNTLEN
);
271 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
);
272 trojanscan_database_query("CREATE TABLE settings (id INT(10) PRIMARY KEY AUTO_INCREMENT, setting VARCHAR(255) NOT NULL UNIQUE, value VARCHAR(255) NOT NULL)");
273 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)");
274 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);
276 trojanscan_database_query("DELETE FROM settings WHERE setting = 'rehash' OR setting = 'changed'");
277 trojanscan_database_query("INSERT INTO settings (setting, value) VALUES ('rehash','0')");
278 trojanscan_database_query("INSERT INTO settings (setting, value) VALUES ('changed','0')");
280 /* assumption: constants aren't supplied by someone evil */
281 trojanscan_database_query("INSERT INTO settings (setting, value) VALUES ('versionreply','" TROJANSCAN_DEFAULT_VERSION_REPLY
"')");
283 trojanscan_refresh_settings();
284 trojanscan_read_database(1);
291 trojanscan_registerclones(NULL
);
293 trojanscan_rehashschedule
= scheduleoneshot(time(NULL
) + 60, &trojanscan_rehash_schedule
, NULL
);
295 registerhook(HOOK_CHANNEL_PART
, trojanscan_part_watch
);
299 char *trojanscan_get_setting(char *setting
) {
302 for(i
=0;i
<settingcount
;i
++)
303 if(!strcmp(trojanscan_settings
[i
].setting
, setting
))
304 return trojanscan_settings
[i
].value
;
309 void trojanscan_refresh_settings(void) {
310 trojanscan_database_res
*res
;
311 trojanscan_database_row sqlrow
;
314 if(trojanscan_database_query("SELECT setting, value FROM settings"))
317 if(!(res
= trojanscan_database_store_result(&trojanscan_sql
)))
320 if (trojanscan_database_num_rows(res
) <= 0)
323 while((sqlrow
= trojanscan_database_fetch_row(res
))) {
324 strlcpy(trojanscan_settings
[i
].setting
, sqlrow
[0], TROJANSCAN_SETTING_SIZE
);
325 strlcpy(trojanscan_settings
[i
].value
, sqlrow
[1], TROJANSCAN_SETTING_SIZE
);
327 trojanscan_sanitise(trojanscan_settings
[i
].value
);
329 if(++i
== TROJANSCAN_MAX_SETTINGS
)
335 trojanscan_database_free_result(res
);
337 /* optimisation hack */
338 versionreply
= trojanscan_get_setting("versionreply");
341 void trojanscan_rehash_schedule(void *arg
) {
343 trojanscan_rehashschedule
= scheduleoneshot(time(NULL
) + 60, &trojanscan_rehash_schedule
, NULL
);
345 trojanscan_refresh_settings();
347 v
= trojanscan_get_setting("rehash");
348 if(v
&& v
[0] == '1') {
349 trojanscan_mainchanmsg("n: rehash initiated by website. . .");
350 trojanscan_read_database(0);
354 void trojanscan_free_database(void) {
356 for(i
=0;i
<trojanscan_database
.total_channels
;i
++)
357 freesstring(trojanscan_database
.channels
[i
].name
);
358 tfree(trojanscan_database
.channels
);
359 for(i
=0;i
<trojanscan_database
.total_phrases
;i
++) {
360 if (trojanscan_database
.phrases
[i
].phrase
)
361 pcre_free(trojanscan_database
.phrases
[i
].phrase
);
362 if (trojanscan_database
.phrases
[i
].hint
)
363 pcre_free(trojanscan_database
.phrases
[i
].hint
);
365 tfree(trojanscan_database
.phrases
);
366 for(i
=0;i
<trojanscan_database
.total_worms
;i
++)
367 freesstring(trojanscan_database
.worms
[i
].name
);
368 tfree(trojanscan_database
.worms
);
369 trojanscan_database
.total_channels
= 0;
370 trojanscan_database
.total_phrases
= 0;
371 trojanscan_database
.total_worms
= 0;
372 trojanscan_database
.channels
= NULL
;
373 trojanscan_database
.phrases
= NULL
;
374 trojanscan_database
.worms
= NULL
;
377 char *trojanscan_sanitise(char *input
) {
381 if(*p
== '\r' || *p
== '\n')
387 sstring
*trojanscan_getsstring(char *string
, int length
) {
390 for(i
=0;i
<length
;i
++) {
391 if ((string
[i
] == '\r') || (string
[i
] == '\n')) {
392 Error("trojanscan", ERR_WARNING
, "Error reading %s at position %d, set to ERROR!", string
, i
+1);
393 return getsstring("ERROR", sizeof("ERROR"));
397 return getsstring(string
, length
);
400 int trojanscan_strip_codes(char *buf
, size_t max
, char *original
) {
401 int i
, j
, length
= TROJANSCAN_MMIN(strlen(original
), max
-1);
402 char *p2
= original
, *p3
, flag
= 0;
404 for(i
=0;i
<length
+1;i
++) {
413 if ((i
+ 1) > length
)
415 if ((j
== 4) && flag
)
419 if ((j
== 0) && (!((*p2
>= '0') && (*p2
<= '9'))))
424 if ((i
+ 1) > length
)
426 if (!((*(p2
+ 1) >= '0') && (*(p2
+ 1) <= '9')))
429 } else if ((*p2
>= '0') && (*p2
<= '9')) {
437 if (!((*p2
>= '0') && (*p2
<= '9')))
443 if ((i
+ 1) > length
)
445 if (!((*(p2
+ 1) >= '0') && (*(p2
+ 1) <= '9')))
450 if ((j
== 3) && (!((*p2
>= '0') && (*p2
<= '9'))))
452 if ((j
== 4) && (!((*p2
>= '0') && (*p2
<= '9'))))
469 struct trojanscan_worms
*trojanscan_find_worm_by_id(int id
) {
471 for(i
=0;i
<trojanscan_database
.total_worms
;i
++)
472 if (trojanscan_database
.worms
[i
].id
== id
)
473 return &trojanscan_database
.worms
[i
];
477 void trojanscan_read_database(int first_time
) {
479 int erroroffset
, i
, tempresult
;
481 trojanscan_database_res
*res
;
482 trojanscan_database_row sqlrow
;
485 trojanscan_free_database();
487 trojanscan_database
.total_channels
= 0;
488 trojanscan_database
.total_phrases
= 0;
489 trojanscan_database
.total_worms
= 0;
492 if (!(trojanscan_database_query("SELECT channel, exempt FROM channels"))) {
493 if ((res
= trojanscan_database_store_result(&trojanscan_sql
))) {
494 trojanscan_database
.total_channels
= trojanscan_database_num_rows(res
);
495 if (trojanscan_database
.total_channels
> 0) {
496 if ((trojanscan_database
.channels
= (trojanscan_channels
*)tmalloc(sizeof(trojanscan_channels
) * trojanscan_database
.total_channels
))) {
497 if ((trojanscan_database
.total_channels
>0) && trojanscan_database
.channels
) {
499 while((sqlrow
= trojanscan_database_fetch_row(res
))) {
500 trojanscan_database
.channels
[i
].name
= trojanscan_getsstring(trojanscan_sanitise(sqlrow
[0]), strlen(sqlrow
[0]));
501 trojanscan_database
.channels
[i
].exempt
= (sqlrow
[1][0] == '1');
507 trojanscan_database_free_result(res
);
511 if (!(trojanscan_database_query("SELECT id, wormname, glinetype, length(data), hitmsgs, hitchans, epidemic FROM worms"))) {
512 if ((res
= trojanscan_database_store_result(&trojanscan_sql
))) {
513 trojanscan_database
.total_worms
= trojanscan_database_num_rows(res
);
514 if (trojanscan_database
.total_worms
> 0) {
515 if ((trojanscan_database
.worms
= (trojanscan_worms
*)tmalloc(sizeof(trojanscan_worms
) * trojanscan_database
.total_worms
))) {
517 while((sqlrow
= trojanscan_database_fetch_row(res
))) {
518 trojanscan_database
.worms
[i
].id
= atoi(sqlrow
[0]);
519 trojanscan_database
.worms
[i
].name
= trojanscan_getsstring(trojanscan_sanitise(sqlrow
[1]), strlen(sqlrow
[1]));
520 tempresult
= atoi(sqlrow
[2]);
521 trojanscan_database
.worms
[i
].glineuser
= (tempresult
== 0);
522 trojanscan_database
.worms
[i
].glinehost
= (tempresult
== 1);
523 trojanscan_database
.worms
[i
].monitor
= (tempresult
== 2);
525 trojanscan_database
.worms
[i
].datalen
= ((atoi(sqlrow
[3]) == 0) ? 0 : 1);
527 trojanscan_database
.worms
[i
].datalen
= 0;
530 trojanscan_database
.worms
[i
].hitpriv
= (atoi(sqlrow
[4]) == 1);
531 trojanscan_database
.worms
[i
].hitchans
= (atoi(sqlrow
[5]) == 1);
532 trojanscan_database
.worms
[i
].epidemic
= (atoi(sqlrow
[6]) == 1);
538 trojanscan_database_free_result(res
);
542 if (!(trojanscan_database_query("SELECT id, phrase, wormid FROM phrases WHERE disabled = 0 ORDER BY priority DESC"))) {
543 if ((res
= trojanscan_database_store_result(&trojanscan_sql
))) {
544 trojanscan_database
.total_phrases
= trojanscan_database_num_rows(res
);
545 if (trojanscan_database
.total_phrases
> 0) {
546 if ((trojanscan_database
.phrases
= (trojanscan_phrases
*)tmalloc(sizeof(trojanscan_phrases
) * trojanscan_database
.total_phrases
))) {
548 while((sqlrow
= trojanscan_database_fetch_row(res
))) {
549 trojanscan_database
.phrases
[i
].id
= atoi(sqlrow
[0]);
550 trojanscan_database
.phrases
[i
].worm
= trojanscan_find_worm_by_id(atoi(sqlrow
[2]));
551 if (!(trojanscan_database
.phrases
[i
].phrase
= pcre_compile(sqlrow
[1], PCRE_CASELESS
, &error
, &erroroffset
, NULL
))) {
552 Error("trojanscan", ERR_WARNING
, "Error compiling expression %s at offset %d: %s", sqlrow
[1], erroroffset
, error
);
554 trojanscan_database
.phrases
[i
].hint
= pcre_study(trojanscan_database
.phrases
[i
].phrase
, 0, &error
);
556 Error("trojanscan", ERR_WARNING
, "Error studying expression %s: %s", sqlrow
[1], error
);
557 pcre_free(trojanscan_database
.phrases
[i
].phrase
);
558 trojanscan_database
.phrases
[i
].phrase
= NULL
;
565 trojanscan_database_free_result(res
);
569 trojanscan_database_query("UPDATE settings SET value = '0' where setting = 'rehash'");
572 void trojanscan_log(nick
*np
, char *event
, char *details
, ...) {
574 char eevent
[TROJANSCAN_QUERY_TEMP_BUF_SIZE
], edetails
[TROJANSCAN_QUERY_TEMP_BUF_SIZE
], buf
[513];
577 va_start(va
, details
);
578 vsnprintf(buf
, sizeof(buf
) - 1, details
, va
);
583 nickid
= trojanscan_user_id_by_authname(np
->authname
);
585 trojanscan_database_escape_string(eevent
, event
, strlen(event
));
586 trojanscan_database_escape_string(edetails
, buf
, strlen(buf
));
587 trojanscan_database_query("INSERT INTO logs (userid, act, description) VALUES ('%d', '%s', '%s')", nickid
, eevent
, edetails
);
590 void trojanscan_generateclone(void *arg
) {
593 i
= (int)((long)arg
);
595 trojanscan_swarm
[i
].clone
= patrol_generateclone(0, &trojanscan_clonehandlemessages
);
597 if(trojanscan_swarm
[i
].clone
&& !trojanscan_swarm_created
) {
598 nick
*np
= trojanscan_selectuser();
599 if(np
) /* select a 'random' sign on time for whois generation */
600 trojanscan_swarm
[i
].clone
->timestamp
= np
->timestamp
;
602 trojanscan_swarm
[i
].remaining
= trojanscan_minmaxrand(5, 100);
604 trojanscan_swarm
[i
].sitting
= 0;
608 void trojanscan_free_channels(void) {
610 if(trojanscan_chans
) {
611 for(i
=0;i
<trojanscan_activechans
;i
++)
612 freesstring(trojanscan_chans
[i
].channel
);
613 tfree(trojanscan_chans
);
614 trojanscan_chans
= NULL
;
615 trojanscan_activechans
= 0;
619 void trojanscan_registerclones(void *arg
) {
622 if (!patrol_repool()) {
623 trojanscan_cloneschedule
= scheduleoneshot(time(NULL
) + 10, &trojanscan_registerclones
, NULL
);
627 trojanscan_cloneschedule
= NULL
;
629 for (i
=0;i
<TROJANSCAN_CLONE_TOTAL
;i
++)
630 trojanscan_generateclone((void *)((long)i
));
631 trojanscan_mainchanmsg("n: swarm (%d clones) created.", TROJANSCAN_CLONE_TOTAL
);
632 trojanscan_swarm_created
= 1;
634 trojanscan_initialschedule
= scheduleoneshot(time(NULL
) + 60, &trojanscan_fill_channels
, NULL
);
637 int trojanscan_status(void *sender
, int cargc
, char **cargv
) {
638 nick
*np
= (nick
*)sender
;
639 trojanscan_log(np
, "status", "");
640 trojanscan_reply(np
, "Channels in schedule: %d", trojanscan_activechans
);
641 trojanscan_reply(np
, "Channels in database: %d", trojanscan_database
.total_channels
);
642 trojanscan_reply(np
, "Phrases: %d", trojanscan_database
.total_phrases
);
643 trojanscan_reply(np
, "Worms: %d", trojanscan_database
.total_worms
);
644 trojanscan_reply(np
, "Detections: %d", trojanscan_database
.detections
);
645 trojanscan_reply(np
, "Glines: %d", trojanscan_database
.glines
);
646 trojanscan_reply(np
, "Cycletime: %d", trojanscan_cycletime
);
647 trojanscan_reply(np
, "Clones: %d", TROJANSCAN_CLONE_TOTAL
);
651 int trojanscan_chanlist(void *sender
, int cargc
, char **cargv
) {
653 nick
*np
= (nick
*)sender
;
654 char buf
[CHANNELLEN
* 2 + 20];
655 trojanscan_reply(np
, "Channel list (%d total):", trojanscan_activechans
);
658 for(i
=0;i
<trojanscan_activechans
;i
++) {
659 if(trojanscan_chans
[i
].channel
->length
+ 3 > sizeof(buf
) - strlen(buf
)) {
660 trojanscan_reply(np
, "%s", buf
);
664 /* if splidge sees this I'm going to die */
665 strlcat(buf
, trojanscan_chans
[i
].channel
->content
, sizeof(buf
));
666 strlcat(buf
, " ", sizeof(buf
));
669 trojanscan_reply(np
, "%s", buf
);
671 trojanscan_reply(np
, "Done.");
675 int trojanscan_whois(void *sender
, int cargc
, char **cargv
) {
677 nick
*np
= (nick
*)sender
, *np2
;
681 trojanscan_reply(np
, "Not enough parameters.");
685 if (cargv
[0][0] == '#') {
686 tochange
= cargv
[0] + 1;
689 np2
= getnickbynick(cargv
[0]);
691 trojanscan_reply(np
, "That nickname is not on the network.");
694 for(i
=0;i
<TROJANSCAN_CLONE_TOTAL
;i
++) {
695 if(trojanscan_swarm
[i
].clone
->nick
&& !ircd_strcmp(trojanscan_swarm
[i
].clone
->nick
, np2
->nick
)) {
696 trojanscan_reply(np
, "Nickname : %s", np2
->nick
);
697 trojanscan_reply(np
, "Swarm : yes");
701 if (!IsAccount(np2
)) {
702 trojanscan_reply(np
, "User is not authed.");
705 tochange
= np2
->authname
;
708 templevel
= trojanscan_user_level_by_authname(tochange
);
709 if (templevel
== -1) {
710 trojanscan_reply(np
, "User does not exist.");
712 union trojanscan_userlevel flags
;
713 flags
.number
= templevel
;
714 trojanscan_reply(np
, "Authname : %s", tochange
);
715 trojanscan_reply(np
, "Flags : +" TROJANSCAN_FLAG_MASK
, TrojanscanFlagsInfo(flags
));
721 void trojanscan_privmsg_chan_or_nick(channel
*cp
, nick
*np
, char *message
, ...) {
725 if (!trojanscan_nick
)
728 va_start(va
, message
);
729 vsnprintf(buf
, sizeof(buf
) - 1, message
, va
);
733 sendmessagetochannel(trojanscan_nick
, cp
, "%s", buf
);
735 sendmessagetouser(trojanscan_nick
, np
, "%s", buf
);
740 int trojanscan_mew(void *sender
, int cargc
, char **cargv
) {
741 nick
*np
= (nick
*)sender
, *np2
= NULL
;
745 trojanscan_reply(np
, "Not enough paramaters.");
749 if(cargv
[0][0] == '#') {
750 if (!(cp
= findchannel(cargv
[0]))) {
751 trojanscan_reply(np
, "Channel not found.");
754 trojanscan_log(np
, "mew", "%s %s", cp
->index
->name
->content
, cargv
[1]);
756 if (!(np2
= getnickbynick(cargv
[0]))) {
757 trojanscan_reply(np
, "Nickname is not present on the network.");
760 trojanscan_log(np
, "mew", "%s %s", np2
->nick
, cargv
[1]);
763 trojanscan_privmsg_chan_or_nick(cp
, np2
, "\001ACTION mews hopefully at %s\001", cargv
[1]);
766 trojanscan_reply(np
, "Mewed at %s in %s.", cargv
[1], cp
->index
->name
->content
);
768 trojanscan_reply(np
, "Mewed at %s at %s.", cargv
[1], np2
->nick
);
772 trojanscan_mainchanmsg("n: mew: %s %s (%s/%s)", cargv
[1], cp
?cp
->index
->name
->content
:np2
->nick
, np
->nick
, np
->authname
);
777 int trojanscan_cat(void *sender
, int cargc
, char **cargv
) {
778 nick
*np
= (nick
*)sender
, *np2
= NULL
;
784 trojanscan_reply(np
, "Not enough paramaters.");
788 if(cargv
[0][0] == '#') {
789 if (!(cp
= findchannel(cargv
[0]))) {
790 trojanscan_reply(np
, "Channel not found.");
793 trojanscan_log(np
, "cat", cp
->index
->name
->content
);
795 if (!(np2
= getnickbynick(cargv
[0]))) {
796 trojanscan_reply(np
, "Nickname is not present on the network.");
799 trojanscan_log(np
, "cat", np2
->nick
);
802 if ((!(cat
= fopen(TROJANSCAN_CAT
, "r")))) {
803 trojanscan_reply(np
, "Unable to open cat!");
807 while (fgets(buf
, sizeof(buf
) - 1, cat
)) {
808 if ((p
= strchr(buf
, '\n'))) {
810 trojanscan_privmsg_chan_or_nick(cp
, np2
, "%s", buf
);
811 } else if (feof(cat
)) {
812 trojanscan_privmsg_chan_or_nick(cp
, np2
, "%s", buf
);
819 trojanscan_reply(np
, "Spammed cat in %s.", cp
->index
->name
->content
);
821 trojanscan_reply(np
, "Spammed cat at %s.", np2
->nick
);
827 int trojanscan_reschedule(void *sender
, int cargc
, char **cargv
) {
828 nick
*np
= (nick
*)sender
;
829 trojanscan_log(np
, "reschedule", "");
830 trojanscan_fill_channels(NULL
);
832 trojanscan_reply(np
, "Rescheduled.");
836 int trojanscan_listusers(void *sender
, int cargc
, char **cargv
) {
837 nick
*np
= (nick
*)sender
;
839 trojanscan_log(np
, "listusers", "");
841 trojanscan_reply(np
, "User list:");
843 if (!(trojanscan_database_query("SELECT authname, authlevel FROM users ORDER BY authlevel DESC, authname"))) {
844 trojanscan_database_res
*res
;
845 if ((res
= trojanscan_database_store_result(&trojanscan_sql
))) {
846 if (trojanscan_database_num_rows(res
)) {
847 trojanscan_database_row sqlrow
;
848 union trojanscan_userlevel flags
;
849 while((sqlrow
= trojanscan_database_fetch_row(res
))) {
850 flags
.number
= atoi(sqlrow
[1]);
851 trojanscan_reply(np
, "%s +" TROJANSCAN_FLAG_MASK
, sqlrow
[0], TrojanscanIsDeveloper(flags
) ? "d" : "", TrojanscanIsTeamLeader(flags
) ? "t" : "", TrojanscanIsStaff(flags
) ? "s" : "", TrojanscanIsWebsite(flags
) ? "w" : "", TrojanscanIsCat(flags
) ? "c" : "");
854 trojanscan_database_free_result(res
);
858 trojanscan_reply(np
, "Done.");
862 int trojanscan_help(void *sender
, int cargc
, char **cargv
) {
863 nick
*np
= (nick
*)sender
;
866 trojanscan_reply(np
, "Not enough parameters.");
870 if (!strcasecmp("help", cargv
[0])) {
871 trojanscan_reply(np
, "Syntax: help <command name>");
872 trojanscan_reply(np
, "Gives help on commands.");
873 } else if (!strcasecmp("status", cargv
[0])) {
874 trojanscan_reply(np
, "Syntax: status");
875 trojanscan_reply(np
, "Gives statistical information about the bot.");
876 } else if (!strcasecmp("join", cargv
[0])) {
877 trojanscan_reply(np
, "Syntax: join <#channel>");
878 trojanscan_reply(np
, "Orders a clone to join supplied channel.");
879 } else if (!strcasecmp("showcommands", cargv
[0])) {
880 trojanscan_reply(np
, "Syntax: showcommands");
881 trojanscan_reply(np
, "Pretty obvious.");
882 } else if (!strcasecmp("hello", cargv
[0])) {
883 trojanscan_reply(np
, "Syntax: hello ?nickname?");
884 trojanscan_reply(np
, "Creates a new user.");
885 } else if (!strcasecmp("rehash", cargv
[0])) {
886 trojanscan_reply(np
, "Syntax: rehash");
887 trojanscan_reply(np
, "Reloads bot database.");
888 } else if (!strcasecmp("changelev", cargv
[0])) {
889 trojanscan_reply(np
, "Syntax: changelev <nickname or #authname> <flags>");
890 trojanscan_reply(np
, "Changes access flags of selected user to supplied input.");
891 trojanscan_reply(np
, "+d -> developer");
892 trojanscan_reply(np
, "+t -> team leader");
893 trojanscan_reply(np
, "+s -> staff");
894 trojanscan_reply(np
, "+w -> web management");
895 trojanscan_reply(np
, "+c -> cat access");
896 } else if (!strcasecmp("deluser", cargv
[0])) {
897 trojanscan_reply(np
, "Syntax: deluser <nickname or #authname>");
898 trojanscan_reply(np
, "Deletes selected user from my database.");
899 } else if (!strcasecmp("mew", cargv
[0])) {
900 trojanscan_reply(np
, "Syntax: mew <#channel or nickname> <nickname>");
901 trojanscan_reply(np
, "Gracefully mews at target in selected channel or query.");
902 } else if (!strcasecmp("cat", cargv
[0])) {
903 trojanscan_reply(np
, "Syntax: cat <#channel or nickname>");
904 trojanscan_reply(np
, "Shows the almightly cat.");
905 } else if (!strcasecmp("reschedule", cargv
[0])) {
906 trojanscan_reply(np
, "Syntax: reschedule");
907 trojanscan_reply(np
, "Recalculates bots schedule.");
908 } else if (!strcasecmp("chanlist", cargv
[0])) {
909 trojanscan_reply(np
, "Syntax: chanlist");
910 trojanscan_reply(np
, "Displays bots current channel list.");
911 } else if (!strcasecmp("whois", cargv
[0])) {
912 trojanscan_reply(np
, "Syntax: whois <nickname or #authname>");
913 trojanscan_reply(np
, "Displays information on given user.");
914 } else if (!strcasecmp("whois", cargv
[0])) {
915 trojanscan_reply(np
, "Syntax: listusers <flags>");
916 trojanscan_reply(np
, "Displays users with listusersing flags.");
918 trojanscan_reply(np
, "Command not found.");
925 int trojanscan_hello(void *sender
, int cargc
, char **cargv
) {
926 nick
*np
= (nick
*)sender
, *toadd
;
927 char eaccount
[TROJANSCAN_QUERY_TEMP_BUF_SIZE
];
931 toadd
= getnickbynick(cargv
[0]);
933 trojanscan_reply(np
, "That nickname is not on the network.");
936 if (!IsAccount(toadd
)) {
937 trojanscan_reply(np
, "That user is not authed with the network.");
941 if (!IsAccount(np
)) {
942 trojanscan_reply(np
, "You are not authed with the network, auth before creating your user.");
948 if (trojanscan_user_level_by_authname(toadd
->authname
)!=-1) {
949 trojanscan_reply(np
, "Authname (%s) is already on file.", toadd
->authname
);
953 trojanscan_log(np
, "hello", toadd
->authname
);
955 if (!(trojanscan_database_query("SELECT id FROM users LIMIT 1"))) {
956 trojanscan_database_res
*res
;
957 if ((res
= trojanscan_database_store_result(&trojanscan_sql
))) {
958 if (trojanscan_database_num_rows(res
) == 0)
959 level
= TROJANSCAN_ACL_DEVELOPER
| TROJANSCAN_ACL_STAFF
| TROJANSCAN_ACL_WEBSITE
| TROJANSCAN_ACL_CAT
;
960 trojanscan_database_free_result(res
);
964 trojanscan_database_escape_string(eaccount
, toadd
->authname
, strlen(toadd
->authname
));
965 trojanscan_database_query("INSERT INTO users (authname, authlevel) VALUES ('%s', %d)", eaccount
, level
);
966 trojanscan_reply(np
, "Account added to database, account %s%s.", toadd
->authname
, level
>0?" (first user so developer access)":"");
971 int trojanscan_user_level_by_authname(char *authname
) {
972 int result
= -1, sl
= strlen(authname
);
973 char eaccount
[TROJANSCAN_QUERY_TEMP_BUF_SIZE
];
975 trojanscan_database_escape_string(eaccount
, authname
, sl
);
976 if (!(trojanscan_database_query("SELECT authlevel, authname FROM users WHERE authname = '%s'", eaccount
))) {
977 trojanscan_database_res
*res
;
978 if ((res
= trojanscan_database_store_result(&trojanscan_sql
))) {
979 if (trojanscan_database_num_rows(res
) > 0) {
980 trojanscan_database_row sqlrow
= trojanscan_database_fetch_row(res
);
981 result
= atoi(sqlrow
[0]);
982 strlcpy(authname
, sqlrow
[1], sl
+ 1);
984 trojanscan_database_free_result(res
);
990 int trojanscan_user_id_by_authname(char *authname
) {
992 char eaccount
[TROJANSCAN_QUERY_TEMP_BUF_SIZE
];
994 trojanscan_database_escape_string(eaccount
, authname
, strlen(authname
));
995 if (!(trojanscan_database_query("SELECT id FROM users WHERE authname = '%s'", eaccount
))) {
996 trojanscan_database_res
*res
;
997 if ((res
= trojanscan_database_store_result(&trojanscan_sql
))) {
998 if (trojanscan_database_num_rows(res
) > 0) {
999 trojanscan_database_row sqlrow
= trojanscan_database_fetch_row(res
);
1000 result
= atoi(sqlrow
[0]);
1002 trojanscan_database_free_result(res
);
1008 struct trojanscan_clones
*trojanscan_selectclone(char type
) {
1009 struct trojanscan_clones
*rc
;
1010 int randomclone
, hits
= 0, minlimit
, maxlimit
;
1012 if(type
== TROJANSCAN_WATCH_CLONES
) {
1013 minlimit
= TROJANSCAN_CLONE_MAX
;
1014 maxlimit
= minlimit
+ TROJANSCAN_WATCHCLONE_MAX
- 1;
1017 maxlimit
= TROJANSCAN_CLONE_MAX
- 1;
1021 randomclone
= trojanscan_minmaxrand(minlimit
, maxlimit
);
1024 rc
= &trojanscan_swarm
[randomclone
];
1025 if ((type
== TROJANSCAN_NORMAL_CLONES
) && (rc
->sitting
== 0) && (rc
->remaining
== 0))
1028 } while (rc
->remaining
== 0);
1030 if(type
== TROJANSCAN_NORMAL_CLONES
) {
1031 if ((rc
->sitting
== 0) && (rc
->remaining
== 0)) {
1032 if ((!rc
->remaining
) && (!rc
->sitting
)) {
1034 deregisterlocaluser(rc
->clone
, NULL
);
1037 trojanscan_generateclone((void *)((long)rc
->index
));
1046 struct trojanscan_realchannels
*trojanscan_allocaterc(char *chan
) {
1047 struct trojanscan_realchannels
*rc
;
1048 struct trojanscan_clones
*clonep
;
1050 int attempts_left
= 10;
1053 trojanscan_errorcode
= 1; /* sorry splidge ;( */
1057 if(chan
[0] != '#') {
1058 trojanscan_errorcode
= 2;
1062 if (strlen(chan
) > 1) {
1063 if(strrchr(chan
, ',')) {
1064 trojanscan_errorcode
= 3;
1068 if(strrchr(chan
, ' ')) {
1069 trojanscan_errorcode
= 4;
1074 cp
= findchannel(chan
);
1076 trojanscan_errorcode
= 5;
1081 clonep
= trojanscan_selectclone(TROJANSCAN_NORMAL_CLONES
);
1083 trojanscan_errorcode
= 6;
1086 if(!nickbanned(clonep
->clone
, cp
, 0))
1088 } while (--attempts_left
> 0);
1090 if (!attempts_left
) {
1091 trojanscan_errorcode
= 7;
1095 rc
= (struct trojanscan_realchannels
*)tmalloc(sizeof(struct trojanscan_realchannels
));
1105 void trojanscan_join(struct trojanscan_realchannels
*rc
) {
1106 struct trojanscan_realchannels
*rp
= trojanscan_realchanlist
;
1108 if (rc
->clone
&& rc
->clone
->clone
) {
1109 if (!localjoinchannel(rc
->clone
->clone
, rc
->chan
)) {
1110 rc
->clone
->remaining
--;
1111 rc
->clone
->sitting
++;
1112 if (trojanscan_minmaxrand(1, TROJANSCAN_NICKCHANGE_ODDS
)%TROJANSCAN_NICKCHANGE_ODDS
== 0)
1113 trojanscan_donickchange((void *)rc
->clone
);
1115 rc
->schedule
= scheduleoneshot(time(NULL
)+trojanscan_part_time
, &trojanscan_dopart
, (void *)rc
);
1118 for(;rp
->next
;rp
=rp
->next
);
1121 trojanscan_realchanlist
= rc
;
1128 int trojanscan_userjoin(void *sender
, int cargc
, char **cargv
) {
1129 nick
*np
= (nick
*)sender
;
1130 struct trojanscan_realchannels
*rc
;
1133 trojanscan_reply(np
, "Not enough paramaters");
1137 if (!trojanscan_swarm_created
) {
1138 trojanscan_reply(np
, "My swarm is currently empty.");
1142 if((rc
= trojanscan_allocaterc(cargv
[0]))) {
1143 trojanscan_log(np
, "join", cargv
[0]);
1144 trojanscan_join(rc
);
1145 trojanscan_reply(np
, "Clone has joined channel.");
1147 trojanscan_mainchanmsg("n: join: %s (%s/%s)", cargv
[0], np
->nick
, np
->authname
);
1149 if (trojanscan_errorcode
== 5) {
1150 trojanscan_reply(np
, "Not joining empty channel, check you entered the correct channel name.");
1152 trojanscan_reply(np
, "Clone could not join channel (error code %d)!", trojanscan_errorcode
);
1158 int trojanscan_rehash(void *sender
, int cargc
, char **cargv
) {
1159 nick
*np
= (void *)sender
;
1160 trojanscan_refresh_settings();
1161 trojanscan_read_database(0);
1162 trojanscan_log(np
, "rehash", "");
1163 trojanscan_reply(np
, "Done.");
1167 int trojanscan_changelev(void *sender
, int cargc
, char **cargv
) {
1168 nick
*np
= (nick
*)sender
, *np2
;
1170 char eaccount
[TROJANSCAN_QUERY_TEMP_BUF_SIZE
], *tochange
, *p
, mode
= 1, error
= 0, clast
= 0, specialcase
;
1171 union trojanscan_userlevel flags1
, flags2
;
1174 trojanscan_reply(np
, "Not enough parameters.");
1178 templevel
= trojanscan_user_level_by_authname(np
->authname
);
1180 if (templevel
== -1) {
1181 trojanscan_reply(np
, "You do not have an account.");
1185 flags1
.number
= templevel
;
1187 if (cargv
[0][0] == '#') {
1188 tochange
= cargv
[0] + 1;
1190 np2
= getnickbynick(cargv
[0]);
1192 trojanscan_reply(np
, "That nickname is not on the network.");
1195 if (!IsAccount(np2
)) {
1196 trojanscan_reply(np
, "That user is not authed with the network.");
1199 tochange
= np2
->authname
;
1202 templevel
= trojanscan_user_level_by_authname(tochange
);
1204 if (templevel
== -1) {
1205 trojanscan_reply(np
, "User does not exist.");
1209 flags2
.number
= templevel
;
1211 if (!ircd_strcmp(np
->authname
, tochange
)) {
1217 for (p
=cargv
[1];*p
;p
++) {
1224 if (!TrojanscanIsDeveloper(flags1
))
1226 flags2
.values
.developer
= mode
;
1229 if (!TrojanscanIsDeveloper(flags1
))
1231 flags2
.values
.teamleader
= mode
;
1234 if (!TrojanscanIsLeastTeamLeader(flags1
))
1236 flags2
.values
.staff
= mode
;
1239 if (!TrojanscanIsDeveloper(flags1
))
1241 flags2
.values
.website
= mode
;
1244 if (!TrojanscanIsDeveloper(flags1
))
1246 flags2
.values
.cat
= mode
;
1254 if (specialcase
&& !mode
) { /* allow user to remove their own flags */
1265 trojanscan_reply(np
, "Unknown mode: %c%c.", mode
?'+':'-', *p
);
1267 trojanscan_reply(np
, "You have insufficient privilidges to add/remove one or more flags specified.");
1272 trojanscan_log(np
, "changelev", "%s %s", tochange
, cargv
[1]);
1273 trojanscan_database_escape_string(eaccount
, tochange
, strlen(tochange
));
1274 trojanscan_database_query("UPDATE users SET authlevel = %d WHERE authname = '%s'", flags2
.number
, eaccount
);
1276 trojanscan_reply(np
, "Flags changed.");
1281 int trojanscan_deluser(void *sender
, int cargc
, char **cargv
) {
1282 nick
*np
= (nick
*)sender
, *to
;
1284 char eaccount
[TROJANSCAN_QUERY_TEMP_BUF_SIZE
], *account
;
1285 union trojanscan_userlevel flags1
, flags2
;
1288 trojanscan_reply(np
, "Not enough parameters.");
1292 if (cargv
[0][0] == '#') {
1293 account
= cargv
[0] + 1;
1295 to
= getnickbynick(cargv
[0]);
1297 trojanscan_reply(np
, "That nickname is not on the network.");
1300 if (!IsAccount(to
)) {
1301 trojanscan_reply(np
, "That user is not authed with the network.");
1304 account
= to
->authname
;
1307 flags1
.number
= trojanscan_user_level_by_authname(np
->authname
);
1308 templevel
= trojanscan_user_level_by_authname(account
);
1310 if (templevel
== -1) {
1311 trojanscan_reply(np
, "Auth %s does not exist.", account
);
1315 flags2
.number
= templevel
;
1317 if (!TrojanscanIsDeveloper(flags1
) && TrojanscanIsLeastTeamLeader(flags2
)) {
1318 trojanscan_reply(np
, "Your cannot delete %s as his/her flags equal or surpass your own.", account
);
1322 trojanscan_log(np
, "deluser", account
);
1323 trojanscan_database_escape_string(eaccount
, account
, strlen(account
));
1324 trojanscan_database_query("DELETE FROM users WHERE authname = '%s'", eaccount
);
1325 trojanscan_reply(np
, "User deleted.");
1330 int trojanscan_add_ll(struct trojanscan_prechannels
**head
, struct trojanscan_prechannels
*newitem
) {
1331 struct trojanscan_prechannels
*position
, *lastitem
= NULL
, *location
= NULL
;
1334 newitem
->next
= NULL
;
1335 if (newitem
->exempt
) {
1341 /* if its exempt, we don't give a monkeys where it is... */
1342 if (newitem
->exempt
) {
1343 newitem
->next
= *head
;
1348 for(position
=*head
;position
;lastitem
=position
,position
=position
->next
) {
1349 if (!ircd_strcmp(position
->name
->content
, newitem
->name
->content
)) {
1353 if (!location
&& (position
->size
< newitem
->size
)) {
1357 location
= lastitem
;
1362 newitem
->next
= NULL
;
1363 lastitem
->next
= newitem
;
1365 newitem
->next
= location
->next
;
1366 location
->next
= newitem
;
1368 if(newitem
->exempt
) {
1375 void trojanscan_watch_clone_update(struct trojanscan_prechannels
*hp
, int count
) {
1377 struct trojanscan_prechannels
*lp
;
1378 struct trojanscan_templist
*markedlist
= NULL
;
1381 markedlist
= (struct trojanscan_templist
*)tmalloc(count
* sizeof(struct trojanscan_templist
));
1384 memset(markedlist
, 0, sizeof(struct trojanscan_templist
) * count
);
1387 for(i
=0;i
<trojanscan_activechans
;i
++) {
1390 for(lp
=hp
,j
=0;j
<count
&&lp
;j
++,lp
=lp
->next
) {
1391 if(!markedlist
[j
].active
&& !lp
->exempt
&& !ircd_strcmp(lp
->name
->content
, trojanscan_chans
[i
].channel
->content
)) { /* we're already on the channel */
1392 if(trojanscan_chans
[i
].watch_clone
) {
1393 markedlist
[j
].active
= 1;
1394 markedlist
[j
].watch_clone
= trojanscan_chans
[i
].watch_clone
;
1395 lp
->watch_clone
= trojanscan_chans
[i
].watch_clone
;
1402 if(!marked
&& trojanscan_chans
[i
].watch_clone
) {
1403 channel
*cp
= findchannel(trojanscan_chans
[i
].channel
->content
);
1405 localpartchannel(trojanscan_chans
[i
].watch_clone
->clone
, cp
, NULL
);
1412 for(j
=0,lp
=hp
;j
<count
&&lp
;j
++,lp
=lp
->next
) {
1413 if((!markedlist
[j
].active
|| !markedlist
[j
].watch_clone
) && !lp
->exempt
) {
1414 channel
*cp
= findchannel(lp
->name
->content
);
1418 lp
->watch_clone
= trojanscan_selectclone(TROJANSCAN_WATCH_CLONES
);
1419 if(!lp
->watch_clone
)
1421 if(!nickbanned(lp
->watch_clone
->clone
, cp
, 0)) {
1422 if(localjoinchannel(lp
->watch_clone
->clone
, cp
))
1423 lp
->watch_clone
= NULL
;
1426 } while(--attempts
> 0);
1428 lp
->watch_clone
= NULL
;
1437 void trojanscan_fill_channels(void *arg
) {
1438 struct trojanscan_prechannels
*head
= NULL
, *lp
, *last
= NULL
;
1439 int i
, count
, tempctime
= 0;
1443 for (count
=i
=0;i
<trojanscan_database
.total_channels
;i
++) {
1444 lp
= (trojanscan_prechannels
*)tmalloc(sizeof(trojanscan_prechannels
));
1445 lp
->name
= trojanscan_database
.channels
[i
].name
;
1447 lp
->exempt
= trojanscan_database
.channels
[i
].exempt
;
1448 lp
->watch_clone
= NULL
;
1449 if (trojanscan_add_ll(&head
, lp
))
1453 for (i
=0;i
<CHANNELHASHSIZE
;i
++) {
1454 for(chn
=chantable
[i
];chn
;chn
=chn
->next
) {
1455 if (chn
->channel
&& !IsKey(chn
->channel
) && !IsInviteOnly(chn
->channel
) && !IsRegOnly(chn
->channel
) && (chn
->channel
->users
->totalusers
>= trojanscan_minchansize
)) {
1456 lp
= (trojanscan_prechannels
*)tmalloc(sizeof(trojanscan_prechannels
));
1457 lp
->name
= chn
->name
;
1458 lp
->size
= chn
->channel
->users
->totalusers
;
1460 lp
->watch_clone
= NULL
;
1461 if (trojanscan_add_ll(&head
, lp
))
1467 count
= TROJANSCAN_MMIN(count
, trojanscan_maxchans
);
1469 trojanscan_watch_clone_update(head
, count
);
1471 trojanscan_free_channels();
1472 trojanscan_chans
= (struct trojanscan_inchannel
*)tmalloc(count
* sizeof(struct trojanscan_inchannel
));
1473 memset(trojanscan_chans
, 0, count
* sizeof(struct trojanscan_inchannel
));
1474 trojanscan_activechans
= count
;
1477 for(lp
=head
;lp
;last
=lp
,lp
=lp
->next
) {
1478 if (!(lp
->exempt
) && (i
< count
)) {
1479 trojanscan_chans
[i
].channel
= getsstring(lp
->name
->content
, lp
->name
->length
);
1480 trojanscan_chans
[i
++].watch_clone
= lp
->watch_clone
;
1489 if (trojanscan_activechans
> 0) {
1490 tempctime
= trojanscan_cycletime
/ trojanscan_activechans
;
1493 trojanscan_mainchanmsg("d: just escaped a divide by zero error (no activechans!), rescheduling in 60 seconds");
1496 if(trojanscan_schedule
)
1497 deleteschedule(trojanscan_schedule
, &trojanscan_dojoin
, NULL
);
1499 trojanscan_channumber
= 0;
1501 trojanscan_schedule
= schedulerecurring(time(NULL
) + tempctime
, trojanscan_activechans
+ 1, tempctime
, trojanscan_dojoin
, NULL
);
1505 void trojanscan_dojoin(void *arg
) {
1506 struct trojanscan_realchannels
*rc
;
1507 if (trojanscan_channumber
>= trojanscan_activechans
) {
1508 trojanscan_schedule
= NULL
;
1509 trojanscan_fill_channels(NULL
);
1511 if ((rc
= trojanscan_allocaterc(trojanscan_chans
[trojanscan_channumber
++].channel
->content
)))
1512 trojanscan_join(rc
);
1517 void trojanscan_dopart(void *arg
) {
1518 struct trojanscan_realchannels
*rc
= (struct trojanscan_realchannels
*)arg
, *rp
, *past
= NULL
;
1520 if (rc
->kickedout
) { /* there's a join scheduled, wait for it (reschedule) */
1521 rc
->schedule
= scheduleoneshot(time(NULL
)+5, &trojanscan_dopart
, (void *)rc
);
1525 if (rc
->clone
->clone
&& (!(rc
->donotpart
)))
1526 localpartchannel(rc
->clone
->clone
, rc
->chan
, NULL
);
1528 rc
->clone
->sitting
--;
1530 for(rp
=trojanscan_realchanlist
;rp
;rp
=rp
->next
) {
1533 trojanscan_realchanlist
= rp
->next
;
1535 past
->next
= rp
->next
;
1545 void trojanscan_donickchange(void *arg
) { /* just incase I choose to make this schedule at some point */
1546 struct trojanscan_clones
*clone
= (trojanscan_clones
*)arg
;
1548 if (clone
&& clone
->clone
)
1549 patrol_nickchange(clone
->clone
);
1552 int trojanscan_keysort(const void *v1
, const void *v2
) {
1553 return ((*(trojanscan_prechannels
**)v2
)->size
- (*(trojanscan_prechannels
**)v1
)->size
);
1556 int trojanscan_showcommands(void *sender
, int cargc
, char **cargv
) {
1557 nick
*np
= (nick
*)sender
;
1558 Command
*cmdlist
[100];
1562 n
= getcommandlist(trojanscan_cmds
, cmdlist
, 100);
1564 trojanscan_reply(np
, "The following commands are registered at present:");
1567 if (cmdlist
[i
]->level
& TROJANSCAN_ACL_STAFF
) {
1569 } else if (cmdlist
[i
]->level
& TROJANSCAN_ACL_DEVELOPER
) {
1571 } else if (cmdlist
[i
]->level
& TROJANSCAN_ACL_TEAMLEADER
) {
1573 } else if (cmdlist
[i
]->level
& TROJANSCAN_ACL_CAT
) {
1575 } else if (cmdlist
[i
]->level
& TROJANSCAN_ACL_WEBSITE
) {
1577 } else if (cmdlist
[i
]->level
& TROJANSCAN_ACL_UNAUTHED
) {
1581 trojanscan_reply(np
, "%s (+%c)", cmdlist
[i
]->command
->content
, level
);
1583 trojanscan_reply(np
, "%s", cmdlist
[i
]->command
->content
);
1586 trojanscan_reply(np
, "End of list.");
1590 void trojanscan_handlemessages(nick
*target
, int messagetype
, void **args
) {
1593 int cargc
, templevel
;
1595 union trojanscan_userlevel level
;
1597 switch(messagetype
) {
1600 /* If it's a message, first arg is nick and second is message */
1601 sender
= (nick
*)args
[0];
1603 if(strncmp(TROJANSCAN_VERSION_DETECT
, args
[1], sizeof(TROJANSCAN_VERSION_DETECT
)-1)==0) {
1604 char p
= ((char *)args
[1])[sizeof(TROJANSCAN_VERSION_DETECT
)-1];
1605 if((p
== ' ') || (p
== '\0') || (p
== 1)) {
1606 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
);
1611 /* Split the line into params */
1612 cargc
= splitline((char *)args
[1], cargv
, 50, 0);
1613 if(cargc
== 0 || !cargv
[0])
1616 cmd
=findcommandintree(trojanscan_cmds
, cargv
[0], 1);
1618 trojanscan_reply(sender
, "Unknown command.");
1622 if ((cmd
->level
& TROJANSCAN_ACL_OPER
) && !IsOper(sender
)) {
1623 trojanscan_reply(sender
, "You need to be opered to use this command.");
1627 /* bit grim code... */
1629 if (!(cmd
->level
& TROJANSCAN_ACL_UNAUTHED
)) {
1630 if (!IsAccount(sender
)) {
1631 trojanscan_reply(sender
, "You must be authed with the network to access this command!");
1634 templevel
= trojanscan_user_level_by_authname(sender
->authname
);
1636 if (templevel
== -1) {
1637 trojanscan_reply(sender
, "You do not have an account.");
1641 level
.number
= templevel
;
1643 if ((cmd
->level
& TROJANSCAN_ACL_DEVELOPER
) && !TrojanscanIsDeveloper(level
)) {
1644 trojanscan_reply(sender
, "Access denied.");
1647 if ((cmd
->level
& TROJANSCAN_ACL_TEAMLEADER
) && !TrojanscanIsLeastTeamLeader(level
)) {
1648 trojanscan_reply(sender
, "Access denied.");
1651 if ((cmd
->level
& TROJANSCAN_ACL_STAFF
) && !TrojanscanIsLeastStaff(level
)) {
1652 trojanscan_reply(sender
, "Access denied.");
1655 if ((cmd
->level
& TROJANSCAN_ACL_CAT
) && !TrojanscanIsCat(level
)) {
1656 trojanscan_reply(sender
, "Access denied.");
1659 if ((cmd
->level
& TROJANSCAN_ACL_WEBSITE
) && !TrojanscanIsLeastWebsite(level
)) {
1660 trojanscan_reply(sender
, "Access denied.");
1665 /* Check the maxargs */
1666 if (cmd
->maxparams
<(cargc
-1)) {
1667 /* We need to do some rejoining */
1668 rejoinline(cargv
[cmd
->maxparams
], cargc
-(cmd
->maxparams
));
1669 cargc
= (cmd
->maxparams
) + 1;
1672 (cmd
->handler
)((void *)sender
, cargc
- 1, &(cargv
[1]));
1676 /* someone killed me? Bastards */
1677 trojanscan_connect_nick_schedule
= scheduleoneshot(time(NULL
) + 1, &trojanscan_connect_nick
, NULL
);
1678 trojanscan_nick
= NULL
;
1686 static char trojanscan_getmtfromhooktype(int input
) {
1688 case HOOK_CHANNEL_PART
: return 'P';
1689 default: return '?';
1693 char trojanscan_getmtfrommessagetype(int input
) {
1695 case LU_PRIVMSG
: return 'm';
1696 case LU_PRIVNOTICE
: return 'n';
1697 case LU_SECUREMSG
: return 's';
1698 case LU_CHANMSG
: return 'M';
1699 case LU_CHANNOTICE
: return 'N';
1700 default: return '?';
1704 static void trojanscan_process(nick
*sender
, channel
*cp
, char mt
, char *pretext
) {
1708 struct trojanscan_worms
*worm
;
1709 int vector
[30], detected
= 0;
1711 trojanscan_strip_codes(text
, sizeof(text
) - 1, pretext
);
1715 for(i
=0;i
<trojanscan_database
.total_phrases
;i
++) {
1718 (worm
= trojanscan_database
.phrases
[i
].worm
)
1723 (mt
== 'm') || (mt
== 's') || (mt
== 'n')
1726 (trojanscan_database
.phrases
[i
].worm
->hitpriv
)
1731 (mt
== 'M') || (mt
== 'N') || (mt
== 'P')
1734 (trojanscan_database
.phrases
[i
].worm
->hitchans
)
1738 (trojanscan_database
.phrases
[i
].phrase
)
1740 int pre
= pcre_exec(trojanscan_database
.phrases
[i
].phrase
, trojanscan_database
.phrases
[i
].hint
, text
, len
, 0, 0, vector
, 30);
1744 matchbuf
[512] = 0; /* hmm */
1747 if(pcre_copy_substring(text
, vector
, pre
, 1, matchbuf
, sizeof(matchbuf
) - 1) <= 0)
1750 trojanscan_phrasematch(cp
, sender
, &trojanscan_database
.phrases
[i
], mt
, matchbuf
);
1757 if (!detected
&& (mt
!= 'N') && (mt
!= 'M')) {
1758 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
];
1759 trojanscan_database_escape_string(etext
, text
, len
);
1760 trojanscan_database_escape_string(enick
, sender
->nick
, strlen(sender
->nick
));
1761 trojanscan_database_escape_string(eident
, sender
->ident
, strlen(sender
->ident
));
1762 trojanscan_database_escape_string(ehost
, sender
->host
->name
->content
, sender
->host
->name
->length
);
1763 trojanscan_database_query("INSERT INTO unknownlog (data, user) VALUES ('%s','%s!%s@%s')", etext
, enick
, eident
, ehost
);
1767 void trojanscan_clonehandlemessages(nick
*target
, int messagetype
, void **args
) {
1768 char *pretext
= NULL
;
1770 struct trojanscan_realchannels
*rp
;
1771 struct trojanscan_rejoinlist
*rj
;
1772 char mt
= trojanscan_getmtfrommessagetype(messagetype
);
1777 switch(messagetype
) {
1782 pretext
= (char *)args
[1];
1786 sender
= (nick
*)args
[0];
1788 if (strlen(sender
->nick
) < 2)
1792 pretext
= (char *)args
[2];
1796 if(strncmp(TROJANSCAN_VERSION_DETECT
, pretext
, sizeof(TROJANSCAN_VERSION_DETECT
)-1)==0) {
1797 char p
= pretext
[sizeof(TROJANSCAN_VERSION_DETECT
)-1];
1798 if((p
== ' ') || (p
== '\0') || (p
== 1)) {
1800 if (IsOper(sender
)) {
1803 if (IsAccount(sender
)) {
1804 int templevel
= trojanscan_user_level_by_authname(sender
->authname
);
1805 if (templevel
!= -1) {
1806 union trojanscan_userlevel level
;
1807 level
.number
= templevel
;
1808 if (TrojanscanIsLeastStaff(level
))
1814 if(trojanscan_nick
) {
1815 sendnoticetouser(target
, sender
, "\001VERSION T clone, check T for confirmation.\001");
1816 sendnoticetouser(trojanscan_nick
, sender
, "\001VERSION %s is part of my swarm.\001", target
->nick
);
1818 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");
1821 sendnoticetouser(target
, sender
, "\001VERSION %s\001", versionreply
);
1828 trojanscan_process(sender
, cp
, mt
, pretext
);
1831 /* someone killed me? Bastards */
1833 /* PPA: we do NOT rejoin channels at this moment in time, it is possible to do this though */
1834 for (i
=0;i
<TROJANSCAN_CLONE_TOTAL
;i
++) {
1835 if (trojanscan_swarm
[i
].clone
== target
) {
1837 scheduleoneshot(time(NULL
)+1, &trojanscan_generateclone
, (void *)((long)i
));
1838 if(i
>= TROJANSCAN_CLONE_MAX
) {
1840 for(j
=0;j
<trojanscan_activechans
;j
++)
1841 if(trojanscan_chans
[j
].watch_clone
== &trojanscan_swarm
[i
])
1842 trojanscan_chans
[j
].watch_clone
= NULL
;
1844 for(rp
=trojanscan_realchanlist
;rp
;rp
=rp
->next
)
1845 if (rp
->clone
== &(trojanscan_swarm
[i
]))
1848 trojanscan_swarm
[i
].clone
= NULL
;
1849 trojanscan_swarm
[i
].remaining
= 0; /* bah */
1856 channel_name
= ((channel
*)args
[1])->index
->name
->content
;
1857 for (i
=0;i
<trojanscan_activechans
;i
++) {
1858 if (!trojanscan_chans
[i
].watch_clone
)
1860 if ((trojanscan_chans
[i
].watch_clone
->clone
== target
) && (!strcmp(trojanscan_chans
[i
].channel
->content
, channel_name
)))
1863 if(i
!= trojanscan_activechans
) {
1865 for(j
=0;j
<TROJANSCAN_CLONE_TOTAL
;j
++) {
1866 if(&trojanscan_swarm
[j
] == trojanscan_chans
[i
].watch_clone
) {
1867 trojanscan_chans
[i
].watch_clone
= NULL
;
1873 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)");
1875 rj
= (struct trojanscan_rejoinlist
*)tmalloc(sizeof(struct trojanscan_rejoinlist
));
1878 for(rp
=trojanscan_realchanlist
;rp
;rp
=rp
->next
)
1879 if ((rp
->clone
->clone
== target
) && (rp
->chan
== args
[1])) {
1889 rj
->channel
= getsstring(((channel
*)args
[1])->index
->name
->content
, ((channel
*)args
[1])->index
->name
->length
);
1891 trojanscan_mainchanmsg("d: unable to allocate memory for channel: %s upon rejoin", ((channel
*)args
[1])->index
->name
->content
);
1896 rj
->clone
= rp
->clone
;
1897 rj
->next
= trojanscan_schedulerejoins
;
1898 trojanscan_schedulerejoins
= rj
;
1900 rj
->schedule
= scheduleoneshot(time(NULL
)+1, &trojanscan_rejoin_channel
, (void *)rj
);
1909 static void trojanscan_part_watch(int hook
, void *arg
) {
1910 void **arglist
= (void **)arg
;
1911 channel
*cp
= (channel
*)arglist
[0];
1912 nick
*np
= arglist
[1];
1913 char *reason
= arglist
[2];
1915 if(!cp
|| !np
|| !reason
|| (*reason
== '\0'))
1918 trojanscan_process(np
, cp
, trojanscan_getmtfromhooktype(hook
), reason
);
1921 void trojanscan_phrasematch(channel
*chp
, nick
*sender
, trojanscan_phrases
*phrase
, char messagetype
, char *matchbuf
) {
1922 char glinemask
[HOSTLEN
+ USERLEN
+ NICKLEN
+ 4], enick
[TROJANSCAN_QUERY_TEMP_BUF_SIZE
], eident
[TROJANSCAN_QUERY_TEMP_BUF_SIZE
], ehost
[TROJANSCAN_QUERY_TEMP_BUF_SIZE
];
1923 unsigned int frequency
;
1924 int glining
= 0, usercount
;
1925 struct trojanscan_worms
*worm
= phrase
->worm
;
1928 trojanscan_database
.detections
++;
1931 if (worm
->monitor
) {
1933 } else if(worm
->glinehost
|| worm
->glineuser
) {
1936 usercount
= glinebynick(sender
, 0, NULL
, GLINE_SIMULATE
, "trojanscan");
1940 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
);
1944 if (glining
&& (usercount
> trojanscan_maxusers
)) {
1945 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
);
1949 if (glining
&& !worm
->datalen
) {
1950 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
);
1954 trojanscan_database_escape_string(enick
, sender
->nick
, strlen(sender
->nick
));
1955 trojanscan_database_escape_string(eident
, sender
->ident
, strlen(sender
->ident
));
1956 trojanscan_database_escape_string(ehost
, sender
->host
->name
->content
, sender
->host
->name
->length
);
1960 if (!(trojanscan_database_query("SELECT COUNT(*) FROM hits WHERE glined = %d AND host = '%s'", glining
, ehost
))) {
1961 trojanscan_database_res
*res
;
1962 if ((res
= trojanscan_database_store_result(&trojanscan_sql
))) {
1963 trojanscan_database_row sqlrow
;
1964 if ((trojanscan_database_num_rows(res
) > 0) && (sqlrow
= trojanscan_database_fetch_row(res
)))
1965 frequency
= atoi(sqlrow
[0]) + 1;
1966 trojanscan_database_free_result(res
);
1971 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
:"");
1972 #ifdef TROJANSCAN_PEONCHANNEL
1973 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
:"");
1976 int glinetime
= TROJANSCAN_FIRST_OFFENSE
* frequency
* (worm
->epidemic
?TROJANSCAN_EPIDEMIC_MULTIPLIER
:1);
1977 if(glinetime
> 7 * 24)
1978 glinetime
= 7 * 24; /* can't set glines over 7 days with normal non U:lined glines */
1980 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
);
1981 trojanscan_database
.glines
++;
1983 snprintf(reason
, sizeof(reason
), "You (%s!%s@%s) are infected with a trojan (%s/%d), see %s%d for details - banned for %d hours", sender
->nick
, sender
->ident
, sender
->host
->name
->content
, worm
->name
->content
, phrase
->id
, TROJANSCAN_URL_PREFIX
, worm
->id
, glinetime
);
1984 glinebynick(sender
, glinetime
* 3600, reason
, 0, "trojanscan");
1986 trojanscan_mainchanmsg("g: *!%s t: %c u: %s!%s@%s%s%s c: %d w: %s%s p: %d f: %d%s%s", 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
, matchbuf
[0]?" --: ":"", matchbuf
[0]?matchbuf
:"");
1990 void trojanscan_rejoin_channel(void *arg
) {
1991 struct trojanscan_rejoinlist
*rj2
, *lrj
, *rj
= (struct trojanscan_rejoinlist
*)arg
;
1993 channel
*cp
= findchannel(rj
->channel
->content
);
1994 freesstring(rj
->channel
);
1997 rj
->rp
->kickedout
--;
1999 rj
->rp
->donotpart
= 1; /* we were the last user on the channel, so we need to be VERY careful freeing it */
2001 if(!rj
->rp
->donotpart
&& !rj
->rp
->kickedout
) { /* check we're allowed to join channels (not killed), and we're the last one to join */
2002 if (nickbanned(rj
->clone
->clone
, cp
, 0)) {
2003 rj
->rp
->donotpart
= 1;
2005 localjoinchannel(rj
->clone
->clone
, cp
);
2011 rj2
= trojanscan_schedulerejoins
;
2015 trojanscan_schedulerejoins
= rj
->next
;
2018 for(rj2
=trojanscan_schedulerejoins
;rj2
;lrj
=rj2
,rj2
=rj2
->next
) {
2020 lrj
->next
= rj2
->next
;
2029 void trojanscan_reply(nick
*target
, char *message
, ... ) {
2033 if (!trojanscan_nick
)
2036 va_start(va
, message
);
2037 vsnprintf(buf
, sizeof(buf
) - 1, message
, va
);
2040 sendnoticetouser(trojanscan_nick
, target
, "%s", buf
);
2044 void trojanscan_mainchanmsg(char *message
, ...) {
2049 if (!trojanscan_nick
)
2051 if (!(cp
= findchannel(TROJANSCAN_CHANNEL
)))
2054 va_start(va
, message
);
2055 vsnprintf(buf
, sizeof(buf
) - 1, message
, va
);
2058 sendmessagetochannel(trojanscan_nick
, cp
, "%s", buf
);
2061 #ifdef TROJANSCAN_PEONCHANNEL
2062 void trojanscan_peonchanmsg(char *message
, ...) {
2067 if (!trojanscan_nick
)
2069 if (!(cp
= findchannel(TROJANSCAN_PEONCHANNEL
)))
2072 va_start(va
, message
);
2073 vsnprintf(buf
, sizeof(buf
) - 1, message
, va
);
2076 sendmessagetochannel(trojanscan_nick
, cp
, "%s", buf
);
2080 int trojanscan_minmaxrand(float min
, float max
) {
2081 return (int)((max
-min
+1)*rand()/(RAND_MAX
+min
))+min
;
2084 nick
*trojanscan_selectuser(void) {
2085 int target
= trojanscan_minmaxrand(0, 500), loops
= 150, j
;
2088 for (j
=trojanscan_minmaxrand(0, NICKHASHSIZE
-1);j
<NICKHASHSIZE
;j
++)
2089 for(np
=nicktable
[j
];np
;np
=np
->next
)
2092 } while(--loops
> 0);
2096 static void db_ping(void *arg
) {
2097 if (!(trojanscan_database_query("SELECT 1"))) {
2098 trojanscan_database_res
*res
;
2099 if ((res
= trojanscan_database_store_result(&trojanscan_sql
))) {
2100 trojanscan_database_free_result(res
);
2104 db_ping_schedule
= scheduleoneshot(time(NULL
) + 60, &db_ping
, NULL
);
2107 void trojanscan_database_close(void) {
2108 if(db_ping_schedule
)
2109 deleteschedule(db_ping_schedule
, db_ping
, NULL
);
2111 mysql_close(&trojanscan_sql
);
2114 int trojanscan_database_connect(char *dbhost
, char *dbuser
, char *dbpass
, char *db
, unsigned int port
) {
2115 mysql_init(&trojanscan_sql
);
2116 if (!mysql_real_connect(&trojanscan_sql
, dbhost
, dbuser
, dbpass
, db
, port
, NULL
, 0))
2120 db_ping_schedule
= scheduleoneshot(time(NULL
) + 60, &db_ping
, NULL
);
2125 void trojanscan_database_escape_string(char *dest
, char *source
, size_t length
) {
2126 mysql_escape_string(dest
, source
, length
);
2129 int trojanscan_database_query(char *format
, ...) {
2130 char trojanscan_sqlquery
[TROJANSCAN_QUERY_BUF_SIZE
];
2133 va_start(va
, format
);
2134 vsnprintf(trojanscan_sqlquery
, sizeof(trojanscan_sqlquery
) - 1, format
, va
);
2136 return mysql_query(&trojanscan_sql
, trojanscan_sqlquery
);
2139 int trojanscan_database_num_rows(trojanscan_database_res
*res
) {
2140 return mysql_num_rows(res
);
2143 trojanscan_database_res
*trojanscan_database_store_result() {
2144 return mysql_store_result(&trojanscan_sql
);
2147 trojanscan_database_row
trojanscan_database_fetch_row(trojanscan_database_res
*res
) {
2148 return mysql_fetch_row(res
);
2151 void trojanscan_database_free_result(trojanscan_database_res
*res
) {
2152 mysql_free_result(res
);
2155 int trojanscan_isip(char *host
) {
2156 char *p
= host
, components
= 0, length
= 0;
2160 if(((!length
) || (length
= 0)) || (++components
> 3))
2163 if ((++length
> 3) || !isdigit(*p
))
2167 return components
== 3;