You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@santuario.apache.org by bl...@apache.org on 2003/08/31 14:45:16 UTC

cvs commit: xml-security/c/src/tools/cipher cipher.cpp

blautenb    2003/08/31 05:45:16

  Added:       c/src/tools/cipher cipher.cpp
  Log:
  New tool for encrypting/decrypting XML
  
  Revision  Changes    Path
  1.1                  xml-security/c/src/tools/cipher/cipher.cpp
  
  Index: cipher.cpp
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "<WebSig>" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 2001, Institute for
   * Data Communications Systems, <http://www.nue.et-inf.uni-siegen.de/>.
   * The development of this software was partly funded by the European 
   * Commission in the <WebSig> project in the ISIS Programme. 
   * For more information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  /*
   * XSEC
   *
   * cipher := Tool to handle basic encryption/decryption of XML documents
   *
   * Author(s): Berin Lautenbach
   *
   * $Id: cipher.cpp,v 1.1 2003/08/31 12:45:16 blautenb Exp $
   *
   */
  
  // XSEC
  
  #include <xsec/utils/XSECPlatformUtils.hpp>
  #include <xsec/framework/XSECProvider.hpp>
  #include <xsec/framework/XSECException.hpp>
  #include <xsec/enc/XSECCryptoException.hpp>
  #include <xsec/enc/OpenSSL/OpenSSLCryptoSymmetricKey.hpp>
  
  // ugly :<
  
  #if defined(_WIN32)
  #	include <xsec/utils/winutils/XSECURIResolverGenericWin32.hpp>
  #else
  #	include <xsec/utils/unixutils/XSECURIResolverGenericUnix.hpp>
  #endif
  
  // General
  
  #include <memory.h>
  #include <string.h>
  #include <iostream>
  #include <stdlib.h>
  
  #if defined(HAVE_UNISTD_H)
  # include <unistd.h>
  # define _MAX_PATH PATH_MAX
  #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/framework/XMLFormatter.hpp>
  #include <xercesc/framework/StdOutFormatTarget.hpp>
  
  XSEC_USING_XERCES(XercesDOMParser);
  XSEC_USING_XERCES(DOMImplementationLS);
  XSEC_USING_XERCES(DOMImplementationRegistry);
  XSEC_USING_XERCES(DOMImplementation);
  XSEC_USING_XERCES(DOMWriter);
  XSEC_USING_XERCES(StdOutFormatTarget);
  XSEC_USING_XERCES(XMLException);
  XSEC_USING_XERCES(XMLPlatformUtils);
  XSEC_USING_XERCES(DOMException);
  XSEC_USING_XERCES(XMLUri);
  XSEC_USING_XERCES(XMLUni);
  XSEC_USING_XERCES(Janitor);
  
  using std::cerr;
  using std::cout;
  using std::endl;
  
  #ifndef XSEC_NO_XALAN
  
  // XALAN
  
  #include <xalanc/XPath/XPathEvaluator.hpp>
  #include <xalanc/XalanTransformer/XalanTransformer.hpp>
  
  XALAN_USING_XALAN(XPathEvaluator)
  XALAN_USING_XALAN(XalanTransformer)
  
  #endif
  
  #if defined (HAVE_OPENSSL)
  // OpenSSL
  
  #	include <xsec/enc/OpenSSL/OpenSSLCryptoKeyHMAC.hpp>
  #	include <openssl/err.h>
  
  #endif
  
  #if defined (HAVE_WINCAPI)
  
  #	include <xsec/enc/WinCAPI/WinCAPICryptoProvider.hpp>
  #	include <xsec/enc/WinCAPI/WinCAPICryptoKeyHMAC.hpp>
  
  #endif
  
  #include <time.h>
  
  #ifdef XSEC_NO_XALAN
  
  std::ostream& operator<< (std::ostream& target, const XMLCh * s)
  {
      char *p = XMLString::transcode(s);
      target << p;
      delete [] 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-element/-de\n";
  	cerr << "         Decrypt the first encrypted element found\n";
  	cerr << "     --key/-k [key string]\n";
  	cerr << "         Use the key provided in [key string] to encrypt/decrypt\n\n";
  
  	cerr << "     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					* keyStr = NULL;
  	bool					doDecryptElement = false;
  
  #if defined(_WIN32) && defined (HAVE_WINCAPI)
  	HCRYPTPROV				win32DSSCSP = 0;		// Crypto Providers
  	HCRYPTPROV				win32RSACSP = 0;		
  #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++;
  			doDecryptElement = true;
  		}
  
  		if (stricmp(argv[paramCount], "--key") == 0 || stricmp(argv[paramCount], "-k") == 0) {
  
  			// Have set a key string
  			paramCount++;
  			keyStr = argv[paramCount];
  			paramCount++;
  		}
  
  		else {
  			printUsage();
  			return 2;
  		}
  	}
  
  	if (paramCount >= argc) {
  		printUsage();
  		return 2;
  	}
  
  	filename = argv[paramCount];
  
  	// Create and set up the parser
  
  	XercesDOMParser * parser = new XercesDOMParser;
  	Janitor<XercesDOMParser> j_parser(parser);
  
  	parser->setDoNamespaces(true);
  	parser->setCreateEntityReferenceNodes(true);
  
  	// Now parse out file
  
  	bool errorsOccured = false;
  	int errorCount = 0;
      try
      {
      	parser->parse(filename);
          errorCount = parser->getErrorCount();
          if (errorCount > 0)
              errorsOccured = true;
      }
  
      catch (const XMLException& e)
      {
          cerr << "An error occured during parsing\n   Message: "
               << e.getMessage() << endl;
          errorsOccured = true;
      }
  
  
      catch (const DOMException& e)
      {
         cerr << "A DOM error occured 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
  
  	*/
  	
  	DOMNode *doc;		// The document that we parsed
  
  	doc = parser->getDocument();
  	DOMDocument *theDOM = parser->getDocument();
  
  	XSECProvider prov;
  
  	// Find the EncryptedData node
  	DOMNode * n = findXENCNode(doc, "EncryptedData");
  
  	XENCCipher * cipher = prov.newCipher(theDOM);
  
  	try {
  
  		OpenSSLCryptoSymmetricKey * k;
  		if (keyStr != NULL) {
  			k = new OpenSSLCryptoSymmetricKey(XSECCryptoSymmetricKey::KEY_3DES_CBC_192);
  			k->setKey((unsigned char *) keyStr, strlen(keyStr));
  			cipher->setKey(k);
  		}
  		cipher->decryptElement(static_cast<DOMElement *>(n));
  
  		// Output the result
  
  		XMLCh core[] = {
  			XERCES_CPP_NAMESPACE :: chLatin_C,
  			XERCES_CPP_NAMESPACE :: chLatin_o,
  			XERCES_CPP_NAMESPACE :: chLatin_r,
  			XERCES_CPP_NAMESPACE :: chLatin_e,
  			XERCES_CPP_NAMESPACE :: chNull
  		};
  
  		DOMImplementation *impl = DOMImplementationRegistry::getDOMImplementation(core);
  		DOMWriter         *theSerializer = ((DOMImplementationLS*)impl)->createDOMWriter();
  
  		theSerializer->setEncoding(MAKE_UNICODE_STRING("UTF-8"));
  		if (theSerializer->canSetFeature(XMLUni::fgDOMWRTFormatPrettyPrint, false))
  			theSerializer->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, false);
  
  
  		XMLFormatTarget *formatTarget = new StdOutFormatTarget();
  
  		theSerializer->writeNode(formatTarget, *doc);
  		
  		cout << endl;
  
  		delete theSerializer;
  		delete formatTarget;
  
  
  	}
  
  	catch (XSECException &e) {
  		char * msg = XMLString::transcode(e.getMsg());
  		cerr << "An error occured during signature verification\n   Message: "
  		<< msg << endl;
  		delete [] msg;
  		errorsOccured = true;
  		return 2;
  	}
  	catch (XSECCryptoException &e) {
  		cerr << "An error occured during signature verification\n   Message: "
  		<< e.getMsg() << endl;
  		errorsOccured = true;
  
  #if defined (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;
  	}
  
  	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();
  #ifndef XSEC_NO_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();
  #ifndef XSEC_NO_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;
  }