Exemplo n.º 1
0
/** 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;
}
Exemplo n.º 2
0
/** Find Except configuration for \a cptr with flags matching \a flags
 * @param[in] cptr Client to match an Except configuration against.
 * @param[in] mask Bitmask of EFLAG_* flags to test for exemption.
 * @return -1 if an exception was found, 0 otherwise.
 */
int find_except_conf(struct Client *cptr, int flags)
{
  struct ExceptConf *econf;

  if (flags & EFLAG_IPCHECK) {
    if (IsIPCheckExempt(cptr))
      return -1;
    if (IsNotIPCheckExempt(cptr))
      return 0;
  }

  for(econf = exceptConfList; econf; econf = econf->next) {
    if (!(econf->flags & flags))
      continue;

    if (econf->usermask && match(econf->usermask, cli_username(cptr)))
      continue;
    if (econf->bits > 0) {
      if (!ipmask_check(&cli_ip(cptr), &econf->address, econf->bits))
        continue;
    } else if (econf->hostmask && match(econf->hostmask, cli_sockhost(cptr)))
      continue;

    if (econf->flags & EFLAG_IPCHECK)
      SetIPCheckExempt(cptr);

    return -1;
  }

  if (flags & EFLAG_IPCHECK)
    SetNotIPCheckExempt(cptr);

  return 0;
}
Exemplo n.º 3
0
/** Find a ConfItem that has the same name and user+host fields as
 * specified.  Requires an exact match for \a name.
 * @param name Name to match
 * @param cptr Client to match against
 * @param statmask Filter for ConfItem::status
 * @return First found matching ConfItem.
 */
struct ConfItem* find_conf_exact(const char* name, struct Client *cptr, int statmask)
{
  struct ConfItem *tmp;

  for (tmp = GlobalConfList; tmp; tmp = tmp->next) {
    if (!(tmp->status & statmask) || !tmp->name || !tmp->host ||
        0 != ircd_strcmp(tmp->name, name))
      continue;
    if (tmp->username
        && (EmptyString(cli_username(cptr))
            || match(tmp->username, cli_username(cptr))))
      continue;
    if (tmp->addrbits < 0)
    {
      if (match(tmp->host, cli_sockhost(cptr)))
        continue;
    }
    else if (!ipmask_check(&cli_ip(cptr), &tmp->address.addr, tmp->addrbits))
      continue;
    if ((tmp->status & CONF_OPERATOR)
        && (MaxLinks(tmp->conn_class) > 0)
        && (tmp->clients >= MaxLinks(tmp->conn_class)))
      continue;
    return tmp;
  }
  return 0;
}
Exemplo n.º 4
0
/** Find a matching Z-line for a user.
 * @param[in] cptr Client to compare against.
 * @param[in] flags Bitwise combination of ZLINE_GLOBAL and/or
 * ZLINE_LASTMOD to limit matches.
 * @return Matching Z-line, or NULL if none are found.
 */
struct Zline *
zline_lookup(struct Client *cptr, unsigned int flags)
{
  struct Zline *zline;
  struct Zline *szline;

  if (find_except_conf(cptr, EFLAG_ZLINE))
    return 0;

  zliter(GlobalZlineList, zline, szline) {
    if ((flags & ZLINE_GLOBAL && zline->zl_flags & ZLINE_LOCAL) ||
        (flags & ZLINE_LASTMOD && !zline->zl_lastmod))
      continue;

    if (ZlineIsIpMask(zline)) {
      if (!irc_in_addr_type_cmp(&cli_ip(cptr), &zline->zl_addr) && zline->zl_bits)
        continue;
      if (!ipmask_check(&cli_ip(cptr), &zline->zl_addr, zline->zl_bits))
        continue;
    }
    else {
      if (match(zline->zl_mask, cli_sock_ip(cptr)) != 0)
        continue;
    }
    if (ZlineIsActive(zline))
      return zline;
  }
  /*
   * No Zlines matched
   */
  return 0;
}
Exemplo n.º 5
0
/** Find Except configuration for \a addr with flags matching \a flags
 * @param[in] addr IP Address to match an Except configuration against.
 * @param[in] mask Bitmask of EFLAG_* flags to test for exemption.
 * @return -1 if an exception was found, 0 otherwise.
 */
