From e7f05eb60829f2cb85b2308fc501d2e691944e23 Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike Date: Thu, 30 Jul 2015 12:54:58 -0700 Subject: [PATCH] Be more careful with JSON processing of server responses. // FREEBIE --- .../internal/push/PushServiceSocket.java | 49 +++++++++++++------ .../textsecure/internal/util/JsonUtil.java | 20 +++----- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/java/src/main/java/org/whispersystems/textsecure/internal/push/PushServiceSocket.java b/java/src/main/java/org/whispersystems/textsecure/internal/push/PushServiceSocket.java index ebe7f35de0..fc5ca9a92c 100644 --- a/java/src/main/java/org/whispersystems/textsecure/internal/push/PushServiceSocket.java +++ b/java/src/main/java/org/whispersystems/textsecure/internal/push/PushServiceSocket.java @@ -17,6 +17,7 @@ package org.whispersystems.textsecure.internal.push; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; import org.apache.http.conn.ssl.StrictHostnameVerifier; import org.whispersystems.libaxolotl.IdentityKey; @@ -259,8 +260,6 @@ public class PushServiceSocket { } return bundles; - } catch (JsonUtil.JsonParseException e) { - throw new IOException(e); } catch (NotFoundException nfe) { throw new UnregisteredUserException(destination.getNumber(), nfe); } @@ -301,8 +300,6 @@ public class PushServiceSocket { return new PreKeyBundle(device.getRegistrationId(), device.getDeviceId(), preKeyId, preKey, signedPreKeyId, signedPreKey, signedPreKeySignature, response.getIdentityKey()); - } catch (JsonUtil.JsonParseException e) { - throw new IOException(e); } catch (NotFoundException nfe) { throw new UnregisteredUserException(destination.getNumber(), nfe); } @@ -359,11 +356,16 @@ public class PushServiceSocket { public List retrieveDirectory(Set contactTokens) throws NonSuccessfulResponseCodeException, PushNetworkException { - ContactTokenList contactTokenList = new ContactTokenList(new LinkedList<>(contactTokens)); - String response = makeRequest(DIRECTORY_TOKENS_PATH, "PUT", JsonUtil.toJson(contactTokenList)); - ContactTokenDetailsList activeTokens = JsonUtil.fromJson(response, ContactTokenDetailsList.class); + try { + ContactTokenList contactTokenList = new ContactTokenList(new LinkedList<>(contactTokens)); + String response = makeRequest(DIRECTORY_TOKENS_PATH, "PUT", JsonUtil.toJson(contactTokenList)); + ContactTokenDetailsList activeTokens = JsonUtil.fromJson(response, ContactTokenDetailsList.class); - return activeTokens.getContacts(); + return activeTokens.getContacts(); + } catch (IOException e) { + Log.w(TAG, e); + throw new NonSuccessfulResponseCodeException("Unable to parse entity"); + } } public ContactTokenDetails getContactTokenDetails(String contactToken) throws IOException { @@ -501,26 +503,45 @@ public class PushServiceSocket { connection.disconnect(); throw new NotFoundException("Not found"); case 409: + MismatchedDevices mismatchedDevices; + try { - response = Util.readFully(connection.getErrorStream()); + response = Util.readFully(connection.getErrorStream()); + mismatchedDevices = JsonUtil.fromJson(response, MismatchedDevices.class); + } catch (JsonProcessingException e) { + Log.w(TAG, e); + throw new NonSuccessfulResponseCodeException("Bad response: " + responseCode + " " + responseMessage); } catch (IOException e) { throw new PushNetworkException(e); } - throw new MismatchedDevicesException(JsonUtil.fromJson(response, MismatchedDevices.class)); + + throw new MismatchedDevicesException(mismatchedDevices); case 410: + StaleDevices staleDevices; + try { - response = Util.readFully(connection.getErrorStream()); + response = Util.readFully(connection.getErrorStream()); + staleDevices = JsonUtil.fromJson(response, StaleDevices.class); + } catch (JsonProcessingException e) { + throw new NonSuccessfulResponseCodeException("Bad response: " + responseCode + " " + responseMessage); } catch (IOException e) { throw new PushNetworkException(e); } - throw new StaleDevicesException(JsonUtil.fromJson(response, StaleDevices.class)); + + throw new StaleDevicesException(staleDevices); case 411: + DeviceLimit deviceLimit; + try { - response = Util.readFully(connection.getErrorStream()); + response = Util.readFully(connection.getErrorStream()); + deviceLimit = JsonUtil.fromJson(response, DeviceLimit.class); + } catch (JsonProcessingException e) { + throw new NonSuccessfulResponseCodeException("Bad response: " + responseCode + " " + responseMessage); } catch (IOException e) { throw new PushNetworkException(e); } - throw new DeviceLimitExceededException(JsonUtil.fromJson(response, DeviceLimit.class)); + + throw new DeviceLimitExceededException(deviceLimit); case 417: throw new ExpectationFailedException(); } diff --git a/java/src/main/java/org/whispersystems/textsecure/internal/util/JsonUtil.java b/java/src/main/java/org/whispersystems/textsecure/internal/util/JsonUtil.java index 104a79fc3a..37f50dd0bd 100644 --- a/java/src/main/java/org/whispersystems/textsecure/internal/util/JsonUtil.java +++ b/java/src/main/java/org/whispersystems/textsecure/internal/util/JsonUtil.java @@ -2,6 +2,7 @@ package org.whispersystems.textsecure.internal.util; import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; @@ -36,21 +37,12 @@ public class JsonUtil { } } - public static T fromJson(String json, Class clazz) { - try { - return objectMapper.readValue(json, clazz); - } catch (IOException e) { - Log.w(TAG, e); - throw new JsonParseException(e); - } + public static T fromJson(String json, Class clazz) + throws IOException + { + return objectMapper.readValue(json, clazz); } - - public static class JsonParseException extends RuntimeException { - public JsonParseException(Exception e) { - super(e); - } - } - + public static class IdentityKeySerializer extends JsonSerializer { @Override public void serialize(IdentityKey value, JsonGenerator gen, SerializerProvider serializers)