int tgh_ext;
int tgb_ext;
+int tgn_ext;
unsigned long trusts_lasttrustgroupid;
unsigned long trusts_lasttrusthostid;
unsigned long trusts_lasttrustblockid;
-int trusts_loaded;
+int trusts_loaded = 0;
int removeusers = 0;
static void trusts_status(int hooknum, void *arg);
return;
}
- if ( !trusts_load_db()) {
+ tgn_ext = registernickext("trustnick");
+ if ( !tgn_ext ) {
+ Error("trusts", ERR_FATAL, "Could not register a required nick extension (trustnick)");
return;
}
-
+
registerhook(HOOK_TRUSTS_DBLOADED, trustsfinishinit);
+ if ( !trusts_load_db()) {
+ return;
+ }
+
if (trusts_loaded)
trustsfinishinit(HOOK_TRUSTS_DBLOADED, NULL);
}
void trustsfinishinit(int hooknum, void *arg) {
- Error("trusts",ERR_INFO,"Database loaded, finishing initialisation.");
-
- deregisterhook(HOOK_TRUSTS_DBLOADED, trustsfinishinit);
-
registerhook(HOOK_NICK_NEWNICK, &trusts_hook_newuser);
registerhook(HOOK_NICK_LOSTNICK, &trusts_hook_lostuser);
trustgroupidentcount_t *t;
int i;
- for ( i = 0; i < TRUSTS_HASH_HOSTSIZE ; i++ ) {
- for ( thptr = trusthostidtable[i]; thptr; thptr = thptr-> nextbyid ) {
- derefnode(iptree,thptr->node);
- }
- }
- if (tgh_ext)
- releasenodeext(tgh_ext);
- if (tgb_ext)
- releasenodeext(tgb_ext);
+
+ deregisterhook(HOOK_TRUSTS_DBLOADED, trustsfinishinit);
if ( trusts_loaded ) {
deregisterhook(HOOK_NICK_NEWNICK, &trusts_hook_newuser);
}
}
- trustblock_freeall();
+ patricia_node_t *node;
+ PATRICIA_WALK_CLEAR(iptree->head,node) {
+ if (node && node->exts[tgb_ext]) {
+ trustblock_free(node->exts[tgb_ext]);
+ node->exts[tgb_ext] = NULL;
+ }
+ } PATRICIA_WALK_CLEAR_END;
+
+ if (tgh_ext)
+ releasenodeext(tgh_ext);
+ if (tgb_ext)
+ releasenodeext(tgb_ext);
+ if (tgn_ext)
+ releasenodeext(tgn_ext);
/* @@@ CLOSE DB */
}
}
-void trust_debug(char *format, ...) {
- char buf[512];
- va_list va;
- channel *debugcp = findchannel("#qnet.trusts");
- if(debugcp) {
- va_start(va, format);
- vsnprintf(buf, sizeof(buf), format, va);
- va_end(va);
- controlchanmsg(debugcp,buf);
- }
-}
-
static void trusts_status(int hooknum, void *arg) {
if((long)arg > 10) {
char message[100];
snprintf(message, sizeof(message), "Trusts :%7d groups, %7d hosts", tgcount, thcount);
triggerhook(HOOK_CORE_STATSREPLY, message);
}
+}
+int trusts_ignore_np(nick *np) {
+ if(SIsService(&serverlist[homeserver(np->numeric)])) {
+ /* ANY user created by a server (nterface,fakeusers,Q) are ignored in relation to trusts */
+ /* NOTE: we might need to review this if we ever used newserv to handle client/user connections in some way */
+ return 1;
+ }
+ return 0;
}
#define TRUSTS_MAXGROUPNAMELEN 20
+/* node extensions */
extern int tgh_ext;
extern int tgb_ext;
+
+/* nick extensions */
+extern int tgn_ext;
+
extern int removeusers;
extern int trusts_loaded;
extern unsigned long trusts_lasttrustgroupid, trusts_lasttrusthostid, trusts_lasttrustblockid;
-void trust_debug(char *format, ...);
-
/* trusts alloc */
trustgroup_t *newtrustgroup();
void freetrustgroup (trustgroup_t *trustgroup);
void trusts_create_tables(void);
void trusts_cleanup_db(void);
void trusts_loadtrustgroups(DBConn *dbconn, void *arg);
+void trusts_loadtrustgroupsmax(DBConn *dbconn, void *arg);
void trusts_loadtrusthosts(DBConn *dbconn, void *arg);
+void trusts_loadtrusthostsmax(DBConn *dbconn, void *arg);
void trusts_loadtrustblocks(DBConn *dbconn, void *arg);
void trustsdb_addtrustgroup(trustgroup_t *t);
void trustsdb_updatetrustgroup(trustgroup_t *t);
/* trusts */
void decrement_trust_ipnode(patricia_node_t *node);
void increment_trust_ipnode(patricia_node_t *node);
+int trusts_ignore_np(nick *np);
/* trusts cmds */
void trusts_cmdinit();
int trust_stats(void *source, int cargc, char **cargv);
int trust_dump(void *source, int cargc, char **cargv);
+int trust_dotrustlog(void *source, int cargc, char **cargv);
+
#endif
if (pst) {
pst->next = st->next;
}
+
derefnode(iptree,st->node);
if (st->reason_public ) {
freesstring(st->reason_public);
while(tb) {
ptb=tb;
tb=tb->next;
+
derefnode(iptree,ptb->node);
if (ptb->reason_public ) {
freesstring(ptb->reason_public);
if (ptb->reason_private) {
freesstring(ptb->reason_private);
}
+ ptb->node->exts[tgb_ext] = NULL;
}
}
#include <stdlib.h>
#include <stdarg.h>
+static int commandsregistered;
+
void _init(void) {
registerhook(HOOK_TRUSTS_DBLOADED, trusts_cmdinit);
void _fini(void) {
deregisterhook(HOOK_TRUSTS_DBLOADED, trusts_cmdinit);
- trusts_cmdfini();
+ trusts_cmdfini(0, NULL);
}
void trusts_cmdinit(int hooknum, void *arg) {
+ if(commandsregistered)
+ return;
registercontrolcmd("trustgroupadd",10,7,trust_groupadd);
registercontrolcmd("trustgroupmodify",10,4,trust_groupmodify);
registercontrolcmd("trustgroupdel",10,2,trust_groupdel);
registercontrolcmd("truststats",10,2,trust_stats);
registercontrolcmd("trustdump",10,2,trust_dump);
+ registercontrolcmd("trustlog", 10,2, trust_dotrustlog);
+
+ commandsregistered = 1;
removeusers = 0;
}
void trusts_cmdfini() {
+ if(!commandsregistered)
+ return;
+
deregistercontrolcmd("trustgroupadd",trust_groupadd);
deregistercontrolcmd("trustgroupmodify",trust_groupmodify);
deregistercontrolcmd("trustgroupdel",trust_groupdel);
deregistercontrolcmd("truststats",trust_stats);
deregistercontrolcmd("trustdump",trust_dump);
+ deregistercontrolcmd("trustlog", trust_dotrustlog);
+
+ commandsregistered = 0;
removeusers = 0;
}
}
expiry = durationtolong(cargv[1]);
if (expiry > (365 * 86400) ) {
- controlreply(sender,"ERROR: Invalid duration given - temporary trusts can not be longer then 1 year");
+ controlreply(sender,"ERROR: Invalid duration given - temporary trusts must be less than 1 year");
return CMD_ERROR;
}
ownerid = strtoul(cargv[6],NULL,10);
return CMD_ERROR;
}
+ if (!is_normalized_ipmask(&sin,bits)) {
+ controlreply(sender, "ERROR: non-normalized mask.");
+ return CMD_ERROR;
+ }
+
node = refnode(iptree, &sin, bits);
if(!node->exts[tgh_ext]) {
controlreply(sender,"ERROR: That CIDR was not trusted.");
return CMD_ERROR;
}
+ if (!is_normalized_ipmask(&sin,bits)) {
+ controlreply(sender, "ERROR: non-normalized mask.");
+ return CMD_ERROR;
+ }
+
if ( irc_in_addr_is_ipv4(&sin) ) {
if (bits>128 || bits<112) {
controlreply(sender,"ERROR: Not a valid netmask (needs to be between 16 and 32)");
th = trusthostadd(node, tg, expiry );
if ( !th ) {
controlreply(sender,"ERROR: Unable to add trusted host");
+ return CMD_ERROR;
}
trustsdb_addtrusthost(th);
return CMD_ERROR;
}
+ if (!is_normalized_ipmask(&sin,bits)) {
+ controlreply(sender, "ERROR: non-normalized mask.");
+ return CMD_ERROR;
+ }
+
if ( irc_in_addr_is_ipv4(&sin) ) {
if (bits>128 || bits<112) {
controlreply(sender,"ERROR: Not a valid netmask (needs to be between 8 and 32)");
return CMD_ERROR;
}
+ if (!is_normalized_ipmask(&sin,bits)) {
+ controlreply(sender, "ERROR: non-normalized mask.");
+ return CMD_ERROR;
+ }
+
if ( irc_in_addr_is_ipv4(&sin) ) {
if (bits>128 || bits<112) {
controlreply(sender,"ERROR: Not a valid netmask (needs to be between 8 and 32)");
controlreply(sender, "ERROR: Invalid mask.");
return CMD_ERROR;
}
+
+ if (!is_normalized_ipmask(&sin,bits)) {
+ controlreply(sender, "ERROR: non-normalized mask.");
+ return CMD_ERROR;
+ }
node = refnode(iptree, &sin, bits);
if(!node->exts[tgb_ext]) {
maxthmask4 = (((patricia_node_t *)thptr->node)->prefix->bitlen-96);
}
} else {
+ controlreply(sender, "%s", IPtostr(((patricia_node_t *)thptr->node)->prefix->sin));
netcount6[((patricia_node_t *)thptr->node)->prefix->bitlen]++;
netucount6[((patricia_node_t *)thptr->node)->prefix->bitlen]+=thptr->node->usercount;
netmcount6[((patricia_node_t *)thptr->node)->prefix->bitlen]+=thptr->maxused;
controlwall(NO_OPER, NL_TRUSTS, "Comment: %s for trustgroup %lu", cargv[1], tg->id);
return CMD_OK;
-
}
+int trust_dotrustlog(void *source, int cargc, char **cargv) {
+ nick *np=source;
+ unsigned long interval;
+ int trustid;
+
+ if (cargc < 1) {
+ controlreply(np,"Syntax: trustlog <#groupid> [duration]");
+ return CMD_ERROR;
+ }
+
+ if(cargv[0][0]== '#'){
+ trustid = strtol(&cargv[0][1],NULL,10);
+ } else {
+ trustid = strtol(cargv[0],NULL,10);
+ }
+
+ if (cargc > 1)
+ interval=getnettime() - durationtolong(cargv[1]);
+ else
+ interval=0;
+
+ trustsdb_retrievetrustlog(np, trustid, interval);
+ return CMD_OK;
+}
int trustdb_loaded = 0;
+static void trusts_dbtriggerdbloaded(void *arg);
+
int trusts_load_db(void) {
if(!dbconnected()) {
Error("trusts", ERR_STOP, "Could not connect to database.");
dbasyncquery(trusts_loadtrustgroups, NULL,
"SELECT trustid,maxusage,maxclones,maxperident,maxperip,enforceident,startdate,lastused,expires,owneruserid,type,created,modified FROM trusts.groups WHERE enddate = 0");
+ dbasyncquery(trusts_loadtrustgroupsmax, NULL,
+ "SELECT max(trustid) from trusts.groups");
+
dbasyncquery(trusts_loadtrusthosts, NULL,
"SELECT * FROM trusts.hosts WHERE enddate = 0");
+ dbasyncquery(trusts_loadtrusthostsmax, NULL,
+ "SELECT max(hostid) FROM trusts.hosts");
+
dbasyncquery(trusts_loadtrustblocks, NULL,
"SELECT * FROM trusts.blocks");
"trustid INT4 NOT NULL,"
"startdate INT4 NOT NULL,"
"enddate INT4,"
- "host INET NOT NULL,"
+ "host VARCHAR NOT NULL,"
"maxusage INT4 NOT NULL,"
"lastused INT4,"
"expires INT4 NOT NULL,"
dbcreatequery(
"CREATE TABLE trusts.blocks ("
"blockid INT4 NOT NULL PRIMARY KEY,"
- "block INET NOT NULL,"
+ "block VARCHAR NOT NULL,"
"owner INT4,"
"expires INT4,"
"startdate INT4,"
rows++;
}
- Error("trusts",ERR_INFO,"Loaded %d trusts (highest ID was %lu)",rows,trusts_lasttrustgroupid);
+ Error("trusts",ERR_INFO,"Loaded %d trusts (highest ID was %lu)",rows,trusts_lasttrustgroupid);
+
+ dbclear(pgres);
+}
+
+void trusts_loadtrustgroupsmax(DBConn *dbconn, void *arg) {
+ DBResult *pgres = dbgetresult(dbconn);
+ unsigned long trustmax = 0;
+
+ if(!dbquerysuccessful(pgres)) {
+ Error("trusts", ERR_ERROR, "Error loading trustgroup max.");
+ dbclear(pgres);
+ return;
+ }
+
+ while(dbfetchrow(pgres)) {
+ trustmax = strtoul(dbgetvalue(pgres,0),NULL,10);
+ }
+
+ if ( trustmax < trusts_lasttrustgroupid ) {
+ Error("trusts",ERR_INFO,"trust max failed - %lu, %lu", trustmax, trusts_lasttrustgroupid);
+ }
+ trusts_lasttrustgroupid = trustmax;
+
+ Error("trusts",ERR_INFO,"Loaded Trust Max %lu", trusts_lasttrustgroupid);
dbclear(pgres);
}
while(dbfetchrow(pgres)) {
/*node*/
- ipmask_parse(dbgetvalue(pgres,4), &sin, &bits);
+ if( ipmask_parse(dbgetvalue(pgres,4), &sin, &bits) == 0) {
+ Error("trusts", ERR_ERROR, "Failed to parse trusthost: %s", dbgetvalue(pgres,4));
+ continue;
+ }
+
node = refnode(iptree, &sin, bits);
/*tg*/
tg=findtrustgroupbyid(tgid);
if (!tg) {
Error("trusts", ERR_ERROR, "Error loading trusthosts - invalid group: %d.", tgid);
+
+ /* update last hostid - although we probably should fail here more loudly */
+ if(t->id > trusts_lasttrusthostid)
+ trusts_lasttrusthostid = t->id;
+
continue;
}
dbclear(pgres);
}
+void trusts_loadtrusthostsmax(DBConn *dbconn, void *arg) {
+ DBResult *pgres = dbgetresult(dbconn);
+ unsigned long trustmax = 0;
+
+ if(!dbquerysuccessful(pgres)) {
+ Error("trusts", ERR_ERROR, "Error loading trusthost max.");
+ dbclear(pgres);
+ return;
+ }
+
+ while(dbfetchrow(pgres)) {
+ trustmax = strtoul(dbgetvalue(pgres,0),NULL,10);
+ }
+
+ if ( trustmax < trusts_lasttrusthostid ) {
+ Error("trusts", ERR_FATAL, "trusthost max failed - %lu, %lu", trustmax, trusts_lasttrusthostid);
+ }
+ trusts_lasttrusthostid = trustmax;
+
+ Error("trusts",ERR_INFO,"Loaded Trust Host Max %lu", trusts_lasttrusthostid);
+
+ dbclear(pgres);
+}
+
void trusts_loadtrustblocks(DBConn *dbconn, void *arg) {
DBResult *pgres = dbgetresult(dbconn);
int rows=0;
while(dbfetchrow(pgres)) {
/*node*/
- ipmask_parse(dbgetvalue(pgres,1), &sin, &bits);
+ if( ipmask_parse(dbgetvalue(pgres,1), &sin, &bits) == 0) {
+ Error("trusts", ERR_ERROR, "Failed to parse trustblock: %s", dbgetvalue(pgres,1));
+ continue;
+ }
node = refnode(iptree, &sin, bits);
t = createtrustblockfromdb(
dbclear(pgres);
trusts_loaded = 1;
- triggerhook(HOOK_TRUSTS_DBLOADED, NULL);
+ scheduleoneshot(time(NULL), trusts_dbtriggerdbloaded, NULL);
}
+static void trusts_dbtriggerdbloaded(void *arg) {
+ triggerhook(HOOK_TRUSTS_DBLOADED, NULL);
+}
/* trust group */
void trustsdb_addtrustgroup(trustgroup_t *t) {
dbescapestring(escmessage,message, strlen(message));
dbquery("INSERT INTO trusts.log (trustid, timestamp, userid, type, message) VALUES ( %lu, %lu, %lu, %d, '%s')", tg->id, getnettime(), userid, type, escmessage);
}
+
+void trust_dotrustlog_real(DBConn *dbconn, void *arg) {
+ nick *np=getnickbynumeric((unsigned long)arg);
+ DBResult *pgres;
+ unsigned long logid, trustid, userid, type;
+ time_t timestamp;
+ char *message;
+ char timebuf[30];
+ int header=0;
+
+ if(!dbconn)
+ return;
+
+ pgres=dbgetresult(dbconn);
+
+ if (!dbquerysuccessful(pgres)) {
+ Error("trusts", ERR_ERROR, "Error loading trusts log data.");
+ dbclear(pgres);
+ return;
+ }
+
+ if (dbnumfields(pgres) != 6) {
+ Error("trusts", ERR_ERROR, "trusts log data format error.");
+ dbclear(pgres);
+ return;
+ }
+
+ if (!np) {
+ dbclear(pgres);
+ return;
+ }
+
+ while(dbfetchrow(pgres)) {
+ logid=strtoul(dbgetvalue(pgres, 0), NULL, 10);
+ trustid=strtoul(dbgetvalue(pgres, 1), NULL, 10);
+ timestamp=strtoul(dbgetvalue(pgres, 2), NULL, 10);
+ userid=strtoul(dbgetvalue(pgres, 3), NULL, 10);
+ type=strtoul(dbgetvalue(pgres, 4), NULL, 10);
+ message=dbgetvalue(pgres, 5);
+
+ if (!header) {
+ header=1;
+ controlreply(np, "Display trustlog for trust %lu", trustid);
+ controlreply(np, "ID Time OperID Type Message");
+ }
+ strftime(timebuf, 30, "%d/%m/%y %H:%M", localtime(×tamp));
+ controlreply(np, "%-3lu %s %-7lu %-2lu %s", logid, timebuf, userid, type, message);
+ }
+
+ if (!header) {
+ controlreply(np, "No trust log entries found.");
+ } else {
+ controlreply(np, "End Of List.");
+ }
+ dbclear(pgres);
+}
+
+
+void trustsdb_retrievetrustlog(nick *np, unsigned int trustid, time_t starttime) {
+ dbasyncquery(trust_dotrustlog_real, (void *)np->numeric, "SELECT * FROM trusts.log WHERE trustid=%u AND timestamp>%lu order by timestamp desc limit 1000", trustid, starttime);
+ Error("trusts", ERR_ERROR, "SELECT * FROM trusts.log WHERE trustid=%u AND timestamp>%lu order by timestamp desc limit 1000", trustid, starttime);
+}
trustgroup_t *tg = NULL;
patricia_node_t *parent;
+ if (trusts_ignore_np(np)) {
+ return;
+ }
+
if(np->ipnode->exts[tgh_ext]) {
/* we have a new user on a trust group host */
tgh = (trusthost_t *)np->ipnode->exts[tgh_ext];
}
/* Trust Checks Passed: OK - increment counters */
increment_trust_ipnode(np->ipnode);
+
+ /* set nick extension for user for future use */
+ np->exts[tgn_ext] = tgh;
+
return;
}
/* non trusted user - OK */
Error("nodecount", ERR_ERROR, "np->ipnode->exts was NULL");
}
+ if (trusts_ignore_np(np)) {
+ return;
+ }
+
decrement_trust_ipnode(np->ipnode);
if(np->ipnode->exts[tgh_ext]) {
decrement_ident_count(np, tg);
}
}
+
+ /* clear nick extension */
+ np->exts[tgn_ext] = NULL;
}
void trusthost_free(trusthost_t* t)
{
trusts_removetrusthostfromhash(t);
+
derefnode(iptree,t->node);
freetrusthost(t);
}
time_t timenow;
if(!tgh) {
+ Error("trusts", ERR_FATAL, "trusthostadd failed to createtrusthost");
return NULL;
}
if (pnp ) {
for (i = 0; i < PATRICIANICK_HASHSIZE; i++) {
for (np = pnp->identhash[i]; np; np=np->exts[pnick_ext]) {
+ if (trusts_ignore_np(np)) {
+ continue;
+ }
increment_ident_count(np, tg);
}
}
if (pnp ) {
for (i = 0; i < PATRICIANICK_HASHSIZE; i++) {
for (np = pnp->identhash[i]; np; np=np->exts[pnick_ext]) {
+ if (trusts_ignore_np(np)) {
+ continue;
+ }
increment_ident_count(np, tg);
+ np->exts[tgn_ext] = tgh;
}
}
}
trustgroupidentcount_t *getnewtrustgroupidentcount(trustgroup_t *tg, char *ident) {
trustgroupidentcount_t *tgic = newtrustgroupidentcount();
tgic->ident = getsstring(ident,USERLEN);
- tgic->currenton = 1;
+ tgic->currenton = 1;
tgic->trustgroup = tg;
trusts_addtrustgroupidenttohash(tgic);