aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt
diff options
context:
space:
mode:
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.kt41
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
7import android.os.ParcelFileDescriptor 7import android.os.ParcelFileDescriptor
8import android.util.Log 8import android.util.Log
9import org.apache.commons.configuration2.ex.ConversionException 9import org.apache.commons.configuration2.ex.ConversionException
10import org.bouncycastle.openssl.PEMException
10import org.pacien.tincapp.BuildConfig 11import org.pacien.tincapp.BuildConfig
11import org.pacien.tincapp.R 12import org.pacien.tincapp.R
12import org.pacien.tincapp.commands.Tinc 13import org.pacien.tincapp.commands.Tinc
13import org.pacien.tincapp.commands.Tincd 14import org.pacien.tincapp.commands.Tincd
14import org.pacien.tincapp.context.App 15import org.pacien.tincapp.context.App
15import org.pacien.tincapp.context.AppPaths 16import org.pacien.tincapp.context.AppPaths
17import org.pacien.tincapp.data.TincConfiguration
16import org.pacien.tincapp.data.VpnInterfaceConfiguration 18import org.pacien.tincapp.data.VpnInterfaceConfiguration
17import org.pacien.tincapp.extensions.Java.applyIgnoringException 19import org.pacien.tincapp.extensions.Java.applyIgnoringException
18import org.pacien.tincapp.extensions.VpnServiceBuilder.applyCfg 20import org.pacien.tincapp.extensions.VpnServiceBuilder.applyCfg
19import org.pacien.tincapp.intent.action.TINC_SCHEME 21import org.pacien.tincapp.intent.action.TINC_SCHEME
22import org.pacien.tincapp.utils.PemUtils
23import java.io.File
20import java.io.FileNotFoundException 24import java.io.FileNotFoundException
21import java.io.IOException 25import 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() {