From: Kevin L. Mitchell Date: Sat, 16 Dec 2000 08:20:48 +0000 (+0000) Subject: Author: Kev X-Git-Url: http://git.pk910.de/?a=commitdiff_plain;h=9ba21beb4e8832a9a4f7355c096af81637bfa3df;p=ircu2.10.12-pk.git Author: Kev Log message: Implement an ACL for IRC operators; set ACL out of information provided by the .conf through the feature system. Testing: It's been tested on one server all by its lonesome, and seems to work fine; it needs to be rigorously tested on a network with other users, and by both local and global operators, with various fiddling of the /set's. This big a change to the privileges structure can lead to interesting anomolies. Unfortunately, documentation is sparse; I'll look into correcting that when I can, but don't hold your breath. git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@344 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- diff --git a/ChangeLog b/ChangeLog index 1f0909d..674ba51 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,99 @@ +2000-12-16 Kevin L. Mitchell + + * ircd/whocmds.c (do_who): use HasPriv to determine whether or not + to indicate a user is an oper + + * ircd/s_user.c: clear privileges setting when deopping; don't + propagate +o unless user has PRIV_PROPAGATE privilege + + * ircd/s_debug.c (debug_serveropts): created debug_serveropts() + function and replaced how the server option string is generated + + * ircd/parse.c: remove conditional on CONFIG_OPERCMDS + + * ircd/m_whois.c (do_whois): use HasPriv to determine whether or + not to indicate the user is an operator + + * ircd/m_who.c: use HasPriv to determine whether or not a user + should be displayed in the list of opers + + * ircd/m_version.c: call debug_serveropts() to get server option + string + + * ircd/m_userip.c (userip_formatter): use HasPriv to determine + whether or not to show oper status + + * ircd/m_userhost.c (userhost_formatter): use HasPriv to determine + whether or not to show oper status + + * ircd/m_restart.c (mo_restart): replace ugly #ifdef conditional + checks with HasPriv check; remove dead code + + * ircd/m_rehash.c (mo_rehash): replace ugly #ifdef conditional + checks with HasPriv check + + * ircd/m_opmode.c (mo_opmode): use HasPriv to check permissions; + use feature_bool to check if disabled + + * ircd/m_oper.c (m_oper): set oper priviliges + + * ircd/m_mode.c (m_mode): replace #ifdef conditional with HasPriv + check + + * ircd/m_kill.c (mo_kill): use HasPriv checks to determine if we + can kill + + * ircd/m_kick.c (m_kick): replace #ifdef conditional with HasPriv + check + + * ircd/m_jupe.c (mo_jupe): rework permissions checking structure; + use feature_bool to check if disabled + + * ircd/m_join.c (m_join): remove BADCHAN conditional; replace + #ifdef conditional with a HasPriv check + + * ircd/m_gline.c (mo_gline): rework permissions checking + structure; use feature_bool to check if any part is disabled + + * ircd/m_die.c: replace ugly #ifdef conditionals with HasPriv + check; remove dead code + + * ircd/m_clearmode.c: use feature_bool() to detect if we're + disabled; use HasPriv to figure out what we're permitted to do; + only allow clearmode on moded channels + + * ircd/ircd_features.c: define various features; use HasPriv to + verify permissions to set/reset + + * ircd/gline.c (gline_add): use HasPriv instead of #ifdef + conditionals + + * ircd/client.c (client_set_privs): function to set an oper's + privileges + + * ircd/channel.c: use HasPriv calls instead of #ifdef conditionals + + * include/whocmds.h: deconditionalize several macros and + substitute appropriate calls to HasPriv() + + * include/s_debug.h: get rid of global serveropts[]; define new + function debug_serveropts() to build that string on the fly + + * include/ircd_features.h: define some features + + * include/client.h: add privs member to struct Connection; define + various priviledges + + * include/channel.h: no longer using IsOperOnLocalChannel; remove + conditional of MAGIC_OPER_OVERRIDE on OPER_WALK_THROUGH_LMODES + + * doc/Configure.help: remove help information for deprecated + options + + * config/config-sh.in: remove certain deprecated options having to + do with what opers can and cannot do--first stage in moving + compile-time constants into the .conf + 2000-12-16 Isomer * ircd/parse.c: detect if the prefix is missing and try and recover instead of coring. diff --git a/config/config-sh.in b/config/config-sh.in index bf2c430..d464cd8 100644 --- a/config/config-sh.in +++ b/config/config-sh.in @@ -225,19 +225,6 @@ comment 'Paths and files' string 'File for server pid' PPATH 'ircd.pid' endmenu -mainmenu_option next_comment -comment 'Logging (filenames are either full paths or files within DPATH)' - -comment 'Bad Channel G-Lines allow operators to add channel masks to a list which prohibits local clients from being able joining channels which match the mask. Remote BadChan Glines allow Uworld to add or remove channels from the servers internal list of badchans' - bool 'Do you want to enable Bad Channel G-lines' BADCHAN y - if [ "$BADCHAN" = "y" ]; then - echo " " - echo " WARNING DO _NOT_ USE LOCAL BADCHANNEL GLINES ON UNDERNET" - echo " Use of LOCAL BAD Channel G-Lines can be cause for REMOVAL" - bool 'Allow LOCAL BAD Channel G-lines' LOCAL_BADCHAN - fi -endmenu - mainmenu_option next_comment comment 'Configuration' bool 'Use crypted passwords for operators' CRYPT_OPER_PASSWORD y @@ -267,34 +254,6 @@ comment 'Configuration' bool 'Kill connecting clients when forward and reverse DNS mismatch' KILL_IPMISMATCH n endmenu -mainmenu_option next_comment -comment 'Oper commands' - bool 'Allow (local) Opers to see all local invisible users' SHOW_INVISIBLE_USERS y - if [ "$SHOW_INVISIBLE_USERS" = "y" ]; then - bool 'Allow Opers to see all invisible users' SHOW_ALL_INVISIBLE_USERS y - fi - bool 'Allow global Opers (O:) to see inside secret channels' OPERS_SEE_IN_SECRET_CHANNELS y - if [ "$OPERS_SEE_IN_SECRET_CHANNELS" = "y" ]; then - bool 'Allow local Opers (o:) to see inside secret channels' LOCOP_SEE_IN_SECRET_CHANNELS n - fi - bool 'Do not truncate obnoxiously long /who output for opers' UNLIMIT_OPER_QUERY - bool 'Allow Opers to use the KILL command' OPER_KILL y - bool 'Allow Opers to use the REHASH command' OPER_REHASH y - bool 'Allow Opers to use the RESTART command' OPER_RESTART y - bool 'Allow Opers to use the DIE command' OPER_DIE y - bool 'Allow Opers to add local G-lines' OPER_LGLINE y - bool 'Allow Opers to connect from a remote site' OPER_REMOTE y - bool 'Allow local opers to use the REHASH command' LOCOP_REHASH y - bool 'Allow local opers to use the RESTART command' LOCOP_RESTART - bool 'Allow local opers to use the DIE command' LOCOP_DIE - bool 'Allow local opers to add local G-lines' LOCOP_LGLINE y - bool 'Allow local/global opers to be on any number of channels' OPER_NO_CHAN_LIMIT y - bool 'Allow local/global opers to set modes on local channels' OPER_MODE_LCHAN y - bool 'Allow local/global opers to walk through local channels modes' OPER_WALK_THROUGH_LMODES n - bool 'Prevent local/global opers from being kicked or deoped on local channels' NO_OPER_DEOP_LCHAN n - -endmenu - mainmenu_option next_comment comment 'Server characteristics' bool 'Do you want to have a default LIST parameter' CONFIG_LIST y @@ -312,11 +271,6 @@ endmenu mainmenu_option next_comment comment 'Mandatory defines (you should leave these untouched)' int 'Max auto connects per class (1!)' MAXIMUM_LINKS 1 - if [ "$OPER_KILL" = "y" ]; then - bool 'Only allow KILLs of local clients' LOCAL_KILL_ONLY - else - define_bool LOCAL_KILL_ONLY $LOCAL_KILL_ONLY - fi int 'KILL nick chase time limit (30)' KILLCHASETIMELIMIT 30 int 'Max number of channels per user' MAXCHANNELSPERUSER 10 int 'Max number of silence masks (15!)' MAXSILES 15 @@ -331,8 +285,3 @@ comment 'Mandatory defines (you should leave these untouched)' int 'connect(2) timeout (90!)' CONNECTTIMEOUT 90 int 'Max send queue (40000)' DEFAULTMAXSENDQLENGTH 40000 endmenu - -mainmenu_option next_comment -comment 'Experimental options (Do you know what you'\''re doing?)' - bool 'Use new oper commands (JUPE, CLEARMODE, OPMODE, GLINE)' CONFIG_OPERCMDS y -endmenu diff --git a/doc/Configure.help b/doc/Configure.help index e4b979b..d66b16e 100644 --- a/doc/Configure.help +++ b/doc/Configure.help @@ -628,119 +628,6 @@ R_LINES_OFTEN Note that this is -very- likely to cause a severe drain on your resources. Use at your own risk, specify 'n' unless your really sure. -Allow (local) Opers to see all local invisible users -SHOW_INVISIBLE_USERS - If you specify 'y' here, then your (local) IRC Operators will be able to - see all local invisible users (clients connected to your own server). - The reason for this is to hunt for clone bots, make sure your Operators do - not use this "feature" for spying on individuals and respect the user that - wishes to be invisible (mostly meaning that they don't want to be found when - on certain channels). - Note: If you answer 'n' here, then you will also not be able to see remote - invisible users (if you specify 'y' you will also get a configuration - question that asks you to specify whether or not you want your Opers to see - remote invisible users or not). - -Allow Opers to see all invisible users -SHOW_ALL_INVISIBLE_USERS - If you specify 'y' here, then your global IRC Operators (O:) will be able - to see ALL invisible users. The reason for this is to hunt for clone bots, - make sure your Operators do not use this "feature" for spying on individuals - and respect the user that wishes to be invisible (mostly meaning that they - don't want to be found when on certain channels). - -Allow global Opers (O:) to see inside secret channels -OPERS_SEE_IN_SECRET_CHANNELS - If you specify 'y' here, then your global IRC Operators (O:) will be able - to see who is on a specified, secret channel, without joining themselfs. - This can be needed to make a reasonable judgement in the case of a "channel - takeover" being reported, while the channel is set invite only. - See doc/readme.who for more details. - -Allow local Opers (o:) to see inside secret channels -LOCOP_SEE_IN_SECRET_CHANNELS - If you specify 'y' here, then your local IRC Operators (o:) will be able - to see who is on a specified, secret channel, without joining themselfs. - This can be needed to make a reasonable judgement in the case of a "channel - takeover" being reported, while the channel is set invite only. - See doc/readme.who for more details. - If unsure, specify 'n'. - -Don't truncate obnoxiously long /who output for opers -UNLIMIT_OPER_QUERY - A /who command can sometimes return several hundred lines of info. To - reduce flooding and sending too much, the output is truncated. By - answering 'y' to this, when an IRC Operator uses /who, the output will - not be truncated, no matter how much data is returned. - -Allow Opers to use the KILL command -OPER_KILL - You can select 'n' if you don't think operators should be able - to use the KILL command, and wish to prevent your operators from - using it. This will not, however, prevent operators on other - servers from issuing KILLs to your clients. You probably want to - select 'y' for this unless you really really don't think KILL - should -ever- be used by an operator. - -Allow Opers to use the REHASH command -OPER_REHASH - Allows operators to use the REHASH command to reload the servers - configuration file (ircd.conf) if you select 'n', you can still - reload the configuration file with a unix command, - kill -HUP `cat ircd.pid`. If unsure, select 'y'. - -Allow Opers to use the RESTART command -OPER_RESTART - Allows an operator to use the RESTART command to cause the server - to restart, using the ircd executable in SPATH. If unsure, select 'y'. - -Allow Opers to use the DIE command -OPER_DIE - Allows an operator to use the DIE command to shutdown the server - online. If you select 'n' you will need to send the server a kill - signal to shutdown the server. If unsure, select 'y'. - -Allow Opers to add local G-lines -OPER_LGLINE - Allows operators to add local G-lines with the GLINE command. This is - like a *local* KILL, except that the user being killed can't immediately - reconnect: He will have to wait for the G-line to expire. - The reason for adding this is that a KILL is rather useless for removing - (or 'warning') abusers (it is still THE command to remove ghosts and - a-like, the reason KILL was added in the first place). However, adding - G-lines for a dynamic IP with expire times larger then 10 minutes is highly - discouraged: The user will already have dialed in via another IP or account - and the G-line would only harm other, innocent, users. - -Allow Opers to connect from a remote site -OPER_REMOTE - If you select 'n' for this, clients must be on the 'same network' as - the server in order to gain oper privledges. If you're not sure, just - select 'y'. - -Allow local opers to use the REHASH command -LOCOP_REHASH - Allows a local operator (defined by a lowercase o:line in ircd.conf) - to cause the server to reload its configuration file (ircd.conf) with - the REHASH command. If unsure, select 'n'. - -Allow local opers to use the RESTART command -LOCOP_RESTART - Allows a local operator (defined by a lowercase o:line in ircd.conf) - to use the RESTART command. If unsure, select 'n'. - -Allow local opers to use the DIE command -LOCOP_DIE - Allows a local operator (defined by a lowercase o:line in ircd.conf) - to use the DIE command. If unsure, select 'n'. - -Allow local opers to add local G-lines -LOCOP_LGLINE - Allows a local operator (defined by a lowercase o:line in ircd.conf) - to add local G-lines with the GLINE command. This is like a *local* KILL, - except that the user being killed can't immediately reconnect: He will - have to wait for the G-line to expire. - Do you want to have a default LIST parameter CONFIG_LIST Pre-Undernet, the LIST command could either be given with one channel @@ -827,14 +714,6 @@ MSGLOG_SIZE of _static_ memory! Recommended value is 128. You must include this even if you selected 'n' for MSGLOG_ENABLED. -Only allow KILLs of local clients -LOCAL_KILL_ONLY - This only allows operators of this server to KILL clients directly connected - to this server. Operators will not be able to issue KILLs for clients on - other servers. Some networks (not Undernet) require that this be defined - for newly linking servers, but if you haven't been told to do otherwise, - specify 'n' here. - Max server idle time (60) TIMESEC This is the maximum idle time for the server. If no messages are received @@ -937,11 +816,3 @@ DEFAULTMAXSENDQLENGTH (see doc/example.conf for details on Y: lines). You will probably always override this value in your "ircd.conf" with the Y: lines. The given value used to be an often used value for client sendqs. - -Use new oper commands (JUPE, CLEARMODE, OPMODE, GLINE) -CONFIG_OPERCMDS - Several new oper-only commands were added to the server source - during the Uworld integration project. Until all servers are - upgraded to versions that understand the new server<->server - traffic, they must remain disabled, however. This option activates - the client-side part of those changes. diff --git a/include/channel.h b/include/channel.h index b59b402..5655487 100644 --- a/include/channel.h +++ b/include/channel.h @@ -116,12 +116,6 @@ struct Client; #define IsChannelName(name) (*(name) == '#' || \ IsModelessChannel(name) || IsLocalChannel(name)) -/* - * Check if a sptr is an oper, and chptr is a local channel. - */ -#define IsOperOnLocalChannel(sptr,chname) \ - ((IsAnOper(sptr)) && (IsLocalChannel(chname))) - typedef enum ChannelGetType { CGT_NO_CREATE, CGT_CREATE @@ -153,12 +147,10 @@ typedef enum ChannelGetType { */ #define MAGIC_REMOTE_JOIN_TS 1270080000 -#ifdef OPER_WALK_THROUGH_LMODES /* * used in can_join to determine if an oper forced a join on a channel */ #define MAGIC_OPER_OVERRIDE 1000 -#endif extern const char* const PartFmt1; diff --git a/include/client.h b/include/client.h index 3bbce51..910ee6e 100644 --- a/include/client.h +++ b/include/client.h @@ -138,6 +138,7 @@ struct Client { struct in_addr cli_ip; /* Real ip# NOT defined for remote servers! */ short cli_status; /* Client type */ unsigned char cli_local; /* local or remote client */ + unsigned int cli_privs; /* Oper privileges */ char cli_name[HOSTLEN + 1]; /* Unique name of the client, nick or host */ char cli_username[USERLEN + 1]; /* username here now for auth stuff */ char cli_info[REALLEN + 1]; /* Free form additional client information */ @@ -162,6 +163,7 @@ struct Client { #define cli_ip(cli) ((cli)->cli_ip) #define cli_status(cli) ((cli)->cli_status) #define cli_local(cli) ((cli)->cli_local) +#define cli_privs(cli) ((cli)->cli_privs) #define cli_name(cli) ((cli)->cli_name) #define cli_username(cli) ((cli)->cli_username) #define cli_info(cli) ((cli)->cli_info) @@ -403,6 +405,37 @@ struct Client { #define SNO_OPER (SNO_CONNEXIT|SNO_OLDREALOP) #define SNO_NOISY (SNO_SERVKILL|SNO_UNAUTH) +#define PRIV_CHAN_LIMIT 0x00000001 /* no channel limit on oper */ +#define PRIV_MODE_LCHAN 0x00000002 /* oper can mode local chans */ +#define PRIV_WALK_LCHAN 0x00000004 /* oper can walk thru local modes */ +#define PRIV_DEOP_LCHAN 0x00000008 /* no deop oper on local chans */ +#define PRIV_SHOW_INVIS 0x00000010 /* show local invisible users */ +#define PRIV_SHOW_ALL_INVIS 0x00000020 /* show all invisible users */ +#define PRIV_UNLIMIT_QUERY 0x00000040 /* unlimit who queries */ + +#define PRIV_KILL 0x00000080 /* oper can KILL */ +#define PRIV_LOCAL_KILL 0x00000100 /* oper can local KILL */ +#define PRIV_REHASH 0x00000200 /* oper can REHASH */ +#define PRIV_RESTART 0x00000400 /* oper can RESTART */ +#define PRIV_DIE 0x00000800 /* oper can DIE */ +#define PRIV_GLINE 0x00001000 /* oper can GLINE */ +#define PRIV_LOCAL_GLINE 0x00002000 /* oper can local GLINE */ +#define PRIV_JUPE 0x00004000 /* oper can JUPE */ +#define PRIV_LOCAL_JUPE 0x00008000 /* oper can local JUPE */ +#define PRIV_OPMODE 0x00010000 /* oper can OP/CLEARMODE */ +#define PRIV_LOCAL_OPMODE 0x00020000 /* oper can local OP/CLEARMODE */ +#define PRIV_SET 0x00040000 /* oper can SET */ +#define PRIV_WHOX 0x00080000 /* oper can use /who x */ +#define PRIV_BADCHAN 0x00100000 /* oper can BADCHAN */ +#define PRIV_LOCAL_BADCHAN 0x00200000 /* oper can local BADCHAN */ +#define PRIV_SEE_CHAN 0x00400000 /* oper can see in secret chans */ + +#define PRIV_PROPAGATE 0x00800000 /* propagate oper status */ +#define PRIV_DISPLAY 0x01000000 /* "Is an oper" displayed */ +#define PRIV_SEE_OPERS 0x02000000 /* display hidden opers */ + +#define HasPriv(cli, priv) (cli_privs(cli) & (priv)) + typedef enum ShowIPType { HIDE_IP, SHOW_IP, @@ -414,6 +447,7 @@ extern int client_get_ping(const struct Client* local_client); extern void client_drop_sendq(struct Connection* con); extern void client_add_sendq(struct Connection* con, struct Connection** con_p); +extern void client_set_privs(struct Client* client); #endif /* INCLUDED_client_h */ diff --git a/include/ircd_features.h b/include/ircd_features.h index e76140e..2335fa6 100644 --- a/include/ircd_features.h +++ b/include/ircd_features.h @@ -25,6 +25,41 @@ struct Client; enum Feature { FEAT_LOG, + + FEAT_OPER_NO_CHAN_LIMIT, + FEAT_OPER_MODE_LCHAN, + FEAT_OPER_WALK_THROUGH_LMODES, + FEAT_NO_OPER_DEOP_LCHAN, + FEAT_SHOW_INVISIBLE_USERS, + FEAT_SHOW_ALL_INVISIBLE_USERS, + FEAT_UNLIMIT_OPER_QUERY, + FEAT_LOCAL_KILL_ONLY, + FEAT_CONFIG_OPERCMDS, + + FEAT_OPER_KILL, + FEAT_OPER_REHASH, + FEAT_OPER_RESTART, + FEAT_OPER_DIE, + FEAT_OPER_GLINE, + FEAT_OPER_LGLINE, + FEAT_OPER_JUPE, + FEAT_OPER_LJUPE, + FEAT_OPER_OPMODE, + FEAT_OPER_LOPMODE, + FEAT_OPER_BADCHAN, + FEAT_OPER_LBADCHAN, + FEAT_OPERS_SEE_IN_SECRET_CHANNELS, + + FEAT_LOCOP_KILL, + FEAT_LOCOP_REHASH, + FEAT_LOCOP_RESTART, + FEAT_LOCOP_DIE, + FEAT_LOCOP_LGLINE, + FEAT_LOCOP_LJUPE, + FEAT_LOCOP_LOPMODE, + FEAT_LOCOP_LBADCHAN, + FEAT_LOCOP_SEE_IN_SECRET_CHANNELS, + FEAT_LAST_F }; diff --git a/include/s_debug.h b/include/s_debug.h index 8eefe1f..a707a71 100644 --- a/include/s_debug.h +++ b/include/s_debug.h @@ -56,8 +56,8 @@ extern void send_usage(struct Client *cptr, char *nick); #endif /* !DEBUGMODE */ +extern const char* debug_serveropts(void); extern void debug_init(int use_tty); extern void count_memory(struct Client *cptr, char *nick); -extern char serveropts[]; #endif /* INCLUDED_s_debug_h */ diff --git a/include/whocmds.h b/include/whocmds.h index e02358a..247f6c5 100644 --- a/include/whocmds.h +++ b/include/whocmds.h @@ -44,33 +44,13 @@ struct Channel; #define IS_VISIBLE_USER(s,ac) ((s==ac) || (!IsInvisible(ac))) -#if defined(SHOW_INVISIBLE_LUSERS) || defined(SHOW_ALL_INVISIBLE_USERS) -#define SEE_LUSER(s, ac, b) (IS_VISIBLE_USER(s, ac) || ((b & WHOSELECT_EXTRA) && MyConnect(ac) && IsAnOper(s))) -#else -#define SEE_LUSER(s, ac, b) (IS_VISIBLE_USER(s, ac)) -#endif +#define SEE_LUSER(s, ac, b) (IS_VISIBLE_USER(s, ac) || ((b & WHOSELECT_EXTRA) && MyConnect(ac) && HasPriv((s), PRIV_SHOW_INVIS | PRIV_SHOW_ALL_INVIS))) -#ifdef SHOW_ALL_INVISIBLE_USERS -#define SEE_USER(s, ac, b) (SEE_LUSER(s, ac, b) || ((b & WHOSELECT_EXTRA) && IsOper(s))) -#else -#define SEE_USER(s, ac, b) (SEE_LUSER(s, ac, b)) -#endif +#define SEE_USER(s, ac, b) (SEE_LUSER(s, ac, b) || ((b & WHOSELECT_EXTRA) && HasPriv((s), PRIV_SHOW_ALL_INVIS))) -#ifdef UNLIMIT_OPER_QUERY -#define SHOW_MORE(sptr, counter) (IsAnOper(sptr) || (!(counter-- < 0)) ) -#else -#define SHOW_MORE(sptr, counter) (!(counter-- < 0)) -#endif +#define SHOW_MORE(sptr, counter) (HasPriv(sptr, PRIV_UNLIMIT_QUERY) || (!(counter-- < 0)) ) -#ifdef OPERS_SEE_IN_SECRET_CHANNELS -#ifdef LOCOP_SEE_IN_SECRET_CHANNELS -#define SEE_CHANNEL(s, chptr, b) (!SecretChannel(chptr) || ((b & WHOSELECT_EXTRA) && IsAnOper(s))) -#else -#define SEE_CHANNEL(s, chptr, b) (!SecretChannel(chptr) || ((b & WHOSELECT_EXTRA) && IsOper(s))) -#endif -#else -#define SEE_CHANNEL(s, chptr, b) (!SecretChannel(chptr)) -#endif +#define SEE_CHANNEL(s, chptr, b) (!SecretChannel(chptr) || ((b & WHOSELECT_EXTRA) && HasPriv((s), PRIV_SEE_CHAN))) #define MAX_WHOIS_LINES 50 diff --git a/ircd/channel.c b/ircd/channel.c index 68d7a86..114deb0 100644 --- a/ircd/channel.c +++ b/ircd/channel.c @@ -1053,15 +1053,12 @@ int can_join(struct Client *sptr, struct Channel *chptr, char *key) if (lp->value.chptr == chptr) return 0; -#ifdef OPER_WALK_THROUGH_LMODES /* An oper can force a join on a local channel using "OVERRIDE" as the key. a HACK(4) notice will be sent if he would not have been supposed to join normally. */ - if (IsOperOnLocalChannel(sptr,chptr->chname) && !BadPtr(key) && compall("OVERRIDE",key) == 0) - { + if (IsLocalChannel(chptr->chname) && HasPriv(sptr, PRIV_WALK_LCHAN) && + !BadPtr(key) && compall("OVERRIDE",key) == 0) overrideJoin = MAGIC_OPER_OVERRIDE; - } -#endif if (chptr->mode.mode & MODE_INVITEONLY) return overrideJoin + ERR_INVITEONLYCHAN; @@ -2386,17 +2383,15 @@ mode_process_clients(struct ParseState *state) } } -#ifdef NO_OPER_DEOP_LCHAN /* don't allow local opers to be deopped on local channels */ if (MyUser(state->sptr) && state->cli_change[i].client != state->sptr && - IsOperOnLocalChannel(state->cli_change[i].client, - state->chptr->chname)) { + IsLocalChannel(state->chptr->chname) && + HasPriv(state->cli_change[i].client, PRIV_DEOP_LCHAN)) { send_reply(state->sptr, ERR_ISOPERLCHAN, cli_name(state->cli_change[i].client), state->chptr->chname); continue; } -#endif } /* accumulate the change */ diff --git a/ircd/client.c b/ircd/client.c index 317efc7..33d45ee 100644 --- a/ircd/client.c +++ b/ircd/client.c @@ -21,6 +21,7 @@ #include "client.h" #include "class.h" #include "ircd.h" +#include "ircd_features.h" #include "ircd_reply.h" #include "list.h" #include "numeric.h" @@ -92,3 +93,103 @@ void client_add_sendq(struct Connection* con, struct Connection** con_p) *con_p = con; } } + +/* client_set_privs(struct Client* client) + * + * Sets the privileges for opers. + */ +void +client_set_privs(struct Client* client) +{ + unsigned int privs = 0; + unsigned int antiprivs = 0; + + if (!IsAnOper(client)) { + cli_privs(client) = 0; /* clear privilege mask */ + return; + } else if (!MyConnect(client)) { + cli_privs(client) = ~(PRIV_SET); /* everything but set... */ + return; + } + + /* This sequence is temporary until the .conf is carefully rewritten */ + + privs |= (PRIV_WHOX | PRIV_DISPLAY); + if (feature_bool(FEAT_OPER_NO_CHAN_LIMIT)) + privs |= PRIV_CHAN_LIMIT; + if (feature_bool(FEAT_OPER_MODE_LCHAN)) + privs |= (PRIV_MODE_LCHAN | PRIV_LOCAL_OPMODE); + if (feature_bool(FEAT_OPER_WALK_THROUGH_LMODES)) + privs |= PRIV_WALK_LCHAN; + if (feature_bool(FEAT_NO_OPER_DEOP_LCHAN)) + privs |= PRIV_DEOP_LCHAN; + if (feature_bool(FEAT_SHOW_INVISIBLE_USERS)) + privs |= PRIV_SHOW_INVIS; + if (feature_bool(FEAT_SHOW_ALL_INVISIBLE_USERS)) + privs |= PRIV_SHOW_ALL_INVIS; + if (feature_bool(FEAT_UNLIMIT_OPER_QUERY)) + privs |= PRIV_UNLIMIT_QUERY; + if (feature_bool(FEAT_LOCAL_KILL_ONLY)) + antiprivs |= PRIV_KILL; + if (!feature_bool(FEAT_CONFIG_OPERCMDS)) + antiprivs |= (PRIV_GLINE | PRIV_JUPE | PRIV_OPMODE | PRIV_BADCHAN); + + if (IsOper(client)) { + privs |= (PRIV_SET | PRIV_PROPAGATE | PRIV_SEE_OPERS); + if (feature_bool(FEAT_OPER_KILL)) + privs |= (PRIV_KILL | PRIV_LOCAL_KILL); + if (feature_bool(FEAT_OPER_REHASH)) + privs |= PRIV_REHASH; + if (feature_bool(FEAT_OPER_RESTART)) + privs |= PRIV_RESTART; + if (feature_bool(FEAT_OPER_DIE)) + privs |= PRIV_DIE; + if (feature_bool(FEAT_OPER_GLINE)) + privs |= PRIV_GLINE; + if (feature_bool(FEAT_OPER_LGLINE)) + privs |= PRIV_LOCAL_GLINE; + if (feature_bool(FEAT_OPER_JUPE)) + privs |= PRIV_JUPE; + if (feature_bool(FEAT_OPER_LJUPE)) + privs |= PRIV_LOCAL_JUPE; + if (feature_bool(FEAT_OPER_OPMODE)) + privs |= PRIV_OPMODE; + if (feature_bool(FEAT_OPER_LOPMODE)) + privs |= PRIV_LOCAL_OPMODE; + if (feature_bool(FEAT_OPER_BADCHAN)) + privs |= PRIV_BADCHAN; + if (feature_bool(FEAT_OPER_LBADCHAN)) + privs |= PRIV_LOCAL_BADCHAN; + if (feature_bool(FEAT_OPERS_SEE_IN_SECRET_CHANNELS)) + privs |= PRIV_SEE_CHAN; + } else { /* is a local operator */ + if (feature_bool(FEAT_LOCOP_KILL)) + privs |= PRIV_LOCAL_KILL; + if (feature_bool(FEAT_LOCOP_REHASH)) + privs |= PRIV_REHASH; + if (feature_bool(FEAT_LOCOP_RESTART)) + privs |= PRIV_RESTART; + if (feature_bool(FEAT_LOCOP_DIE)) + privs |= PRIV_DIE; + if (feature_bool(FEAT_LOCOP_LGLINE)) + privs |= PRIV_LOCAL_GLINE; + if (feature_bool(FEAT_LOCOP_LJUPE)) + privs |= PRIV_LOCAL_JUPE; + if (feature_bool(FEAT_LOCOP_LOPMODE)) + privs |= PRIV_LOCAL_OPMODE; + if (feature_bool(FEAT_LOCOP_LBADCHAN)) + privs |= PRIV_LOCAL_BADCHAN; + if (feature_bool(FEAT_LOCOP_SEE_IN_SECRET_CHANNELS)) + privs |= PRIV_SEE_CHAN; + } + + /* This is the end of the gross section */ + + if (privs & PRIV_PROPAGATE) + privs |= PRIV_DISPLAY; + else + antiprivs |= (PRIV_KILL | PRIV_GLINE | PRIV_JUPE | PRIV_OPMODE | + PRIV_BADCHAN); + + cli_privs(client) = privs & ~antiprivs; +} diff --git a/ircd/gline.c b/ircd/gline.c index 565d711..6746af2 100644 --- a/ircd/gline.c +++ b/ircd/gline.c @@ -248,10 +248,9 @@ gline_add(struct Client *cptr, struct Client *sptr, char *userhost, || userhost[2] == '#' || userhost[2] == '&' || userhost[2] == '+' # endif /* OLD_GLINE */ ) { -# ifndef LOCAL_BADCHAN - if (flags & GLINE_LOCAL) - return 0; -# endif + if ((flags & GLINE_LOCAL) && !HasPriv(sptr, PRIV_LOCAL_BADCHAN)) + return send_reply(sptr, ERR_NOPRIVILEGES); + flags |= GLINE_BADCHAN; } diff --git a/ircd/ircd_features.c b/ircd/ircd_features.c index 2ac6398..7e6a62d 100644 --- a/ircd/ircd_features.c +++ b/ircd/ircd_features.c @@ -205,16 +205,58 @@ static struct FeatureDesc { feat_report_call report; /* report feature values */ } features[] = { #define F(type, flags, v_int, v_str, set, reset, get, unmark, mark, report) \ - { FEAT_##type, #type, (flags), \ - 0, (v_int), 0, (v_str), \ - (set), (reset), (get), \ - (unmark), (mark), \ - (report) } + { FEAT_ ## type, #type, (flags), 0, (v_int), 0, (v_str), \ + (set), (reset), (get), (unmark), (mark), (report) } +#define F_I(type, v_int) \ + { FEAT_ ## type, #type, FEAT_INT, 0, (v_int), 0, 0, 0, 0, 0, 0, 0, 0 } +#define F_B(type, v_int) \ + { FEAT_ ## type, #type, FEAT_BOOL, 0, (v_int), 0, 0, 0, 0, 0, 0, 0, 0 } +#define F_S(type, flags, v_int) \ + { FEAT_ ## type, #type, FEAT_STR | (flags), 0, 0, 0, (v_str), \ + 0, 0, 0, 0, 0, 0 } F(LOG, FEAT_NONE | FEAT_MYOPER, 0, 0, feature_log_set, feature_log_reset, feature_log_get, log_feature_unmark, log_feature_mark, log_feature_report), + F_B(OPER_NO_CHAN_LIMIT, 1), + F_B(OPER_MODE_LCHAN, 1), + F_B(OPER_WALK_THROUGH_LMODES, 0), + F_B(NO_OPER_DEOP_LCHAN, 0), + F_B(SHOW_INVISIBLE_USERS, 1), + F_B(SHOW_ALL_INVISIBLE_USERS, 1), + F_B(UNLIMIT_OPER_QUERY, 0), + F_B(LOCAL_KILL_ONLY, 0), + F_B(CONFIG_OPERCMDS, 1), /* XXX change default before release */ + + F_B(OPER_KILL, 1), + F_B(OPER_REHASH, 1), + F_B(OPER_RESTART, 1), + F_B(OPER_DIE, 1), + F_B(OPER_GLINE, 1), + F_B(OPER_LGLINE, 1), + F_B(OPER_JUPE, 1), + F_B(OPER_LJUPE, 1), + F_B(OPER_OPMODE, 1), + F_B(OPER_LOPMODE, 1), + F_B(OPER_BADCHAN, 0), + F_B(OPER_LBADCHAN, 0), + F_B(OPERS_SEE_IN_SECRET_CHANNELS, 1), + + F_B(LOCOP_KILL, 0), + F_B(LOCOP_REHASH, 1), + F_B(LOCOP_RESTART, 0), + F_B(LOCOP_DIE, 0), + F_B(LOCOP_LGLINE, 1), + F_B(LOCOP_LJUPE, 1), + F_B(LOCOP_LOPMODE, 1), + F_B(LOCOP_LBADCHAN, 0), + F_B(LOCOP_SEE_IN_SECRET_CHANNELS, 0), + +#undef F_S +#undef F_B +#undef F_I +#undef F { FEAT_LAST_F, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; @@ -246,6 +288,9 @@ feature_set(struct Client* from, const char* const* fields, int count) int i; struct FeatureDesc *feat; + if (from && !HasPriv(from, PRIV_SET)) + return send_reply(from, ERR_NOPRIVILEGES); + if (count < 1) { if (from) /* report an error in the number of arguments */ need_more_params(from, "SET"); @@ -348,6 +393,9 @@ feature_reset(struct Client* from, const char* const* fields, int count) assert(0 != from); + if (!HasPriv(from, PRIV_SET)) + return send_reply(from, ERR_NOPRIVILEGES); + if (count < 1) /* check arguments */ need_more_params(from, "RESET"); else if ((feat = feature_desc(from, fields[0]))) { /* get descriptor */ diff --git a/ircd/m_clearmode.c b/ircd/m_clearmode.c index 5eca38b..b64dd00 100644 --- a/ircd/m_clearmode.c +++ b/ircd/m_clearmode.c @@ -93,6 +93,7 @@ #include "hash.h" #include "ircd.h" #include "ircd_alloc.h" +#include "ircd_features.h" #include "ircd_log.h" #include "ircd_reply.h" #include "ircd_string.h" @@ -281,12 +282,12 @@ ms_clearmode(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) int mo_clearmode(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { -#ifndef CONFIG_OPERCMDS - return send_reply(sptr, ERR_DISABLED, "CLEARMODE"); -#else struct Channel *chptr; char *control = "ovpsmikbl"; /* default control string */ + if (!feature_bool(FEAT_CONFIG_OPERCMDS)) + return send_reply(sptr, ERR_DISABLED, "CLEARMODE"); + if (parc < 2) return need_more_params(sptr, "CLEARMODE"); @@ -295,12 +296,12 @@ mo_clearmode(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) clean_channelname(parv[1]); - if (!IsOper(sptr) && !IsLocalChannel(parv[1])) + if (!HasPriv(sptr, + IsLocalChannel(parv[1]) ? PRIV_LOCAL_OPMODE : PRIV_OPMODE)) return send_reply(sptr, ERR_NOPRIVILEGES); - if (!IsChannelName(parv[1]) || !(chptr = FindChannel(parv[1]))) + if (('#' != *parv[1] && '&' != *parv[1]) || !(chptr = FindChannel(parv[1]))) return send_reply(sptr, ERR_NOSUCHCHANNEL, parv[1]); return do_clearmode(cptr, sptr, chptr, control); -#endif /* CONFIG_OPERCMDS */ } diff --git a/ircd/m_die.c b/ircd/m_die.c index 2288130..fbc1c42 100644 --- a/ircd/m_die.c +++ b/ircd/m_die.c @@ -105,22 +105,11 @@ */ int mo_die(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { -#if defined(OPER_DIE) || defined(LOCOP_DIE) struct Client *acptr; int i; -#ifndef LOCOP_DIE - if (!MyUser(sptr) || !IsOper(sptr)) -#else -#ifdef OPER_DIE - if (!MyUser(sptr) || !IsAnOper(sptr)) -#else - if (!MyUser(sptr) || !IsLocOp(sptr)) -#endif -#endif - { + if (!HasPriv(sptr, PRIV_DIE)) return send_reply(sptr, ERR_NOPRIVILEGES); - } for (i = 0; i <= HighestFd; i++) { @@ -134,49 +123,6 @@ int mo_die(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) get_client_name(sptr, HIDE_IP)); } server_die("received DIE"); -#endif /* defined(OPER_DIE) || defined(LOCOP_DIE) */ - return 0; -} - - -#if 0 -#if defined(OPER_DIE) || defined(LOCOP_DIE) -/* - * m_die - */ -int m_die(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) -{ - struct Client *acptr; - int i; - -#ifndef LOCOP_DIE - if (!MyUser(sptr) || !IsOper(sptr)) -#else -#ifdef OPER_DIE - if (!MyUser(sptr) || !IsAnOper(sptr)) -#else - if (!MyUser(sptr) || !IsLocOp(sptr)) -#endif -#endif - { - sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); /* XXX DEAD */ - return 0; - } - for (i = 0; i <= HighestFd; i++) - { - if (!(acptr = LocalClientArray[i])) - continue; - if (IsUser(acptr)) - sendto_one(acptr, ":%s NOTICE %s :Server Terminating. %s", /* XXX DEAD */ - me.name, acptr->name, get_client_name(sptr, HIDE_IP)); - else if (IsServer(acptr)) - sendto_one(acptr, ":%s ERROR :Terminated by %s", /* XXX DEAD */ - me.name, get_client_name(sptr, HIDE_IP)); - } - server_die("received DIE"); return 0; } -#endif -#endif /* 0 */ - diff --git a/ircd/m_gline.c b/ircd/m_gline.c index 7f01f9b..6a5f1e0 100644 --- a/ircd/m_gline.c +++ b/ircd/m_gline.c @@ -91,6 +91,7 @@ #include "gline.h" #include "hash.h" #include "ircd.h" +#include "ircd_features.h" #include "ircd_reply.h" #include "ircd_string.h" #include "match.h" @@ -227,16 +228,12 @@ mo_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) if (*mask == '+') { flags |= GLINE_ACTIVE; mask++; + } else if (*mask == '-') mask++; else return gline_list(sptr, mask); -#ifndef LOCOP_LGLINE - if (!IsOper(sptr)) - return send_reply(sptr, ERR_NOPRIVILEGES); -#endif - if (parc == 4) { expire_off = atoi(parv[2]); reason = parv[3]; @@ -254,28 +251,26 @@ mo_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) return send_reply(sptr, ERR_NOSUCHSERVER, target); if (!IsMe(acptr)) { /* manually propagate, since we don't set it */ -#ifndef CONFIG_OPERCMDS - return send_reply(sptr, ERR_DISABLED, "GLINE"); -#else - if (!IsOper(sptr)) + if (!feature_bool(FEAT_CONFIG_OPERCMDS)) + return send_reply(sptr, ERR_DISABLED, "GLINE"); + + if (!HasPriv(sptr, PRIV_GLINE)) return send_reply(sptr, ERR_NOPRIVILEGES); sendcmdto_one(sptr, CMD_GLINE, acptr, "%C %c%s %s %Tu :%s", acptr, - flags & GLINE_ACTIVE ? '?' : '-', mask, parv[3], + flags & GLINE_ACTIVE ? '+' : '-', mask, parv[3], TStime(), reason); return 0; -#endif - } + } else if (!HasPriv(sptr, PRIV_LOCAL_GLINE)) + return send_reply(sptr, ERR_NOPRIVILEGES); flags |= GLINE_LOCAL; - } else if (!IsOper(sptr)) + } else if (!HasPriv(sptr, PRIV_GLINE)) return send_reply(sptr, ERR_NOPRIVILEGES); } -#ifndef CONFIG_OPERCMDS - if (!(flags & GLINE_LOCAL)) + if (!(flags & GLINE_LOCAL) && !feature_bool(FEAT_CONFIG_OPERCMDS)) return send_reply(sptr, ERR_DISABLED, "GLINE"); -#endif /* CONFIG_OPERCMDS */ agline = gline_find(mask, GLINE_ANY | GLINE_EXACT); diff --git a/ircd/m_join.c b/ircd/m_join.c index 051216e..b0d28d7 100644 --- a/ircd/m_join.c +++ b/ircd/m_join.c @@ -172,9 +172,7 @@ int m_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) struct Channel *chptr; struct JoinBuf join; struct JoinBuf create; -#ifdef BADCHAN struct Gline *gline; -#endif unsigned int flags = 0; int i; char *p = 0; @@ -204,14 +202,12 @@ int m_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) continue; } -#ifdef BADCHAN /* BADCHANed channel */ if ((gline = gline_find(name, GLINE_BADCHAN | GLINE_EXACT)) && GlineIsActive(gline) && !IsAnOper(sptr)) { send_reply(sptr, ERR_BANNEDFROMCHAN, name); continue; } -#endif if ((chptr = FindChannel(name))) { if (find_member_link(chptr, sptr)) @@ -221,12 +217,8 @@ int m_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) } else flags = IsModelessChannel(name) ? CHFL_DEOPPED : CHFL_CHANOP; - if (cli_user(sptr)->joined >= MAXCHANNELSPERUSER -#ifdef OPER_NO_CHAN_LIMIT - /* Opers are allowed to join any number of channels */ - && !IsAnOper(sptr) -#endif - ) { + if (cli_user(sptr)->joined >= MAXCHANNELSPERUSER && + !HasPriv(sptr, PRIV_CHAN_LIMIT)) { send_reply(sptr, ERR_TOOMANYCHANNELS, chptr ? chptr->chname : name); break; /* no point processing the other channels */ } @@ -235,7 +227,6 @@ int m_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) if (check_target_limit(sptr, chptr, chptr->chname, 0)) continue; /* exceeded target limit */ else if ((i = can_join(sptr, chptr, keys))) { -#ifdef OPER_WALK_THROUGH_LMODES if (i > MAGIC_OPER_OVERRIDE) { /* oper overrode mode */ switch (i - MAGIC_OPER_OVERRIDE) { case ERR_CHANNELISFULL: /* figure out which mode */ @@ -262,10 +253,6 @@ int m_join(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) send_reply(sptr, i, chptr->chname); continue; } -#else - send_reply(sptr, i, chptr->chname); - continue; -#endif } /* else if ((i = can_join(sptr, chptr, keys))) { */ joinbuf_join(&join, chptr, flags); diff --git a/ircd/m_jupe.c b/ircd/m_jupe.c index 4be6856..3926f32 100644 --- a/ircd/m_jupe.c +++ b/ircd/m_jupe.c @@ -92,6 +92,7 @@ #include "jupe.h" #include "hash.h" #include "ircd.h" +#include "ircd_features.h" #include "ircd_reply.h" #include "ircd_string.h" #include "match.h" @@ -192,7 +193,6 @@ int ms_jupe(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) * parv[4] = [Comment] * */ -#ifdef CONFIG_OPERCMDS int mo_jupe(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { struct Client *acptr = 0; @@ -212,6 +212,9 @@ int mo_jupe(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) else return jupe_list(sptr, server); + if (!feature_bool(FEAT_CONFIG_OPERCMDS)) + return send_reply(sptr, ERR_DISABLED, "JUPE"); + if (parc == 4) { expire_off = atoi(parv[2]); reason = parv[3]; @@ -229,17 +232,18 @@ int mo_jupe(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) return send_reply(sptr, ERR_NOSUCHSERVER, target); if (!IsMe(acptr)) { /* manually propagate, since we don't set it */ - if (!IsOper(sptr)) + if (!HasPriv(sptr, PRIV_GLINE)) return send_reply(sptr, ERR_NOPRIVILEGES); sendcmdto_one(sptr, CMD_JUPE, acptr, "%C %c%s %s %Tu :%s", acptr, flags & JUPE_ACTIVE ? '+' : '-', server, parv[3], TStime(), reason); return 0; - } + } else if (!HasPriv(sptr, PRIV_LOCAL_GLINE)) + return send_reply(sptr, ERR_NOPRIVILEGES); flags |= JUPE_LOCAL; - } else if (!IsOper(sptr)) + } else if (!HasPriv(sptr, PRIV_GLINE)) return send_reply(sptr, ERR_NOPRIVILEGES); } @@ -258,7 +262,6 @@ int mo_jupe(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) return jupe_add(cptr, sptr, server, reason, expire_off, TStime(), flags); } -#endif /* CONFIG_OPERCMDS */ /* * m_jupe - user message handler diff --git a/ircd/m_kick.c b/ircd/m_kick.c index 4703216..6252247 100644 --- a/ircd/m_kick.c +++ b/ircd/m_kick.c @@ -136,11 +136,9 @@ int m_kick(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) if (IsChannelService(who)) return send_reply(sptr, ERR_ISCHANSERVICE, cli_name(who), chptr->chname); -#ifdef NO_OPER_DEOP_LCHAN /* Prevent kicking opers from local channels -DM- */ - if (IsOperOnLocalChannel(who, chptr->chname)) + if (IsLocalChannel(chptr->chname) && HasPriv(who, PRIV_DEOP_LCHAN)) return send_reply(sptr, ERR_ISOPERLCHAN, cli_name(who), chptr->chname); -#endif /* check if kicked user is actually on the channel */ if (!(member = find_member_link(chptr, who)) || IsZombie(member)) diff --git a/ircd/m_kill.c b/ircd/m_kill.c index dd5b36a..52c64a4 100644 --- a/ircd/m_kill.c +++ b/ircd/m_kill.c @@ -244,8 +244,6 @@ int mo_kill(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) assert(cptr == sptr); assert(IsAnOper(sptr)); -#if defined(OPER_KILL) - if (parc < 3 || EmptyString(parv[parc - 1])) return need_more_params(sptr, "KILL"); @@ -262,7 +260,7 @@ int mo_kill(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Changed KILL %s into %s", sptr, user, cli_name(victim)); } - if (!MyConnect(victim) && IsLocOp(cptr)) + if (!HasPriv(sptr, MyConnect(victim) ? PRIV_LOCAL_KILL : PRIV_KILL)) return send_reply(sptr, ERR_NOPRIVILEGES); if (IsServer(victim) || IsMe(victim)) { @@ -275,13 +273,12 @@ int mo_kill(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) return send_reply(sptr, ERR_ISCHANSERVICE, "KILL", cli_name(victim)); -#ifdef LOCAL_KILL_ONLY - if (!MyConnect(victim)) { - sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Nick %s isnt on your server", sptr, - cli_name(victim)); + if (!MyConnect(victim) && !HasPriv(sptr, PRIV_KILL)) { + sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Nick %s isnt on your server", + sptr, cli_name(victim)); return 0; } -#endif + /* * The kill originates from this server, initialize path. * (In which case the 'path' may contain user suplied @@ -346,12 +343,6 @@ int mo_kill(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) } return exit_client(cptr, victim, sptr, buf); - -#else /* !defined(OPER_KILL) */ - - return send_reply(sptr, ERR_NOPRIVILEGES); - -#endif /* !defined(OPER_KILL) */ } #if 0 diff --git a/ircd/m_mode.c b/ircd/m_mode.c index 54abb04..7479232 100644 --- a/ircd/m_mode.c +++ b/ircd/m_mode.c @@ -129,8 +129,7 @@ m_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) } if (!(member = find_member_link(chptr, sptr)) || !IsChanOp(member)) { -#ifdef OPER_MODE_LCHAN - if (IsOperOnLocalChannel(sptr, chptr->chname)) { + if (IsLocalChannel(chptr->chname) && HasPriv(sptr, PRIV_MODE_LCHAN)) { modebuf_init(&mbuf, sptr, cptr, chptr, (MODEBUF_DEST_CHANNEL | /* Send mode to channel */ MODEBUF_DEST_HACK4)); /* Send HACK(4) notice */ @@ -139,7 +138,6 @@ m_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) MODE_PARSE_FORCE)); /* Force it to take */ return modebuf_flush(&mbuf); } else -#endif mode_parse(0, cptr, sptr, chptr, parc - 2, parv + 2, (member ? MODE_PARSE_NOTOPER : MODE_PARSE_NOTMEMBER)); return 0; diff --git a/ircd/m_oper.c b/ircd/m_oper.c index 3681506..b57c685 100644 --- a/ircd/m_oper.c +++ b/ircd/m_oper.c @@ -189,6 +189,7 @@ int m_oper(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) cli_flags(sptr) |= (FLAGS_WALLOP | FLAGS_SERVNOTICE | FLAGS_DEBUG); set_snomask(sptr, SNO_OPERDEFAULT, SNO_ADD); + client_set_privs(sptr); send_umode_out(cptr, sptr, old_mode); send_reply(sptr, RPL_YOUREOPER); diff --git a/ircd/m_opmode.c b/ircd/m_opmode.c index fb4d524..af9b03f 100644 --- a/ircd/m_opmode.c +++ b/ircd/m_opmode.c @@ -92,6 +92,7 @@ #include "channel.h" #include "hash.h" #include "ircd.h" +#include "ircd_features.h" #include "ircd_reply.h" #include "ircd_string.h" #include "msg.h" @@ -140,18 +141,22 @@ int ms_opmode(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) */ int mo_opmode(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { -#ifndef CONFIG_OPERCMDS - return send_reply(sptr, ERR_DISABLED, "OPMODE"); -#else struct Channel *chptr = 0; struct ModeBuf mbuf; struct Membership *member; + if (!feature_bool(FEAT_CONFIG_OPERCMDS)) + return send_reply(sptr, ERR_DISABLED, "OPMODE"); + if (parc < 3) return need_more_params(sptr, "OPMODE"); clean_channelname(parv[1]); + if (!HasPriv(sptr, + IsLocalChannel(parv[1]) ? PRIV_LOCAL_OPMODE : PRIV_OPMODE)) + return send_reply(sptr, ERR_NOPRIVILEGES); + if (('#' != *parv[1] && '&' != *parv[1]) || !(chptr = FindChannel(parv[1]))) return send_reply(sptr, ERR_NOSUCHCHANNEL, parv[1]); @@ -172,6 +177,5 @@ int mo_opmode(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) modebuf_flush(&mbuf); /* flush the modes */ return 0; -#endif /* CONFIG_OPERCMDS */ } diff --git a/ircd/m_rehash.c b/ircd/m_rehash.c index f95562c..28864e7 100644 --- a/ircd/m_rehash.c +++ b/ircd/m_rehash.c @@ -108,19 +108,10 @@ */ int mo_rehash(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { -#if defined(OPER_REHASH) || defined(LOCOP_REHASH) int flag = 0; -# if !defined(OPER_REHASH) || !defined(LOCOP_REHASH) - if ( -# ifdef OPER_REHASH - !IsOper(sptr) -# else - !IsLocOp(sptr) -# endif - ) + if (!HasPriv(sptr, PRIV_REHASH)) return send_reply(sptr, ERR_NOPRIVILEGES); -# endif if (parc > 1) { /* special processing */ if (*parv[1] == 'm') { @@ -142,7 +133,5 @@ int mo_rehash(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) log_write(LS_SYSTEM, L_INFO, 0, "REHASH From %#C", sptr); return rehash(cptr, flag); -#endif /* defined(OPER_REHASH) || defined(LOCOP_REHASH) */ - return 0; } diff --git a/ircd/m_restart.c b/ircd/m_restart.c index aed3bf6..d566eae 100644 --- a/ircd/m_restart.c +++ b/ircd/m_restart.c @@ -103,52 +103,11 @@ */ int mo_restart(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { -#if defined(OPER_RESTART) || defined(LOCOP_RESTART) -#ifndef LOCOP_RESTART - if (!MyUser(sptr) || !IsOper(sptr)) -#else -#ifdef OPER_RESTART - if (!MyUser(sptr) || !IsAnOper(sptr)) -#else - if (!MyUser(sptr) || !IsLocOp(sptr)) -#endif -#endif - { - send_reply(sptr, ERR_NOPRIVILEGES); - return 0; - } + if (!HasPriv(sptr, PRIV_RESTART)) + return send_reply(sptr, ERR_NOPRIVILEGES); + log_write(LS_SYSTEM, L_NOTICE, 0, "Server RESTART by %#C", sptr); server_restart("received RESTART"); -#endif /* defined(OPER_RESTART) || defined(LOCOP_RESTART) */ return 0; } - - -#if 0 -#if defined(OPER_RESTART) || defined(LOCOP_RESTART) -/* - * m_restart - */ -int m_restart(struct Client *cptr, struct Client *sptr, int parc, - char *parv[]) -{ -#ifndef LOCOP_RESTART - if (!MyUser(sptr) || !IsOper(sptr)) -#else -#ifdef OPER_RESTART - if (!MyUser(sptr) || !IsAnOper(sptr)) -#else - if (!MyUser(sptr) || !IsLocOp(sptr)) -#endif -#endif - { - sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); /* XXX DEAD */ - return 0; - } - ircd_log(L_NOTICE, "Server RESTART by %s\n", get_client_name(sptr, HIDE_IP)); /* XXX DEAD */ - server_restart("received RESTART"); - return 0; -} -#endif -#endif /* 0 */ diff --git a/ircd/m_userhost.c b/ircd/m_userhost.c index d8ffb95..63b0a51 100644 --- a/ircd/m_userhost.c +++ b/ircd/m_userhost.c @@ -100,7 +100,8 @@ static void userhost_formatter(struct Client* cptr, struct MsgBuf* mb) { assert(IsUser(cptr)); - msgq_append(0, mb, "%s%s=%c%s@%s", cli_name(cptr), IsAnOper(cptr) ? "*" : "", + msgq_append(0, mb, "%s%s=%c%s@%s", cli_name(cptr), + HasPriv(cptr, PRIV_DISPLAY) ? "*" : "", cli_user(cptr)->away ? '-' : '+', cli_user(cptr)->username, cli_user(cptr)->host); } diff --git a/ircd/m_userip.c b/ircd/m_userip.c index 4fa321d..41aa223 100644 --- a/ircd/m_userip.c +++ b/ircd/m_userip.c @@ -100,7 +100,8 @@ static void userip_formatter(struct Client* cptr, struct MsgBuf* mb) { assert(IsUser(cptr)); - msgq_append(0, mb, "%s%s=%c%s@%s", cli_name(cptr), IsAnOper(cptr) ? "*" : "", + msgq_append(0, mb, "%s%s=%c%s@%s", cli_name(cptr), + HasPriv(cptr, PRIV_DISPLAY) ? "*" : "", cli_user(cptr)->away ? '-' : '+', cli_user(cptr)->username, ircd_ntoa((const char*) &(cli_ip(cptr)))); } diff --git a/ircd/m_version.c b/ircd/m_version.c index 6bbc795..1366879 100644 --- a/ircd/m_version.c +++ b/ircd/m_version.c @@ -130,7 +130,8 @@ int m_version(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) sprintf_irc(featurebuf,FEATURES,FEATURESVALUES); - send_reply(sptr, RPL_VERSION, version, debugmode, cli_name(&me), serveropts); + send_reply(sptr, RPL_VERSION, version, debugmode, cli_name(&me), + debug_serveropts()); send_reply(sptr, RPL_ISUPPORT, featurebuf); } @@ -160,7 +161,8 @@ int ms_version(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) if (hunt_server_cmd(sptr, CMD_VERSION, cptr, 0, ":%C", 1, parc, parv) == HUNTED_ISME) { - send_reply(sptr, RPL_VERSION, version, debugmode, cli_name(&me), serveropts); + send_reply(sptr, RPL_VERSION, version, debugmode, cli_name(&me), + debug_serveropts()); } return 0; diff --git a/ircd/m_who.c b/ircd/m_who.c index dd31cf1..ecb27b4 100644 --- a/ircd/m_who.c +++ b/ircd/m_who.c @@ -188,7 +188,7 @@ int m_who(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) case 'x': case 'X': bitsel |= WHOSELECT_EXTRA; - if (IsAnOper(sptr)) + if (HasPriv(sptr, PRIV_WHOX)) log_write(LS_WHO, L_INFO, LOG_NOSNOTICE, "%#C WHO %s %s", sptr, (BadPtr(parv[3]) ? parv[1] : parv[3]), parv[2]); continue; @@ -316,7 +316,9 @@ int m_who(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) for (member = chptr->members; member; member = member->next_member) { acptr = member->user; - if ((bitsel & WHOSELECT_OPER) && !(IsAnOper(acptr))) + if ((bitsel & WHOSELECT_OPER) && + !(IsAnOper(acptr) && (HasPriv(acptr, PRIV_DISPLAY) || + HasPriv(sptr, PRIV_SEE_OPERS)))) continue; if ((acptr != sptr) && (member->status & CHFL_ZOMBIE)) continue; @@ -333,7 +335,9 @@ int m_who(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) else { if ((acptr = FindUser(nick)) && - ((!(bitsel & WHOSELECT_OPER)) || IsAnOper(acptr)) && + ((!(bitsel & WHOSELECT_OPER)) || + (IsAnOper(acptr) && (HasPriv(acptr, PRIV_DISPLAY) || + HasPriv(sptr, PRIV_SEE_OPERS)))) && Process(acptr) && SHOW_MORE(sptr, counter)) { do_who(sptr, acptr, 0, fields, qrt); @@ -377,8 +381,10 @@ int m_who(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) if (!(IsUser(acptr) && Process(acptr))) continue; /* Now Process() is at the beginning, if we fail we'll never have to show this acptr in this query */ - if ((bitsel & WHOSELECT_OPER) && !IsAnOper(acptr)) - continue; + if ((bitsel & WHOSELECT_OPER) && + !(IsAnOper(acptr) && (HasPriv(acptr, PRIV_DISPLAY) || + HasPriv(sptr, PRIV_SEE_OPERS)))) + continue; if ((mask) && ((!(matchsel & WHO_FIELD_NIC)) || matchexec(cli_name(acptr), mymask, minlen)) @@ -408,8 +414,10 @@ int m_who(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { if (!(IsUser(acptr) && Process(acptr))) continue; - if ((bitsel & WHOSELECT_OPER) && !IsAnOper(acptr)) - continue; + if ((bitsel & WHOSELECT_OPER) && + !(IsAnOper(acptr) && (HasPriv(acptr, PRIV_DISPLAY) || + HasPriv(sptr, PRIV_SEE_OPERS)))) + continue; if (!(SEE_USER(sptr, acptr, bitsel))) continue; if ((mask) && diff --git a/ircd/m_whois.c b/ircd/m_whois.c index 9c6ea1b..5a46bdf 100644 --- a/ircd/m_whois.c +++ b/ircd/m_whois.c @@ -194,7 +194,7 @@ static void do_whois(struct Client* sptr, struct Client *acptr) if (user->away) send_reply(sptr, RPL_AWAY, name, user->away); - if (IsAnOper(acptr)) + if (HasPriv(acptr, PRIV_DISPLAY) || HasPriv(sptr, PRIV_SEE_OPERS)) send_reply(sptr, RPL_WHOISOPERATOR, name); /* Hint: if your looking to add more flags to a user, eg +h, here's diff --git a/ircd/parse.c b/ircd/parse.c index da26232..700eec6 100644 --- a/ircd/parse.c +++ b/ircd/parse.c @@ -448,11 +448,7 @@ struct Message msgtab[] = { TOK_JUPE, 0, MAXPARA, MFLG_SLOW, 0, /* UNREG, CLIENT, SERVER, OPER, SERVICE */ -#ifdef CONFIG_OPERCMDS { m_unregistered, m_jupe, ms_jupe, mo_jupe, m_ignore } -#else - { m_unregistered, m_jupe, ms_jupe, m_jupe, m_ignore } -#endif /* CONFIG_OPERCMDS */ }, { MSG_OPMODE, diff --git a/ircd/s_debug.c b/ircd/s_debug.c index 32134b9..482e077 100644 --- a/ircd/s_debug.c +++ b/ircd/s_debug.c @@ -26,6 +26,7 @@ #include "client.h" #include "hash.h" #include "ircd_alloc.h" +#include "ircd_features.h" #include "ircd_log.h" #include "ircd_osdep.h" #include "ircd_reply.h" @@ -51,129 +52,113 @@ #include #include -/* *INDENT-OFF* */ - /* * Option string. Must be before #ifdef DEBUGMODE. */ -char serveropts[] = { +static char serveropts[256]; /* should be large enough for anything */ + +const char* debug_serveropts(void) +{ + int i = 0; +#define AddC(c) serveropts[i++] = (c) + #if BUFFERPOOL < 1000000 - 'b', + AddC('b'); #if BUFFERPOOL > 99999 - (char)('0' + (BUFFERPOOL/100000)), + AddC((char)('0' + (BUFFERPOOL/100000))); #endif #if BUFFERPOOL > 9999 - (char)('0' + (BUFFERPOOL/10000) % 10), + AddC((char)('0' + (BUFFERPOOL/10000) % 10)); #endif - (char)('0' + (BUFFERPOOL/1000) % 10), + AddC((char)('0' + (BUFFERPOOL/1000) % 10)); #else - 'B', + AddC('B'); #if BUFFERPOOL > 99999999 - (char)('0' + (BUFFERPOOL/100000000)), + AddC((char)('0' + (BUFFERPOOL/100000000))); #endif #if BUFFERPOOL > 9999999 - (char)('0' + (BUFFERPOOL/10000000) % 10), + AddC((char)('0' + (BUFFERPOOL/10000000) % 10)); #endif - (char)('0' + (BUFFERPOOL/1000000) % 10), + AddC((char)('0' + (BUFFERPOOL/1000000) % 10)); #endif #ifdef CHROOTDIR - 'c', + AddC('c'); #endif #ifdef CMDLINE_CONFIG - 'C', -#endif -#ifdef DO_ID - 'd', + AddC('C'); #endif #ifdef DEBUGMODE - 'D', -#endif -#ifdef LOCOP_REHASH - 'e', -#endif -#ifdef OPER_REHASH - 'E', -#endif -#ifdef OPER_NO_CHAN_LIMIT - 'F', -#endif -#ifdef OPER_MODE_LCHAN - 'f', + AddC('D'); #endif + + if (feature_bool(FEAT_LOCOP_REHASH)) + AddC('e'); + + if (feature_bool(FEAT_OPER_REHASH)) + AddC('E'); + + if (feature_bool(FEAT_OPER_NO_CHAN_LIMIT)) + AddC('F'); + + if (feature_bool(FEAT_OPER_MODE_LCHAN)) + AddC('f'); + #ifdef HUB - 'H', -#endif -#if defined(SHOW_INVISIBLE_USERS) || defined(SHOW_ALL_INVISIBLE_USERS) -#ifdef SHOW_ALL_INVISIBLE_USERS - 'I', -#else - 'i', -#endif -#endif -#ifdef OPER_KILL -#ifdef LOCAL_KILL_ONLY - 'k', -#else - 'K', -#endif -#endif -#ifdef LEAST_IDLE - 'L', -#endif -#ifdef OPER_WALK_THROUGH_LMODES - 'l', + AddC('H'); #endif + + if (feature_bool(FEAT_SHOW_ALL_INVISIBLE_USERS)) + AddC('I'); + else if (feature_bool(FEAT_SHOW_INVISIBLE_USERS)) + AddC('i'); + + if (feature_bool(FEAT_OPER_KILL)) { + if (feature_bool(FEAT_LOCAL_KILL_ONLY)) + AddC('k'); + else + AddC('K'); + } + + if (feature_bool(FEAT_OPER_WALK_THROUGH_LMODES)) + AddC('l'); + #ifdef IDLE_FROM_MSG - 'M', + AddC('M'); #endif #ifdef USEONE - 'O', -#endif -#ifdef NO_OPER_DEOP_LCHAN - 'o', + AddC('O'); #endif + + if (feature_bool(FEAT_NO_OPER_DEOP_LCHAN)) + AddC('o'); + #ifdef CRYPT_OPER_PASSWORD - 'p', + AddC('p'); #endif #ifdef CRYPT_LINK_PASSWORD - 'P', -#endif -#ifdef DEBUGMALLOC -#ifdef MEMLEAKSTATS - 'Q', -#else - 'q', -#endif + AddC('P'); #endif #ifdef RELIABLE_CLOCK - 'R', -#endif -#ifdef LOCOP_RESTART - 's', -#endif -#ifdef OPER_RESTART - 'S', -#endif -#ifdef OPER_REMOTE - 't', + AddC('R'); #endif + + if (feature_bool(FEAT_LOCOP_RESTART)) + AddC('s'); + + if (feature_bool(FEAT_OPER_RESTART)) + AddC('S'); + #if defined(USE_POLL) && defined(HAVE_POLL_H) - 'U', + AddC('U'); #endif #ifdef VIRTUAL_HOST - 'v', -#endif -#ifdef BADCHAN - 'W', -#ifdef LOCAL_BADCHAN - 'x', + AddC('v'); #endif -#endif - '\0' -}; -/* *INDENT-ON* */ + serveropts[i] = '\0'; + return serveropts; +} /* * debug_init diff --git a/ircd/s_user.c b/ircd/s_user.c index ea7b01f..1539369 100644 --- a/ircd/s_user.c +++ b/ircd/s_user.c @@ -1005,7 +1005,8 @@ void send_umode_out(struct Client *cptr, struct Client *sptr, int old) int i; struct Client *acptr; - send_umode(NULL, sptr, old, SEND_UMODES); + send_umode(NULL, sptr, old, + SEND_UMODES & ~(HasPriv(sptr, PRIV_PROPAGATE) ? 0 : FLAGS_OPER)); for (i = HighestFd; i >= 0; i--) { if ((acptr = LocalClientArray[i]) && IsServer(acptr) && @@ -1238,10 +1239,14 @@ int set_user_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv * Compare new flags with old flags and send string which * will cause servers to update correctly. */ - if ((setflags & FLAGS_OPER) && !IsOper(sptr)) + if ((setflags & FLAGS_OPER) && !IsOper(sptr)) { --UserStats.opers; - if (!(setflags & FLAGS_OPER) && IsOper(sptr)) + client_set_privs(sptr); + } + if (!(setflags & FLAGS_OPER) && IsOper(sptr)) { ++UserStats.opers; + client_set_privs(sptr); + } if ((setflags & FLAGS_INVISIBLE) && !IsInvisible(sptr)) --UserStats.inv_clients; if (!(setflags & FLAGS_INVISIBLE) && IsInvisible(sptr)) @@ -1261,7 +1266,11 @@ char *umode_str(struct Client *cptr) int i; int c_flags; - c_flags = cli_flags(cptr) & SEND_UMODES; /* cleaning up the original code */ + c_flags = cli_flags(cptr) & SEND_UMODES; /* cleaning up the original code */ + if (HasPriv(cptr, PRIV_PROPAGATE)) + c_flags |= FLAGS_OPER; + else + c_flags &= ~FLAGS_OPER; for (i = 0; i < USERMODELIST_SIZE; ++i) { if ( (c_flags & userModeList[i].flag)) diff --git a/ircd/whocmds.c b/ircd/whocmds.c index 775ad39..f1b2d50 100644 --- a/ircd/whocmds.c +++ b/ircd/whocmds.c @@ -152,7 +152,8 @@ void do_who(struct Client* sptr, struct Client* acptr, struct Channel* repchan, *(p1++) = 'G'; else *(p1++) = 'H'; - if (IsAnOper(acptr)) + if (IsAnOper(acptr) && + (HasPriv(acptr, PRIV_DISPLAY) || HasPriv(sptr, PRIV_SEE_OPERS))) *(p1++) = '*'; if (fields) { /* If you specified flags then we assume you know how to parse