[PWE] Implement "request,certificate,confirm" smart callback for PWA apps 47/128847/7
authorPawel Niemirski <p.niemirski@samsung.com>
Fri, 19 May 2017 07:59:32 +0000 (09:59 +0200)
committerPawel Niemirski <p.niemirski@samsung.com>
Wed, 31 May 2017 11:47:21 +0000 (13:47 +0200)
Due to certificate error (e.g. untrusted certificate or wrong time),
some pages can be untrusted. This is why some resources can be blocked
by the engine resulting in missing images and styles.

In org.tizen.browser, a confirmation popup takes place whenever
certificate issue happens, so user is able to decide whether
to use resources from untrusted site or not.

However, such mechanism is unavailable for PWA applications, therefore
the engine is responsible for making decisions on certificate issue
and it blocks all sub-resources with certificate error by default.

This CL implements "request,certificate,confirm" smart callback for PWA
to give user opportunity of making decisions on untrusted PWA apps.

Bug: suprem.sec.samsung.net/jira/browse/RWASP-1181

Change-Id: I81734bc614bd9bab7c25c7dae0eb1d6e631aaf68
Signed-off-by: Pawel Niemirski <p.niemirski@samsung.com>
services/SimpleUI/SimpleUI.cpp
services/WebEngineMin/WebEngineMin.cpp
services/WebEngineMin/WebEngineMin.h

index 6d5c7b0d6a7b3ef05657c83567a489d625cd8fd3..44e0cee5281fa1a175dd3589285602bb39952951 100755 (executable)
@@ -231,12 +231,22 @@ void SimpleUI::preparePWAServices() {
                     core::ServiceManager::getInstance().getService(
                                     "org.tizen.browser.storageservice",
                                     "libStorageService.so"));
-
+#if PWE_SHUB
+    m_certificateContents = std::dynamic_pointer_cast<
+                    services::CertificateContents, core::AbstractService>(
+                    core::ServiceManager::getInstance().getService(
+                                    "org.tizen.browser.certificateservice",
+                                    "libCertificateService.so"));
+#endif
     connectPWASignals();
 
     m_platformInputManager->init(m_window.get());
     m_webPageMin->init(m_viewManager.getContent());
     m_webEngine->init(m_webPageMin->getContent());
+#if PWE_SHUB
+    assert(m_certificateContents.get());
+    m_certificateContents->init();
+#endif
 }
 
 int SimpleUI::exec(const std::string& url, const std::string& caller,
@@ -959,6 +969,10 @@ void SimpleUI::connectPWASignals() {
                     [this] {return m_pwa.getPWAinfo().serviceWorkerUri;});
     m_webEngine->getPWAURI.connect(
                     [this] {return m_pwa.getPWAinfo().uri;});
+    m_webEngine->confirmationRequest.connect(
+                    [this](const auto& conf) {
+                        this->handleConfirmationRequest(conf);
+                    });
 #endif
     m_webEngine->getPWAInstanceIDSignal.connect(
                     [this] {return m_pushPwaData.getInstanceId();});
@@ -984,6 +998,9 @@ void SimpleUI::connectPWASignals() {
         BROWSER_LOGD("[%s:%d] ", __PRETTY_FUNCTION__, __LINE__);
         return m_storageService->getPWAStorage().getPermissionsMap();
     });
