HTTPDigestCredentials added support for RFC7616 algorithms (#3026)

This commit is contained in:
Maksim Kita 2022-05-30 04:52:39 +02:00 committed by GitHub
parent 1f587cfd3b
commit fe59436763
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 331 additions and 27 deletions

View File

@ -38,10 +38,12 @@ class Foundation_API SHA2Engine: public DigestEngine
public:
enum ALGORITHM
{
SHA_224 = 224,
SHA_256 = 256,
SHA_384 = 384,
SHA_512 = 512
SHA_224 = 1,
SHA_256,
SHA_384,
SHA_512,
SHA_512_224,
SHA_512_256
};
SHA2Engine(ALGORITHM algorithm = SHA_256);

View File

@ -41,7 +41,6 @@ typedef struct
Poco::UInt64 state64[8];
} state;
SHA2Engine::ALGORITHM size;
unsigned char buffer[128];
} HASHCONTEXT;
@ -274,7 +273,7 @@ void SHA2Engine::updateImpl(const void* buffer_, std::size_t count)
Poco::UInt32 left = 0;
HASHCONTEXT* pContext = (HASHCONTEXT*)_context;
unsigned char* data = (unsigned char*)buffer_;
if (pContext->size > SHA_256)
if (_algorithm > SHA_256)
{
left = (Poco::UInt32)(pContext->total.total64[0] & 0x7F);
size_t fill = 128 - left;
@ -323,7 +322,31 @@ void SHA2Engine::updateImpl(const void* buffer_, std::size_t count)
std::size_t SHA2Engine::digestLength() const
{
return (size_t)((int)_algorithm / 8);
size_t result = 0;
switch (_algorithm)
{
case SHA_224:
result = 224;
break;
case SHA_256:
result = 256;
break;
case SHA_384:
result = 384;
break;
case SHA_512:
result = 512;
break;
case SHA_512_224:
result = 224;
break;
case SHA_512_256:
result = 256;
break;
}
return result / 8;
}
@ -332,7 +355,6 @@ void SHA2Engine::reset()
if (_context != NULL) free(_context);
_context = calloc(1, sizeof(HASHCONTEXT));
HASHCONTEXT* pContext = (HASHCONTEXT*)_context;
pContext->size = _algorithm;
if (_algorithm == SHA_224)
{
pContext->state.state32[0] = 0xC1059ED8;
@ -366,7 +388,7 @@ void SHA2Engine::reset()
pContext->state.state64[6] = UL64(0xDB0C2E0D64F98FA7);
pContext->state.state64[7] = UL64(0x47B5481DBEFA4FA4);
}
else
else if (_algorithm == SHA_512)
{
pContext->state.state64[0] = UL64(0x6A09E667F3BCC908);
pContext->state.state64[1] = UL64(0xBB67AE8584CAA73B);
@ -377,6 +399,27 @@ void SHA2Engine::reset()
pContext->state.state64[6] = UL64(0x1F83D9ABFB41BD6B);
pContext->state.state64[7] = UL64(0x5BE0CD19137E2179);
}
else if (_algorithm == SHA_512_224)
{
pContext->state.state64[0] = UL64(0x8C3D37C819544DA2);
pContext->state.state64[1] = UL64(0x73E1996689DCD4D6);
pContext->state.state64[2] = UL64(0x1DFAB7AE32FF9C82);
pContext->state.state64[3] = UL64(0x679DD514582F9FCF);
pContext->state.state64[4] = UL64(0x0F6D2B697BD44DA8);
pContext->state.state64[5] = UL64(0x77E36F7304C48942);
pContext->state.state64[6] = UL64(0x3F9D85A86A1D36C8);
pContext->state.state64[7] = UL64(0x1112E6AD91D692A1);
} else
{
pContext->state.state64[0] = UL64(0x22312194FC2BF72C);
pContext->state.state64[1] = UL64(0x9F555FA3C84C64C2);
pContext->state.state64[2] = UL64(0x2393B86B6F53B151);
pContext->state.state64[3] = UL64(0x963877195940EABD);
pContext->state.state64[4] = UL64(0x96283EE2A88EFFE3);
pContext->state.state64[5] = UL64(0xBE5E1E2553863992);
pContext->state.state64[6] = UL64(0x2B0199FC2C85B8AA);
pContext->state.state64[7] = UL64(0x0EB72DDC81C52CA2);
}
}
@ -388,7 +431,8 @@ const DigestEngine::Digest& SHA2Engine::digest()
size_t last, padn;
unsigned char hash[64];
memset(hash, 0, 64);
if (pContext->size > SHA_256)
if (_algorithm > SHA_256)
{
unsigned char msglen[16];
Poco::UInt64 high = (pContext->total.total64[0] >> 61) | (pContext->total.total64[1] << 3);
@ -405,7 +449,7 @@ const DigestEngine::Digest& SHA2Engine::digest()
PUT_UINT64(pContext->state.state64[3], hash, 24);
PUT_UINT64(pContext->state.state64[4], hash, 32);
PUT_UINT64(pContext->state.state64[5], hash, 40);
if (pContext->size > SHA_384)
if (_algorithm > SHA_384)
{
PUT_UINT64(pContext->state.state64[6], hash, 48);
PUT_UINT64(pContext->state.state64[7], hash, 56);
@ -429,7 +473,7 @@ const DigestEngine::Digest& SHA2Engine::digest()
PUT_UINT32(pContext->state.state32[4], hash, 16);
PUT_UINT32(pContext->state.state32[5], hash, 20);
PUT_UINT32(pContext->state.state32[6], hash, 24);
if (pContext->size > SHA_224) PUT_UINT32(pContext->state.state32[7], hash, 28);
if (_algorithm > SHA_224) PUT_UINT32(pContext->state.state32[7], hash, 28);
}
_digest.insert(_digest.begin(), hash, hash + digestLength());
reset();

View File

@ -36,6 +36,9 @@ void SHA2EngineTest::testSHA224()
{
SHA2Engine engine(SHA2Engine::SHA_224);
engine.update("");
assertTrue (DigestEngine::digestToHex(engine.digest()) == "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f");
engine.update("abc");
assertTrue (DigestEngine::digestToHex(engine.digest()) == "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7");
@ -55,6 +58,9 @@ void SHA2EngineTest::testSHA256()
{
SHA2Engine engine(SHA2Engine::SHA_256);
engine.update("");
assertTrue (DigestEngine::digestToHex(engine.digest()) == "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
engine.update("abc");
assertTrue (DigestEngine::digestToHex(engine.digest()) == "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
@ -74,6 +80,9 @@ void SHA2EngineTest::testSHA384()
{
SHA2Engine engine(SHA2Engine::SHA_384);
engine.update("");
assertTrue (DigestEngine::digestToHex(engine.digest()) == "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b");
engine.update("abc");
assertTrue (DigestEngine::digestToHex(engine.digest()) == "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7");
@ -93,6 +102,9 @@ void SHA2EngineTest::testSHA512()
{
SHA2Engine engine(SHA2Engine::SHA_512);
engine.update("");
assertTrue (DigestEngine::digestToHex(engine.digest()) == "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e");
engine.update("abc");
assertTrue (DigestEngine::digestToHex(engine.digest()) == "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f");
@ -107,6 +119,47 @@ void SHA2EngineTest::testSHA512()
assertTrue (DigestEngine::digestToHex(engine.digest()) == "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b");
}
void SHA2EngineTest::testSHA512_224()
{
SHA2Engine engine(SHA2Engine::SHA_512_224);
engine.update("");
assertTrue (DigestEngine::digestToHex(engine.digest()) == "6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4");
engine.update("abc");
assertTrue (DigestEngine::digestToHex(engine.digest()) == "4634270f707b6a54daae7530460842e20e37ed265ceee9a43e8924aa");
engine.update("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
assertTrue (DigestEngine::digestToHex(engine.digest()) == "e5302d6d54bb242275d1e7622d68df6eb02dedd13f564c13dbda2174");
engine.update("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");
assertTrue (DigestEngine::digestToHex(engine.digest()) == "23fec5bb94d60b23308192640b0c453335d664734fe40e7268674af9");
for (int i = 0; i < 1000000; ++i)
engine.update('a');
assertTrue (DigestEngine::digestToHex(engine.digest()) == "37ab331d76f0d36de422bd0edeb22a28accd487b7a8453ae965dd287");
}
void SHA2EngineTest::testSHA512_256()
{
SHA2Engine engine(SHA2Engine::SHA_512_256);
engine.update("");
assertTrue (DigestEngine::digestToHex(engine.digest()) == "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a");
engine.update("abc");
assertTrue (DigestEngine::digestToHex(engine.digest()) == "53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23");
engine.update("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
assertTrue (DigestEngine::digestToHex(engine.digest()) == "bde8e1f9f19bb9fd3406c90ec6bc47bd36d8ada9f11880dbc8a22a7078b6a461");
engine.update("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu");
assertTrue (DigestEngine::digestToHex(engine.digest()) == "3928e184fb8690f840da3988121d31be65cb9d3ef83ee6146feac861e19b563a");
for (int i = 0; i < 1000000; ++i)
engine.update('a');
assertTrue (DigestEngine::digestToHex(engine.digest()) == "9a59a052930187a97038cae692f30708aa6491923ef5194394dc68d56c74fb21");
}
void SHA2EngineTest::setUp()
{
@ -126,6 +179,7 @@ CppUnit::Test* SHA2EngineTest::suite()
CppUnit_addTest(pSuite, SHA2EngineTest, testSHA256);
CppUnit_addTest(pSuite, SHA2EngineTest, testSHA384);
CppUnit_addTest(pSuite, SHA2EngineTest, testSHA512);
CppUnit_addTest(pSuite, SHA2EngineTest, testSHA512_224);
CppUnit_addTest(pSuite, SHA2EngineTest, testSHA512_256);
return pSuite;
}

View File

@ -28,6 +28,8 @@ public:
void testSHA256();
void testSHA384();
void testSHA512();
void testSHA512_224();
void testSHA512_256();
void setUp();
void tearDown();

View File

@ -120,6 +120,9 @@ public:
/// and HTTPAuthenticationParams by recomputing the response and comparing
/// it with what's in the request.
bool isAlgorithmSupported(const std::string& algorithm) const;
/// Check if digest algorithm is supported
static std::string createNonce();
/// Creates a random nonce string.
@ -133,7 +136,19 @@ private:
void updateAuthParams(const HTTPRequest& request);
int updateNonceCounter(const std::string& nonce);
static const std::string DEFAULT_ALGORITHM;
class DigestEngineProvider;
static const std::string MD_5_ALGORITHM;
static const std::string MD_5_SESS_ALGORITHM;
static const std::string SHA_ALGORITHM;
static const std::string SHA_SESS_ALGORITHM;
static const std::string SHA_256_ALGORITHM;
static const std::string SHA_256_SESS_ALGORITHM;
static const std::string SHA_512_256_ALGORITHM;
static const std::string SHA_512_256_SESS_ALGORITHM;
static const std::string SHA_512_ALGORITHM;
static const std::string SHA_512_SESS_ALGORITHM;
static const std::vector<std::string> SUPPORTED_ALGORITHMS;
static const std::string DEFAULT_QOP;
static const std::string NONCE_PARAM;
static const std::string REALM_PARAM;

View File

@ -18,12 +18,15 @@
#include "Poco/DateTimeFormatter.h"
#include "Poco/Exception.h"
#include "Poco/MD5Engine.h"
#include "Poco/SHA1Engine.h"
#include "Poco/SHA2Engine.h"
#include "Poco/Net/HTTPDigestCredentials.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/NumberFormatter.h"
#include "Poco/StringTokenizer.h"
#include <iostream>
namespace
{
@ -68,7 +71,28 @@ namespace Net {
const std::string HTTPDigestCredentials::SCHEME = "Digest";
const std::string HTTPDigestCredentials::DEFAULT_ALGORITHM("MD5");
const std::vector<std::string> HTTPDigestCredentials::SUPPORTED_ALGORITHMS = {
"MD5",
"MD5-sess",
"SHA",
"SHA-sess",
"SHA-256",
"SHA-256-sess",
"SHA-512-256",
"SHA-512-256-sess",
"SHA-512",
"SHA-512-sess"
};
const std::string HTTPDigestCredentials::MD_5_ALGORITHM = "MD5";
const std::string HTTPDigestCredentials::MD_5_SESS_ALGORITHM = "MD5-sess";
const std::string HTTPDigestCredentials::SHA_ALGORITHM = "SHA";
const std::string HTTPDigestCredentials::SHA_SESS_ALGORITHM = "SHA-sess";
const std::string HTTPDigestCredentials::SHA_256_ALGORITHM = "SHA-256";
const std::string HTTPDigestCredentials::SHA_256_SESS_ALGORITHM = "SHA-256-sess";
const std::string HTTPDigestCredentials::SHA_512_256_ALGORITHM = "SHA-512-256";
const std::string HTTPDigestCredentials::SHA_512_256_SESS_ALGORITHM = "SHA-512-256-sess";
const std::string HTTPDigestCredentials::SHA_512_ALGORITHM = "SHA-512";
const std::string HTTPDigestCredentials::SHA_512_SESS_ALGORITHM = "SHA-512-sess";
const std::string HTTPDigestCredentials::DEFAULT_QOP("");
const std::string HTTPDigestCredentials::NONCE_PARAM("nonce");
const std::string HTTPDigestCredentials::REALM_PARAM("realm");
@ -84,6 +108,44 @@ const std::string HTTPDigestCredentials::NC_PARAM("nc");
int HTTPDigestCredentials::_nonceCounter(0);
Poco::FastMutex HTTPDigestCredentials::_nonceMutex;
class HTTPDigestCredentials::DigestEngineProvider {
public:
DigestEngineProvider(std::string algorithm): _algorithm(algorithm) {
_isSessionAlgorithm = _algorithm.find("sess") != std::string::npos;
}
DigestEngine& engine() {
if (icompare(_algorithm, SHA_ALGORITHM) == 0 || icompare(_algorithm, SHA_SESS_ALGORITHM) == 0)
{
return _sha1Engine;
}
if (icompare(_algorithm, SHA_256_ALGORITHM) == 0 || icompare(_algorithm, SHA_256_SESS_ALGORITHM) == 0)
{
return _sha256Engine;
} else if (icompare(_algorithm, SHA_512_256_ALGORITHM) == 0 || icompare(_algorithm, SHA_512_256_SESS_ALGORITHM) == 0)
{
return _sha512_256Engine;
} else if (icompare(_algorithm, SHA_512_ALGORITHM) == 0 || icompare(_algorithm, SHA_512_SESS_ALGORITHM) == 0)
{
return _sha512;
}
else {
return _md5Engine;
}
}
bool isSessionAlgorithm() {
return _isSessionAlgorithm;
}
private:
std::string _algorithm;
SHA1Engine _sha1Engine;
MD5Engine _md5Engine;
SHA2Engine _sha256Engine { SHA2Engine::ALGORITHM::SHA_256 };
SHA2Engine _sha512_256Engine { SHA2Engine::ALGORITHM::SHA_512_256 };
SHA2Engine _sha512 { SHA2Engine::ALGORITHM::SHA_512 };
bool _isSessionAlgorithm;
};
HTTPDigestCredentials::HTTPDigestCredentials()
{
@ -191,11 +253,6 @@ void HTTPDigestCredentials::createAuthParams(const HTTPRequest& request, const H
if (!responseAuthParams.has(NONCE_PARAM) || !responseAuthParams.has(REALM_PARAM))
throw InvalidArgumentException("Invalid HTTP authentication parameters");
const std::string& algorithm = responseAuthParams.get(ALGORITHM_PARAM, DEFAULT_ALGORITHM);
if (icompare(algorithm, DEFAULT_ALGORITHM) != 0)
throw NotImplementedException("Unsupported digest algorithm", algorithm);
const std::string& nonce = responseAuthParams.get(NONCE_PARAM);
const std::string& qop = responseAuthParams.get(QOP_PARAM, DEFAULT_QOP);
const std::string& realm = responseAuthParams.getRealm();
@ -208,6 +265,10 @@ void HTTPDigestCredentials::createAuthParams(const HTTPRequest& request, const H
{
_requestAuthParams.set(OPAQUE_PARAM, responseAuthParams.get(OPAQUE_PARAM));
}
if (responseAuthParams.has(ALGORITHM_PARAM))
{
_requestAuthParams.set(ALGORITHM_PARAM, responseAuthParams.get(ALGORITHM_PARAM));
}
if (qop.empty())
{
@ -233,10 +294,8 @@ void HTTPDigestCredentials::createAuthParams(const HTTPRequest& request, const H
}
}
void HTTPDigestCredentials::updateAuthParams(const HTTPRequest& request)
{
MD5Engine engine;
const std::string qop = _requestAuthParams.get(QOP_PARAM, DEFAULT_QOP);
const std::string realm = _requestAuthParams.getRealm();
const std::string nonce = _requestAuthParams.get(NONCE_PARAM);
@ -245,6 +304,11 @@ void HTTPDigestCredentials::updateAuthParams(const HTTPRequest& request)
if (qop.empty())
{
/// Assume that https://tools.ietf.org/html/rfc7616 does not supported
/// and still using https://tools.ietf.org/html/rfc2069#section-2.4
MD5Engine engine;
const std::string ha1 = digest(engine, _username, realm, _password);
const std::string ha2 = digest(engine, request.getMethod(), request.getURI());
@ -252,13 +316,28 @@ void HTTPDigestCredentials::updateAuthParams(const HTTPRequest& request)
}
else if (icompare(qop, AUTH_PARAM) == 0)
{
const std::string cnonce = _requestAuthParams.get(CNONCE_PARAM);
const std::string algorithm = _requestAuthParams.get(ALGORITHM_PARAM, MD_5_ALGORITHM);
const std::string ha1 = digest(engine, _username, realm, _password);
const std::string ha2 = digest(engine, request.getMethod(), request.getURI());
if (!isAlgorithmSupported(algorithm)) {
throw NotImplementedException("Unsupported digest algorithm", algorithm);
}
const std::string cnonce = _requestAuthParams.get(CNONCE_PARAM);
const std::string nc = formatNonceCounter(updateNonceCounter(nonce));
DigestEngineProvider engineProvider(algorithm);
DigestEngine &engine = engineProvider.engine();
std::string ha1 = digest(engine, _username, realm, _password);
if (engineProvider.isSessionAlgorithm()) {
ha1 = digest(engine, ha1, nonce, cnonce);
}
const std::string ha2 = digest(engine, request.getMethod(), request.getURI());
_requestAuthParams.set(NC_PARAM, nc);
_requestAuthParams.set(CNONCE_PARAM, cnonce);
_requestAuthParams.set(RESPONSE_PARAM, digest(engine, ha1, nonce, nc, cnonce, qop, ha2));
}
}
@ -277,18 +356,34 @@ bool HTTPDigestCredentials::verifyAuthParams(const HTTPRequest& request, const H
const std::string& realm = params.getRealm();
const std::string& qop = params.get(QOP_PARAM, DEFAULT_QOP);
std::string response;
MD5Engine engine;
if (qop.empty())
{
MD5Engine engine;
const std::string ha1 = digest(engine, _username, realm, _password);
const std::string ha2 = digest(engine, request.getMethod(), request.getURI());
response = digest(engine, ha1, nonce, ha2);
}
else if (icompare(qop, AUTH_PARAM) == 0)
{
const std::string& algorithm = params.get(ALGORITHM_PARAM, MD_5_ALGORITHM);
if (!isAlgorithmSupported(algorithm)) {
throw NotImplementedException("Unsupported digest algorithm", algorithm);
}
DigestEngineProvider engineProvider(algorithm);
DigestEngine& engine = engineProvider.engine();
const std::string& cnonce = params.get(CNONCE_PARAM);
const std::string& nc = params.get(NC_PARAM);
const std::string ha1 = digest(engine, _username, realm, _password);
std::string ha1 = digest(engine, _username, realm, _password);
if (engineProvider.isSessionAlgorithm()) {
ha1 = digest(engine, ha1, nonce, cnonce);
}
const std::string ha2 = digest(engine, request.getMethod(), request.getURI());
response = digest(engine, ha1, nonce, nc, cnonce, qop, ha2);
}
@ -309,5 +404,15 @@ int HTTPDigestCredentials::updateNonceCounter(const std::string& nonce)
return iter->second;
}
bool HTTPDigestCredentials::isAlgorithmSupported(const std::string& algorithm) const
{
bool isAlgorithmSupported = std::find_if(std::begin(SUPPORTED_ALGORITHMS),
std::end(SUPPORTED_ALGORITHMS),
[&algorithm](const std::string& supportedAlgorithm) {
return icompare(algorithm, supportedAlgorithm) == 0;
}) != std::end(SUPPORTED_ALGORITHMS);
return isAlgorithmSupported;
}
} } // namespace Poco::Net

View File

@ -214,6 +214,45 @@ void HTTPCredentialsTest::testDigestCredentialsQoP()
assertTrue (params.size() == 9);
}
void HTTPCredentialsTest::testDigestCredentialsQoPSHA256()
{
HTTPDigestCredentials creds("user", "s3cr3t");
HTTPRequest request(HTTPRequest::HTTP_GET, "/digest/");
HTTPResponse response;
response.set("WWW-Authenticate", "Digest realm=\"TestDigest\", nonce=\"212573bb90170538efad012978ab811f%lu\", opaque=\"opaque\", qop=\"auth,auth-int\", algorithm=SHA-256");
creds.authenticate(request, response);
HTTPAuthenticationParams params(request);
assertTrue (params["nonce"] == "212573bb90170538efad012978ab811f%lu");
assertTrue (params["realm"] == "TestDigest");
assertTrue (params["response"] != "40e4889cfbd0e561f71e3107a2863bc4");
assertTrue (params["uri"] == "/digest/");
assertTrue (params["username"] == "user");
assertTrue (params["opaque"] == "opaque");
assertTrue (params["cnonce"] != "");
assertTrue (params["nc"] == "00000001");
assertTrue (params["qop"] == "auth");
assertTrue (params["algorithm"] == "SHA-256");
assertTrue (params.size() == 10);
std::string cnonce = params["cnonce"];
std::string aresp = params["response"];
params.clear();
creds.updateAuthInfo(request);
params.fromRequest(request);
assertTrue (params["nonce"] == "212573bb90170538efad012978ab811f%lu");
assertTrue (params["realm"] == "TestDigest");
assertTrue (params["response"] != aresp);
assertTrue (params["uri"] == "/digest/");
assertTrue (params["username"] == "user");
assertTrue (params["opaque"] == "opaque");
assertTrue (params["cnonce"] == cnonce);
assertTrue (params["nc"] == "00000002");
assertTrue (params["qop"] == "auth");
assertTrue (params.size() == 10);
}
void HTTPCredentialsTest::testCredentialsBasic()
{
@ -311,6 +350,43 @@ void HTTPCredentialsTest::testVerifyAuthInfoQoP()
assertTrue (!creds.verifyAuthInfo(request));
}
void HTTPCredentialsTest::testVerifyAuthInfoQoPSHA256() {
HTTPDigestCredentials sha256Creds("user", "s3cr3t");
HTTPRequest sha256Request(HTTPRequest::HTTP_GET, "/digest/");
HTTPResponse sha256Response;
sha256Response.set("WWW-Authenticate", "Digest realm=\"TestDigest\", nonce=\"212573bb90170538efad012978ab811f%lu\", opaque=\"opaque\", qop=\"auth,auth-int\", algorithm=SHA-256");
sha256Creds.authenticate(sha256Request, sha256Response);
assertTrue (sha256Creds.verifyAuthInfo(sha256Request));
sha256Request.set("Authorization", "Digest cnonce=\"f9c80ffd1c3bc4ee47ed92b704ba75a4\", nc=00000001, nonce=\"212573bb90170538efad012978ab811f%lu\", opaque=\"opaque\", qop=\"auth\", realm=\"TestDigest\", response=\"ff0e90b9aa019120ea0ed6e23ce95d9a\", uri=\"/digest/\", username=\"user\", algorithm=SHA-256");
assertTrue (!sha256Creds.verifyAuthInfo(sha256Request));
HTTPDigestCredentials sha256SessCreds("user", "s3cr3t");
HTTPRequest sha256SessRequest(HTTPRequest::HTTP_GET, "/digest/");
HTTPResponse sha256SessResponse;
sha256SessResponse.set("WWW-Authenticate", "Digest realm=\"TestDigest\", nonce=\"212573bb90170538efad012978ab811f%lu\", opaque=\"opaque\", qop=\"auth,auth-int\", algorithm=SHA-256-sess");
sha256SessCreds.authenticate(sha256SessRequest, sha256SessResponse);
assertTrue (sha256SessCreds.verifyAuthInfo(sha256SessRequest));
sha256SessRequest.set("Authorization", "Digest cnonce=\"f9c80ffd1c3bc4ee47ed92b704ba75a4\", nc=00000001, nonce=\"212573bb90170538efad012978ab811f%lu\", opaque=\"opaque\", qop=\"auth\", realm=\"TestDigest\", response=\"ff0e90b9aa019120ea0ed6e23ce95d9a\", uri=\"/digest/\", username=\"user\", algorithm=SHA-256-sess");
assertTrue (!sha256SessCreds.verifyAuthInfo(sha256SessRequest));
}
void HTTPCredentialsTest::testIsAlgorithmSupported() {
HTTPDigestCredentials sha256Creds("user", "s3cr3t");
assertTrue (sha256Creds.isAlgorithmSupported("MD5"));
assertTrue (sha256Creds.isAlgorithmSupported("MD5-sess"));
assertTrue (sha256Creds.isAlgorithmSupported("SHA"));
assertTrue (sha256Creds.isAlgorithmSupported("SHA-sess"));
assertTrue (sha256Creds.isAlgorithmSupported("SHA-256"));
assertTrue (sha256Creds.isAlgorithmSupported("SHA-256-sess"));
assertTrue (sha256Creds.isAlgorithmSupported("SHA-512-256"));
assertTrue (sha256Creds.isAlgorithmSupported("SHA-512-256-sess"));
assertTrue (sha256Creds.isAlgorithmSupported("SHA-512"));
assertTrue (sha256Creds.isAlgorithmSupported("SHA-512-sess"));
assertFalse (sha256Creds.isAlgorithmSupported("random_algorithm"));
}
void HTTPCredentialsTest::setUp()
{
@ -333,6 +409,7 @@ CppUnit::Test* HTTPCredentialsTest::suite()
CppUnit_addTest(pSuite, HTTPCredentialsTest, testAuthenticationParamsMultipleHeaders);
CppUnit_addTest(pSuite, HTTPCredentialsTest, testDigestCredentials);
CppUnit_addTest(pSuite, HTTPCredentialsTest, testDigestCredentialsQoP);
CppUnit_addTest(pSuite, HTTPCredentialsTest, testDigestCredentialsQoPSHA256);
CppUnit_addTest(pSuite, HTTPCredentialsTest, testCredentialsBasic);
CppUnit_addTest(pSuite, HTTPCredentialsTest, testProxyCredentialsBasic);
CppUnit_addTest(pSuite, HTTPCredentialsTest, testCredentialsDigest);
@ -341,6 +418,8 @@ CppUnit::Test* HTTPCredentialsTest::suite()
CppUnit_addTest(pSuite, HTTPCredentialsTest, testExtractCredentials);
CppUnit_addTest(pSuite, HTTPCredentialsTest, testVerifyAuthInfo);
CppUnit_addTest(pSuite, HTTPCredentialsTest, testVerifyAuthInfoQoP);
CppUnit_addTest(pSuite, HTTPCredentialsTest, testVerifyAuthInfoQoPSHA256);
CppUnit_addTest(pSuite, HTTPCredentialsTest, testIsAlgorithmSupported);
return pSuite;
}

View File

@ -31,6 +31,7 @@ public:
void testAuthenticationParamsMultipleHeaders();
void testDigestCredentials();
void testDigestCredentialsQoP();
void testDigestCredentialsQoPSHA256();
void testCredentialsBasic();
void testProxyCredentialsBasic();
void testCredentialsDigest();
@ -39,6 +40,8 @@ public:
void testExtractCredentials();
void testVerifyAuthInfo();
void testVerifyAuthInfoQoP();
void testVerifyAuthInfoQoPSHA256();
void testIsAlgorithmSupported();
void setUp();
void tearDown();