/** Create a Zline structure. * @param[in] mask Mask. * @param[in] reason Reason for Z-line. * @param[in] expire Expiration timestamp. * @param[in] lastmod Last modification timestamp. * @param[in] flags Bitwise combination of ZLINE_* bits. * @return Newly allocated Z-line. */ static struct Zline * make_zline(char *mask, char *reason, time_t expire, time_t lastmod, time_t lifetime, unsigned int flags) { struct Zline *zline; assert(0 != expire); zline = (struct Zline *)MyMalloc(sizeof(struct Zline)); /* alloc memory */ assert(0 != zline); DupString(zline->zl_reason, reason); /* initialize zline... */ zline->zl_expire = expire; zline->zl_lifetime = lifetime; zline->zl_lastmod = lastmod; zline->zl_flags = flags & ZLINE_MASK; zline->zl_state = ZLOCAL_GLOBAL; /* not locally modified */ DupString(zline->zl_mask, mask); if (ipmask_parse(mask, &zline->zl_addr, &zline->zl_bits)) { zline->zl_flags |= ZLINE_IPMASK; zline->zl_addr = ipmask_clean(&zline->zl_addr, zline->zl_bits); } zline->zl_next = GlobalZlineList; /* then link it into list */ zline->zl_prev_p = &GlobalZlineList; if (GlobalZlineList) GlobalZlineList->zl_prev_p = &zline->zl_next; GlobalZlineList = zline; return zline; }
/** Count number of users who match \a mask. * @param[in] mask ip mask to check. * @param[in] flags Bitmask possibly containing the value ZLINE_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 ipbuf[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 & ZLINE_LOCAL) && !MyConnect(acptr)) continue; ircd_snprintf(0, ipbuf, sizeof(ipbuf), "%s", ircd_ntoa(&cli_ip(acptr))); if (!match(mask, ipbuf) || (ipmask_valid && ipmask_check(&cli_ip(acptr), &ipmask, ipmask_len) && (irc_in_addr_type_cmp(&cli_ip(acptr), &ipmask) && ipmask_len))) count++; } return count; }
struct searchNode *cidr_parse(searchCtx *ctx, int argc, char **argv) { struct searchNode *thenode, *convsn; struct cidr_localdata *c; struct irc_in_addr ip; unsigned char bits; char *p; int ret; if(argc != 1) { parseError = "usage: cidr ip/mask"; return NULL; } if (!(convsn=argtoconststr("cidr", ctx, argv[0], &p))) return NULL; ret = ipmask_parse(p, &ip, &bits); convsn->free(ctx, convsn); if(!ret) { parseError = "usage: cidr ip/mask"; return NULL; } if (!(thenode=(struct searchNode *)malloc(sizeof (struct searchNode)))) { parseError = "malloc: could not allocate memory for this search."; return NULL; } thenode->returntype = RETURNTYPE_BOOL; if (!(c = malloc(sizeof(struct cidr_localdata)))) { /* couldn't malloc() memory for thenode->localdata, so free thenode to avoid leakage */ parseError = "malloc: could not allocate memory for this search."; free(thenode); return NULL; } memcpy(&c->ip, &ip, sizeof(struct irc_in_addr)); c->bits = bits; thenode->localdata = (void *)c; thenode->free = cidr_free; thenode->exe = cidr_exe; return thenode; }
static int trusts_cmdtrustglinesuggest(void *source, int cargc, char **cargv) { nick *sender = source; char mask[512]; char *p, *user, *host; struct irc_in_addr ip; unsigned char bits; int count; glinebuf gbuf; char creator[32]; if(cargc < 1) return CMD_USAGE; strncpy(mask, cargv[0], sizeof(mask)); p = strchr(mask, '@'); if(!p) return CMD_USAGE; user = mask; host = p + 1; *p = '\0'; if(!ipmask_parse(host, &ip, &bits)) { controlreply(sender, "Invalid CIDR."); return CMD_ERROR; } snprintf(creator, sizeof(creator), "#%s", sender->authname); glinebufinit(&gbuf, 0); glinebufaddbyip(&gbuf, user, &ip, 128, 0, creator, "Simulate", getnettime(), getnettime(), getnettime()); glinebufcounthits(&gbuf, &count, NULL); glinebufspew(&gbuf, sender); glinebufabort(&gbuf); controlreply(sender, "Total hits: %d", count); return CMD_OK; }
/** Create a struct Motd and initialize it. * @param[in] hostmask Hostmask (or connection class name) to filter on. * @param[in] path Path to MOTD file. * @param[in] maxcount Maximum number of lines permitted for MOTD. */ static struct Motd * motd_create(const char *hostmask, const char *path, int maxcount, int type) { struct Motd* tmp; assert(0 != path); /* allocate memory and initialize the structure */ if (MotdList.freelist) { tmp = MotdList.freelist; MotdList.freelist = tmp->next; } else tmp = (struct Motd *)MyMalloc(sizeof(struct Motd)); tmp->next = 0; if (hostmask == NULL) tmp->type = MOTD_UNIVERSAL; else if (type == MOTD_COUNTRY) tmp->type = MOTD_COUNTRY; else if (type == MOTD_CONTINENT) tmp->type = MOTD_CONTINENT; else if (find_class(hostmask)) tmp->type = MOTD_CLASS; else if (ipmask_parse(hostmask, &tmp->address, &tmp->addrbits)) tmp->type = MOTD_IPMASK; else tmp->type = MOTD_HOSTMASK; if (hostmask != NULL) DupString(tmp->hostmask, hostmask); else tmp->hostmask = NULL; DupString(tmp->path, path); tmp->maxcount = maxcount; tmp->cache = 0; return tmp; }
/** Parse a user\@host mask into username and host or IP parts. * If \a host contains no username part, set \a aconf->username to * NULL. If the host part of \a host looks like an IP mask, set \a * aconf->addrbits and \a aconf->address to match. Otherwise, set * \a aconf->host, and set \a aconf->addrbits to -1. * @param[in,out] aconf Configuration item to set. * @param[in] host user\@host mask to parse. */ void conf_parse_userhost(struct ConfItem *aconf, char *host) { char *host_part; unsigned char addrbits; MyFree(aconf->username); MyFree(aconf->host); host_part = strchr(host, '@'); if (host_part) { *host_part = '\0'; DupString(aconf->username, host); host_part++; } else { aconf->username = NULL; host_part = host; } DupString(aconf->host, host_part); if (ipmask_parse(aconf->host, &aconf->address.addr, &addrbits)) aconf->addrbits = addrbits; else aconf->addrbits = -1; }
static int trusts_cmdtrustlist(void *source, int cargc, char **cargv) { nick *sender = source; trustgroup *tg = NULL; int found = 0, remaining = 50; char *name; trusthost *th; struct irc_in_addr ip; unsigned char bits; int showchildren; char *cmpbuf; if(cargc < 1) return CMD_USAGE; if(strcmp(cargv[0], "-v") == 0) { if(cargc < 2) return CMD_USAGE; showchildren = 1; name = cargv[1]; } else { showchildren = 0; name = cargv[0]; } tg = tg_strtotg(name); if(tg) { displaygroup(sender, tg, showchildren); controlreply(sender, "End of list."); return CMD_OK; } if(ipmask_parse(name, &ip, &bits)) { th = th_getbyhost(&ip); if(!th) { controlreply(sender, "Specified IP address is not trusted."); return CMD_OK; } displaygroup(sender, th->group, showchildren); controlreply(sender, "End of list."); return CMD_OK; } if(name[0] == '&') { int size = strlen(name) + strlen("Qwhois") + 1; cmpbuf = alloca(size); snprintf(cmpbuf, size, "Qwhois%s", name); } else { cmpbuf = NULL; } for(tg=tglist;tg;tg=tg->next) { if(cmpbuf) { if(!tg->contact->content || strcasecmp(cmpbuf, tg->contact->content)) continue; } else if(match(name, tg->name->content)) { continue; } displaygroup(sender, tg, showchildren); if(--remaining == 0) { controlreply(sender, "Maximum number of matches reached."); return CMD_OK; } found = 1; } if(found) { controlreply(sender, "End of list."); } else { controlreply(sender, "No matches found."); } return CMD_OK; }
/** Send a (prefixed) command to all users matching \a to as \a who. * @warning \a pattern must not contain %v. * @param[in] from Source of the command. * @param[in] cmd Long name of command. * @param[in] tok Short name of command. * @param[in] to Destination host/server mask. * @param[in] one Client direction to skip (or NULL). * @param[in] who Type of match for \a to (either MATCH_HOST or MATCH_SERVER). * @param[in] pattern Format string for command arguments. */ void sendcmdto_match(struct Client *from, const char *cmd, const char *tok, const char *to, struct Client *one, unsigned int who, const char *pattern, ...) { struct VarData vd; struct irc_in_addr addr; struct Client *cptr; struct MsgBuf *user_mb; struct MsgBuf *serv_mb; unsigned char nbits; vd.vd_format = pattern; /* See if destination looks like an IP mask. */ if (!ipmask_parse(to, &addr, &nbits)) nbits = 255; /* Build buffer to send to users */ va_start(vd.vd_args, pattern); /* TODO-ZOLTAN: Revisar el tema de Globales if (IsUser(from) && IsService(cli_user(from)->server)) */ user_mb = msgq_make(0, "%:#C %s %v", from, cmd, &vd); /* else { char *mask, *msg; mask = (char *)va_arg(vd.vd_args, char *); msg = (char *)va_arg(vd.vd_args, char *); user_mb = msgq_make(0, "%:#C %s :*** Global Message -> (%s): %s", from, cmd, mask, msg); } */ va_end(vd.vd_args); /* Build buffer to send to servers */ va_start(vd.vd_args, pattern); serv_mb = msgq_make(&me, "%C %s %v", from, tok, &vd); va_end(vd.vd_args); /* send buffer along */ bump_sentalong(one); for (cptr = GlobalClientList; cptr; cptr = cli_next(cptr)) { if (cli_sentalong(cptr) == sentalong_marker || !IsRegistered(cptr) || IsServer(cptr) || !match_it(from, cptr, to, &addr, nbits, who) || cli_fd(cli_from(cptr)) < 0) continue; /* skip it */ cli_sentalong(cptr) = sentalong_marker; if (MyConnect(cptr)) /* send right buffer */ send_buffer(cptr, user_mb, 0); else send_buffer(cptr, serv_mb, 0); } msgq_clean(user_mb); msgq_clean(serv_mb); }
int patrol_isip(char *host) { struct irc_in_addr ip; unsigned char bits; return (ipmask_parse(host, &ip, &bits)); }
/* * m_who - generic message handler * * parv[0] = sender prefix * parv[1] = nickname mask list * parv[2] = additional selection flag, only 'o' for now. * and %flags to specify what fields to output * plus a ,querytype if the t flag is specified * so the final thing will be like o%tnchu,777 * parv[3] = _optional_ parameter that overrides parv[1] * This can be used as "/quote who foo % :The Black Hacker * to find me, parv[3] _can_ contain spaces !. */ int m_who(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { char *mask; /* The mask we are looking for */ char ch; /* Scratch char register */ struct Channel *chptr; /* Channel to show */ struct Client *acptr; /* Client to show */ int bitsel; /* Mask of selectors to apply */ int matchsel; /* Which fields the match should apply on */ int counter; /* Query size counter, initially used to count fields */ int commas; /* Does our mask contain any comma ? If so is a list.. */ int fields; /* Mask of fields to show */ int isthere = 0; /* When this set the user is member of chptr */ char *nick; /* Single element extracted from the mask list */ char *p; /* Scratch char pointer */ char *qrt; /* Pointer to the query type */ static char mymask[512]; /* To save the mask before corrupting it */ /* Let's find where is our mask, and if actually contains something */ mask = ((parc > 1) ? parv[1] : 0); if (parc > 3 && parv[3]) mask = parv[3]; if (mask && ((mask[0] == '\0') || (mask[1] == '\0' && ((mask[0] == '0') || (mask[0] == '*'))))) mask = 0; /* Evaluate the flags now, we consider the second parameter as "matchFlags%fieldsToInclude,querytype" */ bitsel = fields = counter = matchsel = 0; qrt = 0; if (parc > 2 && parv[2] && *parv[2]) { p = parv[2]; while (((ch = *(p++))) && (ch != '%') && (ch != ',')) switch (ch) { case 'd': case 'D': bitsel |= WHOSELECT_DELAY; continue; case 'o': case 'O': bitsel |= WHOSELECT_OPER; continue; case 'x': case 'X': bitsel |= WHOSELECT_EXTRA; if (HasPriv(sptr, PRIV_WHOX)) log_write(LS_WHO, L_INFO, LOG_NOSNOTICE, "%#C WHO %s %s", sptr, (BadPtr(parv[3]) ? parv[1] : parv[3]), parv[2]); continue; case 'n': case 'N': matchsel |= WHO_FIELD_NIC; continue; case 'u': case 'U': matchsel |= WHO_FIELD_UID; continue; case 'h': case 'H': matchsel |= WHO_FIELD_HOS; continue; case 'i': case 'I': matchsel |= WHO_FIELD_NIP; continue; case 's': case 'S': matchsel |= WHO_FIELD_SER; continue; case 'r': case 'R': matchsel |= WHO_FIELD_REN; continue; case 'a': case 'A': matchsel |= WHO_FIELD_ACC; continue; } if (ch == '%') while ((ch = *p++) && (ch != ',')) { counter++; switch (ch) { case 'c': case 'C': fields |= WHO_FIELD_CHA; break; case 'd': case 'D': fields |= WHO_FIELD_DIS; break; case 'f': case 'F': fields |= WHO_FIELD_FLA; break; case 'h': case 'H': fields |= WHO_FIELD_HOS; break; case 'i': case 'I': fields |= WHO_FIELD_NIP; break; case 'l': case 'L': fields |= WHO_FIELD_IDL; case 'n': case 'N': fields |= WHO_FIELD_NIC; break; case 'r': case 'R': fields |= WHO_FIELD_REN; break; case 's': case 'S': fields |= WHO_FIELD_SER; break; case 't': case 'T': fields |= WHO_FIELD_QTY; break; case 'u': case 'U': fields |= WHO_FIELD_UID; break; case 'a': case 'A': fields |= WHO_FIELD_ACC; break; case 'o': case 'O': fields |= WHO_FIELD_OPL; break; default: break; } }; if (ch) qrt = p; } if (!matchsel) matchsel = WHO_FIELD_DEF; if (!fields) counter = 7; if (feature_bool(FEAT_HIS_WHO_SERVERNAME) && !IsAnOper(sptr)) matchsel &= ~WHO_FIELD_SER; if (qrt && (fields & WHO_FIELD_QTY)) { p = qrt; if (!((*p > '9') || (*p < '0'))) p++; if (!((*p > '9') || (*p < '0'))) p++; if (!((*p > '9') || (*p < '0'))) p++; *p = '\0'; } else qrt = 0; /* I'd love to add also a check on the number of matches fields per time */ counter = (2048 / (counter + 4)); if (mask && (strlen(mask) > 510)) mask[510] = '\0'; move_marker(); commas = (mask && strchr(mask, ',')); /* First treat mask as a list of plain nicks/channels */ if (mask) { strcpy(mymask, mask); for (p = 0, nick = ircd_strtok(&p, mymask, ","); nick; nick = ircd_strtok(&p, 0, ",")) { if (IsChannelName(nick) && (chptr = FindChannel(nick))) { isthere = (find_channel_member(sptr, chptr) != 0); if (isthere || SEE_CHANNEL(sptr, chptr, bitsel)) { struct Membership* member; for (member = chptr->members; member; member = member->next_member) { acptr = member->user; if ((bitsel & WHOSELECT_OPER) && !SeeOper(sptr,acptr)) continue; if ((acptr != sptr) && ((member->status & CHFL_ZOMBIE) || ((member->status & CHFL_DELAYED) && !(bitsel & WHOSELECT_DELAY)))) continue; if (!(isthere || (SEE_USER(sptr, acptr, bitsel)))) continue; if (!Process(acptr)) /* This can't be moved before other checks */ continue; if (!(isthere || (SHOW_MORE(sptr, counter)))) break; do_who(sptr, acptr, chptr, fields, qrt); } } } else { if ((acptr = FindUser(nick)) && ((!(bitsel & WHOSELECT_OPER)) || SeeOper(sptr,acptr)) && Process(acptr) && SHOW_MORE(sptr, counter)) { do_who(sptr, acptr, 0, fields, qrt); } } } } /* If we didn't have any comma in the mask treat it as a real mask and try to match all relevant fields */ if (!(commas || (counter < 1))) { struct irc_in_addr imask; int minlen, cset; unsigned char ibits; if (mask) { matchcomp(mymask, &minlen, &cset, mask); if (!ipmask_parse(mask, &imask, &ibits)) matchsel &= ~WHO_FIELD_NIP; if ((minlen > NICKLEN) || !(cset & NTL_IRCNK)) matchsel &= ~WHO_FIELD_NIC; if ((matchsel & WHO_FIELD_SER) && ((minlen > HOSTLEN) || (!(cset & NTL_IRCHN)) || (!markMatchexServer(mymask, minlen)))) matchsel &= ~WHO_FIELD_SER; if ((minlen > USERLEN) || !(cset & NTL_IRCUI)) matchsel &= ~WHO_FIELD_UID; if ((minlen > HOSTLEN) || !(cset & NTL_IRCHN)) matchsel &= ~WHO_FIELD_HOS; if ((minlen > ACCOUNTLEN)) matchsel &= ~WHO_FIELD_ACC; } /* First of all loop through the clients in common channels */ if ((!(counter < 1)) && matchsel) { struct Membership* member; struct Membership* chan; for (chan = cli_user(sptr)->channel; chan; chan = chan->next_channel) { chptr = chan->channel; for (member = chptr->members; member; member = member->next_member) { acptr = member->user; if (!(IsUser(acptr) && Process(acptr))) continue; /* Now Process() is at the beginning, if we fail we'll never have to show this acptr in this query */ if ((bitsel & WHOSELECT_OPER) && !SeeOper(sptr,acptr)) continue; if ((mask) && ((!(matchsel & WHO_FIELD_NIC)) || matchexec(cli_name(acptr), mymask, minlen)) && ((!(matchsel & WHO_FIELD_UID)) || matchexec(cli_user(acptr)->username, mymask, minlen)) && ((!(matchsel & WHO_FIELD_SER)) || (!(HasFlag(cli_user(acptr)->server, FLAG_MAP)))) && ((!(matchsel & WHO_FIELD_HOS)) || matchexec(cli_user(acptr)->host, mymask, minlen)) && ((!(matchsel & WHO_FIELD_HOS)) || !HasHiddenHost(acptr) || !IsAnOper(sptr) || matchexec(cli_user(acptr)->realhost, mymask, minlen)) && ((!(matchsel & WHO_FIELD_REN)) || matchexec(cli_info(acptr), mymask, minlen)) && ((!(matchsel & WHO_FIELD_NIP)) || (HasHiddenHost(acptr) && !IsAnOper(sptr)) || !ipmask_check(&cli_ip(acptr), &imask, ibits)) && ((!(matchsel & WHO_FIELD_ACC)) || matchexec(cli_user(acptr)->account, mymask, minlen))) continue; if (!SHOW_MORE(sptr, counter)) break; do_who(sptr, acptr, chptr, fields, qrt); } } } /* Loop through all clients :-\, if we still have something to match to and we can show more clients */ if ((!(counter < 1)) && matchsel) for (acptr = cli_prev(&me); acptr; acptr = cli_prev(acptr)) { if (!(IsUser(acptr) && Process(acptr))) continue; if ((bitsel & WHOSELECT_OPER) && !SeeOper(sptr,acptr)) continue; if (!(SEE_USER(sptr, acptr, bitsel))) continue; if ((mask) && ((!(matchsel & WHO_FIELD_NIC)) || matchexec(cli_name(acptr), mymask, minlen)) && ((!(matchsel & WHO_FIELD_UID)) || matchexec(cli_user(acptr)->username, mymask, minlen)) && ((!(matchsel & WHO_FIELD_SER)) || (!(HasFlag(cli_user(acptr)->server, FLAG_MAP)))) && ((!(matchsel & WHO_FIELD_HOS)) || matchexec(cli_user(acptr)->host, mymask, minlen)) && ((!(matchsel & WHO_FIELD_HOS)) || !HasHiddenHost(acptr) || !IsAnOper(sptr) || matchexec(cli_user(acptr)->realhost, mymask, minlen)) && ((!(matchsel & WHO_FIELD_REN)) || matchexec(cli_info(acptr), mymask, minlen)) && ((!(matchsel & WHO_FIELD_NIP)) || (HasHiddenHost(acptr) && !IsAnOper(sptr)) || !ipmask_check(&cli_ip(acptr), &imask, ibits)) && ((!(matchsel & WHO_FIELD_ACC)) || matchexec(cli_user(acptr)->account, mymask, minlen))) continue; if (!SHOW_MORE(sptr, counter)) break; do_who(sptr, acptr, 0, fields, qrt); } } /* Make a clean mask suitable to be sent in the "end of" */ if (mask && (p = strchr(mask, ' '))) *p = '\0'; /* Notify the user if we decided that his query was too long */ if (counter < 0) send_reply(sptr, ERR_QUERYTOOLONG, BadPtr(mask) ? "*" : mask); send_reply(sptr, RPL_ENDOFWHO, BadPtr(mask) ? "*" : mask); return 0; }