]>
Commit | Line | Data |
---|---|---|
3841dd46 | 1 | /* |
bbc27441 | 2 | * Copyright (C) 1996-2014 The Squid Software Foundation and contributors |
3841dd46 | 3 | * |
bbc27441 AJ |
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. | |
3841dd46 | 7 | */ |
8 | ||
bbc27441 AJ |
9 | /* DEBUG: section 28 Access Control */ |
10 | ||
582c2af2 | 11 | #include "squid.h" |
3ad63615 | 12 | #include "acl/Checklist.h" |
602d9612 | 13 | #include "acl/DomainData.h" |
8a01b99e | 14 | #include "cache_cf.h" |
582c2af2 | 15 | #include "Debug.h" |
c9c46c8b | 16 | #include "src/URL.h" |
ed6e9fb9 | 17 | #include "util.h" |
3841dd46 | 18 | |
3841dd46 | 19 | template<class T> |
20 | inline void | |
21 | xRefFree(T &thing) | |
22 | { | |
23 | xfree (thing); | |
24 | } | |
25 | ||
26 | ACLDomainData::~ACLDomainData() | |
27 | { | |
28 | if (domains) | |
62e76326 | 29 | domains->destroy(xRefFree); |
30 | } | |
3841dd46 | 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 | ||
7e6b941f | 49 | /* compare a host and a domain */ |
50 | ||
51 | static int | |
52 | aclHostDomainCompare( char *const &a, char * const &b) | |
53 | { | |
1dc746da AJ |
54 | const char *h = static_cast<const char *>(a); |
55 | const char *d = static_cast<const char *>(b); | |
7e6b941f | 56 | return matchDomainName(h, d); |
57 | } | |
58 | ||
3841dd46 | 59 | /* compare two domains */ |
60 | ||
61 | template<class T> | |
62 | int | |
63 | aclDomainCompare(T const &a, T const &b) | |
64 | { | |
1dc746da AJ |
65 | char * const d1 = static_cast<char *>(b); |
66 | char * const d2 = static_cast<char *>(a); | |
3841dd46 | 67 | int ret; |
68 | ret = aclHostDomainCompare(d1, d2); | |
62e76326 | 69 | |
3841dd46 | 70 | if (ret != 0) { |
62e76326 | 71 | char *const d3 = d2; |
72 | char *const d4 = d1; | |
73 | ret = aclHostDomainCompare(d3, d4); | |
14e563cb AJ |
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 | |
3a835d3f AJ |
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"); | |
14e563cb AJ |
81 | } |
82 | } else if (ret == 0) { | |
3a835d3f AJ |
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 | } | |
14e563cb AJ |
89 | // When a.example.com comes before .example.com in an ACL |
90 | // discarding the wildcard is critically bad. | |
3a835d3f AJ |
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 << "'"); | |
14e563cb | 95 | self_destruct(); |
3841dd46 | 96 | } |
62e76326 | 97 | |
3841dd46 | 98 | return ret; |
99 | } | |
100 | ||
3841dd46 | 101 | bool |
102 | ACLDomainData::match(char const *host) | |
103 | { | |
104 | if (host == NULL) | |
62e76326 | 105 | return 0; |
106 | ||
bf8fe701 | 107 | debugs(28, 3, "aclMatchDomainList: checking '" << host << "'"); |
62e76326 | 108 | |
3841dd46 | 109 | domains = domains->splay((char *)host, aclHostDomainCompare); |
62e76326 | 110 | |
bf8fe701 | 111 | debugs(28, 3, "aclMatchDomainList: '" << host << "' " << (splayLastResult ? "NOT found" : "found")); |
62e76326 | 112 | |
3841dd46 | 113 | return !splayLastResult; |
114 | } | |
115 | ||
116 | static void | |
117 | aclDumpDomainListWalkee(char * const & node_data, void *outlist) | |
118 | { | |
8966008b FC |
119 | /* outlist is really a SBufList ** */ |
120 | static_cast<SBufList *>(outlist)->push_back(SBuf(node_data)); | |
3841dd46 | 121 | } |
122 | ||
8966008b | 123 | SBufList |
4f8ca96e | 124 | ACLDomainData::dump() const |
3841dd46 | 125 | { |
8966008b | 126 | SBufList sl; |
3841dd46 | 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 | */ | |
8966008b FC |
131 | domains->walk(aclDumpDomainListWalkee, &sl); |
132 | return sl; | |
3841dd46 | 133 | } |
134 | ||
135 | void | |
136 | ACLDomainData::parse() | |
137 | { | |
138 | char *t = NULL; | |
62e76326 | 139 | |
3841dd46 | 140 | while ((t = strtokFile())) { |
62e76326 | 141 | Tolower(t); |
142 | domains = domains->insert(xstrdup(t), aclDomainCompare); | |
3841dd46 | 143 | } |
144 | } | |
145 | ||
65092baf | 146 | bool |
147 | ACLDomainData::empty() const | |
148 | { | |
290eb6b9 | 149 | return domains->empty(); |
65092baf | 150 | } |
151 | ||
5dee515e | 152 | ACLData<char const *> * |
3841dd46 | 153 | ACLDomainData::clone() const |
154 | { | |
155 | /* Splay trees don't clone yet. */ | |
156 | assert (!domains); | |
157 | return new ACLDomainData; | |
158 | } | |
f53969cc | 159 |