Skip to content

Commit

Permalink
Show specific error in Hub unlock on pre Android 12
Browse files Browse the repository at this point in the history
  • Loading branch information
SailReal committed Dec 23, 2024
1 parent edf0248 commit 9a4bc00
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import org.cryptomator.cryptolib.api.CryptorProvider
import org.cryptomator.domain.KeyLoadingStrategy
import org.cryptomator.domain.UnverifiedHubVaultConfig
import org.cryptomator.domain.UnverifiedVaultConfig
import org.cryptomator.domain.exception.vaultconfig.HubNotSupportedOnPreAndroid31Exception
import org.cryptomator.domain.exception.vaultconfig.VaultConfigLoadException
import org.cryptomator.domain.exception.vaultconfig.VaultKeyInvalidException
import org.cryptomator.domain.exception.vaultconfig.VaultVersionMismatchException
Expand Down Expand Up @@ -92,6 +93,9 @@ class VaultConfig private constructor(builder: VaultConfigBuilder) {
return when (KeyLoadingStrategy.fromKeyId(keyId)) {
KeyLoadingStrategy.MASTERKEY -> UnverifiedVaultConfig(token, keyId, vaultFormat)
KeyLoadingStrategy.HUB -> {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.S) {
throw HubNotSupportedOnPreAndroid31Exception()
}
val hubClaim = unverifiedJwt.getHeaderClaim("hub").asMap()
val clientId = hubClaim["clientId"] as? String ?: throw VaultConfigLoadException("Missing or invalid 'clientId' claim in JWT header")
val authEndpoint = parseUri(hubClaim, "authEndpoint")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,13 @@
@Singleton
public class HubRepositoryImpl implements HubRepository {

private final OkHttpClient httpClient;
private final HubDeviceCryptor hubDeviceCryptor;
private final Context context;
private OkHttpClient httpClient;
private HubDeviceCryptor hubDeviceCryptor;

@Inject
public HubRepositoryImpl(Context context) {
this.httpClient = new OkHttpClient.Builder() //
.addInterceptor(httpLoggingInterceptor(context)) //
.connectTimeout(NetworkTimeout.CONNECTION.getTimeout(), NetworkTimeout.CONNECTION.getUnit()) //
.readTimeout(NetworkTimeout.READ.getTimeout(), NetworkTimeout.READ.getUnit()) //
.writeTimeout(NetworkTimeout.WRITE.getTimeout(), NetworkTimeout.WRITE.getUnit()) //
.build();
this.hubDeviceCryptor = HubDeviceCryptor.getInstance();
this.context = context;
}

private Interceptor httpLoggingInterceptor(Context context) {
Expand All @@ -65,7 +60,7 @@ public String getVaultKeyJwe(UnverifiedHubVaultConfig unverifiedHubVaultConfig,
.header("Authorization", "Bearer " + accessToken) //
.url(unverifiedHubVaultConfig.getApiBaseUrl() + "vaults/" + unverifiedHubVaultConfig.vaultId() + "/access-token") //
.build();
try (var response = httpClient.newCall(request).execute()) {
try (var response = getHttpClient().newCall(request).execute()) {
switch (response.code()) {
case HttpURLConnection.HTTP_OK:
if (response.body() != null) {
Expand Down Expand Up @@ -95,7 +90,7 @@ public UserDto getUser(UnverifiedHubVaultConfig unverifiedHubVaultConfig, String
.header("Authorization", "Bearer " + accessToken) //
.url(unverifiedHubVaultConfig.getApiBaseUrl() + "users/me") //
.build();
try (var response = httpClient.newCall(request).execute()) {
try (var response = getHttpClient().newCall(request).execute()) {
if (response.code() == HttpURLConnection.HTTP_OK) {
if (response.body() != null) {
JSONObject jsonObject = new JSONObject(response.body().string());
Expand All @@ -121,8 +116,8 @@ public UserDto getUser(UnverifiedHubVaultConfig unverifiedHubVaultConfig, String
public DeviceDto getDevice(UnverifiedHubVaultConfig unverifiedHubVaultConfig, String accessToken) throws BackendException {
var request = new Request.Builder().get() //
.header("Authorization", "Bearer " + accessToken) //
.url(unverifiedHubVaultConfig.getApiBaseUrl() + "devices/" + hubDeviceCryptor.getDeviceId()).build();
try (var response = httpClient.newCall(request).execute()) {
.url(unverifiedHubVaultConfig.getApiBaseUrl() + "devices/" + getHubDeviceCryptor().getDeviceId()).build();
try (var response = getHttpClient().newCall(request).execute()) {
switch (response.code()) {
case HttpURLConnection.HTTP_OK:
if (response.body() != null) {
Expand All @@ -143,12 +138,12 @@ public DeviceDto getDevice(UnverifiedHubVaultConfig unverifiedHubVaultConfig, St

@Override
public void createDevice(UnverifiedHubVaultConfig unverifiedHubVaultConfig, String accessToken, String deviceName, String setupCode, String userPrivateKey) throws BackendException {
var deviceId = hubDeviceCryptor.getDeviceId();
var devicePublicKey = hubDeviceCryptor.getDevicePublicKeyEncoded();
var deviceId = getHubDeviceCryptor().getDeviceId();
var devicePublicKey = getHubDeviceCryptor().getDevicePublicKeyEncoded();
var publicKey = BaseEncoding.base64().encode(devicePublicKey);
JWEObject encryptedUserKey;
try {
encryptedUserKey = hubDeviceCryptor.reEncryptUserKey(JWEObject.parse(userPrivateKey), setupCode);
encryptedUserKey = getHubDeviceCryptor().reEncryptUserKey(JWEObject.parse(userPrivateKey), setupCode);
} catch (HubDeviceCryptor.InvalidJweKeyException e) {
throw new HubInvalidSetupCodeException(e);
} catch (ParseException e) {
Expand All @@ -171,7 +166,7 @@ public void createDevice(UnverifiedHubVaultConfig unverifiedHubVaultConfig, Stri
.header("Authorization", "Bearer " + accessToken) //
.url(unverifiedHubVaultConfig.getApiBaseUrl() + "devices/" + deviceId) //
.build();
try (var response = httpClient.newCall(request).execute()) {
try (var response = getHttpClient().newCall(request).execute()) {
switch (response.code()) {
case HttpURLConnection.HTTP_CREATED:
Timber.tag("HubRepositoryImpl").i("Device created");
Expand All @@ -191,7 +186,7 @@ public ConfigDto getConfig(UnverifiedHubVaultConfig unverifiedHubVaultConfig, St
var request = new Request.Builder().get() //
.header("Authorization", "Bearer " + accessToken) //
.url(unverifiedHubVaultConfig.getApiBaseUrl() + "config").build();
try (var response = httpClient.newCall(request).execute()) {
try (var response = getHttpClient().newCall(request).execute()) {
if (response.code() == HttpURLConnection.HTTP_OK) {
if (response.body() != null) {
JSONObject jsonObject = new JSONObject(response.body().string());
Expand All @@ -206,4 +201,23 @@ public ConfigDto getConfig(UnverifiedHubVaultConfig unverifiedHubVaultConfig, St
throw new FatalBackendException("Failed to load device", e);
}
}

private HubDeviceCryptor getHubDeviceCryptor() {
if (hubDeviceCryptor == null) {
hubDeviceCryptor = HubDeviceCryptor.getInstance();
}
return hubDeviceCryptor;
}

private OkHttpClient getHttpClient() {
if (httpClient == null) {
httpClient = new OkHttpClient.Builder() //
.addInterceptor(httpLoggingInterceptor(context)) //
.connectTimeout(NetworkTimeout.CONNECTION.getTimeout(), NetworkTimeout.CONNECTION.getUnit()) //
.readTimeout(NetworkTimeout.READ.getTimeout(), NetworkTimeout.READ.getUnit()) //
.writeTimeout(NetworkTimeout.WRITE.getTimeout(), NetworkTimeout.WRITE.getUnit()) //
.build();
}
return httpClient;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.cryptomator.domain.exception.vaultconfig;

import org.cryptomator.domain.exception.BackendException;

public class HubNotSupportedOnPreAndroid31Exception extends BackendException {

public HubNotSupportedOnPreAndroid31Exception() {
super();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import org.cryptomator.domain.exception.license.LicenseNotValidException
import org.cryptomator.domain.exception.license.NoLicenseAvailableException
import org.cryptomator.domain.exception.update.GeneralUpdateErrorException
import org.cryptomator.domain.exception.update.HashMismatchUpdateCheckException
import org.cryptomator.domain.exception.vaultconfig.HubNotSupportedOnPreAndroid31Exception
import org.cryptomator.domain.exception.vaultconfig.MissingVaultConfigFileException
import org.cryptomator.domain.exception.vaultconfig.UnsupportedMasterkeyLocationException
import org.cryptomator.domain.exception.vaultconfig.VaultConfigLoadException
Expand Down Expand Up @@ -55,6 +56,7 @@ class ExceptionHandlers @Inject constructor(private val context: Context, defaul
staticHandler(LicenseNotValidException::class.java, R.string.dialog_enter_license_not_valid_content)
staticHandler(NoLicenseAvailableException::class.java, R.string.dialog_enter_license_no_content)
staticHandler(HashMismatchUpdateCheckException::class.java, R.string.error_hash_mismatch_update)
staticHandler(HubNotSupportedOnPreAndroid31Exception::class.java, R.string.error_hub_unlock_pre_31)
staticHandler(GeneralUpdateErrorException::class.java, R.string.error_general_update)
staticHandler(
MissingVaultConfigFileException::class.java, String.format(
Expand Down
1 change: 1 addition & 0 deletions presentation/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
<string name="error_hub_device_already_register_for_other_user">This device is already registered for a different user. Try to change the user account or use a different device.</string>
<string name="error_hub_invalid_setup_code">The Account Key is invalid.</string>
<string name="error_hub_invalid_version">Unsupported Hub version.</string>
<string name="error_hub_unlock_pre_31">Hub is only supported on Android 12 and above.</string>

<!-- # clouds -->

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ public class HubDeviceCryptor {
private final KeyStore keyStore;

HubDeviceCryptor(KeyStore keyStore) {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.S) {
throw new IllegalStateException("Hub unlock is only supported for devices using Android >= 12");
}
try {
this.keyStore = keyStore;
this.keyStore.load(null);
Expand Down

0 comments on commit 9a4bc00

Please sign in to comment.