Skip to content

Commit

Permalink
v1.09.50
Browse files Browse the repository at this point in the history
Docs: update changelog
Release: version bump to 1.09.50
Feat: add "Lock database" button to DB unlocker
Feat(yk): add YubiKey challenge-response support (closes #25)
Fix(db): assertion crash when auto-loading kp1 databases
Feat(yk): add YubiKey challenge-response (NFC/MFi)
Refactor(db): switch to CompositeKey instead of several arrays
Chore(db): remove excessive SecureByteArray wrapping
Feat(yk): integrate YubiKit
Fix(viewGroup): enforce minimal row height for entries without title
  • Loading branch information
keepassium committed Feb 25, 2020
1 parent e02ad29 commit c521cd5
Show file tree
Hide file tree
Showing 369 changed files with 29,000 additions and 193 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
#CHANGELOG

## [1.09.50] - 2020-01-14

- Internal beta release
- Invalid: missing camera usage description


## [1.09.49] - 2020-01-14

### Added
Expand Down
63 changes: 56 additions & 7 deletions KeePassium AutoFill/MainCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -141,30 +141,46 @@ class MainCoordinator: NSObject, Coordinator {
(topVC as? KeyFileChooserVC)?.refresh()
}


private func challengeHandler(
challenge: SecureByteArray,
responseHandler: @escaping ResponseHandler)
{
Diag.warning("YubiKey is not available in AutoFill")
responseHandler(SecureByteArray(), .notAvailableInAutoFill)
}

private func tryToUnlockDatabase(
database: URLReference,
password: String,
keyFile: URLReference?)
keyFile: URLReference?,
yubiKey: YubiKey?)
{
Settings.current.isAutoFillFinishedOK = false

let _challengeHandler = (yubiKey != nil) ? challengeHandler : nil
isLoadingUsingStoredDatabaseKey = false
DatabaseManager.shared.startLoadingDatabase(
database: database,
password: password,
keyFile: keyFile)
keyFile: keyFile,
challengeHandler: _challengeHandler
)
}

private func tryToUnlockDatabase(
database: URLReference,
compositeKey: SecureByteArray)
compositeKey: CompositeKey,
yubiKey: YubiKey?)
{
Settings.current.isAutoFillFinishedOK = false

compositeKey.challengeHandler = (yubiKey != nil) ? challengeHandler : nil
isLoadingUsingStoredDatabaseKey = true
DatabaseManager.shared.startLoadingDatabase(
database: database,
compositeKey: compositeKey)
compositeKey: compositeKey
)
}


Expand Down Expand Up @@ -250,7 +266,11 @@ class MainCoordinator: NSObject, Coordinator {
navigationController.pushViewController(vc, animated: animated)
completion?()
if let storedDatabaseKey = storedDatabaseKey {
tryToUnlockDatabase(database: database, compositeKey: storedDatabaseKey)
tryToUnlockDatabase(
database: database,
compositeKey: storedDatabaseKey,
yubiKey: dbSettings?.associatedYubiKey
)
}
}

Expand Down Expand Up @@ -394,17 +414,46 @@ extension MainCoordinator: DatabaseUnlockerDelegate {
_ sender: DatabaseUnlockerVC,
database: URLReference,
password: String,
keyFile: URLReference?)
keyFile: URLReference?,
yubiKey: YubiKey?)
{
watchdog.restart()
tryToUnlockDatabase(database: database, password: password, keyFile: keyFile)
tryToUnlockDatabase(
database: database,
password: password,
keyFile: keyFile,
yubiKey: yubiKey)
}

func didPressSelectHardwareKey(in databaseUnlocker: DatabaseUnlockerVC, at popoverAnchor: PopoverAnchor) {
let hardwareKeyPicker = HardwareKeyPicker.create(delegate: self)
hardwareKeyPicker.modalPresentationStyle = .popover
if let popover = hardwareKeyPicker.popoverPresentationController {
popoverAnchor.apply(to: popover)
popover.delegate = hardwareKeyPicker.dismissablePopoverDelegate
}
hardwareKeyPicker.key = databaseUnlocker.yubiKey
navigationController.present(hardwareKeyPicker, animated: true, completion: nil)
}

func didPressNewsItem(in databaseUnlocker: DatabaseUnlockerVC, newsItem: NewsItem) {
newsItem.show(in: databaseUnlocker)
}
}

extension MainCoordinator: HardwareKeyPickerDelegate {
func didDismiss(_ picker: HardwareKeyPicker) {
}
func didSelectKey(yubiKey: YubiKey?, in picker: HardwareKeyPicker) {
watchdog.restart()
if let databaseUnlockerVC = navigationController.topViewController as? DatabaseUnlockerVC {
databaseUnlockerVC.setYubiKey(yubiKey)
} else {
assertionFailure()
}
}
}