int find_except_conf_by_ip(const struct irc_in_addr *addr, int flags)
{
  struct ExceptConf *econf;
  char ipbuf[SOCKIPLEN];

  ircd_ntoa_r(ipbuf, addr);

  for(econf = exceptConfList; econf; econf = econf->next) {
    if (!(econf->flags & flags))
      continue;

    /* Attempt to match usermask against "%nobody" to ensure this isn't
     * an Except that requires a user name to match.
     */
    if (econf->usermask && match(econf->usermask, "%nobody"))
      continue;
    if (econf->bits > 0) {
      if (!ipmask_check(addr, &econf->address, econf->bits))
        continue;
    } else if (econf->hostmask && match(econf->hostmask, ipbuf))
      continue;

    return -1;
  }

  return 0;
}
Exemplo n.º 6
0
/** Find Spoofhost configuration for \a cptr with spoof host matching host and
 *  a password matching \a passwd
 * @param[in] cptr Client to match Spoofhost configuration against.
 * @param[in] host Spoofhost host to look for, if NULL look for an autoapply Spoofhost.
 * @param[in] passwd Password to compare against Spoofhost configuration.
 * @param[out] status 0 for Success, 1 for invalid password and 2 for no Spoofhost configuration.
 * @return SHostConf struct of matching Spoofhost configuration or 0 on error.
 */
struct SHostConf* find_shost_conf(struct Client *cptr, char *host, char *passwd, int *status)
{
  struct SHostConf* sconf;
  char *crypted;
  int res = 0;

  *status = 2;

  for(sconf = shostConfList; sconf; sconf = sconf->next) {
    if ((host == NULL) && !(sconf->flags & SHFLAG_AUTOAPPLY))
      continue;
    if (host != NULL) {
      if (!(sconf->flags & SHFLAG_ISMASK) && strcmp(sconf->spoofhost, host))
        continue;
      if ((sconf->flags & SHFLAG_ISMASK) && match(sconf->spoofhost, host))
        continue;
    }

    if (sconf->usermask) {
      if (match(sconf->usermask, cli_username(cptr)) &&
          !((sconf->flags & SHFLAG_MATCHUSER) && !match(sconf->usermask, cli_user(cptr)->username)))
        continue;
    }

    if (sconf->bits > 0) {
      if (!ipmask_check(&cli_ip(cptr), &sconf->address, sconf->bits))
        continue;
    } else if (sconf->hostmask && match(sconf->hostmask, cli_sockhost(cptr)))
      continue;

    *status = 1;
    res = 0;

    if ((host == NULL) && (sconf->flags & SHFLAG_AUTOAPPLY)) {
      *status = 0;
      return sconf;
    }

    if (EmptyString(passwd) && !EmptyString(sconf->passwd))
      continue;
    if (!EmptyString(passwd) && EmptyString(sconf->passwd))
      continue;
    if (!EmptyString(passwd) && !EmptyString(sconf->passwd)) {
      crypted = ircd_crypt(passwd, sconf->passwd);
      if (!crypted)
        continue;

      res = strcmp(crypted, sconf->passwd);
      MyFree(crypted);
    }

    if (0 == res) {
      *status = 0;
      return sconf;
    }
  }

