]> git.ipfire.org Git - thirdparty/squid.git/blob - src/acl/DomainData.cc
SourceLayout: shuffle memory pool allocators to mem/libmem.la
[thirdparty/squid.git] / src / acl / DomainData.cc
1 /*
2 * Copyright (C) 1996-2014 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 /* DEBUG: section 28 Access Control */
10
11 #include "squid.h"
12 #include "acl/Checklist.h"
13 #include "acl/DomainData.h"
14 #include "cache_cf.h"
15 #include "Debug.h"
16 #include "src/URL.h"
17 #include "util.h"
18
19 template<class T>
20 inline void
21 xRefFree(T &thing)
22 {
23 xfree (thing);
24 }
25
26 ACLDomainData::~ACLDomainData()
27 {
28 if (domains)
29 domains->destroy(xRefFree);
30 }
31
32 template<class T>
33 inline int
34 splaystrcasecmp (T&l, T&r)
35 {
36 return strcasecmp ((char *)l,(char *)r);
37 }
38
39 template<class T>
40 inline int
41 splaystrcmp (T&l, T&r)
42 {
43 return strcmp ((char *)l,(char *)r);
44 }
45
46 /* general compare functions, these are used for tree search algorithms
47 * so they return <0, 0 or >0 */
48
49 /* compare a host and a domain */
50
51 static int
52 aclHostDomainCompare( char *const &a, char * const &b)
53 {
54 const char *h = static_cast<const char *>(a);
55 const char *d = static_cast<const char *>(b);
56 return matchDomainName(h, d);
57 }
58
59 /* compare two domains */
60
61 template<class T>
62 int
63 aclDomainCompare(T const &a, T const &b)
64 {
65 char * const d1 = static_cast<char *>(b);
66 char * const d2 = static_cast<char *>(a);
67 int ret;
68 ret = aclHostDomainCompare(d1, d2);
69
70 if (ret != 0) {
71 char *const d3 = d2;
72 char *const d4 = d1;
73 ret = aclHostDomainCompare(d3, d4);
74 if (ret == 0) {
75 // When a.example.com comes after .example.com in an ACL
76 // sub-domain is ignored. That is okay. Just important
77 bool d3big = (strlen(d3) > strlen(d4)); // Always suggest removing the longer one.
78 debugs(28, DBG_IMPORTANT, "WARNING: '" << (d3big?d3:d4) << "' is a subdomain of '" << (d3big?d4:d3) << "'");
79 debugs(28, DBG_IMPORTANT, "WARNING: You should remove '" << (d3big?d3:d4) << "' from the ACL named '" << AclMatchedName << "'");
80 debugs(28, 2, HERE << "Ignore '" << d3 << "' to keep splay tree searching predictable");
81 }
82 } else if (ret == 0) {
83 // It may be an exact duplicate. No problem. Just drop.
84 if (strcmp(d1,d2)==0) {
85 debugs(28, 2, "WARNING: '" << d2 << "' is duplicated in the list.");
86 debugs(28, 2, "WARNING: You should remove one '" << d2 << "' from the ACL named '" << AclMatchedName << "'");
87 return ret;
88 }
89 // When a.example.com comes before .example.com in an ACL
90 // discarding the wildcard is critically bad.
91 // or Maybe even both are wildcards. Things are very weird in those cases.
92 bool d1big = (strlen(d1) > strlen(d2)); // Always suggest removing the longer one.
93 debugs(28, DBG_CRITICAL, "ERROR: '" << (d1big?d1:d2) << "' is a subdomain of '" << (d1big?d2:d1) << "'");
94 debugs(28, DBG_CRITICAL, "ERROR: You need to remove '" << (d1big?d1:d2) << "' from the ACL named '" << AclMatchedName << "'");
95 self_destruct();
96 }
97
98 return ret;
99 }
100
101 bool
102 ACLDomainData::match(char const *host)
103 {
104 if (host == NULL)
105 return 0;
106
107 debugs(28, 3, "aclMatchDomainList: checking '" << host << "'");
108
109 domains = domains->splay((char *)host, aclHostDomainCompare);
110
111 debugs(28, 3, "aclMatchDomainList: '" << host << "' " << (splayLastResult ? "NOT found" : "found"));
112
113 return !splayLastResult;
114 }
115
116 static void
117 aclDumpDomainListWalkee(char * const & node_data, void *outlist)
118 {
119 /* outlist is really a SBufList ** */
120 static_cast<SBufList *>(outlist)->push_back(SBuf(node_data));
121 }
122
123 SBufList
124 ACLDomainData::dump() const
125 {
126 SBufList sl;
127 /* damn this is VERY inefficient for long ACL lists... filling
128 * a wordlist this way costs Sum(1,N) iterations. For instance
129 * a 1000-elements list will be filled in 499500 iterations.
130 */
131 domains->walk(aclDumpDomainListWalkee, &sl);
132 return sl;
133 }
134
135 void
136 ACLDomainData::parse()
137 {
138 char *t = NULL;
139
140 while ((t = strtokFile())) {
141 Tolower(t);
142 domains = domains->insert(xstrdup(t), aclDomainCompare);
143 }
144 }
145
146 bool
147 ACLDomainData::empty() const
148 {
149 return domains->empty();
150 }
151
152 ACLData<char const *> *
153 ACLDomainData::clone() const
154 {
155 /* Splay trees don't clone yet. */
156 assert (!domains);
157 return new ACLDomainData;
158 }