File indexing completed on 2025-01-18 09:29:02
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_ASIO_SSL_IMPL_RFC2818_VERIFICATION_IPP
0012 #define BOOST_ASIO_SSL_IMPL_RFC2818_VERIFICATION_IPP
0013
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif
0017
0018 #include <boost/asio/detail/config.hpp>
0019
0020 #if !defined(BOOST_ASIO_NO_DEPRECATED)
0021
0022 #include <cctype>
0023 #include <cstring>
0024 #include <boost/asio/ip/address.hpp>
0025 #include <boost/asio/ssl/rfc2818_verification.hpp>
0026 #include <boost/asio/ssl/detail/openssl_types.hpp>
0027
0028 #include <boost/asio/detail/push_options.hpp>
0029
0030 namespace boost {
0031 namespace asio {
0032 namespace ssl {
0033
0034 bool rfc2818_verification::operator()(
0035 bool preverified, verify_context& ctx) const
0036 {
0037 using namespace std;
0038
0039
0040 if (!preverified)
0041 return false;
0042
0043
0044 int depth = X509_STORE_CTX_get_error_depth(ctx.native_handle());
0045 if (depth > 0)
0046 return true;
0047
0048
0049
0050 boost::system::error_code ec;
0051 ip::address address = ip::make_address(host_, ec);
0052 bool is_address = !ec;
0053
0054 X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
0055
0056
0057
0058 GENERAL_NAMES* gens = static_cast<GENERAL_NAMES*>(
0059 X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0));
0060 for (int i = 0; i < sk_GENERAL_NAME_num(gens); ++i)
0061 {
0062 GENERAL_NAME* gen = sk_GENERAL_NAME_value(gens, i);
0063 if (gen->type == GEN_DNS && !is_address)
0064 {
0065 ASN1_IA5STRING* domain = gen->d.dNSName;
0066 if (domain->type == V_ASN1_IA5STRING && domain->data && domain->length)
0067 {
0068 const char* pattern = reinterpret_cast<const char*>(domain->data);
0069 std::size_t pattern_length = domain->length;
0070 if (match_pattern(pattern, pattern_length, host_.c_str()))
0071 {
0072 GENERAL_NAMES_free(gens);
0073 return true;
0074 }
0075 }
0076 }
0077 else if (gen->type == GEN_IPADD && is_address)
0078 {
0079 ASN1_OCTET_STRING* ip_address = gen->d.iPAddress;
0080 if (ip_address->type == V_ASN1_OCTET_STRING && ip_address->data)
0081 {
0082 if (address.is_v4() && ip_address->length == 4)
0083 {
0084 ip::address_v4::bytes_type bytes = address.to_v4().to_bytes();
0085 if (memcmp(bytes.data(), ip_address->data, 4) == 0)
0086 {
0087 GENERAL_NAMES_free(gens);
0088 return true;
0089 }
0090 }
0091 else if (address.is_v6() && ip_address->length == 16)
0092 {
0093 ip::address_v6::bytes_type bytes = address.to_v6().to_bytes();
0094 if (memcmp(bytes.data(), ip_address->data, 16) == 0)
0095 {
0096 GENERAL_NAMES_free(gens);
0097 return true;
0098 }
0099 }
0100 }
0101 }
0102 }
0103 GENERAL_NAMES_free(gens);
0104
0105
0106
0107 X509_NAME* name = X509_get_subject_name(cert);
0108 int i = -1;
0109 ASN1_STRING* common_name = 0;
0110 while ((i = X509_NAME_get_index_by_NID(name, NID_commonName, i)) >= 0)
0111 {
0112 X509_NAME_ENTRY* name_entry = X509_NAME_get_entry(name, i);
0113 common_name = X509_NAME_ENTRY_get_data(name_entry);
0114 }
0115 if (common_name && common_name->data && common_name->length)
0116 {
0117 const char* pattern = reinterpret_cast<const char*>(common_name->data);
0118 std::size_t pattern_length = common_name->length;
0119 if (match_pattern(pattern, pattern_length, host_.c_str()))
0120 return true;
0121 }
0122
0123 return false;
0124 }
0125
0126 bool rfc2818_verification::match_pattern(const char* pattern,
0127 std::size_t pattern_length, const char* host)
0128 {
0129 using namespace std;
0130
0131 const char* p = pattern;
0132 const char* p_end = p + pattern_length;
0133 const char* h = host;
0134
0135 while (p != p_end && *h)
0136 {
0137 if (*p == '*')
0138 {
0139 ++p;
0140 while (*h && *h != '.')
0141 if (match_pattern(p, p_end - p, h++))
0142 return true;
0143 }
0144 else if (tolower(*p) == tolower(*h))
0145 {
0146 ++p;
0147 ++h;
0148 }
0149 else
0150 {
0151 return false;
0152 }
0153 }
0154
0155 return p == p_end && !*h;
0156 }
0157
0158 }
0159 }
0160 }
0161
0162 #include <boost/asio/detail/pop_options.hpp>
0163
0164 #endif
0165
0166 #endif