Home | History | Annotate | Download | only in keystore
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "keystore"
     18 
     19 #include "permissions.h"
     20 
     21 #include <cutils/log.h>
     22 #include <cutils/sockets.h>
     23 #include <private/android_filesystem_config.h>
     24 
     25 #include <selinux/android.h>
     26 
     27 #include "keystore_utils.h"
     28 
     29 /* perm_labels associcated with keystore_key SELinux class verbs. */
     30 const char* perm_labels[] = {
     31     "get_state", "get",      "insert",    "delete",    "exist",    "list",
     32     "reset",     "password", "lock",      "unlock",    "is_empty", "sign",
     33     "verify",    "grant",    "duplicate", "clear_uid", "add_auth", "user_changed",
     34 };
     35 
     36 struct user_euid {
     37     uid_t uid;
     38     uid_t euid;
     39 };
     40 
     41 user_euid user_euids[] = {
     42     {AID_VPN, AID_SYSTEM}, {AID_WIFI, AID_SYSTEM}, {AID_ROOT, AID_SYSTEM},
     43 };
     44 
     45 struct user_perm {
     46     uid_t uid;
     47     perm_t perms;
     48 };
     49 
     50 static user_perm user_perms[] = {
     51     {AID_SYSTEM, static_cast<perm_t>((uint32_t)(~0))},
     52     {AID_VPN, static_cast<perm_t>(P_GET | P_SIGN | P_VERIFY)},
     53     {AID_WIFI, static_cast<perm_t>(P_GET | P_SIGN | P_VERIFY)},
     54     {AID_ROOT, static_cast<perm_t>(P_GET)},
     55 };
     56 
     57 static const perm_t DEFAULT_PERMS = static_cast<perm_t>(P_GET_STATE | P_GET | P_INSERT | P_DELETE |
     58                                                         P_EXIST | P_LIST | P_SIGN | P_VERIFY);
     59 
     60 struct audit_data {
     61     pid_t pid;
     62     uid_t uid;
     63 };
     64 
     65 const char* get_perm_label(perm_t perm) {
     66     unsigned int index = ffs(perm);
     67     if (index > 0 && index <= (sizeof(perm_labels) / sizeof(perm_labels[0]))) {
     68         return perm_labels[index - 1];
     69     } else {
     70         ALOGE("Keystore: Failed to retrieve permission label.\n");
     71         abort();
     72     }
     73 }
     74 
     75 static int audit_callback(void* data, security_class_t /* cls */, char* buf, size_t len) {
     76     struct audit_data* ad = reinterpret_cast<struct audit_data*>(data);
     77     if (!ad) {
     78         ALOGE("No keystore audit data");
     79         return 0;
     80     }
     81 
     82     snprintf(buf, len, "pid=%d uid=%d", ad->pid, ad->uid);
     83     return 0;
     84 }
     85 
     86 static char* tctx;
     87 static int ks_is_selinux_enabled;
     88 
     89 int configure_selinux() {
     90     ks_is_selinux_enabled = is_selinux_enabled();
     91     if (ks_is_selinux_enabled) {
     92         union selinux_callback cb;
     93         cb.func_audit = audit_callback;
     94         selinux_set_callback(SELINUX_CB_AUDIT, cb);
     95         cb.func_log = selinux_log_callback;
     96         selinux_set_callback(SELINUX_CB_LOG, cb);
     97         if (getcon(&tctx) != 0) {
     98             ALOGE("SELinux: Could not acquire target context. Aborting keystore.\n");
     99             return -1;
    100         }
    101     } else {
    102         ALOGI("SELinux: Keystore SELinux is disabled.\n");
    103     }
    104 
    105     return 0;
    106 }
    107 
    108 static bool keystore_selinux_check_access(uid_t uid, perm_t perm, pid_t spid) {
    109     if (!ks_is_selinux_enabled) {
    110         return true;
    111     }
    112 
    113     audit_data ad;
    114     char* sctx = NULL;
    115     const char* selinux_class = "keystore_key";
    116     const char* str_perm = get_perm_label(perm);
    117 
    118     if (!str_perm) {
    119         return false;
    120     }
    121 
    122     if (getpidcon(spid, &sctx) != 0) {
    123         ALOGE("SELinux: Failed to get source pid context.\n");
    124         return false;
    125     }
    126 
    127     ad.pid = spid;
    128     ad.uid = uid;
    129 
    130     bool allowed = selinux_check_access(sctx, tctx, selinux_class, str_perm,
    131                                         reinterpret_cast<void*>(&ad)) == 0;
    132     freecon(sctx);
    133     return allowed;
    134 }
    135 
    136 /**
    137  * Returns the UID that the callingUid should act as. This is here for
    138  * legacy support of the WiFi and VPN systems and should be removed
    139  * when WiFi can operate in its own namespace.
    140  */
    141 uid_t get_keystore_euid(uid_t uid) {
    142     for (size_t i = 0; i < sizeof(user_euids) / sizeof(user_euids[0]); i++) {
    143         struct user_euid user = user_euids[i];
    144         if (user.uid == uid) {
    145             return user.euid;
    146         }
    147     }
    148 
    149     return uid;
    150 }
    151 
    152 bool has_permission(uid_t uid, perm_t perm, pid_t spid) {
    153     // All system users are equivalent for multi-user support.
    154     if (get_app_id(uid) == AID_SYSTEM) {
    155         uid = AID_SYSTEM;
    156     }
    157 
    158     for (size_t i = 0; i < sizeof(user_perms) / sizeof(user_perms[0]); i++) {
    159         struct user_perm user = user_perms[i];
    160         if (user.uid == uid) {
    161             return (user.perms & perm) && keystore_selinux_check_access(uid, perm, spid);
    162         }
    163     }
    164 
    165     return (DEFAULT_PERMS & perm) && keystore_selinux_check_access(uid, perm, spid);
    166 }
    167 
    168 /**
    169  * Returns true if the callingUid is allowed to interact in the targetUid's
    170  * namespace.
    171  */
    172 bool is_granted_to(uid_t callingUid, uid_t targetUid) {
    173     if (callingUid == targetUid) {
    174         return true;
    175     }
    176     for (size_t i = 0; i < sizeof(user_euids) / sizeof(user_euids[0]); i++) {
    177         struct user_euid user = user_euids[i];
    178         if (user.euid == callingUid && user.uid == targetUid) {
    179             return true;
    180         }
    181     }
    182 
    183     return false;
    184 }
    185