Skip to content

Commit 9c5afb4

Browse files
committed
Merge branch 'release/1.10.3'
2 parents 43d82c8 + 676be05 commit 9c5afb4

File tree

106 files changed

+1896
-307
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

106 files changed

+1896
-307
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,7 @@ local.properties
5151
**/fastlane/izzyscript/iod-scan-apk.php
5252
**/fastlane/izzyscript/current_iod-scan-apk.php
5353
**/fastlane/izzyscript/current_result_*.json
54+
55+
# Fluid Attacks
56+
**/fastlane/fluidattacks/results.csv
57+
**/fastlane/fluidattacks/apks/**

build.gradle

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ def getVersionCode = { ->
3636
allprojects {
3737
ext {
3838
androidApplicationId = 'org.cryptomator'
39-
androidVersionCode = 2904 // must be getVersionCode(). only at release tag set the actual value
40-
androidVersionName = '1.10.2'
39+
androidVersionCode = 2939 // must be getVersionCode(). only at release tag set the actual value
40+
androidVersionName = '1.10.3'
4141
}
4242
repositories {
4343
mavenCentral()

buildsystem/Dockerfile

+8
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,11 @@ RUN yes | sdkmanager --licenses --sdk_root="${ANDROID_HOME}"
3838
RUN update-java-alternatives -s java-1.17.0-openjdk-amd64
3939

4040
RUN rm -rf ${ANDROID_HOME}/tools
41+
42+
# Create a non-root user and group
43+
RUN groupadd -r appuser && useradd --no-log-init -r -g appuser appuser
44+
45+
# RUN mkdir -p /home/appuser/.gradle && chown -R appuser:appuser /home/appuser/.gradle
46+
47+
# Switch to the non-root user
48+
USER appuser

buildsystem/docker/dependencies.txt

+4
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1+
apt-utils=2.9.3
2+
wget=1.24.5-1
3+
git=1:2.45.1-1
4+
unzip=6.0-28
15
openjdk-17-jdk=17.0.11+9-1

data/build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ android {
9090
}
9191

9292
greendao {
93-
schemaVersion 12
93+
schemaVersion 13
9494
}
9595

9696
configurations.all {

data/src/androidTest/java/org/cryptomator/data/db/UpgradeDatabaseTest.kt

+310-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import org.cryptomator.data.db.entities.VaultEntityDao
1212
import org.cryptomator.domain.CloudType
1313
import org.cryptomator.util.SharedPreferencesHandler
1414
import org.cryptomator.util.crypto.CredentialCryptor
15+
import org.cryptomator.util.crypto.CryptoMode
1516
import org.greenrobot.greendao.database.Database
1617
import org.greenrobot.greendao.database.StandardDatabase
1718
import org.greenrobot.greendao.internal.DaoConfig
@@ -53,6 +54,8 @@ class UpgradeDatabaseTest {
5354
Upgrade8To9(sharedPreferencesHandler).applyTo(db, 8)
5455
Upgrade9To10(sharedPreferencesHandler).applyTo(db, 9)
5556
Upgrade10To11().applyTo(db, 10)
57+
Upgrade11To12(sharedPreferencesHandler).applyTo(db, 11)
58+
Upgrade12To13(context).applyTo(db, 12)
5659

5760
CloudEntityDao(DaoConfig(db, CloudEntityDao::class.java)).loadAll()
5861
VaultEntityDao(DaoConfig(db, VaultEntityDao::class.java)).loadAll()
@@ -303,7 +306,7 @@ class UpgradeDatabaseTest {
303306
}
304307

305308
@Test
306-
fun recoverUpgrade6to7DueToSQLiteExceptionThrown() {
309+
fun upgrade6To7DueToSQLiteExceptionThrown() {
307310
Upgrade0To1().applyTo(db, 0)
308311
Upgrade1To2().applyTo(db, 1)
309312
Upgrade2To3(context).applyTo(db, 2)
@@ -643,4 +646,310 @@ class UpgradeDatabaseTest {
643646

644647
Assert.assertThat(sharedPreferencesHandler.updateIntervalInDays(), CoreMatchers.`is`(Optional.absent()))
645648
}
649+
650+
@Test
651+
fun upgrade12To13BaseTests() {
652+
Upgrade0To1().applyTo(db, 0)
653+
Upgrade1To2().applyTo(db, 1)
654+
Upgrade2To3(context).applyTo(db, 2)
655+
Upgrade3To4().applyTo(db, 3)
656+
Upgrade4To5().applyTo(db, 4)
657+
Upgrade5To6().applyTo(db, 5)
658+
Upgrade6To7().applyTo(db, 6)
659+
Upgrade7To8().applyTo(db, 7)
660+
Upgrade8To9(sharedPreferencesHandler).applyTo(db, 8)
661+
Upgrade9To10(sharedPreferencesHandler).applyTo(db, 9)
662+
Upgrade10To11().applyTo(db, 10)
663+
Upgrade11To12(sharedPreferencesHandler).applyTo(db, 11)
664+
665+
val gcmCryptor = CredentialCryptor.getInstance(context, CryptoMode.GCM)
666+
val cbcCryptor = CredentialCryptor.getInstance(context, CryptoMode.CBC)
667+
668+
val accessTokenPlain = "accessToken"
669+
val accessTokenCiphertext = cbcCryptor.encrypt(accessTokenPlain)
670+
val s3SecretPlain = "s3SecretKey"
671+
val s3SecretCiphertext = cbcCryptor.encrypt(s3SecretPlain)
672+
val vaultPasswordPlain = "password"
673+
674+
Sql.insertInto("CLOUD_ENTITY") //
675+
.integer("_id", 15) //
676+
.text("TYPE", CloudType.S3.name) //
677+
.text("URL", "url") //
678+
.text("ACCESS_TOKEN", accessTokenCiphertext)
679+
.text("S3_BUCKET", "s3Bucket") //
680+
.text("S3_REGION", "s3Region") //
681+
.text("S3_SECRET_KEY", s3SecretCiphertext) //
682+
.executeOn(db)
683+
684+
Sql.insertInto("VAULT_ENTITY") //
685+
.integer("_id", 1) //
686+
.integer("FOLDER_CLOUD_ID", 15) //
687+
.text("FOLDER_PATH", "path1") //
688+
.text("FOLDER_NAME", "name") //
689+
.text("CLOUD_TYPE", CloudType.S3.name) //
690+
.text("PASSWORD", vaultPasswordPlain) //
691+
.integer("POSITION", 1) //
692+
.integer("FORMAT", 8) //
693+
.integer("SHORTENING_THRESHOLD", 4)
694+
.executeOn(db)
695+
696+
Sql.insertInto("VAULT_ENTITY") //
697+
.integer("_id", 2) //
698+
.integer("FOLDER_CLOUD_ID", 15) //
699+
.text("FOLDER_PATH", "path2") //
700+
.text("FOLDER_NAME", "name") //
701+
.text("CLOUD_TYPE", CloudType.S3.name) //
702+
.text("PASSWORD", null) //
703+
.integer("POSITION", 2) //
704+
.integer("FORMAT", 8) //
705+
.integer("SHORTENING_THRESHOLD", 4)
706+
.executeOn(db)
707+
708+
Upgrade12To13(context).applyTo(db, 12)
709+
710+
Sql.query("CLOUD_ENTITY").where("_id", Sql.eq(15)).executeOn(db).use {
711+
it.moveToFirst()
712+
Assert.assertThat(gcmCryptor.decrypt(it.getString(it.getColumnIndex("ACCESS_TOKEN"))), CoreMatchers.`is`(accessTokenPlain))
713+
Assert.assertThat(it.getString(it.getColumnIndex("ACCESS_TOKEN_CRYPTO_MODE")), CoreMatchers.`is`(CryptoMode.GCM.name))
714+
Assert.assertThat(gcmCryptor.decrypt(it.getString(it.getColumnIndex("S3_SECRET_KEY"))), CoreMatchers.`is`(s3SecretPlain))
715+
Assert.assertThat(it.getString(it.getColumnIndex("S3_SECRET_KEY_CRYPTO_MODE")), CoreMatchers.`is`(CryptoMode.GCM.name))
716+
}
717+
718+
Sql.query("VAULT_ENTITY").where("_id", Sql.eq(1)).executeOn(db).use {
719+
it.moveToFirst()
720+
Assert.assertThat(it.getString(it.getColumnIndex("PASSWORD")), CoreMatchers.`is`(vaultPasswordPlain))
721+
Assert.assertThat(it.getString(it.getColumnIndex("PASSWORD_CRYPTO_MODE")), CoreMatchers.`is`(CryptoMode.CBC.name))
722+
723+
Assert.assertThat(it.getString(it.getColumnIndex("FOLDER_PATH")), CoreMatchers.`is`("path1"))
724+
Assert.assertThat(it.getString(it.getColumnIndex("FOLDER_NAME")), CoreMatchers.`is`("name"))
725+
Assert.assertThat(it.getString(it.getColumnIndex("CLOUD_TYPE")), CoreMatchers.`is`(CloudType.S3.name))
726+
Assert.assertThat(it.getInt(it.getColumnIndex("POSITION")), CoreMatchers.`is`(1))
727+
Assert.assertThat(it.getInt(it.getColumnIndex("FORMAT")), CoreMatchers.`is`(8))
728+
Assert.assertThat(it.getInt(it.getColumnIndex("SHORTENING_THRESHOLD")), CoreMatchers.`is`(4))
729+
}
730+
731+
Sql.query("VAULT_ENTITY").where("_id", Sql.eq(2)).executeOn(db).use {
732+
it.moveToFirst()
733+
Assert.assertNull(it.getString(it.getColumnIndex("PASSWORD")))
734+
Assert.assertNull(it.getString(it.getColumnIndex("PASSWORD_CRYPTO_MODE")))
735+
736+
Assert.assertThat(it.getString(it.getColumnIndex("FOLDER_PATH")), CoreMatchers.`is`("path2"))
737+
Assert.assertThat(it.getString(it.getColumnIndex("FOLDER_NAME")), CoreMatchers.`is`("name"))
738+
Assert.assertThat(it.getString(it.getColumnIndex("CLOUD_TYPE")), CoreMatchers.`is`(CloudType.S3.name))
739+
Assert.assertThat(it.getInt(it.getColumnIndex("POSITION")), CoreMatchers.`is`(2))
740+
Assert.assertThat(it.getInt(it.getColumnIndex("FORMAT")), CoreMatchers.`is`(8))
741+
Assert.assertThat(it.getInt(it.getColumnIndex("SHORTENING_THRESHOLD")), CoreMatchers.`is`(4))
742+
}
743+
}
744+
745+
@Test
746+
fun upgrade12To13DropGoogleDriveUsernameInAccessToken() {
747+
Upgrade0To1().applyTo(db, 0)
748+
Upgrade1To2().applyTo(db, 1)
749+
Upgrade2To3(context).applyTo(db, 2)
750+
Upgrade3To4().applyTo(db, 3)
751+
Upgrade4To5().applyTo(db, 4)
752+
Upgrade5To6().applyTo(db, 5)
753+
Upgrade6To7().applyTo(db, 6)
754+
Upgrade7To8().applyTo(db, 7)
755+
Upgrade8To9(sharedPreferencesHandler).applyTo(db, 8)
756+
Upgrade9To10(sharedPreferencesHandler).applyTo(db, 9)
757+
Upgrade10To11().applyTo(db, 10)
758+
Upgrade11To12(sharedPreferencesHandler).applyTo(db, 11)
759+
760+
Sql.insertInto("CLOUD_ENTITY") //
761+
.integer("_id", 15) //
762+
.text("TYPE", CloudType.GOOGLE_DRIVE.name) //
763+
.text("USERNAME", "username") //
764+
.text("ACCESS_TOKEN", "username") //
765+
.executeOn(db)
766+
767+
Upgrade12To13(context).applyTo(db, 12)
768+
769+
Sql.query("CLOUD_ENTITY").where("_id", Sql.eq(15)).executeOn(db).use {
770+
it.moveToFirst()
771+
Assert.assertNull(it.getString(it.getColumnIndex("ACCESS_TOKEN")))
772+
}
773+
}
774+
775+
@Test
776+
fun upgrade12To13MovingAccessTokenToUrlInLocalStorage() {
777+
Upgrade0To1().applyTo(db, 0)
778+
Upgrade1To2().applyTo(db, 1)
779+
Upgrade2To3(context).applyTo(db, 2)
780+
Upgrade3To4().applyTo(db, 3)
781+
Upgrade4To5().applyTo(db, 4)
782+
Upgrade5To6().applyTo(db, 5)
783+
Upgrade6To7().applyTo(db, 6)
784+
Upgrade7To8().applyTo(db, 7)
785+
Upgrade8To9(sharedPreferencesHandler).applyTo(db, 8)
786+
Upgrade9To10(sharedPreferencesHandler).applyTo(db, 9)
787+
Upgrade10To11().applyTo(db, 10)
788+
Upgrade11To12(sharedPreferencesHandler).applyTo(db, 11)
789+
790+
Sql.insertInto("CLOUD_ENTITY") //
791+
.integer("_id", 15) //
792+
.text("TYPE", CloudType.LOCAL.name) //
793+
.text("ACCESS_TOKEN", "testUrl3000") //
794+
.executeOn(db)
795+
796+
Upgrade12To13(context).applyTo(db, 12)
797+
798+
Sql.query("CLOUD_ENTITY").where("_id", Sql.eq(15)).executeOn(db).use {
799+
it.moveToFirst()
800+
Assert.assertThat(it.getString(it.getColumnIndex("URL")), CoreMatchers.`is`("testUrl3000"))
801+
Assert.assertNull(it.getString(it.getColumnIndex("ACCESS_TOKEN")))
802+
}
803+
}
804+
805+
@Test
806+
fun upgrade12To13Dropbox() {
807+
Upgrade0To1().applyTo(db, 0)
808+
Upgrade1To2().applyTo(db, 1)
809+
Upgrade2To3(context).applyTo(db, 2)
810+
Upgrade3To4().applyTo(db, 3)
811+
Upgrade4To5().applyTo(db, 4)
812+
Upgrade5To6().applyTo(db, 5)
813+
Upgrade6To7().applyTo(db, 6)
814+
Upgrade7To8().applyTo(db, 7)
815+
Upgrade8To9(sharedPreferencesHandler).applyTo(db, 8)
816+
Upgrade9To10(sharedPreferencesHandler).applyTo(db, 9)
817+
Upgrade10To11().applyTo(db, 10)
818+
Upgrade11To12(sharedPreferencesHandler).applyTo(db, 11)
819+
820+
val gcmCryptor = CredentialCryptor.getInstance(context, CryptoMode.GCM)
821+
val cbcCryptor = CredentialCryptor.getInstance(context, CryptoMode.CBC)
822+
823+
val accessTokenPlain = "accessToken"
824+
val accessTokenCiphertext = cbcCryptor.encrypt(accessTokenPlain)
825+
826+
Sql.insertInto("CLOUD_ENTITY") //
827+
.integer("_id", 15) //
828+
.text("TYPE", CloudType.DROPBOX.name) //
829+
.text("USERNAME", "username") //
830+
.text("ACCESS_TOKEN", accessTokenCiphertext) //
831+
.executeOn(db)
832+
833+
Upgrade12To13(context).applyTo(db, 12)
834+
835+
Sql.query("CLOUD_ENTITY").where("_id", Sql.eq(15)).executeOn(db).use {
836+
it.moveToFirst()
837+
Assert.assertThat(gcmCryptor.decrypt(it.getString(it.getColumnIndex("ACCESS_TOKEN"))), CoreMatchers.`is`(accessTokenPlain))
838+
Assert.assertThat(it.getString(it.getColumnIndex("ACCESS_TOKEN_CRYPTO_MODE")), CoreMatchers.`is`(CryptoMode.GCM.name))
839+
}
840+
}
841+
842+
843+
@Test
844+
fun upgrade12To13OneDrive() {
845+
Upgrade0To1().applyTo(db, 0)
846+
Upgrade1To2().applyTo(db, 1)
847+
Upgrade2To3(context).applyTo(db, 2)
848+
Upgrade3To4().applyTo(db, 3)
849+
Upgrade4To5().applyTo(db, 4)
850+
Upgrade5To6().applyTo(db, 5)
851+
Upgrade6To7().applyTo(db, 6)
852+
Upgrade7To8().applyTo(db, 7)
853+
Upgrade8To9(sharedPreferencesHandler).applyTo(db, 8)
854+
Upgrade9To10(sharedPreferencesHandler).applyTo(db, 9)
855+
Upgrade10To11().applyTo(db, 10)
856+
Upgrade11To12(sharedPreferencesHandler).applyTo(db, 11)
857+
858+
val gcmCryptor = CredentialCryptor.getInstance(context, CryptoMode.GCM)
859+
val cbcCryptor = CredentialCryptor.getInstance(context, CryptoMode.CBC)
860+
861+
val accessTokenPlain = "accessToken"
862+
val accessTokenCiphertext = cbcCryptor.encrypt(accessTokenPlain)
863+
864+
Sql.insertInto("CLOUD_ENTITY") //
865+
.integer("_id", 15) //
866+
.text("TYPE", CloudType.ONEDRIVE.name) //
867+
.text("USERNAME", "username") //
868+
.text("ACCESS_TOKEN", accessTokenCiphertext) //
869+
.executeOn(db)
870+
871+
Upgrade12To13(context).applyTo(db, 12)
872+
873+
Sql.query("CLOUD_ENTITY").where("_id", Sql.eq(15)).executeOn(db).use {
874+
it.moveToFirst()
875+
Assert.assertThat(gcmCryptor.decrypt(it.getString(it.getColumnIndex("ACCESS_TOKEN"))), CoreMatchers.`is`(accessTokenPlain))
876+
Assert.assertThat(it.getString(it.getColumnIndex("ACCESS_TOKEN_CRYPTO_MODE")), CoreMatchers.`is`(CryptoMode.GCM.name))
877+
}
878+
}
879+
880+
@Test
881+
fun upgrade12To13PCloud() {
882+
Upgrade0To1().applyTo(db, 0)
883+
Upgrade1To2().applyTo(db, 1)
884+
Upgrade2To3(context).applyTo(db, 2)
885+
Upgrade3To4().applyTo(db, 3)
886+
Upgrade4To5().applyTo(db, 4)
887+
Upgrade5To6().applyTo(db, 5)
888+
Upgrade6To7().applyTo(db, 6)
889+
Upgrade7To8().applyTo(db, 7)
890+
Upgrade8To9(sharedPreferencesHandler).applyTo(db, 8)
891+
Upgrade9To10(sharedPreferencesHandler).applyTo(db, 9)
892+
Upgrade10To11().applyTo(db, 10)
893+
Upgrade11To12(sharedPreferencesHandler).applyTo(db, 11)
894+
895+
val gcmCryptor = CredentialCryptor.getInstance(context, CryptoMode.GCM)
896+
val cbcCryptor = CredentialCryptor.getInstance(context, CryptoMode.CBC)
897+
898+
val accessTokenPlain = "accessToken"
899+
val accessTokenCiphertext = cbcCryptor.encrypt(accessTokenPlain)
900+
901+
Sql.insertInto("CLOUD_ENTITY") //
902+
.integer("_id", 15) //
903+
.text("TYPE", CloudType.PCLOUD.name) //
904+
.text("USERNAME", "username") //
905+
.text("ACCESS_TOKEN", accessTokenCiphertext) //
906+
.text("URL", "url") //
907+
.executeOn(db)
908+
909+
Upgrade12To13(context).applyTo(db, 12)
910+
911+
Sql.query("CLOUD_ENTITY").where("_id", Sql.eq(15)).executeOn(db).use {
912+
it.moveToFirst()
913+
Assert.assertThat(gcmCryptor.decrypt(it.getString(it.getColumnIndex("ACCESS_TOKEN"))), CoreMatchers.`is`(accessTokenPlain))
914+
Assert.assertThat(it.getString(it.getColumnIndex("ACCESS_TOKEN_CRYPTO_MODE")), CoreMatchers.`is`(CryptoMode.GCM.name))
915+
}
916+
}
917+
918+
@Test
919+
fun upgrade12To13Webdav() {
920+
Upgrade0To1().applyTo(db, 0)
921+
Upgrade1To2().applyTo(db, 1)
922+
Upgrade2To3(context).applyTo(db, 2)
923+
Upgrade3To4().applyTo(db, 3)
924+
Upgrade4To5().applyTo(db, 4)
925+
Upgrade5To6().applyTo(db, 5)
926+
Upgrade6To7().applyTo(db, 6)
927+
Upgrade7To8().applyTo(db, 7)
928+
Upgrade8To9(sharedPreferencesHandler).applyTo(db, 8)
929+
Upgrade9To10(sharedPreferencesHandler).applyTo(db, 9)
930+
Upgrade10To11().applyTo(db, 10)
931+
Upgrade11To12(sharedPreferencesHandler).applyTo(db, 11)
932+
933+
val gcmCryptor = CredentialCryptor.getInstance(context, CryptoMode.GCM)
934+
val cbcCryptor = CredentialCryptor.getInstance(context, CryptoMode.CBC)
935+
936+
val accessTokenPlain = "accessToken"
937+
val accessTokenCiphertext = cbcCryptor.encrypt(accessTokenPlain)
938+
939+
Sql.insertInto("CLOUD_ENTITY") //
940+
.integer("_id", 15) //
941+
.text("TYPE", CloudType.WEBDAV.name) //
942+
.text("USERNAME", "username") //
943+
.text("ACCESS_TOKEN", accessTokenCiphertext) //
944+
.text("URL", "url") //
945+
.executeOn(db)
946+
947+
Upgrade12To13(context).applyTo(db, 12)
948+
949+
Sql.query("CLOUD_ENTITY").where("_id", Sql.eq(15)).executeOn(db).use {
950+
it.moveToFirst()
951+
Assert.assertThat(gcmCryptor.decrypt(it.getString(it.getColumnIndex("ACCESS_TOKEN"))), CoreMatchers.`is`(accessTokenPlain))
952+
Assert.assertThat(it.getString(it.getColumnIndex("ACCESS_TOKEN_CRYPTO_MODE")), CoreMatchers.`is`(CryptoMode.GCM.name))
953+
}
954+
}
646955
}

0 commit comments

Comments
 (0)