  return 0;
}
Exemplo n.º 7
0
void *cidr_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput) {
  nick *np = (nick *)theinput;
  struct cidr_localdata *c = thenode->localdata;

  if(!ipmask_check(&np->ipaddress, &c->ip, c->bits))
    return (void *)0;

  return (void *)1;
}
Exemplo n.º 8
0
trusthost *th_getbyhostandmask(struct irc_in_addr *ip, uint32_t bits) {
  trustgroup *tg;
  trusthost *th;

  for(tg=tglist;tg;tg=tg->next)
    for(th=tg->hosts;th;th=th->next)
      if(ipmask_check(ip, &th->ip, 128) && th->bits == bits)
        return th;

  return NULL;
}
Exemplo n.º 9
0
/** Check local clients against a new Z-line.
 * If the Z-line is inactive, return immediately.
 * Otherwise, if any users match it, disconnect them.
 * @param[in] cptr Peer connect that sent the Z-line.
 * @param[in] sptr Client that originated the Z-line.
 * @param[in] zline New Z-line to check.
 * @return Zero, unless \a sptr Z-lined himself, in which case CPTR_KILLED.
 */
static int
do_zline(struct Client *cptr, struct Client *sptr, struct Zline *zline)
{
  struct Client *acptr;
  int fd, retval = 0, tval;

  if (feature_bool(FEAT_DISABLE_ZLINES))
    return 0; /* Z-lines are disabled */

  if (!ZlineIsActive(zline)) /* no action taken on inactive zlines */
    return 0;

  for (fd = HighestFd; fd >= 0; --fd) {
    /*
     * get the users!
     */
    if ((acptr = LocalClientArray[fd])) {
      if (!cli_user(acptr))
	continue;

      if (find_except_conf(acptr, EFLAG_ZLINE))
        continue;

      /* IP zline */
      if (ZlineIsIpMask(zline)) {
        if (!irc_in_addr_type_cmp(&cli_ip(acptr), &zline->zl_addr) && zline->zl_bits)
          continue;
        if (!ipmask_check(&cli_ip(acptr), &zline->zl_addr, zline->zl_bits))
          continue;
      }
      else {
        if (match(zline->zl_mask, cli_sock_ip(acptr)) != 0)
          continue;
      }

      /* ok, here's one that got Z-lined */
      send_reply(acptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP, ":%s",
      	   zline->zl_reason);

      /* let the ops know about it */
      sendto_opmask_butone_global(&me, SNO_GLINE, "Z-line active for %s",
                           get_client_name(acptr, SHOW_IP));

      /* and get rid of him */
      if ((tval = exit_client_msg(cptr, acptr, &me, "Z-lined%s%s%s",
          (!feature_bool(FEAT_HIS_ZLINE_REASON) ? " (" : ""),
          (!feature_bool(FEAT_HIS_ZLINE_REASON) ? zline->zl_reason : ""),
          (!feature_bool(FEAT_HIS_ZLINE_REASON) ? ")" : ""))))
        retval = tval; /* retain killed status */
    }
  }
  return retval;
}
Exemplo n.º 10
0
/** Find an IP registry entry if one exists for the IP address.
 * If \a ip looks like an IPv6 address, only consider the first 64 bits
 * of the address. Otherwise, only consider the final 32 bits.
 * @param[in] ip IP address to search for.
 * @return Matching registry entry, or NULL if none exists.
 */
static struct IPRegistryEntry* ip_registry_find(const struct irc_in_addr *ip)
{
  struct irc_in_addr canon;
  struct IPRegistryEntry* entry;
  ip_registry_canonicalize(&canon, ip);
  entry = hashTable[ip_registry_hash(&canon)];
  for ( ; entry; entry = entry->next) {
    int bits = (canon.in6_16[0] == htons(0x2002)) ? 48 : 64;
    if (ipmask_check(&canon, &entry->addr, bits))
      break;
  }
  return entry;
}
Exemplo n.º 11
0
Arquivo: send.c Projeto: mojadita/ircd
/** Check whether a client matches a target mask.
 * @param[in] from Client trying to send a message (ignored).
 * @param[in] one Client being considered as a target.
 * @param[in] mask Mask for matching against.
 * @param[in] addr IP address prefix to match against.
 * @param[in] nbits Number of bits in \a addr (> 128 if none valid).
 * @param[in] what Type of match (either MATCH_HOST or MATCH_SERVER).
 * @return Non-zero if \a one matches, zero if not.
 */
