mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-23 04:28:35 +00:00
Fix incorrect registration challenge handling when requesting verification codes.
This commit is contained in:
@@ -5,19 +5,17 @@
|
|||||||
|
|
||||||
package org.thoughtcrime.securesms.registration.data.network
|
package org.thoughtcrime.securesms.registration.data.network
|
||||||
|
|
||||||
import okio.IOException
|
|
||||||
import org.signal.core.util.logging.Log
|
import org.signal.core.util.logging.Log
|
||||||
import org.thoughtcrime.securesms.registration.data.RegistrationRepository
|
import org.thoughtcrime.securesms.registration.data.RegistrationRepository
|
||||||
import org.whispersystems.signalservice.api.NetworkResult
|
import org.whispersystems.signalservice.api.NetworkResult
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.AlreadyVerifiedException
|
import org.whispersystems.signalservice.api.push.exceptions.AlreadyVerifiedException
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.CaptchaRequiredException
|
import org.whispersystems.signalservice.api.push.exceptions.ChallengeRequiredException
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.ExternalServiceFailureException
|
import org.whispersystems.signalservice.api.push.exceptions.ExternalServiceFailureException
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.ImpossiblePhoneNumberException
|
import org.whispersystems.signalservice.api.push.exceptions.ImpossiblePhoneNumberException
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.InvalidTransportModeException
|
import org.whispersystems.signalservice.api.push.exceptions.InvalidTransportModeException
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.MalformedRequestException
|
import org.whispersystems.signalservice.api.push.exceptions.MalformedRequestException
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.NoSuchSessionException
|
import org.whispersystems.signalservice.api.push.exceptions.NoSuchSessionException
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.NonNormalizedPhoneNumberException
|
import org.whispersystems.signalservice.api.push.exceptions.NonNormalizedPhoneNumberException
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.PushChallengeRequiredException
|
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.RateLimitException
|
import org.whispersystems.signalservice.api.push.exceptions.RateLimitException
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.RegistrationRetryException
|
import org.whispersystems.signalservice.api.push.exceptions.RegistrationRetryException
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.TokenNotAcceptedException
|
import org.whispersystems.signalservice.api.push.exceptions.TokenNotAcceptedException
|
||||||
@@ -26,7 +24,6 @@ import org.whispersystems.signalservice.internal.push.AuthCredentials
|
|||||||
import org.whispersystems.signalservice.internal.push.LockedException
|
import org.whispersystems.signalservice.internal.push.LockedException
|
||||||
import org.whispersystems.signalservice.internal.push.RegistrationSessionMetadataJson
|
import org.whispersystems.signalservice.internal.push.RegistrationSessionMetadataJson
|
||||||
import org.whispersystems.signalservice.internal.push.RegistrationSessionMetadataResponse
|
import org.whispersystems.signalservice.internal.push.RegistrationSessionMetadataResponse
|
||||||
import org.whispersystems.signalservice.internal.util.JsonUtil
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a processor to map a [RegistrationSessionMetadataResponse] to all the known outcomes.
|
* This is a processor to map a [RegistrationSessionMetadataResponse] to all the known outcomes.
|
||||||
@@ -61,8 +58,7 @@ sealed class VerificationCodeRequestResult(cause: Throwable?) : RegistrationResu
|
|||||||
is NetworkResult.NetworkError -> UnknownError(networkResult.exception)
|
is NetworkResult.NetworkError -> UnknownError(networkResult.exception)
|
||||||
is NetworkResult.StatusCodeError -> {
|
is NetworkResult.StatusCodeError -> {
|
||||||
when (val cause = networkResult.exception) {
|
when (val cause = networkResult.exception) {
|
||||||
is PushChallengeRequiredException -> createChallengeRequiredProcessor(networkResult)
|
is ChallengeRequiredException -> createChallengeRequiredProcessor(cause.response)
|
||||||
is CaptchaRequiredException -> createChallengeRequiredProcessor(networkResult)
|
|
||||||
is RateLimitException -> createRateLimitProcessor(cause)
|
is RateLimitException -> createRateLimitProcessor(cause)
|
||||||
is ImpossiblePhoneNumberException -> ImpossibleNumber(cause)
|
is ImpossiblePhoneNumberException -> ImpossibleNumber(cause)
|
||||||
is NonNormalizedPhoneNumberException -> NonNormalizedNumber(cause = cause, originalNumber = cause.originalNumber, normalizedNumber = cause.normalizedNumber)
|
is NonNormalizedPhoneNumberException -> NonNormalizedNumber(cause = cause, originalNumber = cause.originalNumber, normalizedNumber = cause.normalizedNumber)
|
||||||
@@ -80,19 +76,8 @@ sealed class VerificationCodeRequestResult(cause: Throwable?) : RegistrationResu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createChallengeRequiredProcessor(errorResult: NetworkResult.StatusCodeError<RegistrationSessionMetadataResponse>): VerificationCodeRequestResult {
|
private fun createChallengeRequiredProcessor(response: RegistrationSessionMetadataJson): VerificationCodeRequestResult {
|
||||||
if (errorResult.stringBody == null) {
|
|
||||||
Log.w(TAG, "Attempted to parse error body with response code ${errorResult.code} for list of requested information, but body was null.")
|
|
||||||
return UnknownError(errorResult.exception)
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
val response = JsonUtil.fromJson(errorResult.stringBody, RegistrationSessionMetadataJson::class.java)
|
|
||||||
return ChallengeRequired(Challenge.parse(response.requestedInformation))
|
return ChallengeRequired(Challenge.parse(response.requestedInformation))
|
||||||
} catch (parseException: IOException) {
|
|
||||||
Log.w(TAG, "Attempted to parse error body for list of requested information, but encountered exception.", parseException)
|
|
||||||
return UnknownError(parseException)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createRateLimitProcessor(exception: RateLimitException): VerificationCodeRequestResult {
|
private fun createRateLimitProcessor(exception: RateLimitException): VerificationCodeRequestResult {
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
package org.whispersystems.signalservice.api.push.exceptions;
|
|
||||||
|
|
||||||
public class CaptchaRequiredException extends NonSuccessfulResponseCodeException {
|
|
||||||
public CaptchaRequiredException() {
|
|
||||||
super(402);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025 Signal Messenger, LLC
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.whispersystems.signalservice.api.push.exceptions
|
||||||
|
|
||||||
|
import org.whispersystems.signalservice.internal.push.RegistrationSessionMetadataJson
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We tried to do something on registration endpoints that didn't go well, so now we have to do a challenge. And not a
|
||||||
|
* fun one involving ice buckets.
|
||||||
|
*/
|
||||||
|
class ChallengeRequiredException(val response: RegistrationSessionMetadataJson) : NonSuccessfulResponseCodeException(409)
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
package org.whispersystems.signalservice.api.push.exceptions
|
|
||||||
|
|
||||||
class PushChallengeRequiredException : NonSuccessfulResponseCodeException(409)
|
|
||||||
@@ -84,7 +84,7 @@ import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
|||||||
import org.whispersystems.signalservice.api.push.SignedPreKeyEntity;
|
import org.whispersystems.signalservice.api.push.SignedPreKeyEntity;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.AlreadyVerifiedException;
|
import org.whispersystems.signalservice.api.push.exceptions.AlreadyVerifiedException;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
|
import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.CaptchaRequiredException;
|
import org.whispersystems.signalservice.api.push.exceptions.ChallengeRequiredException;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.ConflictException;
|
import org.whispersystems.signalservice.api.push.exceptions.ConflictException;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.ContactManifestMismatchException;
|
import org.whispersystems.signalservice.api.push.exceptions.ContactManifestMismatchException;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException;
|
import org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException;
|
||||||
@@ -103,7 +103,6 @@ import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulRespons
|
|||||||
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResumableUploadResponseCodeException;
|
import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResumableUploadResponseCodeException;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.NotFoundException;
|
import org.whispersystems.signalservice.api.push.exceptions.NotFoundException;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException;
|
import org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.PushChallengeRequiredException;
|
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.RangeException;
|
import org.whispersystems.signalservice.api.push.exceptions.RangeException;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.RateLimitException;
|
import org.whispersystems.signalservice.api.push.exceptions.RateLimitException;
|
||||||
@@ -3155,10 +3154,8 @@ public class PushServiceSocket {
|
|||||||
}
|
}
|
||||||
if (response.getVerified()) {
|
if (response.getVerified()) {
|
||||||
throw new AlreadyVerifiedException();
|
throw new AlreadyVerifiedException();
|
||||||
} else if (response.pushChallengedRequired()) {
|
} else if (response.pushChallengedRequired() || response.captchaRequired()) {
|
||||||
throw new PushChallengeRequiredException();
|
throw new ChallengeRequiredException(response);
|
||||||
} else if (response.captchaRequired()) {
|
|
||||||
throw new CaptchaRequiredException();
|
|
||||||
} else {
|
} else {
|
||||||
Log.i(TAG, "Received 409 in reg session handler that is not verified, with required information: " + String.join(", ", response.getRequestedInformation()));
|
Log.i(TAG, "Received 409 in reg session handler that is not verified, with required information: " + String.join(", ", response.getRequestedInformation()));
|
||||||
throw new HttpConflictException();
|
throw new HttpConflictException();
|
||||||
@@ -3198,10 +3195,8 @@ public class PushServiceSocket {
|
|||||||
}
|
}
|
||||||
if (response.getVerified()) {
|
if (response.getVerified()) {
|
||||||
throw new AlreadyVerifiedException();
|
throw new AlreadyVerifiedException();
|
||||||
} else if (response.pushChallengedRequired()) {
|
} else if (response.pushChallengedRequired() || response.captchaRequired()) {
|
||||||
throw new PushChallengeRequiredException();
|
throw new ChallengeRequiredException(response);
|
||||||
} else if (response.captchaRequired()) {
|
|
||||||
throw new CaptchaRequiredException();
|
|
||||||
} else {
|
} else {
|
||||||
Log.i(TAG, "Received 409 in for reg code request that is not verified, with required information: " + String.join(", ", response.getRequestedInformation()));
|
Log.i(TAG, "Received 409 in for reg code request that is not verified, with required information: " + String.join(", ", response.getRequestedInformation()));
|
||||||
throw new HttpConflictException();
|
throw new HttpConflictException();
|
||||||
@@ -3243,10 +3238,8 @@ public class PushServiceSocket {
|
|||||||
}
|
}
|
||||||
if (response.getVerified()) {
|
if (response.getVerified()) {
|
||||||
throw new AlreadyVerifiedException();
|
throw new AlreadyVerifiedException();
|
||||||
} else if (response.pushChallengedRequired()) {
|
} else if (response.pushChallengedRequired() || response.captchaRequired()) {
|
||||||
throw new PushChallengeRequiredException();
|
throw new ChallengeRequiredException(response);
|
||||||
} else if (response.captchaRequired()) {
|
|
||||||
throw new CaptchaRequiredException();
|
|
||||||
} else {
|
} else {
|
||||||
Log.i(TAG, "Received 409 for patching reg session that is not verified, with required information: " + String.join(", ", response.getRequestedInformation()));
|
Log.i(TAG, "Received 409 for patching reg session that is not verified, with required information: " + String.join(", ", response.getRequestedInformation()));
|
||||||
throw new HttpConflictException();
|
throw new HttpConflictException();
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package org.whispersystems.signalservice.internal.websocket;
|
|||||||
|
|
||||||
|
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
|
import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.CaptchaRequiredException;
|
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException;
|
import org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.ExpectationFailedException;
|
import org.whispersystems.signalservice.api.push.exceptions.ExpectationFailedException;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.MalformedResponseException;
|
import org.whispersystems.signalservice.api.push.exceptions.MalformedResponseException;
|
||||||
@@ -12,7 +11,6 @@ import org.whispersystems.signalservice.api.push.exceptions.NotFoundException;
|
|||||||
import org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException;
|
import org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.RateLimitException;
|
import org.whispersystems.signalservice.api.push.exceptions.RateLimitException;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException;
|
import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException;
|
||||||
import org.whispersystems.signalservice.internal.push.AuthCredentials;
|
|
||||||
import org.whispersystems.signalservice.internal.push.DeviceLimit;
|
import org.whispersystems.signalservice.internal.push.DeviceLimit;
|
||||||
import org.whispersystems.signalservice.internal.push.DeviceLimitExceededException;
|
import org.whispersystems.signalservice.internal.push.DeviceLimitExceededException;
|
||||||
import org.whispersystems.signalservice.internal.push.LockedException;
|
import org.whispersystems.signalservice.internal.push.LockedException;
|
||||||
@@ -81,8 +79,6 @@ public final class DefaultErrorMapper implements ErrorMapper {
|
|||||||
case 401:
|
case 401:
|
||||||
case 403:
|
case 403:
|
||||||
return new AuthorizationFailedException(status, "Authorization failed!");
|
return new AuthorizationFailedException(status, "Authorization failed!");
|
||||||
case 402:
|
|
||||||
return new CaptchaRequiredException();
|
|
||||||
case 404:
|
case 404:
|
||||||
return new NotFoundException("Not found");
|
return new NotFoundException("Not found");
|
||||||
case 409:
|
case 409:
|
||||||
|
|||||||
Reference in New Issue
Block a user