• 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     switch (type) {
150         case AppDistributedKv::DeviceChangeType::DEVICE_OFFLINE:
151             ZLOGD("device is offline, deviceId:%{public}s", Anonymous::Change(info.uuid).c_str());
152             EraseSensitiveByUuid(info.uuid);
153             break;
154         case AppDistributedKv::DeviceChangeType::DEVICE_ONLINE:
155             ZLOGD("device is online, deviceId:%{public}s", Anonymous::Change(info.uuid).c_str());
156             (void)GetSensitiveByUuid(info.uuid);
157             break;
158         default:
159             break;
160     }
161 }
162 
IsExits(const std::string & file) const163 bool Security::IsExits(const std::string &file) const
164 {
165     return access(file.c_str(), F_OK) == 0;
166 }
167 
GetSensitiveByUuid(const std::string & uuid) const168 Sensitive Security::GetSensitiveByUuid(const std::string &uuid) const
169 {
170     auto it = devicesUdid_.Find(uuid);
171     if (!it.first) {
172         executors_->Execute([this, uuid]() {
173             auto iter = devicesUdid_.Find(uuid);
174             if (iter.first) {
175                 return;
176             }
177             auto udid = DistributedData::DeviceManagerAdapter::GetInstance().ToUDID(uuid);
178             if (udid.empty()) {
179                 return;
180             }
181             Sensitive sensitive(udid);
182             auto level = sensitive.GetDeviceSecurityLevel();
183             ZLOGI("udid:%{public}s, uuid:%{public}s, security level:%{public}d",
184                   Anonymous::Change(udid).c_str(), Anonymous::Change(uuid).c_str(), level);
185             devicesUdid_.Insert(uuid, sensitive);
186         });
187     }
188     return it.second;
189 }
190 
EraseSensitiveByUuid(const std::string & uuid) const191 bool Security::EraseSensitiveByUuid(const std::string &uuid) const
192 {
193     devicesUdid_.Erase(uuid);
194     return true;
195 }
196 
GetCurrentUserStatus() const197 int32_t Security::GetCurrentUserStatus() const
198 {
199     return NO_PWD;
200 }
201 
SetFileSecurityOption(const std::string & filePath,const SecurityOption & option)202 DBStatus Security::SetFileSecurityOption(const std::string &filePath, const SecurityOption &option)
203 {
204     if (!IsExits(filePath)) {
205         ZLOGE("option:%{public}d file:%{public}s not exits", option.securityLabel, filePath.c_str());
206         return INVALID_ARGS;
207     }
208     if (option.securityLabel == NOT_SET) {
209         return OK;
210     }
211     auto dataLevel = Convert2Name(option);
212     if (dataLevel.empty()) {
213         ZLOGE("Invalid args! label:%{public}d path:%{public}s", option.securityLabel, filePath.c_str());
214         return INVALID_ARGS;
215     }
216 
217     bool result = OHOS::DistributedFS::ModuleSecurityLabel::SecurityLabel::SetSecurityLabel(filePath, dataLevel);
218     if (result) {
219         return OK;
220     }
221 
222     auto error = errno;
223     std::string current = OHOS::DistributedFS::ModuleSecurityLabel::SecurityLabel::GetSecurityLabel(filePath);
224     ZLOGE("failed! error:%{public}d current:%{public}s label:%{public}s file:%{public}s", error, current.c_str(),
225         dataLevel.c_str(), filePath.c_str());
226     if (current == dataLevel) {
227         return OK;
228     }
229     return DistributedDB::DB_ERROR;
230 }
231 
SetDirSecurityOption(const std::string & filePath,const SecurityOption & option)232 DBStatus Security::SetDirSecurityOption(const std::string &filePath, const SecurityOption &option)
233 {
234     ZLOGI("the filePath is a directory!");
235     (void)filePath;
236     (void)option;
237     return DBStatus::NOT_SUPPORT;
238 }
239 
GetFileSecurityOption(const std::string & filePath,SecurityOption & option) const240 DBStatus Security::GetFileSecurityOption(const std::string &filePath, SecurityOption &option) const
241 {
242     if (!IsExits(filePath)) {
243         option = {NOT_SET, ECE};
244         return OK;
245     }
246 
247     std::string value = OHOS::DistributedFS::ModuleSecurityLabel::SecurityLabel::GetSecurityLabel(filePath);
248     if (!IsXattrValueValid(value)) {
249         option = {NOT_SET, ECE};
250         return OK;
251     }
252 
253     ZLOGI("get security option %{public}s", value.c_str());
254     if (value == "s3") {
255         option = { Convert2Security(value), SECE };
256     } else {
257         option = { Convert2Security(value), ECE };
258     }
259     return OK;
260 }
261 
GetDirSecurityOption(const std::string & filePath,SecurityOption & option) const262 DBStatus Security::GetDirSecurityOption(const std::string &filePath, SecurityOption &option) const
263 {
264     ZLOGI("the filePath is a directory!");
265     (void)filePath;
266     (void)option;
267     return DBStatus::NOT_SUPPORT;
268 }
269 } // namespace OHOS::DistributedKv
270