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