2
0
mirror of https://github.com/boostorg/mysql.git synced 2026-02-15 01:02:17 +00:00

Refactored auth calculation

This commit is contained in:
ruben
2020-04-07 11:37:40 +01:00
parent cff5c75daa
commit 9bf70a31e3
15 changed files with 460 additions and 223 deletions

View File

@@ -1,11 +1,9 @@
sha256_password auth plugin
Unit tests for auth calculator & refactor
Set error_info when there is an auth plugin involved
Unknown auth plugin
Auth plugin requires SSL
Test for an unknown auth plugin
Update readme
Unit test for auth_more_data
Multiresultset
Text protocol
Binary protocol (stored procedures)

View File

@@ -1,119 +0,0 @@
#ifndef INCLUDE_BOOST_MYSQL_DETAIL_AUTH_AUTH_HPP_
#define INCLUDE_BOOST_MYSQL_DETAIL_AUTH_AUTH_HPP_
#include "boost/mysql/detail/auth/mysql_native_password.hpp"
#include "boost/mysql/detail/auth/caching_sha2_password.hpp"
#include "boost/mysql/error.hpp"
namespace boost {
namespace mysql {
namespace detail {
class auth_response_calculator
{
//std::array<std::uint8_t, mysql_native_password::response_length> auth_response_buffer_ {};
//std::string_view res_;
//bool use_buffer_ {};
std::string response_;
std::string plugin_name_;
error_code calculate_impl(
std::string_view plugin_name,
std::string_view password,
std::string_view challenge,
bool use_ssl
)
{
plugin_name_ = plugin_name;
// Blank password: we should just return an empty auth string
if (password.empty())
{
response_ = "";
return error_code();
}
if (plugin_name == mysql_native_password::plugin_name)
{
// Check challenge size
if (challenge.size() != mysql_native_password::challenge_length)
{
return make_error_code(errc::protocol_value_error);
}
// Do the calculation
std::array<std::uint8_t, mysql_native_password::response_length> buff;
mysql_native_password::compute_auth_string(
password,
challenge.data(),
buff.data()
);
response_.assign(reinterpret_cast<const char*>(buff.data()), buff.size());
return error_code();
}
else if (plugin_name == "caching_sha2_password")
{
if (challenge.size() == 1 && challenge[0] == 4)
{
if (!use_ssl)
{
return make_error_code(errc::auth_plugin_requires_ssl);
}
response_ = password;
response_.push_back(0);
return error_code();
}
else
{
// Check challenge size
if (challenge.size() != caching_sha2_password::challenge_length)
{
return make_error_code(errc::protocol_value_error);
}
// Do the calculation
std::array<std::uint8_t, caching_sha2_password::response_length> buff;
caching_sha2_password::compute_auth_string(
password,
challenge.data(),
buff.data()
);
response_.assign(reinterpret_cast<const char*>(buff.data()), buff.size());
return error_code();
}
}
else
{
return make_error_code(errc::unknown_auth_plugin);
}
}
public:
error_code calculate(
std::string_view plugin_name,
std::string_view password,
std::string_view challenge,
bool use_ssl
)
{
auto res = calculate_impl(plugin_name, password, challenge, use_ssl);
if (res)
{
response_.clear();
}
return res;
}
std::string_view response() const noexcept
{
return response_;
}
const auto& get_plugin_name() const { return plugin_name_; }
};
}
}
}
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_AUTH_AUTH_HPP_ */

View File

