1/* 2 * Copyright (C) 2017 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#include "grant_store.h" 18 19#include <algorithm> 20#include <sstream> 21 22namespace keystore { 23 24static constexpr uint64_t kInvalidGrantNo = std::numeric_limits<uint64_t>::max(); 25static const char* kKeystoreGrantInfix = "_KEYSTOREGRANT_"; 26static constexpr size_t kKeystoreGrantInfixLength = 15; 27 28Grant::Grant(const std::string& alias, const std::string& owner_dir_name, const uid_t owner_uid, 29 const uint64_t grant_no) 30 : alias_(alias), owner_dir_name_(owner_dir_name), owner_uid_(owner_uid), 31 grant_no_(grant_no) {} 32 33static std::pair<uint64_t, std::string> parseGrantAlias(const std::string& grantAlias) { 34 auto pos = grantAlias.rfind(kKeystoreGrantInfix); 35 if (pos == std::string::npos) return {kInvalidGrantNo, ""}; 36 std::stringstream s(grantAlias.substr(pos + kKeystoreGrantInfixLength)); 37 std::string wrapped_alias = grantAlias.substr(0, pos); 38 uint64_t grant_no = kInvalidGrantNo; 39 s >> grant_no; 40 if (s.fail() || grant_no == kInvalidGrantNo) return {kInvalidGrantNo, ""}; 41 return {grant_no, wrapped_alias}; 42} 43 44std::string GrantStore::put(const uid_t uid, const std::string& alias, 45 const std::string& owner_dir_name, const uid_t owner_uid) { 46 std::stringstream s; 47 s << alias << kKeystoreGrantInfix; 48 auto& uid_grant_list = grants_[uid]; 49 50 bool success = false; 51 auto iterator = std::find_if(uid_grant_list.begin(), uid_grant_list.end(), 52 [&](auto& entry) { 53 return success = entry.alias_ == alias && entry.owner_dir_name_ == owner_dir_name 54 && entry.owner_uid_ == owner_uid; 55 }); 56 while (!success) { 57 std::tie(iterator, success) = uid_grant_list.emplace(alias, owner_dir_name, owner_uid, 58 std::rand()); 59 } 60 s << iterator->grant_no_; 61 return s.str(); 62} 63 64const Grant* GrantStore::get(const uid_t uid, const std::string& alias) const { 65 uint64_t grant_no; 66 std::string wrappedAlias; 67 std::tie(grant_no, wrappedAlias) = parseGrantAlias(alias); 68 if (grant_no == kInvalidGrantNo) return nullptr; 69 auto uid_set_iter = grants_.find(uid); 70 if (uid_set_iter == grants_.end()) return nullptr; 71 auto& uid_grant_list = uid_set_iter->second; 72 auto grant = uid_grant_list.find(grant_no); 73 if (grant == uid_grant_list.end()) return nullptr; 74 if (grant->alias_ != wrappedAlias) return nullptr; 75 return &(*grant); 76} 77 78bool GrantStore::removeByFileAlias(const uid_t granteeUid, const uid_t granterUid, 79 const std::string& alias) { 80 auto& uid_grant_list = grants_[granteeUid]; 81 for (auto i = uid_grant_list.begin(); i != uid_grant_list.end(); ++i) { 82 if (i->alias_ == alias && i->owner_uid_ == granterUid) { 83 uid_grant_list.erase(i); 84 return true; 85 } 86 } 87 return false; 88} 89 90void GrantStore::removeAllGrantsToKey(const uid_t granterUid, const std::string& alias) { 91 for (auto& uid_grant_list : grants_) { 92 for (auto i = uid_grant_list.second.begin(); i != uid_grant_list.second.end(); ++i) { 93 if (i->alias_ == alias && i->owner_uid_ == granterUid) { 94 uid_grant_list.second.erase(i); 95 break; 96 } 97 } 98 } 99} 100 101void GrantStore::removeAllGrantsToUid(const uid_t granteeUid) { 102 grants_.erase(granteeUid); 103} 104 105} // namespace keystore 106