diff options
3 files changed, 38 insertions, 21 deletions
diff --git a/app/src/main/java/org/pacien/tincapp/context/AppPaths.kt b/app/src/main/java/org/pacien/tincapp/context/AppPaths.kt index 1efb7cf..2394586 100644 --- a/app/src/main/java/org/pacien/tincapp/context/AppPaths.kt +++ b/app/src/main/java/org/pacien/tincapp/context/AppPaths.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 |
@@ -25,7 +25,7 @@ import java.io.FileNotFoundException | |||
25 | /** | 25 | /** |
26 | * @author pacien | 26 | * @author pacien |
27 | * | 27 | * |
28 | * @implNote Logs and PID files are stored in the cache directory for easy clean up. | 28 | * @implNote Logs and PID files are stored in the cache directory for automatic collection. |
29 | */ | 29 | */ |
30 | object AppPaths { | 30 | object AppPaths { |
31 | private const val TINCD_BIN = "libtincd.so" | 31 | private const val TINCD_BIN = "libtincd.so" |
@@ -40,15 +40,16 @@ object AppPaths { | |||
40 | private const val NET_TINC_CONF_FILE = "tinc.conf" | 40 | private const val NET_TINC_CONF_FILE = "tinc.conf" |
41 | private const val NET_HOSTS_DIR = "hosts" | 41 | private const val NET_HOSTS_DIR = "hosts" |
42 | private const val NET_INVITATION_FILE = "invitation-data" | 42 | private const val NET_INVITATION_FILE = "invitation-data" |
43 | private const val NET_DEFAULT_ED25519_PRIVATE_KEY_FILE = "ed25519_key.priv" | 43 | |
44 | private const val NET_DEFAULT_RSA_PRIVATE_KEY_FILE = "rsa_key.priv" | 44 | const val NET_DEFAULT_ED25519_PRIVATE_KEY_FILE = "ed25519_key.priv" |
45 | const val NET_DEFAULT_RSA_PRIVATE_KEY_FILE = "rsa_key.priv" | ||
45 | 46 | ||
46 | private val context by lazy { App.getContext() } | 47 | private val context by lazy { App.getContext() } |
47 | 48 | ||
48 | fun storageAvailable() = | 49 | fun storageAvailable() = |
49 | Environment.getExternalStorageState().let { it == Environment.MEDIA_MOUNTED && it != Environment.MEDIA_MOUNTED_READ_ONLY } | 50 | Environment.getExternalStorageState().let { it == Environment.MEDIA_MOUNTED && it != Environment.MEDIA_MOUNTED_READ_ONLY } |
50 | 51 | ||
51 | private fun internalCacheDir() = context.cacheDir!! | 52 | fun internalCacheDir() = context.cacheDir!! |
52 | fun cacheDir() = context.externalCacheDir!! | 53 | fun cacheDir() = context.externalCacheDir!! |
53 | fun confDir() = context.getExternalFilesDir(null)!! | 54 | fun confDir() = context.getExternalFilesDir(null)!! |
54 | private fun binDir() = File(context.applicationInfo.nativeLibraryDir) | 55 | private fun binDir() = File(context.applicationInfo.nativeLibraryDir) |
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 48cb1df..c688742 100644 --- a/app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt +++ b/app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt | |||
@@ -102,12 +102,17 @@ class TincVpnService : VpnService() { | |||
102 | log.info("Starting tinc daemon for network \"$netName\".") | 102 | log.info("Starting tinc daemon for network \"$netName\".") |
103 | if (isConnected() || getCurrentNetName() != null) stopVpn().join() | 103 | if (isConnected() || getCurrentNetName() != null) stopVpn().join() |
104 | 104 | ||
105 | // FIXME: pass decrypted private keys via temp file | ||
106 | val privateKeys = try { | 105 | val privateKeys = try { |
107 | TincConfiguration.fromTincConfiguration(AppPaths.existing(AppPaths.tincConfFile(netName))).let { tincCfg -> | 106 | TincConfiguration.fromTincConfiguration(AppPaths.existing(AppPaths.tincConfFile(netName))).let { tincCfg -> |
108 | Pair( | 107 | Pair( |
109 | TincKeyring.openPrivateKey(tincCfg.ed25519PrivateKeyFile ?: AppPaths.defaultEd25519PrivateKeyFile(netName), passphrase), | 108 | TincKeyring.unlockKey( |
110 | TincKeyring.openPrivateKey(tincCfg.privateKeyFile ?: AppPaths.defaultRsaPrivateKeyFile(netName), passphrase)) | 109 | AppPaths.NET_DEFAULT_ED25519_PRIVATE_KEY_FILE, |
110 | tincCfg.ed25519PrivateKeyFile ?: AppPaths.defaultEd25519PrivateKeyFile(netName), | ||
111 | passphrase), | ||
112 | TincKeyring.unlockKey( | ||
113 | AppPaths.NET_DEFAULT_RSA_PRIVATE_KEY_FILE, | ||
114 | tincCfg.privateKeyFile ?: AppPaths.defaultRsaPrivateKeyFile(netName), | ||
115 | passphrase)) | ||
111 | } | 116 | } |
112 | } catch (e: FileNotFoundException) { | 117 | } catch (e: FileNotFoundException) { |
113 | Pair(null, null) | 118 | Pair(null, null) |
@@ -143,15 +148,12 @@ class TincVpnService : VpnService() { | |||
143 | val serverSocket = LocalServerSocket(DEVICE_FD_ABSTRACT_SOCKET) | 148 | val serverSocket = LocalServerSocket(DEVICE_FD_ABSTRACT_SOCKET) |
144 | Executor.runAsyncTask { serveDeviceFd(serverSocket, deviceFd) } | 149 | Executor.runAsyncTask { serveDeviceFd(serverSocket, deviceFd) } |
145 | 150 | ||
146 | // FIXME: pass decrypted private keys via temp file | 151 | val daemon = Tincd.start(netName, DEVICE_FD_ABSTRACT_SOCKET, privateKeys.first, privateKeys.second) |
147 | val daemon = Tincd.start(netName, DEVICE_FD_ABSTRACT_SOCKET, null, null) | ||
148 | setState(netName, passphrase, interfaceCfg, deviceFd, daemon) | 152 | setState(netName, passphrase, interfaceCfg, deviceFd, daemon) |
149 | 153 | ||
150 | waitForDaemonStartup().whenComplete { _, exception -> | 154 | waitForDaemonStartup().whenComplete { _, exception -> |
151 | serverSocket.close() | 155 | serverSocket.close() |
152 | deviceFd.close() | 156 | deviceFd.close() |
153 | privateKeys.first?.close() | ||
154 | privateKeys.second?.close() | ||
155 | 157 | ||
156 | if (exception != null) { | 158 | if (exception != null) { |
157 | reportError(resources.getString(R.string.notification_error_message_daemon_exited, exception.cause!!.defaultMessage()), exception) | 159 | reportError(resources.getString(R.string.notification_error_message_daemon_exited, exception.cause!!.defaultMessage()), exception) |
diff --git a/app/src/main/java/org/pacien/tincapp/utils/TincKeyring.kt b/app/src/main/java/org/pacien/tincapp/utils/TincKeyring.kt index bae38ac..89bb246 100644 --- a/app/src/main/java/org/pacien/tincapp/utils/TincKeyring.kt +++ b/app/src/main/java/org/pacien/tincapp/utils/TincKeyring.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,10 +18,11 @@ | |||
18 | 18 | ||
19 | package org.pacien.tincapp.utils | 19 | package org.pacien.tincapp.utils |
20 | 20 | ||
21 | import android.os.ParcelFileDescriptor | ||
22 | import org.pacien.tincapp.commands.TincApp | 21 | import org.pacien.tincapp.commands.TincApp |
22 | import org.pacien.tincapp.context.AppPaths | ||
23 | import java.io.File | 23 | import java.io.File |
24 | import java.io.FileNotFoundException | 24 | import java.io.FileNotFoundException |
25 | import java.io.FileWriter | ||
25 | 26 | ||
26 | /** | 27 | /** |
27 | * @author pacien | 28 | * @author pacien |
@@ -33,12 +34,25 @@ object TincKeyring { | |||
33 | false | 34 | false |
34 | } | 35 | } |
35 | 36 | ||
36 | fun openPrivateKey(f: File?, passphrase: String?): ParcelFileDescriptor? { | 37 | fun unlockKey(target: String, input: File?, passphrase: String?): File? { |
37 | if (f == null || !f.exists() || passphrase == null) return null | 38 | if (input == null || !input.exists() || passphrase == null) return null |
38 | val pipe = ParcelFileDescriptor.createPipe() | 39 | val decryptedKey = PemUtils.decrypt(PemUtils.read(input), passphrase) |
39 | val decryptedKey = PemUtils.decrypt(PemUtils.read(f), passphrase) | 40 | val decryptedFile = tempKey(target) |
40 | val outputStream = ParcelFileDescriptor.AutoCloseOutputStream(pipe[1]) | 41 | PemUtils.write(decryptedKey, FileWriter(decryptedFile, false)) |
41 | PemUtils.write(decryptedKey, outputStream.writer()) | 42 | return decryptedFile |
42 | return pipe[0] | 43 | } |
44 | |||
45 | private fun tempKey(name: String): File { | ||
46 | val file = File(AppPaths.internalCacheDir(), name) | ||
47 | file.createNewFile() | ||
48 | file.deleteOnExit() | ||
49 | file.makePrivate() | ||
50 | return file | ||
51 | } | ||
52 | |||
53 | private fun File.makePrivate() { | ||
54 | this.setExecutable(false, false) | ||
55 | this.setReadable(true, true) | ||
56 | this.setWritable(true, true) | ||
43 | } | 57 | } |
44 | } | 58 | } |