diff --git a/desktop/app/src/main/kotlin/com/abdownloadmanager/desktop/di/Di.kt b/desktop/app/src/main/kotlin/com/abdownloadmanager/desktop/di/Di.kt index cfe7118..5e44606 100644 --- a/desktop/app/src/main/kotlin/com/abdownloadmanager/desktop/di/Di.kt +++ b/desktop/app/src/main/kotlin/com/abdownloadmanager/desktop/di/Di.kt @@ -32,6 +32,7 @@ import ir.amirab.downloader.monitor.DownloadMonitor import ir.amirab.downloader.utils.IDiskStat import ir.amirab.util.startup.Startup import com.abdownloadmanager.integration.Integration +import com.abdownloadmanager.shared.utils.* import com.abdownloadmanager.updateapplier.DesktopUpdateApplier import com.abdownloadmanager.updateapplier.UpdateApplier import ir.amirab.downloader.DownloadManager @@ -46,10 +47,6 @@ import org.koin.dsl.bind import org.koin.dsl.module import com.abdownloadmanager.updatechecker.GithubUpdateChecker import com.abdownloadmanager.updatechecker.UpdateChecker -import com.abdownloadmanager.shared.utils.DownloadFoldersRegistry -import com.abdownloadmanager.shared.utils.DownloadSystem -import com.abdownloadmanager.shared.utils.FileIconProvider -import com.abdownloadmanager.shared.utils.FileIconProviderUsingCategoryIcons import ir.amirab.util.AppVersionTracker import com.abdownloadmanager.shared.utils.appinfo.PreviousVersion import com.abdownloadmanager.shared.utils.autoremove.RemovedDownloadsFromDiskTracker @@ -128,13 +125,7 @@ val downloaderModule = module { } single { OkHttpDownloaderClient( - OkHttpClient - .Builder() - .dispatcher(Dispatcher().apply { - //bypass limit on concurrent connections! - maxRequests = Int.MAX_VALUE - maxRequestsPerHost = Int.MAX_VALUE - }).build(), + get(), get(), get(), get(), @@ -348,6 +339,28 @@ val appModule = module { ) } + single { + val appSettingsStorage: AppSettingsStorage = get() + AppSSLFactoryProvider( + ignoreSSLCertificates = appSettingsStorage.ignoreSSLCertificates + ) + } + single { + val appSSLFactoryProvider: AppSSLFactoryProvider = get() + OkHttpClient + .Builder() + .dispatcher(Dispatcher().apply { + //bypass limit on concurrent connections! + maxRequests = Int.MAX_VALUE + maxRequestsPerHost = Int.MAX_VALUE + }) + .sslSocketFactory( + appSSLFactoryProvider.createSSLSocketFactory(), + appSSLFactoryProvider.trustManager, + ) + .build() + } + } diff --git a/desktop/app/src/main/kotlin/com/abdownloadmanager/desktop/pages/settings/SettingsComponent.kt b/desktop/app/src/main/kotlin/com/abdownloadmanager/desktop/pages/settings/SettingsComponent.kt index 6be2cbe..f6a5f52 100644 --- a/desktop/app/src/main/kotlin/com/abdownloadmanager/desktop/pages/settings/SettingsComponent.kt +++ b/desktop/app/src/main/kotlin/com/abdownloadmanager/desktop/pages/settings/SettingsComponent.kt @@ -139,6 +139,21 @@ fun trackDeletedFilesOnDisk(appRepository: AppRepository): BooleanConfigurable { ) } +fun ignoreSSLCertificates(appSettingsStorage: AppSettingsStorage): BooleanConfigurable { + return BooleanConfigurable( + title = Res.string.settings_ignore_ssl_certificates.asStringSource(), + description = Res.string.settings_ignore_ssl_certificates_description.asStringSource(), + backedBy = appSettingsStorage.ignoreSSLCertificates, + describe = { + if (it) { + Res.string.enabled.asStringSource() + } else { + Res.string.disabled.asStringSource() + } + }, + ) +} + fun speedUnit(appRepository: AppRepository, scope: CoroutineScope): EnumConfigurable { return EnumConfigurable( title = Res.string.settings_download_speed_unit.asStringSource(), @@ -478,6 +493,7 @@ class SettingsComponent( useServerLastModified(appRepository), useSparseFileAllocation(appRepository), trackDeletedFilesOnDisk(appRepository), + ignoreSSLCertificates(appSettings), ) } } diff --git a/desktop/app/src/main/kotlin/com/abdownloadmanager/desktop/storage/AppSettingsStorage.kt b/desktop/app/src/main/kotlin/com/abdownloadmanager/desktop/storage/AppSettingsStorage.kt index ef1875b..43a20c2 100644 --- a/desktop/app/src/main/kotlin/com/abdownloadmanager/desktop/storage/AppSettingsStorage.kt +++ b/desktop/app/src/main/kotlin/com/abdownloadmanager/desktop/storage/AppSettingsStorage.kt @@ -34,6 +34,7 @@ data class AppSettingsModel( val browserIntegrationPort: Int = 15151, val trackDeletedFilesOnDisk: Boolean = false, val useBitsForSpeed: Boolean = false, + val ignoreSSLCertificates: Boolean = false, ) { companion object { val default: AppSettingsModel get() = AppSettingsModel() @@ -60,6 +61,7 @@ data class AppSettingsModel( val browserIntegrationPort = intKeyOf("browserIntegrationPort") val trackDeletedFilesOnDisk = booleanKeyOf("trackDeletedFilesOnDisk") val useBitsForSpeed = booleanKeyOf("useBitsForSpeed") + val ignoreSSLCertificates = booleanKeyOf("ignoreSSLCertificates") } @@ -89,6 +91,7 @@ data class AppSettingsModel( browserIntegrationPort = source.get(Keys.browserIntegrationPort) ?: default.browserIntegrationPort, trackDeletedFilesOnDisk = source.get(Keys.trackDeletedFilesOnDisk) ?: default.trackDeletedFilesOnDisk, useBitsForSpeed = source.get(Keys.useBitsForSpeed) ?: default.useBitsForSpeed, + ignoreSSLCertificates = source.get(Keys.ignoreSSLCertificates) ?: default.ignoreSSLCertificates, ) } @@ -113,6 +116,7 @@ data class AppSettingsModel( put(Keys.browserIntegrationPort, focus.browserIntegrationPort) put(Keys.trackDeletedFilesOnDisk, focus.trackDeletedFilesOnDisk) put(Keys.useBitsForSpeed, focus.useBitsForSpeed) + put(Keys.ignoreSSLCertificates, focus.ignoreSSLCertificates) } } } @@ -161,4 +165,5 @@ class AppSettingsStorage( val browserIntegrationPort = from(AppSettingsModel.browserIntegrationPort) val trackDeletedFilesOnDisk = from(AppSettingsModel.trackDeletedFilesOnDisk) val useBitsForSpeed = from(AppSettingsModel.useBitsForSpeed) + val ignoreSSLCertificates = from(AppSettingsModel.ignoreSSLCertificates) } diff --git a/shared/app-utils/src/main/kotlin/com/abdownloadmanager/shared/utils/AppSSLFactoryProvider.kt b/shared/app-utils/src/main/kotlin/com/abdownloadmanager/shared/utils/AppSSLFactoryProvider.kt new file mode 100644 index 0000000..4c42c83 --- /dev/null +++ b/shared/app-utils/src/main/kotlin/com/abdownloadmanager/shared/utils/AppSSLFactoryProvider.kt @@ -0,0 +1,49 @@ +package com.abdownloadmanager.shared.utils + +import kotlinx.coroutines.flow.StateFlow +import okhttp3.internal.platform.Platform +import java.security.cert.X509Certificate +import javax.net.ssl.SSLSocketFactory +import javax.net.ssl.X509TrustManager + +/** + * at the moment we simply use okhttp ssl factory provider with a toggleable trust manager to ignore ssl certificates + */ +class AppSSLFactoryProvider( + private val ignoreSSLCertificates: StateFlow, +) { + val trustManager: X509TrustManager by lazy { + ToggleableTrustManager( + trustManager = Platform.get().platformTrustManager(), + shouldCheck = { !ignoreSSLCertificates.value } + ) + } + + fun createSSLSocketFactory(): SSLSocketFactory { + return Platform.get().newSslSocketFactory( + trustManager = trustManager, + ) + } +} + + +private class ToggleableTrustManager( + private val trustManager: X509TrustManager, + private val shouldCheck: () -> Boolean, +) : X509TrustManager { + override fun checkClientTrusted(chain: Array?, authType: String?) { + if (shouldCheck()) { + trustManager.checkClientTrusted(chain, authType) + } + } + + override fun checkServerTrusted(chain: Array?, authType: String?) { + if (shouldCheck()) { + trustManager.checkServerTrusted(chain, authType) + } + } + + override fun getAcceptedIssuers(): Array { + return trustManager.acceptedIssuers + } +} diff --git a/shared/resources/src/main/resources/com/abdownloadmanager/resources/locales/en_US.properties b/shared/resources/src/main/resources/com/abdownloadmanager/resources/locales/en_US.properties index df976df..3206f65 100644 --- a/shared/resources/src/main/resources/com/abdownloadmanager/resources/locales/en_US.properties +++ b/shared/resources/src/main/resources/com/abdownloadmanager/resources/locales/en_US.properties @@ -184,6 +184,8 @@ settings_use_server_last_modified_time=Use Server's Last-Modified Time settings_use_server_last_modified_time_description=When downloading a file, use server's last modified time for the local file settings_use_sparse_file_allocation=Sparse File Allocation settings_use_sparse_file_allocation_description=Create files more efficiently, especially on SSDs, by reducing unnecessary data writing. This can speed up download starts and reduce disk usage. If downloads start slowly or you experience unusual download speeds, consider disabling this option, as it may not be fully supported on some devices. +settings_ignore_ssl_certificates=Ignore SSL Certificates +settings_ignore_ssl_certificates_description=Disables SSL certificate verification. Use only if necessary, as it may expose your connection to security risks. settings_global_speed_limiter=Global Speed Limiter settings_global_speed_limiter_description=Global download speed limit (0 means unlimited) settings_show_average_speed=Show Average Speed