Merge "keystore: allow system UID to WiFi or VPN"
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index 1ddf4ee..09bcf33 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -171,6 +171,11 @@
     return DEFAULT_PERMS & perm;
 }
 
+/**
+ * Returns the UID that the callingUid should act as. This is here for
+ * legacy support of the WiFi and VPN systems and should be removed
+ * when WiFi can operate in its own namespace.
+ */
 static uid_t get_keystore_euid(uid_t uid) {
     for (size_t i = 0; i < sizeof(user_euids)/sizeof(user_euids[0]); i++) {
         struct user_euid user = user_euids[i];
@@ -182,6 +187,21 @@
     return uid;
 }
 
+/**
+ * Returns true if the callingUid is allowed to interact in the targetUid's
+ * namespace.
+ */
+static bool is_granted_to(uid_t callingUid, uid_t targetUid) {
+    for (size_t i = 0; i < sizeof(user_euids)/sizeof(user_euids[0]); i++) {
+        struct user_euid user = user_euids[i];
+        if (user.euid == callingUid && user.uid == targetUid) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 /* Here is the encoding of keys. This is necessary in order to allow arbitrary
  * characters in keys. Characters in [0-~] are not encoded. Others are encoded
  * into two bytes. The first byte is one of [+-.] which represents the first
@@ -901,10 +921,10 @@
         return responseCode;
     }
 
-    // If this is the Wifi or VPN user, they actually want system
-    // UID keys.
-    if (uid == AID_WIFI || uid == AID_VPN) {
-        encode_key_for_uid(filename, AID_SYSTEM, keyName);
+    // If this is one of the legacy UID->UID mappings, use it.
+    uid_t euid = get_keystore_euid(uid);
+    if (euid != uid) {
+        encode_key_for_uid(filename, euid, keyName);
         responseCode = keyStore->get(filename, keyBlob, type);
         if (responseCode == NO_ERROR) {
             return responseCode;
@@ -949,7 +969,6 @@
             ALOGW("permission denied for %d: get", callingUid);
             return ::PERMISSION_DENIED;
         }
-        callingUid = get_keystore_euid(callingUid);
 
         State state = mKeyStore->getState();
         if (!isKeystoreUnlocked(state)) {
@@ -959,11 +978,10 @@
 
         String8 name8(name);
         char filename[NAME_MAX];
-
-        encode_key_for_uid(filename, callingUid, name8);
-
         Blob keyBlob;
-        ResponseCode responseCode = mKeyStore->get(filename, &keyBlob, TYPE_GENERIC);
+
+        ResponseCode responseCode = get_key_for_name(mKeyStore, &keyBlob, name8, callingUid,
+                TYPE_GENERIC);
         if (responseCode != ::NO_ERROR) {
             ALOGW("Could not read %s", filename);
             *item = NULL;
@@ -978,15 +996,16 @@
         return ::NO_ERROR;
     }
 
-    int32_t insert(const String16& name, const uint8_t* item, size_t itemLength, int uid) {
+    int32_t insert(const String16& name, const uint8_t* item, size_t itemLength, int targetUid) {
         uid_t callingUid = IPCThreadState::self()->getCallingUid();
         if (!has_permission(callingUid, P_INSERT)) {
             ALOGW("permission denied for %d: insert", callingUid);
             return ::PERMISSION_DENIED;
         }
-        callingUid = get_keystore_euid(callingUid);
 
-        if (uid != -1) {
+        if (targetUid == -1) {
+            targetUid = callingUid;
+        } else if (!is_granted_to(callingUid, targetUid)) {
             return ::PERMISSION_DENIED;
         }
 
@@ -999,28 +1018,29 @@
         String8 name8(name);
         char filename[NAME_MAX];
 
-        encode_key_for_uid(filename, callingUid, name8);
+        encode_key_for_uid(filename, targetUid, name8);
 
         Blob keyBlob(item, itemLength, NULL, 0, ::TYPE_GENERIC);
         return mKeyStore->put(filename, &keyBlob);
     }
 
-    int32_t del(const String16& name, int uid) {
+    int32_t del(const String16& name, int targetUid) {
         uid_t callingUid = IPCThreadState::self()->getCallingUid();
         if (!has_permission(callingUid, P_DELETE)) {
             ALOGW("permission denied for %d: del", callingUid);
             return ::PERMISSION_DENIED;
         }
-        callingUid = get_keystore_euid(callingUid);
 
-        if (uid != -1) {
+        if (targetUid == -1) {
+            targetUid = callingUid;
+        } else if (!is_granted_to(callingUid, targetUid)) {
             return ::PERMISSION_DENIED;
         }
 
         String8 name8(name);
         char filename[NAME_MAX];
 
-        encode_key_for_uid(filename, callingUid, name8);
+        encode_key_for_uid(filename, targetUid, name8);
 
         Blob keyBlob;
         ResponseCode responseCode = mKeyStore->get(filename, &keyBlob, TYPE_GENERIC);
@@ -1030,22 +1050,23 @@
         return (unlink(filename) && errno != ENOENT) ? ::SYSTEM_ERROR : ::NO_ERROR;
     }
 
-    int32_t exist(const String16& name, int uid) {
+    int32_t exist(const String16& name, int targetUid) {
         uid_t callingUid = IPCThreadState::self()->getCallingUid();
         if (!has_permission(callingUid, P_EXIST)) {
             ALOGW("permission denied for %d: exist", callingUid);
             return ::PERMISSION_DENIED;
         }
-        callingUid = get_keystore_euid(callingUid);
 
-        if (uid != -1) {
+        if (targetUid == -1) {
+            targetUid = callingUid;
+        } else if (!is_granted_to(callingUid, targetUid)) {
             return ::PERMISSION_DENIED;
         }
 
         String8 name8(name);
         char filename[NAME_MAX];
 
-        encode_key_for_uid(filename, callingUid, name8);
+        encode_key_for_uid(filename, targetUid, name8);
 
         if (access(filename, R_OK) == -1) {
             return (errno != ENOENT) ? ::SYSTEM_ERROR : ::KEY_NOT_FOUND;
@@ -1053,15 +1074,16 @@
         return ::NO_ERROR;
     }
 
-    int32_t saw(const String16& prefix, int uid, Vector<String16>* matches) {
+    int32_t saw(const String16& prefix, int targetUid, Vector<String16>* matches) {
         uid_t callingUid = IPCThreadState::self()->getCallingUid();
         if (!has_permission(callingUid, P_SAW)) {
             ALOGW("permission denied for %d: saw", callingUid);
             return ::PERMISSION_DENIED;
         }
-        callingUid = get_keystore_euid(callingUid);
 
-        if (uid != -1) {
+        if (targetUid == -1) {
+            targetUid = callingUid;
+        } else if (!is_granted_to(callingUid, targetUid)) {
             return ::PERMISSION_DENIED;
         }
 
@@ -1073,7 +1095,7 @@
         const String8 prefix8(prefix);
         char filename[NAME_MAX];
 
-        int n = encode_key_for_uid(filename, callingUid, prefix8);
+        int n = encode_key_for_uid(filename, targetUid, prefix8);
 
         struct dirent* file;
         while ((file = readdir(dir)) != NULL) {
@@ -1202,15 +1224,16 @@
         return mKeyStore->isEmpty() ? ::KEY_NOT_FOUND : ::NO_ERROR;
     }
 
-    int32_t generate(const String16& name, int uid) {
+    int32_t generate(const String16& name, int targetUid) {
         uid_t callingUid = IPCThreadState::self()->getCallingUid();
         if (!has_permission(callingUid, P_INSERT)) {
             ALOGW("permission denied for %d: generate", callingUid);
             return ::PERMISSION_DENIED;
         }
-        callingUid = get_keystore_euid(callingUid);
 
-        if (uid != -1) {
+        if (targetUid == -1) {
+            targetUid = callingUid;
+        } else if (!is_granted_to(callingUid, targetUid)) {
             return ::PERMISSION_DENIED;
         }
 
@@ -1245,7 +1268,7 @@
             return ::SYSTEM_ERROR;
         }
 
-        encode_key_for_uid(filename, callingUid, name8);
+        encode_key_for_uid(filename, targetUid, name8);
 
         Blob keyBlob(data, dataLength, NULL, 0, TYPE_KEY_PAIR);
         free(data);
@@ -1253,15 +1276,16 @@
         return mKeyStore->put(filename, &keyBlob);
     }
 
-    int32_t import(const String16& name, const uint8_t* data, size_t length, int uid) {
+    int32_t import(const String16& name, const uint8_t* data, size_t length, int targetUid) {
         uid_t callingUid = IPCThreadState::self()->getCallingUid();
         if (!has_permission(callingUid, P_INSERT)) {
             ALOGW("permission denied for %d: import", callingUid);
             return ::PERMISSION_DENIED;
         }
-        callingUid = get_keystore_euid(callingUid);
 
-        if (uid != -1) {
+        if (targetUid == -1) {
+            targetUid = callingUid;
+        } else if (!is_granted_to(callingUid, targetUid)) {
             return ::PERMISSION_DENIED;
         }
 
@@ -1274,7 +1298,7 @@
         String8 name8(name);
         char filename[NAME_MAX];
 
-        encode_key_for_uid(filename, callingUid, name8);
+        encode_key_for_uid(filename, targetUid, name8);
 
         return mKeyStore->importKey(data, length, filename);
     }
@@ -1286,7 +1310,6 @@
             ALOGW("permission denied for %d: saw", callingUid);
             return ::PERMISSION_DENIED;
         }
-        callingUid = get_keystore_euid(callingUid);
 
         State state = mKeyStore->getState();
         if (!isKeystoreUnlocked(state)) {
@@ -1338,7 +1361,6 @@
             ALOGW("permission denied for %d: verify", callingUid);
             return ::PERMISSION_DENIED;
         }
-        callingUid = get_keystore_euid(callingUid);
 
         State state = mKeyStore->getState();
         if (!isKeystoreUnlocked(state)) {
@@ -1350,7 +1372,8 @@
         String8 name8(name);
         int rc;
 
-        ResponseCode responseCode = get_key_for_name(mKeyStore, &keyBlob, name8, callingUid, TYPE_KEY_PAIR);
+        ResponseCode responseCode = get_key_for_name(mKeyStore, &keyBlob, name8, callingUid,
+                TYPE_KEY_PAIR);
         if (responseCode != ::NO_ERROR) {
             return responseCode;
         }
@@ -1394,7 +1417,6 @@
             ALOGW("permission denied for %d: get_pubkey", callingUid);
             return ::PERMISSION_DENIED;
         }
-        callingUid = get_keystore_euid(callingUid);
 
         State state = mKeyStore->getState();
         if (!isKeystoreUnlocked(state)) {
@@ -1432,22 +1454,23 @@
         return ::NO_ERROR;
     }
 
-    int32_t del_key(const String16& name, int uid) {
+    int32_t del_key(const String16& name, int targetUid) {
         uid_t callingUid = IPCThreadState::self()->getCallingUid();
         if (!has_permission(callingUid, P_DELETE)) {
             ALOGW("permission denied for %d: del_key", callingUid);
             return ::PERMISSION_DENIED;
         }
-        callingUid = get_keystore_euid(callingUid);
 
-        if (uid != -1) {
+        if (targetUid == -1) {
+            targetUid = callingUid;
+        } else if (!is_granted_to(callingUid, targetUid)) {
             return ::PERMISSION_DENIED;
         }
 
         String8 name8(name);
         char filename[NAME_MAX];
 
-        encode_key_for_uid(filename, callingUid, name8);
+        encode_key_for_uid(filename, targetUid, name8);
 
         Blob keyBlob;
         ResponseCode responseCode = mKeyStore->get(filename, &keyBlob, ::TYPE_KEY_PAIR);
@@ -1482,7 +1505,6 @@
             ALOGW("permission denied for %d: grant", callingUid);
             return ::PERMISSION_DENIED;
         }
-        callingUid = get_keystore_euid(callingUid);
 
         State state = mKeyStore->getState();
         if (!isKeystoreUnlocked(state)) {
@@ -1509,7 +1531,6 @@
             ALOGW("permission denied for %d: ungrant", callingUid);
             return ::PERMISSION_DENIED;
         }
-        callingUid = get_keystore_euid(callingUid);
 
         State state = mKeyStore->getState();
         if (!isKeystoreUnlocked(state)) {
@@ -1535,7 +1556,6 @@
             ALOGW("permission denied for %d: getmtime", callingUid);
             return -1L;
         }
-        callingUid = get_keystore_euid(callingUid);
 
         String8 name8(name);
         char filename[NAME_MAX];