Skip to content

Commit fad8fa8

Browse files
committed
Merge branch 'origin/jens/handle-yubiotp-usbc-piv-extension'
2 parents c620f01 + d9b8a05 commit fad8fa8

File tree

6 files changed

+294
-49
lines changed

6 files changed

+294
-49
lines changed

Authenticator.xcodeproj/project.pbxproj

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
archiveVersion = 1;
44
classes = {
55
};
6-
objectVersion = 54;
6+
objectVersion = 60;
77
objects = {
88

99
/* Begin PBXBuildFile section */
@@ -81,8 +81,9 @@
8181
B40327762847AE0A00DF4DB0 /* Licensing.md in Resources */ = {isa = PBXBuildFile; fileRef = B40327752847AE0A00DF4DB0 /* Licensing.md */; };
8282
B40D61A02AE7F37900467AE9 /* DisableOTPView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B40D619F2AE7F37900467AE9 /* DisableOTPView.swift */; };
8383
B40D61A22AE7F89500467AE9 /* DisableOTPModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B40D61A12AE7F89500467AE9 /* DisableOTPModel.swift */; };
84+
B40F44452B27033A000D5E02 /* TokenRequestYubiOTPViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B40F44442B27033A000D5E02 /* TokenRequestYubiOTPViewController.swift */; };
8485
B411242F29D423A300D58001 /* ListStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B411242E29D423A300D58001 /* ListStatusView.swift */; };
85-
B432B1BF28B65B8600A7182F /* YubiKit in Frameworks */ = {isa = PBXBuildFile; productRef = B432B1BE28B65B8600A7182F /* YubiKit */; };
86+
B42A39332B2A03D20039DB26 /* YubiKit in Frameworks */ = {isa = PBXBuildFile; productRef = B42A39322B2A03D20039DB26 /* YubiKit */; };
8687
B452EC1F2A1E4F460045E5D9 /* YubiOtpRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B452EC1E2A1E4F460045E5D9 /* YubiOtpRowView.swift */; };
8788
B452EC3D2A264A620045E5D9 /* ToastView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B452EC3C2A264A620045E5D9 /* ToastView.swift */; };
8889
B452EC442A2A06940045E5D9 /* ToastPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B452EC432A2A06940045E5D9 /* ToastPresenter.swift */; };
@@ -224,6 +225,7 @@
224225
B40327752847AE0A00DF4DB0 /* Licensing.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Licensing.md; sourceTree = "<group>"; };
225226
B40D619F2AE7F37900467AE9 /* DisableOTPView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisableOTPView.swift; sourceTree = "<group>"; };
226227
B40D61A12AE7F89500467AE9 /* DisableOTPModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisableOTPModel.swift; sourceTree = "<group>"; };
228+
B40F44442B27033A000D5E02 /* TokenRequestYubiOTPViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenRequestYubiOTPViewController.swift; sourceTree = "<group>"; };
227229
B411242E29D423A300D58001 /* ListStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListStatusView.swift; sourceTree = "<group>"; };
228230
B452EC1E2A1E4F460045E5D9 /* YubiOtpRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YubiOtpRowView.swift; sourceTree = "<group>"; };
229231
B452EC3C2A264A620045E5D9 /* ToastView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastView.swift; sourceTree = "<group>"; };
@@ -263,7 +265,7 @@
263265
isa = PBXFrameworksBuildPhase;
264266
buildActionMask = 2147483647;
265267
files = (
266-
B432B1BF28B65B8600A7182F /* YubiKit in Frameworks */,
268+
B42A39332B2A03D20039DB26 /* YubiKit in Frameworks */,
267269
B9F0FF11F842A39183974083 /* (null) in Frameworks */,
268270
51AFD4DA271D4278008F2630 /* QuartzCore.framework in Frameworks */,
269271
);
@@ -307,6 +309,7 @@
307309
children = (
308310
5156D05C265D2602007A94F8 /* TokenRequestViewController.swift */,
309311
B4FE90D32A443D8400B59170 /* TokenRequestWrapper.swift */,
312+
B40F44442B27033A000D5E02 /* TokenRequestYubiOTPViewController.swift */,
310313
);
311314
path = TokenSession;
312315
sourceTree = "<group>";
@@ -581,7 +584,7 @@
581584
);
582585
name = Authenticator;
583586
packageProductDependencies = (
584-
B432B1BE28B65B8600A7182F /* YubiKit */,
587+
B42A39322B2A03D20039DB26 /* YubiKit */,
585588
);
586589
productName = Authenticator;
587590
productReference = 818866B322DFD729006BC0A8 /* Authenticator.app */;
@@ -642,7 +645,7 @@
642645
);
643646
mainGroup = 818866AA22DFD729006BC0A8;
644647
packageReferences = (
645-
B432B1BD28B65B8600A7182F /* XCRemoteSwiftPackageReference "yubikit-ios" */,
648+
B42A39312B2A03D20039DB26 /* XCLocalSwiftPackageReference "../yubikit-ios" */,
646649
);
647650
productRefGroup = 818866B422DFD729006BC0A8 /* Products */;
648651
projectDirPath = "";
@@ -720,6 +723,7 @@
720723
A525965B23A45501006AA3C0 /* UIImageAdditions.swift in Sources */,
721724
51A162862678A1F100C3FA1E /* OATHConfigurationController.swift in Sources */,
722725
515542622649C88900B19C59 /* PasswordConfigurationViewModel.swift in Sources */,
726+
B40F44452B27033A000D5E02 /* TokenRequestYubiOTPViewController.swift in Sources */,
723727
B4C93E60299D156C00C2A8B8 /* ErrorAlertView.swift in Sources */,
724728
A591411D23830EB800CCCF67 /* UIApplicationExtension.swift in Sources */,
725729
81FA3C34231AF2D8009C22AB /* AdvancedSettingsViewController.swift in Sources */,
@@ -1002,7 +1006,7 @@
10021006
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
10031007
CODE_SIGN_ENTITLEMENTS = Authenticator/Authenticator.entitlements;
10041008
CODE_SIGN_STYLE = Automatic;
1005-
CURRENT_PROJECT_VERSION = 121;
1009+
CURRENT_PROJECT_VERSION = 126;
10061010
DEVELOPMENT_TEAM = LQA3CS5MM7;
10071011
HEADER_SEARCH_PATHS = "../Submodules/YubiKit/**";
10081012
INFOPLIST_FILE = Authenticator/Info.plist;
@@ -1012,7 +1016,7 @@
10121016
"@executable_path/Frameworks",
10131017
);
10141018
LIBRARY_SEARCH_PATHS = "";
1015-
MARKETING_VERSION = 1.7.8;
1019+
MARKETING_VERSION = 1.7.9;
10161020
OTHER_LDFLAGS = "-ObjC";
10171021
PRODUCT_BUNDLE_IDENTIFIER = com.yubico.Authenticator;
10181022
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1030,7 +1034,7 @@
10301034
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
10311035
CODE_SIGN_ENTITLEMENTS = Authenticator/Authenticator.entitlements;
10321036
CODE_SIGN_STYLE = Automatic;
1033-
CURRENT_PROJECT_VERSION = 121;
1037+
CURRENT_PROJECT_VERSION = 126;
10341038
DEVELOPMENT_TEAM = LQA3CS5MM7;
10351039
HEADER_SEARCH_PATHS = "../Submodules/YubiKit/**";
10361040
INFOPLIST_FILE = Authenticator/Info.plist;
@@ -1040,7 +1044,7 @@
10401044
"@executable_path/Frameworks",
10411045
);
10421046
LIBRARY_SEARCH_PATHS = "";
1043-
MARKETING_VERSION = 1.7.8;
1047+
MARKETING_VERSION = 1.7.9;
10441048
OTHER_LDFLAGS = "-ObjC";
10451049
PRODUCT_BUNDLE_IDENTIFIER = com.yubico.Authenticator;
10461050
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1136,21 +1140,16 @@
11361140
};
11371141
/* End XCConfigurationList section */
11381142

