From 074e285c94a752609c6b6e8f079db26bd9d77f0f Mon Sep 17 00:00:00 2001
From: cyBerta <cyberta@riseup.net>
Date: Mon, 27 Jan 2025 15:57:31 +0100
Subject: [PATCH] add auth token to introducer model class, pass auth token to
 bitmask-core

---
 .../bitmaskclient/base/models/Introducer.java | 25 +++++++++++++++----
 .../providersetup/ProviderApiManager.java     |  1 +
 .../fragments/ProviderSelectionFragment.java  | 10 ++++++--
 3 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Introducer.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Introducer.java
index 671992ca0..7048c48d0 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/models/Introducer.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Introducer.java
@@ -3,8 +3,10 @@ package se.leap.bitmaskclient.base.models;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.net.URLEncoder;
 
 public class Introducer implements Parcelable {
     private String type;
@@ -13,12 +15,15 @@ public class Introducer implements Parcelable {
     private String fullyQualifiedDomainName;
     private boolean kcpEnabled;
 
-    public Introducer(String type, String address, String certificate, String fullyQualifiedDomainName, boolean kcpEnabled) {
+    private String auth;
+
+    public Introducer(String type, String address, String certificate, String fullyQualifiedDomainName, boolean kcpEnabled, String auth) {
         this.type = type;
         this.address = address;
         this.certificate = certificate;
         this.fullyQualifiedDomainName = fullyQualifiedDomainName;
         this.kcpEnabled = kcpEnabled;
+        this.auth = auth;
     }
 
     protected Introducer(Parcel in) {
@@ -27,6 +32,7 @@ public class Introducer implements Parcelable {
         certificate = in.readString();
         fullyQualifiedDomainName = in.readString();
         kcpEnabled = in.readByte() != 0;
+        auth = in.readString();
     }
 
     public String getFullyQualifiedDomainName() {
@@ -40,6 +46,7 @@ public class Introducer implements Parcelable {
         dest.writeString(certificate);
         dest.writeString(fullyQualifiedDomainName);
         dest.writeByte((byte) (kcpEnabled ? 1 : 0));
+        dest.writeString(auth);
     }
 
     @Override
@@ -72,10 +79,14 @@ public class Introducer implements Parcelable {
         if (!"localhost".equals(fullyQualifiedDomainName) && fullyQualifiedDomainName.split("\\.").length < 2) {
             throw new IllegalArgumentException("Expected a FQDN, got: " + fullyQualifiedDomainName);
         }
+
+        if (auth == null || auth.isEmpty()) {
+            throw new IllegalArgumentException("Auth token is missing");
+        }
         return true;
     }
 
-    public static Introducer fromUrl(String introducerUrl) throws URISyntaxException {
+    public static Introducer fromUrl(String introducerUrl) throws URISyntaxException, IllegalArgumentException {
         URI uri = new URI(introducerUrl);
         String fqdn = getQueryParam(uri, "fqdn");
         if (fqdn == null || fqdn.isEmpty()) {
@@ -89,11 +100,15 @@ public class Introducer implements Parcelable {
             throw new IllegalArgumentException("Cert not found in the introducer URL");
         }
 
-        return new Introducer(uri.getScheme(), uri.getAuthority(), cert, fqdn, kcp);
+        String auth = getQueryParam(uri, "auth");
+        if (auth == null || auth.isEmpty()) {
+            throw new IllegalArgumentException("Authentication token not found in the introducer URL");
+        }
+        return new Introducer(uri.getScheme(), uri.getAuthority(), cert, fqdn, kcp, auth);
     }
 
-    public String toUrl() {
-        return String.format("%s://%s?fqdn=%s&kcp=%d&cert=%s", type, address, fullyQualifiedDomainName, kcpEnabled ? 1 : 0, certificate);
+    public String toUrl() throws UnsupportedEncodingException {
+        return String.format("%s://%s?fqdn=%s&kcp=%d&cert=%s&auth=%s", type, address, URLEncoder.encode(fullyQualifiedDomainName, "UTF-8"), kcpEnabled ? 1 : 0, URLEncoder.encode(certificate, "UTF-8"),  URLEncoder.encode(auth, "UTF-8"));
     }
 
     private static String getQueryParam(URI uri, String param) {
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManager.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManager.java
index b370f0f62..79c6f5c40 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManager.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManager.java
@@ -150,6 +150,7 @@ public class ProviderApiManager extends ProviderApiManagerBase {
             }
             return bm.getProvider();
         } catch (Exception e) {
+            e.printStackTrace();
             try {
                 if (allowRetry &&
                         TorStatusObservable.getStatus() == OFF &&
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java
index 3a75925e6..66b1dd006 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ProviderSelectionFragment.java
@@ -20,6 +20,7 @@ import androidx.lifecycle.ViewModelProvider;
 import com.journeyapps.barcodescanner.ScanContract;
 import com.journeyapps.barcodescanner.ScanOptions;
 
+import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
 
 import se.leap.bitmaskclient.R;
@@ -61,6 +62,7 @@ public class ProviderSelectionFragment extends BaseSetupFragment implements Canc
                             Introducer introducer = Introducer.fromUrl(result.getContents());
                             binding.editCustomProvider.setText(introducer.toUrl());
                         } catch (Exception e) {
+                            e.printStackTrace();
                             //binding.editCustomProvider.setText(result.getContents());
                         }
                     }
@@ -191,8 +193,12 @@ public class ProviderSelectionFragment extends BaseSetupFragment implements Canc
     public void providerSelectionChanged(){
         Provider provider = setupActivityCallback.getSelectedProvider();
         if (provider != null && provider.hasIntroducer()) {
-            binding.providerRadioGroup.check(INVITE_CODE_PROVIDER);
-            binding.editCustomProvider.setText(provider.getIntroducer().toUrl());
+            try {
+                binding.providerRadioGroup.check(INVITE_CODE_PROVIDER);
+                binding.editCustomProvider.setText(provider.getIntroducer().toUrl());
+            } catch (UnsupportedEncodingException e) {
+                e.printStackTrace();
+            }
         } else {
             binding.providerRadioGroup.check(viewModel.getSelected());
         }
-- 
GitLab