Exemple #1
0
void relay_private_notice(struct Client* sptr, const char* name, const char* text)
{
  struct Client* acptr;
  assert(0 != sptr);
  assert(0 != name);
  assert(0 != text);

  if (0 == (acptr = FindUser(name)))
    return;
  if (IsOnlyreg(acptr) && !IsRegnick(sptr)) {
	  send_reply(sptr, RPL_MSGONLYREG, cli_name(acptr));
	  return;
  }

  if (!IsChannelService(acptr))
  {
    if (check_target_limit(sptr, acptr, cli_name(acptr), 0))
    {
      return;
    }
    if (is_silenced(sptr, acptr))
    {
      send_reply(sptr, ERR_SILENCED, cli_name(acptr));
      return;
    }
  }
    
  /*
   * deliver the message
   */
  if (MyUser(acptr))
    add_target(acptr, sptr);

  sendcmdto_one(sptr, CMD_NOTICE, acptr, "%C :%s", acptr, text);
}
Exemple #2
0
/** Send a jupe (or a list of jupes) to a server.
 * @param[in] sptr Client searching for jupes.
 * @param[in] server Name of jupe to search for (if NULL, list all).
 * @return Zero.
 */
int
jupe_list(struct Client *sptr, char *server)
{
  struct Jupe *jupe;
  struct Jupe *sjupe;

  if (server) {
    if (!(jupe = jupe_find(server))) /* no such jupe */
      return send_reply(sptr, ERR_NOSUCHJUPE, server);

    /* send jupe information along */
    send_reply(sptr, RPL_JUPELIST, jupe->ju_server, jupe->ju_expire + TSoffset,
	       JupeIsLocal(jupe) ? cli_name(&me) : "*",
	       JupeIsActive(jupe) ? '+' : '-', jupe->ju_reason);
  } else {
    for (jupe = GlobalJupeList; jupe; jupe = sjupe) { /* go through jupes */
      sjupe = jupe->ju_next;

      if (jupe->ju_expire <= CurrentTime) /* expire any that need expiring */
	jupe_free(jupe);
      else /* send jupe information along */
	send_reply(sptr, RPL_JUPELIST, jupe->ju_server,
		   jupe->ju_expire + TSoffset,
		   JupeIsLocal(jupe) ? cli_name(&me) : "*",
		   JupeIsActive(jupe) ? '+' : '-', jupe->ju_reason);
    }
  }

  /* end of jupe information */
  return send_reply(sptr, RPL_ENDOFJUPELIST);
}
Exemple #3
0
void server_relay_private_message(struct Client* sptr, const char* name, const char* text)
{
  struct Client* acptr;
  assert(0 != sptr);
  assert(0 != name);
  assert(0 != text);
  /*
   * nickname addressed?
   */
  if (0 == (acptr = findNUser(name)) || !IsUser(acptr)) {
    send_reply(sptr, SND_EXPLICIT | ERR_NOSUCHNICK, "* :Target left %s. "
	       "Failed to deliver: [%.20s]", feature_str(FEAT_NETWORK), text);
    return;
  }

  if (!IsChannelService(sptr) && is_silenced(sptr, acptr))
  {
    send_reply(sptr, ERR_SILENCED, cli_name(acptr));
    return;
  }

  if (IsOnlyreg(acptr) && !IsRegnick(sptr)) {
	  send_reply(sptr, RPL_MSGONLYREG, cli_name(acptr));
	  return;
  }

  if (MyUser(acptr))
    add_target(acptr, sptr);

  sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%C :%s", acptr, text);
}
/*
 * mr_pong - registration message handler
 *
 * parv[0] = sender prefix
 * parv[1] = pong response echo
 * NOTE: cptr is always unregistered here
 */
int mr_pong(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  assert(0 != cptr);
  assert(cptr == sptr);
  assert(!IsRegistered(sptr));

  ClrFlag(cptr, FLAG_PINGSENT);
  cli_lasttime(cptr) = CurrentTime;
  /*
   * Check to see if this is a PONG :cookie reply from an
   * unregistered user.  If so, process it. -record
   */
  if (0 != cli_cookie(sptr) && COOKIE_VERIFIED != cli_cookie(sptr)) {
    if (parc > 1 && cli_cookie(sptr) == atol(parv[parc - 1])) {
      cli_cookie(sptr) = COOKIE_VERIFIED;
      if (cli_user(sptr) && *(cli_user(sptr))->host && (cli_name(sptr))[0])
        /*
         * NICK and USER OK
         */
        return register_user(cptr, sptr, cli_name(sptr), cli_user(sptr)->username);
    }
    else  
      send_reply(sptr, SND_EXPLICIT | ERR_BADPING,
		 ":To connect, type /QUOTE PONG %u", cli_cookie(sptr));
  }
  return 0;
}
Exemple #5
0
void server_relay_private_notice(struct Client* sptr, const char* name, const char* text)
{
  struct Client* acptr;
  assert(0 != sptr);
  assert(0 != name);
  assert(0 != text);
  /*
   * nickname addressed?
   */
  if (0 == (acptr = findNUser(name)) || !IsUser(acptr))
    return;

  if (!IsChannelService(sptr) && is_silenced(sptr, acptr))
  {
    send_reply(sptr, ERR_SILENCED, cli_name(acptr));
    return;
  }

  if (IsOnlyreg(acptr) && !IsRegnick(sptr)) {
	  send_reply(sptr, RPL_MSGONLYREG, cli_name(acptr));
	  return;
  }

  if (MyUser(acptr))
    add_target(acptr, sptr);

  sendcmdto_one(sptr, CMD_NOTICE, acptr, "%C :%s", acptr, text);
}
Exemple #6
0
/*
 * mo_asll - oper message handler
 */
