diff --git a/doc/reference.conf b/doc/reference.conf index 58b5fed1..e4ab5e83 100644 --- a/doc/reference.conf +++ b/doc/reference.conf @@ -47,6 +47,7 @@ * Charybdis contains several extensions that are not enabled by default. * To use them, uncomment the lines below. * + * Message tag containing a user's gateway -- cap_gateway * Channel mode +-A (admin only) -- chm_adminonly * Channel mode +-T (blocks notices) -- chm_nonotice * Channel mode +-O (oper only) -- chm_operonly @@ -58,6 +59,7 @@ * Other-channel bans (+b $c:mask) -- extb_channel * Combination extbans -- extb_combi * Extended ban (+b $x:mask) -- extb_extgecos + * Gateway bans (+b $w:gateway) -- extb_gateway * Hostmask bans (for combination extbans) -- extb_hostmask * Oper bans (+b $o) -- extb_oper * Realname (gecos) bans (+b $r:mask) -- extb_realname @@ -80,6 +82,7 @@ * Stop services kills -- no_kill_services * Allows you to hide your idle time (umode +I) -- umode_hide_idle_time */ +#loadmodule "extensions/cap_gateway"; #loadmodule "extensions/chm_adminonly"; #loadmodule "extensions/chm_nonotice"; #loadmodule "extensions/chm_operonly"; @@ -91,6 +94,7 @@ #loadmodule "extensions/extb_channel"; #loadmodule "extensions/extb_combi"; #loadmodule "extensions/extb_extgecos"; +#loadmodule "extensions/extb_gateway"; #loadmodule "extensions/extb_hostmask"; #loadmodule "extensions/extb_oper"; #loadmodule "extensions/extb_realname"; @@ -377,6 +381,12 @@ auth { * just do everyone a favour and dont abuse it. (OLD I: = flag) */ spoof = "I.still.hate.packets"; + + /* gateway: identifies the gateway this auth block belongs to + * and is displayed in WHOIS for all users connecting through + * this auth block + */ + gateway = "matrix"; /* Possible flags in auth: * diff --git a/extensions/Makefile.am b/extensions/Makefile.am index b09e1824..aa17673a 100644 --- a/extensions/Makefile.am +++ b/extensions/Makefile.am @@ -19,6 +19,7 @@ extension_LTLIBRARIES = \ extb_account.la \ extb_canjoin.la \ extb_channel.la \ + extb_gateway.la \ extb_guest.la \ extb_hostmask.la \ extb_oper.la \ @@ -67,6 +68,7 @@ extension_LTLIBRARIES = \ drain.la \ identify_msg.la \ cap_realhost.la \ + cap_gateway.la \ invex_regonly.la \ umode_hide_idle_time.la \ cap_oper.la \ diff --git a/extensions/cap_gateway.c b/extensions/cap_gateway.c new file mode 100644 index 00000000..b7372c95 --- /dev/null +++ b/extensions/cap_gateway.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2021 David Schultz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include +#include +#include +#include +#include +#include +#include + +static char cap_gateway_desc[] = "Provides the solanum.chat/gateway capability"; + +static void cap_gateway_outbound_msgbuf(void *); + +static unsigned CLICAP_GATEWAY; + +mapi_cap_list_av2 cap_gateway_caps[] = { + { MAPI_CAP_CLIENT, "solanum.chat/gateway", NULL, &CLICAP_GATEWAY }, + { 0, NULL, NULL, NULL } +}; + +mapi_hfn_list_av1 cap_gateway_hfnlist[] = { + { "outbound_msgbuf", cap_gateway_outbound_msgbuf, HOOK_NORMAL }, + { NULL, NULL, 0 } +}; + + +static void +cap_gateway_outbound_msgbuf(void *data_) +{ + hook_data *data = data_; + struct MsgBuf *msgbuf = data->arg1; + + if (data->client == NULL || !IsPerson(data->client)) + return; + + if (!EmptyString(data->client->gateway)) + msgbuf_append_tag(msgbuf, "solanum.chat/gateway", data->client->gateway, CLICAP_GATEWAY); +} + +DECLARE_MODULE_AV2(cap_gateway, NULL, NULL, NULL, NULL, cap_gateway_hfnlist, cap_gateway_caps, NULL, cap_gateway_desc); diff --git a/extensions/extb_gateway.c b/extensions/extb_gateway.c new file mode 100644 index 00000000..3f7338d5 --- /dev/null +++ b/extensions/extb_gateway.c @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2021 David Schultz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + +#include "stdinc.h" +#include "modules.h" +#include "client.h" +#include "ircd.h" + +static const char extb_desc[] = "Gateway name ($w) extban type"; + +static int _modinit(void); +static void _moddeinit(void); +static int eb_gateway(const char *data, struct Client *client_p, struct Channel *chptr, long mode_type); + +DECLARE_MODULE_AV2(extb_gateway, _modinit, _moddeinit, NULL, NULL, NULL, NULL, NULL, extb_desc); + +static int +_modinit(void) +{ + extban_table['w'] = eb_gateway; + + return 0; +} + +static void +_moddeinit(void) +{ + extban_table['w'] = NULL; +} + +static int eb_gateway(const char *data, struct Client *client_p, + struct Channel *chptr, long mode_type) +{ + /* $w by itself will match all gateway users */ + if (data == NULL) + return EmptyString(client_p->gateway) ? EXTBAN_NOMATCH : EXTBAN_MATCH; + return match(data, client_p->gateway) ? EXTBAN_MATCH : EXTBAN_NOMATCH; +} diff --git a/include/client.h b/include/client.h index 2d61d5f9..bac349f1 100644 --- a/include/client.h +++ b/include/client.h @@ -135,6 +135,7 @@ struct Client char orighost[HOSTLEN + 1]; /* original hostname (before dynamic spoofing) */ char sockhost[HOSTIPLEN + 1]; /* clients ip */ char info[REALLEN + 1]; /* Free form additional client info */ + char gateway[REALLEN + 1]; /* name of the gateway in i:line */ char id[IDLEN]; /* UID/SID, unique on the network */ diff --git a/include/messages.h b/include/messages.h index 0130111e..5358ab53 100644 --- a/include/messages.h +++ b/include/messages.h @@ -96,6 +96,7 @@ #define NUMERIC_STR_317 "%s %ld %lu :seconds idle, signon time" #define NUMERIC_STR_318 "%s :End of /WHOIS list." #define NUMERIC_STR_319 ":%s 319 %s %s :" +#define NUMERIC_STR_320 "%s :is using gateway: %s" #define NUMERIC_STR_321 ":%s 321 %s Channel :Users Name" #define NUMERIC_STR_322 ":%s 322 %s %s%s %lu :%s" #define NUMERIC_STR_323 ":%s 323 %s :End of /LIST" diff --git a/include/numeric.h b/include/numeric.h index dcabff61..edc97586 100644 --- a/include/numeric.h +++ b/include/numeric.h @@ -144,6 +144,7 @@ #define RPL_ENDOFWHOIS 318 #define RPL_WHOISCHANNELS 319 +#define RPL_WHOISGATEWAY 320 #define RPL_LISTSTART 321 #define RPL_LIST 322 diff --git a/include/s_conf.h b/include/s_conf.h index 53233ee1..29e07d20 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -74,6 +74,7 @@ struct ConfItem struct Class *c_class; /* Class of connection */ rb_patricia_node_t *pnode; /* Our patricia node */ int umodes, umodes_mask; /* Override umodes specified by mask */ + char *gateway; }; #define CONF_ILLEGAL 0x80000000 diff --git a/ircd/newconf.c b/ircd/newconf.c index 33bfd4d1..02b1880d 100644 --- a/ircd/newconf.c +++ b/ircd/newconf.c @@ -1245,6 +1245,12 @@ conf_set_auth_umodes(void *data) parse_umodes(umodes, &yy_aconf->umodes, &yy_aconf->umodes_mask); } +static void +conf_set_auth_gateway(void *data) +{ + yy_aconf->gateway = rb_strdup(data); +} + static int conf_begin_connect(struct TopConf *tc) { @@ -2673,6 +2679,7 @@ static struct ConfEntry conf_auth_table[] = { "redirport", CF_INT, conf_set_auth_redir_port, 0, NULL }, { "flags", CF_STRING | CF_FLIST, conf_set_auth_flags, 0, NULL }, { "umodes", CF_QSTRING, conf_set_auth_umodes, 0, NULL}, + { "gateway", CF_QSTRING, conf_set_auth_gateway, 0, NULL}, { "description",CF_QSTRING, conf_set_auth_desc, 0, NULL}, { "\0", 0, NULL, 0, NULL } }; diff --git a/ircd/s_user.c b/ircd/s_user.c index 48acff5b..0bf0ea9b 100644 --- a/ircd/s_user.c +++ b/ircd/s_user.c @@ -648,6 +648,11 @@ register_local_user(struct Client *client_p, struct Client *source_p) SetDynSpoof(source_p); } + if (!EmptyString(aconf->gateway)) + { + rb_strlcpy(source_p->gateway, aconf->gateway, REALLEN + 1); + } + umodes = ConfigFileEntry.default_umodes & ~aconf->umodes_mask; umodes |= aconf->umodes; umodes &= ~ConfigFileEntry.oper_only_umodes; diff --git a/modules/m_who.c b/modules/m_who.c index d47d44bb..94b6a5f7 100644 --- a/modules/m_who.c +++ b/modules/m_who.c @@ -53,6 +53,7 @@ #define FIELD_USER 0x0400 #define FIELD_ACCOUNT 0x0800 #define FIELD_OPLEVEL 0x1000 /* meaningless and stupid, but whatever */ +#define FIELD_GATEWAY 0x2000 static const char who_desc[] = "Provides the WHO command to display information for users on a channel"; @@ -143,6 +144,7 @@ m_who(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, case 'u': fmt.fields |= FIELD_USER; break; case 'a': fmt.fields |= FIELD_ACCOUNT; break; case 'o': fmt.fields |= FIELD_OPLEVEL; break; + case 'w': fmt.fields |= FIELD_GATEWAY; break; case ',': s++; fmt.querytype = s; @@ -496,6 +498,7 @@ do_who(struct Client *source_p, struct Client *target_p, struct membership *mspt char str[510 + 1]; /* linebuf.c will add \r\n */ size_t pos; const char *q; + const char *w; sprintf(status, "%c%s%s", target_p->user->away ? 'G' : 'H', SeesOper(target_p, source_p) ? "*" : "", msptr ? find_channel_status(msptr, fmt->fields || IsCapable(source_p, CLICAP_MULTI_PREFIX)) : ""); @@ -565,6 +568,21 @@ do_who(struct Client *source_p, struct Client *target_p, struct membership *mspt q = "0"; append_format(str, sizeof str, &pos, " %s", q); } + if (fmt->fields & FIELD_GATEWAY) + { + /* use same the logic as account */ + w = target_p->gateway; + if (!EmptyString(w)) + { + while(IsDigit(*w)) + w++; + if(*w == '\0') + w = target_p->gateway; + } + else + w = "0"; + append_format(str, sizeof str, &pos, " %s", w); + } if (fmt->fields & FIELD_OPLEVEL) append_format(str, sizeof str, &pos, " %s", is_chanop(msptr) ? "999" : "n/a"); if (fmt->fields & FIELD_INFO) diff --git a/modules/m_whois.c b/modules/m_whois.c index 117acadb..1feecc01 100644 --- a/modules/m_whois.c +++ b/modules/m_whois.c @@ -375,6 +375,13 @@ single_whois(struct Client *source_p, struct Client *target_p, int operspy) target_p->name, buf); } + if (!EmptyString(target_p->gateway)) + { + sendto_one_numeric(source_p, RPL_WHOISGATEWAY, + form_str(RPL_WHOISGATEWAY), + target_p->name, target_p->gateway); + } + /* fire the doing_whois_show_idle hook to allow modules to tell us whether to show the idle time */ hook_data_client_approval hdata_showidle;