]> jfr.im git - irc/quakenet/newserv.git/blame - channel/channelbans.c
CHANNEL: eliminate compiler warnings.
[irc/quakenet/newserv.git] / channel / channelbans.c
CommitLineData
c86edd1d
Q
1/* channelbans.c */
2
3#include <assert.h>
4#include <string.h>
5#include <stdio.h>
6
7#include "channel.h"
8#include "../nick/nick.h"
9#include "../lib/irc_string.h"
10#include "../irc/irc_config.h"
11#include "../irc/irc.h"
12
795410dd 13/*
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
17 * +x/+h users.
18 *
19 * copy & pasted this, touch and go whether this was a good idea.
20 */
21
22int nickmatchban_visible(nick *np, chanban *bp) {
795410dd 23 char fakehost[HOSTLEN+1];
24 char *visibleident;
25
26 /* Don't waste time on invalid bans */
27 if (bp->flags & CHANBAN_INVALID)
28 return 0;
29
30 /* nick/ident section: return 0 (no match) if they don't match */
31
32 /* Determine the visible ident for sethost users. Don't test the real one. */
a04aa32c 33 if (IsSetHost(np) && np->shident && *np->shident->content)
795410dd 34 visibleident=np->shident->content;
35 else
36 visibleident=np->ident;
37
38 if (bp->flags & CHANBAN_USEREXACT && ircd_strcmp(visibleident,bp->user->content))
39 return 0;
40
41 if (bp->flags & CHANBAN_NICKEXACT && ircd_strcmp(np->nick,bp->nick->content))
42 return 0;
43
44 if (bp->flags & CHANBAN_USERMASK && !match2strings(bp->user->content,visibleident))
45 return 0;
46
47 if (bp->flags & CHANBAN_NICKMASK && !match2strings(bp->nick->content,np->nick))
48 return 0;
49
50 /* host section. Return 1 (match) if they do match
51 * Note that if user or ident was specified, they've already been checked
52 */
53
54 if (bp->flags & CHANBAN_HOSTANY)
55 return 1;
56
57 if ((bp->flags & CHANBAN_CIDR) && (bp->flags & CHANBAN_HOSTEXACT)) {
58 unsigned int cip;
59 unsigned char *ch;
60
61 /* CIDR bans don't visibly match sethosted users */
62 if (IsSetHost(np) || (IsAccount(np) && IsHideHost(np)))
63 return 0;
64
65 /* CIDR bans don't match IPv6 hosts */
66 if (!irc_in_addr_is_ipv4(&(np->p_ipaddr)))
67 return 0;
68
69 /* Extract the client's IP address into a usable format */
70 ch=(unsigned char *)&(np->p_ipaddr.in6_16[6]);
71 cip=(ch[0]<<24) | (ch[1]<<16) | (ch[2]<<8) | (ch[3]);
72
73 if ((cip & bp->mask) == bp->ipaddr)
74 return 1;
75
76 return 0; /* A CIDR ban won't match any other way */
77 }
78
79 if (bp->flags & CHANBAN_IP) {
80 /* IP bans don't match sethosted users */
81 if (IsSetHost(np) || (IsAccount(np) && IsHideHost(np)))
82 return 0;
83
84 if (bp->flags & CHANBAN_HOSTEXACT) {
3d417b1c 85 /* Only exact IP bans are valid */
795410dd 86 unsigned int cip;
87 unsigned char *ch;
88
89 /* Well, it won't match if it's not an IPv4 host */
90 if (!irc_in_addr_is_ipv4(&(np->p_ipaddr)))
91 return 0;
92
93 /* Extract the client's IP address into a usable format */
94 ch=(unsigned char *)&(np->p_ipaddr.in6_16[6]);
95 cip=(ch[0]<<24) | (ch[1]<<16) | (ch[2]<<8) | (ch[3]);
96
97 if (cip==bp->ipaddr)
98 return 1;
795410dd 99 }
100 } else {
101 /* Hostname bans need to be checked against +x host, +h host (if set)
102 * and actual host. Note that the +x host is only generated (and checked) if it's
103 * possible for the ban to match a hidden host.. */
104
105 if ((bp->flags & CHANBAN_HIDDENHOST) && IsAccount(np)) {
106 sprintf(fakehost,"%s.%s",np->authname, HIS_HIDDENHOST);
107
108 if ((bp->flags & CHANBAN_HOSTEXACT) &&
109 !ircd_strcmp(fakehost, bp->host->content))
110 return 1;
111
112 if ((bp->flags & CHANBAN_HOSTMASK) &&
113 match2strings(bp->host->content, fakehost))
114 return 1;
115 }
116
117 if (IsSetHost(np)) {
118 if ((bp->flags & CHANBAN_HOSTEXACT) &&
119 !ircd_strcmp(np->sethost->content, bp->host->content))
120 return 1;
121
122 if ((bp->flags & CHANBAN_HOSTMASK) &&
123 match2strings(bp->host->content, np->sethost->content))
124 return 1;
125 }
126
127 /* If the user is +h or +rx don't check their real host */
128 if (IsSetHost(np) || (IsHideHost(np) && IsAccount(np)))
129 return 0;
130
131 if (bp->flags & CHANBAN_HOSTEXACT && !ircd_strcmp(np->host->name->content,bp->host->content))
132 return 1;
133
134 if (bp->flags & CHANBAN_HOSTMASK && match2strings(bp->host->content,np->host->name->content))
135 return 1;
136 }
137
138 return 0;
139}
140
c86edd1d
Q
141/*
142 * nickmatchban:
143 * Returns true iff the supplied nick* matches the supplied ban*
144 */
145
146int nickmatchban(nick *np, chanban *bp) {
c86edd1d
Q
147 char fakehost[HOSTLEN+1];
148
149 /* nick/ident section: return 0 (no match) if they don't match */
150
151 if (bp->flags & CHANBAN_INVALID)
152 return 0;
153
154 if (bp->flags & CHANBAN_USEREXACT &&
155 ircd_strcmp(np->ident,bp->user->content) &&
156 (!IsSetHost(np) || !np->shident ||
157 ircd_strcmp(np->shident->content,bp->user->content)))
158 return 0;
159
160 if (bp->flags & CHANBAN_NICKEXACT && ircd_strcmp(np->nick,bp->nick->content))
161 return 0;
162
163 if (bp->flags & CHANBAN_USERMASK &&
164 !match2strings(bp->user->content,np->ident) &&
165 (!IsSetHost(np) || !np->shident ||
166 !match2strings(bp->user->content, np->shident->content)))
167 return 0;
168
169 if (bp->flags & CHANBAN_NICKMASK && !match2strings(bp->nick->content,np->nick))
170 return 0;
171
172 /* host section. Return 1 (match) if they do match
173 * Note that if user or ident was specified, they've already been checked
174 */
175
176 if (bp->flags & CHANBAN_HOSTANY)
177 return 1;
178
e340eee8 179 if ((bp->flags & CHANBAN_CIDR) && (bp->flags & CHANBAN_HOSTEXACT)) {
180 unsigned int cip;
181 unsigned char *ch;
182
183 /* CIDR bans don't match IPv6 hosts */
184 if (!irc_in_addr_is_ipv4(&(np->p_ipaddr)))
185 return 0;
186
187 /* Extract the client's IP address into a usable format */
188 ch=(unsigned char *)&(np->p_ipaddr.in6_16[6]);
189 cip=(ch[0]<<24) | (ch[1]<<16) | (ch[2]<<8) | (ch[3]);
190
191 if ((cip & bp->mask) == bp->ipaddr)
c86edd1d
Q
192 return 1;
193
e340eee8 194 return 0; /* A CIDR ban won't match any other way */
195 }
196
197 if (bp->flags & CHANBAN_IP) {
198 if (bp->flags & CHANBAN_HOSTEXACT) {
3d417b1c 199 /* Only exact matches for IP bans */
e340eee8 200 unsigned int cip;
201 unsigned char *ch;
202
203 /* Well, it won't match if it's not an IPv4 host */
204 if (!irc_in_addr_is_ipv4(&(np->p_ipaddr)))
205 return 0;
206
207 /* Extract the client's IP address into a usable format */
208 ch=(unsigned char *)&(np->p_ipaddr.in6_16[6]);
209 cip=(ch[0]<<24) | (ch[1]<<16) | (ch[2]<<8) | (ch[3]);
210
211 if (cip==bp->ipaddr)
212 return 1;
e340eee8 213 }
c86edd1d
Q
214 } else {
215 /* Hostname bans need to be checked against +x host, +h host (if set)
216 * and actual host. Note that the +x host is only generated (and checked) if it's
217 * possible for the ban to match a hidden host.. */
218
219 if ((bp->flags & CHANBAN_HIDDENHOST) && IsAccount(np)) {
220 sprintf(fakehost,"%s.%s",np->authname, HIS_HIDDENHOST);
221
222 if ((bp->flags & CHANBAN_HOSTEXACT) &&
223 !ircd_strcmp(fakehost, bp->host->content))
224 return 1;
225
226 if ((bp->flags & CHANBAN_HOSTMASK) &&
227 match2strings(bp->host->content, fakehost))
228 return 1;
229 }
230
231 if (IsSetHost(np)) {
232 if ((bp->flags & CHANBAN_HOSTEXACT) &&
233 !ircd_strcmp(np->sethost->content, bp->host->content))
234 return 1;
235
236 if ((bp->flags & CHANBAN_HOSTMASK) &&
237 match2strings(bp->host->content, np->sethost->content))
238 return 1;
239 }
240
241 if (bp->flags & CHANBAN_HOSTEXACT && !ircd_strcmp(np->host->name->content,bp->host->content))
242 return 1;
243
244 if (bp->flags & CHANBAN_HOSTMASK && match2strings(bp->host->content,np->host->name->content))
245 return 1;
246 }
247
248 return 0;
249}
250
251/*
252 * nickbanned:
253 * Returns true iff the supplied nick* is banned on the supplied chan*
795410dd 254 *
255 * Also nickbanned_visible - doesn't violate privacy by checking hidden
256 * hosts and idents. Factored into one function to reduce copy&paste.
c86edd1d 257 */
795410dd 258static int nickbanned_real(nick *np, channel *cp, int (*cmpfunc)(nick *, chanban *)) {
c86edd1d
Q
259 chanban *cbp;
260
261 for (cbp=cp->bans;cbp;cbp=cbp->next) {
795410dd 262 if (cmpfunc(np,cbp))
c86edd1d
Q
263 return 1;
264 }
265
266 return 0;
267}
795410dd 268
269int nickbanned(nick *np, channel *cp) {
270 return nickbanned_real(np,cp,nickmatchban);
271}
272
273int nickbanned_visible(nick *np, channel *cp) {
274 return nickbanned_real(np,cp,nickmatchban_visible);
275}
c86edd1d
Q
276
277/*
278 * setban:
279 * Set the specified ban; if it completely encloses any existing bans
280 * then remove them.
11032584 281 *
282 * Returns 1 if the ban was set, or 0 if the ban was not set because an
283 * existing ban overlapped it.
c86edd1d
Q
284 */
285
11032584 286int setban(channel *cp, const char *ban) {
c86edd1d
Q
287 chanban **cbh,*cbp,*cbp2;
288
289 cbp=makeban(ban);
290
11032584 291 /* Don't set our ban if something encloses it */
292 for (cbp2=cp->bans;cbp2;cbp2=cbp2->next) {
293 if (banoverlap(cbp2, cbp)) {
294 /* This ban overlaps the one we are adding. Abort. */
295 freechanban(cbp);
296 return 0;
297 }
298 }
299
c86edd1d
Q
300 /* Remove enclosed bans first */
301 for (cbh=&(cp->bans);*cbh;) {
302 if (banoverlap(cbp,*cbh)) {
303 cbp2=(*cbh);
304 (*cbh)=cbp2->next;
305 freechanban(cbp2);
306 /* Break out of the loop if we just deleted the last ban */
307 if ((*cbh)==NULL) {
308 break;
309 }
310 } else {
311 cbh=(chanban **)&((*cbh)->next);
312 }
313 }
314
315 /* Now set the new ban */
316 cbp->next=(struct chanban *)cp->bans;
317 cp->bans=cbp;
11032584 318
319 return 1;
c86edd1d
Q
320}
321
322/*
323 * clearban:
324 * Remove the specified ban iff an exact match is found
325 * Returns 1 if the ban was cleared, 0 if the ban didn't exist.
326 * If "optional" is 0 and the ban didn't exist, flags an error
327 */
328
329int clearban(channel *cp, const char *ban, int optional) {
330 chanban **cbh,*cbp,*cbp2;
331 int found=0;
332 int i=0;
333
334 if (!cp)
335 return 0;
336
337 cbp=makeban(ban);
338
339 for (cbh=&(cp->bans);*cbh;cbh=(chanban **)&((*cbh)->next)) {
340 if (banequal(cbp,*cbh)) {
341 cbp2=(*cbh);
342 (*cbh)=cbp2->next;
343 freechanban(cbp2);
344 found=1;
345 break;
346 }
347 }
348
349 if (!found && !optional) {
350 Error("channel",ERR_DEBUG,"Couldn't remove ban %s from %s. Dumping banlist:",ban,cp->index->name->content);
351 for (cbp2=cp->bans;cbp2;cbp2=cbp2->next) {
352 Error("channel",ERR_DEBUG,"%s %d %s",cp->index->name->content, i++, bantostringdebug(cbp2));
353 }
354 }
355
356 freechanban(cbp);
357
358 return found;
359}
360
361/*
362 * clearallbans:
363 * Just free all the bans on the channel
364 */
365
366void clearallbans(channel *cp) {
367 chanban *cbp,*ncbp;
368
369 for (cbp=cp->bans;cbp;cbp=ncbp) {
370 ncbp=(chanban *)cbp->next;
371 freechanban(cbp);
372 }
373
374 cp->bans=NULL;
375}