[cpp-xmltooling] 02/02: CPPXT-139 - DataSealer needs to catch both Santuario exception types
Scott Cantor
cantor.2 at osu.edu
Tue Oct 30 20:12:17 EDT 2018
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch master
in repository cpp-xmltooling.
View the commit online:
http://git.shibboleth.net/view/?p=cpp-xmltooling.git;a=commit;h=e0dc5188ee0698c686c90fb4ea0717d473d87456
commit e0dc5188ee0698c686c90fb4ea0717d473d87456
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Oct 30 20:10:45 2018 -0400
CPPXT-139 - DataSealer needs to catch both Santuario exception types
https://issues.shibboleth.net/jira/browse/CPPXT-139
---
xmltooling/security/impl/DataSealer.cpp | 274 +++++++++++++++++---------------
1 file changed, 145 insertions(+), 129 deletions(-)
diff --git a/xmltooling/security/impl/DataSealer.cpp b/xmltooling/security/impl/DataSealer.cpp
index f6f36ea..c7ec7f9 100644
--- a/xmltooling/security/impl/DataSealer.cpp
+++ b/xmltooling/security/impl/DataSealer.cpp
@@ -31,6 +31,7 @@
#include <sstream>
#include <xercesc/util/Base64.hpp>
#include <xercesc/util/XMLDateTime.hpp>
+#include <xsec/enc/XSECCryptoException.hpp>
#include <xsec/framework/XSECAlgorithmHandler.hpp>
#include <xsec/framework/XSECAlgorithmMapper.hpp>
#include <xsec/framework/XSECEnv.hpp>
@@ -46,6 +47,7 @@ using xercesc::Base64;
using xercesc::DOMDocument;
using xercesc::Janitor;
using xercesc::XMLDateTime;
+using xercesc::XMLException;
using boost::scoped_ptr;
using namespace std;
@@ -81,35 +83,35 @@ DataSealer::~DataSealer()
string DataSealer::wrap(const char* s, time_t exp) const
{
- Locker locker(m_strategy.get());
+ Locker locker(m_strategy.get());
- m_log.debug("wrapping data with default key");
+ m_log.debug("wrapping data with default key");
// Get default key to use.
pair<string,const XSECCryptoSymmetricKey*> defaultKey = m_strategy->getDefaultKey();
- const XMLCh* algorithm = nullptr;
- switch (defaultKey.second->getSymmetricKeyType()) {
- case XSECCryptoSymmetricKey::KEY_AES_128:
- algorithm = DSIGConstants::s_unicodeStrURIAES128_GCM;
- break;
+ const XMLCh* algorithm = nullptr;
+ switch (defaultKey.second->getSymmetricKeyType()) {
+ case XSECCryptoSymmetricKey::KEY_AES_128:
+ algorithm = DSIGConstants::s_unicodeStrURIAES128_GCM;
+ break;
- case XSECCryptoSymmetricKey::KEY_AES_192:
- algorithm = DSIGConstants::s_unicodeStrURIAES192_GCM;
- break;
+ case XSECCryptoSymmetricKey::KEY_AES_192:
+ algorithm = DSIGConstants::s_unicodeStrURIAES192_GCM;
+ break;
- case XSECCryptoSymmetricKey::KEY_AES_256:
- algorithm = DSIGConstants::s_unicodeStrURIAES256_GCM;
- break;
+ case XSECCryptoSymmetricKey::KEY_AES_256:
+ algorithm = DSIGConstants::s_unicodeStrURIAES256_GCM;
+ break;
- default:
- throw XMLSecurityException("Unknown key type.");
- }
+ default:
+ throw XMLSecurityException("Unknown key type.");
+ }
- const XSECAlgorithmHandler* handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(algorithm);
- if (!handler) {
- throw XMLSecurityException("Unable to obtain algorithm handler.");
- }
+ const XSECAlgorithmHandler* handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(algorithm);
+ if (!handler) {
+ throw XMLSecurityException("Unable to obtain algorithm handler.");
+ }
#ifndef HAVE_GMTIME_R
struct tm* ptime = gmtime(&exp);
@@ -120,154 +122,168 @@ string DataSealer::wrap(const char* s, time_t exp) const
char timebuf[32];
strftime(timebuf, 32, "%Y-%m-%dT%H:%M:%SZ", ptime);
- m_log.debug("using key (%s), data will expire on %s", defaultKey.first.c_str(), timebuf);
+ m_log.debug("using key (%s), data will expire on %s", defaultKey.first.c_str(), timebuf);
- // The data format of the plaintext packet is:
- // PLAINTEXT := KEYLABEL + ':' + ISOEXPTIME + DATA
- // The plaintext is zipped, encrypted, base64'd, and prefixed with the
- // KEYLABEL and a colon on the outside, as a key hint.
+ // The data format of the plaintext packet is:
+ // PLAINTEXT := KEYLABEL + ':' + ISOEXPTIME + DATA
+ // The plaintext is zipped, encrypted, base64'd, and prefixed with the
+ // KEYLABEL and a colon on the outside, as a key hint.
// Construct the plaintext packet.
- string sb(defaultKey.first);
- sb = sb + ':' + timebuf + s;
+ string sb(defaultKey.first);
+ sb = sb + ':' + timebuf + s;
- m_log.debug("deflating data");
+ m_log.debug("deflating data");
// zip the plaintext packet
unsigned int len;
char* deflated = XMLHelper::deflate(const_cast<char*>(sb.c_str()), sb.length(), &len);
if (!deflated || !len)
throw IOException("Failed to deflate data.");
- auto_arrayptr<char> arrayjan(deflated);
+ auto_arrayptr<char> arrayjan(deflated);
// Finally we encrypt the data. We have to hack this a bit to reuse the xmlsec routines.
- m_log.debug("encrypting data");
+ m_log.debug("encrypting data");
- DOMDocument* dummydoc = XMLToolingConfig::getConfig().getParser().newDocument();
- Janitor<DOMDocument> docjan(dummydoc);
- scoped_ptr<XSECEnv> env(new XSECEnv(dummydoc));
+ DOMDocument* dummydoc = XMLToolingConfig::getConfig().getParser().newDocument();
+ Janitor<DOMDocument> docjan(dummydoc);
+ scoped_ptr<XSECEnv> env(new XSECEnv(dummydoc));
TXFMChar* ct = new TXFMChar(dummydoc);
ct->setInput(deflated, len);
TXFMChain tx(ct);
- safeBuffer ciphertext;
- try {
- scoped_ptr<XENCEncryptionMethod> method(XENCEncryptionMethod::create(env.get(), algorithm));
- if (!handler->encryptToSafeBuffer(&tx, method.get(), defaultKey.second, dummydoc, ciphertext)) {
- throw XMLSecurityException("Data encryption failed.");
- }
- }
- catch (XSECException& ex) {
- auto_ptr_char msg(ex.getMsg());
- throw XMLSecurityException(msg.get());
- }
+ safeBuffer ciphertext;
+ try {
+ scoped_ptr<XENCEncryptionMethod> method(XENCEncryptionMethod::create(env.get(), algorithm));
+ if (!handler->encryptToSafeBuffer(&tx, method.get(), defaultKey.second, dummydoc, ciphertext)) {
+ throw XMLSecurityException("Data encryption failed.");
+ }
+ }
+ catch (const XSECException& ex) {
+ auto_ptr_char msg(ex.getMsg());
+ throw XMLSecurityException(msg.get());
+ }
+ catch (const XSECCryptoException& ex) {
+ auto_ptr_char msg(ex.getMsg());
+ throw XMLSecurityException(msg.get());
+ }
- defaultKey.first.append(":");
- defaultKey.first.append(ciphertext.rawCharBuffer(), ciphertext.sbRawBufferSize());
+ defaultKey.first.append(":");
+ defaultKey.first.append(ciphertext.rawCharBuffer(), ciphertext.sbRawBufferSize());
- m_log.debug("final data size: %lu", defaultKey.first.length());
+ m_log.debug("final data size: %lu", defaultKey.first.length());
- return defaultKey.first;
+ return defaultKey.first;
}
string DataSealer::unwrap(const char* s) const
{
- Locker locker(m_strategy.get());
-
- // The data format of the plaintext packet is:
- // PLAINTEXT := KEYLABEL + ':' + ISOEXPTIME + DATA
- // The plaintext is zipped, encrypted, base64'd, and prefixed with the
- // KEYLABEL and a colon on the outside, as a key hint.
-
- // First extract the key label up to the first colon.
- pair<string, const XSECCryptoSymmetricKey*> requiredKey = make_pair<string, const XSECCryptoSymmetricKey*>(string(), nullptr);
- const char* delim = strchr(s ? s : "", ':');
- if (delim && delim > s) {
- requiredKey.first.append(s, delim - s);
- requiredKey.second = m_strategy->getKey(requiredKey.first.c_str());
- }
- if (!requiredKey.second)
- throw IOException("Required decryption key ($1) not available.", params(1, requiredKey.first.c_str()));
-
- m_log.debug("decrypting data with key (%s)", requiredKey.first.c_str());
-
- const XMLCh* algorithm = nullptr;
- switch (requiredKey.second->getSymmetricKeyType()) {
- case XSECCryptoSymmetricKey::KEY_AES_128:
- algorithm = DSIGConstants::s_unicodeStrURIAES128_GCM;
- break;
-
- case XSECCryptoSymmetricKey::KEY_AES_192:
- algorithm = DSIGConstants::s_unicodeStrURIAES192_GCM;
- break;
-
- case XSECCryptoSymmetricKey::KEY_AES_256:
- algorithm = DSIGConstants::s_unicodeStrURIAES256_GCM;
- break;
-
- default:
- throw XMLSecurityException("Unknown key type.");
- }
-
- const XSECAlgorithmHandler* handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(algorithm);
- if (!handler) {
- throw XMLSecurityException("Unable to obtain algorithm handler.");
- }
-
- DOMDocument* dummydoc = XMLToolingConfig::getConfig().getParser().newDocument();
- Janitor<DOMDocument> docjan(dummydoc);
- scoped_ptr<XSECEnv> env(new XSECEnv(dummydoc));
-
- TXFMChar* ct = new TXFMChar(dummydoc);
- ct->setInput(++delim);
- TXFMChain tx(ct);
- TXFMBase64* b64 = new TXFMBase64(dummydoc, true); // decodes
- tx.appendTxfm(b64);
-
- unsigned int len = 0;
- safeBuffer plaintext;
- try {
- scoped_ptr<XENCEncryptionMethod> method(XENCEncryptionMethod::create(env.get(), algorithm));
- len = handler->decryptToSafeBuffer(&tx, method.get(), requiredKey.second, dummydoc, plaintext);
- }
- catch (XSECException& ex) {
- auto_ptr_char msg(ex.getMsg());
- throw XMLSecurityException(msg.get());
- }
-
- if (len == 0)
- throw XMLSecurityException("No decrypted data available.");
+ Locker locker(m_strategy.get());
+
+ // The data format of the plaintext packet is:
+ // PLAINTEXT := KEYLABEL + ':' + ISOEXPTIME + DATA
+ // The plaintext is zipped, encrypted, base64'd, and prefixed with the
+ // KEYLABEL and a colon on the outside, as a key hint.
+
+ // First extract the key label up to the first colon.
+ pair<string, const XSECCryptoSymmetricKey*> requiredKey = make_pair<string, const XSECCryptoSymmetricKey*>(string(), nullptr);
+ const char* delim = strchr(s ? s : "", ':');
+ if (delim && delim > s) {
+ requiredKey.first.append(s, delim - s);
+ requiredKey.second = m_strategy->getKey(requiredKey.first.c_str());
+ }
+ if (!requiredKey.second)
+ throw IOException("Required decryption key ($1) not available.", params(1, requiredKey.first.c_str()));
+
+ m_log.debug("decrypting data with key (%s)", requiredKey.first.c_str());
+
+ const XMLCh* algorithm = nullptr;
+ switch (requiredKey.second->getSymmetricKeyType()) {
+ case XSECCryptoSymmetricKey::KEY_AES_128:
+ algorithm = DSIGConstants::s_unicodeStrURIAES128_GCM;
+ break;
+
+ case XSECCryptoSymmetricKey::KEY_AES_192:
+ algorithm = DSIGConstants::s_unicodeStrURIAES192_GCM;
+ break;
+
+ case XSECCryptoSymmetricKey::KEY_AES_256:
+ algorithm = DSIGConstants::s_unicodeStrURIAES256_GCM;
+ break;
+
+ default:
+ throw XMLSecurityException("Unknown key type.");
+ }
+
+ const XSECAlgorithmHandler* handler = XSECPlatformUtils::g_algorithmMapper->mapURIToHandler(algorithm);
+ if (!handler) {
+ throw XMLSecurityException("Unable to obtain algorithm handler.");
+ }
+
+ DOMDocument* dummydoc = XMLToolingConfig::getConfig().getParser().newDocument();
+ Janitor<DOMDocument> docjan(dummydoc);
+ scoped_ptr<XSECEnv> env(new XSECEnv(dummydoc));
+
+ TXFMChar* ct = new TXFMChar(dummydoc);
+ ct->setInput(++delim);
+ TXFMChain tx(ct);
+ TXFMBase64* b64 = new TXFMBase64(dummydoc, true); // decodes
+ tx.appendTxfm(b64);
+
+ unsigned int len = 0;
+ safeBuffer plaintext;
+ try {
+ scoped_ptr<XENCEncryptionMethod> method(XENCEncryptionMethod::create(env.get(), algorithm));
+ len = handler->decryptToSafeBuffer(&tx, method.get(), requiredKey.second, dummydoc, plaintext);
+ }
+ catch (const XSECException& ex) {
+ auto_ptr_char msg(ex.getMsg());
+ throw XMLSecurityException(msg.get());
+ }
+ catch (const XSECCryptoException& ex) {
+ auto_ptr_char msg(ex.getMsg());
+ throw XMLSecurityException(msg.get());
+ }
+
+ if (len == 0)
+ throw XMLSecurityException("No decrypted data available.");
// Now we have to inflate it.
- m_log.debug("inflating data");
+ m_log.debug("inflating data");
- stringstream out;
+ stringstream out;
if (XMLHelper::inflate(const_cast<char*>(plaintext.rawCharBuffer()), len, out) == 0) {
throw IOException("Unable to inflate wrapped data.");
}
string decrypted = out.str();
- // Pull off the key label to verify it.
- size_t i = decrypted.find(':');
- if (i == string::npos)
- throw IOException("Unable to verify key used to decrypt data.");
- string keyLabel = decrypted.substr(0, i);
- if (keyLabel != requiredKey.first) {
- m_log.warn("key mismatch, outside (%s), inside (%s)", requiredKey.first.c_str(), keyLabel.c_str());
- throw IOException("Embedded key label does not match key used to decrypt data.");
- }
+ // Pull off the key label to verify it.
+ size_t i = decrypted.find(':');
+ if (i == string::npos)
+ throw IOException("Unable to verify key used to decrypt data.");
+ string keyLabel = decrypted.substr(0, i);
+ if (keyLabel != requiredKey.first) {
+ m_log.warn("key mismatch, outside (%s), inside (%s)", requiredKey.first.c_str(), keyLabel.c_str());
+ throw IOException("Embedded key label does not match key used to decrypt data.");
+ }
string dstr = decrypted.substr(++i, 20);
auto_ptr_XMLCh expstr(dstr.c_str());
- XMLDateTime exp(expstr.get());
- exp.parseDateTime();
- if (exp.getEpoch() < time(nullptr) - XMLToolingConfig::getConfig().clock_skew_secs) {
- m_log.debug("decrypted data expired at %s", dstr.c_str());
- throw IOException("Decrypted data has expired.");
+ try {
+ XMLDateTime exp(expstr.get());
+ exp.parseDateTime();
+ if (exp.getEpoch() < time(nullptr) - XMLToolingConfig::getConfig().clock_skew_secs) {
+ m_log.debug("decrypted data expired at %s", dstr.c_str());
+ throw IOException("Decrypted data has expired.");
+ }
+ }
+ catch (const XMLException& ex) {
+ auto_ptr_char msg(ex.getMessage());
+ throw IOException(msg.get());
}
return decrypted.substr(i + 20);
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list