+#if PWE_SHUB
+    connectCertificateSignals();
+#endif
 }
 
 void SimpleUI::connectModelSignals() {
@@ -1777,7 +1794,11 @@ void SimpleUI::handleConfirmationRequest(
 
     if (webConfirmation->getConfirmationType()
                     == basic_webengine::WebConfirmation::ConfirmationType::CertificateConfirmation) {
+#if PWE_SHUB
+        if (m_pwa.isActive() || m_webPageUI->stateEquals(WPUState::MAIN_WEB_PAGE)) {
+#else
         if (m_webPageUI->stateEquals(WPUState::MAIN_WEB_PAGE)) {
+#endif
             auto cert = std::dynamic_pointer_cast<
                             basic_webengine::CertificateConfirmation,
                             basic_webengine::WebConfirmation>(webConfirmation);
@@ -1788,6 +1809,9 @@ void SimpleUI::handleConfirmationRequest(
                                 tizen_browser::basic_webengine::WebConfirmation::ConfirmationResult::Confirmed);
                 m_webEngine->confirmationResult(webConfirmation);
             } else {
+#if PWE_SHUB
+                if (!m_pwa.isActive())
+#endif
                 m_webPageUI->getURIEntry().changeUri(webConfirmation->getURI());
                 TextPopup* popup = TextPopup::createPopup(
                                 m_viewManager.getContent());
index 658ed13b87548e0dc9c2a160fdbdf7e8f7b33064..8d99159f02044fc2945dd3fddee8380d49f3e264 100755 (executable)
@@ -8,6 +8,10 @@
 #include "ServiceManager.h"
 #include "URIschemes.h"
 
+#if PWE_SHUB
+#include "boost/format.hpp"
+#endif
+
 namespace tizen_browser {
 namespace basic_webengine {
 
@@ -43,7 +47,9 @@ WebEngineMin::~WebEngineMin()
         evas_object_smart_callback_del_full(m_ewkView, "policy,navigation,decide", __policy_navigation_decide_cb, this);
         evas_object_smart_callback_del_full(m_ewkView, "create,window,url", __newWindowRequestUrl, this);
         evas_object_smart_callback_del_full(m_ewkView, "policy,newwindow,decide", __policy_newwindow_decide_cb, this);
-
+#if PWE_SHUB
+        evas_object_smart_callback_del_full(m_ewkView, "request,certificate,confirm", __requestCertificationConfirm, this);
+#endif
         evas_object_del(m_ewkView);
     }
 }
@@ -112,7 +118,9 @@ void WebEngineMin::init(Evas_Object* guiParent)
     evas_object_smart_callback_add(m_ewkView, "policy,response,decide", __policy_response_decide_cb, this);
     evas_object_smart_callback_add(m_ewkView, "create,window,url", __newWindowRequestUrl, this);
     evas_object_smart_callback_add(m_ewkView, "policy,newwindow,decide", __policy_newwindow_decide_cb, this);
-
+#if PWE_SHUB
+    evas_object_smart_callback_add(m_ewkView, "request,certificate,confirm", __requestCertificationConfirm, this);
+#endif
     auto permissions = *getPermissionsMap();
     Eina_List* permList = nullptr;
     for (const auto& it : permissions) {
@@ -267,6 +275,80 @@ void WebEngineMin::__policy_response_decide_cb(void *data, Evas_Object * /* obj
     }
 }
 
+#if PWE_SHUB
+// Copied from WebView.cpp
+void WebEngineMin::__requestCertificationConfirm(void *data , Evas_Object * /* obj */, void *event_info)
+{
+    BROWSER_LOGD("[%s:%d] ", __PRETTY_FUNCTION__, __LINE__);
+
+    WebEngineMin *self = reinterpret_cast<WebEngineMin *>(data);
+    Ewk_Certificate_Policy_Decision *request = reinterpret_cast<Ewk_Certificate_Policy_Decision *>(event_info);
+    if (!request) {
+        BROWSER_LOGW("[%s:%d] Wrong event_info!", __PRETTY_FUNCTION__, __LINE__);
+        return;
+    }
+
+    int error = ewk_certificate_policy_decision_error_get(request);
+    if (error == EWK_CERTIFICATE_POLICY_DECISION_ERROR_PINNED_KEY_NOT_IN_CHAIN) {
+        ewk_certificate_policy_decision_allowed_set(request, EINA_FALSE);
+        BROWSER_LOGW("[%s:%d] EWK_CERTIFICATE_POLICY_DECISION_ERROR_PINNED_KEY_NOT_IN_CHAIN", __PRETTY_FUNCTION__, __LINE__);
+        self->unsecureConnection();
+        return;
+    }
+
+    self->suspend();
+    ewk_certificate_policy_decision_suspend(request);
+
+    std::string url = tools::extractDomain(self->m_loadingURL);
+
+    ///\todo add translations
+    std::string message = (boost::format("There are problems with the security certificate for this site.<br>%1%") % url).str();
+
+    CertificateConfirmationPtr c = std::make_shared<CertificateConfirmation>(1/*tab_ID*/, url, message);
+    const char *pem = ewk_certificate_policy_decision_certificate_pem_get(request);
+    c->setPem(std::string(pem));
+    c->setData(reinterpret_cast<void*>(request));
+
+    // store
+    self->m_confirmationCertificatenMap[c] = request;
+    self->confirmationRequest(c);
+}
+
+// Copied from WebView.cpp
+void WebEngineMin::confirmationResult(WebConfirmationPtr confirmation)
+{
+    BROWSER_LOGD("[%s:%d] ", __PRETTY_FUNCTION__, __LINE__);
+
+    if (confirmation->getConfirmationType() == WebConfirmation::ConfirmationType::CertificateConfirmation) {
+        //FIXME: https://bugs.tizen.org/jira/browse/TT-229
+        CertificateConfirmationPtr cert = std::dynamic_pointer_cast<CertificateConfirmation, WebConfirmation>(confirmation);
+
+        // The below line doesn't serve any purpose now, but it may become
+        // relevant when implementing https://bugs.tizen.org/jira/browse/TT-229
+        Ewk_Certificate_Policy_Decision *request = m_confirmationCertificatenMap[cert];
+        Eina_Bool result;
+
+        if (cert->getResult() == WebConfirmation::ConfirmationResult::Confirmed) {
+            result = EINA_TRUE;
+        } else if (cert->getResult() == WebConfirmation::ConfirmationResult::Rejected) {
+            result = EINA_FALSE;
+        } else {
+            BROWSER_LOGE("Wrong ConfirmationResult");
+            return;
+        }
+
+        // set certificate confirmation
+        ewk_certificate_policy_decision_allowed_set(request, result);
+        resume();
+
+        // remove from map
+        m_confirmationCertificatenMap.erase(cert);
+    } else {
+        BROWSER_LOGW("[%s:%d] Unknown WebConfirmation::ConfirmationType!", __PRETTY_FUNCTION__, __LINE__);
+    }
+}
+#endif
+
 TabId WebEngineMin::addTab(const std::string& uri,
     const boost::optional<int>,
     const std::string&,
index af81d106ca67ff0b71b62452694eddcb3731c17c..beb88e977ec3bb0d16ead2db6b719f23371bbb0b 100755 (executable)
@@ -92,7 +92,11 @@ public:
     void reload() override { }
     void back() override { }
     void forward() override { }
-    void confirmationResult(WebConfirmationPtr) override { }
+#if PWE_SHUB
+    void confirmationResult(WebConfirmationPtr) override;
+#else
+    void confirmationResult(WebConfirmationPtr) override { };
+#endif
     void setIMEState(const bool&) override { }
     void clearCache() override { }
     void clearCookies() override { }
@@ -116,6 +120,7 @@ private:
 #if PWE_SHUB
     static void _register_service_worker_result_cb(Ewk_Context *context,
         const char* scope_url, const char* script_url, Eina_Bool result, void* data);
+    static void __requestCertificationConfirm(void *data, Evas_Object *obj, void *event_info);
 #endif
     static void __notification_reply_cb(void *data, Evas_Object *obj, void *event_info);
     static void __newWindowRequest(void *data, Evas_Object *, void*);
@@ -128,6 +133,9 @@ private:
     Ewk_Context* m_ewkContext;
     std::string m_loadingURL;
     std::shared_ptr<DownloadControl> m_downloadControl;
+#if PWE_SHUB
+    std::map<CertificateConfirmationPtr, Ewk_Certificate_Policy_Decision *> m_confirmationCertificatenMap;
+#endif
     int m_policyCounter;
 
     static const std::string COOKIES_PATH;