1/* 2 * Copyright (C) 2014 Samsung Electronics. All rights reserved. 3 * Copyright (C) 2014 University of Szeged. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 24 * THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include "config.h" 28 29#include "UnitTestUtils/EWK2UnitTestBase.h" 30#include "UnitTestUtils/EWK2UnitTestServer.h" 31 32using namespace EWK2UnitTest; 33 34extern EWK2UnitTestEnvironment* environment; 35 36static const char indexHTMLString[] = 37 "<html>" 38 "<head><title>EFLWebKit2 SSL test</title></head>" 39 "<body></body></html>"; 40 41static bool finishTest = false; 42static constexpr double testTimeoutSeconds = 2.0; 43 44WTF::CString httpUri; 45 46#define STRINGIFY2(x) #x 47#define STRINGIFY(x) STRINGIFY2(x) 48 49static const gchar certificate_data[] = STRINGIFY(-----BEGIN RSA PRIVATE KEY----- 50MIICXQIBAAKBgQCmcXbusrr8zQr8snIb0OVQibVfgv7zPjh/5xdcrKOejJzp3epA 51AF4TITeFR9vzWIwkmkcRoY+IbQNhh7kefGUYD47bvVamJMtq5cGYVs0HngT+KTMa 52NGH/G44KkFIOaz/b5d/JNKONrlqwxqXS+m6IY4l/E1Ff25ZjND5TaEvI1wIDAQAB 53AoGBAIcDv4A9h6UOBv2ZGyspNvsv2erSblGOhXJrWO4aNNemJJspIp4sLiPCbDE3 54a1po17XRWBkbPz1hgL6axDXQnoeo++ebfrvRSed+Fys4+6SvuSrPOv6PmWTBT/Wa 55GpO+tv48JUNxC/Dy8ROixBXOViuIBEFq3NfVH4HU3+RG20NhAkEA1L3RAhdfPkLI 5682luSOYE3Eq44lICb/yZi+JEihwSeZTJKdZHwYD8KVCjOtjGrOmyEyvThrcIACQz 57JLEreVh33wJBAMhJm9pzJJNkIyBgiXA66FAwbhdDzSTPx0OBjoVWoj6u7jzGvIFT 58Cn1aiTBYzzsiMCaCx+W3e6pK/DcvHSwKrgkCQHZMcxwBmSHLC2lnmD8LQWqqVnLr 59fZV+VnfVw501DQT0uoP8NvygWBg1Uf9YKepfLXnBpidEQjup5ZKivnUEv+sCQA8N 606VcMHI2vkyxV1T7ITrnoSf4ZrIu9yl56mHnRPzSy9VlAHt8hnMI7UeB+bGUndrMO 61VXQgzHzKUhbbxbePvfECQQDTtkOuhJyKDfHCxLDcwNpi+T6OWTEfCw/cq9ZWDbA7 62yCX81pQxfZkfMIS1YFIOGHovK0rMMTraCe+iDNYtVz/L 63-----END RSA PRIVATE KEY----- 64-----BEGIN CERTIFICATE----- 65MIIB9zCCAWACCQDjWWTeC6BQvTANBgkqhkiG9w0BAQQFADBAMQswCQYDVQQGEwJB 66VTETMBEGA1UECBMKU29tZS1TdGF0ZTEcMBoGA1UEChMTV2ViS2l0IExheW91dCBU 67ZXN0czAeFw0wNzA3MTMxMjUxMzJaFw03MTA1MTMwNjIzMTZaMEAxCzAJBgNVBAYT 68AkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMRwwGgYDVQQKExNXZWJLaXQgTGF5b3V0 69IFRlc3RzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmcXbusrr8zQr8snIb 700OVQibVfgv7zPjh/5xdcrKOejJzp3epAAF4TITeFR9vzWIwkmkcRoY+IbQNhh7ke 71fGUYD47bvVamJMtq5cGYVs0HngT+KTMaNGH/G44KkFIOaz/b5d/JNKONrlqwxqXS 72+m6IY4l/E1Ff25ZjND5TaEvI1wIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAAfbUbgD 7301O8DoZA02c1MUMbMHRPSb/qdok2pyWoCPa/BSaOIaNPePc8auPRbrS2XsVWSMft 74CTXiXmrK2Xx1+fJuZLAp0CUng4De4cDH5c8nvlocYmXo+1x53S9DfD0KPryjBRI7 759LnJq2ysHAUawiqFXlwBag6mXawD8YjzcYat 76-----END CERTIFICATE-----); 77 78class EWK2SSLTest : public EWK2UnitTestBase { 79public: 80 81 static void onLoadProvisionalFailedFail(void* userData, Evas_Object*, void* eventInfo) 82 { 83 finishTest = true; 84 // The test passes if an SSL error occurs. 85 ASSERT_TRUE(ewk_error_code_get(static_cast<Ewk_Error*>(eventInfo)) == SOUP_STATUS_SSL_FAILED); 86 } 87 88 static void onLoadFinishedFail(void* userData, Evas_Object*, void*) 89 { 90 bool* isFinished = static_cast<bool*>(userData); 91 if (isFinished) { 92 finishTest = true; 93 // The test fails if the page is loaded. 94 FAIL(); 95 } 96 } 97 98 static void onLoadProvisionalFailedIgnore(void* userData, Evas_Object*, void* eventInfo) 99 { 100 finishTest = true; 101 if (ewk_error_code_get(static_cast<Ewk_Error*>(eventInfo)) == SOUP_STATUS_SSL_FAILED) 102 // The test fails if an SSL error occurs. 103 FAIL(); 104 } 105 106 static void onLoadFinishedIgnore(void* userData, Evas_Object*, void*) 107 { 108 bool* isFinished = static_cast<bool*>(userData); 109 finishTest = true; 110 // The test passes if the page is loaded. 111 ASSERT_TRUE(isFinished); 112 } 113 114 static void serverCallbackBadCertPageLoadTest(SoupServer*, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, void*) 115 { 116 if (message->method != SOUP_METHOD_GET) { 117 soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED); 118 return; 119 } 120 121 if (!strcmp(path, "/index.html")) { 122 soup_message_set_status(message, SOUP_STATUS_OK); 123 soup_message_body_append(message->response_body, SOUP_MEMORY_COPY, indexHTMLString, strlen(indexHTMLString)); 124 } else 125 soup_message_set_status(message, SOUP_STATUS_NOT_FOUND); 126 127 soup_message_body_complete(message->response_body); 128 } 129 130 static void serverCallbackBadCertRedirectHttps(SoupServer*, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, void*) 131 { 132 if (message->method != SOUP_METHOD_GET) { 133 soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED); 134 return; 135 } 136 137 soup_message_set_redirect(message, SOUP_STATUS_MOVED_PERMANENTLY, httpUri.data()); 138 } 139 140 static void serverCallbackBadCertRedirectHttp(SoupServer*, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, void*) 141 { 142 if (message->method != SOUP_METHOD_GET) { 143 soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED); 144 return; 145 } 146 147 if (!strcmp(path, "/index.html")) { 148 soup_message_set_status(message, SOUP_STATUS_OK); 149 soup_message_body_append(message->response_body, SOUP_MEMORY_COPY, indexHTMLString, strlen(indexHTMLString)); 150 } else 151 soup_message_set_status(message, SOUP_STATUS_NOT_FOUND); 152 } 153}; 154 155static GTlsCertificate* getCertificate() 156{ 157 GError** gerror; 158 GTlsCertificate* certificate = g_tls_certificate_new_from_pem( 159 certificate_data, sizeof(certificate_data), gerror); 160 161 if (!certificate) 162 fprintf(stderr, "Unable to create certificate from PEM\n"); 163 164 return certificate; 165} 166 167TEST_F(EWK2SSLTest, ewk_ssl_set_tls_error_policy_ignore) 168{ 169 Ewk_Context* context = ewk_view_context_get(webView()); 170 171 ewk_context_tls_error_policy_set(context, EWK_TLS_ERROR_POLICY_IGNORE); 172 173 ASSERT_TRUE(ewk_context_tls_error_policy_get(context) == EWK_TLS_ERROR_POLICY_IGNORE); 174} 175 176TEST_F(EWK2SSLTest, ewk_ssl_set_tls_error_policy_fail) 177{ 178 Ewk_Context* context = ewk_view_context_get(webView()); 179 180 ewk_context_tls_error_policy_set(context, EWK_TLS_ERROR_POLICY_FAIL); 181 182 ASSERT_TRUE(ewk_context_tls_error_policy_get(context) == EWK_TLS_ERROR_POLICY_FAIL); 183} 184 185TEST_F(EWK2SSLTest, ewk_ssl_bad_cert_page_load_test_policy_ignore) 186{ 187 finishTest = false; 188 189 Ewk_Context* context = ewk_view_context_get(webView()); 190 ewk_context_tls_error_policy_set(context, EWK_TLS_ERROR_POLICY_IGNORE); 191 192 GTlsCertificate* TLSCertificate = getCertificate(); 193 194 if (!TLSCertificate) 195 FAIL(); 196 197 std::unique_ptr<EWK2UnitTestServer> httpsServer = std::make_unique<EWK2UnitTestServer>(TLSCertificate); 198 httpsServer->run(serverCallbackBadCertPageLoadTest); 199 200 Ewk_Error* error = nullptr; 201 evas_object_smart_callback_add(webView(), "load,provisional,failed", onLoadProvisionalFailedIgnore, &error); 202 203 bool isFinished = false; 204 evas_object_smart_callback_add(webView(), "load,finished", onLoadFinishedIgnore, &isFinished); 205 206 ewk_view_url_set(webView(), httpsServer->getURLForPath("/index.html").data()); 207 208 waitUntilTrue(finishTest, testTimeoutSeconds); 209} 210 211TEST_F(EWK2SSLTest, ewk_ssl_bad_cert_page_load_test_policy_fail) 212{ 213 finishTest = false; 214 215 Ewk_Context* context = ewk_view_context_get(webView()); 216 ewk_context_tls_error_policy_set(context, EWK_TLS_ERROR_POLICY_FAIL); 217 218 GTlsCertificate* TLSCertificate = getCertificate(); 219 220 if (!TLSCertificate) 221 FAIL(); 222 223 std::unique_ptr<EWK2UnitTestServer> httpsServer = std::make_unique<EWK2UnitTestServer>(TLSCertificate); 224 httpsServer->run(serverCallbackBadCertPageLoadTest); 225 226 Ewk_Error* error = nullptr; 227 evas_object_smart_callback_add(webView(), "load,provisional,failed", onLoadProvisionalFailedFail, &error); 228 229 bool isFinished = false; 230 evas_object_smart_callback_add(webView(), "load,finished", onLoadFinishedFail, &isFinished); 231 232 ewk_view_url_set(webView(), httpsServer->getURLForPath("/index.html").data()); 233 234 waitUntilTrue(finishTest, testTimeoutSeconds); 235} 236 237TEST_F(EWK2SSLTest, ewk_ssl_bad_cert_redirect_https_to_http) 238{ 239 finishTest = false; 240 241 Ewk_Context* context = ewk_view_context_get(webView()); 242 ewk_context_tls_error_policy_set(context, EWK_TLS_ERROR_POLICY_FAIL); 243 244 GTlsCertificate* TLSCertificate = getCertificate(); 245 246 if (!TLSCertificate) 247 FAIL(); 248 249 std::unique_ptr<EWK2UnitTestServer> httpsServer = std::make_unique<EWK2UnitTestServer>(TLSCertificate); 250 httpsServer->run(serverCallbackBadCertRedirectHttps); 251 std::unique_ptr<EWK2UnitTestServer> httpServer = std::make_unique<EWK2UnitTestServer>(); 252 httpServer->run(serverCallbackBadCertRedirectHttp); 253 254 Ewk_Error* error = nullptr; 255 evas_object_smart_callback_add(webView(), "load,provisional,failed", onLoadProvisionalFailedFail, &error); 256 257 bool isFinished = false; 258 evas_object_smart_callback_add(webView(), "load,finished", onLoadFinishedFail, &isFinished); 259 260 httpUri = httpServer->getURLForPath("/index.html"); 261 ewk_view_url_set(webView(), httpsServer->getURLForPath("/index.html").data()); 262 263 waitUntilTrue(finishTest, testTimeoutSeconds); 264} 265