X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=blobdiff_plain;f=src%2Fngircd%2Firc-mode.c;h=7380c6eb5c70308b030097aadf58a9ab3bc933e4;hp=ad83ae98a7aa93d0ee0931e5e6396de91cfa8d57;hb=8cfb9104419d3c00fbef3fe8639eb04f03d83f3d;hpb=f2fa1045e24f81e5c844dd50d6e299cb1ad9acb2 diff --git a/src/ngircd/irc-mode.c b/src/ngircd/irc-mode.c index ad83ae98..7380c6eb 100644 --- a/src/ngircd/irc-mode.c +++ b/src/ngircd/irc-mode.c @@ -138,6 +138,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) { char the_modes[COMMAND_LEN], x[2], *mode_ptr; bool ok, set; + bool send_RPL_HOSTHIDDEN_MSG = false; int mode_arg; size_t len; @@ -229,6 +230,14 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) ERR_NOPRIVILEGES_MSG, Client_ID(Origin)); break; + case 'B': /* Bot */ + if (Client_HasMode(Client, 'r')) + ok = IRC_WriteStrClient(Origin, + ERR_RESTRICTED_MSG, + Client_ID(Origin)); + else + x[0] = 'B'; + break; case 'c': /* Receive connect notices * (only settable by IRC operators!) */ if (!set || Client_Type(Client) == CLIENT_SERVER @@ -256,6 +265,14 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) ERR_RESTRICTED_MSG, Client_ID(Origin)); break; + case 'R': /* Registered (not [un]settable by clients) */ + if (Client_Type(Client) == CLIENT_SERVER) + x[0] = 'R'; + else + ok = IRC_WriteStrClient(Origin, + ERR_NICKREGISTER_MSG, + Client_ID(Origin)); + break; case 'x': /* Cloak hostname */ if (Client_HasMode(Client, 'r')) ok = IRC_WriteStrClient(Origin, @@ -263,6 +280,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) Client_ID(Origin)); else x[0] = 'x'; + send_RPL_HOSTHIDDEN_MSG = true; break; default: if (Client_Type(Client) != CLIENT_SERVER) { @@ -332,6 +350,10 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) "MODE %s :%s", Client_ID(Target), the_modes); + if (send_RPL_HOSTHIDDEN_MSG) + IRC_WriteStrClient(Client, RPL_HOSTHIDDEN_MSG, + Client_ID(Client), + Client_HostnameCloaked(Client)); } LogDebug("%s \"%s\": Mode change, now \"%s\".", Client_TypeText(Target), Client_Mask(Target), @@ -396,13 +418,16 @@ static bool Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) { char the_modes[COMMAND_LEN], the_args[COMMAND_LEN], x[2], - argadd[CLIENT_PASS_LEN], *mode_ptr; - bool connected, set, skiponce, retval, onchannel, modeok, use_servermode; + argadd[CLIENT_PASS_LEN], *mode_ptr, *o_mode_ptr; + bool connected, set, skiponce, retval, use_servermode, + is_halfop, is_op, is_admin, is_owner, is_machine, is_oper; int mode_arg, arg_arg, mode_arg_count = 0; CLIENT *client; long l; size_t len; + is_halfop = is_op = is_admin = is_owner = is_machine = is_oper = false; + if (Channel_IsModeless(Channel)) return IRC_WriteStrClient(Client, ERR_NOCHANMODES_MSG, Client_ID(Client), Channel_Name(Channel)); @@ -411,10 +436,20 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) if (Req->argc <= 1) return Channel_Mode_Answer_Request(Origin, Channel); - Channel_CheckAdminRights(Channel, Client, Origin, - &onchannel, &modeok, &use_servermode); + /* Check if origin is oper and opers can use mode */ + use_servermode = Conf_OperServerMode; + if(Client_OperByMe(Client) && Conf_OperCanMode) { + is_oper = true; + } + + /* Check if client is a server/service */ + if(Client_Type(Client) == CLIENT_SERVER || + Client_Type(Client) == CLIENT_SERVICE) { + is_machine = true; + } - if (!onchannel && !modeok) + /* Check if client is member of channel or an oper or an server/service */ + if(!Channel_IsMemberOf(Channel, Client) && !is_oper && !is_machine) return IRC_WriteStrClient(Origin, ERR_NOTONCHANNEL_MSG, Client_ID(Origin), Channel_Name(Channel)); @@ -493,20 +528,44 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) if (arg_arg >= Req->argc) arg_arg = -1; + if(!is_machine) { + o_mode_ptr = Channel_UserModes(Channel, Client); + while( *o_mode_ptr ) { + if ( *o_mode_ptr == 'q') + is_owner = true; + if ( *o_mode_ptr == 'a') + is_admin = true; + if ( *o_mode_ptr == 'o') + is_op = true; + if ( *o_mode_ptr == 'h') + is_halfop = true; + o_mode_ptr++; + } + } + /* Validate modes */ x[0] = '\0'; argadd[0] = '\0'; client = NULL; switch (*mode_ptr) { /* --- Channel modes --- */ + case 'R': /* Registered users only */ + case 's': /* Secret channel */ + case 'z': /* Secure connections only */ + if(!is_oper && !is_machine && !is_owner && + !is_admin && !is_op) { + connected = IRC_WriteStrClient(Origin, + ERR_CHANOPRIVSNEEDED_MSG, + Client_ID(Origin), Channel_Name(Channel)); + goto chan_exit; + } case 'i': /* Invite only */ + case 'M': /* Only identified nicks can write */ case 'm': /* Moderated */ case 'n': /* Only members can write */ - case 'R': /* Registered users only */ - case 's': /* Secret channel */ case 't': /* Topic locked */ - case 'z': /* Secure connections only */ - if (modeok) + if(is_oper || is_machine || is_owner || + is_admin || is_op || is_halfop) x[0] = *mode_ptr; else connected = IRC_WriteStrClient(Origin, @@ -517,7 +576,8 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) if (Mode_Limit_Reached(Client, mode_arg_count++)) goto chan_exit; if (!set) { - if (modeok) + if (is_oper || is_machine || is_owner || + is_admin || is_op || is_halfop) x[0] = *mode_ptr; else connected = IRC_WriteStrClient(Origin, @@ -527,7 +587,8 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) break; } if (arg_arg > mode_arg) { - if (modeok) { + if (is_oper || is_machine || is_owner || + is_admin || is_op || is_halfop) { Channel_ModeDel(Channel, 'k'); Channel_SetKey(Channel, Req->argv[arg_arg]); @@ -553,7 +614,8 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) if (Mode_Limit_Reached(Client, mode_arg_count++)) goto chan_exit; if (!set) { - if (modeok) + if (is_oper || is_machine || is_owner || + is_admin || is_op || is_halfop) x[0] = *mode_ptr; else connected = IRC_WriteStrClient(Origin, @@ -563,7 +625,8 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) break; } if (arg_arg > mode_arg) { - if (modeok) { + if (is_oper || is_machine || is_owner || + is_admin || is_op || is_halfop) { l = atol(Req->argv[arg_arg]); if (l > 0 && l < 0xFFFF) { Channel_ModeDel(Channel, 'l'); @@ -588,44 +651,47 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) } break; case 'O': /* IRC operators only */ - if (modeok) { + if (set) { /* Only IRC operators are allowed to * set the 'O' channel mode! */ - if (set && !(Client_OperByMe(Client) - || Client_Type(Client) == CLIENT_SERVER)) + if(is_oper || is_machine) + x[0] = 'O'; + else connected = IRC_WriteStrClient(Origin, ERR_NOPRIVILEGES_MSG, Client_ID(Origin)); - else - x[0] = 'O'; - } else + } else if(is_oper || is_machine || is_owner || + is_admin || is_op) + x[0] = 'O'; + else connected = IRC_WriteStrClient(Origin, - ERR_CHANOPRIVSNEEDED_MSG, - Client_ID(Origin), - Channel_Name(Channel)); - break; + ERR_CHANOPRIVSNEEDED_MSG, + Client_ID(Origin), + Channel_Name(Channel)); + break; case 'P': /* Persistent channel */ - if (modeok) { + if (set) { /* Only IRC operators are allowed to * set the 'P' channel mode! */ - if (set && !(Client_OperByMe(Client) - || Client_Type(Client) == CLIENT_SERVER)) + if(is_oper || is_machine) + x[0] = 'P'; + else connected = IRC_WriteStrClient(Origin, ERR_NOPRIVILEGES_MSG, Client_ID(Origin)); - else - x[0] = 'P'; - } else + } else if(is_oper || is_machine || is_owner || + is_admin || is_op) + x[0] = 'P'; + else connected = IRC_WriteStrClient(Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID(Origin), Channel_Name(Channel)); break; /* --- Channel user modes --- */ - case 'a': - case 'h': - case 'q': - if (Client_Type(Client) != CLIENT_SERVER) { + case 'q': /* Owner */ + case 'a': /* Channel admin */ + if(!is_oper && !is_machine && !is_owner) { connected = IRC_WriteStrClient(Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID(Origin), @@ -633,16 +699,34 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) goto chan_exit; } case 'o': /* Channel operator */ + if(!is_oper && !is_machine && !is_owner && + !is_admin && !is_op) { + connected = IRC_WriteStrClient(Origin, + ERR_CHANOPRIVSNEEDED_MSG, + Client_ID(Origin), + Channel_Name(Channel)); + goto chan_exit; + } + case 'h': /* Half Op */ + if(!is_oper && !is_machine && !is_owner && + !is_admin && !is_op) { + connected = IRC_WriteStrClient(Origin, + ERR_CHANOPRIVSNEEDED_MSG, + Client_ID(Origin), + Channel_Name(Channel)); + goto chan_exit; + } case 'v': /* Voice */ if (arg_arg > mode_arg) { - if (modeok) { + if (is_oper || is_machine || is_owner || + is_admin || is_op || is_halfop) { client = Client_Search(Req->argv[arg_arg]); if (client) x[0] = *mode_ptr; else - connected = IRC_WriteStrClient(Client, + connected = IRC_WriteStrClient(Origin, ERR_NOSUCHNICK_MSG, - Client_ID(Client), + Client_ID(Origin), Req->argv[arg_arg]); } else { connected = IRC_WriteStrClient(Origin, @@ -667,7 +751,8 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) goto chan_exit; if (arg_arg > mode_arg) { /* modify list */ - if (modeok) { + if (is_oper || is_machine || is_owner || + is_admin || is_op || is_halfop) { connected = set ? Add_To_List(*mode_ptr, Origin, Client, Channel, @@ -856,7 +941,8 @@ Add_To_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Pattern) { const char *mask; - struct list_head *list; + struct list_head *list = NULL; + long int current_count; assert(Client != NULL); assert(Channel != NULL); @@ -864,6 +950,9 @@ Add_To_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, assert(what == 'I' || what == 'b' || what == 'e'); mask = Lists_MakeMask(Pattern); + current_count = Lists_Count(Channel_GetListInvites(Channel)) + + Lists_Count(Channel_GetListExcepts(Channel)) + + Lists_Count(Channel_GetListBans(Channel)); switch(what) { case 'I': @@ -880,7 +969,7 @@ Add_To_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, if (Lists_CheckDupeMask(list, mask)) return CONNECTED; if (Client_Type(Client) == CLIENT_USER && - Lists_Count(list) >= MAX_HNDL_CHANNEL_LISTS) + current_count >= MAX_HNDL_CHANNEL_LISTS) return IRC_WriteStrClient(Client, ERR_LISTFULL_MSG, Client_ID(Client), Channel_Name(Channel), mask, @@ -919,7 +1008,7 @@ Del_From_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Pattern) { const char *mask; - struct list_head *list; + struct list_head *list = NULL; assert(Client != NULL); assert(Channel != NULL);