int mo_asll(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  char *mask;
  struct Client *acptr;
  int hits;
  int i;

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

  if (parc == 2 && MyUser(sptr))
    parv[parc++] = cli_name(&me);

  if (hunt_server_prio_cmd(sptr, CMD_ASLL, cptr, 1, "%s %C", 2, parc, parv) != HUNTED_ISME)
    return 0;
  mask = parv[1];

  for (i = hits = 0; i <= HighestFd; i++) {
    acptr = LocalClientArray[i];
    if (!acptr || !IsServer(acptr) || !MyConnect(acptr) || match(mask, cli_name(acptr)))
      continue;
    send_asll_reply(&me, sptr, cli_name(acptr), cli_serv(acptr)->asll_rtt,
      cli_serv(acptr)->asll_to, cli_serv(acptr)->asll_from);
    hits++;
  }
  sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :AsLL for %s: %d local servers matched", sptr, mask, hits);
  return 0;
}
Exemple #7
0
/*
 * ms_links - server message handler
 *
 * parv[0] = sender prefix
 * parv[1] = servername mask
 *
 * or
 *
 * parv[0] = sender prefix
 * parv[1] = server to query
 * parv[2] = servername mask
 */
int
ms_links(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
 {
   char *mask;
   struct Client *acptr;

   if (parc > 2)
   {
     if (hunt_server_cmd(sptr, CMD_LINKS, cptr, 1, "%C :%s", 1, parc, parv) !=
         HUNTED_ISME)
       return 0;
     mask = parv[2];
   }
   else
     mask = parc < 2 ? 0 : parv[1];
 
   for (acptr = GlobalClientList, collapse(mask); acptr; acptr = cli_next(acptr))
   {
     if (!IsServer(acptr) && !IsMe(acptr))
       continue;
     if (!BadPtr(mask) && match(mask, cli_name(acptr)))
       continue;
     send_reply(sptr, RPL_LINKS, cli_name(acptr), cli_name(cli_serv(acptr)->up),
                cli_hopcount(acptr), cli_serv(acptr)->prot,
                ((cli_info(acptr))[0] ? cli_info(acptr) : "(Unknown Location)"));
   }
 
   send_reply(sptr, RPL_ENDOFLINKS, BadPtr(mask) ? "*" : mask);
   return 0;
 }
Exemple #8
0
/** Display one or all Z-lines to a user.
 * If \a ipmask is not NULL, only send the first matching Z-line.
 * Otherwise send the whole list.
 * @param[in] sptr User asking for Z-line list.
 * @param[in] ipmask Z-line mask to search for (or NULL).
 * @return Zero.
 */
int
zline_list(struct Client *sptr, char *ipmask)
{
  struct Zline *zline;
  struct Zline *szline;

  if (ipmask) {
    if (!(zline = zline_find(ipmask, ZLINE_ANY))) /* no such zline */
      return send_reply(sptr, ERR_NOSUCHZLINE, ipmask);

    /* send zline information along */
    send_reply(sptr, RPL_ZLIST,
               zline->zl_mask, zline->zl_expire,
	       zline->zl_lastmod, zline->zl_lifetime,
	       ZlineIsLocal(zline) ? cli_name(&me) : "*",
	       zline->zl_state == ZLOCAL_ACTIVATED ? ">" :
	       (zline->zl_state == ZLOCAL_DEACTIVATED ? "<" : ""),
	       ZlineIsRemActive(zline) ? '+' : '-', zline->zl_reason);
  } else {
    zliter(GlobalZlineList, zline, szline) {
      send_reply(sptr, RPL_ZLIST,
		 zline->zl_mask, zline->zl_expire,
		 zline->zl_lastmod, zline->zl_lifetime,
		 ZlineIsLocal(zline) ? cli_name(&me) : "*",
		 zline->zl_state == ZLOCAL_ACTIVATED ? ">" :
		 (zline->zl_state == ZLOCAL_DEACTIVATED ? "<" : ""),
		 ZlineIsRemActive(zline) ? '+' : '-', zline->zl_reason);
    }
  }
Exemple #9
0
/** Handle a SILENCE command from a local user.
 * See @ref m_functions for general discussion of parameters.
 *
 * \a parv[1] may be any of the following:
 * \li Omitted or empty, to view your own silence list.
 * \li Nickname of a user, to view that user's silence list.
 * \li A comma-separated list of silence updates
 *
 * @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 m_silence(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  struct Client *acptr;
  struct Ban *sile;

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

  /* See if the user is requesting a silence list. */
  acptr = sptr;
  if (parc < 2 || EmptyString(parv[1]) || (acptr = FindUser(parv[1]))) {
    if (cli_user(acptr)) {
      for (sile = cli_user(acptr)->silence; sile; sile = sile->next) {
        send_reply(sptr, RPL_SILELIST, cli_name(acptr),
                   (sile->flags & BAN_EXCEPTION ? "~" : ""),  sile->banstr);
      }
    }
    send_reply(sptr, RPL_ENDOFSILELIST, cli_name(acptr));
    return 0;
  }

  /* The user must be attempting to update their list. */
  forward_silences(sptr, parv[1], NULL);
  return 0;
}
/*
 * mo_version - oper message handler
 *
 *   parv[0] = sender prefix
 *   parv[1] = servername
 */
int mo_version(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  struct Client *acptr;

  if (MyConnect(sptr) && parc > 1)
  {
    if (!(acptr = find_match_server(parv[1])))
    {
      send_reply(sptr, ERR_NOSUCHSERVER, parv[1]);
      return 0;
    }
    parv[1] = cli_name(acptr);
  }

  if (hunt_server_cmd(sptr, CMD_VERSION, cptr, feature_int(FEAT_HIS_REMOTE),
                                                           ":%C", 1,
                                                           parc, parv)
                      == HUNTED_ISME)
  {
    send_reply(sptr, RPL_VERSION, version, debugmode, cli_name(&me),
	       debug_serveropts());
    send_supported(sptr);
  }

  return 0;
}
Exemple #11
0
/** Complete non-blocking connect()-sequence. Check access and
 * terminate connection, if trouble detected.
 * @param cptr Client to which we have connected, with all ConfItem structs attached.
 * @return Zero on failure (caller should exit_client()), non-zero on success.
 */
static int completed_connection(struct Client* cptr)
{
  struct ConfItem *aconf;
  time_t newts;
  struct Client *acptr;
  int i;

  assert(0 != cptr);

  /*
   * get the socket status from the fd first to check if
   * connection actually succeeded
   */
  if ((cli_error(cptr) = os_get_sockerr(cli_fd(cptr)))) {
    const char* msg = strerror(cli_error(cptr));
    if (!msg)
      msg = "Unknown error";
    sendto_opmask_butone(0, SNO_OLDSNO, "Connection failed to %s: %s",
                         cli_name(cptr), msg);
    return 0;
  }
  if (!(aconf = find_conf_byname(cli_confs(cptr), cli_name(cptr), CONF_SERVER))) {
    sendto_opmask_butone(0, SNO_OLDSNO, "Lost Server Line for %s", cli_name(cptr));
    return 0;
  }
  if (s_state(&(cli_socket(cptr))) == SS_CONNECTING)
    socket_state(&(cli_socket(cptr)), SS_CONNECTED);

  if (!EmptyString(aconf->passwd))
    sendrawto_one(cptr, MSG_PASS " :%s", aconf->passwd);

  /*
   * Create a unique timestamp
   */
  newts = TStime();
  for (i = HighestFd; i > -1; --i) {
    if ((acptr = LocalClientArray[i]) && 
        (IsServer(acptr) || IsHandshake(acptr))) {
      if (cli_serv(acptr)->timestamp >= newts)
        newts = cli_serv(acptr)->timestamp + 1;
    }
  }
  assert(0 != cli_serv(cptr));

  cli_serv(cptr)->timestamp = newts;
  SetHandshake(cptr);
  /*
   * Make us timeout after twice the timeout for DNS look ups
   */
  cli_lasttime(cptr) = CurrentTime;
  ClearPingSent(cptr);

  sendrawto_one(cptr, MSG_SERVER " %s 1 %Tu %Tu J%s %s%s +%s6n :%s",
                cli_name(&me), cli_serv(&me)->timestamp, newts,
		MAJOR_PROTOCOL, NumServCap(&me),
		feature_bool(FEAT_HUB) ? "h" : "", cli_info(&me));

  return (IsDead(cptr)) ? 0 : 1;
}
int osc_quota_setdq(struct client_obd *cli, const unsigned int qid[],
		    u64 valid, u32 flags)
{
	int type;
	int rc = 0;

        ENTRY;

	if ((valid & (OBD_MD_FLALLQUOTA)) == 0)
		RETURN(0);

	for (type = 0; type < LL_MAXQUOTAS; type++) {
		struct osc_quota_info *oqi;

		if ((valid & md_quota_flag(type)) == 0)
			continue;

		/* lookup the ID in the per-type hash table */
		oqi = cfs_hash_lookup(cli->cl_quota_hash[type], &qid[type]);
		if ((flags & fl_quota_flag(type)) != 0) {
			/* This ID is getting close to its quota limit, let's
			 * switch to sync I/O */
			if (oqi != NULL)
				continue;

			oqi = osc_oqi_alloc(qid[type]);
			if (oqi == NULL) {
				rc = -ENOMEM;
				break;
			}

			rc = cfs_hash_add_unique(cli->cl_quota_hash[type],
						 &qid[type], &oqi->oqi_hash);
			/* race with others? */
			if (rc == -EALREADY) {
				rc = 0;
				OBD_SLAB_FREE_PTR(oqi, osc_quota_kmem);
			}

			CDEBUG(D_QUOTA, "%s: setdq to insert for %s %d (%d)\n",
			       cli_name(cli), qtype_name(type), qid[type], rc);
		} else {
			/* This ID is now off the hook, let's remove it from
			 * the hash table */
			if (oqi == NULL)
				continue;

			oqi = cfs_hash_del_key(cli->cl_quota_hash[type],
					       &qid[type]);
			if (oqi)
				OBD_SLAB_FREE_PTR(oqi, osc_quota_kmem);

			CDEBUG(D_QUOTA, "%s: setdq to remove for %s %d (%p)\n",
			       cli_name(cli), qtype_name(type), qid[type], oqi);
		}
	}

	RETURN(rc);
}
Exemple #13
0
/** Send a server map to a client.
 * @param[in] cptr Client to who to send the map.
 * @param[in] server Top-level server to display.
 * @param[in] mask Mask to filter which servers are shown.
 * @param[in] prompt_length Number of characters used in prompt.
 */
static void dump_map(struct Client *cptr, struct Client *server, char *mask, int prompt_length)
{
  const char *chr;
  static char prompt[64];
  struct DLink *lp;
  char *p = prompt + prompt_length;
  int cnt = 0;
  
  *p = '\0';
  if (prompt_length > 60)
    send_reply(cptr, RPL_MAPMORE, prompt, cli_name(server));
  else
  {
    char lag[512];
    if (cli_serv(server)->lag>10000)
      lag[0]=0;
    else if (cli_serv(server)->lag<0)
      strcpy(lag,"(0s)");
    else
      sprintf(lag,"(%is)",cli_serv(server)->lag);
    if (IsBurst(server))
      chr = "*";
    else if (IsBurstAck(server))
      chr = "!";
    else
      chr = "";
    send_reply(cptr, RPL_MAP, prompt, chr, cli_name(server),
               lag, (server == &me) ? UserStats.local_clients :
                                      cli_serv(server)->clients);
  }
  if (prompt_length > 0)
  {
    p[-1] = ' ';
    if (p[-2] == '`')
      p[-2] = ' ';
  }
  if (prompt_length > 60)
    return;
  strcpy(p, "|-");
  for (lp = cli_serv(server)->down; lp; lp = lp->next)
    if (match(mask, cli_name(lp->value.cptr)))
      ClrFlag(lp->value.cptr, FLAG_MAP);
    else
    {
      SetFlag(lp->value.cptr, FLAG_MAP);
      cnt++;
    }
  for (lp = cli_serv(server)->down; lp; lp = lp->next)
  {
    if (!HasFlag(lp->value.cptr, FLAG_MAP))
      continue;
    if (--cnt == 0)
      *p = '`';
    dump_map(cptr, lp->value.cptr, mask, prompt_length + 2);
  }
  if (prompt_length > 0)
    p[-1] = '-';
}
/*
 * do_kill - Performs the generic work involved in killing a client
 *
 */
static int do_kill(struct Client* cptr, struct Client* sptr,
		   struct Client* victim, char* inpath, char* path, char* msg)
{
  assert(0 != cptr);
  assert(0 != sptr);
  assert(!IsServer(victim));

  /*
   * Notify all *local* opers about the KILL (this includes the one
   * originating the kill, if from this server--the special numeric
   * reply message is not generated anymore).
   *
   * Note: "victim->name" is used instead of "user" because we may
   *       have changed the target because of the nickname change.
   */
  sendto_opmask_butone(0, IsServer(sptr) ? SNO_SERVKILL : SNO_OPERKILL,
                       "Received KILL message for %s. From %s Path: %s!%s %s",
                       get_client_name(victim, SHOW_IP), cli_name(sptr),
                       inpath, path, msg);
  log_write_kill(victim, sptr, inpath, path, msg);

  /*
   * And pass on the message to other servers. Note, that if KILL
   * was changed, the message has to be sent to all links, also
   * back.
   * Client suicide kills are NOT passed on --SRB
   */
  if (IsServer(cptr) || !MyConnect(victim)) {
    sendcmdto_serv_butone(sptr, CMD_KILL, cptr, "%C :%s!%s %s", victim,
                          inpath, path, msg);

    /*
     * Set FLAG_KILLED. This prevents exit_one_client from sending
     * the unnecessary QUIT for this. (This flag should never be
     * set in any other place)
     */
    SetFlag(victim, FLAG_KILLED);
  }

  /*
   * Tell the victim she/he has been zapped, but *only* if
   * the victim is on current server--no sense in sending the
   * notification chasing the above kill, it won't get far
   * anyway (as this user don't exist there any more either)
   * In accordance with the new hiding rules, the victim
   * always sees the kill as coming from me.
   */
  if (MyConnect(victim))
    sendcmdto_one(feature_bool(FEAT_HIS_KILLWHO) ? &me : sptr, CMD_KILL, 
		  victim, "%C :%s %s", victim, feature_bool(FEAT_HIS_KILLWHO)
		  ? feature_str(FEAT_HIS_SERVERNAME) : cli_name(sptr), msg);
  return exit_client_msg(cptr, victim, feature_bool(FEAT_HIS_KILLWHO)
			 ? &me : sptr, "Killed (%s %s)",
			 feature_bool(FEAT_HIS_KILLWHO) ? 
			 feature_str(FEAT_HIS_SERVERNAME) : cli_name(sptr),
			 msg);
}
Exemple #15
0
/** Deactivate a Z-line.
 * @param[in] cptr Peer that gave us the message.
 * @param[in] sptr Client that initiated the deactivation.
 * @param[in] zline Z-line to deactivate.
 * @param[in] lastmod New value for Z-line last modification timestamp.
 * @param[in] flags ZLINE_LOCAL to only deactivate locally, 0 to propagate.
 * @return Zero.
 */
int
zline_deactivate(struct Client *cptr, struct Client *sptr, struct Zline *zline,
		 time_t lastmod, unsigned int flags)
{
  unsigned int saveflags = 0;
  char *msg;

  assert(0 != zline);

  saveflags = zline->zl_flags;

  if (ZlineIsLocal(zline))
    msg = "removing local";
  else if (!zline->zl_lastmod && !(flags & ZLINE_LOCAL)) {
    msg = "removing global";
    zline->zl_flags &= ~ZLINE_ACTIVE; /* propagate a -<mask> */
  } else {
    msg = "deactivating global";

    if (flags & ZLINE_LOCAL)
      zline->zl_flags |= ZLINE_LDEACT;
    else {
      zline->zl_flags &= ~ZLINE_ACTIVE;

      if (zline->zl_lastmod) {
	if (zline->zl_lastmod >= lastmod)
	  zline->zl_lastmod++;
	else
	  zline->zl_lastmod = lastmod;
      }
    }

    if ((saveflags & ZLINE_ACTMASK) != ZLINE_ACTIVE)
      return 0; /* was inactive to begin with */
  }

  /* Inform ops and log it */
  sendto_opmask_butone(0, SNO_GLINE, "%s %s ZLINE for %s, expiring at %Tu: "
		       "%s",
                       (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ?
                         cli_name(sptr) :
                         cli_name((cli_user(sptr))->server), msg,
		       zline->zl_mask, zline->zl_expire, zline->zl_reason);

  log_write(LS_GLINE, L_INFO, LOG_NOSNOTICE,
	    "%#C %s ZLINE for %s, expiring at %Tu: %s", sptr, msg,
	    zline->zl_mask, zline->zl_expire, zline->zl_reason);

  if (!(flags & ZLINE_LOCAL)) /* don't propagate local changes */
    zline_propagate(cptr, sptr, zline);

  /* if it's a local zline or a Uworld zline (and not locally deactivated).. */
  if (ZlineIsLocal(zline) || (!zline->zl_lastmod && !(flags & ZLINE_LOCAL)))
    zline_free(zline); /* get rid of it */

  return 0;
}
/*
 * m_version - generic message handler
 *
 *   parv[0] = sender prefix
 *   parv[1] = servername
 */
int m_version(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  if (parc > 1 && match(parv[1], cli_name(&me)))
    return send_reply(sptr, ERR_NOPRIVILEGES);

  send_reply(sptr, RPL_VERSION, version, debugmode, cli_name(&me),
             debug_serveropts());
  send_supported(sptr);
  return 0;
}
/** Return the name of the client for various tracking and admin
 * purposes. The main purpose of this function is to return the
 * "socket host" name of the client, if that differs from the
 * advertised name (other than case).  But, this can be used on any
 * client structure.
 * @param sptr Client to operate on.
 * @param showip If non-zero, append [username\@text-ip] to name.
 * @return Either cli_name(\a sptr) or a static buffer.
 */
const char* get_client_name(const struct Client* sptr, int showip)
{
  static char nbuf[HOSTLEN * 2 + USERLEN + 5];

  if (!MyConnect(sptr) || !showip)
    return cli_name(sptr);
  ircd_snprintf(0, nbuf, sizeof(nbuf), "%s[%s@%s]", cli_name(sptr),
                IsIdented(sptr) ? cli_username(sptr) : "",
                cli_sock_ip(sptr));
  return nbuf;
}
/*
 * mo_kill - oper message handler
 *
 * NOTE: IsPrivileged(sptr), IsAnOper(sptr) == true
 *       IsServer(cptr), IsServer(sptr) == false
 *
 * parv[0]      = sender prefix
 * parv[1]      = kill victim
 * parv[parc-1] = kill path
 */
int mo_kill(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  struct Client* victim;
  char*          user;
  char           msg[TOPICLEN + 3]; /* (, ), and \0 */

  assert(0 != cptr);
  assert(0 != sptr);
  /*
   * oper connection to this server, cptr is always sptr
   */
  assert(cptr == sptr);
  assert(IsAnOper(sptr));

  if (parc < 3 || EmptyString(parv[parc - 1]))
    return need_more_params(sptr, "KILL");

  user = parv[1];
  ircd_snprintf(0, msg, sizeof(msg), "(%.*s)", TOPICLEN, parv[parc - 1]);

  if (!(victim = FindClient(user))) {
    /*
     * If the user has recently changed nick, we automaticly
     * rewrite the KILL for this new nickname--this keeps
     * servers in synch when nick change and kill collide
     */
    if (!(victim = get_history(user, (long)15)))
      return send_reply(sptr, ERR_NOSUCHNICK, user);

    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Changed KILL %s into %s", sptr,
		  user, cli_name(victim));
  }
  if (!HasPriv(sptr, MyConnect(victim) ? PRIV_LOCAL_KILL : PRIV_KILL))
    return send_reply(sptr, ERR_NOPRIVILEGES);

  if (IsServer(victim) || IsMe(victim)) {
    return send_reply(sptr, ERR_CANTKILLSERVER);
  }
  /*
   * if the user is +k, prevent a kill from local user
   */
  if (IsChannelService(victim))
    return send_reply(sptr, ERR_ISCHANSERVICE, "KILL", cli_name(victim));


  if (!MyConnect(victim) && !HasPriv(sptr, PRIV_KILL)) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Nick %s isnt on your server",
		  sptr, cli_name(victim));
    return 0;
  }
  return do_kill(cptr, sptr, victim, cli_user(sptr)->host, cli_name(sptr),
		 msg);
}
Exemple #19
0
int ms_rehash(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  int flag = 0;

  if ((parc > 2) && (hunt_server_cmd(sptr, CMD_REHASH, cptr, 1, "%s %C", 2, parc, parv) != HUNTED_ISME))
    return 0;

  /* OK, the message has been forwarded, but before we can act... */
  if (!feature_bool(FEAT_NETWORK_REHASH))
    return 0;

  if (parc > 1) { /* special processing */
    if (parv[1][1] == '\0') { /* one character server name */
      if (*parv[1] == 'm') {
        send_reply(sptr, SND_EXPLICIT | RPL_REHASHING, ":Flushing MOTD cache");
        motd_recache(); /* flush MOTD cache */
        return 0;
      } else if (*parv[1] == 'l') {
        send_reply(sptr, SND_EXPLICIT | RPL_REHASHING, ":Reopening log files");
        log_reopen(); /* reopen log files */
        return 0;
      } else if (*parv[1] == 'a') {
        send_reply(sptr, SND_EXPLICIT | RPL_REHASHING, ":Restarting IAuth");
        auth_restart(); /* Restart IAuth program */
        return 0;
#ifdef USE_SSL
      } else if (*parv[1] == 's') {
        send_reply(sptr, SND_EXPLICIT | RPL_REHASHING, ":Reloading SSL certificates");
        ssl_reinit();
        return 0;
#endif
      } else if (*parv[1] == 'q')
        flag = 2;
    }
    /*
     * Maybe the user wants to rehash another server with no parameters.
     * NOTE: Here we assume that there are no servers named
     * 'm', 'l', 's', or 'q'.
     */
    else if ((parc == 2) && (hunt_server_cmd(sptr, CMD_REHASH, cptr, 1, "%C", 1, parc, parv) != HUNTED_ISME))
      return 0;
  }

  send_reply(sptr, RPL_REHASHING, configfile);
  sendto_opmask_butone(0, SNO_OLDSNO, "%C [%s] is remotely rehashing Server config file",
                       sptr, cli_name(cli_user(sptr)->server));

  log_write(LS_SYSTEM, L_INFO, 0, "Remote REHASH From %#C [%s]", sptr, cli_name(cli_user(sptr)->server));

  return rehash(cptr, flag);
}
Exemple #20
0
/** Send the content of a MotdCache to a user.
 * If \a cache is NULL, simply send ERR_NOOMOTD to the client.
 * @param[in] cptr Client to send MOTD to.
 * @param[in] cache MOTD body to send to client.
 */
