/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/io/async/ssl/OpenSSLUtils.h>
#include <folly/String.h>
#include <folly/portability/GTest.h>
#include <folly/portability/OpenSSL.h>
#include <folly/ssl/OpenSSLPtrTypes.h>
using namespace folly::ssl;
namespace folly {
const std::string kSampleCommonName = "Folly Library";
// a certificate with a CN that uses 64 characters, the max length
const std::string kSampleCommonNameMaxLength =
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
// create and return an X509 object with only the subject's CN set, so tests can
// extract and compare it
X509UniquePtr createMinimalX509(const std::string& commonName) {
X509* x509;
x509 = X509_new();
X509_NAME* name;
name = X509_get_subject_name(x509);
X509_NAME_add_entry_by_txt(
name,
SN_commonName,
MBSTRING_ASC,
reinterpret_cast<const unsigned char*>(commonName.data()),
-1,
-1,
0);
return X509UniquePtr(x509);
}
// Tests that the common name is extracted from the x509 certificate with the
// correct length
TEST(OpenSSLUtilsTest, getCommonName) {
X509UniquePtr x509 = createMinimalX509(kSampleCommonName);
EXPECT_EQ(OpenSSLUtils::getCommonName(x509.get()), kSampleCommonName);
}
// Tests that the common name is extracted from the x509 certificate correctly
// when its length is the maximum, defined as ub_common_name in asn1.h (RFC2459)
TEST(OpenSSLUtilsTest, getCommonNameMaxLength) {
X509UniquePtr x509 = createMinimalX509(kSampleCommonNameMaxLength);
// read common name from certificate
EXPECT_EQ(
OpenSSLUtils::getCommonName(x509.get()), kSampleCommonNameMaxLength);
}
// Tests that getCommonName returns an empty string for a null X509 argument
TEST(OpenSSLUtilsTest, getCommonNameNullX509) {
EXPECT_EQ(OpenSSLUtils::getCommonName(nullptr), "");
}
// Tests that getCommonName returns an empty string because the given
// certificate has no CN
TEST(OpenSSLUtilsTest, getCommonNameEmpty) {
X509UniquePtr x509 = createMinimalX509("");
EXPECT_EQ(OpenSSLUtils::getCommonName(x509.get()), "");
}
// Tests that encodeALPNString returns a serialized version of the ALPN String
TEST(OpenSSLUtilsTest, encodeALPNString) {
EXPECT_EQ(OpenSSLUtils::encodeALPNString({"rs"}), "\x2rs");
EXPECT_EQ(OpenSSLUtils::encodeALPNString({"rs", "h2"}), "\x2rs\x2h2");
EXPECT_EQ(
OpenSSLUtils::encodeALPNString({"rs", "h2", "spdy/3.1"}),
"\x2rs\x2h2\x8spdy/3.1");
EXPECT_EQ(
OpenSSLUtils::encodeALPNString({"rs", "h2", "spdy/3.1", "http/1.1"}),
"\x2rs\x2h2\x8spdy/3.1\x8http/1.1");
std::string maxSizeProtocolString(std::numeric_limits<uint8_t>::max(), 'p');
EXPECT_EQ(
OpenSSLUtils::encodeALPNString({maxSizeProtocolString}),
"\xFF" + maxSizeProtocolString);
EXPECT_EQ(
OpenSSLUtils::encodeALPNString({maxSizeProtocolString, "rs"}),
"\xFF" + maxSizeProtocolString + "\x2rs");
EXPECT_EQ(
OpenSSLUtils::encodeALPNString({maxSizeProtocolString, "rs", "h2"}),
"\xFF" + maxSizeProtocolString + "\x2rs\x2h2");
EXPECT_EQ(
OpenSSLUtils::encodeALPNString(
{maxSizeProtocolString, "rs", "h2", "spdy/3.1"}),
"\xFF" + maxSizeProtocolString + "\x2rs\x2h2\x8spdy/3.1");
EXPECT_EQ(
OpenSSLUtils::encodeALPNString(
{maxSizeProtocolString, "rs", "h2", "spdy/3.1", "http/1.1"}),
"\xFF" + maxSizeProtocolString + "\x2rs\x2h2\x8spdy/3.1\x8http/1.1");
std::string exceedsMaxSizeProtocolString(
std::numeric_limits<uint8_t>::max() + 1, 'p');
try {
OpenSSLUtils::encodeALPNString({exceedsMaxSizeProtocolString});
} catch (std::range_error const& err) {
EXPECT_EQ(
err.what(), std::string("ALPN protocol string exceeds maximum length"));
}
}
} // namespace folly