diff --git a/app/src/main/java/org/torproject/android/OrbotMainActivity.java b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
index 2cb44c4a..07d01993 100644
--- a/app/src/main/java/org/torproject/android/OrbotMainActivity.java
+++ b/app/src/main/java/org/torproject/android/OrbotMainActivity.java
@@ -593,7 +593,8 @@ public class OrbotMainActivity extends AppCompatActivity
private void enableHiddenServicePort(
String hsName, final int hsPort, int hsRemotePort,
- final String backupToPackage, final Uri hsKeyPath
+ final String backupToPackage, final Uri hsKeyPath,
+ final Boolean authCookie
) throws RemoteException, InterruptedException {
String onionHostname = null;
@@ -608,6 +609,7 @@ public class OrbotMainActivity extends AppCompatActivity
fields.put(HSContentProvider.HiddenService.NAME, hsName);
fields.put(HSContentProvider.HiddenService.PORT, hsPort);
fields.put(HSContentProvider.HiddenService.ONION_PORT, hsRemotePort);
+ fields.put(HSContentProvider.HiddenService.AUTH_COOKIE, authCookie);
ContentResolver cr = getContentResolver();
@@ -725,6 +727,7 @@ public class OrbotMainActivity extends AppCompatActivity
final int hiddenServiceRemotePort = intent.getIntExtra("hs_onion_port", -1);
final String hiddenServiceName = intent.getStringExtra("hs_name");
final String backupToPackage = intent.getStringExtra("hs_backup_to_package");
+ final Boolean authCookie = intent.getBooleanExtra("hs_auth_cookie", false);
final Uri mKeyUri = intent.getData();
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
@@ -735,7 +738,8 @@ public class OrbotMainActivity extends AppCompatActivity
try {
enableHiddenServicePort(
hiddenServiceName, hiddenServicePort,
- hiddenServiceRemotePort, backupToPackage, mKeyUri
+ hiddenServiceRemotePort, backupToPackage,
+ mKeyUri, authCookie
);
} catch (RemoteException e) {
// TODO Auto-generated catch block
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java
index 99af1828..c4f55a1c 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/HiddenServicesActivity.java
@@ -90,6 +90,14 @@ public class HiddenServicesActivity extends AppCompatActivity {
"onion", item.getString(item.getColumnIndex(HSContentProvider.HiddenService.DOMAIN))
);
+ arguments.putInt(
+ "auth_cookie", item.getInt(item.getColumnIndex(HSContentProvider.HiddenService.AUTH_COOKIE))
+ );
+
+ arguments.putString(
+ "auth_cookie_value", item.getString(item.getColumnIndex(HSContentProvider.HiddenService.AUTH_COOKIE_VALUE))
+ );
+
HSActionsDialog dialog = new HSActionsDialog();
dialog.setArguments(arguments);
dialog.show(getSupportFragmentManager(), "HSActionsDialog");
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/BackupUtils.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/BackupUtils.java
index 5a1185c0..1dccbf85 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/BackupUtils.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/backup/BackupUtils.java
@@ -88,6 +88,16 @@ public class BackupUtils {
portData.getString(portData.getColumnIndex(HSContentProvider.HiddenService.DOMAIN))
);
+ config.put(
+ HSContentProvider.HiddenService.AUTH_COOKIE,
+ portData.getInt(portData.getColumnIndex(HSContentProvider.HiddenService.AUTH_COOKIE))
+ );
+
+ config.put(
+ HSContentProvider.HiddenService.AUTH_COOKIE_VALUE,
+ portData.getString(portData.getColumnIndex(HSContentProvider.HiddenService.AUTH_COOKIE_VALUE))
+ );
+
config.put(
HSContentProvider.HiddenService.CREATED_BY_USER,
portData.getInt(portData.getColumnIndex(HSContentProvider.HiddenService.CREATED_BY_USER))
@@ -173,6 +183,11 @@ public class BackupUtils {
savedValues.getString(HSContentProvider.HiddenService.DOMAIN)
);
+ fields.put(
+ HSContentProvider.HiddenService.AUTH_COOKIE,
+ savedValues.getInt(HSContentProvider.HiddenService.AUTH_COOKIE)
+ );
+
fields.put(
HSContentProvider.HiddenService.CREATED_BY_USER,
savedValues.getInt(HSContentProvider.HiddenService.CREATED_BY_USER)
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/database/HSDatabase.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/database/HSDatabase.java
index 8f1123fa..93ccd25a 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/database/HSDatabase.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/database/HSDatabase.java
@@ -16,6 +16,8 @@ public class HSDatabase extends SQLiteOpenHelper {
"name TEXT, " +
"domain TEXT, " +
"onion_port INTEGER, " +
+ "auth_cookie INTEGER DEFAULT 0, " +
+ "auth_cookie_value TEXT, " +
"created_by_user INTEGER DEFAULT 0, " +
"port INTEGER);";
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSActionsDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSActionsDialog.java
index e1b9dd3c..06b650bb 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSActionsDialog.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSActionsDialog.java
@@ -83,6 +83,30 @@ public class HSActionsDialog extends DialogFragment {
}
});
+ Button showAuth = (Button) dialog_view.findViewById(R.id.bt_hs_show_auth);
+ showAuth.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ String auth_cookie_value = arguments.getString("auth_cookie_value");
+ if (arguments.getInt("auth_cookie") == 1) {
+ if (auth_cookie_value == null || auth_cookie_value.length() < 1) {
+ Toast.makeText(
+ v.getContext(), R.string.please_restart_Orbot_to_enable_the_changes, Toast.LENGTH_LONG
+ ).show();
+ } else {
+ new AlertDialog.Builder(getActivity())
+ .setMessage(auth_cookie_value)
+ .show();
+ }
+ } else {
+ Toast.makeText(
+ v.getContext(), R.string.auth_cookie_was_not_configured, Toast.LENGTH_LONG
+ ).show();
+ }
+
+ actionDialog.dismiss();
+ }
+ });
+
Button delete = (Button) dialog_view.findViewById(R.id.btn_hs_delete);
delete.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDataDialog.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDataDialog.java
index 329d6a8c..56c6d3f4 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDataDialog.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/dialogs/HSDataDialog.java
@@ -10,6 +10,7 @@ import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.view.View;
import android.widget.Button;
+import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;
@@ -42,8 +43,10 @@ public class HSDataDialog extends DialogFragment {
((EditText) dialog_view.findViewById(R.id.hsOnionPort)).getText().toString()
);
+ Boolean authCookie = ((CheckBox) dialog_view.findViewById(R.id.hsAuth)).isChecked();
+
if (checkInput(serverName, localPort, onionPort)) {
- saveData(serverName, localPort, onionPort);
+ saveData(serverName, localPort, onionPort, authCookie);
serviceDataDialog.dismiss();
}
}
@@ -80,11 +83,13 @@ public class HSDataDialog extends DialogFragment {
return is_ok;
}
- private void saveData(String name, Integer local, Integer remote) {
+ private void saveData(String name, Integer local, Integer remote, Boolean authCookie) {
+
ContentValues fields = new ContentValues();
fields.put(HSContentProvider.HiddenService.NAME, name);
fields.put(HSContentProvider.HiddenService.PORT, local);
fields.put(HSContentProvider.HiddenService.ONION_PORT, remote);
+ fields.put(HSContentProvider.HiddenService.AUTH_COOKIE, authCookie);
fields.put(HSContentProvider.HiddenService.CREATED_BY_USER, 1);
ContentResolver cr = getContext().getContentResolver();
diff --git a/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/HSContentProvider.java b/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/HSContentProvider.java
index fe6dbf16..a0e85dd4 100644
--- a/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/HSContentProvider.java
+++ b/app/src/main/java/org/torproject/android/ui/hiddenservices/providers/HSContentProvider.java
@@ -22,6 +22,8 @@ public class HSContentProvider extends ContentProvider {
HiddenService.PORT,
HiddenService.DOMAIN,
HiddenService.ONION_PORT,
+ HiddenService.AUTH_COOKIE,
+ HiddenService.AUTH_COOKIE_VALUE,
HiddenService.CREATED_BY_USER
};
private static final String AUTH = "org.torproject.android.ui.hiddenservices.providers";
@@ -130,6 +132,8 @@ public class HSContentProvider extends ContentProvider {
public static final String PORT = "port";
public static final String ONION_PORT = "onion_port";
public static final String DOMAIN = "domain";
+ public static final String AUTH_COOKIE = "auth_cookie";
+ public static final String AUTH_COOKIE_VALUE = "auth_cookie_value";
public static final String CREATED_BY_USER = "created_by_user";
private HiddenService() {
diff --git a/app/src/main/res/layout/layout_hs_actions.xml b/app/src/main/res/layout/layout_hs_actions.xml
index 64bda7db..0e5a6680 100644
--- a/app/src/main/res/layout/layout_hs_actions.xml
+++ b/app/src/main/res/layout/layout_hs_actions.xml
@@ -9,6 +9,12 @@
android:layout_height="wrap_content"
android:id="@+id/btn_hs_clipboard" />
+
+
+
+
Done!
Invalid Port
Copy address to clipboard
+ Show auth cookie
Backup Service
Delete Service
Backup saved at external storage
@@ -362,4 +363,7 @@
Confirm service deletion
Click again for backup
Service type
+ Auth cookie
+ Auth cookie was not configured
+ Please restart Orbot to enable the changes
diff --git a/orbotservice/src/main/java/org/torproject/android/service/TorService.java b/orbotservice/src/main/java/org/torproject/android/service/TorService.java
index b7eab99b..ff37d8cf 100644
--- a/orbotservice/src/main/java/org/torproject/android/service/TorService.java
+++ b/orbotservice/src/main/java/org/torproject/android/service/TorService.java
@@ -139,6 +139,8 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
public static final String PORT = "port";
public static final String ONION_PORT = "onion_port";
public static final String DOMAIN = "domain";
+ public static final String AUTH_COOKIE = "auth_cookie";
+ public static final String AUTH_COOKIE_VALUE = "auth_cookie_value";
public static final String CREATED_BY_USER = "created_by_user";
private HiddenService() {
@@ -147,8 +149,11 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
private String[] mProjection = new String[]{
HiddenService._ID,
+ HiddenService.NAME,
HiddenService.DOMAIN,
HiddenService.PORT,
+ HiddenService.AUTH_COOKIE,
+ HiddenService.AUTH_COOKIE_VALUE,
HiddenService.ONION_PORT};
public void debug(String msg)
@@ -777,9 +782,11 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
while (hidden_services.moveToNext()) {
String HSDomain = hidden_services.getString(hidden_services.getColumnIndex(HiddenService.DOMAIN));
Integer HSLocalPort = hidden_services.getInt(hidden_services.getColumnIndex(HiddenService.PORT));
+ Integer HSAuthCookie = hidden_services.getInt(hidden_services.getColumnIndex(HiddenService.AUTH_COOKIE));
+ String HSAuthCookieValue = hidden_services.getString(hidden_services.getColumnIndex(HiddenService.AUTH_COOKIE_VALUE));
- // Update only new domains
- if(HSDomain == null || HSDomain.length() < 1) {
+ // Update only new domains or restored from backup with auth cookie
+ if((HSDomain == null || HSDomain.length() < 1) || (HSAuthCookie == 1 && (HSAuthCookieValue == null || HSAuthCookieValue.length() < 1))) {
String hsDirPath = new File(mHSBasePath.getAbsolutePath(),"hs" + HSLocalPort).getCanonicalPath();
File file = new File(hsDirPath, "hostname");
@@ -789,7 +796,12 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
try {
String onionHostname = Utils.readString(new FileInputStream(file)).trim();
- fields.put("domain", onionHostname);
+ if(HSAuthCookie == 1) {
+ String[] aux = onionHostname.split(" ");
+ onionHostname = aux[0];
+ fields.put(HiddenService.AUTH_COOKIE_VALUE, aux[1]);
+ }
+ fields.put(HiddenService.DOMAIN, onionHostname);
mCR.update(CONTENT_URI, fields, "port=" + HSLocalPort , null);
} catch (FileNotFoundException e) {
logException("unable to read onion hostname file",e);
@@ -1784,14 +1796,19 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon
if(hidden_services != null) {
try {
while (hidden_services.moveToNext()) {
+ String HSname = hidden_services.getString(hidden_services.getColumnIndex(HiddenService.NAME));
Integer HSLocalPort = hidden_services.getInt(hidden_services.getColumnIndex(HiddenService.PORT));
Integer HSOnionPort = hidden_services.getInt(hidden_services.getColumnIndex(HiddenService.ONION_PORT));
+ Integer HSAuthCookie = hidden_services.getInt(hidden_services.getColumnIndex(HiddenService.AUTH_COOKIE));
String hsDirPath = new File(mHSBasePath.getAbsolutePath(),"hs" + HSLocalPort).getCanonicalPath();
debug("Adding hidden service on port: " + HSLocalPort);
extraLines.append("HiddenServiceDir" + ' ' + hsDirPath).append('\n');
extraLines.append("HiddenServicePort" + ' ' + HSOnionPort + " 127.0.0.1:" + HSLocalPort).append('\n');
+
+ if(HSAuthCookie == 1)
+ extraLines.append("HiddenServiceAuthorizeClient stealth " + HSname).append('\n');
}
} catch (NumberFormatException e) {
Log.e(OrbotConstants.TAG,"error parsing hsport",e);