static int match_it(struct Client *from, struct Client *one, const char *mask,
                    struct irc_in_addr *addr, unsigned char nbits, int what)
{
  switch (what)
  {
    case MATCH_HOST:
      return ((nbits <= 128 && ipmask_check(&cli_ip(one), addr, nbits)) ||
        match(mask, cli_user(one)->host) == 0 ||
        (HasHiddenHost(one) && match(mask, cli_user(one)->realhost) == 0));
    case MATCH_SERVER:
    default:
      return (match(mask, cli_name(cli_user(one)->server)) == 0);
  }
}
Exemplo n.º 12
0
/* returns the ip with the smallest prefix that is still a superset of the given host */
trusthost *th_getsmallestsupersetbyhost(struct irc_in_addr *ip, uint32_t bits) {
  trustgroup *tg;
  trusthost *th, *result = NULL;
  uint32_t sbits;

  for(tg=tglist;tg;tg=tg->next) {
    for(th=tg->hosts;th;th=th->next) {
      if(ipmask_check(ip, &th->ip, th->bits)) {
        if((th->bits < bits) && (!result || (th->bits > sbits))) {
          sbits = th->bits;
          result = th;
        }
      }
    }
  }

  return result;
}
Exemplo n.º 13
0
/** Get all the exception flags that apply to the client \a cptr
 * @param[in] cptr Client to find the exception flags for.
 * @return Bitmask of all the exception flags found to apply to \a cptr
 */
int get_except_flags(struct Client *cptr)
{
  int flags = 0;
  struct ExceptConf *econf;

  for(econf = exceptConfList; econf; econf = econf->next) {
    if (econf->usermask && match(econf->usermask, cli_username(cptr)))
      continue;
    if (econf->bits > 0) {
      if (!ipmask_check(&cli_ip(cptr), &econf->address, econf->bits))
        continue;
    } else if (econf->hostmask && match(econf->hostmask, cli_sockhost(cptr)))
      continue;

    flags |= econf->flags;
  }

  return flags;
}
Exemplo n.º 14
0
/** Find WebIRC configuration for \a cptr with password matching \a passwd
 * @param[in] cptr Client to match WebIRC configuration against.
 * @param[in] passwd Password to compare against WebIRC configuration.
 * @param[out] status 0 for Success, 1 for invalid password and 2 for no WebIRC configuration.
 * @return WebIRCConf struct of matching WebIRC configuration or 0 on error.
 */
struct WebIRCConf* find_webirc_conf(struct Client *cptr, char *passwd, int* status)
{
  struct WebIRCConf *wconf;
  char *crypted;
  int res;

  *status = 2;

  if (!passwd)
    return 0;

  for(wconf = webircConfList; wconf; wconf = wconf->next) {
    if (wconf->usermask && match(wconf->usermask, cli_username(cptr)))
      continue;
    if (wconf->bits > 0) {
      if (!ipmask_check(&cli_ip(cptr), &wconf->address, wconf->bits))
        continue;
    } else if (wconf->hostmask && match(wconf->hostmask, cli_sockhost(cptr)))
      continue;

    *status = 1;

    if (!wconf->passwd) {
      *status = 0;
      return wconf;
    }

    crypted = ircd_crypt(passwd, wconf->passwd);

    if (!crypted)
      continue;

    res = strcmp(crypted, wconf->passwd);
    MyFree(crypted);

    if (0 == res) {
      *status = 0;
      return wconf;
    }
  }

  return 0;
}
Exemplo n.º 15
0
/** Find the first (best) Client block to attach.
 * @param cptr Client for whom to check rules.
 * @return Authorization check result.
 */
