Skip to content

Commit

Permalink
Merge branch 'origin/jens/handle-yubiotp-usbc-piv-extension'
Browse files Browse the repository at this point in the history
  • Loading branch information
jensutbult committed Dec 20, 2023
2 parents c620f01 + d9b8a05 commit fad8fa8
Show file tree
Hide file tree
Showing 6 changed files with 294 additions and 49 deletions.
39 changes: 19 additions & 20 deletions Authenticator.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 54;
objectVersion = 60;
objects = {

/* Begin PBXBuildFile section */
Expand Down Expand Up @@ -81,8 +81,9 @@
B40327762847AE0A00DF4DB0 /* Licensing.md in Resources */ = {isa = PBXBuildFile; fileRef = B40327752847AE0A00DF4DB0 /* Licensing.md */; };
B40D61A02AE7F37900467AE9 /* DisableOTPView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B40D619F2AE7F37900467AE9 /* DisableOTPView.swift */; };
B40D61A22AE7F89500467AE9 /* DisableOTPModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B40D61A12AE7F89500467AE9 /* DisableOTPModel.swift */; };
B40F44452B27033A000D5E02 /* TokenRequestYubiOTPViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B40F44442B27033A000D5E02 /* TokenRequestYubiOTPViewController.swift */; };
B411242F29D423A300D58001 /* ListStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B411242E29D423A300D58001 /* ListStatusView.swift */; };
B432B1BF28B65B8600A7182F /* YubiKit in Frameworks */ = {isa = PBXBuildFile; productRef = B432B1BE28B65B8600A7182F /* YubiKit */; };
B42A39332B2A03D20039DB26 /* YubiKit in Frameworks */ = {isa = PBXBuildFile; productRef = B42A39322B2A03D20039DB26 /* YubiKit */; };
B452EC1F2A1E4F460045E5D9 /* YubiOtpRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B452EC1E2A1E4F460045E5D9 /* YubiOtpRowView.swift */; };
B452EC3D2A264A620045E5D9 /* ToastView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B452EC3C2A264A620045E5D9 /* ToastView.swift */; };
B452EC442A2A06940045E5D9 /* ToastPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B452EC432A2A06940045E5D9 /* ToastPresenter.swift */; };
Expand Down Expand Up @@ -224,6 +225,7 @@
B40327752847AE0A00DF4DB0 /* Licensing.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Licensing.md; sourceTree = "<group>"; };
B40D619F2AE7F37900467AE9 /* DisableOTPView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisableOTPView.swift; sourceTree = "<group>"; };
B40D61A12AE7F89500467AE9 /* DisableOTPModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisableOTPModel.swift; sourceTree = "<group>"; };
B40F44442B27033A000D5E02 /* TokenRequestYubiOTPViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenRequestYubiOTPViewController.swift; sourceTree = "<group>"; };
B411242E29D423A300D58001 /* ListStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListStatusView.swift; sourceTree = "<group>"; };
B452EC1E2A1E4F460045E5D9 /* YubiOtpRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YubiOtpRowView.swift; sourceTree = "<group>"; };
B452EC3C2A264A620045E5D9 /* ToastView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -263,7 +265,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
B432B1BF28B65B8600A7182F /* YubiKit in Frameworks */,
B42A39332B2A03D20039DB26 /* YubiKit in Frameworks */,
B9F0FF11F842A39183974083 /* (null) in Frameworks */,
51AFD4DA271D4278008F2630 /* QuartzCore.framework in Frameworks */,
);
Expand Down Expand Up @@ -307,6 +309,7 @@
children = (
5156D05C265D2602007A94F8 /* TokenRequestViewController.swift */,
B4FE90D32A443D8400B59170 /* TokenRequestWrapper.swift */,
B40F44442B27033A000D5E02 /* TokenRequestYubiOTPViewController.swift */,
);
path = TokenSession;
sourceTree = "<group>";
Expand Down Expand Up @@ -581,7 +584,7 @@
);
name = Authenticator;
packageProductDependencies = (
B432B1BE28B65B8600A7182F /* YubiKit */,
B42A39322B2A03D20039DB26 /* YubiKit */,
);
productName = Authenticator;
productReference = 818866B322DFD729006BC0A8 /* Authenticator.app */;
Expand Down Expand Up @@ -642,7 +645,7 @@
);
mainGroup = 818866AA22DFD729006BC0A8;
packageReferences = (
B432B1BD28B65B8600A7182F /* XCRemoteSwiftPackageReference "yubikit-ios" */,
B42A39312B2A03D20039DB26 /* XCLocalSwiftPackageReference "../yubikit-ios" */,
);
productRefGroup = 818866B422DFD729006BC0A8 /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -720,6 +723,7 @@
A525965B23A45501006AA3C0 /* UIImageAdditions.swift in Sources */,
51A162862678A1F100C3FA1E /* OATHConfigurationController.swift in Sources */,
515542622649C88900B19C59 /* PasswordConfigurationViewModel.swift in Sources */,
B40F44452B27033A000D5E02 /* TokenRequestYubiOTPViewController.swift in Sources */,
B4C93E60299D156C00C2A8B8 /* ErrorAlertView.swift in Sources */,
A591411D23830EB800CCCF67 /* UIApplicationExtension.swift in Sources */,
81FA3C34231AF2D8009C22AB /* AdvancedSettingsViewController.swift in Sources */,
Expand Down Expand Up @@ -1002,7 +1006,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = Authenticator/Authenticator.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 121;
CURRENT_PROJECT_VERSION = 126;
DEVELOPMENT_TEAM = LQA3CS5MM7;
HEADER_SEARCH_PATHS = "../Submodules/YubiKit/**";
INFOPLIST_FILE = Authenticator/Info.plist;
Expand All @@ -1012,7 +1016,7 @@
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = "";
MARKETING_VERSION = 1.7.8;
MARKETING_VERSION = 1.7.9;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = com.yubico.Authenticator;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand All @@ -1030,7 +1034,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = Authenticator/Authenticator.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 121;
CURRENT_PROJECT_VERSION = 126;
DEVELOPMENT_TEAM = LQA3CS5MM7;
HEADER_SEARCH_PATHS = "../Submodules/YubiKit/**";
INFOPLIST_FILE = Authenticator/Info.plist;
Expand All @@ -1040,7 +1044,7 @@
"@executable_path/Frameworks",
);
LIBRARY_SEARCH_PATHS = "";
MARKETING_VERSION = 1.7.8;
MARKETING_VERSION = 1.7.9;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_BUNDLE_IDENTIFIER = com.yubico.Authenticator;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down Expand Up @@ -1136,21 +1140,16 @@
};
/* End XCConfigurationList section */

