diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000000000000000000000000000000000..077dd62d77fd9b89be9305d06ba7b3326deb7e25 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "ipscrambling/orbotservice"] + path = ipscrambling/orbotservice + url = git@gitlab.e.foundation:e/os/orbotservice.git diff --git a/app/build.gradle b/app/build.gradle index 8a9f1fdc8d23374f30393db8b53b5cd57b3bc0c8..af05ec08abaec8c0d3224df12d3c7980ba8c6edf 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -150,36 +150,35 @@ dependencies { implementation project(':trackers') - implementation 'foundation.e:privacymodule.tor:1.10.0-orbot-16.6.3-1' - - implementation 'foundation.e:elib:0.0.1-alpha11' + implementation project(':ipscrambling') implementation ( - Libs.Kotlin.stdlib, - Libs.AndroidX.coreKtx, - Libs.AndroidX.appCompat, - Libs.AndroidX.Fragment.fragmentKtx, - Libs.AndroidX.Lifecycle.runtime, - Libs.AndroidX.Lifecycle.viewmodel, - Libs.AndroidX.work, - Libs.material, - - Libs.AndroidX.navigation.fragmentKtx, - Libs.AndroidX.navigation.uiKtx, - - Libs.Retrofit.retrofit, - Libs.Retrofit.scalars, - - Libs.maplibre, - Libs.mpAndroidCharts, - - Libs.telemetry, - Libs.timber + libs.e.elib, + + libs.androidx.core.ktx, + libs.androidx.appcompat, + libs.androidx.fragment.ktx, + libs.androidx.lifecycle.runtime, + libs.androidx.lifecycle.viewmodel, + libs.androidx.work.ktx, + libs.google.material, + + libs.androidx.navigation.fragment, + libs.androidx.navigation.ui, + + libs.retrofit, + libs.retrofit.scalars, + + libs.maplibre, + libs.mpandroidcharts, + + libs.e.telemetry, + libs.timber ) - debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1' + debugImplementation libs.leakcanary - testImplementation 'junit:junit:4.+' + testImplementation libs.junit } static def log(Object val) { diff --git a/app/src/main/java/foundation/e/advancedprivacy/DependencyContainer.kt b/app/src/main/java/foundation/e/advancedprivacy/DependencyContainer.kt index 5664515ac70072b14b80b55226e426817a52eed0..820a8687af54d2954b07256ada712a5292842541 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/DependencyContainer.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/DependencyContainer.kt @@ -44,8 +44,8 @@ import foundation.e.advancedprivacy.features.trackers.TrackersViewModel import foundation.e.advancedprivacy.features.trackers.apptrackers.AppTrackersFragmentArgs import foundation.e.advancedprivacy.features.trackers.apptrackers.AppTrackersViewModel import foundation.e.privacymodules.fakelocation.FakeLocationModule +import foundation.e.privacymodules.ipscrambler.IIpScramblerModule import foundation.e.privacymodules.ipscrambler.IpScramblerModule -import foundation.e.privacymodules.ipscramblermodule.IIpScramblerModule import foundation.e.privacymodules.permissions.PermissionsPrivacyModule import foundation.e.privacymodules.permissions.data.ApplicationDescription import foundation.e.privacymodules.permissions.data.ProfileType diff --git a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/IpScramblingStateUseCase.kt b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/IpScramblingStateUseCase.kt index 6ae07469f767faa42abe0d6cf94533c93e3bd3f6..22da4707909a293eb12876e990a09516c2ab6029 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/IpScramblingStateUseCase.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/domain/usecases/IpScramblingStateUseCase.kt @@ -24,7 +24,7 @@ import foundation.e.advancedprivacy.domain.entities.InternetPrivacyMode.HIDE_IP import foundation.e.advancedprivacy.domain.entities.InternetPrivacyMode.HIDE_IP_LOADING import foundation.e.advancedprivacy.domain.entities.InternetPrivacyMode.REAL_IP import foundation.e.advancedprivacy.domain.entities.InternetPrivacyMode.REAL_IP_LOADING -import foundation.e.privacymodules.ipscramblermodule.IIpScramblerModule +import foundation.e.privacymodules.ipscrambler.IIpScramblerModule import foundation.e.privacymodules.permissions.IPermissionsPrivacyModule import foundation.e.privacymodules.permissions.data.ApplicationDescription import kotlinx.coroutines.CoroutineScope diff --git a/app/src/main/java/foundation/e/advancedprivacy/features/internetprivacy/InternetPrivacyViewModel.kt b/app/src/main/java/foundation/e/advancedprivacy/features/internetprivacy/InternetPrivacyViewModel.kt index 051c8e8fee9eed3401e1fd3530d4e445f85617ec..4c707a23965ab42c3272e1ed985e0bed18867fcd 100644 --- a/app/src/main/java/foundation/e/advancedprivacy/features/internetprivacy/InternetPrivacyViewModel.kt +++ b/app/src/main/java/foundation/e/advancedprivacy/features/internetprivacy/InternetPrivacyViewModel.kt @@ -25,7 +25,7 @@ import foundation.e.advancedprivacy.domain.entities.InternetPrivacyMode import foundation.e.advancedprivacy.domain.usecases.AppListUseCase import foundation.e.advancedprivacy.domain.usecases.GetQuickPrivacyStateUseCase import foundation.e.advancedprivacy.domain.usecases.IpScramblingStateUseCase -import foundation.e.privacymodules.ipscramblermodule.IIpScramblerModule +import foundation.e.privacymodules.ipscrambler.IIpScramblerModule import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.MutableSharedFlow diff --git a/build.gradle b/build.gradle index 824c3069874509c28ad06be238de6ca07f789ee8..8f6ecf34ad7cc9e1dc38242b8ca70964e20fa68c 100644 --- a/build.gradle +++ b/build.gradle @@ -39,28 +39,19 @@ buildscript { // Load properties either from local.properties or system environment (on CI). apply from: rootProject.file('load-properties.gradle') - // Load dependencies as extra properties. - apply from: rootProject.file('dependencies.gradle') - repositories { google() mavenCentral() } - - dependencies { - classpath Libs.androidGradlePlugin - classpath Libs.Kotlin.gradlePlugin - classpath Libs.AndroidX.navigation.safeArgs - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } } plugins { - id 'com.diffplug.spotless' version '5.12.4' - id 'com.github.ben-manes.versions' version '0.38.0' - id 'org.jetbrains.kotlin.android' version '1.6.10' apply false + alias libs.plugins.spotless + alias libs.plugins.benmanes.versions + alias libs.plugins.kotlin.android apply false + alias libs.plugins.android.application apply false + alias libs.plugins.kotlin.kapt apply false + alias libs.plugins.androidx.navigation.safeargs apply false } allprojects { @@ -82,7 +73,7 @@ subprojects { targetExclude("$buildDir/**/*.kt") targetExclude('bin/**/*.kt') targetExclude '**/spotless/*.kt' - ktlint(Versions.ktlint) + ktlint("0.40.0") } format 'misc', { // define the files to apply `misc` to diff --git a/dependencies.gradle b/dependencies.gradle deleted file mode 100644 index 2843f7178488f7f57dfacf6984a718c8e42f24de..0000000000000000000000000000000000000000 --- a/dependencies.gradle +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2022 E FOUNDATION, 2023 MURENA SAS - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -def libs = [:] -ext.Libs = libs - -def versions = [ - ktlint: "0.40.0", -] -ext.Versions = versions - -libs.androidGradlePlugin = "com.android.tools.build:gradle:7.2.1" - -libs.timber = "com.jakewharton.timber:timber:5.0.1" - - -libs.junit = "junit:junit:4.13.1" -libs.robolectric = "org.robolectric:robolectric:4.5" -libs.mockK = "io.mockk:mockk:1.10.5" - -libs.leakCanary = "com.squareup.leakcanary:leakcanary-android:2.6" - -libs.truth = "com.google.truth:truth:1.1" - -versions.kotlin = "1.6.10" -libs.Kotlin = [ - stdlib: "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$versions.kotlin", - gradlePlugin: "org.jetbrains.kotlin:kotlin-gradle-plugin:$versions.kotlin", -] - - - -versions.coroutines = "1.6.1" -libs.Coroutines = [ - core: "org.jetbrains.kotlinx:kotlinx-coroutines-core:$versions.coroutines", - android: "org.jetbrains.kotlinx:kotlinx-coroutines-android:$versions.coroutines", - test: "org.jetbrains.kotlinx:kotlinx-coroutines-test:$versions.coroutines", -] - -libs.AndroidX = [ - collection: "androidx.collection:collection-ktx:1.1.0", - palette: "androidx.palette:palette:1.0.0", - archCoreTesting: "androidx.arch.core:core-testing:2.1.0", - coreKtx: "androidx.core:core-ktx:1.8.0", - coreKtxAPI29: "androidx.core:core-ktx:1.6.0", - appCompat: 'androidx.appcompat:appcompat:1.4.2', - work: 'androidx.work:work-runtime-ktx:2.7.1', -] - -versions.fragment = "1.5.0" -libs.AndroidX.Fragment = [ - fragment: "androidx.fragment:fragment:$versions.fragment", - fragmentKtx: "androidx.fragment:fragment-ktx:$versions.fragment", -] - -versions.navigation = "2.5.3" - -libs.AndroidX.navigation = [ - fragmentKtx: "androidx.navigation:navigation-fragment-ktx:$versions.navigation", - uiKtx: "androidx.navigation:navigation-ui-ktx:$versions.navigation", - safeArgs: "androidx.navigation:navigation-safe-args-gradle-plugin:$versions.navigation", -] - -versions.androidx_test = "1.3.0" -libs.AndroidX.Test = [ - core: "androidx.test:core:$versions.androidx_test", - rules: "androidx.test:rules:$versions.androidx_test", - junit: "androidx.test.ext:junit-ktx:1.1.2", - espresso: "androidx.test.espresso:espresso-core:3.3.0", -] - -versions.lifecycle = "2.5.0" -libs.AndroidX.Lifecycle = [ - runtime: "androidx.lifecycle:lifecycle-runtime-ktx:$versions.lifecycle", - viewmodel: "androidx.lifecycle:lifecycle-viewmodel-ktx:$versions.lifecycle", -] - -versions.room = "2.3.0" -libs.AndroidX.Room = [ - common: "androidx.room:room-common:$versions.room", - runtime: "androidx.room:room-runtime:$versions.room", - compiler: "androidx.room:room-compiler:$versions.room", - ktx: "androidx.room:room-ktx:$versions.room", - testing: "androidx.room:room-testing:$versions.room", -] - -versions.androidxhilt = "1.0.0-beta01" -libs.AndroidX.Hilt = [ - work: "androidx.hilt:hilt-work:$versions.androidxhilt", - compiler: "androidx.hilt:hilt-compiler:$versions.androidxhilt", -] - -versions.hilt = "2.35" -libs.Hilt = [ - library: "com.google.dagger:hilt-android:$versions.hilt", - compiler: "com.google.dagger:hilt-compiler:$versions.hilt", - testing: "com.google.dagger:hilt-android-testing:$versions.hilt", - gradlePlugin: "com.google.dagger:hilt-android-gradle-plugin:$versions.hilt", -] - -libs.material = 'com.google.android.material:material:1.6.1' - -libs.Retrofit = [ - retrofit: 'com.squareup.retrofit2:retrofit:2.9.0', - scalars: 'com.squareup.retrofit2:converter-scalars:2.9.0' -] - -libs.maplibre = 'org.maplibre.gl:android-sdk:10.0.2' - -libs.mpAndroidCharts = 'com.github.PhilJay:MPAndroidChart:v3.1.0' - -libs.telemetry = 'foundation.e.lib:telemetry:0.0.8-alpha' diff --git a/fakelocation/build.gradle b/fakelocation/build.gradle index 945cb66d5058edbbe49c26d8b6c9b63fcbb20eab..91f80315ea05f336ff7b5b5e0415cb21f904ad8d 100644 --- a/fakelocation/build.gradle +++ b/fakelocation/build.gradle @@ -46,11 +46,7 @@ android { } dependencies { - implementation ( - Libs.Kotlin.stdlib, - Libs.AndroidX.coreKtx, - Libs.Coroutines.core - ) + implementation (libs.bundles.kotlin.android.coroutines) implementation project(':privacymodule-api') } diff --git a/fakelocation/fakelocationdemo/build.gradle b/fakelocation/fakelocationdemo/build.gradle index 7e05b8a48fbafaba5cb5551f1a2f8c2f6873ed70..0145eca3686b5f2ce20d242361f2d33ace5c1de9 100644 --- a/fakelocation/fakelocationdemo/build.gradle +++ b/fakelocation/fakelocationdemo/build.gradle @@ -60,12 +60,10 @@ dependencies { implementation ( - Libs.Kotlin.stdlib, - Libs.AndroidX.coreKtx, - Libs.AndroidX.appCompat, - Libs.material, + libs.androidx.core.ktx, + libs.androidx.appcompat, + libs.google.material, ) - testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + testImplementation libs.junit + } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000000000000000000000000000000000000..b5b7a358e3bc1e6f31653d948b4d7f60968d9c87 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,56 @@ +[versions] + +kotlinx-coroutines = "1.6.1" +kotlin = "1.6.10" +androidx-navigation = "2.5.3" +androidx-test = "1.3.0" +androidx-lifecycle = "2.5.0" +androidx-room = "2.3.0" +orbotservice = "orbot-16.6.3-1" +retrofit = "2.9.0" + +[libraries] + +androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version = "1.4.2" } +androidx-arch-core-testing = {group = "androidx.arch.core", name = "core-testing", version = "2.1.0" } +androidx-collection = { group = "androidx.collection", name = "collection-ktx", version = "1.1.0" } +androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version = "1.8.0" } +androidx-fragment-ktx = { group = "androidx.fragment", name = "fragment-ktx", version = "1.5.0" } +androidx-lifecycle-runtime = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "androidx-lifecycle" } +androidx-lifecycle-viewmodel = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "androidx-lifecycle" } +androidx-localbroadcast = { group = "androidx.localbroadcastmanager", name = "localbroadcastmanager", version = "1.0.0" } +androidx-navigation-fragment = { group = "androidx.navigation", name = "navigation-fragment-ktx", version.ref = "androidx-navigation" } +androidx-navigation-ui = { group = "androidx.navigation", name = "navigation-ui-ktx", version.ref = "androidx-navigation" } +androidx-palette = { group = "androidx.palette", name = "palette", version = "1.0.0" } +androidx-room-common = { group = "androidx.room", name = "room-common", version.ref = "androidx-room" } +androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "androidx-room" } +androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "androidx-room" } +androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "androidx-room" } +androidx-work-ktx = { group = "androidx.work", name = "work-runtime-ktx", version = "2.7.1" } +e-elib = { group = "foundation.e", name = "elib", version = "0.0.1-alpha11" } +e-orbotservice = { group = "foundation.e", name = "orbotservice", version.ref = "orbotservice" } +e-telemetry = { group = "foundation.e.lib", name = "telemetry", version = "0.0.8-alpha" } +google-material = { group = "com.google.android.material", name = "material", version = "1.6.1" } +junit = { group = "junit", name = "junit", version = "4.13.1" } +kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" } +kotlinx-coroutines = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" } +leakcanary = { group = "com.squareup.leakcanary", name = "leakcanary-android", version = "2.9.1" } +maplibre = { group = "org.maplibre.gl", name = "android-sdk", version = "10.0.2" } +mockk = { group = "io.mockk", name = "mockk", version = "1.10.5" } +mpandroidcharts = { group = "com.github.PhilJay", name = "MPAndroidChart", version = "v3.1.0" } +retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" } +retrofit-scalars = { group = "com.squareup.retrofit2", name = "converter-scalars", version.ref = "retrofit" } +timber = { group = "com.jakewharton.timber", name = "timber", version = "5.0.1" } + +[bundles] + +kotlin-android-coroutines = ["androidx-core-ktx", "kotlinx-coroutines"] + +[plugins] + +android-application = { id = "com.android.application", version = "7.2.1" } +androidx-navigation-safeargs = { id = "androidx.navigation.safeargs.kotlin", version.ref = "androidx-navigation" } +benmanes-versions = { id = "com.github.ben-manes.versions", version = "0.38.0" } +kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" } +spotless = { id = "com.diffplug.spotless", version = "5.12.4" } diff --git a/ipscrambling/.gitignore b/ipscrambling/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..42afabfd2abebf31384ca7797186a27a4b7dbee8 --- /dev/null +++ b/ipscrambling/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/ipscrambling/Orbot_LICENSE b/ipscrambling/Orbot_LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..194b99d9cf1d4028e28a661986267377876d6275 --- /dev/null +++ b/ipscrambling/Orbot_LICENSE @@ -0,0 +1,206 @@ +This file contains the license for Orbot, a free software project to +provide anonymity on the Internet from a Google Android smartphone. + +It also lists the licenses for other components used by Orbot, including +Tor, and iptables. + +For more information about Orbot, see https://guardianproject.info/apps/org.torproject.android/ + +If you got this file as a part of a larger bundle, there may be other +license terms that you should be aware of. +=============================================================================== +Orbot is distributed under this license (aka the 3-clause BSD license) + +Copyright (c) 2009-2010, Nathan Freitas, The Guardian Project + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + + * Neither the names of the copyright owners nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +***** + +=============================================================================== +Orbot includes the Obfs4 pluggable transport: +https://gitweb.torproject.org/pluggable-transports/obfs4.git + +Copyright (c) 2014, Yawning Angel +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +=============================================================================== + + +***** +Orbot contains a binary distribution of Tor: + + This file contains the license for Tor, + a free software project to provide anonymity on the Internet. + + It also lists the licenses for other components used by Tor. + + For more information about Tor, see https://www.torproject.org/. + + If you got this file as a part of a larger bundle, + there may be other license terms that you should be aware of. + +=============================================================================== +Tor is distributed under this license: + +Copyright (c) 2001-2004, Roger Dingledine +Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson +Copyright (c) 2007-2009, The Tor Project, Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + + * Neither the names of the copyright owners nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +=============================================================================== + +src/common/strlcat.c and src/common/strlcpy.c by Todd C. Miller are licensed +under the following license: + + * Copyright (c) 1998 Todd C. Miller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================== +If you got Tor as a static binary with OpenSSL included, then you should know: + "This product includes software developed by the OpenSSL Project + for use in the OpenSSL Toolkit (http://www.openssl.org/)" +=============================================================================== + +=============================================================================== +"This program uses the IP-to-Country Database provided by +WebHosting.Info (http://www.webhosting.info), available from +http://ip-to-country.webhosting.info." +See the src/config/geoip file in particular. +=============================================================================== + +=============================================================================== +Orbot also uses iptables from the Netfilter.org project + +netfilter/iptables is - like all of the Linux Kernel - Free Software (sometimes +referred to as Open Source Software), distributed under the terms of the GNU GPLv2 +only. Please, note that some source code files might differ, and in that case it +is explicitely stated in the header of every file. + +The GPL also contains some obligations. If you distribute netfilter/iptables code +in binary form, you have to offer the source code, too. +=============================================================================== + +=============================================================================== +Orbot also includes BadVPN tun2socks: https://github.com/ambrop72/badvpn + +Copyright (c) 2009, Ambroz Bizjak +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +=============================================================================== diff --git a/ipscrambling/README.md b/ipscrambling/README.md new file mode 100644 index 0000000000000000000000000000000000000000..777b6a1d46201c74d20ca523ce1bff7b1af97105 --- /dev/null +++ b/ipscrambling/README.md @@ -0,0 +1,42 @@ +# Ipscrambling module + +This Module implements IpScramblerModule functionnalities with Tor, reliying on a fork of OrbotService. + +# Build + +Ipscrambling includes a git repo submodules of OrbotService, the module used by Orbot to run Tor + +Be sure that you have all of the git submodules up-to-date: + + git submodule update --init --recursive + +You can build the AAR modules : + + ./gradlew :ipscrambling:orbotservice:assembleRelease + +To deploy localy during development + + ./gradlew --console=verbose publishToMavenLocal + +This will put compiled AAR and pom file exposing their dependencies in the local maven +repository (usually in ~/.m2/repository). + + +To push release on gitlab + + ./gradlew --console=verbose publish + +# Update orbotservice to an upper Orbot version + +1. Upgrade the code: follow the steps in [orbotservice/README.md](orbotservice/README.md) +2. Prepare the orbotservice the dependencies : follow the steps in [exportdependencies/update_dependencies.md](exportdependencies/update_dependencies.md), first using the mvn install:install-file command +3. build and deploy orbotservice locally: + + ./gradlew :ipscrambling:orbotservice:assembleRelease + ./gradlew --console=verbose :ipscrambling:orbotservice:publishToMavenLocal + +5. Test this new version with advanced privacy, and merge the orbotservice. +6. deploy the orbotservice dependencies to gitlab registry see [exportdependencies/update_dependencies.md](exportdependencies/update_dependencies.md), using mvn deploy:deploy-file command +7. deploy orbotservice in gitlab registry + ./gradlew --console=verbose :orbotservice:publish +8. Create MR in AdvancedPrivacy. diff --git a/ipscrambling/build.gradle b/ipscrambling/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..0e293df255bd812b064e58db4e899b06a2643cba --- /dev/null +++ b/ipscrambling/build.gradle @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2021 E FOUNDATION + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +plugins { + id 'com.android.library' + id 'kotlin-android' +} + +android { + compileSdkVersion buildConfig.compileSdk + + defaultConfig { + minSdkVersion buildConfig.minSdk + targetSdkVersion buildConfig.targetSdk + + consumerProguardFiles "consumer-rules.pro" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = '1.8' + } +} + +dependencies { + implementation( + libs.bundles.kotlin.android.coroutines, + libs.androidx.localbroadcast, + ) + implementation libs.e.orbotservice + //implementation project(':ipscrambling:orbotservice') +} diff --git a/ipscrambling/commons.gradle b/ipscrambling/commons.gradle new file mode 100644 index 0000000000000000000000000000000000000000..3be1be438ef6bc3c33b73ccf7d9c6cbb8da70c56 --- /dev/null +++ b/ipscrambling/commons.gradle @@ -0,0 +1,12 @@ + +/* + Applies across all modules + */ +android { + compileSdkVersion 30 + buildToolsVersion '30.0.3' + compileOptions { + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 + } +} diff --git a/ipscrambling/consumer-rules.pro b/ipscrambling/consumer-rules.pro new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/ipscrambling/dependencies.gradle b/ipscrambling/dependencies.gradle new file mode 100644 index 0000000000000000000000000000000000000000..412bf9acb907bdd747a91d1a229d94ccc850a8de --- /dev/null +++ b/ipscrambling/dependencies.gradle @@ -0,0 +1,61 @@ +ext { + versions = [ + android_material : "1.4.0", + android_shell : "1.0.0", + android_snowfall : "1.2.1", + android_volley : "1.2.0", + androidx_appcompat : "1.3.1", + androidx_constraint : "2.1.0", + androidx_coordinator : "1.1.0", + androidx_core : "1.6.0", + androidx_leanback : "1.2.0-alpha01", + androidx_leanback_paging : "1.1.0-alpha08", + androidx_leanback_tab : "1.1.0-beta01", + androidx_localbroadcast : "1.0.0", + androidx_multidex : "2.0.1", + androidx_palette : "1.0.0", + androidx_recyclerview : "1.2.1", + apl_appintro : "v4.2.3", + bclogic_pulsator : "1.0.3", + fastlane_screengrab : "1.2.0", + guardian_geoip : "20191217", + guardian_jsocks : "1.0.4", + guardian_jtorctl : "0.4.5.7", + ipt_proxy : "1.8.1", + portmapper : "2.0.5", + tor_android : "0.4.7.10", + pcap_core : "1.8.2", + pcap_factory : "1.8.2", + orbot_service : libs.versions.orbotservice, + ] + + libs = [ + android_material : "com.google.android.material:material:$versions.android_material", + android_shell : "com.jaredrummler:android-shell:$versions.android_shell", + android_snowfall : "com.github.jetradarmobile:android-snowfall:$versions.android_snowfall", + android_volley : "com.android.volley:volley:$versions.android_volley", + androidx_appcompat : "androidx.appcompat:appcompat:$versions.androidx_appcompat", + androidx_constraint : "androidx.constraintlayout:constraintlayout:$versions.androidx_constraint", + androidx_coordinator : "androidx.coordinatorlayout:coordinatorlayout:$versions.androidx_coordinator", + androidx_core : "androidx.core:core:$versions.androidx_core", + androidx_leanback_core : "androidx.leanback:leanback:$versions.androidx_leanback", + androidx_leanback_paging : "androidx.leanback:leanback-paging:$versions.androidx_leanback_paging", + androidx_leanback_preferences : "androidx.leanback:leanback-preference:$versions.androidx_leanback", + androidx_leanback_tab : "androidx.leanback:leanback-tab:$versions.androidx_leanback_tab", + androidx_localbroadcast : "androidx.localbroadcastmanager:localbroadcastmanager:$versions.androidx_localbroadcast", + androidx_multidex : "androidx.multidex:multidex:$versions.androidx_multidex", + androidx_palette : "androidx.palette:palette:$versions.androidx_palette", + androidx_recyclerview : "androidx.recyclerview:recyclerview:$versions.androidx_recyclerview", + apl_appintro : "com.github.apl-devs:appintro:$versions.apl_appintro", + bclogic_pulsator : "pl.bclogic:pulsator4droid:$versions.bclogic_pulsator", + fastlane_screengrab : "tools.fastlane:screengrab:$versions.fastlane_screengrab", + guardian_geoip : "foundation.e:geoip:$versions.orbot_service", + guardian_jsocks : "com.gitlab.guardianproject:jsocksandroid:$versions.guardian_jsocks", + guardian_jtorctl : "info.guardianproject:jtorctl:$versions.guardian_jtorctl", + ipt_proxy : "foundation.e:OrbotIPtProxy:$versions.orbot_service", + portmapper : "com.offbynull.portmapper:portmapper:$versions.portmapper", + tor_android : "foundation.e:tor-android:$versions.orbot_service", + pcap_core : "org.pcap4j:pcap4j-core:$versions.pcap_core", + pcap_factory : "org.pcap4j:pcap4j-packetfactory-static:$versions.pcap_factory" + ] +} diff --git a/ipscrambling/exportdependencies/pom.xml b/ipscrambling/exportdependencies/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..be28747479cbcb4dc0d4c0e59bae769e1ade197c --- /dev/null +++ b/ipscrambling/exportdependencies/pom.xml @@ -0,0 +1,24 @@ + + + 4.0.0 + foundation.e + orbotservice + orbot-16.6.3-1 + + + + + ${project.groupId} + ${project.artifactId} + ${project.version} + aar + OrbotLib.aar + + + + + gitlab-e-maven + https://gitlab.e.foundation/api/v4/projects/1063/packages/maven + + + diff --git a/ipscrambling/exportdependencies/publish.gradle b/ipscrambling/exportdependencies/publish.gradle new file mode 100644 index 0000000000000000000000000000000000000000..657ce22afef1b056cfe62c8c60b510d2141a0532 --- /dev/null +++ b/ipscrambling/exportdependencies/publish.gradle @@ -0,0 +1,52 @@ +apply plugin: 'maven-publish' + +publishing { + publications { + maven(MavenPublication) { + groupId 'foundation.e' + artifactId 'orbotservice' + version versions.orbot_service + artifact "$buildDir/outputs/aar/orbotservice-release.aar" + + pom.withXml { + def dependenciesNode = asNode().appendNode('dependencies') + configurations.implementation.allDependencies.each { dependency -> + if (dependency.name != 'unspecified') { + def dependencyNode = dependenciesNode.appendNode('dependency') + dependencyNode.appendNode('groupId', dependency.group) + dependencyNode.appendNode('artifactId', dependency.name) + dependencyNode.appendNode('version', dependency.version) + } + } + } + + repositories { + def ciJobToken = System.getenv("CI_JOB_TOKEN") + def ciApiV4Url = System.getenv("CI_API_V4_URL") + if (ciJobToken != null) { + maven { + url "${ciApiV4Url}/projects/1063/packages/maven" + credentials(HttpHeaderCredentials) { + name = 'Job-Token' + value = ciJobToken + } + authentication { + header(HttpHeaderAuthentication) + } + } + } else { + maven { + url "https://gitlab.e.foundation/api/v4/projects/1063/packages/maven" + credentials(HttpHeaderCredentials) { + name = "Private-Token" + value = gitLabPrivateToken + } + authentication { + header(HttpHeaderAuthentication) + } + } + } + } + } + } +} \ No newline at end of file diff --git a/ipscrambling/exportdependencies/update_dependencies.md b/ipscrambling/exportdependencies/update_dependencies.md new file mode 100644 index 0000000000000000000000000000000000000000..32ef58da8cd963b68ff2eb11abac819c580ef74a --- /dev/null +++ b/ipscrambling/exportdependencies/update_dependencies.md @@ -0,0 +1,43 @@ +A few orbot dependencies are added directly through the /libs directory, because remotely available version are outdated. We can't embed .aar or .jar into the orbotservice.aar (as any aar), so we have to expose this dependencies in the gitlab repository. + +To do that we use the mn deploy:deploy-file command ; and also the mvn install:install-file command to deploy in local maven repository for development. + +1. Update the orbot_service version in + * exportdependencies/pom.xml file + * dependencies.gradle +2. For each dependencies in orbot/libs, update or prepare an entry in dependecies.gradle, using groupId=foundation.e ; version orbot_service, and an approprioate artifactId . +3. For each dependencies in orbot/libs, run with appropriate PATH and ARTIFACTID : + +mvn install:install-file \ +-DartifactId=[ARTIFACTID] \ +-Dpackaging=aar \ +-Dfile=[PATH] + +4. Later, when isvalidated, deploy to gitlab repository: + +mvn deploy:deploy-file \ +-DrepositoryId=gitlab-e-maven \ +-Durl=https://gitlab.e.foundation/api/v4/projects/1063/packages/maven \ +-DartifactId=[ARTIFACTID] \ +-Dpackaging=aar \ +-Dfile=[PATH] + +example, for tor-android-binary +step 2: +"info.guardianproject:tor-android:$versions.tor_android" -> "foundation.e:tor-android:$versions.orbot_service", + +step 3: + +mvn install:install-file \ +-DartifactId=tor-android \ +-Dpackaging=aar \ +-Dfile="../../orbot/libs/tor-android-binary-release.aar + +step 4 : + +mvn deploy:deploy-file \ +-DrepositoryId=gitlab-e-maven \ +-Durl=https://gitlab.e.foundation/api/v4/projects/1063/packages/maven \ +-DartifactId=tor-android \ +-Dpackaging=aar \ +-Dfile="../../orbot/libs/tor-android-binary-release.aar diff --git a/ipscrambling/orbotservice b/ipscrambling/orbotservice new file mode 160000 index 0000000000000000000000000000000000000000..1930a046eff2dd37d23ffd83f0064f60334468a5 --- /dev/null +++ b/ipscrambling/orbotservice @@ -0,0 +1 @@ +Subproject commit 1930a046eff2dd37d23ffd83f0064f60334468a5 diff --git a/ipscrambling/proguard-rules.pro b/ipscrambling/proguard-rules.pro new file mode 100644 index 0000000000000000000000000000000000000000..481bb434814107eb79d7a30b676d344b0df2f8ce --- /dev/null +++ b/ipscrambling/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/ipscrambling/src/main/AndroidManifest.xml b/ipscrambling/src/main/AndroidManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..e9481477dc04fbc26959c59848f6382d0ec570f7 --- /dev/null +++ b/ipscrambling/src/main/AndroidManifest.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + diff --git a/ipscrambling/src/main/java/foundation/e/privacymodules/ipscrambler/IIpScramblerModule.kt b/ipscrambling/src/main/java/foundation/e/privacymodules/ipscrambler/IIpScramblerModule.kt new file mode 100644 index 0000000000000000000000000000000000000000..859319a50192819c446149242a1ef0cabd0b5fec --- /dev/null +++ b/ipscrambling/src/main/java/foundation/e/privacymodules/ipscrambler/IIpScramblerModule.kt @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2021 E FOUNDATION + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package foundation.e.privacymodules.ipscrambler + +import android.content.Intent + +interface IIpScramblerModule { + fun prepareAndroidVpn(): Intent? + + fun start(enableNotification: Boolean = true) + + fun stop() + + fun requestStatus() + + var appList: Set + + var exitCountry: String + fun getAvailablesLocations(): Set + + val httpProxyPort: Int + val socksProxyPort: Int + + fun addListener(listener: Listener) + fun removeListener(listener: Listener) + fun clearListeners() + + fun onCleared() + + interface Listener { + fun onStatusChanged(newStatus: Status) + fun log(message: String) + fun onTrafficUpdate(upload: Long, download: Long, read: Long, write: Long) + } + + enum class Status { + OFF, ON, STARTING, STOPPING, START_DISABLED + } +} diff --git a/ipscrambling/src/main/java/foundation/e/privacymodules/ipscrambler/IpScramblerModule.kt b/ipscrambling/src/main/java/foundation/e/privacymodules/ipscrambler/IpScramblerModule.kt new file mode 100644 index 0000000000000000000000000000000000000000..1c393304c6f5230443149adc085d6c4e8ed39f39 --- /dev/null +++ b/ipscrambling/src/main/java/foundation/e/privacymodules/ipscrambler/IpScramblerModule.kt @@ -0,0 +1,301 @@ +/* + * Copyright (C) 2021 E FOUNDATION + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package foundation.e.privacymodules.ipscrambler + +import android.annotation.SuppressLint +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.net.VpnService +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.util.Log +import androidx.localbroadcastmanager.content.LocalBroadcastManager +import foundation.e.privacymodules.ipscrambler.IIpScramblerModule.Listener +import foundation.e.privacymodules.ipscrambler.IIpScramblerModule.Status +import org.torproject.android.service.OrbotConstants +import org.torproject.android.service.OrbotConstants.ACTION_STOP_FOREGROUND_TASK +import org.torproject.android.service.OrbotService +import org.torproject.android.service.util.Prefs +import java.security.InvalidParameterException + +@SuppressLint("CommitPrefEdits") +class IpScramblerModule(private val context: Context) : IIpScramblerModule { + companion object { + const val TAG = "IpScramblerModule" + + private val EXIT_COUNTRY_CODES = setOf("DE", "AT", "SE", "CH", "IS", "CA", "US", "ES", "FR", "BG", "PL", "AU", "BR", "CZ", "DK", "FI", "GB", "HU", "NL", "JP", "RO", "RU", "SG", "SK") + + // Key where exit country is stored by orbot service. + private const val PREFS_KEY_EXIT_NODES = "pref_exit_nodes" + // Copy of the package private OrbotService.NOTIFY_ID value. + // const val ORBOT_SERVICE_NOTIFY_ID_COPY = 1 + } + + private var currentStatus: Status? = null + private val listeners = mutableSetOf() + + private val localBroadcastReceiver: BroadcastReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + val action = intent.action ?: return + if (action == OrbotConstants.ACTION_RUNNING_SYNC) { + try { + intent.getStringExtra(OrbotConstants.EXTRA_STATUS)?.let { + val newStatus = Status.valueOf(it) + currentStatus = newStatus + } + } catch (e: Exception) { + Log.e(TAG, "Can't parse Orbot service status.") + } + return + } + + val msg = messageHandler.obtainMessage() + msg.obj = action + msg.data = intent.extras + messageHandler.sendMessage(msg) + } + } + + private val messageHandler: Handler = object : Handler(Looper.getMainLooper()) { + override fun handleMessage(msg: Message) { + val action = msg.obj as? String ?: return + val data = msg.data + when (action) { + OrbotConstants.LOCAL_ACTION_LOG -> + data.getString(OrbotConstants.LOCAL_EXTRA_LOG)?.let { newLog(it) } + + OrbotConstants.LOCAL_ACTION_BANDWIDTH -> { + trafficUpdate( + data.getLong("up", 0), + data.getLong("down", 0), + data.getLong("written", 0), + data.getLong("read", 0) + ) + } + + OrbotConstants.LOCAL_ACTION_PORTS -> { + httpProxyPort = data.getInt(OrbotService.EXTRA_HTTP_PROXY_PORT, -1) + socksProxyPort = data.getInt(OrbotService.EXTRA_SOCKS_PROXY_PORT, -1) + } + + OrbotConstants.LOCAL_ACTION_STATUS -> + data.getString(OrbotConstants.EXTRA_STATUS)?.let { + try { + val newStatus = Status.valueOf(it) + updateStatus(newStatus, force = true) + } catch (e: Exception) { + Log.e(TAG, "Can't parse Orbot service status.") + } + } + } + super.handleMessage(msg) + } + } + + init { + Prefs.setContext(context) + + val lbm = LocalBroadcastManager.getInstance(context) + lbm.registerReceiver( + localBroadcastReceiver, + IntentFilter(OrbotConstants.LOCAL_ACTION_STATUS) + ) + lbm.registerReceiver( + localBroadcastReceiver, + IntentFilter(OrbotConstants.LOCAL_ACTION_BANDWIDTH) + ) + lbm.registerReceiver( + localBroadcastReceiver, + IntentFilter(OrbotConstants.LOCAL_ACTION_LOG) + ) + lbm.registerReceiver( + localBroadcastReceiver, + IntentFilter(OrbotConstants.LOCAL_ACTION_PORTS) + ) + lbm.registerReceiver( + localBroadcastReceiver, + IntentFilter(OrbotConstants.ACTION_RUNNING_SYNC) + ) + + Prefs.getSharedPrefs(context).edit() + .putInt(OrbotConstants.PREFS_DNS_PORT, OrbotConstants.TOR_DNS_PORT_DEFAULT) + .apply() + } + + private fun updateStatus(status: Status, force: Boolean = false) { + if (force || status != currentStatus) { + currentStatus = status + listeners.forEach { + it.onStatusChanged(status) + } + } + } + + private fun isServiceRunning(): Boolean { + // Reset status, and then ask to refresh it synchronously. + currentStatus = Status.OFF + LocalBroadcastManager.getInstance(context) + .sendBroadcastSync(Intent(OrbotConstants.ACTION_CHECK_RUNNING_SYNC)) + return currentStatus != Status.OFF + } + + private fun newLog(message: String) { + listeners.forEach { it.log(message) } + } + + private fun trafficUpdate(upload: Long, download: Long, read: Long, write: Long) { + listeners.forEach { it.onTrafficUpdate(upload, download, read, write) } + } + + private fun sendIntentToService(action: String, extra: Bundle? = null) { + val intent = Intent(context, OrbotService::class.java) + intent.action = action + extra?.let { intent.putExtras(it) } + context.startService(intent) + } + + @SuppressLint("ApplySharedPref") + private fun saveTorifiedApps(packageNames: Collection) { + packageNames.joinToString("|") + Prefs.getSharedPrefs(context).edit().putString( + OrbotConstants.PREFS_KEY_TORIFIED, packageNames.joinToString("|") + ).commit() + + if (isServiceRunning()) { + sendIntentToService(OrbotConstants.ACTION_RESTART_VPN) + } + } + + private fun getTorifiedApps(): Set { + val list = Prefs.getSharedPrefs(context).getString(OrbotConstants.PREFS_KEY_TORIFIED, "") + ?.split("|") + return if (list == null || list == listOf("")) { + emptySet() + } else { + list.toSet() + } + } + + @SuppressLint("ApplySharedPref") + private fun setExitCountryCode(countryCode: String) { + val countryParam = when { + countryCode.isEmpty() -> "" + countryCode in EXIT_COUNTRY_CODES -> "{$countryCode}" + else -> throw InvalidParameterException( + "Only these countries are available: ${EXIT_COUNTRY_CODES.joinToString { ", " } }" + ) + } + + if (isServiceRunning()) { + val extra = Bundle() + extra.putString("exit", countryParam) + sendIntentToService(OrbotConstants.CMD_SET_EXIT, extra) + } else { + Prefs.getSharedPrefs(context) + .edit().putString(PREFS_KEY_EXIT_NODES, countryParam) + .commit() + } + } + + private fun getExitCountryCode(): String { + val raw = Prefs.getExitNodes() + return if (raw.isEmpty()) raw else raw.slice(1..2) + } + + override fun prepareAndroidVpn(): Intent? { + return VpnService.prepare(context) + } + + override fun start(enableNotification: Boolean) { + Prefs.enableNotification(enableNotification) + Prefs.putUseVpn(true) + Prefs.putStartOnBoot(true) + + sendIntentToService(OrbotConstants.ACTION_START) + sendIntentToService(OrbotConstants.ACTION_START_VPN) + } + + override fun stop() { + updateStatus(Status.STOPPING) + + Prefs.putUseVpn(false) + Prefs.putStartOnBoot(false) + + sendIntentToService(OrbotConstants.ACTION_STOP_VPN) + sendIntentToService( + action = OrbotConstants.ACTION_STOP, + extra = Bundle().apply { putBoolean(ACTION_STOP_FOREGROUND_TASK, true) } + ) + stoppingWatchdog(5) + } + + private fun stoppingWatchdog(countDown: Int) { + Handler(Looper.getMainLooper()).postDelayed( + { + if (isServiceRunning() && countDown > 0) { + stoppingWatchdog(countDown - 1) + } else { + updateStatus(Status.OFF, force = true) + } + }, + 500 + ) + } + + override fun requestStatus() { + if (isServiceRunning()) { + sendIntentToService(OrbotConstants.ACTION_STATUS) + } else { + updateStatus(Status.OFF, force = true) + } + } + + override var appList: Set + get() = getTorifiedApps() + set(value) = saveTorifiedApps(value) + + override var exitCountry: String + get() = getExitCountryCode() + set(value) = setExitCountryCode(value) + + override fun getAvailablesLocations(): Set = EXIT_COUNTRY_CODES + + override var httpProxyPort: Int = -1 + private set + + override var socksProxyPort: Int = -1 + private set + + override fun addListener(listener: Listener) { + listeners.add(listener) + } + override fun removeListener(listener: Listener) { + listeners.remove(listener) + } + override fun clearListeners() { + listeners.clear() + } + + override fun onCleared() { + LocalBroadcastManager.getInstance(context).unregisterReceiver(localBroadcastReceiver) + } +} diff --git a/permissionse/build.gradle b/permissionse/build.gradle index 8ca075415b3113e88a3062cd5a8da65f19d242f0..90e062250db887bd88da8b90fa1798b076228926 100644 --- a/permissionse/build.gradle +++ b/permissionse/build.gradle @@ -26,11 +26,7 @@ android { dependencies { compileOnly project(':permissionse:libs:hidden-apis-stub') - implementation( - Libs.Kotlin.stdlib, - Libs.AndroidX.coreKtx, - Libs.Coroutines.core - ) + implementation(libs.bundles.kotlin.android.coroutines) implementation project(':privacymodule-api') } diff --git a/permissionsstandalone/build.gradle b/permissionsstandalone/build.gradle index 8d2def87229619b7de14db563f474de8f97a1f38..cf3563e44fc4f57e6c152d18605d273fa5e13c2c 100644 --- a/permissionsstandalone/build.gradle +++ b/permissionsstandalone/build.gradle @@ -46,15 +46,9 @@ android { } dependencies { - implementation( - Libs.Kotlin.stdlib, - Libs.AndroidX.coreKtx, - Libs.Coroutines.core - ) + implementation(libs.bundles.kotlin.android.coroutines) implementation project(':privacymodule-api') - testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + testImplementation libs.junit } diff --git a/privacymodule-api/build.gradle b/privacymodule-api/build.gradle index c0b1303dfdddd13edcf32ff9ec7ff22560251fc2..259672bf610dab0a559faf468a4d2d188df19c4b 100644 --- a/privacymodule-api/build.gradle +++ b/privacymodule-api/build.gradle @@ -46,9 +46,8 @@ android { dependencies { implementation( - Libs.Kotlin.stdlib, - Libs.AndroidX.coreKtxAPI29, - Libs.Coroutines.core + libs.androidx.core.ktx, + libs.kotlinx.coroutines ) } diff --git a/settings.gradle b/settings.gradle index 24ddbbd37861deeffc063e1d1697cff25e080eb6..c9b8f062883fe6f82f5b9b19d9c501c9b90a2546 100644 --- a/settings.gradle +++ b/settings.gradle @@ -6,6 +6,8 @@ pluginManagement { } } +enableFeaturePreview("VERSION_CATALOGS") + include ':app' rootProject.name = "AdvancedPrivacy" include ':fakelocation' @@ -15,7 +17,8 @@ include ':permissionsstandalone' include ':trackers' include ':permissionse' include ':permissionse:libs:hidden-apis-stub' - +include ':ipscrambling' +include ':ipscrambling:orbotservice' dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) @@ -26,4 +29,5 @@ dependencyResolutionManagement { maven { url 'https://gitlab.e.foundation/api/v4/groups/9/-/packages/maven'} maven { url "https://raw.githubusercontent.com/guardianproject/gpmaven/master" } } -} \ No newline at end of file +} + diff --git a/trackers/build.gradle b/trackers/build.gradle index ecf95bee733e297e9d4b2f859e89e17351d64788..bb9489a50519d7280e506293bac30a211b24378e 100644 --- a/trackers/build.gradle +++ b/trackers/build.gradle @@ -44,9 +44,7 @@ android { dependencies { implementation project(':privacymodule-api') implementation( - Libs.Kotlin.stdlib, - Libs.AndroidX.coreKtx, - Libs.Coroutines.core, - Libs.timber + libs.bundles.kotlin.android.coroutines, + libs.timber ) }