1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-06-15 22:57:12 +02:00

Major plugin refactor and cleanup.

Switched to POCO library for unified platform/library interface.
Deprecated the external module API. It was creating more problems than solving.
Removed most built-in libraries in favor of system libraries for easier maintenance.
Cleaned and secured code with help from static analyzers.
This commit is contained in:
Sandu Liviu Catalin
2021-01-30 08:51:39 +02:00
parent e0e34b4030
commit 4a6bfc086c
6219 changed files with 1209835 additions and 454916 deletions

35
vendor/POCO/JWT/src/JWTException.cpp vendored Normal file
View File

@ -0,0 +1,35 @@
//
// JWTException.cpp
//
// Library: JWT
// Package: JWT
// Module: JWTException
//
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/JWT/JWTException.h"
#include <typeinfo>
using Poco::Exception;
namespace Poco {
namespace JWT {
POCO_IMPLEMENT_EXCEPTION(JWTException, Exception, "JWT Exception")
POCO_IMPLEMENT_EXCEPTION(ParseException, JWTException, "JWT parsing failed")
POCO_IMPLEMENT_EXCEPTION(UnsupportedAlgorithmException, JWTException, "Unsupported signing algorithm")
POCO_IMPLEMENT_EXCEPTION(UnallowedAlgorithmException, JWTException, "Unallowed signing algorithm")
POCO_IMPLEMENT_EXCEPTION(SignatureException, JWTException, "JWT Signature Exception")
POCO_IMPLEMENT_EXCEPTION(SignatureVerificationException, SignatureException, "JWT signature verification failed")
POCO_IMPLEMENT_EXCEPTION(SignatureGenerationException, SignatureException, "JWT signature generation failed")
} } // namespace Poco::JWT

81
vendor/POCO/JWT/src/Serializer.cpp vendored Normal file
View File

@ -0,0 +1,81 @@
//
// Serializer.cpp
//
// Library: JWT
// Package: JWT
// Module: Serializer
//
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/JWT/Serializer.h"
#include "Poco/JWT/JWTException.h"
#include "Poco/JSON/Parser.h"
#include "Poco/Base64Encoder.h"
#include "Poco/Base64Decoder.h"
#include "Poco/MemoryStream.h"
#include "Poco/StringTokenizer.h"
#include <sstream>
namespace Poco {
namespace JWT {
std::string Serializer::serialize(const Poco::JSON::Object& object)
{
std::ostringstream stream;
serialize(object, stream);
return stream.str();
}
void Serializer::serialize(const Poco::JSON::Object& object, std::ostream& stream)
{
Poco::Base64Encoder encoder(stream, Poco::BASE64_URL_ENCODING | Poco::BASE64_NO_PADDING);
object.stringify(encoder);
encoder.close();
}
Poco::JSON::Object::Ptr Serializer::deserialize(const std::string& serialized)
{
Poco::MemoryInputStream stream(serialized.data(), serialized.size());
return deserialize(stream);
}
Poco::JSON::Object::Ptr Serializer::deserialize(std::istream& stream)
{
Poco::Base64Decoder decoder(stream, Poco::BASE64_URL_ENCODING | Poco::BASE64_NO_PADDING);
Poco::JSON::Parser parser;
try
{
Poco::Dynamic::Var json = parser.parse(decoder);
Poco::JSON::Object::Ptr pObject = json.extract<Poco::JSON::Object::Ptr>();
return pObject;
}
catch (Poco::BadCastException&)
{
throw ParseException("String does not deserialize to a JSON object");
}
catch (Poco::Exception& exc)
{
throw ParseException("Failed to deserialize JWT component", exc.displayText());
}
}
std::vector<std::string> Serializer::split(const std::string& token)
{
Poco::StringTokenizer tokenizer(token, ".");
std::vector<std::string> result(tokenizer.begin(), tokenizer.end());
return result;
}
} } // namespace Poco::JWT

505
vendor/POCO/JWT/src/Signer.cpp vendored Normal file
View File

