]> git.ipfire.org Git - thirdparty/squid.git/blob - src/acl/ServerName.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / acl / ServerName.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/Checklist.h"
13 #include "acl/DomainData.h"
14 #include "acl/RegexData.h"
15 #include "acl/ServerName.h"
16 #include "client_side.h"
17 #include "fde.h"
18 #include "HttpRequest.h"
19 #include "ipcache.h"
20 #include "SquidString.h"
21 #include "ssl/bio.h"
22 #include "ssl/ServerBump.h"
23 #include "ssl/support.h"
24 #include "URL.h"
25
26 // Compare function for tree search algorithms
27 static int
28 aclHostDomainCompare( char *const &a, char * const &b)
29 {
30 const char *h = static_cast<const char *>(a);
31 const char *d = static_cast<const char *>(b);
32 debugs(28, 7, "Match:" << h << " <> " << d);
33 return matchDomainName(h, d, true);
34 }
35
36 bool
37 ACLServerNameData::match(const char *host)
38 {
39 if (host == NULL)
40 return 0;
41
42 debugs(28, 3, "checking '" << host << "'");
43
44 char *h = const_cast<char *>(host);
45 char const * const * result = domains->find(h, aclHostDomainCompare);
46
47 debugs(28, 3, "'" << host << "' " << (result ? "found" : "NOT found"));
48
49 return (result != NULL);
50
51 }
52
53 ACLData<char const *> *
54 ACLServerNameData::clone() const
55 {
56 /* Splay trees don't clone yet. */
57 assert (!domains);
58 return new ACLServerNameData;
59 }
60
61 /// A helper function to be used with Ssl::matchX509CommonNames().
62 /// \retval 0 when the name (cn or an alternate name) matches acl data
63 /// \retval 1 when the name does not match
64 template<class MatchType>
65 int
66 check_cert_domain( void *check_data, ASN1_STRING *cn_data)
67 {
68 char cn[1024];
69 ACLData<MatchType> * data = (ACLData<MatchType> *)check_data;
70
71 if (cn_data->length > (int)sizeof(cn) - 1)
72 return 1; // ignore data that does not fit our buffer
73
74 char *s = reinterpret_cast<char *>(cn_data->data);
75 char *d = cn;
76 for (int i = 0; i < cn_data->length; ++i, ++d, ++s) {
77 if (*s == '\0')
78 return 1; // always a domain mismatch. contains 0x00
79 *d = *s;
80 }
81 cn[cn_data->length] = '\0';
82 debugs(28, 4, "Verifying certificate name/subjectAltName " << cn);
83 if (data->match(cn))
84 return 0;
85 return 1;
86 }
87
88 int
89 ACLServerNameStrategy::match (ACLData<MatchType> * &data, ACLFilledChecklist *checklist, ACLFlags &flags)
90 {
91 assert(checklist != NULL && checklist->request != NULL);
92
93 if (checklist->conn() && checklist->conn()->serverBump()) {
94 if (X509 *peer_cert = checklist->conn()->serverBump()->serverCert.get()) {
95 if (Ssl::matchX509CommonNames(peer_cert, (void *)data, check_cert_domain<MatchType>))
96 return 1;
97 }
98 }
99
100 const char *serverName = NULL;
101 if (checklist->conn() && !checklist->conn()->sslCommonName().isEmpty()) {
102 SBuf scn = checklist->conn()->sslCommonName();
103 serverName = scn.c_str();
104 }
105
106 if (serverName == NULL)
107 serverName = checklist->request->url.host();
108
109 if (serverName && data->match(serverName)) {
110 return 1;
111 }
112
113 return data->match("none");
114 }
115
116 ACLServerNameStrategy *
117 ACLServerNameStrategy::Instance()
118 {
119 return &Instance_;
120 }
121
122 ACLServerNameStrategy ACLServerNameStrategy::Instance_;
123