]> jfr.im git - solanum.git/blob - extensions/override.c
override: Send notice when overriding can_send.
[solanum.git] / extensions / override.c
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
25 static void check_umode_change(void *data);
26 static void hack_channel_access(void *data);
27 static void hack_can_join(void *data);
28 static void hack_can_send(void *data);
29 static void handle_client_exit(void *data);
30
31 mapi_hfn_list_av1 override_hfnlist[] = {
32 { "umode_changed", (hookfn) check_umode_change },
33 { "get_channel_access", (hookfn) hack_channel_access },
34 { "can_join", (hookfn) hack_can_join },
35 { "can_send", (hookfn) hack_can_send },
36 { "client_exit", (hookfn) handle_client_exit },
37 { NULL, NULL }
38 };
39
40 #define IsOperOverride(x) (HasPrivilege((x), "oper:override"))
41
42 struct OverrideSession {
43 rb_dlink_node node;
44
45 struct Client *client;
46 time_t deadline;
47 };
48
49 rb_dlink_list overriding_opers = { NULL, NULL, 0 };
50
51 static void
52 update_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
82 static void
83 expire_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
101 static void
102 check_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
110 /* didn't change +p umode, we don't need to do anything */
111 if (!((data->oldumodes ^ source_p->umodes) & user_modes['p']))
112 return;
113
114 if (!IsOperOverride(source_p))
115 {
116 sendto_one_notice(source_p, ":*** You need oper:override privilege for +p");
117 source_p->umodes &= ~user_modes['p'];
118 return;
119 }
120
121 if (source_p->umodes & user_modes['p'])
122 {
123 update_session_deadline(source_p, NULL);
124
125 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s has enabled oper-override (+p)",
126 get_oper_name(source_p));
127 }
128 else if (!(source_p->umodes & user_modes['p']))
129 {
130 rb_dlink_node *n, *tn;
131
132 RB_DLINK_FOREACH_SAFE(n, tn, overriding_opers.head)
133 {
134 struct OverrideSession *session_p = n->data;
135
136 if (session_p->client != source_p)
137 continue;
138
139 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s has disabled oper-override (+p)",
140 get_oper_name(session_p->client));
141
142 rb_dlinkDelete(n, &overriding_opers);
143 rb_free(session_p);
144 }
145 }
146 }
147
148 static void
149 hack_channel_access(void *vdata)
150 {
151 hook_data_channel_approval *data = (hook_data_channel_approval *) vdata;
152
153 if (data->approved == CHFL_CHANOP)
154 return;
155
156 if (data->client->umodes & user_modes['p'])
157 {
158 update_session_deadline(data->client, NULL);
159 data->approved = CHFL_CHANOP;
160
161 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is using oper-override on %s (modehacking)",
162 get_oper_name(data->client), data->chptr->chname);
163 }
164 }
165
166 static void
167 hack_can_join(void *vdata)
168 {
169 hook_data_channel *data = (hook_data_channel *) vdata;
170
171 if (data->approved == 0)
172 return;
173
174 if (data->client->umodes & user_modes['p'])
175 {
176 update_session_deadline(data->client, NULL);
177 data->approved = 0;
178
179 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is using oper-override on %s (banwalking)",
180 get_oper_name(data->client), data->chptr->chname);
181 }
182 }
183
184 static void
185 hack_can_send(void *vdata)
186 {
187 hook_data_channel_approval *data = (hook_data_channel_approval *) vdata;
188
189 if (data->approved == CAN_SEND_NONOP || data->approved == CAN_SEND_OPV)
190 return;
191
192 if (data->client->umodes & user_modes['p'])
193 {
194 data->approved = CAN_SEND_NONOP;
195
196 if (MyClient(data->client))
197 {
198 update_session_deadline(data->client, NULL);
199 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is using oper-override on %s (forcing message)",
200 get_oper_name(data->client), data->chptr->chname);
201 }
202 }
203 }
204
205 static void
206 handle_client_exit(void *vdata)
207 {
208 hook_data_client_exit *data = (hook_data_client_exit *) vdata;
209 rb_dlink_node *n, *tn;
210 struct Client *source_p = data->target;
211
212 RB_DLINK_FOREACH_SAFE(n, tn, overriding_opers.head)
213 {
214 struct OverrideSession *session_p = n->data;
215
216 if (session_p->client != source_p)
217 continue;
218
219 rb_dlinkDelete(n, &overriding_opers);
220 rb_free(session_p);
221 }
222 }
223
224 struct ev_entry *expire_override_deadlines_ev = NULL;
225
226 static int
227 _modinit(void)
228 {
229 /* add the usermode to the available slot */
230 user_modes['p'] = find_umode_slot();
231 construct_umodebuf();
232
233 expire_override_deadlines_ev = rb_event_add("expire_override_deadlines", expire_override_deadlines, NULL, 60);
234
235 return 0;
236 }
237
238 static void
239 _moddeinit(void)
240 {
241 /* disable the umode and remove it from the available list */
242 user_modes['p'] = 0;
243 construct_umodebuf();
244
245 rb_event_delete(expire_override_deadlines_ev);
246 }
247
248 DECLARE_MODULE_AV1(override, _modinit, _moddeinit, NULL, NULL,
249 override_hfnlist, "$Revision: 3526 $");