]> git.ipfire.org Git - thirdparty/squid.git/blob - src/acl/DomainData.cc
Merge splayfix branch
[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 delete domains;
31 }
32 }
33
34 template<class T>
35 inline int
36 splaystrcasecmp (T&l, T&r)
37 {
38 return strcasecmp ((char *)l,(char *)r);
39 }
40
41 template<class T>
42 inline int
43 splaystrcmp (T&l, T&r)
44 {
45 return strcmp ((char *)l,(char *)r);
46 }
47
48 /* general compare functions, these are used for tree search algorithms
49 * so they return <0, 0 or >0 */
50
51 /* compare a host and a domain */
52
53 static int
54 aclHostDomainCompare( char *const &a, char * const &b)
55 {
56 const char *h = static_cast<const char *>(a);
57 const char *d = static_cast<const char *>(b);
58 return matchDomainName(h, d);
59 }
60
61 /* compare two domains */
62
63 template<class T>
64 int
65 aclDomainCompare(T const &a, T const &b)
66 {
67 char * const d1 = static_cast<char *>(b);
68 char * const d2 = static_cast<char *>(a);
69 int ret;
70 ret = aclHostDomainCompare(d1, d2);
71
72 if (ret != 0) {
73 char *const d3 = d2;
74 char *const d4 = d1;
75 ret = aclHostDomainCompare(d3, d4);
76 if (ret == 0) {
77 // When a.example.com comes after .example.com in an ACL
78 // sub-domain is ignored. That is okay. Just important
79 bool d3big = (strlen(d3) > strlen(d4)); // Always suggest removing the longer one.
80 debugs(28, DBG_IMPORTANT, "WARNING: '" << (d3big?d3:d4) << "' is a subdomain of '" << (d3big?d4:d3) << "'");
81 debugs(28, DBG_IMPORTANT, "WARNING: You should remove '" << (d3big?d3:d4) << "' from the ACL named '" << AclMatchedName << "'");
82 debugs(28, 2, HERE << "Ignore '" << d3 << "' to keep splay tree searching predictable");
83 }
84 } else if (ret == 0) {
85 // It may be an exact duplicate. No problem. Just drop.
86 if (strcmp(d1,d2)==0) {
87 debugs(28, 2, "WARNING: '" << d2 << "' is duplicated in the list.");
88 debugs(28, 2, "WARNING: You should remove one '" << d2 << "' from the ACL named '" << AclMatchedName << "'");
89 return ret;
90 }
91 // When a.example.com comes before .example.com in an ACL
92 // discarding the wildcard is critically bad.
93 // or Maybe even both are wildcards. Things are very weird in those cases.
94 bool d1big = (strlen(d1) > strlen(d2)); // Always suggest removing the longer one.
95 debugs(28, DBG_CRITICAL, "ERROR: '" << (d1big?d1:d2) << "' is a subdomain of '" << (d1big?d2:d1) << "'");
96 debugs(28, DBG_CRITICAL, "ERROR: You need to remove '" << (d1big?d1:d2) << "' from the ACL named '" << AclMatchedName << "'");
97 self_destruct();
98 }
99
100 return ret;
101 }
102
103 bool
104 ACLDomainData::match(char const *host)
105 {
106 if (host == NULL)
107 return 0;
108
109 debugs(28, 3, "aclMatchDomainList: checking '" << host << "'");
110
111 char *h = const_cast<char *>(host);
112 char const * const * result = domains->find(h, aclHostDomainCompare);
113
114 debugs(28, 3, "aclMatchDomainList: '" << host << "' " << (result ? "found" : "NOT found"));
115
116 return (result != NULL);
117 }
118
119 struct AclDomainDataDumpVisitor {
120 SBufList contents;
121 void operator() (char * const & node_data) {
122 contents.push_back(SBuf(node_data));
123 }
124 };
125
126 SBufList
127 ACLDomainData::dump() const
128 {
129 AclDomainDataDumpVisitor visitor;
130 domains->visit(visitor);
131 return visitor.contents;
132 }
133
134 void
135 ACLDomainData::parse()
136 {
137 char *t = NULL;
138
139 if (!domains)
140 domains = new Splay<char *>();
141
142 while ((t = strtokFile())) {
143 Tolower(t);
144 domains->insert(xstrdup(t), aclDomainCompare);
145 }
146 }
147
148 bool
149 ACLDomainData::empty() const
150 {
151 return domains->empty();
152 }
153
154 ACLData<char const *> *
155 ACLDomainData::clone() const
156 {
157 /* Splay trees don't clone yet. */
158 assert (!domains);
159 return new ACLDomainData;
160 }
161