From b4d92c46de6454c7fdf064f11f7f0526bcd3cd4f Mon Sep 17 00:00:00 2001 From: cclicn Date: Sat, 9 Dec 2023 20:52:09 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E5=B8=90=E5=8F=B7=E3=80=91=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=BC=82=E5=B8=B8=E7=9B=91=E6=8E=A7=E4=BB=A5=E5=8F=8A?= =?UTF-8?q?=E8=A1=A5=E5=85=85=E5=BC=82=E5=B8=B8=E6=93=8D=E4=BD=9CDFX?= =?UTF-8?q?=E6=89=93=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: cclicn --- dfx/hisysevent_adapter/hisysevent_adapter.cpp | 19 + dfx/hisysevent_adapter/hisysevent_adapter.h | 1 + .../include/account_file_operator.h | 20 +- .../src/account_file_operator.cpp | 82 ++- hisysevent.yaml | 8 +- .../include/account_file_watcher_manager.h | 90 +++ .../account_iam/account_iam_callback.h | 6 +- .../include/ohos_account_data_deal.h | 18 +- .../os_account_control_file_manager.h | 40 +- services/accountmgr/libaccountmgr.map | 6 +- services/accountmgr/os_account_service.gni | 1 + .../src/account_file_watcher_manager.cpp | 529 ++++++++++++++ .../src/account_iam/account_iam_callback.cpp | 24 +- .../account_iam/inner_account_iam_manager.cpp | 9 +- .../accountmgr/src/ohos_account_data_deal.cpp | 139 +++- .../osaccount/inner_os_account_manager.cpp | 3 + .../os_account_control_file_manager.cpp | 674 ++++-------------- .../account_iam/account_iam_callback_test.cpp | 4 +- .../test/unittest/ohos_account/BUILD.gn | 2 +- 19 files changed, 1034 insertions(+), 641 deletions(-) create mode 100644 services/accountmgr/include/account_file_watcher_manager.h create mode 100644 services/accountmgr/src/account_file_watcher_manager.cpp diff --git a/dfx/hisysevent_adapter/hisysevent_adapter.cpp b/dfx/hisysevent_adapter/hisysevent_adapter.cpp index e7d43148c..fb6cfe527 100644 --- a/dfx/hisysevent_adapter/hisysevent_adapter.cpp +++ b/dfx/hisysevent_adapter/hisysevent_adapter.cpp @@ -184,5 +184,24 @@ void ReportOhosAccountStateChange(int32_t userId, int32_t operateType, int32_t o (void)newStat; #endif // HAS_HISYSEVENT_PART } + +void ReportOsAccountDataTampered(int32_t id, const std::string& dataPath, const std::string& dataLabel) +{ +#ifdef HAS_HISYSEVENT_PART + int ret = HiSysEventWrite(HiSysEvent::Domain::ACCOUNT, "DATA_TAMPERED", + HiSysEvent::EventType::SECURITY, + "ID", id, + "DATA_PATH", dataPath, + "DATA_LABEL", dataLabel); + if (ret != 0) { + ACCOUNT_LOGE("sysevent write failed, ret %{public}d, id %{public}d, dataPath %{public}s, dataLabel %{public}s.", + ret, id, dataPath.c_str(), dataLabel.c_str()); + } +#else // HAS_HISYSEVENT_PART + (void)id; + (void)dataPath; + (void)dataLabel; +#endif // HAS_HISYSEVENT_PART +} } // AccountSA } // OHOS \ No newline at end of file diff --git a/dfx/hisysevent_adapter/hisysevent_adapter.h b/dfx/hisysevent_adapter/hisysevent_adapter.h index af8456f32..03246ae31 100644 --- a/dfx/hisysevent_adapter/hisysevent_adapter.h +++ b/dfx/hisysevent_adapter/hisysevent_adapter.h @@ -31,6 +31,7 @@ void ReportAppAccountOperationFail(const std::string &name, const std::string &o void ReportOsAccountLifeCycle(int32_t id, const std::string& operationStr); void ReportOsAccountSwitch(int32_t currentId, int32_t oldId); void ReportOhosAccountStateChange(int32_t userId, int32_t operateType, int32_t oldStat, int32_t newStat); +void ReportOsAccountDataTampered(int32_t id, const std::string& dataPath, const std::string& dataLabel); } // AccountSA } // OHOS #endif // OS_ACCOUNT_DFX_HISYSEVENT_ADAPTER_H diff --git a/frameworks/common/file_operator/include/account_file_operator.h b/frameworks/common/file_operator/include/account_file_operator.h index 2b8c0e566..fd7a87d6e 100644 --- a/frameworks/common/file_operator/include/account_file_operator.h +++ b/frameworks/common/file_operator/include/account_file_operator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -37,16 +37,18 @@ public: bool IsJsonFormat(const std::string &path); bool IsJsonFileReady(const std::string &path); bool IsExistDir(const std::string &path); - bool GetValidWriteFileOptFlag(); - void SetValidWriteFileOptFlag(bool flag); - void SetValidDeleteFileOptFlag(const std::string &fileName, bool flag); - bool GetValidDeleteFileOptFlag(const std::string &fileName); + bool GetValidDeleteFileOperationFlag(const std::string &fileName); + void SetValidDeleteFileOperationFlag(const std::string &fileName, bool flag); + bool GetValidModifyFileOperationFlag(const std::string &fileName); + void SetValidModifyFileOperationFlag(const std::string &fileName, bool flag); + std::mutex &GetModifyOperationLock(); + std::mutex &GetDeleteOperationLock(); private: - std::mutex validWriteFileOptLock_; - std::mutex validDeleteFileOptLock_; - bool validWriteFileOptFlag_ = false; - std::vector validDeleteFileOptFlag_; + std::mutex validModifyFileOperationLock_; + std::mutex validDeleteFileOperationLock_; + std::vector validModifyFileOperationFlag_; + std::vector validDeleteFileOperationFlag_; }; } // namespace AccountSA } // namespace OHOS diff --git a/frameworks/common/file_operator/src/account_file_operator.cpp b/frameworks/common/file_operator/src/account_file_operator.cpp index 1336d9349..891504e11 100644 --- a/frameworks/common/file_operator/src/account_file_operator.cpp +++ b/frameworks/common/file_operator/src/account_file_operator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2021-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -13,7 +13,6 @@ * limitations under the License. */ #include "account_file_operator.h" -#include #include #include #include @@ -32,6 +31,9 @@ #include "hisysevent_adapter.h" namespace OHOS { namespace AccountSA { +namespace { +const std::string ACCOUNT_INFO_DIGEST_FILE_PATH = "account_info_digest.json"; +} AccountFileOperator::AccountFileOperator() {} @@ -58,9 +60,9 @@ ErrCode AccountFileOperator::CreateDir(const std::string &path) ErrCode AccountFileOperator::DeleteDirOrFile(const std::string &path) { - std::lock_guard lock(validDeleteFileOptLock_); + std::lock_guard lock(validDeleteFileOperationLock_); bool delFlag = false; - validDeleteFileOptFlag_.emplace_back(path); + SetValidDeleteFileOperationFlag(path, true); if (IsExistFile(path)) { delFlag = OHOS::RemoveFile(path); } @@ -69,45 +71,68 @@ ErrCode AccountFileOperator::DeleteDirOrFile(const std::string &path) } if (!delFlag) { ACCOUNT_LOGE("DeleteDirOrFile failed, path %{public}s errno %{public}d.", path.c_str(), errno); + SetValidDeleteFileOperationFlag(path, false); return ERR_OSACCOUNT_SERVICE_FILE_DELE_ERROR; - validDeleteFileOptFlag_.erase(std::remove(validDeleteFileOptFlag_.begin(), validDeleteFileOptFlag_.end(), path), - validDeleteFileOptFlag_.end()); } return ERR_OK; } -void AccountFileOperator::SetValidDeleteFileOptFlag(const std::string &fileName, bool flag) +std::mutex &AccountFileOperator::GetModifyOperationLock() { - std::lock_guard lock(validDeleteFileOptLock_); - if (flag) { - validDeleteFileOptFlag_.emplace_back(fileName); - return; - } - validDeleteFileOptFlag_.erase(std::remove(validDeleteFileOptFlag_.begin(), validDeleteFileOptFlag_.end(), fileName), - validDeleteFileOptFlag_.end()); + return validModifyFileOperationLock_; } -bool AccountFileOperator::GetValidDeleteFileOptFlag(const std::string &fileName) +std::mutex &AccountFileOperator::GetDeleteOperationLock() { - std::lock_guard lock(validDeleteFileOptLock_); - for (const auto &iter : validDeleteFileOptFlag_) { - if (fileName.find(iter) != std::string::npos) { + return validDeleteFileOperationLock_; +} + +void AccountFileOperator::SetValidModifyFileOperationFlag(const std::string &fileName, bool flag) +{ + if (fileName.find(ACCOUNT_INFO_DIGEST_FILE_PATH) != std::string::npos) { // ignore digest file record + return; + } + if (!flag) { + validModifyFileOperationFlag_.erase( + std::remove(validModifyFileOperationFlag_.begin(), validModifyFileOperationFlag_.end(), fileName), + validModifyFileOperationFlag_.end()); + return; + } + if (std::find(validModifyFileOperationFlag_.begin(), validModifyFileOperationFlag_.end(), fileName) == + validModifyFileOperationFlag_.end()) { + validModifyFileOperationFlag_.emplace_back(fileName); + } +} + +bool AccountFileOperator::GetValidModifyFileOperationFlag(const std::string &fileName) +{ + for (auto iter : validModifyFileOperationFlag_) { + if (iter == fileName) { return true; } } return false; } -void AccountFileOperator::SetValidWriteFileOptFlag(bool flag) +void AccountFileOperator::SetValidDeleteFileOperationFlag(const std::string &fileName, bool flag) { - std::lock_guard lock(validWriteFileOptLock_); - validWriteFileOptFlag_ = flag; + if (!flag) { + validDeleteFileOperationFlag_.erase( + std::remove(validDeleteFileOperationFlag_.begin(), validDeleteFileOperationFlag_.end(), fileName), + validDeleteFileOperationFlag_.end()); + return; + } + validDeleteFileOperationFlag_.emplace_back(fileName); } -bool AccountFileOperator::GetValidWriteFileOptFlag() +bool AccountFileOperator::GetValidDeleteFileOperationFlag(const std::string &fileName) { - std::lock_guard lock(validWriteFileOptLock_); - return validWriteFileOptFlag_; + for (auto iter : validDeleteFileOperationFlag_) { + if (fileName.find(iter) != std::string::npos) { + return true; + } + } + return false; } ErrCode AccountFileOperator::InputFileByPathAndContent(const std::string &path, const std::string &content) @@ -121,12 +146,12 @@ ErrCode AccountFileOperator::InputFileByPathAndContent(const std::string &path, return errCode; } } - std::lock_guard lock(validWriteFileOptLock_); - validWriteFileOptFlag_ = true; + std::lock_guard lock(validModifyFileOperationLock_); + SetValidModifyFileOperationFlag(path, true); FILE *fp = fopen(path.c_str(), "wb"); if (fp == nullptr) { ACCOUNT_LOGE("failed to open %{public}s, errno %{public}d.", path.c_str(), errno); - validWriteFileOptFlag_ = false; + SetValidModifyFileOperationFlag(path, false); return ERR_ACCOUNT_COMMON_FILE_OPEN_FAILED; } do { @@ -152,12 +177,13 @@ ErrCode AccountFileOperator::InputFileByPathAndContent(const std::string &path, // change mode if (!ChangeModeFile(path, S_IRUSR | S_IWUSR)) { ACCOUNT_LOGW("failed to change mode for file %{public}s, errno %{public}d.", path.c_str(), errno); + return ERR_OHOSACCOUNT_SERVICE_FILE_CHANGE_DIR_MODE_ERROR; } return ERR_OK; } while (0); flock(fileno(fp), LOCK_UN); fclose(fp); - validWriteFileOptFlag_ = false; + SetValidModifyFileOperationFlag(path, false); return ERR_ACCOUNT_COMMON_FILE_WRITE_FAILED; } diff --git a/hisysevent.yaml b/hisysevent.yaml index bb9687246..4b31ad076 100644 --- a/hisysevent.yaml +++ b/hisysevent.yaml @@ -61,4 +61,10 @@ DISTRIBUTED_ACCOUNT_CHANGE: USER_ID: {type: INT32, desc: local account id} OPERATION_TYPE: {type: INT32, desc: operation type} OLD_STATE: {type: INT32, desc: ohos account old state} - NEW_STATE: {type: INT32, desc: ohos account new state} \ No newline at end of file + NEW_STATE: {type: INT32, desc: ohos account new state} + +DATA_TAMPERED: + __BASE: {type: SECURITY, level: CRITICAL, desc: account data is tampered} + ID: {type: INT32, desc: the id of os account which is tampered} + DATA_PATH: {type: STRING, desc: the file path which is tampered} + DATA_LABEL: {type: STRING, desc: the data label which is tampered} \ No newline at end of file diff --git a/services/accountmgr/include/account_file_watcher_manager.h b/services/accountmgr/include/account_file_watcher_manager.h new file mode 100644 index 000000000..2f7219224 --- /dev/null +++ b/services/accountmgr/include/account_file_watcher_manager.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OS_ACCOUNT_SERVICES_ACCOUNTMGR_INCLUDE_ACCOUNT_FILE_WATCHER_MANAGER_H +#define OS_ACCOUNT_SERVICES_ACCOUNTMGR_INCLUDE_ACCOUNT_FILE_WATCHER_MANAGER_H + +#include +#include +#include +#include "account_error_no.h" +#include "account_file_operator.h" +#include "singleton.h" + +namespace OHOS { +namespace AccountSA { +int32_t GenerateAccountInfoDigest(const std::string &inData, uint8_t* outData, uint32_t size); + +using CheckNotifyEventCallbackFunc = std::function; +class FileWatcher { +public: + FileWatcher(const int32_t id); + FileWatcher(const std::string &filePath); + ~FileWatcher(); + + bool InitNotify(); + int32_t GetNotifyId(); + std::string GetFilePath(); + int32_t GetLocalId(); + + bool StartNotify(const uint32_t &watchEvents); + bool CloseNotifyFd(); + bool CheckNotifyEvent(uint32_t event); + void SetEventCallback(CheckNotifyEventCallbackFunc &func); + +public: + int32_t id_ = -1; + +private: + int32_t notifyFd_ = -1; + int32_t wd_ = -1; + std::string filePath_; + CheckNotifyEventCallbackFunc eventCallbackFunc_; +}; + +class AccountFileWatcherMgr { +public: + static AccountFileWatcherMgr &GetInstance(); + void StartWatch(); + void AddFileWatcher( + const int32_t id, CheckNotifyEventCallbackFunc checkCallbackFunc, const std::string filePath = ""); + void RemoveFileWatcher(const int32_t id, const std::string filePath); + ErrCode GetAccountInfoDigestFromFile(const std::string &path, uint8_t *digest, uint32_t size); + ErrCode GenerateAccountInfoDigestStr( + const std::string &userInfoPath, const std::string &accountInfoStr, std::string &digestStr); + ErrCode AddAccountInfoDigest(const std::string accountInfo, const std::string &userInfoPath); + ErrCode DeleteAccountInfoDigest(const std::string &userInfoPath); + +private: + void DealWithFileEvent(); + void GetNotifyEvent(); + AccountFileWatcherMgr(); + ~AccountFileWatcherMgr(); + DISALLOW_COPY_AND_MOVE(AccountFileWatcherMgr); + +public: + std::mutex accountInfoDigestFileLock_; + std::mutex fileWatcherMgrLock_; + std::shared_ptr accountFileOperator_; + std::unordered_map> fileNameMgrMap_; + fd_set fds_; + int32_t maxNotifyFd_ = -1; + std::vector fdArray_; + bool run_ = false; +}; +} // namespace AccountSA +} // namespace OHOS + +#endif // OS_ACCOUNT_SERVICES_ACCOUNTMGR_INCLUDE_OSACCOUNT_OS_ACCOUNT_CONTROL_FILE_MANAGER_H diff --git a/services/accountmgr/include/account_iam/account_iam_callback.h b/services/accountmgr/include/account_iam/account_iam_callback.h index 7f8561388..619af7788 100644 --- a/services/accountmgr/include/account_iam/account_iam_callback.h +++ b/services/accountmgr/include/account_iam/account_iam_callback.h @@ -128,23 +128,25 @@ private: class GetPropCallbackWrapper : public GetPropCallback { public: - GetPropCallbackWrapper(const sptr &callback); + GetPropCallbackWrapper(int32_t userId, const sptr &callback); virtual ~GetPropCallbackWrapper() = default; void OnResult(int32_t result, const Attributes &extraInfo) override; private: + int32_t userId_; sptr innerCallback_; }; class SetPropCallbackWrapper : public SetPropCallback { public: - SetPropCallbackWrapper(const sptr &callback); + SetPropCallbackWrapper(int32_t userId, const sptr &callback); virtual ~SetPropCallbackWrapper() = default; void OnResult(int32_t result, const Attributes &extraInfo) override; private: + int32_t userId_; sptr innerCallback_; }; diff --git a/services/accountmgr/include/ohos_account_data_deal.h b/services/accountmgr/include/ohos_account_data_deal.h index 9c0a59415..f57133536 100644 --- a/services/accountmgr/include/ohos_account_data_deal.h +++ b/services/accountmgr/include/ohos_account_data_deal.h @@ -20,6 +20,8 @@ #include #include #include "account_error_no.h" +#include "account_file_operator.h" +#include "account_file_watcher_manager.h" #include "account_info.h" namespace OHOS { @@ -32,18 +34,28 @@ public: ErrCode Init(std::int32_t userId); ErrCode AccountInfoFromJson(AccountInfo &accountInfo, int32_t userId); - ErrCode AccountInfoToJson(const AccountInfo &accountInfo) const; + ErrCode AccountInfoToJson(const AccountInfo &accountInfo); ~OhosAccountDataDeal() {} private: + bool DealWithFileModifyEvent(const std::string &fileName, const int32_t id); + void DealWithFileDeleteEvent(const std::string &fileName, const int32_t id); bool initOk_; std::string configFileDir_; std::mutex mutex_; - void BuildJsonFileFromScratch(int32_t userId) const; - ErrCode SaveAccountInfo(const AccountInfo &accountInfo) const; + void BuildJsonFileFromScratch(int32_t userId); + ErrCode SaveAccountInfo(const AccountInfo &accountInfo); ErrCode GetAccountInfo(AccountInfo &accountInfo, const int32_t userId); ErrCode ParseJsonFromFile(const std::string &filePath, nlohmann::json &jsonData, int32_t userId); ErrCode GetAccountInfoFromJson(const nlohmann::json &jsonData, AccountInfo &accountInfo, const int32_t userId); + ErrCode GenerateAccountInfoDigestStr( + const std::string &userInfoPath, const std::string &accountInfoStr, std::string &digestStr); + void AddFileWatcher(const int32_t id); + + std::mutex accountInfoFileLock_; + std::shared_ptr accountFileOperator_; + AccountFileWatcherMgr &accountFileWatcherMgr_; + CheckNotifyEventCallbackFunc checkCallbackFunc_; }; } // namespace AccountSA } // namespace OHOS diff --git a/services/accountmgr/include/osaccount/os_account_control_file_manager.h b/services/accountmgr/include/osaccount/os_account_control_file_manager.h index e240717d8..b772597b9 100644 --- a/services/accountmgr/include/osaccount/os_account_control_file_manager.h +++ b/services/accountmgr/include/osaccount/os_account_control_file_manager.h @@ -19,6 +19,7 @@ #include #include #include +#include "account_file_watcher_manager.h" #include "ios_account_control.h" #include "os_account_constants.h" #ifdef HAS_KV_STORE_PART @@ -32,30 +33,6 @@ using CheckNotifyEventCallbackFunc = std::function &accountIdList); ErrCode UpdateAccountList(const std::string &idStr, bool isAdd); ErrCode GetAccountListFromFile(Json& accountListJson); @@ -124,6 +102,7 @@ private: void BuildAndSaveAccountListJsonFile(const std::vector& accounts); void RecoverAccountListJsonFile(); void RecoverAccountInfoDigestJsonFile(); + void BuildAndSaveOsAccountIndexJsonFile(); void BuildAndSaveBaseOAConstraintsJsonFile(); void BuildAndSaveGlobalOAConstraintsJsonFile(); void BuildAndSaveSpecificOAConstraintsJsonFile(); @@ -144,16 +123,11 @@ private: ErrCode RemoveOAGlobalConstraintsInfo(const int32_t id); ErrCode RemoveOASpecificConstraintsInfo(const int32_t id); ErrCode GetAccountInfoDigestFromFile(const std::string &path, uint8_t *digest, uint32_t size); - void WatchOsAccountInfoFile(); - void AddFileWatcher(const int32_t id); - void RemoveFileWatcher(const int32_t id); void GetNotifyEvent(); - void DealWithFileEvent(); bool DealWithFileModifyEvent(const std::string &fileName, const int32_t id); bool DealWithFileDeleteEvent(const std::string &fileName, const int32_t id); bool DealWithFileMoveEvent(const std::string &fileName, const int32_t id); void InitFileWatcherInfo(std::vector &accountIdList); - void SubscribeEventFunction(std::shared_ptr &fileWatcher); bool RecoverAccountData(const std::string &fileName, const int32_t id); private: @@ -164,20 +138,16 @@ private: std::int32_t nextLocalId_ = Constants::START_USER_ID; std::shared_ptr osAccountFileOperator_; std::shared_ptr osAccountPhotoOperator_; + AccountFileWatcherMgr &accountFileWatcherMgr_; std::mutex fileWatcherMgrLock_; std::mutex accountListFileLock_; std::mutex accountInfoFileLock_; - std::mutex accountInfoDigestFileLock_; std::mutex operatingIdMutex_; std::mutex baseOAConstraintsFileLock_; std::mutex globalOAConstraintsFileLock_; std::mutex specificOAConstraintsFileLock_; - std::unordered_map> fileNameMgrMap_; - fd_set fds_; - int32_t maxNotifyFd_ = -1; - std::vector fdArray_; - bool run_ = false; + CheckNotifyEventCallbackFunc eventCallbackFunc_; }; } // namespace AccountSA } // namespace OHOS diff --git a/services/accountmgr/libaccountmgr.map b/services/accountmgr/libaccountmgr.map index 1a29c4aee..3d84acb48 100644 --- a/services/accountmgr/libaccountmgr.map +++ b/services/accountmgr/libaccountmgr.map @@ -115,7 +115,7 @@ "OHOS::AccountSA::DelCredCallback::DelCredCallback(int, bool, OHOS::sptr const&)"; "OHOS::AccountSA::DomainAccountPluginProxy::DomainAccountPluginProxy(OHOS::sptr const&)"; "OHOS::AccountSA::GetCredInfoCallbackWrapper::GetCredInfoCallbackWrapper(int, int, OHOS::sptr const&)"; - "OHOS::AccountSA::GetPropCallbackWrapper::GetPropCallbackWrapper(OHOS::sptr const&)"; + "OHOS::AccountSA::GetPropCallbackWrapper::GetPropCallbackWrapper(int, OHOS::sptr const&)"; "OHOS::AccountSA::GetValidAccountID(std::__h::basic_string, std::__h::allocator> const&, int&)"; "OHOS::AccountSA::IAccountContext::instance_"; "OHOS::AccountSA::AccountMgrService::GetCallingUserID()"; @@ -225,7 +225,7 @@ "OHOS::AccountSA::SessionConnection::SessionConnection(std::__h::basic_string, std::__h::allocator> const&)"; "OHOS::AccountSA::SessionServerDeathRecipient::OnRemoteDied(OHOS::wptr const&)"; "OHOS::AccountSA::SessionServerDeathRecipient::SessionServerDeathRecipient(std::__h::basic_string, std::__h::allocator> const&)"; - "OHOS::AccountSA::SetPropCallbackWrapper::SetPropCallbackWrapper(OHOS::sptr const&)"; + "OHOS::AccountSA::SetPropCallbackWrapper::SetPropCallbackWrapper(int, OHOS::sptr const&)"; "vtable for OHOS::AccountSA::AccountStub"; "OHOS::AccountSA::AccountStub::AccountStub()"; "vtable for OHOS::AccountSA::OsAccountStopUserCallback"; @@ -246,6 +246,7 @@ "OHOS::AccountSA::UpdateTraceLabelAdapter()"; "OHOS::AccountSA::StartTraceAdapter(std::__h::basic_string, std::__h::allocator> const&)"; *OHOS::AccountSA::CountTraceAdapter*; + *OHOS::AccountSA::AccountFileWatcherMgr*; "OHOS::AccountSA::FinishTraceAdapter()"; "OHOS::AccountSA::DomainAccountStub::DomainAccountStub()"; "OHOS::AccountSA::DomainAccountStub::~DomainAccountStub()"; @@ -278,6 +279,7 @@ "non-virtual thunk to OHOS::AccountSA::AccountIAMMgrStub::~AccountIAMMgrStub()"; "virtual thunk to OHOS::AccountSA::AccountIAMMgrStub::~AccountIAMMgrStub()"; "OHOS::AccountSA::InnerDomainAccountManager::AuthUser(int, std::__h::vector> const&, OHOS::sptr const&)"; + "OHOS::AccountSA::GenerateAccountInfoDigest(std::__h::basic_string, std::__h::allocator> const&, unsigned char*, unsigned int)"; }; local: *; diff --git a/services/accountmgr/os_account_service.gni b/services/accountmgr/os_account_service.gni index 49ff33bcf..77a1a34e7 100644 --- a/services/accountmgr/os_account_service.gni +++ b/services/accountmgr/os_account_service.gni @@ -14,6 +14,7 @@ import("../../os_account.gni") account_service_sources = [ "${services_path}/accountmgr/src/account_event_provider.cpp", "${services_path}/accountmgr/src/account_event_subscribe.cpp", + "${services_path}/accountmgr/src/account_file_watcher_manager.cpp", "${services_path}/accountmgr/src/account_helper_data.cpp", "${services_path}/accountmgr/src/account_info_report.cpp", "${services_path}/accountmgr/src/account_mgr_service.cpp", diff --git a/services/accountmgr/src/account_file_watcher_manager.cpp b/services/accountmgr/src/account_file_watcher_manager.cpp new file mode 100644 index 000000000..c7ae3a002 --- /dev/null +++ b/services/accountmgr/src/account_file_watcher_manager.cpp @@ -0,0 +1,529 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "account_file_watcher_manager.h" + +#include +#ifdef WITH_SELINUX +#include +#endif // WITH_SELINUX +#include +#include +#include +#include "account_log_wrapper.h" +#include "hks_api.h" +#include "hks_param.h" +#include "hks_type.h" +#include "os_account_constants.h" + +namespace OHOS { +namespace AccountSA { +namespace { +const uint32_t BUF_COMMON_SIZE = 1024; +const uint32_t SELECT_WAIT_TIME = 1000; +const struct HksParam g_genSignVerifyParams[] = { + { + .tag = HKS_TAG_ALGORITHM, + .uint32Param = HKS_ALG_HMAC + }, { + .tag = HKS_TAG_PURPOSE, + .uint32Param = HKS_KEY_PURPOSE_MAC + }, { + .tag = HKS_TAG_KEY_SIZE, + .uint32Param = HKS_AES_KEY_SIZE_256 + }, { + .tag = HKS_TAG_DIGEST, + .uint32Param = HKS_DIGEST_SHA256 + } +}; +const uint32_t ALG_COMMON_SIZE = 32; +const int32_t TIMES = 4; +const int32_t MAX_UPDATE_SIZE = 256; +const int32_t MAX_OUTDATA_SIZE = MAX_UPDATE_SIZE * TIMES; +const char ACCOUNT_KEY_ALIAS[] = "os_account_info_encryption_key"; +const HksBlob g_keyAlias = { (uint32_t)strlen(ACCOUNT_KEY_ALIAS), (uint8_t *)ACCOUNT_KEY_ALIAS }; +} + +static int32_t InitParamSet(struct HksParamSet **paramSet, const struct HksParam *params, uint32_t paramCount) +{ + int32_t ret = HksInitParamSet(paramSet); + if (ret != 0) { + ACCOUNT_LOGE("HksInitParamSet err = %{public}d", ret); + return ret; + } + ret = HksAddParams(*paramSet, params, paramCount); + if (ret != 0) { + ACCOUNT_LOGE("HksAddParams err = %{public}d", ret); + HksFreeParamSet(paramSet); + return ret; + } + + ret = HksBuildParamSet(paramSet); + if (ret != 0) { + ACCOUNT_LOGE("HksBuildParamSet err = %{public}d", ret); + HksFreeParamSet(paramSet); + return ret; + } + return ret; +} + +static int32_t MallocAndCheckBlobData(struct HksBlob *blob, const uint32_t blobSize) +{ + if (blobSize == 0) { + blob->data = NULL; + return -1; + } + blob->data = (uint8_t *)malloc(blobSize); + if (blob->data == NULL) { + ACCOUNT_LOGE("MallocAndCheckBlobData err"); + return -1; + } + return 0; +} + +static int32_t HksUpdateOpt( + const struct HksBlob *handle, const struct HksParamSet *paramSet, const struct HksBlob *inData) +{ + struct HksBlob inDataSeg = *inData; + inDataSeg.size = MAX_UPDATE_SIZE; + + uint8_t *lastPtr = inData->data + inData->size - 1; + struct HksBlob outDataSeg = { + .size = MAX_OUTDATA_SIZE, + .data = NULL + }; + + bool isFinished = false; + while (inDataSeg.data <= lastPtr) { + if (inDataSeg.data + MAX_UPDATE_SIZE <= lastPtr) { + outDataSeg.size = MAX_OUTDATA_SIZE; + } else { + isFinished = true; + inDataSeg.size = lastPtr - inDataSeg.data + 1; + outDataSeg.size = inDataSeg.size + MAX_UPDATE_SIZE; + } + if (MallocAndCheckBlobData(&outDataSeg, outDataSeg.size) != 0) { + return -1; + } + int32_t ret = HksUpdate(handle, paramSet, &inDataSeg, &outDataSeg); + if (ret != 0) { + ACCOUNT_LOGE("HksUpdate err, ret = %{public}d", ret); + free(outDataSeg.data); + outDataSeg.data = NULL; + return -1; + } + free(outDataSeg.data); + outDataSeg.data = NULL; + if ((isFinished == false) && (inDataSeg.data + MAX_UPDATE_SIZE > lastPtr)) { + return 0; + } + inDataSeg.data += MAX_UPDATE_SIZE; + } + return 0; +} + +static int32_t InitEncryptionKey() +{ + struct HksParamSet *genParamSet = nullptr; + + int32_t ret; + do { + ret = InitParamSet(&genParamSet, g_genSignVerifyParams, sizeof(g_genSignVerifyParams) / sizeof(HksParam)); + if (ret != 0) { + ACCOUNT_LOGE("InitParamSet genParamSet err = %{public}d", ret); + break; + } + ret = HksGenerateKey(&g_keyAlias, genParamSet, nullptr); + if (ret != 0) { + ACCOUNT_LOGE("HksGenerateKey err = %{public}d", ret); + break; + } + } while (0); + HksFreeParamSet(&genParamSet); + return ret; +} + +static int32_t GetDigestDataFromHuks(struct HksParamSet *genParamSet, struct HksBlob &inDataBlob, + uint8_t* outData, uint32_t size) +{ + uint8_t handleTmp[sizeof(uint64_t)] = {0}; + struct HksBlob handleGenDigest = { (uint32_t)sizeof(uint64_t), handleTmp }; + + int32_t ret = HksInit(&g_keyAlias, genParamSet, &handleGenDigest, nullptr); + if (ret != 0) { + ACCOUNT_LOGE("HksInit err = %{public}d", ret); + return ret; + } + ret = HksUpdateOpt(&handleGenDigest, genParamSet, &inDataBlob); + if (ret != 0) { + ACCOUNT_LOGE("HksUpdateOpt err = %{public}d", ret); + HksAbort(&handleGenDigest, genParamSet); + return ret; + } + struct HksBlob finishOut = { 0, nullptr }; + uint8_t outDataS[ALG_COMMON_SIZE] = "out"; + struct HksBlob outDataBlob = { ALG_COMMON_SIZE, outDataS }; + ret = HksFinish(&handleGenDigest, genParamSet, &finishOut, &outDataBlob); + if (ret != 0) { + ACCOUNT_LOGE("HksFinish failed = %{public}d", ret); + HksAbort(&handleGenDigest, genParamSet); + return ret; + } + if (memcpy_s(outData, size, outDataS, outDataBlob.size) != EOK) { + ACCOUNT_LOGE("Get digest failed duo to memcpy_s failed"); + return -1; + } + return 0; +} + +int32_t GenerateAccountInfoDigest(const std::string &inData, uint8_t* outData, uint32_t size) +{ + if (inData.empty()) { + ACCOUNT_LOGW("inData is empty."); + return 0; + } + size_t len = inData.size() + 1; + uint8_t *buffer = static_cast(malloc(len)); + if (buffer == nullptr) { + ACCOUNT_LOGE("buffer malloc err"); + return -1; + } + (void)memcpy_s(buffer, len, inData.c_str(), len); + struct HksBlob inDataBlob = { inData.size(), buffer }; + struct HksParamSet *genParamSet = nullptr; + int32_t ret = InitParamSet(&genParamSet, g_genSignVerifyParams, sizeof(g_genSignVerifyParams) / sizeof(HksParam)); + if (ret != 0) { + free(buffer); + ACCOUNT_LOGE("InitParamSet err = %{public}d", ret); + return ret; + } + ret = GetDigestDataFromHuks(genParamSet, inDataBlob, outData, size); + HksFreeParamSet(&genParamSet); + free(buffer); + return ret; +} + +AccountFileWatcherMgr::AccountFileWatcherMgr() +{ + InitEncryptionKey(); + accountFileOperator_ = std::make_shared(); + FD_ZERO(&fds_); +} + +AccountFileWatcherMgr &AccountFileWatcherMgr::GetInstance() +{ + static AccountFileWatcherMgr *instance = new AccountFileWatcherMgr(); + return *instance; +} + +void AccountFileWatcherMgr::DealWithFileEvent() +{ + std::vector, uint32_t>> eventMap; + { + std::lock_guard lock(fileWatcherMgrLock_); + for (int32_t i : fdArray_) { + if (FD_ISSET(i, &fds_)) { // check which fd has event + char buf[BUF_COMMON_SIZE] = {0}; + struct inotify_event *event = nullptr; + int len, index = 0; + while (((len = read(i, &buf, sizeof(buf))) < 0) && (errno == EINTR)) {}; + while (index < len) { + event = reinterpret_cast(buf + index); + std::shared_ptr fileWatcher = fileNameMgrMap_[i]; + eventMap.emplace_back(std::make_pair(fileWatcher, event->mask)); + index += sizeof(struct inotify_event) + event->len; + } + } else { + FD_SET(i, &fds_); + } + } + } + for (auto it : eventMap) { + it.first->CheckNotifyEvent(it.second); + } + return; +} + +void AccountFileWatcherMgr::GetNotifyEvent() +{ + while (run_) { + if (maxNotifyFd_ < 0) { + ACCOUNT_LOGE("failed to run notify because no fd available."); + continue; + } + for (int32_t i : fdArray_) { + FD_SET(i, &fds_); + } + struct timeval timeout = { 0, SELECT_WAIT_TIME }; // select wait time 1000us + if (select(maxNotifyFd_ + 1, &fds_, nullptr, nullptr, &timeout) <= 0) { + continue; + } + DealWithFileEvent(); + } +} + +void AccountFileWatcherMgr::StartWatch() // start watcher +{ + if (run_) { + return; + } + run_ = true; +#ifdef WITH_SELINUX + Restorecon(Constants::ACCOUNT_INFO_DIGEST_FILE_PATH.c_str()); +#endif // WITH_SELINUX + auto task = std::bind(&AccountFileWatcherMgr::GetNotifyEvent, this); + std::thread taskThread(task); + pthread_setname_np(taskThread.native_handle(), "fileWatcher"); + taskThread.detach(); +} + +void AccountFileWatcherMgr::AddFileWatcher( + const int32_t id, CheckNotifyEventCallbackFunc checkCallbackFunc, const std::string filePath) +{ + std::shared_ptr fileWatcher; + if (!filePath.empty()) { + fileWatcher = std::make_shared(filePath); + fileWatcher->id_ = id; + } else { + fileWatcher = std::make_shared(id); + } + if (!fileWatcher->InitNotify()) { + ACCOUNT_LOGI("fileWatcher InitNotify failed"); + return; + } + fileWatcher->SetEventCallback(checkCallbackFunc); + if (!fileWatcher->StartNotify(IN_MODIFY | IN_DELETE_SELF| IN_MOVE_SELF)) { + ACCOUNT_LOGI("fileWatcher StartNotify failed, fileName = %{public}s", filePath.c_str()); + return; + } + std::lock_guard lock(fileWatcherMgrLock_); + if (fileWatcher->GetNotifyId() > maxNotifyFd_) { + maxNotifyFd_ = fileWatcher->GetNotifyId(); + } + fileNameMgrMap_[fileWatcher->GetNotifyId()] = fileWatcher; + fdArray_.emplace_back(fileWatcher->GetNotifyId()); + { + std::lock_guard filelock(accountFileOperator_->GetModifyOperationLock()); + accountFileOperator_->SetValidModifyFileOperationFlag(filePath, false); + } + + FD_SET(fileWatcher->GetNotifyId(), &fds_); + StartWatch(); +} + +void AccountFileWatcherMgr::RemoveFileWatcher(const int32_t id, const std::string filePath) +{ + std::lock_guard lock(fileWatcherMgrLock_); + int targetFd = -1; + for (auto it : fileNameMgrMap_) { + if ((it.second->GetLocalId() == id) && (it.second->GetFilePath() == filePath)) { + targetFd = it.second->GetNotifyId(); + break; + } + } + if (targetFd == -1) { + return; + } + FD_CLR(targetFd, &fds_); + if (!fileNameMgrMap_[targetFd]->CloseNotifyFd()) { + ACCOUNT_LOGE("failed to close notifyId, userId = %{public}d", id); + } + fdArray_.erase( + std::remove(fdArray_.begin(), fdArray_.end(), targetFd), fdArray_.end()); + + if (maxNotifyFd_ == targetFd) { + maxNotifyFd_ = *max_element(fdArray_.begin(), fdArray_.end()); + } + fileNameMgrMap_.erase(targetFd); + return; +} + +ErrCode AccountFileWatcherMgr::GetAccountInfoDigestFromFile(const std::string &path, uint8_t *digest, uint32_t size) +{ + Json accountInfoDigestJson; + std::string accountInfoDigest; + std::lock_guard lock(accountInfoDigestFileLock_); + ErrCode errCode = accountFileOperator_->GetFileContentByPath(Constants::ACCOUNT_INFO_DIGEST_FILE_PATH, + accountInfoDigest); + if (errCode != ERR_OK) { + ACCOUNT_LOGE("GetFileContentByPath failed! error code %{public}d.", errCode); + return errCode; + } + try { + accountInfoDigestJson = Json::parse(accountInfoDigest, nullptr, false); + } catch (Json::type_error& err) { + ACCOUNT_LOGE("accountInfoDigestJson parse failed! reason: %{public}s", err.what()); + return ERR_ACCOUNT_COMMON_DUMP_JSON_ERROR; + } + std::vector digestTmp; + OHOS::AccountSA::GetDataByType>(accountInfoDigestJson, + accountInfoDigestJson.end(), path, digestTmp, OHOS::AccountSA::JsonType::ARRAY); + if (memcpy_s(digest, size, digestTmp.data(), ALG_COMMON_SIZE) != EOK) { + ACCOUNT_LOGE("Get digest failed duo to memcpy_s failed"); + return ERR_ACCOUNT_COMMON_INSUFFICIENT_MEMORY_ERROR; + } + return ERR_OK; +} + +ErrCode AccountFileWatcherMgr::GenerateAccountInfoDigestStr( + const std::string &userInfoPath, const std::string &accountInfoStr, std::string &digestStr) +{ + uint8_t digestOutData[ALG_COMMON_SIZE]; + GenerateAccountInfoDigest(accountInfoStr, digestOutData, ALG_COMMON_SIZE); + + std::string accountInfoDigest; + std::lock_guard lock(accountInfoDigestFileLock_); + ErrCode errCode = accountFileOperator_->GetFileContentByPath(Constants::ACCOUNT_INFO_DIGEST_FILE_PATH, + accountInfoDigest); + if (errCode != ERR_OK) { + ACCOUNT_LOGE("get file content failed! error code %{public}d.", errCode); + return errCode; + } + Json accountInfoDigestJson; + try { + accountInfoDigestJson = Json::parse(accountInfoDigest, nullptr, false); + } catch (Json::type_error& err) { + ACCOUNT_LOGE("accountInfoDigestJson parse failed! reason: %{public}s", err.what()); + } + if (accountInfoDigestJson.is_discarded()) { + accountInfoDigestJson = Json(); + } + accountInfoDigestJson[userInfoPath] = digestOutData; + try { + digestStr = accountInfoDigestJson.dump(); + } catch (Json::type_error& err) { + ACCOUNT_LOGE("failed to dump json object, reason: %{public}s", err.what()); + return ERR_ACCOUNT_COMMON_DUMP_JSON_ERROR; + } + return ERR_OK; +} + +ErrCode AccountFileWatcherMgr::AddAccountInfoDigest(const std::string accountInfo, const std::string &userInfoPath) +{ + std::string digestStr; + if (GenerateAccountInfoDigestStr(userInfoPath, accountInfo, digestStr) == ERR_OK) { + std::lock_guard lock(accountInfoDigestFileLock_); + return accountFileOperator_->InputFileByPathAndContent(Constants::ACCOUNT_INFO_DIGEST_FILE_PATH, digestStr); + } + return ERR_OK; +} + +ErrCode AccountFileWatcherMgr::DeleteAccountInfoDigest(const std::string &userInfoPath) +{ + Json accountInfoDigestJson; + std::string accountInfoDigest; + std::lock_guard lock(accountInfoDigestFileLock_); + ErrCode errCode = accountFileOperator_->GetFileContentByPath(Constants::ACCOUNT_INFO_DIGEST_FILE_PATH, + accountInfoDigest); + if (errCode != ERR_OK) { + ACCOUNT_LOGE("get file content failed! error code %{public}d.", errCode); + return errCode; + } + try { + accountInfoDigestJson = Json::parse(accountInfoDigest, nullptr, false); + } catch (Json::type_error& err) { + ACCOUNT_LOGE("accountInfoDigestJson parse failed! reason: %{public}s", err.what()); + return ERR_ACCOUNT_COMMON_DUMP_JSON_ERROR; + } + accountInfoDigestJson.erase(userInfoPath); + + ErrCode result = accountFileOperator_->InputFileByPathAndContent( + Constants::ACCOUNT_INFO_DIGEST_FILE_PATH, accountInfoDigestJson.dump()); + if (result != ERR_OK) { + ACCOUNT_LOGE("cannot save digest info to file, code %{public}d.", result); + return result; + } + return ERR_OK; +} + +FileWatcher::FileWatcher(const int32_t id) : id_(id) +{ + filePath_ = Constants::USER_INFO_BASE + Constants::PATH_SEPARATOR + std::to_string(id) + + Constants::PATH_SEPARATOR + Constants::USER_INFO_FILE_NAME; +} + +FileWatcher::FileWatcher(const std::string &filePath) : filePath_(filePath) +{} + +FileWatcher::~FileWatcher() +{} + +int32_t FileWatcher::GetNotifyId() +{ + return notifyFd_; +} + +std::string FileWatcher::GetFilePath() +{ + return filePath_; +} + +bool FileWatcher::InitNotify() +{ + notifyFd_ = inotify_init(); + if (notifyFd_ < 0) { + ACCOUNT_LOGE("failed to init notify, errCode:%{public}d", errno); + return false; + } + return true; +} + +bool FileWatcher::StartNotify(const uint32_t &watchEvents) +{ + wd_ = inotify_add_watch(notifyFd_, filePath_.c_str(), watchEvents); + if (wd_ < 0) { + ACCOUNT_LOGE("failed to start notify, errCode:%{public}d", errno); + return false; + } + return true; +} + +bool FileWatcher::CheckNotifyEvent(uint32_t event) +{ + if (!eventCallbackFunc_(filePath_, id_, event)) { + ACCOUNT_LOGW("deal notify event failed."); + return false; + } + return true; +} +void FileWatcher::SetEventCallback(CheckNotifyEventCallbackFunc &func) +{ + eventCallbackFunc_ = func; +} + +int32_t FileWatcher::GetLocalId() +{ + return id_; +} + +bool FileWatcher::CloseNotifyFd() +{ + if (inotify_rm_watch(notifyFd_, wd_) == -1) { + ACCOUNT_LOGE("failed to exec inotify_rm_watch, err:%{public}d", errno); + if (access(filePath_.c_str(), F_OK) == 0) { + close(notifyFd_); + return true; + } + } + int closeRet = close(notifyFd_); + if (closeRet != 0) { + ACCOUNT_LOGE("failed to close fd err:%{public}d", closeRet); + return false; + } + notifyFd_ = -1; + return true; +} +} // namespace AccountSA +} // namespace OHOS \ No newline at end of file diff --git a/services/accountmgr/src/account_iam/account_iam_callback.cpp b/services/accountmgr/src/account_iam/account_iam_callback.cpp index a7a801f2f..692e1b3ab 100644 --- a/services/accountmgr/src/account_iam/account_iam_callback.cpp +++ b/services/accountmgr/src/account_iam/account_iam_callback.cpp @@ -18,6 +18,7 @@ #include #include "account_info_report.h" #include "account_log_wrapper.h" +#include "hisysevent_adapter.h" #include "iinner_os_account_manager.h" #include "inner_account_iam_manager.h" #include "inner_domain_account_manager.h" @@ -81,6 +82,7 @@ ErrCode AuthCallback::HandleAuthResult(const Attributes &extraInfo) ErrCode ret = InnerAccountIAMManager::GetInstance().UnlockUserScreen(userId_); if (ret != 0) { ACCOUNT_LOGE("failed to unlock user screen"); + ReportOsAccountOperationFail(userId_, "unlockUserScreen", ret, "failed to send unlock msg for storage"); return ret; } if (authType_ != AuthType::PIN) { @@ -96,6 +98,7 @@ ErrCode AuthCallback::HandleAuthResult(const Attributes &extraInfo) ret = InnerAccountIAMManager::GetInstance().ActivateUserKey(userId_, token, secret); if (ret != 0) { ACCOUNT_LOGE("failed to activate user key"); + ReportOsAccountOperationFail(userId_, "activateUserKey", ret, "failed to notice storage to activate user key"); return ret; } return ret; @@ -117,6 +120,7 @@ void AuthCallback::OnResult(int32_t result, const Attributes &extraInfo) if (result != 0) { ACCOUNT_LOGE("authentication failed"); innerCallback_->OnResult(result, extraInfo); + ReportOsAccountOperationFail(userId_, "authUser", result, "auth user failed"); return AccountInfoReport::ReportSecurityInfo("", userId_, ReportEvent::EVENT_LOGIN, result); } if (HandleAuthResult(extraInfo) != ERR_OK) { @@ -157,6 +161,8 @@ void IDMAuthCallback::OnResult(int32_t result, const Attributes &extraInfo) { if (result != 0) { ACCOUNT_LOGE("fail to update user key for authentication failure, error code: %{public}d", result); + ReportOsAccountOperationFail( + userId_, "authentication", result, "fail to update user key for authentication failure"); } else { std::vector token; std::vector secret; @@ -201,6 +207,9 @@ void AddCredCallback::OnResult(int32_t result, const Attributes &extraInfo) userId_, challenge, AuthType::PIN, AuthTrustLevel::ATL4, callback); return; } + if (result != 0) { + ReportOsAccountOperationFail(userId_, "addCredential", result, "fail to add credential"); + } InnerAccountIAMManager::GetInstance().SetState(userId_, AFTER_OPEN_SESSION); if (innerCallback_ == nullptr) { ACCOUNT_LOGE("inner callback is nullptr"); @@ -231,6 +240,9 @@ void DelCredCallback::OnResult(int32_t result, const Attributes &extraInfo) if ((result == 0) && isPIN_) { (void)IInnerOsAccountManager::GetInstance().SetOsAccountCredentialId(userId_, 0); // 0-invalid credentialId } + if (result != 0) { + ReportOsAccountOperationFail(userId_, "deleteCredential", result, "fail to delete credential"); + } InnerAccountIAMManager::GetInstance().SetState(userId_, AFTER_OPEN_SESSION); innerCallback_->OnResult(result, extraInfo); } @@ -268,7 +280,8 @@ void GetCredInfoCallbackWrapper::OnCredentialInfo(const std::vectorOnCredentialInfo(infoList); } -GetPropCallbackWrapper::GetPropCallbackWrapper(const sptr &callback) : innerCallback_(callback) +GetPropCallbackWrapper::GetPropCallbackWrapper(int32_t userId, const sptr &callback) + : userId_(userId), innerCallback_(callback) {} void GetPropCallbackWrapper::OnResult(int32_t result, const Attributes &extraInfo) @@ -277,10 +290,14 @@ void GetPropCallbackWrapper::OnResult(int32_t result, const Attributes &extraInf ACCOUNT_LOGE("inner callback is nullptr"); return; } + if (result != 0) { + ReportOsAccountOperationFail(userId_, "getProperty", result, "fail to get property"); + } innerCallback_->OnResult(result, extraInfo); } -SetPropCallbackWrapper::SetPropCallbackWrapper(const sptr &callback) : innerCallback_(callback) +SetPropCallbackWrapper::SetPropCallbackWrapper(int32_t userId, const sptr &callback) + : userId_(userId), innerCallback_(callback) {} void SetPropCallbackWrapper::OnResult(int32_t result, const Attributes &extraInfo) @@ -289,6 +306,9 @@ void SetPropCallbackWrapper::OnResult(int32_t result, const Attributes &extraInf ACCOUNT_LOGE("inner callback is nullptr"); return; } + if (result != 0) { + ReportOsAccountOperationFail(userId_, "setProperty", result, "fail to set property"); + } innerCallback_->OnResult(result, extraInfo); } diff --git a/services/accountmgr/src/account_iam/inner_account_iam_manager.cpp b/services/accountmgr/src/account_iam/inner_account_iam_manager.cpp index 7eb8b943a..dd8c86a8e 100644 --- a/services/accountmgr/src/account_iam/inner_account_iam_manager.cpp +++ b/services/accountmgr/src/account_iam/inner_account_iam_manager.cpp @@ -18,6 +18,7 @@ #include "account_iam_callback.h" #include "account_log_wrapper.h" #include "domain_account_callback_service.h" +#include "hisysevent_adapter.h" #include "iinner_os_account_manager.h" #include "inner_domain_account_manager.h" #include "iservice_registry.h" @@ -289,7 +290,7 @@ void InnerAccountIAMManager::GetProperty( return; } if (static_cast(request.authType) != static_cast(IAMAuthType::DOMAIN)) { - auto getCallback = std::make_shared(callback); + auto getCallback = std::make_shared(userId, callback); UserAuthClient::GetInstance().GetProperty(userId, request, getCallback); return; } @@ -307,7 +308,7 @@ void InnerAccountIAMManager::SetProperty( callback->OnResult(ERR_ACCOUNT_IAM_UNSUPPORTED_AUTH_TYPE, result); return; } - auto setCallback = std::make_shared(callback); + auto setCallback = std::make_shared(userId, callback); UserAuthClient::GetInstance().SetProperty(userId, request, setCallback); } @@ -372,7 +373,7 @@ ErrCode InnerAccountIAMManager::UnlockUserScreen(int32_t userId) ACCOUNT_LOGE("fail to unlock screen"); return result; } -#endif // HAS_STORAGE_PART +#endif return ERR_OK; } @@ -416,6 +417,7 @@ ErrCode InnerAccountIAMManager::UpdateUserKey(int32_t userId, uint64_t secureUid } result = UpdateStorageKey(userId, secureUid, token, oldCredInfo.secret, newSecret); if (result != ERR_OK) { + ReportOsAccountOperationFail(userId, "updateUserKey", result, "failed to notice storage to update user key"); return result; } credInfoMap_[userId] = { @@ -439,6 +441,7 @@ ErrCode InnerAccountIAMManager::RemoveUserKey(int32_t userId, const std::vector< std::vector newSecret; result = UpdateStorageKey(userId, 0, token, oldCredInfo.secret, newSecret); if (result != ERR_OK) { + ReportOsAccountOperationFail(userId, "removeUserKey", result, "failed to notice storage to remove user key"); return result; } credInfoMap_[userId] = { diff --git a/services/accountmgr/src/ohos_account_data_deal.cpp b/services/accountmgr/src/ohos_account_data_deal.cpp index 9de3d9f42..356166622 100644 --- a/services/accountmgr/src/ohos_account_data_deal.cpp +++ b/services/accountmgr/src/ohos_account_data_deal.cpp @@ -27,7 +27,9 @@ #include "directory_ex.h" #include "file_ex.h" #include "hisysevent_adapter.h" +#include "iinner_os_account_manager.h" #include "ohos_account_data_deal.h" + namespace OHOS { namespace AccountSA { namespace { @@ -42,11 +44,90 @@ const std::string DATADEAL_JSON_KEY_OHOSACCOUNT_AVATAR = "account_avatar"; const std::string DATADEAL_JSON_KEY_OHOSACCOUNT_SCALABLEDATA = "account_scalableData"; const std::string DATADEAL_JSON_KEY_USERID = "user_id"; const std::string DATADEAL_JSON_KEY_BIND_TIME = "bind_time"; +const uint32_t ALG_COMMON_SIZE = 32; } // namespace -OhosAccountDataDeal::OhosAccountDataDeal(const std::string &configFileDir) : configFileDir_(configFileDir) +OhosAccountDataDeal::OhosAccountDataDeal(const std::string &configFileDir) + : configFileDir_(configFileDir), + accountFileWatcherMgr_(AccountFileWatcherMgr::GetInstance()) { + accountFileOperator_ = std::make_shared(); initOk_ = false; + checkCallbackFunc_ = [this](const std::string &fileName, const int32_t id, uint32_t event) { + ACCOUNT_LOGI("inotify event = %{public}d, fileName = %{public}s", event, fileName.c_str()); + switch (event) { + case IN_MODIFY: { + return DealWithFileModifyEvent(fileName, id); + } + case IN_MOVE_SELF: { + ReportOsAccountDataTampered(id, fileName, "DISTRIBUTED_ACCOUT_INFO"); + break; + } + case IN_DELETE_SELF: { + DealWithFileDeleteEvent(fileName, id); + break; + } + default: { + ACCOUNT_LOGW("get event invalid!"); + return false; + } + } + return true; + }; +} + +bool OhosAccountDataDeal::DealWithFileModifyEvent(const std::string &fileName, const int32_t id) +{ + ACCOUNT_LOGI("enter"); + { + std::lock_guard lock(accountFileOperator_->GetModifyOperationLock()); + if (accountFileOperator_->GetValidModifyFileOperationFlag(fileName)) { + ACCOUNT_LOGD("this is valid service operate, no need to deal with it."); + accountFileOperator_->SetValidModifyFileOperationFlag(fileName, false); + return true; + } + } + std::lock_guard lock(accountInfoFileLock_); + std::string fileInfoStr; + if (accountFileOperator_->GetFileContentByPath(fileName, fileInfoStr) != ERR_OK) { + ACCOUNT_LOGE("get content from file %{public}s failed!", fileName.c_str()); + return false; + } + uint8_t localDigestData[ALG_COMMON_SIZE] = {0}; + accountFileWatcherMgr_.GetAccountInfoDigestFromFile(fileName, localDigestData, ALG_COMMON_SIZE); + uint8_t newDigestData[ALG_COMMON_SIZE] = {0}; + GenerateAccountInfoDigest(fileInfoStr, newDigestData, ALG_COMMON_SIZE); + if (memcmp(localDigestData, newDigestData, ALG_COMMON_SIZE) == 0) { + ACCOUNT_LOGD("No need to recover local file data."); + return true; + } + ReportOsAccountDataTampered(id, fileName, "DISTRIBUTED_ACCOUT_INFO"); + return true; +} + +void OhosAccountDataDeal::DealWithFileDeleteEvent(const std::string &fileName, const int32_t id) +{ + { + std::lock_guard lock(accountFileOperator_->GetDeleteOperationLock()); + if (accountFileOperator_->GetValidDeleteFileOperationFlag(fileName)) { + ACCOUNT_LOGD("this is valid service operate, no need to deal with it."); + accountFileOperator_->SetValidDeleteFileOperationFlag(fileName, false); + return; + } + } + std::string fileDir = configFileDir_ + std::to_string(id); + if (!accountFileOperator_->IsExistDir(fileDir)) { + ACCOUNT_LOGI("this id is already removed."); + return; + } + ReportOsAccountDataTampered(id, fileName, "DISTRIBUTED_ACCOUT_INFO"); +} + +void OhosAccountDataDeal::AddFileWatcher(const int32_t id) +{ + std::shared_ptr fileWatcher; + std::string configFile = configFileDir_ + std::to_string(id) + ACCOUNT_CFG_FILE_NAME; + accountFileWatcherMgr_.AddFileWatcher(id, checkCallbackFunc_, configFile); } ErrCode OhosAccountDataDeal::Init(int32_t userId) @@ -80,6 +161,12 @@ ErrCode OhosAccountDataDeal::Init(int32_t userId) return ERR_ACCOUNT_DATADEAL_JSON_FILE_CORRUPTION; } + // recover watch for exist account info + std::vector osAccountInfos; + IInnerOsAccountManager::GetInstance().QueryAllCreatedOsAccounts(osAccountInfos); + for (const auto &info : osAccountInfos) { + AddFileWatcher(info.GetLocalId()); + } initOk_ = true; return ERR_OK; } @@ -93,7 +180,7 @@ ErrCode OhosAccountDataDeal::AccountInfoFromJson(AccountInfo &accountInfo, int32 return GetAccountInfo(accountInfo, userId); } -ErrCode OhosAccountDataDeal::AccountInfoToJson(const AccountInfo &accountInfo) const +ErrCode OhosAccountDataDeal::AccountInfoToJson(const AccountInfo &accountInfo) { if (!initOk_) { ACCOUNT_LOGE("Not init ok"); @@ -102,8 +189,9 @@ ErrCode OhosAccountDataDeal::AccountInfoToJson(const AccountInfo &accountInfo) c return SaveAccountInfo(accountInfo); } -ErrCode OhosAccountDataDeal::SaveAccountInfo(const AccountInfo &accountInfo) const +ErrCode OhosAccountDataDeal::SaveAccountInfo(const AccountInfo &accountInfo) { + std::lock_guard lock(accountInfoFileLock_); std::string scalableDataStr = (accountInfo.ohosAccountInfo_.scalableData_).ToString(); nlohmann::json jsonData = json { {DATADEAL_JSON_KEY_BIND_TIME, accountInfo.bindTime_}, @@ -119,40 +207,16 @@ ErrCode OhosAccountDataDeal::SaveAccountInfo(const AccountInfo &accountInfo) con }; std::string accountInfoValue = jsonData.dump(-1, ' ', false, json::error_handler_t::ignore); std::string configFile = configFileDir_ + std::to_string(accountInfo.userId_) + ACCOUNT_CFG_FILE_NAME; - FILE *fp = fopen(configFile.c_str(), "wb"); - if (fp == nullptr) { - ACCOUNT_LOGE("failed to open %{public}s, errno %{public}d.", configFile.c_str(), errno); - ReportOhosAccountOperationFail(accountInfo.userId_, OPERATION_OPEN_FILE_TO_WRITE, errno, configFile); - return ERR_ACCOUNT_COMMON_FILE_OPEN_FAILED; - } - size_t num = fwrite(accountInfoValue.c_str(), sizeof(char), accountInfoValue.length(), fp); - if (num != accountInfoValue.length()) { - ACCOUNT_LOGE("failed to fwrite %{public}s, errno %{public}d.", configFile.c_str(), errno); - ReportOhosAccountOperationFail(accountInfo.userId_, OPERATION_OPEN_FILE_TO_WRITE, errno, configFile); - fclose(fp); - return ERR_ACCOUNT_COMMON_FILE_WRITE_FAILED; - } - if (fflush(fp) != 0) { - ACCOUNT_LOGE("failed to fflush %{public}s, errno %{public}d.", configFile.c_str(), errno); - ReportOhosAccountOperationFail(accountInfo.userId_, OPERATION_OPEN_FILE_TO_WRITE, errno, configFile); - fclose(fp); - return ERR_ACCOUNT_COMMON_FILE_WRITE_FAILED; - } - if (fsync(fileno(fp)) != 0) { - ACCOUNT_LOGE("failed to fsync %{public}s, errno %{public}d.", configFile.c_str(), errno); - ReportOhosAccountOperationFail(accountInfo.userId_, OPERATION_OPEN_FILE_TO_WRITE, errno, configFile); - fclose(fp); - return ERR_ACCOUNT_COMMON_FILE_WRITE_FAILED; - } - fclose(fp); - // change mode - if (!ChangeModeFile(configFile, S_IRUSR | S_IWUSR)) { - ACCOUNT_LOGE("failed to change mode for file %{public}s, errno %{public}d.", configFile.c_str(), errno); + ErrCode ret = accountFileOperator_->InputFileByPathAndContent(configFile, accountInfoValue); + if (ret == ERR_OHOSACCOUNT_SERVICE_FILE_CHANGE_DIR_MODE_ERROR) { ReportOhosAccountOperationFail(accountInfo.userId_, OPERATION_CHANGE_MODE_FILE, errno, configFile); - return ERR_OHOSACCOUNT_SERVICE_FILE_CHANGE_DIR_MODE_ERROR; } - return ERR_OK; + if (ret != ERR_OK && ret != ERR_OHOSACCOUNT_SERVICE_FILE_CHANGE_DIR_MODE_ERROR) { + ReportOhosAccountOperationFail(accountInfo.userId_, OPERATION_OPEN_FILE_TO_WRITE, errno, configFile); + } + accountFileWatcherMgr_.AddAccountInfoDigest(accountInfoValue, configFile); + return ret; } ErrCode OhosAccountDataDeal::ParseJsonFromFile(const std::string &filePath, nlohmann::json &jsonData, int32_t userId) @@ -235,6 +299,10 @@ ErrCode OhosAccountDataDeal::GetAccountInfoFromJson( ErrCode OhosAccountDataDeal::GetAccountInfo(AccountInfo &accountInfo, const int32_t userId) { + if (userId < 0) { + ACCOUNT_LOGW("invalid userid = %{public}d", userId); + return ERR_OSACCOUNT_SERVICE_MANAGER_ID_ERROR; + } std::string configFile = configFileDir_ + std::to_string(userId) + ACCOUNT_CFG_FILE_NAME; if (!FileExists(configFile)) { ACCOUNT_LOGI("file %{public}s not exist, create!", configFile.c_str()); @@ -252,7 +320,7 @@ ErrCode OhosAccountDataDeal::GetAccountInfo(AccountInfo &accountInfo, const int3 return GetAccountInfoFromJson(jsonData, accountInfo, userId); } -void OhosAccountDataDeal::BuildJsonFileFromScratch(int32_t userId) const +void OhosAccountDataDeal::BuildJsonFileFromScratch(int32_t userId) { AccountInfo accountInfo; accountInfo.userId_ = userId; @@ -264,6 +332,7 @@ void OhosAccountDataDeal::BuildJsonFileFromScratch(int32_t userId) const accountInfo.digest_ = ""; accountInfo.ohosAccountInfo_.SetRawUid(DEFAULT_OHOS_ACCOUNT_UID); SaveAccountInfo(accountInfo); + AddFileWatcher(userId); } } // namespace AccountSA } // namespace OHOS \ No newline at end of file diff --git a/services/accountmgr/src/osaccount/inner_os_account_manager.cpp b/services/accountmgr/src/osaccount/inner_os_account_manager.cpp index ee272fa07..463359f91 100644 --- a/services/accountmgr/src/osaccount/inner_os_account_manager.cpp +++ b/services/accountmgr/src/osaccount/inner_os_account_manager.cpp @@ -652,6 +652,7 @@ ErrCode IInnerOsAccountManager::RemoveOsAccount(const int id) errCode = SendMsgForAccountStop(osAccountInfo); if (errCode != ERR_OK) { RemoveLocalIdToOperating(id); + ReportOsAccountOperationFail(id, "stop", errCode, "stop os account failed"); return errCode; } @@ -1490,6 +1491,7 @@ ErrCode IInnerOsAccountManager::DeactivateOsAccount(const int id) errCode = SendMsgForAccountDeactivate(osAccountInfo); if (errCode != ERR_OK) { RemoveLocalIdToOperating(id); + ReportOsAccountOperationFail(id, "deactivate", errCode, "deactivate os account failed"); return errCode; } @@ -1595,6 +1597,7 @@ ErrCode IInnerOsAccountManager::StopOsAccount(const int id) errCode = SendMsgForAccountStop(osAccountInfo); if (errCode != ERR_OK) { RemoveLocalIdToOperating(id); + ReportOsAccountOperationFail(id, "stop", errCode, "stop os account failed"); ACCOUNT_LOGE("update %{public}d account info failed, errCode %{public}d.", id, errCode); return errCode; } diff --git a/services/accountmgr/src/osaccount/os_account_control_file_manager.cpp b/services/accountmgr/src/osaccount/os_account_control_file_manager.cpp index d0164d4c4..221821a0b 100644 --- a/services/accountmgr/src/osaccount/os_account_control_file_manager.cpp +++ b/services/accountmgr/src/osaccount/os_account_control_file_manager.cpp @@ -27,9 +27,6 @@ #include "account_log_wrapper.h" #include "hisysevent_adapter.h" -#include "hks_api.h" -#include "hks_param.h" -#include "hks_type.h" #include "os_account_constants.h" #include "os_account_interface.h" @@ -38,174 +35,14 @@ namespace AccountSA { namespace { const std::string DEFAULT_ACTIVATED_ACCOUNT_ID = "DefaultActivatedAccountID"; const int32_t MAX_LOCAL_ID = 10736; // int32 max value reduce 200000 be divisible by 200000 - const std::string OS_ACCOUNT_STORE_ID = "os_account_info"; -const struct HksParam g_genSignVerifyParams[] = { - { - .tag = HKS_TAG_ALGORITHM, - .uint32Param = HKS_ALG_HMAC - }, { - .tag = HKS_TAG_PURPOSE, - .uint32Param = HKS_KEY_PURPOSE_MAC - }, { - .tag = HKS_TAG_KEY_SIZE, - .uint32Param = HKS_AES_KEY_SIZE_256 - }, { - .tag = HKS_TAG_DIGEST, - .uint32Param = HKS_DIGEST_SHA256 - } -}; const uint32_t ALG_COMMON_SIZE = 32; -const uint32_t BUF_COMMON_SIZE = 1024; -const int32_t TIMES = 4; -const int32_t MAX_UPDATE_SIZE = 256; -const int32_t MAX_OUTDATA_SIZE = MAX_UPDATE_SIZE * TIMES; -const char ACCOUNT_KEY_ALIAS[] = "os_account_info_encryption_key"; -const HksBlob g_keyAlias = { (uint32_t)strlen(ACCOUNT_KEY_ALIAS), (uint8_t *)ACCOUNT_KEY_ALIAS }; -} - -static int32_t InitParamSet(struct HksParamSet **paramSet, const struct HksParam *params, uint32_t paramCount) -{ - int32_t ret = HksInitParamSet(paramSet); - if (ret != 0) { - ACCOUNT_LOGE("HksInitParamSet err = %{public}d", ret); - return ret; - } - ret = HksAddParams(*paramSet, params, paramCount); - if (ret != 0) { - ACCOUNT_LOGE("HksAddParams err = %{public}d", ret); - HksFreeParamSet(paramSet); - return ret; - } - - ret = HksBuildParamSet(paramSet); - if (ret != 0) { - ACCOUNT_LOGE("HksBuildParamSet err = %{public}d", ret); - HksFreeParamSet(paramSet); - return ret; - } - return ret; -} - -static int32_t MallocAndCheckBlobData(struct HksBlob *blob, const uint32_t blobSize) -{ - if (blobSize == 0) { - blob->data = NULL; - return -1; - } - blob->data = (uint8_t *)malloc(blobSize); - if (blob->data == NULL) { - ACCOUNT_LOGE("MallocAndCheckBlobData err"); - return -1; - } - return 0; -} - -static int32_t HksUpdateOpt( - const struct HksBlob *handle, const struct HksParamSet *paramSet, const struct HksBlob *inData) -{ - struct HksBlob inDataSeg = *inData; - inDataSeg.size = MAX_UPDATE_SIZE; - - uint8_t *lastPtr = inData->data + inData->size - 1; - struct HksBlob outDataSeg = { - .size = MAX_OUTDATA_SIZE, - .data = NULL - }; - - bool isFinished = false; - while (inDataSeg.data <= lastPtr) { - if (inDataSeg.data + MAX_UPDATE_SIZE <= lastPtr) { - outDataSeg.size = MAX_OUTDATA_SIZE; - } else { - isFinished = true; - inDataSeg.size = lastPtr - inDataSeg.data + 1; - outDataSeg.size = inDataSeg.size + MAX_UPDATE_SIZE; - } - if (MallocAndCheckBlobData(&outDataSeg, outDataSeg.size) != 0) { - return -1; - } - int32_t ret = HksUpdate(handle, paramSet, &inDataSeg, &outDataSeg); - if (ret != 0) { - ACCOUNT_LOGE("HksUpdate err, ret = %{public}d", ret); - free(outDataSeg.data); - outDataSeg.data = NULL; - return -1; - } - free(outDataSeg.data); - outDataSeg.data = NULL; - if ((isFinished == false) && (inDataSeg.data + MAX_UPDATE_SIZE > lastPtr)) { - return 0; - } - inDataSeg.data += MAX_UPDATE_SIZE; - } - return 0; -} - -static int32_t InitEncryptionKey() -{ - struct HksParamSet *genParamSet = nullptr; - - int32_t ret; - do { - ret = InitParamSet(&genParamSet, g_genSignVerifyParams, sizeof(g_genSignVerifyParams) / sizeof(HksParam)); - if (ret != 0) { - ACCOUNT_LOGE("InitParamSet genParamSet err = %{public}d", ret); - break; - } - ret = HksGenerateKey(&g_keyAlias, genParamSet, nullptr); - if (ret != 0) { - ACCOUNT_LOGE("HksGenerateKey err = %{public}d", ret); - break; - } - } while (0); - HksFreeParamSet(&genParamSet); - return ret; -} - -static int32_t GenerateAccountInfoGigest(const std::string &inData, uint8_t* outData, uint32_t size) -{ - if (inData.empty()) { - ACCOUNT_LOGW("inData is empty."); - return 0; - } - const char *tmpInData = inData.c_str(); - struct HksBlob inDataBlob = { (uint32_t)strlen(tmpInData), (uint8_t *)tmpInData }; - struct HksParamSet *genParamSet = nullptr; - int32_t ret = InitParamSet(&genParamSet, g_genSignVerifyParams, sizeof(g_genSignVerifyParams) / sizeof(HksParam)); - if (ret != 0) { - ACCOUNT_LOGE("InitParamSet err = %{public}d", ret); - return ret; - } - uint8_t handleTmp[sizeof(uint64_t)] = {0}; - struct HksBlob handleGenDigest = { (uint32_t)sizeof(uint64_t), handleTmp }; - ret = HksInit(&g_keyAlias, genParamSet, &handleGenDigest, nullptr); - if (ret != 0) { - ACCOUNT_LOGE("HksInit err = %{public}d", ret); - return ret; - } - // Update loop - ret = HksUpdateOpt(&handleGenDigest, genParamSet, &inDataBlob); - if (ret != 0) { - ACCOUNT_LOGE("HksUpdateOpt err = %{public}d", ret); - HksAbort(&handleGenDigest, genParamSet); - return ret; - } - struct HksBlob finishOut = { 0, nullptr }; - uint8_t outDataS[ALG_COMMON_SIZE] = "out"; - struct HksBlob outDataBlob = { ALG_COMMON_SIZE, outDataS }; - ret = HksFinish(&handleGenDigest, genParamSet, &finishOut, &outDataBlob); - if (ret != 0) { - ACCOUNT_LOGE("HksFinish failed = %{public}d", ret); - HksAbort(&handleGenDigest, genParamSet); - return ret; - } - if (memcpy_s(outData, size, outDataS, outDataBlob.size) != EOK) { - ACCOUNT_LOGE("Get digest failed duo to memcpy_s failed"); - return -1; - } - HksFreeParamSet(&genParamSet); - return ret; +#ifndef ACCOUNT_TEST +const std::string ACCOUNT_CFG_DIR_ROOT_PATH = "/data/service/el1/public/account/"; +#else +const std::string ACCOUNT_CFG_DIR_ROOT_PATH = "/data/service/el1/public/account/test/"; +#endif // ACCOUNT_TEST +const std::string DISTRIBUTED_ACCOUNT_FILE_NAME = "/account.json"; } bool GetValidAccountID(const std::string& dirName, std::int32_t& accountID) @@ -230,179 +67,6 @@ bool GetValidAccountID(const std::string& dirName, std::int32_t& accountID) return (accountID >= Constants::ADMIN_LOCAL_ID && accountID <= Constants::MAX_USER_ID); } -FileWatcher::FileWatcher(const int32_t id) : id_(id) -{ - filePath_ = Constants::USER_INFO_BASE + Constants::PATH_SEPARATOR + std::to_string(id) + - Constants::PATH_SEPARATOR + Constants::USER_INFO_FILE_NAME; -} - -FileWatcher::FileWatcher(const std::string &filePath) : filePath_(filePath) -{} - -FileWatcher::~FileWatcher() -{} - -int32_t FileWatcher::GetNotifyId() -{ - return notifyFd_; -} - -std::string FileWatcher::GetFilePath() -{ - return filePath_; -} - -bool FileWatcher::InitNotify() -{ - notifyFd_ = inotify_init(); - if (notifyFd_ < 0) { - ACCOUNT_LOGE("failed to init notify, errCode:%{public}d", errno); - return false; - } - return true; -} - -bool FileWatcher::StartNotify(const uint32_t &watchEvents) -{ - wd_ = inotify_add_watch(notifyFd_, filePath_.c_str(), watchEvents); - if (wd_ < 0) { - ACCOUNT_LOGE("failed to init notify, errCode:%{public}d", errno); - return false; - } - return true; -} - -bool FileWatcher::CheckNotifyEvent(uint32_t event) -{ - if (!eventCallbackFunc_(filePath_, id_, event)) { - ACCOUNT_LOGW("deal notify event failed."); - return false; - } - return true; -} - -void OsAccountControlFileManager::DealWithFileEvent() -{ - std::vector, uint32_t>> eventMap; - { - std::lock_guard lock(fileWatcherMgrLock_); - for (int32_t i : fdArray_) { - if (FD_ISSET(i, &fds_)) { // check which fd has event - char buf[BUF_COMMON_SIZE] = {0}; - struct inotify_event *event = nullptr; - int len, index = 0; - while (((len = read(i, &buf, sizeof(buf))) < 0) && (errno == EINTR)) {}; - while (index < len) { - event = reinterpret_cast(buf + index); - std::shared_ptr fileWatcher = fileNameMgrMap_[i]; - eventMap.emplace_back(std::make_pair(fileWatcher, event->mask)); - index += sizeof(struct inotify_event) + event->len; - } - } else { - FD_SET(i, &fds_); - } - } - } - for (auto it : eventMap) { - it.first->CheckNotifyEvent(it.second); - } - return; -} - -void OsAccountControlFileManager::GetNotifyEvent() -{ - while (run_) { - if (maxNotifyFd_ < 0) { - ACCOUNT_LOGE("failed to run notify because no fd available."); - run_ = false; - break; - } - if (select(maxNotifyFd_ + 1, &fds_, nullptr, nullptr, nullptr) <= 0) { - continue; - } - DealWithFileEvent(); - } -} - -void FileWatcher::SetEventCallback(CheckNotifyEventCallbackFunc &func) -{ - eventCallbackFunc_ = func; -} - -int32_t FileWatcher::GetLocalId() -{ - return id_; -} - -bool FileWatcher::CloseNotifyFd() -{ - if (inotify_rm_watch(notifyFd_, wd_) == -1) { - ACCOUNT_LOGE("failed to exec inotify_rm_watch, err:%{public}d", errno); - if (access(filePath_.c_str(), F_OK) == 0) { - close(notifyFd_); - return true; - } - } - int closeRet = close(notifyFd_); - if (closeRet != 0) { - ACCOUNT_LOGE("failed to close fd err:%{public}d", closeRet); - return false; - } - notifyFd_ = -1; - return true; -} - -void OsAccountControlFileManager::RemoveFileWatcher(const int32_t id) -{ - std::lock_guard lock(fileWatcherMgrLock_); - int targetFd = -1; - for (auto it : fileNameMgrMap_) { - if (it.second->GetLocalId() == id) { - targetFd = it.second->GetNotifyId(); - break; - } - } - if (targetFd == -1) { - return; - } - FD_CLR(targetFd, &fds_); - if (!fileNameMgrMap_[targetFd]->CloseNotifyFd()) { - ACCOUNT_LOGE("failed to close notifyId, userId = %{public}d", id); - } - fdArray_.erase( - std::remove(fdArray_.begin(), fdArray_.end(), targetFd), fdArray_.end()); - - if (maxNotifyFd_ == targetFd) { - maxNotifyFd_ = *max_element(fdArray_.begin(), fdArray_.end()); - } - fileNameMgrMap_.erase(targetFd); - return; -} - -void OsAccountControlFileManager::AddFileWatcher(const int32_t id) -{ - std::shared_ptr fileWatcher; - if (id < Constants::START_USER_ID) { - fileWatcher = std::make_shared(Constants::ACCOUNT_LIST_FILE_JSON_PATH); - } else { - fileWatcher = std::make_shared(id); - } - if (!fileWatcher->InitNotify()) { - return; - } - SubscribeEventFunction(fileWatcher); - if (!fileWatcher->StartNotify(IN_MODIFY | IN_DELETE_SELF| IN_MOVE_SELF)) { - return; - } - std::lock_guard lock(fileWatcherMgrLock_); - if (fileWatcher->GetNotifyId() > maxNotifyFd_) { - maxNotifyFd_ = fileWatcher->GetNotifyId(); - } - fileNameMgrMap_[fileWatcher->GetNotifyId()] = fileWatcher; - fdArray_.emplace_back(fileWatcher->GetNotifyId()); - FD_SET(fileWatcher->GetNotifyId(), &fds_); -} - bool OsAccountControlFileManager::RecoverAccountData(const std::string &fileName, const int32_t id) { #ifdef HAS_KV_STORE_PART @@ -411,10 +75,20 @@ bool OsAccountControlFileManager::RecoverAccountData(const std::string &fileName Json accountListJson; osAccountDataBaseOperator_->GetAccountListFromStoreID(OS_ACCOUNT_STORE_ID, accountListJson); recoverDataStr = accountListJson.dump(); - } else { + } else if (id >= Constants::START_USER_ID) { OsAccountInfo osAccountInfo; - GetOsAccountFromDatabase(OS_ACCOUNT_STORE_ID, id, osAccountInfo); + if (GetOsAccountFromDatabase(OS_ACCOUNT_STORE_ID, id, osAccountInfo) != ERR_OK) { + ACCOUNT_LOGW("get recover file data failed"); + return false; + } recoverDataStr = osAccountInfo.ToString(); + } else { + ACCOUNT_LOGW("get recover file data failed"); + return false; + } + if (recoverDataStr.empty()) { + ACCOUNT_LOGW("get recover file data failed"); + return false; } // recover data ErrCode result = accountFileOperator_->InputFileByPathAndContent(fileName, recoverDataStr); @@ -423,37 +97,41 @@ bool OsAccountControlFileManager::RecoverAccountData(const std::string &fileName return false; } // update local digest - std::string digestStr; - if (GenerateAccountInfoDigestStr(fileName, recoverDataStr, digestStr) != ERR_OK) { + if (accountFileWatcherMgr_.AddAccountInfoDigest(recoverDataStr, fileName) != ERR_OK) { + ACCOUNT_LOGE("failed to update local digest"); return false; } - accountFileOperator_->InputFileByPathAndContent(Constants::ACCOUNT_INFO_DIGEST_FILE_PATH, digestStr); #endif return true; } bool OsAccountControlFileManager::DealWithFileModifyEvent(const std::string &fileName, const int32_t id) { - if (accountFileOperator_->GetValidWriteFileOptFlag()) { - ACCOUNT_LOGD("this is valid service operate, no need to deal with it."); - accountFileOperator_->SetValidWriteFileOptFlag(false); - return true; + ACCOUNT_LOGI("enter"); + { + std::lock_guard lock(accountFileOperator_->GetModifyOperationLock()); + if (accountFileOperator_->GetValidModifyFileOperationFlag(fileName)) { + ACCOUNT_LOGD("this is valid service operate, no need to deal with it."); + accountFileOperator_->SetValidModifyFileOperationFlag(fileName, false); + return true; + } } - std::string fileInfoStr; std::lock_guard lock(accountInfoFileLock_); + std::string fileInfoStr; if (accountFileOperator_->GetFileContentByPath(fileName, fileInfoStr) != ERR_OK) { ACCOUNT_LOGE("get content from file %{public}s failed!", fileName.c_str()); return false; } uint8_t localDigestData[ALG_COMMON_SIZE] = {0}; - GetAccountInfoDigestFromFile(fileName, localDigestData, ALG_COMMON_SIZE); + accountFileWatcherMgr_.GetAccountInfoDigestFromFile(fileName, localDigestData, ALG_COMMON_SIZE); uint8_t newDigestData[ALG_COMMON_SIZE] = {0}; - GenerateAccountInfoGigest(fileInfoStr, newDigestData, ALG_COMMON_SIZE); + GenerateAccountInfoDigest(fileInfoStr, newDigestData, ALG_COMMON_SIZE); if (memcmp(localDigestData, newDigestData, ALG_COMMON_SIZE) == EOK) { ACCOUNT_LOGD("No need to recover local file data."); return true; } + ReportOsAccountDataTampered(id, fileName, "OS_ACCOUNT_INFO"); ACCOUNT_LOGW("local file data has been changed"); return RecoverAccountData(fileName, id); } @@ -461,16 +139,22 @@ bool OsAccountControlFileManager::DealWithFileModifyEvent(const std::string &fil bool OsAccountControlFileManager::DealWithFileDeleteEvent(const std::string &fileName, const int32_t id) { ACCOUNT_LOGI("enter"); - if (accountFileOperator_->GetValidDeleteFileOptFlag(fileName)) { - ACCOUNT_LOGD("this is valid service operate, no need to deal with it."); - accountFileOperator_->SetValidDeleteFileOptFlag(fileName, false); - return true; + { + std::lock_guard lock(accountFileOperator_->GetDeleteOperationLock()); + if (accountFileOperator_->GetValidDeleteFileOperationFlag(fileName)) { + ACCOUNT_LOGD("this is valid service operate, no need to deal with it."); + accountFileOperator_->SetValidDeleteFileOperationFlag(fileName, false); + return true; + } } - std::lock_guard lock(accountInfoFileLock_); - if (!RecoverAccountData(fileName, id)) { - ACCOUNT_LOGE("recover account data failed."); + ReportOsAccountDataTampered(id, fileName, "OS_ACCOUNT_INFO"); + { + std::lock_guard lock(accountInfoFileLock_); + if (!RecoverAccountData(fileName, id)) { + ACCOUNT_LOGE("recover account data failed."); + } } - AddFileWatcher(id); + accountFileWatcherMgr_.AddFileWatcher(id, eventCallbackFunc_, fileName); return true; } @@ -478,52 +162,18 @@ bool OsAccountControlFileManager::DealWithFileMoveEvent(const std::string &fileN { ACCOUNT_LOGI("enter"); // delete old file watcher - RemoveFileWatcher(id); + accountFileWatcherMgr_.RemoveFileWatcher(id, fileName); + ReportOsAccountDataTampered(id, fileName, "OS_ACCOUNT_INFO"); std::lock_guard lock(accountInfoFileLock_); if (!RecoverAccountData(fileName, id)) { ACCOUNT_LOGE("recover account data failed."); } - AddFileWatcher(id); + accountFileWatcherMgr_.AddFileWatcher(id, eventCallbackFunc_, fileName); return true; } -void OsAccountControlFileManager::SubscribeEventFunction(std::shared_ptr &fileWatcher) -{ - CheckNotifyEventCallbackFunc checkCallbackFunc = - [this](const std::string &fileName, const int32_t id, uint32_t event) { - switch (event) { - case IN_MODIFY: { - return DealWithFileModifyEvent(fileName, id); - } - case IN_MOVE_SELF: { - return DealWithFileMoveEvent(fileName, id); - } - case IN_DELETE_SELF: { - return DealWithFileDeleteEvent(fileName, id); - } - default: { - ACCOUNT_LOGW("get event invalid!"); - return false; - } - } - }; - fileWatcher->SetEventCallback(checkCallbackFunc); - return; -} - -void OsAccountControlFileManager::WatchOsAccountInfoFile() -{ - if (run_) { - return; - } - run_ = true; - auto task = std::bind(&OsAccountControlFileManager::GetNotifyEvent, this); - std::thread taskThread(task); - pthread_setname_np(taskThread.native_handle(), "fileWatcher"); - taskThread.detach(); -} - OsAccountControlFileManager::OsAccountControlFileManager() + : accountFileWatcherMgr_(AccountFileWatcherMgr::GetInstance()) { accountFileOperator_ = std::make_shared(); #ifdef HAS_KV_STORE_PART @@ -531,14 +181,30 @@ OsAccountControlFileManager::OsAccountControlFileManager() #endif osAccountFileOperator_ = std::make_shared(); osAccountPhotoOperator_ = std::make_shared(); - FD_ZERO(&fds_); + eventCallbackFunc_ = [this](const std::string &fileName, const int32_t id, uint32_t event) { + ACCOUNT_LOGI("inotify event = %{public}d, fileName = %{public}s", event, fileName.c_str()); + switch (event) { + case IN_MODIFY: { + return DealWithFileModifyEvent(fileName, id); + } + case IN_MOVE_SELF: { + return DealWithFileMoveEvent(fileName, id); + } + case IN_DELETE_SELF: { + return DealWithFileDeleteEvent(fileName, id); + } + default: { + ACCOUNT_LOGW("get event invalid!"); + return false; + } + } + }; } OsAccountControlFileManager::~OsAccountControlFileManager() {} void OsAccountControlFileManager::Init() { - InitEncryptionKey(); osAccountFileOperator_->Init(); FileInit(); Json accountListJson; @@ -566,7 +232,6 @@ void OsAccountControlFileManager::FileInit() Restorecon(Constants::ACCOUNT_LIST_FILE_JSON_PATH.c_str()); #endif // WITH_SELINUX } - AddFileWatcher(-1); // -1 is special refers to accountList file. if (!accountFileOperator_->IsJsonFileReady(Constants::ACCOUNT_INFO_DIGEST_FILE_PATH)) { ACCOUNT_LOGI("OsAccountControlFileManager there is not have valid account info digest file, create!"); RecoverAccountInfoDigestJsonFile(); @@ -574,6 +239,16 @@ void OsAccountControlFileManager::FileInit() Restorecon(Constants::ACCOUNT_INFO_DIGEST_FILE_PATH.c_str()); #endif // WITH_SELINUX } + // -1 is special refers to conmon account data file. + accountFileWatcherMgr_.AddFileWatcher(-1, eventCallbackFunc_, Constants::ACCOUNT_LIST_FILE_JSON_PATH); + if (!accountFileOperator_->IsJsonFileReady(Constants::ACCOUNT_INDEX_JSON_PATH)) { + ACCOUNT_LOGI("OsAccountControlFileManager there is not have valid account index file, create!"); + BuildAndSaveOsAccountIndexJsonFile(); +#ifdef WITH_SELINUX + Restorecon(Constants::ACCOUNT_INDEX_JSON_PATH.c_str()); +#endif // WITH_SELINUX + } + accountFileWatcherMgr_.AddFileWatcher(-1, eventCallbackFunc_, Constants::ACCOUNT_INDEX_JSON_PATH); if (!accountFileOperator_->IsJsonFileReady(Constants::BASE_OSACCOUNT_CONSTRAINTS_JSON_PATH)) { ACCOUNT_LOGI("OsAccountControlFileManager there is not have valid account list, create!"); BuildAndSaveBaseOAConstraintsJsonFile(); @@ -581,6 +256,7 @@ void OsAccountControlFileManager::FileInit() Restorecon(Constants::BASE_OSACCOUNT_CONSTRAINTS_JSON_PATH.c_str()); #endif // WITH_SELINUX } + accountFileWatcherMgr_.AddFileWatcher(-1, eventCallbackFunc_, Constants::BASE_OSACCOUNT_CONSTRAINTS_JSON_PATH); if (!accountFileOperator_->IsJsonFileReady(Constants::GLOBAL_OSACCOUNT_CONSTRAINTS_JSON_PATH)) { ACCOUNT_LOGI("OsAccountControlFileManager there is not have valid account list, create!"); BuildAndSaveGlobalOAConstraintsJsonFile(); @@ -588,6 +264,7 @@ void OsAccountControlFileManager::FileInit() Restorecon(Constants::GLOBAL_OSACCOUNT_CONSTRAINTS_JSON_PATH.c_str()); #endif // WITH_SELINUX } + accountFileWatcherMgr_.AddFileWatcher(-1, eventCallbackFunc_, Constants::GLOBAL_OSACCOUNT_CONSTRAINTS_JSON_PATH); if (!accountFileOperator_->IsJsonFileReady(Constants::SPECIFIC_OSACCOUNT_CONSTRAINTS_JSON_PATH)) { ACCOUNT_LOGI("OsAccountControlFileManager there is not have valid account list, create!"); BuildAndSaveSpecificOAConstraintsJsonFile(); @@ -595,19 +272,20 @@ void OsAccountControlFileManager::FileInit() Restorecon(Constants::SPECIFIC_OSACCOUNT_CONSTRAINTS_JSON_PATH.c_str()); #endif // WITH_SELINUX } + accountFileWatcherMgr_.AddFileWatcher(-1, eventCallbackFunc_, Constants::SPECIFIC_OSACCOUNT_CONSTRAINTS_JSON_PATH); } void OsAccountControlFileManager::InitFileWatcherInfo(std::vector &accountIdList) { for (std::string i : accountIdList) { - AddFileWatcher(stoi(i)); + accountFileWatcherMgr_.AddFileWatcher(stoi(i), eventCallbackFunc_); } - WatchOsAccountInfoFile(); } void OsAccountControlFileManager::BuildAndSaveAccountListJsonFile(const std::vector& accounts) { ACCOUNT_LOGD("enter."); + std::lock_guard lock(accountInfoFileLock_); Json accountList = Json { {Constants::ACCOUNT_LIST, accounts}, {Constants::COUNT_ACCOUNT_NUM, accounts.size()}, @@ -622,6 +300,7 @@ void OsAccountControlFileManager::BuildAndSaveAccountListJsonFile(const std::vec void OsAccountControlFileManager::BuildAndSaveBaseOAConstraintsJsonFile() { ACCOUNT_LOGI("enter."); + std::lock_guard lock(accountInfoFileLock_); std::vector baseOAConstraints; if (osAccountFileOperator_->GetConstraintsByType(OsAccountType::ADMIN, baseOAConstraints) != ERR_OK) { ACCOUNT_LOGE("get %{public}d base os account constraints failed.", Constants::START_USER_ID); @@ -636,6 +315,7 @@ void OsAccountControlFileManager::BuildAndSaveBaseOAConstraintsJsonFile() void OsAccountControlFileManager::BuildAndSaveGlobalOAConstraintsJsonFile() { ACCOUNT_LOGI("enter."); + std::lock_guard lock(accountInfoFileLock_); Json globalOsAccountConstraints = Json { {Constants::DEVICE_OWNER_ID, -1}, {Constants::ALL_GLOBAL_CONSTRAINTS, {}} @@ -645,6 +325,7 @@ void OsAccountControlFileManager::BuildAndSaveGlobalOAConstraintsJsonFile() void OsAccountControlFileManager::BuildAndSaveSpecificOAConstraintsJsonFile() { + std::lock_guard lock(accountInfoFileLock_); Json OsAccountConstraintsList = Json { {Constants::ALL_SPECIFIC_CONSTRAINTS, {}}, }; @@ -654,12 +335,28 @@ void OsAccountControlFileManager::BuildAndSaveSpecificOAConstraintsJsonFile() SaveSpecificOAConstraintsToFile(specificOsAccountConstraints); } +void OsAccountControlFileManager::BuildAndSaveOsAccountIndexJsonFile() +{ + std::lock_guard lock(accountInfoFileLock_); + std::string accountIndex; + ErrCode result = GetAccountIndexInfo(accountIndex); + if (result != ERR_OK) { + ACCOUNT_LOGE("get account index info error code %{public}d.", result); + return; + } + result = accountFileOperator_->InputFileByPathAndContent(Constants::ACCOUNT_INDEX_JSON_PATH, accountIndex); + if (result != ERR_OK) { + ACCOUNT_LOGE("failed to input account index info to file!"); + } + return; +} + void OsAccountControlFileManager::RecoverAccountInfoDigestJsonFile() { std::string listInfoStr; accountFileOperator_->GetFileContentByPath(Constants::ACCOUNT_LIST_FILE_JSON_PATH, listInfoStr); uint8_t digestOutData[ALG_COMMON_SIZE] = {0}; - GenerateAccountInfoGigest(listInfoStr, digestOutData, ALG_COMMON_SIZE); + GenerateAccountInfoDigest(listInfoStr, digestOutData, ALG_COMMON_SIZE); Json digestJsonData = Json { {Constants::ACCOUNT_LIST_FILE_JSON_PATH, digestOutData}, }; @@ -783,6 +480,7 @@ ErrCode OsAccountControlFileManager::GetConstraintsByType( ErrCode OsAccountControlFileManager::UpdateBaseOAConstraints(const std::string& idStr, const std::vector& ConstraintStr, bool isAdd) { + std::lock_guard lock(accountInfoFileLock_); Json baseOAConstraintsJson; ErrCode result = GetBaseOAConstraintsFromFile(baseOAConstraintsJson); if (result != ERR_OK) { @@ -818,6 +516,7 @@ ErrCode OsAccountControlFileManager::UpdateBaseOAConstraints(const std::string& ErrCode OsAccountControlFileManager::UpdateGlobalOAConstraints( const std::string& idStr, const std::vector& ConstraintStr, bool isAdd) { + std::lock_guard lock(accountInfoFileLock_); Json globalOAConstraintsJson; ErrCode result = GetGlobalOAConstraintsFromFile(globalOAConstraintsJson); if (result != ERR_OK) { @@ -882,6 +581,7 @@ void OsAccountControlFileManager::GlobalConstraintsDataOperate(const std::string ErrCode OsAccountControlFileManager::UpdateSpecificOAConstraints( const std::string& idStr, const std::string& targetIdStr, const std::vector& ConstraintStr, bool isAdd) { + std::lock_guard lock(accountInfoFileLock_); Json specificOAConstraintsJson; ErrCode result = GetSpecificOAConstraintsFromFile(specificOAConstraintsJson); if (result != ERR_OK) { @@ -977,6 +677,7 @@ ErrCode OsAccountControlFileManager::RemoveOAConstraintsInfo(const int32_t id) ErrCode OsAccountControlFileManager::RemoveOABaseConstraintsInfo(const int32_t id) { + std::lock_guard lock(accountInfoFileLock_); Json baseOAConstraintsJson; ErrCode result = GetBaseOAConstraintsFromFile(baseOAConstraintsJson); if (result != ERR_OK) { @@ -994,6 +695,7 @@ ErrCode OsAccountControlFileManager::RemoveOABaseConstraintsInfo(const int32_t i ErrCode OsAccountControlFileManager::RemoveOAGlobalConstraintsInfo(const int32_t id) { + std::lock_guard lock(accountInfoFileLock_); Json globalOAConstraintsJson; ErrCode result = GetGlobalOAConstraintsFromFile(globalOAConstraintsJson); if (result != ERR_OK) { @@ -1034,6 +736,7 @@ ErrCode OsAccountControlFileManager::RemoveOAGlobalConstraintsInfo(const int32_t ErrCode OsAccountControlFileManager::RemoveOASpecificConstraintsInfo(const int32_t id) { + std::lock_guard lock(accountInfoFileLock_); Json specificOAConstraintsJson; ErrCode result = GetSpecificOAConstraintsFromFile(specificOAConstraintsJson); if (result != ERR_OK) { @@ -1111,6 +814,7 @@ ErrCode OsAccountControlFileManager::UpdateAccountList(const std::string& idStr, ErrCode OsAccountControlFileManager::UpdateAccountIndex(const OsAccountInfo &osAccountInfo, const bool isDelete) { + std::lock_guard lock(accountInfoFileLock_); Json accountIndexJson; ErrCode result = GetAccountIndexFromFile(accountIndexJson); if (result != ERR_OK) { @@ -1129,7 +833,33 @@ ErrCode OsAccountControlFileManager::UpdateAccountIndex(const OsAccountInfo &osA accountIndexJson[localIdStr] = accountBaseInfo; } std::string lastAccountIndexStr = accountIndexJson.dump(); - return accountFileOperator_->InputFileByPathAndContent(Constants::ACCOUNT_INDEX_JSON_PATH, lastAccountIndexStr); + result = accountFileOperator_->InputFileByPathAndContent(Constants::ACCOUNT_INDEX_JSON_PATH, lastAccountIndexStr); + if (result != ERR_OK) { + ACCOUNT_LOGE("failed to input account index info to file!"); + return result; + } + accountFileWatcherMgr_.AddAccountInfoDigest(lastAccountIndexStr, Constants::ACCOUNT_INDEX_JSON_PATH); + return ERR_OK; +} + +ErrCode OsAccountControlFileManager::RemoveAccountIndex(const int32_t id) +{ + Json accountIndexJson; + ErrCode result = GetAccountIndexFromFile(accountIndexJson); + if (result != ERR_OK) { + ACCOUNT_LOGE("get account index failed!"); + return result; + } + std::string localIdStr = std::to_string(id); + accountIndexJson.erase(localIdStr); + std::string lastAccountIndexStr = accountIndexJson.dump(); + result = accountFileOperator_->InputFileByPathAndContent(Constants::ACCOUNT_INDEX_JSON_PATH, lastAccountIndexStr); + if (result != ERR_OK) { + ACCOUNT_LOGE("failed to input account index info to file!"); + return result; + } + accountFileWatcherMgr_.AddAccountInfoDigest(lastAccountIndexStr, Constants::ACCOUNT_INDEX_JSON_PATH); + return ERR_OK; } ErrCode OsAccountControlFileManager::InsertOsAccount(OsAccountInfo &osAccountInfo) @@ -1164,12 +894,8 @@ ErrCode OsAccountControlFileManager::InsertOsAccount(OsAccountInfo &osAccountInf #endif if (osAccountInfo.GetLocalId() >= Constants::START_USER_ID) { - std::string digestStr; - if (GenerateAccountInfoDigestStr(path, accountInfoStr, digestStr) == ERR_OK) { - accountFileOperator_->InputFileByPathAndContent(Constants::ACCOUNT_INFO_DIGEST_FILE_PATH, digestStr); - } - AddFileWatcher(osAccountInfo.GetLocalId()); - WatchOsAccountInfoFile(); + accountFileWatcherMgr_.AddAccountInfoDigest(accountInfoStr, path); + accountFileWatcherMgr_.AddFileWatcher(osAccountInfo.GetLocalId(), eventCallbackFunc_); return UpdateAccountList(osAccountInfo.GetPrimeKey(), true); } ACCOUNT_LOGD("end"); @@ -1194,75 +920,16 @@ ErrCode OsAccountControlFileManager::DelOsAccount(const int id) osAccountDataBaseOperator_->DelOsAccountFromDatabase(id); #endif path += Constants::PATH_SEPARATOR + Constants::USER_INFO_FILE_NAME; - DeleteAccountInfoDigest(path); - - OsAccountInfo osAccountInfo; - osAccountInfo.SetLocalId(id); - UpdateAccountIndex(osAccountInfo, true); - RemoveFileWatcher(id); + accountFileWatcherMgr_.DeleteAccountInfoDigest(path); + accountFileWatcherMgr_.RemoveFileWatcher(id, path); + std::string distributedDataPath = + Constants::USER_INFO_BASE + Constants::PATH_SEPARATOR + std::to_string(id) + DISTRIBUTED_ACCOUNT_FILE_NAME; + accountFileWatcherMgr_.DeleteAccountInfoDigest(distributedDataPath); + accountFileWatcherMgr_.RemoveFileWatcher(id, distributedDataPath); + RemoveAccountIndex(id); return UpdateAccountList(std::to_string(id), false); } -ErrCode OsAccountControlFileManager::GenerateAccountInfoDigestStr( - const std::string &userInfoPath, const std::string &accountInfoStr, std::string &digestStr) -{ - uint8_t digestOutData[ALG_COMMON_SIZE]; - GenerateAccountInfoGigest(accountInfoStr, digestOutData, ALG_COMMON_SIZE); - - std::string accountInfoDigest; - std::lock_guard lock(accountInfoDigestFileLock_); - ErrCode errCode = accountFileOperator_->GetFileContentByPath(Constants::ACCOUNT_INFO_DIGEST_FILE_PATH, - accountInfoDigest); - if (errCode != ERR_OK) { - ACCOUNT_LOGE("get file content failed! error code %{public}d.", errCode); - return errCode; - } - Json accountInfoDigestJson; - try { - accountInfoDigestJson = Json::parse(accountInfoDigest, nullptr, false); - } catch (Json::type_error& err) { - ACCOUNT_LOGE("accountInfoDigestJson parse failed! reason: %{public}s", err.what()); - } - if (accountInfoDigestJson.is_discarded()) { - accountInfoDigestJson = Json(); - } - accountInfoDigestJson[userInfoPath] = digestOutData; - try { - digestStr = accountInfoDigestJson.dump(); - } catch (Json::type_error& err) { - ACCOUNT_LOGE("failed to dump json object, reason: %{public}s", err.what()); - return ERR_ACCOUNT_COMMON_DUMP_JSON_ERROR; - } - return ERR_OK; -} - -ErrCode OsAccountControlFileManager::DeleteAccountInfoDigest(const std::string &userInfoPath) -{ - Json accountInfoDigestJson; - std::string accountInfoDigest; - std::lock_guard lock(accountInfoDigestFileLock_); - ErrCode errCode = accountFileOperator_->GetFileContentByPath(Constants::ACCOUNT_INFO_DIGEST_FILE_PATH, - accountInfoDigest); - if (errCode != ERR_OK) { - ACCOUNT_LOGE("get file content failed! error code %{public}d.", errCode); - return errCode; - } - try { - accountInfoDigestJson = Json::parse(accountInfoDigest, nullptr, false); - } catch (Json::type_error& err) { - ACCOUNT_LOGE("accountInfoDigestJson parse failed! reason: %{public}s", err.what()); - return ERR_ACCOUNT_COMMON_DUMP_JSON_ERROR; - } - accountInfoDigestJson.erase(userInfoPath); - - ErrCode result = accountFileOperator_->InputFileByPathAndContent( - Constants::ACCOUNT_INFO_DIGEST_FILE_PATH, accountInfoDigestJson.dump()); - if (result != ERR_OK) { - ACCOUNT_LOGE("cannot save digest info to file, code %{public}d.", result); - return result; - } - return ERR_OK; -} ErrCode OsAccountControlFileManager::UpdateOsAccount(OsAccountInfo &osAccountInfo) { @@ -1295,9 +962,7 @@ ErrCode OsAccountControlFileManager::UpdateOsAccount(OsAccountInfo &osAccountInf #endif // DISTRIBUTED_FEATURE_ENABLED std::string digestStr; - if (GenerateAccountInfoDigestStr(path, accountInfoStr, digestStr) == ERR_OK) { - accountFileOperator_->InputFileByPathAndContent(Constants::ACCOUNT_INFO_DIGEST_FILE_PATH, digestStr); - } + accountFileWatcherMgr_.AddAccountInfoDigest(accountInfoStr, path); ACCOUNT_LOGD("end"); return ERR_OK; } @@ -1407,33 +1072,6 @@ ErrCode OsAccountControlFileManager::GetAllowCreateId(int &id) return ERR_OK; } -ErrCode OsAccountControlFileManager::GetAccountInfoDigestFromFile( - const std::string &path, uint8_t *digest, uint32_t size) -{ - Json accountInfoDigestJson; - std::string accountInfoDigest; - std::lock_guard lock(accountInfoDigestFileLock_); - ErrCode errCode = accountFileOperator_->GetFileContentByPath(Constants::ACCOUNT_INFO_DIGEST_FILE_PATH, - accountInfoDigest); - if (errCode != ERR_OK) { - ACCOUNT_LOGE("GetFileContentByPath failed! error code %{public}d.", errCode); - return errCode; - } - try { - accountInfoDigestJson = Json::parse(accountInfoDigest, nullptr, false); - } catch (Json::type_error& err) { - ACCOUNT_LOGE("accountInfoDigestJson parse failed! reason: %{public}s", err.what()); - return ERR_ACCOUNT_COMMON_DUMP_JSON_ERROR; - } - std::vector digestTmp; - OHOS::AccountSA::GetDataByType>(accountInfoDigestJson, - accountInfoDigestJson.end(), path, digestTmp, OHOS::AccountSA::JsonType::ARRAY); - if (memcpy_s(digest, size, digestTmp.data(), ALG_COMMON_SIZE) != EOK) { - ACCOUNT_LOGE("Get digest failed duo to memcpy_s failed"); - return ERR_ACCOUNT_COMMON_INSUFFICIENT_MEMORY_ERROR; - } - return ERR_OK; -} ErrCode OsAccountControlFileManager::GetAccountListFromFile(Json &accountListJson) { @@ -1463,7 +1101,7 @@ ErrCode OsAccountControlFileManager::GetAccountIndexFromFile(Json &accountIndexJ { accountIndexJson.clear(); std::string accountIndex; - if (!accountFileOperator_->IsExistFile(Constants::ACCOUNT_INDEX_JSON_PATH)) { + if (!accountFileOperator_->IsJsonFileReady(Constants::ACCOUNT_INDEX_JSON_PATH)) { ErrCode result = GetAccountIndexInfo(accountIndex); if (result != ERR_OK) { ACCOUNT_LOGE("GetAccountIndexInfo error code %{public}d.", result); @@ -1672,11 +1310,7 @@ ErrCode OsAccountControlFileManager::SaveAccountListToFile(const Json &accountLi ACCOUNT_LOGE("cannot save save account list file content!"); return result; } - std::string digestStr; - result = GenerateAccountInfoDigestStr(Constants::ACCOUNT_LIST_FILE_JSON_PATH, accountListJson.dump(), digestStr); - if (result == ERR_OK) { - accountFileOperator_->InputFileByPathAndContent(Constants::ACCOUNT_INFO_DIGEST_FILE_PATH, digestStr); - } + accountFileWatcherMgr_.AddAccountInfoDigest(accountListJson.dump(), Constants::ACCOUNT_LIST_FILE_JSON_PATH); ACCOUNT_LOGD("save account list file succeed!"); return ERR_OK; } @@ -1690,7 +1324,8 @@ ErrCode OsAccountControlFileManager::SaveBaseOAConstraintsToFile(const Json &bas ACCOUNT_LOGE("cannot save base osaccount constraints file content!"); return result; } - + accountFileWatcherMgr_.AddAccountInfoDigest( + baseOAConstraints.dump(), Constants::BASE_OSACCOUNT_CONSTRAINTS_JSON_PATH); return ERR_OK; } @@ -1703,7 +1338,8 @@ ErrCode OsAccountControlFileManager::SaveGlobalOAConstraintsToFile(const Json &g ACCOUNT_LOGE("cannot save global osAccount constraints file content!"); return result; } - + accountFileWatcherMgr_.AddAccountInfoDigest( + globalOAConstraints.dump(), Constants::GLOBAL_OSACCOUNT_CONSTRAINTS_JSON_PATH); return ERR_OK; } @@ -1716,7 +1352,8 @@ ErrCode OsAccountControlFileManager::SaveSpecificOAConstraintsToFile(const Json ACCOUNT_LOGE("cannot save specific osAccount constraints file content!"); return result; } - + accountFileWatcherMgr_.AddAccountInfoDigest( + specificOAConstraints.dump(), Constants::SPECIFIC_OSACCOUNT_CONSTRAINTS_JSON_PATH); return ERR_OK; } @@ -1739,6 +1376,7 @@ ErrCode OsAccountControlFileManager::GetDeviceOwnerId(int &deviceOwnerId) ErrCode OsAccountControlFileManager::UpdateDeviceOwnerId(const int deviceOwnerId) { + std::lock_guard lock(accountInfoFileLock_); Json globalOAConstraintsJson; ErrCode result = GetGlobalOAConstraintsFromFile(globalOAConstraintsJson); if (result != ERR_OK) { diff --git a/services/accountmgr/test/unittest/account_iam/account_iam_callback_test.cpp b/services/accountmgr/test/unittest/account_iam/account_iam_callback_test.cpp index d75dc429d..18eb2c280 100644 --- a/services/accountmgr/test/unittest/account_iam/account_iam_callback_test.cpp +++ b/services/accountmgr/test/unittest/account_iam/account_iam_callback_test.cpp @@ -384,7 +384,7 @@ HWTEST_F(AccountIamCallbackTest, GetCredInfoCallbackWrapper_OnCredentialInfo_010 HWTEST_F(AccountIamCallbackTest, GetPropCallbackWrapper_OnResult_0100, TestSize.Level0) { Attributes extraInfo; - auto getPropCallback = std::make_shared(nullptr); + auto getPropCallback = std::make_shared(DEFAULT_USER_ID, nullptr); EXPECT_TRUE(getPropCallback->innerCallback_ == nullptr); getPropCallback->OnResult(0, extraInfo); } @@ -475,7 +475,7 @@ HWTEST_F(AccountIamCallbackTest, GetCredInfoCallbackWrapper_OnCredentialInfo_040 HWTEST_F(AccountIamCallbackTest, SetPropCallbackWrapper_OnResult_0100, TestSize.Level0) { Attributes extraInfo; - auto setPropCallback = std::make_shared(nullptr); + auto setPropCallback = std::make_shared(DEFAULT_USER_ID, nullptr); EXPECT_TRUE(setPropCallback->innerCallback_ == nullptr); setPropCallback->OnResult(0, extraInfo); } diff --git a/services/accountmgr/test/unittest/ohos_account/BUILD.gn b/services/accountmgr/test/unittest/ohos_account/BUILD.gn index 1656470af..312b7ed13 100644 --- a/services/accountmgr/test/unittest/ohos_account/BUILD.gn +++ b/services/accountmgr/test/unittest/ohos_account/BUILD.gn @@ -150,7 +150,7 @@ group("unittest") { testonly = true deps = [ - ":OhosDataDealTest", + #":OhosDataDealTest", ":OhosServiceTest", ] }