static int
motd_forward_type(struct Client *cptr, int type)
{
  int i;
  struct MotdCache *cache = NULL;

  assert(0 != cptr);

  if (type == MOTD_OPER)
    cache = motd_cache(MotdList.oper);
  else if (type == MOTD_RULES)
    cache = motd_cache(MotdList.rules);

  if (!cache) {/* no motd to send */
    if (type == MOTD_OPER)
      return send_reply(cptr, ERR_NOOMOTD);
    else if (type == MOTD_RULES)
      return send_reply(cptr, ERR_NORULES);
    else
      return send_reply(cptr, ERR_NOMOTD);
  }

  if (type == MOTD_OPER) {
    /* send the motd */
    send_reply(cptr, RPL_OMOTDSTART, cli_name(&me));
    send_reply(cptr, SND_EXPLICIT | RPL_OMOTD, ":- %d-%d-%d %d:%02d",
               cache->modtime.tm_year + 1900, cache->modtime.tm_mon + 1,
               cache->modtime.tm_mday, cache->modtime.tm_hour,
               cache->modtime.tm_min);

    for (i = 0; i < cache->count; i++)
      send_reply(cptr, RPL_OMOTD, cache->motd[i]);

    return send_reply(cptr, RPL_ENDOFOMOTD); /* end */
  } else if (type == MOTD_RULES) {
    /* send the motd */
    send_reply(cptr, RPL_RULESSTART, cli_name(&me));
    send_reply(cptr, SND_EXPLICIT | RPL_RULES, ":- %d-%d-%d %d:%02d",
               cache->modtime.tm_year + 1900, cache->modtime.tm_mon + 1,
               cache->modtime.tm_mday, cache->modtime.tm_hour,
               cache->modtime.tm_min);

    for (i = 0; i < cache->count; i++)
      send_reply(cptr, RPL_RULES, cache->motd[i]);

    return send_reply(cptr, RPL_ENDOFRULES); /* end */
  }else {
    return send_reply(cptr, ERR_NOMOTD);
  }
}
Exemple #21
0
/** Deactivate a jupe.
 * @param[in] cptr Local client that sent us the jupe.
 * @param[in] sptr Originator of the jupe.
 * @param[in] jupe Jupe to deactivate.
 * @param[in] lastmod New timestamp for last modification of the jupe.
 * @param[in] flags Flags to set on the jupe.
 * @return Zero.
 */
