... |
... |
@@ -16,15 +16,10 @@ import androidx.annotation.Nullable; |
16
|
16
|
|
17
|
17
|
import java.io.BufferedReader;
|
18
|
18
|
import java.io.File;
|
|
19
|
+import java.io.FileOutputStream;
|
19
|
20
|
import java.io.IOException;
|
20
|
21
|
import java.io.InputStream;
|
21
|
22
|
import java.io.InputStreamReader;
|
22
|
|
-import java.nio.file.Files;
|
23
|
|
-import java.nio.file.Path;
|
24
|
|
-import java.nio.file.Paths;
|
25
|
|
-import java.nio.file.StandardCopyOption;
|
26
|
|
-import java.nio.file.attribute.PosixFilePermission;
|
27
|
|
-import java.nio.file.attribute.PosixFilePermissions;
|
28
|
23
|
import java.util.ArrayList;
|
29
|
24
|
import java.util.HashMap;
|
30
|
25
|
import java.util.HashSet;
|
... |
... |
@@ -69,9 +64,9 @@ public class TorIntegrationAndroid implements BundleEventListener { |
69
|
64
|
private static final String COOKIE_AUTH_FILE = "/auth-file";
|
70
|
65
|
|
71
|
66
|
private final String mLibraryDir;
|
72
|
|
- private final Path mCacheDir;
|
|
67
|
+ private final String mCacheDir;
|
73
|
68
|
private final String mIpcDirectory;
|
74
|
|
- private final String mDataDir;
|
|
69
|
+ private final File mDataDir;
|
75
|
70
|
|
76
|
71
|
private TorProcess mTorProcess = null;
|
77
|
72
|
/**
|
... |
... |
@@ -91,9 +86,9 @@ public class TorIntegrationAndroid implements BundleEventListener { |
91
|
86
|
|
92
|
87
|
/* package */ TorIntegrationAndroid(Context context) {
|
93
|
88
|
mLibraryDir = context.getApplicationInfo().nativeLibraryDir;
|
94
|
|
- mCacheDir = context.getCacheDir().toPath();
|
|
89
|
+ mCacheDir = context.getCacheDir().getAbsolutePath();
|
95
|
90
|
mIpcDirectory = mCacheDir + "/tor-private";
|
96
|
|
- mDataDir = context.getDataDir().getAbsolutePath() + "/tor";
|
|
91
|
+ mDataDir = new File(context.getFilesDir(), "tor");
|
97
|
92
|
registerListener();
|
98
|
93
|
}
|
99
|
94
|
|
... |
... |
@@ -260,7 +255,7 @@ public class TorIntegrationAndroid implements BundleEventListener { |
260
|
255
|
args.add("CookieAuthFile");
|
261
|
256
|
args.add(ipcDir + COOKIE_AUTH_FILE);
|
262
|
257
|
args.add("DataDirectory");
|
263
|
|
- args.add(mDataDir);
|
|
258
|
+ args.add(mDataDir.getAbsolutePath());
|
264
|
259
|
boolean copied = true;
|
265
|
260
|
try {
|
266
|
261
|
copyAndUseConfigFile("--defaults-torrc", "torrc-defaults", args);
|
... |
... |
@@ -322,15 +317,19 @@ public class TorIntegrationAndroid implements BundleEventListener { |
322
|
317
|
|
323
|
318
|
private void cleanIpcDirectory() {
|
324
|
319
|
File directory = new File(TorIntegrationAndroid.this.mIpcDirectory);
|
325
|
|
- if (!Files.isDirectory(directory.toPath())) {
|
|
320
|
+ if (!directory.isDirectory()) {
|
326
|
321
|
if (!directory.mkdirs()) {
|
327
|
322
|
Log.e(TAG, "Failed to create the IPC directory.");
|
328
|
323
|
return;
|
329
|
324
|
}
|
330
|
325
|
try {
|
331
|
|
- Set<PosixFilePermission> chmod = PosixFilePermissions.fromString("rwx------");
|
332
|
|
- Files.setPosixFilePermissions(directory.toPath(), chmod);
|
333
|
|
- } catch (IOException e) {
|
|
326
|
+ directory.setReadable(false, false);
|
|
327
|
+ directory.setReadable(true, true);
|
|
328
|
+ directory.setWritable(false, false);
|
|
329
|
+ directory.setWritable(true, true);
|
|
330
|
+ directory.setExecutable(false, false);
|
|
331
|
+ directory.setExecutable(true, true);
|
|
332
|
+ } catch (SecurityException e) {
|
334
|
333
|
Log.e(TAG, "Could not set the permissions to the IPC directory.", e);
|
335
|
334
|
}
|
336
|
335
|
return;
|
... |
... |
@@ -347,15 +346,46 @@ public class TorIntegrationAndroid implements BundleEventListener { |
347
|
346
|
}
|
348
|
347
|
|
349
|
348
|
private void copyAndUseConfigFile(String option, String name, ArrayList<String> args) throws IOException {
|
350
|
|
- final Path path = Paths.get(mCacheDir.toFile().getAbsolutePath(), name);
|
351
|
|
- if (!mCopiedConfigFiles || !path.toFile().exists()) {
|
352
|
|
- final Context context = GeckoAppShell.getApplicationContext();
|
353
|
|
- final InputStream in = context.getAssets().open("common/" + name);
|
354
|
|
- Files.copy(in, path, StandardCopyOption.REPLACE_EXISTING);
|
|
349
|
+ File file = copyConfigFile(name);
|
|
350
|
+ args.add(option);
|
|
351
|
+ args.add(file.getAbsolutePath());
|
|
352
|
+ }
|
|
353
|
+
|
|
354
|
+ private File copyConfigFile(String name) throws IOException {
|
|
355
|
+ final File file = new File(mCacheDir, name);
|
|
356
|
+ if (mCopiedConfigFiles && file.exists()) {
|
|
357
|
+ return file;
|
|
358
|
+ }
|
|
359
|
+
|
|
360
|
+ final Context context = GeckoAppShell.getApplicationContext();
|
|
361
|
+ final InputStream in = context.getAssets().open("common/" + name);
|
|
362
|
+ // Files.copy is API 26+, so use java.io and a loop for now.
|
|
363
|
+ FileOutputStream out = null;
|
|
364
|
+ try {
|
|
365
|
+ out = new FileOutputStream(file);
|
|
366
|
+ } catch (IOException e) {
|
355
|
367
|
in.close();
|
|
368
|
+ throw e;
|
356
|
369
|
}
|
357
|
|
- args.add(option);
|
358
|
|
- args.add(path.toString());
|
|
370
|
+ try {
|
|
371
|
+ byte buffer[] = new byte[4096];
|
|
372
|
+ int read;
|
|
373
|
+ while ((read = in.read(buffer)) >= 0) {
|
|
374
|
+ out.write(buffer, 0, read);
|
|
375
|
+ }
|
|
376
|
+ } finally {
|
|
377
|
+ try {
|
|
378
|
+ in.close();
|
|
379
|
+ } catch (IOException e) {
|
|
380
|
+ Log.w(TAG, "Cannot close the input stream for " + name);
|
|
381
|
+ }
|
|
382
|
+ try {
|
|
383
|
+ out.close();
|
|
384
|
+ } catch (IOException e) {
|
|
385
|
+ Log.w(TAG, "Cannot close the output stream for " + name);
|
|
386
|
+ }
|
|
387
|
+ }
|
|
388
|
+ return file;
|
359
|
389
|
}
|
360
|
390
|
|
361
|
391
|
public void shutdown() {
|
... |
... |
@@ -406,9 +436,10 @@ public class TorIntegrationAndroid implements BundleEventListener { |
406
|
436
|
setName("meek-" + id);
|
407
|
437
|
final ProcessBuilder builder = new ProcessBuilder(mLibraryDir + "/libObfs4proxy.so");
|
408
|
438
|
{
|
|
439
|
+ File ptStateDir = new File(mDataDir, "pt_state");
|
409
|
440
|
final Map<String, String> env = builder.environment();
|
410
|
441
|
env.put("TOR_PT_MANAGED_TRANSPORT_VER", "1");
|
411
|
|
- env.put("TOR_PT_STATE_LOCATION", mDataDir + "/pt_state");
|
|
442
|
+ env.put("TOR_PT_STATE_LOCATION", ptStateDir.getAbsolutePath());
|
412
|
443
|
env.put("TOR_PT_EXIT_ON_STDIN_CLOSE", "1");
|
413
|
444
|
env.put("TOR_PT_CLIENT_TRANSPORTS", TRANSPORT);
|
414
|
445
|
}
|