Fixed Certificate update issue during updating RDS mode
[framework/web/wrt-installer.git] / src / jobs / widget_install / task_certify.cpp
old mode 100755 (executable)
new mode 100644 (file)
index 532c206..b3273b1
 #include <widget_install/widget_install_errors.h>
 #include <widget_install/widget_install_context.h>
 #include <dpl/log/log.h>
-#include <wrt_error.h>
 #include <dpl/wrt-dao-ro/global_config.h>
 #include "wac_widget_id.h"
 
+#include <vcore/Certificate.h>
 #include <vcore/SignatureReader.h>
 #include <vcore/SignatureFinder.h>
-#include <vcore/SignatureValidator.h>
+#include <vcore/WrtSignatureValidator.h>
 #include <vcore/DeveloperModeValidator.h>
 #include <dpl/utils/wrt_global_settings.h>
 #include <dpl/wrt-dao-ro/global_dao_read_only.h>
@@ -53,8 +53,8 @@ using namespace WrtDB;
 namespace {
 const std::string LABEL_NEW_LINE = "<br>";
 const std::string LABEL_NEW_LINE_2 = "<br><br>";
-const std::string UNTRUSTED_WIDGET ="It is an Untrusted Widget";
-const char *QUESTION ="Do you wanto to install?";
+const std::string UNTRUSTED_WIDGET = "It is an Untrusted Widget";
+const char *QUESTION = "Do you wanto to install?";
 
 WidgetCertificateData toWidgetCertificateData(const SignatureData &data,
                                               bool root)
@@ -62,6 +62,7 @@ WidgetCertificateData toWidgetCertificateData(const SignatureData &data,
     WidgetCertificateData result;
 
     result.chainId = data.getSignatureNumber();
+    LogDebug("result.chainId : " << result.chainId);
 
     result.owner = data.isAuthorSignature() ?
         WidgetCertificateData::AUTHOR : WidgetCertificateData::DISTRIBUTOR;
@@ -78,37 +79,67 @@ WidgetCertificateData toWidgetCertificateData(const SignatureData &data,
     }
 
     Assert(certificate && !certificate->getCommonName().IsNull() &&
-            "CommonName is Null");
+           "CommonName is Null");
 
     result.strCommonName = *certificate->getCommonName();
 
     result.strMD5Fingerprint = std::string("md5 ") +
-        SignatureValidator::FingerprintToColonHex(
+        Certificate::FingerprintToColonHex(
             certificate->getFingerprint(Certificate::FINGERPRINT_MD5));
 
     result.strSHA1Fingerprint = std::string("sha-1 ") +
-        SignatureValidator::FingerprintToColonHex(
+        Certificate::FingerprintToColonHex(
             certificate->getFingerprint(Certificate::FINGERPRINT_SHA1));
 
     return result;
 }
+
+CertificatePtr getOldAuthorSignerCertificate(DPL::String appid)
+{
+    WidgetDAOReadOnly dao(appid);
+    CertificateChainList chainList = dao.getWidgetCertificate(SIGNATURE_AUTHOR);
+
+    FOREACH(it, chainList)
+    {
+        ValidationCore::CertificateCollection chain;
+        if (false == chain.load(*it)) {
+            LogError("Chain is broken");
+        }
+
+        if (!chain.sort()) {
+            LogError("Chain failed at sorting");
+        }
+
+        ValidationCore::CertificateList list = chain.getCertificateList();
+
+        FOREACH(cert, list)
+        {
+            if (!(*cert)->isRootCert() && !(*cert)->isCA()) {
+                return *cert;
+            }
+        }
+    }
+    return CertificatePtr(NULL);
+}
 } // namespace anonymous
 
 namespace Jobs {
 namespace WidgetInstall {
 TaskCertify::TaskCertify(InstallerContext &inCont) :
     DPL::TaskDecl<TaskCertify>(this),
-    m_contextData(inCont),
-    WidgetInstallPopup(inCont)
+    WidgetInstallPopup(inCont),
+    m_contextData(inCont)
 {
-    /* This is temporary comment for certi error
-       After security-server, cert-svc release, should remove comment
     AddStep(&TaskCertify::stepSignature);
-    */
+    // certi comparison determines whether the update.
+    if (true == m_contextData.existingWidgetInfo.isExist) {
+        AddStep(&TaskCertify::stepVerifyUpdate);
+    }
 
     // Block until fixed popup issues
     if (!GlobalSettings::PopupsTestModeEnabled()
-            && !m_installContext.m_quiet && !isTizenWebApp()) {
+        && !m_installContext.m_quiet && !isTizenWebApp())
+    {
         AddStep(&TaskCertify::stepWarningPopup);
         AddStep(&TaskCertify::stepWarningPopupAnswer);
         AddStep(&TaskCertify::stepAuthorInfoPopup);
@@ -118,8 +149,7 @@ TaskCertify::TaskCertify(InstallerContext &inCont) :
     AddStep(&TaskCertify::stepFinalize);
 }
 
-void TaskCertify::processDistributorSignature(const SignatureData &data,
-                                              bool first)
+void TaskCertify::processDistributorSignature(const SignatureData &data)
 {
     // this signature is verified -
     // no point in check domain WAC_ROOT and WAC_RECOGNIZED
@@ -131,15 +161,17 @@ void TaskCertify::processDistributorSignature(const SignatureData &data,
 
     CertificateCollection collection;
     collection.load(data.getCertList());
-    collection.sort();
+    Assert(collection.sort() &&
+           "Certificate collection can't sort");
+
     Assert(collection.isChain() &&
            "Certificate collection is not able to create chain. "
            "It is not possible to verify this signature.");
 
     m_contextData.wacSecurity.getCertificateChainListRef().push_back(
-            collection);
+        collection);
 
-    if (first) {
+    if (data.getSignatureNumber() == 1) {
         m_contextData.wacSecurity.getCertificateListRef().push_back(
             toWidgetCertificateData(data, true));
         m_contextData.wacSecurity.getCertificateListRef().push_back(
@@ -152,8 +184,9 @@ void TaskCertify::processAuthorSignature(const SignatureData &data)
     using namespace ValidationCore;
     LogInfo("DNS Identity match!");
     // this signature is verified or widget is distributor signed
-    m_contextData.wacSecurity.getAuthorCertificatePtr() =
-        data.getEndEntityCertificatePtr();
+    m_contextData.wacSecurity.setAuthorCertificatePtr(data.getEndEntityCertificatePtr());
+    CertificatePtr test = m_contextData.wacSecurity.getAuthorCertificatePtr();
+
     m_contextData.wacSecurity.getCertificateListRef().push_back(
         toWidgetCertificateData(data, true));
     m_contextData.wacSecurity.getCertificateListRef().push_back(
@@ -174,7 +207,7 @@ void TaskCertify::processAuthorSignature(const SignatureData &data)
            "It is not possible to verify this signature.");
 
     m_contextData.wacSecurity.getAuthorsCertificateChainListRef().push_back(
-            collection);
+        collection);
 
     FOREACH(it, dnsIdentity){
         if (widgetId.matchHost(*it)) {
@@ -186,9 +219,16 @@ void TaskCertify::processAuthorSignature(const SignatureData &data)
 
 void TaskCertify::stepSignature()
 {
-    LogInfo("enter");
+    LogInfo("================ Step: <<Signature>> ENTER ===============");
 
-    std::string widgetPath = m_contextData.locations->getTemporaryRootDir() + "/";
+    std::string widgetPath;
+    if (m_contextData.widgetConfig.packagingType ==
+        WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
+    {
+        widgetPath = m_contextData.locations->getSourceDir() + "/";
+    } else {
+        widgetPath = m_contextData.locations->getTemporaryPackageDir() + "/";
+    }
 
     SignatureFileInfoSet signatureFiles;
     SignatureFinder signatureFinder(widgetPath);
@@ -199,9 +239,8 @@ void TaskCertify::stepSignature()
     }
 
     SignatureFileInfoSet::reverse_iterator iter = signatureFiles.rbegin();
-    LogInfo("No of signatures: " << signatureFiles.size());
+    LogInfo("Number of signatures: " << signatureFiles.size());
 
-    bool firstDistributorSignature = true;
     bool testCertificate = false;
 
     bool complianceMode = GlobalDAOReadOnly::getComplianceMode();
@@ -216,19 +255,42 @@ void TaskCertify::stepSignature()
             xml.initialize(data, GlobalConfig::GetSignatureXmlSchema());
             xml.read(data);
 
-            SignatureValidator validator(!GlobalSettings::OCSPTestModeEnabled(),
-                                         !GlobalSettings::CrlTestModeEnabled(),
-                                         complianceMode);
-            SignatureValidator::Result result =
-                validator.check(data, widgetPath);
+            WrtSignatureValidator::AppType appType =
+                WrtSignatureValidator::WAC20;
+
+            if (m_installContext.widgetConfig.webAppType ==
+                APP_TYPE_TIZENWEBAPP)
+            {
+                appType = WrtSignatureValidator::TIZEN;
+            }
+
+            WrtSignatureValidator::Result result;
+
+            WrtSignatureValidator validator(
+                    appType,
+                    !GlobalSettings::
+                    OCSPTestModeEnabled(),
+                    !GlobalSettings::
+                    CrlTestModeEnabled(),
+                    complianceMode);
+
+            result = validator.check(data, widgetPath);
+
+            if (m_contextData.widgetConfig.packagingType
+                == WrtDB::PKG_TYPE_DIRECTORY_WEB_APP)
+            {
+                // In directory installation mode, the validation is skipped.
+
+                result = WrtSignatureValidator::SIGNATURE_VERIFIED;
+            }
 
-            if (result == SignatureValidator::SIGNATURE_REVOKED) {
+            if (result == WrtSignatureValidator::SIGNATURE_REVOKED) {
                 LogWarning("Certificate is REVOKED");
                 ThrowMsg(Exceptions::InvalidPackage,
                          "Certificate is REVOKED");
             }
 
-            if (result == SignatureValidator::SIGNATURE_INVALID) {
+            if (result == WrtSignatureValidator::SIGNATURE_INVALID) {
                 LogWarning("Signature is INVALID");
                 // TODO change exception name
                 ThrowMsg(Exceptions::InvalidPackage,
@@ -236,20 +298,21 @@ void TaskCertify::stepSignature()
             }
 
             if (data.isAuthorSignature()) {
-                if (result == SignatureValidator::SIGNATURE_VERIFIED ||
+                if (result == WrtSignatureValidator::SIGNATURE_VERIFIED ||
                     m_contextData.wacSecurity.isDistributorSigned())
                 {
                     processAuthorSignature(data);
-                } else if (result == SignatureValidator::SIGNATURE_DISREGARD) {
+                } else if (result ==
+                           WrtSignatureValidator::SIGNATURE_DISREGARD)
+                {
                     continue;
                 }
             } else {
-                if (result == SignatureValidator::SIGNATURE_DISREGARD) {
+                if (result == WrtSignatureValidator::SIGNATURE_DISREGARD) {
                     continue;
                 }
                 // now signature _must_ be verified
-                processDistributorSignature(data, firstDistributorSignature);
-                firstDistributorSignature = false;
+                processDistributorSignature(data);
             }
 
             bool developerMode = GlobalDAOReadOnly::GetDeveloperMode();
@@ -257,8 +320,7 @@ void TaskCertify::stepSignature()
             std::string realMEID;
             TapiHandle *tapiHandle = tel_init(NULL);
             char *meid = tel_get_misc_me_sn_sync(tapiHandle);
-            if (meid)
-            {
+            if (meid) {
                 realMEID = meid;
                 free(meid);
             }
@@ -300,7 +362,7 @@ void TaskCertify::stepSignature()
         LogInfo("No signature files has been found.");
     }
 
-    LogInfo("================ Step: <<CSignature>> DONE ================");
+    LogInfo("================ Step: <<Signature>> DONE ================");
 
     m_contextData.job->UpdateProgress(
         InstallerContext::INSTALL_DIGSIG_CHECK,
@@ -310,11 +372,11 @@ void TaskCertify::stepSignature()
 void TaskCertify::createInstallPopup(PopupType type, const std::string &label)
 {
     m_contextData.job->Pause();
-    if(m_popup)
+    if (m_popup) {
         destroyPopup();
+    }
     bool ret = createPopup();
-    if(ret)
-    {
+    if (ret) {
         loadPopup(type, label);
         showPopup();
     }
@@ -395,9 +457,9 @@ std::string TaskCertify::createAuthorWidgetInfo() const
 void TaskCertify::stepAuthorInfoPopup()
 {
     LogInfo("Step:: <<Author Popup Information>>");
-        std::string label
-            = createAuthorWidgetInfo() + LABEL_NEW_LINE_2 + QUESTION;
-        createInstallPopup(PopupType::WIDGET_AUTHOR_INFO, label);
+    std::string label
+        = createAuthorWidgetInfo() + LABEL_NEW_LINE_2 + QUESTION;
+    createInstallPopup(PopupType::WIDGET_AUTHOR_INFO, label);
 }
 
 void TaskCertify::stepFinalize()
@@ -409,12 +471,11 @@ void TaskCertify::stepFinalize()
         "Widget Certification Check Finished");
 }
 
-
 void TaskCertify::stepWarningPopupAnswer()
 {
     LogInfo("Step: <<Warning Popup Answer>>");
     if (false == m_contextData.wacSecurity.isDistributorSigned() &&
-            WRT_POPUP_BUTTON_CANCEL == m_installCancel)
+        WRT_POPUP_BUTTON_CANCEL == m_installCancel)
     {
         LogWarning("User does not agreed to install unsigned widgets!");
         m_installCancel = WRT_POPUP_BUTTON;
@@ -426,7 +487,7 @@ void TaskCertify::stepWarningPopupAnswer()
 void TaskCertify::stepAuthorInfoPopupAnswer()
 {
     LogInfo("Step: <<Author Info Popup Answer>>");
-    if ( WRT_POPUP_BUTTON_CANCEL == m_installCancel) {
+    if (WRT_POPUP_BUTTON_CANCEL == m_installCancel) {
         LogWarning("User does not agreed to install widget!");
         m_installCancel = WRT_POPUP_BUTTON;
         destroyPopup();
@@ -438,11 +499,40 @@ bool TaskCertify::isTizenWebApp() const
 {
     bool ret = FALSE;
     if (m_installContext.widgetConfig.webAppType.appType
-            == WrtDB::AppType::APP_TYPE_TIZENWEBAPP)
+        == WrtDB::AppType::APP_TYPE_TIZENWEBAPP)
+    {
         ret = TRUE;
+    }
 
     return ret;
 }
+
+void TaskCertify::stepVerifyUpdate()
+{
+    LogInfo("Step: <<Check Update>>");
+    CertificatePtr newCertificate =
+        m_contextData.wacSecurity.getAuthorCertificatePtr();
+    CertificatePtr oldCertificate =
+        getOldAuthorSignerCertificate(m_installContext.widgetConfig.tzAppid);
+
+    if (!!newCertificate && !!oldCertificate) {
+        if (0 != newCertificate->getBase64().compare(oldCertificate->getBase64())) {
+            LogDebug("old widget's author signer certificate : " <<
+                    oldCertificate->getBase64());
+            LogDebug("new widget's author signer certificate : " <<
+                    newCertificate->getBase64());
+            ThrowMsg(Exceptions::InvalidPackage,
+                    "Author signer certificates doesn't match \
+                    between old widget and installing widget");
+        }
+    } else {
+        if (!(NULL == newCertificate.Get() && NULL == oldCertificate.Get())) {
+            ThrowMsg(Exceptions::InvalidPackage,
+                    "Author signer certificates doesn't match \
+                    between old widget and installing widget");
+        }
+    }
+}
 } //namespace WidgetInstall
 } //namespace Jobs