int
jupe_deactivate(struct Client *cptr, struct Client *sptr, struct Jupe *jupe,
		time_t lastmod, unsigned int flags)
{
  unsigned int saveflags = 0;

  assert(0 != jupe);

  saveflags = jupe->ju_flags;

  if (!JupeIsLocal(jupe)) {
    if (flags & JUPE_LOCAL)
      jupe->ju_flags |= JUPE_LDEACT;
    else {
      jupe->ju_flags &= ~JUPE_ACTIVE;

      if (jupe->ju_lastmod >= lastmod) /* force lastmod to increase */
	jupe->ju_lastmod++;
      else
	jupe->ju_lastmod = lastmod;
    }

    if ((saveflags & JUPE_ACTMASK) != JUPE_ACTIVE)
      return 0; /* was inactive to begin with */
  }

  /* Inform ops and log it */
  sendto_opmask_butone(0, SNO_NETWORK, "%s %s JUPE for %s, expiring at %Tu: "
		       "%s",
                       (feature_bool(FEAT_HIS_SNOTICES) || IsServer(sptr)) ?
                         cli_name(sptr) :
                         cli_name((cli_user(sptr))->server),
		       JupeIsLocal(jupe) ? "removing local" : "deactivating",
		       jupe->ju_server, jupe->ju_expire + TSoffset,
		       jupe->ju_reason);

  log_write(LS_JUPE, L_INFO, LOG_NOSNOTICE,
	    "%#C %s JUPE for %s, expiring at %Tu: %s", sptr,
	    JupeIsLocal(jupe) ? "removing local" : "deactivating",
	    jupe->ju_server, jupe->ju_expire + TSoffset, jupe->ju_reason);

  if (JupeIsLocal(jupe))
    jupe_free(jupe);
  else if (!(flags & JUPE_LOCAL)) /* don't propagate local changes */
    propagate_jupe(cptr, sptr, jupe);

  return 0;
}
void start_auth(struct Client* client)
{
  struct AuthRequest* auth = 0;

  assert(0 != client);

  if (conf_check_slines(client)) {
    sendheader(client, REPORT_USING_SLINE);
    SetSLined(client);
    release_auth_client(client);
    return;
  }

  auth = make_auth_request(client);
  assert(0 != auth);

  Debug((DEBUG_INFO, "Beginning auth request on client %p", client));

  if (!feature_bool(FEAT_NODNS)) {
    if (LOOPBACK == inet_netof(cli_ip(client)))
      strcpy(cli_sockhost(client), cli_name(&me));
    else {
      struct DNSQuery query;

      query.vptr     = auth;
      query.callback = auth_dns_callback;

      if (IsUserPort(auth->client))
	sendheader(client, REPORT_DO_DNS);

      cli_dns_reply(client) = gethost_byaddr((const char*) &(cli_ip(client)),
					     &query);

      if (cli_dns_reply(client)) {
	++(cli_dns_reply(client))->ref_count;
	ircd_strncpy(cli_sockhost(client), cli_dns_reply(client)->hp->h_name,
		     HOSTLEN);
	if (IsUserPort(auth->client))
	  sendheader(client, REPORT_FIN_DNSC);
	Debug((DEBUG_LIST, "DNS entry for %p was cached", auth->client));
      } else
	SetDNSPending(auth);
    }
  }

  if (start_auth_query(auth)) {
    Debug((DEBUG_LIST, "identd query for %p initiated successfully",
	   auth->client));
    link_auth_request(auth, &AuthPollList);
  } else if (IsDNSPending(auth)) {
    Debug((DEBUG_LIST, "identd query for %p not initiated successfully; "
	   "waiting on DNS", auth->client));
    link_auth_request(auth, &AuthIncompleteList);
  } else {
    Debug((DEBUG_LIST, "identd query for %p not initiated successfully; "
	   "no DNS pending; releasing immediately", auth->client));
    free_auth_request(auth);
    release_auth_client(client);
  }
}
/*
 * mr_error - unregistered client message handler
 *
 * parv[0] = sender prefix
 * parv[parc-1] = text
 */
