diff options
author | pacien | 2017-09-07 14:27:37 +0200 |
---|---|---|
committer | pacien | 2017-09-07 14:27:37 +0200 |
commit | 4989dad67b68b38e75416916df406dcec908b399 (patch) | |
tree | 1857d313393788234ffa75b9203122d3ae822d3f /app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt | |
parent | 9e5aa1a9f95a3b5541aba7e511e13ae51b614416 (diff) | |
download | tincapp-4989dad67b68b38e75416916df406dcec908b399.tar.gz |
Implement encrypted private keys support
Diffstat (limited to 'app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt')
-rw-r--r-- | app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt | 41 |
1 files changed, 34 insertions, 7 deletions
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 cd1dd74..3db8dce 100644 --- a/app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt +++ b/app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt | |||
@@ -7,16 +7,20 @@ import android.net.VpnService | |||
7 | import android.os.ParcelFileDescriptor | 7 | import android.os.ParcelFileDescriptor |
8 | import android.util.Log | 8 | import android.util.Log |
9 | import org.apache.commons.configuration2.ex.ConversionException | 9 | import org.apache.commons.configuration2.ex.ConversionException |
10 | import org.bouncycastle.openssl.PEMException | ||
10 | import org.pacien.tincapp.BuildConfig | 11 | import org.pacien.tincapp.BuildConfig |
11 | import org.pacien.tincapp.R | 12 | import org.pacien.tincapp.R |
12 | import org.pacien.tincapp.commands.Tinc | 13 | import org.pacien.tincapp.commands.Tinc |
13 | import org.pacien.tincapp.commands.Tincd | 14 | import org.pacien.tincapp.commands.Tincd |
14 | import org.pacien.tincapp.context.App | 15 | import org.pacien.tincapp.context.App |
15 | import org.pacien.tincapp.context.AppPaths | 16 | import org.pacien.tincapp.context.AppPaths |
17 | import org.pacien.tincapp.data.TincConfiguration | ||
16 | import org.pacien.tincapp.data.VpnInterfaceConfiguration | 18 | import org.pacien.tincapp.data.VpnInterfaceConfiguration |
17 | import org.pacien.tincapp.extensions.Java.applyIgnoringException | 19 | import org.pacien.tincapp.extensions.Java.applyIgnoringException |
18 | import org.pacien.tincapp.extensions.VpnServiceBuilder.applyCfg | 20 | import org.pacien.tincapp.extensions.VpnServiceBuilder.applyCfg |
19 | import org.pacien.tincapp.intent.action.TINC_SCHEME | 21 | import org.pacien.tincapp.intent.action.TINC_SCHEME |
22 | import org.pacien.tincapp.utils.PemUtils | ||
23 | import java.io.File | ||
20 | import java.io.FileNotFoundException | 24 | import java.io.FileNotFoundException |
21 | import java.io.IOException | 25 | import java.io.IOException |
22 | 26 | ||
@@ -32,11 +36,11 @@ class TincVpnService : VpnService() { | |||
32 | 36 | ||
33 | override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { | 37 | override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { |
34 | if (isConnected()) stopVpn() | 38 | if (isConnected()) stopVpn() |
35 | startVpn(intent.data.schemeSpecificPart) | 39 | startVpn(intent.data.schemeSpecificPart, intent.data.fragment) |
36 | return Service.START_REDELIVER_INTENT | 40 | return Service.START_REDELIVER_INTENT |
37 | } | 41 | } |
38 | 42 | ||
39 | private fun startVpn(netName: String) { | 43 | private fun startVpn(netName: String, passphrase: String? = null) { |
40 | if (netName.isBlank()) | 44 | if (netName.isBlank()) |
41 | return reportError(resources.getString(R.string.message_no_network_name_provided), docTopic = "intent-api") | 45 | return reportError(resources.getString(R.string.message_no_network_name_provided), docTopic = "intent-api") |
42 | 46 | ||
@@ -53,7 +57,7 @@ class TincVpnService : VpnService() { | |||
53 | return reportError(resources.getString(R.string.message_network_config_invalid_format, e.message!!), e, "network-interface") | 57 | return reportError(resources.getString(R.string.message_network_config_invalid_format, e.message!!), e, "network-interface") |
54 | } | 58 | } |
55 | 59 | ||
56 | val fd = try { | 60 | val deviceFd = try { |
57 | Builder().setSession(netName) | 61 | Builder().setSession(netName) |
58 | .applyCfg(interfaceCfg) | 62 | .applyCfg(interfaceCfg) |
59 | .also { applyIgnoringException(it::addDisallowedApplication, BuildConfig.APPLICATION_ID) } | 63 | .also { applyIgnoringException(it::addDisallowedApplication, BuildConfig.APPLICATION_ID) } |
@@ -62,11 +66,34 @@ class TincVpnService : VpnService() { | |||
62 | return reportError(resources.getString(R.string.message_network_config_invalid_format, e.message!!), e, "network-interface") | 66 | return reportError(resources.getString(R.string.message_network_config_invalid_format, e.message!!), e, "network-interface") |
63 | } | 67 | } |
64 | 68 | ||
65 | Tincd.start(netName, fd!!.fd) | 69 | val privateKeys = try { |
66 | setState(true, netName, interfaceCfg, fd) | 70 | val tincCfg = TincConfiguration.fromTincConfiguration(AppPaths.existing(AppPaths.tincConfFile(netName))) |
71 | |||
72 | Pair( | ||
73 | openPrivateKey(tincCfg.ed25519PrivateKeyFile ?: AppPaths.defaultEd25519PrivateKeyFile(netName), passphrase), | ||
74 | openPrivateKey(tincCfg.privateKeyFile ?: AppPaths.defaultRsaPrivateKeyFile(netName), passphrase) | ||
75 | ) | ||
76 | } catch (e: FileNotFoundException) { | ||
77 | Pair(null, null) | ||
78 | } catch (e: PEMException) { | ||
79 | return reportError(resources.getString(R.string.message_could_not_decrypt_private_keys_format, e.message!!)) | ||
80 | } | ||
81 | |||
82 | Tincd.start(netName, deviceFd!!.fd, privateKeys.first?.fd, privateKeys.second?.fd) | ||
83 | setState(true, netName, interfaceCfg, deviceFd) | ||
67 | Log.i(TAG, "tinc daemon started.") | 84 | Log.i(TAG, "tinc daemon started.") |
68 | } | 85 | } |
69 | 86 | ||
87 | private fun openPrivateKey(f: File?, passphrase: String?): ParcelFileDescriptor? { | ||
88 | if (f == null || !f.exists() || passphrase == null) return null | ||
89 | |||
90 | val pipe = ParcelFileDescriptor.createPipe() | ||
91 | val decryptedKey = PemUtils.decrypt(PemUtils.read(f), passphrase) | ||
92 | val outputStream = ParcelFileDescriptor.AutoCloseOutputStream(pipe[1]) | ||
93 | PemUtils.write(decryptedKey, outputStream.writer()) | ||
94 | return pipe[0] | ||
95 | } | ||
96 | |||
70 | private fun reportError(msg: String, e: Throwable? = null, docTopic: String? = null) { | 97 | private fun reportError(msg: String, e: Throwable? = null, docTopic: String? = null) { |
71 | if (e != null) | 98 | if (e != null) |
72 | Log.e(TAG, msg, e) | 99 | Log.e(TAG, msg, e) |
@@ -93,9 +120,9 @@ class TincVpnService : VpnService() { | |||
93 | TincVpnService.fd = fd | 120 | TincVpnService.fd = fd |
94 | } | 121 | } |
95 | 122 | ||
96 | fun startVpn(netName: String) { | 123 | fun startVpn(netName: String, passphrase: String? = null) { |
97 | App.getContext().startService(Intent(App.getContext(), TincVpnService::class.java) | 124 | App.getContext().startService(Intent(App.getContext(), TincVpnService::class.java) |
98 | .setData(Uri.Builder().scheme(TINC_SCHEME).opaquePart(netName).build())) | 125 | .setData(Uri.Builder().scheme(TINC_SCHEME).opaquePart(netName).fragment(passphrase).build())) |
99 | } | 126 | } |
100 | 127 | ||
101 | fun stopVpn() { | 128 | fun stopVpn() { |