Esempio n. 1
0
/** Remove all conf entries from the client except those which match
 * the status field mask.
 * @param cptr Client to operate on.
 * @param mask ConfItem types to keep.
 */
void det_confs_butmask(struct Client* cptr, int mask)
{
  struct SLink* link;
  struct SLink* next;
  assert(0 != cptr);

  for (link = cli_confs(cptr); link; link = next) {
    next = link->next;
    if ((link->value.aconf->status & mask) == 0)
      detach_conf(cptr, link->value.aconf);
  }
}
Esempio n. 2
0
/*
 * m_challenge - generate RSA challenge for wouldbe oper
 * parv[0] = sender prefix
 * parv[1] = operator to challenge for, or +response
 *
 */
static void
m_challenge(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
	char *challenge;
	dlink_node *ptr;
	struct ConfItem *aconf, *oconf;
	if(!(source_p->user) || !source_p->localClient)
		return;

	/* if theyre an oper, reprint oper motd and ignore */
	if(IsOper(source_p))
	{
		sendto_one(source_p, form_str(RPL_YOUREOPER), me.name, parv[0]);
		SendMessageFile(source_p, &ConfigFileEntry.opermotd);
		return;
	}

	if(*parv[1] == '+')
	{
		/* Ignore it if we aren't expecting this... -A1kmm */
		if(!source_p->user->response)
			return;

		if(irccmp(source_p->user->response, ++parv[1]))
		{
			sendto_one(source_p, form_str(ERR_PASSWDMISMATCH), me.name, source_p->name);
			log_foper(source_p, source_p->user->auth_oper);

			if(ConfigFileEntry.failed_oper_notice)
				sendto_realops_flags(UMODE_ALL, L_ALL,
						     "Failed OPER attempt by %s (%s@%s)",
						     source_p->name, source_p->username,
						     source_p->host);
			return;
		}

		if((aconf = find_conf_by_name(source_p->user->auth_oper, CONF_OPERATOR)) == NULL)
		{
			sendto_one(source_p, form_str(ERR_NOOPERHOST), me.name, parv[0]);
			log_foper(source_p, source_p->user->auth_oper);

			if(ConfigFileEntry.failed_oper_notice)
				sendto_realops_flags(UMODE_ALL, L_ALL,
						     "Failed CHALLENGE attempt - host mismatch by %s (%s@%s)",
						     source_p->name, source_p->username,
						     source_p->host);
			return;
		}

		ptr = source_p->localClient->confs.head;
		oconf = ptr->data;
		detach_conf(source_p, oconf);

		if(attach_conf(source_p, aconf) != 0)
		{
			sendto_one(source_p, ":%s NOTICE %s :Can't attach conf!",
				   me.name, source_p->name);
			sendto_realops_flags(UMODE_ALL, L_ALL,
					     "Failed CHALLENGE attempt by %s (%s@%s) can't attach conf!",
					     source_p->name, source_p->username, source_p->host);
			log_foper(source_p, source_p->user->auth_oper);

			attach_conf(source_p, oconf);
			return;
		}

		oper_up(source_p, aconf);

		ilog(L_TRACE, "OPER %s by %s!%s@%s",
		     source_p->user->auth_oper, source_p->name, source_p->username, source_p->host);
		log_oper(source_p, source_p->user->auth_oper);

		MyFree(source_p->user->response);
		MyFree(source_p->user->auth_oper);
		source_p->user->response = NULL;
		source_p->user->auth_oper = NULL;
		return;
	}

	MyFree(source_p->user->response);
	MyFree(source_p->user->auth_oper);
	source_p->user->response = NULL;
	source_p->user->auth_oper = NULL;

	if(!(aconf = find_conf_exact(parv[1], source_p->username, source_p->host,
				     CONF_OPERATOR)) &&
	   !(aconf = find_conf_exact(parv[1], source_p->username,
				     source_p->localClient->sockhost, CONF_OPERATOR)))
	{
		sendto_one(source_p, form_str(ERR_NOOPERHOST), me.name, parv[0]);
		log_foper(source_p, parv[1]);

		if(ConfigFileEntry.failed_oper_notice)
			sendto_realops_flags(UMODE_ALL, L_ALL,
					     "Failed CHALLENGE attempt - host mismatch by %s (%s@%s)",
					     source_p->name, source_p->username, source_p->host);
		return;
	}

	if(!aconf->rsa_public_key)
	{
		sendto_one(source_p, ":%s NOTICE %s :I'm sorry, PK authentication "
			   "is not enabled for your oper{} block.", me.name, parv[0]);
		return;
	}

	if(!generate_challenge(&challenge, &(source_p->user->response), aconf->rsa_public_key))
	{
		sendto_one(source_p, form_str(RPL_RSACHALLENGE), me.name, parv[0], challenge);
	}

	DupString(source_p->user->auth_oper, aconf->name);
	MyFree(challenge);
	return;
}
Esempio n. 3
0
/*
** m_oper
**      parv[0] = sender prefix
**      parv[1] = oper name
**      parv[2] = oper password
*/
static void
m_oper(struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
	struct ConfItem *aconf;
	struct ConfItem *oconf = NULL;
	char *name;
	char *password;
	dlink_node *ptr;

	name = parv[1];
	password = parv[2];

	if(EmptyString(password))
	{
		sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "OPER");
		return;
	}

	/* end the grace period */
	if(!IsFloodDone(source_p))
		flood_endgrace(source_p);

	if((aconf = find_password_aconf(name, source_p)) == NULL)
	{
		sendto_one(source_p, form_str(ERR_NOOPERHOST), me.name, source_p->name);
		log_foper(source_p, name);

		if(ConfigFileEntry.failed_oper_notice)
		{
			sendto_realops_flags(UMODE_ALL, L_ALL,
					     "Failed OPER attempt - host mismatch by %s (%s@%s)",
					     source_p->name, source_p->username, source_p->host);
		}
		return;
	}

	if(match_oper_password(password, aconf))
	{
		/*
		   20001216:
		   detach old iline
		   -einride
		 */
		ptr = source_p->localClient->confs.head;
		if(ptr)
		{

			oconf = ptr->data;
			detach_conf(source_p, oconf);
		}

		if(attach_conf(source_p, aconf) != 0)
		{
			sendto_one(source_p, ":%s NOTICE %s :Can't attach conf!",
				   me.name, source_p->name);
			sendto_realops_flags(UMODE_ALL, L_ALL,
					     "Failed OPER attempt by %s (%s@%s) can't attach conf!",
					     source_p->name, source_p->username, source_p->host);
			log_foper(source_p, name);
			/* 
			   20001216:
			   Reattach old iline
			   -einride
			 */
			attach_conf(source_p, oconf);
			return;
		}

		oper_up(source_p, aconf);

		ilog(L_TRACE, "OPER %s by %s!%s@%s",
		     name, source_p->name, source_p->username, source_p->host);
		log_oper(source_p, name);
		return;
	}
	else
	{
		sendto_one(source_p, form_str(ERR_PASSWDMISMATCH), me.name, parv[0]);
		log_foper(source_p, name);

		if(ConfigFileEntry.failed_oper_notice)
		{
			sendto_realops_flags(UMODE_ALL, L_ALL,
					     "Failed OPER attempt by %s (%s@%s)",
					     source_p->name, source_p->username, source_p->host);
		}
	}
}
Esempio n. 4
0
/*
 * close_connection
 *        Close the physical connection. This function must make
 *        MyConnect(client_p) == FALSE, and set client_p->from == NULL.
 */
