• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "security.h"
17 #include <regex>
18 #include <sys/stat.h>
19 #include <thread>
20 #include <unistd.h>
21 #include "dev_slinfo_mgr.h"
22 #include "device_manager_adapter.h"
23 #include "log_print.h"
24 #include "security_label.h"
25 #include "utils/anonymous.h"
26 
27 #undef LOG_TAG
28 #define LOG_TAG "Security"
29 namespace OHOS::DistributedKv {
30 namespace {
31     constexpr const char *SECURITY_VALUE_XATTR_PARRERN = "s([01234])";
32 }
33 using namespace DistributedDB;
34 using Anonymous = DistributedData::Anonymous;
35 const std::string Security::LABEL_VALUES[S4 + 1] = {
36     "", "s0", "s1", "s2", "s3", "s4"
37 };
Security()38 Security::Security()
39 {
40     ZLOGD("construct");
41 }
42 
~Security()43 Security::~Security()
44 {
45     ZLOGD("destructor");
46 }
47 
GetChangeLevelType() const48 AppDistributedKv::ChangeLevelType Security::GetChangeLevelType() const
49 {
50     return AppDistributedKv::ChangeLevelType::LOW;
51 }
52 
RegOnAccessControlledEvent(const OnAccessControlledEvent & callback)53 DBStatus Security::RegOnAccessControlledEvent(const OnAccessControlledEvent &callback)
54 {
55     ZLOGD("add new lock status observer!");
56     return DBStatus::NOT_SUPPORT;
57 }
58 
IsAccessControlled() const59 bool Security::IsAccessControlled() const
60 {
61     auto curStatus = GetCurrentUserStatus();
62     return !(curStatus == UNLOCK || curStatus == NO_PWD);
63 }
64 
SetSecurityOption(const std::string & filePath,const SecurityOption & option)65 DBStatus Security::SetSecurityOption(const std::string &filePath, const SecurityOption &option)
66 {
67     if (filePath.empty()) {
68         return INVALID_ARGS;
69     }
70 
71     struct stat curStat;
72     stat(filePath.c_str(), &curStat);
73     if (S_ISDIR(curStat.st_mode)) {
74         return SetDirSecurityOption(filePath, option);
75     } else {
76         return SetFileSecurityOption(filePath, option);
77     }
78 }
79 
GetSecurityOption(const std::string & filePath,SecurityOption & option) const80 DBStatus Security::GetSecurityOption(const std::string &filePath, SecurityOption &option) const
81 {
82     if (filePath.empty()) {
83         return INVALID_ARGS;
84     }
85 
86     struct stat curStat;
87     stat(filePath.c_str(), &curStat);
88     if (S_ISDIR(curStat.st_mode)) {
89         return GetDirSecurityOption(filePath, option);
90     } else {
91         return GetFileSecurityOption(filePath, option);
92     }
93 }
94 
CheckDeviceSecurityAbility(const std::string & deviceId,const SecurityOption & option) const95 bool Security::CheckDeviceSecurityAbility(const std::string &deviceId, const SecurityOption &option) const
96 {
97     ZLOGD("The kvstore security level: label:%d", option.securityLabel);
98     Sensitive sensitive = GetSensitiveByUuid(deviceId);
99     return (sensitive >= option);
100 }
101 
Convert2Security(const std::string & name)102 int Security::Convert2Security(const std::string &name)
103 {
104     for (int i = 0; i <= S4; i++) {
105         if (name == LABEL_VALUES[i]) {
106             return i;
107         }
108     }
109     return NOT_SET;
110 }
111 
Convert2Name(const SecurityOption & option)112 const std::string Security::Convert2Name(const SecurityOption &option)
113 {
114     if (option.securityLabel <= NOT_SET || option.securityLabel > S4) {
115         return "";
116     }
117 
118     return LABEL_VALUES[option.securityLabel];
119 }
120 
IsXattrValueValid(const std::string & value) const121 bool Security::IsXattrValueValid(const std::string& value) const
122 {
123     if (value.empty()) {
124         ZLOGD("value is empty");
125         return false;
126     }
127 
128     return std::regex_match(value, std::regex(SECURITY_VALUE_XATTR_PARRERN));
129 }
130 
IsSupportSecurity()131 bool Security::IsSupportSecurity()
132 {
133     return false;
134 }
135 
OnDeviceChanged(const AppDistributedKv::DeviceInfo & info,const AppDistributedKv::DeviceChangeType & type) const136 void Security::OnDeviceChanged(const AppDistributedKv::DeviceInfo &info,
137                                const AppDistributedKv::DeviceChangeType &type) const
138 {
139     if (info.networkId.empty()) {
140         ZLOGD("deviceId is empty");
141         return;
142     }
143 
144     if (info.uuid == DistributedData::DeviceManagerAdapter::CLOUD_DEVICE_UUID) {
145         ZLOGD("This is network change");
146         return;
147     }
148 
149     bool isOnline = type == AppDistributedKv::DeviceChangeType::DEVICE_ONLINE;
150     if (isOnline) {
151         (void)GetSensitiveByUuid(info.uuid);
152         ZLOGD("device is online, deviceId:%{public}s", Anonymous::Change(info.uuid).c_str());
153     } else {
154         EraseSensitiveByUuid(info.uuid);
155         ZLOGD("device is offline, deviceId:%{public}s", Anonymous::Change(info.uuid).c_str());
156     }
157 }
158 
IsExits(const std::string & file) const159 bool Security::IsExits(const std::string &file) const
160 {
161     return access(file.c_str(), F_OK) == 0;
162 }
163 
GetSensitiveByUuid(const std::string & uuid) const164 Sensitive Security::GetSensitiveByUuid(const std::string &uuid) const
165 {
166     auto it = devicesUdid_.Find(uuid);
167     if (!it.first) {
168         executors_->Execute([this, uuid]() {
169             auto iter = devicesUdid_.Find(uuid);
170             if (iter.first) {
171                 return;
172             }
173             auto udid = DistributedData::DeviceManagerAdapter::GetInstance().ToUDID(uuid);
174             if (udid.empty()) {
175                 return;
176             }
177             Sensitive sensitive(udid);
178             auto level = sensitive.GetDeviceSecurityLevel();
179             ZLOGI("udid:%{public}s, uuid:%{public}s, security level:%{public}d",
180                   Anonymous::Change(udid).c_str(), Anonymous::Change(uuid).c_str(), level);
181             devicesUdid_.Insert(uuid, sensitive);
182         });
183     }
184     return it.second;
185 }
186 
EraseSensitiveByUuid(const std::string & uuid) const187 bool Security::EraseSensitiveByUuid(const std::string &uuid) const
188 {
189     devicesUdid_.Erase(uuid);
190     return true;
191 }
192 
GetCurrentUserStatus() const193 int32_t Security::GetCurrentUserStatus() const
194 {
195     return NO_PWD;
196 }
197 
SetFileSecurityOption(const std::string & filePath,const SecurityOption & option)198 DBStatus Security::SetFileSecurityOption(const std::string &filePath, const SecurityOption &option)
199 {
200     if (!IsExits(filePath)) {
201         ZLOGE("option:%{public}d file:%{public}s not exits", option.securityLabel, filePath.c_str());
202         return INVALID_ARGS;
203     }
204     if (option.securityLabel == NOT_SET) {
205         return OK;
206     }
207     auto dataLevel = Convert2Name(option);
208     if (dataLevel.empty()) {
209         ZLOGE("Invalid args! label:%{public}d path:%{public}s", option.securityLabel, filePath.c_str());
210         return INVALID_ARGS;
211     }
212 
213     bool result = OHOS::DistributedFS::ModuleSecurityLabel::SecurityLabel::SetSecurityLabel(filePath, dataLevel);
214     if (result) {
215         return OK;
216     }
217 
218     auto error = errno;
219     std::string current = OHOS::DistributedFS::ModuleSecurityLabel::SecurityLabel::GetSecurityLabel(filePath);
220     ZLOGE("failed! error:%{public}d current:%{public}s label:%{public}s file:%{public}s", error, current.c_str(),
221         dataLevel.c_str(), filePath.c_str());
222     if (current == dataLevel) {
223         return OK;
224     }
225     return DistributedDB::DB_ERROR;
226 }
227 
SetDirSecurityOption(const std::string & filePath,const SecurityOption & option)228 DBStatus Security::SetDirSecurityOption(const std::string &filePath, const SecurityOption &option)
229 {
230     ZLOGI("the filePath is a directory!");
231     (void)filePath;
232     (void)option;
233     return DBStatus::NOT_SUPPORT;
234 }
235 
GetFileSecurityOption(const std::string & filePath,SecurityOption & option) const236 DBStatus Security::GetFileSecurityOption(const std::string &filePath, SecurityOption &option) const
237 {
238     if (!IsExits(filePath)) {
239         option = {NOT_SET, ECE};
240         return OK;
241     }
242 
243     std::string value = OHOS::DistributedFS::ModuleSecurityLabel::SecurityLabel::GetSecurityLabel(filePath);
244     if (!IsXattrValueValid(value)) {
245         option = {NOT_SET, ECE};
246         return OK;
247     }
248 
249     ZLOGI("get security option %{public}s", value.c_str());
250     if (value == "s3") {
251         option = { Convert2Security(value), SECE };
252     } else {
253         option = { Convert2Security(value), ECE };
254     }
255     return OK;
256 }
257 
GetDirSecurityOption(const std::string & filePath,SecurityOption & option) const258 DBStatus Security::GetDirSecurityOption(const std::string &filePath, SecurityOption &option) const
259 {
260     ZLOGI("the filePath is a directory!");
261     (void)filePath;
262     (void)option;
263     return DBStatus::NOT_SUPPORT;
264 }
265 } // namespace OHOS::DistributedKv
266