From ab53484d7b7337ac6897facd74488411745041eb Mon Sep 17 00:00:00 2001 From: Jeff Vander Stoep Date: Wed, 11 Jul 2018 15:46:21 -0700 Subject: [PATCH] VpnTest: test getConnectionOwnerUid API Test connection->UID resolution for both UDP and TCP connections. Bug: 9496886 Bug: 109758967 Test: atest HostsideVpnTests Change-Id: Ic17c64df74f65d788fd3d95a25af3c5b44946881 --- .../com/android/cts/net/hostside/VpnTest.java | 49 +++++++++++++++++-- .../com/android/cts/net/HostsideVpnTests.java | 4 ++ 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java index bc982cec78..1ba701de29 100755 --- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java +++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java @@ -16,6 +16,7 @@ package com.android.cts.net.hostside; +import static android.os.Process.INVALID_UID; import static android.system.OsConstants.*; import android.content.Intent; @@ -36,6 +37,7 @@ import android.support.test.uiautomator.UiScrollable; import android.support.test.uiautomator.UiSelector; import android.system.ErrnoException; import android.system.Os; +import android.system.OsConstants; import android.system.StructPollfd; import android.test.InstrumentationTestCase; import android.test.MoreAsserts; @@ -353,7 +355,7 @@ public class VpnTest extends InstrumentationTestCase { MoreAsserts.assertEquals(data, read); } - private static void checkTcpReflection(String to, String expectedFrom) throws IOException { + private void checkTcpReflection(String to, String expectedFrom) throws IOException { // Exercise TCP over the VPN by "connecting to ourselves". We open a server socket and a // client socket, and connect the client socket to a remote host, with the port of the // server socket. The PacketReflector reflects the packets, changing the source addresses @@ -391,7 +393,8 @@ public class VpnTest extends InstrumentationTestCase { // Accept the connection on the server side. listen.setSoTimeout(SOCKET_TIMEOUT_MS); server = listen.accept(); - + checkConnectionOwnerUidTcp(client); + checkConnectionOwnerUidTcp(server); // Check that the source and peer addresses are as expected. assertEquals(expectedFrom, client.getLocalAddress().getHostAddress()); assertEquals(expectedFrom, server.getLocalAddress().getHostAddress()); @@ -424,7 +427,23 @@ public class VpnTest extends InstrumentationTestCase { } } - private static void checkUdpEcho(String to, String expectedFrom) throws IOException { + private void checkConnectionOwnerUidUdp(DatagramSocket s, boolean expectSuccess) { + final int expectedUid = expectSuccess ? Process.myUid() : INVALID_UID; + InetSocketAddress loc = new InetSocketAddress(s.getLocalAddress(), s.getLocalPort()); + InetSocketAddress rem = new InetSocketAddress(s.getInetAddress(), s.getPort()); + int uid = mCM.getConnectionOwnerUid(OsConstants.IPPROTO_UDP, loc, rem); + assertEquals(expectedUid, uid); + } + + private void checkConnectionOwnerUidTcp(Socket s) { + final int expectedUid = Process.myUid(); + InetSocketAddress loc = new InetSocketAddress(s.getLocalAddress(), s.getLocalPort()); + InetSocketAddress rem = new InetSocketAddress(s.getInetAddress(), s.getPort()); + int uid = mCM.getConnectionOwnerUid(OsConstants.IPPROTO_TCP, loc, rem); + assertEquals(expectedUid, uid); + } + + private void checkUdpEcho(String to, String expectedFrom) throws IOException { DatagramSocket s; InetAddress address = InetAddress.getByName(to); if (address instanceof Inet6Address) { // http://b/18094870 @@ -448,6 +467,7 @@ public class VpnTest extends InstrumentationTestCase { try { if (expectedFrom != null) { s.send(p); + checkConnectionOwnerUidUdp(s, true); s.receive(p); MoreAsserts.assertEquals(data, p.getData()); } else { @@ -455,7 +475,9 @@ public class VpnTest extends InstrumentationTestCase { s.send(p); s.receive(p); fail("Received unexpected reply"); - } catch(IOException expected) {} + } catch (IOException expected) { + checkConnectionOwnerUidUdp(s, false); + } } } finally { s.close(); @@ -580,4 +602,23 @@ public class VpnTest extends InstrumentationTestCase { checkNoTrafficOnVpn(); } + + public void testGetConnectionOwnerUidSecurity() throws Exception { + + if (!supportedHardware()) return; + + DatagramSocket s; + InetAddress address = InetAddress.getByName("localhost"); + s = new DatagramSocket(); + s.setSoTimeout(SOCKET_TIMEOUT_MS); + s.connect(address, 7); + InetSocketAddress loc = new InetSocketAddress(s.getLocalAddress(), s.getLocalPort()); + InetSocketAddress rem = new InetSocketAddress(s.getInetAddress(), s.getPort()); + try { + int uid = mCM.getConnectionOwnerUid(OsConstants.IPPROTO_TCP, loc, rem); + fail("Only an active VPN app may call this API."); + } catch (SecurityException expected) { + return; + } + } } diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java b/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java index 69b07af193..853668c719 100644 --- a/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java +++ b/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java @@ -44,4 +44,8 @@ public class HostsideVpnTests extends HostsideNetworkTestCase { public void testAppDisallowed() throws Exception { runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testAppDisallowed"); } + + public void testGetConnectionOwnerUidSecurity() throws Exception { + runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testGetConnectionOwnerUidSecurity"); + } }