/* Begin XCRemoteSwiftPackageReference section */
B432B1BD28B65B8600A7182F /* XCRemoteSwiftPackageReference "yubikit-ios" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/Yubico/yubikit-ios";
requirement = {
branch = main;
kind = branch;
};
/* Begin XCLocalSwiftPackageReference section */
B42A39312B2A03D20039DB26 /* XCLocalSwiftPackageReference "../yubikit-ios" */ = {
isa = XCLocalSwiftPackageReference;
relativePath = "../yubikit-ios";
};
/* End XCRemoteSwiftPackageReference section */
/* End XCLocalSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
B432B1BE28B65B8600A7182F /* YubiKit */ = {
B42A39322B2A03D20039DB26 /* YubiKit */ = {
isa = XCSwiftPackageProductDependency;
package = B432B1BD28B65B8600A7182F /* XCRemoteSwiftPackageReference "yubikit-ios" */;
productName = YubiKit;
};
/* End XCSwiftPackageProductDependency section */
Expand Down
72 changes: 68 additions & 4 deletions Authenticator/Model/TokenRequestViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,20 @@ class TokenRequestViewModel: NSObject {
}

var isWiredKeyConnectedHandler: ((Bool) -> Void)?

var isYubiOTPEnabledHandler: ((Bool) -> Void)?

func isWiredKeyConnected(handler: @escaping (Bool) -> Void) {
isWiredKeyConnectedHandler = handler
connection.smartCardConnection { [weak self] connection in
DispatchQueue.main.async {
self?.isWiredKeyConnectedHandler?(connection != nil)
}
}
connection.accessoryConnection { [weak self] connection in
DispatchQueue.main.async {
self?.isWiredKeyConnectedHandler?(connection != nil)
if YubiKitDeviceCapabilities.supportsMFIAccessoryKey {
connection.accessoryConnection { [weak self] connection in
DispatchQueue.main.async {
self?.isWiredKeyConnectedHandler?(connection != nil)
}
}
}
}
Expand Down Expand Up @@ -178,6 +181,67 @@ class TokenRequestViewModel: NSObject {
}
}


extension TokenRequestViewModel {

func isYubiOTPEnabledOverUSBC(completion: @escaping (Bool?) -> Void) {
isYubiOTPEnabledHandler = completion

// If this device does not have a lightning port return nil
if YubiKitDeviceCapabilities.supportsMFIAccessoryKey {
completion(nil)
return
}
connection.smartCardConnection { [weak self] connection in
connection?.managementSession { session, error in
guard let session else { self?.isYubiOTPEnabledHandler?(false); return }
session.getDeviceInfo { deviceInfo, error in
guard let deviceInfo, let configuration = deviceInfo.configuration else { self?.isYubiOTPEnabledHandler?(false); return }
guard !configuration.isEnabled(.OTP, overTransport: .USB) || SettingsConfig.isOTPOverUSBIgnored(deviceId: deviceInfo.serialNumber) else {
self?.isYubiOTPEnabledHandler?(true)
return
}
self?.isYubiOTPEnabledHandler?(false)
}
}
}
}

func disableOTP(completion: @escaping (Error?) -> Void) {
connection.smartCardConnection { connection in
connection?.managementSession { session, error in
guard let session else { completion(error); return }
session.getDeviceInfo { deviceInfo, error in
guard let deviceInfo, let configuration = deviceInfo.configuration else { completion(error); return }
configuration.setEnabled(false, application: .OTP, overTransport: .USB)
session.write(configuration, reboot: true) { error in
completion(error)
}
}
}
}
}

func waitForKeyRemoval(completion: @escaping () -> Void) {
connection.didDisconnect { _, _ in
completion()
}
}

func ignoreThisKey(completion: @escaping (Error?) -> Void) {
connection.smartCardConnection { connection in
connection?.managementSession { session, error in
guard let session else { completion(error); return }
session.getDeviceInfo { deviceInfo, error in
guard let deviceInfo else { completion(error); return }
SettingsConfig.registerUSBCDeviceToIgnore(deviceId: deviceInfo.serialNumber)
completion(nil)
}
}
}
}
}

@available(iOS 14.0, *)
private extension YKFPIVSession {
func slotForObjectId(_ objectId: String, completion: @escaping (YKFPIVSlot?, TokenRequestViewModel.TokenError?) -> Void) {
Expand Down
Loading

0 comments on commit fad8fa8

Please sign in to comment.