]> git.ipfire.org Git - thirdparty/squid.git/blob - src/acl/DestinationIp.cc
Merged from trunk rev.14625
[thirdparty/squid.git] / src / acl / DestinationIp.cc
1 /*
2 * Copyright (C) 1996-2016 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/DestinationIp.h"
13 #include "acl/FilledChecklist.h"
14 #include "client_side.h"
15 #include "comm/Connection.h"
16 #include "http/Stream.h"
17 #include "HttpRequest.h"
18 #include "SquidConfig.h"
19
20 ACLFlag ACLDestinationIP::SupportedFlags[] = {ACL_F_NO_LOOKUP, ACL_F_END};
21
22 char const *
23 ACLDestinationIP::typeString() const
24 {
25 return "dst";
26 }
27
28 int
29 ACLDestinationIP::match(ACLChecklist *cl)
30 {
31 ACLFilledChecklist *checklist = Filled(cl);
32
33 // if there is no HTTP request details fallback to the dst_addr
34 if (!checklist->request)
35 return ACLIP::match(checklist->dst_addr);
36
37 // Bug 3243: CVE 2009-0801
38 // Bypass of browser same-origin access control in intercepted communication
39 // To resolve this we will force DIRECT and only to the original client destination.
40 // In which case, we also need this ACL to accurately match the destination
41 if (Config.onoff.client_dst_passthru && (checklist->request->flags.intercepted || checklist->request->flags.interceptTproxy)) {
42 const auto conn = checklist->conn();
43 return (conn && conn->clientConnection) ?
44 ACLIP::match(conn->clientConnection->local) : -1;
45 }
46
47 if (flags.isSet(ACL_F_NO_LOOKUP)) {
48 if (!checklist->request->url.hostIsNumeric()) {
49 debugs(28, 3, "No-lookup DNS ACL '" << AclMatchedName << "' for " << checklist->request->url.host());
50 return 0;
51 }
52
53 if (ACLIP::match(checklist->request->url.hostIP()))
54 return 1;
55 return 0;
56 }
57
58 const ipcache_addrs *ia = ipcache_gethostbyname(checklist->request->url.host(), IP_LOOKUP_IF_MISS);
59
60 if (ia) {
61 /* Entry in cache found */
62
63 for (int k = 0; k < (int) ia->count; ++k) {
64 if (ACLIP::match(ia->in_addrs[k]))
65 return 1;
66 }
67
68 return 0;
69 } else if (!checklist->request->flags.destinationIpLookedUp) {
70 /* No entry in cache, lookup not attempted */
71 debugs(28, 3, "can't yet compare '" << name << "' ACL for " << checklist->request->url.host());
72 if (checklist->goAsync(DestinationIPLookup::Instance()))
73 return -1;
74 // else fall through to mismatch, hiding the lookup failure (XXX)
75 }
76
77 return 0;
78 }
79
80 DestinationIPLookup DestinationIPLookup::instance_;
81
82 DestinationIPLookup *
83 DestinationIPLookup::Instance()
84 {
85 return &instance_;
86 }
87
88 void
89 DestinationIPLookup::checkForAsync(ACLChecklist *cl)const
90 {
91 ACLFilledChecklist *checklist = Filled(cl);
92 ipcache_nbgethostbyname(checklist->request->url.host(), LookupDone, checklist);
93 }
94
95 void
96 DestinationIPLookup::LookupDone(const ipcache_addrs *, const Dns::LookupDetails &details, void *data)
97 {
98 ACLFilledChecklist *checklist = Filled((ACLChecklist*)data);
99 checklist->request->flags.destinationIpLookedUp = true;
100 checklist->request->recordLookup(details);
101 checklist->resumeNonBlockingCheck(DestinationIPLookup::Instance());
102 }
103
104 ACL *
105 ACLDestinationIP::clone() const
106 {
107 return new ACLDestinationIP(*this);
108 }
109