Exemple #1
0
/*! \brief OPER 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] = oper name
 *      - parv[2] = oper password
 */
static int
m_oper(struct Client *source_p, int parc, char *parv[])
{
  const char *const opername = parv[1];
  const char *const password = parv[2];

  if (EmptyString(password))
  {
    sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, "OPER");
    return 0;
  }

  struct MaskItem *conf;
  if ((conf = operator_find(source_p, opername)) == NULL)
  {
    sendto_one_numeric(source_p, &me, ERR_NOOPERHOST);

    conf = operator_find(NULL, opername);
    failed_oper_notice(source_p, opername, conf ? "host mismatch" : "no operator {} block");
    return 0;
  }

  if (IsConfSSL(conf) && !HasUMode(source_p, UMODE_SSL))
  {
    sendto_one_numeric(source_p, &me, ERR_NOOPERHOST);
    failed_oper_notice(source_p, opername, "requires SSL/TLS");
    return 0;
  }

  if (!EmptyString(conf->certfp))
  {
    if (EmptyString(source_p->certfp) || strcasecmp(source_p->certfp, conf->certfp))
    {
      sendto_one_numeric(source_p, &me, ERR_NOOPERHOST);
      failed_oper_notice(source_p, opername, "client certificate fingerprint mismatch");
      return 0;
    }
  }

  if (match_conf_password(password, conf) == true)
  {
    if (conf_attach(source_p, conf))
    {
      sendto_one_notice(source_p, &me, ":Can't attach conf!");
      failed_oper_notice(source_p, opername, "can't attach conf!");
      return 0;
    }

    oper_up(source_p, conf);
  }
  else
  {
    sendto_one_numeric(source_p, &me, ERR_PASSWDMISMATCH);
    failed_oper_notice(source_p, opername, "password mismatch");
  }

  return 0;
}
Exemple #2
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 *conf;
  struct AccessItem *aconf=NULL;
  const char *name = parv[1];
  const char *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 ((conf = find_password_conf(name,source_p)) == NULL)
  {
    sendto_one(source_p, form_str(ERR_NOOPERHOST), me.name, source_p->name);
    conf = find_exact_name_conf(OPER_TYPE, name, NULL, NULL);
    failed_oper_notice(source_p, name, (conf != NULL) ?
                       "host mismatch" : "no oper {} block");
    log_failed_oper(source_p, name);
    return;
  }

  aconf = (struct AccessItem *)map_to_conf(conf);

  if (match_oper_password(password, aconf))
  {
    if (attach_conf(source_p, conf) != 0)
    {
      sendto_one(source_p, ":%s NOTICE %s :Can't attach conf!",
                 me.name, source_p->name);
      failed_oper_notice(source_p, name, "can't attach conf!");
      log_failed_oper(source_p, name);
      return;
    }

    oper_up(source_p);

    ilog(L_TRACE, "OPER %s by %s!%s@%s",
         name, source_p->name, source_p->username, source_p->host);
    log_oper(source_p, name);
  }
  else
  {
    sendto_one(source_p, form_str(ERR_PASSWDMISMATCH), me.name, parv[0]);
    failed_oper_notice(source_p, name, "password mismatch");
    log_failed_oper(source_p, name);
  }
}
Exemple #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 MaskItem *conf = NULL;
  const char *name = parv[1];
  const char *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 ((conf = find_exact_name_conf(CONF_OPER, source_p, name, NULL, NULL)) == NULL)
  {
    sendto_one(source_p, form_str(ERR_NOOPERHOST), me.name, source_p->name);
    conf = find_exact_name_conf(CONF_OPER, NULL, name, NULL, NULL);
    failed_oper_notice(source_p, name, (conf != NULL) ?
                       "host mismatch" : "no oper {} block");
    return;
  }

  if (match_conf_password(password, conf))
  {
    if (attach_conf(source_p, conf) != 0)
    {
      sendto_one(source_p, ":%s NOTICE %s :Can't attach conf!",
                 me.name, source_p->name);
      failed_oper_notice(source_p, name, "can't attach conf!");
      return;
    }

    ++conf->count;
    oper_up(source_p);

    ilog(LOG_TYPE_OPER, "OPER %s by %s!%s@%s",
         name, source_p->name, source_p->username, source_p->host);
  }
  else
  {
    sendto_one(source_p, form_str(ERR_PASSWDMISMATCH), me.name, source_p->name);
    failed_oper_notice(source_p, name, "password mismatch");
  }
}
static int do_grant(struct Client *source_p, struct Client *target_p, int addflags, int removeflags, int dooper,
		int dodeoper, int add_snomask, int remove_snomask)
{
	const char *newparv[4];
	struct oper_conf oper;
	int changes = 0;
	int orig_snomask = target_p->allowed_snomask;
	char desc[512];
	int j;

	if (dodeoper)
	{
		if (!IsOper(target_p))
			sendto_one_notice(source_p, ":%s is not an oper",
					target_p->name);
		else
		{
			newparv[0] = target_p->name;
			newparv[1] = target_p->name;
			newparv[2] = "-o";
			newparv[3] = NULL;
			sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
					"%s is deopering %s",
					get_oper_name(source_p),
					get_client_name(target_p, HIDE_IP));
			sendto_one_notice(target_p, ":%s is deopering you",
					source_p->name);
			user_mode(target_p, target_p, 3, newparv);
			sendto_one_notice(source_p, ":Deopered %s",
					target_p->name);
			changes++;
		}
	}
	else if (dooper)
	{
		if (IsOper(target_p))
			sendto_one_notice(source_p, ":%s is already an oper",
					target_p->name);
		else
		{
			desc[0] = '\0';
			for (j = 0; flag_table[j].name != NULL; j++)
			{
				if ((addflags & flag_table[j].mode) == flag_table[j].mode)
				{
					if (desc[0] != '\0')
						strlcat(desc, " ", sizeof desc);
					strlcat(desc, "+", sizeof desc);
					strlcat(desc, flag_table[j].name, sizeof desc);
				}
			}
			if (desc[0] == '\0')
				strlcpy(desc, "<none>", sizeof desc);
			oper.name = "<grant>";
			oper.username = "";
			oper.host = "";
			oper.passwd = "";
			oper.flags = addflags;
			oper.umodes = 0;
			oper.snomask = 0;
			oper.allowed_snomask = add_snomask;
			sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
					"%s is opering %s with flags %s and snomask %s",
					get_oper_name(source_p),
					get_client_name(target_p, HIDE_IP),
					desc,
					construct_snobuf(oper.allowed_snomask));
			sendto_one_notice(target_p, ":%s is opering you",
					source_p->name);
			oper_up(target_p, &oper);
			sendto_one_notice(source_p, ":Opered %s with flags %s and snomask %s",
					target_p->name, desc, construct_snobuf(oper.allowed_snomask));
			changes++;
		}
	}
	removeflags &= target_p->operflags;
	addflags &= ~target_p->operflags;
	remove_snomask &= target_p->allowed_snomask;
	add_snomask &= ~target_p->allowed_snomask;
	if ((addflags | removeflags | add_snomask | remove_snomask) != 0)
	{
		if (!IsOper(target_p))
		{
			sendto_one_notice(source_p, ":%s is not an oper",
					target_p->name);
		}
		else
		{
			target_p->operflags |= addflags;
			target_p->operflags &= ~removeflags;
			target_p->allowed_snomask |= add_snomask;
			target_p->allowed_snomask &= ~remove_snomask;
			desc[0] = '\0';
			for (j = 0; flag_table[j].name != NULL; j++)
			{
				if ((addflags & flag_table[j].mode) == flag_table[j].mode)
				{
					if (desc[0] != '\0')
						strlcat(desc, " ", sizeof desc);
					strlcat(desc, "+", sizeof desc);
					strlcat(desc, flag_table[j].name, sizeof desc);
				}
				else if ((removeflags & flag_table[j].mode) == flag_table[j].mode)
				{
					if (desc[0] != '\0')
						strlcat(desc, " ", sizeof desc);
					strlcat(desc, "-", sizeof desc);
					strlcat(desc, flag_table[j].name, sizeof desc);
				}
			}
			if(desc[0] == '\0')
				strlcpy(desc, "<none>", sizeof desc);
			sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
					"%s is changing oper flags on %s (%s, snomask %s)",
					get_oper_name(source_p),
					get_client_name(target_p, HIDE_IP),
					desc,
					construct_snobuf_changes(target_p->allowed_snomask & ~orig_snomask, 
						orig_snomask & ~target_p->allowed_snomask));
			sendto_one_notice(target_p, ":%s is changing oper flags on you: %s, snomask %s",
					source_p->name, desc, construct_snobuf_changes(target_p->allowed_snomask & ~orig_snomask, 
						orig_snomask & ~target_p->allowed_snomask));
			sendto_one_notice(source_p, ":Changed oper flags on %s: %s, snomask %s",
					target_p->name, desc, construct_snobuf_changes(target_p->allowed_snomask & ~orig_snomask, 
						orig_snomask & ~target_p->allowed_snomask));

			sendto_server(source_p, NULL, CAP_TS6, NOCAPS, ":%s ENCAP * OPER %s",
					get_id(target_p, target_p), get_oper_privs(target_p->operflags));

			sendto_server(source_p, NULL, NOCAPS, CAP_TS6, ":%s ENCAP * OPER %s",
					target_p->name, get_oper_privs(target_p->operflags));

			/* fix up any umodes/snomasks they may not have
			 * anymore */
			newparv[0] = target_p->name;
			newparv[1] = target_p->name;
			newparv[2] = "+";
			newparv[3] = NULL;
			user_mode(target_p, target_p, 3, newparv);
			changes++;
		}
	}
	if (!changes)
		sendto_one_notice(source_p, ":Oper flags on %s unchanged",
				target_p->name);

	return 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;
}
Exemple #6
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 = NULL;
	struct ConfItem *conf = NULL;
	struct AccessItem *aconf = NULL;

	/* 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]);
		send_message_file(source_p, &ConfigFileEntry.opermotd);
		return;
	}

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

		if(svsnoop)
		{
			sendto_one(source_p,
				   ":%s NOTICE %s :*** This server is in NOOP mode, you cannot /oper",
				   me.name, source_p->name);
			failed_challenge_notice(source_p, source_p->localClient->auth_oper,
						"This server is in NOOP mode");
			log_oper_action(LOG_FAILED_OPER_TYPE, source_p, "%s\n",
					source_p->localClient->auth_oper);
			return;
		}

		if(irccmp(source_p->localClient->response, ++parv[1]))
		{
			sendto_one(source_p, form_str(ERR_PASSWDMISMATCH), me.name, source_p->name);
			failed_challenge_notice(source_p, source_p->localClient->auth_oper,
						"challenge failed");
			return;
		}

		conf = find_exact_name_conf(OPER_TYPE,
					    source_p->localClient->auth_oper,
					    source_p->username, source_p->host);
		if(conf == NULL)
			conf = find_exact_name_conf(OPER_TYPE,
						    source_p->localClient->auth_oper,
						    source_p->username, source_p->realhost);
		if(conf == NULL)
			conf = find_exact_name_conf(OPER_TYPE,
						    source_p->localClient->auth_oper,
						    source_p->username, source_p->sockhost);
		if(conf == NULL)
		{
			sendto_one(source_p, form_str(ERR_NOOPERHOST), me.name, parv[0]);
			log_oper_action(LOG_FAILED_OPER_TYPE, source_p, "%s\n",
					source_p->localClient->auth_oper);
			return;
		}

		if(attach_conf(source_p, conf) != 0)
		{
			sendto_one(source_p, ":%s NOTICE %s :Can't attach conf!",
				   me.name, source_p->name);
			failed_challenge_notice(source_p, conf->name, "can't attach conf!");
			log_oper_action(LOG_FAILED_OPER_TYPE, source_p, "%s\n",
					source_p->localClient->auth_oper);
			return;
		}

		oper_up(source_p);

		ilog(L_TRACE, "OPER %s by %s!%s@%s",
		     source_p->localClient->auth_oper, source_p->name, source_p->username,
		     source_p->realhost);
		log_oper_action(LOG_OPER_TYPE, source_p, "%s\n", source_p->localClient->auth_oper);

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

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

	if((conf = find_conf_exact(OPER_TYPE, parv[1], source_p->username, source_p->host)) != NULL)
		aconf = map_to_conf(conf);
	else if((conf = find_conf_exact(OPER_TYPE,
					parv[1], source_p->username, source_p->realhost)) != NULL)
		aconf = map_to_conf(conf);
	else if((conf = find_conf_exact(OPER_TYPE,
					parv[1], source_p->username, source_p->sockhost)) != NULL)
		aconf = map_to_conf(conf);

	if(aconf == NULL)
	{
		sendto_one(source_p, form_str(ERR_NOOPERHOST), me.name, parv[0]);
		conf = find_exact_name_conf(OPER_TYPE, parv[1], NULL, NULL);
		failed_challenge_notice(source_p, parv[1], (conf != NULL)
					? "host mismatch" : "no oper {} block");
		log_oper_action(LOG_FAILED_OPER_TYPE, source_p, "%s\n", parv[1]);
		return;
	}

	if(aconf->rsa_public_key == NULL)
	{
		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->localClient->response),
			       aconf->rsa_public_key))
		sendto_one(source_p, form_str(RPL_RSACHALLENGE), me.name, parv[0], challenge);

	DupString(source_p->localClient->auth_oper, conf->name);
	MyFree(challenge);
}
Exemple #7
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);
		}
	}
}
/*
 * m_challenge - generate RSA challenge for wouldbe oper
 * parv[1] = operator to challenge for, or +response
 *
 */
