]> jfr.im git - solanum.git/blame - extensions/override.c
ircd/dns: same
[solanum.git] / extensions / override.c
CommitLineData
429cf1b7
AC
1/*
2 * oper-override for charybdis.
3 *
4 * adds usermode +p and has a timer event that is iterated over to disable
5 * usermode +p after a while...
6 *
7 * you need to have oper:override permission on the opers you want to be
8 * able to use this extension.
9 */
10
11#include "stdinc.h"
12#include "modules.h"
13#include "hook.h"
14#include "client.h"
15#include "ircd.h"
16#include "send.h"
17#include "hash.h"
18#include "s_conf.h"
19#include "s_user.h"
20#include "s_serv.h"
21#include "numeric.h"
22#include "privilege.h"
23#include "s_newconf.h"
24
25static void check_umode_change(void *data);
26static void hack_channel_access(void *data);
d3076881 27static void hack_can_join(void *data);
9101dbcd 28static void hack_can_send(void *data);
5c3014d0 29static void handle_client_exit(void *data);
429cf1b7
AC
30
31mapi_hfn_list_av1 override_hfnlist[] = {
32 { "umode_changed", (hookfn) check_umode_change },
33 { "get_channel_access", (hookfn) hack_channel_access },
d3076881 34 { "can_join", (hookfn) hack_can_join },
9101dbcd 35 { "can_send", (hookfn) hack_can_send },
5c3014d0 36 { "client_exit", (hookfn) handle_client_exit },
429cf1b7
AC
37 { NULL, NULL }
38};
39
40#define IsOperOverride(x) (HasPrivilege((x), "oper:override"))
41
42struct OverrideSession {
43 rb_dlink_node node;
44
45 struct Client *client;
46 time_t deadline;
47};
48
49rb_dlink_list overriding_opers = { NULL, NULL, 0 };
50
51static void
52update_session_deadline(struct Client *source_p, struct OverrideSession *session_p)
53{
54 if (session_p == NULL)
55 {
56 rb_dlink_node *n;
57
58 RB_DLINK_FOREACH(n, overriding_opers.head)
59 {
60 struct OverrideSession *s = n->data;
61
62 if (s->client == source_p)
63 {
64 session_p = s;
65 break;
66 }
67 }
68 }
69
70 if (session_p == NULL)
71 {
72 session_p = rb_malloc(sizeof(struct OverrideSession));
73 session_p->client = source_p;
74 }
75
76 session_p->deadline = rb_current_time() + 1800;
77
78 rb_dlinkDelete(&session_p->node, &overriding_opers);
79 rb_dlinkAdd(session_p, &session_p->node, &overriding_opers);
80}
81
82static void
83expire_override_deadlines(void *unused)
84{
85 rb_dlink_node *n, *tn;
86
87 RB_DLINK_FOREACH_SAFE(n, tn, overriding_opers.head)
88 {
89 struct OverrideSession *session_p = n->data;
90
91 if (session_p->deadline > rb_current_time())
92 break;
93 else if (session_p->deadline < rb_current_time())
94 {
95 const char *parv[4] = {session_p->client->name, session_p->client->name, "-p", NULL};
96 user_mode(session_p->client, session_p->client, 3, parv);
97 }
98 }
99}
100
101static void
102check_umode_change(void *vdata)
103{
104 hook_data_umode_changed *data = (hook_data_umode_changed *)vdata;
105 struct Client *source_p = data->client;
106
107 if (!MyClient(source_p))
108 return;
109
e5c254d7
JT
110 if (data->oldumodes & UMODE_OPER && !IsOper(source_p))
111 source_p->umodes &= ~user_modes['p'];
112
429cf1b7
AC
113 /* didn't change +p umode, we don't need to do anything */
114 if (!((data->oldumodes ^ source_p->umodes) & user_modes['p']))
115 return;
116
429cf1b7
AC
117 if (source_p->umodes & user_modes['p'])
118 {
e5c254d7
JT
119 if (!IsOperOverride(source_p))
120 {
121 sendto_one_notice(source_p, ":*** You need oper:override privilege for +p");
122 source_p->umodes &= ~user_modes['p'];
123 return;
124 }
125
429cf1b7
AC
126 update_session_deadline(source_p, NULL);
127
128 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s has enabled oper-override (+p)",
129 get_oper_name(source_p));
130 }
131 else if (!(source_p->umodes & user_modes['p']))
132 {
133 rb_dlink_node *n, *tn;
134
135 RB_DLINK_FOREACH_SAFE(n, tn, overriding_opers.head)
136 {
137 struct OverrideSession *session_p = n->data;
138
139 if (session_p->client != source_p)
140 continue;
141
142 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s has disabled oper-override (+p)",
143 get_oper_name(session_p->client));
144
145 rb_dlinkDelete(n, &overriding_opers);
146 rb_free(session_p);
147 }
148 }
149}
150
151static void
152hack_channel_access(void *vdata)
153{
154 hook_data_channel_approval *data = (hook_data_channel_approval *) vdata;
155
202d4966
AC
156 if (data->dir == MODE_QUERY)
157 return;
158
429cf1b7
AC
159 if (data->approved == CHFL_CHANOP)
160 return;
161
162 if (data->client->umodes & user_modes['p'])
163 {
164 update_session_deadline(data->client, NULL);
165 data->approved = CHFL_CHANOP;
166
167 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is using oper-override on %s (modehacking)",
168 get_oper_name(data->client), data->chptr->chname);
169 }
170}
171
d3076881
AC
172static void
173hack_can_join(void *vdata)
174{
175 hook_data_channel *data = (hook_data_channel *) vdata;
176
177 if (data->approved == 0)
178 return;
179
180 if (data->client->umodes & user_modes['p'])
181 {
182 update_session_deadline(data->client, NULL);
183 data->approved = 0;
184
185 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is using oper-override on %s (banwalking)",
186 get_oper_name(data->client), data->chptr->chname);
187 }
188}
189
9101dbcd
AC
190static void
191hack_can_send(void *vdata)
192{
193 hook_data_channel_approval *data = (hook_data_channel_approval *) vdata;
194
202d4966
AC
195 if (data->dir == MODE_QUERY)
196 return;
197
9101dbcd
AC
198 if (data->approved == CAN_SEND_NONOP || data->approved == CAN_SEND_OPV)
199 return;
200
201 if (data->client->umodes & user_modes['p'])
202 {
0d165b52 203 data->approved = CAN_SEND_NONOP;
9101dbcd 204
b4cdedaa
JT
205 if (MyClient(data->client))
206 {
207 update_session_deadline(data->client, NULL);
208 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is using oper-override on %s (forcing message)",
209 get_oper_name(data->client), data->chptr->chname);
210 }
9101dbcd
AC
211 }
212}
213
5c3014d0
AC
214static void
215handle_client_exit(void *vdata)
216{
217 hook_data_client_exit *data = (hook_data_client_exit *) vdata;
218 rb_dlink_node *n, *tn;
219 struct Client *source_p = data->target;
220
221 RB_DLINK_FOREACH_SAFE(n, tn, overriding_opers.head)
222 {
223 struct OverrideSession *session_p = n->data;
224
225 if (session_p->client != source_p)
226 continue;
227
228 rb_dlinkDelete(n, &overriding_opers);
229 rb_free(session_p);
55abcbb2 230 }
5c3014d0
AC
231}
232
429cf1b7
AC
233struct ev_entry *expire_override_deadlines_ev = NULL;
234
235static int
236_modinit(void)
237{
238 /* add the usermode to the available slot */
239 user_modes['p'] = find_umode_slot();
240 construct_umodebuf();
241
242 expire_override_deadlines_ev = rb_event_add("expire_override_deadlines", expire_override_deadlines, NULL, 60);
243
244 return 0;
245}
246
247static void
248_moddeinit(void)
249{
250 /* disable the umode and remove it from the available list */
251 user_modes['p'] = 0;
252 construct_umodebuf();
253
254 rb_event_delete(expire_override_deadlines_ev);
255}
256
257DECLARE_MODULE_AV1(override, _modinit, _moddeinit, NULL, NULL,
258 override_hfnlist, "$Revision: 3526 $");