1 /* groupserv - group services.
2 * Copyright (C) 2010 Atheme Development Group
3 */
4
5 #include "groupserv_main.h"
6
mygroup_expire(void * unused)7 static void mygroup_expire(void *unused)
8 {
9 myentity_t *mt;
10 myentity_iteration_state_t state;
11
12 MYENTITY_FOREACH_T(mt, &state, ENT_GROUP)
13 {
14 mygroup_t *mg = group(mt);
15
16 continue_if_fail(mt != NULL);
17 continue_if_fail(mg != NULL);
18
19 if (!mygroup_count_flag(mg, GA_FOUNDER))
20 {
21 remove_group_chanacs(mg);
22 object_unref(mg);
23 }
24 }
25 }
26
grant_channel_access_hook(user_t * u)27 static void grant_channel_access_hook(user_t *u)
28 {
29 mowgli_node_t *n, *tn;
30 mowgli_list_t *l;
31
32 return_if_fail(u->myuser != NULL);
33
34 l = myentity_get_membership_list(entity(u->myuser));
35
36 MOWGLI_ITER_FOREACH_SAFE(n, tn, l->head)
37 {
38 groupacs_t *ga = n->data;
39
40 if (!(ga->flags & GA_CHANACS))
41 continue;
42
43 MOWGLI_ITER_FOREACH(n, entity(ga->mg)->chanacs.head)
44 {
45 chanacs_t *ca;
46 chanuser_t *cu;
47
48 ca = (chanacs_t *)n->data;
49
50 if (ca->mychan->chan == NULL)
51 continue;
52
53 cu = chanuser_find(ca->mychan->chan, u);
54 if (cu && chansvs.me != NULL)
55 {
56 if (ca->level & CA_AKICK && !(ca->level & CA_EXEMPT))
57 {
58 /* Stay on channel if this would empty it -- jilles */
59 if (ca->mychan->chan->nummembers - ca->mychan->chan->numsvcmembers == 1)
60 {
61 ca->mychan->flags |= MC_INHABIT;
62 if (ca->mychan->chan->numsvcmembers == 0)
63 join(cu->chan->name, chansvs.nick);
64 }
65 ban(chansvs.me->me, ca->mychan->chan, u);
66 remove_ban_exceptions(chansvs.me->me, ca->mychan->chan, u);
67 kick(chansvs.me->me, ca->mychan->chan, u, "User is banned from this channel");
68 continue;
69 }
70
71 if (ca->level & CA_USEDUPDATE)
72 ca->mychan->used = CURRTIME;
73
74 if (ca->mychan->flags & MC_NOOP || u->myuser->flags & MU_NOOP)
75 continue;
76
77 if (ircd->uses_owner && !(cu->modes & ircd->owner_mode) && ca->level & CA_AUTOOP && ca->level & CA_USEOWNER)
78 {
79 modestack_mode_param(chansvs.nick, ca->mychan->chan, MTYPE_ADD, ircd->owner_mchar[1], CLIENT_NAME(u));
80 cu->modes |= ircd->owner_mode;
81 }
82
83 if (ircd->uses_protect && !(cu->modes & ircd->protect_mode) && !(ircd->uses_owner && cu->modes & ircd->owner_mode) && ca->level & CA_AUTOOP && ca->level & CA_USEPROTECT)
84 {
85 modestack_mode_param(chansvs.nick, ca->mychan->chan, MTYPE_ADD, ircd->protect_mchar[1], CLIENT_NAME(u));
86 cu->modes |= ircd->protect_mode;
87 }
88
89 if (!(cu->modes & CSTATUS_OP) && ca->level & CA_AUTOOP)
90 {
91 modestack_mode_param(chansvs.nick, ca->mychan->chan, MTYPE_ADD, 'o', CLIENT_NAME(u));
92 cu->modes |= CSTATUS_OP;
93 }
94
95 if (ircd->uses_halfops && !(cu->modes & (CSTATUS_OP | ircd->halfops_mode)) && ca->level & CA_AUTOHALFOP)
96 {
97 modestack_mode_param(chansvs.nick, ca->mychan->chan, MTYPE_ADD, 'h', CLIENT_NAME(u));
98 cu->modes |= ircd->halfops_mode;
99 }
100
101 if (!(cu->modes & (CSTATUS_OP | ircd->halfops_mode | CSTATUS_VOICE)) && ca->level & CA_AUTOVOICE)
102 {
103 modestack_mode_param(chansvs.nick, ca->mychan->chan, MTYPE_ADD, 'v', CLIENT_NAME(u));
104 cu->modes |= CSTATUS_VOICE;
105 }
106 }
107 }
108 }
109 }
110
user_info_hook(hook_user_req_t * req)111 static void user_info_hook(hook_user_req_t *req)
112 {
113 static char buf[BUFSIZE];
114 mowgli_node_t *n;
115 mowgli_list_t *l;
116
117 *buf = 0;
118
119 l = myentity_get_membership_list(entity(req->mu));
120
121 MOWGLI_ITER_FOREACH(n, l->head)
122 {
123 groupacs_t *ga = n->data;
124
125 if (ga->flags & GA_BAN)
126 continue;
127
128 if ((ga->mg->flags & MG_PUBLIC) || (req->si->smu == req->mu || has_priv(req->si, PRIV_GROUP_AUSPEX)))
129 {
130 if (*buf != 0)
131 mowgli_strlcat(buf, ", ", BUFSIZE);
132
133 mowgli_strlcat(buf, entity(ga->mg)->name, BUFSIZE);
134 }
135 }
136
137 if (*buf != 0)
138 command_success_nodata(req->si, _("Groups : %s"), buf);
139 }
140
sasl_may_impersonate_hook(hook_sasl_may_impersonate_t * req)141 static void sasl_may_impersonate_hook(hook_sasl_may_impersonate_t *req)
142 {
143 char priv[BUFSIZE];
144 mowgli_list_t *l;
145 mowgli_node_t *n;
146
147 /* if the request is already granted, don't bother doing any of this. */
148 if (req->allowed)
149 return;
150
151 l = myentity_get_membership_list(entity(req->target_mu));
152
153 MOWGLI_ITER_FOREACH(n, l->head)
154 {
155 groupacs_t *ga = n->data;
156
157 snprintf(priv, sizeof(priv), PRIV_IMPERSONATE_ENTITY_FMT, entity(ga->mg)->name);
158
159 if (has_priv_myuser(req->source_mu, priv))
160 {
161 req->allowed = true;
162 return;
163 }
164 }
165 }
166
myuser_delete_hook(myuser_t * mu)167 static void myuser_delete_hook(myuser_t *mu)
168 {
169 mowgli_node_t *n, *tn;
170 mowgli_list_t *l;
171
172 l = myentity_get_membership_list(entity(mu));
173
174 MOWGLI_ITER_FOREACH_SAFE(n, tn, l->head)
175 {
176 groupacs_t *ga = n->data;
177
178 groupacs_delete(ga->mg, ga->mt);
179 }
180
181 mowgli_list_free(l);
182 }
183
osinfo_hook(sourceinfo_t * si)184 static void osinfo_hook(sourceinfo_t *si)
185 {
186 return_if_fail(si != NULL);
187
188 command_success_nodata(si, "Maximum number of groups one user can own: %u", gs_config.maxgroups);
189 command_success_nodata(si, "Maximum number of ACL entries allowed for one group: %u", gs_config.maxgroupacs);
190 command_success_nodata(si, "Are open groups allowed: %s", gs_config.enable_open_groups ? "Yes" : "No");
191 command_success_nodata(si, "Default joinflags for open groups: %s", gs_config.join_flags);
192 }
193
194 static mowgli_eventloop_timer_t *mygroup_expire_timer = NULL;
195
gs_hooks_init(void)196 void gs_hooks_init(void)
197 {
198 mygroup_expire_timer = mowgli_timer_add(base_eventloop, "mygroup_expire", mygroup_expire, NULL, 3600);
199
200 hook_add_event("myuser_delete");
201 hook_add_event("user_info");
202 hook_add_event("grant_channel_access");
203 hook_add_event("operserv_info");
204 hook_add_event("sasl_may_impersonate");
205
206 hook_add_user_info(user_info_hook);
207 hook_add_myuser_delete(myuser_delete_hook);
208 hook_add_grant_channel_access(grant_channel_access_hook);
209 hook_add_operserv_info(osinfo_hook);
210 hook_add_sasl_may_impersonate(sasl_may_impersonate_hook);
211 }
212
gs_hooks_deinit(void)213 void gs_hooks_deinit(void)
214 {
215 mowgli_timer_destroy(base_eventloop, mygroup_expire_timer);
216
217 hook_del_user_info(user_info_hook);
218 hook_del_myuser_delete(myuser_delete_hook);
219 hook_del_grant_channel_access(grant_channel_access_hook);
220 hook_del_operserv_info(osinfo_hook);
221 hook_del_sasl_may_impersonate(sasl_may_impersonate_hook);
222 }
223