Esempio n. 1
0
/** Send a server notice to all users with the indicated \a mode except
 * for \a one.
 * @param[in] one Client direction to skip (or NULL).
 * @param[in] mode One mode character.
 * @param[in] pattern Format string for server notice.
 * @param[in] vl Argument list for format string.
 */
void vsendto_mode_butone(struct Client *one, struct Client *from, const char *mode,
                           const char *pattern, va_list vl)
{
  struct VarData vd;
  struct MsgBuf *mb;
  struct Client* acptr = 0;

  vd.vd_format = pattern;
  va_copy(vd.vd_args, vl);

  /* send to local users */
   mb = msgq_make(0, ":%s " MSG_NOTICE " * :*** Notice -- %v", cli_name(from),
              &vd);
  for (acptr = &me; acptr; acptr = cli_prev(acptr)) {
    if (IsUser(acptr))  {
      switch (*mode) {
        case 'O':
          if (IsLocOp(acptr))
            send_buffer(acptr, mb, 0);
          break;
        case 'o':
          if (IsOper(acptr))
            send_buffer(acptr, mb, 0);
          break;
        default:
          break; /* ignore, should only happen if incorrectly injected via raw */
      }
    }
  }
  msgq_clean(mb);
}
Esempio n. 2
0
/*
 *  mo_squit (oper)
 *
 *    parv[0] = sender prefix
 *    parv[1] = server name
 *    parv[2] = comment (optional)
 *
 */
int mo_squit(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  const char* server;
  struct Client *acptr;
  struct Client *acptr2;
  char *comment;
      
  if (parc < 2) 
    return need_more_params(sptr, "SQUIT");

  if (parc < 3 || BadPtr(parv[2]))
    comment = cli_name(sptr);
  else
    comment = parv[2];

  server = parv[1];
  /*
   * The following allows wild cards in SQUIT. Only useful
   * when the command is issued by an oper.
   */
  for (acptr = GlobalClientList; (acptr = next_client(acptr, server));
      acptr = cli_next(acptr)) {
    if (IsServer(acptr) || IsMe(acptr))
      break;
  }
  
  /* Not found? Bugger. */
  if (!acptr || IsMe(acptr))
    return send_reply(sptr, ERR_NOSUCHSERVER, server);

  /*
   * Look for a matching server that is closer,
   * that way we won't accidentally squit two close
   * servers like davis.* and davis-r.* when typing
   * /SQUIT davis*
   */
  for (acptr2 = cli_serv(acptr)->up; acptr2 != &me;
      acptr2 = cli_serv(acptr2)->up)
    if (!match(server, cli_name(acptr2)))
      acptr = acptr2;
  
  /* Disallow local opers to squit remote servers */
  if (IsLocOp(sptr) && !MyConnect(acptr))
    return send_reply(sptr, ERR_NOPRIVILEGES);

  return exit_client(cptr, acptr, sptr, comment);
}
Esempio n. 3
0
DLLFUNC int m_chghost(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
	aClient *acptr;

	if (MyClient(sptr) && !IsAnOper(sptr))
	{
		sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,
			parv[0]);
		return 0;
	}

#ifdef DISABLE_USERMOD
	if (MyClient(sptr))
	{
		sendto_one(sptr, err_str(ERR_DISABLED), me.name, sptr->name, "CHGHOST",
			"This command is disabled on this server");
		return 0;
	}
#endif

	if ((parc < 3) || !*parv[2])
	{
		sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, sptr->name, "CHGHOST");
		return 0;
	}

	if (strlen(parv[2]) > (HOSTLEN))
	{
		sendnotice(sptr, "*** ChgName Error: Requested hostname too long -- rejected.");
		return 0;
	}

	if (!valid_host(parv[2]))
	{
		sendnotice(sptr, "*** /ChgHost Error: A hostname may contain a-z, A-Z, 0-9, '-' & '.' - Please only use them");
		return 0;
	}

	if (parv[2][0] == ':')
	{
		sendnotice(sptr, "*** A hostname cannot start with ':'");
		return 0;
	}

	if ((acptr = find_person(parv[1], NULL)))
	{
		if (MyClient(sptr) && (IsLocOp(sptr) && !MyClient(acptr)))
		{
			sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,
				parv[0]);
			return 0;
		}

		if (!strcmp(GetHost(acptr), parv[2]))
		{
			sendnotice(sptr, "*** /ChgHost Error: requested host is same as current host.");
			return 0;
		}
		switch (UHOST_ALLOWED)
		{
			case UHALLOW_NEVER:
				if (MyClient(sptr))
				{
					sendto_one(sptr, err_str(ERR_DISABLED), me.name, sptr->name, "CHGHOST",
						"This command is disabled on this server");
					return 0;
				}
				break;
			case UHALLOW_ALWAYS:
				break;
			case UHALLOW_NOCHANS:
				if (IsPerson(acptr) && MyClient(sptr) && acptr->user->joined)
				{
					sendnotice(sptr, "*** /ChgHost can not be used while %s is on a channel", acptr->name);
					return 0;
				}
				break;
			case UHALLOW_REJOIN:
				rejoin_doquits(acptr);
				/* join sent later when the host has been changed */
				break;
		}
				
		if (!IsULine(sptr))
		{
			sendto_snomask(SNO_EYES,
			    "%s changed the virtual hostname of %s (%s@%s) to be %s",
			    sptr->name, acptr->name, acptr->user->username,
			    acptr->user->realhost, parv[2]);
			/* Logging added by XeRXeS */
 		      	ircd_log(LOG_CHGCMDS,                                         
				"CHGHOST: %s changed the virtual hostname of %s (%s@%s) to be %s",
				sptr->name, acptr->name, acptr->user->username, acptr->user->realhost, parv[2]); 
		}
 
                  
		acptr->umodes |= UMODE_HIDE;
		acptr->umodes |= UMODE_SETHOST;
		sendto_server(cptr, 0, 0, ":%s CHGHOST %s %s",
		    sptr->name, acptr->name, parv[2]);
		if (acptr->user->virthost)
		{
			MyFree(acptr->user->virthost);
			acptr->user->virthost = 0;
		}
		acptr->user->virthost = strdup(parv[2]);
		if (UHOST_ALLOWED == UHALLOW_REJOIN)
			rejoin_dojoinandmode(acptr);
		return 0;
	}
	else
	{
		sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, sptr->name,
		    parv[1]);
		return 0;
	}
	return 0;
}
Esempio n. 4
0
/*
 * m_squit - SQUIT message handler
 *      parv[0] = sender prefix
 *      parv[1] = server name
 *      parv[2] = comment
 */
