/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "grant_store.h" #include <algorithm> #include <sstream> namespace keystore { static constexpr uint64_t kInvalidGrantNo = std::numeric_limits<uint64_t>::max(); static const char* kKeystoreGrantInfix = "_KEYSTOREGRANT_"; static constexpr size_t kKeystoreGrantInfixLength = 15; Grant::Grant(const std::string& alias, const std::string& owner_dir_name, const uid_t owner_uid, const uint64_t grant_no) : alias_(alias), owner_dir_name_(owner_dir_name), owner_uid_(owner_uid), grant_no_(grant_no) {} static std::pair<uint64_t, std::string> parseGrantAlias(const std::string& grantAlias) { auto pos = grantAlias.rfind(kKeystoreGrantInfix); if (pos == std::string::npos) return {kInvalidGrantNo, ""}; std::stringstream s(grantAlias.substr(pos + kKeystoreGrantInfixLength)); std::string wrapped_alias = grantAlias.substr(0, pos); uint64_t grant_no = kInvalidGrantNo; s >> grant_no; if (s.fail() || grant_no == kInvalidGrantNo) return {kInvalidGrantNo, ""}; return {grant_no, wrapped_alias}; } std::string GrantStore::put(const uid_t uid, const std::string& alias, const std::string& owner_dir_name, const uid_t owner_uid) { std::stringstream s; s << alias << kKeystoreGrantInfix; auto& uid_grant_list = grants_[uid]; bool success = false; auto iterator = std::find_if(uid_grant_list.begin(), uid_grant_list.end(), [&](auto& entry) { return success = entry.alias_ == alias && entry.owner_dir_name_ == owner_dir_name && entry.owner_uid_ == owner_uid; }); while (!success) { std::tie(iterator, success) = uid_grant_list.emplace(alias, owner_dir_name, owner_uid, std::rand()); } s << iterator->grant_no_; return s.str(); } const Grant* GrantStore::get(const uid_t uid, const std::string& alias) const { uint64_t grant_no; std::string wrappedAlias; std::tie(grant_no, wrappedAlias) = parseGrantAlias(alias); if (grant_no == kInvalidGrantNo) return nullptr; auto uid_set_iter = grants_.find(uid); if (uid_set_iter == grants_.end()) return nullptr; auto& uid_grant_list = uid_set_iter->second; auto grant = uid_grant_list.find(grant_no); if (grant == uid_grant_list.end()) return nullptr; if (grant->alias_ != wrappedAlias) return nullptr; return &(*grant); } bool GrantStore::removeByFileAlias(const uid_t granteeUid, const uid_t granterUid, const std::string& alias) { auto& uid_grant_list = grants_[granteeUid]; for (auto i = uid_grant_list.begin(); i != uid_grant_list.end(); ++i) { if (i->alias_ == alias && i->owner_uid_ == granterUid) { uid_grant_list.erase(i); return true; } } return false; } void GrantStore::removeAllGrantsToKey(const uid_t granterUid, const std::string& alias) { for (auto& uid_grant_list : grants_) { for (auto i = uid_grant_list.second.begin(); i != uid_grant_list.second.end(); ++i) { if (i->alias_ == alias && i->owner_uid_ == granterUid) { uid_grant_list.second.erase(i); break; } } } } void GrantStore::removeAllGrantsToUid(const uid_t granteeUid) { grants_.erase(granteeUid); } } // namespace keystore