1
#pragma once
2

            
3
#include <memory>
4

            
5
#include "envoy/config/core/v3/extension.pb.h"
6
#include "envoy/extensions/transport_sockets/tls/v3/common.pb.h"
7
#include "envoy/ssl/certificate_validation_context_config.h"
8
#include "envoy/type/matcher/v3/string.pb.h"
9

            
10
#include "source/common/common/hash.h"
11
#include "source/common/common/matchers.h"
12
#include "source/common/protobuf/protobuf.h"
13
#include "source/common/tls/utility.h"
14

            
15
#include "openssl/x509v3.h"
16

            
17
namespace Envoy {
18
namespace Ssl {
19

            
20
/**
21
 * Interface to verify if there is a match in a list of subject alternative
22
 * names.
23
 */
24
class SanMatcher {
25
public:
26
  virtual bool match(GENERAL_NAME const*) const PURE;
27
8118
  virtual bool match(GENERAL_NAME const* general_name, const StreamInfo::StreamInfo&) const {
28
8118
    return match(general_name);
29
8118
  }
30
5269
  virtual ~SanMatcher() = default;
31
};
32

            
33
using SanMatcherPtr = std::unique_ptr<SanMatcher>;
34
} // namespace Ssl
35

            
36
namespace Extensions {
37
namespace TransportSockets {
38
namespace Tls {
39

            
40
using Ssl::SanMatcher;
41
using Ssl::SanMatcherPtr;
42

            
43
class StringSanMatcher : public SanMatcher {
44
public:
45
  bool match(GENERAL_NAME const* general_name) const override;
46
  bool match(GENERAL_NAME const* general_name,
47
             const StreamInfo::StreamInfo& stream_info) const override;
48
3977
  ~StringSanMatcher() override = default;
49

            
50
  StringSanMatcher(int general_name_type, envoy::type::matcher::v3::StringMatcher matcher,
51
                   Server::Configuration::CommonFactoryContext& context,
52
                   bssl::UniquePtr<ASN1_OBJECT>&& general_name_oid = nullptr)
53
3977
      : general_name_type_(general_name_type), matcher_(matcher, context),
54
3977
        general_name_oid_(std::move(general_name_oid)) {
55
    // For DNS SAN, if the StringMatcher type is exact, we have to follow DNS matching semantics.
56
    // The DnsStringSanMatcher should be used in this case.
57
3977
    ASSERT(general_name_type != GEN_DNS ||
58
3977
           matcher.match_pattern_case() !=
59
3977
               envoy::type::matcher::v3::StringMatcher::MatchPatternCase::kExact);
60
3977
  }
61

            
62
private:
63
  bool typeCompatible(const GENERAL_NAME* general_name) const;
64

            
65
  const int general_name_type_;
66
  const Envoy::Matchers::StringMatcherImpl matcher_;
67
  bssl::UniquePtr<ASN1_OBJECT> general_name_oid_;
68
};
69

            
70
// A DNS string SAN matcher that uses the dnsNameMatch() function.
71
// This should be used for DNS SAN where the StringMatcher type is exact,
72
// and the DNS matching semantics must be followed.
73
class DnsExactStringSanMatcher : public SanMatcher {
74
public:
75
  // To avoid hiding other implementations of match.
76
  using SanMatcher::match;
77

            
78
  bool match(GENERAL_NAME const* general_name) const override;
79
1292
  ~DnsExactStringSanMatcher() override = default;
80

            
81
1292
  DnsExactStringSanMatcher(absl::string_view dns_exact_match) : dns_exact_match_(dns_exact_match) {}
82

            
83
private:
84
  const std::string dns_exact_match_;
85
};
86

            
87
SanMatcherPtr createStringSanMatcher(
88
    const envoy::extensions::transport_sockets::tls::v3::SubjectAltNameMatcher& matcher,
89
    Server::Configuration::CommonFactoryContext& context);
90

            
91
} // namespace Tls
92
} // namespace TransportSockets
93
} // namespace Extensions
94
} // namespace Envoy