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