Support multiple sequential captcha challenges.

main
Nicholas 2023-03-03 09:51:27 -05:00 zatwierdzone przez GitHub
rodzic 89ad213994
commit d1d73fef30
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
5 zmienionych plików z 53 dodań i 2 usunięć

Wyświetl plik

@ -8,6 +8,7 @@ import org.whispersystems.signalservice.api.push.exceptions.MustRequestNewCodeEx
import org.whispersystems.signalservice.api.push.exceptions.NoSuchSessionException
import org.whispersystems.signalservice.api.push.exceptions.NonNormalizedPhoneNumberException
import org.whispersystems.signalservice.api.push.exceptions.RateLimitException
import org.whispersystems.signalservice.api.push.exceptions.TokenNotAcceptedException
import org.whispersystems.signalservice.api.util.Preconditions
import org.whispersystems.signalservice.internal.ServiceResponse
import org.whispersystems.signalservice.internal.ServiceResponseProcessor
@ -41,6 +42,10 @@ sealed class RegistrationSessionProcessor(response: ServiceResponse<Registration
return PUSH_CHALLENGE_KEY == getChallenge()
}
fun isTokenRejected(): Boolean {
return error is TokenNotAcceptedException
}
fun isImpossibleNumber(): Boolean {
return error is ImpossiblePhoneNumberException
}

Wyświetl plik

@ -299,6 +299,9 @@ public final class EnterPhoneNumberFragment extends LoggingFragment implements R
String.format(getString(R.string.RegistrationActivity_the_number_you_specified_s_is_invalid), viewModel.getNumber().getFullFormattedNumber()));
} else if (processor.isNonNormalizedNumber()) {
handleNonNormalizedNumberError(processor.getOriginalNumber(), processor.getNormalizedNumber(), mode);
} else if (processor.isTokenRejected()) {
Log.i(TAG, "The server did not accept the information.", processor.getError());
showErrorDialog(register.getContext(), getString(R.string.RegistrationActivity_we_need_to_verify_that_youre_human));
} else {
Log.i(TAG, "Unknown error during verification code request", processor.getError());
showErrorDialog(register.getContext(), getString(R.string.RegistrationActivity_unable_to_connect_to_service));

Wyświetl plik

@ -10,6 +10,7 @@ import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.pin.KbsRepository;
import org.thoughtcrime.securesms.pin.TokenData;
@ -36,6 +37,8 @@ import io.reactivex.rxjava3.core.Single;
*/
public abstract class BaseRegistrationViewModel extends ViewModel {
private static final String TAG = Log.tag(BaseRegistrationViewModel.class);
private static final String STATE_NUMBER = "NUMBER";
private static final String STATE_REGISTRATION_SECRET = "REGISTRATION_SECRET";
private static final String STATE_VERIFICATION_CODE = "TEXT_CODE_ENTERED";
@ -280,10 +283,14 @@ public abstract class BaseRegistrationViewModel extends ViewModel {
}
if (hasCaptchaToken() && processor.captchaRequired()) {
return verifyAccountRepository.verifyCaptcha(sessionId, Objects.requireNonNull(getCaptchaToken()), e164, getRegistrationSecret())
Log.d(TAG, "Submitting completed captcha challenge");
final String captcha = Objects.requireNonNull(getCaptchaToken());
clearCaptchaResponse();
return verifyAccountRepository.verifyCaptcha(sessionId, captcha, e164, getRegistrationSecret())
.map(RegistrationSessionProcessor.RegistrationSessionProcessorForSession::new);
} else {
String challenge = processor.getChallenge();
Log.d(TAG, "Handling challenge of type " + challenge);
if (challenge != null) {
switch (challenge) {
case RegistrationSessionProcessor.PUSH_CHALLENGE_KEY:

Wyświetl plik

@ -0,0 +1,6 @@
package org.whispersystems.signalservice.api.push.exceptions
/**
* Exception representing that the submitted information was not accepted (e.g. the push challenge token or captcha did not match)
*/
class TokenNotAcceptedException : NonSuccessfulResponseCodeException(403)

Wyświetl plik

@ -86,6 +86,7 @@ import org.whispersystems.signalservice.api.push.exceptions.RateLimitException;
import org.whispersystems.signalservice.api.push.exceptions.RemoteAttestationResponseExpiredException;
import org.whispersystems.signalservice.api.push.exceptions.ResumeLocationInvalidException;
import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException;
import org.whispersystems.signalservice.api.push.exceptions.TokenNotAcceptedException;
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
import org.whispersystems.signalservice.api.push.exceptions.UsernameIsNotAssociatedWithAnAccountException;
import org.whispersystems.signalservice.api.push.exceptions.UsernameIsNotReservedException;
@ -348,7 +349,7 @@ public class PushServiceSocket {
String path = VERIFICATION_SESSION_PATH + "/" + sessionId;
final UpdateVerificationSessionRequestBody requestBody = new UpdateVerificationSessionRequestBody(captchaToken, pushToken, pushChallengeToken, mcc, mnc);
try (Response response = makeServiceRequest(path, "PATCH", jsonRequestBody(JsonUtil.toJson(requestBody)), NO_HEADERS, new RegistrationSessionResponseHandler(), Optional.empty(), false)) {
try (Response response = makeServiceRequest(path, "PATCH", jsonRequestBody(JsonUtil.toJson(requestBody)), NO_HEADERS, new PatchRegistrationSessionResponseHandler(), Optional.empty(), false)) {
return parseSessionMetadataResponse(response);
}
}
@ -2543,6 +2544,35 @@ public class PushServiceSocket {
}
}
private static class PatchRegistrationSessionResponseHandler implements ResponseCodeHandler {
@Override
public void handle(int responseCode, ResponseBody body) throws NonSuccessfulResponseCodeException, PushNetworkException {
switch (responseCode) {
case 403:
throw new TokenNotAcceptedException();
case 404:
throw new NoSuchSessionException();
case 409:
RegistrationSessionMetadataJson response;
try {
response = JsonUtil.fromJson(body.string(), RegistrationSessionMetadataJson.class);
} catch (IOException e) {
Log.e(TAG, "Unable to read response body.", e);
throw new NonSuccessfulResponseCodeException(409);
}
if (response.pushChallengedRequired()) {
throw new PushChallengeRequiredException();
} else if (response.captchaRequired()) {
throw new CaptchaRequiredException();
} else {
throw new HttpConflictException();
}
}
}
}
private static class RegistrationCodeRequestResponseHandler implements ResponseCodeHandler {
@Override public void handle(int responseCode, ResponseBody body) throws NonSuccessfulResponseCodeException, PushNetworkException {
switch (responseCode) {