]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/ACLIP.cc
4 * DEBUG: section 28 Access Control
5 * AUTHOR: Duane Wessels
7 * SQUID Web Proxy Cache http://www.squid-cache.org/
8 * ----------------------------------------------------------
10 * Squid is the result of efforts by numerous individuals from
11 * the Internet community; see the CONTRIBUTORS file for full
12 * details. Many organizations have provided support for Squid's
13 * development; see the SPONSORS file for full details. Squid is
14 * Copyrighted (C) 2001 by the Regents of the University of
15 * California; see the COPYRIGHT file for full details. Squid
16 * incorporates software developed and/or copyrighted by other
17 * sources; see the CREDITS file for full details.
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
33 * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
38 #include "ACLChecklist.h"
43 ACLIP::operator new (size_t byteCount
)
45 fatal ("ACLIP::operator new: unused");
50 ACLIP::operator delete (void *address
)
52 fatal ("ACLIP::operator delete: unused");
56 ACLIP::DumpIpListWalkee(acl_ip_data
* const & ip
, void *state
)
59 wordlist
**W
= static_cast<wordlist
**>(state
);
61 mb
.Printf("%s", inet_ntoa(ip
->addr1
));
63 if (ip
->addr2
.s_addr
!= any_addr
.s_addr
)
64 mb
.Printf("-%s", inet_ntoa(ip
->addr2
));
66 if (ip
->mask
.s_addr
!= no_addr
.s_addr
)
67 mb
.Printf("/%s", inet_ntoa(ip
->mask
));
69 wordlistAdd(W
, mb
.buf
);
75 * aclIpDataToStr - print/format an acl_ip_data structure for
79 acl_ip_data::toStr(char *buf
, int len
) const
84 snprintf(b1
, 20, "%s", inet_ntoa(addr1
));
86 if (addr2
.s_addr
!= any_addr
.s_addr
)
87 snprintf(b2
, 20, "-%s", inet_ntoa(addr2
));
91 if (mask
.s_addr
!= no_addr
.s_addr
)
92 snprintf(b3
, 20, "/%s", inet_ntoa(mask
));
96 snprintf(buf
, len
, "%s%s%s", b1
, b2
, b3
);
100 * aclIpAddrNetworkCompare - The guts of the comparison for IP ACLs.
101 * The first argument (a) is a "host" address, i.e. the IP address
102 * of a cache client. The second argument (b) is a "network" address
103 * that might have a subnet and/or range. We mask the host address
104 * bits with the network subnet mask.
107 * aclIpAddrNetworkCompare - The comparison function used for ACL
108 * matching checks. The first argument (a) is a "host" address,
109 * i.e. the IP address of a cache client. The second argument (b)
110 * is an entry in some address-based access control element. This
111 * function is called via ACLIP::match() and the splay library.
114 aclIpAddrNetworkCompare(acl_ip_data
* const &p
, acl_ip_data
* const &q
)
117 struct IN_ADDR A
= p
->addr1
;
119 const struct IN_ADDR B
= q
->addr1
;
121 const struct IN_ADDR C
= q
->addr2
;
122 A
.s_addr
&= q
->mask
.s_addr
; /* apply netmask */
124 if (C
.s_addr
== 0) { /* single address check */
126 if (ntohl(A
.s_addr
) > ntohl(B
.s_addr
))
128 else if (ntohl(A
.s_addr
) < ntohl(B
.s_addr
))
132 } else { /* range address check */
134 if (ntohl(A
.s_addr
) > ntohl(C
.s_addr
))
136 else if (ntohl(A
.s_addr
) < ntohl(B
.s_addr
))
145 * acl_ip_data::NetworkCompare - Compare two acl_ip_data entries. Strictly
146 * used by the splay insertion routine. It emits a warning if it
147 * detects a "collision" or overlap that would confuse the splay
148 * sorting algorithm. Much like aclDomainCompare.
151 acl_ip_data::NetworkCompare(acl_ip_data
* const & a
, acl_ip_data
* const &b
)
154 ret
= aclIpAddrNetworkCompare(b
, a
);
157 ret
= aclIpAddrNetworkCompare(a
, b
);
164 b
->toStr(buf_n1
, 60);
165 a
->toStr(buf_n2
, 60);
167 /* TODO: this warning may display the wrong way around */
168 debug(28, 0) ("WARNING: '%s' is a subnetwork of "
169 "'%s'\n", buf_n1
, buf_n2
);
170 debug(28, 0) ("WARNING: because of this '%s' is ignored "
171 "to keep splay tree searching predictable\n", buf_a
);
172 debug(28, 0) ("WARNING: You should probably remove '%s' "
173 "from the ACL named '%s'\n", buf_n1
, AclMatchedName
);
180 * Decode a ascii representation (asc) of a IP adress, and place
181 * adress and netmask information in addr and mask.
182 * This function should NOT be called if 'asc' is a hostname!
186 acl_ip_data::DecodeMask(const char *asc
, struct IN_ADDR
*mask
)
193 mask
->s_addr
= htonl(0xFFFFFFFFul
);
197 if (sscanf(asc
, "%d%c", &a1
, &junk
) == 1 && a1
>= 0 && a1
< 33)
198 { /* a significant bits value for a mask */
199 mask
->s_addr
= a1
? htonl(0xfffffffful
<< (32 - a1
)) : 0;
203 /* dotted notation */
204 if (safe_inet_addr(asc
, mask
))
210 #define SCAN_ACL1 "%[0123456789.]-%[0123456789.]/%[0123456789.]"
211 #define SCAN_ACL2 "%[0123456789.]-%[0123456789.]%c"
212 #define SCAN_ACL3 "%[0123456789.]/%[0123456789.]"
215 acl_ip_data::FactoryParse(const char *t
)
217 LOCAL_ARRAY(char, addr2
, 256);
218 LOCAL_ARRAY(char, mask
, 256);
223 debug(28, 5) ("aclParseIpData: %s\n", t
);
224 acl_ip_data
*q
= new acl_ip_data
;
226 if (!strcasecmp(t
, "all")) {
233 LOCAL_ARRAY(char, addr1
, 256);
235 if (sscanf(t
, SCAN_ACL1
, addr1
, addr2
, mask
) == 3) {
237 } else if (sscanf(t
, SCAN_ACL2
, addr1
, addr2
, &c
) == 2) {
239 } else if (sscanf(t
, SCAN_ACL3
, addr1
, mask
) == 2) {
241 } else if (sscanf(t
, "%[^/]/%s", addr1
, mask
) == 2) {
243 } else if (sscanf(t
, "%s", addr1
) == 1) {
250 * Note, must use plain gethostbyname() here because at startup
251 * ipcache hasn't been initialized
256 if ((hp
= gethostbyname(addr1
)) == NULL
) {
257 debug(28, 0) ("aclParseIpData: Bad host/IP: '%s'\n", t
);
263 for (x
= hp
->h_addr_list
; x
!= NULL
&& *x
!= NULL
; x
++) {
264 if ((r
= *Q
) == NULL
)
265 r
= *Q
= new acl_ip_data
;
267 xmemcpy(&r
->addr1
.s_addr
, *x
, sizeof(r
->addr1
.s_addr
));
271 if (!DecodeMask(mask
, &r
->mask
)) {
272 debug(28, 0) ("aclParseIpData: unknown netmask '%s' in '%s'\n", mask
, t
);
282 debug(28, 3) ("%s --> %s\n", addr1
, inet_ntoa(r
->addr1
));
286 debug(28, 0) ("aclParseIpData: Bad host/IP: '%s'\n", t
);
294 if (!safe_inet_addr(addr1
, &q
->addr1
)) {
295 debug(28, 0) ("aclParseIpData: unknown first address in '%s'\n", t
);
302 if (!safe_inet_addr(addr2
, &q
->addr2
)) {
303 debug(28, 0) ("aclParseIpData: unknown second address in '%s'\n", t
);
310 if (!DecodeMask(mask
, &q
->mask
)) {
311 debug(28, 0) ("aclParseIpData: unknown netmask '%s' in '%s'\n", mask
, t
);
317 if ((q
->addr1
.s_addr
& q
->mask
.s_addr
) != q
->addr1
.s_addr
||
318 (q
->addr2
.s_addr
& q
->mask
.s_addr
) != q
->addr2
.s_addr
)
319 debug(28, 0) ("aclParseIpData: WARNING: Netmask masks away part of the specified IP in '%s'\n", t
);
321 q
->addr1
.s_addr
&= q
->mask
.s_addr
;
323 q
->addr2
.s_addr
&= q
->mask
.s_addr
;
325 /* 1.2.3.4/255.255.255.0 --> 1.2.3.0 */
334 while ((t
= strtokFile())) {
335 acl_ip_data
*q
= acl_ip_data::FactoryParse(t
);
338 data
= data
->insert(q
, acl_ip_data::NetworkCompare
);
347 data
->destroy(IPSplay::DefaultFree
);
354 data
->walk (DumpIpListWalkee
, &w
);
359 ACLIP::empty () const
361 return data
->empty();
366 ACLIP::match(struct IN_ADDR
&clientip
)
368 static acl_ip_data
ClientAddress (any_addr
, any_addr
, no_addr
, NULL
);
370 * aclIpAddrNetworkCompare() takes two acl_ip_data pointers as
371 * arguments, so we must create a fake one for the client's IP
372 * address, and use a /32 netmask. However, the current code
373 * probably only accesses the addr1 element of this argument,
374 * so it might be possible to leave addr2 and mask unset.
376 ClientAddress
.addr1
= clientip
;
377 acl_ip_data
*ClientAddressPointer
= &ClientAddress
;
378 data
= data
->splay(ClientAddressPointer
, aclIpAddrNetworkCompare
);
379 debug(28, 3) ("aclMatchIp: '%s' %s\n",
380 inet_ntoa(clientip
), splayLastResult
? "NOT found" : "found");
381 return !splayLastResult
;
384 acl_ip_data::acl_ip_data () :addr1(any_addr
), addr2(any_addr
), mask (any_addr
), next (NULL
) {}
386 acl_ip_data::acl_ip_data (struct IN_ADDR
const &anAddress1
, struct IN_ADDR
const &anAddress2
, struct IN_ADDR
const &aMask
, acl_ip_data
*aNext
) : addr1(anAddress1
), addr2(anAddress2
), mask(aMask
), next(aNext
){}