From 0e2cbdd11e49cb747feb0c38844be27892fe1037 Mon Sep 17 00:00:00 2001 From: M66B Date: Fri, 22 Jul 2022 12:24:44 +0200 Subject: [PATCH] Proof of concept: VirusTotal API --- app/build.gradle | 4 ++ .../extra/java/eu/faircode/email/Check.java | 61 +++++++++++++++++-- .../faircode/email/FragmentOptionsMisc.java | 3 +- 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 7e07656d7f..862c53a044 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -163,6 +163,7 @@ android { buildConfigField "String", "GPA_URI", localProperties.getProperty("gpa.uri", "\"\"") buildConfigField "String", "INFO_URI", localProperties.getProperty("info.uri", "\"\"") buildConfigField "String", "DEV_DOMAIN", localProperties.getProperty("dev.domain", "\"\"") + buildConfigField "String", "VT_APIKEY", localProperties.getProperty("vt.apikey", "\"\"") buildConfigField "String", "FDROID", "\"https://f-droid.org/packages/%s/\"" } fdroid { @@ -179,6 +180,7 @@ android { buildConfigField "String", "GPA_URI", "\"\"" buildConfigField "String", "INFO_URI", "\"\"" buildConfigField "String", "DEV_DOMAIN", "\"\"" + buildConfigField "String", "VT_APIKEY", "\"\"" buildConfigField "String", "FDROID", "\"https://f-droid.org/packages/%s/\"" } play { @@ -196,6 +198,7 @@ android { buildConfigField "String", "GPA_URI", "\"\"" buildConfigField "String", "INFO_URI", "\"\"" buildConfigField "String", "DEV_DOMAIN", "\"\"" + buildConfigField "String", "VT_APIKEY", "\"\"" buildConfigField "String", "FDROID", "\"\"" } amazon { @@ -213,6 +216,7 @@ android { buildConfigField "String", "GPA_URI", "\"\"" buildConfigField "String", "INFO_URI", "\"\"" buildConfigField "String", "DEV_DOMAIN", "\"\"" + buildConfigField "String", "VT_APIKEY", "\"\"" buildConfigField "String", "FDROID", "\"\"" } } diff --git a/app/src/extra/java/eu/faircode/email/Check.java b/app/src/extra/java/eu/faircode/email/Check.java index 0c642f361c..d2254def28 100644 --- a/app/src/extra/java/eu/faircode/email/Check.java +++ b/app/src/extra/java/eu/faircode/email/Check.java @@ -22,16 +22,24 @@ package eu.faircode.email; import android.content.Context; import android.net.Uri; import android.os.Bundle; +import android.text.TextUtils; import androidx.fragment.app.FragmentManager; import androidx.lifecycle.LifecycleOwner; +import org.json.JSONObject; + import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.InputStream; +import java.net.URL; + +import javax.net.ssl.HttpsURLConnection; public class Check { - static final String URI_PRIVACY = "https://support.virustotal.com/hc/en-us/articles/115002168385-Privacy-Policy"; - private static final String URI_VIRUS_TOTAL = "https://www.virustotal.com/"; + static final String URI_VT_PRIVACY = "https://support.virustotal.com/hc/en-us/articles/115002168385-Privacy-Policy"; + private static final int VT_TIMEOUT = 20; // seconds + private static final String URI_VT_ENDPOINT = "https://www.virustotal.com/"; static void virus(Context context, LifecycleOwner owner, FragmentManager fm, long id) { Bundle args = new Bundle(); @@ -47,9 +55,54 @@ public class Check { if (attachment == null) return null; + String hash; try (InputStream is = new FileInputStream(attachment.getFile(context))) { - return Helper.getHash(is, "SHA-256"); + hash = Helper.getHash(is, "SHA-256"); } + + if (!TextUtils.isEmpty(BuildConfig.VT_APIKEY)) { + //hash = "51e31f76c8d70eaeda1aba0e21fc50f44d261b81416c4338ac3f71694a6648b3"; + URL url = new URL(URI_VT_ENDPOINT + "api/v3/files/" + hash); + HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); + connection.setRequestMethod("GET"); + connection.setReadTimeout(VT_TIMEOUT * 1000); + connection.setConnectTimeout(VT_TIMEOUT * 1000); + ConnectionHelper.setUserAgent(context, connection); + connection.setRequestProperty("x-apikey", BuildConfig.VT_APIKEY); + connection.connect(); + + try { + int status = connection.getResponseCode(); + if (status != HttpsURLConnection.HTTP_OK && status != HttpsURLConnection.HTTP_NOT_FOUND) { + String error = "Error " + status + ": " + connection.getResponseMessage(); + try { + InputStream is = connection.getErrorStream(); + if (is != null) + error += "\n" + Helper.readStream(is); + } catch (Throwable ex) { + Log.w(ex); + } + throw new FileNotFoundException(error); + } + + if (status == HttpsURLConnection.HTTP_OK) { + String response = Helper.readStream(connection.getInputStream()); + Log.i("VT response=" + response); + + JSONObject jroot = new JSONObject(response); + JSONObject jdata = jroot.getJSONObject("data"); + JSONObject jattributes = jdata.getJSONObject("attributes"); + JSONObject jclassification = jattributes.getJSONObject("popular_threat_classification"); + String label = jclassification.getString("suggested_threat_label"); + + args.putString("label", label); + } + } finally { + connection.disconnect(); + } + } + + return hash; } @Override @@ -57,7 +110,7 @@ public class Check { if (hash == null) return; - Uri uri = Uri.parse(URI_VIRUS_TOTAL + "gui/file/" + hash); + Uri uri = Uri.parse(URI_VT_ENDPOINT + "gui/file/" + hash); Helper.view(context, uri, false); } diff --git a/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java b/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java index cd11aa54b3..8e766083a1 100644 --- a/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java +++ b/app/src/main/java/eu/faircode/email/FragmentOptionsMisc.java @@ -71,7 +71,6 @@ import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.SwitchCompat; import androidx.cardview.widget.CardView; import androidx.constraintlayout.widget.Group; -import androidx.lifecycle.Lifecycle; import androidx.lifecycle.Observer; import androidx.preference.PreferenceManager; @@ -650,7 +649,7 @@ public class FragmentOptionsMisc extends FragmentBase implements SharedPreferenc tvVirusTotalPrivacy.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - Helper.view(v.getContext(), Uri.parse(Check.URI_PRIVACY), true); + Helper.view(v.getContext(), Uri.parse(Check.URI_VT_PRIVACY), true); } });