]> jfr.im git - solanum.git/blob - extensions/cap_realhost.c
cap_realhost: Don't send realhost to non-opers
[solanum.git] / extensions / cap_realhost.c
1 /*
2 * Copyright (C) 2020 Ed Kellett
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17 * USA
18 */
19
20 #include <stdinc.h>
21 #include <modules.h>
22 #include <capability.h>
23 #include <s_serv.h>
24 #include <s_newconf.h>
25 #include <client.h>
26 #include <msgbuf.h>
27
28 static char cap_realhost_desc[] = "Provides the solanum.chat/realhost oper-only capability";
29
30 static bool cap_oper_realhost_visible(struct Client *);
31 static void cap_realhost_outbound_msgbuf(void *);
32 static void cap_realhost_umode_changed(void *);
33 static void cap_realhost_cap_change(void *);
34
35 static unsigned CLICAP_REALHOST;
36 static unsigned CLICAP_OPER_REALHOST;
37
38 static struct ClientCapability capdata_oper_realhost = {
39 .visible = cap_oper_realhost_visible,
40 };
41
42 mapi_cap_list_av2 cap_realhost_caps[] = {
43 { MAPI_CAP_CLIENT, "solanum.chat/realhost", NULL, &CLICAP_REALHOST },
44 { MAPI_CAP_CLIENT, "?oper_realhost", &capdata_oper_realhost, &CLICAP_OPER_REALHOST },
45 { 0, NULL, NULL, NULL },
46 };
47
48 mapi_hfn_list_av1 cap_realhost_hfnlist[] = {
49 { "outbound_msgbuf", cap_realhost_outbound_msgbuf, HOOK_NORMAL },
50 { "umode_changed", cap_realhost_umode_changed, HOOK_MONITOR },
51 { "cap_change", cap_realhost_cap_change, HOOK_MONITOR },
52 { NULL, NULL, 0 },
53 };
54
55 static bool
56 cap_oper_realhost_visible(struct Client *client)
57 {
58 return false;
59 }
60
61 static void
62 cap_realhost_outbound_msgbuf(void *data_)
63 {
64 hook_data *data = data_;
65 struct MsgBuf *msgbuf = data->arg1;
66
67 if (data->client == NULL || !IsPerson(data->client))
68 return;
69
70 if (!IsIPSpoof(data->client) && !EmptyString(data->client->sockhost) && strcmp(data->client->sockhost, "0"))
71 {
72 if (IsDynSpoof(data->client))
73 msgbuf_append_tag(msgbuf, "solanum.chat/ip", data->client->sockhost, CLICAP_OPER_REALHOST);
74 else
75 msgbuf_append_tag(msgbuf, "solanum.chat/ip", data->client->sockhost, CLICAP_REALHOST);
76 }
77
78 if (!EmptyString(data->client->orighost))
79 msgbuf_append_tag(msgbuf, "solanum.chat/realhost", data->client->orighost, CLICAP_OPER_REALHOST);
80 }
81
82 static inline void
83 update_clicap_oper_realhost(struct Client *client)
84 {
85 client->localClient->caps &= ~CLICAP_OPER_REALHOST;
86 if (client->localClient->caps & CLICAP_REALHOST && HasPrivilege(client, "auspex:hostname"))
87 {
88 client->localClient->caps |= CLICAP_OPER_REALHOST;
89 }
90 }
91
92 static void
93 cap_realhost_umode_changed(void *data_)
94 {
95 hook_data_umode_changed *data = data_;
96
97 if (!MyClient(data->client))
98 return;
99
100 update_clicap_oper_realhost(data->client);
101 }
102
103 static void
104 cap_realhost_cap_change(void *data_)
105 {
106 hook_data_cap_change *data = data_;
107
108 update_clicap_oper_realhost(data->client);
109 }
110
111 static int
112 modinit(void)
113 {
114 rb_dlink_node *ptr;
115
116 RB_DLINK_FOREACH(ptr, lclient_list.head)
117 {
118 struct Client *client = ptr->data;
119
120 update_clicap_oper_realhost(client);
121 }
122
123 return 0;
124 }
125
126 DECLARE_MODULE_AV2(cap_realhost, modinit, NULL, NULL, NULL, cap_realhost_hfnlist, cap_realhost_caps, NULL, cap_realhost_desc);