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 "dlp_credential.h"
17 #include <thread>
18 #include <unistd.h>
19 #include <unordered_map>
20 #include "account_adapt.h"
21 #include "bundle_manager_adapter.h"
22 #include "dlp_credential_client.h"
23 #include "dlp_policy_mgr_client.h"
24 #include "dlp_permission.h"
25 #include "dlp_permission_log.h"
26 #include "dlp_permission_serializer.h"
27 #include "ipc_skeleton.h"
28 #include "ohos_account_kits.h"
29 #include "os_account_manager.h"
30 #include "parameters.h"
31 #include "permission_policy.h"
32 #include "securec.h"
33
34 namespace OHOS {
35 namespace Security {
36 namespace DlpPermission {
37 using namespace OHOS::AppExecFwk;
38 namespace {
39 const std::string LOCAL_ENCRYPTED_CERT = "encryptedPolicy";
40 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_DLP_PERMISSION, "DlpCredential"};
41 const std::string PERMISSION_ACCESS_DLP_FILE = "ohos.permission.ACCESS_DLP_FILE";
42 static const size_t MAX_REQUEST_NUM = 100;
43 static const uint32_t MAX_APPID_LIST_NUM = 250;
44 static const uint32_t MAX_APPID_LENGTH = 200;
45 static const uint32_t DLP_RESTORE_POLICY_DATA_LEN = 1024 * 200;
46 static const std::string POLICY_CERT = "policyCert";
47 static const std::string DLP_MANAGER_BUNDLE_NAME = "com.ohos.dlpmanager";
48 static std::unordered_map<uint64_t, RequestInfo> g_requestMap;
49 static std::unordered_map<uint64_t, DlpAccountType> g_requestAccountTypeMap;
50 static const std::string DEVELOPER_MODE = "const.security.developermode.state";
51 std::mutex g_lockRequest;
52 std::mutex g_instanceMutex;
53 } // namespace
54
IsDlpCredentialHuksError(int errorCode)55 static bool IsDlpCredentialHuksError(int errorCode)
56 {
57 return ((errorCode >= DLP_ERR_GENERATE_KEY_FAILED) && (errorCode < DLP_ERR_IPC_INTERNAL_FAILED));
58 }
59
IsDlpCredentialIpcError(int errorCode)60 static bool IsDlpCredentialIpcError(int errorCode)
61 {
62 return ((errorCode >= DLP_ERR_IPC_INTERNAL_FAILED) && (errorCode < DLP_ERR_CONNECTION_TIME_OUT));
63 }
64
IsDlpCredentialServerError(int errorCode)65 static bool IsDlpCredentialServerError(int errorCode)
66 {
67 return ((errorCode >= DLP_ERR_CONNECTION_TIME_OUT) && (errorCode < DLP_ERR_FILE_PATH));
68 }
69
IsNoPermissionError(int errorCode)70 static bool IsNoPermissionError(int errorCode)
71 {
72 return ((errorCode == DLP_ERR_CONNECTION_VIP_RIGHT_EXPIRED) || (errorCode == DLP_ERR_CONNECTION_NO_PERMISSION));
73 }
74
IsNoInternetError(int errorCode)75 static bool IsNoInternetError(int errorCode)
76 {
77 return ((errorCode == DLP_ERR_CONNECTION_TIME_OUT) || (errorCode == DLP_ERR_TOKEN_CONNECTION_TIME_OUT) ||
78 (errorCode == DLP_ERR_TOKEN_CONNECTION_FAIL));
79 }
80
ConvertCredentialError(int errorCode)81 static int32_t ConvertCredentialError(int errorCode)
82 {
83 if (errorCode == DLP_SUCCESS) {
84 return DLP_OK;
85 }
86 if (errorCode == DLP_ERR_CONNECTION_POLICY_PERMISSION_EXPIRED) {
87 return DLP_CREDENTIAL_ERROR_TIME_EXPIRED;
88 }
89 if (errorCode == DLP_ERR_APPID_NOT_AUTHORIZED) {
90 return DLP_CREDENTIAL_ERROR_APPID_NOT_AUTHORIZED;
91 }
92 if (errorCode == DLP_ERR_CALLBACK_TIME_OUT) {
93 return DLP_CREDENTIAL_ERROR_SERVER_TIME_OUT_ERROR;
94 }
95 if (errorCode == DLP_ERR_ACCOUNT_NOT_LOG_IN) {
96 return DLP_CREDENTIAL_ERROR_NO_ACCOUNT_ERROR;
97 }
98 if (IsNoInternetError(errorCode)) {
99 return DLP_CREDENTIAL_ERROR_NO_INTERNET;
100 }
101 if (IsNoPermissionError(errorCode)) {
102 return DLP_CREDENTIAL_ERROR_NO_PERMISSION_ERROR;
103 }
104 if (IsDlpCredentialHuksError(errorCode)) {
105 return DLP_CREDENTIAL_ERROR_HUKS_ERROR;
106 }
107 if (IsDlpCredentialIpcError(errorCode)) {
108 return DLP_CREDENTIAL_ERROR_IPC_ERROR;
109 }
110 if (IsDlpCredentialServerError(errorCode)) {
111 return DLP_CREDENTIAL_ERROR_SERVER_ERROR;
112 }
113 return DLP_CREDENTIAL_ERROR_COMMON_ERROR;
114 }
115
GetCallbackFromRequestMap(uint64_t requestId,RequestInfo & info)116 static bool GetCallbackFromRequestMap(uint64_t requestId, RequestInfo& info)
117 {
118 DLP_LOG_INFO(LABEL, "Get callback, requestId: %{public}llu", static_cast<unsigned long long>(requestId));
119 std::lock_guard<std::mutex> lock(g_lockRequest);
120 auto iter = g_requestMap.find(requestId);
121 if (iter != g_requestMap.end()) {
122 info = iter->second;
123 g_requestMap.erase(requestId);
124 return true;
125 }
126 DLP_LOG_ERROR(LABEL, "Callback not found");
127 return false;
128 }
129
InsertCallbackToRequestMap(uint64_t requestId,const RequestInfo & info)130 static int32_t InsertCallbackToRequestMap(uint64_t requestId, const RequestInfo& info)
131 {
132 DLP_LOG_DEBUG(LABEL, "insert request, requestId: %{public}llu", static_cast<unsigned long long>(requestId));
133 if (g_requestMap.count(requestId) > 0) {
134 DLP_LOG_ERROR(LABEL, "Duplicate task, requestId: %{public}llu", static_cast<unsigned long long>(requestId));
135 return DLP_SERVICE_ERROR_CREDENTIAL_TASK_DUPLICATE;
136 }
137 g_requestMap[requestId] = info;
138 return DLP_OK;
139 }
140
QueryRequestIdle()141 static int32_t QueryRequestIdle()
142 {
143 DLP_LOG_DEBUG(LABEL, "Total tasks: %{public}zu", g_requestMap.size());
144 if (g_requestMap.size() > MAX_REQUEST_NUM) {
145 DLP_LOG_ERROR(LABEL, "Task busy");
146 return DLP_SERVICE_ERROR_CREDENTIAL_BUSY;
147 }
148 return DLP_OK;
149 }
150
DlpPackPolicyCallback(uint64_t requestId,int errorCode,DLP_EncPolicyData * outParams)151 static void DlpPackPolicyCallback(uint64_t requestId, int errorCode, DLP_EncPolicyData* outParams)
152 {
153 DLP_LOG_INFO(LABEL, "Called, requestId: %{public}llu", static_cast<unsigned long long>(requestId));
154 RequestInfo info;
155 if (!GetCallbackFromRequestMap(requestId, info)) {
156 DLP_LOG_ERROR(LABEL, "callback is null");
157 return;
158 }
159
160 if (errorCode != 0) {
161 DLP_LOG_ERROR(LABEL, "Pack Policy error, errorCode: %{public}d", errorCode);
162 info.callback->OnGenerateDlpCertificate(ConvertCredentialError(errorCode), std::vector<uint8_t>());
163 return;
164 }
165
166 if (outParams == nullptr || outParams->data == nullptr || outParams->featureName == nullptr) {
167 DLP_LOG_ERROR(LABEL, "Params is null");
168 info.callback->OnGenerateDlpCertificate(DLP_SERVICE_ERROR_VALUE_INVALID, std::vector<uint8_t>());
169 return;
170 }
171 unordered_json encDataJson;
172 int32_t res = DlpPermissionSerializer::GetInstance().SerializeEncPolicyData(*outParams, encDataJson);
173 if (res != DLP_OK) {
174 DLP_LOG_ERROR(LABEL, "Serialize fail");
175 return;
176 }
177 std::string encData = encDataJson.dump();
178 std::vector<uint8_t> cert(encData.begin(), encData.end());
179 info.callback->OnGenerateDlpCertificate(errorCode, cert);
180 }
181
GetNewCert(const unordered_json & plainPolicyJson,std::vector<uint8_t> & cert,DlpAccountType ownerAccountType)182 static int32_t GetNewCert(const unordered_json& plainPolicyJson, std::vector<uint8_t>& cert,
183 DlpAccountType ownerAccountType)
184 {
185 #ifdef SUPPORT_DLP_CREDENTIAL
186 unordered_json json;
187 if (plainPolicyJson.find(POLICY_CERT) == plainPolicyJson.end() || !plainPolicyJson.at(POLICY_CERT).is_object()) {
188 DLP_LOG_ERROR(LABEL, "can not found policyCert");
189 return DLP_CREDENTIAL_ERROR_SERVER_ERROR;
190 }
191 plainPolicyJson.at(POLICY_CERT).get_to(json);
192 std::string encData = json.dump();
193 DLP_EncPolicyData params;
194 params.data = reinterpret_cast<uint8_t*>(strdup(encData.c_str()));
195 if (params.data == nullptr) {
196 DLP_LOG_ERROR(LABEL, "Strdup failed.");
197 return DLP_CREDENTIAL_ERROR_VALUE_INVALID;
198 }
199 params.dataLen = encData.length();
200 params.accountType = static_cast<AccountType>(ownerAccountType);
201 unordered_json encDataJson;
202 int32_t res = DlpPermissionSerializer::GetInstance().SerializeEncPolicyData(params, encDataJson);
203 if (res != DLP_OK) {
204 DLP_LOG_ERROR(LABEL, "Serialize fail");
205 free(params.data);
206 params.data = nullptr;
207 return res;
208 }
209 free(params.data);
210 params.data = nullptr;
211 std::string encDataStr = encDataJson.dump();
212 cert.assign(encDataStr.begin(), encDataStr.end());
213 #endif
214 return DLP_OK;
215 }
216
DlpRestorePolicyCallbackCheck(sptr<IDlpPermissionCallback> callback,DlpAccountType accountType,int errorCode,DLP_RestorePolicyData * outParams,PermissionPolicy policyInfo)217 static int32_t DlpRestorePolicyCallbackCheck(sptr<IDlpPermissionCallback> callback, DlpAccountType accountType,
218 int errorCode, DLP_RestorePolicyData* outParams, PermissionPolicy policyInfo)
219 {
220 if (callback == nullptr || accountType == INVALID_ACCOUNT) {
221 DLP_LOG_ERROR(LABEL, "callback is null or accountType is 0");
222 return DLP_SERVICE_ERROR_VALUE_INVALID;
223 }
224 if (errorCode != 0) {
225 DLP_LOG_ERROR(LABEL, "Restore Policy error, errorCode: %{public}d", errorCode);
226 callback->OnParseDlpCertificate(ConvertCredentialError(errorCode), policyInfo, {});
227 return DLP_SERVICE_ERROR_VALUE_INVALID;
228 }
229 if (outParams == nullptr || outParams->data == nullptr) {
230 DLP_LOG_ERROR(LABEL, "Params is null");
231 callback->OnParseDlpCertificate(DLP_SERVICE_ERROR_VALUE_INVALID, policyInfo, {});
232 return DLP_SERVICE_ERROR_VALUE_INVALID;
233 }
234 return DLP_OK;
235 }
236
FreeBuffer(char ** buff,uint32_t buffLen)237 static void FreeBuffer(char** buff, uint32_t buffLen)
238 {
239 if (buff == nullptr) {
240 DLP_LOG_ERROR(LABEL, "Uint8 buffer is already nullptr.");
241 return;
242 }
243 if (*buff != nullptr) {
244 memset_s(*buff, buffLen, 0, buffLen);
245 delete[] *buff;
246 *buff = nullptr;
247 }
248 }
249
SetPermissionPolicy(DLP_RestorePolicyData * outParams,sptr<IDlpPermissionCallback> callback,PermissionPolicy & policyInfo,unordered_json & jsonObj)250 static bool SetPermissionPolicy(DLP_RestorePolicyData* outParams, sptr<IDlpPermissionCallback> callback,
251 PermissionPolicy& policyInfo, unordered_json& jsonObj)
252 {
253 if (outParams->dataLen > DLP_RESTORE_POLICY_DATA_LEN) {
254 DLP_LOG_ERROR(LABEL, "outParams->dataLen is out of size.");
255 return false;
256 }
257 auto policyStr = new (std::nothrow) char[outParams->dataLen + 1];
258 if (policyStr == nullptr) {
259 DLP_LOG_ERROR(LABEL, "New memory fail");
260 callback->OnParseDlpCertificate(DLP_SERVICE_ERROR_MEMORY_OPERATE_FAIL, policyInfo, {});
261 return false;
262 }
263 if (memcpy_s(policyStr, outParams->dataLen + 1, outParams->data, outParams->dataLen) != EOK) {
264 DLP_LOG_ERROR(LABEL, "Memcpy_s fail");
265 FreeBuffer(&policyStr, outParams->dataLen + 1);
266 callback->OnParseDlpCertificate(DLP_SERVICE_ERROR_MEMORY_OPERATE_FAIL, policyInfo, {});
267 return false;
268 }
269 policyStr[outParams->dataLen] = '\0';
270 jsonObj = unordered_json::parse(policyStr, policyStr + outParams->dataLen + 1, nullptr, false);
271 if (jsonObj.is_discarded() || (!jsonObj.is_object())) {
272 DLP_LOG_ERROR(LABEL, "JsonObj is discarded");
273 FreeBuffer(&policyStr, outParams->dataLen + 1);
274 callback->OnParseDlpCertificate(DLP_SERVICE_ERROR_JSON_OPERATE_FAIL, policyInfo, {});
275 return false;
276 }
277 FreeBuffer(&policyStr, outParams->dataLen + 1);
278 auto res = DlpPermissionSerializer::GetInstance().DeserializeDlpPermission(jsonObj, policyInfo);
279 if (res != DLP_OK) {
280 callback->OnParseDlpCertificate(res, policyInfo, {});
281 return false;
282 }
283 return true;
284 }
285
CheckDebugPermission(const RequestInfo & requestInfo,PermissionPolicy & policyInfo)286 static int32_t CheckDebugPermission(const RequestInfo& requestInfo, PermissionPolicy& policyInfo)
287 {
288 bool isDebugApp = (requestInfo.appProvisionType == AppExecFwk::Constants::APP_PROVISION_TYPE_DEBUG);
289 if (!isDebugApp) {
290 return DLP_OK;
291 }
292 bool isDeveloperMode = OHOS::system::GetBoolParameter(DEVELOPER_MODE, false);
293 if (isDeveloperMode && policyInfo.debug_) {
294 return DLP_OK;
295 }
296 DLP_LOG_ERROR(LABEL, "CheckDebugPermission error, isDeveloperMode=%{public}d "
297 "isDebugApp=%{public}d isDebugFile=%{public}d.", isDeveloperMode, isDebugApp, policyInfo.debug_);
298 return DLP_SERVICE_ERROR_PERMISSION_DENY;
299 }
300
DlpRestorePolicyCallback(uint64_t requestId,int errorCode,DLP_RestorePolicyData * outParams)301 static void DlpRestorePolicyCallback(uint64_t requestId, int errorCode, DLP_RestorePolicyData* outParams)
302 {
303 DLP_LOG_INFO(LABEL, "Called, requestId: %{public}llu", static_cast<unsigned long long>(requestId));
304 RequestInfo requestInfo;
305 if (!GetCallbackFromRequestMap(requestId, requestInfo)) {
306 DLP_LOG_ERROR(LABEL, "callback is null");
307 return;
308 }
309 PermissionPolicy policyInfo;
310 int32_t res = DlpRestorePolicyCallbackCheck(
311 requestInfo.callback, requestInfo.accountType, errorCode, outParams, policyInfo);
312 if (res != DLP_OK) {
313 return;
314 }
315 unordered_json jsonObj;
316 if (!SetPermissionPolicy(outParams, requestInfo.callback, policyInfo, jsonObj)) {
317 return;
318 }
319 policyInfo.ownerAccountType_ = requestInfo.accountType;
320 std::vector<uint8_t> cert;
321 res = GetNewCert(jsonObj, cert, requestInfo.accountType);
322 if (res != DLP_OK) {
323 requestInfo.callback->OnParseDlpCertificate(res, policyInfo, {});
324 return;
325 }
326 res = CheckDebugPermission(requestInfo, policyInfo);
327 if (res != DLP_OK) {
328 requestInfo.callback->OnParseDlpCertificate(res, policyInfo, {});
329 return;
330 }
331 requestInfo.callback->OnParseDlpCertificate(errorCode, policyInfo, cert);
332 }
333
GetInstance()334 DlpCredential& DlpCredential::GetInstance()
335 {
336 static DlpCredential* instance = nullptr;
337 if (instance == nullptr) {
338 std::lock_guard<std::mutex> lock(g_instanceMutex);
339 if (instance == nullptr) {
340 instance = new DlpCredential();
341 }
342 }
343 return *instance;
344 }
345
FreeDlpPackPolicyParams(DLP_PackPolicyParams & packPolicy)346 static void FreeDlpPackPolicyParams(DLP_PackPolicyParams& packPolicy)
347 {
348 if (packPolicy.featureName != nullptr) {
349 free(packPolicy.featureName);
350 packPolicy.featureName = nullptr;
351 }
352 if (packPolicy.data != nullptr) {
353 free(packPolicy.data);
354 packPolicy.data = nullptr;
355 }
356 if (packPolicy.senderAccountInfo.accountId != nullptr) {
357 free(packPolicy.senderAccountInfo.accountId);
358 packPolicy.senderAccountInfo.accountId = nullptr;
359 }
360 }
361
DlpCredential()362 DlpCredential::DlpCredential()
363 {}
364
PackPolicy(DLP_PackPolicyParams & packPolicy,DlpAccountType accountType,const sptr<IDlpPermissionCallback> & callback)365 static int32_t PackPolicy(DLP_PackPolicyParams &packPolicy, DlpAccountType accountType,
366 const sptr<IDlpPermissionCallback>& callback)
367 {
368 uint64_t requestId;
369 int32_t res = DLP_PackPolicy(GetCallingUserId(), &packPolicy, DlpPackPolicyCallback, &requestId);
370 if (res != 0) {
371 DLP_LOG_ERROR(LABEL, "Start request fail, error: %{public}d", res);
372 return ConvertCredentialError(res);
373 }
374 DLP_LOG_INFO(
375 LABEL, "Start request success, requestId: %{public}llu", static_cast<unsigned long long>(requestId));
376 RequestInfo info = {
377 .callback = callback,
378 .accountType = accountType
379 };
380 return InsertCallbackToRequestMap(requestId, info);
381 }
382
GenerateDlpCertificate(const std::string & policy,const std::string & accountInfo,DlpAccountType accountType,const sptr<IDlpPermissionCallback> & callback)383 int32_t DlpCredential::GenerateDlpCertificate(const std::string& policy, const std::string& accountInfo,
384 DlpAccountType accountType, const sptr<IDlpPermissionCallback>& callback)
385 {
386 EncAndDecOptions encAndDecOptions = {
387 .opt = RECEIVER_DECRYPT_MUST_USE_CLOUD,
388 .extraInfo = nullptr,
389 .extraInfoLen = 0
390 };
391
392 AccountInfo accountCfg = {
393 .accountId = reinterpret_cast<uint8_t*>(strdup(accountInfo.c_str())),
394 .accountIdLen = accountInfo.size(),
395 };
396 if (accountCfg.accountId == nullptr) {
397 DLP_LOG_ERROR(LABEL, "Strdup failed.");
398 return DLP_PARSE_ERROR_ACCOUNT_INVALID;
399 }
400
401 DLP_PackPolicyParams packPolicy = {
402 .featureName = strdup("dlp_permission_service"),
403 .data = reinterpret_cast<uint8_t*>(strdup(policy.c_str())),
404 .dataLen = policy.size(),
405 .options = encAndDecOptions,
406 .accountType = static_cast<AccountType>(accountType),
407 .senderAccountInfo = accountCfg,
408 .reserved = {0},
409 };
410 if (packPolicy.featureName == nullptr || packPolicy.data == nullptr) {
411 DLP_LOG_ERROR(LABEL, "Strdup failed.");
412 free(accountCfg.accountId);
413 accountCfg.accountId = nullptr;
414 FreeDlpPackPolicyParams(packPolicy);
415 return DLP_PARSE_ERROR_ACCOUNT_INVALID;
416 }
417 int32_t res = 0;
418 {
419 std::lock_guard<std::mutex> lock(g_lockRequest);
420 int32_t status = QueryRequestIdle();
421 if (status != DLP_OK) {
422 FreeDlpPackPolicyParams(packPolicy);
423 return status;
424 }
425 res = PackPolicy(packPolicy, accountType, callback);
426 }
427 FreeDlpPackPolicyParams(packPolicy);
428 return res;
429 }
430
FreeDLPEncPolicyData(DLP_EncPolicyData & encPolicy)431 static void FreeDLPEncPolicyData(DLP_EncPolicyData& encPolicy)
432 {
433 if (encPolicy.featureName != nullptr) {
434 free(encPolicy.featureName);
435 encPolicy.featureName = nullptr;
436 }
437 if (encPolicy.data != nullptr) {
438 delete[] encPolicy.data;
439 encPolicy.data = nullptr;
440 }
441 if (encPolicy.options.extraInfo != nullptr) {
442 delete[] encPolicy.options.extraInfo;
443 encPolicy.options.extraInfo = nullptr;
444 }
445 if (encPolicy.receiverAccountInfo.accountId != nullptr) {
446 free(encPolicy.receiverAccountInfo.accountId);
447 encPolicy.receiverAccountInfo.accountId = nullptr;
448 }
449 }
450
GetLocalAccountName(std::string & account,const std::string & contactAccount,bool * isOwner)451 static int32_t GetLocalAccountName(std::string& account, const std::string& contactAccount, bool* isOwner)
452 {
453 std::pair<bool, AccountSA::OhosAccountInfo> accountInfo =
454 AccountSA::OhosAccountKits::GetInstance().QueryOhosAccountInfo();
455 if (accountInfo.first) {
456 account = accountInfo.second.uid_;
457 if (contactAccount.compare("") != 0 && contactAccount.compare(accountInfo.second.name_) == 0) {
458 *isOwner = true;
459 }
460 return DLP_OK;
461 }
462 return DLP_PARSE_ERROR_ACCOUNT_INVALID;
463 }
464
GetDomainAccountName(std::string & account,const std::string & contactAccount,bool * isOwner)465 static int32_t GetDomainAccountName(std::string& account, const std::string& contactAccount, bool* isOwner)
466 {
467 int32_t userId;
468 int32_t res = OHOS::AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(userId);
469 if (res != 0) {
470 DLP_LOG_ERROR(LABEL, "GetForegroundOsAccountLocalId failed %{public}d", res);
471 return DLP_PARSE_ERROR_ACCOUNT_INVALID;
472 }
473 AccountSA::OsAccountInfo osAccountInfo;
474 if (OHOS::AccountSA::OsAccountManager::QueryOsAccountById(userId, osAccountInfo) != 0) {
475 DLP_LOG_ERROR(LABEL, "GetOsAccountLocalIdFromDomain return not 0");
476 return DLP_PARSE_ERROR_ACCOUNT_INVALID;
477 }
478 AccountSA::DomainAccountInfo domainInfo;
479 osAccountInfo.GetDomainInfo(domainInfo);
480 if (domainInfo.accountName_.empty()) {
481 DLP_LOG_ERROR(LABEL, "accountName_ empty");
482 return DLP_PARSE_ERROR_ACCOUNT_INVALID;
483 }
484 if (contactAccount.compare("") != 0 && contactAccount.compare(domainInfo.accountName_) == 0) {
485 *isOwner = true;
486 }
487 account = domainInfo.accountId_;
488 return DLP_OK;
489 }
490
GetAccoutInfo(DlpAccountType accountType,AccountInfo & accountCfg,const std::string & contactAccount,bool * isOwner)491 static int32_t GetAccoutInfo(DlpAccountType accountType, AccountInfo& accountCfg,
492 const std::string& contactAccount, bool* isOwner)
493 {
494 std::string account;
495 if (accountType == DOMAIN_ACCOUNT) {
496 if (GetDomainAccountName(account, contactAccount, isOwner) != DLP_OK) {
497 DLP_LOG_ERROR(LABEL, "query GetDomainAccountName failed");
498 accountCfg = {
499 .accountId = nullptr,
500 .accountIdLen = 0,
501 };
502 return DLP_OK;
503 }
504 } else {
505 if (GetLocalAccountName(account, contactAccount, isOwner) != DLP_OK) {
506 DLP_LOG_ERROR(LABEL, "query GetLocalAccountName failed");
507 return DLP_PARSE_ERROR_ACCOUNT_INVALID;
508 }
509 }
510
511 accountCfg = {
512 .accountId = reinterpret_cast<uint8_t*>(strdup(account.c_str())),
513 .accountIdLen = account.size(),
514 };
515 if (accountCfg.accountId == nullptr) {
516 DLP_LOG_ERROR(LABEL, "Strdup failed.");
517 return DLP_CREDENTIAL_ERROR_VALUE_INVALID;
518 }
519 return DLP_OK;
520 }
521
AdapterData(const std::vector<uint8_t> & offlineCert,bool isOwner,unordered_json jsonObj,DLP_EncPolicyData & encPolicy)522 static int32_t AdapterData(const std::vector<uint8_t>& offlineCert, bool isOwner, unordered_json jsonObj,
523 DLP_EncPolicyData& encPolicy)
524 {
525 DLP_LOG_DEBUG(LABEL, "enter");
526 unordered_json offlineJsonObj;
527 if (!offlineCert.empty()) {
528 std::string offlineEncDataJsonStr(offlineCert.begin(), offlineCert.end());
529 offlineJsonObj = unordered_json::parse(offlineEncDataJsonStr, nullptr, false);
530 if (offlineJsonObj.is_discarded()) {
531 DLP_LOG_ERROR(LABEL, "offlineJsonObj is discarded");
532 return DLP_SERVICE_ERROR_JSON_OPERATE_FAIL;
533 }
534 }
535 std::string ownerAccountId = "";
536 if (isOwner) {
537 std::string temp(reinterpret_cast<const char*>(encPolicy.receiverAccountInfo.accountId));
538 ownerAccountId = temp;
539 }
540 int32_t result = DlpPermissionSerializer::GetInstance().DeserializeEncPolicyDataByFirstVersion(jsonObj,
541 offlineJsonObj, encPolicy, ownerAccountId);
542 if (result != DLP_OK) {
543 FreeDLPEncPolicyData(encPolicy);
544 return result;
545 }
546 return DLP_OK;
547 }
548
InitEncPolicyData(EncAndDecOptions & options,DLP_EncPolicyData & encPolicy,const bool offlineAccess,const std::string & appId)549 static int32_t InitEncPolicyData(EncAndDecOptions& options, DLP_EncPolicyData& encPolicy, const bool offlineAccess,
550 const std::string& appId)
551 {
552 options = {.opt = CloudEncOption::RECEIVER_DECRYPT_MUST_USE_CLOUD, .extraInfo = nullptr};
553 if (offlineAccess) {
554 options.opt = CloudEncOption::RECEIVER_DECRYPT_MUST_USE_CLOUD_AND_RETURN_ENCRYPTION_VALUE;
555 }
556 encPolicy = {
557 .featureName = strdup(const_cast<char *>(appId.c_str())),
558 .options = options,
559 .reserved = {0},
560 };
561 if (encPolicy.featureName == nullptr) {
562 DLP_LOG_ERROR(LABEL, "Strdup failed.");
563 return DLP_CREDENTIAL_ERROR_VALUE_INVALID;
564 }
565 return DLP_OK;
566 }
567
RestorePolicy(DLP_EncPolicyData & encPolicy,AppExecFwk::ApplicationInfo & applicationInfo,const sptr<IDlpPermissionCallback> & callback,DlpAccountType accountType)568 static int32_t RestorePolicy(DLP_EncPolicyData &encPolicy, AppExecFwk::ApplicationInfo& applicationInfo,
569 const sptr<IDlpPermissionCallback>& callback, DlpAccountType accountType)
570 {
571 uint64_t requestId;
572 int32_t res = DLP_RestorePolicy(GetCallingUserId(), &encPolicy, DlpRestorePolicyCallback, &requestId);
573 if (res != 0) {
574 DLP_LOG_ERROR(LABEL, "Start request fail, error: %{public}d", res);
575 return ConvertCredentialError(res);
576 }
577 DLP_LOG_INFO(
578 LABEL, "Start request success, requestId: %{public}llu", static_cast<unsigned long long>(requestId));
579 RequestInfo info = {
580 .callback = callback,
581 .accountType = accountType,
582 .appProvisionType = applicationInfo.appProvisionType
583 };
584 return InsertCallbackToRequestMap(requestId, info);
585 }
586
ParseDlpCertificate(sptr<CertParcel> & certParcel,const sptr<IDlpPermissionCallback> & callback,const std::string & appId,const bool & offlineAccess,AppExecFwk::ApplicationInfo & applicationInfo)587 int32_t DlpCredential::ParseDlpCertificate(sptr<CertParcel>& certParcel, const sptr<IDlpPermissionCallback>& callback,
588 const std::string& appId, const bool& offlineAccess, AppExecFwk::ApplicationInfo& applicationInfo)
589 {
590 std::string encDataJsonStr(certParcel->cert.begin(), certParcel->cert.end());
591 auto jsonObj = unordered_json::parse(encDataJsonStr, nullptr, false);
592 if (jsonObj.is_discarded() || (!jsonObj.is_object())) {
593 DLP_LOG_ERROR(LABEL, "JsonObj is discarded");
594 return DLP_SERVICE_ERROR_JSON_OPERATE_FAIL;
595 }
596 EncAndDecOptions options;
597 DLP_EncPolicyData encPolicy;
598 int32_t ret = InitEncPolicyData(options, encPolicy, offlineAccess, appId);
599 if (ret != DLP_OK) {
600 return ret;
601 }
602 int32_t result =
603 DlpPermissionSerializer::GetInstance().DeserializeEncPolicyData(jsonObj, encPolicy, certParcel->isNeedAdapter);
604 auto accountType = static_cast<DlpAccountType>(encPolicy.accountType);
605 if (result != DLP_OK) {
606 FreeDLPEncPolicyData(encPolicy);
607 return DLP_SERVICE_ERROR_JSON_OPERATE_FAIL;
608 }
609 bool isOwner = false;
610 int32_t infoRet = GetAccoutInfo(accountType, encPolicy.receiverAccountInfo, certParcel->contactAccount, &isOwner);
611 if (infoRet != DLP_OK) {
612 FreeDLPEncPolicyData(encPolicy);
613 return infoRet;
614 }
615 if (certParcel->isNeedAdapter) {
616 AdapterData(certParcel->offlineCert, isOwner, jsonObj, encPolicy);
617 }
618 int32_t res = 0;
619 {
620 std::lock_guard<std::mutex> lock(g_lockRequest);
621 int32_t status = QueryRequestIdle();
622 if (status != DLP_OK) {
623 FreeDLPEncPolicyData(encPolicy);
624 return status;
625 }
626 res = RestorePolicy(encPolicy, applicationInfo, callback, accountType);
627 }
628 FreeDLPEncPolicyData(encPolicy);
629 return res;
630 }
631
ParseStringVectorToUint8TypedArray(const std::vector<std::string> & appIdList,uint8_t * policy,uint32_t policySize)632 int32_t ParseStringVectorToUint8TypedArray(const std::vector<std::string>& appIdList, uint8_t *policy,
633 uint32_t policySize)
634 {
635 uint32_t count = static_cast<uint32_t>(appIdList.size());
636 if (memcpy_s(policy, policySize, &count, sizeof(uint32_t)) != EOK) {
637 DLP_LOG_ERROR(LABEL, "Memcpy policy fail");
638 return DLP_CREDENTIAL_ERROR_MEMORY_OPERATE_FAIL;
639 }
640 int32_t offset = sizeof(uint32_t);
641 for (int32_t i = 0; i < static_cast<int32_t>(appIdList.size()); i++) {
642 if (appIdList[i].empty()) {
643 DLP_LOG_ERROR(LABEL, "Empty appId");
644 return DLP_SERVICE_ERROR_VALUE_INVALID;
645 }
646 char *appId = const_cast<char *>(appIdList[i].c_str());
647 uint32_t length = static_cast<uint32_t>(strlen(appId));
648 if (length > MAX_APPID_LENGTH) {
649 DLP_LOG_ERROR(LABEL, "AppId longer than limit");
650 return DLP_SERVICE_ERROR_VALUE_INVALID;
651 }
652 if (memcpy_s(policy + offset, policySize - offset, &length, sizeof(uint32_t)) != EOK) {
653 DLP_LOG_ERROR(LABEL, "Memcpy policy fail");
654 return DLP_CREDENTIAL_ERROR_MEMORY_OPERATE_FAIL;
655 }
656 offset += sizeof(uint32_t);
657 if (memcpy_s(policy + offset, policySize - offset, appId, strlen(appId)) != EOK) {
658 DLP_LOG_ERROR(LABEL, "Memcpy policy fail");
659 return DLP_CREDENTIAL_ERROR_MEMORY_OPERATE_FAIL;
660 }
661 offset += strlen(appId);
662 }
663 return offset;
664 }
665
ParseUint8TypedArrayToStringVector(uint8_t * policy,const uint32_t * policyLen,std::vector<std::string> & appIdList)666 int32_t ParseUint8TypedArrayToStringVector(uint8_t *policy, const uint32_t *policyLen,
667 std::vector<std::string>& appIdList)
668 {
669 if (*policyLen > MAX_APPID_LIST_NUM * MAX_APPID_LENGTH) {
670 return DLP_SERVICE_ERROR_VALUE_INVALID;
671 }
672 uint32_t count = reinterpret_cast<uint32_t *>(policy)[0];
673 if (count < 0 || count > MAX_APPID_LIST_NUM) {
674 DLP_LOG_ERROR(LABEL, "get appId List too large");
675 return DLP_SERVICE_ERROR_VALUE_INVALID;
676 }
677 int32_t offset = sizeof(uint32_t);
678 for (uint32_t i = 0; i < count; i++) {
679 int32_t length = reinterpret_cast<int32_t *>(policy + offset)[0];
680 offset += sizeof(uint32_t);
681 appIdList.push_back(std::string(reinterpret_cast<char *>(policy + offset), length));
682 offset += length;
683 }
684 return DLP_OK;
685 }
686
PresetDLPPolicy(const std::vector<std::string> & srcList,std::vector<std::string> & dstList)687 int32_t PresetDLPPolicy(const std::vector<std::string>& srcList, std::vector<std::string>& dstList)
688 {
689 AppExecFwk::BundleInfo bundleInfo;
690 int32_t userId;
691 bool result = GetUserIdByForegroundAccount(&userId);
692 if (!result) {
693 DLP_LOG_ERROR(LABEL, "get userId error");
694 return DLP_SERVICE_ERROR_VALUE_INVALID;
695 }
696 if (BundleManagerAdapter::GetInstance().CheckHapPermission(DLP_MANAGER_BUNDLE_NAME, PERMISSION_ACCESS_DLP_FILE) &&
697 !BundleManagerAdapter::GetInstance().GetBundleInfo(DLP_MANAGER_BUNDLE_NAME,
698 static_cast<int32_t>(AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_SIGNATURE_INFO), bundleInfo, userId)) {
699 DLP_LOG_ERROR(LABEL, "get appId error");
700 return DLP_SERVICE_ERROR_IPC_REQUEST_FAIL;
701 }
702 dstList.assign(srcList.begin(), srcList.end());
703 dstList.push_back(bundleInfo.appId);
704 return DLP_OK;
705 }
706
RemovePresetDLPPolicy(std::vector<std::string> & appIdList)707 int32_t RemovePresetDLPPolicy(std::vector<std::string>& appIdList)
708 {
709 if (appIdList.size() > 0) {
710 appIdList.pop_back();
711 }
712 return DLP_OK;
713 }
714
SetMDMPolicy(const std::vector<std::string> & appIdList)715 int32_t DlpCredential::SetMDMPolicy(const std::vector<std::string>& appIdList)
716 {
717 if (size(appIdList) > MAX_APPID_LENGTH) {
718 DLP_LOG_ERROR(LABEL, "appId List too large");
719 return DLP_SERVICE_ERROR_VALUE_INVALID;
720 }
721 uint32_t policySize = (size(appIdList) + 1) * MAX_APPID_LENGTH;
722 uint8_t *policy = new (std::nothrow)uint8_t[policySize];
723 if (policy == nullptr) {
724 DLP_LOG_WARN(LABEL, "alloc policy failed.");
725 delete[] policy;
726 return DLP_CREDENTIAL_ERROR_MEMORY_OPERATE_FAIL;
727 }
728 std::vector<std::string> presetAppIdList;
729 int32_t res = PresetDLPPolicy(appIdList, presetAppIdList);
730 if (res != DLP_OK) {
731 delete[] policy;
732 return res;
733 }
734 int32_t policyLen = ParseStringVectorToUint8TypedArray(presetAppIdList, policy, policySize);
735 if (policyLen <= 0) {
736 delete[] policy;
737 return policyLen;
738 }
739 res = DLP_AddPolicy(PolicyType::AUTHORIZED_APPLICATION_LIST, policy, policyLen);
740 if (res != DLP_OK) {
741 DLP_LOG_ERROR(LABEL, "SetMDMPolicy request fail, error: %{public}d", res);
742 }
743 delete[] policy;
744 return res;
745 }
746
GetMDMPolicy(std::vector<std::string> & appIdList)747 int32_t DlpCredential::GetMDMPolicy(std::vector<std::string>& appIdList)
748 {
749 uint32_t policyLen = MAX_APPID_LIST_NUM * MAX_APPID_LENGTH;
750 uint8_t *policy = new (std::nothrow)uint8_t[policyLen];
751 if (policy == nullptr) {
752 DLP_LOG_WARN(LABEL, "alloc policy failed.");
753 return DLP_CREDENTIAL_ERROR_MEMORY_OPERATE_FAIL;
754 }
755 int32_t res = DLP_GetPolicy(PolicyType::AUTHORIZED_APPLICATION_LIST, policy, &policyLen);
756 if (res != DLP_OK) {
757 DLP_LOG_ERROR(LABEL, "GetMDMPolicy request fail, error: %{public}d", res);
758 delete[] policy;
759 return res;
760 }
761 if (policyLen == 0) {
762 DLP_LOG_WARN(LABEL, "appIdList is empty.");
763 delete[] policy;
764 return DLP_OK;
765 }
766 res = ParseUint8TypedArrayToStringVector(policy, &policyLen, appIdList);
767 delete[] policy;
768 if (res == DLP_OK) {
769 res = RemovePresetDLPPolicy(appIdList);
770 }
771 return res;
772 }
773
RemoveMDMPolicy()774 int32_t DlpCredential::RemoveMDMPolicy()
775 {
776 int32_t res = DLP_RemovePolicy(PolicyType::AUTHORIZED_APPLICATION_LIST);
777 if (res != DLP_OK) {
778 DLP_LOG_ERROR(LABEL, "RemoveMDMPolicy request fail, error: %{public}d", res);
779 }
780 return res;
781 }
782
CheckMdmPermission(const std::string & bundleName,int32_t userId)783 int32_t DlpCredential::CheckMdmPermission(const std::string& bundleName, int32_t userId)
784 {
785 AppExecFwk::BundleInfo bundleInfo;
786 bool result = BundleManagerAdapter::GetInstance().GetBundleInfo(bundleName,
787 static_cast<int32_t>(AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_SIGNATURE_INFO), bundleInfo, userId);
788 if (!result) {
789 DLP_LOG_ERROR(LABEL, "get appId error");
790 return DLP_SERVICE_ERROR_IPC_REQUEST_FAIL;
791 }
792 PolicyHandle handle = {.id = strdup(const_cast<char *>(bundleInfo.appId.c_str()))};
793 if (handle.id == nullptr) {
794 DLP_LOG_ERROR(LABEL, "Strdup failed.");
795 return DLP_CREDENTIAL_ERROR_SERVER_ERROR;
796 }
797 int32_t res = DLP_CheckPermission(PolicyType::AUTHORIZED_APPLICATION_LIST, handle);
798 if (res != DLP_OK) {
799 DLP_LOG_ERROR(LABEL, "DLP_CheckPermission error:%{public}d", res);
800 res = DLP_CREDENTIAL_ERROR_APPID_NOT_AUTHORIZED;
801 }
802 if (handle.id != nullptr) {
803 free(handle.id);
804 handle.id = nullptr;
805 }
806 return res;
807 }
808 } // namespace DlpPermission
809 } // namespace Security
810 } // namespace OHOS
811