LoginWindow.swift 22 KB
Newer Older
Joel Rennich's avatar
Joel Rennich committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14
//
//  Login.swift
//  NoMAD
//
//  Created by Joel Rennich on 4/21/16.
//  Copyright © 2016 Trusource Labs. All rights reserved.
//

import Cocoa

protocol LoginWindowDelegate {
    func updateUserInfo()
}

15
let resetNotificationKey = Notification(name: Notification.Name(rawValue: "resetPassword"), object: nil)
Joel Rennich's avatar
Joel Rennich committed
16 17

class LoginWindow: NSWindowController, NSWindowDelegate {
Joel Rennich's avatar
Joel Rennich committed
18

Joel Rennich's avatar
Joel Rennich committed
19
    var delegate: LoginWindowDelegate?
Joel Rennich's avatar
Joel Rennich committed
20

Joel Rennich's avatar
Joel Rennich committed
21 22
    @IBOutlet weak var userName: NSTextField!
    @IBOutlet weak var Password: NSSecureTextField!
Joel Rennich's avatar
Joel Rennich committed
23

Joel Rennich's avatar
Joel Rennich committed
24 25 26 27 28 29 30
    @IBOutlet weak var changePasswordButton: NSButton!
    @IBOutlet weak var newPasswordLabel2: NSTextField!
    @IBOutlet weak var newPasswordLable: NSTextField!
    @IBOutlet weak var passwordLabel: NSTextField!
    @IBOutlet var logInButton: NSButton!
    @IBOutlet weak var changePasswordField1: NSSecureTextField!
    @IBOutlet weak var changePasswordField2: NSSecureTextField!
Joel Rennich's avatar
Joel Rennich committed
31 32 33 34

