Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions FlowCrypt.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,18 @@
04B472951ECE29F600B8266F /* MyMenuViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B472921ECE29F600B8266F /* MyMenuViewController.swift */; };
04B472961ECE29F600B8266F /* SideMenuNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B472931ECE29F600B8266F /* SideMenuNavigationController.swift */; };
211392A5266511E6009202EC /* PubLookup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 211392A4266511E6009202EC /* PubLookup.swift */; };
2133D51626A0571F00CC686F /* ClientConfigurationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2133D51526A0571F00CC686F /* ClientConfigurationService.swift */; };
2133D51826A1E45400CC686F /* DecryptedPrivateKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2133D51726A1E45300CC686F /* DecryptedPrivateKey.swift */; };
21489B78267CB42400BDE4AC /* ClientConfigurationProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B77267CB42400BDE4AC /* ClientConfigurationProvider.swift */; };
21489B7A267CB4DF00BDE4AC /* ClientConfigurationObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B79267CB4DF00BDE4AC /* ClientConfigurationObject.swift */; };
21489B7C267CBA0E00BDE4AC /* ClientConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B7B267CBA0E00BDE4AC /* ClientConfiguration.swift */; };
21489B80267CC39E00BDE4AC /* OrganisationalRulesService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B7F267CC39E00BDE4AC /* OrganisationalRulesService.swift */; };
21489B83267CC99C00BDE4AC /* OrganisationalRulesServiceError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21489B82267CC99C00BDE4AC /* OrganisationalRulesServiceError.swift */; };
214A023A26A3029700C24066 /* EmailKeyManagerApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = 214A023926A3029700C24066 /* EmailKeyManagerApi.swift */; };
215002A32690B1DD00980DDD /* client_configuraion_with_unknown_flag.json in Resources */ = {isa = PBXBuildFile; fileRef = 215002A22690B1DD00980DDD /* client_configuraion_with_unknown_flag.json */; };
215897E8267A553300423694 /* FilesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 215897E7267A553200423694 /* FilesManager.swift */; };
2196A2202684B9BE001B9E00 /* URLExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2196A21F2684B9BE001B9E00 /* URLExtension.swift */; };
21B15C9426AA00A400D8522B /* ClientConfigurationServiceResults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21B15C9326AA00A400D8522B /* ClientConfigurationServiceResults.swift */; };
21C7DEFC26669A3700C44800 /* CalendarExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21C7DEFB26669A3700C44800 /* CalendarExtension.swift */; };
21C7DEFE26669CE100C44800 /* DateFormattingExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F56BD3723438C7000A7371A /* DateFormattingExtensions.swift */; };
21C7DF0526697DA500C44800 /* PromiseKitExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21C7DF0426697DA500C44800 /* PromiseKitExtension.swift */; };
Expand Down Expand Up @@ -367,16 +371,20 @@
113F04B20ECC35FC59A81A6C /* Pods-FlowCryptTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FlowCryptTests.release.xcconfig"; path = "Target Support Files/Pods-FlowCryptTests/Pods-FlowCryptTests.release.xcconfig"; sourceTree = "<group>"; };
11C1375F41411882DC4C9431 /* Pods-FlowCryptUIApplication.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FlowCryptUIApplication.release.xcconfig"; path = "Target Support Files/Pods-FlowCryptUIApplication/Pods-FlowCryptUIApplication.release.xcconfig"; sourceTree = "<group>"; };
211392A4266511E6009202EC /* PubLookup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PubLookup.swift; sourceTree = "<group>"; };
2133D51526A0571F00CC686F /* ClientConfigurationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientConfigurationService.swift; sourceTree = "<group>"; };
2133D51726A1E45300CC686F /* DecryptedPrivateKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecryptedPrivateKey.swift; sourceTree = "<group>"; };
21489B6A267B7BD800BDE4AC /* FilesManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilesManagerTests.swift; sourceTree = "<group>"; };
21489B6D267B7D5000BDE4AC /* FileMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileMock.swift; sourceTree = "<group>"; };
21489B77267CB42400BDE4AC /* ClientConfigurationProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientConfigurationProvider.swift; sourceTree = "<group>"; };
21489B79267CB4DF00BDE4AC /* ClientConfigurationObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientConfigurationObject.swift; sourceTree = "<group>"; };
21489B7B267CBA0E00BDE4AC /* ClientConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientConfiguration.swift; sourceTree = "<group>"; };
21489B7F267CC39E00BDE4AC /* OrganisationalRulesService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrganisationalRulesService.swift; sourceTree = "<group>"; };
21489B82267CC99C00BDE4AC /* OrganisationalRulesServiceError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrganisationalRulesServiceError.swift; sourceTree = "<group>"; };
214A023926A3029700C24066 /* EmailKeyManagerApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmailKeyManagerApi.swift; sourceTree = "<group>"; };
215002A22690B1DD00980DDD /* client_configuraion_with_unknown_flag.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = client_configuraion_with_unknown_flag.json; sourceTree = "<group>"; };
215897E7267A553200423694 /* FilesManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FilesManager.swift; sourceTree = "<group>"; };
2196A21F2684B9BE001B9E00 /* URLExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLExtension.swift; sourceTree = "<group>"; };
21B15C9326AA00A400D8522B /* ClientConfigurationServiceResults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientConfigurationServiceResults.swift; sourceTree = "<group>"; };
21C7DEFB26669A3700C44800 /* CalendarExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarExtension.swift; sourceTree = "<group>"; };
21C7DF0426697DA500C44800 /* PromiseKitExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromiseKitExtension.swift; sourceTree = "<group>"; };
21C7DF08266C0D8F00C44800 /* EnterpriseServerApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnterpriseServerApi.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -795,9 +803,11 @@
21489B81267CC3BC00BDE4AC /* Organisational Rules Service */ = {
isa = PBXGroup;
children = (
2133D51526A0571F00CC686F /* ClientConfigurationService.swift */,
21489B77267CB42400BDE4AC /* ClientConfigurationProvider.swift */,
21489B7F267CC39E00BDE4AC /* OrganisationalRulesService.swift */,
21489B82267CC99C00BDE4AC /* OrganisationalRulesServiceError.swift */,
21B15C9326AA00A400D8522B /* ClientConfigurationServiceResults.swift */,
);
path = "Organisational Rules Service";
sourceTree = "<group>";
Expand Down Expand Up @@ -997,6 +1007,7 @@
32DCAC9C0512037018F434A1 /* BackendApi.swift */,
21EFF61E265A5C6700AB0B71 /* WKDURLsApi.swift */,
21C7DF08266C0D8F00C44800 /* EnterpriseServerApi.swift */,
214A023926A3029700C24066 /* EmailKeyManagerApi.swift */,
D274724024F97C5C006BA6EF /* CacheService.swift */,
C132B9CA1EC2DE6400763715 /* GeneralConstants.swift */,
9FB22CFD25715DDF0026EE64 /* Key Services */,
Expand Down Expand Up @@ -1584,6 +1595,7 @@
D212D35C24C1AACF00035991 /* PrvKeyInfo.swift */,
D2E26F6B24F25B1F00612AF1 /* KeyAlgo.swift */,
9FC7EAB2266A404D00F3BF5D /* PassPhraseObject.swift */,
2133D51726A1E45300CC686F /* DecryptedPrivateKey.swift */,
);
path = Models;
sourceTree = "<group>";
Expand Down Expand Up @@ -2485,9 +2497,12 @@
D2F6D147243506DA00DB4065 /* MailSettingsCredentials.swift in Sources */,
9F9361A52573CE260009912F /* MessageProvider.swift in Sources */,
32DCA2BB910FA1B19BA8B328 /* Imap.swift in Sources */,
2133D51626A0571F00CC686F /* ClientConfigurationService.swift in Sources */,
D274724424FD1932006BA6EF /* FolderObject.swift in Sources */,
21B15C9426AA00A400D8522B /* ClientConfigurationServiceResults.swift in Sources */,
9FE1B3802563F85400D6D086 /* MessagesListProvider.swift in Sources */,
32DCA1B95DDC04D671F662F8 /* URLSessionExtension.swift in Sources */,
214A023A26A3029700C24066 /* EmailKeyManagerApi.swift in Sources */,
D2E26F7424F2705B00612AF1 /* ContactDetailDecorator.swift in Sources */,
21C7DF0526697DA500C44800 /* PromiseKitExtension.swift in Sources */,
9F7E8F19269C538E0021C07F /* NavigationChildController.swift in Sources */,
Expand Down Expand Up @@ -2551,6 +2566,7 @@
9F9362192573D10E0009912F /* Imap+Message.swift in Sources */,
32DCA9C61ABB3234649B374E /* CoreHost.swift in Sources */,
9F41FA28253B75F4003B970D /* BackupSelectKeyViewController.swift in Sources */,
2133D51826A1E45400CC686F /* DecryptedPrivateKey.swift in Sources */,
21489B83267CC99C00BDE4AC /* OrganisationalRulesServiceError.swift in Sources */,
D2F6D1402435008500DB4065 /* SessionCredentialsProvider.swift in Sources */,
9F9ABC8723AC1EAA00D560E3 /* MessageContext.swift in Sources */,
Expand Down
76 changes: 61 additions & 15 deletions FlowCrypt/Controllers/Setup/SetupInitialViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,19 @@ final class SetupInitialViewController: TableNodeViewController {
}

