Set fourth file version digit to signify rebuild.
[shibboleth/cpp-xmltooling.git] / xmltooling / XMLToolingConfig.cpp
index be5ec26..6925a23 100644 (file)
@@ -1,18 +1,21 @@
-/*
- * Licensed to UCAID 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
+/**
+ * Licensed to the University Corporation for Advanced Internet
+ * Development, Inc. (UCAID) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * UCAID 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
+ * 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.
+ * 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.
  */
 
 /**
 #include "security/OpenSSLCryptoX509CRL.h"
 #include "security/CredentialResolver.h"
 #include "security/KeyInfoResolver.h"
+#include "security/PathValidator.h"
 #include "signature/KeyInfo.h"
 #include "signature/Signature.h"
 #include "soap/SOAP.h"
+#include "soap/SOAPTransport.h"
 #include "util/NDC.h"
 #include "util/PathResolver.h"
 #include "util/ReplayCache.h"
@@ -50,6 +55,8 @@
 #endif
 
 #include <stdexcept>
+#include <boost/ptr_container/ptr_vector.hpp>
+
 #if defined(XMLTOOLING_LOG4SHIB)
 # include <log4shib/PropertyConfigurator.hh>
 # include <log4shib/OstreamAppender.hh>
@@ -73,6 +80,7 @@ using namespace soap11;
 using namespace xmltooling::logging;
 using namespace xmltooling;
 using namespace xercesc;
+using namespace boost;
 using namespace std;
 
 #ifdef WIN32
@@ -103,14 +111,14 @@ using namespace xmlsignature;
 namespace {
     static XMLToolingInternalConfig g_config;
 #ifndef XMLTOOLING_NO_XMLSEC
-    static vector<Mutex*> g_openssl_locks;
+    static ptr_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();
+            g_openssl_locks[n].lock();
         else
-            g_openssl_locks[n]->unlock();
+            g_openssl_locks[n].unlock();
     }
 
 # ifndef WIN32
@@ -124,7 +132,7 @@ namespace {
     class TXFMOutputLog : public TXFMBase {
            TXFMOutputLog();
     public:
-        TXFMOutputLog(DOMDocument* doc) : TXFMBase(doc), m_log(Category::getInstance(XMLTOOLING_LOGCAT".Signature.Debugger")) {
+        TXFMOutputLog(DOMDocument* doc) : TXFMBase(doc), m_log(Category::getInstance(XMLTOOLING_LOGCAT ".Signature.Debugger")) {
             input = nullptr;
         }
         ~TXFMOutputLog() {
@@ -170,7 +178,7 @@ namespace {
     };
 
     TXFMBase* TXFMOutputLogFactory(DOMDocument* doc) {
-        if (Category::getInstance(XMLTOOLING_LOGCAT".Signature.Debugger").isDebugEnabled())
+        if (Category::getInstance(XMLTOOLING_LOGCAT ".Signature.Debugger").isDebugEnabled())
             return new TXFMOutputLog(doc);
         return nullptr;
     }
@@ -286,7 +294,6 @@ XMLToolingInternalConfig::XMLToolingInternalConfig() :
 
 XMLToolingInternalConfig::~XMLToolingInternalConfig()
 {
-    delete m_lock;
 }
 
 bool XMLToolingInternalConfig::log_config(const char* config)
@@ -344,12 +351,12 @@ bool XMLToolingInternalConfig::log_config(const char* config)
         }
 
 #ifndef XMLTOOLING_NO_XMLSEC
-        Category::getInstance(XMLTOOLING_LOGCAT".Signature.Debugger").setAdditivity(false);
+        Category::getInstance(XMLTOOLING_LOGCAT ".Signature.Debugger").setAdditivity(false);
 #endif
        }
     catch (const ConfigureFailure& e) {
-        string msg = string("failed to configure logging: ") + e.what();
-        Category::getInstance(XMLTOOLING_LOGCAT".Logging").crit(msg);
+        string msg = string("error in file permissions or logging configuration: ") + e.what();
+        Category::getInstance(XMLTOOLING_LOGCAT ".Logging").crit(msg);
 #ifdef WIN32
         LogEvent(nullptr, EVENTLOG_ERROR_TYPE, 2100, nullptr, msg.c_str());
 #endif
@@ -364,11 +371,11 @@ bool XMLToolingInternalConfig::init()
 #ifdef _DEBUG
     xmltooling::NDC ndc("init");
 #endif
-    Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Config");
+    Category& log=Category::getInstance(XMLTOOLING_LOGCAT ".Config");
 
     Lock initLock(m_lock);
 
-    if (m_initCount == LONG_MAX) {
+    if (m_initCount == INT_MAX) {
         log.crit("library initialized too many times");
         return false;
     }
@@ -390,7 +397,9 @@ bool XMLToolingInternalConfig::init()
         if (curlver) {
             log.debug("libcurl %s initialization complete", curlver->version);
             if (!(curlver->features & CURL_VERSION_SSL)) {
-                log.warn("libcurl lacks TLS/SSL support, this will greatly limit functionality");
+                log.crit("libcurl lacks TLS/SSL support, this will greatly limit functionality");
+            } else if (curlver->ssl_version && !strstr(curlver->ssl_version, "OpenSSL")) {
+                log.crit("libcurl lacks OpenSSL-specific options, this will greatly limit functionality");
             }
         }
         else {
@@ -406,28 +415,19 @@ bool XMLToolingInternalConfig::init()
 # ifdef XMLTOOLING_XMLSEC_DEBUGLOGGING
         XSECPlatformUtils::SetReferenceLoggingSink(TXFMOutputLogFactory);
 # endif
-        m_xsecProvider=new XSECProvider();
+        m_xsecProvider = new XSECProvider();
         log.debug("XML-Security %s initialization complete", XSEC_FULLVERSIONDOT);
 #endif
 
-        m_parserPool=new ParserPool();
-        m_validatingPool=new ParserPool(true,true);
-
-        // Load catalogs from path.
-        if (!catalog_path.empty()) {
-            char* catpath=strdup(catalog_path.c_str());
-            char* sep=nullptr;
-            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 : nullptr;
-            }
-            free(catpath);
-        }
+        m_parserPool = new ParserPool();
+        m_validatingPool = new ParserPool(true,true);
+
+        m_pathResolver = new PathResolver();
+        m_urlEncoder = new URLEncoder();
+
+        // Load catalogs from deprecated path setting.
+        if (!catalog_path.empty())
+            m_validatingPool->loadCatalogs(catalog_path.c_str());
 
         // default registrations
         XMLObjectBuilder::registerDefaultBuilder(new UnknownElementBuilder());
@@ -450,18 +450,19 @@ bool XMLToolingInternalConfig::init()
         REGISTER_XMLTOOLING_EXCEPTION_FACTORY(EncryptionException,xmlencryption);
         registerKeyInfoClasses();
         registerEncryptionClasses();
-        registerKeyInfoResolvers();
         registerCredentialResolvers();
+        registerKeyInfoResolvers();
+        registerPathValidators();
         registerTrustEngines();
         registerXMLAlgorithms();
-        registerSOAPTransports();
-        initSOAPTransports();
-        registerStorageServices();
         m_keyInfoResolver = KeyInfoResolverManager.newPlugin(INLINE_KEYINFO_RESOLVER,nullptr);
 #endif
 
-        m_pathResolver = new PathResolver();
-        m_urlEncoder = new URLEncoder();
+#ifndef XMLTOOLING_LITE
+        registerStorageServices();
+#endif
+        registerSOAPTransports();
+        initSOAPTransports();
 
         HTTPResponse::getAllowedSchemes().push_back("https");
         HTTPResponse::getAllowedSchemes().push_back("http");
@@ -501,7 +502,7 @@ void XMLToolingInternalConfig::term()
 
     Lock initLock(m_lock);
     if (m_initCount == 0) {
-        Category::getInstance(XMLTOOLING_LOGCAT".Config").crit("term without corresponding init");
+        Category::getInstance(XMLTOOLING_LOGCAT ".Config").crit("term without corresponding init");
         return;
     }
     else if (--m_initCount > 0) {
@@ -510,7 +511,6 @@ void XMLToolingInternalConfig::term()
 
 #ifndef XMLTOOLING_NO_XMLSEC
     CRYPTO_set_locking_callback(nullptr);
-    for_each(g_openssl_locks.begin(), g_openssl_locks.end(), xmltooling::cleanup<Mutex>());
     g_openssl_locks.clear();
 #endif
 
@@ -519,10 +519,14 @@ void XMLToolingInternalConfig::term()
     XMLToolingException::deregisterFactories();
     AttributeExtensibleXMLObject::deregisterIDAttributes();
 
-#ifndef XMLTOOLING_NO_XMLSEC
-    StorageServiceManager.deregisterFactories();
     termSOAPTransports();
     SOAPTransportManager.deregisterFactories();
+
+#ifndef XMLTOOLING_LITE
+    StorageServiceManager.deregisterFactories();
+#endif
+
+#ifndef XMLTOOLING_NO_XMLSEC
     TrustEngineManager.deregisterFactories();
     CredentialResolverManager.deregisterFactories();
     KeyInfoResolverManager.deregisterFactories();
@@ -566,6 +570,9 @@ void XMLToolingInternalConfig::term()
     delete m_validatingPool;
     m_validatingPool=nullptr;
 
+    for_each(m_namedLocks.begin(), m_namedLocks.end(), cleanup_pair<string,Mutex>());
+    m_namedLocks.clear();
+
 #ifndef XMLTOOLING_NO_XMLSEC
     delete m_xsecProvider;
     m_xsecProvider=nullptr;
@@ -577,7 +584,7 @@ void XMLToolingInternalConfig::term()
 #ifndef XMLTOOLING_NO_XMLSEC
     curl_global_cleanup();
 #endif
-   Category::getInstance(XMLTOOLING_LOGCAT".Config").info("%s library shutdown complete", PACKAGE_STRING);
+   Category::getInstance(XMLTOOLING_LOGCAT ".Config").info("%s library shutdown complete", PACKAGE_STRING);
 }
 
 Lockable* XMLToolingInternalConfig::lock()
@@ -591,12 +598,23 @@ void XMLToolingInternalConfig::unlock()
     m_lock->unlock();
 }
 
+Mutex& XMLToolingInternalConfig::getNamedMutex(const char* name)
+{
+    Locker glock(this);
+    map<string,Mutex*>::const_iterator m = m_namedLocks.find(name);
+    if (m != m_namedLocks.end())
+        return *(m->second);
+    Mutex* newlock = Mutex::create();
+    m_namedLocks[name] = newlock;
+    return *newlock;
+}
+
 bool XMLToolingInternalConfig::load_library(const char* path, void* context)
 {
 #ifdef _DEBUG
     xmltooling::NDC ndc("LoadLibrary");
 #endif
-    Category& log=Category::getInstance(XMLTOOLING_LOGCAT".Config");
+    Category& log=Category::getInstance(XMLTOOLING_LOGCAT ".Config");
     log.info("loading extension: %s", path);
 
     Locker locker(this);
@@ -624,7 +642,7 @@ bool XMLToolingInternalConfig::load_library(const char* path, void* context)
             throw runtime_error(string("detected error in xmltooling_extension_init: ") + resolved);
         SetErrorMode(em);
     }
-    catch(exception&) {
+    catch(std::exception&) {
         if (handle)
             FreeLibrary(handle);
         SetErrorMode(em);
@@ -647,7 +665,7 @@ bool XMLToolingInternalConfig::load_library(const char* path, void* context)
         if (fn(context)!=0)
             throw runtime_error(string("detected error in xmltooling_extension_init in ") + resolved);
     }
-    catch(exception&) {
+    catch(std::exception&) {
         if (handle)
             dlclose(handle);
         throw;
@@ -698,6 +716,9 @@ void XMLToolingInternalConfig::registerXMLAlgorithm(
     )
 {
     m_algorithmMap[type][xmlAlgorithm] = pair<string,unsigned int>((keyAlgorithm ? keyAlgorithm : ""), size);
+    // Authenticated encryption algorithms are also generic encryption algorithms.
+    if (type == ALGTYPE_AUTHNENCRYPT)
+        m_algorithmMap[ALGTYPE_ENCRYPT][xmlAlgorithm] = pair<string,unsigned int>((keyAlgorithm ? keyAlgorithm : ""), size);
 }
 
 bool XMLToolingInternalConfig::isXMLAlgorithmSupported(const XMLCh* xmlAlgorithm, XMLSecurityAlgorithmType type)
@@ -726,8 +747,9 @@ void XMLToolingInternalConfig::registerXMLAlgorithms()
 
     // With ECDSA, XML-Security exports a public macro for OpenSSL's support, and any
     // versions of XML-Security that didn't provide the macro don't handle ECDSA anyway.
+    // However, the SHA-224 variant was left out of the initial XML-Security release.
 
-    // With AES, all supported XML-Security versions export a macro for OpenSSL's support.
+    // With AES and GCM, all supported XML-Security versions export a macro for OpenSSL's support.
 
     // With SHA2, only the very latest XML-Security exports a macro, but all the versions
     // will handle SHA2 *if* OpenSSL does. So we use our own macro to check OpenSSL's
@@ -745,6 +767,10 @@ void XMLToolingInternalConfig::registerXMLAlgorithms()
 #endif
 
     registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIDSA_SHA1, "DSA", 0, ALGTYPE_SIGN);
+#if defined(URI_ID_DSA_SHA256) && defined(XMLTOOLING_OPENSSL_HAVE_SHA2) && !defined(OPENSSL_NO_SHA256)
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIDSA_SHA256, "DSA", 0, ALGTYPE_SIGN);
+#endif
+
     registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIRSA_MD5, "RSA", 0, ALGTYPE_SIGN);
     registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIRSA_SHA1, "RSA", 0, ALGTYPE_SIGN);
 #if defined(XMLTOOLING_OPENSSL_HAVE_SHA2) && !defined(OPENSSL_NO_SHA256)
@@ -758,10 +784,13 @@ void XMLToolingInternalConfig::registerXMLAlgorithms()
 
 #ifdef XSEC_OPENSSL_HAVE_EC
     registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIECDSA_SHA1, "EC", 0, ALGTYPE_SIGN);
-#if defined(XMLTOOLING_OPENSSL_HAVE_SHA2) && !defined(OPENSSL_NO_SHA256)
+# if defined(XMLTOOLING_OPENSSL_HAVE_SHA2) && !defined(OPENSSL_NO_SHA256)
     registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIECDSA_SHA256, "EC", 0, ALGTYPE_SIGN);
+#  ifdef URI_ID_ECDSA_SHA224
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIECDSA_SHA224, "EC", 0, ALGTYPE_SIGN);
+#  endif
 # endif
-#if defined(XMLTOOLING_OPENSSL_HAVE_SHA2) && !defined(OPENSSL_NO_SHA512)
+# if defined(XMLTOOLING_OPENSSL_HAVE_SHA2) && !defined(OPENSSL_NO_SHA512)
     registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIECDSA_SHA384, "EC", 0, ALGTYPE_SIGN);
     registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIECDSA_SHA512, "EC", 0, ALGTYPE_SIGN);
 # endif
@@ -779,6 +808,9 @@ void XMLToolingInternalConfig::registerXMLAlgorithms()
 
     registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIRSA_1_5, "RSA", 0, ALGTYPE_KEYENCRYPT);
     registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIRSA_OAEP_MGFP1, "RSA", 0, ALGTYPE_KEYENCRYPT);
+#ifdef URI_ID_RSA_OAEP
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIRSA_OAEP, "RSA", 0, ALGTYPE_KEYENCRYPT);
+#endif
 
     registerXMLAlgorithm(DSIGConstants::s_unicodeStrURI3DES_CBC, "DESede", 192, ALGTYPE_ENCRYPT);
     registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIKW_3DES, "DESede", 192, ALGTYPE_KEYENCRYPT);
@@ -792,6 +824,18 @@ void XMLToolingInternalConfig::registerXMLAlgorithms()
 
     registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIAES256_CBC, "AES", 256, ALGTYPE_ENCRYPT);
     registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIKW_AES256, "AES", 256, ALGTYPE_KEYENCRYPT);
+
+# ifdef URI_ID_KW_AES128_PAD
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIKW_AES128_PAD, "AES", 128, ALGTYPE_KEYENCRYPT);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIKW_AES192_PAD, "AES", 192, ALGTYPE_KEYENCRYPT);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIKW_AES256_PAD, "AES", 256, ALGTYPE_KEYENCRYPT);
+# endif
+#endif
+
+#ifdef XSEC_OPENSSL_HAVE_GCM
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIAES128_GCM, "AES", 128, ALGTYPE_AUTHNENCRYPT);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIAES192_GCM, "AES", 192, ALGTYPE_AUTHNENCRYPT);
+    registerXMLAlgorithm(DSIGConstants::s_unicodeStrURIAES256_GCM, "AES", 256, ALGTYPE_AUTHNENCRYPT);
 #endif
 }