int mr_error(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  const char *para;

  if (!IsHandshake(cptr) && !IsConnecting(cptr))
    return 0; /* ignore ERROR from regular clients */

  para = (parc > 1 && *parv[parc - 1] != '\0') ? parv[parc - 1] : "<>";

  Debug((DEBUG_ERROR, "Received ERROR message from %s: %s", cli_name(sptr), para));

  if (cptr == sptr)
    sendto_opmask_butone(0, SNO_OLDSNO, "ERROR :from %C -- %s", cptr, para);
  else
    sendto_opmask_butone(0, SNO_OLDSNO, "ERROR :from %C via %C -- %s", sptr,
			 cptr, para);

  if (cli_serv(sptr))
  {
    MyFree(cli_serv(sptr)->last_error_msg);
    DupString(cli_serv(sptr)->last_error_msg, para);
  }

  return 0;
}
Exemple #24
0
/** Set a channel topic or report an error.
 * @param[in] sptr Original topic setter.
 * @param[in] cptr Neighbor that sent the topic message.
 * @param[in] chptr Channel to set topic on.
 * @param[in] topic New topic.
 * @param[in] ts Timestamp that topic was set (0 for current time).
 */
static void do_settopic(struct Client *sptr, struct Client *cptr,
                        struct Channel *chptr, char *topic, time_t ts)
{
    struct Client *from;
    int newtopic;

