Refactor XmlsecAdaptor class 60/52560/4
authorKyungwook Tak <k.tak@samsung.com>
Tue, 24 Nov 2015 08:01:16 +0000 (17:01 +0900)
committerKyungwook Tak <k.tak@samsung.com>
Wed, 25 Nov 2015 01:28:25 +0000 (10:28 +0900)
Change-Id: Icd2b43ad4e48629b62f478abd949c6105359d9aa
Signed-off-by: Kyungwook Tak <k.tak@samsung.com>
vcore/vcore/SignatureValidator.cpp
vcore/vcore/ValidatorCommon.h [deleted file]
vcore/vcore/XmlsecAdapter.cpp
vcore/vcore/XmlsecAdapter.h

index 5dc2f07..ec3a1f2 100644 (file)
@@ -205,6 +205,9 @@ VCerr SignatureValidator::Impl::parseSignature(void)
                SignatureReader xml;
                xml.initialize(m_data, SIGNATURE_SCHEMA_PATH);
                xml.read(m_data);
+       } catch (ParserSchemaException::CertificateLoaderError &e) {
+               LogError("Certificate loader error: " << e.DumpToString());
+               return E_SIG_INVALID_CERT;
        } catch (...) {
                LogError("Failed to parse signature file by signature reader.");
                return E_SIG_INVALID_FORMAT;
@@ -276,11 +279,10 @@ VCerr SignatureValidator::Impl::preStep(void)
                        m_disregarded = true;
                }
        } else {
-               LogDebug("signaturefile name = " << m_data.getSignatureFileName());
                if (storeIdSet.contains(TIZEN_DEVELOPER)) {
-                       LogError("distributor has author level siganture! "
-                               "Signature will be disregarded.");
-                       return E_SIG_INVALID_FORMAT;
+                       LogError("distributor should not have developer set: "
+                               << m_data.getSignatureFileName());
+                       return E_SIG_INVALID_CHAIN;
                }
 
                if (m_data.getSignatureNumber() == 1 && !storeIdSet.isContainsVis()) {
@@ -333,10 +335,7 @@ VCerr SignatureValidator::Impl::baseCheck(
                        return result;
 
                if (!m_data.isAuthorSignature()) {
-                       if (XmlSec::NO_ERROR != XmlSecSingleton::Instance().validate(&m_context)) {
-                               LogWarning("Installation break - invalid package!");
-                               return E_SIG_INVALID_FORMAT;
-                       }
+                       XmlSecSingleton::Instance().validate(m_context);
 
                        m_data.setReference(m_context.referenceSet);
                        if (!checkObjectReferences()) {
@@ -363,8 +362,20 @@ VCerr SignatureValidator::Impl::baseCheck(
        } catch (const CertificateCollection::Exception::Base &e) {
                LogError("CertificateCollection exception : " << e.DumpToString());
                return E_SIG_INVALID_CHAIN;
+       } catch (const XmlSec::Exception::InternalError &e) {
+               LogError("XmlSec internal error : " << e.DumpToString());
+               return E_SIG_INVALID_FORMAT;
+       } catch (const XmlSec::Exception::InvalidFormat &e) {
+               LogError("XmlSec invalid format : " << e.DumpToString());
+               return E_SIG_INVALID_FORMAT;
+       } catch (const XmlSec::Exception::InvalidSig &e) {
+               LogError("XmlSec invalid signature : " << e.DumpToString());
+               return E_SIG_INVALID_SIG;
+       } catch (const XmlSec::Exception::OutOfMemory &e) {
+               LogError("XmlSec out of memory : " << e.DumpToString());
+               return E_SIG_OUT_OF_MEM;
        } catch (const XmlSec::Exception::Base &e) {
-               LogError("XmlSec exception : " << e.DumpToString());
+               LogError("XmlSec unknown exception : " << e.DumpToString());
                return E_SIG_INVALID_FORMAT;
        } catch (const Ocsp::Exception::Base &e) {
                LogInfo("OCSP will be handled by cert-checker later. : " << e.DumpToString());
@@ -395,18 +406,10 @@ VCerr SignatureValidator::Impl::baseCheckList(
                if (result != E_SIG_NONE)
                        return result;
 
-               if (uriList.size() == 0) {
-                       if (XmlSec::NO_ERROR != XmlSecSingleton::Instance().validateNoHash(&m_context)) {
-                               LogWarning("Installation break - invalid package! >> validateNoHash");
-                               return E_SIG_INVALID_FORMAT;
-                       }
-               } else {
-                       XmlSecSingleton::Instance().setPartialHashList(uriList);
-                       if (XmlSec::NO_ERROR != XmlSecSingleton::Instance().validatePartialHash(&m_context)) {
-                               LogWarning("Installation break - invalid package! >> validatePartialHash");
-                               return E_SIG_INVALID_FORMAT;
-                       }
-               }
+               if (uriList.size() == 0)
+                       XmlSecSingleton::Instance().validateNoHash(m_context);
+               else
+                       XmlSecSingleton::Instance().validatePartialHash(m_context, uriList);
 
                m_data.setReference(m_context.referenceSet);
                /*
@@ -434,8 +437,20 @@ VCerr SignatureValidator::Impl::baseCheckList(
        } catch (const CertificateCollection::Exception::Base &e) {
                LogError("CertificateCollection exception : " << e.DumpToString());
                return E_SIG_INVALID_CHAIN;
+       } catch (const XmlSec::Exception::InternalError &e) {
+               LogError("XmlSec internal error : " << e.DumpToString());
+               return E_SIG_INVALID_FORMAT;
+       } catch (const XmlSec::Exception::InvalidFormat &e) {
+               LogError("XmlSec invalid format : " << e.DumpToString());
+               return E_SIG_INVALID_FORMAT;
+       } catch (const XmlSec::Exception::InvalidSig &e) {
+               LogError("XmlSec invalid signature : " << e.DumpToString());
+               return E_SIG_INVALID_SIG;
+       } catch (const XmlSec::Exception::OutOfMemory &e) {
+               LogError("XmlSec out of memory : " << e.DumpToString());
+               return E_SIG_OUT_OF_MEM;
        } catch (const XmlSec::Exception::Base &e) {
-               LogError("XmlSec exception : " << e.DumpToString());
+               LogError("XmlSec unknown exception : " << e.DumpToString());
                return E_SIG_INVALID_FORMAT;
        } catch (const Ocsp::Exception::Base &e) {
                LogInfo("OCSP will be handled by cert-checker later. : " << e.DumpToString());
@@ -580,4 +595,3 @@ VCerr SignatureValidator::makeChainBySignature(
 }
 
 } // namespace ValidationCore
-
diff --git a/vcore/vcore/ValidatorCommon.h b/vcore/vcore/ValidatorCommon.h
deleted file mode 100644 (file)
index 05f2b7c..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
- *
- *    Licensed 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.
- */
-/*
- * @file        ValidatorCommon.h
- * @author      Bartlomiej Grzelewski (b.grzelewski@samsung.com)
- * @version     1.0
- * @brief       This file contais definictions of common types used in ValidationCore.
- */
-#ifndef _VALIDATORCOMMON_H_
-#define _VALIDATORCOMMON_H_
-
-#include <list>
-#include <set>
-#include <string>
-
-namespace ValidationCore {
-
-/*
- * base deleter func
- */
-template <typename T>
-struct ValidatorCoreUniversalFree {};
-
-// Template Specialization
-#define VC_DECLARE_DELETER(type, function)           \
-    template <> \
-    struct ValidatorCoreUniversalFree <type> {           \
-        void universal_free(type *ptr){                  \
-            if (ptr) {                                      \
-                function(ptr); }                           \
-        }                                                \
-    };
-
-template <typename T>
-class AutoPtr
-{
-  public:
-    AutoPtr(T *ptr) :
-        m_data(ptr)
-    {
-    }
-
-    AutoPtr(const AutoPtr<T> &second)
-    {
-        m_data = second.m_data;
-        second.m_data = 0;
-    }
-
-    AutoPtr & operator=(const AutoPtr &second)
-    {
-        if (this != &second) {
-            ValidatorCoreUniversalFree<T> deleter;
-            deleter.universal_free(m_data);
-            m_data = second.m_data;
-            second.m_data = 0;
-        }
-        return *this;
-    }
-
-    /**
-     * overloaded -> operator, so smart ptr could act as ordinary ptr
-     */
-    T* operator->()
-    {
-        return m_data;
-    }
-
-    ~AutoPtr()
-    {
-        ValidatorCoreUniversalFree<T> deleter;
-        deleter.universal_free(m_data);
-    }
-
-    /**
-     * get internal pointer
-     */
-    T* get(void)
-    {
-        return m_data;
-    }
-
-  private:
-    mutable T *m_data;
-};
-} // namespace ValidationCore
-
-#endif // _VALIDATORCOMMON_H_
index 6f3c8e7..e77a5d7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
 /*
  * @file        XmlsecAdapter.cpp
  * @author      Bartlomiej Grzelewski (b.grzelewski@samsung.com)
- * @version     1.0
+ * @version     2.0
  * @brief
  */
 #include <cstdlib>
 #include <cstring>
+#include <functional>
 
 #include <libxml/tree.h>
 #include <libxml/xmlmemory.h>
@@ -28,7 +29,7 @@
 
 #ifndef XMLSEC_NO_XSLT
 #include <libxslt/xslt.h>
-#endif /*   XMLSEC_NO_XSLT */
+#endif
 
 #include <xmlsec/xmlsec.h>
 #include <xmlsec/xmltree.h>
 
 #include <dpl/assert.h>
 #include <dpl/log/log.h>
+#include <dpl/singleton_impl.h>
 
 #include <vcore/XmlsecAdapter.h>
 
-#include <vcore/ValidatorCommon.h>
-
-#include <dpl/singleton_impl.h>
 IMPLEMENT_SINGLETON(ValidationCore::XmlSec)
 
 namespace {
 
+template <typename Type>
+struct CustomPtr {
+    Type ptr;
+    std::function<void(Type)> deleter;
+
+    CustomPtr() = delete;
+
+    explicit CustomPtr(Type in, std::function<void(Type)> d)
+        : ptr(in)
+        , deleter(d) {}
+
+    ~CustomPtr()
+    {
+        deleter(ptr);
+    }
+
+    inline Type get(void) const
+    {
+        return ptr;
+    }
+
+    inline Type operator->() const
+    {
+        return ptr;
+    }
+
+    inline bool operator!() const
+    {
+        return (ptr == nullptr) ? true : false;
+    }
+};
+
 struct FileWrapper {
     FileWrapper(void *argFile, bool argReleased)
       : file(argFile)
@@ -62,24 +93,24 @@ struct FileWrapper {
 } // anonymous namespace
 
 namespace ValidationCore {
-VC_DECLARE_DELETER(xmlSecKeysMngr, xmlSecKeysMngrDestroy)
 
-static const char* DIGEST_MD5 = "md5";
+static const std::string DIGEST_MD5 = "md5";
 
 std::string XmlSec::s_prefixPath;
 
 int XmlSec::fileMatchCallback(const char *filename)
 {
     std::string path = s_prefixPath + filename;
+
     return xmlFileMatch(path.c_str());
 }
 
-voidXmlSec::fileOpenCallback(const char *filename)
+void *XmlSec::fileOpenCallback(const char *filename)
 {
     std::string path = s_prefixPath + filename;
 
-   // LogDebug("Xmlsec opening : " << path);
-    return new FileWrapper(xmlFileOpen(path.c_str()),false);
+    LogDebug("Xmlsec opening : " << path);
+    return new FileWrapper(xmlFileOpen(path.c_str()), false);
 }
 
 int XmlSec::fileReadCallback(void *context,
@@ -87,14 +118,15 @@ int XmlSec::fileReadCallback(void *context,
         int len)
 {
     FileWrapper *fw = static_cast<FileWrapper*>(context);
-    if (fw->released) {
+    if (fw->released)
         return 0;
-    }
+
     int output = xmlFileRead(fw->file, buffer, len);
     if (output == 0) {
         fw->released = true;
         xmlFileClose(fw->file);
     }
+
     return output;
 }
 
@@ -102,52 +134,51 @@ int XmlSec::fileCloseCallback(void *context)
 {
     FileWrapper *fw = static_cast<FileWrapper*>(context);
     int output = 0;
-    if (!(fw->released)) {
+    if (!fw->released)
         output = xmlFileClose(fw->file);
-    }
+
     delete fw;
+
     return output;
 }
 
-void XmlSec::fileExtractPrefix(XmlSecContext *context)
+void XmlSec::fileExtractPrefix(XmlSecContext &context)
 {
-    if (!(context->workingDirectory.empty())) {
-        s_prefixPath = context->workingDirectory;
+    if (!context.workingDirectory.empty()) {
+        s_prefixPath = context.workingDirectory;
         return;
     }
 
-    s_prefixPath = context->signatureFile;
+    s_prefixPath = context.signatureFile;
     size_t pos = s_prefixPath.rfind('/');
-    if (pos == std::string::npos) {
+    if (pos == std::string::npos)
         s_prefixPath.clear();
-    } else {
+    else
         s_prefixPath.erase(pos + 1, std::string::npos);
-    }
 }
 
-void LogDebugPrint(const char* file, int line, const char* func, 
-       const char* errorObject, const char* errorSubject, 
-       int reason, const char* msg)
+void LogDebugPrint(const char *file,
+                   int line,
+                   const char *func,
+                   const char *errorObject,
+                   const char *errorSubject,
+                   int reason,
+                   const char *msg)
 {
-    char total[1024];
-    snprintf(total, sizeof(total), "[%s:%d][%s] : [%s] : [%s] : [%s]", file, line, func, errorObject, errorSubject, msg);
+    std::stringstream ss;
+    ss << "[" << file << ":" << line << "][" << func
+        << "] : [" << errorObject << "] : [" << errorSubject
+        << "] : [" << msg << "]" << std::endl;
 
-    if(reason != 256)
-    {
-       fprintf(stderr, "## [validate error]: %s\n", total);
-       LogError(" " << total);
-    }
+    if (reason == 256)
+        LogError(ss.str());
     else
-    {
-       LogDebug(" " << total);
-    }
+        LogDebug(ss.str());
 }
 
-XmlSec::XmlSec() :
-    m_initialized(false),
-    m_noHash(false),
-    m_partialHash(false),
-    m_pList(NULL)
+XmlSec::XmlSec()
+    : m_initialized(false)
+    , m_pList(nullptr)
 {
     LIBXML_TEST_VERSION
         xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
@@ -156,14 +187,11 @@ XmlSec::XmlSec() :
     xmlIndentTreeOutput = 1;
 #endif
 
-    if (xmlSecInit() < 0) {
-        LogError("Xmlsec initialization failed.");
+    if (xmlSecInit() < 0)
         ThrowMsg(Exception::InternalError, "Xmlsec initialization failed.");
-    }
 
     if (xmlSecCheckVersion() != 1) {
         xmlSecShutdown();
-        LogError("Loaded xmlsec library version is not compatible.");
         ThrowMsg(Exception::InternalError,
                  "Loaded xmlsec library version is not compatible.");
     }
@@ -180,16 +208,14 @@ XmlSec::XmlSec() :
     }
 #endif
 
-    if (xmlSecCryptoAppInit(NULL) < 0) {
+    if (xmlSecCryptoAppInit(nullptr) < 0) {
         xmlSecShutdown();
-        LogError("Crypto initialization failed.");
         ThrowMsg(Exception::InternalError, "Crypto initialization failed.");
     }
 
     if (xmlSecCryptoInit() < 0) {
         xmlSecCryptoAppShutdown();
         xmlSecShutdown();
-        LogError("Xmlsec-crypto initialization failed.");
         ThrowMsg(Exception::InternalError,
                  "Xmlsec-crypto initialization failed.");
     }
@@ -197,45 +223,25 @@ XmlSec::XmlSec() :
     m_initialized = true;
 }
 
-void XmlSec::deinitialize(void)
+XmlSec::~XmlSec()
 {
-    Assert(m_initialized);
+    if (m_initialized)
+        return;
 
-    /*   Shutdown xmlsec-crypto library */
     xmlSecCryptoShutdown();
-
-    /*   Shutdown crypto library */
     xmlSecCryptoAppShutdown();
-
-    /*   Shutdown xmlsec library */
     xmlSecShutdown();
 
-    /*   Shutdown libxslt/libxml */
 #ifndef XMLSEC_NO_XSLT
     xsltCleanupGlobals();
-#endif /*   XMLSEC_NO_XSLT */
+#endif
 
     s_prefixPath.clear();
     m_initialized = false;
 }
 
-XmlSec::~XmlSec()
+void XmlSec::validateFile(XmlSecContext &context, xmlSecKeysMngrPtr mngrPtr)
 {
-   m_noHash= false;
-   m_partialHash = false;
-    if (m_initialized) {
-        deinitialize();
-    }
-}
-
-XmlSec::Result XmlSec::validateFile(XmlSecContext *context,
-        xmlSecKeysMngrPtr mngr)
-{
-    xmlDocPtr doc = NULL;
-    xmlNodePtr node = NULL;
-    xmlSecDSigCtxPtr dsigCtx = NULL;
-    int size, res = -1;
-
     fileExtractPrefix(context);
     LogDebug("Prefix path : " << s_prefixPath);
 
@@ -247,266 +253,168 @@ XmlSec::Result XmlSec::validateFile(XmlSecContext *context,
         fileReadCallback,
         fileCloseCallback);
 
-    /*   load file */
-    doc = xmlParseFile(context->signatureFile.c_str());
-    if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)) {
-        LogWarning("Unable to parse file " << context->signatureFile);
-        goto done;
-    }
+    CustomPtr<xmlDocPtr> docPtr(xmlParseFile(context.signatureFile.c_str()), xmlFreeDoc);
+    if (!docPtr || xmlDocGetRootElement(docPtr.get()) == nullptr)
+        ThrowMsg(Exception::InvalidFormat,
+                "Unable to parse sig xml file: " << context.signatureFile);
 
-    /*   find start node */
-    node = xmlSecFindNode(xmlDocGetRootElement(
-                              doc), xmlSecNodeSignature, xmlSecDSigNs);
-    if (node == NULL) {
-        LogWarning("Start node not found in " << context->signatureFile);
-        goto done;
-    }
+    xmlNodePtr node = xmlSecFindNode(
+            xmlDocGetRootElement(docPtr.get()),
+            xmlSecNodeSignature,
+            xmlSecDSigNs);
+    if (node == nullptr)
+        ThrowMsg(Exception::InvalidFormat,
+                "Start node not found in " << context.signatureFile);
 
-    /*   create signature context */
-    dsigCtx = xmlSecDSigCtxCreate(mngr);
-    if (dsigCtx == NULL) {
-        LogError("Failed to create signature context.");
-        goto done;
-    }
+    CustomPtr<xmlSecDSigCtxPtr> dsigCtx(xmlSecDSigCtxCreate(mngrPtr), xmlSecDSigCtxDestroy);
+    if (!dsigCtx)
+        ThrowMsg(Exception::OutOfMemory, "Failed to create signature context.");
 
-    if (context->allowBrokenChain) {
-        dsigCtx->keyInfoReadCtx.flags |=
-            XMLSEC_KEYINFO_FLAGS_ALLOW_BROKEN_CHAIN;
-    }
+    if (context.allowBrokenChain)
+        dsigCtx->keyInfoReadCtx.flags |= XMLSEC_KEYINFO_FLAGS_ALLOW_BROKEN_CHAIN;
 
-    if (context->validationTime) {
+    if (context.validationTime) {
         LogDebug("Setting validation time.");
-        dsigCtx->keyInfoReadCtx.certsVerificationTime = context->validationTime;
+        dsigCtx->keyInfoReadCtx.certsVerificationTime = context.validationTime;
     }
 
-    if( m_noHash == true || m_partialHash == true ) {
-        LogDebug("SignatureEx start >> ");
-        if( m_pList == NULL ) {
-            LogWarning("## [validate]: uriList does not exist" );
-            fprintf(stderr, "## [validate]: uriList does not exist\n");
-            res = xmlSecDSigCtxVerifyEx(dsigCtx, node, 1, NULL);
-    } else {
-        int n = 0;
-        int i = 0;
-
-        if(m_pList == NULL)
-        {
-          LogWarning("## [validate]: uriList does not exist" );
-          fprintf(stderr, "## [validate]: uriList does not exist\n");
-          res = -1;
-          goto done;
-        }
+    int res;
+    switch (m_mode) {
+    case ValidateMode::NORMAL:
+        res = xmlSecDSigCtxVerify(dsigCtx.get(), node);
+        break;
 
-        n = m_pList->size();
-
-        char* pList[n + 1];
-        std::list<std::string>::const_iterator itr = m_pList->begin();
-        std::string tmpString;
-        char* uri = NULL;
-        int len;
-
-        for(; itr != m_pList->end(); ++itr) {
-           tmpString = (*itr);
-           uri = (char*)tmpString.c_str();
-           len = strlen(uri);
-           pList[i] = (char*)malloc(len + 1);
-           memcpy(pList[i], uri, len);
-           pList[i][len] = '\0';
-           fprintf(stderr, "## [validate]: uriList[%d] = %s\n", i, pList[i]);
-           ++i;
-        }
-        pList[n] = '\0';
+    case ValidateMode::NO_HASH:
+        res = xmlSecDSigCtxVerifyEx(dsigCtx.get(), node, 1, nullptr);
+        break;
 
-        res = xmlSecDSigCtxVerifyEx(dsigCtx, node, 0, (void*)pList);
-        i = 0;
-        while(pList[i] != NULL) {
-          free(pList[i]);
-          ++i;
-        }
-     }
-
-     if(res < 0) {
-        LogError("SignatureEx verify error.");
-        fprintf(stderr, "## [validate error]: SignatureEx verify error\n");
-        res = -1;
-        goto done;
-     }
-    } else {
-       LogDebug("Signature start >> ");
-
-       /*  Verify signature */
-       if (xmlSecDSigCtxVerify(dsigCtx, node) < 0) {
-         LogError("Signature verify error.");
-         fprintf(stderr, "## [validate error]: Signature verify error\n");
-         res = -1;
-         goto done;
-      }
-    }
+    case ValidateMode::PARTIAL_HASH:
+    {
+        size_t n = m_pList->size();
+        const char *pList[n + 1] = {0};
 
-    if (dsigCtx->keyInfoReadCtx.flags2 &
-     XMLSEC_KEYINFO_ERROR_FLAGS_BROKEN_CHAIN) {
-        LogWarning("XMLSEC_KEYINFO_FLAGS_ALLOW_BROKEN_CHAIN was set to true!");
-        LogWarning("Signature contains broken chain!");
-        context->errorBrokenChain = true;
-    }
+        size_t i = 0;
+        for (auto uri : *m_pList)
+            pList[i++] = uri.c_str();
 
-    /*   print verification result to stdout */
-    if (dsigCtx->status == xmlSecDSigStatusSucceeded) {
-        LogDebug("Signature is OK");
-        res = 0;
-    } else {
-        LogDebug("Signature is INVALID");
-        res = -1;
-        goto done;
+        res = xmlSecDSigCtxVerifyEx(dsigCtx.get(), node, 0, pList);
+        break;
     }
-
-    if (dsigCtx->c14nMethod && dsigCtx->c14nMethod->id &&
-        dsigCtx->c14nMethod->id->name) {
-       // LogInfo("Canonicalization method: " << (reinterpret_cast<const char *>(dsigCtx->c14nMethod->id->name)).c_str());
+    default:
+        ThrowMsg(Exception::InternalError, "ValidateMode is invalid");
     }
 
-    size = xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences));
-    for (int i = 0; i < size; ++i) {
-        xmlSecDSigReferenceCtxPtr dsigRefCtx =
-            (xmlSecDSigReferenceCtxPtr)xmlSecPtrListGetItem(&(dsigCtx->
-                                                                  signedInfoReferences),
-                                                            i);
-        if (dsigRefCtx && dsigRefCtx->uri) {
-            if (dsigRefCtx->digestMethod && dsigRefCtx->digestMethod->id &&
-                dsigRefCtx->digestMethod->id->name) {
-                const char* pDigest =
-                    reinterpret_cast<const char *>(dsigRefCtx->digestMethod->id
-                                                       ->name);
-                std::string strDigest(pDigest);
-                /*LogInfo("reference digest method: " << (reinterpret_cast<const char *>(dsigRefCtx->digestMethod->id->name)).c_str());*/
-                if (strDigest == DIGEST_MD5) {
-                    LogWarning("MD5 digest method used! Please use sha");
-                    res = -1;
-                    break;
-                }
-            }
-            context->referenceSet.insert(std::string(reinterpret_cast<char *>(
-                                                         dsigRefCtx->uri)));
-        }
+    if (res != 0)
+        ThrowMsg(Exception::InvalidSig, "Signature verify error.");
+
+    if (dsigCtx->keyInfoReadCtx.flags2 & XMLSEC_KEYINFO_ERROR_FLAGS_BROKEN_CHAIN) {
+        LogWarning("Signature contains broken chain!");
+        context.errorBrokenChain = true;
     }
 
-done:
-    m_pList = NULL;
-    m_noHash = false;
-    m_partialHash = false;
+    if (dsigCtx->status != xmlSecDSigStatusSucceeded)
+        ThrowMsg(Exception::InvalidSig, "Signature status is not succedded.");
 
-    /*   cleanup */
-    if (dsigCtx != NULL) {
-        xmlSecDSigCtxDestroy(dsigCtx);
-    }
+    xmlSecSize refSize = xmlSecPtrListGetSize(&(dsigCtx->signedInfoReferences));
+    for (xmlSecSize i = 0; i < refSize; ++i) {
+        xmlSecDSigReferenceCtxPtr dsigRefCtx = static_cast<xmlSecDSigReferenceCtxPtr>(
+                xmlSecPtrListGetItem(&(dsigCtx->signedInfoReferences), i));
 
-    if (doc != NULL) {
-        xmlFreeDoc(doc);
-    }
+        if (!dsigRefCtx || !dsigRefCtx->uri)
+            continue;
+
+        if (dsigRefCtx->digestMethod
+            && dsigRefCtx->digestMethod->id
+            && dsigRefCtx->digestMethod->id->name) {
+            auto digest = reinterpret_cast<const char * const>(
+                    dsigRefCtx->digestMethod->id->name);
 
-    if (res) {
-        return ERROR_INVALID_SIGNATURE;
+            if (DIGEST_MD5.compare(digest) == 0)
+                ThrowMsg(Exception::InvalidFormat,
+                        "MD5 digest method used! Please use sha");
+        }
+
+        context.referenceSet.emplace(reinterpret_cast<char *>(dsigRefCtx->uri));
     }
-    return NO_ERROR;
 }
 
-void XmlSec::loadDERCertificateMemory(XmlSecContext *context,
-        xmlSecKeysMngrPtr mngr)
+void XmlSec::loadDERCertificateMemory(XmlSecContext &context, xmlSecKeysMngrPtr mngrPtr)
 {
-    unsigned char *derCertificate = NULL;
-    int size = i2d_X509(context->certificatePtr->getX509(), &derCertificate);
-
-    if (!derCertificate) {
-        LogError("Failed during x509 conversion to der format.");
-        ThrowMsg(Exception::InternalError,
-                 "Failed during x509 conversion to der format.");
-    }
+    std::string derCert;
 
-    if (xmlSecCryptoAppKeysMngrCertLoadMemory(mngr,
-                                              derCertificate,
-                                              size,
-                                              xmlSecKeyDataFormatDer,
-                                              xmlSecKeyDataTypeTrusted) < 0) {
-        OPENSSL_free(derCertificate);
-        LogError("Failed to load der certificate from memory.");
+    try {
+        derCert = context.certificatePtr->getDER();
+    } catch (Certificate::Exception::Base &e) {
         ThrowMsg(Exception::InternalError,
-                 "Failed to load der certificate from memory.");
+                 "Failed during x509 conversion to der format: " << e.DumpToString());
     }
 
-    OPENSSL_free(derCertificate);
+    if (xmlSecCryptoAppKeysMngrCertLoadMemory(
+            mngrPtr,
+            reinterpret_cast<const xmlSecByte *>(derCert.data()),
+            reinterpret_cast<xmlSecSize>(derCert.length()),
+            xmlSecKeyDataFormatDer,
+            xmlSecKeyDataTypeTrusted) < 0)
+        ThrowMsg(Exception::InternalError, "Failed to load der cert from memory.");
 }
 
-void XmlSec::loadPEMCertificateFile(XmlSecContext *context,
-        xmlSecKeysMngrPtr mngr)
+void XmlSec::loadPEMCertificateFile(XmlSecContext &context, xmlSecKeysMngrPtr mngrPtr)
 {
-    if (xmlSecCryptoAppKeysMngrCertLoad(mngr,
-                                        context->certificatePath.c_str(),
-                                        xmlSecKeyDataFormatPem,
-                                        xmlSecKeyDataTypeTrusted) < 0) {
-        LogError("Failed to load PEM certificate from file.");
-        ThrowMsg(Exception::InternalError,
-                 "Failed to load PEM certificate from file.");
-    }
+    if (xmlSecCryptoAppKeysMngrCertLoad(
+            mngrPtr,
+            context.certificatePath.c_str(),
+            xmlSecKeyDataFormatPem,
+            xmlSecKeyDataTypeTrusted) < 0)
+        ThrowMsg(Exception::InternalError, "Failed to load PEM cert from file.");
 }
 
-XmlSec::Result XmlSec::validate(XmlSecContext *context)
+void XmlSec::validateInternal(XmlSecContext &context)
 {
-    Assert(context);
-    Assert(!(context->signatureFile.empty()));
-    Assert(context->certificatePtr.get() || !(context->certificatePath.empty()));
+    Assert(!context.signatureFile.empty());
+    Assert(!!context.certificatePtr || !context.certificatePath.empty());
 
     xmlSecErrorsSetCallback(LogDebugPrint);
 
-    if (!m_initialized) {
-        LogError("XmlSec is not initialized.");
+    if (!m_initialized)
         ThrowMsg(Exception::InternalError, "XmlSec is not initialized");
-    }
 
-    AutoPtr<xmlSecKeysMngr> mngr(xmlSecKeysMngrCreate());
+    CustomPtr<xmlSecKeysMngrPtr> mngrPtr(xmlSecKeysMngrCreate(), xmlSecKeysMngrDestroy);
 
-    if (!mngr.get()) {
-        LogError("Failed to create keys manager.");
+    if (!mngrPtr)
         ThrowMsg(Exception::InternalError, "Failed to create keys manager.");
-    }
 
-    if (xmlSecCryptoAppDefaultKeysMngrInit(mngr.get()) < 0) {
-        LogError("Failed to initialize keys manager.");
+    if (xmlSecCryptoAppDefaultKeysMngrInit(mngrPtr.get()) < 0)
         ThrowMsg(Exception::InternalError, "Failed to initialize keys manager.");
-    }
-    context->referenceSet.clear();
 
-    if (context->certificatePtr.get()) {
-        loadDERCertificateMemory(context, mngr.get());
-    }
+    context.referenceSet.clear();
 
-    if (!context->certificatePath.empty()) {
-        loadPEMCertificateFile(context, mngr.get());
-    }
+    if (!!context.certificatePtr)
+        loadDERCertificateMemory(context, mngrPtr.get());
+
+    if (!context.certificatePath.empty())
+        loadPEMCertificateFile(context, mngrPtr.get());
 
-    return validateFile(context, mngr.get());
+    validateFile(context, mngrPtr.get());
 }
 
-XmlSec::Result XmlSec::validateNoHash(XmlSecContext *context)
+void XmlSec::validate(XmlSecContext &context)
 {
-    xmlSecErrorsSetCallback(LogDebugPrint);
-
-    m_noHash = true;
-    return validate(context);
+    m_mode = ValidateMode::NORMAL;
+    validateInternal(context);
 }
 
-XmlSec::Result XmlSec::validatePartialHash(XmlSecContext *context)
+void XmlSec::validateNoHash(XmlSecContext &context)
 {
-    xmlSecErrorsSetCallback(LogDebugPrint);
-
-    m_partialHash = true;
-    return validate(context);
+    m_mode = ValidateMode::NO_HASH;
+    validateInternal(context);
 }
 
-XmlSec::Result XmlSec::setPartialHashList(const std::list<std::string>& targetUri)
+void XmlSec::validatePartialHash(XmlSecContext &context, const std::list<std::string> &targetUri)
 {
-  xmlSecErrorsSetCallback(LogDebugPrint);
+    m_mode = ValidateMode::PARTIAL_HASH;
+    m_pList = &targetUri;
 
-    m_pList = (std::list<std::string>*)&targetUri;
-    return NO_ERROR;
+    validateInternal(context);
 }
+
 } // namespace ValidationCore
index 3c8d94f..7c4d6ab 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
 /*
  * @file        XmlSecAdapter.h
  * @author      Bartlomiej Grzelewski (b.grzelewski@samsung.com)
- * @version     1.0
+ * @version     2.0
  * @brief
  */
-#ifndef _VALIDATION_CORE_XMLSECADAPTER_H_
-#define _VALIDATION_CORE_XMLSECADAPTER_H_
+#pragma once
+
+#include <string>
+#include <list>
 
 #include <xmlsec/keysmngr.h>
 
 #include <vcore/SignatureData.h>
 
 namespace ValidationCore {
-class XmlSec : public VcoreDPL::Noncopyable
-{
-  public:
+class XmlSec : public VcoreDPL::Noncopyable {
 
-    struct XmlSecContext
-    {
+public:
+    struct XmlSecContext {
         /* You _must_ set one of the value: certificatePath or certificate. */
-        XmlSecContext() :
-            validationTime(0),
-            allowBrokenChain(false),
-            errorBrokenChain(false)
-        {
-        }
+        XmlSecContext()
+            : validationTime(0)
+            , allowBrokenChain(false)
+            , errorBrokenChain(false) {}
 
         /*
          * Absolute path to signature file.
@@ -88,57 +86,47 @@ class XmlSec : public VcoreDPL::Noncopyable
         ReferenceSet referenceSet;
     };
 
-    enum Result
-    {
-        NO_ERROR,
-        ERROR_INVALID_SIGNATURE
-    };
-
-    class Exception
-    {
-      public:
+    struct Exception {
         DECLARE_EXCEPTION_TYPE(VcoreDPL::Exception, Base)
         DECLARE_EXCEPTION_TYPE(Base, InternalError)
+        DECLARE_EXCEPTION_TYPE(Base, InvalidFormat)
+        DECLARE_EXCEPTION_TYPE(Base, InvalidSig)
+        DECLARE_EXCEPTION_TYPE(Base, OutOfMemory)
     };
 
-    /*
-     * Context - input/output param.
-     */
-    Result validate(XmlSecContext *context);
-    Result validateNoHash(XmlSecContext *context);
-    Result validatePartialHash(XmlSecContext *context);
-    Result setPartialHashList(const std::list<std::string>& targetUri);
- protected:
+    /* context - input/output param. */
+    void validate(XmlSecContext &context);
+    void validateNoHash(XmlSecContext &context);
+    void validatePartialHash(XmlSecContext &context, const std::list<std::string> &targetUri);
+
+protected:
     XmlSec();
     ~XmlSec();
-  private:
-    void deinitialize(void);
 
-    void loadDERCertificateMemory(XmlSecContext *context,
-            xmlSecKeysMngrPtr mngr);
-    void loadPEMCertificateFile(XmlSecContext *context,
-            xmlSecKeysMngrPtr mngr);
-    Result validateFile(XmlSecContext *context,
-            xmlSecKeysMngrPtr mngr);
+private:
+    enum class ValidateMode : int {
+        NORMAL,
+        NO_HASH,
+        PARTIAL_HASH
+    };
 
+    ValidateMode m_mode;
     bool m_initialized;
-    bool m_noHash;
-    bool m_partialHash;
-    std::list<std::string>* m_pList;
+    const std::list<std::string> *m_pList;
+
+    void loadDERCertificateMemory(XmlSecContext &context, xmlSecKeysMngrPtr mngr);
+    void loadPEMCertificateFile(XmlSecContext &context, xmlSecKeysMngrPtr mngr);
+    void validateInternal(XmlSecContext &context);
+    void validateFile(XmlSecContext &context, xmlSecKeysMngrPtr mngr);
 
     static std::string s_prefixPath;
     static int fileMatchCallback(const char *filename);
-    static void* fileOpenCallback(const char *filename);
-    static int fileReadCallback(void *context,
-            char *buffer,
-            int len);
+    static void *fileOpenCallback(const char *filename);
+    static int fileReadCallback(void *context, char *buffer, int len);
     static int fileCloseCallback(void *context);
-    static void fileExtractPrefix(XmlSecContext *context);
+    static void fileExtractPrefix(XmlSecContext &context);
 };
 
 typedef VcoreDPL::Singleton<XmlSec> XmlSecSingleton;
 
 } // namespace ValidationCore
-
-#endif // _VALIDATION_CORE_XMLSECVERIFICATOR_H_