Multi-line svn commit, see body.
[shibboleth/cpp-xmltooling.git] / xmltooling / XMLToolingConfig.cpp
index 6cd8826..476f8f1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2006 Internet2
+ *  Copyright 2001-2007 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * Library configuration 
  */
 
-#define XMLTOOLING_DECLARE_VALIDATORS
-
 #include "internal.h"
 #include "exceptions.h"
+#include "logging.h"
 #include "XMLToolingConfig.h"
+#include "encryption/Encryption.h"
+#include "encryption/Encrypter.h"
+#include "io/HTTPRequest.h"
+#include "io/HTTPResponse.h"
 #include "impl/UnknownElement.h"
-#include "signature/KeyInfo.h"
+#include "security/TrustEngine.h"
+#include "security/OpenSSLCryptoX509CRL.h"
+#include "security/CredentialResolver.h"
+#include "security/KeyInfoResolver.h"
 #include "signature/Signature.h"
+#include "soap/SOAP.h"
+#include "soap/SOAPTransport.h"
 #include "util/NDC.h"
+#include "util/ReplayCache.h"
+#include "util/StorageService.h"
+#include "util/TemplateEngine.h"
+#include "util/URLEncoder.h"
 #include "util/XMLConstants.h"
-#include "validation/Validator.h"
+#include "validation/ValidatorSuite.h"
 
 #ifdef HAVE_DLFCN_H
 # include <dlfcn.h>
 #endif
 
-#include <log4cpp/Category.hh>
-#include <log4cpp/PropertyConfigurator.hh>
-#include <log4cpp/OstreamAppender.hh>
+#include <stdexcept>
+#if defined(XMLTOOLING_LOG4SHIB)
+# include <log4shib/PropertyConfigurator.hh>
+# include <log4shib/OstreamAppender.hh>
+#elif defined(XMLTOOLING_LOG4CPP)
+# include <log4cpp/PropertyConfigurator.hh>
+# include <log4cpp/OstreamAppender.hh>
+#endif
 #include <xercesc/util/PlatformUtils.hpp>
 #ifndef XMLTOOLING_NO_XMLSEC
-    #include <xsec/framework/XSECProvider.hpp>
+# include <curl/curl.h>
+# include <openssl/err.h>
+# include <xsec/framework/XSECProvider.hpp>
 #endif
 
-#include <stdexcept>
-
+using namespace soap11;
+using namespace xmlencryption;
 using namespace xmlsignature;
+using namespace xmltooling::logging;
 using namespace xmltooling;
-using namespace log4cpp;
 using namespace std;
 
