diff --git a/doc/ircd.conf.example b/doc/ircd.conf.example index 4de004bd..705a0d6d 100644 --- a/doc/ircd.conf.example +++ b/doc/ircd.conf.example @@ -236,7 +236,7 @@ auth { * means they must be defined before operator {}. */ privset "local_op" { - privs = oper:general, auspex:oper, oper:local_kill, oper:operwall; + privs = oper:general, auspex:oper, oper:privs, oper:local_kill, oper:operwall; }; privset "server_bot" { diff --git a/doc/reference.conf b/doc/reference.conf index 3b0a5d54..6a268613 100644 --- a/doc/reference.conf +++ b/doc/reference.conf @@ -433,6 +433,7 @@ privset "local_op" { * oper:general: enable most general oper privileges that came * with +o in older releases * auspex:oper: allows the oper to see through oper hiding + * oper:privs: allows /stats o/O and seeing privset in /whois * oper:local_kill: allows local users to be /KILL'd * oper:global_kill: allows local and remote users to be /KILL'd * oper:routing: allows remote SQUIT and CONNECT @@ -458,7 +459,7 @@ privset "local_op" { * oper:mass_notice: allows sending wallops and mass notices * oper:grant: allows using the GRANT command */ - privs = oper:general, auspex:oper, oper:local_kill, oper:operwall; + privs = oper:general, auspex:oper, oper:privs, oper:local_kill, oper:operwall; }; privset "server_bot" { diff --git a/modules/m_privs.c b/modules/m_privs.c index fff49a85..29e141ae 100644 --- a/modules/m_privs.c +++ b/modules/m_privs.c @@ -177,6 +177,13 @@ mo_privs(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source } } + if (target_p != source_p && !HasPrivilege(source_p, "oper:privs")) + { + sendto_one(source_p, form_str(ERR_NOPRIVS), + me.name, source_p->name, "privs"); + return; + } + if (!IsServer(server_p)) server_p = server_p->servptr; diff --git a/modules/m_stats.c b/modules/m_stats.c index 03a70d6a..bc4ed1db 100644 --- a/modules/m_stats.c +++ b/modules/m_stats.c @@ -789,7 +789,7 @@ stats_oper(struct Client *source_p) sendto_one_numeric(source_p, RPL_STATSOLINE, form_str(RPL_STATSOLINE), oper_p->username, oper_p->host, oper_p->name, - IsOperGeneral(source_p) ? oper_p->privset->name : "0", "-1"); + HasPrivilege(source_p, "oper:privs") ? oper_p->privset->name : "0", "-1"); } } @@ -810,6 +810,13 @@ stats_capability(struct Client *client_p) static void stats_privset(struct Client *source_p) { + if (!HasPrivilege(source_p, "oper:privs")) + { + sendto_one(source_p, form_str(ERR_NOPRIVS), + me.name, source_p->name, "privs"); + return; + } + privilegeset_report(source_p); } diff --git a/modules/m_whois.c b/modules/m_whois.c index b0ca2c2a..a45b67c0 100644 --- a/modules/m_whois.c +++ b/modules/m_whois.c @@ -318,7 +318,7 @@ single_whois(struct Client *source_p, struct Client *target_p, int operspy) GlobalSetOptions.operstring)); } - if(!EmptyString(target_p->user->opername) && IsOper(target_p) && IsOper(source_p)) + if(!EmptyString(target_p->user->opername) && IsOper(target_p) && (target_p == source_p || HasPrivilege(source_p, "oper:privs"))) { char buf[512]; const char *privset = "(missing)";