void
close_connection(struct Client *client_p)
{
  struct ConfItem *conf;
  struct AccessItem *aconf;
  struct ClassItem *aclass;

  assert(NULL != client_p);

  if (!IsDead(client_p))
  {
    /* attempt to flush any pending dbufs. Evil, but .. -- adrian */
    /* there is still a chance that we might send data to this socket
     * even if it is marked as blocked (COMM_SELECT_READ handler is called
     * before COMM_SELECT_WRITE). Let's try, nothing to lose.. -adx
     */
    ClearSendqBlocked(client_p);
    send_queued_write(client_p);
  }

  if (IsServer(client_p))
  {
    ++ServerStats.is_sv;
    ServerStats.is_sbs += client_p->localClient->send.bytes;
    ServerStats.is_sbr += client_p->localClient->recv.bytes;
    ServerStats.is_sti += CurrentTime - client_p->firsttime;

    /* XXX Does this even make any sense at all anymore?
     * scheduling a 'quick' reconnect could cause a pile of
     * nick collides under TSora protocol... -db
     */
    /*
     * If the connection has been up for a long amount of time, schedule
     * a 'quick' reconnect, else reset the next-connect cycle.
     */
    if ((conf = find_conf_exact(SERVER_TYPE,
				  client_p->name, client_p->username,
				  client_p->host)))
    {
      /*
       * Reschedule a faster reconnect, if this was a automatically
       * connected configuration entry. (Note that if we have had
       * a rehash in between, the status has been changed to
       * CONF_ILLEGAL). But only do this if it was a "good" link.
       */
      aconf = (struct AccessItem *)map_to_conf(conf);
      aclass = (struct ClassItem *)map_to_conf(aconf->class_ptr);
      aconf->hold = time(NULL);
      aconf->hold += (aconf->hold - client_p->since > HANGONGOODLINK) ?
        HANGONRETRYDELAY : ConFreq(aclass);
      if (nextconnect > aconf->hold)
        nextconnect = aconf->hold;
    }
  }
  else if (IsClient(client_p))
  {
    ++ServerStats.is_cl;
    ServerStats.is_cbs += client_p->localClient->send.bytes;
    ServerStats.is_cbr += client_p->localClient->recv.bytes;
    ServerStats.is_cti += CurrentTime - client_p->firsttime;
  }
  else
    ++ServerStats.is_ni;

#ifdef HAVE_LIBCRYPTO
  if (client_p->localClient->fd.ssl)
  {
    SSL_set_shutdown(client_p->localClient->fd.ssl, SSL_RECEIVED_SHUTDOWN);

    if (!SSL_shutdown(client_p->localClient->fd.ssl))
      SSL_shutdown(client_p->localClient->fd.ssl);
  }
#endif
  if (client_p->localClient->fd.flags.open)
    fd_close(&client_p->localClient->fd);

  if (HasServlink(client_p))
  {
    if (client_p->localClient->ctrlfd.flags.open)
      fd_close(&client_p->localClient->ctrlfd);
  }

  dbuf_clear(&client_p->localClient->buf_sendq);
  dbuf_clear(&client_p->localClient->buf_recvq);
  
  MyFree(client_p->localClient->passwd);
  detach_conf(client_p, CONF_TYPE);
  client_p->from = NULL; /* ...this should catch them! >:) --msa */
}
Esempio n. 5
0
/*! \brief SVSMODE command handler
 *
 * \param source_p Pointer to allocated Client struct from which the message
 *                 originally comes from.  This can be a local or remote client.
 * \param parc     Integer holding the number of supplied arguments.
 * \param parv     Argument vector where parv[0] .. parv[parc-1] are non-NULL
 *                 pointers.
 * \note Valid arguments for this command are:
 *      - parv[0] = command
 *      - parv[1] = nickname
 *      - parv[2] = TS
 *      - parv[3] = mode
 *      - parv[4] = optional argument (services account, vhost)
 */
