]> jfr.im git - irc/quakenet/newserv.git/blame - glines/glines.c
Clean up gline_activate and gline_deactivate.
[irc/quakenet/newserv.git] / glines / glines.c
CommitLineData
8f128e0d 1#include <stdio.h>
a44fc5f7
GB
2#include <string.h>
3#include <assert.h>
a473a1be 4#include "../lib/irc_string.h"
c4610da5 5#include "../lib/version.h"
580103bc 6#include "../core/schedule.h"
813c5b73 7#include "../irc/irc.h"
813c5b73 8#include "../trusts/trusts.h"
a473a1be 9#include "../control/control.h"
813c5b73
CP
10#include "glines.h"
11
c4610da5
GB
12MODULE_VERSION("");
13
580103bc
GB
14static void glines_sched_save(void *arg);
15
a44fc5f7
GB
16void _init() {
17 /* If we're connected to IRC, force a disconnect. */
18 if (connected) {
c684f472
GB
19 irc_send("%s SQ %s 0 :Resync [adding gline support]", mynumeric->content, myserver->content);
20 irc_disconnected();
a44fc5f7
GB
21 }
22
23 registerserverhandler("GL", handleglinemsg, 6);
24 registerhook(HOOK_CORE_STATSREQUEST, handleglinestats);
580103bc
GB
25
26 schedulerecurring(time(NULL), 0, GLSTORE_SAVE_INTERVAL, &glines_sched_save, NULL);
27
28 glstore_load();
a44fc5f7
GB
29}
30
31void _fini() {
32 deregisterserverhandler("GL", handleglinemsg);
33 deregisterhook(HOOK_CORE_STATSREQUEST, handleglinestats);
580103bc
GB
34
35 deleteschedule(NULL, glines_sched_save, NULL);
36}
37
38static void glines_sched_save(void *arg) {
39 glstore_save();
a44fc5f7
GB
40}
41
c684f472
GB
42int gline_match_nick(gline *gl, nick *np) {
43 if (gl->flags & GLINE_BADCHAN)
44 return 0;
45
46 if (gl->flags & GLINE_REALNAME) {
96662a86 47 if (gl->user && match(gl->user->content, np->realname->name->content) != 0)
c684f472
GB
48 return 0;
49
50 return 1;
51 }
52
53 if (gl->nick && match(gl->nick->content, np->nick) != 0)
54 return 0;
55
56 if (gl->user && match(gl->user->content, np->ident) != 0)
57 return 0;
58
59 if (gl->flags & GLINE_IPMASK) {
60 if (!ipmask_check(&gl->ip, &np->p_ipaddr, gl->bits))
61 return 0;
62 } else {
63 if (gl->host && match(gl->host->content, np->host->name->content) != 0)
64 return 0;
65 }
66
67 return 1;
68}
69
70int gline_match_channel(gline *gl, channel *cp) {
71 if (!(gl->flags & GLINE_BADCHAN))
72 return 0;
73
74 if (match(gl->user->content, cp->index->name->content) != 0)
75 return 0;
76
77 return 1;
78}
79
96662a86 80gline *findgline(const char *mask) {
c684f472 81 gline *gl, *next;
a44fc5f7
GB
82 gline *globalgline;
83 time_t curtime = time(0);
84
c684f472
GB
85 globalgline = makegline(mask);
86
87 if (!globalgline)
88 return NULL; /* gline mask couldn't be processed */
a44fc5f7 89
c684f472
GB
90 for (gl = glinelist; gl; gl = next) {
91 next = gl->next;
a44fc5f7
GB
92
93 if (gl->lifetime <= curtime) {
94 removegline(gl);
95 continue;
96 } else if (gl->expire <= curtime) {
97 gl->flags &= ~GLINE_ACTIVE;
98 }
99
100 if (glineequal(globalgline, gl)) {
101 freegline(globalgline);
102 return gl;
103 }
104 }
105
106 freegline(globalgline);
107 return 0;
108}
109
331ecd41 110void gline_activate(gline *agline, time_t lastmod, int propagate) {
a44fc5f7
GB
111 time_t now = getnettime();
112 agline->flags |= GLINE_ACTIVE;
113
331ecd41 114 if (lastmod)
a44fc5f7 115 agline->lastmod = lastmod;
331ecd41
GB
116 else if (now <= agline->lastmod)
117 agline->lastmod++;
118 else
119 agline->lastmod = now;
a44fc5f7
GB
120
121 if (propagate)
122 gline_propagate(agline);
a44fc5f7
GB
123}
124
331ecd41 125void gline_deactivate(gline *agline, time_t lastmod, int propagate) {
a44fc5f7
GB
126 time_t now = getnettime();
127 agline->flags &= ~GLINE_ACTIVE;
128
331ecd41 129 if (lastmod)
a44fc5f7 130 agline->lastmod = lastmod;
331ecd41
GB
131 else if (now <= agline->lastmod)
132 agline->lastmod++;
133 else
134 agline->lastmod = now;
a44fc5f7
GB
135
136 if (propagate)
137 gline_propagate(agline);
a44fc5f7
GB
138}
139
140void gline_propagate(gline *agline) {
141 if (agline->flags & GLINE_ACTIVE) {
5649ec17 142 controlwall(NO_OPER, NL_GLINES, "Activating G-Line on '%s' lasting %s with reason '%s', created by: %s",
c684f472
GB
143 glinetostring(agline), longtoduration(agline->expire-getnettime(), 0),
144 agline->reason->content, agline->creator->content);
5649ec17 145
cb581522 146#if 1
c684f472
GB
147 irc_send("%s GL * +%s %lu %lu :%s\r\n", mynumeric->content,
148 glinetostring(agline), agline->expire - getnettime(),
149 agline->lastmod, agline->reason->content);
cb581522 150#else
5649ec17
GB
151 controlwall(NO_OPER, NL_GLINES, "%s GL * +%s %lu %lu :%s\r\n", mynumeric->content,
152 glinetostring(agline), agline->expire - getnettime(),
153 agline->lastmod, agline->reason->content);
cb581522 154#endif
a44fc5f7 155 } else {
5649ec17
GB
156 controlwall(NO_OPER, NL_GLINES, "Deactivating G-Line on '%s'",
157 glinetostring(agline));
158
cb581522 159#if 1
c684f472
GB
160 irc_send("%s GL * -%s %lu %lu :%s\r\n", mynumeric->content,
161 glinetostring(agline), agline->expire - getnettime(),
162 agline->lastmod, agline->reason->content);
cb581522 163#else
5649ec17
GB
164 controlwall(NO_OPER, NL_GLINES, "%s GL * -%s %lu %lu :%s\r\n", mynumeric->content,
165 glinetostring(agline), agline->expire - getnettime(),
166 agline->lastmod, agline->reason->content);
cb581522 167#endif
a44fc5f7
GB
168 }
169}
170
171/* returns non-zero if the glines are exactly the same */
172int glineequal(gline *gla, gline *glb) {
c684f472 173 if ((gla->flags & GLINE_BADCHAN) != (glb->flags & GLINE_BADCHAN))
a44fc5f7
GB
174 return 0;
175
c684f472 176 if ((gla->flags & GLINE_REALNAME) != (glb->flags & GLINE_REALNAME))
a44fc5f7
GB
177 return 0;
178
c684f472
GB
179 if ((gla->flags & GLINE_IPMASK) != (glb->flags & GLINE_IPMASK))
180 return 0;
181
182 if ((!gla->nick && glb->nick) || (gla->nick && !glb->nick))
a44fc5f7
GB
183 return 0;
184
c684f472 185 if (gla->nick && ircd_strcmp(gla->nick->content, glb->nick->content) != 0)
a44fc5f7
GB
186 return 0;
187
c684f472 188 if ((!gla->user && glb->user) || (gla->user && !glb->user))
a44fc5f7
GB
189 return 0;
190
c684f472 191 if (gla->user && ircd_strcmp(gla->user->content, glb->user->content) != 0)
a44fc5f7
GB
192 return 0;
193
c684f472
GB
194 if (gla->flags & GLINE_IPMASK) {
195 if (gla->bits != glb->bits)
196 return 0;
197
198 if (!ipmask_check(&gla->ip, &glb->ip, gla->bits))
199 return 0;
200 } else {
201 if ((!gla->host && glb->host) || (gla->host && !glb->host))
202 return 0;
203
204 if (gla->host && ircd_strcmp(gla->host->content, glb->host->content) != 0)
205 return 0;
206 }
207
a44fc5f7
GB
208 return 1;
209}
210
211/* returns non-zero on match */
c684f472
GB
212int gline_match_mask(gline *gla, gline *glb) {
213 if ((gla->flags & GLINE_BADCHAN) != (glb->flags & GLINE_BADCHAN))
a44fc5f7
GB
214 return 0;
215
c684f472 216 if ((gla->flags & GLINE_REALNAME) != (glb->flags & GLINE_REALNAME))
a44fc5f7
GB
217 return 0;
218
c684f472 219 if ((gla->flags & GLINE_IPMASK) != (glb->flags & GLINE_IPMASK))
a44fc5f7
GB
220 return 0;
221
c684f472 222 if (gla->nick && !glb->nick)
a44fc5f7
GB
223 return 0;
224
c684f472 225 if (gla->nick && glb->nick && match(gla->nick->content, glb->nick->content) != 0)
a44fc5f7
GB
226 return 0;
227
c684f472 228 if (gla->user && !glb->user)
a44fc5f7
GB
229 return 0;
230
c684f472
GB
231 if (gla->user && glb->user && match(gla->user->content, glb->user->content) != 0)
232 return 0;
a44fc5f7 233
c684f472
GB
234 if (gla->flags & GLINE_IPMASK) {
235 if (gla->bits > glb->bits)
236 return 0;
a44fc5f7 237
c684f472
GB
238 if (!ipmask_check(&gla->ip, &glb->ip, gla->bits))
239 return 0;
240 } else {
241 if (gla->host && !glb->host)
242 return 0;
243
244 if (gla->host && glb->host && match(gla->host->content, glb->host->content) != 0)
245 return 0;
246 }
247
248 return 1;
a44fc5f7
GB
249}
250
a86fc0c4
GB
251int isglinesane(gline *gl, const char **hint) {
252 int wildcard, nowildcardcount;
253 char *pos;
254 trusthost *th;
255
256 /* Hits all realnames. */
257 if ((gl->flags & GLINE_REALNAME) && !gl->user) {
258 *hint = "Matches all realnames.";
259 return 0;
260 }
261
262 /* Hits all local/non-local channels. */
263 if ((gl->flags & GLINE_BADCHAN) && (strcmp(gl->user->content, "&*") == 0 || strcmp(gl->user->content, "#*") == 0)) {
264 *hint = "Matches all local/non-local channels.";
265 return 0;
266 }
267
521d4392
GB
268 /* Skip the other checks for nickname glines. */
269 if (gl->nick)
270 return 1;
271
a86fc0c4
GB
272 /* Mask wider than /16 for IPv4 or /32 for IPv6. */
273 if ((gl->flags & GLINE_IPMASK) && gl->bits < (irc_in_addr_is_ipv4(&gl->ip) ? (96 + 16) : 32)) {
274 *hint = "CIDR mask too wide.";
275 return 0;
276 }
277
278 /* Doesn't have at least two non-wildcarded host components. */
279 if (gl->flags & GLINE_HOSTMASK) {
280 nowildcardcount = 0;
281
282 wildcard = 0;
283 pos = gl->host->content;
284
285 for (;;) {
286 switch (*pos) {
287 case '*':
288 /* fall through */
289 case '?':
290 wildcard = 1;
291 break;
292
293 case '.':
294 case '\0':
295 if (!wildcard)
296 nowildcardcount++;
297 else
298 wildcard = 0;
299
300 if (*pos == '\0')
301 pos = NULL; /* Leave the loop. */
302
303 break;
304 }
305
306 if (pos)
307 pos++;
308 else
309 break;
310 }
311
312 if (nowildcardcount < 2) {
313 *hint = "Needs at least 2 non-wildcarded host components.";
314 return 0;
315 }
316 }
317
318 /* Wildcard username match for trusted host with reliable usernames. */
319 if (gl->flags & GLINE_IPMASK && (!gl->user || strchr(gl->user->content, '*') || strchr(gl->user->content, '?'))) {
320 th = th_getbyhost(&gl->ip);
321
322 if (th && (th->group->flags & TRUST_RELIABLE_USERNAME)) {
323 *hint = "Wildcard username match for a trusted host that has reliable usernames.";
324 return 0;
325 }
326 }
327
328 return 1;
329}