]>
Commit | Line | Data |
---|---|---|
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 | |
28 | static int | |
29 | aclHostDomainCompare( 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 | ||
37 | bool | |
38 | ACLServerNameData::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 | ||
54 | ACLData<char const *> * | |
55 | ACLServerNameData::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 | |
65 | template<class MatchType> | |
66 | int | |
67 | check_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 | ||
89 | int | |
90 | ACLServerNameStrategy::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 | ||
119 | ACLServerNameStrategy * | |
120 | ACLServerNameStrategy::Instance() | |
121 | { | |
122 | return &Instance_; | |
123 | } | |
124 | ||
125 | ACLServerNameStrategy ACLServerNameStrategy::Instance_; | |
126 |