From 3b4731951f58e980a189016383c177cb86c8e0c0 Mon Sep 17 00:00:00 2001 From: Ed Kellett Date: Thu, 22 Oct 2020 14:46:21 +0100 Subject: [PATCH] Implement oper realhost view via a hidden cap --- extensions/cap_realhost.c | 70 ++++++++++++++++++++++++++++++++------- 1 file changed, 58 insertions(+), 12 deletions(-) diff --git a/extensions/cap_realhost.c b/extensions/cap_realhost.c index 1ddf96b0..46de2532 100644 --- a/extensions/cap_realhost.c +++ b/extensions/cap_realhost.c @@ -27,31 +27,35 @@ static char cap_realhost_desc[] = "Provides the solanum.chat/realhost oper-only capability"; -static bool cap_realhost_visible(struct Client *); +static bool cap_oper_realhost_visible(struct Client *); static void cap_realhost_outbound_msgbuf(void *); static void cap_realhost_umode_changed(void *); +static void cap_realhost_cap_change(void *); static unsigned CLICAP_REALHOST; +static unsigned CLICAP_OPER_REALHOST; -static struct ClientCapability cap_realhost = { - .visible = cap_realhost_visible, +static struct ClientCapability capdata_oper_realhost = { + .visible = cap_oper_realhost_visible, }; mapi_cap_list_av2 cap_realhost_caps[] = { - { MAPI_CAP_CLIENT, "solanum.chat/realhost", &cap_realhost, &CLICAP_REALHOST }, + { MAPI_CAP_CLIENT, "solanum.chat/realhost", NULL, &CLICAP_REALHOST }, + { MAPI_CAP_CLIENT, "?oper_realhost", &capdata_oper_realhost, &CLICAP_OPER_REALHOST }, { 0, NULL, NULL, NULL }, }; mapi_hfn_list_av1 cap_realhost_hfnlist[] = { { "outbound_msgbuf", cap_realhost_outbound_msgbuf, HOOK_NORMAL }, { "umode_changed", cap_realhost_umode_changed, HOOK_MONITOR }, + { "cap_change", cap_realhost_cap_change, HOOK_MONITOR }, { NULL, NULL, 0 }, }; static bool -cap_realhost_visible(struct Client *client) +cap_oper_realhost_visible(struct Client *client) { - return HasPrivilege(client, "cap:realhost"); + return false; } static void @@ -60,14 +64,34 @@ cap_realhost_outbound_msgbuf(void *data_) hook_data *data = data_; struct MsgBuf *msgbuf = data->arg1; - if (data->client == NULL) + if (data->client == NULL || !IsPerson(data->client)) return; if (!IsIPSpoof(data->client) && !EmptyString(data->client->sockhost) && strcmp(data->client->sockhost, "0")) - msgbuf_append_tag(msgbuf, "solanum.chat/ip", data->client->sockhost, CLICAP_REALHOST); + { + if (IsDynSpoof(data->client)) + msgbuf_append_tag(msgbuf, "solanum.chat/ip", data->client->sockhost, CLICAP_OPER_REALHOST); + else + msgbuf_append_tag(msgbuf, "solanum.chat/ip", data->client->sockhost, CLICAP_REALHOST); + } if (!EmptyString(data->client->orighost)) - msgbuf_append_tag(msgbuf, "solanum.chat/realhost", data->client->orighost, CLICAP_REALHOST); + { + if (IsDynSpoof(data->client)) + msgbuf_append_tag(msgbuf, "solanum.chat/realhost", data->client->orighost, CLICAP_OPER_REALHOST); + else + msgbuf_append_tag(msgbuf, "solanum.chat/realhost", data->client->orighost, CLICAP_REALHOST); + } +} + +static inline void +update_clicap_oper_realhost(struct Client *client) +{ + client->localClient->caps &= ~CLICAP_OPER_REALHOST; + if (client->localClient->caps & CLICAP_REALHOST && HasPrivilege(client, "auspex:hostname")) + { + client->localClient->caps |= CLICAP_OPER_REALHOST; + } } static void @@ -78,8 +102,30 @@ cap_realhost_umode_changed(void *data_) if (!MyClient(data->client)) return; - if (!cap_realhost_visible(data->client)) - data->client->localClient->caps &= ~CLICAP_REALHOST; + update_clicap_oper_realhost(data->client); } -DECLARE_MODULE_AV2(cap_realhost, NULL, NULL, NULL, NULL, cap_realhost_hfnlist, cap_realhost_caps, NULL, cap_realhost_desc); +static void +cap_realhost_cap_change(void *data_) +{ + hook_data_cap_change *data = data_; + + update_clicap_oper_realhost(data->client); +} + +static int +modinit(void) +{ + rb_dlink_node *ptr; + + RB_DLINK_FOREACH(ptr, lclient_list.head) + { + struct Client *client = ptr->data; + + update_clicap_oper_realhost(client); + } + + return 0; +} + +DECLARE_MODULE_AV2(cap_realhost, modinit, NULL, NULL, NULL, cap_realhost_hfnlist, cap_realhost_caps, NULL, cap_realhost_desc);