]>
jfr.im git - irc/quakenet/newserv.git/blob - glines/glines.c
4 #include "../lib/irc_string.h"
5 #include "../lib/version.h"
6 #include "../core/schedule.h"
7 #include "../irc/irc.h"
8 #include "../trusts/trusts.h"
9 #include "../control/control.h"
15 /* If we're connected to IRC, force a disconnect. */
17 irc_send("%s SQ %s 0 :Resync [adding gline support]", mynumeric
->content
, myserver
->content
);
21 registerserverhandler("GL", handleglinemsg
, 6);
22 registerhook(HOOK_CORE_STATSREQUEST
, handleglinestats
);
26 deregisterserverhandler("GL", handleglinemsg
);
27 deregisterhook(HOOK_CORE_STATSREQUEST
, handleglinestats
);
30 int gline_match_nick(gline
*gl
, nick
*np
) {
31 if (gl
->flags
& GLINE_BADCHAN
)
34 if (gl
->flags
& GLINE_REALNAME
) {
35 if (gl
->user
&& match(gl
->user
->content
, np
->realname
->name
->content
) != 0)
41 if (gl
->nick
&& match(gl
->nick
->content
, np
->nick
) != 0)
44 if (gl
->user
&& match(gl
->user
->content
, np
->ident
) != 0)
47 if (gl
->flags
& GLINE_IPMASK
) {
48 if (!ipmask_check(&gl
->ip
, &np
->p_ipaddr
, gl
->bits
))
51 if (gl
->host
&& match(gl
->host
->content
, np
->host
->name
->content
) != 0)
58 int gline_match_channel(gline
*gl
, channel
*cp
) {
59 if (!(gl
->flags
& GLINE_BADCHAN
))
62 if (match(gl
->user
->content
, cp
->index
->name
->content
) != 0)
68 gline
*findgline(const char *mask
) {
71 time_t curtime
= time(0);
73 globalgline
= makegline(mask
);
76 return NULL
; /* gline mask couldn't be processed */
78 for (gl
= glinelist
; gl
; gl
= next
) {
81 if (gl
->lifetime
<= curtime
) {
84 } else if (gl
->expire
<= curtime
) {
85 gl
->flags
&= ~GLINE_ACTIVE
;
88 if (glineequal(globalgline
, gl
)) {
89 freegline(globalgline
);
94 freegline(globalgline
);
98 void gline_activate(gline
*agline
, time_t lastmod
, int propagate
) {
99 time_t now
= getnettime();
101 agline
->flags
|= GLINE_ACTIVE
;
104 agline
->lastmod
= lastmod
;
105 else if (now
<= agline
->lastmod
)
108 agline
->lastmod
= now
;
111 gline_propagate(agline
);
114 void gline_deactivate(gline
*agline
, time_t lastmod
, int propagate
) {
115 time_t now
= getnettime();
117 if (agline
->lastmod
== 0) {
118 Error("gline", ERR_WARNING
, "Tried to deactivate gline with lastmod == 0: %s", glinetostring(agline
));
122 agline
->flags
&= ~GLINE_ACTIVE
;
125 agline
->lastmod
= lastmod
;
126 else if (now
<= agline
->lastmod
)
129 agline
->lastmod
= now
;
132 gline_propagate(agline
);
135 void gline_destroy(gline
*agline
, time_t lastmod
, int propagate
) {
136 time_t now
= getnettime();
138 agline
->flags
&= ~GLINE_ACTIVE
;
139 agline
->flags
|= GLINE_DESTROYED
;
141 if (agline
->lastmod
== 0) {
142 Error("gline", ERR_WARNING
, "Tried to destroy gline with lastmod == 0: %s", glinetostring(agline
));
147 agline
->lastmod
= lastmod
;
148 else if (now
<= agline
->lastmod
)
151 agline
->lastmod
= now
;
154 gline_propagate(agline
);
159 void gline_propagate(gline
*agline
) {
160 /* Don't propagate Ulined glines. */
161 if (agline
->lastmod
== 0) {
162 Error("gline", ERR_WARNING
, "Tried to propagate gline with lastmod == 0: %s", glinetostring(agline
));
166 #if SNIRCD_VERSION >= 140
167 #error TODO: implement 6 parameter glines for snircd >=1.4.0
168 #endif /* SNIRCD_VERSION */
170 if (agline
->flags
& GLINE_DESTROYED
) {
171 #if SNIRCD_VERSION < 135
172 controlwall(NO_OPER
, NL_GLINES_AUTO
, "Tried to destroy G-Line on '%s' however SNIRCD_VERSION is too old.", glinetostring(agline
));
174 controlwall(NO_OPER
, NL_GLINES_AUTO
, "Destroying G-Line on '%s' lasting %s with reason '%s', created by: %s",
175 glinetostring(agline
), longtoduration(agline
->expire
-getnettime(), 0),
176 agline
->reason
? agline
->reason
->content
: "", agline
->creator
->content
);
178 irc_send("%s GL * %%-%s %lu %lu :%s\r\n", mynumeric
->content
,
179 glinetostring(agline
), agline
->expire
- getnettime(),
180 agline
->lastmod
, agline
->reason
? agline
->reason
->content
: "");
181 #endif /* SNIRCD_VERSION */
182 } else if (agline
->flags
& GLINE_ACTIVE
) {
183 controlwall(NO_OPER
, NL_GLINES_AUTO
, "Activating G-Line on '%s' lasting %s created by %s with reason '%s'",
184 glinetostring(agline
), longtoduration(agline
->expire
-getnettime(), 0),
185 agline
->creator
->content
, agline
->reason
? agline
->reason
->content
: "");
187 irc_send("%s GL * +%s %lu %lu :%s\r\n", mynumeric
->content
,
188 glinetostring(agline
), agline
->expire
- getnettime(),
189 agline
->lastmod
, agline
->reason
? agline
->reason
->content
: "");
191 controlwall(NO_OPER
, NL_GLINES_AUTO
, "Deactivating G-Line on '%s' lasting %s created by %s with reason '%s'",
192 glinetostring(agline
), longtoduration(agline
->expire
-getnettime(), 0),
193 agline
->creator
->content
, agline
->reason
? agline
->reason
->content
: "");
195 irc_send("%s GL * -%s %lu %lu :%s\r\n", mynumeric
->content
,
196 glinetostring(agline
), agline
->expire
- getnettime(),
197 agline
->lastmod
, agline
->reason
? agline
->reason
->content
: "");
201 /* returns non-zero if the glines are exactly the same */
202 int glineequal(gline
*gla
, gline
*glb
) {
203 if ((gla
->flags
& GLINE_BADCHAN
) != (glb
->flags
& GLINE_BADCHAN
))
206 if ((gla
->flags
& GLINE_REALNAME
) != (glb
->flags
& GLINE_REALNAME
))
209 if ((gla
->flags
& GLINE_IPMASK
) != (glb
->flags
& GLINE_IPMASK
))
212 if ((!gla
->nick
&& glb
->nick
) || (gla
->nick
&& !glb
->nick
))
215 if (gla
->nick
&& ircd_strcmp(gla
->nick
->content
, glb
->nick
->content
) != 0)
218 if ((!gla
->user
&& glb
->user
) || (gla
->user
&& !glb
->user
))
221 if (gla
->user
&& ircd_strcmp(gla
->user
->content
, glb
->user
->content
) != 0)
224 if (gla
->flags
& GLINE_IPMASK
) {
225 if (gla
->bits
!= glb
->bits
)
228 if (!ipmask_check(&gla
->ip
, &glb
->ip
, gla
->bits
))
231 if ((!gla
->host
&& glb
->host
) || (gla
->host
&& !glb
->host
))
234 if (gla
->host
&& ircd_strcmp(gla
->host
->content
, glb
->host
->content
) != 0)
241 /* returns non-zero on match */
242 int gline_match_mask(gline
*gla
, gline
*glb
) {
243 if ((gla
->flags
& GLINE_BADCHAN
) != (glb
->flags
& GLINE_BADCHAN
))
246 if ((gla
->flags
& GLINE_REALNAME
) != (glb
->flags
& GLINE_REALNAME
))
249 if (gla
->nick
&& !glb
->nick
)
252 if (gla
->nick
&& glb
->nick
&& match(gla
->nick
->content
, glb
->nick
->content
) != 0)
255 if (gla
->user
&& !glb
->user
)
258 if (gla
->user
&& glb
->user
&& match(gla
->user
->content
, glb
->user
->content
) != 0)
261 if (gla
->flags
& GLINE_IPMASK
&& glb
->flags
& GLINE_IPMASK
) {
262 if (gla
->bits
> glb
->bits
)
265 if (!ipmask_check(&gla
->ip
, &glb
->ip
, gla
->bits
))
268 if (gla
->host
&& !glb
->host
)
271 if (gla
->host
&& glb
->host
&& match(gla
->host
->content
, glb
->host
->content
) != 0)
278 int isglinesane(gline
*gl
, const char **hint
) {
279 int wildcard
, nowildcardcount
;
283 /* Reason is too short */
284 if (!gl
->reason
|| strlen(gl
->reason
->content
) < MINGLINEREASONLEN
) {
285 *hint
= "G-Line reason is too short.";
289 /* Duration is too long */
290 if (gl
->expire
- getnettime() > MAXGLINEDURATION
) {
291 *hint
= "G-Line duration is too long.";
295 /* Hits all realnames. */
296 if ((gl
->flags
& GLINE_REALNAME
) && !gl
->user
) {
297 *hint
= "Matches all realnames.";
301 /* Hits all local/non-local channels. */
302 if ((gl
->flags
& GLINE_BADCHAN
) && (strcmp(gl
->user
->content
, "&*") == 0 || strcmp(gl
->user
->content
, "#*") == 0)) {
303 *hint
= "Matches all local/non-local channels.";
307 /* Hostmask is too long. */
308 if (!(gl
->flags
& (GLINE_BADCHAN
| GLINE_REALNAME
)) &&
309 ((gl
->nick
&& strlen(gl
->nick
->content
) > NICKLEN
) ||
310 (gl
->user
&& strlen(gl
->user
->content
) > USERLEN
) ||
311 (gl
->host
&& strlen(gl
->host
->content
) > HOSTLEN
))) {
312 *hint
= "Hostmask components are too long.";
316 /* Skip the other checks for nickname glines. */
320 /* Mask wider than /16 for IPv4 or /32 for IPv6. */
321 if ((gl
->flags
& GLINE_IPMASK
) && gl
->bits
< (irc_in_addr_is_ipv4(&gl
->ip
) ? (96 + 16) : 32)) {
322 *hint
= "CIDR mask too wide.";
326 /* Doesn't have at least two non-wildcarded host components. */
327 if (gl
->flags
& GLINE_HOSTMASK
) {
331 pos
= gl
->host
->content
;
349 pos
= NULL
; /* Leave the loop. */
360 if (nowildcardcount
< 2) {
361 *hint
= "Needs at least 2 non-wildcarded host components.";
366 /* Wildcard username match for trusted host with reliable usernames. */
367 if ((gl
->flags
& GLINE_IPMASK
) && (!gl
->user
|| strchr(gl
->user
->content
, '*') || strchr(gl
->user
->content
, '?'))) {
368 th
= th_getbyhost(&gl
->ip
);
370 if (th
&& (th
->group
->flags
& TRUST_RELIABLE_USERNAME
)) {
371 *hint
= "Wildcard username match for a trusted host that has reliable usernames.";
379 gline
*glinedup(gline
*gl
) {
388 sgl
->nick
= getsstring(gl
->nick
->content
, 512);
391 sgl
->user
= getsstring(gl
->user
->content
, 512);
394 sgl
->host
= getsstring(gl
->host
->content
, 512);
396 sgl
->reason
= gl
->reason
? getsstring(gl
->reason
->content
, 512) : NULL
;
397 sgl
->creator
= getsstring(gl
->creator
->content
, 512);
399 memcpy(&sgl
->ip
, &gl
->ip
, sizeof(gl
->ip
));
400 sgl
->bits
= gl
->bits
;
402 sgl
->expire
= gl
->expire
;
403 sgl
->lastmod
= gl
->lastmod
;
404 sgl
->lifetime
= gl
->lifetime
;
406 sgl
->flags
= gl
->flags
;