diff --git a/include/client.h b/include/client.h index af8ccfa4..d3ff6a57 100644 --- a/include/client.h +++ b/include/client.h @@ -452,7 +452,6 @@ struct ListClient #define UMODE_SERVICE 0x0040 #define UMODE_DEAF 0x0080 #define UMODE_NOFORWARD 0x0100 /* don't forward */ -#define UMODE_REGONLYMSG 0x0200 /* only allow logged in users to msg */ /* user information flags, only settable by remote mode or local oper */ #define UMODE_OPER 0x1000 /* Operator */ @@ -543,7 +542,6 @@ struct ListClient #define IsService(x) ((x)->umodes & UMODE_SERVICE) #define IsDeaf(x) ((x)->umodes & UMODE_DEAF) #define IsNoForward(x) ((x)->umodes & UMODE_NOFORWARD) -#define IsSetRegOnlyMsg(x) ((x)->umodes & UMODE_REGONLYMSG) #define SetGotId(x) ((x)->flags |= FLAGS_GOTID) #define IsGotId(x) (((x)->flags & FLAGS_GOTID) != 0) diff --git a/ircd/newconf.c b/ircd/newconf.c index 7a540606..b69c3bfc 100644 --- a/ircd/newconf.c +++ b/ircd/newconf.c @@ -321,7 +321,6 @@ static struct mode_table umode_table[] = { {"invisible", UMODE_INVISIBLE }, {"locops", UMODE_LOCOPS }, {"noforward", UMODE_NOFORWARD }, - {"regonlymsg", UMODE_REGONLYMSG}, {"servnotice", UMODE_SERVNOTICE}, {"wallop", UMODE_WALLOP }, {"operwall", UMODE_OPERWALL }, diff --git a/ircd/s_user.c b/ircd/s_user.c index 06d3b6cb..5ac5f56e 100644 --- a/ircd/s_user.c +++ b/ircd/s_user.c @@ -81,7 +81,7 @@ int user_modes[256] = { 0, /* O */ 0, /* P */ UMODE_NOFORWARD, /* Q */ - UMODE_REGONLYMSG, /* R */ + 0, /* R */ UMODE_SERVICE, /* S */ 0, /* T */ 0, /* U */ diff --git a/modules/Makefile.am b/modules/Makefile.am index 8b06c829..7f532db7 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -15,6 +15,7 @@ auto_load_mod_LTLIBRARIES = \ cap_server_time.la \ chm_nocolour.la \ chm_noctcp.la \ + um_regonlymsg.la \ m_accept.la \ m_admin.la \ m_alias.la \ diff --git a/modules/core/m_message.c b/modules/core/m_message.c index 3c31554a..e329e7bf 100644 --- a/modules/core/m_message.c +++ b/modules/core/m_message.c @@ -725,8 +725,7 @@ msg_client(enum message_type msgtype, * as a way of griefing. --nenolod */ if(msgtype != MESSAGE_TYPE_NOTICE && - (IsSetCallerId(source_p) || - (IsSetRegOnlyMsg(source_p) && !target_p->user->suser[0])) && + IsSetCallerId(source_p) && !accept_message(target_p, source_p) && !IsOper(target_p)) { @@ -818,8 +817,7 @@ msg_client(enum message_type msgtype, } /* XXX Controversial? allow opers always to send through a +g */ - if(!IsServer(source_p) && (IsSetCallerId(target_p) || - (IsSetRegOnlyMsg(target_p) && !source_p->user->suser[0]))) + if(!IsServer(source_p) && IsSetCallerId(target_p)) { /* Here is the anti-flood bot/spambot code -db */ if(accept_message(source_p, target_p) || IsOper(source_p)) @@ -830,13 +828,6 @@ msg_client(enum message_type msgtype, source_p->username, source_p->host, cmdname[msgtype], target_p->name, text); } - else if (IsSetRegOnlyMsg(target_p) && !source_p->user->suser[0]) - { - if (msgtype != MESSAGE_TYPE_NOTICE) - sendto_one_numeric(source_p, ERR_NONONREG, - form_str(ERR_NONONREG), - target_p->name); - } else { /* check for accept, flag recipient incoming message */ diff --git a/modules/m_invite.c b/modules/m_invite.c index 08bda62f..26c5024d 100644 --- a/modules/m_invite.c +++ b/modules/m_invite.c @@ -161,6 +161,10 @@ m_invite(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source else sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), me.name, source_p->name, parv[2]); + + if (MyClient(target_p)) + add_reply_target(target_p, source_p); + return; } } @@ -200,40 +204,28 @@ m_invite(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source if(MyConnect(target_p)) { - if(!IsOper(source_p) && (IsSetCallerId(target_p) || - (IsSetRegOnlyMsg(target_p) && !source_p->user->suser[0])) && - !accept_message(source_p, target_p)) + if(!IsOper(source_p) && IsSetCallerId(target_p) && !accept_message(source_p, target_p)) { - if (IsSetRegOnlyMsg(target_p) && !source_p->user->suser[0]) + sendto_one_numeric(source_p, ERR_TARGUMODEG, + form_str(ERR_TARGUMODEG), + target_p->name); + + if((target_p->localClient->last_caller_id_time + + ConfigFileEntry.caller_id_wait) < rb_current_time()) { - sendto_one_numeric(source_p, ERR_NONONREG, - form_str(ERR_NONONREG), - target_p->name); - return; + sendto_one_numeric(source_p, RPL_TARGNOTIFY, + form_str(RPL_TARGNOTIFY), + target_p->name); + + add_reply_target(target_p, source_p); + sendto_one(target_p, form_str(RPL_UMODEGMSG), + me.name, target_p->name, source_p->name, + source_p->username, source_p->host); + + target_p->localClient->last_caller_id_time = rb_current_time(); } - else - { - sendto_one_numeric(source_p, ERR_TARGUMODEG, - form_str(ERR_TARGUMODEG), - target_p->name); - if((target_p->localClient->last_caller_id_time + - ConfigFileEntry.caller_id_wait) < rb_current_time()) - { - sendto_one_numeric(source_p, RPL_TARGNOTIFY, - form_str(RPL_TARGNOTIFY), - target_p->name); - - add_reply_target(target_p, source_p); - sendto_one(target_p, form_str(RPL_UMODEGMSG), - me.name, target_p->name, source_p->name, - source_p->username, source_p->host); - - target_p->localClient->last_caller_id_time = rb_current_time(); - } - - return; - } + return; } hdata.chptr = chptr; diff --git a/modules/um_regonlymsg.c b/modules/um_regonlymsg.c new file mode 100644 index 00000000..3b31006a --- /dev/null +++ b/modules/um_regonlymsg.c @@ -0,0 +1,147 @@ +/* + * modules/um_regonlymsg.c + * Copyright (c) 2020 Ariadne Conill + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stdinc.h" +#include "modules.h" +#include "hook.h" +#include "client.h" +#include "ircd.h" +#include "send.h" +#include "hash.h" +#include "s_conf.h" +#include "s_user.h" +#include "s_serv.h" +#include "numeric.h" +#include "privilege.h" +#include "s_newconf.h" +#include "logger.h" + +static int +um_regonlymsg_modinit(void) +{ + user_modes['R'] = find_umode_slot(); + construct_umodebuf(); + + if (!user_modes['R']) + { + ierror("um_regonlymsg: unable to allocate usermode slot for +R, unloading module"); + return -1; + } + + return 0; +} + +static void +um_regonlymsg_moddeinit(void) +{ + user_modes['R'] = 0; + construct_umodebuf(); +} + +#define IsSetRegOnlyMsg(c) ((c->umodes & user_modes['R']) == user_modes['R']) + +static const char um_regonlymsg_desc[] = + "Provides usermode +R which restricts messages from unregistered users."; + +static bool +allow_message(struct Client *source_p, struct Client *target_p) +{ + if (!MyClient(target_p)) + return true; + + if (!IsSetRegOnlyMsg(target_p)) + return true; + + if (IsServer(source_p)) + return true; + + /* XXX: controversial? allow opers to send through +R */ + if (IsOper(source_p)) + return true; + + if (accept_message(source_p, target_p)) + return true; + + if (source_p->user->suser[0]) + return true; + + return false; +} + +static void +h_hdl_invite(void *vdata) +{ + hook_data_channel_approval *data = vdata; + struct Client *source_p = data->client; + struct Client *target_p = data->target; + static char errorbuf[BUFSIZE]; + + if (data->approved) + return; + + if (allow_message(source_p, target_p)) + return; + + snprintf(errorbuf, sizeof errorbuf, form_str(ERR_NONONREG), + target_p->name); + + data->approved = ERR_NONONREG; + data->error = errorbuf; +} + +static void +h_hdl_privmsg_user(void *vdata) +{ + hook_data_privmsg_user *data = vdata; + struct Client *source_p = data->source_p; + struct Client *target_p = data->target_p; + + if (data->approved) + return; + + if (allow_message(source_p, target_p)) + return; + + if (data->msgtype == MESSAGE_TYPE_NOTICE) + return; + + sendto_one_numeric(source_p, ERR_NONONREG, form_str(ERR_NONONREG), + target_p->name); + + data->approved = ERR_NONONREG; +} + +static mapi_hfn_list_av1 um_regonlymsg_hfnlist[] = { + { "invite", h_hdl_invite }, + { "privmsg_user", h_hdl_privmsg_user }, + { NULL, NULL } +}; + +DECLARE_MODULE_AV2(um_regonlymsg, um_regonlymsg_modinit, um_regonlymsg_moddeinit, + NULL, NULL, um_regonlymsg_hfnlist, NULL, NULL, um_regonlymsg_desc);