    if (feature_bool(FEAT_HIS_BANWHO) && IsServer(sptr))
        from = &his;
    else
        from = sptr;
    /* Note if this is just a refresh of an old topic, and don't
     * send it to all the clients to save bandwidth.  We still send
     * it to other servers as they may have split and lost the topic.
     */
    newtopic=ircd_strncmp(chptr->topic,topic,TOPICLEN)!=0;
    /* setting a topic */
    ircd_strncpy(chptr->topic, topic, TOPICLEN);
    ircd_strncpy(chptr->topic_nick, cli_name(from), NICKLEN);
    chptr->topic_time = ts ? ts : TStime();
    /* Fixed in 2.10.11: Don't propagate local topics */
    if (!IsLocalChannel(chptr->chname))
        sendcmdto_serv(sptr, CMD_TOPIC, cptr, "%H %Tu %Tu :%s", chptr,
                       chptr->creationtime, chptr->topic_time, chptr->topic);
    if (newtopic)
        sendcmdto_channel(from, CMD_TOPIC, chptr, NULL, SKIP_SERVERS,
                          "%H :%s", chptr, chptr->topic);
    /* if this is the same topic as before we send it to the person that
     * set it (so they knew it went through ok), but don't bother sending
     * it to everyone else on the channel to save bandwidth
     */
    else if (MyUser(sptr))
        sendcmdto_one(sptr, CMD_TOPIC, sptr, "%H :%s", chptr, chptr->topic);
}
Exemple #25
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);
}
Exemple #26
0
/** Send a server notice to all users subscribing to the indicated \a
 * mask except for \a one.
 * @param[in] one Client direction to skip (or NULL).
 * @param[in] mask One of the SNO_* constants.
 * @param[in] pattern Format string for server notice.
 * @param[in] vl Argument list for format string.
 */
