Merge pull request #31 from ttyz/ssh-password-request

Request ssh key password, if it is not set, but the key is encrypted
This commit is contained in:
Bob Sun 2017-02-23 22:45:46 +08:00 committed by GitHub
commit 586e86052b
4 changed files with 71 additions and 10 deletions

View file

@ -18,7 +18,7 @@ class SSHKeySettingTableViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
passphraseTextField.text = Defaults[.gitRepositorySSHPrivateKeyPassphrase]
passphraseTextField.text = Utils.getPasswordFromKeychain(name: "gitRepositorySSHPrivateKeyPassphrase")!
privateKeyURLTextField.text = Defaults[.gitRepositorySSHPrivateKeyURL]?.absoluteString
publicKeyURLTextField.text = Defaults[.gitRepositorySSHPublicKeyURL]?.absoluteString
var doneBarButtonItem: UIBarButtonItem?
@ -43,7 +43,7 @@ class SSHKeySettingTableViewController: UITableViewController {
Defaults[.gitRepositorySSHPublicKeyURL] = URL(string: publicKeyURLTextField.text!)
Defaults[.gitRepositorySSHPrivateKeyURL] = URL(string: privateKeyURLTextField.text!)
Defaults[.gitRepositorySSHPrivateKeyPassphrase] = passphraseTextField.text!
Utils.addPasswrodToKeychain(name: "gitRepositorySSHPrivateKeyPassphrase", password: passphraseTextField.text!)
do {
try Data(contentsOf: Defaults[.gitRepositorySSHPublicKeyURL]!).write(to: Globals.sshPublicKeyURL, options: .atomic)

View file

@ -113,7 +113,15 @@ class SettingsTableViewController: UITableViewController {
if auth == "Password" {
gitCredential = GitCredential(credential: GitCredential.Credential.http(userName: username, password: password!))
} 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: Utils.getPasswordFromKeychain(name: "gitRepositorySSHPrivateKeyPassphrase")!,
publicKeyFile: Globals.sshPublicKeyURL,
privateKeyFile: Globals.sshPrivateKeyURL,
passwordNotSetCallback: self.requestSshKeyPassword
)
)
}
let dispatchQueue = DispatchQueue.global(qos: .userInitiated)
dispatchQueue.async {
@ -179,7 +187,32 @@ class SettingsTableViewController: UITableViewController {
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() {
pgpKeyTableViewCell.detailTextLabel?.text = "Not Set"
touchIDSwitch.isOn = false

View file

@ -26,7 +26,7 @@ extension DefaultsKeys {
static let gitRepositoryPasswordAttempts = DefaultsKey<Int>("gitRepositoryPasswordAttempts")
static let gitRepositorySSHPublicKeyURL = DefaultsKey<URL?>("gitRepositorySSHPublicKeyURL")
static let gitRepositorySSHPrivateKeyURL = DefaultsKey<URL?>("gitRepositorySSHPrivateKeyURL")
static let gitRepositorySSHPrivateKeyPassphrase = DefaultsKey<String?>("gitRepositorySSHPrivateKeyPassphrase")
static let lastUpdatedTime = DefaultsKey<Date?>("lasteUpdatedTime")
static let isTouchIDOn = DefaultsKey<Bool>("isTouchIDOn")

View file

@ -17,11 +17,11 @@ struct GitCredential {
enum Credential {
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
func credentialProvider() throws -> GTCredentialProvider {
return GTCredentialProvider { (_, _, _) -> (GTCredential?) in
var credential: GTCredential? = nil
@ -65,8 +65,28 @@ struct GitCredential {
Defaults[.gitRepositoryPasswordAttempts] += 1
PasswordStore.shared.gitRepositoryPassword = newPassword
credential = try? GTCredential(userName: userName, password: newPassword)
case let .ssh(userName, password, publicKeyFile, privateKeyFile):
credential = try? GTCredential(userName: userName, publicKeyURL: publicKeyFile, privateKeyURL: privateKeyFile, passphrase: password)
case let .ssh(userName, password, publicKeyFile, privateKeyFile, passwordNotSetCallback):
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!()
}
// Save password for the future
Utils.addPasswrodToKeychain(name: "gitRepositorySSHPrivateKeyPassphrase", password: newPassword!)
// nil is expected in case of empty password
if newPassword == "" {
newPassword = nil
}
credential = try? GTCredential(userName: userName, publicKeyURL: publicKeyFile, privateKeyURL: privateKeyFile, passphrase: newPassword)
}
return credential
}
@ -119,7 +139,15 @@ class PasswordStore {
if Defaults[.gitRepositoryAuthenticationMethod] == "Password" {
gitCredential = GitCredential(credential: GitCredential.Credential.http(userName: Defaults[.gitRepositoryUsername]!, password: Utils.getPasswordFromKeychain(name: "gitRepositoryPassword") ?? ""))
} 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: Utils.getPasswordFromKeychain(name: "gitRepositorySSHPrivateKeyPassphrase")!,
publicKeyFile: Globals.sshPublicKeyURL,
privateKeyFile: Globals.sshPrivateKeyURL,
passwordNotSetCallback: nil
)
)
} else {
gitCredential = nil
}