int m_squit(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  struct ConfItem* aconf;
  char*            server;
  struct Client*   acptr;
  char  *comment = (parc > 2 && parv[2]) ? parv[2] : cptr->name;

  if (!IsPrivileged(sptr))
    {
      sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]);
      return 0;
    }

  if (parc > 1)
    {
      server = parv[1];
      /*
      ** To accomodate host masking, a squit for a masked server
      ** name is expanded if the incoming mask is the same as
      ** the server name for that link to the name of link.
      */
      while ((*server == '*') && IsServer(cptr))
        {
          aconf = cptr->serv->nline;
          if (!aconf)
            break;
          if (!irccmp(server, my_name_for_link(me.name, aconf)))
            server = cptr->name;
          break; /* WARNING is normal here */
          /* NOTREACHED */
        }
      /*
      ** The following allows wild cards in SQUIT. Only useful
      ** when the command is issued by an oper.
      */
      for (acptr = GlobalClientList; (acptr = next_client(acptr, server));
           acptr = acptr->next)
        if (IsServer(acptr) || IsMe(acptr))
          break;
      if (acptr && IsMe(acptr))
        {
          acptr = cptr;
          server = cptr->name;
        }
    }
  else
    {
      /*
      ** This is actually protocol error. But, well, closing
      ** the link is very proper answer to that...
      **
      ** Closing the client's connection probably wouldn't do much
      ** good.. any oper out there should know that the proper way
      ** to disconnect is /QUIT :)
      **
      ** its still valid if its not a local client, its then
      ** a protocol error for sure -Dianora
      */
      if(MyClient(sptr))
        {
          sendto_one(sptr, form_str(ERR_NEEDMOREPARAMS),
               me.name, parv[0], "SQUIT");
          return 0;
        }
      else
        {
          server = cptr->host;
          acptr = cptr;
        }
    }

  /*
  ** SQUIT semantics is tricky, be careful...
  **
  ** The old (irc2.2PL1 and earlier) code just cleans away the
  ** server client from the links (because it is never true
  ** "cptr == acptr".
  **
  ** This logic here works the same way until "SQUIT host" hits
  ** the server having the target "host" as local link. Then it
  ** will do a real cleanup spewing SQUIT's and QUIT's to all
  ** directions, also to the link from which the orinal SQUIT
  ** came, generating one unnecessary "SQUIT host" back to that
  ** link.
  **
  ** One may think that this could be implemented like
  ** "hunt_server" (e.g. just pass on "SQUIT" without doing
  ** nothing until the server having the link as local is
  ** reached). Unfortunately this wouldn't work in the real life,
  ** because either target may be unreachable or may not comply
  ** with the request. In either case it would leave target in
  ** links--no command to clear it away. So, it's better just
  ** clean out while going forward, just to be sure.
  **
  ** ...of course, even better cleanout would be to QUIT/SQUIT
  ** dependant users/servers already on the way out, but
  ** currently there is not enough information about remote
  ** clients to do this...   --msa
  */
  if (!acptr)
    {
      sendto_one(sptr, form_str(ERR_NOSUCHSERVER),
                 me.name, parv[0], server);
      return 0;
    }
  if (IsLocOp(sptr) && !MyConnect(acptr))
    {
      sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]);
      return 0;
    }

  if (MyClient(sptr) && !IsOperRemote(sptr) && !MyConnect(acptr))
    {
      sendto_one(sptr,":%s NOTICE %s :You have no R flag",me.name,parv[0]);
      return 0;
    }

  /*
  **  Notify all opers, if my local link is remotely squitted
  */
  if (MyConnect(acptr) && !IsAnOper(cptr))
    {
      sendto_ops_butone(NULL, &me,
                        ":%s WALLOPS :Received SQUIT %s from %s (%s)",
                        me.name, server, get_client_name(sptr,FALSE), comment);
      log(L_TRACE, "SQUIT From %s : %s (%s)", parv[0], server, comment);
    }
  else if (MyConnect(acptr))
    sendto_ops("Received SQUIT %s from %s (%s)",
               acptr->name, get_client_name(sptr,FALSE), comment);
  
  return exit_client(cptr, acptr, sptr, comment);
}
Esempio n. 5
0
/** Handle a CONNECT message from an operator.
 *
 * \a parv has the following elements:
 * \li \a parv[1] is the server that should initiate the connection
 * \li \a parv[2] is the port number to connect on (zero for the default)
 * \li \a parv[3] is the server to connect to
 *
 * See @ref m_functions for discussion of the arguments.
 * @param[in] cptr Client that sent us the message.
 * @param[in] sptr Original source of message.
 * @param[in] parc Number of arguments.
 * @param[in] parv Argument vector.
 */
