diff --git a/Corona-Warn-App/src/main/assets/pins.properties b/Corona-Warn-App/src/main/assets/pins.properties deleted file mode 100644 index 198e2e9bbfd58f9710527792369c0afe0fe7e132..0000000000000000000000000000000000000000 --- a/Corona-Warn-App/src/main/assets/pins.properties +++ /dev/null @@ -1,13 +0,0 @@ -# TODO add certificate pinning -# -# Intermediates will be encoded like this: -# openssl x509 -in CERTNAME -pubkey -noout | \ -# openssl pkey -pubin -outform der | \ -# openssl dgst -sha256 -binary | \ -# openssl enc -base64 -# -# Format is sha256/BASE64ENCODED -# Pins are delimited by "," -SUBMISSION_PINS= -DISTRIBUTION_PINS= -VERIFICATION_PINS= \ No newline at end of file diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/CwaWebSecurityException.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/CwaWebSecurityException.kt new file mode 100644 index 0000000000000000000000000000000000000000..6dbbbca8d839009580fb20639f7807c8cf9457cc --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/CwaWebSecurityException.kt @@ -0,0 +1,8 @@ +package de.rki.coronawarnapp.exception + +import okio.IOException + +class CwaWebSecurityException(cause: Throwable) : IOException( + "an error occurred while trying to establish a secure connection to the server", + cause +) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/CertificatePinnerFactory.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/CertificatePinnerFactory.kt deleted file mode 100644 index 7a103bea08326d456c187f552de95bf760644f38..0000000000000000000000000000000000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/CertificatePinnerFactory.kt +++ /dev/null @@ -1,23 +0,0 @@ -package de.rki.coronawarnapp.http - -import de.rki.coronawarnapp.util.PropertyLoader -import okhttp3.CertificatePinner - -class CertificatePinnerFactory { - fun getCertificatePinner(): CertificatePinner = PropertyLoader().run { - CertificatePinner.Builder() - .add( - DynamicURLs.DOWNLOAD_CDN_URL.removePrefix(DynamicURLs.PATTERN_PREFIX_HTTPS), - *this.getDistributionPins() - ) - .add( - DynamicURLs.SUBMISSION_CDN_URL.removePrefix(DynamicURLs.PATTERN_PREFIX_HTTPS), - *this.getSubmissionPins() - ) - .add( - DynamicURLs.VERIFICATION_CDN_URL.removePrefix(DynamicURLs.PATTERN_PREFIX_HTTPS), - *this.getVerificationPins() - ) - .build() - } -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/ServiceFactory.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/ServiceFactory.kt index 42604a156a5c48bfd544680758a34cee93df6cef..94c3fd63c68b77f89e0c9b363b73676bb23923a2 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/ServiceFactory.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/ServiceFactory.kt @@ -4,15 +4,22 @@ import android.webkit.URLUtil import de.rki.coronawarnapp.BuildConfig import de.rki.coronawarnapp.CoronaWarnApplication import de.rki.coronawarnapp.exception.http.ServiceFactoryException +import de.rki.coronawarnapp.http.config.DynamicURLs +import de.rki.coronawarnapp.http.config.HTTPVariables +import de.rki.coronawarnapp.http.interceptor.OfflineCacheInterceptor +import de.rki.coronawarnapp.http.interceptor.WebSecurityVerificationInterceptor +import de.rki.coronawarnapp.http.interceptor.RetryInterceptor import de.rki.coronawarnapp.http.service.DistributionService import de.rki.coronawarnapp.http.service.SubmissionService import de.rki.coronawarnapp.http.service.VerificationService import de.rki.coronawarnapp.risk.TimeVariables import okhttp3.Cache +import okhttp3.CipherSuite import okhttp3.ConnectionPool import okhttp3.ConnectionSpec import okhttp3.Interceptor import okhttp3.OkHttpClient +import okhttp3.TlsVersion import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory @@ -37,10 +44,13 @@ class ServiceFactory { * List of interceptors, e.g. logging */ private val mInterceptors: List<Interceptor> = listOf( + WebSecurityVerificationInterceptor(), HttpLoggingInterceptor().also { if (BuildConfig.DEBUG) it.setLevel(HttpLoggingInterceptor.Level.BODY) }, - OfflineCacheInterceptor(CoronaWarnApplication.getAppContext()), + OfflineCacheInterceptor( + CoronaWarnApplication.getAppContext() + ), RetryInterceptor(), HttpErrorParser() ) @@ -64,41 +74,98 @@ class ServiceFactory { private val okHttpClient by lazy { val clientBuilder = OkHttpClient.Builder() - val timeoutMs = TimeVariables.getTransactionTimeout() - clientBuilder.connectTimeout(timeoutMs, TimeUnit.MILLISECONDS) - clientBuilder.readTimeout(timeoutMs, TimeUnit.MILLISECONDS) - clientBuilder.writeTimeout(timeoutMs, TimeUnit.MILLISECONDS) - clientBuilder.callTimeout(timeoutMs, TimeUnit.MILLISECONDS) + clientBuilder.connectTimeout( + HTTPVariables.getHTTPConnectionTimeout(), + TimeUnit.MILLISECONDS + ) + clientBuilder.readTimeout( + HTTPVariables.getHTTPReadTimeout(), + TimeUnit.MILLISECONDS + ) + clientBuilder.writeTimeout( + HTTPVariables.getHTTPWriteTimeout(), + TimeUnit.MILLISECONDS + ) + clientBuilder.callTimeout( + TimeVariables.getTransactionTimeout(), + TimeUnit.MILLISECONDS + ) clientBuilder.connectionPool(conPool) cache.evictAll() clientBuilder.cache(cache) - val spec: ConnectionSpec = ConnectionSpec.Builder(ConnectionSpec.RESTRICTED_TLS) - .allEnabledCipherSuites() // TODO clarify more concrete Ciphers - .build() - - clientBuilder.connectionSpecs(listOf(spec)) - - CertificatePinnerFactory().getCertificatePinner().run { - if (this.pins.isNotEmpty()) { - clientBuilder.certificatePinner(this) - } - } - mInterceptors.forEach { clientBuilder.addInterceptor(it) } clientBuilder.build() } + /** + * For the CDN we want to ensure maximum Compatibility. + */ + private fun getCDNSpecs(): List<ConnectionSpec> = listOf( + ConnectionSpec.Builder(ConnectionSpec.COMPATIBLE_TLS) + .tlsVersions( + TlsVersion.TLS_1_0, + TlsVersion.TLS_1_1, + TlsVersion.TLS_1_2, + TlsVersion.TLS_1_3 + ) + .allEnabledCipherSuites() + .build() + ) + + /** + * For Submission and Verification we want to limit our specifications for TLS. + */ + private fun getRestrictedSpecs(): List<ConnectionSpec> = listOf( + ConnectionSpec.Builder(ConnectionSpec.RESTRICTED_TLS) + .tlsVersions( + TlsVersion.TLS_1_2, + TlsVersion.TLS_1_3 + ) + .cipherSuites( + // TLS 1.2 with Perfect Forward Secrecy (BSI TR-02102-2) + CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, + CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, + CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, + CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, + CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, + CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, + CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, + CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, + CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, + // TLS 1.3 (BSI TR-02102-2) + CipherSuite.TLS_AES_128_GCM_SHA256, + CipherSuite.TLS_AES_256_GCM_SHA384, + CipherSuite.TLS_AES_128_CCM_SHA256 + ) + .build() + ) + + /** + * Helper function to create a new client from an existent Client with New Specs. + * + * @param specs + */ + private fun OkHttpClient.buildClientWithNewSpecs(specs: List<ConnectionSpec>) = + this.newBuilder().connectionSpecs(specs).build() + private val downloadCdnUrl get() = getValidUrl(DynamicURLs.DOWNLOAD_CDN_URL) fun distributionService(): DistributionService = distributionService private val distributionService by lazy { Retrofit.Builder() - .client(okHttpClient) + .client(okHttpClient.buildClientWithNewSpecs(getCDNSpecs())) .baseUrl(downloadCdnUrl) .addConverterFactory(gsonConverterFactory) .build() @@ -111,7 +178,7 @@ class ServiceFactory { fun verificationService(): VerificationService = verificationService private val verificationService by lazy { Retrofit.Builder() - .client(okHttpClient) + .client(okHttpClient.buildClientWithNewSpecs(getRestrictedSpecs())) .baseUrl(verificationCdnUrl) .addConverterFactory(gsonConverterFactory) .build() @@ -124,7 +191,7 @@ class ServiceFactory { fun submissionService(): SubmissionService = submissionService private val submissionService by lazy { Retrofit.Builder() - .client(okHttpClient) + .client(okHttpClient.buildClientWithNewSpecs(getRestrictedSpecs())) .baseUrl(submissionCdnUrl) .addConverterFactory(protoConverterFactory) .addConverterFactory(gsonConverterFactory) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/DynamicURLs.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/config/DynamicURLs.kt similarity index 92% rename from Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/DynamicURLs.kt rename to Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/config/DynamicURLs.kt index 20dd178142426076f75e04862dfe7603a4ad5cbc..cc05f85afe6cf2cd51c6fa1dfd54d908989fe580 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/DynamicURLs.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/config/DynamicURLs.kt @@ -1,4 +1,4 @@ -package de.rki.coronawarnapp.http +package de.rki.coronawarnapp.http.config import de.rki.coronawarnapp.BuildConfig diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/config/HTTPVariables.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/config/HTTPVariables.kt new file mode 100644 index 0000000000000000000000000000000000000000..4939bf675565a6365f9eee6316b1506dbd356a3f --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/config/HTTPVariables.kt @@ -0,0 +1,45 @@ +package de.rki.coronawarnapp.http.config + +object HTTPVariables { + /** + * The maximal runtime of a transaction + * In milliseconds + */ + private const val HTTP_CONNECTION_TIMEOUT = 10000L + + /** + * Getter function for [HTTP_CONNECTION_TIMEOUT] + * + * @return timeout in milliseconds + */ + fun getHTTPConnectionTimeout(): Long = + HTTP_CONNECTION_TIMEOUT + + /** + * The maximal runtime of a transaction + * In milliseconds + */ + private const val HTTP_READ_TIMEOUT = 10000L + + /** + * Getter function for [HTTP_READ_TIMEOUT] + * + * @return timeout in milliseconds + */ + fun getHTTPReadTimeout(): Long = + HTTP_READ_TIMEOUT + + /** + * The maximal runtime of a transaction + * In milliseconds + */ + private const val HTTP_WRITE_TIMEOUT = 10000L + + /** + * Getter function for [HTTP_WRITE_TIMEOUT] + * + * @return timeout in milliseconds + */ + fun getHTTPWriteTimeout(): Long = + HTTP_WRITE_TIMEOUT +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/OfflineCacheInterceptor.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/interceptor/OfflineCacheInterceptor.kt similarity index 97% rename from Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/OfflineCacheInterceptor.kt rename to Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/interceptor/OfflineCacheInterceptor.kt index 15bf62893e84da23d278a2be61571895d2ff4c07..e8d14fab80328ff6708ff3d1f41eb6c375a0443e 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/OfflineCacheInterceptor.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/interceptor/OfflineCacheInterceptor.kt @@ -1,4 +1,4 @@ -package de.rki.coronawarnapp.http +package de.rki.coronawarnapp.http.interceptor import android.content.Context import de.rki.coronawarnapp.util.ConnectivityHelper.isNetworkEnabled diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/RetryInterceptor.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/interceptor/RetryInterceptor.kt similarity index 93% rename from Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/RetryInterceptor.kt rename to Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/interceptor/RetryInterceptor.kt index c4bfa179b98416b7723cef0efa40abd32502c44d..91167efe8a87bab3fb1e16a7f0656b9d17d4aa82 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/RetryInterceptor.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/interceptor/RetryInterceptor.kt @@ -1,4 +1,4 @@ -package de.rki.coronawarnapp.http +package de.rki.coronawarnapp.http.interceptor import android.util.Log import okhttp3.Interceptor diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/interceptor/WebSecurityVerificationInterceptor.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/interceptor/WebSecurityVerificationInterceptor.kt new file mode 100644 index 0000000000000000000000000000000000000000..2af724e76a8e65118663c69caca6b76f1705296b --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/interceptor/WebSecurityVerificationInterceptor.kt @@ -0,0 +1,14 @@ +package de.rki.coronawarnapp.http.interceptor + +import de.rki.coronawarnapp.exception.CwaWebSecurityException +import okhttp3.Interceptor +import okhttp3.Response +import javax.net.ssl.SSLException + +class WebSecurityVerificationInterceptor : Interceptor { + override fun intercept(chain: Interceptor.Chain): Response { + try { return chain.proceed(chain.request()) } catch (e: SSLException) { + throw CwaWebSecurityException(e) + } + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/LauncherActivity.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/LauncherActivity.kt index 7a96494ec5fa66bcf1ea1fb7e4ab195e8dd9a20b..938f0c3026c18209f91378e9f7997b72c3a5456f 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/LauncherActivity.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/LauncherActivity.kt @@ -6,7 +6,7 @@ import android.os.Bundle import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope -import de.rki.coronawarnapp.http.DynamicURLs +import de.rki.coronawarnapp.http.config.DynamicURLs import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.ui.main.MainActivity import de.rki.coronawarnapp.ui.onboarding.OnboardingActivity diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/IndexHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/IndexHelper.kt deleted file mode 100644 index 1ea82db6601c7181370e508749466e95b26aa402..0000000000000000000000000000000000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/IndexHelper.kt +++ /dev/null @@ -1,79 +0,0 @@ -/****************************************************************************** - * Corona-Warn-App * - * * - * SAP SE and all other contributors / * - * copyright owners license this file to you under the Apache * - * License, Version 2.0 (the "License"); you may not use this * - * file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, * - * software distributed under the License is distributed on an * - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * - * KIND, either express or implied. See the License for the * - * specific language governing permissions and limitations * - * under the License. * - ******************************************************************************/ - -package de.rki.coronawarnapp.util - -import android.util.Log -import com.google.common.base.Splitter -import de.rki.coronawarnapp.BuildConfig -import java.util.regex.Pattern - -@Suppress("ComplexCondition", "TooGenericExceptionThrown") -object IndexHelper { - private val TAG: String? = IndexHelper::class.simpleName - private val WHITESPACE_SPLITTER: Splitter = - Splitter.onPattern("\\s+").trimResults().omitEmptyStrings() - - private val INDEX_ELEMENT_PATTERN: Pattern = Pattern.compile("Cwa-([A-Z]{2})/([0-9]{10})-([0-9]+).zip") - - private const val GROUP_COUNT = 3 - private const val COUNTRY_CODE_GROUP = 1 - private const val TIMESTAMP_GROUP = 2 - private const val BATCH_NUMBER_GROUP = 3 - - /** - * Converts a String to an index according to the Delimiter defined in [WHITESPACE_SPLITTER] and the - * Regular Expression of an index element defined in [INDEX_ELEMENT_PATTERN]. The Pattern has to define - * 3 Groups. - * 1. Country Code Information - * 2. Creation Epoch of the Batch - * 3. Batch Number - * - * @return Map of Batch Number to File Names (from the Index) - */ - fun String.convertToIndex(): Map<Long, String> = WHITESPACE_SPLITTER.splitToList(this).also { - if (BuildConfig.DEBUG) Log.d(TAG, "Index(${it.size} Elements):$it") - }.associateBy { indexElement -> - val matcher = INDEX_ELEMENT_PATTERN.matcher(indexElement) - if ( - !matcher.matches() || - matcher.groupCount() != GROUP_COUNT || - matcher.group(COUNTRY_CODE_GROUP) != null || - matcher.group(TIMESTAMP_GROUP) != null || - matcher.group(BATCH_NUMBER_GROUP) != null - ) throw RuntimeException("Failed to parse batch from $indexElement") - val isoCountryCode = - matcher.group(COUNTRY_CODE_GROUP) - ?: throw NullPointerException("Batch Regex Group 1 (Country Code) must not be null") - val timestampString = - matcher.group(TIMESTAMP_GROUP) - ?: throw NullPointerException("Batch Regex Group 2 (Timestamp) must not be null") - val batchNumberString = - matcher.group(BATCH_NUMBER_GROUP) - ?: throw NullPointerException("Batch Regex Group 3 (Batch Number) must not be null") - - if (BuildConfig.DEBUG) Log.d( - TAG, "index element " + - "$indexElement=(Timestamp:$timestampString, BatchNum:$batchNumberString, " + - "ISOCountryCode:$isoCountryCode" - ) - - timestampString.toLong() - } -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/PropertyLoader.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/PropertyLoader.kt deleted file mode 100644 index c162ac72f2968063000b03d4b7fef9b3bf923bea..0000000000000000000000000000000000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/PropertyLoader.kt +++ /dev/null @@ -1,28 +0,0 @@ -package de.rki.coronawarnapp.util - -import android.util.Log -import de.rki.coronawarnapp.CoronaWarnApplication -import java.util.Properties - -class PropertyLoader { - companion object { - private const val PIN_PROPERTIES_FILE_NAME = "pins.properties" - private const val PIN_FILE_DELIMITER = "," - private const val DISTRIBUTION_PIN_PROPERTY_NAME = "DISTRIBUTION_PINS" - private const val SUBMISSION_PINS_PROPERTY_NAME = "SUBMISSION_PINS" - private const val VERIFICATION_PINS_PROPERTY_NAME = "VERIFICATION_PINS" - } - - fun getDistributionPins() = getCertificatePins(DISTRIBUTION_PIN_PROPERTY_NAME) - fun getSubmissionPins() = getCertificatePins(SUBMISSION_PINS_PROPERTY_NAME) - fun getVerificationPins() = getCertificatePins(VERIFICATION_PINS_PROPERTY_NAME) - - private fun getCertificatePins(key: String): Array<String> = Properties().run { - this.load(CoronaWarnApplication.getAppContext().assets.open(PIN_PROPERTIES_FILE_NAME)) - this.getProperty(key) - .split(PIN_FILE_DELIMITER) - .filter { it.isNotEmpty() } - .also { Log.v(key, it.toString()) } - .toTypedArray() - } -} diff --git a/Corona-Warn-App/src/main/res/xml/network_security_config.xml b/Corona-Warn-App/src/main/res/xml/network_security_config.xml index ce472cd5196ac5b863a89c323fac3d026518bcd0..6ec4e91c1f8786782c2f4b604509eebea660dbd3 100644 --- a/Corona-Warn-App/src/main/res/xml/network_security_config.xml +++ b/Corona-Warn-App/src/main/res/xml/network_security_config.xml @@ -1,2 +1,27 @@ <?xml version="1.0" encoding="utf-8"?> -<network-security-config></network-security-config> \ No newline at end of file +<network-security-config xmlns:tools="http://schemas.android.com/tools"> + + <domain-config cleartextTrafficPermitted="false"> + <!-- TODO Add Production Domain for Verification Service--> + <domain includeSubdomains="true">submission.coronawarn.app</domain> + <domain includeSubdomains="true">prodVerify.com</domain> + <pin-set expiration="2024-02-12" tools:ignore="MissingBackupPin"> + <pin digest="SHA-256">c3jf+L8VIAFQnJJDM6Mfb4MtI1JnhVS8JwZHMwJj28M=</pin> + </pin-set> + <trust-anchors> + <certificates + src="system" + overridePins="false" /> + </trust-anchors> + </domain-config> + + <domain-config cleartextTrafficPermitted="false"> + <domain includeSubdomains="true">svc90.main.px.t-online.de</domain> + <trust-anchors> + <certificates + src="system" + overridePins="false" /> + </trust-anchors> + </domain-config> + +</network-security-config> \ No newline at end of file