153c3577eSopenharmony_ci/* 253c3577eSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 353c3577eSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 453c3577eSopenharmony_ci * you may not use this file except in compliance with the License. 553c3577eSopenharmony_ci * You may obtain a copy of the License at 653c3577eSopenharmony_ci * 753c3577eSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 853c3577eSopenharmony_ci * 953c3577eSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1053c3577eSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1153c3577eSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1253c3577eSopenharmony_ci * See the License for the specific language governing permissions and 1353c3577eSopenharmony_ci * limitations under the License. 1453c3577eSopenharmony_ci */ 1553c3577eSopenharmony_ci 1653c3577eSopenharmony_ci#include "security.h" 1753c3577eSopenharmony_ci#include <regex> 1853c3577eSopenharmony_ci#include <sys/stat.h> 1953c3577eSopenharmony_ci#include <thread> 2053c3577eSopenharmony_ci#include <unistd.h> 2153c3577eSopenharmony_ci#include "dev_slinfo_mgr.h" 2253c3577eSopenharmony_ci#include "device_manager_adapter.h" 2353c3577eSopenharmony_ci#include "log_print.h" 2453c3577eSopenharmony_ci#include "security_label.h" 2553c3577eSopenharmony_ci#include "utils/anonymous.h" 2653c3577eSopenharmony_ci 2753c3577eSopenharmony_ci#undef LOG_TAG 2853c3577eSopenharmony_ci#define LOG_TAG "Security" 2953c3577eSopenharmony_cinamespace OHOS::DistributedKv { 3053c3577eSopenharmony_cinamespace { 3153c3577eSopenharmony_ci constexpr const char *SECURITY_VALUE_XATTR_PARRERN = "s([01234])"; 3253c3577eSopenharmony_ci} 3353c3577eSopenharmony_ciusing namespace DistributedDB; 3453c3577eSopenharmony_ciusing Anonymous = DistributedData::Anonymous; 3553c3577eSopenharmony_ciconst std::string Security::LABEL_VALUES[S4 + 1] = { 3653c3577eSopenharmony_ci "", "s0", "s1", "s2", "s3", "s4" 3753c3577eSopenharmony_ci}; 3853c3577eSopenharmony_ciSecurity::Security() 3953c3577eSopenharmony_ci{ 4053c3577eSopenharmony_ci ZLOGD("construct"); 4153c3577eSopenharmony_ci} 4253c3577eSopenharmony_ci 4353c3577eSopenharmony_ciSecurity::~Security() 4453c3577eSopenharmony_ci{ 4553c3577eSopenharmony_ci ZLOGD("destructor"); 4653c3577eSopenharmony_ci} 4753c3577eSopenharmony_ci 4853c3577eSopenharmony_ciAppDistributedKv::ChangeLevelType Security::GetChangeLevelType() const 4953c3577eSopenharmony_ci{ 5053c3577eSopenharmony_ci return AppDistributedKv::ChangeLevelType::LOW; 5153c3577eSopenharmony_ci} 5253c3577eSopenharmony_ci 5353c3577eSopenharmony_ciDBStatus Security::RegOnAccessControlledEvent(const OnAccessControlledEvent &callback) 5453c3577eSopenharmony_ci{ 5553c3577eSopenharmony_ci ZLOGD("add new lock status observer!"); 5653c3577eSopenharmony_ci return DBStatus::NOT_SUPPORT; 5753c3577eSopenharmony_ci} 5853c3577eSopenharmony_ci 5953c3577eSopenharmony_cibool Security::IsAccessControlled() const 6053c3577eSopenharmony_ci{ 6153c3577eSopenharmony_ci auto curStatus = GetCurrentUserStatus(); 6253c3577eSopenharmony_ci return !(curStatus == UNLOCK || curStatus == NO_PWD); 6353c3577eSopenharmony_ci} 6453c3577eSopenharmony_ci 6553c3577eSopenharmony_ciDBStatus Security::SetSecurityOption(const std::string &filePath, const SecurityOption &option) 6653c3577eSopenharmony_ci{ 6753c3577eSopenharmony_ci if (filePath.empty()) { 6853c3577eSopenharmony_ci return INVALID_ARGS; 6953c3577eSopenharmony_ci } 7053c3577eSopenharmony_ci 7153c3577eSopenharmony_ci struct stat curStat; 7253c3577eSopenharmony_ci stat(filePath.c_str(), &curStat); 7353c3577eSopenharmony_ci if (S_ISDIR(curStat.st_mode)) { 7453c3577eSopenharmony_ci return SetDirSecurityOption(filePath, option); 7553c3577eSopenharmony_ci } else { 7653c3577eSopenharmony_ci return SetFileSecurityOption(filePath, option); 7753c3577eSopenharmony_ci } 7853c3577eSopenharmony_ci} 7953c3577eSopenharmony_ci 8053c3577eSopenharmony_ciDBStatus Security::GetSecurityOption(const std::string &filePath, SecurityOption &option) const 8153c3577eSopenharmony_ci{ 8253c3577eSopenharmony_ci if (filePath.empty()) { 8353c3577eSopenharmony_ci return INVALID_ARGS; 8453c3577eSopenharmony_ci } 8553c3577eSopenharmony_ci 8653c3577eSopenharmony_ci struct stat curStat; 8753c3577eSopenharmony_ci stat(filePath.c_str(), &curStat); 8853c3577eSopenharmony_ci if (S_ISDIR(curStat.st_mode)) { 8953c3577eSopenharmony_ci return GetDirSecurityOption(filePath, option); 9053c3577eSopenharmony_ci } else { 9153c3577eSopenharmony_ci return GetFileSecurityOption(filePath, option); 9253c3577eSopenharmony_ci } 9353c3577eSopenharmony_ci} 9453c3577eSopenharmony_ci 9553c3577eSopenharmony_cibool Security::CheckDeviceSecurityAbility(const std::string &deviceId, const SecurityOption &option) const 9653c3577eSopenharmony_ci{ 9753c3577eSopenharmony_ci ZLOGD("The kvstore security level: label:%d", option.securityLabel); 9853c3577eSopenharmony_ci Sensitive sensitive = GetSensitiveByUuid(deviceId); 9953c3577eSopenharmony_ci return (sensitive >= option); 10053c3577eSopenharmony_ci} 10153c3577eSopenharmony_ci 10253c3577eSopenharmony_ciint Security::Convert2Security(const std::string &name) 10353c3577eSopenharmony_ci{ 10453c3577eSopenharmony_ci for (int i = 0; i <= S4; i++) { 10553c3577eSopenharmony_ci if (name == LABEL_VALUES[i]) { 10653c3577eSopenharmony_ci return i; 10753c3577eSopenharmony_ci } 10853c3577eSopenharmony_ci } 10953c3577eSopenharmony_ci return NOT_SET; 11053c3577eSopenharmony_ci} 11153c3577eSopenharmony_ci 11253c3577eSopenharmony_ciconst std::string Security::Convert2Name(const SecurityOption &option) 11353c3577eSopenharmony_ci{ 11453c3577eSopenharmony_ci if (option.securityLabel <= NOT_SET || option.securityLabel > S4) { 11553c3577eSopenharmony_ci return ""; 11653c3577eSopenharmony_ci } 11753c3577eSopenharmony_ci 11853c3577eSopenharmony_ci return LABEL_VALUES[option.securityLabel]; 11953c3577eSopenharmony_ci} 12053c3577eSopenharmony_ci 12153c3577eSopenharmony_cibool Security::IsXattrValueValid(const std::string& value) const 12253c3577eSopenharmony_ci{ 12353c3577eSopenharmony_ci if (value.empty()) { 12453c3577eSopenharmony_ci ZLOGD("value is empty"); 12553c3577eSopenharmony_ci return false; 12653c3577eSopenharmony_ci } 12753c3577eSopenharmony_ci 12853c3577eSopenharmony_ci return std::regex_match(value, std::regex(SECURITY_VALUE_XATTR_PARRERN)); 12953c3577eSopenharmony_ci} 13053c3577eSopenharmony_ci 13153c3577eSopenharmony_cibool Security::IsSupportSecurity() 13253c3577eSopenharmony_ci{ 13353c3577eSopenharmony_ci return false; 13453c3577eSopenharmony_ci} 13553c3577eSopenharmony_ci 13653c3577eSopenharmony_civoid Security::OnDeviceChanged(const AppDistributedKv::DeviceInfo &info, 13753c3577eSopenharmony_ci const AppDistributedKv::DeviceChangeType &type) const 13853c3577eSopenharmony_ci{ 13953c3577eSopenharmony_ci if (info.networkId.empty()) { 14053c3577eSopenharmony_ci ZLOGD("deviceId is empty"); 14153c3577eSopenharmony_ci return; 14253c3577eSopenharmony_ci } 14353c3577eSopenharmony_ci 14453c3577eSopenharmony_ci if (info.uuid == DistributedData::DeviceManagerAdapter::CLOUD_DEVICE_UUID) { 14553c3577eSopenharmony_ci ZLOGD("This is network change"); 14653c3577eSopenharmony_ci return; 14753c3577eSopenharmony_ci } 14853c3577eSopenharmony_ci 14953c3577eSopenharmony_ci switch (type) { 15053c3577eSopenharmony_ci case AppDistributedKv::DeviceChangeType::DEVICE_OFFLINE: 15153c3577eSopenharmony_ci ZLOGD("device is offline, deviceId:%{public}s", Anonymous::Change(info.uuid).c_str()); 15253c3577eSopenharmony_ci EraseSensitiveByUuid(info.uuid); 15353c3577eSopenharmony_ci break; 15453c3577eSopenharmony_ci case AppDistributedKv::DeviceChangeType::DEVICE_ONLINE: 15553c3577eSopenharmony_ci ZLOGD("device is online, deviceId:%{public}s", Anonymous::Change(info.uuid).c_str()); 15653c3577eSopenharmony_ci (void)GetSensitiveByUuid(info.uuid); 15753c3577eSopenharmony_ci break; 15853c3577eSopenharmony_ci default: 15953c3577eSopenharmony_ci break; 16053c3577eSopenharmony_ci } 16153c3577eSopenharmony_ci} 16253c3577eSopenharmony_ci 16353c3577eSopenharmony_cibool Security::IsExits(const std::string &file) const 16453c3577eSopenharmony_ci{ 16553c3577eSopenharmony_ci return access(file.c_str(), F_OK) == 0; 16653c3577eSopenharmony_ci} 16753c3577eSopenharmony_ci 16853c3577eSopenharmony_civoid Security::InitLocalSecurity() 16953c3577eSopenharmony_ci{ 17053c3577eSopenharmony_ci auto devInfo = DistributedData::DeviceManagerAdapter::GetInstance().GetLocalDevice(); 17153c3577eSopenharmony_ci GetSensitiveByUuid(devInfo.uuid); 17253c3577eSopenharmony_ci} 17353c3577eSopenharmony_ci 17453c3577eSopenharmony_ciSensitive Security::GetSensitiveByUuid(const std::string &uuid) const 17553c3577eSopenharmony_ci{ 17653c3577eSopenharmony_ci auto it = devicesUdid_.Find(uuid); 17753c3577eSopenharmony_ci if (!it.first) { 17853c3577eSopenharmony_ci executors_->Execute([this, uuid]() { 17953c3577eSopenharmony_ci auto iter = devicesUdid_.Find(uuid); 18053c3577eSopenharmony_ci if (iter.first) { 18153c3577eSopenharmony_ci return; 18253c3577eSopenharmony_ci } 18353c3577eSopenharmony_ci auto udid = DistributedData::DeviceManagerAdapter::GetInstance().ToUDID(uuid); 18453c3577eSopenharmony_ci if (udid.empty()) { 18553c3577eSopenharmony_ci return; 18653c3577eSopenharmony_ci } 18753c3577eSopenharmony_ci Sensitive sensitive(udid); 18853c3577eSopenharmony_ci auto level = sensitive.GetDeviceSecurityLevel(); 18953c3577eSopenharmony_ci ZLOGI("udid:%{public}s, uuid:%{public}s, security level:%{public}d", 19053c3577eSopenharmony_ci Anonymous::Change(udid).c_str(), Anonymous::Change(uuid).c_str(), level); 19153c3577eSopenharmony_ci devicesUdid_.Insert(uuid, sensitive); 19253c3577eSopenharmony_ci }); 19353c3577eSopenharmony_ci } 19453c3577eSopenharmony_ci return it.second; 19553c3577eSopenharmony_ci} 19653c3577eSopenharmony_ci 19753c3577eSopenharmony_cibool Security::EraseSensitiveByUuid(const std::string &uuid) const 19853c3577eSopenharmony_ci{ 19953c3577eSopenharmony_ci devicesUdid_.Erase(uuid); 20053c3577eSopenharmony_ci return true; 20153c3577eSopenharmony_ci} 20253c3577eSopenharmony_ci 20353c3577eSopenharmony_ciint32_t Security::GetCurrentUserStatus() const 20453c3577eSopenharmony_ci{ 20553c3577eSopenharmony_ci return NO_PWD; 20653c3577eSopenharmony_ci} 20753c3577eSopenharmony_ci 20853c3577eSopenharmony_ciDBStatus Security::SetFileSecurityOption(const std::string &filePath, const SecurityOption &option) 20953c3577eSopenharmony_ci{ 21053c3577eSopenharmony_ci if (!IsExits(filePath)) { 21153c3577eSopenharmony_ci ZLOGE("option:%{public}d file:%{public}s not exits", option.securityLabel, filePath.c_str()); 21253c3577eSopenharmony_ci return INVALID_ARGS; 21353c3577eSopenharmony_ci } 21453c3577eSopenharmony_ci if (option.securityLabel == NOT_SET) { 21553c3577eSopenharmony_ci return OK; 21653c3577eSopenharmony_ci } 21753c3577eSopenharmony_ci auto dataLevel = Convert2Name(option); 21853c3577eSopenharmony_ci if (dataLevel.empty()) { 21953c3577eSopenharmony_ci ZLOGE("Invalid args! label:%{public}d path:%{public}s", option.securityLabel, filePath.c_str()); 22053c3577eSopenharmony_ci return INVALID_ARGS; 22153c3577eSopenharmony_ci } 22253c3577eSopenharmony_ci 22353c3577eSopenharmony_ci bool result = OHOS::FileManagement::ModuleSecurityLabel::SecurityLabel::SetSecurityLabel(filePath, dataLevel); 22453c3577eSopenharmony_ci if (result) { 22553c3577eSopenharmony_ci return OK; 22653c3577eSopenharmony_ci } 22753c3577eSopenharmony_ci 22853c3577eSopenharmony_ci auto error = errno; 22953c3577eSopenharmony_ci std::string current = OHOS::FileManagement::ModuleSecurityLabel::SecurityLabel::GetSecurityLabel(filePath); 23053c3577eSopenharmony_ci ZLOGE("failed! error:%{public}d current:%{public}s label:%{public}s file:%{public}s", error, current.c_str(), 23153c3577eSopenharmony_ci dataLevel.c_str(), filePath.c_str()); 23253c3577eSopenharmony_ci if (current == dataLevel) { 23353c3577eSopenharmony_ci return OK; 23453c3577eSopenharmony_ci } 23553c3577eSopenharmony_ci return DistributedDB::DB_ERROR; 23653c3577eSopenharmony_ci} 23753c3577eSopenharmony_ci 23853c3577eSopenharmony_ciDBStatus Security::SetDirSecurityOption(const std::string &filePath, const SecurityOption &option) 23953c3577eSopenharmony_ci{ 24053c3577eSopenharmony_ci ZLOGI("the filePath is a directory!"); 24153c3577eSopenharmony_ci (void)filePath; 24253c3577eSopenharmony_ci (void)option; 24353c3577eSopenharmony_ci return DBStatus::NOT_SUPPORT; 24453c3577eSopenharmony_ci} 24553c3577eSopenharmony_ci 24653c3577eSopenharmony_ciDBStatus Security::GetFileSecurityOption(const std::string &filePath, SecurityOption &option) const 24753c3577eSopenharmony_ci{ 24853c3577eSopenharmony_ci if (!IsExits(filePath)) { 24953c3577eSopenharmony_ci option = {NOT_SET, ECE}; 25053c3577eSopenharmony_ci return OK; 25153c3577eSopenharmony_ci } 25253c3577eSopenharmony_ci 25353c3577eSopenharmony_ci std::string value = OHOS::FileManagement::ModuleSecurityLabel::SecurityLabel::GetSecurityLabel(filePath); 25453c3577eSopenharmony_ci if (!IsXattrValueValid(value)) { 25553c3577eSopenharmony_ci option = {NOT_SET, ECE}; 25653c3577eSopenharmony_ci return OK; 25753c3577eSopenharmony_ci } 25853c3577eSopenharmony_ci 25953c3577eSopenharmony_ci ZLOGI("get security option %{public}s", value.c_str()); 26053c3577eSopenharmony_ci if (value == "s3") { 26153c3577eSopenharmony_ci option = { Convert2Security(value), SECE }; 26253c3577eSopenharmony_ci } else { 26353c3577eSopenharmony_ci option = { Convert2Security(value), ECE }; 26453c3577eSopenharmony_ci } 26553c3577eSopenharmony_ci return OK; 26653c3577eSopenharmony_ci} 26753c3577eSopenharmony_ci 26853c3577eSopenharmony_ciDBStatus Security::GetDirSecurityOption(const std::string &filePath, SecurityOption &option) const 26953c3577eSopenharmony_ci{ 27053c3577eSopenharmony_ci ZLOGI("the filePath is a directory!"); 27153c3577eSopenharmony_ci (void)filePath; 27253c3577eSopenharmony_ci (void)option; 27353c3577eSopenharmony_ci return DBStatus::NOT_SUPPORT; 27453c3577eSopenharmony_ci} 27553c3577eSopenharmony_ci} // namespace OHOS::DistributedKv 276