private enum State {
case idle, searching, noKeyBackups, error(Error)
case idle, decidingIfEKMshouldBeUsed, fetchingKeysFromEKM, searchingKeyBackupsInInbox, noKeyBackupsInInbox, error(Error)

var numberOfRows: Int {
switch self {
// title
case .idle:
case .idle, .decidingIfEKMshouldBeUsed, .fetchingKeysFromEKM:
return 1
// title, loading
case .searching:
case .searchingKeyBackupsInInbox:
return 2
case .error:
return 3
case .noKeyBackups:
case .noKeyBackupsInInbox:
return Parts.allCases.count
}
}
Expand All @@ -54,6 +54,8 @@ final class SetupInitialViewController: TableNodeViewController {
private let router: GlobalRouterType
private let decorator: SetupViewDecorator
private let organisationalRules: OrganisationalRules
private let emailKeyManagerApi: EmailKeyManagerApiType
private let clientConfigurationService: ClientConfigurationServiceType

private lazy var logger = Logger.nested(in: Self.self, with: .setup)

Expand All @@ -62,13 +64,17 @@ final class SetupInitialViewController: TableNodeViewController {
backupService: BackupServiceType = BackupService(),
router: GlobalRouterType = GlobalRouter(),
decorator: SetupViewDecorator = SetupViewDecorator(),
organisationalRulesService: OrganisationalRulesServiceType = OrganisationalRulesService()
organisationalRulesService: OrganisationalRulesServiceType = OrganisationalRulesService(),
emailKeyManagerApi: EmailKeyManagerApiType = EmailKeyManagerApi(),
clientConfigurationService: ClientConfigurationServiceType = ClientConfigurationService()
) {
self.user = user
self.backupService = backupService
self.router = router
self.decorator = decorator
self.organisationalRules = organisationalRulesService.getSavedOrganisationalRulesForCurrentUser()
self.emailKeyManagerApi = emailKeyManagerApi
self.clientConfigurationService = clientConfigurationService

super.init(node: TableNode())
}
Expand All @@ -86,7 +92,7 @@ final class SetupInitialViewController: TableNodeViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
setNeedsStatusBarAppearanceUpdate()
state = .searching
state = .decidingIfEKMshouldBeUsed
}
}

