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