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
This commit is contained in:
Andrey Goncharov
2021-12-17 03:53:44 -08:00
committed by Facebook GitHub Bot
parent 95529e3d6e
commit 6a8135af38
4 changed files with 42 additions and 2 deletions

View File

@@ -6,6 +6,7 @@
*/
#include "ConnectionContextStore.h"
#include <folly/Optional.h>
#include <folly/json.h>
#include <folly/portability/SysStat.h>
#include <openssl/err.h>
@@ -110,6 +111,21 @@ std::string ConnectionContextStore::getDeviceId() {
}
}
folly::Optional<FlipperCertificateExchangeMedium>
ConnectionContextStore::getLastKnownMedium() {
try {
std::string config =
loadStringFromFile(absoluteFilePath(CONNECTION_CONFIG_FILE));
auto maybeMedium = folly::parseJson(config)["medium"];
return maybeMedium.isInt()
? folly::Optional<FlipperCertificateExchangeMedium>{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));

View File

@@ -7,9 +7,11 @@
#pragma once
#include <folly/Optional.h>
#include <folly/dynamic.h>
#include <folly/io/async/SSLContext.h>
#include <string>
#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<FlipperCertificateExchangeMedium> getLastKnownMedium();
void storeConnectionConfig(folly::dynamic& config);
bool resetState();

View File

@@ -5,4 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/
#pragma once
enum FlipperCertificateExchangeMedium { FS_ACCESS = 1, WWW = 2 };

View File

@@ -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_) {