aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/java
diff options
context:
space:
mode:
authorpacien2020-01-20 17:07:12 +0100
committerpacien2020-01-20 17:07:12 +0100
commit883b5abc7b2a770146683e7e27bf275bd4064511 (patch)
tree81dd200fc2cea8e2030b5b5b68c39abe3c32ab46 /app/src/main/java
parent3fc8a2ed3bfbcbd29bc22c2c73416e2708cd7615 (diff)
downloadtincapp-883b5abc7b2a770146683e7e27bf275bd4064511.tar.gz
pass network device fd via unix socket instead of inheritance
Workaround for new shared memory restrictions added in Android 10 preventing file descriptor leakage to sub-processes. This change set BREAKS ENCRYPTED PRIVATE KEYS SUPPORT. GitHub: https://github.com/pacien/tincapp/issues/92
Diffstat (limited to 'app/src/main/java')
-rw-r--r--app/src/main/java/org/pacien/tincapp/commands/Executor.kt34
-rw-r--r--app/src/main/java/org/pacien/tincapp/commands/Tincd.kt15
-rw-r--r--app/src/main/java/org/pacien/tincapp/context/App.kt10
-rw-r--r--app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt34
4 files changed, 46 insertions, 47 deletions
diff --git a/app/src/main/java/org/pacien/tincapp/commands/Executor.kt b/app/src/main/java/org/pacien/tincapp/commands/Executor.kt
index 29e011f..0a8a774 100644
--- a/app/src/main/java/org/pacien/tincapp/commands/Executor.kt
+++ b/app/src/main/java/org/pacien/tincapp/commands/Executor.kt
@@ -1,6 +1,6 @@
1/* 1/*
2 * Tinc App, an Android binding and user interface for the tinc mesh VPN daemon 2 * Tinc App, an Android binding and user interface for the tinc mesh VPN daemon
3 * Copyright (C) 2017-2018 Pacien TRAN-GIRARD 3 * Copyright (C) 2017-2020 Pacien TRAN-GIRARD
4 * 4 *
5 * This program is free software: you can redistribute it and/or modify 5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
@@ -30,42 +30,10 @@ import java.io.InputStreamReader
30 * @author pacien 30 * @author pacien
31 */ 31 */
32internal object Executor { 32internal object Executor {
33 private const val FAILED = -1
34 private const val SUCCESS = 0
35
36 class CommandExecutionException(msg: String) : Exception(msg) 33 class CommandExecutionException(msg: String) : Exception(msg)
37 34
38 init {
39 System.loadLibrary("exec")
40 }
41
42 /**
43 * @return FAILED (-1) on error, forked child PID otherwise
44 */
45 private external fun forkExec(args: Array<String>): Int
46
47 /**
48 * @return FAILED (-1) on error, the exit status of the process otherwise
49 */
50 private external fun wait(pid: Int): Int
51
52 private fun read(stream: InputStream) = BufferedReader(InputStreamReader(stream)).readLines() 35 private fun read(stream: InputStream) = BufferedReader(InputStreamReader(stream)).readLines()
53 36
54 fun forkExec(cmd: Command): CompletableFuture<Unit> {
55 val pid = forkExec(cmd.asArray()).also {
56 if (it == FAILED) throw CommandExecutionException("Could not fork child process.")
57 }
58
59 return runAsyncTask {
60 val exitCode = wait(pid)
61 when (exitCode) {
62 SUCCESS -> Unit
63 FAILED -> throw CommandExecutionException("Process terminated abnormally.")
64 else -> throw CommandExecutionException("Non-zero exit status code ($exitCode).")
65 }
66 }
67 }
68
69 fun run(cmd: Command): Process = try { 37 fun run(cmd: Command): Process = try {
70 ProcessBuilder(cmd.asList()).start() 38 ProcessBuilder(cmd.asList()).start()
71 } catch (e: IOException) { 39 } catch (e: IOException) {
diff --git a/app/src/main/java/org/pacien/tincapp/commands/Tincd.kt b/app/src/main/java/org/pacien/tincapp/commands/Tincd.kt
index 92be0f5..c0b0048 100644
--- a/app/src/main/java/org/pacien/tincapp/commands/Tincd.kt
+++ b/app/src/main/java/org/pacien/tincapp/commands/Tincd.kt
@@ -1,6 +1,6 @@
1/* 1/*
2 * Tinc App, an Android binding and user interface for the tinc mesh VPN daemon 2 * Tinc App, an Android binding and user interface for the tinc mesh VPN daemon
3 * Copyright (C) 2017-2018 Pacien TRAN-GIRARD 3 * Copyright (C) 2017-2020 Pacien TRAN-GIRARD
4 * 4 *
5 * This program is free software: you can redistribute it and/or modify 5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
@@ -18,20 +18,23 @@
18 18
19package org.pacien.tincapp.commands 19package org.pacien.tincapp.commands
20 20
21import java8.util.concurrent.CompletableFuture
21import org.pacien.tincapp.context.AppPaths 22import org.pacien.tincapp.context.AppPaths
23import java.io.File
22 24
23/** 25/**
24 * @author pacien 26 * @author pacien
25 */ 27 */
26object Tincd { 28object Tincd {
27 fun start(netName: String, deviceFd: Int, ed25519PrivateKeyFd: Int? = null, rsaPrivateKeyFd: Int? = null) = 29 fun start(netName: String, device: String, ed25519PrivateKey: File? = null, rsaPrivateKey: File? = null): CompletableFuture<Unit> =
28 Executor.forkExec(Command(AppPaths.tincd().absolutePath) 30 Executor.call(Command(AppPaths.tincd().absolutePath)
29 .withOption("no-detach") 31 .withOption("no-detach")
30 .withOption("config", AppPaths.confDir(netName).absolutePath) 32 .withOption("config", AppPaths.confDir(netName).absolutePath)
31 .withOption("pidfile", AppPaths.pidFile(netName).absolutePath) 33 .withOption("pidfile", AppPaths.pidFile(netName).absolutePath)
32 .withOption("logfile", AppPaths.logFile(netName).absolutePath) 34 .withOption("logfile", AppPaths.logFile(netName).absolutePath)
33 .withOption("option", "DeviceType=fd") 35 .withOption("option", "DeviceType=fd")
34 .withOption("option", "Device=$deviceFd") 36 .withOption("option", "Device=@$device")
35 .apply { if (ed25519PrivateKeyFd != null) withOption("option", "Ed25519PrivateKeyFile=/proc/self/fd/$ed25519PrivateKeyFd") } 37 .apply { if (ed25519PrivateKey != null) withOption("option", "Ed25519PrivateKeyFile=${ed25519PrivateKey.absolutePath}") }
36 .apply { if (rsaPrivateKeyFd != null) withOption("option", "PrivateKeyFile=/proc/self/fd/$rsaPrivateKeyFd") }) 38 .apply { if (rsaPrivateKey != null) withOption("option", "PrivateKeyFile=${rsaPrivateKey.absolutePath}") }
39 ).thenApply { }
37} 40}
diff --git a/app/src/main/java/org/pacien/tincapp/context/App.kt b/app/src/main/java/org/pacien/tincapp/context/App.kt
index a877929..4d8d5d0 100644
--- a/app/src/main/java/org/pacien/tincapp/context/App.kt
+++ b/app/src/main/java/org/pacien/tincapp/context/App.kt
@@ -1,6 +1,6 @@
1/* 1/*
2 * Tinc App, an Android binding and user interface for the tinc mesh VPN daemon 2 * Tinc App, an Android binding and user interface for the tinc mesh VPN daemon
3 * Copyright (C) 2017-2019 Pacien TRAN-GIRARD 3 * Copyright (C) 2017-2020 Pacien TRAN-GIRARD
4 * 4 *
5 * This program is free software: you can redistribute it and/or modify 5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@ package org.pacien.tincapp.context
21import android.app.Application 21import android.app.Application
22import android.content.Context 22import android.content.Context
23import android.content.Intent 23import android.content.Intent
24import android.content.pm.ApplicationInfo
24import android.net.Uri 25import android.net.Uri
25import android.os.Build 26import android.os.Build
26import android.os.Handler 27import android.os.Handler
@@ -47,7 +48,7 @@ class App : Application() {
47 48
48 private fun setupCrashHandler() { 49 private fun setupCrashHandler() {
49 val logger = LoggerFactory.getLogger(this.javaClass) 50 val logger = LoggerFactory.getLogger(this.javaClass)
50 val systemCrashHandler = Thread.getDefaultUncaughtExceptionHandler() 51 val systemCrashHandler = Thread.getDefaultUncaughtExceptionHandler()!!
51 val crashRecorder = CrashRecorder(logger, systemCrashHandler) 52 val crashRecorder = CrashRecorder(logger, systemCrashHandler)
52 Thread.setDefaultUncaughtExceptionHandler(crashRecorder) 53 Thread.setDefaultUncaughtExceptionHandler(crashRecorder)
53 } 54 }
@@ -61,6 +62,11 @@ class App : Application() {
61 fun getContext() = appContext!! 62 fun getContext() = appContext!!
62 fun getResources() = getContext().resources!! 63 fun getResources() = getContext().resources!!
63 64
65 fun getApplicationInfo(): ApplicationInfo =
66 getContext()
67 .packageManager
68 .getApplicationInfo(BuildConfig.APPLICATION_ID, 0)
69
64 fun alert(@StringRes title: Int, msg: String, manualLink: String? = null) = 70 fun alert(@StringRes title: Int, msg: String, manualLink: String? = null) =
65 notificationManager.notifyError(appContext!!.getString(title), msg, manualLink) 71 notificationManager.notifyError(appContext!!.getString(title), msg, manualLink)
66 72
diff --git a/app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt b/app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt
index 40e9004..48cb1df 100644
--- a/app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt
+++ b/app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt
@@ -1,6 +1,6 @@
1/* 1/*
2 * Tinc App, an Android binding and user interface for the tinc mesh VPN daemon 2 * Tinc App, an Android binding and user interface for the tinc mesh VPN daemon
3 * Copyright (C) 2017-2019 Pacien TRAN-GIRARD 3 * Copyright (C) 2017-2020 Pacien TRAN-GIRARD
4 * 4 *
5 * This program is free software: you can redistribute it and/or modify 5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@ package org.pacien.tincapp.service
21import android.app.Service 21import android.app.Service
22import android.content.Context 22import android.content.Context
23import android.content.Intent 23import android.content.Intent
24import android.net.LocalServerSocket
24import android.net.VpnService 25import android.net.VpnService
25import android.os.ParcelFileDescriptor 26import android.os.ParcelFileDescriptor
26import androidx.localbroadcastmanager.content.LocalBroadcastManager 27import androidx.localbroadcastmanager.content.LocalBroadcastManager
@@ -43,6 +44,7 @@ import org.pacien.tincapp.intent.Actions
43import org.pacien.tincapp.utils.TincKeyring 44import org.pacien.tincapp.utils.TincKeyring
44import org.slf4j.LoggerFactory 45import org.slf4j.LoggerFactory
45import java.io.FileNotFoundException 46import java.io.FileNotFoundException
47import java.security.AccessControlException
46 48
47/** 49/**
48 * @author pacien 50 * @author pacien
@@ -100,6 +102,7 @@ class TincVpnService : VpnService() {
100 log.info("Starting tinc daemon for network \"$netName\".") 102 log.info("Starting tinc daemon for network \"$netName\".")
101 if (isConnected() || getCurrentNetName() != null) stopVpn().join() 103 if (isConnected() || getCurrentNetName() != null) stopVpn().join()
102 104
105 // FIXME: pass decrypted private keys via temp file
103 val privateKeys = try { 106 val privateKeys = try {
104 TincConfiguration.fromTincConfiguration(AppPaths.existing(AppPaths.tincConfFile(netName))).let { tincCfg -> 107 TincConfiguration.fromTincConfiguration(AppPaths.existing(AppPaths.tincConfFile(netName))).let { tincCfg ->
105 Pair( 108 Pair(
@@ -125,13 +128,10 @@ class TincVpnService : VpnService() {