blob: ba2e2a9f0a272a711cf2ef3231440c9add5cf965 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/*
* XSEC
*
* cipher := Tool to handle basic encryption/decryption of XML documents
*
* Author(s): Berin Lautenbach
*
* $Id$
*
*/
// XSEC
#include <xsec/utils/XSECPlatformUtils.hpp>
#include <xsec/framework/XSECProvider.hpp>
#include <xsec/framework/XSECException.hpp>
#include <xsec/enc/XSECCryptoException.hpp>
#include <xsec/enc/XSECCryptoUtils.hpp>
#include <xsec/enc/OpenSSL/OpenSSLCryptoSymmetricKey.hpp>
#include <xsec/utils/XSECBinTXFMInputStream.hpp>
#include <xsec/xenc/XENCEncryptedData.hpp>
#include <xsec/xenc/XENCEncryptedKey.hpp>
#include "XencInteropResolver.hpp"
#include "../../utils/XSECDOMUtils.hpp"
// General
#include <memory.h>
#include <string.h>
#include <iostream>
#include <fstream>
#include <stdlib.h>
#if defined(HAVE_UNISTD_H)
# include <unistd.h>
#else
# if defined(HAVE_DIRECT_H)
# include <direct.h>
# endif
#endif
#if defined (_DEBUG) && defined (_MSC_VER)
#include <crtdbg.h>
#endif
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/util/XMLException.hpp>
#include <xercesc/util/XMLUri.hpp>
#include <xercesc/util/XMLUni.hpp>
#include <xercesc/util/Janitor.hpp>
#include <xercesc/util/BinFileInputStream.hpp>
#include <xercesc/framework/XMLFormatter.hpp>
#include <xercesc/framework/StdOutFormatTarget.hpp>
#include <xercesc/framework/LocalFileFormatTarget.hpp>
XERCES_CPP_NAMESPACE_USE
using std::cerr;
using std::cout;
using std::endl;
using std::ostream;
#ifdef XSEC_HAVE_XALAN
// XALAN
#include <xalanc/XPath/XPathEvaluator.hpp>
#include <xalanc/XalanTransformer/XalanTransformer.hpp>
XALAN_USING_XALAN(XPathEvaluator)
XALAN_USING_XALAN(XalanTransformer)
#endif
#if defined (XSEC_HAVE_OPENSSL)
// OpenSSL
# include <xsec/enc/OpenSSL/OpenSSLCryptoKeyHMAC.hpp>
# include <xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.hpp>
# include <openssl/err.h>
# include <openssl/bio.h>
# include <openssl/evp.h>
# include <openssl/pem.h>
#endif
#if defined (XSEC_HAVE_WINCAPI)
# include <xsec/enc/WinCAPI/WinCAPICryptoProvider.hpp>
# include <xsec/enc/WinCAPI/WinCAPICryptoSymmetricKey.hpp>
# include <xsec/enc/WinCAPI/WinCAPICryptoKeyHMAC.hpp>
#endif
#if defined (XSEC_HAVE_NSS)
# include <xsec/enc/NSS/NSSCryptoProvider.hpp>
# include <xsec/enc/NSS/NSSCryptoSymmetricKey.hpp>
# include <xsec/enc/NSS/NSSCryptoKeyHMAC.hpp>
#endif
#include <time.h>
#ifndef XSEC_HAVE_XALAN
std::ostream& operator<< (std::ostream& target, const XMLCh * s)
{
char *p = XMLString::transcode(s);
target << p;
XSEC_RELEASE_XMLCH(p);
return target;
}
#endif
// ----------------------------------------------------------------------------
// Checksig
// ----------------------------------------------------------------------------
void printUsage(void) {
cerr << "\nUsage: cipher [options] <input file name>\n\n";
cerr << " Where options are :\n\n";
cerr << " --decrypt/-d\n";
cerr << " Operate in decrypt mode (default) - outputs the decrypted octet stream\n";
cerr << " Reads in the input file as an XML file, searches for an EncryptedData node\n";
cerr << " and decrypts the content\n";
cerr << " --decrypt-element/-de\n";
cerr << " Operate in decrypt and XML mode.\n";
cerr << " This will output the original XML document with the first encrypted\n";
cerr << " element decrypted.\n";
cerr << " --encrypt-file/-ef\n";
cerr << " Encrypt the contents of the input file as raw data and create an\n";
cerr << " XML Encrypted Data outpu\n";
cerr << " --encrypt-xml/-ex\n";
cerr << " Parse the input file and encrypt the doc element down, storing the\n";
cerr << " output as a XML Encrypted Data\n";
cerr << " --key/-k [kek] <KEY_TYPE> [options]\n";
cerr << " Set the key to use.\n";
cerr << " If the first parameter is \"kek\", the key arguments will be used\n";
cerr << " as a Key EncryptionKey\n";
cerr << " KEY_TYPE defines what the key is. Can be one of :\n";
cerr << " X509, RSA, AES128, AES192, AES256, AES128-GCM, AES192-GCM, AES256-GCM or 3DES\n";
cerr << " options are :\n";
cerr << " <filename> - for X509 PEM files (must be an RSA KEK certificate\n";
cerr << " <filename> <password> - for RSA private key files (MUST be a KEK)\n";
cerr << " <key-string> - For a string to use as the key for AES or DES keys\n";
#ifdef XSEC_XKMS_ENABLED
cerr << " --xkms/-x\n";
cerr << " The key that follows on the command line is to be interpreted as\n";
cerr << " an XKMS RSAKeyPair encryption key\n";
#endif
cerr << " --interop/-i\n";
cerr << " Use the interop resolver for Baltimore interop examples\n";
cerr << " --out-file/-o\n";
cerr << " Output the result to the indicated file (rather than stdout)\n";
#ifdef XSEC_HAVE_WINCAPI
cerr << " --wincapi/-w\n";
cerr << " Force use of Windows Crypto API\n";
#endif
#ifdef XSEC_HAVE_NSS
cerr << " --nss/-n\n";
cerr << " Force use of NSS Crypto API\n";
#endif
cerr << "\n Exits with codes :\n";
cerr << " 0 = Decrypt/Encrypt OK\n";
cerr << " 1 = Decrypt/Encrypt failed\n";
cerr << " 2 = Processing error\n";
}
int evaluate(int argc, char ** argv) {
char * filename = NULL;
char * outfile = NULL;
unsigned char * keyStr = NULL;
bool doDecrypt = true;
bool errorsOccured = false;
bool doDecryptElement = false;
bool useInteropResolver = false;
bool encryptFileAsData = false;
bool parseXMLInput = true;
bool doXMLOutput = false;
#ifdef XSEC_XKMS_ENABLED
bool isXKMSKey = false;
#endif
XSECCryptoKey * kek = NULL;
XSECCryptoKey * key = NULL;
int keyLen = 0;
const XMLCh* kekAlg = NULL;
const XMLCh* keyAlg = NULL;
DOMDocument *doc;
unsigned char keyBuf[24];
XMLFormatTarget *formatTarget ;
#if defined(_WIN32) && defined (XSEC_HAVE_WINCAPI)
HCRYPTPROV win32DSSCSP = 0; // Crypto Providers
HCRYPTPROV win32RSACSP = 0;
CryptAcquireContext(&win32DSSCSP, NULL, NULL, PROV_DSS, CRYPT_VERIFYCONTEXT);
CryptAcquireContext(&win32RSACSP, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
#endif
if (argc < 2) {
printUsage();
return 2;
}
// Run through parameters
int paramCount = 1;
while (paramCount < argc - 1) {
if (_stricmp(argv[paramCount], "--decrypt-element") == 0 || _stricmp(argv[paramCount], "-de") == 0) {
paramCount++;
doDecrypt = true;
doDecryptElement = true;
doXMLOutput = true;
parseXMLInput = true;
}
else if (_stricmp(argv[paramCount], "--interop") == 0 || _stricmp(argv[paramCount], "-i") == 0) {
// Use the interop key resolver
useInteropResolver = true;
paramCount++;
}
else if (_stricmp(argv[paramCount], "--encrypt-file") == 0 || _stricmp(argv[paramCount], "-ef") == 0) {
// Use this file as the input
doDecrypt = false;
encryptFileAsData = true;
doXMLOutput = true;
parseXMLInput = false;
paramCount++;
}
else if (_stricmp(argv[paramCount], "--encrypt-xml") == 0 || _stricmp(argv[paramCount], "-ex") == 0) {
// Us this file as an XML input file
doDecrypt = false;
encryptFileAsData = false;
doXMLOutput = true;
parseXMLInput = true;
paramCount++;
}
else if (_stricmp(argv[paramCount], "--out-file") == 0 || _stricmp(argv[paramCount], "-o") == 0) {
if (paramCount +2 >= argc) {
printUsage();
return 1;
}
paramCount++;
outfile = argv[paramCount];
paramCount++;
}
#ifdef XSEC_XKMS_ENABLED
else if (_stricmp(argv[paramCount], "--xkms") == 0 || _stricmp(argv[paramCount], "-x") == 0) {
paramCount++;
isXKMSKey = true;
}
#endif
#ifdef XSEC_HAVE_WINCAPI
else if (_stricmp(argv[paramCount], "--wincapi") == 0 || _stricmp(argv[paramCount], "-w") == 0) {
// Use the interop key resolver
WinCAPICryptoProvider * cp = new WinCAPICryptoProvider();
XSECPlatformUtils::SetCryptoProvider(cp);
paramCount++;
}
#endif
#ifdef XSEC_HAVE_NSS
else if (_stricmp(argv[paramCount], "--nss") == 0 || _stricmp(argv[paramCount], "-n") == 0) {
// NSS Crypto Provider
NSSCryptoProvider * cp = new NSSCryptoProvider();
XSECPlatformUtils::SetCryptoProvider(cp);
paramCount++;
}
#endif
else if (_stricmp(argv[paramCount], "--key") == 0 || _stricmp(argv[paramCount], "-k") == 0) {
// Have a key!
paramCount++;
bool isKEK = false;
XSECCryptoSymmetricKey::SymmetricKeyType loadKeyAs =
XSECCryptoSymmetricKey::KEY_NONE;
if (_stricmp(argv[paramCount], "kek") == 0) {
isKEK = true;
paramCount++;
if (paramCount >= argc) {
printUsage();
return 2;
}
}
if (_stricmp(argv[paramCount], "3DES") == 0 ||
_stricmp(argv[paramCount], "AES128") == 0 ||
_stricmp(argv[paramCount], "AES192") == 0 ||
_stricmp(argv[paramCount], "AES256") == 0 ||
_stricmp(argv[paramCount], "AES128-GCM") == 0 ||
_stricmp(argv[paramCount], "AES192-GCM") == 0 ||
_stricmp(argv[paramCount], "AES256-GCM") == 0) {
if (paramCount +2 >= argc) {
printUsage();
return 2;
}
switch(argv[paramCount][4]) {
case '\0' :
keyLen = 24;
loadKeyAs = XSECCryptoSymmetricKey::KEY_3DES_192;
keyAlg = DSIGConstants::s_unicodeStrURI3DES_CBC;
break;
case '2' :
keyLen = 16;
loadKeyAs = XSECCryptoSymmetricKey::KEY_AES_128;
if (isKEK) {
kekAlg = DSIGConstants::s_unicodeStrURIKW_AES128;
}
else if (strlen(argv[paramCount]) == 6) {
keyAlg = DSIGConstants::s_unicodeStrURIAES128_CBC;
}
else {
keyAlg = DSIGConstants::s_unicodeStrURIAES128_GCM;
}
break;
case '9' :
keyLen = 24;
loadKeyAs = XSECCryptoSymmetricKey::KEY_AES_192;
if (isKEK) {
kekAlg = DSIGConstants::s_unicodeStrURIKW_AES192;
}
else if (strlen(argv[paramCount]) == 6) {
keyAlg = DSIGConstants::s_unicodeStrURIAES192_CBC;
}
else {
keyAlg = DSIGConstants::s_unicodeStrURIAES192_GCM;
}
break;
case '5' :
keyLen = 32;
loadKeyAs = XSECCryptoSymmetricKey::KEY_AES_256;
if (isKEK) {
kekAlg = DSIGConstants::s_unicodeStrURIKW_AES256;
}
else if (strlen(argv[paramCount]) == 6) {
keyAlg = DSIGConstants::s_unicodeStrURIAES256_CBC;
}
else {
keyAlg = DSIGConstants::s_unicodeStrURIAES256_GCM;
}
break;
}
paramCount++;
unsigned char keyStr[64];
if (strlen(argv[paramCount]) > 64) {
cerr << "Key string too long\n";
return 2;
}
XSECCryptoSymmetricKey * sk =
XSECPlatformUtils::g_cryptoProvider->keySymmetric(loadKeyAs);
#ifdef XSEC_XKMS_ENABLED
if (isXKMSKey) {
unsigned char kbuf[XSEC_MAX_HASH_SIZE];
CalculateXKMSKEK((unsigned char *) argv[paramCount], (int) strlen(argv[paramCount]), kbuf, XSEC_MAX_HASH_SIZE);
sk->setKey(kbuf, keyLen);
}
else {
#endif
memset(keyStr, 0, 64);
strcpy((char *) keyStr, argv[paramCount]);
sk->setKey(keyStr, keyLen);
#ifdef XSEC_XKMS_ENABLED
}
#endif
paramCount++;
if (isKEK)
kek = sk;
else
key = sk;
}
#ifdef XSEC_HAVE_OPENSSL
else if (_stricmp(argv[paramCount], "RSA") == 0) {
// RSA private key file
if (paramCount + 3 >= argc) {
printUsage();
return 2;
}
if (!isKEK) {
cerr << "RSA private keys may only be KEKs\n";
return 2;
}
BIO * bioKey;
if ((bioKey = BIO_new(BIO_s_file())) == NULL) {
cerr << "Error opening private key file\n\n";
return 1;
}
if (BIO_read_filename(bioKey, argv[paramCount + 1]) <= 0) {
cerr << "Error opening private key file\n\n";
return 1;
}
EVP_PKEY * pkey;
pkey = PEM_read_bio_PrivateKey(bioKey,NULL,NULL,argv[paramCount + 2]);
if (pkey == NULL) {
cerr << "Error loading private key\n\n";
return 1;
}
kek = new OpenSSLCryptoKeyRSA(pkey);
kekAlg = DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1;
EVP_PKEY_free(pkey);
BIO_free(bioKey);
paramCount += 3;
}
else if (_stricmp(argv[paramCount], "X509") == 0) {
// X509 cert used to load an encrypting key
if (paramCount + 2 >= argc) {
printUsage();
exit (1);
}
if (!isKEK) {
cerr << "X509 private keys may only be KEKs\n";
return 2;
}
// Load the encrypting key
// For now just read a particular file
BIO * bioX509;
if ((bioX509 = BIO_new(BIO_s_file())) == NULL) {
cerr << "Error opening file\n\n";
exit (1);
}
if (BIO_read_filename(bioX509, argv[paramCount + 1]) <= 0) {
cerr << "Error opening X509 Certificate " << argv[paramCount + 1] << "\n\n";
exit (1);
}
X509 * x
;
x = PEM_read_bio_X509_AUX(bioX509,NULL,NULL,NULL);
if (x == NULL) {
BIO * bio_err;
if ((bio_err=BIO_new(BIO_s_file())) != NULL)
BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
cerr << "Error loading certificate key\n\n";
ERR_print_errors(bio_err);
BIO_free(bio_err);
exit (1);
}
// Now load the key
EVP_PKEY *pkey;
pkey = X509_get_pubkey(x);
#ifdef XSEC_OPENSSL_HAVE_EVP_PKEY_ID
if (pkey == NULL || EVP_PKEY_id(pkey) != EVP_PKEY_RSA)
#else
if (pkey == NULL || pkey->type != EVP_PKEY_RSA)
#endif
{
cerr << "Error extracting RSA key from certificate" << endl;
}
kek = new OpenSSLCryptoKeyRSA(pkey);
kekAlg = DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1;
// Clean up
EVP_PKEY_free (pkey);
X509_free(x);
BIO_free(bioX509);
paramCount += 2;
} /* argv[1] = "--x509cert" */
#endif /* XSEC_HAVE_OPENSSL */
else {
printUsage();
return 2;
}
}
else {
cerr << "Unknown option: " << argv[paramCount] << endl;
printUsage();
return 2;
}
}
if (paramCount >= argc) {
printUsage();
return 2;
}
if (outfile != NULL) {
formatTarget = new LocalFileFormatTarget(outfile);
}
else {
formatTarget = new StdOutFormatTarget();
}
filename = argv[paramCount];
if (parseXMLInput) {
XercesDOMParser * parser = new XercesDOMParser;
Janitor<XercesDOMParser> j_parser(parser);
parser->setDoNamespaces(true);
parser->setCreateEntityReferenceNodes(true);
// Now parse out file
XMLSize_t errorCount = 0;
try
{
parser->parse(filename);
errorCount = parser->getErrorCount();
if (errorCount > 0)
errorsOccured = true;
}
catch (const XMLException& e)
{
cerr << "An error occurred during parsing\n Message: "
<< e.getMessage() << endl;
errorsOccured = true;
}
catch (const DOMException& e)
{
cerr << "A DOM error occurred during parsing\n DOMException code: "
<< e.code << endl;
errorsOccured = true;
}
if (errorsOccured) {
cout << "Errors during parse" << endl;
return (2);
}
/*
Now that we have the parsed file, get the DOM document and start looking at it
*/
doc = parser->adoptDocument();
}
else {
// Create an empty document
XMLCh tempStr[100];
XMLString::transcode("Core", tempStr, 99);
DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(tempStr);
doc = impl->createDocument(
0, // root element namespace URI.
MAKE_UNICODE_STRING("ADoc"), // root element name
NULL);// DOMDocumentType()); // document type object (DTD).
}
XSECProvider prov;
XENCCipher * cipher = prov.newCipher(doc);
if (kek != NULL)
cipher->setKEK(kek);
if (key != NULL)
cipher->setKey(key);
try {
if (doDecrypt) {
if (useInteropResolver == true) {
// Map out base path of the file
#ifdef XSEC_HAVE_GETCWD_DYN
char *path = getcwd(NULL, 0);
char *baseURI = (char*)malloc(strlen(path) + 8 + 1 + strlen(filename) + 1);
#else
char path[PATH_MAX];
char baseURI[(PATH_MAX * 2) + 10];
getcwd(path, PATH_MAX);
#endif
strcpy(baseURI, "file:///");
// Ugly and nasty but quick
if (filename[0] != '\\' && filename[0] != '/' && filename[1] != ':') {
strcat(baseURI, path);
strcat(baseURI, "/");
} else if (path[1] == ':') {
path[2] = '\0';
strcat(baseURI, path);
}
strcat(baseURI, filename);
// Find any ':' and "\" characters
int lastSlash = 0;
for (unsigned int i = 8; i < strlen(baseURI); ++i) {
if (baseURI[i] == '\\') {
lastSlash = i;
baseURI[i] = '/';
}
else if (baseURI[i] == '/')
lastSlash = i;
}
// The last "\\" must prefix the filename
baseURI[lastSlash + 1] = '\0';
XMLCh * uriT = XMLString::transcode(baseURI);
#ifdef XSEC_HAVE_GETCWD_DYN
free(path);
free(baseURI);
#endif
XencInteropResolver ires(doc, &(uriT[8]));
XSEC_RELEASE_XMLCH(uriT);
cipher->setKeyInfoResolver(&ires);
}
// Find the EncryptedData node
DOMNode * n = findXENCNode(doc, "EncryptedData");
if (doDecryptElement) {
while (n != NULL) {
// decrypt
cipher->decryptElement(static_cast<DOMElement *>(n));
// Find the next EncryptedData node
n = findXENCNode(doc, "EncryptedData");
}
}
else {
XSECBinTXFMInputStream * bis = cipher->decryptToBinInputStream(static_cast<DOMElement *>(n));
Janitor<XSECBinTXFMInputStream> j_bis(bis);
XMLByte buf[1024];
XMLSize_t read = bis->readBytes(buf, 1023);
while (read > 0) {
formatTarget->writeChars(buf, read, NULL);
read = bis->readBytes(buf, 1023);
}
}
}
else {
XENCEncryptedData *xenc = NULL;
// Encrypting
if (kek != NULL && key == NULL) {
XSECPlatformUtils::g_cryptoProvider->getRandom(keyBuf, 24);
XSECCryptoSymmetricKey * k =
XSECPlatformUtils::g_cryptoProvider->keySymmetric(XSECCryptoSymmetricKey::KEY_3DES_192);
k->setKey(keyBuf, 24);
cipher->setKey(k);
keyAlg = DSIGConstants::s_unicodeStrURI3DES_CBC;
keyStr = keyBuf;
keyLen = 24;
}
if (encryptFileAsData) {
// Create a BinInputStream
BinFileInputStream * is = new BinFileInputStream(filename, XMLPlatformUtils::fgMemoryManager);
xenc = cipher->encryptBinInputStream(is, keyAlg);
// Replace the document element
DOMElement * elt = doc->getDocumentElement();
doc->replaceChild(xenc->getElement(), elt);
elt->release();
}
else {
// Document encryption
cipher->encryptElement(doc->getDocumentElement(), keyAlg);
}
// Do we encrypt a created key?
if (kek != NULL && xenc != NULL) {
XENCEncryptedKey *xkey = cipher->encryptKey(keyStr, keyLen, kekAlg);
// Add to the EncryptedData
xenc->appendEncryptedKey(xkey);
}
}
if (doXMLOutput) {
// Output the result
XMLCh core[] = {
XERCES_CPP_NAMESPACE_QUALIFIER chLatin_C,
XERCES_CPP_NAMESPACE_QUALIFIER chLatin_o,
XERCES_CPP_NAMESPACE_QUALIFIER chLatin_r,
XERCES_CPP_NAMESPACE_QUALIFIER chLatin_e,
XERCES_CPP_NAMESPACE_QUALIFIER chNull
};
DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(core);
DOMLSSerializer *theSerializer = ((DOMImplementationLS*)impl)->createLSSerializer();
Janitor<DOMLSSerializer> j_theSerializer(theSerializer);
// Get the config so we can set up pretty printing
DOMConfiguration *dc = theSerializer->getDomConfig();
dc->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, false);
// Now create an output object to format to UTF-8
DOMLSOutput *theOutput = ((DOMImplementationLS*)impl)->createLSOutput();
Janitor<DOMLSOutput> j_theOutput(theOutput);
theOutput->setEncoding(MAKE_UNICODE_STRING("UTF-8"));
theOutput->setByteStream(formatTarget);
theSerializer->write(doc, theOutput);
cout << endl;
}
}
catch (const XSECException &e) {
char * msg = XMLString::transcode(e.getMsg());
cerr << "An error occurred during encryption/decryption operation\n Message: "
<< msg << endl;
XSEC_RELEASE_XMLCH(msg);
errorsOccured = true;
if (formatTarget != NULL)
delete formatTarget;
doc->release();
return 2;
}
catch (const XSECCryptoException &e) {
cerr << "An error occurred during encryption/decryption operation\n Message: "
<< e.getMsg() << endl;
errorsOccured = true;
if (formatTarget != NULL)
delete formatTarget;
doc->release();
#ifdef XSEC_HAVE_OPENSSL
ERR_load_crypto_strings();
BIO * bio_err;
if ((bio_err=BIO_new(BIO_s_file())) != NULL)
BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
ERR_print_errors(bio_err);
#endif
return 2;
}
if (formatTarget != NULL)
delete formatTarget;
doc->release();
return 0;
}
int main(int argc, char **argv) {
int retResult;
#if defined (_DEBUG) && defined (_MSC_VER)
// Do some memory debugging under Visual C++
_CrtMemState s1, s2, s3;
// At this point we are about to start really using XSEC, so
// Take a "before" checkpoing
_CrtMemCheckpoint( &s1 );
#endif
// Initialise the XML system
try {
XMLPlatformUtils::Initialize();
#ifdef XSEC_HAVE_XALAN
XPathEvaluator::initialize();
XalanTransformer::initialize();
#endif
XSECPlatformUtils::Initialise();
}
catch (const XMLException &e) {
cerr << "Error during initialisation of Xerces" << endl;
cerr << "Error Message = : "
<< e.getMessage() << endl;
}
retResult = evaluate(argc, argv);
XSECPlatformUtils::Terminate();
#ifdef XSEC_HAVE_XALAN
XalanTransformer::terminate();
XPathEvaluator::terminate();
#endif
XMLPlatformUtils::Terminate();
#if defined (_DEBUG) && defined (_MSC_VER)
_CrtMemCheckpoint( &s2 );
if ( _CrtMemDifference( &s3, &s1, &s2 ) && (
s3.lCounts[0] > 0 ||
s3.lCounts[1] > 1 ||
// s3.lCounts[2] > 2 || We don't worry about C Runtime
s3.lCounts[3] > 0 ||
s3.lCounts[4] > 0)) {
// Note that there is generally 1 Normal and 1 CRT block
// still taken. 1 is from Xalan and 1 from stdio
// Send all reports to STDOUT
_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );
_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );
// Dumpy memory stats
_CrtMemDumpAllObjectsSince( &s3 );
_CrtMemDumpStatistics( &s3 );
}
// Now turn off memory leak checking and end as there are some
// Globals that are allocated that get seen as leaks (Xalan?)
int dbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
dbgFlag &= ~(_CRTDBG_LEAK_CHECK_DF);
_CrtSetDbgFlag( dbgFlag );
#endif
return retResult;
}