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