1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "os_account_plugin_manager.h"
17 #include <chrono>
18 #include <dlfcn.h>
19 #include <unistd.h>
20 #include <future>
21 #include <pthread.h>
22 #include <thread>
23 
24 namespace OHOS {
25 namespace AccountSA {
26 namespace {
27 #ifdef _ARM64_
28 static const std::string OS_ACCOUNT_PLUGIN_LIB_PATH = "/system/lib64/platformsdk/";
29 #else
30 static const std::string OS_ACCOUNT_PLUGIN_LIB_PATH = "/system/lib/platformsdk/";
31 #endif
32 static const std::string OS_ACCOUNT_PLUGIN_LIB_NAME = "libactivation_lock_sdk.z.so";
33 }
34 
OsAccountPluginManager()35 OsAccountPluginManager::OsAccountPluginManager()
36 {
37     LoaderLib(OS_ACCOUNT_PLUGIN_LIB_PATH, OS_ACCOUNT_PLUGIN_LIB_NAME);
38     ACCOUNT_LOGI("OsAccountPluginManager init end.");
39 }
40 
~OsAccountPluginManager()41 OsAccountPluginManager::~OsAccountPluginManager()
42 {
43     CloseLib();
44 }
45 
GetInstance()46 OsAccountPluginManager &OsAccountPluginManager::GetInstance()
47 {
48     static OsAccountPluginManager *instance = new (std::nothrow) OsAccountPluginManager();
49     return *instance;
50 }
51 
GetMethodNameByEnum(OsPluginMethodEnum methondEnum)52 std::string GetMethodNameByEnum(OsPluginMethodEnum methondEnum)
53 {
54     switch (methondEnum) {
55         case OsPluginMethodEnum::VERIFY_ACTIVATION_LOCK:
56             return "VerifyActivationLock";
57         default:
58             ACCOUNT_LOGE("Find method name failed, enum=%{public}d.", methondEnum);
59             return "";
60     }
61 }
62 
LoaderLib(const std::string & path,const std::string & libName)63 void OsAccountPluginManager::LoaderLib(const std::string &path, const std::string &libName)
64 {
65     if (IsPluginAvailable()) {
66         ACCOUNT_LOGE("LibHandle_ is not nullptr.");
67         return;
68     }
69     std::lock_guard<std::mutex> lock(libMutex_);
70     std::string soPath = path + libName;
71     libHandle_ = dlopen(soPath.c_str(), RTLD_LAZY);
72     if (libHandle_ == nullptr) {
73         ACCOUNT_LOGE("Call dlopen failed, error=%{public}s.", dlerror());
74         return;
75     }
76     for (auto i = 0; i < static_cast<int>(OsPluginMethodEnum::OS_ACCOUNT_PLUGIN_COUNT); ++i) {
77         std::string methodName = GetMethodNameByEnum(static_cast<OsPluginMethodEnum>(i));
78         if (methodName.empty()) {
79             ACCOUNT_LOGE("Call check methodName empty.");
80             dlclose(libHandle_);
81             libHandle_ = nullptr;
82             methodMap_.clear();
83             return;
84         }
85         dlerror();
86         void *func = dlsym(libHandle_, methodName.c_str());
87         const char *dlsym_error = dlerror();
88         if (dlsym_error) {
89             ACCOUNT_LOGE("Call check failed, method=%{public}s error=%{public}s.", methodName.c_str(), dlsym_error);
90             dlclose(libHandle_);
91             libHandle_ = nullptr;
92             methodMap_.clear();
93             return;
94         }
95         methodMap_.emplace(static_cast<OsPluginMethodEnum>(i), func);
96     }
97     ACCOUNT_LOGI("Load library success.");
98 }
99 
CloseLib()100 void OsAccountPluginManager::CloseLib()
101 {
102     std::lock_guard<std::mutex> lock(libMutex_);
103     if (libHandle_ == nullptr) {
104         ACCOUNT_LOGE("LibHandle_ is nullptr.");
105         return;
106     }
107     dlclose(libHandle_);
108     libHandle_ = nullptr;
109 }
110 
IsPluginAvailable()111 bool OsAccountPluginManager::IsPluginAvailable()
112 {
113     std::lock_guard<std::mutex> lock(libMutex_, std::adopt_lock);
114     return libHandle_ != nullptr;
115 }
116 
PluginVerifyActivationLockFunc(bool & isAllowed)117 ErrCode OsAccountPluginManager::PluginVerifyActivationLockFunc(bool& isAllowed)
118 {
119     std::lock_guard<std::mutex> lock(libMutex_);
120     auto iter = methodMap_.find(OsPluginMethodEnum::VERIFY_ACTIVATION_LOCK);
121     if (iter == methodMap_.end() || iter->second == nullptr) {
122         ACCOUNT_LOGE("Caller method=%{public}d not exsit.", OsPluginMethodEnum::VERIFY_ACTIVATION_LOCK);
123         return ERR_OSACCOUNT_SERVICE_INNER_ACCOUNT_PLUGIN_NOT_EXIST_ERROR;
124     }
125 
126     auto promise = std::make_shared<std::promise<bool>>();
127     auto future = promise->get_future();
128     auto callback = [promise] (bool isActivated) mutable -> int32_t {
129         promise->set_value(isActivated);
130         return ERR_OK;
131     };
132 
133     int32_t res = (*reinterpret_cast<VerifyActivationLockFunc>(iter->second))(callback);
134     if (res != ERR_OK) {
135         ACCOUNT_LOGE("Call plugin method failed.");
136         return res;
137     }
138     isAllowed = future.get();
139     return ERR_OK;
140 }
141 
IsCreationAllowed()142 bool OsAccountPluginManager::IsCreationAllowed()
143 {
144 #if defined(ACCOUNT_TEST) || defined(ACCOUNT_COVERAGE_TEST)
145     return true;
146 #else
147     if (!IsPluginAvailable()) {
148         ACCOUNT_LOGI("Plugin not availabel.");
149         return true;
150     }
151     bool isAllowed = false;
152     ACCOUNT_LOGI("Call plugin method start.");
153     ErrCode res = PluginVerifyActivationLockFunc(isAllowed);
154     ACCOUNT_LOGI("Call plugin method end.");
155     if (res != ERR_OK) {
156         ACCOUNT_LOGE("Call IsOsAccountCreationAllowed failed, ErrCode=%{public}d", res);
157         return false;
158     }
159     return isAllowed;
160 #endif
161 }
162 }  // namespace AccountSA
163 }  // namespace OHOS