-#define REGISTER_ELEMENT(namespaceURI,cname) \
-    q=QName(namespaceURI,cname::LOCAL_NAME); \
-    XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
-    Validator::registerValidator(q,new cname##SchemaValidator())
-    
-#define REGISTER_TYPE(namespaceURI,cname) \
-    q=QName(namespaceURI,cname::TYPE_NAME); \
-    XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
-    Validator::registerValidator(q,new cname##SchemaValidator())
-
+DECL_XMLTOOLING_EXCEPTION_FACTORY(XMLParserException,xmltooling);
+DECL_XMLTOOLING_EXCEPTION_FACTORY(XMLObjectException,xmltooling);
+DECL_XMLTOOLING_EXCEPTION_FACTORY(MarshallingException,xmltooling);
+DECL_XMLTOOLING_EXCEPTION_FACTORY(UnmarshallingException,xmltooling);
+DECL_XMLTOOLING_EXCEPTION_FACTORY(UnknownElementException,xmltooling);
+DECL_XMLTOOLING_EXCEPTION_FACTORY(UnknownAttributeException,xmltooling);
+DECL_XMLTOOLING_EXCEPTION_FACTORY(UnknownExtensionException,xmltooling);
+DECL_XMLTOOLING_EXCEPTION_FACTORY(ValidationException,xmltooling);
+DECL_XMLTOOLING_EXCEPTION_FACTORY(IOException,xmltooling);
 
-DECL_EXCEPTION_FACTORY(XMLParserException);
-DECL_EXCEPTION_FACTORY(XMLObjectException);
-DECL_EXCEPTION_FACTORY(MarshallingException);
-DECL_EXCEPTION_FACTORY(UnmarshallingException);
-DECL_EXCEPTION_FACTORY(UnknownElementException);
-DECL_EXCEPTION_FACTORY(UnknownAttributeException);
-DECL_EXCEPTION_FACTORY(ValidationException);
-DECL_EXCEPTION_FACTORY(SignatureException);
+#ifndef XMLTOOLING_NO_XMLSEC
+    DECL_XMLTOOLING_EXCEPTION_FACTORY(XMLSecurityException,xmltooling);
+    DECL_XMLTOOLING_EXCEPTION_FACTORY(SignatureException,xmlsignature);
+    DECL_XMLTOOLING_EXCEPTION_FACTORY(EncryptionException,xmlencryption);
+#endif
 
 namespace xmltooling {
-   XMLToolingInternalConfig g_config;
+    static XMLToolingInternalConfig g_config;
+#ifndef XMLTOOLING_NO_XMLSEC
+    static vector<Mutex*> g_openssl_locks;
+
+    extern "C" void openssl_locking_callback(int mode,int n,const char *file,int line)
+    {
+        if (mode & CRYPTO_LOCK)
+            g_openssl_locks[n]->lock();
+        else
+            g_openssl_locks[n]->unlock();
+    }
+    
+# ifndef WIN32
+    extern "C" unsigned long openssl_thread_id(void)
+    {
+        return (unsigned long)(pthread_self());
+    }
+# endif
+#endif
 }
 
 XMLToolingConfig& XMLToolingConfig::getConfig()
@@ -144,6 +177,26 @@ bool XMLToolingInternalConfig::log_config(const char* config)
     return true;
 }
 
+#ifndef XMLTOOLING_LITE
+void XMLToolingConfig::setReplayCache(ReplayCache* replayCache)
+{
+    delete m_replayCache;
+    m_replayCache = replayCache;
+}
+#endif
+
+void XMLToolingConfig::setTemplateEngine(TemplateEngine* templateEngine)
+{
+    delete m_templateEngine;
+    m_templateEngine = templateEngine;
+}
+
+void XMLToolingConfig::setURLEncoder(URLEncoder* urlEncoder)
+{
+    delete m_urlEncoder;
+    m_urlEncoder = urlEncoder;
+}
+
 bool XMLToolingInternalConfig::init()
 {
 #ifdef _DEBUG
@@ -153,7 +206,15 @@ bool XMLToolingInternalConfig::init()
     try {
         log.debug("library initialization started");
 
-        xercesc::XMLPlatformUtils::Initialize();
+#ifndef XMLTOOLING_NO_XMLSEC
+        if (curl_global_init(CURL_GLOBAL_ALL)) {
+            log.fatal("failed to initialize libcurl, OpenSSL, or Winsock");
+            return false;
+        }
+        log.debug("libcurl %s initialization complete", LIBCURL_VERSION);
+#endif
+
+        XMLPlatformUtils::Initialize();
         log.debug("Xerces initialization complete");
 
 #ifndef XMLTOOLING_NO_XMLSEC
@@ -163,62 +224,118 @@ bool XMLToolingInternalConfig::init()
 #endif
 
         m_parserPool=new ParserPool();
-        m_lock=xercesc::XMLPlatformUtils::makeMutex();
+        m_validatingPool=new ParserPool(true,true);
+        m_lock=XMLPlatformUtils::makeMutex();
+        
+        // Load catalogs from path.
+        if (!catalog_path.empty()) {
+            char* catpath=strdup(catalog_path.c_str());
+            char* sep=NULL;
+            char* start=catpath;
+            while (start && *start) {
+                sep=strchr(start,PATH_SEPARATOR_CHAR);
+                if (sep)
+                    *sep=0;
+                auto_ptr_XMLCh temp(start);
+                m_validatingPool->loadCatalog(temp.get());
+                start = sep ? sep + 1 : NULL;
+            }
+            free(catpath);
+        }
 
         // default registrations
         XMLObjectBuilder::registerDefaultBuilder(new UnknownElementBuilder());
-        
-        QName q;
-        REGISTER_ELEMENT(XMLConstants::XMLSIG_NS,KeyInfo);
-        REGISTER_ELEMENT(XMLConstants::XMLSIG_NS,KeyName);
-        REGISTER_ELEMENT(XMLConstants::XMLSIG_NS,KeyValue);
-        REGISTER_ELEMENT(XMLConstants::XMLSIG_NS,MgmtData);
-        REGISTER_ELEMENT(XMLConstants::XMLSIG_NS,DSAKeyValue);
-        REGISTER_ELEMENT(XMLConstants::XMLSIG_NS,RSAKeyValue);
-        REGISTER_ELEMENT(XMLConstants::XMLSIG_NS,Exponent);
-        REGISTER_ELEMENT(XMLConstants::XMLSIG_NS,Modulus);
-        REGISTER_ELEMENT(XMLConstants::XMLSIG_NS,P);
-        REGISTER_ELEMENT(XMLConstants::XMLSIG_NS,Q);
-        REGISTER_ELEMENT(XMLConstants::XMLSIG_NS,G);
-        REGISTER_ELEMENT(XMLConstants::XMLSIG_NS,Y);
-        REGISTER_ELEMENT(XMLConstants::XMLSIG_NS,J);
-        REGISTER_ELEMENT(XMLConstants::XMLSIG_NS,Seed);
-        REGISTER_ELEMENT(XMLConstants::XMLSIG_NS,PgenCounter);
-        REGISTER_ELEMENT(XMLConstants::XMLSIG_NS,XPath);
-        REGISTER_ELEMENT(XMLConstants::XMLSIG_NS,Transform);
-        REGISTER_ELEMENT(XMLConstants::XMLSIG_NS,Transforms);
-        REGISTER_TYPE(XMLConstants::XMLSIG_NS,KeyInfo);
-        REGISTER_TYPE(XMLConstants::XMLSIG_NS,KeyValue);
-        REGISTER_TYPE(XMLConstants::XMLSIG_NS,DSAKeyValue);
-        REGISTER_TYPE(XMLConstants::XMLSIG_NS,RSAKeyValue);
-        REGISTER_TYPE(XMLConstants::XMLSIG_NS,Transform);
-        REGISTER_TYPE(XMLConstants::XMLSIG_NS,Transforms);
 
+        registerKeyInfoClasses();
+        registerEncryptionClasses();
+        registerSOAPClasses();
+
+        REGISTER_XMLTOOLING_EXCEPTION_FACTORY(XMLParserException,xmltooling);
+        REGISTER_XMLTOOLING_EXCEPTION_FACTORY(XMLObjectException,xmltooling);
+        REGISTER_XMLTOOLING_EXCEPTION_FACTORY(MarshallingException,xmltooling);
+        REGISTER_XMLTOOLING_EXCEPTION_FACTORY(UnmarshallingException,xmltooling);
+        REGISTER_XMLTOOLING_EXCEPTION_FACTORY(UnknownElementException,xmltooling);
+        REGISTER_XMLTOOLING_EXCEPTION_FACTORY(UnknownAttributeException,xmltooling);
+        REGISTER_XMLTOOLING_EXCEPTION_FACTORY(ValidationException,xmltooling);
+        REGISTER_XMLTOOLING_EXCEPTION_FACTORY(IOException,xmltooling);
+        
 #ifndef XMLTOOLING_NO_XMLSEC
-        XMLObjectBuilder::registerBuilder(QName(XMLConstants::XMLSIG_NS,Signature::LOCAL_NAME),new SignatureBuilder());
+        XMLObjectBuilder::registerBuilder(QName(xmlconstants::XMLSIG_NS,Signature::LOCAL_NAME),new SignatureBuilder());
+        REGISTER_XMLTOOLING_EXCEPTION_FACTORY(XMLSecurityException,xmltooling);
+        REGISTER_XMLTOOLING_EXCEPTION_FACTORY(SignatureException,xmlsignature);
+        REGISTER_XMLTOOLING_EXCEPTION_FACTORY(EncryptionException,xmlencryption);
+        registerKeyInfoResolvers();
+        registerCredentialResolvers();
+        registerTrustEngines();
+        registerXMLAlgorithms();
+        registerSOAPTransports();
+        initSOAPTransports();
+        registerStorageServices();
+        m_keyInfoResolver = KeyInfoResolverManager.newPlugin(INLINE_KEYINFO_RESOLVER,NULL);
 #endif
 
-        REGISTER_EXCEPTION_FACTORY(XMLParserException);
-        REGISTER_EXCEPTION_FACTORY(XMLObjectException);
-        REGISTER_EXCEPTION_FACTORY(MarshallingException);
-        REGISTER_EXCEPTION_FACTORY(UnmarshallingException);
-        REGISTER_EXCEPTION_FACTORY(UnknownElementException);
-        REGISTER_EXCEPTION_FACTORY(UnknownAttributeException);
-        REGISTER_EXCEPTION_FACTORY(ValidationException);
-        REGISTER_EXCEPTION_FACTORY(SignatureException);
+        m_urlEncoder = new URLEncoder();
+        
+        // Register xml:id as an ID attribute.        
+        static const XMLCh xmlid[] = UNICODE_LITERAL_2(i,d);
+        AttributeExtensibleXMLObject::registerIDAttribute(QName(xmlconstants::XML_NS, xmlid)); 
     }
     catch (const xercesc::XMLException&) {
         log.fatal("caught exception while initializing Xerces");
+#ifndef XMLTOOLING_NO_XMLSEC
+        curl_global_cleanup();
+#endif
         return false;
     }
 
+#ifndef XMLTOOLING_NO_XMLSEC
+    // Set up OpenSSL locking.
+    for (int i=0; i<CRYPTO_num_locks(); i++)
+        g_openssl_locks.push_back(Mutex::create());
+    CRYPTO_set_locking_callback(openssl_locking_callback);
+# ifndef WIN32
+    CRYPTO_set_id_callback(openssl_thread_id);
+# endif
+#endif
+
     log.info("library initialization complete");
     return true;
 }
 
 void XMLToolingInternalConfig::term()
 {
+#ifndef XMLTOOLING_NO_XMLSEC
+    CRYPTO_set_locking_callback(NULL);
+    for_each(g_openssl_locks.begin(), g_openssl_locks.end(), xmltooling::cleanup<Mutex>());
+    g_openssl_locks.clear();
+#endif
+
+    SchemaValidators.destroyValidators();
     XMLObjectBuilder::destroyBuilders();
+    XMLToolingException::deregisterFactories();
+    AttributeExtensibleXMLObject::deregisterIDAttributes();
+
+#ifndef XMLTOOLING_NO_XMLSEC
+    StorageServiceManager.deregisterFactories();
+    termSOAPTransports();
+    SOAPTransportManager.deregisterFactories();
+    TrustEngineManager.deregisterFactories();
+    CredentialResolverManager.deregisterFactories();
+    KeyInfoResolverManager.deregisterFactories();
+    m_algorithmMap.clear();
+
+    delete m_keyInfoResolver;
+    m_keyInfoResolver = NULL;
+
+    delete m_replayCache;
+    m_replayCache = NULL;
+#endif
+
+    delete m_templateEngine;
+    m_templateEngine = NULL;
+
+    delete m_urlEncoder;
+    m_urlEncoder = NULL;
 
     for (vector<void*>::reverse_iterator i=m_libhandles.rbegin(); i!=m_libhandles.rend(); i++) {
 #if defined(WIN32)
@@ -239,6 +356,8 @@ void XMLToolingInternalConfig::term()
     
     delete m_parserPool;
     m_parserPool=NULL;
+    delete m_validatingPool;
+    m_validatingPool=NULL;
 
 #ifndef XMLTOOLING_NO_XMLSEC
     delete m_xsecProvider;
@@ -246,20 +365,23 @@ void XMLToolingInternalConfig::term()
     XSECPlatformUtils::Terminate();
 #endif
 
-    xercesc::XMLPlatformUtils::closeMutex(m_lock);
+    XMLPlatformUtils::closeMutex(m_lock);
     m_lock=NULL;
-    xercesc::XMLPlatformUtils::Terminate();
+    XMLPlatformUtils::Terminate();
 
- #ifdef _DEBUG
+#ifndef XMLTOOLING_NO_XMLSEC
+    curl_global_cleanup();
+#endif   
+#ifdef _DEBUG
     xmltooling::NDC ndc("term");
 #endif
    Category::getInstance(XMLTOOLING_LOGCAT".XMLToolingConfig").info("library shutdown complete");
 }
 
-ILockable& XMLToolingInternalConfig::lock()
+Lockable* XMLToolingInternalConfig::lock()
 {
     xercesc::XMLPlatformUtils::lockMutex(m_lock);
-    return *this;
+    return this;
 }
 
 void XMLToolingInternalConfig::unlock()
@@ -342,3 +464,59 @@ bool XMLToolingInternalConfig::load_library(const char* path, void* context)
     log.info("loaded extension: %s", path);
     return true;
 }
+
+#ifndef XMLTOOLING_NO_XMLSEC
+void xmltooling::log_openssl()
+{
+    const char* file;
+    const char* data;
+    int flags,line;
+
+    unsigned long code=ERR_get_error_line_data(&file,&line,&data,&flags);
+    while (code) {
+        Category& log=Category::getInstance("OpenSSL");
+        log.errorStream() << "error code: " << code << " in " << file << ", line " << line << CategoryStream::ENDLINE;
+        if (data && (flags & ERR_TXT_STRING))
+            log.errorStream() << "error data: " << data << CategoryStream::ENDLINE;
+        code=ERR_get_error_line_data(&file,&line,&data,&flags);
+    }
+}
+
+XSECCryptoX509CRL* XMLToolingInternalConfig::X509CRL() const
+{
+    return new OpenSSLCryptoX509CRL();
+}
+
+void XMLToolingInternalConfig::registerXMLAlgorithms()
+{
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIRSA_MD5, "RSA", 0);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIRSA_SHA1, "RSA", 0);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIRSA_SHA224, "RSA", 0);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIRSA_SHA256, "RSA", 0);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIRSA_SHA384, "RSA", 0);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIRSA_SHA512, "RSA", 0);
+
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIRSA_1_5, "RSA", 0);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1, "RSA", 0);
+
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIDSA_SHA1, "DSA", 0);
+
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIHMAC_SHA1, "HMAC", 0);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIHMAC_SHA224, "HMAC", 0);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIHMAC_SHA256, "HMAC", 0);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIHMAC_SHA384, "HMAC", 0);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIHMAC_SHA512, "HMAC", 0);
+
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURI3DES_CBC, "DESede", 192);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIKW_3DES, "DESede", 192);
+
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIAES128_CBC, "AES", 128);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIKW_AES128, "AES", 128);
+
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIAES192_CBC, "AES", 192);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIKW_AES192, "AES", 192);
+
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIAES256_CBC, "AES", 256);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIKW_AES256, "AES", 256);
+}
+#endif