X-Git-Url: https://jfr.im/git/irc/quakenet/snircd.git/blobdiff_plain/8ebc3d85b4e8a93d72e84eed7db999470aa43ab2..98de26a372686a2e3adba41029149878e9ac3d37:/ircd/gline.c diff --git a/ircd/gline.c b/ircd/gline.c index af7f621..2b39497 100644 --- a/ircd/gline.c +++ b/ircd/gline.c @@ -76,32 +76,43 @@ struct Gline* BadChanGlineList = 0; * Otherwise, assign \a def_user to *user_p and \a userhost to *host_p. * * @param[in] userhost Input string from user. + * @param[out] nick_p Gets pointer to nick part of hostmask. * @param[out] user_p Gets pointer to user (or channel/realname) part of hostmask. * @param[out] host_p Gets point to host part of hostmask (may be assigned NULL). * @param[in] def_user Default value for user part. */ static void -canon_userhost(char *userhost, char **user_p, char **host_p, char *def_user) +canon_userhost(char *userhost, char **nick_p, char **user_p, char **host_p, char *def_user) { - char *tmp; + char *tmp, *s; if (*userhost == '$') { *user_p = userhost; *host_p = NULL; + *nick_p = NULL; return; } - if (!(tmp = strchr(userhost, '@'))) { - *user_p = def_user; - *host_p = userhost; - } else { - *user_p = userhost; + if ((tmp = strchr(userhost, '!'))) { + *nick_p = userhost; *(tmp++) = '\0'; + } else { + *nick_p = def_user; + tmp = userhost; + } + + if (!(s = strchr(tmp, '@'))) { + *user_p = def_user; *host_p = tmp; + } else { + *user_p = tmp; + *(s++) = '\0'; + *host_p = s; } } /** Create a Gline structure. + * @param[in] nick Nick part of mask. * @param[in] user User part of mask. * @param[in] host Host part of mask (NULL if not applicable). * @param[in] reason Reason for G-line. @@ -111,12 +122,12 @@ canon_userhost(char *userhost, char **user_p, char **host_p, char *def_user) * @return Newly allocated G-line. */ static struct Gline * -make_gline(char *user, char *host, char *reason, time_t expire, time_t lastmod, +make_gline(char *nick, char *user, char *host, char *reason, time_t expire, time_t lastmod, unsigned int flags) { struct Gline *gline, *sgline, *after = 0; - if (!(flags & GLINE_BADCHAN)) { /* search for overlapping glines first */ + if (!(flags & (GLINE_BADCHAN|GLINE_REALNAME))) { /* search for overlapping glines first */ for (gline = GlobalGlineList; gline; gline = sgline) { sgline = gline->gl_next; @@ -126,13 +137,15 @@ make_gline(char *user, char *host, char *reason, time_t expire, time_t lastmod, 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 */ + else if (!mmatch(gline->gl_nick, nick) && /* gline contains new mask */ + !mmatch(gline->gl_user, user) && (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 */ + } else if (!mmatch(nick, gline->gl_nick) && /* new mask contains gline */ + !mmatch(user, gline->gl_user) && (gline->gl_host==NULL || !mmatch(host, gline->gl_host)) && gline->gl_expire <= expire) /* old expires before new */ gline_free(gline); /* save some memory */ @@ -157,7 +170,11 @@ make_gline(char *user, char *host, char *reason, time_t expire, time_t lastmod, BadChanGlineList->gl_prev_p = &gline->gl_next; BadChanGlineList = gline; } else { - DupString(gline->gl_user, user); /* remember them... */ + if (*user!='$') + DupString(gline->gl_nick, nick); /* remember them... */ + else + gline->gl_nick = 0; + DupString(gline->gl_user, user); if (*user != '$') DupString(gline->gl_host, host); else @@ -250,6 +267,10 @@ do_gline(struct Client *cptr, struct Client *sptr, struct Gline *gline) continue; Debug((DEBUG_DEBUG,"Matched!")); } else { /* Host/IP gline */ + if (cli_name(acptr) && + match(gline->gl_nick, cli_name(acptr)) !=0) + continue; + if (cli_user(acptr)->username && match(gline->gl_user, (cli_user(acptr))->realusername) != 0) continue; @@ -368,16 +389,21 @@ gline_propagate(struct Client *cptr, struct Client *sptr, struct Gline *gline) return 0; if (gline->gl_lastmod) - sendcmdto_serv_butone(sptr, CMD_GLINE, cptr, "* %c%s%s%s %Tu %Tu :%s", - GlineIsRemActive(gline) ? '+' : '-', gline->gl_user, - gline->gl_host ? "@" : "", + sendcmdto_serv_butone(sptr, CMD_GLINE, cptr, "* %c%s%s%s%s%s %Tu %Tu :%s", + GlineIsRemActive(gline) ? '+' : '-', + GlineIsBadChan(gline)|GlineIsRealName(gline) ? "" : gline->gl_nick, + GlineIsBadChan(gline)|GlineIsRealName(gline) ? "" : "!", + gline->gl_user, + gline->gl_host ? "@" : "", gline->gl_host ? gline->gl_host : "", gline->gl_expire - CurrentTime, gline->gl_lastmod, gline->gl_reason); else sendcmdto_serv_butone(sptr, CMD_GLINE, cptr, (GlineIsRemActive(gline) ? - "* +%s%s%s %Tu :%s" : "* -%s%s%s"), + "* +%s%s%s%s%s %Tu :%s" : "* -%s%s%s%s%s"), + GlineIsBadChan(gline)|GlineIsRealName(gline) ? "" : gline->gl_nick, + GlineIsBadChan(gline)|GlineIsRealName(gline) ? "" : "!", gline->gl_user, gline->gl_host ? "@" : "", gline->gl_host ? gline->gl_host : "", @@ -407,8 +433,8 @@ gline_add(struct Client *cptr, struct Client *sptr, char *userhost, char *reason, time_t expire, time_t lastmod, unsigned int flags) { struct Gline *agline; - char uhmask[USERLEN + HOSTLEN + 2]; - char *user, *host; + char uhmask[NICKLEN + USERLEN + HOSTLEN + 3]; + char *nick, *user, *host; int tmp; assert(0 != userhost); @@ -439,7 +465,7 @@ gline_add(struct Client *cptr, struct Client *sptr, char *userhost, user = (*userhost =='$' ? userhost : userhost+2); host = 0; } else { - canon_userhost(userhost, &user, &host, "*"); + canon_userhost(userhost, &nick, &user, &host, "*"); if (sizeof(uhmask) < ircd_snprintf(0, uhmask, sizeof(uhmask), "%s@%s", user, host)) return send_reply(sptr, ERR_LONGMASK); @@ -474,28 +500,34 @@ gline_add(struct Client *cptr, struct Client *sptr, char *userhost, /* 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 for %s%s%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_LOCAL) ? "local" : "global", - (flags & GLINE_BADCHAN) ? "BADCHAN" : "GLINE", user, + (flags & GLINE_BADCHAN) ? "BADCHAN" : "GLINE", + (flags & (GLINE_BADCHAN|GLINE_REALNAME)) ? "" : nick, + (flags & (GLINE_BADCHAN|GLINE_REALNAME)) ? "" : "!", + user, (flags & (GLINE_BADCHAN|GLINE_REALNAME)) ? "" : "@", (flags & (GLINE_BADCHAN|GLINE_REALNAME)) ? "" : host, expire + TSoffset, reason); /* and log it */ log_write(LS_GLINE, L_INFO, LOG_NOSNOTICE, - "%#C adding %s %s for %s%s%s, expiring at %Tu: %s", sptr, + "%#C adding %s %s for %s%s%s%s%s, expiring at %Tu: %s", sptr, flags & GLINE_LOCAL ? "local" : "global", - flags & GLINE_BADCHAN ? "BADCHAN" : "GLINE", user, + flags & GLINE_BADCHAN ? "BADCHAN" : "GLINE", + flags & (GLINE_BADCHAN|GLINE_REALNAME) ? "" : nick, + flags & (GLINE_BADCHAN|GLINE_REALNAME) ? "" : "!", + user, flags & (GLINE_BADCHAN|GLINE_REALNAME) ? "" : "@", flags & (GLINE_BADCHAN|GLINE_REALNAME) ? "" : host, expire + TSoffset, reason); /* make the gline */ - agline = make_gline(user, host, reason, expire, lastmod, flags); + agline = make_gline(nick, user, host, reason, expire, lastmod, flags); if (!agline) /* if it overlapped, silently return */ return 0; @@ -540,19 +572,24 @@ gline_activate(struct Client *cptr, struct Client *sptr, struct Gline *gline, return 0; /* was active to begin with */ /* Inform ops and log it */ - sendto_opmask_butone(0, SNO_GLINE, "%s activating global %s for %s%s%s, " + sendto_opmask_butone(0, SNO_GLINE, "%s activating global %s for %s%s%s%s%s, " "expiring at %Tu: %s", (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ? cli_name(sptr) : cli_name((cli_user(sptr))->server), GlineIsBadChan(gline) ? "BADCHAN" : "GLINE", + GlineIsBadChan(gline)|GlineIsRealName(gline) ? "" : gline->gl_nick, + GlineIsBadChan(gline)|GlineIsRealName(gline) ? "" : "!", gline->gl_user, gline->gl_host ? "@" : "", gline->gl_host ? gline->gl_host : "", gline->gl_expire + TSoffset, gline->gl_reason); log_write(LS_GLINE, L_INFO, LOG_NOSNOTICE, - "%#C activating global %s for %s%s%s, expiring at %Tu: %s", sptr, - GlineIsBadChan(gline) ? "BADCHAN" : "GLINE", gline->gl_user, + "%#C activating global %s for %s%s%s%s%s, expiring at %Tu: %s", sptr, + GlineIsBadChan(gline) ? "BADCHAN" : "GLINE", + GlineIsBadChan(gline)|GlineIsRealName(gline) ? "" : gline->gl_nick, + GlineIsBadChan(gline)|GlineIsRealName(gline) ? "" : "!", + gline->gl_user, gline->gl_host ? "@" : "", gline->gl_host ? gline->gl_host : "", gline->gl_expire + TSoffset, gline->gl_reason); @@ -608,19 +645,24 @@ gline_deactivate(struct Client *cptr, struct Client *sptr, struct Gline *gline, } /* Inform ops and log it */ - sendto_opmask_butone(0, SNO_GLINE, "%s %s %s for %s%s%s, expiring at %Tu: " + sendto_opmask_butone(0, SNO_GLINE, "%s %s %s for %s%s%s%s%s, expiring at %Tu: " "%s", (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ? cli_name(sptr) : cli_name((cli_user(sptr))->server), msg, GlineIsBadChan(gline) ? "BADCHAN" : "GLINE", + GlineIsBadChan(gline)|GlineIsRealName(gline) ? "" : gline->gl_nick, + GlineIsBadChan(gline)|GlineIsRealName(gline) ? "" : "!", gline->gl_user, gline->gl_host ? "@" : "", gline->gl_host ? gline->gl_host : "", gline->gl_expire + TSoffset, gline->gl_reason); log_write(LS_GLINE, L_INFO, LOG_NOSNOTICE, - "%#C %s %s for %s%s%s, expiring at %Tu: %s", sptr, msg, - GlineIsBadChan(gline) ? "BADCHAN" : "GLINE", gline->gl_user, + "%#C %s %s for %s%s%s%s%s, expiring at %Tu: %s", sptr, msg, + GlineIsBadChan(gline) ? "BADCHAN" : "GLINE", + GlineIsBadChan(gline)|GlineIsRealName(gline) ? "" : gline->gl_nick, + GlineIsBadChan(gline)|GlineIsRealName(gline) ? "" : "!", + gline->gl_user, gline->gl_host ? "@" : "", gline->gl_host ? gline->gl_host : "", gline->gl_expire + TSoffset, gline->gl_reason); @@ -654,7 +696,7 @@ gline_find(char *userhost, unsigned int flags) { struct Gline *gline; struct Gline *sgline; - char *user, *host, *t_uh; + char *nick, *user, *host, *t_uh; if (flags & (GLINE_BADCHAN | GLINE_ANY)) { for (gline = BadChanGlineList; gline; gline = sgline) { @@ -676,7 +718,7 @@ gline_find(char *userhost, unsigned int flags) return 0; DupString(t_uh, userhost); - canon_userhost(t_uh, &user, &host, "*"); + canon_userhost(t_uh, &nick, &user, &host, "*"); for (gline = GlobalGlineList; gline; gline = sgline) { sgline = gline->gl_next; @@ -689,12 +731,18 @@ gline_find(char *userhost, unsigned int flags) else if (flags & GLINE_EXACT) { if (((gline->gl_host && host && ircd_strcmp(gline->gl_host, host) == 0) || (!gline->gl_host && !host)) && - (ircd_strcmp(gline->gl_user, user) == 0)) + ((!user && ircd_strcmp(gline->gl_user, "*") == 0) || + (user && ircd_strcmp(gline->gl_user, user) == 0)) && + ((!nick && gline->gl_nick && ircd_strcmp(gline->gl_nick, "*") == 0) || + (nick && gline->gl_nick && ircd_strcmp(gline->gl_nick, nick) == 0) || (!gline->gl_nick && !nick))) break; } else { if (((gline->gl_host && host && match(gline->gl_host, host) == 0) || (!gline->gl_host && !host)) && - (match(gline->gl_user, user) == 0)) + ((!user && ircd_strcmp(gline->gl_user, "*") == 0) || + (user && match(gline->gl_user, user) == 0)) && + ((!nick && gline->gl_nick && ircd_strcmp(gline->gl_nick, "*") == 0) || + (nick && gline->gl_nick && (match(gline->gl_nick, nick) == 0)) || (!gline->gl_nick && !nick))) break; } } @@ -734,7 +782,9 @@ gline_lookup(struct Client *cptr, unsigned int flags) continue; } else { - if (match(gline->gl_user, (cli_user(cptr))->username) != 0) + if (match(gline->gl_nick, cli_name(cptr)) != 0) + continue; + if (match(gline->gl_user, (cli_user(cptr))->realusername) != 0) continue; if (GlineIsIpMask(gline)) { @@ -789,8 +839,12 @@ gline_burst(struct Client *cptr) if (gline->gl_expire <= CurrentTime) /* expire any that need expiring */ gline_free(gline); else if (!GlineIsLocal(gline) && gline->gl_lastmod) - sendcmdto_one(&me, CMD_GLINE, cptr, "* %c%s%s%s %Tu %Tu :%s", - GlineIsRemActive(gline) ? '+' : '-', gline->gl_user, + sendcmdto_one(&me, CMD_GLINE, cptr, "* %c%s%s%s%s%s %Tu %Tu :%s", + GlineIsRemActive(gline) ? '+' : '-', + gline->gl_nick ? gline->gl_nick : "", + gline->gl_nick ? "!" : "", + gline->gl_user, + gline->gl_host ? "@" : "", gline->gl_host ? gline->gl_host : "", gline->gl_expire - CurrentTime, gline->gl_lastmod, @@ -849,7 +903,10 @@ gline_list(struct Client *sptr, char *userhost) return send_reply(sptr, ERR_NOSUCHGLINE, userhost); /* send gline information along */ - send_reply(sptr, RPL_GLIST, gline->gl_user, + send_reply(sptr, RPL_GLIST, + GlineIsBadChan(gline) | GlineIsRealName(gline) ? "" : gline->gl_nick, + GlineIsBadChan(gline) | GlineIsRealName(gline) ? "" : "!", + gline->gl_user, GlineIsBadChan(gline) || GlineIsRealName(gline) ? "" : "@", gline->gl_host ? "@" : "", gline->gl_host ? gline->gl_host : "", gline->gl_expire + TSoffset, @@ -862,7 +919,10 @@ gline_list(struct Client *sptr, char *userhost) if (gline->gl_expire <= CurrentTime) gline_free(gline); else - send_reply(sptr, RPL_GLIST, gline->gl_user, + send_reply(sptr, RPL_GLIST, + gline->gl_nick ? gline->gl_nick : "", + gline->gl_nick ? "!" : "", + gline->gl_user, gline->gl_host ? "@" : "", gline->gl_host ? gline->gl_host : "", gline->gl_expire + TSoffset, @@ -876,7 +936,7 @@ gline_list(struct Client *sptr, char *userhost) if (gline->gl_expire <= CurrentTime) gline_free(gline); else - send_reply(sptr, RPL_GLIST, gline->gl_user, "", "", + send_reply(sptr, RPL_GLIST, gline->gl_user, "", "", "", "", gline->gl_expire + TSoffset, GlineIsLocal(gline) ? cli_name(&me) : "*", GlineIsActive(gline) ? '+' : '-', gline->gl_reason); @@ -905,7 +965,10 @@ gline_stats(struct Client *sptr, const struct StatDesc *sd, if (gline->gl_expire <= CurrentTime) gline_free(gline); else - send_reply(sptr, RPL_STATSGLINE, 'G', gline->gl_user, + send_reply(sptr, RPL_STATSGLINE, 'G', + gline->gl_nick ? gline->gl_nick : "", + gline->gl_nick ? "!" : "", + gline->gl_user, gline->gl_host ? "@" : "", gline->gl_host ? gline->gl_host : "", gline->gl_expire + TSoffset, gline->gl_reason); @@ -926,9 +989,53 @@ gline_memory_count(size_t *gl_size) { gl++; *gl_size += sizeof(struct Gline); + *gl_size += gline->gl_nick ? (strlen(gline->gl_nick) +1) : 0; *gl_size += gline->gl_user ? (strlen(gline->gl_user) + 1) : 0; *gl_size += gline->gl_host ? (strlen(gline->gl_host) + 1) : 0; *gl_size += gline->gl_reason ? (strlen(gline->gl_reason) + 1) : 0; } return gl; } + +struct Gline * +IsNickGlined(struct Client *cptr, char *nick) +{ + struct Gline *gline; + struct Gline *sgline; + + for (gline = GlobalGlineList; gline; gline = sgline) { + sgline = gline->gl_next; + + if (gline->gl_expire <= CurrentTime) { + gline_free(gline); + continue; + } + + if (GlineIsRealName(gline)) /* skip realname glines */ + continue; + + if (!ircd_strcmp(gline->gl_nick, "*")) /* skip glines w. wildcarded nick */ + continue; + + if (match(gline->gl_nick, nick) != 0) + continue; + + if (match(gline->gl_user, (cli_user(cptr))->username) != 0) + continue; + + if (GlineIsIpMask(gline)) { + if (!ipmask_check(&(cli_ip(cptr)), &gline->gl_addr, gline->gl_bits)) + continue; + } + else { + if (match(gline->gl_host, (cli_user(cptr))->realhost) != 0) + continue; + } + return gline; + } + /* + * No Glines matched + */ + return 0; +} +