void vsendto_opmask_butone(struct Client *from, struct Client *one,
                           unsigned int mask, const char *pattern, va_list vl)
{
  struct VarData vd;
  struct MsgBuf *mb;
  int i = 0; /* so that 1 points to opsarray[0] */
  struct SLink *opslist;

  while ((mask >>= 1))
    i++;

  if (!(opslist = opsarray[i]))
    return;

  /*
   * build string; I don't want to bother with client nicknames, so I hope
   * this is ok...
   */
  vd.vd_format = pattern;
  va_copy(vd.vd_args, vl);
  mb = msgq_make(0, ":%s " MSG_NOTICE " * :*** Notice -- %v", cli_name(from),
		 &vd);

  for (; opslist; opslist = opslist->next)
    if (opslist->value.cptr != one)
      send_buffer(opslist->value.cptr, mb, 0);

  msgq_clean(mb);
}
Exemple #27
0
void
failed_challenge_notice(struct Client *sptr, char *name, char *reason)
{
    sendto_allops(&me, SNO_OLDREALOP, "Failed CHALLENGE attempt as %s "
                  "by %s (%s@%s) - %s", name, cli_name(sptr),
                  cli_user(sptr)->realusername, cli_user(sptr)->host, reason);
}
/**
 * Removes all clients and downlinks (+clients) of any server
 * QUITs are generated and sent to local users.
 * @param cptr server that must have all dependents removed
 * @param sptr source who thought that this was a good idea
 * @param comment comment sent as sign off message to local clients
 */
