Skip to content

Commit

Permalink
Update processing for file permissions check, added function for retu…
Browse files Browse the repository at this point in the history
…rning the owner and permissions of a file

Add check for file permission i the share folder and update as necessary
Fix up how overrides are processed. should fix #1 and #2
Fix global `console_user` - was using `NSUserName()` which returns the username of the process owner, not the console user
  • Loading branch information
bartreardon committed Jan 13, 2023
1 parent 6d3c2b0 commit 61c0900
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 37 deletions.
52 changes: 37 additions & 15 deletions swift/outset/outset/Functions/FileUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,22 @@ func ensure_shared_folder() {
writeLog("Something went wrong. \(share_dir) could not be created.", status: .error)
}
}

// Update permissions on files in share folder
let share_files = list_folder(path: share_dir)

for filename in share_files {
if get_file_owner_and_permissions(pathname: filename).permissions != filePermissions {
let attributes = [FileAttributeKey.posixPermissions: filePermissions]
do {
writeLog("Updating permissions of \(filename) to \(String(filePermissions.intValue, radix: 8, uppercase: false))", status: .debug)
try FileManager.default.setAttributes(attributes, ofItemAtPath: filename)
} catch {
writeLog("Failed to update permissions of \(filename) with error: \(error)", status: .error)
}
}
}

}

