]>
jfr.im git - irc/quakenet/newserv.git/blob - channel/channelbans.c
8 #include "../nick/nick.h"
9 #include "../lib/irc_string.h"
10 #include "../irc/irc_config.h"
11 #include "../irc/irc.h"
14 * nickmatchban_visible:
15 * Returns true iff the supplied nick* matches the supplied ban*
16 * Doesn't check "invisible" things like true hosts and IPs for
19 * copy & pasted this, touch and go whether this was a good idea.
22 int nickmatchban_visible(nick
*np
, chanban
*bp
) {
24 char fakehost
[HOSTLEN
+1];
27 /* Don't waste time on invalid bans */
28 if (bp
->flags
& CHANBAN_INVALID
)
31 /* nick/ident section: return 0 (no match) if they don't match */
33 /* Determine the visible ident for sethost users. Don't test the real one. */
34 if (IsSetHost(np
) && np
->shident
&& *np
->shident
->content
)
35 visibleident
=np
->shident
->content
;
37 visibleident
=np
->ident
;
39 if (bp
->flags
& CHANBAN_USEREXACT
&& ircd_strcmp(visibleident
,bp
->user
->content
))
42 if (bp
->flags
& CHANBAN_NICKEXACT
&& ircd_strcmp(np
->nick
,bp
->nick
->content
))
45 if (bp
->flags
& CHANBAN_USERMASK
&& !match2strings(bp
->user
->content
,visibleident
))
48 if (bp
->flags
& CHANBAN_NICKMASK
&& !match2strings(bp
->nick
->content
,np
->nick
))
51 /* host section. Return 1 (match) if they do match
52 * Note that if user or ident was specified, they've already been checked
55 if (bp
->flags
& CHANBAN_HOSTANY
)
58 if ((bp
->flags
& CHANBAN_CIDR
) && (bp
->flags
& CHANBAN_HOSTEXACT
)) {
62 /* CIDR bans don't visibly match sethosted users */
63 if (IsSetHost(np
) || (IsAccount(np
) && IsHideHost(np
)))
66 /* CIDR bans don't match IPv6 hosts */
67 if (!irc_in_addr_is_ipv4(&(np
->p_ipaddr
)))
70 /* Extract the client's IP address into a usable format */
71 ch
=(unsigned char *)&(np
->p_ipaddr
.in6_16
[6]);
72 cip
=(ch
[0]<<24) | (ch
[1]<<16) | (ch
[2]<<8) | (ch
[3]);
74 if ((cip
& bp
->mask
) == bp
->ipaddr
)
77 return 0; /* A CIDR ban won't match any other way */
80 if (bp
->flags
& CHANBAN_IP
) {
81 /* IP bans don't match sethosted users */
82 if (IsSetHost(np
) || (IsAccount(np
) && IsHideHost(np
)))
85 if (bp
->flags
& CHANBAN_HOSTEXACT
) {
86 /* Only exact IP bans are valid */
90 /* Well, it won't match if it's not an IPv4 host */
91 if (!irc_in_addr_is_ipv4(&(np
->p_ipaddr
)))
94 /* Extract the client's IP address into a usable format */
95 ch
=(unsigned char *)&(np
->p_ipaddr
.in6_16
[6]);
96 cip
=(ch
[0]<<24) | (ch
[1]<<16) | (ch
[2]<<8) | (ch
[3]);
102 /* Hostname bans need to be checked against +x host, +h host (if set)
103 * and actual host. Note that the +x host is only generated (and checked) if it's
104 * possible for the ban to match a hidden host.. */
106 if ((bp
->flags
& CHANBAN_HIDDENHOST
) && IsAccount(np
)) {
107 sprintf(fakehost
,"%s.%s",np
->authname
, HIS_HIDDENHOST
);
109 if ((bp
->flags
& CHANBAN_HOSTEXACT
) &&
110 !ircd_strcmp(fakehost
, bp
->host
->content
))
113 if ((bp
->flags
& CHANBAN_HOSTMASK
) &&
114 match2strings(bp
->host
->content
, fakehost
))
119 if ((bp
->flags
& CHANBAN_HOSTEXACT
) &&
120 !ircd_strcmp(np
->sethost
->content
, bp
->host
->content
))
123 if ((bp
->flags
& CHANBAN_HOSTMASK
) &&
124 match2strings(bp
->host
->content
, np
->sethost
->content
))
128 /* If the user is +h or +rx don't check their real host */
129 if (IsSetHost(np
) || (IsHideHost(np
) && IsAccount(np
)))
132 if (bp
->flags
& CHANBAN_HOSTEXACT
&& !ircd_strcmp(np
->host
->name
->content
,bp
->host
->content
))
135 if (bp
->flags
& CHANBAN_HOSTMASK
&& match2strings(bp
->host
->content
,np
->host
->name
->content
))
144 * Returns true iff the supplied nick* matches the supplied ban*
147 int nickmatchban(nick
*np
, chanban
*bp
) {
148 const char *ipstring
;
149 char fakehost
[HOSTLEN
+1];
151 /* nick/ident section: return 0 (no match) if they don't match */
153 if (bp
->flags
& CHANBAN_INVALID
)
156 if (bp
->flags
& CHANBAN_USEREXACT
&&
157 ircd_strcmp(np
->ident
,bp
->user
->content
) &&
158 (!IsSetHost(np
) || !np
->shident
||
159 ircd_strcmp(np
->shident
->content
,bp
->user
->content
)))
162 if (bp
->flags
& CHANBAN_NICKEXACT
&& ircd_strcmp(np
->nick
,bp
->nick
->content
))
165 if (bp
->flags
& CHANBAN_USERMASK
&&
166 !match2strings(bp
->user
->content
,np
->ident
) &&
167 (!IsSetHost(np
) || !np
->shident
||
168 !match2strings(bp
->user
->content
, np
->shident
->content
)))
171 if (bp
->flags
& CHANBAN_NICKMASK
&& !match2strings(bp
->nick
->content
,np
->nick
))
174 /* host section. Return 1 (match) if they do match
175 * Note that if user or ident was specified, they've already been checked
178 if (bp
->flags
& CHANBAN_HOSTANY
)
181 if ((bp
->flags
& CHANBAN_CIDR
) && (bp
->flags
& CHANBAN_HOSTEXACT
)) {
185 /* CIDR bans don't match IPv6 hosts */
186 if (!irc_in_addr_is_ipv4(&(np
->p_ipaddr
)))
189 /* Extract the client's IP address into a usable format */
190 ch
=(unsigned char *)&(np
->p_ipaddr
.in6_16
[6]);
191 cip
=(ch
[0]<<24) | (ch
[1]<<16) | (ch
[2]<<8) | (ch
[3]);
193 if ((cip
& bp
->mask
) == bp
->ipaddr
)
196 return 0; /* A CIDR ban won't match any other way */
199 if (bp
->flags
& CHANBAN_IP
) {
200 if (bp
->flags
& CHANBAN_HOSTEXACT
) {
201 /* Only exact matches for IP bans */
205 /* Well, it won't match if it's not an IPv4 host */
206 if (!irc_in_addr_is_ipv4(&(np
->p_ipaddr
)))
209 /* Extract the client's IP address into a usable format */
210 ch
=(unsigned char *)&(np
->p_ipaddr
.in6_16
[6]);
211 cip
=(ch
[0]<<24) | (ch
[1]<<16) | (ch
[2]<<8) | (ch
[3]);
217 /* Hostname bans need to be checked against +x host, +h host (if set)
218 * and actual host. Note that the +x host is only generated (and checked) if it's
219 * possible for the ban to match a hidden host.. */
221 if ((bp
->flags
& CHANBAN_HIDDENHOST
) && IsAccount(np
)) {
222 sprintf(fakehost
,"%s.%s",np
->authname
, HIS_HIDDENHOST
);
224 if ((bp
->flags
& CHANBAN_HOSTEXACT
) &&
225 !ircd_strcmp(fakehost
, bp
->host
->content
))
228 if ((bp
->flags
& CHANBAN_HOSTMASK
) &&
229 match2strings(bp
->host
->content
, fakehost
))
234 if ((bp
->flags
& CHANBAN_HOSTEXACT
) &&
235 !ircd_strcmp(np
->sethost
->content
, bp
->host
->content
))
238 if ((bp
->flags
& CHANBAN_HOSTMASK
) &&
239 match2strings(bp
->host
->content
, np
->sethost
->content
))
243 if (bp
->flags
& CHANBAN_HOSTEXACT
&& !ircd_strcmp(np
->host
->name
->content
,bp
->host
->content
))
246 if (bp
->flags
& CHANBAN_HOSTMASK
&& match2strings(bp
->host
->content
,np
->host
->name
->content
))
255 * Returns true iff the supplied nick* is banned on the supplied chan*
257 * Also nickbanned_visible - doesn't violate privacy by checking hidden
258 * hosts and idents. Factored into one function to reduce copy&paste.
260 static int nickbanned_real(nick
*np
, channel
*cp
, int (*cmpfunc
)(nick
*, chanban
*)) {
263 for (cbp
=cp
->bans
;cbp
;cbp
=cbp
->next
) {
271 int nickbanned(nick
*np
, channel
*cp
) {
272 return nickbanned_real(np
,cp
,nickmatchban
);
275 int nickbanned_visible(nick
*np
, channel
*cp
) {
276 return nickbanned_real(np
,cp
,nickmatchban_visible
);
281 * Set the specified ban; if it completely encloses any existing bans
284 * Returns 1 if the ban was set, or 0 if the ban was not set because an
285 * existing ban overlapped it.
288 int setban(channel
*cp
, const char *ban
) {
289 chanban
**cbh
,*cbp
,*cbp2
;
293 /* Don't set our ban if something encloses it */
294 for (cbp2
=cp
->bans
;cbp2
;cbp2
=cbp2
->next
) {
295 if (banoverlap(cbp2
, cbp
)) {
296 /* This ban overlaps the one we are adding. Abort. */
302 /* Remove enclosed bans first */
303 for (cbh
=&(cp
->bans
);*cbh
;) {
304 if (banoverlap(cbp
,*cbh
)) {
308 /* Break out of the loop if we just deleted the last ban */
313 cbh
=(chanban
**)&((*cbh
)->next
);
317 /* Now set the new ban */
318 cbp
->next
=(struct chanban
*)cp
->bans
;
326 * Remove the specified ban iff an exact match is found
327 * Returns 1 if the ban was cleared, 0 if the ban didn't exist.
328 * If "optional" is 0 and the ban didn't exist, flags an error
331 int clearban(channel
*cp
, const char *ban
, int optional
) {
332 chanban
**cbh
,*cbp
,*cbp2
;
341 for (cbh
=&(cp
->bans
);*cbh
;cbh
=(chanban
**)&((*cbh
)->next
)) {
342 if (banequal(cbp
,*cbh
)) {
351 if (!found
&& !optional
) {
352 Error("channel",ERR_DEBUG
,"Couldn't remove ban %s from %s. Dumping banlist:",ban
,cp
->index
->name
->content
);
353 for (cbp2
=cp
->bans
;cbp2
;cbp2
=cbp2
->next
) {
354 Error("channel",ERR_DEBUG
,"%s %d %s",cp
->index
->name
->content
, i
++, bantostringdebug(cbp2
));
365 * Just free all the bans on the channel
368 void clearallbans(channel
*cp
) {
371 for (cbp
=cp
->bans
;cbp
;cbp
=ncbp
) {
372 ncbp
=(chanban
*)cbp
->next
;