From 1437d1adbb2ece47af1ba4d28253765a08ff4f43 Mon Sep 17 00:00:00 2001
From: Marten Rebane <54431068+martenrebane@users.noreply.github.com>
Date: Mon, 15 Jan 2024 19:49:37 +0200
Subject: [PATCH] Add proxy support
---
.../xcschemes/xcschememanagement.plist | 4 +-
MoppApp/MoppApp.xcodeproj/project.pbxproj | 31 +-
MoppApp/MoppApp/Constants.swift | 2 +
MoppApp/MoppApp/DefaultsHelper.swift | 69 ++-
MoppApp/MoppApp/FileDownloader.swift | 10 +-
.../InitializationViewController.swift | 3 +-
MoppApp/MoppApp/LocalizationKeys.swift | 17 +
MoppApp/MoppApp/ManualProxy.swift | 43 ++
MoppApp/MoppApp/MoppApp-Bridging-Header.h | 1 +
MoppApp/MoppApp/MoppApp.swift | 10 +-
MoppApp/MoppApp/ProxyCategoryCell.swift | 66 +++
.../ProxyChoiceTapGestureRecognizer.swift | 29 +
MoppApp/MoppApp/ProxyViewController.swift | 147 +++++
MoppApp/MoppApp/Session.swift | 2 +-
MoppApp/MoppApp/SessionCertificate.swift | 2 +-
MoppApp/MoppApp/SessionStatus.swift | 2 +-
MoppApp/MoppApp/Settings.storyboard | 507 ++++++++++++++++++
MoppApp/MoppApp/SettingsConfiguration.swift | 15 +-
MoppApp/MoppApp/SettingsFieldCell.swift | 1 +
MoppApp/MoppApp/SettingsProxyCell.swift | 350 ++++++++++++
MoppApp/MoppApp/SettingsViewController.swift | 37 +-
.../SigningCategoryViewController.swift | 27 +-
.../{ => Siva}/SivaCertViewController.swift | 2 +
MoppApp/MoppApp/SmartIDSignature.swift | 6 +-
MoppApp/MoppApp/en.lproj/Localizable.strings | 17 +
MoppApp/MoppApp/et.lproj/Localizable.strings | 17 +
MoppApp/MoppApp/ru.lproj/Localizable.strings | 17 +
MoppLib/MoppLib.xcodeproj/project.pbxproj | 8 +
MoppLib/MoppLib/MoppLibDigidocManager.h | 3 +-
MoppLib/MoppLib/MoppLibDigidocManager.mm | 25 +-
.../MoppLib/PublicInterface/MoppLibManager.h | 3 +-
.../MoppLib/PublicInterface/MoppLibManager.m | 4 +-
.../MoppLibProxyConfiguration.h | 35 ++
.../MoppLibProxyConfiguration.m | 40 ++
.../SkSigningLib.xcodeproj/project.pbxproj | 16 +
.../xcschemes/xcschememanagement.plist | 2 +-
.../Requests/Mobile-ID/RequestSession.swift | 18 +-
.../Requests/Mobile-ID/RequestSignature.swift | 9 +-
.../Requests/Smart-ID/SIDRequest.swift | 24 +-
.../SkSigningLib/Utilities/Proxy/Proxy.swift | 40 ++
.../Utilities/Proxy/ProxyUtil.swift | 94 ++++
41 files changed, 1697 insertions(+), 58 deletions(-)
create mode 100644 MoppApp/MoppApp/ManualProxy.swift
create mode 100644 MoppApp/MoppApp/ProxyCategoryCell.swift
create mode 100644 MoppApp/MoppApp/ProxyChoiceTapGestureRecognizer.swift
create mode 100644 MoppApp/MoppApp/ProxyViewController.swift
create mode 100644 MoppApp/MoppApp/SettingsProxyCell.swift
rename MoppApp/MoppApp/Signing/{ => Siva}/SivaCertViewController.swift (97%)
create mode 100644 MoppLib/MoppLib/PublicInterface/MoppLibProxyConfiguration.h
create mode 100644 MoppLib/MoppLib/PublicInterface/MoppLibProxyConfiguration.m
create mode 100644 SkSigningLib/SkSigningLib/Utilities/Proxy/Proxy.swift
create mode 100644 SkSigningLib/SkSigningLib/Utilities/Proxy/ProxyUtil.swift
diff --git a/CryptoLib/CryptoLib.xcodeproj/xcuserdata/martenr.xcuserdatad/xcschemes/xcschememanagement.plist b/CryptoLib/CryptoLib.xcodeproj/xcuserdata/martenr.xcuserdatad/xcschemes/xcschememanagement.plist
index 53fee9481..662173333 100644
--- a/CryptoLib/CryptoLib.xcodeproj/xcuserdata/martenr.xcuserdatad/xcschemes/xcschememanagement.plist
+++ b/CryptoLib/CryptoLib.xcodeproj/xcuserdata/martenr.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -7,12 +7,12 @@
CryptoLib.xcscheme_^#shared#^_
orderHint
- 13
+ 25
cdoc.xcscheme_^#shared#^_
orderHint
- 18
+ 26
diff --git a/MoppApp/MoppApp.xcodeproj/project.pbxproj b/MoppApp/MoppApp.xcodeproj/project.pbxproj
index 594ea6cfd..c7357f0bd 100644
--- a/MoppApp/MoppApp.xcodeproj/project.pbxproj
+++ b/MoppApp/MoppApp.xcodeproj/project.pbxproj
@@ -188,6 +188,7 @@
DF3D29CF23F6B3CF007181B8 /* SkSigningLib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF3D29CE23F6B3CF007181B8 /* SkSigningLib.framework */; };
DF3D29D023F6B3CF007181B8 /* SkSigningLib.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DF3D29CE23F6B3CF007181B8 /* SkSigningLib.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
DF3F62B026BD71180070F930 /* FileDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF3F62AF26BD71180070F930 /* FileDownloader.swift */; };
+ DF41B5512B50736600594D01 /* ManualProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF41B5502B50736600594D01 /* ManualProxy.swift */; };
DF46181F2962E464003A1B56 /* FileUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF46181E2962E464003A1B56 /* FileUtil.swift */; };
DF4B8418284008CF005CB875 /* SignatureDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4B8417284008CF005CB875 /* SignatureDetail.swift */; };
DF4B841A2840F8FC005CB875 /* CertificateDetailsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF4B84192840F8FC005CB875 /* CertificateDetailsCell.swift */; };
@@ -207,6 +208,10 @@
DF8A948A29AFD11A004F6E4B /* CharacterSet+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF8A948929AFD11A004F6E4B /* CharacterSet+Additions.swift */; };
DF8EFB1A287498B900A96DE3 /* SettingsDefaultValueCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF8EFB19287498B900A96DE3 /* SettingsDefaultValueCell.swift */; };
DF900C972386768F00887385 /* tslFiles.bundle in Resources */ = {isa = PBXBuildFile; fileRef = DF900C94238567CA00887385 /* tslFiles.bundle */; };
+ DF9709692B4D79E400361544 /* ProxyCategoryCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF9709682B4D79E400361544 /* ProxyCategoryCell.swift */; };
+ DF97096B2B4D7A4600361544 /* ProxyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF97096A2B4D7A4600361544 /* ProxyViewController.swift */; };
+ DF97096D2B4D7AA900361544 /* SettingsProxyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF97096C2B4D7AA900361544 /* SettingsProxyCell.swift */; };
+ DF97096F2B4D92A700361544 /* ProxyChoiceTapGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF97096E2B4D92A700361544 /* ProxyChoiceTapGestureRecognizer.swift */; };
DF97A51129DC8CAB006FB917 /* ContainerAddAllButtonCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF97A51029DC8CAB006FB917 /* ContainerAddAllButtonCell.swift */; };
DFA56CEE2AEFEE45007D7F7E /* SettingsSivaCertCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFA56CED2AEFEE45007D7F7E /* SettingsSivaCertCell.swift */; };
DFA56CF22AF003F8007D7F7E /* RadioButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFA56CF12AF003F8007D7F7E /* RadioButton.swift */; };
@@ -531,6 +536,7 @@
DF3D299C23F5ADB7007181B8 /* MimeTypeExtractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MimeTypeExtractor.swift; sourceTree = ""; };
DF3D29CE23F6B3CF007181B8 /* SkSigningLib.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SkSigningLib.framework; sourceTree = BUILT_PRODUCTS_DIR; };
DF3F62AF26BD71180070F930 /* FileDownloader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileDownloader.swift; sourceTree = ""; };
+ DF41B5502B50736600594D01 /* ManualProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManualProxy.swift; sourceTree = ""; };
DF46181E2962E464003A1B56 /* FileUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileUtil.swift; sourceTree = ""; };
DF4B8417284008CF005CB875 /* SignatureDetail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignatureDetail.swift; sourceTree = ""; };
DF4B84192840F8FC005CB875 /* CertificateDetailsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CertificateDetailsCell.swift; sourceTree = ""; };
@@ -550,6 +556,10 @@
DF8A948929AFD11A004F6E4B /* CharacterSet+Additions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CharacterSet+Additions.swift"; sourceTree = ""; };
DF8EFB19287498B900A96DE3 /* SettingsDefaultValueCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsDefaultValueCell.swift; sourceTree = ""; };
DF900C94238567CA00887385 /* tslFiles.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = tslFiles.bundle; sourceTree = ""; };
+ DF9709682B4D79E400361544 /* ProxyCategoryCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProxyCategoryCell.swift; sourceTree = ""; };
+ DF97096A2B4D7A4600361544 /* ProxyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProxyViewController.swift; sourceTree = ""; };
+ DF97096C2B4D7AA900361544 /* SettingsProxyCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsProxyCell.swift; sourceTree = ""; };
+ DF97096E2B4D92A700361544 /* ProxyChoiceTapGestureRecognizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProxyChoiceTapGestureRecognizer.swift; sourceTree = ""; };
DF97A51029DC8CAB006FB917 /* ContainerAddAllButtonCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerAddAllButtonCell.swift; sourceTree = ""; };
DFA56CED2AEFEE45007D7F7E /* SettingsSivaCertCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsSivaCertCell.swift; sourceTree = ""; };
DFA56CF12AF003F8007D7F7E /* RadioButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioButton.swift; sourceTree = ""; };
@@ -820,6 +830,7 @@
DFA56CF12AF003F8007D7F7E /* RadioButton.swift */,
DFA56CF32AF009E5007D7F7E /* RadioButton.xib */,
DF50BBCE2AF06A0800C1A7D0 /* SivaChoiceTapGestureRecognizer.swift */,
+ DF97096E2B4D92A700361544 /* ProxyChoiceTapGestureRecognizer.swift */,
);
name = "Custom views";
sourceTree = "";
@@ -957,6 +968,7 @@
DFD54CF429CDDB0600CD92C7 /* SettingsTSACertCell.swift */,
DFBDF1F127D79B8B00A5CF3C /* SettingsStateCell.swift */,
DFA56CED2AEFEE45007D7F7E /* SettingsSivaCertCell.swift */,
+ DF97096C2B4D7AA900361544 /* SettingsProxyCell.swift */,
DF3756172AFABEB7006960C5 /* SettingsResetCell.swift */,
);
name = Settings;
@@ -1042,12 +1054,23 @@
name = Protocols;
sourceTree = "";
};
+ DF548B142B4C6CDE00340EE5 /* Proxy */ = {
+ isa = PBXGroup;
+ children = (
+ DF9709682B4D79E400361544 /* ProxyCategoryCell.swift */,
+ DF97096A2B4D7A4600361544 /* ProxyViewController.swift */,
+ DF41B5502B50736600594D01 /* ManualProxy.swift */,
+ );
+ name = Proxy;
+ path = ..;
+ sourceTree = "";
+ };
DF716E932B45CFD60004DCB6 /* Signing */ = {
isa = PBXGroup;
children = (
DFB29EE22B4604BF005BEB34 /* Siva */,
+ DF548B142B4C6CDE00340EE5 /* Proxy */,
DF716E942B45CFE90004DCB6 /* SigningCategoryViewController.swift */,
- DF716E962B45D0F10004DCB6 /* SivaCertViewController.swift */,
DF716E982B45D1FF0004DCB6 /* SigningCategoryCell.swift */,
);
path = Signing;
@@ -1057,6 +1080,7 @@
isa = PBXGroup;
children = (
DFB29EE32B4604DB005BEB34 /* SivaCategoryCell.swift */,
+ DF716E962B45D0F10004DCB6 /* SivaCertViewController.swift */,
);
path = Siva;
sourceTree = "";
@@ -1659,6 +1683,7 @@
C56C6206201A189600CCC2A5 /* MenuHeaderCell.swift in Sources */,
DFBF242E23DB0923008DD8D0 /* LOTLDecoder.swift in Sources */,
DF24E9D62AD5ECFB00471FFA /* DiagnosticError.swift in Sources */,
+ DF97096B2B4D7A4600361544 /* ProxyViewController.swift in Sources */,
DF3950602AD766DF005D96AC /* KeychainUtil.swift in Sources */,
C50DCD441FDD7E4A00D48E16 /* DataFilePreviewViewController.swift in Sources */,
C50FC431224BA3B20041925C /* ScreenDisguise.swift in Sources */,
@@ -1668,6 +1693,7 @@
C506EC7C1FB9CBFD00E07226 /* Constants.swift in Sources */,
DFD54CF529CDDB0600CD92C7 /* SettingsTSACertCell.swift in Sources */,
C58FCD5B206505BE00FE3B57 /* MyeIDStatusViewController.swift in Sources */,
+ DF41B5512B50736600594D01 /* ManualProxy.swift in Sources */,
DF32A67D2909B20C00AE5F82 /* AlertUtil.swift in Sources */,
C5310F2620C1777B004D3E78 /* MenuLanguageCell.swift in Sources */,
DF4B841A2840F8FC005CB875 /* CertificateDetailsCell.swift in Sources */,
@@ -1708,6 +1734,7 @@
39CDA7EE20ADBE93006E2E9F /* CryptoViewController.swift in Sources */,
C52E82781FC1D3ED0074B280 /* MenuViewController.swift in Sources */,
C50DCCC71FC32A2500D48E16 /* MyeIDViewController.swift in Sources */,
+ DF9709692B4D79E400361544 /* ProxyCategoryCell.swift in Sources */,
DF26DC8326CD45670073ABA7 /* SivaUtil.swift in Sources */,
DF35B1922AEAE32A0018AC7E /* PersonalCodeField.swift in Sources */,
DFF3C3B5233231F20079458A /* Notification+Additions.swift in Sources */,
@@ -1720,6 +1747,7 @@
C5964CE820079AE0001FE732 /* TabButton.swift in Sources */,
3921CA9920B2F5B200BF3178 /* PreviewActions.swift in Sources */,
DFBA32A629A5A64000788A87 /* CancelUtil.swift in Sources */,
+ DF97096D2B4D7AA900361544 /* SettingsProxyCell.swift in Sources */,
DFBDF1FC27DF6BA800A5CF3C /* MobileIDParameters.swift in Sources */,
C56C620F201A2B6500CCC2A5 /* RecentContainersHeaderCell.swift in Sources */,
C593D9F4208F3526000B3BF6 /* SettingsChoiceView.swift in Sources */,
@@ -1738,6 +1766,7 @@
DFD54CF729D1CBAF00CD92C7 /* CertUtil.swift in Sources */,
4E59080024B0F914001B23A6 /* SmartIDEditViewController.swift in Sources */,
DFD8BEF7291C434500FE8F07 /* FontUtil.swift in Sources */,
+ DF97096F2B4D92A700361544 /* ProxyChoiceTapGestureRecognizer.swift in Sources */,
DFB29EE42B4604DB005BEB34 /* SivaCategoryCell.swift in Sources */,
C50DCD1B1FD1576B00D48E16 /* SigningTableViewHeaderView.swift in Sources */,
C54EA73A2057E58D0039AC78 /* MoppButton.swift in Sources */,
diff --git a/MoppApp/MoppApp/Constants.swift b/MoppApp/MoppApp/Constants.swift
index 9be53ee1b..405ec0f14 100644
--- a/MoppApp/MoppApp/Constants.swift
+++ b/MoppApp/MoppApp/Constants.swift
@@ -43,6 +43,8 @@ let kAlternativeDisplayTextFormat = "UCS-2"
let kDigestMethodSHA256 = "http://www.w3.org/2001/04/xmlenc#sha256"
let kHashType = "SHA256"
+let proxyPasswordKey = "proxyPasswordKey"
+
// Mobile-ID and Smart-ID polling interval
let kDefaultTimeoutMs = 5000
let kDefaultTimeoutS = 5
diff --git a/MoppApp/MoppApp/DefaultsHelper.swift b/MoppApp/MoppApp/DefaultsHelper.swift
index 9d41d9561..cf8821d4f 100644
--- a/MoppApp/MoppApp/DefaultsHelper.swift
+++ b/MoppApp/MoppApp/DefaultsHelper.swift
@@ -21,6 +21,9 @@
*
*/
+import Foundation
+import SkSigningLib
+
let ContainerFormatAdoc = "adoc"
let ContainerFormatBdoc = "bdoc"
let ContainerFormatEdoc = "edoc"
@@ -46,6 +49,7 @@ let CrashlyticsAlwaysSend = "Always"
let CrashlyticsNeverSend = "Never"
let CrashlyticsDefault = "Default"
// Keys
+fileprivate let kFirstStartKey = "kFirstStartKey"
fileprivate let kSignMethodKey = "kSignMethodKey"
fileprivate let kPhoneNumberKey = "kPhoneNumberKey"
fileprivate let kIDCodeKey = "kIDCodeKey"
@@ -75,19 +79,35 @@ fileprivate let kIsRoleAndAddressEnabled = "kIsRoleAndAddressEnabled"
fileprivate let kSivaAccessState = "kSivaAccessState"
fileprivate let kSivaUrl = "kSivaUrl"
fileprivate let kSivaFileCertName = "kSivaFileCertName"
+fileprivate let kProxySetting = "kProxySetting"
+fileprivate let kIsProxyForSSLEnabled = "kIsProxyForSSLEnabled"
+fileprivate let kProxyHost = "kProxyHost"
+fileprivate let kProxyPort = "kProxyPort"
+fileprivate let kProxyUsername = "kProxyUsername"
class DefaultsHelper
{
static func setDefaultKeys() {
UserDefaults.standard.register(
defaults: [
+ kFirstStartKey: true,
kSettingsDefaultSwitchKey: true,
kMobileIdRememberMeKey: true,
- kSmartIdRememberMeKey: true
+ kSmartIdRememberMeKey: true,
+ kIsProxyForSSLEnabled: true
]
)
}
+ class var firstStart: Bool {
+ set {
+ UserDefaults.standard.set(newValue, forKey: kFirstStartKey)
+ }
+ get {
+ return (UserDefaults.standard.bool(forKey: kFirstStartKey))
+ }
+ }
+
class var signMethod: String {
set {
UserDefaults.standard.set(newValue, forKey: kSignMethodKey)
@@ -334,4 +354,51 @@ class DefaultsHelper
return UserDefaults.standard.value(forKey: kSivaFileCertName) as? String
}
}
+
+ class var proxySetting: ProxySetting {
+ set {
+ UserDefaults.standard.set(newValue.rawValue, forKey: kProxySetting)
+ }
+ get {
+ return ProxySetting(rawValue: UserDefaults.standard.value(forKey: kProxySetting) as? String ?? "") ?? .noProxy
+ }
+ }
+
+ class var isProxyForSSLEnabled: Bool {
+ set {
+ UserDefaults.standard.set(newValue, forKey: kIsProxyForSSLEnabled)
+ }
+ get {
+ return UserDefaults.standard.bool(forKey: kIsProxyForSSLEnabled)
+ }
+ }
+
+ class var proxyHost: String? {
+ set {
+ UserDefaults.standard.set(newValue, forKey: kProxyHost)
+ }
+ get {
+ return UserDefaults.standard.value(forKey: kProxyHost) as? String
+ }
+ }
+
+ class var proxyPort: Int {
+ set {
+ // Set default port 80
+ UserDefaults.standard.set(newValue == 0 ? 80 : newValue, forKey: kProxyPort)
+ }
+ get {
+ let port = UserDefaults.standard.integer(forKey: kProxyPort)
+ return port == 0 ? 80 : port
+ }
+ }
+
+ class var proxyUsername: String? {
+ set {
+ UserDefaults.standard.set(newValue, forKey: kProxyUsername)
+ }
+ get {
+ return UserDefaults.standard.value(forKey: kProxyUsername) as? String
+ }
+ }
}
diff --git a/MoppApp/MoppApp/FileDownloader.swift b/MoppApp/MoppApp/FileDownloader.swift
index 8a63a97fa..df494bba7 100644
--- a/MoppApp/MoppApp/FileDownloader.swift
+++ b/MoppApp/MoppApp/FileDownloader.swift
@@ -22,13 +22,21 @@
*/
import Foundation
+import SkSigningLib
class FileDownloader: NSObject, URLSessionDelegate {
static let shared = FileDownloader()
func downloadFile(url: URL, completion: @escaping (URL?) -> Void) {
- let downloadTask: URLSessionDownloadTask = URLSession(configuration: .default, delegate: self, delegateQueue: nil).downloadTask(with: url) { (fileTempUrl, response, error) in
+ let manualProxyConf = ManualProxy.getManualProxyConfiguration()
+ var urlSessionConfiguration = URLSessionConfiguration.default
+ ProxyUtil.configureURLSessionWithProxy(urlSessionConfiguration: &urlSessionConfiguration, manualProxyConf: manualProxyConf)
+
+ var request = URLRequest(url: url)
+ ProxyUtil.setProxyAuthorizationHeader(request: &request, urlSessionConfiguration: urlSessionConfiguration, manualProxyConf: manualProxyConf)
+
+ let downloadTask: URLSessionDownloadTask = URLSession.shared.downloadTask(with: request) { (fileTempUrl, response, error) in
if error != nil { printLog("Unable to download file: \(error?.localizedDescription ?? "Unable to display error")"); return completion(nil) }
if let fileTempUrl: URL = fileTempUrl {
do {
diff --git a/MoppApp/MoppApp/InitializationViewController.swift b/MoppApp/MoppApp/InitializationViewController.swift
index 525594694..8a9a0dcd3 100644
--- a/MoppApp/MoppApp/InitializationViewController.swift
+++ b/MoppApp/MoppApp/InitializationViewController.swift
@@ -65,7 +65,8 @@ class InitializationViewController : UIViewController {
},
usingTestDigiDocService: useTestDDS,
andTSUrl: DefaultsHelper.timestampUrl ?? MoppConfiguration.getMoppLibConfiguration().tsaurl,
- withMoppConfiguration: MoppConfiguration.getMoppLibConfiguration()
+ withMoppConfiguration: MoppConfiguration.getMoppLibConfiguration(),
+ andProxyConfiguration: ManualProxy.getMoppLibProxyConfiguration()
)
}
diff --git a/MoppApp/MoppApp/LocalizationKeys.swift b/MoppApp/MoppApp/LocalizationKeys.swift
index 5470cf442..fadaf68ec 100644
--- a/MoppApp/MoppApp/LocalizationKeys.swift
+++ b/MoppApp/MoppApp/LocalizationKeys.swift
@@ -314,6 +314,15 @@ enum LocKey : String
case settingsTimestampCertAddCertificateButton = "settings-timestamp-cert-add-certificate-button"
case settingsTimestampCertShowCertificateButton = "settings-timestamp-cert-show-certificate-button"
case settingsSivaServiceTitle = "settings-siva-service-title"
+ case settingsProxyTitle = "settings-proxy-title"
+ case settingsProxyNoProxy = "settings-proxy-no-proxy"
+ case settingsProxyUseSystem = "settings-proxy-use-system"
+ case settingsProxyUseManual = "settings-proxy-use-manual"
+ case settingsProxyHost = "settings-proxy-host"
+ case settingsProxyPort = "settings-proxy-port"
+ case settingsProxyUsername = "settings-proxy-username"
+ case settingsProxyPassword = "settings-proxy-password"
+ case settingsProxyAllowSSL = "settings-proxy-allow-ssl"
case settingsSivaDefaultAccessTitle = "settings-siva-default-access-title"
case settingsSivaDefaultManualAccessTitle = "settings-siva-default-manual-access-title"
case settingsSivaDefaultCertificateTitle = "settings-siva-default-certificate-title"
@@ -492,4 +501,12 @@ enum LocKey : String
case voiceControlDisableDefaultTimestampingService = "voice-control-disable-default-timestamping-service";
case voiceControlEnableRoleAndAddress = "voice-control-enable-role-and-address";
case voiceControlDisableRoleAndAddress = "voice-control-disable-role-and-address";
+ case voiceControlProxyNoProxy = "voice-control-no-proxy";
+ case voiceControlProxySystemProxy = "voice-control-proxy-system";
+ case voiceControlProxyManualProxy = "voice-control-proxy-manual";
+ case voiceControlProxyHost = "voice-control-proxy-host";
+ case voiceControlProxyPort = "voice-control-proxy-port";
+ case voiceControlProxyUsername = "voice-control-proxy-username";
+ case voiceControlProxyPassword = "voice-control-proxy-password";
+ case voiceControlProxyDisallowSsl = "voice-control-proxy-disallow-ssl";
}
diff --git a/MoppApp/MoppApp/ManualProxy.swift b/MoppApp/MoppApp/ManualProxy.swift
new file mode 100644
index 000000000..5366b66aa
--- /dev/null
+++ b/MoppApp/MoppApp/ManualProxy.swift
@@ -0,0 +1,43 @@
+//
+// ManualProxy.swift
+// MoppApp
+//
+/*
+ * Copyright 2017 - 2023 Riigi Infosüsteemi Amet
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+import Foundation
+import MoppLib
+import SkSigningLib
+
+public class ManualProxy {
+
+ public static func getManualProxyConfiguration() -> Proxy {
+ return Proxy(
+ host: DefaultsHelper.proxyHost ?? "",
+ port: DefaultsHelper.proxyPort,
+ username: DefaultsHelper.proxyUsername ?? "",
+ password: KeychainUtil.retrieve(key: proxyPasswordKey) ?? "",
+ isSSLEnabled: DefaultsHelper.isProxyForSSLEnabled)
+ }
+
+ public static func getMoppLibProxyConfiguration() -> MoppLibProxyConfiguration {
+ let manualProxy = ManualProxy.getManualProxyConfiguration()
+ return MoppLibProxyConfiguration(configuration: manualProxy.host, port: NSNumber(value: manualProxy.port), username: manualProxy.username, password: manualProxy.password)
+ }
+}
diff --git a/MoppApp/MoppApp/MoppApp-Bridging-Header.h b/MoppApp/MoppApp/MoppApp-Bridging-Header.h
index 406a8307a..b8e91a2af 100644
--- a/MoppApp/MoppApp/MoppApp-Bridging-Header.h
+++ b/MoppApp/MoppApp/MoppApp-Bridging-Header.h
@@ -6,3 +6,4 @@
#import
#import
#import
+#import
diff --git a/MoppApp/MoppApp/MoppApp.swift b/MoppApp/MoppApp/MoppApp.swift
index a3ec594c3..457d3e15f 100644
--- a/MoppApp/MoppApp/MoppApp.swift
+++ b/MoppApp/MoppApp/MoppApp.swift
@@ -24,6 +24,7 @@
import Foundation
import FirebaseCrashlytics
import Firebase
+import SkSigningLib
class MoppApp: UIApplication, URLSessionDelegate, URLSessionDownloadDelegate {
@@ -96,6 +97,11 @@ class MoppApp: UIApplication, URLSessionDelegate, URLSessionDownloadDelegate {
Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(false)
DefaultsHelper.setDefaultKeys()
+
+ if DefaultsHelper.firstStart {
+ DefaultsHelper.firstStart = false
+ KeychainUtil.remove(key: proxyPasswordKey)
+ }
window = UIWindow(frame: UIScreen.main.bounds)
window?.backgroundColor = UIColor.white
@@ -438,7 +444,9 @@ class MoppApp: UIApplication, URLSessionDelegate, URLSessionDownloadDelegate {
func handleEventsForBackgroundURLSession(identifier: String, completionHandler: @escaping () -> Void) {
downloadCompletion = completionHandler
- let conf = URLSessionConfiguration.background(withIdentifier: identifier)
+ let manualProxyConf = ManualProxy.getManualProxyConfiguration()
+ var conf = URLSessionConfiguration.background(withIdentifier: identifier)
+ ProxyUtil.configureURLSessionWithProxy(urlSessionConfiguration: &conf, manualProxyConf: manualProxyConf)
let session = URLSession(configuration: conf, delegate: self, delegateQueue: nil)
session.getTasksWithCompletionHandler({(_ dataTasks: [URLSessionDataTask], _ uploadTasks: [URLSessionUploadTask], _ downloadTasks: [URLSessionDownloadTask]) -> Void in
})
diff --git a/MoppApp/MoppApp/ProxyCategoryCell.swift b/MoppApp/MoppApp/ProxyCategoryCell.swift
new file mode 100644
index 000000000..15e2d189a
--- /dev/null
+++ b/MoppApp/MoppApp/ProxyCategoryCell.swift
@@ -0,0 +1,66 @@
+//
+// ProxyCategoryCell.swift
+// MoppApp
+//
+/*
+ * Copyright 2017 - 2023 Riigi Infosüsteemi Amet
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+import UIKit
+
+class ProxyCategoryCell: UITableViewCell {
+
+
+ @IBOutlet weak var accessToProxySettings: ScaledButton!
+
+ @IBAction func openAccessToProxySettings(_ sender: ScaledButton) {
+ openAccessToProxyView()
+ }
+
+ weak var topViewController: UIViewController?
+
+ override func awakeFromNib() {
+ updateUI()
+
+ guard let accessToProxyUISettings: ScaledButton = accessToProxySettings else {
+ printLog("Unable to get accessToProxySettings")
+ return
+ }
+
+ if UIAccessibility.isVoiceOverRunning {
+ self.accessibilityElements = [accessToProxyUISettings]
+ }
+ }
+
+ func populate() {
+ updateUI()
+ }
+
+ func updateUI() {
+ self.accessToProxySettings.setTitle(L(.settingsProxyTitle))
+ self.accessToProxySettings.accessibilityLabel = self.accessToProxySettings.titleLabel?.text?.lowercased()
+ self.accessToProxySettings.mediumFont()
+ }
+
+ private func openAccessToProxyView() {
+ let accessToProxyViewController = UIStoryboard.settings.instantiateViewController(of: ProxyViewController.self)
+ accessToProxyViewController.modalPresentationStyle = .custom
+ accessToProxyViewController.modalTransitionStyle = .crossDissolve
+ topViewController?.present(accessToProxyViewController, animated: true)
+ }
+}
diff --git a/MoppApp/MoppApp/ProxyChoiceTapGestureRecognizer.swift b/MoppApp/MoppApp/ProxyChoiceTapGestureRecognizer.swift
new file mode 100644
index 000000000..b3b1def5b
--- /dev/null
+++ b/MoppApp/MoppApp/ProxyChoiceTapGestureRecognizer.swift
@@ -0,0 +1,29 @@
+//
+// ProxyChoiceTapGestureRecognizer.swift
+// MoppApp
+//
+/*
+ * Copyright 2017 - 2023 Riigi Infosüsteemi Amet
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+import Foundation
+import SkSigningLib
+
+class ProxyChoiceTapGestureRecognizer: UITapGestureRecognizer {
+ var proxySetting: ProxySetting = .noProxy
+}
diff --git a/MoppApp/MoppApp/ProxyViewController.swift b/MoppApp/MoppApp/ProxyViewController.swift
new file mode 100644
index 000000000..8d861dd07
--- /dev/null
+++ b/MoppApp/MoppApp/ProxyViewController.swift
@@ -0,0 +1,147 @@
+//
+// ProxyViewController.swift
+// MoppApp
+//
+/*
+ * Copyright 2017 - 2023 Riigi Infosüsteemi Amet
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+import UIKit
+
+class ProxyViewController: MoppViewController {
+
+ @IBOutlet weak var tableView: UITableView!
+
+ var currentlyEditingCell: IndexPath?
+ var currentlyEditingField: UITextField?
+
+ enum Section {
+ case header
+ case fields
+ }
+
+ enum FieldId {
+ case proxy
+ }
+
+ var sections:[Section] = [.header, .fields]
+
+ var fields: [FieldId] = [
+ .proxy
+ ]
+
+ override func viewWillAppear(_ animated: Bool) {
+ super.viewWillAppear(animated)
+ view.backgroundColor = .gray.withAlphaComponent(0.5)
+ }
+
+ override func keyboardWillShow(notification: NSNotification) {
+ tableView.setContentOffset(CGPoint(x: 0, y: (currentlyEditingField?.frame.origin.y ?? 0)), animated: true)
+ }
+
+ override func keyboardWillHide(notification: NSNotification) {
+ tableView.setContentOffset(CGPoint(x: 0, y: 0), animated: true)
+ }
+}
+
+extension ProxyViewController: UITableViewDelegate, UITableViewDataSource {
+ func numberOfSections(in tableView: UITableView) -> Int {
+ return sections.count
+ }
+
+ func tableView(_ tableView: UITableView, numberOfRowsInSection section_: Int) -> Int {
+ switch sections[section_] {
+ case .header:
+ return 1
+ case .fields:
+ return fields.count
+ }
+ }
+
+ func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
+ return UITableView.automaticDimension
+ }
+
+ func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
+ tableView.estimatedRowHeight = 44
+ return UITableView.automaticDimension
+ }
+
+ func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+ switch sections[indexPath.section] {
+ case .header:
+ let headerCell = tableView.dequeueReusableCell(withType: SettingsHeaderCell.self, for: indexPath)!
+ headerCell.delegate = self
+ headerCell.populate(with: " ")
+ headerCell.titleLabel.isAccessibilityElement = false
+ return headerCell
+ case .fields:
+ let field = fields[indexPath.row]
+ switch field {
+ case .proxy:
+ let proxyCell = tableView.dequeueReusableCell(withType: SettingsProxyCell.self, for: indexPath)!
+ proxyCell.topViewController = getTopViewController()
+ proxyCell.delegate = self
+ proxyCell.populate()
+ return proxyCell
+ }
+ }
+ }
+
+ @objc func editingChanged(sender: UITextField) {
+ let text = sender.text ?? String()
+ if (text.count > 11) {
+ sender.deleteBackward()
+ }
+ }
+}
+
+extension ProxyViewController: SettingsHeaderCellDelegate {
+ func didDismissSettings() {
+ dismiss(animated: true, completion: nil)
+ }
+}
+
+extension ProxyViewController: SettingsCellDelegate {
+ func didStartEditingField(_ field: SigningCategoryViewController.FieldId, _ textField: UITextField) {
+ switch field {
+ case .proxy:
+ currentlyEditingField = textField
+ break
+ default:
+ break
+ }
+ }
+
+ func didStartEditingField(_ field: SigningCategoryViewController.FieldId, _ indexPath: IndexPath) {
+ currentlyEditingCell = indexPath
+ }
+
+ func didStartEditingField(_ field: FieldId, _ indexPath: IndexPath) {
+ switch field {
+ case .proxy:
+ currentlyEditingCell = indexPath
+ break
+ }
+ }
+
+ func didEndEditingField(_ fieldId: SigningCategoryViewController.FieldId, with value: String) {
+ currentlyEditingCell = nil
+ UIAccessibility.post(notification: .screenChanged, argument: L(.settingsValueChanged))
+ }
+}
diff --git a/MoppApp/MoppApp/Session.swift b/MoppApp/MoppApp/Session.swift
index 82d8534f8..388dd6482 100644
--- a/MoppApp/MoppApp/Session.swift
+++ b/MoppApp/MoppApp/Session.swift
@@ -29,7 +29,7 @@ class Session {
func getSession(baseUrl: String, uuid: String, phoneNumber: String, nationalIdentityNumber: String, hash: String, hashType: String, language: String, trustedCertificates: [String]?, completionHandler: @escaping (Result) -> Void) -> Void {
do {
- _ = try RequestSession.shared.getSession(baseUrl: baseUrl, requestParameters: SessionRequestParameters(relyingPartyName: kRelyingPartyName, relyingPartyUUID: uuid, phoneNumber: "+\(phoneNumber)", nationalIdentityNumber: nationalIdentityNumber, hash: hash, hashType: hashType, language: language, displayText: L(.simToolkitSignDocumentTitle).asUnicode, displayTextFormat: DefaultsHelper.moppLanguageID == "ru" ? kAlternativeDisplayTextFormat : kDisplayTextFormat), trustedCertificates: trustedCertificates) { (sessionResult) in
+ _ = try RequestSession.shared.getSession(baseUrl: baseUrl, requestParameters: SessionRequestParameters(relyingPartyName: kRelyingPartyName, relyingPartyUUID: uuid, phoneNumber: "+\(phoneNumber)", nationalIdentityNumber: nationalIdentityNumber, hash: hash, hashType: hashType, language: language, displayText: L(.simToolkitSignDocumentTitle).asUnicode, displayTextFormat: DefaultsHelper.moppLanguageID == "ru" ? kAlternativeDisplayTextFormat : kDisplayTextFormat), trustedCertificates: trustedCertificates, manualProxyConf: ManualProxy.getManualProxyConfiguration()) { (sessionResult) in
switch sessionResult {
case .success(let response):
diff --git a/MoppApp/MoppApp/SessionCertificate.swift b/MoppApp/MoppApp/SessionCertificate.swift
index bdb4835d0..d13b99f27 100644
--- a/MoppApp/MoppApp/SessionCertificate.swift
+++ b/MoppApp/MoppApp/SessionCertificate.swift
@@ -30,7 +30,7 @@ class SessionCertificate {
func getCertificate(baseUrl: String, uuid: String, phoneNumber: String, nationalIdentityNumber: String, trustedCertificates: [String]?, completionHandler: @escaping (Result) -> Void) -> Void {
do {
- _ = try RequestSignature.shared.getCertificate(baseUrl: baseUrl, requestParameters: CertificateRequestParameters(relyingPartyUUID: uuid, relyingPartyName: kRelyingPartyName, phoneNumber: "+\(phoneNumber)", nationalIdentityNumber: nationalIdentityNumber), trustedCertificates: trustedCertificates) { (result) in
+ _ = try RequestSignature.shared.getCertificate(baseUrl: baseUrl, requestParameters: CertificateRequestParameters(relyingPartyUUID: uuid, relyingPartyName: kRelyingPartyName, phoneNumber: "+\(phoneNumber)", nationalIdentityNumber: nationalIdentityNumber), trustedCertificates: trustedCertificates, manualProxyConf: ManualProxy.getManualProxyConfiguration()) { (result) in
switch result {
case .success(let response):
diff --git a/MoppApp/MoppApp/SessionStatus.swift b/MoppApp/MoppApp/SessionStatus.swift
index c1ed401bf..38dc2ffb3 100644
--- a/MoppApp/MoppApp/SessionStatus.swift
+++ b/MoppApp/MoppApp/SessionStatus.swift
@@ -31,7 +31,7 @@ class SessionStatus {
func getSessionStatus(baseUrl: String, process: PollingProcess, sessionId: String, timeoutMs: Int?, trustedCertificates: [String]?, completionHandler: @escaping (Result) -> Void ) {
DispatchQueue.main.async {
do {
- _ = try RequestSession.shared.getSessionStatus(baseUrl: baseUrl, process: process, requestParameters: SessionStatusRequestParameters(sessionId: sessionId, timeoutMs: timeoutMs), trustedCertificates: trustedCertificates) { (sessionStatusResult: Result) in
+ _ = try RequestSession.shared.getSessionStatus(baseUrl: baseUrl, process: process, requestParameters: SessionStatusRequestParameters(sessionId: sessionId, timeoutMs: timeoutMs), trustedCertificates: trustedCertificates, manualProxyConf: ManualProxy.getManualProxyConfiguration()) { (sessionStatusResult: Result) in
switch sessionStatusResult {
case .success(let sessionStatus):
if self.isSessionStateComplete(sessionState: self.getSessionState(sessionStatus: sessionStatus)) {
diff --git a/MoppApp/MoppApp/Settings.storyboard b/MoppApp/MoppApp/Settings.storyboard
index 7b0fc0008..1446797fb 100644
--- a/MoppApp/MoppApp/Settings.storyboard
+++ b/MoppApp/MoppApp/Settings.storyboard
@@ -650,6 +650,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1024,6 +1052,482 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1505,6 +2009,9 @@
+
+
+
diff --git a/MoppApp/MoppApp/SettingsConfiguration.swift b/MoppApp/MoppApp/SettingsConfiguration.swift
index 75387c211..e3893c040 100644
--- a/MoppApp/MoppApp/SettingsConfiguration.swift
+++ b/MoppApp/MoppApp/SettingsConfiguration.swift
@@ -43,6 +43,7 @@
*/
import Foundation
+import SkSigningLib
class SettingsConfiguration: NSObject, URLSessionDelegate, URLSessionTaskDelegate, URLSessionDataDelegate {
@@ -217,21 +218,26 @@ class SettingsConfiguration: NSObject, URLSessionDelegate, URLSessionTaskDelegat
private func fetchDataFromCentralConfiguration(fromUrl: String, completionHandler: @escaping (String?, Error?) -> Void) -> Void {
guard let url = URL(string: fromUrl) else { return }
-
- let urlSessionConfiguration: URLSessionConfiguration = URLSessionConfiguration.default
+
+ let manualProxyConf = ManualProxy.getManualProxyConfiguration()
+
+ var urlSessionConfiguration = URLSessionConfiguration.default
+ ProxyUtil.configureURLSessionWithProxy(urlSessionConfiguration: &urlSessionConfiguration, manualProxyConf: manualProxyConf)
urlSessionConfiguration.timeoutIntervalForResource = 5.0
urlSessionConfiguration.requestCachePolicy = .reloadIgnoringLocalAndRemoteCacheData
+
let urlSession = URLSession(configuration: urlSessionConfiguration, delegate: self, delegateQueue: nil)
let userAgent = MoppLibManager.sharedInstance().userAgent()
var request = URLRequest(url: url)
request.setValue(userAgent, forHTTPHeaderField: "User-Agent")
+ ProxyUtil.setProxyAuthorizationHeader(request: &request, urlSessionConfiguration: urlSessionConfiguration, manualProxyConf: manualProxyConf)
let task = urlSession.dataTask(with: request, completionHandler: { data, response, error in
if let err = error as? NSError {
- if err.code == -1009 {
+ if err.code == -1009 || err.code == -1003 || err.code == 310 {
completionHandler(nil, DiagnosticError.noInternetConnection)
} else {
completionHandler(nil, err)
@@ -338,7 +344,8 @@ class SettingsConfiguration: NSObject, URLSessionDelegate, URLSessionTaskDelegat
printLog("Failed to reload DigiDocConf")
fatalError("Failed to reload DigiDocConf")
}, usingTestDigiDocService: useTestDDS, andTSUrl: DefaultsHelper.timestampUrl ?? MoppConfiguration.getMoppLibConfiguration().tsaurl,
- withMoppConfiguration: MoppConfiguration.getMoppLibConfiguration())
+ withMoppConfiguration: MoppConfiguration.getMoppLibConfiguration(),
+ andProxyConfiguration: ManualProxy.getMoppLibProxyConfiguration())
}
diff --git a/MoppApp/MoppApp/SettingsFieldCell.swift b/MoppApp/MoppApp/SettingsFieldCell.swift
index 4e4252eb3..c30028974 100644
--- a/MoppApp/MoppApp/SettingsFieldCell.swift
+++ b/MoppApp/MoppApp/SettingsFieldCell.swift
@@ -25,6 +25,7 @@ import UIKit
protocol SettingsCellDelegate: AnyObject {
func didStartEditingField(_ field: SigningCategoryViewController.FieldId, _ indexPath: IndexPath)
+ func didStartEditingField(_ field: SigningCategoryViewController.FieldId, _ textField: UITextField)
func didEndEditingField(_ field: SigningCategoryViewController.FieldId, with value: String)
}
diff --git a/MoppApp/MoppApp/SettingsProxyCell.swift b/MoppApp/MoppApp/SettingsProxyCell.swift
new file mode 100644
index 000000000..19ff7dacf
--- /dev/null
+++ b/MoppApp/MoppApp/SettingsProxyCell.swift
@@ -0,0 +1,350 @@
+//
+// SettingsProxyCell.swift
+// MoppApp
+//
+/*
+ * Copyright 2017 - 2023 Riigi Infosüsteemi Amet
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+import UIKit
+import SkSigningLib
+
+class SettingsProxyCell: UITableViewCell {
+
+ private static let defaultEnableSSLWidth = CGFloat(150)
+
+ @IBOutlet weak var proxyTitle: ScaledLabel!
+
+ @IBOutlet weak var proxyChoicesStackView: UIStackView!
+ @IBOutlet weak var noProxyTitle: ScaledLabel!
+ @IBOutlet weak var systemProxyTitle: ScaledLabel!
+ @IBOutlet weak var manualProxyTitle: ScaledLabel!
+
+ @IBOutlet weak var noProxyStackView: UIStackView!
+ @IBOutlet weak var noProxyView: UIView!
+ @IBOutlet weak var systemProxyStackView: UIStackView!
+ @IBOutlet weak var systemProxyView: UIView!
+ @IBOutlet weak var manualProxyStackView: UIStackView!
+ @IBOutlet weak var manualProxyView: UIView!
+ @IBOutlet weak var noProxyRadioButton: RadioButton!
+ @IBOutlet weak var useSystemProxyRadioButton: RadioButton!
+ @IBOutlet weak var useManualProxyRadioButton: RadioButton!
+
+ @IBOutlet weak var hostTitle: ScaledLabel!
+ @IBOutlet weak var hostTextField: SettingsTextField!
+
+ @IBOutlet weak var portTitle: ScaledLabel!
+ @IBOutlet weak var portTextField: SettingsTextField!
+ @IBOutlet weak var portNumberError: ScaledLabel!
+
+ @IBOutlet weak var usernameTitle: ScaledLabel!
+ @IBOutlet weak var usernameTextField: SettingsTextField!
+
+ @IBOutlet weak var passwordTitle: ScaledLabel!
+ @IBOutlet weak var passwordTextField: SettingsTextField!
+
+ @IBOutlet weak var enableSSLStackView: UIStackView!
+ @IBOutlet weak var enableSSLTitle: ScaledLabel!
+ @IBOutlet weak var enableSSLButton: SwitchButton!
+
+ weak var delegate: SettingsCellDelegate!
+
+ weak var topViewController: UIViewController?
+
+ @IBAction func toggleProxySSL(_ sender: SwitchButton) {
+ DefaultsHelper.isProxyForSSLEnabled = sender.isOn
+ setSSLButtonVoiceLabel()
+ }
+
+ override func awakeFromNib() {
+ hostTextField.delegate = self
+ portTextField.delegate = self
+ usernameTextField.delegate = self
+ passwordTextField.delegate = self
+
+ noProxyTitle.text = L(.settingsProxyNoProxy)
+ systemProxyTitle.text = L(.settingsProxyUseSystem)
+ manualProxyTitle.text = L(.settingsProxyUseManual)
+
+ presentDismissButton(hostTextField)
+ presentDismissButton(portTextField)
+ presentDismissButton(usernameTextField)
+ presentDismissButton(passwordTextField)
+
+ setBorder(hostTextField)
+ setBorder(portTextField)
+ setBorder(usernameTextField)
+ setBorder(passwordTextField)
+
+ hostTextField.isAccessibilityElement = true
+ portTextField.isAccessibilityElement = true
+ usernameTextField.isAccessibilityElement = true
+ passwordTextField.isAccessibilityElement = true
+
+ hostTextField.accessibilityLabel = L(.settingsProxyHost)
+ portTextField.accessibilityLabel = L(.settingsProxyPort)
+ usernameTextField.accessibilityLabel = L(.settingsProxyUsername)
+ passwordTextField.accessibilityLabel = L(.settingsProxyPassword)
+
+ hostTextField.accessibilityUserInputLabels = [L(.voiceControlProxyHost)]
+ portTextField.accessibilityUserInputLabels = [L(.voiceControlProxyPort)]
+ usernameTextField.accessibilityUserInputLabels = [L(.voiceControlProxyUsername)]
+ passwordTextField.accessibilityUserInputLabels = [L(.voiceControlProxyPassword)]
+
+ noProxyView.accessibilityUserInputLabels = [L(.voiceControlProxyNoProxy)]
+ systemProxyView.accessibilityUserInputLabels = [L(.voiceControlProxySystemProxy)]
+ manualProxyView.accessibilityUserInputLabels = [L(.voiceControlProxyManualProxy)]
+
+ setSSLButtonVoiceLabel()
+
+ guard let proxyUITitle = proxyTitle, let noProxyUIView = noProxyView, let systemProxyUIView = systemProxyView, let manualProxyUIView = manualProxyView, let hostUITextField: UITextField = hostTextField, let portUITextField = portTextField, let usernameUITextField = usernameTextField, let passwordUITextField = passwordTextField, let enableSSLUIButton = enableSSLButton else {
+ printLog("Unable to get proxyTitle, noProxyView, systemProxyView, manualProxyView, hostTextField, portTextField, usernameTextField, passwordTextField or enableSSLButton")
+ return
+ }
+
+ if UIAccessibility.isVoiceOverRunning {
+ self.accessibilityElements = [proxyUITitle, noProxyUIView, systemProxyUIView, manualProxyUIView, hostUITextField, portUITextField, usernameUITextField, passwordUITextField, enableSSLUIButton]
+ }
+
+ updateUI()
+ }
+
+ func populate() {
+ updateUI()
+ }
+
+ func setAccessibilityElementsInStackView(stackView: UIStackView, isAccessibilityElement: Bool) {
+ for subview in stackView.arrangedSubviews {
+ subview.isAccessibilityElement = isAccessibilityElement
+ }
+ }
+
+ func handleProxySetting(proxySetting: ProxySetting) {
+ switch proxySetting {
+ case .noProxy:
+ self.noProxyRadioButton.setSelectedState(state: true)
+ self.useSystemProxyRadioButton.setSelectedState(state: false)
+ self.useManualProxyRadioButton.setSelectedState(state: false)
+
+ DefaultsHelper.proxySetting = .noProxy
+
+ self.hostTextField.isEnabled = false
+ self.portTextField.isEnabled = false
+ self.usernameTextField.isEnabled = false
+ self.passwordTextField.isEnabled = false
+
+ self.hostTextField.textColor = .lightGray
+ self.portTextField.textColor = .lightGray
+ self.usernameTextField.textColor = .lightGray
+ self.passwordTextField.textColor = .lightGray
+
+ case .systemProxy:
+ self.noProxyRadioButton.setSelectedState(state: false)
+ self.useSystemProxyRadioButton.setSelectedState(state: true)
+ self.useManualProxyRadioButton.setSelectedState(state: false)
+
+ DefaultsHelper.proxySetting = .systemProxy
+
+ self.hostTextField.isEnabled = false
+ self.portTextField.isEnabled = false
+ self.usernameTextField.isEnabled = false
+ self.passwordTextField.isEnabled = false
+
+ self.hostTextField.textColor = .lightGray
+ self.portTextField.textColor = .lightGray
+ self.usernameTextField.textColor = .lightGray
+ self.passwordTextField.textColor = .lightGray
+
+ case .manualProxy:
+ self.noProxyRadioButton.setSelectedState(state: false)
+ self.useSystemProxyRadioButton.setSelectedState(state: false)
+ self.useManualProxyRadioButton.setSelectedState(state: true)
+
+ DefaultsHelper.proxySetting = .manualProxy
+
+ self.hostTextField.isEnabled = true
+ self.portTextField.isEnabled = true
+ self.usernameTextField.isEnabled = true
+ self.passwordTextField.isEnabled = true
+
+ self.hostTextField.textColor = .black
+ self.portTextField.textColor = .black
+ self.usernameTextField.textColor = .black
+ self.passwordTextField.textColor = .black
+ }
+ }
+
+ @objc func handleState(_ sender: ProxyChoiceTapGestureRecognizer) {
+ handleProxySetting(proxySetting: sender.proxySetting)
+ }
+
+ func updateUI() {
+ DispatchQueue.main.async {
+
+ self.proxyChoicesStackView.isAccessibilityElement = false
+ self.enableSSLStackView.isAccessibilityElement = false
+
+ self.enableSSLButton.isAccessibilityElement = true
+
+ self.setAccessibilityElementsInStackView(stackView: self.proxyChoicesStackView, isAccessibilityElement: true)
+
+ let savedProxySetting = DefaultsHelper.proxySetting
+ self.noProxyRadioButton.setSelectedState(state: savedProxySetting == .noProxy)
+ self.useSystemProxyRadioButton.setSelectedState(state: savedProxySetting == .systemProxy)
+ self.useManualProxyRadioButton.setSelectedState(state: savedProxySetting == .manualProxy)
+
+ self.hostTextField.text = DefaultsHelper.proxyHost
+ self.portTextField.text = String(DefaultsHelper.proxyPort)
+ self.usernameTextField.text = DefaultsHelper.proxyUsername
+ self.passwordTextField.text = KeychainUtil.retrieve(key: proxyPasswordKey) ?? ""
+
+ self.enableSSLButton.isOn = DefaultsHelper.isProxyForSSLEnabled
+ self.enableSSLButton.accessibilityLabel = L(.settingsProxyAllowSSL)
+
+ // Detect which RadioButton was clicked
+ if !(self.noProxyView.gestureRecognizers?.contains(where: { $0 is ProxyChoiceTapGestureRecognizer }) ?? false) {
+
+ let tapGesture = ProxyChoiceTapGestureRecognizer(target: self, action: #selector(self.handleState(_:)))
+ tapGesture.proxySetting = .noProxy
+ self.noProxyView.addGestureRecognizer(tapGesture)
+ self.noProxyView.isUserInteractionEnabled = true
+ }
+
+ if !(self.systemProxyView.gestureRecognizers?.contains(where: { $0 is ProxyChoiceTapGestureRecognizer }) ?? false) {
+
+ let tapGesture = ProxyChoiceTapGestureRecognizer(target: self, action: #selector(self.handleState(_:)))
+ tapGesture.proxySetting = .systemProxy
+ self.systemProxyView.addGestureRecognizer(tapGesture)
+ self.systemProxyView.isUserInteractionEnabled = true
+ }
+
+ if !(self.manualProxyView.gestureRecognizers?.contains(where: { $0 is ProxyChoiceTapGestureRecognizer }) ?? false) {
+ let tapGesture = ProxyChoiceTapGestureRecognizer(target: self, action: #selector(self.handleState(_:)))
+ tapGesture.proxySetting = .manualProxy
+ self.manualProxyView.addGestureRecognizer(tapGesture)
+ self.manualProxyView.isUserInteractionEnabled = true
+ }
+
+ if let number = Int(self.portTextField.text ?? ""), self.isPortNumberValid(portNumber: number) {
+ self.portNumberError.isHidden = true
+ } else {
+ self.portNumberError.isHidden = false
+ }
+
+ self.noProxyView.isAccessibilityElement = true
+ self.systemProxyView.isAccessibilityElement = true
+ self.manualProxyView.isAccessibilityElement = true
+
+ self.noProxyView.accessibilityLabel = L(.settingsProxyNoProxy)
+ self.systemProxyView.accessibilityLabel = L(.settingsProxyUseSystem)
+ self.manualProxyView.accessibilityLabel = L(.settingsProxyUseManual)
+
+ self.proxyTitle.text = L(.settingsProxyTitle)
+
+ self.noProxyTitle.text = L(.settingsProxyNoProxy)
+ self.systemProxyTitle.text = L(.settingsProxyUseSystem)
+ self.manualProxyTitle.text = L(.settingsProxyUseManual)
+
+ self.hostTitle.text = L(.settingsProxyHost)
+ self.portTitle.text = L(.settingsProxyPort)
+ self.usernameTitle.text = L(.settingsProxyUsername)
+ self.passwordTitle.text = L(.settingsProxyPassword)
+
+ self.enableSSLTitle.text = L(.settingsProxyAllowSSL)
+
+ self.handleProxySetting(proxySetting: savedProxySetting)
+ }
+ }
+
+ func presentDismissButton(_ textField: SettingsTextField) {
+ textField.moppPresentDismissButton()
+ }
+
+ func setBorder(_ textField: SettingsTextField) {
+ textField.layer.borderColor = UIColor.moppContentLine.cgColor
+ textField.layer.borderWidth = 1
+ }
+
+ func isPortNumberValid(portNumber: Int) -> Bool {
+ return (1...65535).contains(portNumber)
+ }
+
+ func setSSLButtonVoiceLabel() {
+ enableSSLButton.accessibilityUserInputLabels = enableSSLButton.isOn ? [L(.voiceControlProxyDisallowSsl)] : [L(.settingsProxyAllowSSL)]
+ }
+
+ deinit {
+ let savedProxySetting = DefaultsHelper.proxySetting
+ if savedProxySetting == .noProxy || savedProxySetting == .systemProxy {
+ DefaultsHelper.proxyHost = ""
+ DefaultsHelper.proxyPort = 80
+ DefaultsHelper.proxyUsername = ""
+ KeychainUtil.remove(key: proxyPasswordKey)
+ }
+ printLog("Deinit SettingsProxyCell")
+ }
+}
+
+extension SettingsProxyCell: UITextFieldDelegate {
+ func textFieldDidBeginEditing(_ textField: UITextField) {
+ delegate.didStartEditingField(.proxy, textField)
+ }
+
+ func textFieldDidEndEditing(_ textField: UITextField) {
+ switch textField {
+ case hostTextField:
+ DefaultsHelper.proxyHost = textField.text
+ case portTextField:
+ DefaultsHelper.proxyPort = Int(textField.text ?? "80") ?? 80
+ case usernameTextField:
+ DefaultsHelper.proxyUsername = textField.text
+ case passwordTextField:
+ let _ = KeychainUtil.save(key: proxyPasswordKey, info: textField.text ?? "")
+ default:
+ break
+ }
+ delegate.didEndEditingField(.proxy, with: textField.text ?? String())
+ UIAccessibility.post(notification: UIAccessibility.Notification.screenChanged, argument: textField)
+ }
+
+ func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
+
+ // Allow only numeric characters
+ if textField == portTextField {
+
+ let allowedCharacterSet = CharacterSet.decimalDigits
+ let inputCharacterSet = CharacterSet(charactersIn: string)
+
+ guard allowedCharacterSet.isSuperset(of: inputCharacterSet) else {
+ return false
+ }
+
+ guard let text = textField.text as? NSString else { return false }
+ let portNumber = text.replacingCharacters(in: range, with: string)
+ guard let number = Int(portNumber) else { if portNumber.isEmpty { return true }; return false }
+
+ // Check if port number is within range
+ let isValidPortNumber = isPortNumberValid(portNumber: Int(number))
+ portNumberError.isHidden = isValidPortNumber
+
+ return true
+ }
+ return true
+ }
+}
+
diff --git a/MoppApp/MoppApp/SettingsViewController.swift b/MoppApp/MoppApp/SettingsViewController.swift
index 4c1e4e661..f041e7c1f 100644
--- a/MoppApp/MoppApp/SettingsViewController.swift
+++ b/MoppApp/MoppApp/SettingsViewController.swift
@@ -73,28 +73,49 @@ class SettingsViewController: MoppViewController {
}
func resetSettings() {
+ resetRPAndTimestamp()
+ resetRoleAndAddress()
+ resetTSA()
+ resetSiva()
+ resetProxy()
+
+ tableView.reloadData()
+ }
+
+ func resetRPAndTimestamp() {
DefaultsHelper.rpUuid = ""
DefaultsHelper.timestampUrl = nil
DefaultsHelper.defaultSettingsSwitch = true
-
+ }
+
+ func resetRoleAndAddress() {
DefaultsHelper.isRoleAndAddressEnabled = false
DefaultsHelper.roleNames = []
DefaultsHelper.roleCity = ""
DefaultsHelper.roleState = ""
DefaultsHelper.roleCountry = ""
DefaultsHelper.roleZip = ""
-
- CertUtil.removeCertificate(folder: SettingsTSACertCell.tsaFileFolder, fileName: DefaultsHelper.tsaCertFileName ?? "")
-
- CertUtil.removeCertificate(folder: SettingsSivaCertCell.sivaFileFolder, fileName: DefaultsHelper.sivaCertFileName ?? "")
+ }
+ func resetTSA() {
+ CertUtil.removeCertificate(folder: SettingsTSACertCell.tsaFileFolder, fileName: DefaultsHelper.tsaCertFileName ?? "")
DefaultsHelper.tsaCertFileName = ""
+ }
+
+ func resetSiva() {
+ CertUtil.removeCertificate(folder: SettingsSivaCertCell.sivaFileFolder, fileName: DefaultsHelper.sivaCertFileName ?? "")
DefaultsHelper.sivaCertFileName = ""
-
DefaultsHelper.sivaAccessState = .defaultAccess
DefaultsHelper.sivaUrl = Configuration.getConfiguration().SIVAURL
-
- tableView.reloadData()
+ }
+
+ func resetProxy() {
+ DefaultsHelper.proxySetting = .noProxy
+ DefaultsHelper.proxyHost = ""
+ DefaultsHelper.proxyPort = 80
+ DefaultsHelper.proxyUsername = ""
+ KeychainUtil.remove(key: proxyPasswordKey)
+ DefaultsHelper.isProxyForSSLEnabled = true
}
deinit {
diff --git a/MoppApp/MoppApp/Signing/SigningCategoryViewController.swift b/MoppApp/MoppApp/Signing/SigningCategoryViewController.swift
index 092b240da..157d0cf26 100644
--- a/MoppApp/MoppApp/Signing/SigningCategoryViewController.swift
+++ b/MoppApp/MoppApp/Signing/SigningCategoryViewController.swift
@@ -47,6 +47,7 @@ class SigningCategoryViewController: MoppViewController {
case useDefault
case tsaCert
case sivaCert
+ case proxy
}
struct Field {
@@ -58,6 +59,7 @@ class SigningCategoryViewController: MoppViewController {
case defaultSwitch
case tsaCert
case sivaCert
+ case proxy
}
let id: FieldId
@@ -114,6 +116,12 @@ class SigningCategoryViewController: MoppViewController {
kind: .sivaCert,
title: L(.settingsSivaServiceTitle),
placeholderText: NSAttributedString(string: L(.settingsSivaServiceTitle)),
+ value: ""),
+ Field(
+ id: .proxy,
+ kind: .proxy,
+ title: L(.settingsProxyTitle),
+ placeholderText: NSAttributedString(string: L(.settingsProxyTitle)),
value: "")
]
@@ -139,7 +147,7 @@ class SigningCategoryViewController: MoppViewController {
@objc func accessibilityElementFocused(_ notification: Notification) {
let topViewController = getTopViewController()
- if topViewController is SivaCertViewController { return }
+ if topViewController is SivaCertViewController || topViewController is ProxyViewController { return }
if let element = notification.userInfo?[UIAccessibility.focusedElementUserInfoKey] as? UIView {
let elementRect = element.convert(element.bounds, to: tableView)
let offsetY = elementRect.midY - (tableView.frame.size.height / 4)
@@ -163,7 +171,7 @@ class SigningCategoryViewController: MoppViewController {
if !isDefaultTimestampSettingsEnabled {
- let classOrder = [SettingsDefaultValueCell.self, SettingsRoleAndAddressCell.self, SettingsFieldCell.self, SettingsTimeStampCell.self, SettingsTSACertCell.self, SivaCategoryCell.self, SettingsHeaderCell.self, SettingsDefaultValueCell.self]
+ let classOrder = [SettingsDefaultValueCell.self, SettingsRoleAndAddressCell.self, SettingsFieldCell.self, SettingsTimeStampCell.self, SettingsTSACertCell.self, SivaCategoryCell.self, ProxyCategoryCell.self, SettingsHeaderCell.self, SettingsDefaultValueCell.self]
for className in classOrder {
for key in tableViewCells.keys.sorted() {
@@ -175,7 +183,7 @@ class SigningCategoryViewController: MoppViewController {
}
}
} else {
- let accessibilityClassOrder = [SettingsDefaultValueCell.self, SettingsRoleAndAddressCell.self, SettingsFieldCell.self, SettingsTimeStampCell.self, SivaCategoryCell.self, SettingsHeaderCell.self, SettingsDefaultValueCell.self]
+ let accessibilityClassOrder = [SettingsDefaultValueCell.self, SettingsRoleAndAddressCell.self, SettingsFieldCell.self, SettingsTimeStampCell.self, SivaCategoryCell.self, ProxyCategoryCell.self, SettingsHeaderCell.self, SettingsDefaultValueCell.self]
for className in accessibilityClassOrder {
for key in tableViewCells.keys.sorted() {
@@ -280,6 +288,12 @@ extension SigningCategoryViewController: UITableViewDelegate, UITableViewDataSou
sivaCertCell.populate()
tableViewCells[indexPath] = sivaCertCell
return sivaCertCell
+ case .proxy:
+ let proxyCell = tableView.dequeueReusableCell(withType: ProxyCategoryCell.self, for: indexPath)!
+ proxyCell.topViewController = getTopViewController()
+ proxyCell.populate()
+ tableViewCells[indexPath] = proxyCell
+ return proxyCell
}
}
return UITableViewCell()
@@ -300,6 +314,10 @@ extension SigningCategoryViewController: SettingsHeaderCellDelegate {
}
extension SigningCategoryViewController: SettingsCellDelegate {
+ func didStartEditingField(_ field: FieldId, _ textField: UITextField) {
+ return
+ }
+
func didStartEditingField(_ field: FieldId, _ indexPath: IndexPath) {
switch field {
case .rpuuid:
@@ -339,7 +357,8 @@ extension SigningCategoryViewController: SettingsTimeStampCellDelegate {
self?.errorAlertWithLink(message: MessageUtil.generateDetailedErrorMessage(error: nsError) ?? L(.genericErrorMessage))
}, usingTestDigiDocService: useTestDDS, andTSUrl: DefaultsHelper.timestampUrl ?? MoppConfiguration.getMoppLibConfiguration().tsaurl,
- withMoppConfiguration: MoppConfiguration.getMoppLibConfiguration())
+ withMoppConfiguration: MoppConfiguration.getMoppLibConfiguration(),
+ andProxyConfiguration: ManualProxy.getMoppLibProxyConfiguration())
}
}
diff --git a/MoppApp/MoppApp/Signing/SivaCertViewController.swift b/MoppApp/MoppApp/Signing/Siva/SivaCertViewController.swift
similarity index 97%
rename from MoppApp/MoppApp/Signing/SivaCertViewController.swift
rename to MoppApp/MoppApp/Signing/Siva/SivaCertViewController.swift
index 011a568db..9a3b608a5 100644
--- a/MoppApp/MoppApp/Signing/SivaCertViewController.swift
+++ b/MoppApp/MoppApp/Signing/Siva/SivaCertViewController.swift
@@ -118,6 +118,8 @@ extension SivaCertViewController: SettingsHeaderCellDelegate {
}
extension SivaCertViewController: SettingsCellDelegate {
+ func didStartEditingField(_ field: SigningCategoryViewController.FieldId, _ textField: UITextField) { return }
+
func didStartEditingField(_ field: SigningCategoryViewController.FieldId, _ indexPath: IndexPath) {
currentlyEditingCell = indexPath
}
diff --git a/MoppApp/MoppApp/SmartIDSignature.swift b/MoppApp/MoppApp/SmartIDSignature.swift
index 657912630..929e3ce87 100644
--- a/MoppApp/MoppApp/SmartIDSignature.swift
+++ b/MoppApp/MoppApp/SmartIDSignature.swift
@@ -72,7 +72,7 @@ class SmartIDSignature {
}
self.selectAccount()
- SIDRequest.shared.getCertificate(baseUrl: baseUrl, country: country, nationalIdentityNumber: nationalIdentityNumber, requestParameters: requestParameters, trustedCertificates: trustedCertificates) { result in
+ SIDRequest.shared.getCertificate(baseUrl: baseUrl, country: country, nationalIdentityNumber: nationalIdentityNumber, requestParameters: requestParameters, trustedCertificates: trustedCertificates, manualProxyConf: ManualProxy.getManualProxyConfiguration()) { result in
switch result {
case .success(let response):
printLog("Received Certificate (session ID): \(response.sessionID)")
@@ -106,7 +106,7 @@ class SmartIDSignature {
return CancelUtil.handleCancelledRequest(errorMessageDetails: "User cancelled Smart-ID signing")
}
- SIDRequest.shared.getSignature(baseUrl: baseUrl, documentNumber: documentNumber, allowedInteractionsOrder: allowedInteractionsOrder, trustedCertificates: trustedCertificates) { result in
+ SIDRequest.shared.getSignature(baseUrl: baseUrl, documentNumber: documentNumber, allowedInteractionsOrder: allowedInteractionsOrder, trustedCertificates: trustedCertificates, manualProxyConf: ManualProxy.getManualProxyConfiguration()) { result in
switch result {
case .success(let response):
printLog("Received Signature (session ID): \(response.sessionID)")
@@ -134,7 +134,7 @@ class SmartIDSignature {
return CancelUtil.handleCancelledRequest(errorMessageDetails: "User cancelled Smart-ID signing")
}
- SIDRequest.shared.getSessionStatus(baseUrl: baseUrl, sessionId: sessionId, timeoutMs: kDefaultTimeoutMs, trustedCertificates: trustedCertificates) { result in
+ SIDRequest.shared.getSessionStatus(baseUrl: baseUrl, sessionId: sessionId, timeoutMs: kDefaultTimeoutMs, trustedCertificates: trustedCertificates, manualProxyConf: ManualProxy.getManualProxyConfiguration()) { result in
switch result {
case .success(let sessionStatus):
printLog("RIA.SmartID - Session status \(sessionStatus.state.rawValue)")
diff --git a/MoppApp/MoppApp/en.lproj/Localizable.strings b/MoppApp/MoppApp/en.lproj/Localizable.strings
index eca2e1388..a7f351161 100755
--- a/MoppApp/MoppApp/en.lproj/Localizable.strings
+++ b/MoppApp/MoppApp/en.lproj/Localizable.strings
@@ -381,6 +381,15 @@
"settings-siva-default-access-title" = "Use default access";
"settings-siva-default-manual-access-title" = "Use manually configured access";
"settings-siva-default-certificate-title" = "Digital Signature Validation Service SiVa SSL certificate";
+"settings-proxy-title" = "Proxy";
+"settings-proxy-no-proxy" = "No proxy";
+"settings-proxy-use-system" = "Use system proxy settings";
+"settings-proxy-use-manual" = "Manual proxy configuration";
+"settings-proxy-host" = "Host";
+"settings-proxy-port" = "Port";
+"settings-proxy-username" = "Username";
+"settings-proxy-password" = "Password";
+"settings-proxy-allow-ssl" = "Enable proxy for SSL connections";
"settings-reset-button" = "USE DEFAULT SETTINGS";
"diagnostics-title" = "Diagnostics";
"diagnostics-activate-one-time-logging" = "Enable one-time log generation";
@@ -535,3 +544,11 @@
"voice-control-disable-default-timestamping-service" = "Disable default TimeStamping service access";
"voice-control-enable-role-and-address" = "Enable role and address";
"voice-control-disable-role-and-address" = "Disable role and address";
+"voice-control-no-proxy" = "No proxy";
+"voice-control-proxy-system" = "Use system proxy";
+"voice-control-proxy-manual" = "Use manual proxy";
+"voice-control-proxy-host" = "Edit proxy host";
+"voice-control-proxy-port" = "Edit proxy port";
+"voice-control-proxy-username" = "Edit proxy username";
+"voice-control-proxy-password" = "Edit proxy password";
+"voice-control-proxy-disallow-ssl" = "Disable proxy for SSL connections";
diff --git a/MoppApp/MoppApp/et.lproj/Localizable.strings b/MoppApp/MoppApp/et.lproj/Localizable.strings
index 173e3f65f..7ea387d35 100755
--- a/MoppApp/MoppApp/et.lproj/Localizable.strings
+++ b/MoppApp/MoppApp/et.lproj/Localizable.strings
@@ -382,6 +382,15 @@
"settings-siva-default-access-title" = "Kasutan vaikimisi määratud ligipääsu";
"settings-siva-default-manual-access-title" = "Kasutan käsitsi määratud ligipääsu";
"settings-siva-default-certificate-title" = "Valideerimisteenuse SiVa SSL sertifikaat";
+"settings-proxy-title" = "Proksi";
+"settings-proxy-no-proxy" = "Ei kasuta proksit";
+"settings-proxy-use-system" = "Kasuta süsteemseid proksi seadeid";
+"settings-proxy-use-manual" = "Proksi seaded määratakse käsitsi";
+"settings-proxy-host" = "Host";
+"settings-proxy-port" = "Port";
+"settings-proxy-username" = "Kasutajanimi";
+"settings-proxy-password" = "Parool";
+"settings-proxy-allow-ssl" = "Luba proksi kasutamine SSL-ühenduste jaoks";
"settings-reset-button" = "TAASTA ALGSEADED";
"diagnostics-title" = "Diagnostika";
"diagnostics-activate-one-time-logging" = "Aktiveeri ühekordne logifaili genereerimine";
@@ -535,3 +544,11 @@
"voice-control-disable-default-timestamping-service" = "Disable default TimeStamping service access";
"voice-control-enable-role-and-address" = "Enable role and address";
"voice-control-disable-role-and-address" = "Disable role and address";
+"voice-control-no-proxy" = "No proxy";
+"voice-control-proxy-system" = "Use system proxy";
+"voice-control-proxy-manual" = "Use manual proxy";
+"voice-control-proxy-host" = "Edit proxy host";
+"voice-control-proxy-port" = "Edit proxy port";
+"voice-control-proxy-username" = "Edit proxy username";
+"voice-control-proxy-password" = "Edit proxy password";
+"voice-control-proxy-disallow-ssl" = "Disable proxy for SSL connections";
diff --git a/MoppApp/MoppApp/ru.lproj/Localizable.strings b/MoppApp/MoppApp/ru.lproj/Localizable.strings
index 62cd512ee..3d287992f 100644
--- a/MoppApp/MoppApp/ru.lproj/Localizable.strings
+++ b/MoppApp/MoppApp/ru.lproj/Localizable.strings
@@ -379,6 +379,15 @@
"settings-timestamp-cert-add-certificate-button" = "ДОБАВИТЬ СЕРТИФИКАТ";
"settings-timestamp-cert-show-certificate-button" = "ПОКАЗАТЬ СЕРТИФИКАТ";
"settings-siva-service-title" = "Доступ к услуге валидации SiVa";
+"settings-proxy-title" = "Прокси";
+"settings-proxy-no-proxy" = "Прокси не используется";
+"settings-proxy-use-system" = "Использовать системные настройки прокси";
+"settings-proxy-use-manual" = "Настроить прокси вручную";
+"settings-proxy-host" = "Хост";
+"settings-proxy-port" = "Порт";
+"settings-proxy-username" = "Имя пользователя";
+"settings-proxy-password" = "Пароль";
+"settings-proxy-allow-ssl" = "Включить прокси-сервер для подключения SSL";
"settings-siva-default-access-title" = "Использовать доступ, назначенный по умолчанию";
"settings-siva-default-manual-access-title" = "Использовать доступ, назначенный вручную";
"settings-siva-default-certificate-title" = "Сертификат услуги валидации SiVa SSL";
@@ -536,3 +545,11 @@
"voice-control-disable-default-timestamping-service" = "Disable default TimeStamping service access";
"voice-control-enable-role-and-address" = "Enable role and address";
"voice-control-disable-role-and-address" = "Disable role and address";
+"voice-control-no-proxy" = "No proxy";
+"voice-control-proxy-system" = "Use system proxy";
+"voice-control-proxy-manual" = "Use manual proxy";
+"voice-control-proxy-host" = "Edit proxy host";
+"voice-control-proxy-port" = "Edit proxy port";
+"voice-control-proxy-username" = "Edit proxy username";
+"voice-control-proxy-password" = "Edit proxy password";
+"voice-control-proxy-disallow-ssl" = "Disable proxy for SSL connections";
diff --git a/MoppLib/MoppLib.xcodeproj/project.pbxproj b/MoppLib/MoppLib.xcodeproj/project.pbxproj
index 6855ab375..61bb31806 100644
--- a/MoppLib/MoppLib.xcodeproj/project.pbxproj
+++ b/MoppLib/MoppLib.xcodeproj/project.pbxproj
@@ -73,6 +73,8 @@
DF87E9CE292CC79500C2E3F4 /* libdigidocpp_util.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DF87E9CD292CC77C00C2E3F4 /* libdigidocpp_util.a */; };
DFBDF1F827DA44BD00A5CF3C /* MoppLibRoleAddressData.h in Headers */ = {isa = PBXBuildFile; fileRef = DFBDF1F727DA44BD00A5CF3C /* MoppLibRoleAddressData.h */; settings = {ATTRIBUTES = (Public, ); }; };
DFBDF1FA27DA44FD00A5CF3C /* MoppLibRoleAddressData.m in Sources */ = {isa = PBXBuildFile; fileRef = DFBDF1F927DA44FD00A5CF3C /* MoppLibRoleAddressData.m */; };
+ DFDD76292B507EFF0008EC2C /* MoppLibProxyConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = DFDD76282B507EFF0008EC2C /* MoppLibProxyConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ DFDD762B2B507F9E0008EC2C /* MoppLibProxyConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = DFDD762A2B507F9E0008EC2C /* MoppLibProxyConfiguration.m */; };
DFF3C3A923322E0D0079458A /* MOPPLibConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = DFF3C3A723322E0C0079458A /* MOPPLibConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; };
DFF3C3AA23322E0D0079458A /* MOPPLibConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = DFF3C3A823322E0C0079458A /* MOPPLibConfiguration.m */; };
DFFFCBCC238D470200059717 /* MoppLibGlobals.h in Headers */ = {isa = PBXBuildFile; fileRef = DFFFCBCB238D470200059717 /* MoppLibGlobals.h */; };
@@ -183,6 +185,8 @@
DF87E9CD292CC77C00C2E3F4 /* libdigidocpp_util.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libdigidocpp_util.a; path = MoppLib/libdigidocpp/libdigidocpp.iphoneos/lib/libdigidocpp_util.a; sourceTree = ""; };
DFBDF1F727DA44BD00A5CF3C /* MoppLibRoleAddressData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MoppLibRoleAddressData.h; sourceTree = ""; };
DFBDF1F927DA44FD00A5CF3C /* MoppLibRoleAddressData.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MoppLibRoleAddressData.m; sourceTree = ""; };
+ DFDD76282B507EFF0008EC2C /* MoppLibProxyConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MoppLibProxyConfiguration.h; sourceTree = ""; };
+ DFDD762A2B507F9E0008EC2C /* MoppLibProxyConfiguration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MoppLibProxyConfiguration.m; sourceTree = ""; };
DFF3C3A723322E0C0079458A /* MOPPLibConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MOPPLibConfiguration.h; sourceTree = ""; };
DFF3C3A823322E0C0079458A /* MOPPLibConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MOPPLibConfiguration.m; sourceTree = ""; };
DFFFCBCB238D470200059717 /* MoppLibGlobals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MoppLibGlobals.h; sourceTree = ""; };
@@ -270,6 +274,8 @@
54DC0DC81E0BCCEF00C62B3D /* MoppLibConstants.m */,
C54EA735204D90D50039AC78 /* MoppLibCardReaderManager.h */,
C54EA737204D91730039AC78 /* MoppLibCardReaderManager.m */,
+ DFDD76282B507EFF0008EC2C /* MoppLibProxyConfiguration.h */,
+ DFDD762A2B507F9E0008EC2C /* MoppLibProxyConfiguration.m */,
);
name = PublicInterface;
path = MoppLib/PublicInterface;
@@ -470,6 +476,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
+ DFDD76292B507EFF0008EC2C /* MoppLibProxyConfiguration.h in Headers */,
DFBDF1F827DA44BD00A5CF3C /* MoppLibRoleAddressData.h in Headers */,
C5AAAF8620CAA3F00087D6DA /* winscard.h in Headers */,
C5AAAF8820CAA4240087D6DA /* wintypes.h in Headers */,
@@ -644,6 +651,7 @@
E42B08B61E1F0B3B00EA24A3 /* MoppLibContainer.m in Sources */,
54D1647C1E926AAB0069C725 /* MoppLibCardActions.m in Sources */,
E42B08CA1E1F11C100EA24A3 /* MoppLibSignature.m in Sources */,
+ DFDD762B2B507F9E0008EC2C /* MoppLibProxyConfiguration.m in Sources */,
54DC0DCA1E0BCCEF00C62B3D /* MoppLibConstants.m in Sources */,
54DC0DF51E0BEF2A00C62B3D /* NSString+Additions.m in Sources */,
540CB2211E1CDCED00FE18A3 /* MoppLibCertificate.mm in Sources */,
diff --git a/MoppLib/MoppLib/MoppLibDigidocManager.h b/MoppLib/MoppLib/MoppLibDigidocManager.h
index 11c6aa9f5..0201d0cee 100644
--- a/MoppLib/MoppLib/MoppLibDigidocManager.h
+++ b/MoppLib/MoppLib/MoppLibDigidocManager.h
@@ -27,6 +27,7 @@
#import "MoppLibConstants.h"
#import "MoppLibConfiguration.h"
#import "MoppLibRoleAddressData.h"
+#import "MoppLibProxyConfiguration.h"
typedef enum {
Unspecified,
@@ -38,7 +39,7 @@ typedef enum {
@property (readonly) BOOL useTestDigiDocService;
+ (MoppLibDigidocManager *)sharedInstance;
-- (void)setupWithSuccess:(VoidBlock)success andFailure:(FailureBlock)failure usingTestDigiDocService:(BOOL)useTestDDS andTSUrl:(NSString*)tsUrl withMoppConfiguration:(MoppLibConfiguration*)moppConfiguration;
+- (void)setupWithSuccess:(VoidBlock)success andFailure:(FailureBlock)failure usingTestDigiDocService:(BOOL)useTestDDS andTSUrl:(NSString*)tsUrl withMoppConfiguration:(MoppLibConfiguration*)moppConfiguration andProxyConfiguration:(MoppLibProxyConfiguration*)proxyConfiguration;
- (MoppLibContainer *)getContainerWithPath:(NSString *)containerPath error:(NSError **)error;
- (MoppLibContainer *)createContainerWithPath:(NSString *)containerPath withDataFilePaths:(NSArray *)dataFilePaths error:(NSError **)error;
diff --git a/MoppLib/MoppLib/MoppLibDigidocManager.mm b/MoppLib/MoppLib/MoppLibDigidocManager.mm
index b07cd103f..4d6252a9e 100644
--- a/MoppLib/MoppLib/MoppLibDigidocManager.mm
+++ b/MoppLib/MoppLib/MoppLibDigidocManager.mm
@@ -42,6 +42,7 @@
#import
#import
#import "MoppLibGlobals.h"
+#import "MoppLibProxyConfiguration.h"
#include
@@ -59,10 +60,11 @@
private:
std::string m_tsUrl;
MoppLibConfiguration *moppLibConfiguration;
+ MoppLibProxyConfiguration *proxyConfiguration;
public:
- DigiDocConf(const std::string& tsUrl, MoppLibConfiguration* moppConfiguration) : m_tsUrl( tsUrl ), moppLibConfiguration( moppConfiguration ) {}
+ DigiDocConf(const std::string& tsUrl, MoppLibConfiguration* moppConfiguration, MoppLibProxyConfiguration* proxyConfiguration) : m_tsUrl( tsUrl ), moppLibConfiguration( moppConfiguration ), proxyConfiguration( proxyConfiguration ) {}
std::string TSLCache() const override {
NSString *tslCachePath = [[MLFileManager sharedInstance] tslCachePath];
@@ -140,6 +142,23 @@
return std::string();
}
}
+
+ virtual std::string proxyHost() const override {
+ return std::string([proxyConfiguration.HOST UTF8String]);
+ }
+
+ virtual std::string proxyPort() const override {
+ NSInteger port = [proxyConfiguration.PORT integerValue];
+ return std::to_string(port);
+ }
+
+ virtual std::string proxyUser() const override {
+ return std::string([proxyConfiguration.USERNAME UTF8String]);
+ }
+
+ virtual std::string proxyPass() const override {
+ return std::string([proxyConfiguration.PASSWORD UTF8String]);
+ }
std::vector stringsToX509Certs(NSArray *certBundle) const {
__block std::vector x509Certs;
@@ -268,7 +287,7 @@ + (MoppLibDigidocManager *)sharedInstance {
return sharedInstance;
}
-- (void)setupWithSuccess:(VoidBlock)success andFailure:(FailureBlock)failure usingTestDigiDocService:(BOOL)useTestDDS andTSUrl:(NSString*)tsUrl withMoppConfiguration:(MoppLibConfiguration*)moppConfiguration {
+- (void)setupWithSuccess:(VoidBlock)success andFailure:(FailureBlock)failure usingTestDigiDocService:(BOOL)useTestDDS andTSUrl:(NSString*)tsUrl withMoppConfiguration:(MoppLibConfiguration*)moppConfiguration andProxyConfiguration:(MoppLibProxyConfiguration*)proxyConfiguration {
dispatch_async(dispatch_get_main_queue(), ^{
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
@@ -278,7 +297,7 @@ - (void)setupWithSuccess:(VoidBlock)success andFailure:(FailureBlock)failure usi
std::string timestampUrl = tsUrl == nil ?
[moppConfiguration.TSAURL cStringUsingEncoding:NSUTF8StringEncoding] :
[tsUrl cStringUsingEncoding:NSUTF8StringEncoding];
- digidoc::Conf::init(new DigiDocConf(timestampUrl, moppConfiguration));
+ digidoc::Conf::init(new DigiDocConf(timestampUrl, moppConfiguration, proxyConfiguration));
NSString *appInfo = [self userAgent];
std::string appInfoObjcString = std::string([appInfo UTF8String]);
digidoc::initialize(appInfoObjcString, appInfoObjcString);
diff --git a/MoppLib/MoppLib/PublicInterface/MoppLibManager.h b/MoppLib/MoppLib/PublicInterface/MoppLibManager.h
index 6013ad3b2..154ee273f 100644
--- a/MoppLib/MoppLib/PublicInterface/MoppLibManager.h
+++ b/MoppLib/MoppLib/PublicInterface/MoppLibManager.h
@@ -26,6 +26,7 @@
#import "MoppLibConstants.h"
#import "MOPPLibConfiguration.h"
#import "MoppLibRoleAddressData.h"
+#import "MoppLibProxyConfiguration.h"
typedef NS_ENUM(NSUInteger, EIDType) {
EIDTypeUnknown,
@@ -46,7 +47,7 @@ typedef NS_ENUM(NSUInteger, EIDType) {
* @param success Block to be called on successful completion of action.
* @param failure Block to be called when action fails. Includes error.
*/
-- (void)setupWithSuccess:(VoidBlock)success andFailure:(FailureBlock)failure usingTestDigiDocService:(BOOL)useTestDDS andTSUrl:(NSString *)tsUrl withMoppConfiguration:(MoppLibConfiguration *)moppConfiguration;
+- (void)setupWithSuccess:(VoidBlock)success andFailure:(FailureBlock)failure usingTestDigiDocService:(BOOL)useTestDDS andTSUrl:(NSString *)tsUrl withMoppConfiguration:(MoppLibConfiguration *)moppConfiguration andProxyConfiguration:(MoppLibProxyConfiguration*)proxyConfiguration;
+ (NSString *)prepareSignature:(NSString *)cert containerPath:(NSString *)containerPath roleData:(MoppLibRoleAddressData *)roleData;
+ (NSArray *)getDataToSign;
diff --git a/MoppLib/MoppLib/PublicInterface/MoppLibManager.m b/MoppLib/MoppLib/PublicInterface/MoppLibManager.m
index 046cde1f0..d69fbf942 100644
--- a/MoppLib/MoppLib/PublicInterface/MoppLibManager.m
+++ b/MoppLib/MoppLib/PublicInterface/MoppLibManager.m
@@ -35,8 +35,8 @@ + (MoppLibManager *)sharedInstance {
return sharedInstance;
}
-- (void)setupWithSuccess:(VoidBlock)success andFailure:(FailureBlock)failure usingTestDigiDocService:(BOOL)useTestDDS andTSUrl:(NSString *)tsUrl withMoppConfiguration:(MoppLibConfiguration *)moppConfiguration {
- [[MoppLibDigidocManager sharedInstance] setupWithSuccess:success andFailure:failure usingTestDigiDocService:useTestDDS andTSUrl:tsUrl withMoppConfiguration: moppConfiguration];
+- (void)setupWithSuccess:(VoidBlock)success andFailure:(FailureBlock)failure usingTestDigiDocService:(BOOL)useTestDDS andTSUrl:(NSString *)tsUrl withMoppConfiguration:(MoppLibConfiguration *)moppConfiguration andProxyConfiguration:(MoppLibProxyConfiguration*)proxyConfiguration {
+ [[MoppLibDigidocManager sharedInstance] setupWithSuccess:success andFailure:failure usingTestDigiDocService:useTestDDS andTSUrl:tsUrl withMoppConfiguration: moppConfiguration andProxyConfiguration: proxyConfiguration];
}
+ (NSString *)prepareSignature:(NSString *)cert containerPath:(NSString *)containerPath roleData:(MoppLibRoleAddressData *)roleData {
diff --git a/MoppLib/MoppLib/PublicInterface/MoppLibProxyConfiguration.h b/MoppLib/MoppLib/PublicInterface/MoppLibProxyConfiguration.h
new file mode 100644
index 000000000..27d6290dc
--- /dev/null
+++ b/MoppLib/MoppLib/PublicInterface/MoppLibProxyConfiguration.h
@@ -0,0 +1,35 @@
+//
+// MoppLibProxyConfiguration.h
+// MoppLib
+//
+/*
+ * Copyright 2017 - 2023 Riigi Infosüsteemi Amet
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#import
+
+@interface MoppLibProxyConfiguration : NSObject
+
+@property (nonatomic, strong) NSString *HOST;
+@property (nonatomic, strong) NSNumber *PORT;
+@property (nonatomic, strong) NSString *USERNAME;
+@property (nonatomic, strong) NSString *PASSWORD;
+
+- (id) initWithConfiguration:(NSString *)HOST PORT:(NSNumber *)PORT USERNAME:(NSString *)USERNAME PASSWORD:(NSString *)PASSWORD;
+
+@end
diff --git a/MoppLib/MoppLib/PublicInterface/MoppLibProxyConfiguration.m b/MoppLib/MoppLib/PublicInterface/MoppLibProxyConfiguration.m
new file mode 100644
index 000000000..511585862
--- /dev/null
+++ b/MoppLib/MoppLib/PublicInterface/MoppLibProxyConfiguration.m
@@ -0,0 +1,40 @@
+//
+// MoppLibProxyConfiguration.m
+// MoppLib
+//
+/*
+ * Copyright 2017 - 2023 Riigi Infosüsteemi Amet
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#import "MoppLibProxyConfiguration.h"
+
+@implementation MoppLibProxyConfiguration
+
+- (id) initWithConfiguration:(NSString *)HOST PORT:(NSNumber *)PORT USERNAME:(NSString *)USERNAME PASSWORD:(NSString *)PASSWORD {
+ self = [super init];
+ if (self) {
+ self.HOST = HOST;
+ self.PORT = PORT;
+ self.USERNAME = USERNAME;
+ self.PASSWORD = PASSWORD;
+ }
+
+ return self;
+}
+
+@end
diff --git a/SkSigningLib/SkSigningLib.xcodeproj/project.pbxproj b/SkSigningLib/SkSigningLib.xcodeproj/project.pbxproj
index 5a6d8928f..bbe8af318 100644
--- a/SkSigningLib/SkSigningLib.xcodeproj/project.pbxproj
+++ b/SkSigningLib/SkSigningLib.xcodeproj/project.pbxproj
@@ -22,6 +22,8 @@
DF3D29B223F6A92A007181B8 /* SkSigningLib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DF3D29A823F6A929007181B8 /* SkSigningLib.framework */; };
DF3D29B723F6A92A007181B8 /* SkSigningLibTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF3D29B623F6A92A007181B8 /* SkSigningLibTests.swift */; };
DF3D29B923F6A92A007181B8 /* SkSigningLib.h in Headers */ = {isa = PBXBuildFile; fileRef = DF3D29AB23F6A929007181B8 /* SkSigningLib.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ DF41B54D2B506F3B00594D01 /* ProxyUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF41B54C2B506F3B00594D01 /* ProxyUtil.swift */; };
+ DF41B54E2B506F3B00594D01 /* Proxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF41B54B2B506F3A00594D01 /* Proxy.swift */; };
DF90EDE024223D6A0040FFE7 /* ControlCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF90EDDF24223D6A0040FFE7 /* ControlCode.swift */; };
DFBA32A2299EA5D400788A87 /* CancelRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFBA32A1299EA5D400788A87 /* CancelRequest.swift */; };
DFBA32A429A59B2500788A87 /* CancelRequestUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFBA32A329A59B2500788A87 /* CancelRequestUtil.swift */; };
@@ -65,6 +67,8 @@
DF3D29B123F6A929007181B8 /* SkSigningLibTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SkSigningLibTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
DF3D29B623F6A92A007181B8 /* SkSigningLibTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SkSigningLibTests.swift; sourceTree = ""; };
DF3D29B823F6A92A007181B8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ DF41B54B2B506F3A00594D01 /* Proxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Proxy.swift; sourceTree = ""; };
+ DF41B54C2B506F3B00594D01 /* ProxyUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProxyUtil.swift; sourceTree = ""; };
DF90EDDF24223D6A0040FFE7 /* ControlCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlCode.swift; sourceTree = ""; };
DFBA32A1299EA5D400788A87 /* CancelRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CancelRequest.swift; sourceTree = ""; };
DFBA32A329A59B2500788A87 /* CancelRequestUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CancelRequestUtil.swift; sourceTree = ""; };
@@ -139,6 +143,7 @@
DF04A88E23FEC7000086C9F9 /* Utilities */ = {
isa = PBXGroup;
children = (
+ DF41B54F2B506F4000594D01 /* Proxy */,
DF04A88F23FEC7130086C9F9 /* EncoderDecoder.swift */,
DF90EDDF24223D6A0040FFE7 /* ControlCode.swift */,
DF3653B1242BA07400C48AC5 /* Logging.swift */,
@@ -226,6 +231,15 @@
path = SkSigningLibTests;
sourceTree = "";
};
+ DF41B54F2B506F4000594D01 /* Proxy */ = {
+ isa = PBXGroup;
+ children = (
+ DF41B54C2B506F3B00594D01 /* ProxyUtil.swift */,
+ DF41B54B2B506F3A00594D01 /* Proxy.swift */,
+ );
+ path = Proxy;
+ sourceTree = "";
+ };
DFBA32A729A5AEC200788A87 /* Mobile-ID */ = {
isa = PBXGroup;
children = (
@@ -395,6 +409,7 @@
files = (
4E59081A24B30B2C001B23A6 /* SIDCertificateRequestParameters.swift in Sources */,
DFD204E7240D274E00EB8150 /* SessionResponse.swift in Sources */,
+ DF41B54D2B506F3B00594D01 /* ProxyUtil.swift in Sources */,
DFD204EF240FD9FD00EB8150 /* SessionStatusResponse.swift in Sources */,
DF04A88D23FEA6950086C9F9 /* RequestSignature.swift in Sources */,
DF3653B2242BA07400C48AC5 /* Logging.swift in Sources */,
@@ -411,6 +426,7 @@
4E59081C24B30C62001B23A6 /* SIDSignatureRequestParameters.swift in Sources */,
DFD204E4240D20B300EB8150 /* SessionRequestParameters.swift in Sources */,
DF90EDE024223D6A0040FFE7 /* ControlCode.swift in Sources */,
+ DF41B54E2B506F3B00594D01 /* Proxy.swift in Sources */,
DF04A89523FEDC810086C9F9 /* CertificateRequestParameters.swift in Sources */,
DFD204F124100C5500EB8150 /* SessionResponseSignature.swift in Sources */,
DFBA32A2299EA5D400788A87 /* CancelRequest.swift in Sources */,
diff --git a/SkSigningLib/SkSigningLib.xcodeproj/xcuserdata/martenr.xcuserdatad/xcschemes/xcschememanagement.plist b/SkSigningLib/SkSigningLib.xcodeproj/xcuserdata/martenr.xcuserdatad/xcschemes/xcschememanagement.plist
index c7f6093c1..feae86fb5 100644
--- a/SkSigningLib/SkSigningLib.xcodeproj/xcuserdata/martenr.xcuserdatad/xcschemes/xcschememanagement.plist
+++ b/SkSigningLib/SkSigningLib.xcodeproj/xcuserdata/martenr.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -7,7 +7,7 @@
SkSigningLib.xcscheme_^#shared#^_
orderHint
- 17
+ 27
diff --git a/SkSigningLib/SkSigningLib/Requests/Mobile-ID/RequestSession.swift b/SkSigningLib/SkSigningLib/Requests/Mobile-ID/RequestSession.swift
index 778a002aa..be5cd906f 100644
--- a/SkSigningLib/SkSigningLib/Requests/Mobile-ID/RequestSession.swift
+++ b/SkSigningLib/SkSigningLib/Requests/Mobile-ID/RequestSession.swift
@@ -32,7 +32,7 @@ protocol SessionRequest {
- requestParameters: Parameters that are sent to the service.
- completionHandler: On request success, callbacks Result
*/
- func getSession(baseUrl: String, requestParameters: SessionRequestParameters, trustedCertificates: [String]?, completionHandler: @escaping (Result) -> Void)
+ func getSession(baseUrl: String, requestParameters: SessionRequestParameters, trustedCertificates: [String]?, manualProxyConf: Proxy, completionHandler: @escaping (Result) -> Void)
/**
Gets session status info for Mobile-ID. This method invokes SIM toolkit
@@ -43,7 +43,7 @@ protocol SessionRequest {
- requestParameters: Parameters that are used in URL
- completionHandler: On request success, callbacks Result
*/
- func getSessionStatus(baseUrl: String, process: PollingProcess, requestParameters: SessionStatusRequestParameters, trustedCertificates: [String]?, completionHandler: @escaping (Result) -> Void)
+ func getSessionStatus(baseUrl: String, process: PollingProcess, requestParameters: SessionStatusRequestParameters, trustedCertificates: [String]?, manualProxyConf: Proxy, completionHandler: @escaping (Result) -> Void)
}
/**
@@ -61,7 +61,7 @@ public class RequestSession: NSObject, URLSessionDelegate, SessionRequest {
urlTask?.cancel()
}
- public func getSession(baseUrl: String, requestParameters: SessionRequestParameters, trustedCertificates: [String]?, completionHandler: @escaping (Result) -> Void) {
+ public func getSession(baseUrl: String, requestParameters: SessionRequestParameters, trustedCertificates: [String]?, manualProxyConf: Proxy, completionHandler: @escaping (Result) -> Void) {
guard let url = URL(string: "\(baseUrl)/signature") else {
completionHandler(.failure(.invalidURL))
return
@@ -87,11 +87,13 @@ public class RequestSession: NSObject, URLSessionDelegate, SessionRequest {
"\tdisplayText: \(requestParameters.displayText ?? "")\n"
)
- let urlSessionConfiguration: URLSessionConfiguration
+ var urlSessionConfiguration: URLSessionConfiguration
let urlSession: URLSession
if trustedCertificates != nil {
urlSessionConfiguration = URLSessionConfiguration.default
+ ProxyUtil.configureURLSessionWithProxy(urlSessionConfiguration: &urlSessionConfiguration, manualProxyConf: manualProxyConf)
+ ProxyUtil.setProxyAuthorizationHeader(request: &request, urlSessionConfiguration: urlSessionConfiguration, manualProxyConf: manualProxyConf)
urlSession = URLSession(configuration: urlSessionConfiguration, delegate: self, delegateQueue: nil)
} else {
urlSession = URLSession.shared
@@ -136,7 +138,7 @@ public class RequestSession: NSObject, URLSessionDelegate, SessionRequest {
CertificatePinning().certificatePinning(trustedCertificates: trustedCerts ?? [""], challenge: challenge, completionHandler: completionHandler)
}
- public func getSessionStatus(baseUrl: String, process: PollingProcess, requestParameters: SessionStatusRequestParameters, trustedCertificates: [String]?, completionHandler: @escaping (Result) -> Void) {
+ public func getSessionStatus(baseUrl: String, process: PollingProcess, requestParameters: SessionStatusRequestParameters, trustedCertificates: [String]?, manualProxyConf: Proxy, completionHandler: @escaping (Result) -> Void) {
guard let url = URL(string: "\(baseUrl)/signature/session/\(requestParameters.sessionId)?timeoutMs=\(requestParameters.timeoutMs ?? Constants.defaultTimeoutMs)") else {
Logging.errorLog(forMethod: "RIA.MobileID - Session status", httpResponse: nil, error: .invalidURL, extraInfo: "Invalid URL \(baseUrl)/signature/session/\(requestParameters.sessionId)?timeoutMs=\(requestParameters.timeoutMs ?? Constants.defaultTimeoutMs)")
return completionHandler(.failure(.invalidURL))
@@ -155,12 +157,14 @@ public class RequestSession: NSObject, URLSessionDelegate, SessionRequest {
"\ttimeoutMs: \(String(requestParameters.timeoutMs ?? Constants.defaultTimeoutMs)) \n"
)
- let urlSessionConfiguration: URLSessionConfiguration
+ var urlSessionConfiguration: URLSessionConfiguration
let urlSession: URLSession
if trustedCertificates != nil {
urlSessionConfiguration = URLSessionConfiguration.default
urlSessionConfiguration.requestCachePolicy = .reloadIgnoringLocalAndRemoteCacheData
+ ProxyUtil.configureURLSessionWithProxy(urlSessionConfiguration: &urlSessionConfiguration, manualProxyConf: manualProxyConf)
+ ProxyUtil.setProxyAuthorizationHeader(request: &request, urlSessionConfiguration: urlSessionConfiguration, manualProxyConf: manualProxyConf)
urlSession = URLSession(configuration: urlSessionConfiguration, delegate: self, delegateQueue: nil)
} else {
urlSession = URLSession.shared
@@ -202,7 +206,7 @@ public class RequestSession: NSObject, URLSessionDelegate, SessionRequest {
} else {
// Poll again as SessionResponseState is not COMPLETE
DispatchQueue.main.asyncAfter(deadline: .now() + Constants.defaultTimeoutS) {
- self.getSessionStatus(baseUrl: baseUrl, process: process, requestParameters: requestParameters, trustedCertificates: trustedCertificates, completionHandler: completionHandler)
+ self.getSessionStatus(baseUrl: baseUrl, process: process, requestParameters: requestParameters, trustedCertificates: trustedCertificates, manualProxyConf: manualProxyConf, completionHandler: completionHandler)
}
}
} else {
diff --git a/SkSigningLib/SkSigningLib/Requests/Mobile-ID/RequestSignature.swift b/SkSigningLib/SkSigningLib/Requests/Mobile-ID/RequestSignature.swift
index 39b91cf16..f96b6a4ac 100644
--- a/SkSigningLib/SkSigningLib/Requests/Mobile-ID/RequestSignature.swift
+++ b/SkSigningLib/SkSigningLib/Requests/Mobile-ID/RequestSignature.swift
@@ -33,7 +33,7 @@ protocol CertificateRequest {
- requestParameters: Parameters that are sent to the service. Uses CertificateRequestParameters struct
- completionHandler: On request response, callbacks Result
*/
- func getCertificate(baseUrl: String, requestParameters: CertificateRequestParameters, trustedCertificates: [String]?, completionHandler: @escaping (Result) -> Void)
+ func getCertificate(baseUrl: String, requestParameters: CertificateRequestParameters, trustedCertificates: [String]?, manualProxyConf: Proxy, completionHandler: @escaping (Result) -> Void)
}
/**
@@ -46,7 +46,7 @@ public class RequestSignature: NSObject, URLSessionDelegate, CertificateRequest
private var trustedCerts: [String]?
private weak var urlTask: URLSessionTask?
- public func getCertificate(baseUrl: String, requestParameters: CertificateRequestParameters, trustedCertificates: [String]?, completionHandler: @escaping (Result) -> Void) {
+ public func getCertificate(baseUrl: String, requestParameters: CertificateRequestParameters, trustedCertificates: [String]?, manualProxyConf: Proxy, completionHandler: @escaping (Result) -> Void) {
guard UUID(uuidString: requestParameters.relyingPartyUUID) != nil else { completionHandler(.failure(.midInvalidAccessRights)); return }
guard let url = URL(string: "\(baseUrl)/certificate") else {
Logging.errorLog(forMethod: "RIA.MobileID - Certificate", httpResponse: nil, error: .invalidURL, extraInfo: "Invalid URL \(baseUrl)/certificate")
@@ -72,11 +72,14 @@ public class RequestSignature: NSObject, URLSessionDelegate, CertificateRequest
"\tnationalIdentityNumber: \(requestParameters.nationalIdentityNumber)\n"
)
- let urlSessionConfiguration: URLSessionConfiguration
+ var urlSessionConfiguration: URLSessionConfiguration
let urlSession: URLSession
if trustedCertificates != nil {
+
urlSessionConfiguration = URLSessionConfiguration.default
+ ProxyUtil.configureURLSessionWithProxy(urlSessionConfiguration: &urlSessionConfiguration, manualProxyConf: manualProxyConf)
+ ProxyUtil.setProxyAuthorizationHeader(request: &request, urlSessionConfiguration: urlSessionConfiguration, manualProxyConf: manualProxyConf)
urlSession = URLSession(configuration: urlSessionConfiguration, delegate: self, delegateQueue: nil)
} else {
urlSession = URLSession.shared
diff --git a/SkSigningLib/SkSigningLib/Requests/Smart-ID/SIDRequest.swift b/SkSigningLib/SkSigningLib/Requests/Smart-ID/SIDRequest.swift
index 49471c222..43c1cec85 100644
--- a/SkSigningLib/SkSigningLib/Requests/Smart-ID/SIDRequest.swift
+++ b/SkSigningLib/SkSigningLib/Requests/Smart-ID/SIDRequest.swift
@@ -31,7 +31,7 @@ protocol SIDRequestProtocol {
- requestParameters: Parameters that are sent to the service. Uses SIDCertificateRequestParameters struct
- completionHandler: On request success, callbacks Result
*/
- func getCertificate(baseUrl: String, country: String, nationalIdentityNumber: String, requestParameters: SIDCertificateRequestParameters, trustedCertificates: [String]?, completionHandler: @escaping (Result) -> Void)
+ func getCertificate(baseUrl: String, country: String, nationalIdentityNumber: String, requestParameters: SIDCertificateRequestParameters, trustedCertificates: [String]?, manualProxyConf: Proxy, completionHandler: @escaping (Result) -> Void)
/**
Gets signature info for Smart-ID.
@@ -42,7 +42,7 @@ protocol SIDRequestProtocol {
- allowedInteractionsOrder: Interaction order.
- completionHandler: On request success, callbacks Result
*/
- func getSignature(baseUrl: String, documentNumber: String, allowedInteractionsOrder: SIDSignatureRequestParametersV2?, trustedCertificates: [String]?, completionHandler: @escaping (Result) -> Void)
+ func getSignature(baseUrl: String, documentNumber: String, allowedInteractionsOrder: SIDSignatureRequestParametersV2?, trustedCertificates: [String]?, manualProxyConf: Proxy, completionHandler: @escaping (Result) -> Void)
/**
Gets session status info for Smart-ID.
@@ -53,7 +53,7 @@ protocol SIDRequestProtocol {
- timeoutMs: TimeoutMs parameter that is used in URL
- completionHandler: On request success, callbacks Result
*/
- func getSessionStatus(baseUrl: String, sessionId: String, timeoutMs: Int?, trustedCertificates: [String]?, completionHandler: @escaping (Result) -> Void)
+ func getSessionStatus(baseUrl: String, sessionId: String, timeoutMs: Int?, trustedCertificates: [String]?, manualProxyConf: Proxy, completionHandler: @escaping (Result) -> Void)
}
/**
@@ -65,23 +65,23 @@ public class SIDRequest: NSObject, URLSessionDelegate, SIDRequestProtocol {
private var trustedCerts: [String]?
private weak var urlTask: URLSessionTask?
- public func getCertificate(baseUrl: String, country: String, nationalIdentityNumber: String, requestParameters: SIDCertificateRequestParameters, trustedCertificates: [String]?, completionHandler: @escaping (Result) -> Void) {
+ public func getCertificate(baseUrl: String, country: String, nationalIdentityNumber: String, requestParameters: SIDCertificateRequestParameters, trustedCertificates: [String]?, manualProxyConf: Proxy, completionHandler: @escaping (Result) -> Void) {
let url = "\(baseUrl)/certificatechoice/etsi/PNO\(country)-\(nationalIdentityNumber)"
guard UUID(uuidString: requestParameters.relyingPartyUUID) != nil else { completionHandler(.failure(.sidInvalidAccessRights)); return }
- exec(method: "Certificate", url: url, data: EncoderDecoder().encode(data: requestParameters), trustedCertificates: trustedCertificates, completionHandler: completionHandler)
+ exec(method: "Certificate", url: url, data: EncoderDecoder().encode(data: requestParameters), trustedCertificates: trustedCertificates, manualProxyConf: manualProxyConf, completionHandler: completionHandler)
}
- public func getSignature(baseUrl: String, documentNumber: String, allowedInteractionsOrder: SIDSignatureRequestParametersV2?, trustedCertificates: [String]?, completionHandler: @escaping (Result) -> Void) {
+ public func getSignature(baseUrl: String, documentNumber: String, allowedInteractionsOrder: SIDSignatureRequestParametersV2?, trustedCertificates: [String]?, manualProxyConf: Proxy, completionHandler: @escaping (Result) -> Void) {
let url = "\(baseUrl)/signature/document/\(documentNumber)"
- exec(method: allowedInteractionsOrder?.relyingPartyName ?? "RIA.SmartID v2 - Signature", url: url, data: allowedInteractionsOrder?.asData, trustedCertificates: trustedCertificates, completionHandler: completionHandler)
+ exec(method: allowedInteractionsOrder?.relyingPartyName ?? "RIA.SmartID v2 - Signature", url: url, data: allowedInteractionsOrder?.asData, trustedCertificates: trustedCertificates, manualProxyConf: manualProxyConf, completionHandler: completionHandler)
}
- public func getSessionStatus(baseUrl: String, sessionId: String, timeoutMs: Int?, trustedCertificates: [String]?, completionHandler: @escaping (Result) -> Void) {
+ public func getSessionStatus(baseUrl: String, sessionId: String, timeoutMs: Int?, trustedCertificates: [String]?, manualProxyConf: Proxy, completionHandler: @escaping (Result) -> Void) {
let url = "\(baseUrl)/session/\(sessionId)?timeoutMs=\(timeoutMs ?? Constants.defaultTimeoutMs)"
- exec(method: "Session", url: url, data: nil, trustedCertificates: trustedCertificates, completionHandler: completionHandler)
+ exec(method: "Session", url: url, data: nil, trustedCertificates: trustedCertificates, manualProxyConf: manualProxyConf, completionHandler: completionHandler)
}
- private func exec(method: String, url: String, data: Data?, trustedCertificates: [String]?, completionHandler: @escaping (Result) -> Void) {
+ private func exec(method: String, url: String, data: Data?, trustedCertificates: [String]?, manualProxyConf: Proxy, completionHandler: @escaping (Result) -> Void) {
guard let _url = URL(string: url) else {
Logging.errorLog(forMethod: "RIA.SmartID - \(method)", httpResponse: nil, error: .invalidURL, extraInfo: "Invalid URL \(url)")
return completionHandler(.failure(.invalidURL))
@@ -98,12 +98,14 @@ public class SIDRequest: NSObject, URLSessionDelegate, SIDRequestProtocol {
)
trustedCerts = trustedCertificates
- let config = URLSessionConfiguration.default
+ var config = URLSessionConfiguration.default
config.requestCachePolicy = .reloadIgnoringLocalCacheData
config.urlCache = nil
let urlSession: URLSession
if trustedCertificates != nil {
+ ProxyUtil.configureURLSessionWithProxy(urlSessionConfiguration: &config, manualProxyConf: manualProxyConf)
+ ProxyUtil.setProxyAuthorizationHeader(request: &request, urlSessionConfiguration: config, manualProxyConf: manualProxyConf)
urlSession = URLSession(configuration: config, delegate: self, delegateQueue: nil)
} else {
urlSession = URLSession.shared
diff --git a/SkSigningLib/SkSigningLib/Utilities/Proxy/Proxy.swift b/SkSigningLib/SkSigningLib/Utilities/Proxy/Proxy.swift
new file mode 100644
index 000000000..85c7ecca2
--- /dev/null
+++ b/SkSigningLib/SkSigningLib/Utilities/Proxy/Proxy.swift
@@ -0,0 +1,40 @@
+//
+// Proxy.swift
+// MoppApp
+//
+/*
+ * Copyright 2017 - 2023 Riigi Infosüsteemi Amet
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+import Foundation
+
+public struct Proxy {
+ public var host: String
+ public var port: Int
+ public var username: String
+ public var password: String
+ public var isSSLEnabled: Bool
+
+ public init(host: String, port: Int, username: String, password: String, isSSLEnabled: Bool) {
+ self.host = host
+ self.port = port
+ self.username = username
+ self.password = password
+ self.isSSLEnabled = isSSLEnabled
+ }
+}
diff --git a/SkSigningLib/SkSigningLib/Utilities/Proxy/ProxyUtil.swift b/SkSigningLib/SkSigningLib/Utilities/Proxy/ProxyUtil.swift
new file mode 100644
index 000000000..25f5089ac
--- /dev/null
+++ b/SkSigningLib/SkSigningLib/Utilities/Proxy/ProxyUtil.swift
@@ -0,0 +1,94 @@
+//
+// ProxyUtil.swift
+// MoppApp
+//
+/*
+ * Copyright 2017 - 2023 Riigi Infosüsteemi Amet
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+import Foundation
+
+public enum ProxySetting: String, Codable {
+ case noProxy
+ case systemProxy
+ case manualProxy
+}
+
+public class ProxyUtil {
+
+ public static func createProxyConfiguration(proxySetting: ProxySetting, proxyHost: String?, proxyPort: Int?, proxyUsername: String?, proxyPassword: String?, isProxySSLEnabled: Bool) -> [AnyHashable: Any]? {
+
+ // Use manual proxy settings
+ if proxySetting == .manualProxy, isProxySSLEnabled, let host = proxyHost, let port = proxyPort, !host.isEmpty, port > 0 {
+ let proxyConfiguration: [AnyHashable : Any] = [
+ String(kCFNetworkProxiesHTTPEnable): 1,
+ String(kCFNetworkProxiesHTTPProxy): host,
+ String(kCFNetworkProxiesHTTPPort): port,
+ String(kCFProxyUsernameKey): proxyUsername ?? "",
+ String(kCFProxyPasswordKey): proxyPassword ?? "",
+ // Using deprecated keys because HTTPS urls may not be routed through a proxy
+ // https://developer.apple.com/forums/thread/19356?answerId=131709022#131709022
+ String(kCFStreamPropertyHTTPSProxyHost): host,
+ String(kCFStreamPropertyHTTPSProxyPort): port
+ ]
+
+ return proxyConfiguration
+ }
+ // Check if system proxy settings exist. iOS automatically handles proxy configuration with system settings
+ else if proxySetting == .systemProxy, isProxySSLEnabled, let proxySettingsUnmanaged = CFNetworkCopySystemProxySettings() {
+ let proxySettings = proxySettingsUnmanaged.takeRetainedValue() as? [AnyHashable : Any]
+ if let systemHost = proxySettings?[kCFNetworkProxiesHTTPProxy] as? String, let systemPort = proxySettings?[kCFNetworkProxiesHTTPPort] as? Int, !systemHost.isEmpty && systemPort > 0 {
+ return nil
+ }
+ }
+
+ return [
+ String(kCFNetworkProxiesHTTPEnable): 0
+ ]
+ }
+
+ public static func getProxyAuthorizationHeader(username: String, password: String) -> String? {
+ let credentials = "\(username):\(password)"
+
+ if let credentialsData = credentials.data(using: .utf8) {
+ return credentialsData.base64EncodedString(options: [])
+ }
+
+ return nil
+ }
+
+ public static func setProxyAuthorizationHeader(request: inout URLRequest, urlSessionConfiguration: URLSessionConfiguration, manualProxyConf: Proxy) {
+ if let connectionProxyDictionary = urlSessionConfiguration.connectionProxyDictionary,
+ !connectionProxyDictionary.isEmpty,
+ !manualProxyConf.host.isEmpty,
+ let proxyHeader = ProxyUtil.getProxyAuthorizationHeader(username: manualProxyConf.username, password: manualProxyConf.password) {
+
+ request.setValue("Basic \(proxyHeader)", forHTTPHeaderField: "Proxy-Authorization")
+ }
+ }
+
+ public static func configureURLSessionWithProxy(urlSessionConfiguration: inout URLSessionConfiguration, manualProxyConf: Proxy) {
+ let proxyConfiguration = ProxyUtil.createProxyConfiguration(
+ proxySetting: .manualProxy,
+ proxyHost: manualProxyConf.host, proxyPort: manualProxyConf.port, proxyUsername: manualProxyConf.username, proxyPassword: manualProxyConf.password, isProxySSLEnabled: manualProxyConf.isSSLEnabled)
+
+ if let proxyConf = proxyConfiguration {
+ urlSessionConfiguration.connectionProxyDictionary = proxyConf
+ }
+ }
+}