@ -0,0 +1,505 @@
//
// Signer.cpp
//
// Library: JWT
// Package: JWT
// Module: Signer
//
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/JWT/Signer.h"
#include "Poco/JWT/Serializer.h"
#include "Poco/JWT/JWTException.h"
#include "Poco/HMACEngine.h"
#include "Poco/RefCountedObject.h"
#include "Poco/AutoPtr.h"
#include "Poco/DynamicFactory.h"
#include "Poco/MemoryStream.h"
#include "Poco/Base64Encoder.h"
#include "Poco/Base64Decoder.h"
#include "Poco/Crypto/DigestEngine.h"
#include "Poco/Crypto/RSADigestEngine.h"
#include "Poco/Crypto/ECDSADigestEngine.h"
#include <sstream>
namespace Poco {
namespace JWT {
//
// Algorithm
//
class Algorithm: public Poco::RefCountedObject
/// Abstraction of an algorithm for signing JWTs.
{
public:
typedef Poco::AutoPtr<Algorithm> Ptr;
Algorithm();
/// Creates the Algorithm.
virtual ~Algorithm();
/// Destroys the Algorithm.
virtual Poco::DigestEngine::Digest sign(const Signer& signer, const std::string& header, const std::string& payload) = 0;
/// Signs the header and payload and returns the signature.
virtual bool verify(const Signer& signer, const std::string& header, const std::string& payload, const Poco::DigestEngine::Digest& signature) = 0;
/// Verifies the header and payload against the signature.
///
/// Returns true if the signature is correct, otherwise false.
static const std::string SHA256;
static const std::string SHA384;
static const std::string SHA512;
};
Algorithm::Algorithm()
{
}
Algorithm::~Algorithm()
{
}
const std::string Algorithm::SHA256("SHA256");
const std::string Algorithm::SHA384("SHA384");
const std::string Algorithm::SHA512("SHA512");
class SHA256Engine: public Poco::Crypto::DigestEngine
{
public:
enum
{
BLOCK_SIZE = 64,
DIGEST_SIZE = 32
};
SHA256Engine():
Poco::Crypto::DigestEngine(Algorithm::SHA256)
{
}
};
class SHA384Engine: public Poco::Crypto::DigestEngine
{
public:
enum
{
BLOCK_SIZE = 128,
DIGEST_SIZE = 48
};
SHA384Engine():
Poco::Crypto::DigestEngine(Algorithm::SHA384)
{
}
};
class SHA512Engine: public Poco::Crypto::DigestEngine
{
public:
enum
{
BLOCK_SIZE = 128,
DIGEST_SIZE = 64
};
SHA512Engine():
Poco::Crypto::DigestEngine(Algorithm::SHA512)
{
}
};
template <typename Engine>
class HMACAlgorithm: public Algorithm
{
public:
Poco::DigestEngine::Digest sign(const Signer& signer, const std::string& header, const std::string& payload)
{
if (signer.getHMACKey().empty()) throw SignatureGenerationException("No HMAC key available");
Poco::HMACEngine<Engine> hmac(signer.getHMACKey());
hmac.update(header);
hmac.update('.');
hmac.update(payload);
return hmac.digest();
}
bool verify(const Signer& signer, const std::string& header, const std::string& payload, const Poco::DigestEngine::Digest& signature)
{
return sign(signer, header, payload) == signature;
}
};
typedef HMACAlgorithm<SHA256Engine> HS256;
typedef HMACAlgorithm<SHA384Engine> HS384;
typedef HMACAlgorithm<SHA512Engine> HS512;
class RSAAlgorithm: public Algorithm
{
public:
RSAAlgorithm(const std::string& digestType):
_digestType(digestType)
{
}
Poco::DigestEngine::Digest sign(const Signer& signer, const std::string& header, const std::string& payload)
{
if (!signer.getRSAKey()) throw SignatureGenerationException("No RSA key available");
Poco::Crypto::RSADigestEngine rsa(*signer.getRSAKey(), _digestType);
rsa.update(header);
rsa.update('.');
rsa.update(payload);
return rsa.signature();
}
bool verify(const Signer& signer, const std::string& header, const std::string& payload, const Poco::DigestEngine::Digest& signature)
{
if (!signer.getRSAKey()) throw SignatureVerificationException("No RSA key available");
Poco::Crypto::RSADigestEngine rsa(*signer.getRSAKey(), _digestType);
rsa.update(header);
rsa.update('.');
rsa.update(payload);
return rsa.verify(signature);
}
private:
std::string _digestType;
};
class RS256: public RSAAlgorithm
{
public:
RS256():
RSAAlgorithm(Algorithm::SHA256)
{
}
};
class RS384: public RSAAlgorithm
{
public:
RS384():
RSAAlgorithm(Algorithm::SHA384)
{
}
};
class RS512: public RSAAlgorithm
{
public:
RS512():
RSAAlgorithm(Algorithm::SHA512)
{
}
};
class ECDSAAlgorithm: public Algorithm
{
public:
ECDSAAlgorithm(const std::string& digestType):
_digestType(digestType)
{
}
Poco::DigestEngine::Digest sign(const Signer& signer, const std::string& header, const std::string& payload)
{
if (!signer.getECKey()) throw SignatureGenerationException("No EC key available");
Poco::Crypto::ECDSADigestEngine ecdsa(*signer.getECKey(), _digestType);
ecdsa.update(header);
ecdsa.update('.');
ecdsa.update(payload);
Poco::Crypto::ECDSASignature ecdsaSig(ecdsa.signature());
Poco::DigestEngine::Digest jwtSig(ecdsaSig.rawR());
Poco::DigestEngine::Digest rawS(ecdsaSig.rawS());
jwtSig.insert(jwtSig.end(), rawS.begin(), rawS.end());
return jwtSig;
}
bool verify(const Signer& signer, const std::string& header, const std::string& payload, const Poco::DigestEngine::Digest& signature)
{
if (!signer.getECKey()) throw SignatureVerificationException("No EC key available");
Poco::DigestEngine::Digest rawR(signature.begin(), signature.begin() + signature.size() / 2);
Poco::DigestEngine::Digest rawS(signature.begin() + signature.size() / 2, signature.end());
Poco::Crypto::ECDSASignature ecdsaSig(rawR, rawS);
Poco::DigestEngine::Digest derSig = ecdsaSig.toDER();
Poco::Crypto::ECDSADigestEngine ecdsa(*signer.getECKey(), _digestType);
ecdsa.update(header);
ecdsa.update('.');
ecdsa.update(payload);
return ecdsa.verify(derSig);
}
private:
std::string _digestType;
};
class ES256: public ECDSAAlgorithm
{
public:
ES256():
ECDSAAlgorithm(Algorithm::SHA256)
{
}
};
class ES384: public ECDSAAlgorithm
{
public:
ES384():
ECDSAAlgorithm(Algorithm::SHA384)
{
}
};
class ES512: public ECDSAAlgorithm
{
public:
ES512():
ECDSAAlgorithm(Algorithm::SHA512)
{
}
};
//
// AlgorithmFactory
//
class AlgorithmFactory: public Poco::DynamicFactory<Algorithm>
{
public:
AlgorithmFactory()
{
registerClass<HS256>(Signer::ALGO_HS256);
registerClass<HS384>(Signer::ALGO_HS384);
registerClass<HS512>(Signer::ALGO_HS512);
registerClass<RS256>(Signer::ALGO_RS256);
registerClass<RS384>(Signer::ALGO_RS384);
registerClass<RS512>(Signer::ALGO_RS512);
registerClass<ES256>(Signer::ALGO_ES256);
registerClass<ES384>(Signer::ALGO_ES384);
registerClass<ES512>(Signer::ALGO_ES512);
}
};
//
// Signer
//
const std::string Signer::ALGO_NONE("none");
const std::string Signer::ALGO_HS256("HS256");
const std::string Signer::ALGO_HS384("HS384");
const std::string Signer::ALGO_HS512("HS512");
const std::string Signer::ALGO_RS256("RS256");
const std::string Signer::ALGO_RS384("RS384");
const std::string Signer::ALGO_RS512("RS512");
const std::string Signer::ALGO_ES256("ES256");
const std::string Signer::ALGO_ES384("ES384");
const std::string Signer::ALGO_ES512("ES512");
Signer::Signer()
{
_algorithms.insert(ALGO_HS256);
}
Signer::Signer(const std::string& hmacKey):
_hmacKey(hmacKey)
{
_algorithms.insert(ALGO_HS256);
}
Signer::Signer(const Poco::SharedPtr<Poco::Crypto::RSAKey>& pRSAKey):
_pRSAKey(pRSAKey)
{
_algorithms.insert(ALGO_HS256);
}
Signer::Signer(const Poco::SharedPtr<Poco::Crypto::ECKey>& pECKey):
_pECKey(pECKey)
{
_algorithms.insert(ALGO_HS256);
}
Signer::~Signer()
{
}
Signer& Signer::setAlgorithms(const std::set<std::string>& algorithms)
{
_algorithms = algorithms;
return *this;
}
Signer& Signer::addAlgorithm(const std::string& algorithm)
{
_algorithms.insert(algorithm);
return *this;
}
Signer& Signer::addAllAlgorithms()
{
_algorithms.insert(ALGO_HS256);
_algorithms.insert(ALGO_HS384);
_algorithms.insert(ALGO_HS512);
_algorithms.insert(ALGO_RS256);
_algorithms.insert(ALGO_RS384);
_algorithms.insert(ALGO_RS512);
_algorithms.insert(ALGO_ES256);
_algorithms.insert(ALGO_ES384);
_algorithms.insert(ALGO_ES512);
return *this;
}
Signer& Signer::setHMACKey(const std::string& key)
{
_hmacKey = key;
return *this;
}
Signer& Signer::setRSAKey(const Poco::SharedPtr<Poco::Crypto::RSAKey>& pKey)
{
_pRSAKey = pKey;
return *this;
}
Signer& Signer::setECKey(const Poco::SharedPtr<Poco::Crypto::ECKey>& pKey)
{
_pECKey = pKey;
return *this;
}
std::string Signer::sign(Token& token, const std::string& algorithm) const
{
AlgorithmFactory factory;
if (!factory.isClass(algorithm)) throw UnsupportedAlgorithmException(algorithm);
token.setAlgorithm(algorithm);
std::string header = Serializer::serialize(token.header());
std::string payload = Serializer::serialize(token.payload());
Algorithm::Ptr pAlgorithm = factory.createInstance(algorithm);
Poco::DigestEngine::Digest digest = pAlgorithm->sign(*this, header, payload);
std::string signature = encode(digest);
token.sign(signature);
std::string jwt = header;
jwt += '.';
jwt += payload;
jwt += '.';
jwt += signature;
return jwt;
}
Token Signer::verify(const std::string& jwt) const
{
Token token;
if (tryVerify(jwt, token))
return token;
else
throw SignatureVerificationException();
}
bool Signer::tryVerify(const std::string& jwt, Token& token) const
{
std::vector<std::string> parts = Serializer::split(jwt);
if (parts.size() < 3) throw ParseException("Not a valid JWT", jwt);
token.assign(parts[0], parts[1], parts[2]);
std::string algorithm = token.getAlgorithm();
if (_algorithms.find(algorithm) == _algorithms.end()) throw UnallowedAlgorithmException(algorithm);
AlgorithmFactory factory;
if (!factory.isClass(algorithm)) throw UnsupportedAlgorithmException(algorithm);
Algorithm::Ptr pAlgorithm = factory.createInstance(algorithm);
return pAlgorithm->verify(*this, parts[0], parts[1], decode(parts[2]));
}
std::string Signer::encode(const Poco::DigestEngine::Digest& digest)
{
std::ostringstream stream;
Poco::Base64Encoder encoder(stream, Poco::BASE64_URL_ENCODING | Poco::BASE64_NO_PADDING);
encoder.write(reinterpret_cast<const char*>(&digest[0]), digest.size());
encoder.close();
return stream.str();
}
Poco::DigestEngine::Digest Signer::decode(const std::string& signature)
{
Poco::DigestEngine::Digest digest;
digest.reserve(64);
Poco::MemoryInputStream stream(signature.data(), signature.size());
Poco::Base64Decoder decoder(stream, Poco::BASE64_URL_ENCODING | Poco::BASE64_NO_PADDING);
int ch = decoder.get();
while (ch != -1)
{
digest.push_back(static_cast<unsigned char>(static_cast<unsigned>(ch)));
ch = decoder.get();
}
return digest;
}
} } // namespace Poco::JWT

