2 * oper-override for charybdis.
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 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_kick(void *data
);
29 static void hack_can_send(void *data
);
30 static void handle_client_exit(void *data
);
32 mapi_hfn_list_av1 override_hfnlist
[] = {
33 { "umode_changed", (hookfn
) check_umode_change
},
34 { "get_channel_access", (hookfn
) hack_channel_access
},
35 { "can_join", (hookfn
) hack_can_join
},
36 { "can_kick", (hookfn
) hack_can_kick
},
37 { "can_send", (hookfn
) hack_can_send
},
38 { "client_exit", (hookfn
) handle_client_exit
},
42 #define CHFL_OVERRIDE 0x0004
43 #define IsOperOverride(x) (HasPrivilege((x), "oper:override"))
45 struct OverrideSession
{
48 struct Client
*client
;
52 rb_dlink_list overriding_opers
= { NULL
, NULL
, 0 };
55 update_session_deadline(struct Client
*source_p
, struct OverrideSession
*session_p
)
57 if (session_p
== NULL
)
61 RB_DLINK_FOREACH(n
, overriding_opers
.head
)
63 struct OverrideSession
*s
= n
->data
;
65 if (s
->client
== source_p
)
73 if (session_p
== NULL
)
75 session_p
= rb_malloc(sizeof(struct OverrideSession
));
76 session_p
->client
= source_p
;
79 session_p
->deadline
= rb_current_time() + 1800;
81 rb_dlinkDelete(&session_p
->node
, &overriding_opers
);
82 rb_dlinkAdd(session_p
, &session_p
->node
, &overriding_opers
);
86 expire_override_deadlines(void *unused
)
88 rb_dlink_node
*n
, *tn
;
90 RB_DLINK_FOREACH_SAFE(n
, tn
, overriding_opers
.head
)
92 struct OverrideSession
*session_p
= n
->data
;
94 if (session_p
->deadline
> rb_current_time())
96 else if (session_p
->deadline
< rb_current_time())
98 const char *parv
[4] = {session_p
->client
->name
, session_p
->client
->name
, "-p", NULL
};
99 user_mode(session_p
->client
, session_p
->client
, 3, parv
);
105 check_umode_change(void *vdata
)
107 hook_data_umode_changed
*data
= (hook_data_umode_changed
*)vdata
;
108 struct Client
*source_p
= data
->client
;
110 if (!MyClient(source_p
))
113 if (data
->oldumodes
& UMODE_OPER
&& !IsOper(source_p
))
114 source_p
->umodes
&= ~user_modes
['p'];
116 /* didn't change +p umode, we don't need to do anything */
117 if (!((data
->oldumodes
^ source_p
->umodes
) & user_modes
['p']))
120 if (source_p
->umodes
& user_modes
['p'])
122 if (!IsOperOverride(source_p
))
124 sendto_one_notice(source_p
, ":*** You need oper:override privilege for +p");
125 source_p
->umodes
&= ~user_modes
['p'];
129 update_session_deadline(source_p
, NULL
);
131 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
, "%s has enabled oper-override (+p)",
132 get_oper_name(source_p
));
134 else if (!(source_p
->umodes
& user_modes
['p']))
136 rb_dlink_node
*n
, *tn
;
138 RB_DLINK_FOREACH_SAFE(n
, tn
, overriding_opers
.head
)
140 struct OverrideSession
*session_p
= n
->data
;
142 if (session_p
->client
!= source_p
)
145 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
, "%s has disabled oper-override (+p)",
146 get_oper_name(session_p
->client
));
148 rb_dlinkDelete(n
, &overriding_opers
);
155 hack_channel_access(void *vdata
)
157 hook_data_channel_approval
*data
= (hook_data_channel_approval
*) vdata
;
159 if (data
->dir
== MODE_QUERY
)
162 if (data
->approved
== CHFL_CHANOP
)
165 if (data
->client
->umodes
& user_modes
['p'])
167 update_session_deadline(data
->client
, NULL
);
168 data
->approved
= CHFL_OVERRIDE
;
170 /* we only want to report modehacks, which are always non-NULL */
172 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
, "%s is using oper-override on %s (modehacking: %s)",
173 get_oper_name(data
->client
), data
->chptr
->chname
, data
->modestr
);
178 hack_can_join(void *vdata
)
180 hook_data_channel
*data
= (hook_data_channel
*) vdata
;
182 if (data
->approved
== 0)
185 if (data
->client
->umodes
& user_modes
['p'])
187 update_session_deadline(data
->client
, NULL
);
190 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
, "%s is using oper-override on %s (banwalking)",
191 get_oper_name(data
->client
), data
->chptr
->chname
);
196 hack_can_kick(void *vdata
)
198 hook_data_channel_approval
*data
= (hook_data_channel_approval
*) vdata
;
201 alevel
= get_channel_access(data
->client
, data
->chptr
, data
->msptr
, data
->dir
, NULL
);
202 if (alevel
!= CHFL_OVERRIDE
)
205 if (data
->client
->umodes
& user_modes
['p'])
207 update_session_deadline(data
->client
, NULL
);
208 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
, "%s is using oper-override on %s (KICK %s)",
209 get_oper_name(data
->client
), data
->chptr
->chname
, data
->target
->name
);
214 hack_can_send(void *vdata
)
216 hook_data_channel_approval
*data
= (hook_data_channel_approval
*) vdata
;
218 if (data
->dir
== MODE_QUERY
)
221 if (data
->approved
== CAN_SEND_NONOP
|| data
->approved
== CAN_SEND_OPV
)
224 if (data
->client
->umodes
& user_modes
['p'])
226 data
->approved
= CAN_SEND_NONOP
;
228 if (MyClient(data
->client
))
230 update_session_deadline(data
->client
, NULL
);
231 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
, "%s is using oper-override on %s (forcing message)",
232 get_oper_name(data
->client
), data
->chptr
->chname
);
238 handle_client_exit(void *vdata
)
240 hook_data_client_exit
*data
= (hook_data_client_exit
*) vdata
;
241 rb_dlink_node
*n
, *tn
;
242 struct Client
*source_p
= data
->target
;
244 RB_DLINK_FOREACH_SAFE(n
, tn
, overriding_opers
.head
)
246 struct OverrideSession
*session_p
= n
->data
;
248 if (session_p
->client
!= source_p
)
251 rb_dlinkDelete(n
, &overriding_opers
);
256 struct ev_entry
*expire_override_deadlines_ev
= NULL
;
261 /* add the usermode to the available slot */
262 user_modes
['p'] = find_umode_slot();
263 construct_umodebuf();
265 expire_override_deadlines_ev
= rb_event_add("expire_override_deadlines", expire_override_deadlines
, NULL
, 60);
273 /* disable the umode and remove it from the available list */
275 construct_umodebuf();
277 rb_event_delete(expire_override_deadlines_ev
);
280 DECLARE_MODULE_AV1(override
, _modinit
, _moddeinit
, NULL
, NULL
,
281 override_hfnlist
, NULL
);