From 6a8135af385412dd9a60775659222a6061174468 Mon Sep 17 00:00:00 2001 From: Andrey Goncharov Date: Fri, 17 Dec 2021 03:53:44 -0800 Subject: [PATCH] Initiate cert exchange when medium changes Summary: Changelog: Initiate cert exchange when medium changes Fixes the following bug: 1. Start an iOS app with WWW cert exchange 2. Get cert (and fake serial of a virtual device) 3. Close app 4. Restart Flipper 5. Switch app to FS_ACCESS cert exchange 6. Start app Expected result: App re-initializes cert exchange to get a new serial of a real device Current result: App tries to connect securely using the previous fake serial of a virtual device. Flipper does not recognize it and refuses the connection. Reviewed By: lblasa Differential Revision: D33163798 fbshipit-source-id: 67126a9b562f2cb7cfe6521a46abf38b2699fb2d --- xplat/Flipper/ConnectionContextStore.cpp | 16 +++++++++++++++ xplat/Flipper/ConnectionContextStore.h | 6 ++++++ .../FlipperCertificateExchangeMedium.h | 2 ++ .../Flipper/FlipperConnectionManagerImpl.cpp | 20 +++++++++++++++++-- 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/xplat/Flipper/ConnectionContextStore.cpp b/xplat/Flipper/ConnectionContextStore.cpp index 514eef14f..ffcf2d515 100644 --- a/xplat/Flipper/ConnectionContextStore.cpp +++ b/xplat/Flipper/ConnectionContextStore.cpp @@ -6,6 +6,7 @@ */ #include "ConnectionContextStore.h" +#include #include #include #include @@ -110,6 +111,21 @@ std::string ConnectionContextStore::getDeviceId() { } } +folly::Optional +ConnectionContextStore::getLastKnownMedium() { + try { + std::string config = + loadStringFromFile(absoluteFilePath(CONNECTION_CONFIG_FILE)); + auto maybeMedium = folly::parseJson(config)["medium"]; + return maybeMedium.isInt() + ? folly::Optional{static_cast< + FlipperCertificateExchangeMedium>(maybeMedium.getInt())} + : folly::none; + } catch (std::exception&) { + return folly::none; + } +} + void ConnectionContextStore::storeConnectionConfig(folly::dynamic& config) { std::string json = folly::toJson(config); writeStringToFile(json, absoluteFilePath(CONNECTION_CONFIG_FILE)); diff --git a/xplat/Flipper/ConnectionContextStore.h b/xplat/Flipper/ConnectionContextStore.h index a8a2b0eb1..bc13898b4 100644 --- a/xplat/Flipper/ConnectionContextStore.h +++ b/xplat/Flipper/ConnectionContextStore.h @@ -7,9 +7,11 @@ #pragma once +#include #include #include #include +#include "FlipperCertificateExchangeMedium.h" #include "FlipperInitConfig.h" namespace facebook { @@ -24,6 +26,10 @@ class ConnectionContextStore { std::string getCertificateDirectoryPath(); std::string getCACertificatePath(); std::string getDeviceId(); + /** + * Get medium over which the certificate was received. + */ + folly::Optional getLastKnownMedium(); void storeConnectionConfig(folly::dynamic& config); bool resetState(); diff --git a/xplat/Flipper/FlipperCertificateExchangeMedium.h b/xplat/Flipper/FlipperCertificateExchangeMedium.h index 552b081e5..0604dcd68 100644 --- a/xplat/Flipper/FlipperCertificateExchangeMedium.h +++ b/xplat/Flipper/FlipperCertificateExchangeMedium.h @@ -5,4 +5,6 @@ * LICENSE file in the root directory of this source tree. */ +#pragma once + enum FlipperCertificateExchangeMedium { FS_ACCESS = 1, WWW = 2 }; diff --git a/xplat/Flipper/FlipperConnectionManagerImpl.cpp b/xplat/Flipper/FlipperConnectionManagerImpl.cpp index 506db8580..a5ab36a35 100644 --- a/xplat/Flipper/FlipperConnectionManagerImpl.cpp +++ b/xplat/Flipper/FlipperConnectionManagerImpl.cpp @@ -357,6 +357,21 @@ bool FlipperConnectionManagerImpl::isCertificateExchangeNeeded() { return true; } + auto last_known_medium = contextStore_->getLastKnownMedium(); + if (!last_known_medium) { + return true; + } + + // When we exchange certs over WWW, we use a fake generated serial number and + // a virtual device. If medium changes to FS_ACCESS at some point, we should + // restart the exchange process to get the device ID of the real device. + int medium = certProvider_ != nullptr + ? certProvider_->getCertificateExchangeMedium() + : FlipperCertificateExchangeMedium::FS_ACCESS; + if (last_known_medium != medium) { + return true; + } + auto step = flipperState_->start("Check required certificates are present"); bool hasRequiredFiles = contextStore_->hasRequiredFiles(); if (hasRequiredFiles) { @@ -380,10 +395,10 @@ void FlipperConnectionManagerImpl::requestSignedCertFromFlipper() { certificateExchangeCompleted_ = false; - flipperEventBase_->add([this, message, gettingCert]() { + flipperEventBase_->add([this, message, gettingCert, medium]() { client_->sendExpectResponse( folly::toJson(message), - [this, message, gettingCert]( + [this, message, gettingCert, medium]( const std::string& response, bool isError) { /** Need to keep track of whether the response has been handled. @@ -412,6 +427,7 @@ void FlipperConnectionManagerImpl::requestSignedCertFromFlipper() { } if (!response.empty()) { folly::dynamic config = folly::parseJson(response); + config["medium"] = medium; contextStore_->storeConnectionConfig(config); } if (certProvider_) {