From: Gunnar Beutner Date: Sat, 20 Jul 2013 20:11:08 +0000 (+0200) Subject: Merge shroudcloak. X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/commitdiff_plain/d813ed1e568bc45e9959e6dd1ca3194f657b6fb1?hp=b765396dabc996ee84670502b53ef77395b1c0ff Merge shroudcloak. --- diff --git a/chanserv/chancmds/addchan.c b/chanserv/chancmds/addchan.c index ec4e13cb..a77e2258 100644 --- a/chanserv/chancmds/addchan.c +++ b/chanserv/chancmds/addchan.c @@ -37,7 +37,7 @@ int csc_doaddchan(void *source, int cargc, char **cargv) { reguser *founder; flag_t flags; short type=0; - unsigned int i; + unsigned int i, count; void *args[3]; if (!rup) @@ -102,7 +102,19 @@ int csc_doaddchan(void *source, int cargc, char **cargv) { chanservstdmessage(notify, QM_ALREADYREGISTERED, cip->name->content); return CMD_ERROR; } - + + count = 0; + + for (rcup=founder->knownon;rcup;rcup=rcup->nextbyuser) + count++; + + if (count > MAXCHANNELS) { + chanservstdmessage(sender, QM_TOOMANYCHANNELS, cip->name->content); + if (notify) + chanservstdmessage(sender, QM_TOOMANYCHANNELS, cip->name->content); + return CMD_ERROR; + } + /* Initialise the channel */ rcp=getregchan(); diff --git a/chanserv/chancmds/adduser.c b/chanserv/chancmds/adduser.c index 556b32ac..b5e544f1 100644 --- a/chanserv/chancmds/adduser.c +++ b/chanserv/chancmds/adduser.c @@ -33,12 +33,12 @@ int csc_doadduser(void *source, int cargc, char **cargv) { nick *sender=source; chanindex *cip; - regchanuser *rcup, *rcuplist; + regchanuser *rcup, *trcup, *rcuplist; regchan *rcp; reguser *rup; flag_t addflags; char *flagbuf; - unsigned int count=0; + unsigned int chanlevcount=0, channelcount=0; int added=0; int i, foundflags=0; void *args[3]; @@ -82,9 +82,9 @@ int csc_doadduser(void *source, int cargc, char **cargv) { flagbuf=printflags(addflags, rcuflags); /* ugh */ - for (count=i=0;iregusers[i];rcuplist;rcuplist=rcuplist->nextbychan) - count++; + chanlevcount++; /* If we found flags don't try to add them as a user as well.. */ for (i=1+foundflags;i= MAXCHANLEVS) { + if(chanlevcount++ >= MAXCHANLEVS) { chanservstdmessage(sender, QM_TOOMANYCHANLEVS); chanservstdmessage(sender, QM_DONE); return CMD_OK; } + channelcount=0; + for (trcup=rup->knownon;trcup;trcup=trcup->nextbyuser) + channelcount++; + + if(channelcount >= MAXCHANNELS) { + chanservstdmessage(sender, QM_TOOMANYCHANNELS); + return CMD_ERROR; + } + rcup=getregchanuser(); rcup->chan=rcp; rcup->user=rup; diff --git a/chanserv/chancmds/chanlev.c b/chanserv/chancmds/chanlev.c index ee0588e7..3a9e6678 100644 --- a/chanserv/chancmds/chanlev.c +++ b/chanserv/chancmds/chanlev.c @@ -90,7 +90,7 @@ int csc_dochanlev(void *source, int cargc, char **cargv) { nick *sender=source; chanindex *cip; regchan *rcp; - regchanuser *rcup, *rcuplist; + regchanuser *rcup, *trcup, *rcuplist; regchanuser **rusers; reguser *rup=getreguserfromnick(sender), *target; char time1[TIMELEN],time2[TIMELEN]; @@ -267,17 +267,26 @@ int csc_dochanlev(void *source, int cargc, char **cargv) { if (!rcuplist) { /* new user, we could store a count instead... that's probably better... */ - unsigned int count; + unsigned int chanlevcount, channelcount; - for (count=i=0;iregusers[i];rcuplist;rcuplist=rcuplist->nextbychan) - count++; + chanlevcount++; - if(count >= MAXCHANLEVS) { + if(chanlevcount >= MAXCHANLEVS) { chanservstdmessage(sender, QM_TOOMANYCHANLEVS); return CMD_ERROR; } - + + channelcount=0; + for (trcup=target->knownon;trcup;trcup=trcup->nextbyuser) + channelcount++; + + if(channelcount >= MAXCHANNELS) { + chanservstdmessage(sender, QM_TOOMANYCHANNELS); + return CMD_ERROR; + } + rcuplist=getregchanuser(); rcuplist->user=target; rcuplist->chan=rcp; diff --git a/chanserv/chanserv.h b/chanserv/chanserv.h index e9539b87..280a3977 100644 --- a/chanserv/chanserv.h +++ b/chanserv/chanserv.h @@ -113,6 +113,9 @@ #define MAXCHANLEVS 500 #define MAXBANS 50 +/* Maximum number of channels a user may be known on */ +#define MAXCHANNELS 500 + /* Sources of entropy and standard length defines */ #define ENTROPYSOURCE "/dev/urandom" #define ENTROPYLEN 8 diff --git a/chanserv/chanserv_messages.h b/chanserv/chanserv_messages.h index d31b09c9..e18dbac8 100644 --- a/chanserv/chanserv_messages.h +++ b/chanserv/chanserv_messages.h @@ -56,6 +56,7 @@ BeginMessages() { msg(QM_NOCHANBANAUTOREMOVE, "Bans on $0 will not be automatically removed.", "s"), msg(QM_INVALIDCHANNAME, "$0 is not a valid channel name.", "s"), msg(QM_ALREADYREGISTERED, "$0 is already registered.", "s"), + msg(QM_TOOMANYCHANNELS, "User is known on too many channels.", ""), msg(QM_CURUSERFLAGS, "User flags for $0: $1", "ss"), msg(QM_WELCOMEMESSAGEIS, "Welcome message for $0: $1", "ss"), msg(QM_GLOBALINFO, "Default info line: $0", "s"), diff --git a/core/modules.c b/core/modules.c index 08a17497..6cdf2e42 100644 --- a/core/modules.c +++ b/core/modules.c @@ -22,7 +22,7 @@ #define DEPFILE "modules.dep" -#define MAXMODULES 100 +#define MAXMODULES 200 /* Module dependency stuff. * diff --git a/fakeq/fakeq.c b/fakeq/fakeq.c index 42ed422d..b8792deb 100644 --- a/fakeq/fakeq.c +++ b/fakeq/fakeq.c @@ -1,3 +1,4 @@ +#define CS_NODB #include "../chanserv/chanserv.h" static nick *fakeq; diff --git a/invalidbans/Makefile.in b/invalidbans/Makefile.in new file mode 100644 index 00000000..d6c3686b --- /dev/null +++ b/invalidbans/Makefile.in @@ -0,0 +1,6 @@ +@include@ @includel@../build.mk@includel@ + +.PHONY: all +all: invalidbans.so + +invalidbans.so: invalidbans.o diff --git a/invalidbans/invalidbans.c b/invalidbans/invalidbans.c new file mode 100644 index 00000000..5abc427d --- /dev/null +++ b/invalidbans/invalidbans.c @@ -0,0 +1,149 @@ +#include +#include "../core/schedule.h" +#include "../control/control.h" +#include "../lib/irc_string.h" +#include "../localuser/localuserchannel.h" +#include "../lib/version.h" + +MODULE_VERSION(""); + +static int ib_nickext; + +typedef struct ibnick { + time_t timeout; + void *sched; +} ibnick; + +static void ib_clear_ext(void *arg) { + nick *np = arg; + + if (!np->exts[ib_nickext]) + return; + + free(np->exts[ib_nickext]); + np->exts[ib_nickext] = NULL; +} + +static void ib_hook_newnick(int hooknum, void *arg) { + nick *np = arg; + np->exts[ib_nickext] = NULL; +} + +static void ib_hook_lostnick(int hooknum, void *arg) { + nick *np = arg; + ibnick *inp = np->exts[ib_nickext]; + + if (!inp) + return; + + deleteschedule(inp->sched, ib_clear_ext, np); + free(np->exts[ib_nickext]); +} + +static void ib_hook_modechange(int hooknum, void *arg) { + void **arglist=(void **)arg; + channel *cp=(channel *)arglist[0]; + nick *np=(nick *)arglist[1]; + long changeflags=(long)arglist[2]; + chanban *cbp; + const char *p; + int colons, colonsnext; + modechanges changes; + ibnick *inp; + char *mask, *pos; + int slot, i; + array bans; + + if (!(changeflags & MODECHANGE_BANS)) + return; + + inp = np->exts[ib_nickext]; + + /* Ignore the mode change if the same user has recently + * set/unset a channel ban. */ + if (inp && inp->timeout > time(NULL)) + return; + + if (inp) { + deleteschedule(inp->sched, ib_clear_ext, np); + free(inp); + np->exts[ib_nickext] = NULL; + } + + array_init(&bans, 512); + + for (cbp = cp->bans; cbp; cbp = cbp->next) { + if (!cbp->host) + continue; + + colons = 0; + colonsnext = 0; + + for (p = cbp->host->content; *p; p++) { + if (*p == ':') { + colons++; + + if (*(p + 1) == ':') + colonsnext = 1; + } + } + + if (colons - colonsnext >= 8) { + slot = array_getfreeslot(&bans); + mask = ((char *)bans.content) + slot * 512; + strncpy(mask, bantostring(cbp), 512); + } + } + + if (bans.cursi > 0) { + localsetmodeinit(&changes, cp, NULL); + + for (i = 0; i < bans.cursi; i++) { + mask = ((char *)bans.content) + i * 512; + + pos = strchr(mask, '@'); + + if (!pos) + continue; /* This should never happen. */ + + pos++; /* Skip over the @ sign. */ + + for (; *pos; pos++) { + if (*pos != ':') { + *pos = '?'; + break; + } + } + + localdosetmode_ban(&changes, mask, MCB_ADD); + } + + localsetmodeflush(&changes, 1); + + /* Ignore the user for a short amount of time. If it's a bot + * it'll probably try re-setting the ban immediately. */ + inp = malloc(sizeof(ibnick)); + inp->timeout = time(NULL) + 15; + inp->sched = scheduleoneshot(inp->timeout + 1, ib_clear_ext, np); + np->exts[ib_nickext] = inp; + } + + array_free(&bans); +} + +void _init() { + registerhook(HOOK_NICK_NEWNICK, &ib_hook_newnick); + registerhook(HOOK_NICK_LOSTNICK, &ib_hook_lostnick); + registerhook(HOOK_CHANNEL_MODECHANGE, &ib_hook_modechange); + + ib_nickext = registernickext("invalidbans"); +} + +void _fini () { + deregisterhook(HOOK_NICK_NEWNICK, &ib_hook_newnick); + deregisterhook(HOOK_NICK_LOSTNICK, &ib_hook_lostnick); + deregisterhook(HOOK_CHANNEL_MODECHANGE, &ib_hook_modechange); + + releasenickext(ib_nickext); +} + diff --git a/newsearch/ns-gline.c b/newsearch/ns-gline.c index 30b11337..55dbcab4 100644 --- a/newsearch/ns-gline.c +++ b/newsearch/ns-gline.c @@ -134,7 +134,8 @@ void *gline_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput) { if (ctx->searchcmd == reg_chansearch) { cip = (chanindex *)theinput; cip->marker = localdata->marker; - localdata->count += cip->channel->users->totalusers; + if (cip->channel != NULL) + localdata->count += cip->channel->users->totalusers; } else { np = (nick *)theinput; diff --git a/nick/nickhandlers.c b/nick/nickhandlers.c index ad45b24a..db496319 100644 --- a/nick/nickhandlers.c +++ b/nick/nickhandlers.c @@ -128,10 +128,6 @@ int handlenickmsg(void *source, int cargc, char **cargv) { } base64toip(cargv[cargc-3], &ipaddress); - if (!irc_in_addr_valid(&ipaddress)) { - Error("nick",ERR_ERROR,"Received NICK with invalid ipaddress for %s from %s.",cargv[0],sender); - return CMD_ERROR; - } /* At this stage the nick is cleared to proceed */ np=newnick(); diff --git a/request/Makefile.in b/request/Makefile.in index 2e1b6aa8..22f02d88 100644 --- a/request/Makefile.in +++ b/request/Makefile.in @@ -6,4 +6,4 @@ LDFLAGS+=$(LIBPGSQL) .PHONY: all all: request.so -request.so: lrequest.o request.o request_block.o sqrequest.o user.o +request.so: lrequest.o request.o request_block.o request_fasttrack.o sqrequest.o diff --git a/request/lrequest.c b/request/lrequest.c index f8da1b2a..51d7ebd8 100644 --- a/request/lrequest.c +++ b/request/lrequest.c @@ -5,13 +5,12 @@ #include "request.h" #include "lrequest.h" #include "request_block.h" +#include "request_fasttrack.h" #include "../localuser/localuser.h" /* stats counters */ -int lr_noregops = 0; -int lr_scoretoolow = 0; int lr_top5 = 0; -int lr_floodattempts = 0; +int lr_notargets = 0; #define min(a,b) ((a > b) ? b : a) @@ -30,56 +29,38 @@ int lr_requestl(nick *svc, nick *np, channel *cp, nick *qnick) { cf = cf_findchanfix(cp->index); - if (cf == NULL) { - sendnoticetouser(svc, np, "Sorry, your channel '%s' was created recently. " - "Please try again in an hour.", cp->index->name->content); + if(cf) { + rocount = cf_getsortedregops(cf, LR_TOPX, rolist); - lr_noregops++; + ro = NULL; - return RQ_ERROR; - } - - rocount = cf_getsortedregops(cf, LR_TOPX, rolist); - - ro = NULL; - - for (i = 0; i < min(LR_TOPX, rocount); i++) { - if (cf_cmpregopnick(rolist[i], np)) { - ro = rolist[i]; - break; + for (i = 0; i < min(LR_TOPX, rocount); i++) { + if (cf_cmpregopnick(rolist[i], np)) { + ro = rolist[i]; + break; + } } - } - if (ro == NULL) { - sendnoticetouser(svc, np, "Sorry, you must be one of the top %d ops " - "for the channel '%s'.", LR_TOPX, cp->index->name->content); + if (ro == NULL) { + sendnoticetouser(svc, np, "Sorry, you must be one of the top %d ops " + "for the channel '%s'.", LR_TOPX, cp->index->name->content); - lr_top5++; - - return RQ_ERROR; - } - - /* treat blocked users as if their score is too low */ - if (ro->score < LR_CFSCORE || rq_findblock(np->authname)) { - if (rq_isspam(np)) { - sendnoticetouser(svc, np, "Do not flood the request system. " - "Try again in %s.", rq_longtoduration(rq_blocktime(np))); - - lr_floodattempts++; + lr_top5++; return RQ_ERROR; } + } - sendnoticetouser(svc, np, "Sorry, you do not meet the " - "%s request requirements; please try again in an hour, " - "see http://www.quakenet.org/faq/faq.php?c=1&f=6#6", RQ_QNICK); + /* treat blocked users as if they're out of targets */ + if(rq_findblock(np->authname) || !rq_tryfasttrack(np)) { + sendnoticetouser(svc, np, "Sorry, you may not request %s for another " + "channel at this time. Please try again in an hour.", RQ_QNICK); - lr_scoretoolow++; + lr_notargets++; return RQ_ERROR; } - sendmessagetouser(svc, qnick, "addchan %s #%s +jp upgrade %s", cp->index->name->content, np->authname, np->nick); @@ -91,8 +72,6 @@ int lr_requestl(nick *svc, nick *np, channel *cp, nick *qnick) { } void lr_requeststats(nick *rqnick, nick *np) { - sendnoticetouser(rqnick, np, "- No registered ops (Q): %d", lr_noregops); - sendnoticetouser(rqnick, np, "- Score too low (Q): %d", lr_scoretoolow); + sendnoticetouser(rqnick, np, "- Too many requests (Q): %d", lr_notargets); sendnoticetouser(rqnick, np, "- Not in top%d (Q): %d", LR_TOPX, lr_top5); - sendnoticetouser(rqnick, np, "- Floods (Q): %d", lr_floodattempts); } diff --git a/request/request.c b/request/request.c index 2cd84a36..823da228 100644 --- a/request/request.c +++ b/request/request.c @@ -12,9 +12,9 @@ #include "../splitlist/splitlist.h" #include "request.h" #include "request_block.h" +#include "request_fasttrack.h" #include "lrequest.h" #include "sqrequest.h" -#include "user.h" MODULE_VERSION(""); @@ -33,11 +33,6 @@ int rqcmd_listblocks(void *user, int cargc, char **cargv); int rqcmd_stats(void *user, int cargc, char **cargv); int rqcmd_requestop(void *user, int cargc, char **cargv); -int rqcmd_adduser(void *user, int cargc, char **cargv); -int rqcmd_deluser(void *user, int cargc, char **cargv); -int rqcmd_changelev(void *user, int cargc, char **cargv); -int rqcmd_userlist(void *user, int cargc, char **cargv); - #define min(a,b) ((a > b) ? b : a) /* stats counters */ @@ -55,6 +50,9 @@ void _init(void) { if(!rq_initblocks()) return; + if(!rq_initfasttrack()) + return; + extloaded = 1; rqcommands = newcommandtree(); @@ -64,18 +62,12 @@ void _init(void) { addcommandtotree(rqcommands, "requestspamscan", RQU_ANY, 1, &rqcmd_requestspamscan); addcommandtotree(rqcommands, "requestop", RQU_ANY, 2, &rqcmd_requestop); - addcommandtotree(rqcommands, "addblock", RQU_ACCOUNT, 3, &rqcmd_addblock); - addcommandtotree(rqcommands, "delblock", RQU_ACCOUNT, 1, &rqcmd_delblock); - addcommandtotree(rqcommands, "listblocks", RQU_ACCOUNT, 1, &rqcmd_listblocks); - addcommandtotree(rqcommands, "stats", RQU_ACCOUNT, 1, &rqcmd_stats); - - addcommandtotree(rqcommands, "adduser", RQU_OPER, 2, &rqcmd_adduser); - addcommandtotree(rqcommands, "deluser", RQU_OPER, 1, &rqcmd_deluser); - addcommandtotree(rqcommands, "changelev", RQU_OPER, 2, &rqcmd_changelev); - addcommandtotree(rqcommands, "userlist", RQU_OPER, 1, &rqcmd_userlist); + addcommandtotree(rqcommands, "addblock", RQU_OPER, 3, &rqcmd_addblock); + addcommandtotree(rqcommands, "delblock", RQU_OPER, 1, &rqcmd_delblock); + addcommandtotree(rqcommands, "listblocks", RQU_OPER, 1, &rqcmd_listblocks); + addcommandtotree(rqcommands, "stats", RQU_OPER, 1, &rqcmd_stats); qr_initrequest(); - ru_load(); rq_logfd = fopen(RQ_LOGFILE, "a"); @@ -98,16 +90,11 @@ void _fini(void) { deletecommandfromtree(rqcommands, "listblocks", &rqcmd_listblocks); deletecommandfromtree(rqcommands, "stats", &rqcmd_stats); - deletecommandfromtree(rqcommands, "adduser", &rqcmd_adduser); - deletecommandfromtree(rqcommands, "deluser", &rqcmd_deluser); - deletecommandfromtree(rqcommands, "changelev", &rqcmd_changelev); - deletecommandfromtree(rqcommands, "userlist", &rqcmd_userlist); - destroycommandtree(rqcommands); rq_finiblocks(); + rq_finifasttrack(); qr_finirequest(); - ru_persist(); if (rq_logfd != NULL) fclose(rq_logfd); @@ -119,7 +106,7 @@ void rq_registeruser(void) { channel *cp; rqnick = registerlocaluserflags(RQ_REQUEST_NICK, RQ_REQUEST_USER, RQ_REQUEST_HOST, - RQ_REQUEST_REAL, RQ_REQUEST_AUTH, 1780711, 0, + RQ_REQUEST_REAL, RQ_REQUEST_AUTH, RQ_REQUEST_AUTHID, 0, UMODE_ACCOUNT | UMODE_SERVICE | UMODE_OPER, rq_handler); @@ -175,13 +162,6 @@ void rq_handler(nick *target, int type, void **params) { return; } - if ((cmd->level & RQU_ACCOUNT) && (!IsAccount(user) || ru_getlevel(user) == 0) && !IsOper(user)) { - sendnoticetouser(rqnick, user, "Sorry, this command is not " - "available to you."); - - return; - } - if (cargc - 1 > cmd->maxparams) rejoinline(cargv[cmd->maxparams], cargc - cmd->maxparams); @@ -214,9 +194,6 @@ int rqcmd_showcommands(void *user, int cargc, char **cargv) { if ((cmdlist[i]->level & RQU_OPER) && !IsOper(np)) continue; - if ((cmdlist[i]->level & RQU_ACCOUNT) && !(IsOper(np) || (IsAccount(np) && ru_getlevel(np) > 0))) - continue; - sendnoticetouser(rqnick, np, "%s", cmdlist[i]->command->content); } @@ -567,9 +544,8 @@ int rqcmd_addblock(void *user, int cargc, char **cargv) { rq_block *block; time_t expires; char *account; - int level = ru_getlevel(np); - if (level < 20) { + if (!IsOper(np)) { sendnoticetouser(rqnick, np, "You do not have access to this command."); return RQ_ERROR; @@ -597,12 +573,6 @@ int rqcmd_addblock(void *user, int cargc, char **cargv) { expires = getnettime() + durationtolong(cargv[1]); - if (expires > getnettime() + RQU_HELPER_MAXEXPIRE && level < 30) { - sendnoticetouser(rqnick, np, "Maximum expiry time is %s.", rq_longtoduration(RQU_HELPER_MAXEXPIRE)); - - return RQ_ERROR; - } - rq_addblock(cargv[0], cargv[2], account, 0, expires); sendnoticetouser(rqnick, np, "Blocked channels/accounts matching '%s' from " @@ -613,12 +583,9 @@ int rqcmd_addblock(void *user, int cargc, char **cargv) { int rqcmd_delblock(void *user, int cargc, char **cargv) { nick *np = (nick*)user; - int result, level; - rq_block *block; + int result; - level = ru_getlevel(np); - - if (level < 20) { + if (!IsOper(np)) { sendnoticetouser(rqnick, np, "You do not have access to this command."); return RQ_ERROR; @@ -630,16 +597,6 @@ int rqcmd_delblock(void *user, int cargc, char **cargv) { return RQ_ERROR; } - block = rq_findblock(cargv[0]); - - if (block != NULL && level < 50) { - if (ircd_strcmp(block->creator->content, np->authname) != 0) { - sendnoticetouser(rqnick, np, "This block was created by someone else. You cannot remove it."); - - return RQ_ERROR; - } - } - result = rq_removeblock(cargv[0]); if (result > 0) { @@ -656,11 +613,9 @@ int rqcmd_delblock(void *user, int cargc, char **cargv) { int rqcmd_listblocks(void *user, int cargc, char **cargv) { nick *np = (nick*)user; rq_block block; - int i, level; + int i; - level = ru_getlevel(np); - - if (level < 10) { + if (!IsOper(np)) { sendnoticetouser(rqnick, np, "You do not have access to this command."); return RQ_ERROR; @@ -690,9 +645,8 @@ int rqcmd_listblocks(void *user, int cargc, char **cargv) { int rqcmd_stats(void *user, int cargc, char **cargv) { nick *np = (nick*)user; - int level = ru_getlevel(np); - if (level < 10) { + if (!IsOper(np)) { sendnoticetouser(rqnick, np, "You do not have access to this command."); return RQ_ERROR; @@ -709,112 +663,3 @@ int rqcmd_stats(void *user, int cargc, char **cargv) { return RQ_OK; } -int rqcmd_adduser(void *user, int cargc, char **cargv) { - nick *np = (nick*)user; - int result, level; - - if (cargc < 2) { - sendnoticetouser(rqnick, np, "Syntax: adduser "); - - return RQ_ERROR; - } - - level = atoi(cargv[1]); - - if (level <= 0) { - sendnoticetouser(rqnick, np, "Level must be a positive integer."); - - return RQ_ERROR; - } - - result = ru_create(cargv[0], level); - - if (result) { - sendnoticetouser(rqnick, np, "User '%s' was added with level '%d'.", cargv[0], level); - - return RQ_OK; - } else { - sendnoticetouser(rqnick, np, "Something strange happened. Contact shroud."); - - return RQ_ERROR; - } -} - -int rqcmd_deluser(void *user, int cargc, char **cargv) { - nick *np = (nick*)user; - int level; - - if (cargc < 1) { - sendnoticetouser(rqnick, np, "Syntax: deluser "); - - return RQ_ERROR; - } - - level = ru_getlevel_str(cargv[0]); - - if (level <= 0) { - sendnoticetouser(rqnick, np, "There is no such user."); - - return RQ_ERROR; - } - - ru_destroy(cargv[0]); - - sendnoticetouser(rqnick, np, "Done."); - - return RQ_OK; -} - -int rqcmd_changelev(void *user, int cargc, char **cargv) { - nick *np = (nick*)user; - int result, level; - - if (cargc < 2) { - sendnoticetouser(rqnick, np, "Syntax: changelev "); - - return RQ_ERROR; - } - - level = atoi(cargv[1]); - - if (level <= 0) { - sendnoticetouser(rqnick, np, "Level must be a positive integer."); - - return RQ_ERROR; - } - - if (ru_getlevel_str(cargv[0]) <= 0) { - sendnoticetouser(rqnick, np, "Unknown user."); - - return RQ_ERROR; - } - - result = ru_setlevel(cargv[0], level); - - if (result != 0) { - sendnoticetouser(rqnick, np, "Done."); - - return RQ_OK; - } else { - sendnoticetouser(rqnick, np, "Something strange happened. Contact shroud."); - - return RQ_ERROR; - } -} - -int rqcmd_userlist(void *user, int cargc, char **cargv) { - nick *np = (nick*)user; - r_user_t *userp = r_userlist; - - sendnoticetouser(rqnick, np, "User Level"); - - while (userp) { - sendnoticetouser(rqnick, np, "%s %d", userp->name, userp->level); - userp = userp->next; - } - - sendnoticetouser(rqnick, np, "--- End of USERS."); - - return RQ_OK; -} - diff --git a/request/request.h b/request/request.h index 27409980..c962fa63 100644 --- a/request/request.h +++ b/request/request.h @@ -3,7 +3,7 @@ #define RQ_QSERVER "CServe.quakenet.org" #define RQ_QNICK "Q" -#define RQ_SSERVER "services.de.quakenet.org" +#define RQ_SSERVER "services2.uk.quakenet.org" #define RQ_SNICK "S" #define RQ_REQUEST_NICK "R" @@ -11,15 +11,11 @@ #define RQ_REQUEST_HOST "request.quakenet.org" #define RQ_REQUEST_REAL "Service Request v0.23" #define RQ_REQUEST_AUTH "R" +#define RQ_REQUEST_AUTHID 1780711 #define RQU_ANY 0 #define RQU_OPER 1 -#define RQU_ACCOUNT 2 -/* one week by default */ -#define RQU_HELPER_MAXEXPIRE 604800 - -#define RQ_USERFILE "data/rqusers" #define RQ_LOGFILE "logs/request.log" #define RQ_OK 0 diff --git a/request/request_block.c b/request/request_block.c index fa7f59de..779c87f3 100644 --- a/request/request_block.c +++ b/request/request_block.c @@ -7,19 +7,10 @@ /* array of blocks */ array rqblocks; -/* our anti-flood nick extension */ -int rqnext; - /* are we currently loading blocks? */ int rq_loading; -void rqhook_lostnick(int hook, void *arg); - int rq_initblocks(void) { - rqnext = registernickext("request"); - if(rqnext < 0) - return 0; - array_init(&rqblocks, sizeof(rq_block)); array_setlim1(&rqblocks, 5); array_setlim2(&rqblocks, 20); @@ -31,15 +22,12 @@ int rq_initblocks(void) { rq_addblock("#qnet*", "Reserved for QuakeNet use only.", "request", 0, 0); rq_addblock("#help*", "Reserved for QuakeNet use only.", "request", 0, 0); - registerhook(HOOK_NICK_LOSTNICK, &rqhook_lostnick); - return 1; } void rq_finiblocks(void) { int i; rq_block block; - nick *nip; for (i = 0; i < rqblocks.cursi; i++) { block = ((rq_block*)rqblocks.content)[i]; @@ -50,64 +38,6 @@ void rq_finiblocks(void) { } array_free(&rqblocks); - - for (i=0; inext) - free(nip->exts[rqnext]); - - deregisterhook(HOOK_NICK_LOSTNICK, &rqhook_lostnick); - - releasenickext(rqnext); -} - -void rqhook_lostnick(int hook, void *arg) { - nick *np = (nick*)arg; - - free(np->exts[rqnext]); -} - -int rq_isspam(nick *np) { - rq_flood *lf; - - if (np->exts[rqnext] == NULL) { - np->exts[rqnext] = lf = (rq_flood*)malloc(sizeof(rq_flood)); - - lf->count = 1; - lf->created = getnettime(); - lf->expire = 0; - - return 0; - } else { - lf = np->exts[rqnext]; - - lf->count -= (getnettime() - lf->created) / (RQ_SPAMBLOCK / RQ_SPAMCOUNT); - - if (lf->count < 0) - lf->count = 0; - - if (lf->count > RQ_SPAMCOUNT && lf->expire > getnettime()) { - return 1; - } else { - lf->count++; - - if (lf->count > RQ_SPAMCOUNT) { - lf->expire = getnettime() + RQ_SPAMBLOCK; - - rq_addblock(np->authname, "Flooding the request system.", "request", 0, getnettime() + 3600); - - return 1; - } - - return 0; - } - } -} - -time_t rq_blocktime(nick *np) { - if (np->exts[rqnext] == NULL) - return 0; - else - return ((rq_flood*)np->exts[rqnext])->expire - getnettime(); } rq_block *rq_findblock(const char *pattern) { diff --git a/request/request_block.h b/request/request_block.h index 8a73f898..afca63fb 100644 --- a/request/request_block.h +++ b/request/request_block.h @@ -1,12 +1,6 @@ #include "../nick/nick.h" #include "../channel/channel.h" -typedef struct { - int count; - time_t created; - time_t expire; -} rq_flood; - typedef struct { sstring *pattern; sstring *reason; @@ -21,9 +15,6 @@ extern array rqblocks; #define RQ_BLOCKFILE "data/rqblocks" #define RQ_BLOCKLEN 256 -#define RQ_SPAMCOUNT 5 -#define RQ_SPAMBLOCK 3600 - int rq_initblocks(void); void rq_finiblocks(void); @@ -34,7 +25,3 @@ int rq_saveblocks(void); rq_block *rq_findblock(const char *pattern); void rq_addblock(const char *pattern, const char *reason, const char *creator, time_t created, time_t expires); int rq_removeblock(const char *pattern); - -/* anti-spam blocks */ -int rq_isspam(nick *np); -time_t rq_blocktime(nick *np); diff --git a/request/request_fasttrack.c b/request/request_fasttrack.c new file mode 100644 index 00000000..2663c9dc --- /dev/null +++ b/request/request_fasttrack.c @@ -0,0 +1,149 @@ +#include +#include +#include "../core/schedule.h" +#include "../irc/irc.h" +#include "../lib/irc_string.h" +#include "request_fasttrack.h" + +typedef struct rq_fasttrack { + unsigned long userid; + + unsigned int targets; + time_t refill_time; + + struct rq_fasttrack *next; +} rq_fasttrack; + +static rq_fasttrack *ftlist; + +/* our fast-track extension */ +int rqnext; + +static void rq_cleanup_fasttrack(void *arg); +static void rqhook_account(int hook, void *arg); + +int rq_initfasttrack(void) { + rqnext = registernickext("request_fasttrack"); + if(rqnext < 0) + return 0; + + registerhook(HOOK_NICK_NEWNICK, &rqhook_account); + registerhook(HOOK_NICK_ACCOUNT, &rqhook_account); + + schedulerecurring(time(NULL)+1, 0, 3600, rq_cleanup_fasttrack, NULL); + + return 1; +} + +void rq_finifasttrack(void) { + rq_fasttrack *ft, *next; + + deregisterhook(HOOK_NICK_NEWNICK, &rqhook_account); + deregisterhook(HOOK_NICK_ACCOUNT, &rqhook_account); + + for(ft=ftlist;ft;) { + next = ft->next; + free(ft); + ft = next; + } + + releasenickext(rqnext); +} + +static void rqhook_account(int hook, void *arg) { + nick *np = (nick *)arg; + rq_fasttrack *ft; + + /* Auth might be null for the newnick hook. */ + if(!np->auth) + return; + + /* Try to find an existing fasttrack record for this user. */ + for(ft=ftlist;ft;ft=ft->next) { + if(np->auth->userid==ft->userid) { + np->exts[rqnext] = ft; + break; + } + } +} + +static void rq_cleanup_fasttrack(void *arg) { + time_t now = getnettime(); + rq_fasttrack **pft, *ft; + int j; + nick *tnp; + + now = getnettime(); + + pft = &ftlist; + + for(ft=*pft;*pft;pft=&((*pft)->next)) { + int foundnick = 0; + + for(j=0;jnext) { + if(tnp->exts[rqnext]==ft) { + foundnick = 1; + break; + } + } + } + + if(!foundnick && ft->refill_time < now) { + *pft = ft->next; + free(ft); + } + + if (!*pft) + break; + } +} + +static rq_fasttrack *rq_getfasttrack(nick *np) { + rq_fasttrack *ft; + + /* Use an existing fast-track record if the nick has one. */ + if(np->exts[rqnext]) + return np->exts[rqnext]; + + if(!np->auth) + return NULL; + + ft = malloc(sizeof(rq_fasttrack)); + + if(!ft) + return NULL; + + ft->userid = np->auth->userid; + ft->targets = 0; + ft->refill_time = 0; + + ft->next = ftlist; + ftlist = ft; + + np->exts[rqnext] = ft; + + return ft; +} + +int rq_tryfasttrack(nick *np) { + rq_fasttrack *ft = rq_getfasttrack(np); + + /* Don't fast-track if we can't find a fast-track record. */ + if(!ft) + return 0; + + /* Refill targets if necessary. */ + if(getnettime() > ft->refill_time) { + ft->targets = RQ_FASTTRACK_TARGETS; + ft->refill_time = getnettime() + RQ_FASTTRACK_TIMEOUT; + } + + /* Check if we have a free target. */ + if(ft->targets==0) + return 0; + + ft->targets--; + return 1; +} + diff --git a/request/request_fasttrack.h b/request/request_fasttrack.h new file mode 100644 index 00000000..884d8b16 --- /dev/null +++ b/request/request_fasttrack.h @@ -0,0 +1,10 @@ +#include "../nick/nick.h" +#include "../channel/channel.h" + +#define RQ_FASTTRACK_TARGETS 2 +#define RQ_FASTTRACK_TIMEOUT (60 * 60) + +int rq_initfasttrack(void); +void rq_finifasttrack(void); + +int rq_tryfasttrack(nick *np); diff --git a/request/sqrequest.c b/request/sqrequest.c index 025be5cc..1857b575 100644 --- a/request/sqrequest.c +++ b/request/sqrequest.c @@ -730,21 +730,10 @@ int qr_instantrequestq(nick *sender, channel *cp) { int qr_requests(nick *rqnick, nick *sender, channel *cp, nick *qnick) { chanindex *cip = cp->index; - int who = 0; requestrec *nextreq, *lastreq; - if (rq_isspam(sender)) { - sendnoticetouser(rqnick, sender, "Do not flood the request system." - " Try again in %s.", rq_longtoduration(rq_blocktime(sender))); - - return RQ_ERROR; - } - /* check which service is on the channel */ if (getnumerichandlefromchanhash(cp->users, qnick->numeric) != NULL) { - /* we've found Q */ - who = QR_Q; - /* Request stats from Q */ sendmessagetouser(rqnick, qnick, "CHANLEV %s", cip->name->content); @@ -809,10 +798,10 @@ void qr_finirequest(void) { void qr_requeststats(nick *rqnick, nick *np) { sendnoticetouser(rqnick, np, "- Suspended (S): %d", qr_suspended); - sendnoticetouser(rqnick, np, "- No chanstats (S): %d", qr_nohist); - sendnoticetouser(rqnick, np, "- Too small (S): %d", qr_toosmall); - sendnoticetouser(rqnick, np, "- User was not on chanlev (S): %d", qr_nochanlev); - sendnoticetouser(rqnick, np, "- User was not the owner (S): %d", qr_notowner); + sendnoticetouser(rqnick, np, "- No chanstats (S): %d", qr_nohist); + sendnoticetouser(rqnick, np, "- Too small (S): %d", qr_toosmall); + sendnoticetouser(rqnick, np, "- User was not on chanlev (S): %d", qr_nochanlev); + sendnoticetouser(rqnick, np, "- User was not the owner (S): %d", qr_notowner); sendnoticetouser(rqnick, np, "- A: %d", qr_a); sendnoticetouser(rqnick, np, "- B: %d", qr_b); sendnoticetouser(rqnick, np, "- C: %d", qr_c); diff --git a/request/user.c b/request/user.c deleted file mode 100644 index 563591f0..00000000 --- a/request/user.c +++ /dev/null @@ -1,192 +0,0 @@ -#include -#include - -#include "../irc/irc_config.h" -#include "../lib/irc_string.h" -#include "../lib/strlfunc.h" -#include "../nick/nick.h" -#include "request.h" -#include "user.h" - -r_user_t *r_userlist = NULL; -int ru_loading = 0; - -r_user_t *ru_find(char *name); - -int ru_create(char *name, unsigned int level) { - r_user_t *user, *trav; - - if (ru_setlevel(name, level) != 0) - return 1; - - user = (r_user_t*)malloc(sizeof(r_user_t)); - - if (user == NULL) - return 0; - - user->next = NULL; - strlcpy(user->name, name, sizeof(user->name)); - user->level = level; - - if (r_userlist == NULL) - r_userlist = user; - else { - trav = r_userlist; - - while (trav->next) - trav = trav->next; - - trav->next = user; - } - - ru_persist(); - - return 1; -} - -void ru_destroy(char *name) { - r_user_t *puser; - r_user_t *user = r_userlist; - - if (user && ircd_strcmp(user->name, name) == 0) { - free(r_userlist); - - r_userlist = NULL; - - ru_persist(); - - return; - } - - if (user == NULL) - return; - - while (user && user->next) { - if (ircd_strcmp(user->next->name, name) == 0) { - puser = user->next; - user->next = user->next->next; - - free(puser); - } - - user = user->next; - } - - ru_persist(); -} - -int ru_parseline(char *line) { - char name[ACCOUNTLEN]; - unsigned int level; - int result; - - if (sscanf(line, "%s %u", name, &level) < 2) - return 0; - - ru_loading = 1; - result = ru_create(name, level); - ru_loading = 0; - - return result; -} - -int ru_load(void) { - char line[4096]; - FILE *rudata; - int count; - - rudata = fopen(RQ_USERFILE, "r"); - - if (rudata == NULL) - return 0; - - count = 0; - - while (!feof(rudata)) { - if (fgets(line, sizeof(line), rudata) == NULL) - break; - - if (line[strlen(line) - 1] == '\n') - line[strlen(line) - 1] = '\0'; - - if (line[strlen(line) - 1] == '\r') - line[strlen(line) - 1] = '\0'; - - if (line[0] != '\0') { - if (ru_parseline(line)) - count++; - } - } - - fclose(rudata); - - return count; -} - -int ru_persist(void) { - FILE *rudata; - int count = 0; - r_user_t *user = r_userlist; - - if (ru_loading) - return 0; - - rudata = fopen(RQ_USERFILE, "w"); - - if (rudata == NULL) - return 0; - - while (user) { - fprintf(rudata, "%s %u\n", user->name, user->level); - - user = user->next; - } - - fclose(rudata); - - return count; -} - -r_user_t *ru_find(char *name) { - r_user_t *user = r_userlist; - - while (user) { - if (ircd_strcmp(user->name, name) == 0) - return user; - - user = user->next; - } - - return NULL; -} - -unsigned int ru_getlevel(nick *np) { - if (IsOper(np)) - return 999; - else if (!IsAccount(np)) - return 0; - - return ru_getlevel_str(np->authname); -} - -unsigned int ru_getlevel_str(char *name) { - r_user_t *user = ru_find(name); - - if (user) - return user->level; - else - return 0; -} - -int ru_setlevel(char *name, unsigned int level) { - r_user_t *user = ru_find(name); - - if (user) { - user->level = level; - - ru_persist(); - - return 1; - } else - return 0; -} diff --git a/request/user.h b/request/user.h deleted file mode 100644 index 09b08164..00000000 --- a/request/user.h +++ /dev/null @@ -1,18 +0,0 @@ -/* R user system */ - -typedef struct r_user_s { - struct r_user_s *next; - char name[ACCOUNTLEN]; - unsigned int level; -} r_user_t; - -extern r_user_t *r_userlist; - -int ru_load(void); -int ru_persist(void); - -int ru_create(char *name, unsigned int level); -void ru_destroy(char *name); -unsigned int ru_getlevel(nick *np); -unsigned int ru_getlevel_str(char *name); -int ru_setlevel(char *name, unsigned int level); diff --git a/whowas/Makefile.in b/whowas/Makefile.in new file mode 100644 index 00000000..b6f9648a --- /dev/null +++ b/whowas/Makefile.in @@ -0,0 +1,5 @@ +@include@ @includel@../build.mk@includel@ +.PHONY: all +all: whowas.so + +whowas.so: whowas.o diff --git a/whowas/whowas.c b/whowas/whowas.c new file mode 100644 index 00000000..2132e90f --- /dev/null +++ b/whowas/whowas.c @@ -0,0 +1,121 @@ +#include +#include +#include "../core/hooks.h" +#include "../control/control.h" +#include "../irc/irc.h" +#include "../lib/irc_string.h" +#include "whowas.h" + +static whowas *wwhead, *wwtail; +static int wwcount; + +int ww_cmdwhowas(void *source, int cargc, char **cargv) { + nick *np = source; + char *pattern; + whowas *ww; + char hostmask[WW_MASKLEN+1]; + char timebuf[30]; + int matches = 0, limit = 500; + + if(cargc<1) + return CMD_USAGE; + + pattern = cargv[0]; + + if(cargc>1) + limit = strtol(cargv[1], NULL, 10); + + for(ww=wwhead;ww;ww=ww->next) { + snprintf(hostmask, sizeof(hostmask), "%s!%s@%s", ww->nick, ww->ident, ww->host); + + if (match2strings(pattern, hostmask)) { + matches++; + + if(matches<=limit) { + strftime(timebuf, 30, "%d/%m/%y %H:%M:%S", localtime(&(ww->seen))); + + controlreply(np, "[%s] %s (%s): %s", timebuf, hostmask, ww->realname, ww->reason->content); + } else if(matches==limit+1) { + controlreply(np, "--- More than %d matches, skipping the rest", limit); + } + } + } + + controlreply(np, "--- Found %d entries.", matches); + + return CMD_OK; +} + +void ww_handlequitorkill(int hooknum, void *arg) { + void **args=arg; + nick *np=args[0]; + char *reason=args[1]; + char *rreason; + char resbuf[512]; + whowas *ww; + time_t now; + + time(&now); + + /* Clean up old records. */ + while((ww = wwtail) && (ww->seen < now - WW_MAXAGE || wwcount >= WW_MAXENTRIES)) { + wwtail = ww->prev; + + if (ww->prev) + ww->prev->next = NULL; + else + wwhead = ww->prev; + + wwcount--; + free(ww); + } + + /* Create a new record. */ + ww = malloc(sizeof(whowas)); + strncpy(ww->nick, np->nick, NICKLEN); + strncpy(ww->ident, np->ident, USERLEN); + strncpy(ww->host, np->host->name->content, HOSTLEN); + strncpy(ww->realname, np->realname->name->content, REALLEN); + ww->seen = getnettime(); + + if(hooknum==HOOK_NICK_KILL && (rreason=strchr(reason,' '))) { + sprintf(resbuf,"Killed%s",rreason); + reason=resbuf; + } + + ww->reason = getsstring(reason, WW_REASONLEN); + + if(wwhead) + wwhead->prev = ww; + + ww->next = wwhead; + wwhead = ww; + + ww->prev = NULL; + + if(!wwtail) + wwtail = ww; + + wwcount++; +} + +void _init(void) { + registerhook(HOOK_NICK_QUIT, ww_handlequitorkill); + registerhook(HOOK_NICK_KILL, ww_handlequitorkill); + + registercontrolhelpcmd("whowas", NO_OPER, 2, &ww_cmdwhowas, "Usage: whowas ?limit?\nLooks up information about recently disconnected users."); +} + +void _fini(void) { + whowas *ww; + + deregisterhook(HOOK_NICK_QUIT, ww_handlequitorkill); + deregisterhook(HOOK_NICK_KILL, ww_handlequitorkill); + + deregistercontrolcmd("whowas", &ww_cmdwhowas); + + while((ww = wwhead)) { + wwhead = ww->next; + free(ww); + } +} diff --git a/whowas/whowas.h b/whowas/whowas.h new file mode 100644 index 00000000..f98074be --- /dev/null +++ b/whowas/whowas.h @@ -0,0 +1,17 @@ +#define WW_MAXAGE 3600 +#define WW_MAXENTRIES 100000 +#define WW_MASKLEN (HOSTLEN + USERLEN + NICKLEN) +#define WW_REASONLEN 512 + +typedef struct whowas { + char nick[NICKLEN+1]; + char ident[USERLEN+1]; + char host[HOSTLEN+1]; + char realname[REALLEN+1]; + sstring *reason; + + time_t seen; + + struct whowas *next; + struct whowas *prev; +} whowas;