Commit ba475a47 authored by Tiago Cunha's avatar Tiago Cunha

Improved server validation implementation

parent b7ec5aac
package chat.rocket.android.api.rest;
import android.support.annotation.NonNull;
import org.json.JSONObject;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
public class DefaultServerPolicyApi implements ServerPolicyApi {
private static final String SECURE_PROTOCOL = "https://";
private static final String INSECURE_PROTOCOL = "http://";
private static final String API_INFO_PATH = "/api/info";
private final OkHttpClient client;
private final String host;
public DefaultServerPolicyApi(@NonNull OkHttpClient client, @NonNull String host) {
this.client = client;
this.host = host;
}
@Override
public void getApiInfoSecurely(@NonNull Callback callback) {
client.newCall(createRequest(SECURE_PROTOCOL)).enqueue(getOkHttpCallback(callback));
}
@Override
public void getApiInfoInsecurely(@NonNull Callback callback) {
client.newCall(createRequest(INSECURE_PROTOCOL)).enqueue(getOkHttpCallback(callback));
}
private Request createRequest(@NonNull String protocol) {
return new Request.Builder()
.url(protocol + host + API_INFO_PATH)
.get()
.build();
}
private okhttp3.Callback getOkHttpCallback(@NonNull Callback callback) {
return new okhttp3.Callback() {
@Override
public void onFailure(Call call, IOException e) {
callback.onNetworkError();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (!response.isSuccessful()) {
callback.onResponseError();
return;
}
final ResponseBody body = response.body();
if (body == null || body.contentLength() == 0) {
callback.onResponseError();
return;
}
try {
callback.onSuccess(new JSONObject(body.string()));
} catch (Exception e) {
callback.onResponseError();
}
}
};
}
}
package chat.rocket.android.api.rest;
import android.support.annotation.NonNull;
import org.json.JSONObject;
public interface ServerPolicyApi {
void getApiInfoSecurely(@NonNull Callback callback);
void getApiInfoInsecurely(@NonNull Callback callback);
interface Callback {
void onSuccess(JSONObject jsonObject);
void onResponseError();
void onNetworkError();
}
}
...@@ -6,6 +6,8 @@ import org.json.JSONObject; ...@@ -6,6 +6,8 @@ import org.json.JSONObject;
import chat.rocket.android.R; import chat.rocket.android.R;
import chat.rocket.android.RocketChatCache; import chat.rocket.android.RocketChatCache;
import chat.rocket.android.api.rest.DefaultServerPolicyApi;
import chat.rocket.android.api.rest.ServerPolicyApi;
import chat.rocket.android.helper.LogcatIfError; import chat.rocket.android.helper.LogcatIfError;
import chat.rocket.android.helper.OkHttpHelper; import chat.rocket.android.helper.OkHttpHelper;
import chat.rocket.android.helper.ServerPolicyHelper; import chat.rocket.android.helper.ServerPolicyHelper;
...@@ -41,7 +43,10 @@ public class InputHostnameFragment extends AbstractServerConfigFragment { ...@@ -41,7 +43,10 @@ public class InputHostnameFragment extends AbstractServerConfigFragment {
private void handleConnect() { private void handleConnect() {
final String hostname = ServerPolicyHelper.enforceHostname(getHostname()); final String hostname = ServerPolicyHelper.enforceHostname(getHostname());
ServerPolicyHelper.isApiVersionValid(OkHttpHelper.getClientForUploadFile(), hostname, ServerPolicyApi serverPolicyApi =
new DefaultServerPolicyApi(OkHttpHelper.getClientForUploadFile(), hostname);
ServerPolicyHelper.isApiVersionValid(serverPolicyApi,
new ServerPolicyHelper.Callback() { new ServerPolicyHelper.Callback() {
@Override @Override
public void isValid(boolean usesSecureConnection) { public void isValid(boolean usesSecureConnection) {
......
...@@ -4,17 +4,11 @@ import android.support.annotation.NonNull; ...@@ -4,17 +4,11 @@ import android.support.annotation.NonNull;
import org.json.JSONObject; import org.json.JSONObject;
import java.io.IOException; import chat.rocket.android.api.rest.ServerPolicyApi;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
public class ServerPolicyHelper { public class ServerPolicyHelper {
private static final String DEFAULT_HOST = ".rocket.chat"; private static final String DEFAULT_HOST = ".rocket.chat";
private static final String API_INFO_PATH = "/api/info";
private static final String VERSION_PROPERTY = "version"; private static final String VERSION_PROPERTY = "version";
public static String enforceHostname(String hostname) { public static String enforceHostname(String hostname) {
...@@ -25,9 +19,9 @@ public class ServerPolicyHelper { ...@@ -25,9 +19,9 @@ public class ServerPolicyHelper {
return removeTrailingSlash(removeProtocol(enforceDefaultHost(hostname))); return removeTrailingSlash(removeProtocol(enforceDefaultHost(hostname)));
} }
public static void isApiVersionValid(@NonNull OkHttpClient client, @NonNull String host, public static void isApiVersionValid(@NonNull ServerPolicyApi serverPolicyApi,
@NonNull Callback callback) { @NonNull Callback callback) {
trySecureValidation(client, host, new Callback() { trySecureValidation(serverPolicyApi, new Callback() {
@Override @Override
public void isValid(boolean usesSecureConnection) { public void isValid(boolean usesSecureConnection) {
callback.isValid(usesSecureConnection); callback.isValid(usesSecureConnection);
...@@ -40,7 +34,7 @@ public class ServerPolicyHelper { ...@@ -40,7 +34,7 @@ public class ServerPolicyHelper {
@Override @Override
public void onNetworkError() { public void onNetworkError() {
tryInsecureValidation(client, host, callback); tryInsecureValidation(serverPolicyApi, callback);
} }
}); });
} }
...@@ -68,14 +62,12 @@ public class ServerPolicyHelper { ...@@ -68,14 +62,12 @@ public class ServerPolicyHelper {
return hostname.replaceAll("/+$", ""); return hostname.replaceAll("/+$", "");
} }
private static boolean isValid(ResponseBody body) { private static boolean isValid(JSONObject jsonObject) {
if (body == null || body.contentLength() == 0) { if (jsonObject == null) {
return false; return false;
} }
try { try {
final JSONObject jsonObject = new JSONObject(body.string());
return jsonObject.has(VERSION_PROPERTY) return jsonObject.has(VERSION_PROPERTY)
&& isVersionValid(jsonObject.getString(VERSION_PROPERTY)); && isVersionValid(jsonObject.getString(VERSION_PROPERTY));
} catch (Exception e) { } catch (Exception e) {
...@@ -92,57 +84,38 @@ public class ServerPolicyHelper { ...@@ -92,57 +84,38 @@ public class ServerPolicyHelper {
return versionParts.length >= 3 && Integer.parseInt(versionParts[1]) >= 49; return versionParts.length >= 3 && Integer.parseInt(versionParts[1]) >= 49;
} }
private static void trySecureValidation(@NonNull OkHttpClient client, @NonNull String host, private static void trySecureValidation(@NonNull ServerPolicyApi serverPolicyApi,
@NonNull Callback callback) { @NonNull Callback callback) {
Request request; serverPolicyApi.getApiInfoSecurely(getServerPolicyApiCallback(true, callback));
try {
request = createRequest("https://", host);
} catch (Exception e) {
callback.isNotValid();
return;
}
validate(request, client, callback, true);
} }
private static void tryInsecureValidation(@NonNull OkHttpClient client, @NonNull String host, private static void tryInsecureValidation(@NonNull ServerPolicyApi serverPolicyApi,
@NonNull Callback callback) { @NonNull Callback callback) {
Request request; serverPolicyApi.getApiInfoInsecurely(getServerPolicyApiCallback(false, callback));
try {
request = createRequest("http://", host);
} catch (Exception e) {
callback.isNotValid();
return;
}
validate(request, client, callback, false);
} }
private static Request createRequest(@NonNull String protocol, @NonNull String host) { private static ServerPolicyApi.Callback getServerPolicyApiCallback(boolean isSecureConnection,
return new Request.Builder() @NonNull Callback callback) {
.url(protocol + host + API_INFO_PATH) return new ServerPolicyApi.Callback() {
.get()
.build();
}
private static void validate(@NonNull Request request, @NonNull OkHttpClient client,
@NonNull Callback callback, boolean usesSecureConnection) {
client.newCall(request).enqueue(new okhttp3.Callback() {
@Override @Override
public void onFailure(Call call, IOException exception) { public void onSuccess(JSONObject jsonObject) {
callback.onNetworkError(); if (isValid(jsonObject)) {
callback.isValid(isSecureConnection);
return;
}
callback.isNotValid();
} }
@Override @Override
public void onResponse(Call call, Response response) throws IOException { public void onResponseError() {
if (!response.isSuccessful() || !isValid(response.body())) { callback.isNotValid();
callback.isNotValid(); }
return;
}
callback.isValid(usesSecureConnection); @Override
public void onNetworkError() {
callback.onNetworkError();
} }
}); };
} }
public interface Callback { public interface Callback {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment