Skip to content

Commit

Permalink
feat: Self update fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
dz0ny committed Feb 5, 2025
1 parent 3da34dc commit 5bcb3e0
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 42 deletions.
10 changes: 10 additions & 0 deletions Pareto Security.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,10 @@
4FDA93A32771D9FC00F9D8B4 /* Checks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FDA93A22771D9FC00F9D8B4 /* Checks.swift */; };
4FDA93A42771D9FC00F9D8B4 /* Checks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FDA93A22771D9FC00F9D8B4 /* Checks.swift */; };
4FDAD88F26EB784A00F64E61 /* License.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FDAD88E26EB784A00F64E61 /* License.swift */; };
4FDDE1972D53BA3200D9E853 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FDDE1962D53BA3200D9E853 /* String.swift */; };
4FDDE1982D53BA3200D9E853 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FDDE1962D53BA3200D9E853 /* String.swift */; };
4FDDE1992D53BA3200D9E853 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FDDE1962D53BA3200D9E853 /* String.swift */; };
4FDDE19A2D53BA3200D9E853 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FDDE1962D53BA3200D9E853 /* String.swift */; };
4FE23EED276BB13700CA9BA0 /* FollowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FE23EEC276BB13700CA9BA0 /* FollowView.swift */; };
4FE23EEE276BB13700CA9BA0 /* FollowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FE23EEC276BB13700CA9BA0 /* FollowView.swift */; };
4FE9C35A28B76117002C28FE /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FE9C35928B76117002C28FE /* User.swift */; };
Expand Down Expand Up @@ -392,6 +396,7 @@
4FD0A24026A024440070BED4 /* Gatekeeper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Gatekeeper.swift; sourceTree = "<group>"; };
4FDA93A22771D9FC00F9D8B4 /* Checks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Checks.swift; sourceTree = "<group>"; };
4FDAD88E26EB784A00F64E61 /* License.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = License.swift; sourceTree = "<group>"; };
4FDDE1962D53BA3200D9E853 /* String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = String.swift; sourceTree = "<group>"; };
4FE23EEC276BB13700CA9BA0 /* FollowView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FollowView.swift; sourceTree = "<group>"; };
4FE9C35928B76117002C28FE /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = "<group>"; };
4FEBA2EE269CD48F009B2469 /* Pareto Security.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Pareto Security.app"; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -633,6 +638,7 @@
4FB7C67F26AFF22C00FB1C41 /* Extensions */ = {
isa = PBXGroup;
children = (
4FDDE1962D53BA3200D9E853 /* String.swift */,
4F4E23B42C4E484500484782 /* Trim.swift */,
4F6A2CE529CDC7C800B653C2 /* SSHCheck.swift */,
4FB7C68026AFF25300FB1C41 /* Date.swift */,
Expand Down Expand Up @@ -1074,6 +1080,7 @@
4F38D8C9273AC5AE00671756 /* IntroView.swift in Sources */,
4F9A444D29264FC10095BB6C /* 1Password8.swift in Sources */,
4F37E71D2718122E00A2B254 /* Defaults.swift in Sources */,
4FDDE1982D53BA3200D9E853 /* String.swift in Sources */,
4F37E71E2718122E00A2B254 /* Autologin.swift in Sources */,
4F38D8CF273AC62500671756 /* EndView.swift in Sources */,
4F8ECA382798262F00361728 /* FirewallStealth.swift in Sources */,
Expand Down Expand Up @@ -1141,6 +1148,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4FDDE1972D53BA3200D9E853 /* String.swift in Sources */,
4F6A92F226C555C6006C2F2D /* ParetoSecurityUITests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -1150,6 +1158,7 @@
buildActionMask = 2147483647;
files = (
4F84A94426CBBA6900A1579D /* SettingsTests.swift in Sources */,
4FDDE19A2D53BA3200D9E853 /* String.swift in Sources */,
4F57135326F8A6AC004B4359 /* LicenseTest.swift in Sources */,
4F6EF8992760046100752559 /* SoftwareUpdatesTest.swift in Sources */,
4F57135526F8ACCC004B4359 /* WelcomeTest.swift in Sources */,
Expand Down Expand Up @@ -1212,6 +1221,7 @@
4F38D8C8273AC5AE00671756 /* IntroView.swift in Sources */,
4F9A444C29264FC10095BB6C /* 1Password8.swift in Sources */,
4F47221026B08A0E0071CE2A /* Defaults.swift in Sources */,
4FDDE1992D53BA3200D9E853 /* String.swift in Sources */,
4F868DD126A5C51C005B876E /* Autologin.swift in Sources */,
4F38D8CE273AC62500671756 /* EndView.swift in Sources */,
4F8ECA372798262F00361728 /* FirewallStealth.swift in Sources */,
Expand Down
6 changes: 5 additions & 1 deletion Pareto/Checks/Access Security/PasswordManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,11 @@ class PasswordManager: ParetoCheck {
let browserExtensions = [
"LastPass",
"ProtonPass",
"NordPass"
"NordPass",
"Bitwarden",
"1Password",
"KeePass",
"Dashlane",
]

let browsers = [
Expand Down
8 changes: 3 additions & 5 deletions Pareto/Checks/System Integrity/TimeMachine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,18 @@ class TimeMachineCheck: ParetoCheck {

override public func debugInfo() -> String {
let tmutil = runCMD(app: "/usr/bin/tmutil", args: ["destinationinfo"])
return "tmutil:\n\(tmutil)\nTimeMachine: \(dict as AnyObject)"
return "tmutil:\n\(tmutil)\nTimeMachine: \(readDefaultsFile(path: "/Library/Preferences/com.apple.TimeMachine.plist") as! [String: Any]? as AnyObject)"
}

var isConfigured: Bool {
let status = runCMD(app: "/usr/bin/tmutil", args: ["destinationinfo"])
return status.contains("ID") && status.contains("Name")
}

private var dict: [String: Any]? {
readDefaultsFile(path: "/Library/Preferences/com.apple.TimeMachine.plist") as! [String: Any]?
}


override func checkPasses() -> Bool {
guard let settings = dict else {
guard let settings = readDefaultsFile(path: "/Library/Preferences/com.apple.TimeMachine.plist") as! [String: Any]? else {
os_log("/Library/Preferences/com.apple.TimeMachine.plist use fallback")
let status = runCMD(app: "/usr/bin/tmutil", args: ["status"])
return isConfigured && !status.contains("Stopping = 1")
Expand Down
14 changes: 3 additions & 11 deletions Pareto/Checks/System Integrity/TimeMachineHasBackup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,16 @@ class TimeMachineHasBackupCheck: ParetoCheck {
"Time Machine is missing up to date backup"
}

private var dict: [String: Any]? {
readDefaultsFile(path: "/Library/Preferences/com.apple.TimeMachine.plist") as! [String: Any]?
}

override public var isRunnable: Bool {
return dict != nil && isActive
}

override public var showSettings: Bool {
return dict != nil
return readDefaultsFile(path: "/Library/Preferences/com.apple.TimeMachine.plist") as! [String: Any]? != nil
}

override public var showSettingsWarnDiskAccess: Bool {
return true && dict == nil
return true && readDefaultsFile(path: "/Library/Preferences/com.apple.TimeMachine.plist") as! [String: Any]? == nil
}

override func checkPasses() -> Bool {
guard let settings = dict else {
guard let settings = readDefaultsFile(path: "/Library/Preferences/com.apple.TimeMachine.plist") as! [String: Any]? else {
os_log("/Library/Preferences/com.apple.TimeMachine.plist is empty")
return false
}
Expand Down
22 changes: 3 additions & 19 deletions Pareto/Checks/System Integrity/TimeMachineIsEncrypted.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,32 +21,16 @@ class TimeMachineIsEncryptedCheck: ParetoCheck {
"Time Machine backup is not encrypted"
}

private var dict: [String: Any]? {
readDefaultsFile(path: "/Library/Preferences/com.apple.TimeMachine.plist") as! [String: Any]?
}

override public var isRunnable: Bool {
guard let settings = dict else {
return false
}

if isActive {
let tmConf = TimeMachineConfig(dict: settings)
return tmConf.canCheckIsEncryptedBackup
}
return false
}

override public var showSettings: Bool {
return dict != nil
return readDefaultsFile(path: "/Library/Preferences/com.apple.TimeMachine.plist") as! [String: Any]? != nil
}

override public var showSettingsWarnDiskAccess: Bool {
return true && dict == nil
return true && readDefaultsFile(path: "/Library/Preferences/com.apple.TimeMachine.plist") as! [String: Any]? == nil
}

override func checkPasses() -> Bool {
guard let settings = dict else {
guard let settings = readDefaultsFile(path: "/Library/Preferences/com.apple.TimeMachine.plist") as! [String: Any]? else {
os_log("/Library/Preferences/com.apple.TimeMachine.plist is empty")
return false
}
Expand Down
6 changes: 6 additions & 0 deletions Pareto/Extensions/String.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,10 @@ extension String {
var isUUID: Bool {
return UUID(uuidString: self) != nil
}
/// Escapes the string for safe shell usage.
func shellEscaped() -> String {
// Replace any single quote with an escaped version
let escaped = self.replacingOccurrences(of: "'", with: "'\\''")
return "'\(escaped)'"
}
}
2 changes: 1 addition & 1 deletion Pareto/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>5504</string>
<string>5523</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSMinimumSystemVersion</key>
Expand Down
49 changes: 47 additions & 2 deletions Pareto/ParetoApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,53 @@ class AppDelegate: AppHandlers, NSApplicationDelegate {
}
}
}

func killOtherInstances() {
let bundleID = Bundle.main.bundleIdentifier!
let currentProcessID = ProcessInfo.processInfo.processIdentifier

let runningApps = NSRunningApplication.runningApplications(withBundleIdentifier: bundleID)

for app in runningApps {
if app.processIdentifier != currentProcessID {
app.forceTerminate()
print("Terminated instance with PID: \(app.processIdentifier)")
}
}
}

func moveToApplicationsFolderIfNeeded() {
let fileManager = FileManager.default
let bundlePath = Bundle.main.bundlePath
let destinationPath = "/Applications/\(bundlePath.components(separatedBy: "/").last!)"

// Check if the app is already in /Applications
if bundlePath == destinationPath {
killOtherInstances()
}

// Ensure that the destination does not already exist
if fileManager.fileExists(atPath: destinationPath) {
try? fileManager.removeItem(atPath: destinationPath)
}

do {
try fileManager.moveItem(atPath: bundlePath, toPath: destinationPath)
print("Moved app to /Applications")

// Relaunch from the new location
let task = Process()
task.launchPath = "/usr/bin/open"
task.arguments = [destinationPath]
task.launch()


} catch {
print("Failed to move the app: \(error)")
}
exit(0) // Terminate old instance
}

func applicationWillFinishLaunching(_: Notification) {
if CommandLine.arguments.contains("-export") {
var export: [String: [String: [String]]] = [:]
Expand All @@ -51,8 +97,7 @@ class AppDelegate: AppHandlers, NSApplicationDelegate {
}

if CommandLine.arguments.contains("-update") {
doUpdateCheck()
exit(0)
moveToApplicationsFolderIfNeeded()
}

if CommandLine.arguments.contains("-report") {
Expand Down
11 changes: 8 additions & 3 deletions Pareto/Updater.swift
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,13 @@ public class AppUpdater {


static func runCMDasAdmin(cmd: String) -> Bool {
let myAppleScript = "do shell script \"\(cmd)\" with administrator privileges"
let code =
"""
do shell script "\(cmd)" with administrator privileges
"""
os_log("\(code)")
var error: NSDictionary?
if let scriptObject = NSAppleScript(source: myAppleScript) {
if let scriptObject = NSAppleScript(source: code) {
scriptObject.executeAndReturnError(&error)
if error != nil {
os_log("OSA Error: %{public}s", error.debugDescription)
Expand All @@ -186,7 +190,8 @@ public class AppUpdater {
try downloadedAppBundle.path.move(to: installedAppBundle.path)
os_log("Move new app to installedAppBundle: \(installedAppBundle)")
} else {
AppUpdater.runCMDasAdmin(cmd: "'\(downloadedAppBundle.path)/MacOS/Pareto Security -update'")
let path = "\(downloadedAppBundle.path)/Contents/MacOS/Pareto Security".shellEscaped()
AppUpdater.runCMDasAdmin(cmd: "\(path) -update")

Check warning on line 194 in Pareto/Updater.swift

View workflow job for this annotation

GitHub Actions / Build and Archive SetApp

result of call to 'runCMDasAdmin(cmd:)' is unused

Check warning on line 194 in Pareto/Updater.swift

View workflow job for this annotation

GitHub Actions / Build and Archive SetApp

result of call to 'runCMDasAdmin(cmd:)' is unused

Check warning on line 194 in Pareto/Updater.swift

View workflow job for this annotation

GitHub Actions / Build and Archive Native

result of call to 'runCMDasAdmin(cmd:)' is unused

Check warning on line 194 in Pareto/Updater.swift

View workflow job for this annotation

GitHub Actions / Build and Archive Native

result of call to 'runCMDasAdmin(cmd:)' is unused
return
}

Expand Down

0 comments on commit 5bcb3e0

Please sign in to comment.