Tighten and test name-checking functions.
This change follows up from e759a9cd
with more extensive changes and
tests:
If a name checking function (like |X509_VERIFY_PARAM_set1_host|) fails,
it now poisons the |X509_VERIFY_PARAM| so that all verifications will
fail. This is because we have observed that some callers are not
checking the return value of these functions.
Using a length of zero for a hostname to mean |strlen| is now an error.
It also an error for email addresses and IP addresses now, and doesn't
end up trying to call |strlen| on a (binary) IP address.
Setting an email address with embedded NULs now fails. So does trying to
configure an empty hostname or email with (NULL, 0).
|X509_check_*| functions in BoringSSL don't accept zero lengths (unlike
OpenSSL). It's now tested that such calls always fail.
Change-Id: I4484176f2aae74e502a09081c7e912c85e8d090b
Update-Note: several behaviour changes. See change description.
Reviewed-on: https://boringssl-review.googlesource.com/26764
Reviewed-by: David Benjamin <davidben@google.com>
This commit is contained in:
parent
56f5eb9ffd
commit
1902d818ac
@ -67,4 +67,5 @@ struct X509_VERIFY_PARAM_ID_st {
|
||||
size_t emaillen;
|
||||
unsigned char *ip; /* If not NULL IP address to match */
|
||||
size_t iplen; /* Length of IP address */
|
||||
unsigned char poison; /* Fail all verifications */
|
||||
};
|
||||
|
@ -12,6 +12,7 @@
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -422,6 +423,78 @@ static const char kEd25519CertNull[] =
|
||||
"recgVPpVS7B+d9g4EwtZXIh4lodTBDHBBw==\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
// kSANTypesLeaf is a leaf certificate (signed by |kSANTypesRoot|) which
|
||||
// contains SANS for example.com, test@example.com, 127.0.0.1, and
|
||||
// https://example.com/. (The latter is useless for now since crypto/x509
|
||||
// doesn't deal with URI SANs directly.)
|
||||
static const char kSANTypesLeaf[] =
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIClzCCAgCgAwIBAgIJAOjwnT/iW+qmMA0GCSqGSIb3DQEBCwUAMCsxFzAVBgNV\n"
|
||||
"BAoTDkJvcmluZ1NTTCBUZXN0MRAwDgYDVQQDEwdSb290IENBMB4XDTE1MDEwMTAw\n"
|
||||
"MDAwMFoXDTI1MDEwMTAwMDAwMFowLzEXMBUGA1UEChMOQm9yaW5nU1NMIFRlc3Qx\n"
|
||||
"FDASBgNVBAMTC2V4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n"
|
||||
"gQDbRn2TLhInBki8Bighq37EtqJd/h5SRYh6NkelCA2SQlvCgcC+l3mYQPtPbRT9\n"
|
||||
"KxOLwqUuZ9jUCZ7WIji3Sgt0cyvCNPHRk+WW2XR781ifbGE8wLBB1NkrKyQjd1sc\n"
|
||||
"O711Xc4gVM+hY4cdHiTE8x0aUIuqthRD7ZendWL0FMhS1wIDAQABo4G+MIG7MA4G\n"
|
||||
"A1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYD\n"
|
||||
"VR0TAQH/BAIwADAZBgNVHQ4EEgQQn5EWH0NDPkmm3m22gNefYDAbBgNVHSMEFDAS\n"
|
||||
"gBBAN9cB+0AvuBx+VAQnjFkBMEQGA1UdEQQ9MDuCC2V4YW1wbGUuY29tgRB0ZXN0\n"
|
||||
"QGV4YW1wbGUuY29thwR/AAABhhRodHRwczovL2V4YW1wbGUuY29tLzANBgkqhkiG\n"
|
||||
"9w0BAQsFAAOBgQBtwJvY6+Tk6D6DOtDVaNoJ5y8E25CCuE/Ga4OuIcYJas+yLckf\n"
|
||||
"dZwUV3GUG2oBXl2MrpUFxXd4hKBO1CmlBY+hZEeIx0Yp6QWK9P/vnZeydOTP26mk\n"
|
||||
"jusJ2PqSmtKNU1Zcaba4d29oFejmOAfeguhR8AHpsc/zHEaS5Q9cJsuJcw==\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
// -----BEGIN RSA PRIVATE KEY-----
|
||||
// MIICWwIBAAKBgQDbRn2TLhInBki8Bighq37EtqJd/h5SRYh6NkelCA2SQlvCgcC+
|
||||
// l3mYQPtPbRT9KxOLwqUuZ9jUCZ7WIji3Sgt0cyvCNPHRk+WW2XR781ifbGE8wLBB
|
||||
// 1NkrKyQjd1scO711Xc4gVM+hY4cdHiTE8x0aUIuqthRD7ZendWL0FMhS1wIDAQAB
|
||||
// AoGACwf7z0i1DxOI2zSwFimLghfyCSp8mgT3fbZ3Wj0SebYu6ZUffjceneM/AVrq
|
||||
// gGYHYLOVHcWJqfkl7X3hPo9SDhzLx0mM545/q21ZWCwjhswH7WiCEqV2/zeDO9WU
|
||||
// NIO1VU0VoLm0AQ7ZvwnyB+fpgF9kkkDtbBJW7XWrfNVtlnECQQD97YENpEJ3X1kj
|
||||
// 3rrkrHWDkKAyoWWY1i8Fm7LnganC9Bv6AVwgn5ZlE/479aWHF8vbOFEA3pFPiNZJ
|
||||
// t9FTCfpJAkEA3RCXjGI0Y6GALFLwEs+nL/XZAfJaIpJEZVLCVosYQOSaMS4SchfC
|
||||
// GGYVquT7ZgKk9uvz89Fg87OtBMWS9lrkHwJADGkGLKeBhBoJ3kHtem2fVK3F1pOi
|
||||
// xoR5SdnhNYVVyaxqjZ5xZTrHe+stOrr3uxGDqhQniVZXXb6/Ul0Egv1y2QJAVg/h
|
||||
// kAujba4wIhFf2VLyOZ+yjil1ocPj0LZ5Zgvcs1bMGJ1hHP3W2HzVrqRaowoggui1
|
||||
// HpTC891dXGA2qKYV7QJAFDmT2A7OVvh3y4AEgzVwHrDmCMwMHKjCIntS7fjxrJnF
|
||||
// YvJUG1zoHwUVrxxbR3DbpTODlktLcl/0b97D0IkH3w==
|
||||
// -----END RSA PRIVATE KEY-----
|
||||
|
||||
static const char kSANTypesRoot[] =
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIICTTCCAbagAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwKzEXMBUGA1UE\n"
|
||||
"ChMOQm9yaW5nU1NMIFRlc3QxEDAOBgNVBAMTB1Jvb3QgQ0EwHhcNMTUwMTAxMDAw\n"
|
||||
"MDAwWhcNMjUwMTAxMDAwMDAwWjArMRcwFQYDVQQKEw5Cb3JpbmdTU0wgVGVzdDEQ\n"
|
||||
"MA4GA1UEAxMHUm9vdCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6Q5/\n"
|
||||
"EQzmWuaGg3D2UQcuAngR9bIkkjjuJmICx5TxPqF3asCP1SJotl3iTNrghRE1wpJy\n"
|
||||
"SY2BtIiXa7f8skRb2U0GcPkMxo/ps9+jaoRsQ1m+nbLQdpvD1/qZWcO45fNTA71J\n"
|
||||
"1rPMokP+rcILuQG4VimUAySnDSghKamulFtK+Z8CAwEAAaN6MHgwDgYDVR0PAQH/\n"
|
||||
"BAQDAgIEMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAPBgNVHRMBAf8E\n"
|
||||
"BTADAQH/MBkGA1UdDgQSBBBAN9cB+0AvuBx+VAQnjFkBMBsGA1UdIwQUMBKAEEA3\n"
|
||||
"1wH7QC+4HH5UBCeMWQEwDQYJKoZIhvcNAQELBQADgYEAc4N6hTE62/3gwg+kyc2f\n"
|
||||
"c/Jj1mHrOt+0NRaBnmvbmNpsEjHS96Ef4Wt/ZlPXPkkv1C1VosJnOIMF3Q522wRH\n"
|
||||
"bqaxARldS12VAa3gcWisDWD+SqSyDxjyojz0XDiJkTrFuCTCUiZO+1GLB7SO10Ms\n"
|
||||
"d5YVX0c90VMnUhF/dlrqS9U=\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
// -----BEGIN RSA PRIVATE KEY-----
|
||||
// MIICXAIBAAKBgQDpDn8RDOZa5oaDcPZRBy4CeBH1siSSOO4mYgLHlPE+oXdqwI/V
|
||||
// Imi2XeJM2uCFETXCknJJjYG0iJdrt/yyRFvZTQZw+QzGj+mz36NqhGxDWb6dstB2
|
||||
// m8PX+plZw7jl81MDvUnWs8yiQ/6twgu5AbhWKZQDJKcNKCEpqa6UW0r5nwIDAQAB
|
||||
// AoGALEF5daZqc+aEsp8X1yky3nsoheyPL0kqSBWii33IFemZgKcSaRnAoqjPWWLS
|
||||
// 8dHj0I/4rej2MW8iuezVSpDak9tK5boHORC3w4p/wifkizQkLt1DANxTVbzcKvrt
|
||||
// aZ7LjVaKkhjRJbLddniowFHkkWVbUccjvzcUd7Y2VuLbAhECQQDq4FE88aHio8zg
|
||||
// bxSd0PwjEFwLYQTR19u812SoR8PmR6ofIL+pDwOV+fVs+OGcAAOgkhIukOrksQ4A
|
||||
// 1cKtnyhXAkEA/gRI+u3tZ7UE1twIkBfZ6IvCdRodkPqHAYIxMRLzL+MhyZt4MEGc
|
||||
// Ngb/F6U9/WOBFnoR/PI7IwE3ejutzKcL+QJBAKh+6eilk7QKPETZi1m3/dmNt+p1
|
||||
// 3EZJ65pqjwxmB3Rg/vs7vCMk4TarTdSyKu+F1xRPFfoP/mK3Xctdjj6NyhsCQAYF
|
||||
// 7/0TOzfkUPMPUJyqFB6xgbDpJ55ScnUUsznoqx+NkTWInDb4t02IqO/UmT2y6FKy
|
||||
// Hk8TJ1fTJY+ebqaVp3ECQApx9gQ+n0zIhx97FMUuiRse73xkcW4+pZ8nF+8DmeQL
|
||||
// /JKuuFGmzkG+rUbXFmo/Zg2ozVplw71NnQJ4znPsf7A=
|
||||
// -----END RSA PRIVATE KEY-----
|
||||
|
||||
|
||||
// CertFromPEM parses the given, NUL-terminated pem block and returns an
|
||||
// |X509*|.
|
||||
static bssl::UniquePtr<X509> CertFromPEM(const char *pem) {
|
||||
@ -484,12 +557,10 @@ static bssl::UniquePtr<STACK_OF(X509_CRL)> CRLsToStack(
|
||||
}
|
||||
|
||||
static int Verify(X509 *leaf, const std::vector<X509 *> &roots,
|
||||
const std::vector<X509 *> &intermediates,
|
||||
const std::vector<X509_CRL *> &crls,
|
||||
unsigned long flags,
|
||||
bool use_additional_untrusted,
|
||||
const char *hostname,
|
||||
size_t hostname_len) {
|
||||
const std::vector<X509 *> &intermediates,
|
||||
const std::vector<X509_CRL *> &crls, unsigned long flags,
|
||||
bool use_additional_untrusted,
|
||||
std::function<void(X509_VERIFY_PARAM *)> configure_callback) {
|
||||
bssl::UniquePtr<STACK_OF(X509)> roots_stack(CertsToStack(roots));
|
||||
bssl::UniquePtr<STACK_OF(X509)> intermediates_stack(
|
||||
CertsToStack(intermediates));
|
||||
@ -528,7 +599,9 @@ static int Verify(X509 *leaf, const std::vector<X509 *> &roots,
|
||||
}
|
||||
X509_VERIFY_PARAM_set_time(param, 1474934400 /* Sep 27th, 2016 */);
|
||||
X509_VERIFY_PARAM_set_depth(param, 16);
|
||||
X509_VERIFY_PARAM_set1_host(param, hostname, hostname_len);
|
||||
if (configure_callback) {
|
||||
configure_callback(param);
|
||||
}
|
||||
if (flags) {
|
||||
X509_VERIFY_PARAM_set_flags(param, flags);
|
||||
}
|
||||
@ -547,9 +620,9 @@ static int Verify(X509 *leaf, const std::vector<X509 *> &roots,
|
||||
const std::vector<X509_CRL *> &crls,
|
||||
unsigned long flags = 0) {
|
||||
const int r1 =
|
||||
Verify(leaf, roots, intermediates, crls, flags, false, nullptr, 0);
|
||||
Verify(leaf, roots, intermediates, crls, flags, false, nullptr);
|
||||
const int r2 =
|
||||
Verify(leaf, roots, intermediates, crls, flags, true, nullptr, 0);
|
||||
Verify(leaf, roots, intermediates, crls, flags, true, nullptr);
|
||||
|
||||
if (r1 != r2) {
|
||||
fprintf(stderr,
|
||||
@ -617,19 +690,152 @@ TEST(X509Test, TestVerify) {
|
||||
Verify(forgery.get(),
|
||||
{intermediate_self_signed.get(), root_cross_signed.get()},
|
||||
{leaf_no_key_usage.get(), intermediate.get()}, empty_crls));
|
||||
}
|
||||
|
||||
static const char kHostname[] = "example.com";
|
||||
static const char kWrongHostname[] = "example2.com";
|
||||
ASSERT_EQ(X509_V_OK,
|
||||
Verify(leaf.get(), {root.get()}, {intermediate.get()}, empty_crls,
|
||||
0, false, kHostname, strlen(kHostname)));
|
||||
// The wrong hostname should trigger a hostname error.
|
||||
ASSERT_EQ(X509_V_ERR_HOSTNAME_MISMATCH,
|
||||
Verify(leaf.get(), {root.get()}, {intermediate.get()}, empty_crls,
|
||||
0, false, kWrongHostname, strlen(kWrongHostname)));
|
||||
// Passing zero, for this API, is supported for compatibility with OpenSSL.
|
||||
ASSERT_EQ(X509_V_OK, Verify(leaf.get(), {root.get()}, {intermediate.get()},
|
||||
empty_crls, 0, false, kHostname, 0));
|
||||
static const char kHostname[] = "example.com";
|
||||
static const char kWrongHostname[] = "example2.com";
|
||||
static const char kEmail[] = "test@example.com";
|
||||
static const char kWrongEmail[] = "test2@example.com";
|
||||
static const uint8_t kIP[4] = {127, 0, 0, 1};
|
||||
static const uint8_t kWrongIP[4] = {127, 0, 0, 2};
|
||||
static const char kIPString[] = "127.0.0.1";
|
||||
static const char kWrongIPString[] = "127.0.0.2";
|
||||
|
||||
TEST(X509Test, ZeroLengthsWithX509PARAM) {
|
||||
bssl::UniquePtr<X509> leaf(CertFromPEM(kSANTypesLeaf));
|
||||
bssl::UniquePtr<X509> root(CertFromPEM(kSANTypesRoot));
|
||||
ASSERT_TRUE(leaf);
|
||||
ASSERT_TRUE(root);
|
||||
|
||||
std::vector<X509_CRL *> empty_crls;
|
||||
|
||||
struct Test {
|
||||
const char *correct_value;
|
||||
size_t correct_value_len;
|
||||
const char *incorrect_value;
|
||||
size_t incorrect_value_len;
|
||||
int (*func)(X509_VERIFY_PARAM *, const char *, size_t);
|
||||
int mismatch_error;
|
||||
};
|
||||
const std::vector<Test> kTests = {
|
||||
{kHostname, strlen(kHostname), kWrongHostname, strlen(kWrongHostname),
|
||||
X509_VERIFY_PARAM_set1_host, X509_V_ERR_HOSTNAME_MISMATCH},
|
||||
{kEmail, strlen(kEmail), kWrongEmail, strlen(kWrongEmail),
|
||||
X509_VERIFY_PARAM_set1_email, X509_V_ERR_EMAIL_MISMATCH},
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < kTests.size(); i++) {
|
||||
SCOPED_TRACE(i);
|
||||
const Test &test = kTests[i];
|
||||
|
||||
// The correct value should work.
|
||||
ASSERT_EQ(X509_V_OK,
|
||||
Verify(leaf.get(), {root.get()}, {}, empty_crls, 0, false,
|
||||
[&test](X509_VERIFY_PARAM *param) {
|
||||
ASSERT_TRUE(test.func(param, test.correct_value,
|
||||
test.correct_value_len));
|
||||
}));
|
||||
|
||||
// The wrong value should trigger a verification error.
|
||||
ASSERT_EQ(test.mismatch_error,
|
||||
Verify(leaf.get(), {root.get()}, {}, empty_crls, 0, false,
|
||||
[&test](X509_VERIFY_PARAM *param) {
|
||||
ASSERT_TRUE(test.func(param, test.incorrect_value,
|
||||
test.incorrect_value_len));
|
||||
}));
|
||||
|
||||
// Passing zero as the length, unlike OpenSSL, should trigger an error and
|
||||
// should cause verification to fail.
|
||||
ASSERT_EQ(X509_V_ERR_INVALID_CALL,
|
||||
Verify(leaf.get(), {root.get()}, {}, empty_crls, 0, false,
|
||||
[&test](X509_VERIFY_PARAM *param) {
|
||||
ASSERT_FALSE(test.func(param, test.correct_value, 0));
|
||||
}));
|
||||
|
||||
// Passing an empty value should be an error when setting and should cause
|
||||
// verification to fail.
|
||||
ASSERT_EQ(X509_V_ERR_INVALID_CALL,
|
||||
Verify(leaf.get(), {root.get()}, {}, empty_crls, 0, false,
|
||||
[&test](X509_VERIFY_PARAM *param) {
|
||||
ASSERT_FALSE(test.func(param, nullptr, 0));
|
||||
}));
|
||||
|
||||
// Passing a value with embedded NULs should also be an error and should
|
||||
// also cause verification to fail.
|
||||
ASSERT_EQ(X509_V_ERR_INVALID_CALL,
|
||||
Verify(leaf.get(), {root.get()}, {}, empty_crls, 0, false,
|
||||
[&test](X509_VERIFY_PARAM *param) {
|
||||
ASSERT_FALSE(test.func(param, "a", 2));
|
||||
}));
|
||||
}
|
||||
|
||||
// IP addresses work slightly differently:
|
||||
|
||||
// The correct value should still work.
|
||||
ASSERT_EQ(X509_V_OK, Verify(leaf.get(), {root.get()}, {}, empty_crls, 0,
|
||||
false, [](X509_VERIFY_PARAM *param) {
|
||||
ASSERT_TRUE(X509_VERIFY_PARAM_set1_ip(
|
||||
param, kIP, sizeof(kIP)));
|
||||
}));
|
||||
|
||||
// Incorrect values should still fail.
|
||||
ASSERT_EQ(X509_V_ERR_IP_ADDRESS_MISMATCH,
|
||||
Verify(leaf.get(), {root.get()}, {}, empty_crls, 0, false,
|
||||
[](X509_VERIFY_PARAM *param) {
|
||||
ASSERT_TRUE(X509_VERIFY_PARAM_set1_ip(param, kWrongIP,
|
||||
sizeof(kWrongIP)));
|
||||
}));
|
||||
|
||||
// Zero length values should trigger an error when setting and cause
|
||||
// verification to always fail.
|
||||
ASSERT_EQ(X509_V_ERR_INVALID_CALL,
|
||||
Verify(leaf.get(), {root.get()}, {}, empty_crls, 0, false,
|
||||
[](X509_VERIFY_PARAM *param) {
|
||||
ASSERT_FALSE(X509_VERIFY_PARAM_set1_ip(param, kIP, 0));
|
||||
}));
|
||||
|
||||
// ... and so should NULL values.
|
||||
ASSERT_EQ(X509_V_ERR_INVALID_CALL,
|
||||
Verify(leaf.get(), {root.get()}, {}, empty_crls, 0, false,
|
||||
[](X509_VERIFY_PARAM *param) {
|
||||
ASSERT_FALSE(X509_VERIFY_PARAM_set1_ip(param, nullptr, 0));
|
||||
}));
|
||||
|
||||
// Zero bytes in an IP address are, of course, fine. This is tested above
|
||||
// because |kIP| contains zeros.
|
||||
}
|
||||
|
||||
TEST(X509Test, ZeroLengthsWithCheckFunctions) {
|
||||
bssl::UniquePtr<X509> leaf(CertFromPEM(kSANTypesLeaf));
|
||||
|
||||
EXPECT_EQ(
|
||||
1, X509_check_host(leaf.get(), kHostname, strlen(kHostname), 0, nullptr));
|
||||
EXPECT_NE(1, X509_check_host(leaf.get(), kWrongHostname,
|
||||
strlen(kWrongHostname), 0, nullptr));
|
||||
|
||||
EXPECT_EQ(1, X509_check_email(leaf.get(), kEmail, strlen(kEmail), 0));
|
||||
EXPECT_NE(1,
|
||||
X509_check_email(leaf.get(), kWrongEmail, strlen(kWrongEmail), 0));
|
||||
|
||||
EXPECT_EQ(1, X509_check_ip(leaf.get(), kIP, sizeof(kIP), 0));
|
||||
EXPECT_NE(1, X509_check_ip(leaf.get(), kWrongIP, sizeof(kWrongIP), 0));
|
||||
|
||||
EXPECT_EQ(1, X509_check_ip_asc(leaf.get(), kIPString, 0));
|
||||
EXPECT_NE(1, X509_check_ip_asc(leaf.get(), kWrongIPString, 0));
|
||||
|
||||
// OpenSSL supports passing zero as the length for host and email. We do not
|
||||
// and it should always fail.
|
||||
EXPECT_NE(1, X509_check_host(leaf.get(), kHostname, 0, 0, nullptr));
|
||||
EXPECT_NE(1, X509_check_host(leaf.get(), kWrongHostname, 0, 0, nullptr));
|
||||
|
||||
EXPECT_NE(1, X509_check_email(leaf.get(), kEmail, 0, 0));
|
||||
EXPECT_NE(1, X509_check_email(leaf.get(), kWrongEmail, 0, 0));
|
||||
|
||||
EXPECT_NE(1, X509_check_ip(leaf.get(), kIP, 0, 0));
|
||||
EXPECT_NE(1, X509_check_ip(leaf.get(), kWrongIP, 0, 0));
|
||||
|
||||
// Unlike all the other functions, |X509_check_ip_asc| doesn't take a length,
|
||||
// so it cannot be zero.
|
||||
}
|
||||
|
||||
TEST(X509Test, TestCRL) {
|
||||
|
@ -784,6 +784,10 @@ static int check_id(X509_STORE_CTX *ctx)
|
||||
X509_VERIFY_PARAM *vpm = ctx->param;
|
||||
X509_VERIFY_PARAM_ID *id = vpm->id;
|
||||
X509 *x = ctx->cert;
|
||||
if (id->poison) {
|
||||
if (!check_id_error(ctx, X509_V_ERR_INVALID_CALL))
|
||||
return 0;
|
||||
}
|
||||
if (id->hosts && check_hosts(x, id) <= 0) {
|
||||
if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH))
|
||||
return 0;
|
||||
|
@ -89,12 +89,9 @@ static int int_x509_param_set_hosts(X509_VERIFY_PARAM_ID *id, int mode,
|
||||
{
|
||||
char *copy;
|
||||
|
||||
// This is an OpenSSL quirk that BoringSSL typically doesn't support.
|
||||
// However, we didn't make this a fatal error at the time, which was a
|
||||
// mistake. Because of that, given the risk that someone could assume the
|
||||
// OpenSSL semantics from BoringSSL, it's supported in this case.
|
||||
if (name != NULL && namelen == 0) {
|
||||
namelen = strlen(name);
|
||||
if (name == NULL || namelen == 0) {
|
||||
// Unlike OpenSSL, we reject trying to set or add an empty name.
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -108,8 +105,6 @@ static int int_x509_param_set_hosts(X509_VERIFY_PARAM_ID *id, int mode,
|
||||
string_stack_free(id->hosts);
|
||||
id->hosts = NULL;
|
||||
}
|
||||
if (name == NULL || namelen == 0)
|
||||
return 1;
|
||||
|
||||
copy = BUF_strndup(name, namelen);
|
||||
if (copy == NULL)
|
||||
@ -170,7 +165,7 @@ static void x509_verify_param_zero(X509_VERIFY_PARAM *param)
|
||||
paramid->ip = NULL;
|
||||
paramid->iplen = 0;
|
||||
}
|
||||
|
||||
paramid->poison = 0;
|
||||
}
|
||||
|
||||
X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void)
|
||||
@ -324,6 +319,8 @@ int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
|
||||
return 0;
|
||||
}
|
||||
|
||||
dest->id->poison = src->id->poison;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -342,18 +339,17 @@ static int int_x509_param_set1(char **pdest, size_t *pdestlen,
|
||||
const char *src, size_t srclen)
|
||||
{
|
||||
void *tmp;
|
||||
if (src) {
|
||||
if (srclen == 0) {
|
||||
tmp = BUF_strdup(src);
|
||||
srclen = strlen(src);
|
||||
} else
|
||||
tmp = BUF_memdup(src, srclen);
|
||||
if (!tmp)
|
||||
return 0;
|
||||
} else {
|
||||
tmp = NULL;
|
||||
srclen = 0;
|
||||
if (src == NULL || srclen == 0) {
|
||||
// Unlike OpenSSL, we do not allow an empty string to disable previously
|
||||
// configured checks.
|
||||
return 0;
|
||||
}
|
||||
|
||||
tmp = BUF_memdup(src, srclen);
|
||||
if (!tmp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*pdest)
|
||||
OPENSSL_free(*pdest);
|
||||
*pdest = tmp;
|
||||
@ -462,13 +458,21 @@ int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
|
||||
int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
|
||||
const char *name, size_t namelen)
|
||||
{
|
||||
return int_x509_param_set_hosts(param->id, SET_HOST, name, namelen);
|
||||
if (!int_x509_param_set_hosts(param->id, SET_HOST, name, namelen)) {
|
||||
param->id->poison = 1;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
|
||||
const char *name, size_t namelen)
|
||||
{
|
||||
return int_x509_param_set_hosts(param->id, ADD_HOST, name, namelen);
|
||||
if (!int_x509_param_set_hosts(param->id, ADD_HOST, name, namelen)) {
|
||||
param->id->poison = 1;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
|
||||
@ -485,17 +489,27 @@ char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param)
|
||||
int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
|
||||
const char *email, size_t emaillen)
|
||||
{
|
||||
return int_x509_param_set1(¶m->id->email, ¶m->id->emaillen,
|
||||
email, emaillen);
|
||||
if (OPENSSL_memchr(email, '\0', emaillen) != NULL ||
|
||||
!int_x509_param_set1(¶m->id->email, ¶m->id->emaillen,
|
||||
email, emaillen)) {
|
||||
param->id->poison = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
|
||||
const unsigned char *ip, size_t iplen)
|
||||
{
|
||||
if (iplen != 0 && iplen != 4 && iplen != 16)
|
||||
if ((iplen != 4 && iplen != 16) ||
|
||||
!int_x509_param_set1((char **)¶m->id->ip, ¶m->id->iplen,
|
||||
(char *)ip, iplen)) {
|
||||
param->id->poison = 1;
|
||||
return 0;
|
||||
return int_x509_param_set1((char **)¶m->id->ip, ¶m->id->iplen,
|
||||
(char *)ip, iplen);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc)
|
||||
@ -520,7 +534,7 @@ const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param)
|
||||
}
|
||||
|
||||
static const X509_VERIFY_PARAM_ID _empty_id =
|
||||
{ NULL, 0U, NULL, NULL, 0, NULL, 0 };
|
||||
{ NULL, 0U, NULL, NULL, 0, NULL, 0, 0 };
|
||||
|
||||
#define vpm_empty_id ((X509_VERIFY_PARAM_ID *)&_empty_id)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user