int mo_connect(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  unsigned short   port;
  unsigned short   tmpport;
  const char*      rule;
  struct ConfItem* aconf;
  struct Client*   acptr;
  struct Jupe*     ajupe;

  assert(0 != cptr);
  assert(cptr == sptr);
  assert(IsAnOper(sptr));

  if (parc < 2)
    return need_more_params(sptr, "CONNECT");

  if (parc > 3) {
    /*
     * if parc > 3, we are trying to connect two remote
     * servers to each other
     */
    if (IsLocOp(sptr)) {
      /*
       * Only allow LocOps to make local CONNECTS --SRB
       */
      return send_reply(cptr, ERR_NOPRIVILEGES);
    }
    else {
      struct Client* acptr2;
      struct Client* acptr3;

      if (!(acptr3 = find_match_server(parv[3]))) {
        return send_reply(sptr, ERR_NOSUCHSERVER, parv[3]);
      }

      /*
       * Look for closest matching server 
       * needed for "/connect blah 4400 *"?
       */
      for (acptr2 = acptr3; acptr2 != &me; acptr2 = cli_serv(acptr2)->up) {
        if (!match(parv[3], cli_name(acptr2)))
          acptr3 = acptr2;
      }
      parv[3] = cli_name(acptr3);
      if (hunt_server_cmd(sptr, CMD_CONNECT, cptr, 1, "%s %s :%C", 3, parc,
			  parv) != HUNTED_ISME)
        return 0;
    }
  }
  /*
   * need to find the conf entry first so we can use the server name from
   * the conf entry instead of parv[1] to find out if the server is already
   * present below. --Bleep
   */
  if (0 == (aconf = conf_find_server(parv[1]))) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Connect: Host %s not listed "
		  "in ircd.conf", sptr, parv[1]);
    return 0;
  }
  /*
   * use aconf->name to look up the server, see above
   */
  if ((acptr = FindServer(aconf->name))) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Connect: Server %s already "
		  "exists from %s", sptr, parv[1], cli_name(cli_from(acptr)));
    return 0;
  }
  /*
   * Evaluate connection rules...  If no rules found, allow the
   * connect.   Otherwise stop with the first true rule (ie: rules
   * are ored together.  Oper connects are effected only by D
   * lines (CRULEALL) not d lines (CRULEAUTO).
   */
  if ((rule = conf_eval_crule(aconf->name, CRULE_ALL))) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Connect: Disallowed by rule: %s", sptr, rule);
    return 0;
  }
  /*
   * Check to see if the server is juped; if it is, disallow the connect
   */
  if ((ajupe = jupe_find(aconf->name)) && JupeIsActive(ajupe)) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Connect: Server %s is juped: %s",
		  sptr, JupeServer(ajupe), JupeReason(ajupe));
    return 0;
  }
  /*
   *  Get port number from user, if given. If not specified,
   *  use the default from configuration structure. If missing
   *  from there, then use the precompiled default.
   */
  port = aconf->address.port;
  if (parc > 2) {
    assert(0 != parv[2]);
    if (0 == (port = atoi(parv[2]))) {
      sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Connect: Invalid port number",
		    sptr);
      return 0;
    }
  }
  if (0 == port && 0 == (port = feature_int(FEAT_SERVER_PORT))) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Connect: missing port number",
		  sptr);
    return 0;
  }

  tmpport = aconf->address.port;
  aconf->address.port = port;

  if (connect_server(aconf, sptr)) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :*** Connecting to %s.", sptr,
		  aconf->name);
  }
  else {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :*** Connection to %s failed",
		  sptr, aconf->name);
  }
  aconf->address.port = tmpport;
  return 0;
}
Esempio n. 6
0
int m_chgident(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
aClient *acptr;
char *s;
int  legalident = 1;

	if (MyClient(sptr) && !IsAnOper(sptr))
	{
		sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
		return 0;
	}


#ifdef DISABLE_USERMOD
	if (MyClient(sptr))
	{
		sendto_one(sptr, err_str(ERR_DISABLED), me.name, sptr->name, "CHGIDENT",
			"This command is disabled on this server");
		return 0;
	}
#endif

	if ((parc < 3) || !*parv[2])
	{
		sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, sptr->name, "CHGIDENT");
		return 0;
	}

	if (strlen(parv[2]) > (USERLEN))
	{
		sendnotice(sptr, "*** ChgIdent Error: Requested ident too long -- rejected.");
		return 0;
	}

	/* illegal?! */
	for (s = parv[2]; *s; s++)
	{
		if ((*s == '~') && (s == parv[2]))
			continue;
		if (!isallowed(*s))
		{
			legalident = 0;
		}
	}

	if (legalident == 0)
	{
		sendnotice(sptr, "*** /ChgIdent Error: A ident may contain a-z, A-Z, 0-9, '-' & '.' - Please only use them");
		return 0;
	}

	if ((acptr = find_person(parv[1], NULL)))
	{
		DYN_LOCAL(char, did_parts, acptr->user->joined);
		if (MyClient(sptr) && (IsLocOp(sptr) && !MyClient(acptr)))
		{
			sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name,
				parv[0]);
			DYN_FREE(did_parts);
			return 0;
		}

		switch (UHOST_ALLOWED)
		{
			case UHALLOW_NEVER:
				if (MyClient(sptr))
				{
					sendto_one(sptr, err_str(ERR_DISABLED), me.name, sptr->name, "CHGIDENT",
						"This command is disabled on this server");
					DYN_FREE(did_parts);
					return 0;
				}
				break;
			case UHALLOW_ALWAYS:
				break;
			case UHALLOW_NOCHANS:
				if (IsPerson(acptr) && MyClient(sptr) && acptr->user->joined)
				{
					sendnotice(sptr, "*** /ChgIdent can not be used while %s is on a channel", acptr->name);
					DYN_FREE(did_parts);
					return 0;
				}
				break;
			case UHALLOW_REJOIN:
				rejoin_doparts(acptr, did_parts);
				/* join sent later when the ident has been changed */
				break;
		}
		if (!IsULine(sptr))
		{
			sendto_snomask(SNO_EYES,
			    "%s changed the virtual ident of %s (%s@%s) to be %s",
			    sptr->name, acptr->name, acptr->user->username,
			    GetHost(acptr), parv[2]);
			/* Logging ability added by XeRXeS */
			ircd_log(LOG_CHGCMDS,
				"CHGIDENT: %s changed the virtual ident of %s (%s@%s) to be %s",
				sptr->name, acptr->name, acptr->user->username,    
				GetHost(acptr), parv[2]);
		}



		sendto_serv_butone_token(cptr, sptr->name,
		    MSG_CHGIDENT,
		    TOK_CHGIDENT, "%s %s", acptr->name, parv[2]);
		ircsprintf(acptr->user->username, "%s", parv[2]);
		if (UHOST_ALLOWED == UHALLOW_REJOIN)
			rejoin_dojoinandmode(acptr, did_parts);
		DYN_FREE(did_parts);
		return 0;
	}
