mirror of
https://github.com/unrealircd/unrealircd.git
synced 2026-07-03 18:43:12 +02:00
67d691fce9
that use outdated SSL/TLS protocols (eg: TLSv1.0) and ciphers. The default settings are to warn in all cases: users connecting, opers /OPER'ing up and servers linking in. The user will see a message telling them to upgrade their IRC client. This should help with migrating such users since in the future, say one or two years from now, we would want to change the default to only allow TSLv1.2+ with ciphers that provide Forward Secrecy. Instead of rejecting clients without any error message, this provides a way to warn them and give them some time to upgrade their outdated IRC client. https://www.unrealircd.org/docs/Set_block#set::outdated-tls-policy
340 lines
10 KiB
C
340 lines
10 KiB
C
/*
|
|
* Unreal Internet Relay Chat Daemon, src/modules/m_oper.c
|
|
* (C) 2000-2001 Carsten V. Munk and the UnrealIRCd Team
|
|
* Moved to modules by Fish (Justin Hammond)
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 1, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include "unrealircd.h"
|
|
|
|
CMD_FUNC(m_oper);
|
|
|
|
|
|
/* Place includes here */
|
|
#define MSG_OPER "OPER" /* OPER */
|
|
|
|
ModuleHeader MOD_HEADER(m_oper)
|
|
= {
|
|
"oper", /* Name of module */
|
|
"4.2", /* Version */
|
|
"command /oper", /* Short description of module */
|
|
"3.2-b8-1",
|
|
NULL
|
|
};
|
|
|
|
/* This is called on module init, before Server Ready */
|
|
MOD_INIT(m_oper)
|
|
{
|
|
CommandAdd(modinfo->handle, MSG_OPER, m_oper, MAXPARA, M_USER);
|
|
MARK_AS_OFFICIAL_MODULE(modinfo);
|
|
return MOD_SUCCESS;
|
|
}
|
|
|
|
/* Is first run when server is 100% ready */
|
|
MOD_LOAD(m_oper)
|
|
{
|
|
return MOD_SUCCESS;
|
|
}
|
|
|
|
/* Called when module is unloaded */
|
|
MOD_UNLOAD(m_oper)
|
|
{
|
|
return MOD_SUCCESS;
|
|
}
|
|
|
|
void set_oper_host(aClient *sptr, char *host)
|
|
{
|
|
char uhost[HOSTLEN + USERLEN + 1];
|
|
char *p;
|
|
|
|
strlcpy(uhost, host, sizeof(uhost));
|
|
|
|
if ((p = strchr(uhost, '@')))
|
|
{
|
|
*p++ = '\0';
|
|
strlcpy(sptr->user->username, uhost, sizeof(sptr->user->username));
|
|
sendto_server(NULL, 0, 0, ":%s SETIDENT %s",
|
|
sptr->name, sptr->user->username);
|
|
host = p;
|
|
}
|
|
iNAH_host(sptr, host);
|
|
SetHidden(sptr);
|
|
}
|
|
|
|
/*
|
|
** m_oper
|
|
** parv[1] = oper name
|
|
** parv[2] = oper password
|
|
*/
|
|
CMD_FUNC(m_oper)
|
|
{
|
|
ConfigItem_oper *operblock;
|
|
char *name, *password;
|
|
int i = 0, j = 0;
|
|
long old = sptr->umodes & ALL_UMODES; /* old user modes */
|
|
|
|
if (!MyClient(sptr))
|
|
return 0;
|
|
|
|
if ((parc < 2) || BadPtr(parv[1]))
|
|
{
|
|
sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
|
|
me.name, sptr->name, "OPER");
|
|
return 0;
|
|
}
|
|
|
|
if (SVSNOOP)
|
|
{
|
|
sendnotice(sptr,
|
|
"*** This server is in NOOP mode, you cannot /oper");
|
|
return 0;
|
|
}
|
|
|
|
if (IsOper(sptr))
|
|
{
|
|
sendto_one(sptr, rpl_str(RPL_YOUREOPER),
|
|
me.name, sptr->name);
|
|
// TODO: de-confuse this ? ;)
|
|
return 0;
|
|
}
|
|
|
|
name = parv[1];
|
|
password = (parc > 2) ? parv[2] : "";
|
|
|
|
/* set::plaintext-policy::oper 'deny' */
|
|
if (!IsSecure(sptr) && !IsLocal(sptr) && (iConf.plaintext_policy_oper == POLICY_DENY))
|
|
{
|
|
sendnotice(sptr, "%s", iConf.plaintext_policy_oper_message);
|
|
sendto_snomask_global
|
|
(SNO_OPER, "Failed OPER attempt by %s (%s@%s) [not using SSL/TLS]",
|
|
sptr->name, sptr->user->username, sptr->local->sockhost);
|
|
ircd_log(LOG_OPER, "OPER NO-SSL/TLS (%s) by (%s!%s@%s)", name, sptr->name,
|
|
sptr->user->username, sptr->local->sockhost);
|
|
sptr->local->since += 7;
|
|
return 0;
|
|
}
|
|
|
|
/* set::outdated-tls-policy::oper 'deny' */
|
|
if (IsSecure(sptr) && (iConf.outdated_tls_policy_oper == POLICY_DENY) && outdated_tls_client(sptr))
|
|
{
|
|
sendnotice(sptr, "%s", outdated_tls_client_build_string(iConf.outdated_tls_policy_oper_message, sptr));
|
|
sendto_snomask_global
|
|
(SNO_OPER, "Failed OPER attempt by %s (%s@%s) [outdated SSL/TLS protocol or cipher]",
|
|
sptr->name, sptr->user->username, sptr->local->sockhost);
|
|
ircd_log(LOG_OPER, "OPER OUTDATED-SSL/TLS (%s) by (%s!%s@%s)", name, sptr->name,
|
|
sptr->user->username, sptr->local->sockhost);
|
|
sptr->local->since += 7;
|
|
return 0;
|
|
}
|
|
|
|
if (!(operblock = Find_oper(name)))
|
|
{
|
|
sendto_one(sptr, err_str(ERR_NOOPERHOST), me.name, sptr->name);
|
|
sendto_snomask_global
|
|
(SNO_OPER, "Failed OPER attempt by %s (%s@%s) [unknown oper]",
|
|
sptr->name, sptr->user->username, sptr->local->sockhost);
|
|
ircd_log(LOG_OPER, "OPER UNKNOWNOPER (%s) by (%s!%s@%s)", name, sptr->name,
|
|
sptr->user->username, sptr->local->sockhost);
|
|
sptr->local->since += 7;
|
|
return 0;
|
|
}
|
|
|
|
if (!unreal_mask_match(sptr, operblock->mask))
|
|
{
|
|
sendto_one(sptr, err_str(ERR_NOOPERHOST), me.name, sptr->name);
|
|
sendto_snomask_global
|
|
(SNO_OPER, "Failed OPER attempt by %s (%s@%s) using UID %s [host doesnt match]",
|
|
sptr->name, sptr->user->username, sptr->local->sockhost, name);
|
|
ircd_log(LOG_OPER, "OPER NOHOSTMATCH (%s) by (%s!%s@%s)", name, sptr->name,
|
|
sptr->user->username, sptr->local->sockhost);
|
|
sptr->local->since += 7;
|
|
return 0;
|
|
}
|
|
|
|
i = Auth_Check(cptr, operblock->auth, password);
|
|
if (i == -1)
|
|
{
|
|
sendto_one(sptr, err_str(ERR_PASSWDMISMATCH), me.name, sptr->name);
|
|
if (FAILOPER_WARN)
|
|
sendnotice(sptr,
|
|
"*** Your attempt has been logged.");
|
|
ircd_log(LOG_OPER, "OPER FAILEDAUTH (%s) by (%s!%s@%s)", name, sptr->name,
|
|
sptr->user->username, sptr->local->sockhost);
|
|
sendto_snomask_global
|
|
(SNO_OPER, "Failed OPER attempt by %s (%s@%s) using UID %s [FAILEDAUTH]",
|
|
sptr->name, sptr->user->username, sptr->local->sockhost, name);
|
|
sptr->local->since += 7;
|
|
return 0;
|
|
}
|
|
|
|
if (i < 2)
|
|
return 0; /* anything below 2 means 'not really authenticated' */
|
|
|
|
/* Authentication of the oper succeeded (like, password, ssl cert),
|
|
* but we still have some other restrictions to check below as well,
|
|
* like 'require-modes' and 'maxlogins'...
|
|
*/
|
|
|
|
/* Check oper::require_modes */
|
|
if (operblock->require_modes & ~sptr->umodes)
|
|
{
|
|
sendto_one(sptr, ":%s %d %s :You are missing user modes required to OPER", me.name, ERR_NOOPERHOST, sptr->name);
|
|
sendto_snomask_global
|
|
(SNO_OPER, "Failed OPER attempt by %s (%s@%s) [lacking modes '%s' in oper::require-modes]",
|
|
sptr->name, sptr->user->username, sptr->local->sockhost, get_modestr(operblock->require_modes & ~sptr->umodes));
|
|
ircd_log(LOG_OPER, "OPER MISSINGMODES (%s) by (%s!%s@%s), needs modes=%s",
|
|
name, sptr->name, sptr->user->username, sptr->local->sockhost,
|
|
get_modestr(operblock->require_modes & ~sptr->umodes));
|
|
sptr->local->since += 7;
|
|
return 0;
|
|
}
|
|
|
|
if (!Find_operclass(operblock->operclass))
|
|
{
|
|
sendnotice(sptr, "ERROR: There is a non-existant oper::operclass specified for your oper block");
|
|
ircd_log(LOG_ERROR, "OPER MISSINGOPERCLASS (%s) by (%s!%s@%s), oper::operclass does not exist: %s",
|
|
name, sptr->name, sptr->user->username, sptr->local->sockhost,
|
|
operblock->operclass);
|
|
sendto_snomask_global
|
|
(SNO_OPER, "Failed OPER attempt by %s (%s@%s) [oper::operclass does not exist: '%s']",
|
|
sptr->name, sptr->user->username, sptr->local->sockhost, operblock->operclass);
|
|
return 0;
|
|
}
|
|
|
|
if (operblock->maxlogins && (count_oper_sessions(operblock->name) >= operblock->maxlogins))
|
|
{
|
|
sendto_one(sptr, err_str(ERR_NOOPERHOST), me.name, sptr->name);
|
|
sendto_one(sptr, ":%s NOTICE %s :Your maximum number of concurrent oper logins has been reached (%d)",
|
|
me.name, sptr->name, operblock->maxlogins);
|
|
sendto_snomask_global
|
|
(SNO_OPER, "Failed OPER attempt by %s (%s@%s) using UID %s [maxlogins reached]",
|
|
sptr->name, sptr->user->username, sptr->local->sockhost, name);
|
|
ircd_log(LOG_OPER, "OPER TOOMANYLOGINS (%s) by (%s!%s@%s)", name, sptr->name,
|
|
sptr->user->username, sptr->local->sockhost);
|
|
sptr->local->since += 4;
|
|
return 0;
|
|
}
|
|
|
|
/* /OPER really succeeded now. Start processing it. */
|
|
|
|
/* Store which oper block was used to become IRCOp (for maxlogins and whois) */
|
|
safefree(sptr->user->operlogin);
|
|
sptr->user->operlogin = strdup(operblock->name);
|
|
|
|
/* Put in the right class */
|
|
if (sptr->local->class)
|
|
sptr->local->class->clients--;
|
|
sptr->local->class = operblock->class;
|
|
sptr->local->class->clients++;
|
|
|
|
/* oper::swhois */
|
|
if (operblock->swhois)
|
|
{
|
|
SWhois *s;
|
|
for (s = operblock->swhois; s; s = s->next)
|
|
swhois_add(sptr, "oper", -100, s->line, &me, NULL);
|
|
}
|
|
|
|
/* set oper user modes */
|
|
sptr->umodes |= UMODE_OPER;
|
|
if (operblock->modes)
|
|
sptr->umodes |= operblock->modes; /* oper::modes */
|
|
else
|
|
sptr->umodes |= OPER_MODES; /* set::modes-on-oper */
|
|
|
|
/* oper::vhost */
|
|
if (operblock->vhost)
|
|
{
|
|
set_oper_host(sptr, operblock->vhost);
|
|
} else
|
|
if (IsHidden(sptr) && !sptr->user->virthost)
|
|
{
|
|
/* +x has just been set by modes-on-oper and no vhost. cloak the oper! */
|
|
sptr->user->virthost = strdup(sptr->user->cloakedhost);
|
|
}
|
|
|
|
sendto_snomask_global(SNO_OPER,
|
|
"%s (%s@%s) [%s] is now an operator",
|
|
sptr->name, sptr->user->username, sptr->local->sockhost,
|
|
parv[1]);
|
|
|
|
ircd_log(LOG_OPER, "OPER (%s) by (%s!%s@%s)", name, sptr->name, sptr->user->username,
|
|
sptr->local->sockhost);
|
|
|
|
/* set oper snomasks */
|
|
if (operblock->snomask)
|
|
set_snomask(sptr, operblock->snomask); /* oper::snomask */
|
|
else
|
|
set_snomask(sptr, OPER_SNOMASK); /* set::snomask-on-oper */
|
|
|
|
/* some magic to set user mode +s (and snomask +s) if you have any snomasks set */
|
|
if (sptr->user->snomask)
|
|
{
|
|
sptr->user->snomask |= SNO_SNOTICE;
|
|
sptr->umodes |= UMODE_SERVNOTICE;
|
|
}
|
|
|
|
send_umode_out(cptr, sptr, old);
|
|
sendto_one(sptr, rpl_str(RPL_SNOMASK),
|
|
me.name, sptr->name, get_sno_str(sptr));
|
|
|
|
list_add(&sptr->special_node, &oper_list);
|
|
|
|
RunHook2(HOOKTYPE_LOCAL_OPER, sptr, 1);
|
|
|
|
sendto_one(sptr, rpl_str(RPL_YOUREOPER), me.name, sptr->name);
|
|
|
|
/* Update statistics */
|
|
if (IsInvisible(sptr) && !(old & UMODE_INVISIBLE))
|
|
IRCstats.invisible++;
|
|
if (IsOper(sptr) && !IsHideOper(sptr))
|
|
IRCstats.operators++;
|
|
|
|
if (SHOWOPERMOTD == 1)
|
|
(void)do_cmd(cptr, sptr, "OPERMOTD", parc, parv);
|
|
|
|
if (!BadPtr(OPER_AUTO_JOIN_CHANS) && strcmp(OPER_AUTO_JOIN_CHANS, "0"))
|
|
{
|
|
char *chans[3] = {
|
|
sptr->name,
|
|
OPER_AUTO_JOIN_CHANS,
|
|
NULL
|
|
};
|
|
if (do_cmd(cptr, sptr, "JOIN", 3, chans) == FLUSH_BUFFER)
|
|
return FLUSH_BUFFER;
|
|
}
|
|
|
|
/* set::plaintext-policy::oper 'warn' */
|
|
if (!IsSecure(sptr) && !IsLocal(sptr) && (iConf.plaintext_policy_oper == POLICY_WARN))
|
|
{
|
|
sendnotice(sptr, "%s", iConf.plaintext_policy_oper_message);
|
|
sendto_snomask_global
|
|
(SNO_OPER, "OPER %s [%s] used an insecure (non-SSL) connection to /OPER.",
|
|
sptr->name, name);
|
|
}
|
|
|
|
/* set::outdated-tls-policy::oper 'warn' */
|
|
if (IsSecure(sptr) && (iConf.outdated_tls_policy_oper == POLICY_WARN) && outdated_tls_client(sptr))
|
|
{
|
|
sendnotice(sptr, "%s", outdated_tls_client_build_string(iConf.outdated_tls_policy_oper_message, sptr));
|
|
sendto_snomask_global
|
|
(SNO_OPER, "OPER %s [%s] used a connection with an outdated SSL/TLS protocol or cipher to /OPER.",
|
|
sptr->name, name);
|
|
}
|
|
|
|
return 0;
|
|
}
|