Merge "[AWARE] Add UID checking to WifiAware network specifier"
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
index 14d855e..723828d 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
@@ -592,8 +592,6 @@
                 return true;
             }
 
-            // TODO: validate that the client ID actually comes from the correct process and is
-            // not faked?
             nnri = AwareNetworkRequestInformation.processNetworkSpecifier(networkSpecifier, mMgr);
             if (nnri == null) {
                 Log.e(TAG, "WifiAwareNetworkFactory.acceptRequest: request=" + request
@@ -903,6 +901,13 @@
                 }
             }
 
+            // validate UID
+            if (ns.requestorUid != uid) {
+                Log.e(TAG, "processNetworkSpecifier: networkSpecifier=" + ns.toString()
+                        + " -- UID mismatch to clientId's uid=" + uid);
+                return null;
+            }
+
             // create container and populate
             AwareNetworkRequestInformation nnri = new AwareNetworkRequestInformation();
             nnri.state = (ns.role == WifiAwareManager.WIFI_AWARE_DATA_PATH_ROLE_INITIATOR)
diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java
index e7a383c..a2e7c77 100644
--- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java
@@ -57,6 +57,7 @@
 import android.os.INetworkManagementService;
 import android.os.Message;
 import android.os.Messenger;
+import android.os.Process;
 import android.os.test.TestLooper;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Pair;
@@ -302,6 +303,23 @@
         testDataPathInitiatorResponderMismatchUtility(true);
     }
 
+    /**
+     * Validate the fail flow of an Initiator (subscriber) with its UID unset
+     */
+    @Test
+    public void testDataPathInitiatorUidUnsetError() throws Exception {
+        testDataPathInitiatorResponderInvalidUidUtility(false, false);
+    }
+
+    /**
+     * Validate the fail flow of an Initiator (subscriber) with its UID set as a malicious
+     * attacker (i.e. mismatched to its requested client's UID).
+     */
+    @Test
+    public void testDataPathInitiatorUidSetIncorrectlyError() throws Exception {
+        testDataPathInitiatorResponderInvalidUidUtility(false, true);
+    }
+
     /*
      * Responder tests
      */
@@ -395,6 +413,23 @@
         testDataPathInitiatorResponderMismatchUtility(false);
     }
 
+    /**
+     * Validate the fail flow of an Initiator (subscriber) with its UID unset
+     */
+    @Test
+    public void testDataPathResponderUidUnsetError() throws Exception {
+        testDataPathInitiatorResponderInvalidUidUtility(true, false);
+    }
+
+    /**
+     * Validate the fail flow of an Initiator (subscriber) with its UID set as a malicious
+     * attacker (i.e. mismatched to its requested client's UID).
+     */
+    @Test
+    public void testDataPathResponderUidSetIncorrectlyError() throws Exception {
+        testDataPathInitiatorResponderInvalidUidUtility(true, true);
+    }
+
     /*
      * Utilities
      */
@@ -428,8 +463,8 @@
                 ns.peerId,
                 ns.peerMac,
                 ns.pmk,
-                ns.passphrase
-                );
+                ns.passphrase,
+                ns.requestorUid);
         nr.networkCapabilities.setNetworkSpecifier(ns);
 
         Message reqNetworkMsg = Message.obtain();
@@ -453,6 +488,62 @@
         verifyNoMoreInteractions(mMockNative, mMockCm);
     }
 
+    private void testDataPathInitiatorResponderInvalidUidUtility(boolean doPublish,
+            boolean isUidSet) throws Exception {
+        final int clientId = 123;
+        final int pubSubId = 11234;
+        final int ndpId = 2;
+        final byte[] pmk = "some bytes".getBytes();
+        final PeerHandle peerHandle = new PeerHandle(1341234);
+        final byte[] peerDiscoveryMac = HexEncoding.decode("000102030405".toCharArray(), false);
+
+        InOrder inOrder = inOrder(mMockNative, mMockCm, mMockCallback, mMockSessionCallback);
+
+        // (0) initialize
+        Pair<Integer, Messenger> res = initDataPathEndPoint(clientId, pubSubId, peerHandle,
+                peerDiscoveryMac, inOrder, doPublish);
+
+        // (1) create network request
+        NetworkRequest nr = getSessionNetworkRequest(clientId, res.first, peerHandle, pmk,
+                doPublish);
+
+        // (2) corrupt request's UID
+        WifiAwareNetworkSpecifier ns =
+                (WifiAwareNetworkSpecifier) nr.networkCapabilities.getNetworkSpecifier();
+        ns = new WifiAwareNetworkSpecifier(
+                ns.type,
+                ns.role,
+                ns.clientId,
+                ns.sessionId,
+                ns.peerId,
+                ns.peerMac,
+                ns.pmk,
+                ns.passphrase,
+                ns.requestorUid + 1); // corruption hack
+        nr.networkCapabilities.setNetworkSpecifier(ns);
+
+        // (3) request network
+        Message reqNetworkMsg = Message.obtain();
+        reqNetworkMsg.what = NetworkFactory.CMD_REQUEST_NETWORK;
+        reqNetworkMsg.obj = nr;
+        reqNetworkMsg.arg1 = 0;
+        res.second.send(reqNetworkMsg);
+        mMockLooper.dispatchAll();
+
+        // consequences of failure:
+        //   Responder (publisher): responds with a rejection to any data-path requests
+        //   Initiator (subscribe): doesn't initiate (i.e. no HAL requests)
+        if (doPublish) {
+            // (2) get request & respond
+            mDut.onDataPathRequestNotification(pubSubId, peerDiscoveryMac, ndpId);
+            mMockLooper.dispatchAll();
+            inOrder.verify(mMockNative).respondToDataPathRequest(anyShort(), eq(false),
+                    eq(ndpId), eq(""), eq(null), eq(null), any());
+        }
+
+        verifyNoMoreInteractions(mMockNative, mMockCm);
+    }
+
     private void testDataPathInitiatorUtility(boolean useDirect, boolean provideMac,
             boolean providePmk, boolean getConfirmation, boolean immediateHalFailure)
             throws Exception {
@@ -751,7 +842,6 @@
             PeerHandle peerHandle, byte[] peerDiscoveryMac, InOrder inOrder,
             boolean doPublish)
             throws Exception {
-        final int uid = 1000;
         final int pid = 2000;
         final String callingPackage = "com.android.somePackage";
         final String someMsg = "some arbitrary message from peer";
@@ -790,7 +880,8 @@
         mMockLooper.dispatchAll();
 
         // (3) create client & session & rx message
-        mDut.connect(clientId, uid, pid, callingPackage, mMockCallback, configRequest, false);
+        mDut.connect(clientId, Process.myUid(), pid, callingPackage, mMockCallback, configRequest,
+                false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
                 eq(configRequest), eq(false), eq(true));