Expand All @@ -97,15 +103,19 @@ extension SetupInitialViewController {
logger.logInfo("Changed to new state \(state)")

switch state {
case .searching:
searchBackups()
default:
case .searchingKeyBackupsInInbox:
searchKeyBackupsInInbox()
case .decidingIfEKMshouldBeUsed:
decideIfEKMshouldBeUsed()
case .fetchingKeysFromEKM:
fetchKeysFromEKM()
case .error, .idle, .noKeyBackupsInInbox:
break
}
node.reloadData()
}

private func searchBackups() {
private func searchKeyBackupsInInbox() {
if !organisationalRules.canBackupKeys {
logger.logInfo("Skipping backups searching because canBackupKeys == false")
proceedToSetupWith(keys: [])
Expand All @@ -131,6 +141,42 @@ extension SetupInitialViewController {
handleCommon(error: error)
state = .error(error)
}

private func decideIfEKMshouldBeUsed() {
switch clientConfigurationService.checkShouldUseEKM() {
case .usesEKM:
state = .fetchingKeysFromEKM
case .doesNotUseEKM:
state = .searchingKeyBackupsInInbox
case .inconsistentClientConfiguration(let message):
showAlert(message: message) { [weak self] in
self?.router.signOut()
}
}
}

private func fetchKeysFromEKM() {
emailKeyManagerApi.getPrivateKeys()
.then { [weak self] result in
guard let urlString = self?.emailKeyManagerApi.getPrivateKeysUrlString() else {
fatalError("Private keys URL can not be nil at this point")
}
self?.showToast(
"organisational_rules_ekm_private_keys_message".localizeWithArguments(result.privateKeys.count, urlString)
)
// todo - this is temporary, until we finish EKM integration
// instead we should use the keys from EKM for setup
self?.state = .searchingKeyBackupsInInbox
}
.catch { [weak self] error in
if case .noPrivateKeysUrlString = error as? EmailKeyManagerApiError {
return
}
self?.showAlert(message: error.localizedDescription, onOk: {
self?.state = .decidingIfEKMshouldBeUsed
})
}
}
}

// MARK: - ASTableDelegate, ASTableDataSource
Expand All @@ -144,13 +190,13 @@ extension SetupInitialViewController: ASTableDelegate, ASTableDataSource {
guard let self = self else { return ASCellNode() }

switch self.state {
case .idle:
case .idle, .decidingIfEKMshouldBeUsed, .fetchingKeysFromEKM:
return ASCellNode()
case .searching:
case .searchingKeyBackupsInInbox:
return self.searchStateNode(for: indexPath)
case .error(let error):
return self.errorStateNode(for: indexPath, error: error)
case .noKeyBackups:
case .noKeyBackupsInInbox:
return self.noKeysStateNode(for: indexPath)
}
}
Expand Down Expand Up @@ -245,7 +291,7 @@ extension SetupInitialViewController {
)
case 2:
return ButtonCellNode(input: .retry) { [weak self] in
self?.state = .searching
self?.state = .searchingKeyBackupsInInbox
}
default:
return ASCellNode()
Expand All @@ -270,7 +316,7 @@ extension SetupInitialViewController {

if keys.isEmpty {
logger.logInfo("No key backups found in inbox")
state = .noKeyBackups
state = .noKeyBackupsInInbox
} else {
logger.logInfo("\(keys.count) key backups found in inbox")
let viewController = SetupBackupsViewController(fetchedEncryptedKeys: keys, user: user)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ protocol NavigationChildController {

extension NavigationChildController where Self: UIViewController {
var shouldShowBackButton: Bool { true }
func handleBackButtonTap() { }
func handleBackButtonTap() {}
}
21 changes: 21 additions & 0 deletions FlowCrypt/Core/Models/DecryptedPrivateKey.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// DecryptedPrivateKey.swift
// FlowCrypt
//
// Created by Yevhen Kyivskyi on 16.07.2021.
// Copyright © 2021 FlowCrypt Limited. All rights reserved.
//

import Foundation

struct DecryptedPrivateKeysResponse: Decodable {

let privateKeys: [DecryptedPrivateKey]

static let empty = DecryptedPrivateKeysResponse(privateKeys: [])
}

struct DecryptedPrivateKey: Decodable {

let decryptedPrivateKey: String
}
3 changes: 2 additions & 1 deletion FlowCrypt/Extensions/URLSessionExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ extension URLSession {
let status = res?.statusCode ?? GeneralConstants.Global.generalError
let urlMethod = urlRequest.httpMethod ?? "GET"
let urlString = urlRequest.url?.absoluteString ?? "??"
let message = "URLSession.call status:\(status) ms:\(trace.finish()) \(urlMethod) \(urlString)"
let headers = urlRequest.allHTTPHeaderFields ?? [:]
let message = "URLSession.call status:\(status) ms:\(trace.finish()) \(urlMethod) \(urlString), headers: \(headers)"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if printing request headers here would leak user credentials somewhere dangerous. @martgil is this a problem on iOS?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should not be any printing on production build, we need to check that in our Logger.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would highly suggest getting rid of the debug information on a production build. Printing the request headers alone even it contains sensitive information isn't a threat yet. An attacker needs physical access or required a network listener to exploit it. Nevertheless, @ekievsky is correct that there shouldn't be any debug logs on the production build.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ekievsky by "should not be printing" did you mean it does not print any in production build, or that it would be bad if it printed?

We'll have to be very clear about this - I'm making an issue to verify that it in fact does not print it in a production build.

Logger.nested("URLSession").logInfo(message)

let validStatusCode = 200 ... 299
Expand Down
2 changes: 1 addition & 1 deletion FlowCrypt/Functionality/Services/AttesterApi.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ extension AttesterApi {

if let value = token {
httpMethod = .post
headers = [URLHeader(value: "Authorization", httpHeaderField: "Bearer \(value)")]
headers = [URLHeader(value: "Bearer \(value)", httpHeaderField: "Authorization")]
} else {
httpMethod = .put
headers = []
Expand Down
Loading