static int
ms_svsmode(struct Client *source_p, int parc, char *parv[])
{
  const struct user_modes *tab = NULL;
  struct Client *target_p = NULL;
  int what = MODE_ADD;
  unsigned int setmodes = 0;
  const char *modes = NULL, *extarg = NULL;
  time_t ts = 0;

  if (!HasFlag(source_p, FLAGS_SERVICE))
    return 0;

  ts     = atol(parv[2]);
  modes  = parv[3];
  extarg = (parc > 4) ? parv[4] : NULL;

  if ((target_p = find_person(source_p, parv[1])) == NULL)
    return 0;

  if (ts && (ts != target_p->tsinfo))
    return 0;

  setmodes = target_p->umodes;

  for (const char *m = modes; *m; ++m)
  {
    switch (*m)
    {
      case '+':
        what = MODE_ADD;
        break;
      case '-':
        what = MODE_DEL;
        break;

      case 'd':
        if (!EmptyString(extarg))
          strlcpy(target_p->account, extarg, sizeof(target_p->account));
        break;

      case 'x':
        if (!EmptyString(extarg) && valid_hostname(extarg))
          user_set_hostmask(target_p, extarg, what);
        break;

      case 'o':
        if (what == MODE_DEL && HasUMode(target_p, UMODE_OPER))
        {
          ClearOper(target_p);
          --Count.oper;

          if (MyConnect(target_p))
          {
            dlink_node *node = NULL;

            detach_conf(target_p, CONF_OPER);
            ClrOFlag(target_p);
            DelUMode(target_p, ConfigGeneral.oper_only_umodes);

            if ((node = dlinkFindDelete(&oper_list, target_p)))
              free_dlink_node(node);
          }
        }

        break;

      case 'i':
        if (what == MODE_ADD && !HasUMode(target_p, UMODE_INVISIBLE))
        {
          AddUMode(target_p, UMODE_INVISIBLE);
          ++Count.invisi;
        }

        if (what == MODE_DEL && HasUMode(target_p, UMODE_INVISIBLE))
        {
          DelUMode(target_p, UMODE_INVISIBLE);
          --Count.invisi;
        }

        break;

      case 'S':  /* Only servers may set +S in a burst */
      case 'W':  /* Only servers may set +W in a burst */
        break;

      default:
        if ((tab = umode_map[(unsigned char)*m]))
        {
          if (what == MODE_ADD)
            AddUMode(target_p, tab->flag);
          else
            DelUMode(target_p, tab->flag);
        }

        break;
    }
  }

  if (extarg)
    sendto_server(source_p, 0, 0, ":%s SVSMODE %s %lu %s %s",
                  source_p->id,
                  target_p->id, (unsigned long)target_p->tsinfo, modes, extarg);
  else
    sendto_server(source_p, 0, 0, ":%s SVSMODE %s %lu %s",
                  source_p->id,
                  target_p->id, (unsigned long)target_p->tsinfo, modes);

  if (MyConnect(target_p) && (setmodes != target_p->umodes))
  {
    char modebuf[IRCD_BUFSIZE] = "";

    send_umode(target_p, target_p, setmodes, modebuf);
  }

  return 0;
}
Esempio n. 6
0
/*! \brief SVSMODE command handler (called by services)
 *
 * \param client_p Pointer to allocated Client struct with physical connection
 *                 to this server, i.e. with an open socket connected.
 * \param source_p Pointer to allocated Client struct from which the message
 *                 originally comes from.  This can be a local or remote client.
 * \param parc     Integer holding the number of supplied arguments.
 * \param parv     Argument vector where parv[0] .. parv[parc-1] are non-NULL
 *                 pointers.
 * \note Valid arguments for this command are:
 *      - parv[0] = sender prefix
 *      - parv[1] = nickname
 *      - parv[2] = TS (or mode, depending on svs version)
 *      - parv[3] = mode (or services id if old svs version)
 *      - parv[4] = optional argument (services id)
 */