extension MainCoordinator: KeyFileChooserDelegate {

func didSelectFile(in keyFileChooser: KeyFileChooserVC, urlRef: URLReference?) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15400" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="bxv-kR-0w1">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15702" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="bxv-kR-0w1">
<device id="retina4_0" orientation="portrait" appearance="dark"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15404"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15704"/>
<capability name="Named colors" minToolsVersion="9.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
Expand Down Expand Up @@ -124,7 +124,7 @@
<constraint firstAttribute="height" constant="2" id="rNj-qR-5f7"/>
</constraints>
</view>
<textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="No Key File" textAlignment="natural" adjustsFontForContentSizeCategory="YES" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Dnl-vm-GMg">
<textField opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="No Key File" textAlignment="natural" adjustsFontForContentSizeCategory="YES" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Dnl-vm-GMg" customClass="KeyFileTextField" customModule="KeePassiumPro_AutoFill" customModuleProvider="target">
<rect key="frame" x="8" y="46" width="264" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="Sao-Cr-ebW"/>
Expand Down Expand Up @@ -224,7 +224,7 @@
<outlet property="errorMessageLabel" destination="dID-zL-AtZ" id="yty-hV-df1"/>
<outlet property="errorMessagePanel" destination="Crk-4o-Fqu" id="WOd-6g-If7"/>
<outlet property="inputPanel" destination="Q5g-RY-uXD" id="6S7-1l-TIX"/>
<outlet property="keyFileField" destination="Dnl-vm-GMg" id="frD-BC-dbG"/>
<outlet property="keyFileField" destination="Dnl-vm-GMg" id="k6z-2m-zpB"/>
<outlet property="passwordField" destination="U6j-Ph-AWS" id="eKJ-Bd-ciZ"/>
<outlet property="unlockButton" destination="89h-8b-LRO" id="f59-RP-Gbr"/>
</connections>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15400" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15702" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_0" orientation="portrait" appearance="dark"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15404"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15704"/>
<capability name="Named colors" minToolsVersion="9.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
Expand Down Expand Up @@ -43,22 +43,22 @@
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="EntryFinderCell" id="RaK-Ag-MEi" customClass="EntryFinderCell" customModule="KeePassiumPro_AutoFill" customModuleProvider="target">
<rect key="frame" x="0.0" y="99" width="320" height="43.5"/>
<rect key="frame" x="0.0" y="99" width="320" height="51.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="RaK-Ag-MEi" id="LNj-AK-QdV">
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
<rect key="frame" x="0.0" y="0.0" width="320" height="51.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="db-icons/kpbIcon00" translatesAutoresizingMaskIntoConstraints="NO" id="bgc-qJ-rf9">
<rect key="frame" x="16" y="7.5" width="29" height="29"/>
<rect key="frame" x="16" y="11.5" width="29" height="29"/>
<color key="tintColor" name="IconTint"/>
<constraints>
<constraint firstAttribute="height" constant="29" id="P1E-9B-6XL"/>
<constraint firstAttribute="width" secondItem="bgc-qJ-rf9" secondAttribute="height" multiplier="1:1" id="bza-IB-cIr"/>
</constraints>
</imageView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="NKy-ya-6Eb">
<rect key="frame" x="61" y="4.5" width="243" height="35"/>
<rect key="frame" x="61" y="8.5" width="243" height="35"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="249" verticalHuggingPriority="249" text="{Entry Title}" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1xY-Ij-CPq">
<rect key="frame" x="0.0" y="0.0" width="243" height="20.5"/>
Expand All @@ -85,6 +85,8 @@
<constraint firstItem="bgc-qJ-rf9" firstAttribute="centerY" secondItem="LNj-AK-QdV" secondAttribute="centerY" id="2YH-bM-UdN"/>
<constraint firstItem="NKy-ya-6Eb" firstAttribute="centerY" secondItem="LNj-AK-QdV" secondAttribute="centerY" id="UB2-bl-32x"/>
<constraint firstItem="bgc-qJ-rf9" firstAttribute="leading" secondItem="LNj-AK-QdV" secondAttribute="leadingMargin" id="ekQ-4n-Pls"/>
<constraint firstAttribute="bottomMargin" relation="greaterThanOrEqual" secondItem="bgc-qJ-rf9" secondAttribute="bottom" id="gu1-U2-SJ6"/>
<constraint firstItem="bgc-qJ-rf9" firstAttribute="top" relation="greaterThanOrEqual" secondItem="LNj-AK-QdV" secondAttribute="topMargin" id="jbp-3h-dRc"/>
<constraint firstItem="NKy-ya-6Eb" firstAttribute="leading" secondItem="bgc-qJ-rf9" secondAttribute="trailing" constant="16" id="ttY-eH-7wn"/>
<constraint firstAttribute="trailingMargin" secondItem="NKy-ya-6Eb" secondAttribute="trailing" id="tuY-3B-nOL"/>
</constraints>
Expand Down Expand Up @@ -174,10 +176,10 @@
<color red="0.23499999940395355" green="0.23499999940395355" blue="0.2630000114440918" alpha="0.60000002384185791" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="IconTint">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color red="0.0" green="0.41176470588235292" blue="0.85098039215686272" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="PrimaryText">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</namedColor>
</resources>
</document>
42 changes: 38 additions & 4 deletions KeePassium AutoFill/controllers/DatabaseUnlockerVC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@ protocol DatabaseUnlockerDelegate: class {
_ sender: DatabaseUnlockerVC,
database: URLReference,
password: String,
keyFile: URLReference?)
keyFile: URLReference?,
yubiKey: YubiKey?)
func didPressNewsItem(in databaseUnlocker: DatabaseUnlockerVC, newsItem: NewsItem)
func didPressSelectHardwareKey(
in databaseUnlocker: DatabaseUnlockerVC,
at popoverAnchor: PopoverAnchor)
}

