ServerName.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2023 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/FilledChecklist.h"
13 #include "acl/ServerName.h"
14 #include "anyp/Host.h"
15 #include "client_side.h"
16 #include "http/Stream.h"
17 #include "HttpRequest.h"
18 #include "sbuf/Stream.h"
19 #include "ssl/bio.h"
20 #include "ssl/ServerBump.h"
21 #include "ssl/support.h"
22 
23 // Compare function for tree search algorithms
24 static int
25 aclHostDomainCompare( char *const &a, char * const &b)
26 {
27  const char *h = static_cast<const char *>(a);
28  const char *d = static_cast<const char *>(b);
29  debugs(28, 7, "Match:" << h << " <> " << d);
30  return matchDomainName(h, d, mdnHonorWildcards);
31 }
32 
33 bool
34 ACLServerNameData::match(const char *host)
35 {
36  if (host == nullptr)
37  return 0;
38 
39  debugs(28, 3, "checking '" << host << "'");
40 
41  char *h = const_cast<char *>(host);
42  char const * const * result = domains->find(h, aclHostDomainCompare);
43 
44  debugs(28, 3, "'" << host << "' " << (result ? "found" : "NOT found"));
45 
46  return (result != nullptr);
47 
48 }
49 
50 namespace Acl {
51 
54 {
55 public:
57 
58 protected:
59  /* GeneralNameMatcher API */
60  bool matchDomainName(const Dns::DomainName &) const override;
61  bool matchIp(const Ip::Address &) const override;
62 
63 private:
64  // TODO: Make ServerNameCheck::Parameters::match() and this reference constant.
66 };
67 
68 } // namespace Acl
69 
70 bool
72 {
73  return parameters.match(SBuf(domain).c_str()); // TODO: Upgrade string-matching ACLs to SBuf
74 }
75 
76 bool
78 {
79  // We are given an Ip::Address, but our ACL parameters use case-insensitive
80  // string equality (::matchDomainName) or regex string matches. There are
81  // many ways to convert an IPv6 address to a string, but only one format can
82  // correctly match certain configured parameters. Our ssl::server_name docs
83  // request the following ACL parameter formatting (that this to-string
84  // conversion code produces): IPv6 addresses use "::" notation (where
85  // applicable) and are not bracketed.
86  //
87  // Similar problems affect dstdomain ACLs. TODO: Instead of relying on users
88  // reading docs and following their inet_ntop(3) implementation to match
89  // IPv6 addresses handled by matchDomainName(), enhance matchDomainName()
90  // code and ACL parameter storage to support Ip::Address objects.
91  char hostStr[MAX_IPSTRLEN];
92  (void)ip.toStr(hostStr, sizeof(hostStr)); // no brackets
93  return parameters.match(hostStr);
94 }
95 
96 int
98 {
99  const auto checklist = Filled(ch);
100 
101  assert(checklist != nullptr && checklist->request != nullptr);
102 
103  std::optional<AnyP::Host> serverNameFromConn;
104  if (ConnStateData *conn = checklist->conn()) {
105  std::optional<AnyP::Host> clientRequestedServerName;
106  const auto &clientSni = conn->tlsClientSni();
107  if (clientSni.isEmpty()) {
108  clientRequestedServerName = checklist->request->url.parsedHost();
109  } else {
110  // RFC 6066: "The hostname is represented as a byte string using
111  // ASCII encoding"; "Literal IPv4 and IPv6 addresses are not
112  // permitted". TODO: Store TlsDetails::serverName and similar
113  // domains using a new domain-only type instead of SBuf.
114  clientRequestedServerName = AnyP::Host::ParseSimpleDomainName(clientSni);
115  }
116 
117  if (useConsensus) {
118  X509 *peer_cert = conn->serverBump() ? conn->serverBump()->serverCert.get() : nullptr;
119  // use the client requested name if it matches the server
120  // certificate or if the certificate is not available
121  if (!peer_cert || !clientRequestedServerName ||
122  Ssl::HasSubjectName(*peer_cert, *clientRequestedServerName))
123  serverNameFromConn = clientRequestedServerName;
124  } else if (useClientRequested)
125  serverNameFromConn = clientRequestedServerName;
126  else { // either no options or useServerProvided
127  if (X509 *peer_cert = (conn->serverBump() ? conn->serverBump()->serverCert.get() : nullptr))
128  return Ssl::HasMatchingSubjectName(*peer_cert, ServerNameMatcher(*data));
129  if (!useServerProvided)
130  serverNameFromConn = clientRequestedServerName;
131  }
132  }
133 
134  std::optional<SBuf> printedServerName;
135  if (serverNameFromConn)
136  printedServerName = ToSBuf(*serverNameFromConn); // no brackets
137  const auto serverName = printedServerName ? printedServerName->c_str() : "none";
138  return data->match(serverName);
139 }
140 
141 const Acl::Options &
143 {
144  static const Acl::BooleanOption ClientRequested("--client-requested");
145  static const Acl::BooleanOption ServerProvided("--server-provided");
146  static const Acl::BooleanOption Consensus("--consensus");
147  static const Acl::Options MyOptions = { &ClientRequested, &ServerProvided, &Consensus };
148  ClientRequested.linkWith(&useClientRequested);
149  ServerProvided.linkWith(&useServerProvided);
150  Consensus.linkWith(&useConsensus);
151  return MyOptions;
152 }
153 
154 bool
156 {
157  int optionCount = 0;
158 
159  if (useClientRequested)
160  optionCount++;
161  if (useServerProvided)
162  optionCount++;
163  if (useConsensus)
164  optionCount++;
165 
166  if (optionCount > 1) {
167  debugs(28, DBG_CRITICAL, "ERROR: Multiple options given for the server_name ACL");
168  return false;
169  }
170  return true;
171 }
172 
bool HasMatchingSubjectName(X509 &, const GeneralNameMatcher &)
Definition: support.cc:302
const Value * find(FindValue const &, int(*compare)(FindValue const &a, Value const &b)) const
Definition: splay.h:305
a type-specific Option (e.g., a boolean –toggle or -m=SBuf)
Definition: Options.h:129
#define DBG_CRITICAL
Definition: Stream.h:37
bool matchIp(const Ip::Address &) const override
Definition: ServerName.cc:77
std::vector< const Option * > Options
Definition: Options.h:217
bool match(const char *) override
Definition: ServerName.cc:34
@ mdnHonorWildcards
Definition: Uri.h:228
static std::optional< Host > ParseSimpleDomainName(const SBuf &)
Definition: Host.cc:49
ServerNameMatcher(ServerNameCheck::Parameters &p)
Definition: ServerName.cc:56
Definition: SBuf.h:93
void linkWith(Recipient *recipient) const
who to tell when this option is enabled
Definition: Options.h:137
Configured ACL parameter(s) (e.g., domain names in dstdomain ACL).
Definition: Data.h:17
Definition: Acl.cc:33
const Acl::Options & options() override
Definition: ServerName.cc:142
int matchDomainName(const char *h, const char *d, MatchDomainNameFlags flags)
Definition: Uri.cc:860
char * toStr(char *buf, const unsigned int blen, int force=AF_UNSPEC) const
Definition: Address.cc:812
#define MAX_IPSTRLEN
Length of buffer that needs to be allocated to old a null-terminated IP-string.
Definition: forward.h:25
GeneralNameMatcher for matching configured ACL parameters.
Definition: ServerName.cc:53
ACLFilledChecklist * Filled(ACLChecklist *checklist)
convenience and safety wrapper for dynamic_cast<ACLFilledChecklist*>
static int aclHostDomainCompare(char *const &a, char *const &b)
Definition: ServerName.cc:25
Splay< char * > * domains
Definition: DomainData.h:28
#define assert(EX)
Definition: assert.h:17
bool valid() const override
Definition: ServerName.cc:155
an algorithm for checking/testing/comparing X.509 certificate names
Definition: support.h:298
SBuf ToSBuf(Args &&... args)
slowly stream-prints all arguments into a freshly allocated SBuf
Definition: Stream.h:63
virtual bool match(M)=0
bool HasSubjectName(X509 &, const AnyP::Host &)
whether at least one common or alternate subject name matches the given one
Definition: support.cc:333
int match(ACLChecklist *) override
Matches the actual data in checklist against this Acl::Node.
Definition: ServerName.cc:97
ServerNameCheck::Parameters & parameters
configured ACL parameters
Definition: ServerName.cc:65
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:192
bool matchDomainName(const Dns::DomainName &) const override
Definition: ServerName.cc:71

 

Introduction

Documentation

Support

Miscellaneous