static void exit_downlinks(struct Client *cptr, struct Client *sptr, char *comment)
{
  struct Client *acptr;
  struct DLink *next;
  struct DLink *lp;
  struct Client **acptrp;
  int i;

  /* Run over all its downlinks */
  for (lp = cli_serv(cptr)->down; lp; lp = next)
  {
    next = lp->next;
    acptr = lp->value.cptr;
    /* Remove the downlinks and client of the downlink */
    exit_downlinks(acptr, sptr, comment);
    /* Remove the downlink itself */
    exit_one_client(acptr, cli_name(&me));
  }
  /* Remove all clients of this server */
  acptrp = cli_serv(cptr)->client_list;
  for (i = 0; i <= cli_serv(cptr)->nn_mask; ++acptrp, ++i) {
    if (*acptrp)
      exit_one_client(*acptrp, comment);
  }
}
Exemple #29
0
void relay_directed_notice(struct Client* sptr, char* name, char* server, const char* text)
{
  struct Client* acptr;
  char*          host;

  assert(0 != sptr);
  assert(0 != name);
  assert(0 != text);
  assert(0 != server);

  if (0 == (acptr = FindServer(server + 1)))
    return;
  /*
   * NICK[%host]@server addressed? See if <server> is me first
   */
  if (!IsMe(acptr)) {
    sendcmdto_one(sptr, CMD_NOTICE, acptr, "%s :%s", name, text);
    return;
  }
  /*
   * Look for an user whose NICK is equal to <name> and then
   * check if it's hostname matches <host> and if it's a local
   * user.
   */
  *server = '\0';
  if ((host = strchr(name, '%')))
    *host++ = '\0';

  if (!(acptr = FindUser(name)) || !MyUser(acptr) ||
      (!EmptyString(host) && 0 != match(host, cli_user(acptr)->realhost)))
    return;

  *server = '@';
  if (host)
    *--host = '%';

  if (!IsChannelService(sptr) && is_silenced(sptr, acptr))
  {
    send_reply(sptr, ERR_SILENCED, cli_name(acptr));
    return;
  }

  if (IsOnlyreg(acptr) && !IsRegnick(sptr))
    send_reply(sptr, RPL_MSGONLYREG, cli_name(acptr));
  else
    sendcmdto_one(sptr, CMD_NOTICE, acptr, "%s :%s", name, text);
}
Exemple #30
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);
}