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