static int
m_challenge(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct oper_conf *oper_p;
	char *challenge = NULL; /* to placate gcc */
	char chal_line[CHALLENGE_WIDTH];
	unsigned char *b_response;
	size_t cnt;
	int len = 0;

	/* if theyre an oper, reprint oper motd and ignore */
	if(IsOper(source_p))
	{
		sendto_one(source_p, form_str(RPL_YOUREOPER), me.name, source_p->name);
		send_oper_motd(source_p);
		return 0;
	}

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

		if((rb_current_time() - source_p->localClient->chal_time) > CHALLENGE_EXPIRES)
		{
			sendto_one(source_p, form_str(ERR_PASSWDMISMATCH), me.name, source_p->name);
			ilog(L_FOPER, "EXPIRED CHALLENGE (%s) by (%s!%s@%s) (%s)",
			     source_p->localClient->opername, source_p->name,
			     source_p->username, source_p->host, source_p->sockhost);

			if(ConfigFileEntry.failed_oper_notice)
				sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
						     "Expired CHALLENGE attempt by %s (%s@%s)",
						     source_p->name, source_p->username,
						     source_p->host);
			cleanup_challenge(source_p);
			return 0;
		}

		parv[1]++;
		b_response = rb_base64_decode((const unsigned char *)parv[1], strlen(parv[1]), &len);

		if(len != SHA_DIGEST_LENGTH ||
		   memcmp(source_p->localClient->challenge, b_response, SHA_DIGEST_LENGTH))
		{
			sendto_one(source_p, form_str(ERR_PASSWDMISMATCH), me.name, source_p->name);
			ilog(L_FOPER, "FAILED CHALLENGE (%s) by (%s!%s@%s) (%s)",
			     source_p->localClient->opername, source_p->name,
			     source_p->username, source_p->host, source_p->sockhost);

			if(ConfigFileEntry.failed_oper_notice)
				sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
						     "Failed CHALLENGE attempt by %s (%s@%s)",
						     source_p->name, source_p->username,
						     source_p->host);

			rb_free(b_response);
			cleanup_challenge(source_p);
			return 0;
		}

		rb_free(b_response);

		oper_p = find_oper_conf(source_p->username, source_p->orighost,
					source_p->sockhost,
					source_p->localClient->opername);

		if(oper_p == NULL)
		{
			sendto_one_numeric(source_p, ERR_NOOPERHOST, form_str(ERR_NOOPERHOST));
			ilog(L_FOPER, "FAILED OPER (%s) by (%s!%s@%s) (%s)",
			     source_p->localClient->opername, source_p->name,
			     source_p->username, source_p->host,
			     source_p->sockhost);

			if(ConfigFileEntry.failed_oper_notice)
				sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
						     "Failed CHALLENGE attempt - host mismatch by %s (%s@%s)",
						     source_p->name, source_p->username,
						     source_p->host);
			return 0;
		}

		cleanup_challenge(source_p);

		oper_up(source_p, oper_p);

		ilog(L_OPERED, "OPER %s by %s!%s@%s (%s)",
		     source_p->localClient->opername, source_p->name,
		     source_p->username, source_p->host, source_p->sockhost);
		return 0;
	}

	cleanup_challenge(source_p);

	oper_p = find_oper_conf(source_p->username, source_p->orighost,
				source_p->sockhost, parv[1]);

	if(oper_p == NULL)
	{
		sendto_one_numeric(source_p, ERR_NOOPERHOST, form_str(ERR_NOOPERHOST));
		ilog(L_FOPER, "FAILED OPER (%s) by (%s!%s@%s) (%s)",
		     parv[1], source_p->name,
		     source_p->username, source_p->host, source_p->sockhost);

		if(ConfigFileEntry.failed_oper_notice)
			sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
					     "Failed CHALLENGE attempt - host mismatch by %s (%s@%s)",
					     source_p->name, source_p->username, source_p->host);
		return 0;
	}

	if(!oper_p->rsa_pubkey)
	{
		sendto_one_notice(source_p, ":I'm sorry, PK authentication is not enabled for your oper{} block.");
		return 0;
	}

	if(IsOperConfNeedSSL(oper_p) && !IsSSLClient(source_p))
	{
		sendto_one_numeric(source_p, ERR_NOOPERHOST, form_str(ERR_NOOPERHOST));
		ilog(L_FOPER, "FAILED CHALLENGE (%s) by (%s!%s@%s) (%s) -- requires SSL/TLS",
		     parv[1], source_p->name, source_p->username, source_p->host,
		     source_p->sockhost);

		if(ConfigFileEntry.failed_oper_notice)
		{
			sendto_realops_snomask(SNO_GENERAL, L_ALL,
					     "Failed CHALLENGE attempt - missing SSL/TLS by %s (%s@%s)",
					     source_p->name, source_p->username, source_p->host);
		}
		return 0;
	}

	if (oper_p->certfp != NULL)
	{
		if (source_p->certfp == NULL || strcasecmp(source_p->certfp, oper_p->certfp))
		{
			sendto_one_numeric(source_p, ERR_NOOPERHOST, form_str(ERR_NOOPERHOST));
			ilog(L_FOPER, "FAILED OPER (%s) by (%s!%s@%s) (%s) -- client certificate fingerprint mismatch",
			     parv[1], source_p->name,
			     source_p->username, source_p->host, source_p->sockhost);

			if(ConfigFileEntry.failed_oper_notice)
			{
				sendto_realops_snomask(SNO_GENERAL, L_ALL,
						     "Failed OPER attempt - client certificate fingerprint mismatch by %s (%s@%s)",
						     source_p->name, source_p->username, source_p->host);
			}
			return 0;
		}
	}

	if(!generate_challenge(&challenge, &(source_p->localClient->challenge), oper_p->rsa_pubkey))
	{
		char *chal = challenge;
		source_p->localClient->chal_time = rb_current_time();
		for(;;)
		{
			cnt = rb_strlcpy(chal_line, chal, CHALLENGE_WIDTH);
			sendto_one(source_p, form_str(RPL_RSACHALLENGE2), me.name, source_p->name, chal_line);
			if(cnt > CHALLENGE_WIDTH)
				chal += CHALLENGE_WIDTH - 1;
			else
				break;

		}
		sendto_one(source_p, form_str(RPL_ENDOFRSACHALLENGE2),
			   me.name, source_p->name);
		rb_free(challenge);
		source_p->localClient->opername = rb_strdup(oper_p->name);
	}
	else
		sendto_one_notice(source_p, ":Failed to generate challenge.");

	return 0;
}
Exemple #9
0
/*
 * m_oper
 *      parv[1] = oper name
 *      parv[2] = oper password
 */