Esempio n. 7
0
/*
** m_whois
**      parv[0] = sender prefix
**      parv[1] = nickname masklist
*/
int     m_whois(struct Client *cptr,
                struct Client *sptr,
                int parc,
                char *parv[])
{
  static anUser UnknownUser =
  {
    NULL,       /* next */
    NULL,       /* channel */
    NULL,       /* invited */
	NULL,		/* silence */
    NULL,       /* away */
    0,          /* last */
    1,          /* refcount */
    0,          /* joined */
    "<Unknown>"         /* server */
  };
  static char rpl_oper[] = "an IRC Operator";
  static char rpl_locop[] = "an IRC Operator - Local IRC Operator";
  static char rpl_sadmin[] = "an IRC Operator - Services Administrator";
  static char rpl_admin[] = "an IRC Operator - Server Administrator";   
  static char rpl_tadmin[] = "an IRC Operator - Technical Administrator";
  static char rpl_nadmin[] = "an IRC Operator - Network Administrator"; 
  
  Link  *lp;
  anUser        *user;
  struct Client *acptr, *a2cptr;
  aChannel *chptr;
  char  *nick, *name;
  /* char  *tmp; */
  char  *p = NULL;
  int   found, len, mlen;
  static time_t last_used=0L;
  char *nick_match=NULL, *user_match=NULL, *host_match=NULL, *server_match=NULL;
  char *name_match=NULL;
  int found_mode;
  int hits = 0;
  char *mename = me.name;

  if(sptr->user && sptr->user->vlink)
    mename = sptr->user->vlink->name;
  
  if (parc < 2)
    {
      sendto_one(sptr, form_str(ERR_NONICKNAMEGIVEN),
                 mename, parv[0]);
      return 0;
    }

  if(parc > 2)
    {
      if (hunt_server(cptr,sptr,":%s WHOIS %s :%s", 1,parc,parv) !=
          HUNTED_ISME)
        return 0;
      parv[1] = parv[2];
    }

  if(!IsAnOper(sptr) && !MyConnect(sptr)) /* pace non local requests */
    {
      if((last_used + WHOIS_WAIT) > CurrentTime)
        {
          /* Unfortunately, returning anything to a non local
           * request =might= increase sendq to be usable in a split hack
           * Sorry gang ;-( - Dianora
           */
          return 0;
        }
      else
        {
          last_used = CurrentTime;
        }
    }

  /* Multiple whois from remote hosts, can be used
   * to flood a server off. One could argue that multiple whois on
   * local server could remain. Lets think about that, for now
   * removing it totally. 
   * -Dianora 
   */

  /*  for (tmp = parv[1]; (nick = strtoken(&p, tmp, ",")); tmp = NULL) */
  nick = parv[1];
  p = strchr(parv[1],',');
  if(p)
    *p = '\0';

    {
      int       invis, member, wilds;
      found = 0;
      (void)collapse(nick);
      wilds = (nick[0]=='$' || strchr(nick, '?') || strchr(nick, '*'));
      /*
      ** We're no longer allowing remote users to generate
      ** requests with wildcards.
      */
      if (wilds && !IsAnOper(sptr))
        {
          sendto_one(sptr, form_str(ERR_NOSUCHNICK),
                     mename, parv[0], nick);
          return 0;
        }
      /*        continue; */

      /* If the nick doesn't have any wild cards in it,
       * then just pick it up from the hash table
       * - Dianora 
       */

      if(!wilds)
        {
          acptr = hash_find_client(nick,(struct Client *)NULL);
          if(!acptr)
            {
              sendto_one(sptr, form_str(ERR_NOSUCHNICK),
                         mename, parv[0], nick);

              sendto_one(sptr, form_str(RPL_ENDOFWHOIS),
                         mename, parv[0], parv[1]);
						 
              return 0;
              /*              continue; */
            }
          if(IsStealth(acptr)) { 
	    sendto_one(sptr, form_str(ERR_NOSUCHNICK), mename,
	     parv[0], nick);
	     return 0; // Add by ^Stinger^ after the idea of Soldier (:
	  } 
	  if(!IsPerson(acptr))
            {
              sendto_one(sptr, form_str(RPL_ENDOFWHOIS),
                         mename, parv[0], parv[1]);
              return 0;
            }
            /*      continue; */

          user = acptr->user ? acptr->user : &UnknownUser;
          name = (!*acptr->name) ? "?" : acptr->name;
          invis = IsInvisible(acptr);
          member = (user->channel) ? 1 : 0;

          a2cptr = find_server(user->server);
          
          sendto_one(sptr, form_str(RPL_WHOISUSER), mename,
        	    parv[0], name, acptr->username, acptr->host, acptr->info);

	  if((IsOper(sptr) || (acptr == sptr)) && WhoisExtension)
	  {
		sendto_one(sptr, form_str(RPL_WHOISREALHOST), mename,
		    parv[0], name, acptr->realhost);
	  }

          mlen = strlen(mename) + strlen(parv[0]) + 6 +
            strlen(name);
			
          *buf = '\0';			
          if (IsSsl(acptr))
          {
              sendto_one(sptr, form_str(RPL_WHOISSECURE), mename, parv[0], parv[1]);
          }

		  if(((!IsPrivate(acptr) || IsOper(sptr)) || (acptr==sptr))
		  && !IsStealth(acptr))
          for (len = 0, *buf = '\0', lp = user->channel; lp;
               lp = lp->next)
            {
              chptr = lp->value.chptr;
              if (ShowChannel(sptr, chptr))
                {
                  if (len + strlen(chptr->chname)
                      > (size_t) BUFSIZE - 4 - mlen)
                    {
                      sendto_one(sptr,
                                 ":%s %d %s %s :%s",
                                 mename,
                                 RPL_WHOISCHANNELS,
                                 parv[0], name, buf);
                      *buf = '\0';
                      len = 0;
                    }

		  found_mode = user_channel_mode(acptr, chptr);
#ifdef HIDE_OPS
		  if(is_chan_op(sptr,chptr))
#endif
		    {
		      if(found_mode & CHFL_CHANOP)
			*(buf + len++) = '@';
#ifdef HALFOPS
                     else if (found_mode & CHFL_HALFOP)
                       *(buf + len++) = '%';
#endif
		      else if (found_mode & CHFL_VOICE)
			*(buf + len++) = '+';
		    }
                  if (len)
                    *(buf + len) = '\0';
                  (void)strcpy(buf + len, chptr->chname);
                  len += strlen(chptr->chname);
                  (void)strcat(buf + len, " ");
                  len++;
                }
            }
          if (buf[0] != '\0')
            sendto_one(sptr, form_str(RPL_WHOISCHANNELS),
                       mename, parv[0], name, buf);
          if(IsAnOper(sptr) || !HideServerOnWhois)
            {
#ifdef SERVERHIDE
            if (!(IsAnOper(sptr) || acptr == sptr))
              sendto_one(sptr, form_str(RPL_WHOISSERVER),
                       mename, parv[0], name, NetworkName,
                       NetworkDesc);
            else
#endif
            if(acptr->user && acptr->user->vlink)
              sendto_one(sptr, form_str(RPL_WHOISSERVER),
                     mename, parv[0], name, user->vlink->name,
                     user->vlink->passwd);
            else
              {
                if(!IsService(acptr) || IsAnOper(sptr) || !HideServicesServer)
                sendto_one(sptr, form_str(RPL_WHOISSERVER),
                     mename, parv[0], name, user->server,
                     a2cptr?a2cptr->info:"*Not On This Net*");
              }
	    } /* if(IsAnOper(sptr) || HideServerOnWhois) */
	  if (IsIdentified(acptr))
            sendto_one(sptr, form_str(RPL_WHOISIDENTIFIED),
                       mename, parv[0], name);

          if (IsHelper(acptr))
        	sendto_one(sptr, form_str(RPL_WHOISHELPOP),
                           mename, parv[0], name);
					   
          if(IsOper(sptr) && WhoisExtension)
	  {
	    sendto_one(sptr, form_str(RPL_WHOISMODE),
		mename, parv[0], name, get_mode_string(acptr));
	  }
	  
	  if (user->away)
            sendto_one(sptr, form_str(RPL_AWAY), mename,
                       parv[0], name, user->away);
	if(!IsHideOper(acptr) || IsOper(sptr))
	  {	
	    if (IsNetAdmin(acptr))
              sendto_one(sptr, form_str(RPL_WHOISOPERATOR),   
                      mename, parv[0], name, rpl_nadmin);
	    else if (IsTechAdmin(acptr))
              sendto_one(sptr, form_str(RPL_WHOISOPERATOR),   
                      mename, parv[0], name, rpl_tadmin);						   
            else if (IsSAdmin(acptr))
              sendto_one(sptr, form_str(RPL_WHOISOPERATOR),   
                      mename, parv[0], name, rpl_sadmin);						   
            else if (IsAdmin(acptr))
              sendto_one(sptr, form_str(RPL_WHOISOPERATOR),  
                      mename, parv[0], name, rpl_admin);
            else if (IsOper(acptr))
              sendto_one(sptr, form_str(RPL_WHOISOPERATOR), 
            	mename, parv[0], name, rpl_oper);
            else if (IsLocOp(acptr))
              sendto_one(sptr, form_str(RPL_WHOISOPERATOR),
            	mename, parv[0], name, rpl_locop);
	  }
#ifdef WHOIS_NOTICE
          if ((IsOper(acptr)) && ((acptr)->umodes & UMODE_SPY) &&
              (MyConnect(sptr)) && (IsPerson(sptr)) && (acptr != sptr) && !is_silenced(sptr, acptr))
            sendto_one(acptr,
                       ":%s NOTICE %s :*** Notice -- %s (%s@%s) is doing a /whois on you.",
                       me.name, acptr->name, parv[0], sptr->username,
                       sptr->realhost);
#endif /* #ifdef WHOIS_NOTICE */


          if ((acptr->user
#ifdef SERVERHIDE
              && IsAnOper(sptr)
#endif
              && MyConnect(acptr)))
            sendto_one(sptr, form_str(RPL_WHOISIDLE),
                       mename, parv[0], name,
                       CurrentTime - user->last,
                       acptr->firsttime);
					   
          sendto_one(sptr, form_str(RPL_ENDOFWHOIS), mename, parv[0], parv[1]);
          
          return 0;
          /*      continue; */
        }

      /* wild is true so here we go */
          if(nick[0]==':') /* real name match */
            {
              name_match =  &nick[1];
              nick_match = NULL;
            }
          else
	  if(nick[0]=='$') /* server name match */
	    {
	      server_match = &nick[1];
	      nick_match = NULL;
	    }
	  else
		{
		  host_match = strchr(nick,'@');
		  if(host_match)
			{
			  if(*host_match)
				*(host_match++) = '\0';						  
			  user_match=nick;		  		  
			  if(host_match=='\0')
				host_match="*";		  			
			  if(user_match=='\0')
			  user_match="*";		  
			}
		  else
			nick_match = nick;
		}
		
	  				
      for (acptr = GlobalClientList; acptr;
           acptr = acptr->next)
        {
          if (IsServer(acptr))
            continue;
          /*
           * I'm always last :-) and acptr->next == NULL!!
           */
          if (IsMe(acptr))
            break;
          /*
           * 'Rules' established for sending a WHOIS reply:
           *
           *
           * - if wildcards are being used dont send a reply if
           *   the querier isnt any common channels and the
           *   client in question is invisible and wildcards are
           *   in use (allow exact matches only);
           *
           * - only send replies about common or public channels
           *   the target user(s) are on;
           */

/* If its an unregistered client, ignore it, it can
   be "seen" on a /trace anyway  -Dianora */

          if(!IsRegistered(acptr))
            continue;

          user = acptr->user ? acptr->user : &UnknownUser;
          name = (!*acptr->name) ? "?" : acptr->name;
		  
		  if(  (server_match && !match(server_match, user->server))
		    || (nick_match && !match(nick, name)) 
			|| (host_match && !match(host_match, acptr->realhost)
			   && !match(host_match, acptr->host))
			|| (user_match && !match(user_match, acptr->username))
			|| (name_match &&  !match(name_match, acptr->info))
			)
        	  continue;
			  
		  ++hits;
			  
          a2cptr = find_server(user->server);
          
          sendto_one(sptr, form_str(RPL_WHOISUSER), mename,
                    parv[0], name,
                    acptr->username, 
					IsOper(sptr) ? acptr->realhost : acptr->host,					 
					acptr->info);
					
          found = 1;
          mlen = strlen(mename) + strlen(parv[0]) + 6 +
            strlen(name);
          for (len = 0, *buf = '\0', lp = user->channel; lp;
               lp = lp->next)
            {
              chptr = lp->value.chptr;
              if (ShowChannel(sptr, chptr))
                {
                  if (len + strlen(chptr->chname)
                      > (size_t) BUFSIZE - 4 - mlen)
                    {
                      sendto_one(sptr,
                                 ":%s %d %s %s :%s",
                                 mename,
                                 RPL_WHOISCHANNELS,
                                 parv[0], name, buf);
                      *buf = '\0';
                      len = 0;
                    }
		  found_mode = user_channel_mode(acptr, chptr);
#ifdef HIDE_OPS
                  if(is_chan_op(sptr,chptr))
#endif
		     {
		       if (found_mode & CHFL_CHANOP)
			 *(buf + len++) = '@';
#ifdef HALFOPS
                     else if (found_mode & CHFL_HALFOP)
                        *(buf + len++) = '%';
#endif                                            
		       else if (found_mode & CHFL_VOICE)
			 *(buf + len++) = '+';
		     }
                  if (len)
                    *(buf + len) = '\0';
                  (void)strcpy(buf + len, chptr->chname);
                  len += strlen(chptr->chname);
                  (void)strcat(buf + len, " ");
                  len++;
                }
            }
          if (buf[0] != '\0')
            sendto_one(sptr, form_str(RPL_WHOISCHANNELS),
                       mename, parv[0], name, buf);
         
#ifdef SERVERHIDE
          if (!(IsAnOper(sptr) || acptr == sptr))
            sendto_one(sptr, form_str(RPL_WHOISSERVER),
                       mename, parv[0], name, NetworkName,
                       NetworkDesc);
          else    
#endif
          sendto_one(sptr, form_str(RPL_WHOISSERVER),
                     mename, parv[0], name, user->server,
                     a2cptr?a2cptr->info:"*Not On This Net*");

          if (user->away)
            sendto_one(sptr, form_str(RPL_AWAY), mename,
                       parv[0], name, user->away);



  		  if (IsNetAdmin(acptr))
                sendto_one(sptr, form_str(RPL_WHOISOPERATOR),   
                           mename, parv[0], name, rpl_nadmin);
		  else if (IsTechAdmin(acptr))
                sendto_one(sptr, form_str(RPL_WHOISOPERATOR),   
                           mename, parv[0], name, rpl_tadmin);						   
          else if (IsSAdmin(acptr))
                sendto_one(sptr, form_str(RPL_WHOISOPERATOR),   
                           mename, parv[0], name, rpl_sadmin);						   
          else if (IsAdmin(acptr))
                sendto_one(sptr, form_str(RPL_WHOISOPERATOR),  
                           mename, parv[0], name, rpl_admin);
          else if (IsAnOper(acptr))
                sendto_one(sptr, form_str(RPL_WHOISOPERATOR), 
                           mename, parv[0], name, rpl_oper);


#ifdef WHOIS_NOTICE
          if ((MyOper(acptr)) && ((acptr)->umodes & UMODE_SPY) &&
              (MyConnect(sptr)) && (IsPerson(sptr)) && (acptr != sptr))
            sendto_one(acptr,
                       ":%s NOTICE %s :*** Notice -- %s (%s@%s) is doing a /whois on you.",
                       mename, acptr->name, parv[0], sptr->username,
                       sptr->realhost);
#endif /* #ifdef WHOIS_NOTICE */

          if ((acptr->user
#ifdef SERVERHIDE
              && IsAnOper(sptr) 
#endif                 
              && MyConnect(acptr)))
            sendto_one(sptr, form_str(RPL_WHOISIDLE),
                       mename, parv[0], name,
                       CurrentTime - user->last,
                       acptr->firsttime);

		if(hits>50)
		  {
  			sendto_one(sptr,":%s NOTICE %s :Aborting /whois output as flood prevention",
				mename, sptr->name);			  
			break;
		  }
        }
		
      if (!found)	  
        sendto_one(sptr, form_str(ERR_NOSUCHNICK),
                   mename, parv[0], nick);
	  else
		sendto_one(sptr,":%s NOTICE %s :This /whois matched \2%i\2 user(s)", 
			mename, sptr->name,hits);
      /*
      if (p)
        p[-1] = ',';
        */
    }

  sendto_one(sptr, form_str(RPL_ENDOFWHOIS), mename, parv[0], parv[1]);
  
  return 0;
}
Esempio n. 8
0
/*
 * m_connect - CONNECT command handler
 * 
 * Added by Jto 11 Feb 1989
 *
 * m_connect
 *      parv[0] = sender prefix
 *      parv[1] = servername
 *      parv[2] = port number
 *      parv[3] = remote server
 */
