mirror of
https://github.com/monero-project/monero.git
synced 2026-07-28 22:51:07 -07:00
Harden HTTP client auth
This commit is contained in:
@@ -64,6 +64,7 @@
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
@@ -294,13 +295,21 @@ namespace
|
||||
|
||||
std::array<char, 8> nc{{}};
|
||||
boost::copy(out, nc.data());
|
||||
|
||||
std::array<uint8_t, 16> rbuf{{}};
|
||||
if (RAND_bytes(rbuf.data(), rbuf.size()) != 1)
|
||||
return {};
|
||||
|
||||
const std::string cnonce = epee::string_encoding::base64_encode(rbuf.data(), rbuf.size());
|
||||
const auto response = digest(
|
||||
generate_a1(digest, user), u8":", user.server.nonce, u8":", nc, u8"::auth:", digest(method, u8":", uri)
|
||||
generate_a1(digest, user), u8":", user.server.nonce, u8":", nc, u8":", cnonce, u8":auth:", digest(method, u8":", uri)
|
||||
);
|
||||
|
||||
out.clear();
|
||||
init_client_value(out, Digest::name, user, uri, response);
|
||||
add_field(out, u8"qop", ceref(u8"auth"));
|
||||
add_field(out, u8"nc", nc);
|
||||
add_field(out, u8"cnonce", quoted_(cnonce));
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -590,7 +599,7 @@ namespace
|
||||
boost::equals((*digest).name, request.algorithm, ascii_iequal)
|
||||
);
|
||||
if (request.qop.empty())
|
||||
value_generator = old_algorithm<digest_type>{*digest};
|
||||
index = boost::fusion::size(digest_algorithms);
|
||||
else
|
||||
{
|
||||
for (auto elem = boost::make_split_iterator(request.qop, boost::token_finder(http_list_separator));
|
||||
|
||||
@@ -614,10 +614,8 @@ TEST(HTTP_Client_Auth, BadSyntax)
|
||||
|
||||
TEST(HTTP_Client_Auth, MD5)
|
||||
{
|
||||
constexpr char method[] = "NOP";
|
||||
constexpr char nonce[] = "some crazy nonce";
|
||||
constexpr char realm[] = "the only realm";
|
||||
constexpr char uri[] = "/some_file";
|
||||
|
||||
const http::login user{"foo", "bar"};
|
||||
http::http_client_auth auth{user};
|
||||
@@ -636,42 +634,11 @@ TEST(HTTP_Client_Auth, MD5)
|
||||
},
|
||||
});
|
||||
|
||||
EXPECT_EQ(http::http_client_auth::kSuccess, auth.handle_401(response));
|
||||
const auto auth_field = auth.get_auth_field(method, uri);
|
||||
ASSERT_TRUE(bool(auth_field));
|
||||
|
||||
const auto parsed = parse_fields(auth_field->second);
|
||||
EXPECT_STREQ(u8"Authorization", auth_field->first.c_str());
|
||||
EXPECT_EQ(parsed.end(), parsed.find(u8"opaque"));
|
||||
EXPECT_EQ(parsed.end(), parsed.find(u8"qop"));
|
||||
EXPECT_EQ(parsed.end(), parsed.find(u8"nc"));
|
||||
EXPECT_STREQ(u8"MD5", parsed.at(u8"algorithm").c_str());
|
||||
EXPECT_STREQ(nonce, parsed.at(u8"nonce").c_str());
|
||||
EXPECT_STREQ(uri, parsed.at(u8"uri").c_str());
|
||||
EXPECT_EQ(user.username, parsed.at(u8"username"));
|
||||
EXPECT_STREQ(realm, parsed.at(u8"realm").c_str());
|
||||
|
||||
const std::string a1 = get_a1(user, parsed);
|
||||
const std::string a2 = get_a2(uri);
|
||||
const std::string auth_code = md5_hex(
|
||||
boost::join(std::vector<std::string>{md5_hex(a1), nonce, md5_hex(a2)}, u8":")
|
||||
);
|
||||
EXPECT_TRUE(boost::iequals(auth_code, parsed.at(u8"response")));
|
||||
{
|
||||
const auto auth_field_dup = auth.get_auth_field(method, uri);
|
||||
ASSERT_TRUE(bool(auth_field_dup));
|
||||
EXPECT_EQ(*auth_field, *auth_field_dup);
|
||||
}
|
||||
|
||||
|
||||
EXPECT_EQ(http::http_client_auth::kBadPassword, auth.handle_401(response));
|
||||
response.m_header_info.m_etc_fields.front().second.append(u8"," + write_fields({{u8"stale", u8"TRUE"}}));
|
||||
EXPECT_EQ(http::http_client_auth::kSuccess, auth.handle_401(response));
|
||||
EXPECT_EQ(http::http_client_auth::kParseFailure, auth.handle_401(response));
|
||||
}
|
||||
|
||||
TEST(HTTP_Client_Auth, MD5_auth)
|
||||
{
|
||||
constexpr char cnonce[] = "";
|
||||
constexpr char method[] = "NOP";
|
||||
constexpr char nonce[] = "some crazy nonce";
|
||||
constexpr char opaque[] = "this is the opaque";
|
||||
@@ -723,7 +690,7 @@ TEST(HTTP_Client_Auth, MD5_auth)
|
||||
const std::string a1 = get_a1(user, parsed);
|
||||
const std::string a2 = get_a2(uri);
|
||||
const std::string auth_code = md5_hex(
|
||||
boost::join(std::vector<std::string>{md5_hex(a1), nonce, nc, cnonce, u8"auth", md5_hex(a2)}, u8":")
|
||||
boost::join(std::vector<std::string>{md5_hex(a1), nonce, nc, parsed.at(u8"cnonce"), u8"auth", md5_hex(a2)}, u8":")
|
||||
);
|
||||
EXPECT_TRUE(boost::iequals(auth_code, parsed.at(u8"response")));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user