• 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 <unistd.h>
18 #include <thread>
19 #include <algorithm>
20 #include <regex>
21 #include "constant.h"
22 #include "log_print.h"
23 #include "device_manager_adapter.h"
24 #include "dev_slinfo_mgr.h"
25 #include "security_label.h"
26 #include "utils/anonymous.h"
27 
28 #undef LOG_TAG
29 #define LOG_TAG "Security"
30 namespace OHOS::DistributedKv {
31 namespace {
32     constexpr const char *SECURITY_VALUE_XATTR_PARRERN = "s([01234])";
33 }
34 using namespace DistributedDB;
35 using Anonymous = DistributedData::Anonymous;
36 const std::string Security::LABEL_VALUES[S4 + 1] = {
37     "", "s0", "s1", "s2", "s3", "s4"
38 };
Security()39 Security::Security()
40 {
41     ZLOGD("construct");
42 }
43 
~Security()44 Security::~Security()
45 {
46     ZLOGD("destructor");
47 }
48 
GetChangeLevelType() const49 AppDistributedKv::ChangeLevelType Security::GetChangeLevelType() const
50 {
51     return AppDistributedKv::ChangeLevelType::LOW;
52 }
53 
RegOnAccessControlledEvent(const OnAccessControlledEvent & callback)54 DBStatus Security::RegOnAccessControlledEvent(const OnAccessControlledEvent &callback)
55 {
56     ZLOGD("add new lock status observer!");
57     return DBStatus::NOT_SUPPORT;
58 }
59 
IsAccessControlled() const60 bool Security::IsAccessControlled() const
61 {
62     auto curStatus = GetCurrentUserStatus();
63     return !(curStatus == UNLOCK || curStatus == NO_PWD);
64 }
65 
SetSecurityOption(const std::string & filePath,const SecurityOption & option)66 DBStatus Security::SetSecurityOption(const std::string &filePath, const SecurityOption &option)
67 {
68     if (filePath.empty()) {
69         return INVALID_ARGS;
70     }
71 
72     struct stat curStat;
73     stat(filePath.c_str(), &curStat);
74     if (S_ISDIR(curStat.st_mode)) {
75         return SetDirSecurityOption(filePath, option);
76     } else {
77         return SetFileSecurityOption(filePath, option);
78     }
79 }
80 
GetSecurityOption(const std::string & filePath,SecurityOption & option) const81 DBStatus Security::GetSecurityOption(const std::string &filePath, SecurityOption &option) const
82 {
83     if (filePath.empty()) {
84         return INVALID_ARGS;
85     }
86 
87     struct stat curStat;
88     stat(filePath.c_str(), &curStat);
89     if (S_ISDIR(curStat.st_mode)) {
90         return GetDirSecurityOption(filePath, option);
91     } else {
92         return GetFileSecurityOption(filePath, option);
93     }
94 }
95 
CheckDeviceSecurityAbility(const std::string & deviceId,const SecurityOption & option) const96 bool Security::CheckDeviceSecurityAbility(const std::string &deviceId, const SecurityOption &option) const
97 {
98     ZLOGD("The kvstore security level: label:%d", option.securityLabel);
99     Sensitive sensitive = GetSensitiveByUuid(deviceId);
100     return (sensitive >= option);
101 }
102 
Convert2Security(const std::string & name)103 int Security::Convert2Security(const std::string &name)
104 {
105     for (int i = 0; i <= S4; i++) {
106         if (name == LABEL_VALUES[i]) {
107             return i;
108         }
109     }
110     return NOT_SET;
111 }
112 
Convert2Name(const SecurityOption & option)113 const std::string Security::Convert2Name(const SecurityOption &option)
114 {
115     if (option.securityLabel <= NOT_SET || option.securityLabel > S4) {
116         return "";
117     }
118 
119     return LABEL_VALUES[option.securityLabel];
120 }
121 
IsXattrValueValid(const std::string & value) const122 bool Security::IsXattrValueValid(const std::string& value) const
123 {
124     if (value.empty()) {
125         ZLOGD("value is empty");
126         return false;
127     }
128 
129     return std::regex_match(value, std::regex(SECURITY_VALUE_XATTR_PARRERN));
130 }
131 
IsSupportSecurity()132 bool Security::IsSupportSecurity()
133 {
134     return false;
135 }
136 
OnDeviceChanged(const AppDistributedKv::DeviceInfo & info,const AppDistributedKv::DeviceChangeType & type) const137 void Security::OnDeviceChanged(const AppDistributedKv::DeviceInfo &info,
138                                const AppDistributedKv::DeviceChangeType &type) const
139 {
140     if (info.networkId.empty()) {
141         ZLOGD("deviceId is empty");
142         return;
143     }
144 
145     bool isOnline = type == AppDistributedKv::DeviceChangeType::DEVICE_ONLINE;
146     if (isOnline) {
147         (void)GetSensitiveByUuid(info.uuid);
148         ZLOGD("device is online, deviceId:%{public}s", Anonymous::Change(info.uuid).c_str());
149     } else {
150         EraseSensitiveByUuid(info.uuid);
151         ZLOGD("device is offline, deviceId:%{public}s", Anonymous::Change(info.uuid).c_str());
152     }
153 }
154 
IsExits(const std::string & file) const155 bool Security::IsExits(const std::string &file) const
156 {
157     return access(file.c_str(), F_OK) == 0;
158 }
159 
GetSensitiveByUuid(const std::string & uuid) const160 Sensitive Security::GetSensitiveByUuid(const std::string &uuid) const
161 {
162     auto it = devicesUdid_.Find(uuid);
163     if (!it.first) {
164         taskScheduler_.Execute([this, uuid]() {
165             auto it = devicesUdid_.Find(uuid);
166             if (it.first) {
167                 return;
168             }
169             auto udid = DistributedData::DeviceManagerAdapter::GetInstance().ToUDID(uuid);
170             if (udid.empty()) {
171                 return;
172             }
173             Sensitive sensitive(udid);
174             auto level = sensitive.GetDeviceSecurityLevel();
175             ZLOGI("udid:%{public}s, uuid:%{public}s, security level:%{public}d",
176                   Anonymous::Change(udid).c_str(), Anonymous::Change(uuid).c_str(), level);
177             devicesUdid_.Insert(uuid, sensitive);
178         });
179     }
180     return it.second;
181 }
182 
EraseSensitiveByUuid(const std::string & uuid) const183 bool Security::EraseSensitiveByUuid(const std::string &uuid) const
184 {
185     devicesUdid_.Erase(uuid);
186     return true;
187 }
188 
GetCurrentUserStatus() const189 int32_t Security::GetCurrentUserStatus() const
190 {
191     return NO_PWD;
192 }
193 
SetFileSecurityOption(const std::string & filePath,const SecurityOption & option)194 DBStatus Security::SetFileSecurityOption(const std::string &filePath, const SecurityOption &option)
195 {
196     if (!IsExits(filePath)) {
197         ZLOGE("option:%{public}d file:%{public}s not exits", option.securityLabel, filePath.c_str());
198         return INVALID_ARGS;
199     }
200     if (option.securityLabel == NOT_SET) {
201         return OK;
202     }
203     auto dataLevel = Convert2Name(option);
204     if (dataLevel.empty()) {
205         ZLOGE("Invalid args! label:%{public}d path:%{public}s", option.securityLabel, filePath.c_str());
206         return INVALID_ARGS;
207     }
208 
209     bool result = OHOS::DistributedFS::ModuleSecurityLabel::SecurityLabel::SetSecurityLabel(filePath, dataLevel);
210     if (result) {
211         return OK;
212     }
213 
214     auto error = errno;
215     std::string current = OHOS::DistributedFS::ModuleSecurityLabel::SecurityLabel::GetSecurityLabel(filePath);
216     ZLOGE("failed! error:%{public}d current:%{public}s label:%{public}s file:%{public}s", error, current.c_str(),
217         dataLevel.c_str(), filePath.c_str());
218     if (current == dataLevel) {
219         return OK;
220     }
221     return DistributedDB::DB_ERROR;
222 }
223 
SetDirSecurityOption(const std::string & filePath,const SecurityOption & option)224 DBStatus Security::SetDirSecurityOption(const std::string &filePath, const SecurityOption &option)
225 {
226     ZLOGI("the filePath is a directory!");
227     (void)filePath;
228     (void)option;
229     return DBStatus::NOT_SUPPORT;
230 }
231 
GetFileSecurityOption(const std::string & filePath,SecurityOption & option) const232 DBStatus Security::GetFileSecurityOption(const std::string &filePath, SecurityOption &option) const
233 {
234     if (!IsExits(filePath)) {
235         option = {NOT_SET, ECE};
236         return OK;
237     }
238 
239     std::string value = OHOS::DistributedFS::ModuleSecurityLabel::SecurityLabel::GetSecurityLabel(filePath);
240     if (!IsXattrValueValid(value)) {
241         option = {NOT_SET, ECE};
242         return OK;
243     }
244 
245     ZLOGI("get security option %{public}s", value.c_str());
246     if (value == "s3") {
247         option = { Convert2Security(value), SECE };
248     } else {
249         option = { Convert2Security(value), ECE };
250     }
251     return OK;
252 }
253 
GetDirSecurityOption(const std::string & filePath,SecurityOption & option) const254 DBStatus Security::GetDirSecurityOption(const std::string &filePath, SecurityOption &option) const
255 {
256     ZLOGI("the filePath is a directory!");
257     (void)filePath;
258     (void)option;
259     return DBStatus::NOT_SUPPORT;
260 }
261 } // namespace OHOS::DistributedKv
262