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:
commit
586e86052b
4 changed files with 71 additions and 10 deletions
|
|
@ -18,7 +18,7 @@ class SSHKeySettingTableViewController: UITableViewController {
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
passphraseTextField.text = Defaults[.gitRepositorySSHPrivateKeyPassphrase]
|
passphraseTextField.text = Utils.getPasswordFromKeychain(name: "gitRepositorySSHPrivateKeyPassphrase")!
|
||||||
privateKeyURLTextField.text = Defaults[.gitRepositorySSHPrivateKeyURL]?.absoluteString
|
privateKeyURLTextField.text = Defaults[.gitRepositorySSHPrivateKeyURL]?.absoluteString
|
||||||
publicKeyURLTextField.text = Defaults[.gitRepositorySSHPublicKeyURL]?.absoluteString
|
publicKeyURLTextField.text = Defaults[.gitRepositorySSHPublicKeyURL]?.absoluteString
|
||||||
var doneBarButtonItem: UIBarButtonItem?
|
var doneBarButtonItem: UIBarButtonItem?
|
||||||
|
|
@ -43,7 +43,7 @@ class SSHKeySettingTableViewController: UITableViewController {
|
||||||
|
|
||||||
Defaults[.gitRepositorySSHPublicKeyURL] = URL(string: publicKeyURLTextField.text!)
|
Defaults[.gitRepositorySSHPublicKeyURL] = URL(string: publicKeyURLTextField.text!)
|
||||||
Defaults[.gitRepositorySSHPrivateKeyURL] = URL(string: privateKeyURLTextField.text!)
|
Defaults[.gitRepositorySSHPrivateKeyURL] = URL(string: privateKeyURLTextField.text!)
|
||||||
Defaults[.gitRepositorySSHPrivateKeyPassphrase] = passphraseTextField.text!
|
Utils.addPasswrodToKeychain(name: "gitRepositorySSHPrivateKeyPassphrase", password: passphraseTextField.text!)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try Data(contentsOf: Defaults[.gitRepositorySSHPublicKeyURL]!).write(to: Globals.sshPublicKeyURL, options: .atomic)
|
try Data(contentsOf: Defaults[.gitRepositorySSHPublicKeyURL]!).write(to: Globals.sshPublicKeyURL, options: .atomic)
|
||||||
|
|
|
||||||
|
|
@ -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: Utils.getPasswordFromKeychain(name: "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
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ extension DefaultsKeys {
|
||||||
static let gitRepositoryPasswordAttempts = DefaultsKey<Int>("gitRepositoryPasswordAttempts")
|
static let gitRepositoryPasswordAttempts = DefaultsKey<Int>("gitRepositoryPasswordAttempts")
|
||||||
static let gitRepositorySSHPublicKeyURL = DefaultsKey<URL?>("gitRepositorySSHPublicKeyURL")
|
static let gitRepositorySSHPublicKeyURL = DefaultsKey<URL?>("gitRepositorySSHPublicKeyURL")
|
||||||
static let gitRepositorySSHPrivateKeyURL = DefaultsKey<URL?>("gitRepositorySSHPrivateKeyURL")
|
static let gitRepositorySSHPrivateKeyURL = DefaultsKey<URL?>("gitRepositorySSHPrivateKeyURL")
|
||||||
static let gitRepositorySSHPrivateKeyPassphrase = DefaultsKey<String?>("gitRepositorySSHPrivateKeyPassphrase")
|
|
||||||
static let lastUpdatedTime = DefaultsKey<Date?>("lasteUpdatedTime")
|
static let lastUpdatedTime = DefaultsKey<Date?>("lasteUpdatedTime")
|
||||||
|
|
||||||
static let isTouchIDOn = DefaultsKey<Bool>("isTouchIDOn")
|
static let isTouchIDOn = DefaultsKey<Bool>("isTouchIDOn")
|
||||||
|
|
|
||||||
|
|
@ -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,28 @@ 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!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
return credential
|
||||||
}
|
}
|
||||||
|
|
@ -119,7 +139,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: Utils.getPasswordFromKeychain(name: "gitRepositorySSHPrivateKeyPassphrase")!,
|
||||||
|
publicKeyFile: Globals.sshPublicKeyURL,
|
||||||
|
privateKeyFile: Globals.sshPrivateKeyURL,
|
||||||
|
passwordNotSetCallback: nil
|
||||||
|
)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
gitCredential = nil
|
gitCredential = nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue