1 /*
2 * Copyright (c) 2023 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 "visit_record_json_manager.h"
17
18 #include "accesstoken_kit.h"
19 #include "dlp_permission_log.h"
20 #include "dlp_permission.h"
21
22 namespace OHOS {
23 namespace Security {
24 namespace DlpPermission {
25 using namespace Security::AccessToken;
26 using Json = nlohmann::json;
27 using namespace OHOS;
28 namespace {
29 const std::string BUNDLENAME = "bundleName";
30 const std::string DOCURI = "docUri";
31 const std::string USERID = "userId";
32 const std::string TIMESTAMP = "timestamp";
33 const std::string RECORDLIST = "recordList";
34 const std::string ORIGINAL_TOKENID = "originalTokenId";
35 static const uint32_t MAX_RETENTION_SIZE = 1024;
36 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, SECURITY_DOMAIN_DLP_PERMISSION,
37 "VisitRecordJsonManager" };
38 }
39
VisitRecordJsonManager()40 VisitRecordJsonManager::VisitRecordJsonManager()
41 {
42 infoList_.clear();
43 }
44
~VisitRecordJsonManager()45 VisitRecordJsonManager::~VisitRecordJsonManager()
46 {
47 infoList_.clear();
48 }
49
AddVisitRecord(const std::string & bundleName,const int32_t & userId,const std::string & docUri,const int64_t timestamp,const AccessTokenID originalTokenId)50 int32_t VisitRecordJsonManager::AddVisitRecord(const std::string& bundleName, const int32_t& userId,
51 const std::string& docUri, const int64_t timestamp, const AccessTokenID originalTokenId)
52 {
53 std::lock_guard<std::mutex> lock(mutex_);
54 if (infoList_.size() > MAX_RETENTION_SIZE) {
55 DLP_LOG_ERROR(LABEL, "size bigger than MAX_RETENTION_SIZE");
56 return DLP_JSON_UPDATE_ERROR;
57 }
58 for (auto iter = infoList_.begin(); iter != infoList_.end(); ++iter) {
59 if (iter->bundleName == bundleName && iter->userId == userId && iter->docUri == docUri) {
60 infoList_.erase(iter);
61 break;
62 }
63 }
64 VisitRecordInfo info;
65 info.bundleName = bundleName;
66 info.userId = userId;
67 info.docUri = docUri;
68 info.timestamp = timestamp;
69 info.originalTokenId = originalTokenId;
70 infoList_.emplace_back(info);
71 return DLP_OK;
72 }
73
AddVisitRecord(const std::string & bundleName,const int32_t & userId,const std::string & docUri)74 int32_t VisitRecordJsonManager::AddVisitRecord(const std::string& bundleName, const int32_t& userId,
75 const std::string& docUri)
76 {
77 int64_t time =
78 std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch())
79 .count();
80 AccessTokenID originalTokenId = AccessToken::AccessTokenKit::GetHapTokenID(userId, bundleName, 0);
81 if (originalTokenId == 0) {
82 DLP_LOG_ERROR(LABEL, "Get normal tokenId error.");
83 return DLP_SERVICE_ERROR_VALUE_INVALID;
84 }
85 return AddVisitRecord(bundleName, userId, docUri, time, originalTokenId);
86 }
87
GetVisitRecordList(const std::string & bundleName,const int32_t & userId,std::vector<VisitedDLPFileInfo> & infoVec)88 int32_t VisitRecordJsonManager::GetVisitRecordList(const std::string& bundleName, const int32_t& userId,
89 std::vector<VisitedDLPFileInfo>& infoVec)
90 {
91 std::lock_guard<std::mutex> lock(mutex_);
92 if (infoList_.empty()) {
93 return DLP_FILE_NO_NEED_UPDATE;
94 }
95 AccessTokenID originalTokenId = AccessToken::AccessTokenKit::GetHapTokenID(userId, bundleName, 0);
96 if (originalTokenId == 0) {
97 DLP_LOG_ERROR(LABEL, "Get normal tokenId error.");
98 return DLP_SERVICE_ERROR_VALUE_INVALID;
99 }
100 bool isFind = false;
101 for (auto iter = infoList_.begin(); iter != infoList_.end();) {
102 if (iter->bundleName != bundleName || iter->userId != userId) {
103 ++iter;
104 continue;
105 }
106 if (iter->originalTokenId == originalTokenId) {
107 VisitedDLPFileInfo info;
108 info.docUri = iter->docUri;
109 info.visitTimestamp = iter->timestamp;
110 infoVec.emplace_back(info);
111 }
112 iter = infoList_.erase(iter);
113 isFind = true;
114 }
115 if (!isFind) {
116 DLP_LOG_INFO(LABEL, "not find bundleName:%{public}s,userId:%{public}d", bundleName.c_str(), userId);
117 return DLP_FILE_NO_NEED_UPDATE;
118 }
119 return DLP_OK;
120 }
121
122
VisitRecordInfoToJson(Json & json,const VisitRecordInfo & info) const123 void VisitRecordJsonManager::VisitRecordInfoToJson(Json& json, const VisitRecordInfo& info) const
124 {
125 json = Json { { BUNDLENAME, info.bundleName },
126 { USERID, info.userId },
127 { DOCURI, info.docUri },
128 { TIMESTAMP, info.timestamp },
129 { ORIGINAL_TOKENID, info.originalTokenId} };
130 }
131
VisitRecordInfoFromJson(const Json & json,VisitRecordInfo & info) const132 bool VisitRecordJsonManager::VisitRecordInfoFromJson(const Json& json, VisitRecordInfo& info) const
133 {
134 std::string bundleName = "";
135 std::string docUri = "";
136 int32_t userId = -1;
137 int64_t timestamp = -1;
138 AccessTokenID originalTokenId = 0;
139 if (json.contains(BUNDLENAME) && json.at(BUNDLENAME).is_string()) {
140 json.at(BUNDLENAME).get_to(bundleName);
141 }
142 if (json.contains(DOCURI) && json.at(DOCURI).is_string()) {
143 json.at(DOCURI).get_to(docUri);
144 }
145 if (json.contains(USERID) && json.at(USERID).is_number()) {
146 json.at(USERID).get_to(userId);
147 }
148 if (json.contains(TIMESTAMP) && json.at(TIMESTAMP).is_number()) {
149 json.at(TIMESTAMP).get_to(timestamp);
150 }
151 if (json.contains(ORIGINAL_TOKENID) && json.at(ORIGINAL_TOKENID).is_number()) {
152 json.at(ORIGINAL_TOKENID).get_to(originalTokenId);
153 }
154 if (bundleName.empty() || userId < 0 || docUri.empty() || timestamp < 0 || originalTokenId == 0) {
155 DLP_LOG_ERROR(LABEL, "param is invalid");
156 return false;
157 }
158 info.bundleName = bundleName;
159 info.userId = userId;
160 info.docUri = docUri;
161 info.timestamp = timestamp;
162 info.originalTokenId = originalTokenId;
163 return true;
164 }
165
ToJson() const166 Json VisitRecordJsonManager::ToJson() const
167 {
168 std::lock_guard<std::mutex> lock(mutex_);
169 Json jsonObject;
170 for (auto iter = infoList_.begin(); iter != infoList_.end(); ++iter) {
171 Json infoJson;
172 VisitRecordInfoToJson(infoJson, *iter);
173 jsonObject[RECORDLIST].push_back(infoJson);
174 }
175 return jsonObject;
176 }
177
FromJson(const Json & jsonObject)178 void VisitRecordJsonManager::FromJson(const Json& jsonObject)
179 {
180 if (jsonObject.is_null() || jsonObject.is_discarded()) {
181 DLP_LOG_ERROR(LABEL, "json error");
182 return;
183 }
184 if (!jsonObject.contains(RECORDLIST)) {
185 DLP_LOG_ERROR(LABEL, "jsonObject not contains RECORDLIST");
186 return;
187 }
188 for (const auto& json : jsonObject[RECORDLIST]) {
189 VisitRecordInfo info;
190 if (VisitRecordInfoFromJson(json, info)) {
191 AddVisitRecord(info.bundleName, info.userId, info.docUri, info.timestamp, info.originalTokenId);
192 }
193 }
194 }
195
ToString() const196 std::string VisitRecordJsonManager::ToString() const
197 {
198 {
199 std::lock_guard<std::mutex> lock(mutex_);
200 if (infoList_.empty()) {
201 return "";
202 }
203 }
204 auto jsonObject = ToJson();
205 return jsonObject.dump();
206 }
207 } // namespace DlpPermission
208 } // namespace Security
209 } // namespace OHOS
210