Skip to content

Commit

Permalink
fixed window levels, progress screen, background and boot runner issues
Browse files Browse the repository at this point in the history
  • Loading branch information
twocanoes committed May 14, 2023
1 parent 77c52ad commit 4c887fb
Show file tree
Hide file tree
Showing 23 changed files with 491 additions and 447 deletions.
12 changes: 12 additions & 0 deletions Profile Manifest/com.twocanoes.xcreds.plist
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,18 @@ A profile can consist of payloads with different version numbers. For example, c
<key>pfm_type</key>
<string>boolean</string>
</dict>
<dict>
<key>pfm_description</key>
<string>Specify a path for the script that will give a local admin username and password. This will be used to reset a user&apos;s password when the user has forgotten it. It must return valid JSON in format of {&quot;username&quot;: &quot;tcadmin&quot;,&quot;password&quot;: &quot;twocanoes&quot;} </string>
<key>pfm_documentation_url</key>
<string>https://github.com/twocanoes/xcreds/wiki/AdminGuide#localadmincredentialscriptpath</string>
<key>pfm_name</key>
<string>localAdminCredentialScriptPath</string>
<key>pfm_title</key>
<string>Local Admin Credential Script Path</string>
<key>pfm_type</key>
<string>string</string>
</dict>
<dict>
<key>pfm_description</key>
<string>Specify a custom path for the recovery key.</string>
Expand Down
1 change: 0 additions & 1 deletion XCreds/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ class AppDelegate: NSObject, NSApplicationDelegate {


DistributedNotificationCenter.default().addObserver(self, selector: #selector(screenLocked(_:)), name:NSNotification.Name("com.apple.screenIsLocked") , object: nil)
// ManagedPreferences.shared.preference(forKey: .clientID)
mainController = MainController.init()
mainController?.run()
mainMenu.statusBarItem.menu = mainMenu.mainMenu
Expand Down
37 changes: 37 additions & 0 deletions XCreds/DefaultsHelper.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// DefaultsHelper.swift
// XCreds
//
// Created by Timothy Perfitt on 5/13/23.
//

import Cocoa

class DefaultsHelper: NSObject {
static func backgroundImage(includeDefault:Bool=true) -> NSImage? {
if let imagePathURL = UserDefaults.standard.string(forKey: PrefKeys.loginWindowBackgroundImageURL.rawValue), let image = NSImage.imageFromPathOrURL(pathURLString: imagePathURL){

return image

}
else if includeDefault == true {
let allBundles = Bundle.allBundles
for currentBundle in allBundles {
TCSLogWithMark(currentBundle.bundlePath)
if currentBundle.bundlePath.contains("XCreds"), let imagePath = currentBundle.path(forResource: "DefaultBackground", ofType: "png") {
TCSLogWithMark()

let image = NSImage.init(byReferencingFile: imagePath)

if let image = image {
return image
}
break

}
}
}
return nil
}

}
13 changes: 11 additions & 2 deletions XCreds/LoginPasswordWindowController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,24 @@ import Cocoa
class LoginPasswordWindowController: NSWindowController {

@IBOutlet weak var passwordTextField: NSSecureTextField!
@IBOutlet weak var resetButton: NSButton!

var password:String?
var resetKeychain = false

override func windowDidLoad() {
super.windowDidLoad()

// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
if UserDefaults.standard.string(forKey: PrefKeys.localAdminCredentialScriptPath.rawValue) != nil{
resetButton.isHidden=false
}
else {
resetButton.isHidden=true

}

}


@IBAction func removeKeychainButtonPressed(_ sender: Any) {
if self.window?.isModalPanel==true {
Expand Down
26 changes: 14 additions & 12 deletions XCreds/LoginPasswordWindowController.xib
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<customObject id="-2" userLabel="File's Owner" customClass="LoginPasswordWindowController" customModule="XCreds" customModuleProvider="target">
<connections>
<outlet property="passwordTextField" destination="uxk-Kc-Ey2" id="NeY-1n-1d3"/>
<outlet property="resetButton" destination="vfc-Lt-21D" id="b6N-K2-qOU"/>
<outlet property="window" destination="y1s-aj-r0T" id="ZcP-JQ-mk1"/>
</connections>
</customObject>
Expand Down Expand Up @@ -42,7 +43,7 @@
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" selectable="YES" id="raI-nS-JM6">
<font key="font" metaFont="system"/>
<string key="title">If you do not know your local login password, have a local admin log in at the mac login window and reset your local login password in System Settings.</string>
<string key="title">If you do not know your local login password, have a local admin log in at the mac login window and reset your local login password in System Settings..</string>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
Expand Down Expand Up @@ -81,17 +82,6 @@ DQ
<action selector="updateButtonPressed:" target="-2" id="0Yw-3m-Zc7"/>
</connections>
</button>
<button hidden="YES" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vfc-Lt-21D">
<rect key="frame" x="142" y="13" width="69" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Reset" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="AFi-y5-fTi">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="removeKeychainButtonPressed:" target="-2" id="T0U-p4-KUW"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="0Wv-NR-a6r">
<rect key="frame" x="331" y="13" width="76" height="32"/>
<buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="yk2-3t-h59">
Expand All @@ -105,10 +95,22 @@ Gw
<action selector="cancelButtonPressed:" target="-2" id="qAB-hi-1zy"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="vfc-Lt-21D">
<rect key="frame" x="89" y="13" width="69" height="32"/>
<buttonCell key="cell" type="push" title="Reset" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="AFi-y5-fTi">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="removeKeychainButtonPressed:" target="-2" id="T0U-p4-KUW"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="gTn-ws-NVT" secondAttribute="bottom" constant="20" symbolic="YES" id="1PF-dv-8LN"/>
<constraint firstAttribute="bottom" secondItem="vfc-Lt-21D" secondAttribute="bottom" constant="20" symbolic="YES" id="1zB-rS-iwS"/>
<constraint firstAttribute="trailing" secondItem="gTn-ws-NVT" secondAttribute="trailing" constant="20" symbolic="YES" id="Ca3-N3-wr2"/>
<constraint firstItem="vfc-Lt-21D" firstAttribute="leading" secondItem="keP-aO-VT7" secondAttribute="leading" constant="96" id="Gmn-zf-2fn"/>
<constraint firstAttribute="bottom" secondItem="0Wv-NR-a6r" secondAttribute="bottom" constant="20" symbolic="YES" id="MBG-D2-E15"/>
<constraint firstItem="gTn-ws-NVT" firstAttribute="leading" secondItem="0Wv-NR-a6r" secondAttribute="trailing" constant="12" symbolic="YES" id="r3F-ci-tu2"/>
</constraints>
Expand Down
1 change: 1 addition & 0 deletions XCreds/MainController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Cocoa
class MainController: NSObject {
func run() -> Void {

TCSLogWithMark()
let defaultsPath = Bundle.main.path(forResource: "defaults", ofType: "plist")

if let defaultsPath = defaultsPath {
Expand Down
134 changes: 129 additions & 5 deletions XCreds/PasswordUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,18 @@ enum PasswordError: Error, CustomStringConvertible {
}
}
}
enum PasswordVerificationResult {
case success
case incorrectPassword
case accountDoesNotExist
case other
}

class SecureTokenCredential {

var username = ""
var password = ""
}
class PasswordUtils: NSObject {

static let currentConsoleUserName: String = NSUserName()
Expand Down Expand Up @@ -63,6 +74,101 @@ class PasswordUtils: NSObject {
}
return nil
}
class func GetSecureTokenUserList() -> [String] {
let launchPath = "/usr/bin/fdesetup"
let args = [
"list"
]
let secureTokenListRaw = cliTask(launchPath, arguments: args, waitForTermination: true)
let partialList = secureTokenListRaw.components(separatedBy: "\n")
var secureTokenUsers = [String]()
for entry in partialList {
let username = entry.components(separatedBy: ",")[0].trimmingCharacters(in: .whitespacesAndNewlines)
if username != ""{
secureTokenUsers.append(entry.components(separatedBy: ",")[0])
}
}

return secureTokenUsers
}

class func GetSecureTokenCreds() -> SecureTokenCredential? {

TCSLogWithMark("Starting SecureToken Credential acquisition process")
// Initializing the return variables
// var secureTokenManagementUsername = ""
// var secureTokenManagementPassword = ""

// Getting the list of secure token enabled users
// let secureTokenUsers = GetSecureTokenUserList()

if let scriptPath = UserDefaults.standard.string(forKey: PrefKeys.localAdminCredentialScriptPath.rawValue){
TCSLogWithMark("running script \(scriptPath)")
let json = cliTask(scriptPath)
if let data = json.data(using: .utf8) {
let jsonResultDict = try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as? Dictionary<String, Any>

if let jsonResultDict=jsonResultDict, let username = jsonResultDict["username"] as? String, let password = jsonResultDict["password"] as? String{
let secureTokenCreds = SecureTokenCredential()
secureTokenCreds.username=username
secureTokenCreds.password=password
return secureTokenCreds
// secureTokenCreds = ["username":username,
// "password":password]

// if(PasswordUtils.verifyUser(name: username, auth: password)==false){
// TCSLogWithMark("invalid admin password")
// resetButton.isHidden=true
// }
// else {
// TCSLogWithMark("valid admin password")
// resetButton.isHidden=false
// adminPassword=password
// adminUsername=username
//
// }
}

}

}
return nil
// TCSLog("secureTokenManagementUsername is \(secureTokenManagementUsername)")
////
// TCSLog("secureTokenUsers is \(secureTokenUsers.description)")
// if secureTokenUsers.contains(secureTokenManagementUsername) {
// // The Secure Token management account has a token
//
// // Assigning the username to the return variable
// secureTokenCreds.username = secureTokenManagementUsername
// secureTokenCreds.password = secureTokenManagementPassword
// return secureTokenCreds
//
//
// } else {
// // The Secure Token management account does not have a token, but there are tokens already given
// TCSLogWithMark("Secure Token management unable to get credentials")
// return nil
// }
}

class func verifyUser(name: String, auth: String) -> Bool {
os_log("Finding user record", log: noLoMechlog, type: .debug)
var records = [ODRecord]()
let odsession = ODSession.default()
var isValid = false
do {
let node = try ODNode.init(session: odsession, type: ODNodeType(kODNodeTypeLocalNodes))
let query = try ODQuery.init(node: node, forRecordTypes: kODRecordTypeUsers, attribute: kODAttributeTypeRecordName, matchType: ODMatchType(kODMatchEqualTo), queryValues: name, returnAttributes: kODAttributeTypeAllAttributes, maximumResults: 0)
records = try query.resultsAllowingPartial(false) as! [ODRecord]
isValid = ((try records.first?.verifyPassword(auth)) != nil)
} catch {
let errorText = error.localizedDescription
TCSLogWithMark("ODError while trying to check for local user: \(errorText)")
return false
}
return isValid
}

class func verifyPassword(password:String) -> Bool {
let currentUser = PasswordUtils.getCurrentConsoleUserRecord()
Expand Down Expand Up @@ -229,21 +335,39 @@ class PasswordUtils: NSObject {
/// - userPass: The password for the user being tested as a `String`.
/// - Returns: `true` if the name and password combo are valid locally. `false` if the validation fails.
/// - Throws: Either an `ODFrameworkErrors` or a `DSQueryableErrors` if there is an error.
public class func isLocalPasswordValid(userName: String, userPass: String) throws -> Bool {
public class func isLocalPasswordValid(userName: String, userPass: String) -> PasswordVerificationResult {
do {
TCSLogWithMark("getting local record")
let userRecord = try PasswordUtils.getLocalRecord(userName)
TCSLogWithMark("checking password")
try userRecord.verifyPassword(userPass)
TCSLogWithMark("checking password done")
return .success

} catch {
let castError = error as NSError
switch castError.code {
case Int(kODErrorCredentialsInvalid.rawValue):
TCSLogWithMark("Tested password for user account: \(userName) is not valid.")
return false
return .incorrectPassword
case Int(kODErrorCredentialsAccountNotFound.rawValue):
TCSLogWithMark("No Account for user: \(userName) is not valid.")
return .accountDoesNotExist
case Int(kODErrorCredentialsAccountLocked.rawValue):
TCSLogWithMark("No Account for user: \(userName) is not valid.")
return .other

case Int(kODErrorCredentialsAccountTemporarilyLocked.rawValue):
TCSLogWithMark("No Account for user: \(userName) is not valid.")
return .other


default:
throw error
TCSLogWithMark("throw error:\(error.localizedDescription)")
return .accountDoesNotExist
}
}
return true

}

/// Searches DSLocal for an account short name and returns the `ODRecord` for the user if found.
Expand Down Expand Up @@ -274,7 +398,7 @@ class PasswordUtils: NSObject {
TCSLogWithMark("Found local user: \(record)")
return record
} catch {
TCSLogWithMark("ODError while trying to check for local user: %{public}@")
TCSLogWithMark("ODError while trying to check for local user: \(error.localizedDescription)")
throw error
}
}
Expand Down
3 changes: 2 additions & 1 deletion XCreds/PrefKeys.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Foundation

enum PrefKeys: String {
case clientID, clientSecret, password="local password",discoveryURL, redirectURI, scopes, accessToken, idToken, refreshToken, tokenEndpoint, expirationDate, invalidToken, refreshRateHours, showDebug, verifyPassword, shouldShowQuitMenu, shouldShowPreferencesOnStart, shouldSetGoogleAccessTypeToOffline, passwordChangeURL, shouldShowAboutMenu, username, idpHostName, passwordElementID, shouldFindPasswordElement, shouldShowVersionInfo, shouldShowSupportStatus,shouldShowConfigureWifiButton,shouldShowMacLoginButton, loginWindowBackgroundImageURL, shouldShowCloudLoginByDefault,idpHostNames,autoRefreshLoginTimer, loginWindowWidth, loginWindowHeight, shouldShowRefreshBanner, shouldSwitchToLoginWindowWhenLocked
case clientID, clientSecret, password="local password",discoveryURL, redirectURI, scopes, accessToken, idToken, refreshToken, tokenEndpoint, expirationDate, invalidToken, refreshRateHours, showDebug, verifyPassword, shouldShowQuitMenu, shouldShowPreferencesOnStart, shouldSetGoogleAccessTypeToOffline, passwordChangeURL, shouldShowAboutMenu, username, idpHostName, passwordElementID, shouldFindPasswordElement, shouldShowVersionInfo, shouldShowSupportStatus,shouldShowConfigureWifiButton,shouldShowMacLoginButton, loginWindowBackgroundImageURL, shouldShowCloudLoginByDefault,idpHostNames,autoRefreshLoginTimer, loginWindowWidth, loginWindowHeight, shouldShowRefreshBanner, shouldSwitchToLoginWindowWhenLocked,localAdminCredentialScriptPath
}
func getManagedPreference(key: Preferences) -> Any? {

Expand All @@ -22,6 +22,7 @@ func getManagedPreference(key: Preferences) -> Any? {
return nil
}


enum Preferences: String {
/// The desired AD domain as a `String`.
case ADDomain
Expand Down
6 changes: 3 additions & 3 deletions XCreds/PreferencesWindow.xib
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21701" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21701"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
Expand All @@ -18,7 +18,7 @@
<windowStyleMask key="styleMask" titled="YES" closable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="560" y="551" width="494" height="173"/>
<rect key="screenRect" x="0.0" y="0.0" width="1728" height="1079"/>
<rect key="screenRect" x="0.0" y="0.0" width="1496" height="933"/>
<view key="contentView" wantsLayer="YES" id="ZbF-tC-vpZ">
<rect key="frame" x="0.0" y="0.0" width="494" height="173"/>
<autoresizingMask key="autoresizingMask"/>
Expand Down

0 comments on commit 4c887fb

Please sign in to comment.