From 40ecb85a1d4f77b92bc4dd462add44cb8e4f3be1 Mon Sep 17 00:00:00 2001 From: jess Date: Wed, 18 Nov 2020 14:29:08 +0000 Subject: [PATCH] add ConfigFileEntry.oper_secure_only, to require TLS to oper up (#76) --- doc/reference.conf | 3 +++ include/s_conf.h | 1 + ircd/newconf.c | 1 + ircd/s_conf.c | 1 + modules/m_challenge.c | 12 ++++++++++++ modules/m_grant.c | 6 ++++++ modules/m_info.c | 5 +++++ modules/m_oper.c | 12 ++++++++++++ 8 files changed, 41 insertions(+) diff --git a/doc/reference.conf b/doc/reference.conf index e17e70ba..75847787 100644 --- a/doc/reference.conf +++ b/doc/reference.conf @@ -1402,6 +1402,9 @@ general { /* hidden_caps: client capabilities we'll pretend we don't support until they're requested */ #hidden_caps = "userhost-in-names"; + + /* oper_secure_only: require TLS on any connection trying to oper up */ + oper_secure_only = no; }; modules { diff --git a/include/s_conf.h b/include/s_conf.h index 7b9fdc2b..8f7a1855 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -240,6 +240,7 @@ struct config_file_entry int max_ratelimit_tokens; int away_interval; int tls_ciphers_oper_only; + int oper_secure_only; char **hidden_caps; diff --git a/ircd/newconf.c b/ircd/newconf.c index 72441907..b9a329c9 100644 --- a/ircd/newconf.c +++ b/ircd/newconf.c @@ -2714,6 +2714,7 @@ static struct ConfEntry conf_general_table[] = { "certfp_method", CF_STRING, conf_set_general_certfp_method, 0, NULL }, { "drain_reason", CF_QSTRING, NULL, BUFSIZE, &ConfigFileEntry.drain_reason }, { "tls_ciphers_oper_only", CF_YESNO, NULL, 0, &ConfigFileEntry.tls_ciphers_oper_only }, + { "oper_secure_only", CF_YESNO, NULL, 0, &ConfigFileEntry.oper_secure_only }, { "\0", 0, NULL, 0, NULL } }; diff --git a/ircd/s_conf.c b/ircd/s_conf.c index e33dafa4..0776f48f 100644 --- a/ircd/s_conf.c +++ b/ircd/s_conf.c @@ -773,6 +773,7 @@ set_default_conf(void) ConfigFileEntry.max_ratelimit_tokens = 30; ConfigFileEntry.away_interval = 30; ConfigFileEntry.tls_ciphers_oper_only = false; + ConfigFileEntry.oper_secure_only = false; #ifdef HAVE_LIBZ ConfigFileEntry.compression_level = 4; diff --git a/modules/m_challenge.c b/modules/m_challenge.c index 1842f727..607325cd 100644 --- a/modules/m_challenge.c +++ b/modules/m_challenge.c @@ -113,6 +113,18 @@ m_challenge(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sou size_t cnt; int len = 0; + if (ConfigFileEntry.oper_secure_only && !IsSecureClient(source_p)) + { + sendto_one_notice(source_p, ":You must be using a secure connection to /CHALLENGE on this server"); + if (ConfigFileEntry.failed_oper_notice) + { + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, + "Failed CHALLENGE attempt - missing secure connection by %s (%s@%s)", + source_p->name, source_p->username, source_p->host); + } + return; + } + /* if theyre an oper, reprint oper motd and ignore */ if(IsOper(source_p)) { diff --git a/modules/m_grant.c b/modules/m_grant.c index 63ae6c7d..0021b7c0 100644 --- a/modules/m_grant.c +++ b/modules/m_grant.c @@ -109,6 +109,12 @@ static int do_grant(struct Client *source_p, struct Client *target_p, const char sendto_one_notice(source_p, ":%s already has privilege set %s.", target_p->name, target_p->user->privset->name); return 0; } + + if (ConfigFileEntry.oper_secure_only && !IsSecureClient(target_p)) + { + sendto_one_notice(source_p, ":Cannot GRANT %s, opers must be using secure connections.", target_p->name); + return 0; + } } if (!dodeoper) diff --git a/modules/m_info.c b/modules/m_info.c index fd9888da..11ab1db9 100644 --- a/modules/m_info.c +++ b/modules/m_info.c @@ -611,6 +611,11 @@ static struct InfoStruct info_table[] = { "Links rehash delay", INFO_DECIMAL(&ConfigServerHide.links_delay), }, + { + "oper_secure_only", + "Require TLS to become an oper", + INFO_INTBOOL_YN(&ConfigFileEntry.oper_secure_only), + }, { NULL, NULL, 0, { NULL } }, }; diff --git a/modules/m_oper.c b/modules/m_oper.c index ba91547b..6c42561c 100644 --- a/modules/m_oper.c +++ b/modules/m_oper.c @@ -70,6 +70,18 @@ m_oper(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p name = parv[1]; password = parv[2]; + if (ConfigFileEntry.oper_secure_only && !IsSecureClient(source_p)) + { + sendto_one_notice(source_p, ":You must be using a secure connection to /OPER on this server"); + if (ConfigFileEntry.failed_oper_notice) + { + sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, + "Failed OPER attempt - missing secure connection by %s (%s@%s)", + source_p->name, source_p->username, source_p->host); + } + return; + } + if(IsOper(source_p)) { sendto_one(source_p, form_str(RPL_YOUREOPER), me.name, source_p->name);