static void
ms_svsmode(struct Client *client_p, struct Client *source_p,
           int parc, char *parv[])
{
  struct Client *target_p = NULL;
  int what = MODE_ADD;
  unsigned int flag = 0, setflags = 0;
  char *m = NULL, *modes = NULL, *extarg = NULL;
  time_t ts = 0;

  if (!HasFlag(source_p, FLAGS_SERVICE))
    return;

  if ((parc >= 4) && ((*parv[3] == '+') || (*parv[3] == '-')))
  {
    ts     = atol(parv[2]);
    modes  = parv[3];
    extarg = (parc > 4) ? parv[4] : NULL;
  }
  else
  {
    modes  = parv[2];
    extarg = (parc > 3) ? parv[3] : NULL;
  }

  if ((target_p = find_person(client_p, parv[1])) == NULL)
    return;

  if (ts && (ts != target_p->tsinfo))
    return;

  setflags = target_p->umodes;

  for (m = modes; *m; ++m)
  {
    switch (*m)
    {
      case '+':
        what = MODE_ADD;
        break;

      case '-':
        what = MODE_DEL;
        break;

      case 'x':
        if (what == MODE_ADD && extarg)
          user_set_hostmask(target_p, extarg);

        break;

      case 'd':
        if (!EmptyString(extarg))
          strlcpy(target_p->svid, extarg, sizeof(target_p->svid));

        break;

      case 'o':
        if (what == MODE_DEL && HasUMode(target_p, UMODE_OPER))
        {
          ClearOper(target_p);
          Count.oper--;

          if (MyConnect(target_p))
          {
            dlink_node *dm = NULL;

            detach_conf(target_p, OPER_TYPE);
            ClrOFlag(target_p);
            DelUMode(target_p, ConfigFileEntry.oper_only_umodes);

            if ((dm = dlinkFindDelete(&oper_list, target_p)) != NULL)
              free_dlink_node(dm);
          }
        }

        break;

      case 'i':
        if (what == MODE_ADD && !HasUMode(target_p, UMODE_INVISIBLE))
        {
          AddUMode(target_p, UMODE_INVISIBLE);
          ++Count.invisi;
        }

        if (what == MODE_DEL && HasUMode(target_p, UMODE_INVISIBLE))
        {
          DelUMode(target_p, UMODE_INVISIBLE);
          --Count.invisi;
        }

        break;

      case ' ':
      case '\n':
      case '\r':
      case '\t':
        break;

      default:
        if ((flag = user_modes[(unsigned char) * m]))
          execute_callback(umode_cb, client_p, target_p, what, flag);

        break;
    }
  }

  if (extarg)
  {
    sendto_server(client_p, CAP_TS6, NOCAPS,
                  ":%s SVSMODE %s %lu %s %s", ID(source_p),
                  ID(target_p), (unsigned long)target_p->tsinfo, modes, extarg);
    sendto_server(client_p, NOCAPS, CAP_TS6,
                  ":%s SVSMODE %s %lu %s %s", source_p->name,
                  target_p->name, (unsigned long)target_p->tsinfo, modes, extarg);
  }
  else
  {
    sendto_server(client_p, CAP_TS6, NOCAPS,
                  ":%s SVSMODE %s %lu %s", ID(source_p),
                  ID(target_p), (unsigned long)target_p->tsinfo, modes);
    sendto_server(client_p, NOCAPS, CAP_TS6,
                  ":%s SVSMODE %s %lu %s", source_p->name,
                  target_p->name, (unsigned long)target_p->tsinfo, modes);
  }

  if (MyConnect(target_p) && (setflags != target_p->umodes))
  {
    char modebuf[IRCD_BUFSIZE];

    send_umode(target_p, target_p, setflags, 0xffffffff, modebuf);
  }
}
Esempio n. 7
0
/* set_user_mode()
 *
 * added 15/10/91 By Darren Reed.
 * parv[0] - command
 * parv[1] - username to change mode for
 * parv[2] - modes to change
 */
