spectrum2/3rdparty/cpprestsdk/tests/functional/websockets/client/authentication_tests.cpp
2015-11-19 15:19:14 +01:00

253 lines
7 KiB
C++

/***
* ==++==
*
* Copyright (c) Microsoft Corporation. All rights reserved.
* 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.
*
* ==--==
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* authentication_tests.cpp
*
* Tests cases for covering authentication using websocket_client
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
****/
#include "stdafx.h"
#if defined(__cplusplus_winrt) || !defined(_M_ARM)
using namespace web::websockets;
using namespace web::websockets::client;
using namespace tests::functional::websocket::utilities;
namespace tests { namespace functional { namespace websocket { namespace client {
SUITE(authentication_tests)
{
// Authorization not implemented in non WinRT websocket_client yet - CodePlex 254
#if defined(__cplusplus_winrt)
void auth_helper(test_websocket_server& server, const utility::string_t &username = U(""), const utility::string_t &password = U(""))
{
server.set_http_handler([username, password](test_http_request request)
{
test_http_response resp;
if (request->username().empty()) // No credentials -> challenge the request
{
resp.set_status_code(401); // Unauthorized.
resp.set_realm("My Realm");
}
else if (request->username().compare(utility::conversions::to_utf8string(username))
|| request->password().compare(utility::conversions::to_utf8string(password)))
{
resp.set_status_code(403); // User name/password did not match: Forbidden - auth failure.
}
else
{
resp.set_status_code(200); // User name and passwords match. Successful auth.
}
return resp;
});
}
// connect without credentials, when the server expects credentials
TEST_FIXTURE(uri_address, auth_no_credentials, "Ignore", "245")
{
test_websocket_server server;
websocket_client client;
auth_helper(server);
VERIFY_THROWS(client.connect(m_uri).wait(), websocket_exception);
}
// Connect with credentials
TEST_FIXTURE(uri_address, auth_with_credentials, "Ignore", "245")
{
test_websocket_server server;
websocket_client_config config;
web::credentials cred(U("user"), U("password"));
config.set_credentials(cred);
websocket_client client(config);
auth_helper(server, cred.username(), U("password"));
client.connect(m_uri).wait();
client.close().wait();
}
#endif
// helper function to check if failure is due to timeout.
bool is_timeout(const std::string &msg)
{
if (msg.find("set_fail_handler") != std::string::npos)
{
if (msg.find("handshake timed out") != std::string::npos || msg.find("Timer Expired") != std::string::npos)
{
return true;
}
}
return false;
}
TEST(ssl_test)
{
websocket_client client;
std::string body_str("hello");
try
{
client.connect(U("wss://echo.websocket.org/")).wait();
auto receive_task = client.receive().then([body_str](websocket_incoming_message ret_msg)
{
VERIFY_ARE_EQUAL(ret_msg.length(), body_str.length());
auto ret_str = ret_msg.extract_string().get();
VERIFY_ARE_EQUAL(body_str.compare(ret_str), 0);
VERIFY_ARE_EQUAL(ret_msg.message_type(), websocket_message_type::text_message);
});
websocket_outgoing_message msg;
msg.set_utf8_message(body_str);
client.send(msg).wait();
receive_task.wait();
client.close().wait();
}
catch (const websocket_exception &e)
{
if (is_timeout(e.what()))
{
// Since this test depends on an outside server sometimes it sporadically can fail due to timeouts
// especially on our build machines.
return;
}
throw;
}
}
// These tests are specific to our websocketpp based implementation.
#if !defined(__cplusplus_winrt)
void sni_test_impl(websocket_client &client)
{
try
{
client.connect(U("wss://jabbr.net")).wait();
// Should never be reached.
VERIFY_IS_TRUE(false);
}
catch (const websocket_exception &e)
{
if (is_timeout(e.what()))
{
// Since this test depends on an outside server sometimes it sporadically can fail due to timeouts
// especially on our build machines.
return;
}
// This test just covers establishing the TLS connection and verifying
// the server certificate, expect it to return an unexpected HTTP status code.
if (e.error_code().value() == 20)
{
return;
}
throw;
}
}
// Test specifically for server SignalR team hit interesting cases with.
TEST(sni_with_older_server_test)
{
websocket_client client;
sni_test_impl(client);
}
// WinRT doesn't expose option for disabling.
TEST(disable_sni)
{
websocket_client_config config;
config.disable_sni();
websocket_client client(config);
try
{
client.connect(U("wss://jabbr.net")).wait();
// Should never be reached.
VERIFY_IS_TRUE(false);
}
catch (const websocket_exception &e)
{
// Should fail for a reason different than invalid HTTP status.
if (e.error_code().value() != 20)
{
return;
}
throw;
}
}
// Winrt doesn't allow explicitly setting server host for SNI.
TEST(sni_explicit_hostname)
{
websocket_client_config config;
const auto &name = utf8string("jabbr.net");
config.set_server_name(name);
VERIFY_ARE_EQUAL(name, config.server_name());
websocket_client client(config);
sni_test_impl(client);
}
void handshake_error_test_impl(const ::utility::string_t &host)
{
websocket_client client;
try
{
client.connect(host).wait();
VERIFY_IS_TRUE(false);
}
catch (const websocket_exception &e)
{
if (is_timeout(e.what()))
{
// Since this test depends on an outside server sometimes it sporadically can fail due to timeouts
// especially on our build machines.
return;
}
VERIFY_ARE_EQUAL("TLS handshake failed", e.error_code().message());
}
}
TEST(self_signed_cert)
{
handshake_error_test_impl(U("wss://www.pcwebshop.co.uk/"));
}
TEST(hostname_mismatch)
{
handshake_error_test_impl(U("wss://swordsoftruth.com/"));
}
TEST(cert_expired)
{
handshake_error_test_impl(U("wss://tv.eurosport.com/"));
}
#endif
} // SUITE(authentication_tests)
}}}}
#endif