]>
Commit | Line | Data |
---|---|---|
64bdef96 | 1 | /* |
77b1029d | 2 | * Copyright (C) 1996-2020 The Squid Software Foundation and contributors |
64bdef96 | 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. | |
64bdef96 AR |
7 | */ |
8 | ||
582c2af2 | 9 | #include "squid.h" |
71be37e0 | 10 | #include "acl/FilledChecklist.h" |
582c2af2 FC |
11 | #include "acl/Gadgets.h" |
12 | #include "adaptation/AccessRule.h" | |
64bdef96 | 13 | #include "adaptation/Config.h" |
582c2af2 | 14 | #include "adaptation/History.h" |
64bdef96 | 15 | #include "adaptation/Service.h" |
62c7f90e | 16 | #include "adaptation/ServiceGroups.h" |
582c2af2 FC |
17 | #include "ConfigParser.h" |
18 | #include "globals.h" | |
19 | #include "HttpReply.h" | |
71be37e0 | 20 | #include "HttpRequest.h" |
582c2af2 | 21 | #include "Store.h" |
64bdef96 | 22 | |
c8ea3cc0 FC |
23 | #include <algorithm> |
24 | ||
8f361c50 | 25 | bool Adaptation::Config::Enabled = false; |
3ff65596 | 26 | char *Adaptation::Config::masterx_shared_name = NULL; |
a22e6cd3 | 27 | int Adaptation::Config::service_iteration_limit = 16; |
22fff3bf AR |
28 | int Adaptation::Config::send_client_ip = false; |
29 | int Adaptation::Config::send_username = false; | |
30 | int Adaptation::Config::use_indirect_client = true; | |
4668df3d CT |
31 | static const char *protectedFieldNamesRaw[] = { |
32 | "Allow", | |
33 | "Date", | |
d7f4a0b7 | 34 | "Encapsulated", |
4668df3d | 35 | "ISTag", |
d7f4a0b7 | 36 | "Max-Connections", |
4668df3d CT |
37 | "Methods", |
38 | "Opt-body-type", | |
d7f4a0b7 | 39 | "Options-TTL", |
d7f4a0b7 | 40 | "Preview", |
4668df3d CT |
41 | "Service", |
42 | "Service-ID", | |
d7f4a0b7 | 43 | "Transfer-Complete", |
4668df3d CT |
44 | "Transfer-Ignore", |
45 | "Transfer-Preview" | |
d7f4a0b7 | 46 | }; |
4668df3d CT |
47 | static const Notes::Keys protectedFieldNames(std::begin(protectedFieldNamesRaw), std::end(protectedFieldNamesRaw)); |
48 | Notes Adaptation::Config::metaHeaders("ICAP header", &protectedFieldNames); | |
c302ddb5 | 49 | bool Adaptation::Config::needHistory = false; |
8f361c50 | 50 | |
e1e90d26 AR |
51 | Adaptation::ServiceConfig* |
52 | Adaptation::Config::newServiceConfig() const | |
53 | { | |
54 | return new ServiceConfig(); | |
55 | } | |
56 | ||
7e8c4ee9 CT |
57 | void |
58 | Adaptation::Config::removeService(const String& service) | |
59 | { | |
60 | removeRule(service); | |
61 | const Groups& groups = AllGroups(); | |
62 | for (unsigned int i = 0; i < groups.size(); ) { | |
63 | const ServiceGroupPointer group = groups[i]; | |
64 | const ServiceGroup::Store& services = group->services; | |
65 | typedef ServiceGroup::Store::const_iterator SGSI; | |
66 | for (SGSI it = services.begin(); it != services.end(); ++it) { | |
67 | if (*it == service) { | |
68 | group->removedServices.push_back(service); | |
6e1410f9 FC |
69 | ServiceGroup::Store::iterator newend; |
70 | newend = std::remove(group->services.begin(), group->services.end(), service); | |
71 | group->services.resize(newend-group->services.begin()); | |
c8ea3cc0 | 72 | debugs(93, 5, "adaptation service " << service << |
7e8c4ee9 CT |
73 | " removed from group " << group->id); |
74 | break; | |
75 | } | |
76 | } | |
77 | if (services.empty()) { | |
78 | removeRule(group->id); | |
6e1410f9 FC |
79 | Groups::iterator newend; |
80 | newend = std::remove(AllGroups().begin(), AllGroups().end(), group); | |
81 | AllGroups().resize(newend-AllGroups().begin()); | |
7e8c4ee9 CT |
82 | } else { |
83 | ++i; | |
84 | } | |
85 | } | |
86 | } | |
87 | ||
c302ddb5 CT |
88 | Adaptation::ServiceConfigPointer |
89 | Adaptation::Config::findServiceConfig(const String &service) | |
90 | { | |
91 | typedef ServiceConfigs::const_iterator SCI; | |
92 | const ServiceConfigs& configs = serviceConfigs; | |
93 | for (SCI cfg = configs.begin(); cfg != configs.end(); ++cfg) { | |
94 | if ((*cfg)->key == service) | |
95 | return *cfg; | |
96 | } | |
97 | return NULL; | |
98 | } | |
99 | ||
7e8c4ee9 CT |
100 | void |
101 | Adaptation::Config::removeRule(const String& id) | |
102 | { | |
103 | typedef AccessRules::const_iterator ARI; | |
104 | const AccessRules& rules = AllRules(); | |
105 | for (ARI it = rules.begin(); it != rules.end(); ++it) { | |
106 | AccessRule* rule = *it; | |
107 | if (rule->groupId == id) { | |
c8ea3cc0 | 108 | debugs(93, 5, "removing access rules for:" << id); |
6e1410f9 FC |
109 | AccessRules::iterator newend; |
110 | newend = std::remove(AllRules().begin(), AllRules().end(), rule); | |
111 | AllRules().resize(newend-AllRules().begin()); | |
7e8c4ee9 CT |
112 | delete (rule); |
113 | break; | |
114 | } | |
115 | } | |
116 | } | |
117 | ||
118 | void | |
119 | Adaptation::Config::clear() | |
120 | { | |
121 | debugs(93, 3, HERE << "rules: " << AllRules().size() << ", groups: " << | |
122 | AllGroups().size() << ", services: " << serviceConfigs.size()); | |
123 | typedef ServiceConfigs::const_iterator SCI; | |
124 | const ServiceConfigs& configs = serviceConfigs; | |
125 | for (SCI cfg = configs.begin(); cfg != configs.end(); ++cfg) | |
126 | removeService((*cfg)->key); | |
c33a88ca | 127 | serviceConfigs.clear(); |
7e8c4ee9 CT |
128 | debugs(93, 3, HERE << "rules: " << AllRules().size() << ", groups: " << |
129 | AllGroups().size() << ", services: " << serviceConfigs.size()); | |
130 | } | |
131 | ||
64bdef96 AR |
132 | void |
133 | Adaptation::Config::parseService() | |
134 | { | |
e1e90d26 | 135 | ServiceConfigPointer cfg = newServiceConfig(); |
a22e6cd3 AR |
136 | if (!cfg->parse()) { |
137 | fatalf("%s:%d: malformed adaptation service configuration", | |
e1381638 | 138 | cfg_filename, config_lineno); |
a22e6cd3 | 139 | } |
64bdef96 AR |
140 | serviceConfigs.push_back(cfg); |
141 | } | |
142 | ||
143 | void | |
144 | Adaptation::Config::freeService() | |
145 | { | |
76fc7e57 AJ |
146 | FreeAccess(); |
147 | FreeServiceGroups(); | |
148 | ||
149 | DetachServices(); | |
150 | ||
c33a88ca | 151 | serviceConfigs.clear(); |
64bdef96 AR |
152 | } |
153 | ||
154 | void | |
155 | Adaptation::Config::dumpService(StoreEntry *entry, const char *name) const | |
156 | { | |
157 | typedef Services::iterator SCI; | |
158 | for (SCI i = AllServices().begin(); i != AllServices().end(); ++i) { | |
159 | const ServiceConfig &cfg = (*i)->cfg(); | |
88df846b CT |
160 | bool isEcap = cfg.protocol.caseCmp("ecap") == 0; |
161 | bool isIcap = !isEcap; | |
162 | const char *optConnectionEncryption = ""; | |
163 | // Print connections_encrypted option if no default value is used | |
164 | if (cfg.secure.encryptTransport && !cfg.connectionEncryption) | |
165 | optConnectionEncryption = " connection-encryption=off"; | |
166 | else if (isEcap && !cfg.connectionEncryption) | |
167 | optConnectionEncryption = " connection-encryption=off"; | |
168 | else if (isIcap && !cfg.secure.encryptTransport && cfg.connectionEncryption) | |
169 | optConnectionEncryption = " connection-encryption=on"; | |
170 | ||
171 | storeAppendPrintf(entry, "%s " SQUIDSTRINGPH " %s_%s %d " SQUIDSTRINGPH "%s\n", | |
af6a12ee AJ |
172 | name, |
173 | SQUIDSTRINGPRINT(cfg.key), | |
174 | cfg.methodStr(), cfg.vectPointStr(), cfg.bypass, | |
88df846b | 175 | SQUIDSTRINGPRINT(cfg.uri), |
ff89bfa0 | 176 | |
88df846b | 177 | optConnectionEncryption); |
64bdef96 AR |
178 | } |
179 | } | |
180 | ||
7e8c4ee9 | 181 | bool |
64bdef96 AR |
182 | Adaptation::Config::finalize() |
183 | { | |
7e8c4ee9 CT |
184 | if (!onoff) { |
185 | clear(); | |
186 | return false; | |
187 | } | |
188 | ||
64bdef96 | 189 | // create service reps from service configs |
e1e90d26 AR |
190 | int created = 0; |
191 | ||
192 | typedef ServiceConfigs::const_iterator VISCI; | |
193 | const ServiceConfigs &configs = serviceConfigs; | |
62c7f90e | 194 | for (VISCI i = configs.begin(); i != configs.end(); ++i) { |
e1e90d26 AR |
195 | const ServiceConfigPointer cfg = *i; |
196 | if (FindService(cfg->key) != NULL) { | |
fa84c01d | 197 | debugs(93, DBG_CRITICAL, "ERROR: Duplicate adaptation service name: " << |
e1e90d26 | 198 | cfg->key); |
26ac0430 AJ |
199 | continue; // TODO: make fatal |
200 | } | |
e1e90d26 AR |
201 | ServicePointer s = createService(cfg); |
202 | if (s != NULL) { | |
62c7f90e | 203 | AllServices().push_back(s); |
742a021b | 204 | ++created; |
e1e90d26 | 205 | } |
64bdef96 AR |
206 | } |
207 | ||
e1e90d26 AR |
208 | debugs(93,3, HERE << "Created " << created << " adaptation services"); |
209 | ||
210 | // services remember their configs; we do not have to | |
c33a88ca | 211 | serviceConfigs.clear(); |
7e8c4ee9 | 212 | return true; |
64bdef96 AR |
213 | } |
214 | ||
62c7f90e AR |
215 | // poor man for_each |
216 | template <class Collection> | |
217 | static void | |
218 | FinalizeEach(Collection &collection, const char *label) | |
64bdef96 | 219 | { |
62c7f90e AR |
220 | typedef typename Collection::iterator CI; |
221 | for (CI i = collection.begin(); i != collection.end(); ++i) | |
222 | (*i)->finalize(); | |
64bdef96 | 223 | |
192378eb | 224 | debugs(93,2, HERE << "Initialized " << collection.size() << ' ' << label); |
64bdef96 AR |
225 | } |
226 | ||
227 | void | |
8f361c50 | 228 | Adaptation::Config::Finalize(bool enabled) |
64bdef96 | 229 | { |
8f361c50 | 230 | Enabled = enabled; |
e0236918 | 231 | debugs(93, DBG_IMPORTANT, "Adaptation support is " << (Enabled ? "on" : "off.")); |
8f361c50 | 232 | |
62c7f90e AR |
233 | FinalizeEach(AllServices(), "message adaptation services"); |
234 | FinalizeEach(AllGroups(), "message adaptation service groups"); | |
235 | FinalizeEach(AllRules(), "message adaptation access rules"); | |
236 | } | |
64bdef96 AR |
237 | |
238 | void | |
62c7f90e | 239 | Adaptation::Config::ParseServiceSet() |
64bdef96 | 240 | { |
a22e6cd3 AR |
241 | Adaptation::Config::ParseServiceGroup(new ServiceSet); |
242 | } | |
243 | ||
244 | void | |
245 | Adaptation::Config::ParseServiceChain() | |
246 | { | |
247 | Adaptation::Config::ParseServiceGroup(new ServiceChain); | |
248 | } | |
249 | ||
250 | void | |
251 | Adaptation::Config::ParseServiceGroup(ServiceGroupPointer g) | |
252 | { | |
253 | assert(g != NULL); | |
62c7f90e AR |
254 | g->parse(); |
255 | AllGroups().push_back(g); | |
64bdef96 AR |
256 | } |
257 | ||
258 | void | |
a22e6cd3 | 259 | Adaptation::Config::FreeServiceGroups() |
64bdef96 | 260 | { |
62c7f90e | 261 | while (!AllGroups().empty()) { |
a22e6cd3 | 262 | // groups are refcounted so we do not explicitly delete them |
b6b637eb AR |
263 | AllGroups().pop_back(); |
264 | } | |
64bdef96 AR |
265 | } |
266 | ||
267 | void | |
a22e6cd3 | 268 | Adaptation::Config::DumpServiceGroups(StoreEntry *entry, const char *name) |
64bdef96 | 269 | { |
62c7f90e AR |
270 | typedef Groups::iterator GI; |
271 | for (GI i = AllGroups().begin(); i != AllGroups().end(); ++i) | |
2c1fd837 | 272 | storeAppendPrintf(entry, "%s " SQUIDSTRINGPH "\n", name, SQUIDSTRINGPRINT((*i)->id)); |
62c7f90e | 273 | } |
64bdef96 | 274 | |
62c7f90e AR |
275 | void |
276 | Adaptation::Config::ParseAccess(ConfigParser &parser) | |
277 | { | |
2eceb328 | 278 | String groupId = ConfigParser::NextToken(); |
287bbe9a | 279 | AccessRule *r; |
899fad67 | 280 | if (!(r=FindRuleByGroupId(groupId))) { |
af6a12ee AJ |
281 | r = new AccessRule(groupId); |
282 | AllRules().push_back(r); | |
899fad67 | 283 | } |
62c7f90e | 284 | r->parse(parser); |
62c7f90e | 285 | } |
64bdef96 AR |
286 | |
287 | void | |
62c7f90e | 288 | Adaptation::Config::FreeAccess() |
64bdef96 | 289 | { |
62c7f90e AR |
290 | while (!AllRules().empty()) { |
291 | delete AllRules().back(); | |
292 | AllRules().pop_back(); | |
b6b637eb | 293 | } |
64bdef96 AR |
294 | } |
295 | ||
296 | void | |
62c7f90e | 297 | Adaptation::Config::DumpAccess(StoreEntry *entry, const char *name) |
64bdef96 AR |
298 | { |
299 | LOCAL_ARRAY(char, nom, 64); | |
300 | ||
62c7f90e AR |
301 | typedef AccessRules::iterator CI; |
302 | for (CI i = AllRules().begin(); i != AllRules().end(); ++i) { | |
2c1fd837 | 303 | snprintf(nom, 64, "%s " SQUIDSTRINGPH, name, SQUIDSTRINGPRINT((*i)->groupId)); |
62c7f90e | 304 | dump_acl_access(entry, nom, (*i)->acl); |
b6b637eb | 305 | } |
64bdef96 AR |
306 | } |
307 | ||
c9568681 | 308 | Adaptation::Config::Config() : |
f53969cc SM |
309 | onoff(0), service_failure_limit(0), oldest_service_failure(0), |
310 | service_revival_delay(0) | |
c9568681 | 311 | {} |
64bdef96 | 312 | |
26ac0430 | 313 | // XXX: this is called for ICAP and eCAP configs, but deals mostly |
62c7f90e | 314 | // with global arrays shared by those individual configs |
64bdef96 AR |
315 | Adaptation::Config::~Config() |
316 | { | |
62c7f90e | 317 | freeService(); |
64bdef96 | 318 | } |
f53969cc | 319 |