static int
m_oper(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
    struct oper_conf *oper_p;
    const char *name;
    const char *password;

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

    if(IsOper(source_p)) {
        sendto_one(source_p, form_str(RPL_YOUREOPER), me.name, source_p->name);
        send_oper_motd(source_p);
        return 0;
    }

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

    oper_p = find_oper_conf(source_p->username, source_p->orighost,
                            source_p->sockhost, name);

    if(oper_p == NULL) {
        sendto_one_numeric(source_p, ERR_NOOPERHOST, form_str(ERR_NOOPERHOST));
        ilog(L_FOPER, "FAILED OPER (%s) by (%s!%s@%s) (%s)",
             name, source_p->name,
             source_p->username, source_p->host, source_p->sockhost);

        if(ConfigFileEntry.failed_oper_notice) {
            sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
                                   "Failed OPER attempt - host mismatch by %s (%s@%s)",
                                   source_p->name, source_p->username, source_p->host);
        }

        return 0;
    }

    if(IsOperConfNeedSSL(oper_p) && !IsSSLClient(source_p)) {
        sendto_one_numeric(source_p, ERR_NOOPERHOST, form_str(ERR_NOOPERHOST));
        ilog(L_FOPER, "FAILED OPER (%s) by (%s!%s@%s) (%s) -- requires SSL/TLS",
             name, source_p->name,
             source_p->username, source_p->host, source_p->sockhost);

        if(ConfigFileEntry.failed_oper_notice) {
            sendto_realops_snomask(SNO_GENERAL, L_ALL,
                                   "Failed OPER attempt - missing SSL/TLS by %s (%s@%s)",
                                   source_p->name, source_p->username, source_p->host);
        }
        return 0;
    }

    if (oper_p->certfp != NULL) {
        if (source_p->certfp == NULL || strcasecmp(source_p->certfp, oper_p->certfp)) {
            sendto_one_numeric(source_p, ERR_NOOPERHOST, form_str(ERR_NOOPERHOST));
            ilog(L_FOPER, "FAILED OPER (%s) by (%s!%s@%s) (%s) -- client certificate fingerprint mismatch",
                 name, source_p->name,
                 source_p->username, source_p->host, source_p->sockhost);

            if(ConfigFileEntry.failed_oper_notice) {
                sendto_realops_snomask(SNO_GENERAL, L_ALL,
                                       "Failed OPER attempt - client certificate fingerprint mismatch by %s (%s@%s)",
                                       source_p->name, source_p->username, source_p->host);
            }
            return 0;
        }
    }

    if(match_oper_password(password, oper_p)) {
        oper_up(source_p, oper_p);

        ilog(L_OPERED, "OPER %s by %s!%s@%s (%s)",
             name, source_p->name, source_p->username, source_p->host,
             source_p->sockhost);
        return 0;
    } else {
        sendto_one_numeric(source_p, ERR_NOOPERHOST, form_str(ERR_NOOPERHOST));

        ilog(L_FOPER, "FAILED OPER (%s) by (%s!%s@%s) (%s)",
             name, source_p->name, source_p->username, source_p->host,
             source_p->sockhost);

        if(ConfigFileEntry.failed_oper_notice) {
            sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
                                   "Failed OPER attempt by %s (%s@%s)",
                                   source_p->name, source_p->username, source_p->host);
        }
    }

    return 0;
}
Exemple #10
0
static int
do_grant(struct Client *source_p, struct Client *target_p, const char *new_privset)
{
	int dooper = 0, dodeoper = 0;
	struct PrivilegeSet *privset = 0;

	if(!strcmp(new_privset, "deoper"))
	{
		if(!IsAnyOper(target_p))
		{
			sendto_one_notice(source_p, ":You can't deoper someone who isn't an oper.");
			return 0;
		}
		new_privset = "default";
		dodeoper = 1;

		sendto_one_notice(target_p, ":%s is deopering you.", source_p->name);
		sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is deopering %s.",
				       get_oper_name(source_p), target_p->name);
	}
	else
	{
		if(!(privset = privilegeset_get(new_privset)))
		{
			sendto_one_notice(source_p, ":There is no privilege set named '%s'.",
					  new_privset);
			return 0;
		}

		if(privset == target_p->localClient->privset)
		{
			sendto_one_notice(source_p, ":%s already has privilege set %s.",
					  target_p->name, target_p->localClient->privset->name);
			return 0;
		}
	}

	if(!dodeoper)
	{
		if(!IsAnyOper(target_p))
		{
			sendto_one_notice(target_p, ":%s is opering you with privilege set %s",
					  source_p->name, privset->name);
			sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
					       "%s is opering %s with privilege set %s",
					       get_oper_name(source_p), target_p->name,
					       privset->name);
			dooper = 1;
		}
		else
		{
			sendto_one_notice(target_p, ":%s is changing your privilege set to %s",
					  source_p->name, privset->name);
			sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
					       "%s is changing the privilege set of %s to %s",
					       get_oper_name(source_p), target_p->name,
					       privset->name);
		}

		if(privilegeset_in_set(privset, "oper:staffer") && !IsOper(target_p))
		{
			dooper = 1;
			if(IsHelper(target_p))
				dodeoper = 1;
		}
		else if(!privilegeset_in_set(privset, "oper:staffer") && IsOper(target_p))
			dooper = dodeoper = 1;
	}

	if(dodeoper)
	{
		const char *modeparv[4];
		modeparv[0] = modeparv[1] = target_p->name;
		modeparv[2] = "-oO";
		modeparv[3] = NULL;
		user_mode(target_p, target_p, 3, modeparv);
	}

	if(dooper)
	{
		struct oper_conf oper;
		oper.name = "<grant>";
		oper.umodes = 0;
		oper.snomask = 0;
		oper.privset = privset;

		oper_up(target_p, &oper);
	}

	target_p->localClient->privset = privset;
	const char *modeparv[4];
	modeparv[0] = modeparv[1] = target_p->name;
	modeparv[2] = "+";
	modeparv[3] = NULL;
	user_mode(target_p, target_p, 3, modeparv);

	return 0;
}
Exemple #11
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 = NULL;
  struct MaskItem *conf = NULL;

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

    if (irccmp(source_p->localClient->response, ++parv[1]))
    {
      sendto_one(source_p, form_str(ERR_PASSWDMISMATCH), me.name,
                 source_p->name);
      failed_challenge_notice(source_p, source_p->localClient->auth_oper,
                              "challenge failed");
      return;
    }
    
    conf = find_exact_name_conf(CONF_OPER, source_p,
                                source_p->localClient->auth_oper, NULL, NULL);
    if (conf == NULL)
    {
      /* XXX: logging */
      sendto_one (source_p, form_str(ERR_NOOPERHOST), me.name, source_p->name);
      return;
    }

    if (attach_conf(source_p, conf) != 0)
    {
      sendto_one(source_p,":%s NOTICE %s :Can't attach conf!",
		 me.name, source_p->name);   
      failed_challenge_notice(source_p, conf->name, "can't attach conf!");
      return;
    }

    ++conf->count;
    oper_up(source_p);

    ilog(LOG_TYPE_OPER, "OPER %s by %s!%s@%s",
	 source_p->localClient->auth_oper, source_p->name, source_p->username,
	 source_p->host);

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

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

  conf = find_exact_name_conf(CONF_OPER, source_p, parv[1], NULL, NULL);

  if (!conf)
  {
    sendto_one (source_p, form_str(ERR_NOOPERHOST), me.name, source_p->name);
    conf = find_exact_name_conf(CONF_OPER, NULL, parv[1], NULL, NULL);
    failed_challenge_notice(source_p, parv[1], (conf != NULL)
                            ? "host mismatch" : "no oper {} block");
    return;
  }

  if (conf->rsa_public_key == NULL)
  {
    sendto_one (source_p, ":%s NOTICE %s :I'm sorry, PK authentication "
		"is not enabled for your oper{} block.", me.name,
		source_p->name);
    return;
  }

  if (!generate_challenge(&challenge, &(source_p->localClient->response),
                          conf->rsa_public_key))
    sendto_one(source_p, form_str(RPL_RSACHALLENGE),
               me.name, source_p->name, challenge);

  source_p->localClient->auth_oper = xstrdup(conf->name);
  MyFree(challenge);
}