opers: enforce the per-type usermode/chanmode allowlist

The usermodes=/chanmodes= class/type keys were parsed then ignored. Add a
ModeAllow allowlist to the resolved oper type + can_use_mode(), checked in
the oper-only mode handlers (services under mode_sudo pass through).
Unspecified stays permissive so built-in types are unrestricted; a type
opts into restriction with an explicit letter list (or * = all).
This commit is contained in:
Jean Chevronnet 2026-08-29 02:17:32 +00:00
parent bc412c218e
commit e2a64b7806
No known key found for this signature in database
GPG key ID: 439666D63A9477E4
3 changed files with 137 additions and 8 deletions

View file

@ -92,12 +92,19 @@ oper {
#
# A class also grants privileges — named permissions checked at sensitive points.
# "privs=*" grants all. Standard privileges:
# users/auspex see a user's real host+IP and geo (WHOIS/WHO + the connect
# notice), and see +i users who share no channel with you
# channels/auspex see secret/private (+s/+p) channels in LIST/WHO/WHOIS
# Only netadmin holds all privileges by default; grant the built-in "auspex" class to
# any other type that should see through privacy.
# class { name "helpdesk"; commands "CHECK"; snomasks "c"; privs "users/auspex"; }
# users/auspex real host+IP and geo (WHOIS/WHO + connect notice), +i users
# channels/auspex secret/private (+s/+p) channels in LIST/WHO/WHOIS
# servers/auspex services (U-lined) servers hidden by hideservices
# channels/override join through +k/+b/+i/+l/+z/+R/+J, CBAN and the max-chans cap
# users/flood exempt from message- and join-flood limits
# users/ignore-commonchans PM a +c user without sharing a common channel
# Only netadmin holds every privilege by default. Built-in "auspex" grants the auspex
# trio; "override" grants channels/override + users/flood.
#
# usermodes="…"/chanmodes="…" restrict which oper-only modes the type may SET (a letter
# list, or "*" for all). Unspecified = all, so built-ins are unrestricted. ("modes" is
# separate: the usermodes auto-applied at oper-up.)
# class { name "helpdesk"; commands "CHECK"; snomasks "c"; privs "users/auspex"; usermodes "s"; }
# opertype { name "helpdesk"; classes "helpdesk auspex"; modes "+ih"; title "Help_Desk"; level 15; }