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