class DatabaseUnlockerVC: UIViewController, Refreshable {
Expand All @@ -26,7 +30,7 @@ class DatabaseUnlockerVC: UIViewController, Refreshable {
@IBOutlet weak var databaseFileNameLabel: UILabel!
@IBOutlet weak var inputPanel: UIView!
@IBOutlet weak var passwordField: ProtectedTextField!
@IBOutlet weak var keyFileField: UITextField!
@IBOutlet weak var keyFileField: KeyFileTextField!
@IBOutlet weak var announcementButton: UIButton!
@IBOutlet weak var unlockButton: UIButton!

Expand All @@ -37,6 +41,7 @@ class DatabaseUnlockerVC: UIViewController, Refreshable {
didSet { refresh() }
}
private(set) var keyFileRef: URLReference?
private(set) var yubiKey: YubiKey?

override func viewDidLoad() {
super.viewDidLoad()
Expand All @@ -50,8 +55,17 @@ class DatabaseUnlockerVC: UIViewController, Refreshable {

refresh()

keyFileField.delegate = self
passwordField.delegate = self
keyFileField.delegate = self

keyFileField.yubikeyHandler = {
[weak self] (field) in
guard let self = self else { return }
let popoverAnchor = PopoverAnchor(
sourceView: self.keyFileField,
sourceRect: self.keyFileField.bounds)
self.delegate?.didPressSelectHardwareKey(in: self, at: popoverAnchor)
}
}

override func viewDidAppear(_ animated: Bool) {
Expand Down Expand Up @@ -161,6 +175,25 @@ class DatabaseUnlockerVC: UIViewController, Refreshable {
setKeyFile(urlRef: availableKeyFileRef)
}
}

if let associatedYubiKey = dbSettings?.associatedYubiKey {
setYubiKey(associatedYubiKey)
}
}

func setYubiKey(_ yubiKey: YubiKey?) {
self.yubiKey = yubiKey
keyFileField.isYubiKeyActive = (yubiKey != nil)

guard let databaseRef = databaseRef else { assertionFailure(); return }
DatabaseSettingsManager.shared.updateSettings(for: databaseRef) { (dbSettings) in
dbSettings.maybeSetAssociatedYubiKey(yubiKey)
}
if let _yubiKey = yubiKey {
Diag.info("Hardware key selected [key: \(_yubiKey)]")
} else {
Diag.info("No hardware key selected")
}
}

func setKeyFile(urlRef: URLReference?) {
Expand Down Expand Up @@ -248,7 +281,8 @@ class DatabaseUnlockerVC: UIViewController, Refreshable {
self,
database: databaseRef,
password: passwordField.text ?? "",
keyFile: keyFileRef)
keyFile: keyFileRef,
yubiKey: yubiKey)
}

@IBAction func didPressAnouncementButton(_ sender: Any) {
Expand Down
13 changes: 13 additions & 0 deletions KeePassium-Bridging-Header.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// KeePassium Password Manager
// Copyright © 2018–2019 Andrei Popleteev <[email protected]>
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License version 3 as published
// by the Free Software Foundation: https://www.gnu.org/licenses/).
// For commercial licensing, please contact the author.

#ifndef KeePassiumBridgingHeader_h
#define KeePassiumBridgingHeader_h

#import "YubiKit/YubiKit.h"
#endif /* KeePassiumBridgingHeader_h */
Loading

0 comments on commit c521cd5

Please sign in to comment.