enum AuthorizationCheckResult attach_iline(struct Client* cptr)
{
  struct ConfItem* aconf;

  assert(0 != cptr);

  for (aconf = GlobalConfList; aconf; aconf = aconf->next) {
    if (aconf->status != CONF_CLIENT)
      continue;
    /* If you change any of this logic, please make corresponding
     * changes in conf_debug_iline() below.
     */
    if (aconf->address.port && aconf->address.port != cli_listener(cptr)->addr.port)
      continue;
    if (aconf->username && match(aconf->username, cli_username(cptr)))
      continue;
    if (aconf->host && match(aconf->host, cli_sockhost(cptr)))
      continue;
    if (aconf->countrymask && match(aconf->countrymask, cli_countrycode(cptr)))
      continue;
    if (aconf->continentmask && match(aconf->continentmask, cli_continentcode(cptr)))
      continue;
    if ((aconf->addrbits >= 0)
        && !ipmask_check(&cli_ip(cptr), &aconf->address.addr, aconf->addrbits))
      continue;
    if (IPcheck_nr(cptr) > aconf->maximum)
      return ACR_TOO_MANY_FROM_IP;
    if (aconf->redirserver && !EmptyString(aconf->redirserver)) {
      send_reply(cptr, RPL_BOUNCE, aconf->redirserver, aconf->redirport);
      return ACR_NO_AUTHORIZATION;
    }
    if (aconf->username && !IsWebIRCUserIdent(cptr) && (aconf->flags & CONF_NOIDENTTILDE))
      SetFlag(cptr, FLAG_DOID);
    return attach_conf(cptr, aconf);
  }
  return ACR_NO_AUTHORIZATION;
}
Exemplo n.º 16
0
/** Find the first matching MOTD block for a user.
 * If the user is remote, always use remote MOTD.
 * Otherwise, if there is a hostmask- or class-based MOTD that matches
 * the user, use it.
 * Otherwise, use the local MOTD.
 * @param[in] cptr Client to find MOTD for.
 * @return Pointer to first matching MOTD for the client.
 */
static struct Motd *
motd_lookup(struct Client *cptr)
{
  struct Motd *ptr;
  char *c_class = NULL;

  assert(0 != cptr);

  if (!MyUser(cptr)) /* not my user, always return remote motd */
    return MotdList.remote;

  c_class = get_client_class(cptr);
  assert(c_class != NULL);

  /* check the motd blocks first */
  for (ptr = MotdList.other; ptr; ptr = ptr->next)
  {
    if (ptr->type == MOTD_CLASS
        && !match(ptr->hostmask, c_class))
      return ptr;
    else if (ptr->type == MOTD_HOSTMASK
             && !match(ptr->hostmask, cli_sockhost(cptr)))
      return ptr;
    else if (ptr->type == MOTD_IPMASK
             && ipmask_check(&cli_ip(cptr), &ptr->address, ptr->addrbits))
      return ptr;
    else if (ptr->type == MOTD_COUNTRY
             && !match(ptr->hostmask, cli_countrycode(cptr)))
      return ptr;
    else if (ptr->type == MOTD_CONTINENT
             && !match(ptr->hostmask, cli_continentcode(cptr)))
      return ptr;
  }

  return MotdList.local; /* Ok, return the default motd */
}
Exemplo n.º 17
0
/*
 * 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;
}
Exemplo n.º 18
0
/** Interpret \a client as a client specifier and show which Client
 * block(s) match that client.
 *
 * The client specifier may contain an IP address, hostname, listener
 * port, or a combination of those separated by commas.  IP addresses
 * and hostnamese may be preceded by "username@"; the last given
 * username will be used for the match.
 *
 * @param[in] client Client specifier.
 * @return Matching Client block structure.
 */
struct ConfItem *conf_debug_iline(const char *client)
{
  struct irc_in_addr address;
  struct ConfItem *aconf;
  struct DenyConf *deny;
  char *sep;
  unsigned short listener;
  char username[USERLEN+1], hostname[HOSTLEN+1], realname[REALLEN+1];