static void
set_user_mode(struct Client *source_p, const int parc, char *parv[])
{
  const struct user_modes *tab = NULL;
  const unsigned int setmodes = source_p->umodes;
  const struct Client *target_p = NULL;
  int what = MODE_ADD, badmode = 0;

  if ((target_p = find_person(source_p, parv[1])) == NULL)
  {
    if (MyConnect(source_p))
      sendto_one_numeric(source_p, &me, ERR_NOSUCHCHANNEL, parv[1]);
    return;
  }

  if (source_p != target_p)
  {
     sendto_one_numeric(source_p, &me, ERR_USERSDONTMATCH);
     return;
  }

  if (parc < 3)
  {
    char buf[IRCD_BUFSIZE] = "";
    char *m = buf;

    *m++ = '+';
    for (tab = umode_tab; tab->c; ++tab)
      if (HasUMode(source_p, tab->flag))
        *m++ = tab->c;
    *m = '\0';

    sendto_one_numeric(source_p, &me, RPL_UMODEIS, buf);
    return;
  }

  /* Parse user mode change string */
  for (const char *m = parv[2]; *m; ++m)
  {
    switch (*m)
    {
      case '+':
        what = MODE_ADD;
        break;
      case '-':
        what = MODE_DEL;
        break;
      case 'o':
        if (what == MODE_ADD)
        {
          if (!MyConnect(source_p) && !HasUMode(source_p, UMODE_OPER))
          {
            ++Count.oper;
            SetOper(source_p);
          }
        }
        else
        {
          if (!HasUMode(source_p, UMODE_OPER))
            break;

          ClearOper(source_p);
          --Count.oper;

          if (MyConnect(source_p))
          {
            dlink_node *node = NULL;

            detach_conf(source_p, CONF_OPER);
            ClrOFlag(source_p);
            DelUMode(source_p, ConfigGeneral.oper_only_umodes);

            if ((node = dlinkFindDelete(&oper_list, source_p)))
              free_dlink_node(node);
          }
        }

        break;

      case 'S':  /* Only servers may set +S in a burst */
      case 'W':  /* Only servers may set +W in a burst */
      case 'r':  /* Only services may set +r */
      case 'x':  /* Only services may set +x */
        break;

      default:
        if ((tab = umode_map[(unsigned char)*m]))
        {
          if (MyConnect(source_p) && !HasUMode(source_p, UMODE_OPER) &&
              (ConfigGeneral.oper_only_umodes & tab->flag))
            badmode = 1;
          else
          {
            if (what == MODE_ADD)
              AddUMode(source_p, tab->flag);
            else
              DelUMode(source_p, tab->flag);
          }
        }
        else if (MyConnect(source_p))
          badmode = 1;

        break;
    }
  }

  if (badmode)
    sendto_one_numeric(source_p, &me, ERR_UMODEUNKNOWNFLAG);

  if (MyConnect(source_p) && HasUMode(source_p, UMODE_ADMIN) &&
      !HasOFlag(source_p, OPER_FLAG_ADMIN))
  {
    sendto_one_notice(source_p, &me, ":*** You have no admin flag;");
    DelUMode(source_p, UMODE_ADMIN);
  }

  if (!(setmodes & UMODE_INVISIBLE) && HasUMode(source_p, UMODE_INVISIBLE))
    ++Count.invisi;
  if ((setmodes & UMODE_INVISIBLE) && !HasUMode(source_p, UMODE_INVISIBLE))
    --Count.invisi;

  /*
   * Compare new modes with old modes and send string which will cause
   * servers to update correctly.
   */
  send_umode_out(source_p, setmodes);
}