1139-
/* Begin XCRemoteSwiftPackageReference section */
1140-
B432B1BD28B65B8600A7182F /* XCRemoteSwiftPackageReference "yubikit-ios" */ = {
1141-
isa = XCRemoteSwiftPackageReference;
1142-
repositoryURL = "https://github.com/Yubico/yubikit-ios";
1143-
requirement = {
1144-
branch = main;
1145-
kind = branch;
1146-
};
1143+
/* Begin XCLocalSwiftPackageReference section */
1144+
B42A39312B2A03D20039DB26 /* XCLocalSwiftPackageReference "../yubikit-ios" */ = {
1145+
isa = XCLocalSwiftPackageReference;
1146+
relativePath = "../yubikit-ios";
11471147
};
1148-
/* End XCRemoteSwiftPackageReference section */
1148+
/* End XCLocalSwiftPackageReference section */
11491149

11501150
/* Begin XCSwiftPackageProductDependency section */
1151-
B432B1BE28B65B8600A7182F /* YubiKit */ = {
1151+
B42A39322B2A03D20039DB26 /* YubiKit */ = {
11521152
isa = XCSwiftPackageProductDependency;
1153-
package = B432B1BD28B65B8600A7182F /* XCRemoteSwiftPackageReference "yubikit-ios" */;
11541153
productName = YubiKit;
11551154
};
11561155
/* End XCSwiftPackageProductDependency section */

Authenticator/Model/TokenRequestViewModel.swift

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,20 @@ class TokenRequestViewModel: NSObject {
7474
}
7575

7676
var isWiredKeyConnectedHandler: ((Bool) -> Void)?
77-
77+
var isYubiOTPEnabledHandler: ((Bool) -> Void)?
78+
7879
func isWiredKeyConnected(handler: @escaping (Bool) -> Void) {
7980
isWiredKeyConnectedHandler = handler
8081
connection.smartCardConnection { [weak self] connection in
8182
DispatchQueue.main.async {
8283
self?.isWiredKeyConnectedHandler?(connection != nil)
8384
}
8485
}
85-
connection.accessoryConnection { [weak self] connection in
86-
DispatchQueue.main.async {
87-
self?.isWiredKeyConnectedHandler?(connection != nil)
86+
if YubiKitDeviceCapabilities.supportsMFIAccessoryKey {
87+
connection.accessoryConnection { [weak self] connection in
88+
DispatchQueue.main.async {
89+
self?.isWiredKeyConnectedHandler?(connection != nil)
90+
}
8891
}
8992
}
9093
}
@@ -178,6 +181,67 @@ class TokenRequestViewModel: NSObject {
178181
}
179182
}
180183

184+
185+
extension TokenRequestViewModel {
186+
187+
func isYubiOTPEnabledOverUSBC(completion: @escaping (Bool?) -> Void) {
188+
isYubiOTPEnabledHandler = completion
189+
190+
// If this device does not have a lightning port return nil
191+
if YubiKitDeviceCapabilities.supportsMFIAccessoryKey {
192+
completion(nil)
193+
return
194+
}
195+
connection.smartCardConnection { [weak self] connection in
196+
connection?.managementSession { session, error in
197+
guard let session else { self?.isYubiOTPEnabledHandler?(false); return }
198+
session.getDeviceInfo { deviceInfo, error in
199+
guard let deviceInfo, let configuration = deviceInfo.configuration else { self?.isYubiOTPEnabledHandler?(false); return }
200+
guard !configuration.isEnabled(.OTP, overTransport: .USB) || SettingsConfig.isOTPOverUSBIgnored(deviceId: deviceInfo.serialNumber) else {
201+
self?.isYubiOTPEnabledHandler?(true)
202+
return
203+
}
204+
self?.isYubiOTPEnabledHandler?(false)
205+
}
206+
}
207+
}
208+
}
209+
210+
func disableOTP(completion: @escaping (Error?) -> Void) {
211+
connection.smartCardConnection { connection in
212+
connection?.managementSession { session, error in
213+
guard let session else { completion(error); return }
214+
session.getDeviceInfo { deviceInfo, error in
215+
guard let deviceInfo, let configuration = deviceInfo.configuration else { completion(error); return }
216+
configuration.setEnabled(false, application: .OTP, overTransport: .USB)
217+
session.write(configuration, reboot: true) { error in
218+
completion(error)
219+
}
220+
}
221+
}
222+
}
223+
}
224+
225+
func waitForKeyRemoval(completion: @escaping () -> Void) {
226+
connection.didDisconnect { _, _ in
227+
completion()
228+
}
229+
}
230+
231+
func ignoreThisKey(completion: @escaping (Error?) -> Void) {
232+
connection.smartCardConnection { connection in
233+
connection?.managementSession { session, error in
234+
guard let session else { completion(error); return }
235+
session.getDeviceInfo { deviceInfo, error in
236+
guard let deviceInfo else { completion(error); return }
237+
SettingsConfig.registerUSBCDeviceToIgnore(deviceId: deviceInfo.serialNumber)
238+
completion(nil)
239+
}
240+
}
241+
}
242+
}
243+
}
244+
181245
@available(iOS 14.0, *)
182246
private extension YKFPIVSession {
183247
func slotForObjectId(_ objectId: String, completion: @escaping (YKFPIVSlot?, TokenRequestViewModel.TokenError?) -> Void) {

0 commit comments

Comments
 (0)