@@ -0,0 +1,53 @@
#ifndef INCLUDE_BOOST_MYSQL_DETAIL_AUTH_AUTH_CALCULATOR_HPP_
#define INCLUDE_BOOST_MYSQL_DETAIL_AUTH_AUTH_CALCULATOR_HPP_
#include "boost/mysql/error.hpp"
#include <array>
#include <string>
#include <string_view>
namespace boost {
namespace mysql {
namespace detail {
struct authentication_plugin
{
using calculator_signature = error_code (*)(
std::string_view password,
std::string_view challenge,
bool use_ssl,
std::string& output
);
std::string_view name;
calculator_signature calculator;
};
class auth_calculator
{
const authentication_plugin* plugin_ {nullptr};
std::string response_;
inline static const authentication_plugin* find_plugin(std::string_view name);
public:
inline error_code calculate(
std::string_view plugin_name,
std::string_view password,
std::string_view challenge,
bool use_ssl
);
std::string_view response() const noexcept { return response_; }
std::string_view plugin_name() const noexcept
{
assert(plugin_);
return plugin_->name;
}
};
} // detail
} // mysql
} // boost
#include "boost/mysql/detail/auth/impl/auth_calculator.ipp"
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_AUTH_AUTH_CALCULATOR_HPP_ */

View File

@@ -3,25 +3,34 @@
#include <cstddef>
#include <string_view>
#include "boost/mysql/error.hpp"
namespace boost {
namespace mysql {
namespace detail {
namespace caching_sha2_password {
constexpr const char* plugin_name = "caching_sha2_password";
constexpr std::size_t challenge_length = 20;
constexpr std::size_t response_length = 32;
// Authorization for this plugin may be cleartext password or challenge/response.
// The server has a cache that uses when employing challenge/response. When
// the server sends a challenge of challenge_length bytes, we should send
// the password hashed with the challenge. The server may send a challenge
// equals to perform_full_auth, meaning it could not use the cache to
// complete the auth. In this case, we should just send the cleartext password.
// Doing the latter requires a SSL connection. It is possible to perform full
// auth without an SSL connection, but that requires the server public key,
// and we do not implement that.
inline error_code compute_response(
std::string_view password,
std::string_view challenge,
bool use_ssl,
std::string& output
);
// challenge must point to challenge_length bytes of data
// output must point to response_length bytes of data
inline void compute_auth_string(std::string_view password, const void* challenge, void* output);
} // caching_sha2_password
} // detail
} // mysql
} // boost
}
}
}
}
#include "boost/mysql/detail/auth/impl/caching_sha2_password.hpp"
#include "boost/mysql/detail/auth/impl/caching_sha2_password.ipp"
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_AUTH_CACHING_SHA2_PASSWORD_HPP_ */

View File

@@ -0,0 +1,74 @@
#ifndef INCLUDE_BOOST_MYSQL_DETAIL_AUTH_IMPL_AUTH_CALCULATOR_IPP_
#define INCLUDE_BOOST_MYSQL_DETAIL_AUTH_IMPL_AUTH_CALCULATOR_IPP_
#include "boost/mysql/detail/auth/mysql_native_password.hpp"
#include "boost/mysql/detail/auth/caching_sha2_password.hpp"
namespace boost {
namespace mysql {
namespace detail {
constexpr authentication_plugin mysql_native_password_plugin {
"mysql_native_password",
&mysql_native_password::compute_response
};
constexpr authentication_plugin caching_sha2_password_plugin {
"caching_sha2_password",
&caching_sha2_password::compute_response
};
constexpr std::array<const authentication_plugin*, 2> all_authentication_plugins {
&mysql_native_password_plugin,
&caching_sha2_password_plugin
};
} // detail
} // mysql
} // boost
inline const boost::mysql::detail::authentication_plugin*
boost::mysql::detail::auth_calculator::find_plugin(
std::string_view name
)
{
auto it = std::find_if(
all_authentication_plugins.begin(),
all_authentication_plugins.end(),
[name](const authentication_plugin* plugin) { return plugin->name == name; }
);
return it == std::end(all_authentication_plugins) ? nullptr : *it;
}
inline boost::mysql::error_code
boost::mysql::detail::auth_calculator::calculate(
std::string_view plugin_name,
std::string_view password,
std::string_view challenge,
bool use_ssl
)
{
plugin_ = find_plugin(plugin_name);
if (plugin_)
{
// Blank password: we should just return an empty auth string
if (password.empty())
{
response_ = "";
return error_code();
}
else
{
return plugin_->calculator(password, challenge, use_ssl, response_);
}
}
else
{
return make_error_code(errc::unknown_auth_plugin);
}
}
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_AUTH_IMPL_AUTH_CALCULATOR_IPP_ */