198
vendor/POCO/JWT/src/Token.cpp vendored Normal file
View File

@ -0,0 +1,198 @@
//
// Token.cpp
//
// Library: JWT
// Package: JWT
// Module: Token
//
// Copyright (c) 2019, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/JWT/Token.h"
#include "Poco/JWT/Serializer.h"
#include "Poco/JWT/JWTException.h"
namespace Poco {
namespace JWT {
const std::string Token::CLAIM_ISSUER("iss");
const std::string Token::CLAIM_SUBJECT("sub");
const std::string Token::CLAIM_AUDIENCE("aud");
const std::string Token::CLAIM_EXPIRATION("exp");
const std::string Token::CLAIM_NOT_BEFORE("nbf");
const std::string Token::CLAIM_ISSUED_AT("iat");
const std::string Token::CLAIM_JWT_ID("jti");
const std::string Token::CLAIM_TYPE("typ");
const std::string Token::CLAIM_ALGORITHM("alg");
const std::string Token::CLAIM_CONTENT_TYPE("cty");
const std::string Token::EMPTY;
Token::Token():
_pHeader(new Poco::JSON::Object),
_pPayload(new Poco::JSON::Object)
{
}
Token::Token(const std::string& token)
{
std::vector<std::string> parts = Serializer::split(token);
if (parts.size() < 3) throw ParseException("Not a valid JWT", token);
_pHeader = Serializer::deserialize(parts[0]);
_pPayload = Serializer::deserialize(parts[1]);
_signature = parts[2];
}
Token::Token(const Token& token):
_pHeader(new Poco::JSON::Object(*token._pHeader)),
_pPayload(new Poco::JSON::Object(*token._pPayload)),
_signature(token._signature)
{
}
Token::Token(Token&& token) noexcept:
_pHeader(std::move(token._pHeader)),
_pPayload(std::move(token._pPayload)),
_signature(std::move(token._signature))
{
}
Token::Token(const std::string& header, const std::string& payload, const std::string& signature)
{
assign(header, payload, signature);
}
Token::~Token()
{
}
Token& Token::operator = (const Token& token)
{
if (&token != this)
{
Poco::JSON::Object::Ptr pHeader = new Poco::JSON::Object(*token._pHeader);
Poco::JSON::Object::Ptr pPayload = new Poco::JSON::Object(*token._pPayload);
std::string signature = token._signature;
std::swap(_pHeader, pHeader);
std::swap(_pPayload, pPayload);
std::swap(_signature, signature);
}
return *this;
}
Token& Token::operator = (Token&& token) noexcept
{
_pHeader = std::move(token._pHeader);
_pPayload = std::move(token._pPayload);
_signature = std::move(token._signature);
return *this;
}
Token& Token::operator = (const std::string& token)
{
std::vector<std::string> parts = Serializer::split(token);
if (parts.size() < 3) throw ParseException("Not a valid JWT", token);
assign(parts[0], parts[1], parts[2]);
return *this;
}
void Token::assign(const std::string& header, const std::string& payload, const std::string& signature)
{
Poco::JSON::Object::Ptr pHeader = Serializer::deserialize(header);
Poco::JSON::Object::Ptr pPayload = Serializer::deserialize(payload);
std::string aSignature = signature;
std::swap(_pHeader, pHeader);
std::swap(_pPayload, pPayload);
std::swap(_signature, aSignature);
}
std::string Token::toString() const
{
std::ostringstream stream;
Serializer::serialize(*_pHeader, stream);
stream << '.';
Serializer::serialize(*_pPayload, stream);
stream << '.';
stream << _signature;
return stream.str();
}
void Token::setAudience(const std::vector<std::string>& audience)
{
Poco::JSON::Array::Ptr pArray = new Poco::JSON::Array;
for (std::vector<std::string>::const_iterator it = audience.begin(); it != audience.end(); ++it)
{
pArray->add(*it);
}
_pPayload->set(CLAIM_AUDIENCE, pArray);
}
std::vector<std::string> Token::getAudience() const
{
std::vector<std::string> result;
if (_pPayload->has(CLAIM_AUDIENCE))
{
if (_pPayload->isArray(CLAIM_AUDIENCE))
{
Poco::JSON::Array::Ptr pArray = _pPayload->getArray(CLAIM_AUDIENCE);
if (pArray)
{
for (unsigned i = 0; i < pArray->size(); i++)
{
result.push_back(pArray->getElement<std::string>(i));
}
}
}
else
{
result.push_back(_pPayload->getValue<std::string>(CLAIM_AUDIENCE));
}
}
return result;
}
void Token::setTimestamp(const std::string& claim, const Poco::Timestamp& ts)
{
double epochSeconds = static_cast<double>(ts.epochMicroseconds())/Poco::Timestamp::resolution();
_pPayload->set(claim, epochSeconds);
}
Poco::Timestamp Token::getTimestamp(const std::string& claim) const
{
double epochSeconds = _pPayload->optValue(claim, 0.0);
Poco::Timestamp::TimeVal tv = static_cast<Poco::Timestamp::TimeVal>(epochSeconds*Poco::Timestamp::resolution());
return Poco::Timestamp(tv);
}
void Token::sign(const std::string& signature)
{
_signature = signature;
}
} } // namespace Poco::JWT