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