mirror of
https://github.com/confirmedcode/Lockdown-iOS.git
synced 2025-12-21 12:14:02 +01:00
145 lines
5.8 KiB
Swift
145 lines
5.8 KiB
Swift
//
|
|
// FirewallRepair.swift
|
|
// Lockdown
|
|
//
|
|
// Created by Oleg Dreyman on 21.10.2020.
|
|
// Copyright © 2020 Confirmed Inc. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import CocoaLumberjackSwift
|
|
import BackgroundTasks
|
|
|
|
enum FirewallRepair {
|
|
|
|
static let identifier = "com.confirmed.lockdown.firewallscheduler"
|
|
|
|
enum Result {
|
|
case repairAttempted
|
|
case failed(Swift.Error?)
|
|
case noAction
|
|
}
|
|
|
|
enum Context: CustomDebugStringConvertible {
|
|
case backgroundRefresh
|
|
case homeScreenDidLoad
|
|
|
|
var debugDescription: String {
|
|
switch self {
|
|
case .backgroundRefresh:
|
|
return "Background Check"
|
|
case .homeScreenDidLoad:
|
|
return "Home"
|
|
}
|
|
}
|
|
}
|
|
|
|
@available(iOS 13.0, *)
|
|
static func handleAppRefresh(_ task: BGTask) {
|
|
DDLogInfo("BGTask: Handle App Refresh called")
|
|
|
|
let queue = OperationQueue()
|
|
queue.maxConcurrentOperationCount = 1
|
|
|
|
let operation = BlockOperation {
|
|
DDLogInfo("BGTask: Operation started")
|
|
FirewallRepair.run(context: .backgroundRefresh) { (result) in
|
|
DDLogInfo("BGTask: Result: \(result)")
|
|
}
|
|
}
|
|
operation.completionBlock = {
|
|
DDLogInfo("BGTask: Operation completion block")
|
|
let success = !operation.isCancelled
|
|
DDLogInfo("BGTask: Operation completion success: \(success)")
|
|
task.setTaskCompleted(success: success)
|
|
}
|
|
|
|
queue.addOperation(operation)
|
|
|
|
task.expirationHandler = {
|
|
DDLogError("BGTask: Expiration Handler called")
|
|
queue.cancelAllOperations()
|
|
}
|
|
|
|
FirewallRepair.reschedule()
|
|
}
|
|
|
|
static func reschedule() {
|
|
if #available(iOS 13.0, *) {
|
|
DDLogInfo("BGTask: Cancelling all task requests")
|
|
BGTaskScheduler.shared.cancelAllTaskRequests()
|
|
|
|
let timeIntervalSeconds: Double = 3600
|
|
|
|
let request = BGAppRefreshTaskRequest(identifier: FirewallRepair.identifier)
|
|
request.earliestBeginDate = Date(timeIntervalSinceNow: timeIntervalSeconds)
|
|
DDLogInfo("BGTask: Scheduling app refresh id: \(FirewallRepair.identifier), earliest date \(Date(timeIntervalSinceNow: TimeInterval(timeIntervalSeconds)))")
|
|
do {
|
|
try BGTaskScheduler.shared.submit(request)
|
|
} catch {
|
|
DDLogError("Could not schedule app refresh: \(error)")
|
|
}
|
|
}
|
|
else {
|
|
DDLogInfo("BGTask: Not iOS 13, not calling reschedule")
|
|
}
|
|
}
|
|
|
|
static func run(context: Context, completion: @escaping (FirewallRepair.Result) -> Void = { _ in }) {
|
|
DDLogInfo("Repair \(context): Starting")
|
|
|
|
// Check 2 conditions for firewall restart, but reload manager first to get non-stale one
|
|
FirewallController.shared.refreshManager(completion: { error in
|
|
if let e = error {
|
|
DDLogError("Repair \(context): Error refreshing Manager in \(context): \(e)")
|
|
completion(.failed(e))
|
|
return
|
|
}
|
|
DDLogInfo("Repair \(context): refreshed manager")
|
|
DDLogInfo("Repair \(context): userWantsFirewallEnabled \(getUserWantsFirewallEnabled())")
|
|
DDLogInfo("Repair \(context): firewallStatus \(FirewallController.shared.status())")
|
|
if getUserWantsFirewallEnabled() && (FirewallController.shared.status() == .connected || FirewallController.shared.status() == .invalid || FirewallController.shared.status() == .disconnected) {
|
|
DDLogInfo("Repair \(context): user wants enabled")
|
|
if (appHasJustBeenUpgradedOrIsNewInstall()) {
|
|
DDLogInfo("Repair \(context): APP UPGRADED, REFRESHING DEFAULT BLOCK LISTS, WHITELISTS, RESTARTING FIREWALL")
|
|
setupFirewallDefaultBlockLists()
|
|
setupLockdownWhitelistedDomains()
|
|
FirewallController.shared.restart(completion: {
|
|
error in
|
|
if error != nil {
|
|
DDLogError("Error restarting firewall on \(context): \(error!)")
|
|
}
|
|
completion(.repairAttempted)
|
|
})
|
|
}
|
|
else {
|
|
Client.getBlockedDomainTest().done {
|
|
DDLogError("Repair \(context): Repair Fetch Test Failed: Connected to \(testFirewallDomain) even though it's supposed to be blocked")
|
|
DDLogError("Repair \(context): Doing repair")
|
|
FirewallController.shared.restart(completion: {
|
|
error in
|
|
if error != nil {
|
|
DDLogError("Repair \(context): Error restarting firewall on \(context): \(error!)")
|
|
}
|
|
DDLogError("Repair \(context): Returned from restart, no error")
|
|
completion(.repairAttempted)
|
|
})
|
|
}.catch { error in
|
|
let nsError = error as NSError
|
|
if nsError.domain == NSURLErrorDomain {
|
|
DDLogInfo("Repair \(context): Successful blocking of \(testFirewallDomain) with NSURLErrorDomain error: \(nsError)")
|
|
}
|
|
else {
|
|
DDLogInfo("Repair \(context): Successful blocking of \(testFirewallDomain), but seeing non-NSURLErrorDomain error: \(error)")
|
|
}
|
|
completion(.repairAttempted)
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
completion(.noAction)
|
|
}
|
|
})
|
|
}
|
|
}
|