int m_connect(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  int              port;
  int              tmpport;
  struct ConfItem* aconf;
  struct Client*   acptr;

  if (!IsPrivileged(sptr))
    {
      sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]);
      return -1;
    }

  if (IsLocOp(sptr) && parc > 3) {
    /* 
     * Only allow LocOps to make local CONNECTS --SRB
     */
    return 0;
  }

  if (MyConnect(sptr) && !IsOperRemote(sptr) && parc > 3)
    {
      sendto_one(sptr,":%s NOTICE %s :You have no R flag", me.name, parv[0]);
      return 0;
    }

  if (hunt_server(cptr, sptr,
                  ":%s CONNECT %s %s :%s", 3, parc, parv) != HUNTED_ISME)
    return 0;

  if (parc < 2 || *parv[1] == '\0')
    {
      sendto_one(sptr, form_str(ERR_NEEDMOREPARAMS),
                 me.name, parv[0], "CONNECT");
      return -1;
    }

  if ((acptr = find_server(parv[1])))
    {
      sendto_one(sptr, ":%s NOTICE %s :Connect: Server %s %s %s.",
                 me.name, parv[0], parv[1], "already exists from",
                 acptr->from->name);
      return 0;
    }

  /*
   * try to find the name, then host, if both fail notify ops and bail
   */
  if (!(aconf = find_conf_by_name(parv[1], CONF_CONNECT_SERVER))) {
#ifndef HIDE_SERVERS_IPS
    if (!(aconf = find_conf_by_host(parv[1], CONF_CONNECT_SERVER))) {
#endif
      sendto_one(sptr,
                 "NOTICE %s :Connect: Host %s not listed in ircd.conf",
                 parv[0], parv[1]);
      return 0;
#ifndef HIDE_SERVERS_IPS
    }
#endif
  }
  assert(0 != aconf);
  /*
   * Get port number from user, if given. If not specified,
   * use the default form configuration structure. If missing
   * from there, then use the precompiled default.
   */
  tmpport = port = aconf->port;
  if (parc > 2 && !EmptyString(parv[2]))
    {
#ifdef NEG_PORT
      if ((port = atoi(parv[2])) < 0)
#else    
      if ((port = atoi(parv[2])) <= 0)
#endif      
        {
          sendto_one(sptr, "NOTICE %s :Connect: Illegal port number",
                     parv[0]);
          return 0;
        }
    }