func check_file_exists(path: String, isDir: ObjCBool = false) -> Bool {
Expand All @@ -97,41 +113,46 @@ func list_folder(path: String) -> [String] {

func check_permissions(pathname :String) -> Bool {

var fileAttributes : [FileAttributeKey:Any]

do {
fileAttributes = try FileManager.default.attributesOfItem(atPath: pathname)// as Dictionary
} catch {
writeLog("Could not read file at path \(pathname)", status: .error)
return false
}

let ownerID = fileAttributes[.ownerAccountID] as! Int
let mode = fileAttributes[.posixPermissions] as! NSNumber
let (ownerID, mode) = get_file_owner_and_permissions(pathname: pathname) //fileAttributes[.ownerAccountID] as! Int
let posixPermissions = String(mode.intValue, radix: 8, uppercase: false)

writeLog("ownerID for \(pathname) : \(String(describing: ownerID))", status: .debug)
writeLog("posixPermissions for \(pathname) : \(String(describing: posixPermissions))", status: .debug)

if ["pkg", "mpkg", "dmg", "mobileconfig"].contains(pathname.lowercased().split(separator: ".").last) {
if ownerID == 0 && posixPermissions == "644" {
if ownerID == 0 && mode == filePermissions {
return true
} else {
writeLog("Permissions for \(pathname) are incorrect. Should be owned by root and with mode x644", status: .debug)
writeLog("Permissions for \(pathname) are incorrect. Should be owned by root and with mode x644", status: .error)
}
} else {
if ownerID == 0 && posixPermissions == "755" {
if ownerID == 0 && mode == executablePermissions {
return true
} else {
writeLog("Permissions for \(pathname) are incorrect. Should be owned by root and with mode x755", status: .debug)
writeLog("Permissions for \(pathname) are incorrect. Should be owned by root and with mode x755", status: .error)
}
}
return false
}

func get_file_owner_and_permissions(pathname: String) -> (ownerID : Int, permissions : NSNumber) {
var fileAttributes : [FileAttributeKey:Any]
var ownerID : Int = 0
var mode : NSNumber = 0
do {
fileAttributes = try FileManager.default.attributesOfItem(atPath: pathname)// as Dictionary
ownerID = fileAttributes[.ownerAccountID] as! Int
mode = fileAttributes[.posixPermissions] as! NSNumber
} catch {
writeLog("Could not read file at path \(pathname)", status: .error)
}
return (ownerID,mode)
}

func path_cleanup(pathname: String) {
// check if folder and clean all files in that folder
// Deletes given script or cleans folder
writeLog("Cleaning up \(pathname)", status: .debug)
if check_file_exists(path: pathname, isDir: true) {
for fileItem in list_folder(path: pathname) {
delete_file(fileItem)
Expand All @@ -144,6 +165,7 @@ func path_cleanup(pathname: String) {
}

func delete_file(_ path: String) {
writeLog("Deleting \(path)", status: .debug)
do {
try FileManager.default.removeItem(atPath: path)
writeLog("\(path) deleted", status: .debug)
Expand Down
24 changes: 14 additions & 10 deletions swift/outset/outset/Functions/Processing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func process_items(_ path: String, delete_items : Bool=false, once : Bool=false,
var packages : [String] = []
var scripts : [String] = []
var profiles : [String] = []
var runOnceDict : RunOncePlist = RunOncePlist()
var runOnceDict : [String:Date] = [:]

items_to_process = list_folder(path: path)

Expand All @@ -43,15 +43,17 @@ func process_items(_ path: String, delete_items : Bool=false, once : Bool=false,

for package in packages {
if once {
if !runOnceDict.override_login_once.contains(where: {$0.key == package}) {
if !runOnceDict.contains(where: {$0.key == package}) {
if install_package(pkg: package) {
runOnceDict.override_login_once.updateValue(Date(), forKey: package)
runOnceDict.updateValue(Date(), forKey: package)
}
} else {
if override.contains(where: {$0.key == package}) {
if override[package]! > runOnceDict.override_login_once[package]! {
writeLog("override for \(package) dated \(override[package]!)", status: .debug)
if override[package]! > runOnceDict[package]! {
writeLog("Actioning package override", status: .debug)
if install_package(pkg: package) {
runOnceDict.override_login_once.updateValue(Date(), forKey: package)
runOnceDict.updateValue(Date(), forKey: package)
}
}
}
Expand All @@ -72,22 +74,24 @@ func process_items(_ path: String, delete_items : Bool=false, once : Bool=false,

for script in scripts {
if once {
if !runOnceDict.override_login_once.contains(where: {$0.key == script}) {
if !runOnceDict.contains(where: {$0.key == script}) {
let (output, error, status) = runShellCommand(script, verbose: true)
if status != 0 {
writeLog(error, status: .error)
} else {
runOnceDict.override_login_once.updateValue(Date(), forKey: script)
runOnceDict.updateValue(Date(), forKey: script)
writeLog(output)
}
} else {
if override.contains(where: {$0.key == script}) {
if override[script]! > runOnceDict.override_login_once[script]! {
writeLog("override for \(script) dated \(override[script]!)", status: .debug)
if override[script]! > runOnceDict[script]! {
writeLog("Actioning script override", status: .debug)
let (output, error, status) = runShellCommand(script, verbose: true)
if status != 0 {
writeLog(error, status: .error)
} else {
runOnceDict.override_login_once.updateValue(Date(), forKey: script)
runOnceDict.updateValue(Date(), forKey: script)
if !output.isEmpty {
writeLog(output, status: .debug)
}
Expand All @@ -106,7 +110,7 @@ func process_items(_ path: String, delete_items : Bool=false, once : Bool=false,
}
}

if !runOnceDict.override_login_once.isEmpty {
if !runOnceDict.isEmpty {
writeLog("Writing login-once preference file: \(run_once_plist)", status: .debug)
let encoder = PropertyListEncoder()
encoder.outputFormat = .xml
Expand Down
9 changes: 3 additions & 6 deletions swift/outset/outset/Functions/SystemUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ struct OutsetPreferences: Codable {
var override_login_once : [String:Date] = [String:Date]()
}

struct RunOncePlist: Codable {
var override_login_once : [String:Date] = [String:Date]()
}

func ensure_root(_ reason : String) {
if !is_root() {
Expand Down Expand Up @@ -112,13 +109,13 @@ func load_outset_preferences() -> OutsetPreferences {
return outsetPrefs
}

func load_runonce(plist: String) -> RunOncePlist {
var runOncePlist = RunOncePlist()
func load_runonce(plist: String) -> [String:Date] {
var runOncePlist = [String:Date]()
if check_file_exists(path: plist) {
let url = URL(fileURLWithPath: plist)
do {
let data = try Data(contentsOf: url)
runOncePlist = try PropertyListDecoder().decode(RunOncePlist.self, from: data)
runOncePlist = try PropertyListDecoder().decode([String:Date].self, from: data)
} catch {
writeLog("runonce plist import failed", status: .error)
}
Expand Down
20 changes: 14 additions & 6 deletions swift/outset/outset/Outset.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ let outset_preferences = share_dir+"com.chilcote.outset.plist"
let on_demand_trigger = "/private/tmp/.com.github.outset.ondemand.launchd"
let login_privileged_trigger = "/private/tmp/.com.github.outset.login-privileged.launchd"
let cleanup_trigger = "/private/tmp/.com.github.outset.cleanup.launchd"
let filePermissions: NSNumber = 0o644
let executablePermissions: NSNumber = 0o755

// Set some variables
var debugMode : Bool = false
var loginwindow : Bool = true
var console_user : String = NSUserName()
var console_user : String = getConsoleUserInfo().username
var network_wait : Bool = true
var network_timeout : Int = 180
var ignored_users : [String] = []
Expand Down Expand Up @@ -95,6 +97,7 @@ struct Outset: ParsableCommand {
if boot {
writeLog("Processing scheduled runs for boot", status: .debug)
ensure_working_folders()
ensure_shared_folder()
if !check_file_exists(path: outset_preferences) {
dump_outset_preferences(prefs: prefs)
}
Expand Down Expand Up @@ -127,7 +130,7 @@ struct Outset: ParsableCommand {
writeLog("Processing scheduled runs for login", status: .debug)
if !ignored_users.contains(console_user) {
if !list_folder(path: login_once_dir).isEmpty {
process_items(login_once_dir, once: true, override: override_login_once)
process_items(login_once_dir, once: true, override: prefs.override_login_once)
}
if !list_folder(path: login_every_dir).isEmpty {
process_items(login_every_dir)
Expand All @@ -146,7 +149,7 @@ struct Outset: ParsableCommand {
}
if !ignored_users.contains(console_user) {
if !list_folder(path: login_privileged_once_dir).isEmpty {
process_items(login_privileged_once_dir, once: true, override: override_login_once)
process_items(login_privileged_once_dir, once: true, override: prefs.override_login_once)
}
if !list_folder(path: login_privileged_every_dir).isEmpty {
process_items(login_privileged_every_dir)
Expand Down Expand Up @@ -234,17 +237,22 @@ struct Outset: ParsableCommand {
ensure_root("add scripts to override list")
ensure_shared_folder()

for overide in addOveride {
for var overide in addOveride {
if !overide.contains(login_once_dir) {
overide = "\(login_once_dir)/\(overide)"
}
writeLog("Adding \(overide) to overide list", status: .debug)
//let value : [String:Date] = [overide:.now]
prefs.override_login_once[overide] = Date()
}
dump_outset_preferences(prefs: prefs)
}

if !removeOveride.isEmpty {
ensure_root("remove scripts to override list")
for overide in removeOveride {
for var overide in removeOveride {
if !overide.contains(login_once_dir) {
overide = "\(login_once_dir)/\(overide)"
}
writeLog("Removing \(overide) from overide list", status: .debug)
prefs.override_login_once.removeValue(forKey: overide)
}
Expand Down

0 comments on commit 61c0900

Please sign in to comment.