View File

@@ -1,10 +1,21 @@
#ifndef INCLUDE_BOOST_MYSQL_DETAIL_AUTH_IMPL_CACHING_SHA2_PASSWORD_HPP_
#define INCLUDE_BOOST_MYSQL_DETAIL_AUTH_IMPL_CACHING_SHA2_PASSWORD_HPP_
#ifndef INCLUDE_BOOST_MYSQL_DETAIL_AUTH_IMPL_CACHING_SHA2_PASSWORD_IPP_
#define INCLUDE_BOOST_MYSQL_DETAIL_AUTH_IMPL_CACHING_SHA2_PASSWORD_IPP_
#include <openssl/sha.h>
#include <cstring>
inline void boost::mysql::detail::caching_sha2_password::compute_auth_string(
namespace boost {
namespace mysql {
namespace detail {
namespace caching_sha2_password {
constexpr std::size_t challenge_length = 20;
constexpr std::size_t response_length = 32;
constexpr std::string_view perform_full_auth = "\4";
// challenge must point to challenge_length bytes of data
// output must point to response_length bytes of data
inline void compute_auth_string(
std::string_view password,
const void* challenge,
void* output
@@ -34,6 +45,49 @@ inline void boost::mysql::detail::caching_sha2_password::compute_auth_string(
}
}
} // caching_sha2_password
} // detail
} // mysql
} // boost
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_AUTH_IMPL_CACHING_SHA2_PASSWORD_HPP_ */
inline boost::mysql::error_code
boost::mysql::detail::caching_sha2_password::compute_response(
std::string_view password,
std::string_view challenge,
bool use_ssl,
std::string& output
)
{
if (challenge == perform_full_auth)
{
if (!use_ssl)
{
return make_error_code(errc::auth_plugin_requires_ssl);
}
output = password;
output.push_back(0);
return error_code();
}
else
{
// Check challenge size
if (challenge.size() != challenge_length)
{
return make_error_code(errc::protocol_value_error);
}
// Do the calculation
output.resize(response_length);
compute_auth_string(
password,
challenge.data(),
output.data()
);
return error_code();
}
}
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_AUTH_IMPL_CACHING_SHA2_PASSWORD_IPP_ */

View File

@@ -4,8 +4,18 @@
#include <openssl/sha.h>
#include <cstring>
namespace boost {
namespace mysql {
namespace detail {
namespace mysql_native_password {
constexpr std::size_t challenge_length = 20;
constexpr std::size_t response_length = 20;
// challenge must point to challenge_length bytes of data
// output must point to response_length bytes of data
// SHA1( password ) XOR SHA1( "20-bytes random data from server" <concat> SHA1( SHA1( password ) ) )
inline void boost::mysql::detail::mysql_native_password::compute_auth_string(
inline void compute_auth_string(
std::string_view password,
const void* challenge,
void* output
@@ -31,8 +41,36 @@ inline void boost::mysql::detail::mysql_native_password::compute_auth_string(
}
}
} // mysql_native_password
} // detail
} // mysql
} // boost
inline boost::mysql::error_code
boost::mysql::detail::mysql_native_password::compute_response(
std::string_view password,
std::string_view challenge,
bool, // use_ssl
std::string& output
)
{
// Check challenge size
if (challenge.size() != challenge_length)
{
return make_error_code(errc::protocol_value_error);
}
// Do the calculation
output.resize(response_length);
compute_auth_string(
password,
challenge.data(),
output.data()
);
return error_code();
}
#endif

View File

@@ -3,20 +3,21 @@
#include <cstdint>
#include <string_view>
#include <array>
#include "boost/mysql/error.hpp"
namespace boost {
namespace mysql {
namespace detail {
namespace mysql_native_password {
constexpr const char* plugin_name = "mysql_native_password";
constexpr std::size_t challenge_length = 20;
constexpr std::size_t response_length = 20;
// challenge must point to challenge_length bytes of data
// output must point to response_length bytes of data
inline void compute_auth_string(std::string_view password, const void* challenge, void* output);
// Authorization for this plugin is always challenge (nonce) -> response
// (hashed password).
inline error_code compute_response(
std::string_view password,
std::string_view challenge,
bool use_ssl,
std::string& output
);
} // mysql_native_password

View File

@@ -4,7 +4,7 @@
#include "boost/mysql/detail/network_algorithms/common.hpp"
#include "boost/mysql/detail/protocol/capabilities.hpp"
#include "boost/mysql/detail/protocol/handshake_messages.hpp"
#include "boost/mysql/detail/auth/auth.hpp"
#include "boost/mysql/detail/auth/auth_calculator.hpp"
#include <boost/asio/yield.hpp>
namespace boost {
@@ -45,6 +45,16 @@ inline error_code deserialize_handshake(
return deserialize_message(output, ctx);
}
// When receiving an auth response from the server, several things can happen:
// - An OK packet. It means we are done with the auth phase. auth_result::complete.
// - An auth switch response. It means we should change the auth plugin,
// recalculate the auth response and send it back. auth_result::send_more_data.
// - An auth more data. Same as auth switch response, but without changing
// the authentication plugin. Also auth_result::send_more_data.
// - An auth more data with a challenge equals to fast_auth_complete_challenge.
// This means auth is complete and we should wait for an OK packet (auth_result::wait_for_ok).
// I have no clue why the server sends this instead of just an OK packet. It
// happens just for caching_sha2_password.
enum class auth_result
{
complete,
@@ -57,7 +67,7 @@ class handshake_processor
{
connection_params params_;
capabilities negotiated_caps_;
auth_response_calculator auth_calc_;
auth_calculator auth_calc_;
public:
handshake_processor(const connection_params& params): params_(params) {};
capabilities negotiated_capabilities() const noexcept { return negotiated_caps_; }
@@ -125,7 +135,7 @@ public:
string_null(params_.username()),
string_lenenc(auth_calc_.response()),
string_null(params_.database()),
string_null(auth_calc_.get_plugin_name())
string_null(auth_calc_.plugin_name())
};
// Serialize
@@ -183,26 +193,27 @@ public:
err = deserialize_message(more_data, ctx);
if (err) return err;
// TODO: refactor this
std::string_view data = more_data.auth_plugin_data.value;
if (data.size() == 1 && data[0] == 3)
std::string_view challenge = more_data.auth_plugin_data.value;
if (challenge == fast_auth_complete_challenge)
{
result = auth_result::wait_for_ok;
return error_code();
}
// Compute response
auth_switch_response_packet auth_sw_res;
err = auth_calc_.calculate(
auth_calc_.get_plugin_name(),
auth_calc_.plugin_name(),
params_.password(),
more_data.auth_plugin_data.value,
challenge,
use_ssl()
);
if (err) return err;
auth_sw_res.auth_plugin_data.value = auth_calc_.response();
serialize_message(auth_sw_res, negotiated_caps_, buffer);
serialize_message(
auth_switch_response_packet {string_eof(auth_calc_.response())},
negotiated_caps_,
buffer
);
result = auth_result::send_more_data;
return error_code();

View File

@@ -64,6 +64,7 @@ constexpr std::uint8_t ok_packet_header = 0x00;
constexpr std::uint8_t eof_packet_header = 0xfe;
constexpr std::uint8_t auth_switch_request_header = 0xfe;
constexpr std::uint8_t auth_more_data_header = 0x01;
constexpr std::string_view fast_auth_complete_challenge = "\3";
// Column flags
namespace column_flags

View File

@@ -17,8 +17,7 @@ endif()
# of the runtime penalty (specially considerable in integration tests)
add_executable(
mysql_unittests
unit/detail/auth/mysql_native_password.cpp
unit/detail/auth/caching_sha2_password.cpp
unit/detail/auth/auth_calculator.cpp
unit/detail/protocol/serialization_test_common.cpp
unit/detail/protocol/serialization.cpp
unit/detail/protocol/common_messages.cpp

View File

@@ -0,0 +1,174 @@
#include "boost/mysql/detail/auth/auth_calculator.hpp"
#include "test_common.hpp"
#include <gtest/gtest.h>
using namespace boost::mysql::detail;
using namespace boost::mysql::test;
using namespace testing;
using boost::mysql::error_code;
using boost::mysql::errc;
namespace
{
// mysql_native_password
struct MysqlNativePasswordTest : public Test
{
auth_calculator calc;
std::uint8_t challenge_buffer [20] {
0x79, 0x64, 0x3d, 0x12, 0x1d, 0x71, 0x74, 0x47,
0x5f, 0x48, 0x3e, 0x3e, 0x0b, 0x62, 0x0a, 0x03,
0x3d, 0x27, 0x3a, 0x4c
}; // Values snooped using Wireshark
std::uint8_t expected_buffer [20] {
0xf1, 0xb2, 0xfb, 0x1c, 0x8d, 0xe7, 0x5d, 0xb8,
0xeb, 0xa8, 0x12, 0x6a, 0xd1, 0x0f, 0xe9, 0xb1,
0x10, 0x50, 0xd4, 0x28
};
std::string_view challenge = makesv(challenge_buffer);
std::string_view expected = makesv(expected_buffer);
};
TEST_F(MysqlNativePasswordTest, NonEmptyPasswordSslFalse_ReturnsExpectedHash)
{
auto err = calc.calculate("mysql_native_password", "root", challenge, false);
EXPECT_EQ(err, error_code());
EXPECT_EQ(calc.response(), expected);
EXPECT_EQ(calc.plugin_name(), "mysql_native_password");
}
TEST_F(MysqlNativePasswordTest, NonEmptyPasswordSslTrue_ReturnsExpectedHash)
{
auto err = calc.calculate("mysql_native_password", "root", challenge, true);
EXPECT_EQ(err, error_code());
EXPECT_EQ(calc.response(), expected);
EXPECT_EQ(calc.plugin_name(), "mysql_native_password");
}
TEST_F(MysqlNativePasswordTest, EmptyPasswordSslFalse_ReturnsEmpty)
{
auto err = calc.calculate("mysql_native_password", "", challenge, false);
EXPECT_EQ(err, error_code());
EXPECT_EQ(calc.response(), "");
EXPECT_EQ(calc.plugin_name(), "mysql_native_password");
}
TEST_F(MysqlNativePasswordTest, EmptyPasswordSslTrue_ReturnsEmpty)
{
auto err = calc.calculate("mysql_native_password", "", challenge, false);
EXPECT_EQ(err, error_code());
EXPECT_EQ(calc.response(), "");
EXPECT_EQ(calc.plugin_name(), "mysql_native_password");
}
TEST_F(MysqlNativePasswordTest, BadChallengeLength_Fail)
{
EXPECT_EQ((calc.calculate("mysql_native_password", "password", "", true)),
make_error_code(errc::protocol_value_error));
EXPECT_EQ((calc.calculate("mysql_native_password", "password", "bad_challenge", true)),
make_error_code(errc::protocol_value_error));
}
// caching_sha2_password
struct CachingSha2PasswordTest : public Test
{
auth_calculator calc;
std::uint8_t challenge_buffer [20] {
0x3e, 0x3b, 0x4, 0x55, 0x4, 0x70, 0x16, 0x3a,
0x4c, 0x15, 0x35, 0x3, 0x15, 0x76, 0x73, 0x22,
0x46, 0x8, 0x18, 0x1
}; // Values snooped using the MySQL Python connector
std::uint8_t expected_buffer [32] {
0xa1, 0xc1, 0xe1, 0xe9, 0x1b, 0xb6, 0x54, 0x4b,
0xa7, 0x37, 0x4b, 0x9c, 0x56, 0x6d, 0x69, 0x3e,
0x6, 0xca, 0x7, 0x2, 0x98, 0xac, 0xd1, 0x6,
0x18, 0xc6, 0x90, 0x38, 0x9d, 0x88, 0xe1, 0x20
};
std::string_view challenge = makesv(challenge_buffer);
std::string_view expected = makesv(expected_buffer);
std::string_view cleartext_challenge { "\4" };
};
TEST_F(CachingSha2PasswordTest, NonEmptyPasswordChallengeAuthSslFalse_ReturnsExpectedHash)
{
auto err = calc.calculate("caching_sha2_password", "hola", challenge, false);
EXPECT_EQ(err, error_code());
EXPECT_EQ(calc.response(), expected);
EXPECT_EQ(calc.plugin_name(), "caching_sha2_password");
}
TEST_F(CachingSha2PasswordTest, NonEmptyPasswordChallengeAuthSslTrue_ReturnsExpectedHash)
{
auto err = calc.calculate("caching_sha2_password", "hola", challenge, true);
EXPECT_EQ(err, error_code());
EXPECT_EQ(calc.response(), expected);
EXPECT_EQ(calc.plugin_name(), "caching_sha2_password");
}
TEST_F(CachingSha2PasswordTest, NonEmptyPasswordCleartextAuthSslFalse_Fail)
{
auto err = calc.calculate("caching_sha2_password", "hola", cleartext_challenge, false);
EXPECT_EQ(err, make_error_code(errc::auth_plugin_requires_ssl));
}
TEST_F(CachingSha2PasswordTest, NonEmptyPasswordCleartextAuthSslTrue_ReturnsPassword)
{
auto err = calc.calculate("caching_sha2_password", "hola", cleartext_challenge, true);
EXPECT_EQ(err, error_code());
EXPECT_EQ(calc.response(), std::string("hola") + '\0');
EXPECT_EQ(calc.plugin_name(), "caching_sha2_password");
}
TEST_F(CachingSha2PasswordTest, EmptyPasswordChallengeAuthSslFalse_ReturnsEmpty)
{
auto err = calc.calculate("caching_sha2_password", "", challenge, false);
EXPECT_EQ(err, error_code());
EXPECT_EQ(calc.response(), "");
EXPECT_EQ(calc.plugin_name(), "caching_sha2_password");
}
TEST_F(CachingSha2PasswordTest, EmptyPasswordChallengeAuthSslTrue_ReturnsEmpty)
{
auto err = calc.calculate("caching_sha2_password", "", challenge, true);
EXPECT_EQ(err, error_code());
EXPECT_EQ(calc.response(), "");
EXPECT_EQ(calc.plugin_name(), "caching_sha2_password");
}
TEST_F(CachingSha2PasswordTest, EmptyPasswordCleartextAuthSslFalse_ReturnsEmpty)
{
auto err = calc.calculate("caching_sha2_password", "", cleartext_challenge, false);
EXPECT_EQ(err, error_code());
EXPECT_EQ(calc.response(), "");
EXPECT_EQ(calc.plugin_name(), "caching_sha2_password");
}
TEST_F(CachingSha2PasswordTest, EmptyPasswordCleartextAuthSslTrue_ReturnsEmpty)
{
auto err = calc.calculate("caching_sha2_password", "", cleartext_challenge, true);
EXPECT_EQ(err, error_code());
EXPECT_EQ(calc.response(), "");
EXPECT_EQ(calc.plugin_name(), "caching_sha2_password");
}
TEST_F(CachingSha2PasswordTest, BadChallengeLength_Fail)
{
EXPECT_EQ((calc.calculate("caching_sha2_password", "password", "", true)),
make_error_code(errc::protocol_value_error));
EXPECT_EQ((calc.calculate("caching_sha2_password", "password", "bad_challenge", true)),
make_error_code(errc::protocol_value_error));
}
// Bad authentication plugin
TEST(AuthCalculator, UnknownAuthPlugin_Fail)
{
auth_calculator calc;
EXPECT_EQ((calc.calculate("bad_plugin", "password", "challenge", true)),
make_error_code(errc::unknown_auth_plugin));
EXPECT_EQ((calc.calculate("", "password", "challenge", true)),
make_error_code(errc::unknown_auth_plugin));
}
}

View File

@@ -1,27 +0,0 @@
#include "boost/mysql/detail/auth/caching_sha2_password.hpp"
#include <gtest/gtest.h>
#include <array>
using namespace boost::mysql::detail;
TEST(CachingSha2Password, ComputeAuthString_NonEmptyPassword_ReturnsExpectedHash)
{
// Values snooped using the MySQL Python connector
std::array<std::uint8_t, caching_sha2_password::challenge_length> challenge {
0x3e, 0x3b, 0x4, 0x55, 0x4, 0x70, 0x16, 0x3a,
0x4c, 0x15, 0x35, 0x3, 0x15, 0x76, 0x73, 0x22,
0x46, 0x8, 0x18, 0x1
};
std::array<std::uint8_t, caching_sha2_password::response_length> expected {
0xa1, 0xc1, 0xe1, 0xe9, 0x1b, 0xb6, 0x54, 0x4b,
0xa7, 0x37, 0x4b, 0x9c, 0x56, 0x6d, 0x69, 0x3e,
0x6, 0xca, 0x7, 0x2, 0x98, 0xac, 0xd1, 0x6,
0x18, 0xc6, 0x90, 0x38, 0x9d, 0x88, 0xe1, 0x20
};
std::array<std::uint8_t, caching_sha2_password::response_length> actual {};
const char* password = "hola";
caching_sha2_password::compute_auth_string(password, challenge.data(), actual.data());
EXPECT_EQ(expected, actual);
}

View File

@@ -1,37 +0,0 @@
/*
* auth.cpp
*
* Created on: Oct 21, 2019
* Author: ruben
*/
#include "boost/mysql/detail/auth/mysql_native_password.hpp"
#include <gtest/gtest.h>
#include <array>
using namespace boost::mysql::detail;
using namespace testing;
namespace
{
TEST(MysqlNativePassword, ComputeAuthString_NonEmptyPassword_ReturnsExpectedHash)
{
// Values snooped using Wireshark
std::array<std::uint8_t, mysql_native_password::challenge_length> challenge {
0x79, 0x64, 0x3d, 0x12, 0x1d, 0x71, 0x74, 0x47,
0x5f, 0x48, 0x3e, 0x3e, 0x0b, 0x62, 0x0a, 0x03,
0x3d, 0x27, 0x3a, 0x4c
};
std::array<std::uint8_t, mysql_native_password::response_length> expected {
0xf1, 0xb2, 0xfb, 0x1c, 0x8d, 0xe7, 0x5d, 0xb8,
0xeb, 0xa8, 0x12, 0x6a, 0xd1, 0x0f, 0xe9, 0xb1,
0x10, 0x50, 0xd4, 0x28
};
std::array<std::uint8_t, mysql_native_password::response_length> actual {};
const char* password = "root";
mysql_native_password::compute_auth_string(password, challenge.data(), actual.data());
EXPECT_EQ(expected, actual);
}
} // anon namespace

View File

@@ -205,5 +205,13 @@ INSTANTIATE_TEST_SUITE_P(SslRequest, SerializeTest, ::testing::Values(
}, "default")
), test_name_generator);
INSTANTIATE_TEST_SUITE_P(AuthMoreData, DeserializeTest, ::testing::Values(
serialization_testcase(auth_more_data_packet{
string_eof("abc")
}, {
0x61, 0x62, 0x63
}, "default")
), test_name_generator);
} // anon namespace