EXPECT_TRUE(!server.handshakeError_);
}
+/**
+ * Verify that server is able to get client cert by getPeerCert() API.
+ */
+TEST(AsyncSSLSocketTest, GetClientCertificate) {
+ EventBase eventBase;
+ auto clientCtx = std::make_shared<SSLContext>();
+ auto serverCtx = std::make_shared<SSLContext>();
+ serverCtx->setVerificationOption(SSLContext::SSLVerifyPeerEnum::VERIFY);
+ serverCtx->ciphers("ECDHE-RSA-AES128-SHA:AES128-SHA:AES256-SHA");
+ serverCtx->loadPrivateKey(kTestKey);
+ serverCtx->loadCertificate(kTestCert);
+ serverCtx->loadTrustedCertificates(kClientTestCA);
+ serverCtx->loadClientCAList(kClientTestCA);
+
+ clientCtx->setVerificationOption(SSLContext::SSLVerifyPeerEnum::VERIFY);
+ clientCtx->ciphers("AES256-SHA:AES128-SHA");
+ clientCtx->loadPrivateKey(kClientTestKey);
+ clientCtx->loadCertificate(kClientTestCert);
+ clientCtx->loadTrustedCertificates(kTestCA);
+
+ std::array<int, 2> fds;
+ getfds(fds.data());
+
+ AsyncSSLSocket::UniquePtr clientSock(
+ new AsyncSSLSocket(clientCtx, &eventBase, fds[0], false));
+ AsyncSSLSocket::UniquePtr serverSock(
+ new AsyncSSLSocket(serverCtx, &eventBase, fds[1], true));
+
+ SSLHandshakeClient client(std::move(clientSock), true, true);
+ SSLHandshakeServerParseClientHello server(std::move(serverSock), true, true);
+
+ eventBase.loop();
+
+ // Handshake should succeed.
+ EXPECT_TRUE(client.handshakeSuccess_);
+ EXPECT_TRUE(server.handshakeSuccess_);
+
+ // Reclaim the sockets from SSLHandshakeBase.
+ auto cliSocket = std::move(client).moveSocket();
+ auto srvSocket = std::move(server).moveSocket();
+
+ // Client cert retrieved from server side.
+ folly::ssl::X509UniquePtr serverPeerCert = srvSocket->getPeerCert();
+ CHECK(serverPeerCert);
+
+ // Client cert retrieved from client side.
+ const X509* clientSelfCert = cliSocket->getSelfCert();
+ CHECK(clientSelfCert);
+
+ // The two certs should be the same.
+ EXPECT_EQ(0, X509_cmp(clientSelfCert, serverPeerCert.get()));
+}
+
TEST(AsyncSSLSocketTest, SSLParseClientHelloOnePacket) {
EventBase eventBase;
auto ctx = std::make_shared<SSLContext>();
const char* kTestKey = "folly/io/async/test/certs/tests-key.pem";
const char* kTestCA = "folly/io/async/test/certs/ca-cert.pem";
+const char* kClientTestCert = "folly/io/async/test/certs/client_cert.pem";
+const char* kClientTestKey = "folly/io/async/test/certs/client_key.pem";
+const char* kClientTestCA = "folly/io/async/test/certs/client_ca_cert.pem";
+
TestSSLServer::~TestSSLServer() {
if (thread_.joinable()) {
evb_.runInEventBaseThread([&]() { socket_->stopAccepting(); });
extern const char* kTestKey;
extern const char* kTestCA;
+extern const char* kClientTestCert;
+extern const char* kClientTestKey;
+extern const char* kClientTestCA;
+
enum StateEnum { STATE_WAITING, STATE_SUCCEEDED, STATE_FAILED };
class HandshakeCallback;
--- /dev/null
+-----BEGIN CERTIFICATE-----
+MIIDmjCCAoKgAwIBAgIBATANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExDTALBgNVBAoMBEFzb3gxJTAjBgNVBAMMHEFzb3ggQ2VydGlm
+aWNhdGlvbiBBdXRob3JpdHkwHhcNMTcwODAzMjMyMTA1WhcNNDQxMjE5MjMyMTA1
+WjBQMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExDTALBgNVBAoMBEFzb3gxJTAj
+BgNVBAMMHEFzb3ggQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDfv3KonszKqaZLZ5Vwnl/v6BhwQNqyx3nEDXTY
+pCn17En3DJzsa0zlqkmw8XJeQrx6+iZjLyGqEjIcqHAFcabux7PJ5z+T41kabNzU
++WEYBhNbEB1xRm7Rqz9OzroajWIK8Wugzmqu2Sz+QYaFPjsW85+zVB6E3YPbBpz/
+uPmAecwpInzFH7C9o5TZGoYS+0K1fH935EhM617HSVvHQflQL8IcGZuLExVxiOZ+
+SkJIXO+JaM2cXBFnqf4halHQ5O+866Xk09WbhUpOqi/tGE74VQBKC2u2F1DUga0W
+37Gwcp4o9WWdeCL10323QOSnAJoaMccBpILZSL3g7YJD1ZlFAgMBAAGjfzB9MB0G
+A1UdDgQWBBR8WSTHikglMmAbowGKfg4kFNNFbzAfBgNVHSMEGDAWgBR8WSTHikgl
+MmAbowGKfg4kFNNFbzAMBgNVHRMEBTADAQH/MC0GCCsGAQUFBwEBBCEwHzAdBggr
+BgEFBQcwAoYRaHR0cHM6Ly90ZXN0X2NlcnQwDQYJKoZIhvcNAQELBQADggEBAACe
+5R64MK058S3g6mQuviburcnKeBojMt1liqKGcCDwFKFHiYCN3hKoZmEQ4XvQu0U5
+U2a3/sFG5mZD8UjAQzlQQkdjy4CwM3iGA5EeTT+VYnc9/UQU1yeyiGIRkNDJKp2y
+p4vw5sm40uBwc+QfUAl7AExO4Q8FOdVqoS/zixYtFNQ2CjlLEzY5FRgyzfHQQDtn
+rmtdVKOeWd0itvgSCeMs5KfetZlFAHavclcAN/721ukGiaWXyxQPfRLX2dS4RB8j
+TwC15NBTsRTbYhJLYuBoUwTdhCojBUr8NN1kgwjHsT6wjtLJpRl6qeKHMw+Y9IlT
+VgbFH84VIfIB1tnMNNA=
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN CERTIFICATE-----
+MIIDZjCCAk6gAwIBAgIBCjANBgkqhkiG9w0BAQsFADBQMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExDTALBgNVBAoMBEFzb3gxJTAjBgNVBAMMHEFzb3ggQ2VydGlm
+aWNhdGlvbiBBdXRob3JpdHkwHhcNMTcwODAzMjMyMTA2WhcNNDQxMjE5MjMyMTA2
+WjAwMQswCQYDVQQGEwJVUzENMAsGA1UECgwEQXNveDESMBAGA1UEAwwJdGVzdHVz
+ZXIxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxNjbq/fOD9BZN1N+
+UPwTLK0jSE3zW3o4YIIZKnOc8ln3kY6xI0Xtm96uGD/y+nWFHGiEX5eqcTZEEaX7
+4kHBU3mcWaZvC/JfBwyG1gf3/5sl5yxgJB9LsSZRcBKcET+JJ8Ps7WADBU0IVUsj
+yejt25wnpsmglXbt7rObay8H0AYstRmNhpq7N92R6CKeVpHzuvUujSFnMGmxh5ux
+l9anytFfr84E4G/AEUFkEKimFsqtG5Je3ZAfREhoNdCSERENYNtNXgLVCeWLGAT8
+Mp0gNDHgBGheiWDIFRK5PKbJENMfOZt0mjQAM3ypmsLCNhSV81CDc9Q/GEOLMMxX
+VP773wIDAQABo2swaTAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUE
+FjAUBggrBgEFBQgCAgYIKwYBBQUHAwIwLQYIKwYBBQUHAQEEITAfMB0GCCsGAQUF
+BzAChhFodHRwczovL3Rlc3RfY2VydDANBgkqhkiG9w0BAQsFAAOCAQEAO/kPyxvj
+ZXxb4uCjqLFiPWKcGHhX1U+rE6tHf/iBh6WJ7D751Z56AT8YjtSWXxDgD3zOvhml
+TGjkWIofG5yhYBeYEvrlHzXIqsPmUhOYgO42V4AXFB8u5gPw7tB5aozhxA4jB6Ik
+JXkmDiBsyP4DvYknl7gGl4eubOPM/MDy0YasZH3C3shmjAJEW2CEbIrLXyT+N6yK
++zVtxEVlTZ4TPmXzOLqMIrgjLBWq5I9ATf5BCcqjs2bnHvVkErmY6WcpPTKDyCg6
+Nmtla39ffF6V1S9BItLB7nZsGwMuExwPvotFseTppiAQyZGH0rPECxyPDpNNij/G
+5ro+AZN3usfsqw==
+-----END CERTIFICATE-----
--- /dev/null
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAxNjbq/fOD9BZN1N+UPwTLK0jSE3zW3o4YIIZKnOc8ln3kY6x
+I0Xtm96uGD/y+nWFHGiEX5eqcTZEEaX74kHBU3mcWaZvC/JfBwyG1gf3/5sl5yxg
+JB9LsSZRcBKcET+JJ8Ps7WADBU0IVUsjyejt25wnpsmglXbt7rObay8H0AYstRmN
+hpq7N92R6CKeVpHzuvUujSFnMGmxh5uxl9anytFfr84E4G/AEUFkEKimFsqtG5Je
+3ZAfREhoNdCSERENYNtNXgLVCeWLGAT8Mp0gNDHgBGheiWDIFRK5PKbJENMfOZt0
+mjQAM3ypmsLCNhSV81CDc9Q/GEOLMMxXVP773wIDAQABAoIBAGDrlV1aqa7HmuXO
+ykb9lkNNDC4xkzzbNJ7v74wjWIdLHMYiR71iVNeGEJoIAo6nBl8yZtraRiVv3pwB
+6b9BOPrsybqqY8qyD2/dDxaa3dSQg10LUFr4vb//aeGQiB9F9TYLFcDaoSIfB5dX
+Y8uqUFLs0+kfJV3yLLx22nMvuN0HD4ra8pzWOzO6r/cyGV5Q0hY+GjfbXUvO1Kk7
+ez/Hc2MSR/rQTReEldExB839lcYjlxpQ5FyfXBVsBev6DLl3YRZe0Zq3cE94BBTs
+EksD4O1maWpW9RMsLyxGiPKt08zIXdupuOQXWG+d3K/ZhVheGtQz2bqBobDANB2I
+l6o7xcECgYEA8pgXaktdxOxErDeiy0TRYg2/GVkqmzH7JK3cy9vWL67ihbCKSDzF
+H3B27PbBx/DDCRdV1zXHwY2fuqVdrNbJXCzeXg8xw6VrIwtWNKJksi5+echCOgf8
+dfpr5d/ujcVPDd/oqBFBXqTwA93H6rablLRxlIM6j74u+fvfKKYsnLkCgYEAz7mY
+1PHcpf39+SCp1gyP6tNSk5W5gkgmQYNVD1gEgYvAThJ+SYpsq/FvyutF8gQwugZk
++ESlrMn79CxDmxmwLDkI1dhH87rK63QadcKAf6gGzmmW5iF7JpfEI2sCgHRzo+YY
+DvjXPYHORXmG8FzSwXEFeaGmkUfZkQCnlGaBAVcCgYBkeETKSuhM1CUkxe3wDVJC
+L7tDPkB9AdgnOrJE44jzOpSqFZFPlYt2F9fJD/D1Y2sC6t0sQiO2r3bFkBMZr+K5
+AAQgJF7RzkJuwxUyu0bE3KiYuy1iZ0hRfCMPkwxzPpIdBuyOHodaMSkOEN3pATOy
+BIE9ppOsUHGYKo4jgZ7cUQKBgCnUONdgoMr4O4VIM4r72psx1KYNd16pwrJcjOtb
+EQU5LA9MoAuVCU8Sfi2BdQNIHrvG/9wSjr4dqlO/+hkochZlocbWF58X1TbWmWFv
+Okr6fexgzNcolNDvrLppGQbe7E5rzhptt4IWOoA4+Zg7SOFVLgIRMCZ/LmuJkzVJ
+8t5fAoGAT5aji/j7w+isIU4R13w2x5UXyVSapmAPZt0N3KQeD5/WHMEvUgu7Lk3a
+FrBHbs1bvF6Q6uJhe+OvN0/vqhesa334XzBPoyMVa3UfTkVrW6TvEoJa/Gc8oIno
+Pjrn8wSA0SCFf/wuCcXIDhk9Mq2q5dOD5FeTPFciR7zYWFlOQnI=
+-----END RSA PRIVATE KEY-----