#ifdef NEG_PORT
  else if (port < 0 && (port = PORTNUM) <= 0)
#else    
  else if (port <= 0 && (port = PORTNUM) <= 0)
#endif  
    {
      sendto_one(sptr, ":%s NOTICE %s :Connect: missing port number",
                 me.name, parv[0]);
      return 0;
    }
#ifdef NEG_PORT
  if (port == 0)
    port = tmpport; /* From conf */
  if (port == 0)
    port = PORTNUM; /* Default if there wasn't one set in conf */
#endif
    
  /*
   * Notify all operators about remote connect requests
   */
  if (!IsAnOper(cptr))
    {
      sendto_ops_butone(NULL, &me,
                        ":%s WALLOPS :Remote CONNECT %s %s from %s",
                        me.name, parv[1], parv[2] ? parv[2] : "",
                        get_client_name(sptr, FALSE));

      irclog(L_TRACE, "CONNECT From %s : %s %s", 
          parv[0], parv[1], parv[2] ? parv[2] : "");
    }

  aconf->port = port;
  /*
   * at this point we should be calling connect_server with a valid
   * C:line and a valid port in the C:line
   */
  if (connect_server(aconf, sptr, 0))
#if (defined SERVERHIDE) || (defined HIDE_SERVERS_IPS)
    sendto_one(sptr, ":%s NOTICE %s :*** Connecting to %s[%s].%d",
               me.name, parv[0], "255.255.255.255", aconf->name, aconf->port);
  else
    sendto_one(sptr, ":%s NOTICE %s :*** Couldn't connect to %s.%d",
               me.name, parv[0], "255.255.255.255",aconf->port);
#else
    sendto_one(sptr, ":%s NOTICE %s :*** Connecting to %s[%s].%d",
               me.name, parv[0], aconf->host, aconf->name, aconf->port);
  else