From 1123eefcb085802bbad7a04bf0d8b7f082d123d6 Mon Sep 17 00:00:00 2001 From: Ed Kellett Date: Sun, 7 Jul 2019 04:57:53 +0100 Subject: [PATCH] Rework oper hiding As it stands, oper hiding is rather messy and inconsistent. Add SeesOper(target, source), which is true iff target should appear as an oper to source. If I haven't missed something, all commands that reveal oper status now use the same logic. general::hide_opers_in_whois is a special case, and affects /whois only. general::hide_opers is introduced, and has the same effect as giving everyone oper:hidden. All commands that reveal oper status respect both. --- include/s_conf.h | 1 + include/s_newconf.h | 2 ++ ircd/newconf.c | 1 + ircd/s_conf.c | 1 + modules/m_etrace.c | 10 +++++----- modules/m_stats.c | 2 +- modules/m_trace.c | 11 +++++++---- modules/m_userhost.c | 5 +++-- modules/m_who.c | 10 +++++----- modules/m_whois.c | 2 +- 10 files changed, 27 insertions(+), 18 deletions(-) diff --git a/include/s_conf.h b/include/s_conf.h index 9744eb92..f158b61e 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -239,6 +239,7 @@ struct config_file_entry int certfp_method; int hide_opers_in_whois; + int hide_opers; }; struct config_channel_entry diff --git a/include/s_newconf.h b/include/s_newconf.h index 4792b005..41e74442 100644 --- a/include/s_newconf.h +++ b/include/s_newconf.h @@ -166,6 +166,8 @@ extern void cluster_generic(struct Client *, const char *, int cltype, #define IsOperRemoteBan(x) (HasPrivilege((x), "oper:remoteban")) #define IsOperMassNotice(x) (HasPrivilege((x), "oper:mass_notice")) +#define SeesOper(target, source) (IsOper((target)) && (!ConfigFileEntry.hide_opers && !HasPrivilege((target), "oper:hidden") || IsOper((source)))) + extern struct oper_conf *make_oper_conf(void); extern void free_oper_conf(struct oper_conf *); extern void clear_oper_conf(void); diff --git a/ircd/newconf.c b/ircd/newconf.c index 9830cda3..f63669ec 100644 --- a/ircd/newconf.c +++ b/ircd/newconf.c @@ -2797,6 +2797,7 @@ static struct ConfEntry conf_general_table[] = { "max_ratelimit_tokens", CF_INT, NULL, 0, &ConfigFileEntry.max_ratelimit_tokens }, { "away_interval", CF_INT, NULL, 0, &ConfigFileEntry.away_interval }, { "hide_opers_in_whois", CF_YESNO, NULL, 0, &ConfigFileEntry.hide_opers_in_whois }, + { "hide_opers", CF_YESNO, NULL, 0, &ConfigFileEntry.hide_opers }, { "certfp_method", CF_STRING, conf_set_general_certfp_method, 0, NULL }, { "\0", 0, NULL, 0, NULL } }; diff --git a/ircd/s_conf.c b/ircd/s_conf.c index a828c1aa..dbed64d0 100644 --- a/ircd/s_conf.c +++ b/ircd/s_conf.c @@ -809,6 +809,7 @@ set_default_conf(void) ConfigFileEntry.nicklen = NICKLEN; ConfigFileEntry.certfp_method = RB_SSL_CERTFP_METH_CERT_SHA1; ConfigFileEntry.hide_opers_in_whois = 0; + ConfigFileEntry.hide_opers = 0; if (!alias_dict) alias_dict = rb_dictionary_create("alias", rb_strcasecmp); diff --git a/modules/m_etrace.c b/modules/m_etrace.c index fded420b..193d842b 100644 --- a/modules/m_etrace.c +++ b/modules/m_etrace.c @@ -167,7 +167,7 @@ do_etrace(struct Client *source_p, int ipv4, int ipv6) sendto_one(source_p, form_str(RPL_ETRACE), me.name, source_p->name, - IsOper(target_p) ? "Oper" : "User", + SeesOper(target_p, source_p) ? "Oper" : "User", get_client_class(target_p), target_p->name, target_p->username, target_p->host, show_ip(source_p, target_p) ? target_p->sockhost : "255.255.255.255", @@ -206,14 +206,14 @@ do_single_etrace(struct Client *source_p, struct Client *target_p) if(!show_ip(source_p, target_p)) sendto_one(source_p, form_str(RPL_ETRACEFULL), me.name, source_p->name, - IsOper(target_p) ? "Oper" : "User", + SeesOper(target_p, source_p) ? "Oper" : "User", get_client_class(target_p), target_p->name, target_p->username, target_p->host, "255.255.255.255", " ", target_p->info); else sendto_one(source_p, form_str(RPL_ETRACEFULL), me.name, source_p->name, - IsOper(target_p) ? "Oper" : "User", + SeesOper(target_p, source_p) ? "Oper" : "User", get_client_class(target_p), target_p->name, target_p->username, target_p->host, target_p->sockhost, @@ -278,7 +278,7 @@ m_chantrace(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sou sendto_one(source_p, form_str(RPL_ETRACE), me.name, source_p->name, - IsOper(target_p) ? "Oper" : "User", + SeesOper(target_p, source_p) ? "Oper" : "User", /* class field -- pretend its server.. */ target_p->servptr->name, target_p->name, target_p->username, target_p->host, @@ -323,7 +323,7 @@ match_masktrace(struct Client *source_p, rb_dlink_list *list, sendto_one(source_p, form_str(RPL_ETRACE), me.name, source_p->name, - IsOper(target_p) ? "Oper" : "User", + SeesOper(target_p, source_p) ? "Oper" : "User", /* class field -- pretend its server.. */ target_p->servptr->name, target_p->name, target_p->username, target_p->host, diff --git a/modules/m_stats.c b/modules/m_stats.c index 673d2212..af433146 100644 --- a/modules/m_stats.c +++ b/modules/m_stats.c @@ -830,7 +830,7 @@ stats_operedup (struct Client *source_p) { target_p = oper_ptr->data; - if(IsOperInvis(target_p) && !IsOper(source_p)) + if(!SeesOper(target_p, source_p)) continue; if(target_p->user->away) diff --git a/modules/m_trace.c b/modules/m_trace.c index 38550667..1baf2bd7 100644 --- a/modules/m_trace.c +++ b/modules/m_trace.c @@ -204,6 +204,9 @@ m_trace(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_ if(!doall && wilds && (match(tname, target_p->name) == 0)) continue; + if(!SeesOper(target_p, source_p)) + continue; + report_this_status(source_p, target_p); } @@ -233,14 +236,14 @@ m_trace(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_ target_p = ptr->data; /* dont show invisible users to remote opers */ - if(IsInvisible(target_p) && dow && !MyConnect(source_p) && !IsOper(target_p)) + if(IsInvisible(target_p) && dow && !MyConnect(source_p) && !SeesOper(target_p, source_p)) continue; if(!doall && wilds && !match(tname, target_p->name)) continue; /* remote opers may not see invisible normal users */ - if(dow && !MyConnect(source_p) && !IsOper(target_p) && + if(dow && !MyConnect(source_p) && !SeesOper(target_p, source_p) && IsInvisible(target_p)) continue; @@ -379,8 +382,8 @@ report_this_status(struct Client *source_p, struct Client *target_p) case STAT_CLIENT: { sendto_one_numeric(source_p, - IsOper(target_p) ? RPL_TRACEOPERATOR : RPL_TRACEUSER, - IsOper(target_p) ? form_str(RPL_TRACEOPERATOR) : form_str(RPL_TRACEUSER), + SeesOper(target_p, source_p) ? RPL_TRACEOPERATOR : RPL_TRACEUSER, + SeesOper(target_p, source_p) ? form_str(RPL_TRACEOPERATOR) : form_str(RPL_TRACEUSER), class_name, name, show_ip(source_p, target_p) ? ip : empty_sockhost, (unsigned long)(rb_current_time() - target_p->localClient->lasttime), diff --git a/modules/m_userhost.c b/modules/m_userhost.c index 76e6cd17..6b0a9ac1 100644 --- a/modules/m_userhost.c +++ b/modules/m_userhost.c @@ -33,6 +33,7 @@ #include "parse.h" #include "modules.h" #include "s_conf.h" +#include "s_newconf.h" static const char userhost_desc[] = "Provides the USERHOST command to show a user's host"; @@ -85,7 +86,7 @@ m_userhost(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sour { rl = sprintf(response, "%s%s=%c%s@%s ", target_p->name, - IsOper(target_p) ? "*" : "", + SeesOper(target_p, source_p) ? "*" : "", (target_p->user->away) ? '-' : '+', target_p->username, target_p->sockhost); @@ -94,7 +95,7 @@ m_userhost(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sour { rl = sprintf(response, "%s%s=%c%s@%s ", target_p->name, - IsOper(target_p) ? "*" : "", + SeesOper(target_p, source_p) ? "*" : "", (target_p->user->away) ? '-' : '+', target_p->username, target_p->host); } diff --git a/modules/m_who.c b/modules/m_who.c index aa674582..b7198a65 100644 --- a/modules/m_who.c +++ b/modules/m_who.c @@ -218,7 +218,7 @@ m_who(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, /* '/who nick' */ if(((target_p = find_named_person(mask)) != NULL) && - (!server_oper || IsOper(target_p))) + (!server_oper || SeesOper(target_p, source_p))) { int isinvis = 0; @@ -314,7 +314,7 @@ who_common_channel(struct Client *source_p, struct Channel *chptr, if(!IsInvisible(target_p) || IsMarked(target_p)) continue; - if(server_oper && !IsOper(target_p)) + if(server_oper && !SeesOper(target_p, source_p)) continue; SetMark(target_p); @@ -387,7 +387,7 @@ who_global(struct Client *source_p, const char *mask, int server_oper, int opers continue; } - if(server_oper && !IsOper(target_p)) + if(server_oper && !SeesOper(target_p, source_p)) continue; if(maxmatches > 0) @@ -435,7 +435,7 @@ do_who_on_channel(struct Client *source_p, struct Channel *chptr, msptr = ptr->data; target_p = msptr->client_p; - if(server_oper && !IsOper(target_p)) + if(server_oper && !SeesOper(target_p, source_p)) continue; if(member || !IsInvisible(target_p)) @@ -488,7 +488,7 @@ do_who(struct Client *source_p, struct Client *target_p, struct membership *mspt const char *q; sprintf(status, "%c%s%s", - target_p->user->away ? 'G' : 'H', IsOper(target_p) ? "*" : "", msptr ? find_channel_status(msptr, fmt->fields || IsCapable(source_p, CLICAP_MULTI_PREFIX)) : ""); + target_p->user->away ? 'G' : 'H', SeesOper(target_p, source_p) ? "*" : "", msptr ? find_channel_status(msptr, fmt->fields || IsCapable(source_p, CLICAP_MULTI_PREFIX)) : ""); if (fmt->fields == 0) sendto_one(source_p, form_str(RPL_WHOREPLY), me.name, diff --git a/modules/m_whois.c b/modules/m_whois.c index 594656ee..d3384ed3 100644 --- a/modules/m_whois.c +++ b/modules/m_whois.c @@ -309,7 +309,7 @@ single_whois(struct Client *source_p, struct Client *target_p, int operspy) sendto_one_numeric(source_p, RPL_AWAY, form_str(RPL_AWAY), target_p->name, target_p->user->away); - if(IsOper(target_p) && (!ConfigFileEntry.hide_opers_in_whois || IsOper(source_p))) + if((!ConfigFileEntry.hide_opers_in_whois || IsOper(source_p)) && SeesOper(target_p, source_p)) { sendto_one_numeric(source_p, RPL_WHOISOPERATOR, form_str(RPL_WHOISOPERATOR), target_p->name,