• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <cstdint>
17 #include <memory>
18 #include <mutex>
19 
20 #include "ability_manager_client.h"
21 #include "errorcode_convertor.h"
22 #include "extension_ability_info.h"
23 #include "module_template.h"
24 #include "napi/native_node_api.h"
25 #include "napi_common_want.h"
26 #include "napi_utils.h"
27 #include "net_datashare_utils_iface.h"
28 #include "net_manager_constants.h"
29 #include "netmanager_ext_log.h"
30 #include "networkvpn_client.h"
31 #include "vpn_connection_ext.h"
32 #include "vpn_extension_context.h"
33 #include "vpn_monitor_ext.h"
34 #include "want.h"
35 
36 namespace OHOS {
37 namespace NetManagerStandard {
38 constexpr int32_t ARG_NUM_0 = 0;
39 constexpr int32_t PARAM_ONE = 1;
40 
CreateResolvedPromise(napi_env env)41 static napi_value CreateResolvedPromise(napi_env env)
42 {
43     napi_deferred deferred = nullptr;
44     napi_value promise = nullptr;
45     if (napi_create_promise(env, &deferred, &promise) != napi_ok) {
46         return NapiUtils::GetUndefined(env);
47     }
48     napi_resolve_deferred(env, deferred, NapiUtils::GetUndefined(env));
49     return promise;
50 }
51 
CreateRejectedPromise(napi_env env)52 static napi_value CreateRejectedPromise(napi_env env)
53 {
54     napi_deferred deferred = nullptr;
55     napi_value promise = nullptr;
56     if (napi_create_promise(env, &deferred, &promise) != napi_ok) {
57         return NapiUtils::GetUndefined(env);
58     }
59     napi_reject_deferred(env, deferred, NapiUtils::GetUndefined(env));
60     return promise;
61 }
62 
ResolvePromiseInIpcThread(napi_env env,napi_deferred deferred)63 static void ResolvePromiseInIpcThread(napi_env env, napi_deferred deferred)
64 {
65     napi_send_event(
66         env, [env, deferred]() { napi_resolve_deferred(env, deferred, NapiUtils::GetUndefined(env)); },
67         napi_eprio_high);
68 }
69 
RejectPromiseInIpcThread(napi_env env,napi_deferred deferred)70 static void RejectPromiseInIpcThread(napi_env env, napi_deferred deferred)
71 {
72     napi_send_event(
73         env, [env, deferred]() { napi_reject_deferred(env, deferred, NapiUtils::GetUndefined(env)); }, napi_eprio_high);
74 }
75 
CreateObserveDataSharePromise(napi_env env,const std::string & bundleName)76 static napi_value CreateObserveDataSharePromise(napi_env env, const std::string &bundleName)
77 {
78     napi_deferred deferred = nullptr;
79     napi_value promise = nullptr;
80     if (napi_create_promise(env, &deferred, &promise) != napi_ok) {
81         return NapiUtils::GetUndefined(env);
82     }
83 
84     auto once = std::make_shared<std::once_flag>();
85     auto callbackId = std::make_shared<int32_t>();
86     auto deferWrapper = std::make_shared<napi_deferred>();
87     *deferWrapper = deferred;
88     auto onChange = [env, deferWrapper, bundleName, once, callbackId]() {
89         if (!once) {
90             return;
91         }
92         std::call_once(*once, [env, deferWrapper, bundleName, callbackId]() {
93             bool vpnDialogSelect = false;
94             std::string vpnExtMode = std::to_string(vpnDialogSelect);
95             int32_t ret = NetDataShareHelperUtilsIface::Query(VPNEXT_MODE_URI, bundleName, vpnExtMode);
96             NETMANAGER_EXT_LOGI("query vpn state after dialog: %{public}d %{public}s", ret, vpnExtMode.c_str());
97             if (callbackId) {
98                 NetDataShareHelperUtilsIface::UnregisterObserver(VPNEXT_MODE_URI, *callbackId);
99             }
100             if (deferWrapper && *deferWrapper) {
101                 auto deferred = *deferWrapper;
102                 *deferWrapper = nullptr;
103                 if (vpnExtMode == "1") {
104                     ResolvePromiseInIpcThread(env, deferred);
105                 } else {
106                     RejectPromiseInIpcThread(env, deferred);
107                 }
108             }
109         });
110     };
111 
112     *callbackId = NetDataShareHelperUtilsIface::RegisterObserver(VPNEXT_MODE_URI, onChange);
113     return promise;
114 }
115 
MakeDataExt(napi_env env,size_t argc,napi_value * argv,EventManager * manager)116 static void *MakeDataExt(napi_env env, size_t argc, napi_value *argv, EventManager *manager)
117 {
118     if ((argc != PARAM_ONE) || (NapiUtils::GetValueType(env, argv[ARG_NUM_0]) != napi_object)) {
119         NETMANAGER_EXT_LOGE("funciton prameter error");
120         napi_throw_error(env, std::to_string(NETMANAGER_EXT_ERR_PARAMETER_ERROR).c_str(), "Parameter error");
121         return nullptr;
122     }
123 
124     VpnExtensionContext *vpnExtensionContext = nullptr;
125     napi_status status = napi_unwrap(env, argv[ARG_NUM_0], reinterpret_cast<void **>(&vpnExtensionContext));
126     if (status != napi_ok || vpnExtensionContext == nullptr) {
127         NETMANAGER_EXT_LOGE("Failed to get vpnExtensionContext napi instance");
128         napi_throw_error(env, std::to_string(NETMANAGER_EXT_ERR_PARAMETER_ERROR).c_str(), "Parameter error");
129         return nullptr;
130     }
131 
132     int32_t ret = NetworkVpnClient::GetInstance().CreateVpnConnection(true);
133     if (ret != NETMANAGER_EXT_SUCCESS) {
134         NETMANAGER_EXT_LOGE("execute CreateVpnConnection failed: %{public}d", ret);
135         std::string errorMsg = NetBaseErrorCodeConvertor().ConvertErrorCode(ret);
136         napi_throw_error(env, std::to_string(ret).c_str(), errorMsg.c_str());
137         return nullptr;
138     }
139     return reinterpret_cast<void *>(&NetworkVpnClient::GetInstance());
140 }
141 
Replace(std::string s)142 static std::string Replace(std::string s)
143 {
144     std::string tmp = VPN_DIALOG_POSTFIX;
145     auto pos = s.find(tmp);
146     if (pos == std::string::npos) {
147         return s;
148     }
149     s.replace(pos, tmp.length(), "");
150     return s;
151 }
152 
ProcessPermissionRequests(napi_env env,const std::string & bundleName,const std::string & abilityName)153 napi_value ProcessPermissionRequests(napi_env env, const std::string &bundleName, const std::string &abilityName)
154 {
155     std::string selfAppName;
156     std::string selfBundleName;
157     auto getAppNameRes = NetworkVpnClient::GetInstance().GetSelfAppName(selfAppName, selfBundleName);
158     NETMANAGER_EXT_LOGI("StartVpnExtensionAbility SelfAppName = %{public}s %{public}d", selfAppName.c_str(),
159         getAppNameRes);
160     if (bundleName != selfBundleName) {
161         NETMANAGER_EXT_LOGE("Not allowed to start other bundleName vpn!");
162         return CreateRejectedPromise(env);
163     }
164 
165     bool vpnDialogSelect = false;
166     std::string vpnExtMode = std::to_string(vpnDialogSelect);
167     int32_t ret = NetDataShareHelperUtilsIface::Query(VPNEXT_MODE_URI, bundleName, vpnExtMode);
168     if (ret != 0 || vpnExtMode != "1") {
169         NETMANAGER_EXT_LOGE("dataShareHelperUtils Query error, err = %{public}d", ret);
170         VpnMonitor::GetInstance().ShowVpnDialog(bundleName, abilityName, selfAppName);
171         return CreateObserveDataSharePromise(env, bundleName);
172     }
173     return nullptr;
174 }
175 
StartVpnExtensionAbility(napi_env env,napi_callback_info info)176 napi_value StartVpnExtensionAbility(napi_env env, napi_callback_info info)
177 {
178     napi_value thisVal = nullptr;
179     std::size_t argc = MAX_PARAM_NUM;
180 
181     napi_value argv[MAX_PARAM_NUM] = {nullptr};
182     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVal, nullptr));
183     if ((argc != PARAM_ONE) || (NapiUtils::GetValueType(env, argv[ARG_NUM_0]) != napi_object)) {
184         NETMANAGER_EXT_LOGE("funciton prameter error");
185         napi_throw_error(env, std::to_string(NETMANAGER_EXT_ERR_PARAMETER_ERROR).c_str(), "Parameter error");
186         return CreateRejectedPromise(env);
187     }
188     AAFwk::Want want;
189     int32_t accountId = -1;
190     if (!AppExecFwk::UnwrapWant(env, argv[0], want)) {
191         NETMANAGER_EXT_LOGE("Failed to parse want");
192         napi_throw_error(env, std::to_string(NETMANAGER_EXT_ERR_PARAMETER_ERROR).c_str(), "Parse want error");
193         return CreateRejectedPromise(env);
194     }
195 
196     std::string bundleName = want.GetElement().GetBundleName();
197     std::string abilityName = want.GetElement().GetAbilityName();
198     if (abilityName.find(VPN_DIALOG_POSTFIX) == std::string::npos) {
199         NetworkVpnClient::GetInstance().SetSelfVpnPid();
200         napi_value retVal = ProcessPermissionRequests(env, bundleName, abilityName);
201         if (retVal != nullptr) {
202             return retVal;
203         }
204     }
205     auto elem = want.GetElement();
206     elem.SetAbilityName(Replace(abilityName));
207     want.SetElement(elem);
208     ErrCode err = AAFwk::AbilityManagerClient::GetInstance()->StartExtensionAbility(
209         want, nullptr, accountId, AppExecFwk::ExtensionAbilityType::VPN);
210     NETMANAGER_EXT_LOGI("execute StartVpnExtensionAbility result: %{public}d", err);
211     if (err == 0) {
212         int32_t rst = NetworkVpnClient::GetInstance().RegisterBundleName(bundleName, Replace(abilityName));
213         NETMANAGER_EXT_LOGI("VPN RegisterBundleName result = %{public}d", rst);
214     }
215     return CreateResolvedPromise(env);
216 }
217 
StopVpnExtensionAbility(napi_env env,napi_callback_info info)218 napi_value StopVpnExtensionAbility(napi_env env, napi_callback_info info)
219 {
220     napi_value thisVal = nullptr;
221     std::size_t argc = MAX_PARAM_NUM;
222 
223     napi_value argv[MAX_PARAM_NUM] = {nullptr};
224     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVal, nullptr));
225     if ((argc != PARAM_ONE) || (NapiUtils::GetValueType(env, argv[ARG_NUM_0]) != napi_object)) {
226         NETMANAGER_EXT_LOGE("funciton prameter error");
227         napi_throw_error(env, std::to_string(NETMANAGER_EXT_ERR_PARAMETER_ERROR).c_str(), "Parameter error");
228         return CreateRejectedPromise(env);
229     }
230     AAFwk::Want want;
231     int32_t accountId = -1;
232     if (!AppExecFwk::UnwrapWant(env, argv[0], want)) {
233         NETMANAGER_EXT_LOGE("Failed to parse want");
234         napi_throw_error(env, std::to_string(NETMANAGER_EXT_ERR_PARAMETER_ERROR).c_str(), "Parse want error");
235         return CreateRejectedPromise(env);
236     }
237 
238     std::string bundleName = want.GetElement().GetBundleName();
239     std::string selfAppName;
240     std::string selfBundleName;
241     auto getAppNameRes = NetworkVpnClient::GetInstance().GetSelfAppName(selfAppName, selfBundleName);
242     NETMANAGER_EXT_LOGI("StopVpnExtensionAbility SelfAppName = %{public}s %{public}d", selfAppName.c_str(),
243         getAppNameRes);
244     if (bundleName != selfBundleName) {
245         NETMANAGER_EXT_LOGE("Not allowed to stop other bundleName vpn!");
246         return CreateRejectedPromise(env);
247     }
248     bool vpnDialogSelect = false;
249     std::string vpnExtMode = std::to_string(vpnDialogSelect);
250     int32_t ret = NetDataShareHelperUtilsIface::Query(VPNEXT_MODE_URI, bundleName, vpnExtMode);
251     if (ret != 0 || vpnExtMode != "1") {
252         NETMANAGER_EXT_LOGE("dataShareHelperUtils Query error, err = %{public}d", ret);
253         return CreateRejectedPromise(env);
254     }
255 
256     ErrCode err = AAFwk::AbilityManagerClient::GetInstance()->StopExtensionAbility(
257         want, nullptr, accountId, AppExecFwk::ExtensionAbilityType::VPN);
258     NETMANAGER_EXT_LOGI("execute StopExtensionAbility result: %{public}d", err);
259     return CreateResolvedPromise(env);
260 }
261 
CreateVpnConnection(napi_env env,napi_callback_info info)262 static napi_value CreateVpnConnection(napi_env env, napi_callback_info info)
263 {
264     return ModuleTemplate::NewInstance(env, info, VPN_CONNECTION_EXT, MakeDataExt, [](napi_env, void *data, void *) {
265         NETMANAGER_EXT_LOGI("finalize VpnConnection");
266     });
267 }
268 
UpdateVpnAuthorize(napi_env env,napi_callback_info info)269 static napi_value UpdateVpnAuthorize(napi_env env, napi_callback_info info)
270 {
271     napi_value thisVal = nullptr;
272     std::size_t argc = MAX_PARAM_NUM;
273     napi_value argv[MAX_PARAM_NUM] = {nullptr};
274     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVal, nullptr));
275 
276     if ((argc != PARAM_ONE) || (NapiUtils::GetValueType(env, argv[ARG_NUM_0]) != napi_string)) {
277         NETMANAGER_EXT_LOGE("funciton prameter error");
278         napi_throw_error(env, std::to_string(NETMANAGER_EXT_ERR_PARAMETER_ERROR).c_str(), "Parameter error");
279         return nullptr;
280     }
281     std::string bundleName = NapiUtils::GetStringFromValueUtf8(env, argv[ARG_NUM_0]);
282 
283     bool vpnDialogSelect = true;
284     if (bundleName.find(VPN_DIALOG_POSTFIX) != std::string::npos) {
285         vpnDialogSelect = false;
286         bundleName = Replace(bundleName);
287     }
288     std::string vpnExtMode = std::to_string(vpnDialogSelect);
289     int32_t ret = NetDataShareHelperUtilsIface::Update(VPNEXT_MODE_URI, bundleName, vpnExtMode);
290     NETMANAGER_EXT_LOGI("UpdateVpnAuthorize result. ret = %{public}d", ret);
291 
292     napi_value jsValue = nullptr;
293     napi_get_boolean(env, true, &jsValue);
294     return jsValue;
295 }
296 
RegisterVpnExtModule(napi_env env,napi_value exports)297 napi_value RegisterVpnExtModule(napi_env env, napi_value exports)
298 {
299     NapiUtils::DefineProperties(env, exports,
300                                 {
301                                     DECLARE_NAPI_FUNCTION(CREATE_VPN_CONNECTION, CreateVpnConnection),
302                                     DECLARE_NAPI_FUNCTION(START_VPN_EXTENSION, StartVpnExtensionAbility),
303                                     DECLARE_NAPI_FUNCTION(STOP_VPN_EXTENSION, StopVpnExtensionAbility),
304                                     DECLARE_NAPI_FUNCTION(UPDATE_VPN_AUTHORIZE, UpdateVpnAuthorize),
305                                 });
306     ModuleTemplate::DefineClass(env, exports,
307                                 {
308                                     DECLARE_NAPI_FUNCTION(SET_UP_EXT, VpnConnectionExt::SetUp),
309                                     DECLARE_NAPI_FUNCTION(PROTECT_EXT, VpnConnectionExt::Protect),
310                                     DECLARE_NAPI_FUNCTION(DESTROY_EXT, VpnConnectionExt::Destroy),
311                                 },
312                                 VPN_CONNECTION_EXT);
313     return exports;
314 }
315 
316 static napi_module g_vpnModule = {
317     .nm_version = 1,
318     .nm_flags = 0,
319     .nm_filename = nullptr,
320     .nm_register_func = RegisterVpnExtModule,
321     .nm_modname = VPN_EXT_MODULE_NAME,
322     .nm_priv = nullptr,
323     .reserved = {nullptr},
324 };
325 
VpnNapiRegister()326 extern "C" __attribute__((constructor)) void VpnNapiRegister()
327 {
328     napi_module_register(&g_vpnModule);
329 }
330 } // namespace NetManagerStandard
331 } // namespace OHOS
332