Request ssh key password, if it is not set, but the key is encrypted

This commit is contained in:
Evgeny Morozov 2017-02-23 16:34:22 +03:00
parent 5c7fb97dbb
commit 04ceeb87dc
2 changed files with 67 additions and 7 deletions

View file

@ -113,7 +113,15 @@ class SettingsTableViewController: UITableViewController {
if auth == "Password" { if auth == "Password" {
gitCredential = GitCredential(credential: GitCredential.Credential.http(userName: username, password: password!)) gitCredential = GitCredential(credential: GitCredential.Credential.http(userName: username, password: password!))
} else { } else {
gitCredential = GitCredential(credential: GitCredential.Credential.ssh(userName: username, password: Defaults[.gitRepositorySSHPrivateKeyPassphrase]!, publicKeyFile: Globals.sshPublicKeyURL, privateKeyFile: Globals.sshPrivateKeyURL)) gitCredential = GitCredential(
credential: GitCredential.Credential.ssh(
userName: username,
password: Defaults[.gitRepositorySSHPrivateKeyPassphrase]!,
publicKeyFile: Globals.sshPublicKeyURL,
privateKeyFile: Globals.sshPrivateKeyURL,
passwordNotSetCallback: self.requestSshKeyPassword
)
)
} }
let dispatchQueue = DispatchQueue.global(qos: .userInitiated) let dispatchQueue = DispatchQueue.global(qos: .userInitiated)
dispatchQueue.async { dispatchQueue.async {
@ -179,7 +187,32 @@ class SettingsTableViewController: UITableViewController {
touchIDSwitch.isEnabled = false touchIDSwitch.isEnabled = false
} }
} }
func requestSshKeyPassword() -> String {
let sem = DispatchSemaphore(value: 0)
var newPassword = ""
DispatchQueue.main.async {
SVProgressHUD.dismiss()
let alert = UIAlertController(title: "Password", message: "Please fill in the password of your SSH key.", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: {_ in
newPassword = alert.textFields!.first!.text!
sem.signal()
}))
alert.addTextField(configurationHandler: {(textField: UITextField!) in
textField.text = PasswordStore.shared.gitRepositoryPassword
textField.isSecureTextEntry = true
})
self.present(alert, animated: true, completion: nil)
}
let _ = sem.wait(timeout: DispatchTime.distantFuture)
return newPassword
}
func actOnPasswordStoreErasedNotification() { func actOnPasswordStoreErasedNotification() {
pgpKeyTableViewCell.detailTextLabel?.text = "Not Set" pgpKeyTableViewCell.detailTextLabel?.text = "Not Set"
touchIDSwitch.isOn = false touchIDSwitch.isOn = false

View file

@ -17,11 +17,11 @@ struct GitCredential {
enum Credential { enum Credential {
case http(userName: String, password: String) case http(userName: String, password: String)
case ssh(userName: String, password: String, publicKeyFile: URL, privateKeyFile: URL) case ssh(userName: String, password: String, publicKeyFile: URL, privateKeyFile: URL, passwordNotSetCallback: (() -> String)? )
} }
var credential: Credential var credential: Credential
func credentialProvider() throws -> GTCredentialProvider { func credentialProvider() throws -> GTCredentialProvider {
return GTCredentialProvider { (_, _, _) -> (GTCredential?) in return GTCredentialProvider { (_, _, _) -> (GTCredential?) in
var credential: GTCredential? = nil var credential: GTCredential? = nil
@ -65,8 +65,27 @@ struct GitCredential {
Defaults[.gitRepositoryPasswordAttempts] += 1 Defaults[.gitRepositoryPasswordAttempts] += 1
PasswordStore.shared.gitRepositoryPassword = newPassword PasswordStore.shared.gitRepositoryPassword = newPassword
credential = try? GTCredential(userName: userName, password: newPassword) credential = try? GTCredential(userName: userName, password: newPassword)
case let .ssh(userName, password, publicKeyFile, privateKeyFile): case let .ssh(userName, password, publicKeyFile, privateKeyFile, passwordNotSetCallback):
credential = try? GTCredential(userName: userName, publicKeyURL: publicKeyFile, privateKeyURL: privateKeyFile, passphrase: password)
var newPassword:String? = password
// Check if the private key is encrypted
let encrypted = try? String(contentsOf: privateKeyFile).contains("ENCRYPTED")
// Request password if not already set
if encrypted! && password == "" {
newPassword = passwordNotSetCallback!()
}
// nil is expected in case of empty password
if newPassword == "" {
newPassword = nil
}
// Save password for the future
Defaults[.gitRepositorySSHPrivateKeyPassphrase] = newPassword
credential = try? GTCredential(userName: userName, publicKeyURL: publicKeyFile, privateKeyURL: privateKeyFile, passphrase: newPassword)
} }
return credential return credential
} }
@ -119,7 +138,15 @@ class PasswordStore {
if Defaults[.gitRepositoryAuthenticationMethod] == "Password" { if Defaults[.gitRepositoryAuthenticationMethod] == "Password" {
gitCredential = GitCredential(credential: GitCredential.Credential.http(userName: Defaults[.gitRepositoryUsername]!, password: Utils.getPasswordFromKeychain(name: "gitRepositoryPassword") ?? "")) gitCredential = GitCredential(credential: GitCredential.Credential.http(userName: Defaults[.gitRepositoryUsername]!, password: Utils.getPasswordFromKeychain(name: "gitRepositoryPassword") ?? ""))
} else if Defaults[.gitRepositoryAuthenticationMethod] == "SSH Key"{ } else if Defaults[.gitRepositoryAuthenticationMethod] == "SSH Key"{
gitCredential = GitCredential(credential: GitCredential.Credential.ssh(userName: Defaults[.gitRepositoryUsername]!, password: Defaults[.gitRepositorySSHPrivateKeyPassphrase]!, publicKeyFile: Globals.sshPublicKeyURL, privateKeyFile: Globals.sshPrivateKeyURL)) gitCredential = GitCredential(
credential: GitCredential.Credential.ssh(
userName: Defaults[.gitRepositoryUsername]!,
password: Defaults[.gitRepositorySSHPrivateKeyPassphrase]!,
publicKeyFile: Globals.sshPublicKeyURL,
privateKeyFile: Globals.sshPrivateKeyURL,
passwordNotSetCallback: nil
)
)
} else { } else {
gitCredential = nil gitCredential = nil
} }