X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=ircd%2Fgline.c;h=dfbf77d2394fdc38e946d9423fa68ba267edb20e;hb=e471b5cc12c5c0eb40422df1e755123e534f0934;hp=5ae577e785423b82785191bf4f5fc4d0f001cbea;hpb=5dac8d5087c52b5d957e1cba78605dacf7f8efbd;p=ircu2.10.12-pk.git diff --git a/ircd/gline.c b/ircd/gline.c index 5ae577e..dfbf77d 100644 --- a/ircd/gline.c +++ b/ircd/gline.c @@ -44,7 +44,6 @@ #include "msg.h" #include "numnicks.h" #include "numeric.h" -#include "whocmds.h" /* #include -- Now using assert in ircd_log.h */ #include @@ -77,6 +76,10 @@ struct Gline* BadChanGlineList = 0; * @param[in] gl Name of a struct Gline pointer variable that will be made to point to the G-lines in sequence. * @param[in] next Name of a scratch struct Gline pointer variable. */ +/* There is some subtlety here with the boolean operators: + * (x || 1) is used to continue in a logical-and series even when !x. + * (x && 0) is used to continue in a logical-or series even when x. + */ #define gliter(list, gl, next) \ /* Iterate through the G-lines in the list */ \ for ((gl) = (list); (gl); (gl) = (next)) \ @@ -87,8 +90,8 @@ struct Gline* BadChanGlineList = 0; /* Record has expired, so free the G-line */ \ gline_free((gl)); \ /* See if we need to expire the G-line */ \ - else if (((gl)->gl_expire > CurrentTime || \ - ((gl)->gl_flags &= ~GLINE_ACTIVE) || \ + else if ((((gl)->gl_expire > CurrentTime) || \ + (((gl)->gl_flags &= ~GLINE_ACTIVE) && 0) || \ ((gl)->gl_state = GLOCAL_GLOBAL)) && 0) \ ; /* empty statement */ \ else @@ -137,37 +140,9 @@ static struct Gline * make_gline(char *user, char *host, char *reason, time_t expire, time_t lastmod, time_t lifetime, unsigned int flags) { - struct Gline *gline, *after = 0; - - /* Disable checking for overlapping G-lines. The problem is that we - * may have a wide-mask, long lifetime G-line that we've - * deactivated--maybe it was a mistake?--and someone comes along and - * wants to set a narrower overlapping G-line with a shorter - * lifetime. If we were to leave this logic enabled, there would be - * no way to set that narrower G-line. - */ -/* if (!(flags & GLINE_BADCHAN)) { /\* search for overlapping glines first *\/ */ - -/* for (gline = GlobalGlineList; gline; gline = sgline) { */ -/* sgline = gline->gl_next; */ - -/* if (gline->gl_expire <= CurrentTime) */ -/* gline_free(gline); */ -/* else if (((gline->gl_flags & GLINE_LOCAL) != (flags & GLINE_LOCAL)) || */ -/* (gline->gl_host && !host) || (!gline->gl_host && host)) */ -/* continue; */ -/* else if (!mmatch(gline->gl_user, user) /\* gline contains new mask *\/ */ -/* && (gline->gl_host == NULL || !mmatch(gline->gl_host, host))) { */ -/* if (expire <= gline->gl_expire) /\* will expire before wider gline *\/ */ -/* return 0; */ -/* else */ -/* after = gline; /\* stick new gline after this one *\/ */ -/* } else if (!mmatch(user, gline->gl_user) /\* new mask contains gline *\/ */ -/* && (gline->gl_host==NULL || !mmatch(host, gline->gl_host)) */ -/* && gline->gl_expire <= expire) /\* old expires before new *\/ */ -/* gline_free(gline); /\* save some memory *\/ */ -/* } */ -/* } */ + struct Gline *gline; + + assert(0 != expire); gline = (struct Gline *)MyMalloc(sizeof(struct Gline)); /* alloc memory */ assert(0 != gline); @@ -181,7 +156,7 @@ make_gline(char *user, char *host, char *reason, time_t expire, time_t lastmod, if (flags & GLINE_BADCHAN) { /* set a BADCHAN gline */ DupString(gline->gl_user, user); /* first, remember channel */ - gline->gl_host = 0; + gline->gl_host = NULL; gline->gl_next = BadChanGlineList; /* then link it into list */ gline->gl_prev_p = &BadChanGlineList; @@ -198,19 +173,11 @@ make_gline(char *user, char *host, char *reason, time_t expire, time_t lastmod, if (*user != '$' && ipmask_parse(host, &gline->gl_addr, &gline->gl_bits)) gline->gl_flags |= GLINE_IPMASK; - if (after) { - gline->gl_next = after->gl_next; - gline->gl_prev_p = &after->gl_next; - if (after->gl_next) - after->gl_next->gl_prev_p = &gline->gl_next; - after->gl_next = gline; - } else { - gline->gl_next = GlobalGlineList; /* then link it into list */ - gline->gl_prev_p = &GlobalGlineList; - if (GlobalGlineList) - GlobalGlineList->gl_prev_p = &gline->gl_next; - GlobalGlineList = gline; - } + gline->gl_next = GlobalGlineList; /* then link it into list */ + gline->gl_prev_p = &GlobalGlineList; + if (GlobalGlineList) + GlobalGlineList->gl_prev_p = &gline->gl_next; + GlobalGlineList = gline; } return gline; @@ -362,7 +329,7 @@ gline_checkmask(char *mask) * @param[in] gline G-line to forward. * @return Zero. */ -int +static int gline_propagate(struct Client *cptr, struct Client *sptr, struct Gline *gline) { if (GlineIsLocal(gline)) @@ -375,11 +342,73 @@ gline_propagate(struct Client *cptr, struct Client *sptr, struct Gline *gline) gline->gl_host ? "@" : "", gline->gl_host ? gline->gl_host : "", gline->gl_expire - CurrentTime, gline->gl_lastmod, - gline->gl_lifetime - CurrentTime, gline->gl_reason); + gline->gl_lifetime, gline->gl_reason); return 0; } +/** Count number of users who match \a mask. + * @param[in] mask user\@host or user\@ip mask to check. + * @param[in] flags Bitmask possibly containing the value GLINE_LOCAL, to limit searches to this server. + * @return Count of matching users. + */ +static int +count_users(char *mask, int flags) +{ + struct irc_in_addr ipmask; + struct Client *acptr; + int count = 0; + int ipmask_valid; + char namebuf[USERLEN + HOSTLEN + 2]; + char ipbuf[USERLEN + SOCKIPLEN + 2]; + unsigned char ipmask_len; + + ipmask_valid = ipmask_parse(mask, &ipmask, &ipmask_len); + for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr)) { + if (!IsUser(acptr)) + continue; + if ((flags & GLINE_LOCAL) && !MyConnect(acptr)) + continue; + + ircd_snprintf(0, namebuf, sizeof(namebuf), "%s@%s", + cli_user(acptr)->username, cli_user(acptr)->host); + ircd_snprintf(0, ipbuf, sizeof(ipbuf), "%s@%s", cli_user(acptr)->username, + ircd_ntoa(&cli_ip(acptr))); + + if (!match(mask, namebuf) + || !match(mask, ipbuf) + || (ipmask_valid && ipmask_check(&cli_ip(acptr), &ipmask, ipmask_len))) + count++; + } + + return count; +} + +/** Count number of users with a realname matching \a mask. + * @param[in] mask Wildcard mask to match against realnames. + * @return Count of matching users. + */ +static int +count_realnames(const char *mask) +{ + struct Client *acptr; + int minlen; + int count; + char cmask[BUFSIZE]; + + count = 0; + matchcomp(cmask, &minlen, NULL, mask); + for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr)) { + if (!IsUser(acptr)) + continue; + if (strlen(cli_info(acptr)) < minlen) + continue; + if (!matchexec(cli_info(acptr), cmask, minlen)) + count++; + } + return count; +} + /** Create a new G-line and add it to global lists. * \a userhost may be in one of four forms: * \li A channel name, to add a BadChan. @@ -391,7 +420,7 @@ gline_propagate(struct Client *cptr, struct Client *sptr, struct Gline *gline) * @param[in] sptr Client that originated the G-line. * @param[in] userhost Text mask for the G-line. * @param[in] reason Reason for G-line. - * @param[in] expire Duration of G-line in seconds. + * @param[in] expire Expiration time of G-line. * @param[in] lastmod Last modification time of G-line. * @param[in] lifetime Lifetime of G-line. * @param[in] flags Bitwise combination of GLINE_* flags. @@ -409,6 +438,8 @@ gline_add(struct Client *cptr, struct Client *sptr, char *userhost, assert(0 != userhost); assert(0 != reason); + assert(((flags & (GLINE_GLOBAL | GLINE_LOCAL)) == GLINE_GLOBAL) || + ((flags & (GLINE_GLOBAL | GLINE_LOCAL)) == GLINE_LOCAL)); Debug((DEBUG_DEBUG, "gline_add(\"%s\", \"%s\", \"%s\", \"%s\", %Tu, %Tu " "%Tu, 0x%04x)", cli_name(cptr), cli_name(sptr), userhost, reason, @@ -420,7 +451,7 @@ gline_add(struct Client *cptr, struct Client *sptr, char *userhost, flags |= GLINE_BADCHAN; user = userhost; - host = 0; + host = NULL; } else if (*userhost == '$') { switch (userhost[1]) { case 'R': flags |= GLINE_REALNAME; break; @@ -430,14 +461,17 @@ gline_add(struct Client *cptr, struct Client *sptr, char *userhost, -- hikari */ if (IsServer(cptr)) return protocol_violation(sptr,"%s has been smoking the sweet leaf and sent me a whacky gline",cli_name(sptr)); - else { - sendto_opmask_butone(NULL, SNO_GLINE, "%s has been smoking the sweet leaf and sent me a whacky gline", cli_name(sptr)); - return 0; - } - break; + sendto_opmask_butone(NULL, SNO_GLINE, "%s has been smoking the sweet leaf and sent me a whacky gline", cli_name(sptr)); + return 0; + } + user = userhost; + host = NULL; + if (MyUser(sptr) || (IsUser(sptr) && flags & GLINE_LOCAL)) { + tmp = count_realnames(userhost + 2); + if ((tmp >= feature_int(FEAT_GLINEMAXUSERCOUNT)) + && !(flags & GLINE_OPERFORCE)) + return send_reply(sptr, ERR_TOOMANYUSERS, tmp); } - user = userhost; - host = 0; } else { canon_userhost(userhost, &user, &host, "*"); if (sizeof(uhmask) < @@ -454,7 +488,7 @@ gline_add(struct Client *cptr, struct Client *sptr, char *userhost, break; } - if ((tmp = count_users(uhmask)) >= + if ((tmp = count_users(uhmask, flags)) >= feature_int(FEAT_GLINEMAXUSERCOUNT) && !(flags & GLINE_OPERFORCE)) return send_reply(sptr, ERR_TOOMANYUSERS, tmp); } @@ -464,26 +498,29 @@ gline_add(struct Client *cptr, struct Client *sptr, char *userhost, * You cannot set a negative (or zero) expire time, nor can you set an * expiration time for greater than GLINE_MAX_EXPIRE. */ - if (!(flags & GLINE_FORCE) && (expire <= 0 || expire > GLINE_MAX_EXPIRE)) { + if (!(flags & GLINE_FORCE) && + (expire <= CurrentTime || expire > CurrentTime + GLINE_MAX_EXPIRE)) { if (!IsServer(sptr) && MyConnect(sptr)) send_reply(sptr, ERR_BADEXPIRE, expire); return 0; + } else if (expire <= CurrentTime) { + /* This expired G-line was forced to be added, so mark it inactive. */ + flags &= ~GLINE_ACTIVE; } - expire += CurrentTime; /* convert from lifetime to timestamp */ - if (!lifetime) /* no lifetime set, use expiration time */ lifetime = expire; - else /* convert lifetime into timestamp */ - lifetime += CurrentTime; + + /* lifetime is already an absolute timestamp */ /* Inform ops... */ sendto_opmask_butone(0, ircd_strncmp(reason, "AUTO", 4) ? SNO_GLINE : - SNO_AUTO, "%s adding %s %s for %s%s%s, expiring at " + SNO_AUTO, "%s adding %s%s %s for %s%s%s, expiring at " "%Tu: %s", (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ? cli_name(sptr) : cli_name((cli_user(sptr))->server), + (flags & GLINE_ACTIVE) ? "" : "deactivated ", (flags & GLINE_LOCAL) ? "local" : "global", (flags & GLINE_BADCHAN) ? "BADCHAN" : "GLINE", user, (flags & (GLINE_BADCHAN|GLINE_REALNAME)) ? "" : "@", @@ -506,8 +543,6 @@ gline_add(struct Client *cptr, struct Client *sptr, char *userhost, * never be NULL... */ assert(agline); -/* if (!agline) /\* if it overlapped, silently return *\/ */ -/* return 0; */ gline_propagate(cptr, sptr, agline); @@ -650,7 +685,7 @@ gline_deactivate(struct Client *cptr, struct Client *sptr, struct Gline *gline, * @param[in] gline G-line being modified. * @param[in] action Resultant status of the G-line. * @param[in] reason Reason for G-line. - * @param[in] expire Duration of G-line in seconds. + * @param[in] expire Expiration time of G-line. * @param[in] lastmod Last modification time of G-line. * @param[in] lifetime Lifetime of G-line. * @param[in] flags Bitwise combination of GLINE_* flags. @@ -691,14 +726,12 @@ gline_modify(struct Client *cptr, struct Client *sptr, struct Gline *gline, /* All right, we know that there's a change of some sort. What is it? */ /* first, check out the expiration time... */ if ((flags & GLINE_EXPIRE) && expire) { - if (!(flags & GLINE_FORCE) && (expire <= 0 || expire > GLINE_MAX_EXPIRE)) { + if (!(flags & GLINE_FORCE) && + (expire <= CurrentTime || expire > CurrentTime + GLINE_MAX_EXPIRE)) { if (!IsServer(sptr) && MyConnect(sptr)) /* bad expiration time */ send_reply(sptr, ERR_BADEXPIRE, expire); return 0; } - - /* convert to a timestamp... */ - expire += CurrentTime; } else flags &= ~GLINE_EXPIRE; @@ -709,9 +742,7 @@ gline_modify(struct Client *cptr, struct Client *sptr, struct Gline *gline, } /* Next, check out lifetime--this one's a bit trickier... */ - if ((flags & GLINE_LIFETIME) && lifetime) - lifetime += CurrentTime; /* convert to a timestamp */ - else + if (!(flags & GLINE_LIFETIME) || !lifetime) lifetime = gline->gl_lifetime; /* use G-line lifetime */ lifetime = IRCD_MAX(lifetime, expire); /* set lifetime to the max */ @@ -843,7 +874,7 @@ gline_modify(struct Client *cptr, struct Client *sptr, struct Gline *gline, gline->gl_user, gline->gl_host ? "@" : "", gline->gl_host ? gline->gl_host : "", gline->gl_expire - CurrentTime, gline->gl_lastmod, - gline->gl_lifetime - CurrentTime, gline->gl_reason); + gline->gl_lifetime, gline->gl_reason); /* OK, let's do the G-line... */ return do_gline(cptr, sptr, gline); @@ -902,8 +933,7 @@ gline_find(char *userhost, unsigned int flags) if (flags & (GLINE_BADCHAN | GLINE_ANY)) { gliter(BadChanGlineList, gline, sgline) { - if ((flags & GLINE_GLOBAL && gline->gl_flags & GLINE_LOCAL) || - (flags & GLINE_LOCAL && gline->gl_flags & GLINE_GLOBAL) || + if ((flags & (GlineIsLocal(gline) ? GLINE_GLOBAL : GLINE_LOCAL)) || (flags & GLINE_LASTMOD && !gline->gl_lastmod)) continue; else if ((flags & GLINE_EXACT ? ircd_strcmp(gline->gl_user, userhost) : @@ -920,8 +950,7 @@ gline_find(char *userhost, unsigned int flags) canon_userhost(t_uh, &user, &host, "*"); gliter(GlobalGlineList, gline, sgline) { - if ((flags & GLINE_GLOBAL && gline->gl_flags & GLINE_LOCAL) || - (flags & GLINE_LOCAL && gline->gl_flags & GLINE_GLOBAL) || + if ((flags & (GlineIsLocal(gline) ? GLINE_GLOBAL : GLINE_LOCAL)) || (flags & GLINE_LASTMOD && !gline->gl_lastmod)) continue; else if (flags & GLINE_EXACT) { @@ -1021,7 +1050,7 @@ gline_burst(struct Client *cptr) gline->gl_host ? "@" : "", gline->gl_host ? gline->gl_host : "", gline->gl_expire - CurrentTime, gline->gl_lastmod, - gline->gl_lifetime - CurrentTime, gline->gl_reason); + gline->gl_lifetime, gline->gl_reason); } gliter(BadChanGlineList, gline, sgline) { @@ -1029,7 +1058,7 @@ gline_burst(struct Client *cptr) sendcmdto_one(&me, CMD_GLINE, cptr, "* %c%s %Tu %Tu %Tu :%s", GlineIsRemActive(gline) ? '+' : '-', gline->gl_user, gline->gl_expire - CurrentTime, gline->gl_lastmod, - gline->gl_lifetime - CurrentTime, gline->gl_reason); + gline->gl_lifetime, gline->gl_reason); } } @@ -1049,7 +1078,7 @@ gline_resend(struct Client *cptr, struct Gline *gline) gline->gl_host ? "@" : "", gline->gl_host ? gline->gl_host : "", gline->gl_expire - CurrentTime, gline->gl_lastmod, - gline->gl_lifetime - CurrentTime, gline->gl_reason); + gline->gl_lifetime, gline->gl_reason); return 0; }