  /* Initialize variables. */
  listener = 0;
  memset(&address, 0, sizeof(address));
  memset(&username, 0, sizeof(username));
  memset(&hostname, 0, sizeof(hostname));
  memset(&realname, 0, sizeof(realname));

  /* Parse client specifier. */
  while (*client) {
    struct irc_in_addr tmpaddr;
    long tmp;

    /* Try to parse as listener port number first. */
    tmp = strtol(client, &sep, 10);
    if (tmp && (*sep == '\0' || *sep == ',')) {
      listener = tmp;
      client = sep + (*sep != '\0');
      continue;
    }

    /* Maybe username@ before an IP address or hostname? */
    tmp = strcspn(client, ",@");
    if (client[tmp] == '@') {
      if (tmp > USERLEN)
        tmp = USERLEN;
      ircd_strncpy(username, client, tmp);
      /* and fall through */
      client += tmp + 1;
    }

    /* Looks like an IP address? */
    tmp = ircd_aton(&tmpaddr, client);
    if (tmp && (client[tmp] == '\0' || client[tmp] == ',')) {
        memcpy(&address, &tmpaddr, sizeof(address));
        client += tmp + (client[tmp] != '\0');
        continue;
    }

    /* Realname? */
    if (client[0] == '$' && client[1] == 'R') {
      client += 2;
      for (tmp = 0; *client != '\0' && *client != ',' && tmp < REALLEN; ++client, ++tmp) {
        if (*client == '\\')
          realname[tmp] = *++client;
        else
          realname[tmp] = *client;
      }
      continue;
    }

    /* Else must be a hostname. */
    tmp = strcspn(client, ",");
    if (tmp > HOSTLEN)
      tmp = HOSTLEN;
    ircd_strncpy(hostname, client, tmp);
    client += tmp + (client[tmp] != '\0');
  }

  /* Walk configuration to find matching Client block. */
  for (aconf = GlobalConfList; aconf; aconf = aconf->next) {
    if (aconf->status != CONF_CLIENT)
      continue;
    if (aconf->address.port && aconf->address.port != listener) {
      fprintf(stdout, "Listener port mismatch: %u != %u\n", aconf->address.port, listener);
      continue;
    }
    if (aconf->username && match(aconf->username, username)) {
      fprintf(stdout, "Username mismatch: %s != %s\n", aconf->username, username);
      continue;
    }
    if (aconf->host && match(aconf->host, hostname)) {
      fprintf(stdout, "Hostname mismatch: %s != %s\n", aconf->host, hostname);
      continue;
    }
    if ((aconf->addrbits >= 0)
        && !ipmask_check(&address, &aconf->address.addr, aconf->addrbits)) {
      fprintf(stdout, "IP address mismatch: %s != %s\n", aconf->name, ircd_ntoa(&address));
      continue;
    }
    fprintf(stdout, "Match! username=%s host=%s ip=%s class=%s maxlinks=%u password=%s\n",
            (aconf->username ? aconf->username : "******"),
            (aconf->host ? aconf->host : "(null)"),
            (aconf->name ? aconf->name : "(null)"),
            ConfClass(aconf), aconf->maximum,
            (aconf->passwd ? aconf->passwd : "(null)"));
    break;
  }

  /* If no authorization, say so and exit. */
  if (!aconf)
  {
    fprintf(stdout, "No authorization found.\n");
    return NULL;
  }

