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.kt34
1 files changed, 28 insertions, 6 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 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() {
125 } 128 }
126 129
127 val deviceFd = try { 130 val deviceFd = try {
128 val appContextFd = Builder().setSession(netName) 131 Builder().setSession(netName)
129 .applyCfg(interfaceCfg) 132 .applyCfg(interfaceCfg)
130 .also { applyIgnoringException(it::addDisallowedApplication, BuildConfig.APPLICATION_ID) } 133 .also { applyIgnoringException(it::addDisallowedApplication, BuildConfig.APPLICATION_ID) }
131 .establish()!! 134 .establish()!!
132 val daemonContextFd = appContextFd.dup() // necessary since Android 10
133 appContextFd.close()
134 daemonContextFd
135 } catch (e: IllegalArgumentException) { 135 } catch (e: IllegalArgumentException) {
136 return reportError(resources.getString(R.string.notification_error_message_network_config_invalid_format, e.defaultMessage()), e, "network-interface") 136 return reportError(resources.getString(R.string.notification_error_message_network_config_invalid_format, e.defaultMessage()), e, "network-interface")
137 } catch (e: NullPointerException) { 137 } catch (e: NullPointerException) {
@@ -140,10 +140,15 @@ class TincVpnService : VpnService() {
140 return reportError(resources.getString(R.string.notification_error_message_could_not_configure_iface, e.defaultMessage()), e) 140 return reportError(resources.getString(R.string.notification_error_message_could_not_configure_iface, e.defaultMessage()), e)
141 } 141 }
142 142
143 val daemon = Tincd.start(netName, deviceFd.fd, privateKeys.first?.fd, privateKeys.second?.fd) 143 val serverSocket = LocalServerSocket(DEVICE_FD_ABSTRACT_SOCKET)
144 Executor.runAsyncTask { serveDeviceFd(serverSocket, deviceFd) }
145
146 // FIXME: pass decrypted private keys via temp file
147 val daemon = Tincd.start(netName, DEVICE_FD_ABSTRACT_SOCKET, null, null)
144 setState(netName, passphrase, interfaceCfg, deviceFd, daemon) 148 setState(netName, passphrase, interfaceCfg, deviceFd, daemon)
145 149
146 waitForDaemonStartup().whenComplete { _, exception -> 150 waitForDaemonStartup().whenComplete { _, exception ->
151 serverSocket.close()
147 deviceFd.close() 152 deviceFd.close()
148 privateKeys.first?.close() 153 privateKeys.first?.close()
149 privateKeys.second?.close() 154 privateKeys.second?.close()
@@ -189,6 +194,22 @@ class TincVpnService : VpnService() {
189 LocalBroadcastManager.getInstance(this).sendBroadcast(Intent(event)) 194 LocalBroadcastManager.getInstance(this).sendBroadcast(Intent(event))
190 } 195 }
191 196
197 private fun serveDeviceFd(serverSocket: LocalServerSocket, deviceFd: ParcelFileDescriptor) =
198 serverSocket.accept().let { socket ->
199 try {
200 if (socket.peerCredentials.uid != App.getApplicationInfo().uid)
201 throw AccessControlException("Peer UID mismatch.")
202
203 socket.setFileDescriptorsForSend(arrayOf(deviceFd.fileDescriptor))
204 socket.outputStream.write(0) // dummy write
205 socket.outputStream.flush()
206 } catch (e: Exception) {
207 log.error("Error while serving device fd", e)
208 } finally {
209 socket.close()
210 }
211 }
212
192 private fun waitForDaemonStartup() = 213 private fun waitForDaemonStartup() =
193 Executor 214 Executor
194 .runAsyncTask { Thread.sleep(SETUP_DELAY) } 215 .runAsyncTask { Thread.sleep(SETUP_DELAY) }
@@ -196,6 +217,7 @@ class TincVpnService : VpnService() {
196 217
197 companion object { 218 companion object {
198 private const val SETUP_DELAY = 500L // ms 219 private const val SETUP_DELAY = 500L // ms
220 private const val DEVICE_FD_ABSTRACT_SOCKET = "${BuildConfig.APPLICATION_ID}.daemon.socket"
199 221
200 private val STORE_NAME = this::class.java.`package`!!.name 222 private val STORE_NAME = this::class.java.`package`!!.name
201 private const val STORE_KEY_NETNAME = "netname" 223 private const val STORE_KEY_NETNAME = "netname"