2 * oper-override for solanum.
4 * adds usermode +p and has a timer event that is iterated over to disable
5 * usermode +p after a while...
7 * you need to have oper:override permission on the opers you want to be
8 * able to use this extension.
22 #include "privilege.h"
23 #include "s_newconf.h"
25 static const char override_desc
[] =
26 "Adds user mode +p, an operator-only user mode that grants temporary privileges to override anything";
28 static void check_umode_change(void *data
);
29 static void hack_channel_access(void *data
);
30 static void hack_can_join(void *data
);
31 static void hack_can_kick(void *data
);
32 static void hack_can_send(void *data
);
33 static void hack_can_invite(void *data
);
34 static void handle_client_exit(void *data
);
36 mapi_hfn_list_av1 override_hfnlist
[] = {
37 { "umode_changed", (hookfn
) check_umode_change
},
38 { "get_channel_access", (hookfn
) hack_channel_access
, HOOK_HIGHEST
},
39 { "can_join", (hookfn
) hack_can_join
, HOOK_HIGHEST
},
40 { "can_kick", (hookfn
) hack_can_kick
, HOOK_HIGHEST
},
41 { "can_send", (hookfn
) hack_can_send
, HOOK_HIGHEST
},
42 { "can_invite", (hookfn
) hack_can_invite
, HOOK_HIGHEST
},
43 { "client_exit", (hookfn
) handle_client_exit
},
47 #define CHFL_OVERRIDE 0x0004
48 #define IsOperOverride(x) (HasPrivilege((x), "oper:override"))
50 struct OverrideSession
{
53 struct Client
*client
;
57 rb_dlink_list overriding_opers
= { NULL
, NULL
, 0 };
60 update_session_deadline(struct Client
*source_p
)
62 struct OverrideSession
*session_p
= NULL
;
65 RB_DLINK_FOREACH(n
, overriding_opers
.head
)
67 struct OverrideSession
*s
= n
->data
;
69 if (s
->client
== source_p
)
76 if (session_p
!= NULL
)
78 rb_dlinkDelete(&session_p
->node
, &overriding_opers
);
82 session_p
= rb_malloc(sizeof(struct OverrideSession
));
83 session_p
->client
= source_p
;
86 session_p
->deadline
= rb_current_time() + 1800;
88 rb_dlinkAddTail(session_p
, &session_p
->node
, &overriding_opers
);
92 expire_override_deadlines(void *unused
)
94 rb_dlink_node
*n
, *tn
;
96 RB_DLINK_FOREACH_SAFE(n
, tn
, overriding_opers
.head
)
98 struct OverrideSession
*session_p
= n
->data
;
100 if (session_p
->deadline
>= rb_current_time())
106 const char *parv
[4] = {session_p
->client
->name
, session_p
->client
->name
, "-p", NULL
};
107 user_mode(session_p
->client
, session_p
->client
, 3, parv
);
113 check_umode_change(void *vdata
)
115 hook_data_umode_changed
*data
= (hook_data_umode_changed
*)vdata
;
116 bool changed
= false;
117 struct Client
*source_p
= data
->client
;
119 if (!MyClient(source_p
))
122 if (data
->oldumodes
& UMODE_OPER
&& !IsOper(source_p
))
123 source_p
->umodes
&= ~user_modes
['p'];
125 changed
= ((data
->oldumodes
^ source_p
->umodes
) & user_modes
['p']);
127 if (source_p
->umodes
& user_modes
['p'])
129 if (!IsOperOverride(source_p
))
131 sendto_one_notice(source_p
, ":*** You need oper:override privilege for +p");
132 source_p
->umodes
&= ~user_modes
['p'];
138 update_session_deadline(source_p
);
141 else if (changed
&& !(source_p
->umodes
& user_modes
['p']))
143 rb_dlink_node
*n
, *tn
;
145 RB_DLINK_FOREACH_SAFE(n
, tn
, overriding_opers
.head
)
147 struct OverrideSession
*session_p
= n
->data
;
149 if (session_p
->client
!= source_p
)
152 rb_dlinkDelete(n
, &overriding_opers
);
159 hack_channel_access(void *vdata
)
161 hook_data_channel_approval
*data
= (hook_data_channel_approval
*) vdata
;
163 if (data
->dir
== MODE_QUERY
)
166 if (data
->approved
== CHFL_CHANOP
)
169 if (data
->client
->umodes
& user_modes
['p'])
171 update_session_deadline(data
->client
);
172 data
->approved
= CHFL_OVERRIDE
;
174 /* we only want to report modehacks, which are always non-NULL */
176 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
, "%s is using oper-override on %s (modehacking: %s)",
177 get_oper_name(data
->client
), data
->chptr
->chname
, data
->modestr
);
182 hack_can_join(void *vdata
)
184 hook_data_channel
*data
= (hook_data_channel
*) vdata
;
186 if (data
->approved
== 0)
189 if (data
->client
->umodes
& user_modes
['p'])
191 update_session_deadline(data
->client
);
194 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
, "%s is using oper-override on %s (banwalking)",
195 get_oper_name(data
->client
), data
->chptr
->chname
);
200 hack_can_kick(void *vdata
)
202 hook_data_channel_approval
*data
= (hook_data_channel_approval
*) vdata
;
205 alevel
= get_channel_access(data
->client
, data
->chptr
, data
->msptr
, data
->dir
, NULL
);
206 if (alevel
!= CHFL_OVERRIDE
)
209 if (data
->client
->umodes
& user_modes
['p'])
211 update_session_deadline(data
->client
);
212 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
, "%s is using oper-override on %s (KICK %s)",
213 get_oper_name(data
->client
), data
->chptr
->chname
, data
->target
->name
);
218 hack_can_send(void *vdata
)
220 hook_data_channel_approval
*data
= (hook_data_channel_approval
*) vdata
;
222 if (data
->dir
== MODE_QUERY
)
225 if (data
->approved
== CAN_SEND_NONOP
|| data
->approved
== CAN_SEND_OPV
)
228 if (data
->client
->umodes
& user_modes
['p'])
230 data
->approved
= CAN_SEND_NONOP
;
232 if (MyClient(data
->client
))
234 update_session_deadline(data
->client
);
235 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
, "%s is using oper-override on %s (forcing message)",
236 get_oper_name(data
->client
), data
->chptr
->chname
);
242 hack_can_invite(void *vdata
)
244 hook_data_channel_approval
*data
= vdata
;
246 if (data
->approved
== 0)
249 if (data
->client
->umodes
& user_modes
['p'])
252 update_session_deadline(data
->client
);
253 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
, "%s is using oper-override on %s (invite: %s)",
254 get_oper_name(data
->client
), data
->chptr
->chname
, data
->target
->name
);
259 handle_client_exit(void *vdata
)
261 hook_data_client_exit
*data
= (hook_data_client_exit
*) vdata
;
262 rb_dlink_node
*n
, *tn
;
263 struct Client
*source_p
= data
->target
;
265 RB_DLINK_FOREACH_SAFE(n
, tn
, overriding_opers
.head
)
267 struct OverrideSession
*session_p
= n
->data
;
269 if (session_p
->client
!= source_p
)
272 rb_dlinkDelete(n
, &overriding_opers
);
277 struct ev_entry
*expire_override_deadlines_ev
= NULL
;
284 /* add the usermode to the available slot */
285 user_modes
['p'] = find_umode_slot();
286 construct_umodebuf();
288 RB_DLINK_FOREACH(ptr
, lclient_list
.head
)
290 struct Client
*client_p
= ptr
->data
;
291 if (IsPerson(client_p
) && (client_p
->umodes
& user_modes
['p']))
292 update_session_deadline(client_p
);
295 expire_override_deadlines_ev
= rb_event_add("expire_override_deadlines", expire_override_deadlines
, NULL
, 60);
303 rb_dlink_node
*n
, *tn
;
305 /* disable the umode and remove it from the available list */
307 construct_umodebuf();
309 RB_DLINK_FOREACH_SAFE(n
, tn
, overriding_opers
.head
)
311 rb_dlinkDelete(n
, &overriding_opers
);
315 rb_event_delete(expire_override_deadlines_ev
);
318 DECLARE_MODULE_AV2(override
, _modinit
, _moddeinit
, NULL
, NULL
,
319 override_hfnlist
, NULL
, NULL
, override_desc
);