  /* Look for a Kill block with the user's name on it. */
  for (deny = denyConfList; deny; deny = deny->next) {
    if (deny->usermask && match(deny->usermask, username))
      continue;
    if (deny->realmask && match(deny->realmask, realname))
      continue;
    if (deny->bits > 0) {
      if (!ipmask_check(&address, &deny->address, deny->bits))
        continue;
    } else if (deny->hostmask && match(deny->hostmask, hostname))
      continue;

    /* Looks like a match; report it. */
    fprintf(stdout, "Denied! usermask=%s realmask=\"%s\" hostmask=%s (bits=%u)\n",
            deny->usermask ? deny->usermask : "(null)",
            deny->realmask ? deny->realmask : "(null)",
            deny->hostmask ? deny->hostmask : "(null)",
            deny->bits);
  }

  return aconf;
}
Exemplo n.º 19
0
/** Searches for a K/G-line for a client.  If one is found, notify the
 * user and disconnect them.
 * @param cptr Client to search for.
 * @return 0 if client is accepted; -1 if client was locally denied
 * (K-line); -2 if client was globally denied (G-line); -3 if client
 * was globally IP denied (Z-line).
 */
int find_kill(struct Client *cptr)
{
  const char*      host;
  const char*      name;
  const char*      realname;
  const char*      country;
  const char*      continent;
  const char*      version;
  struct DenyConf* deny;
  struct Gline*    agline = NULL;
  struct Zline*    azline = NULL;

  assert(0 != cptr);

  if (!cli_user(cptr))
    return 0;

  host = cli_sockhost(cptr);
  name = cli_user(cptr)->username;
  realname = cli_info(cptr);
  country = cli_countrycode(cptr);
  continent = cli_continentcode(cptr);
  version = cli_version(cptr);

  assert(strlen(host) <= HOSTLEN);
  assert((name ? strlen(name) : 0) <= HOSTLEN);
  assert((realname ? strlen(realname) : 0) <= REALLEN);
  assert((country ? strlen(country) : 0) <= 3);
  assert((continent ? strlen(continent) : 0) <= 3);
  assert((version ? strlen(version) : 0) <= VERSIONLEN);

  /* 2000-07-14: Rewrote this loop for massive speed increases.
   *             -- Isomer
   */
  if (!find_except_conf(cptr, EFLAG_KLINE)) {
    for (deny = denyConfList; deny; deny = deny->next) {
      if (deny->usermask && match(deny->usermask, name))
        continue;
      if (deny->realmask && match(deny->realmask, realname))
        continue;
      if (deny->countrymask && country && match(deny->countrymask, country))
        continue;
      if (deny->continentmask && continent && match(deny->continentmask, continent))
        continue;
      if (feature_bool(FEAT_CTCP_VERSIONING) && feature_bool(FEAT_CTCP_VERSIONING_KILL)) {
        if (deny->version && version && match(deny->version, version))
          continue;
      }
      if (deny->bits > 0) {
        if (!ipmask_check(&cli_ip(cptr), &deny->address, deny->bits))
          continue;
      } else if (deny->hostmask && match(deny->hostmask, host))
        continue;

      if ((deny->flags & DENY_FLAGS_AUTHEX) && IsAccount(cptr)) {
        if (!EmptyString(deny->mark) && EmptyString(cli_killmark(cptr)))
          ircd_strncpy(cli_killmark(cptr), deny->mark, BUFSIZE);
        continue;
      }

      if (EmptyString(deny->message))
        send_reply(cptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP,
                   ":Connection from your host is refused on this server.");
      else {
        if (deny->flags & DENY_FLAGS_FILE)
          killcomment(cptr, deny->message);
        else
          send_reply(cptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP, ":%s.", deny->message);
      }
      return -1;
    }
  }

  /* Check Zlines here just in case a spoofed IP matches */
  if (!feature_bool(FEAT_DISABLE_ZLINES) && (azline = zline_lookup(cptr, 0))) {
    /*
     * find active zlines
     * added a check against the user's IP address to find_zline()
     */
    send_reply(cptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP, ":%s.", ZlineReason(azline));
    return -3;
  }

  /* Don't need to do an except lookup here as it's done in gline_lookup() */
  if (!feature_bool(FEAT_DISABLE_GLINES) && (agline = gline_lookup(cptr, 0))) {
    /*
     * find active glines
     * added a check against the user's IP address to find_gline() -Kev
     */
    send_reply(cptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP, ":%s.", GlineReason(agline));
    return -2;
  }

  return 0;
}
Exemplo n.º 20
0
void th_adjusthosts(trusthost *th, trusthost *superset, trusthost *subset) {
  struct irc_in_addr ipaddress_canonical;

  /*
   * First and foremost, CIDR doesn't allow hosts to cross boundaries, i.e. everything with a smaller prefix
   * is entirely contained with the prefix that is one smaller.
   * e.g. 0.0.0.0/23, 0.0.0.128/23, you can't have a single prefix for 0.0.0.64-0.0.0.192, instead
   * you have two, 0.0.0.64/26 and 0.0.0.128/26.
   *
   * This makes the code MUCH easier as the entire thing is one huge set/tree.
   *
   * Four cases here:
   * 1: host isn't covered by any existing hosts.
   * 2: host is covered by a less specific one only, e.g. adding 0.0.0.1/32, while 0.0.0.0/24 already exists.
   * 3: host is covered by a more specific one only, e.g. adding 0.0.0.0/24 while 0.0.0.1/32 already exists
   *    (note there might be more than one more specific host, e.g. 0.0.0.1/32 and 0.0.0.2/32).
   * 4: covered by more and less specific cases, e.g. adding 0.0.0.0/24 to: { 0.0.0.1/32, 0.0.0.2/32, 0.0.0.0/16 }.
   *
   * CASE 1
   * ------
   *
   * !superset && !subset
   *
   * Scan through the host hash and add any clients which match our host, this is exactly the same as case 3
   * but without needing to check (though checking doesn't hurt), so we'll just use the code for that.
   *
   * CASE 2
   * ------
   *
   * superset && !subset
   *
   * We have the less specific host in 'superset', we know it is the only one so pull out clients in it's
   * ->users list matching our new host.
   * No need to look for extra hosts in the main nick hash as they're all covered already.
   *
   * CASE 3
   * ------
   *
   * !superset && subset
   *
   * We have one host in 'subset', but there might be more than one, we don't care though!
   * We can scan the entire host hash and pull out any hosts that match us and don't have
   * a trust group already, this ignores any with a more specific prefix.
   *
   * CASE 4
   * ------
   *
   * superset && subset
   *
   * Here we first fix up the ones less specific then us, so we just perform what we did for case 2,
   * then we perform what we did for case 3.
   *
   * So in summary:
   *   CASE 1: DO 3
   *   CASE 2: (work)
   *   CASE 3: (work)
   *   CASE 4: DO 2; DO 3
   * Or:
   *   if(2 || 4)     : DO 2
   *   if(1 || 3 || 4): DO 3
   */

  /* we let the compiler do the boolean minimisation for clarity reasons */

  if((superset && !subset) || (superset && subset)) { /* cases 2 and 4 */
    nick *np, *nnp;
    for(np=superset->users;np;np=nnp) {
      nnp = nextbytrust(np);
      ip_canonicalize_tunnel(&ipaddress_canonical, &np->ipaddress);
      if(ipmask_check(&ipaddress_canonical, &th->ip, th->bits)) {
        trusts_lostnick(np, 1);
        trusts_newnick(np, 1);
      }
    }
  }

  if((!superset && !subset) || (!superset && subset) || (superset && subset)) { /* cases 1, 3 and 4 */
    nick *np;
    int i;

    for(i=0;i<NICKHASHSIZE;i++) {
      for(np=nicktable[i];np;np=np->next) {
        ip_canonicalize_tunnel(&ipaddress_canonical, &np->ipaddress);
        if(!gettrusthost(np) && ipmask_check(&ipaddress_canonical, &th->ip, th->bits))
          trusts_newnick(np, 1);
      }
    }
  }
}