    //var noMADUser: NoMADUser? = nil


Joel Rennich's avatar
Joel Rennich committed
35 36 37
    override var windowNibName: String! {
        return "LoginWindow"
    }
Joel Rennich's avatar
Joel Rennich committed
38

Joel Rennich's avatar
Joel Rennich committed
39 40
    override func windowDidLoad() {
        super.windowDidLoad()
41
        guard (( defaults.string(forKey: Preferences.lastUser) ) != "") else {
Joel Rennich's avatar
Joel Rennich committed
42 43 44 45
            self.window?.center()
            setWindowToLogin()
            return
        }
Joel Rennich's avatar
Joel Rennich committed
46

47 48
        changePasswordButton.title = "NoMADMenuController-LogIn".translate
        self.window?.title = "NoMAD - " + "NoMADMenuController-LogIn".translate
Joel Rennich's avatar
Joel Rennich committed
49

50
        userName.stringValue = defaults.string(forKey: Preferences.lastUser)!
Joel Rennich's avatar
Joel Rennich committed
51
        Password.becomeFirstResponder()
Joel Rennich's avatar
Joel Rennich committed
52

Joel Rennich's avatar
Joel Rennich committed
53
        setWindowToLogin()
Joel Rennich's avatar
Joel Rennich committed
54

Joel Rennich's avatar
Joel Rennich committed
55
        self.window?.center()
56

Joel Rennich's avatar
Joel Rennich committed
57
    }
Joel Rennich's avatar
Joel Rennich committed
58

59
    func windowWillClose(_ notification: Notification) {
60 61 62
        Password.stringValue = ""
        changePasswordField1.stringValue = ""
        changePasswordField2.stringValue = ""
Joel Rennich's avatar
Joel Rennich committed
63

64
        NotificationCenter.default.post(updateNotification)
65 66
        delegate?.updateUserInfo()
    }
Joel Rennich's avatar
Joel Rennich committed
67 68


69 70 71
    //When the user clicks "sign in" in NoMAD, goes through the steps
    //to login and verify that everything is correct.

72
    @IBAction func LogInClick(_ sender: Any) {
Joel Rennich's avatar
Joel Rennich committed
73

74
        var userNameChecked = ""
Joel Rennich's avatar
Joel Rennich committed
75

76
        // ensure that user entered just a shortname, in which case add the Kerberos realm
Joel Rennich's avatar
Joel Rennich committed
77 78
        // or if there is an "@" in the name, remove what's after it and put in the AD Domain set in the prefs
        // TODO: support multiple domains at the same time
79

80
        if userName.stringValue.contains("@") {
81
            let split = userName.stringValue.components(separatedBy: "@")
82
            userNameChecked = split[0] + "@" + defaults.string(forKey: Preferences.kerberosRealm)!
83
        } else {
84
            userNameChecked = userName.stringValue + "@" + defaults.string(forKey: Preferences.kerberosRealm)!
85
        }
Joel Rennich's avatar
Joel Rennich committed
86

87
        //let GetCredentials: KerbUtil = KerbUtil()
Joel Rennich's avatar
Joel Rennich committed
88
        var myError: String? = ""
89 90 91 92 93 94 95 96
        let currentPassword = Password.stringValue

        do {
            let noMADUser = try NoMADUser(kerberosPrincipal: userNameChecked)

            // Checks if the remote users's password is correct.
            // If it is and the current console user is not an
            // AD account, then we'll change it.
Joel Rennich's avatar
Joel Rennich committed
97
            
98 99 100 101 102 103 104 105 106
            myError = noMADUser.checkRemoteUserPassword(password: currentPassword)

            // Let's present any errors we got before we do anything else.
            // We're using guard to check if myError is the correct value
            // because we want to force it to return otherwise.
            guard myError == nil else {
                switch myError! {
                // Password expired, so we need to present a password change window for the user to change it.
                case "Password has expired":
107
                    defaults.set(userName.stringValue, forKey: Preferences.userPrincipal)
108 109
                    //print(userName.stringValue)
                    //print(defaults.string(forKey: "userPrincipal"))
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
                    let alertController = NSAlert()
                    alertController.messageText = "Your password has expired. Please reset your password now."
                    alertController.addButton(withTitle: "Change Password")
                    alertController.beginSheetModal(for: self.window!, completionHandler: { [unowned self] (returnCode) -> Void in
                        if returnCode == NSAlertFirstButtonReturn {
                            myLogger.logit(.base, message:myError!)
                            self.setWindowToChange()
                        }
                    })
                case "Client (" + userNameChecked + ") unknown":
                    let alertController = NSAlert()
                    alertController.messageText = "Invalid username. Please try again."
                    alertController.beginSheetModal(for: self.window!, completionHandler: nil)
                    myLogger.logit(.base, message:myError!)
                    EXIT_FAILURE
                //
                default:
                    let alertController = NSAlert()
                    alertController.messageText = "Invalid password. Please try again."
                    alertController.beginSheetModal(for: self.window!, completionHandler: nil)
                    myLogger.logit(.base, message:myError!)
                    EXIT_FAILURE
                }
                // TODO: figure out if this is the proper way to handle this.
                return
            }


            // Checks if console password is correct.
            let consoleUserPasswordIsCorrect = noMADUser.checkCurrentConsoleUserPassword(currentPassword)
            // Checks if keychain password is correct
            let keychainPasswordIsCorrect = try noMADUser.checkKeychainPassword(currentPassword)
            // Check if we want to store the password in the keychain.
143
            let useKeychain = defaults.bool(forKey: Preferences.useKeychain)
144 145 146
            // Check if we want to sync the console user's password with the remote AD password.
            // Only used if console user is not AD.
            var doLocalPasswordSync = false
147
            if defaults.bool(forKey: Preferences.localPasswordSync) {
148 149 150 151 152 153 154 155 156
                doLocalPasswordSync = true
            }

            let consoleUserIsAD = noMADUser.currentConsoleUserIsADuser()


            // make sure the just logged in user is the current user and then reset the password warning
            // TODO: @mactroll - why is this 1296000?
            cliTask("/usr/bin/kswitch -p " + userNameChecked )
157
            defaults.set(1296000, forKey: Preferences.lastPasswordWarning)
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178

            if ( useKeychain ) {
                do {
                    try noMADUser.updateKeychainItem(currentPassword, newPassword2: currentPassword)
                } catch let error as NoMADUserError {
                    myLogger.logit(LogLevel.base, message: error.description)
                } catch {
                    myLogger.logit(LogLevel.base, message: "Unknown error updating keychain item")
                }
            }
            // If the console user's password is incorrect AND
            // the user has it set to sync the local and remote password AND
            // the console user is not an AD account
            // Then prompt the user for their password
            if !consoleUserPasswordIsCorrect && doLocalPasswordSync && !consoleUserIsAD {
                myLogger.logit(LogLevel.debug, message:"Local user's password does not match remote user.")
                myLogger.logit(LogLevel.debug, message:"Local Sync is enabled.")
                myLogger.logit(LogLevel.debug, message:"Console user is not an AD account.")
                myLogger.logit(LogLevel.debug, message:"Lets try to sync the passwords, prompting user.")
                let alertController = NSAlert()
                // TODO: replace with localized text
179
                alertController.messageText = (defaults.string(forKey: Preferences.messageLocalSync) ?? "Your network and local passwords are not the same. Please enter the password for your Mac.")
180
                alertController.addButton(withTitle: "Sync")
181 182
                alertController.addButton(withTitle: "Cancel")
                //alertController.addButton(withTitle: "Sync")
183 184 185 186 187 188 189 190 191 192 193 194 195

                let localPassword = NSSecureTextField(frame: CGRect(x: 0, y: 0, width: 200, height: 24))
                alertController.accessoryView = localPassword
                guard self.window != nil else {
                    myLogger.logit(LogLevel.debug, message: "Window does not exist.")
                    EXIT_FAILURE
                    // TODO: figure out if this is the proper way to handle this.
                    return
                }


                alertController.beginSheetModal(for: self.window!, completionHandler: { [unowned self] (returnCode) -> Void in
                    myLogger.logit(LogLevel.debug, message: "Sheet Modal completed")
196
                    if ( returnCode == NSAlertFirstButtonReturn ) {
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
                        let currentLocalPassword = localPassword.stringValue
                        let newPassword = self.Password.stringValue
                        let localPasswordIsCorrect = noMADUser.checkCurrentConsoleUserPassword(currentLocalPassword)

                        // Making sure the password entered is correct,
                        // if it's not, let's exit.
                        guard localPasswordIsCorrect else {
                            let alertController = NSAlert()
                            alertController.messageText = "Invalid password. Please try again."
                            alertController.beginSheetModal(for: self.window!, completionHandler: nil)
                            myLogger.logit(.base, message:myError!)
                            myLogger.logit(.base, message:"Local password wrong.")
                            EXIT_FAILURE
                            // TODO: figure out if this is the proper way to handle this.
                            return
                        }
                        myLogger.logit(.base, message:"Local password is right. Syncing.")

                        do {
                            try noMADUser.changeCurrentConsoleUserPassword(currentLocalPassword, newPassword1: newPassword, newPassword2: newPassword, forceChange: true)
                        } catch {
                            myError = "Could not change the current console user's password."
                        }
                        // Check if we were able to change the local account password.
                        guard myError == nil else {
                            let alertController = NSAlert()
                            alertController.messageText = myError!
                            alertController.beginSheetModal(for: self.window!, completionHandler: nil)
                            myLogger.logit(LogLevel.debug, message:myError!)
                            EXIT_FAILURE
                            // TODO: figure out if this is the proper way to handle this.
                            return
                        }

                        do {
                            try noMADUser.changeKeychainPassword(currentLocalPassword, newPassword1: newPassword, newPassword2: newPassword)
                        } catch {
                            myLogger.logit(LogLevel.base, message: "Error changing keychain password")
                            myError = "Could not change your local keychain password."
                        }
237
                        self.close()
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
                    } else {
                        myLogger.logit(.base, message:"Local sync cancelled by user.")
                    }
                })

            } else {
                myLogger.logit(LogLevel.info, message: "Not syncing local account because: ")
                if consoleUserPasswordIsCorrect {
                    myLogger.logit(LogLevel.info, message: "Console user's password matches AD already.")
                }
                if !doLocalPasswordSync {
                    myLogger.logit(LogLevel.info, message: "The user/admin doesn't have local password sync enabled.")
                }
                if consoleUserIsAD {
                    myLogger.logit(LogLevel.info, message: "Console user is AD account.")
                }
                self.Password.stringValue = ""
                self.close()
            }
        } catch let nomadUserError as NoMADUserError {
            let alertController = NSAlert()
            alertController.messageText = nomadUserError.description
            alertController.beginSheetModal(for: self.window!, completionHandler: nil)
            myLogger.logit(.base, message:myError!)
            EXIT_FAILURE
            self.Password.stringValue = ""
            self.close()
        } catch {
            let alertController = NSAlert()
            alertController.messageText = "Unknown error."
            alertController.beginSheetModal(for: self.window!, completionHandler: nil)
            myLogger.logit(.base, message:myError!)
            EXIT_FAILURE
            self.Password.stringValue = ""
            self.close()
        }

Joel Rennich's avatar
Joel Rennich committed
275
        // fire off the SignInCommand script if there is one
276

277 278
        if defaults.string(forKey: Preferences.signInCommand) != "" {
            let myResult = cliTask(defaults.string(forKey: Preferences.signInCommand)!)
279 280
            myLogger.logit(LogLevel.base, message: myResult)
        }
Joel Rennich's avatar
Joel Rennich committed
281 282 283

        // DO NOT put self.close() here to try to save code,
        // it will mess up the local password sync code.
Joel Rennich's avatar
Joel Rennich committed
284
    }
Joel Rennich's avatar
Joel Rennich committed
285

286
    @IBAction func changePasswordButtonClick(_ sender: AnyObject) {
Joel Rennich's avatar
Joel Rennich committed
287
        let userPrincipal: String
288
        if userName.stringValue.contains("@") {
Joel Rennich's avatar
Joel Rennich committed
289 290
            userPrincipal = userName.stringValue
        } else {
291
            userPrincipal = userName.stringValue + "@" + defaults.string(forKey: Preferences.kerberosRealm)!
Joel Rennich's avatar
Joel Rennich committed
292 293 294 295
        }
        let currentPassword = Password.stringValue
        let newPassword1 = changePasswordField1.stringValue
        let newPassword2 = changePasswordField2.stringValue
Joel Rennich's avatar
Joel Rennich committed
296

Joel Rennich's avatar
Joel Rennich committed
297 298 299
        // If the user entered the same value for both password fields.
        if ( newPassword1 == newPassword2) {
            var myError = ""
300
            myError = performPasswordChange(username: userPrincipal, currentPassword: currentPassword, newPassword1: newPassword1, newPassword2: newPassword2)
Joel Rennich's avatar
Joel Rennich committed
301

Joel Rennich's avatar
Joel Rennich committed
302 303 304
            if myError != "" {
                let alertController = NSAlert()
                alertController.messageText = myError
305
                alertController.beginSheetModal(for: self.window!, completionHandler: nil)
Joel Rennich's avatar
Joel Rennich committed
306 307 308 309
                EXIT_FAILURE
            } else {
                let alertController = NSAlert()
                alertController.messageText = "Password changed successfully. Note: it may take up to an hour for your password expiration time to be updated."
Joel Rennich's avatar
Joel Rennich committed
310

311
                alertController.beginSheetModal(for: self.window!, completionHandler: {( response ) in
Joel Rennich's avatar
Joel Rennich committed
312
                    if ( response == 0 ) {
Joel Rennich's avatar
Joel Rennich committed
313

Joel Rennich's avatar
Joel Rennich committed
314
                        // login via kinit here with the new password
Joel Rennich's avatar
Joel Rennich committed
315

316 317
                        let GetCredentials: KerbUtil = KerbUtil()
                        var myError: String? = ""
Joel Rennich's avatar
Joel Rennich committed
318

319
                        if myError == "" {
320
                            if userPrincipal.contains("@") {
321 322
                                myError = GetCredentials.getKerbCredentials( newPassword1, userPrincipal );
                            } else {
323
                                myError = GetCredentials.getKerbCredentials( newPassword1, (userPrincipal + "@" + defaults.string(forKey: Preferences.kerberosRealm)!))
324 325
                            }
                        }
Joel Rennich's avatar
Joel Rennich committed
326

Joel Rennich's avatar
Joel Rennich committed
327 328 329 330 331 332 333 334
                        self.setWindowToLogin()
                        self.close()
                    } else {
                        self.setWindowToLogin()
                        self.close()
                    }
                })
            }
335
            myLogger.logit(.base, message:myError)
Joel Rennich's avatar
Joel Rennich committed
336
        } else {
Joel Rennich's avatar
Joel Rennich committed
337

Joel Rennich's avatar
Joel Rennich committed
338 339
            let alertController = NSAlert()
            alertController.messageText = "New passwords don't match!"
340
            alertController.beginSheetModal(for: self.window!, completionHandler: nil)
Joel Rennich's avatar
Joel Rennich committed
341
            EXIT_FAILURE
Joel Rennich's avatar
Joel Rennich committed
342 343 344 345 346

        }

        // fire off the SignInCommand script if there is one

347 348
        if defaults.string(forKey: Preferences.signInCommand) != "" {
            let myResult = cliTask(defaults.string(forKey: Preferences.signInCommand)!)
Joel Rennich's avatar
Joel Rennich committed
349
            myLogger.logit(LogLevel.base, message: myResult)
Joel Rennich's avatar
Joel Rennich committed
350
        }
Joel Rennich's avatar
Joel Rennich committed
351 352 353

        // fire off the SignInCommand script if there is one

354 355
        if defaults.string(forKey: Preferences.signInCommand) != "" {
            let myResult = cliTask(defaults.string(forKey: Preferences.signInCommand)!)
Joel Rennich's avatar
Joel Rennich committed
356 357
            myLogger.logit(LogLevel.base, message: myResult)
        }
Joel Rennich's avatar
Joel Rennich committed
358
    }
Joel Rennich's avatar
Joel Rennich committed
359

360
    fileprivate func setWindowToLogin() {
Joel Rennich's avatar
Joel Rennich committed
361

Joel Rennich's avatar
Joel Rennich committed
362
        // set the size
Joel Rennich's avatar
Joel Rennich committed
363

Joel Rennich's avatar
Joel Rennich committed
364 365 366
        var loginSize = NSSize()
        loginSize.width = 381
        loginSize.height = 114
Joel Rennich's avatar
Joel Rennich committed
367

Joel Rennich's avatar
Joel Rennich committed
368
        // disable the bad things
Joel Rennich's avatar
Joel Rennich committed
369

370 371
        changePasswordButton.isHidden = true
        changePasswordButton.isEnabled = false
Joel Rennich's avatar
Joel Rennich committed
372

373 374 375 376
        changePasswordField1.isHidden = true
        changePasswordField2.isHidden = true
        newPasswordLable.isHidden = true
        newPasswordLabel2.isHidden = true
Joel Rennich's avatar
Joel Rennich committed
377

Joel Rennich's avatar
Joel Rennich committed
378
        // enable the good things
Joel Rennich's avatar
Joel Rennich committed
379

380 381
        logInButton.isHidden = false
        logInButton.isEnabled = true
Joel Rennich's avatar
Joel Rennich committed
382

Joel Rennich's avatar
Joel Rennich committed
383 384
        passwordLabel.stringValue = "Password"
        Password.stringValue = ""
Joel Rennich's avatar
Joel Rennich committed
385

Joel Rennich's avatar
Joel Rennich committed
386
        self.window?.setContentSize(loginSize)
Joel Rennich's avatar
Joel Rennich committed
387

Joel Rennich's avatar
Joel Rennich committed
388
    }
Joel Rennich's avatar
Joel Rennich committed
389

390
    fileprivate func setWindowToChange() {
Joel Rennich's avatar
Joel Rennich committed
391

Joel Rennich's avatar
Joel Rennich committed
392
        // set the size
Joel Rennich's avatar
Joel Rennich committed
393

Joel Rennich's avatar
Joel Rennich committed
394 395 396
        var changeSize = NSSize()
        changeSize.width = 381
        changeSize.height = 178
Joel Rennich's avatar
Joel Rennich committed
397

Joel Rennich's avatar
Joel Rennich committed
398
        // disable the bad things
Joel Rennich's avatar
Joel Rennich committed
399

400 401
        changePasswordButton.isHidden = false
        changePasswordButton.isEnabled = true
Joel Rennich's avatar
Joel Rennich committed
402

403 404 405 406
        changePasswordField1.isHidden = false
        changePasswordField2.isHidden = false
        newPasswordLable.isHidden = false
        newPasswordLabel2.isHidden = false
Joel Rennich's avatar
Joel Rennich committed
407

Joel Rennich's avatar
Joel Rennich committed
408
        // enable the good things
Joel Rennich's avatar
Joel Rennich committed
409

410 411
        logInButton.isHidden = true
        logInButton.isEnabled = false
Joel Rennich's avatar
Joel Rennich committed
412

Joel Rennich's avatar
Joel Rennich committed
413
        passwordLabel.stringValue = "Old Password"
Joel Rennich's avatar
Joel Rennich committed
414

Joel Rennich's avatar
Joel Rennich committed
415
        self.window?.setContentSize(changeSize)
Joel Rennich's avatar
Joel Rennich committed
416

Joel Rennich's avatar
Joel Rennich committed
417
    }
Joel Rennich's avatar
Joel Rennich committed
418

Joel Rennich's avatar
Joel Rennich committed
419
    // username must be of the format username@kerberosRealm
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
    /*
     func performPasswordChange(username: String, currentPassword: String, newPassword1: String, newPassword2: String) -> String {
     let localPasswordSync = defaults.integerForKey("LocalPasswordSync")
     var myError: String = ""

     if (currentPassword.isEmpty || newPassword1.isEmpty || newPassword2.isEmpty) {
     myLogger.logit(.base, message:"Some of the fields are empty")
     myError = "All fields must be filled in"
     return myError
     } else {
     myLogger.logit(.notice, message:"All fields are filled in, continuing")
     }
     // If the user entered the same value for both password fields.
     if ( newPassword1 == newPassword2) {
     let ChangePassword: KerbUtil = KerbUtil()
     myError = ChangePassword.changeKerbPassword(currentPassword, newPassword1, username)
     // If there wasn't an error and Sync Local Password is set
     // Check if the old password entered matches the current local password
     if (localPasswordSync == 1 ) && myError == "" {
     do { try testLocalPassword(currentPassword) }
     catch {
     myLogger.logit(.info, message:"Local password check Swift = no")
     myError = "Your current local password does not match your AD password."
     }
     }

     // update the password in the keychain if we're using it

     if ( defaults.boolForKey("UseKeychain") ) {

     // check if keychain item exists

     let myKeychainUtil = KeychainUtil()

     do { try myKeychainUtil.findPassword(username) } catch {
     myKeychainUtil.setPassword(username, pass: newPassword2)
     }

     }

     // If there wasn't an error and Sync Local Password is set
     // Update the keychain password
     if (localPasswordSync == 1 ) && myError == "" {
     if (ChangePassword.changeKeychainPassword(currentPassword, newPassword1) == 0) {
     myLogger.logit(.info, message:"Error changing local keychain")
     myError = "Could not change your local keychain password."
     }
     }
468

469 470 471 472 473 474 475 476 477 478 479 480 481
     // If there wasn't an error and Sync Local Password is set
     // Update the local password
     if (localPasswordSync == 1 ) && myError == "" {
     do { try changeLocalPassword( currentPassword, newPassword: newPassword1) }
     catch {
     myLogger.logit(.base, message:"Local password change failed")
     myError = "Local password change failed"
     }
     }
     }
     return myError
     }
     */
482 483
    // TODO: Clean this up.
    private func testLocalPassword(password: String) throws {
Joel Rennich's avatar
Joel Rennich committed
484
        let myUser = NSUserName()
485
        let session = ODSession.default()
Joel Rennich's avatar
Joel Rennich committed
486 487 488 489 490 491
        let node = try ODNode.init(session: session, type: UInt32(kODNodeTypeAuthentication))
        let query = try ODQuery.init(node: node, forRecordTypes: kODRecordTypeUsers, attribute: kODAttributeTypeRecordName, matchType: UInt32(kODMatchEqualTo), queryValues: myUser, returnAttributes: kODAttributeTypeNativeOnly, maximumResults: 0)
        let result = try query.resultsAllowingPartial(false)
        let record: ODRecord = result[0] as! ODRecord
        try record.verifyPassword(password)
    }
492

Joel Rennich's avatar
Joel Rennich committed
493
    // TODO: Clean this up.
494
    // Needed to attempt to sync local password with AD on login.
495
    fileprivate func changeLocalPassword(_ oldPassword: String, newPassword: String) throws -> Bool {
Joel Rennich's avatar
Joel Rennich committed
496
        let myUser = NSUserName()
497
        let session = ODSession.default()
Joel Rennich's avatar
Joel Rennich committed
498 499 500 501
        let node = try ODNode.init(session: session, type: UInt32(kODNodeTypeAuthentication))
        let query = try ODQuery.init(node: node, forRecordTypes: kODRecordTypeUsers, attribute: kODAttributeTypeRecordName, matchType: UInt32(kODMatchEqualTo), queryValues: myUser, returnAttributes: kODAttributeTypeNativeOnly, maximumResults: 0)
        let result = try query.resultsAllowingPartial(false)
        let recordRef: ODRecordRef = result[0] as! ODRecordRef
502
        if ODRecordChangePassword(recordRef, oldPassword as CFString!, newPassword as CFString!, nil) {
Joel Rennich's avatar
Joel Rennich committed
503 504 505 506 507 508
            return true
        } else {
            return false
        }
    }
    
509
    fileprivate func sendResetMessage() -> Void {
510
        myLogger.logit(.base, message:"Need to reset user's password.")
511
        NotificationQueue.default.enqueue(resetNotificationKey, postingStyle: .now, coalesceMask: .onName, forModes: nil)
Joel Rennich's avatar
Joel Rennich committed
512 513
    }
}