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 #include "hi_app_event_report.h"
36 #ifdef SUPPORT_SYSVPN
37 #include "ipc_skeleton.h"
38 #include "os_account_manager.h"
39 #endif // SUPPORT_SYSVPN
40
41 namespace OHOS {
42 namespace NetManagerStandard {
43 constexpr int32_t ARG_NUM_0 = 0;
44 constexpr int32_t PARAM_ONE = 1;
45
CreateResolvedPromise(napi_env env)46 static napi_value CreateResolvedPromise(napi_env env)
47 {
48 napi_deferred deferred = nullptr;
49 napi_value promise = nullptr;
50 if (napi_create_promise(env, &deferred, &promise) != napi_ok) {
51 return NapiUtils::GetUndefined(env);
52 }
53 napi_resolve_deferred(env, deferred, NapiUtils::GetUndefined(env));
54 return promise;
55 }
56
CreateRejectedPromise(napi_env env)57 static napi_value CreateRejectedPromise(napi_env env)
58 {
59 napi_deferred deferred = nullptr;
60 napi_value promise = nullptr;
61 if (napi_create_promise(env, &deferred, &promise) != napi_ok) {
62 return NapiUtils::GetUndefined(env);
63 }
64 napi_reject_deferred(env, deferred, NapiUtils::GetUndefined(env));
65 return promise;
66 }
67
ResolvePromiseInIpcThread(napi_env env,napi_deferred deferred)68 static void ResolvePromiseInIpcThread(napi_env env, napi_deferred deferred)
69 {
70 napi_send_event(
71 env, [env, deferred]() { napi_resolve_deferred(env, deferred, NapiUtils::GetUndefined(env)); },
72 napi_eprio_high);
73 }
74
RejectPromiseInIpcThread(napi_env env,napi_deferred deferred)75 static void RejectPromiseInIpcThread(napi_env env, napi_deferred deferred)
76 {
77 napi_send_event(
78 env, [env, deferred]() { napi_reject_deferred(env, deferred, NapiUtils::GetUndefined(env)); }, napi_eprio_high);
79 }
80
CreateObserveDataSharePromise(napi_env env,const std::string & bundleName)81 static napi_value CreateObserveDataSharePromise(napi_env env, const std::string &bundleName)
82 {
83 napi_deferred deferred = nullptr;
84 napi_value promise = nullptr;
85 if (napi_create_promise(env, &deferred, &promise) != napi_ok) {
86 return NapiUtils::GetUndefined(env);
87 }
88
89 auto once = std::make_shared<std::once_flag>();
90 auto callbackId = std::make_shared<int32_t>();
91 auto deferWrapper = std::make_shared<napi_deferred>();
92 *deferWrapper = deferred;
93 auto onChange = [env, deferWrapper, bundleName, once, callbackId]() {
94 if (!once) {
95 return;
96 }
97 std::call_once(*once, [env, deferWrapper, bundleName, callbackId]() {
98 bool vpnDialogSelect = false;
99 std::string vpnExtMode = std::to_string(vpnDialogSelect);
100 int32_t ret = NetDataShareHelperUtilsIface::Query(VPNEXT_MODE_URI, bundleName, vpnExtMode);
101 NETMANAGER_EXT_LOGI("query vpn state after dialog: %{public}d %{public}s", ret, vpnExtMode.c_str());
102 if (callbackId) {
103 NetDataShareHelperUtilsIface::UnregisterObserver(VPNEXT_MODE_URI, *callbackId);
104 }
105 if (deferWrapper && *deferWrapper) {
106 auto deferred = *deferWrapper;
107 *deferWrapper = nullptr;
108 if (vpnExtMode == "1") {
109 ResolvePromiseInIpcThread(env, deferred);
110 } else {
111 RejectPromiseInIpcThread(env, deferred);
112 }
113 }
114 });
115 };
116
117 *callbackId = NetDataShareHelperUtilsIface::RegisterObserver(VPNEXT_MODE_URI, onChange);
118 return promise;
119 }
120
MakeDataExt(napi_env env,size_t argc,napi_value * argv,std::shared_ptr<EventManager> & manager)121 static void *MakeDataExt(napi_env env, size_t argc, napi_value *argv, std::shared_ptr<EventManager>& manager)
122 {
123 if ((argc != PARAM_ONE) || (NapiUtils::GetValueType(env, argv[ARG_NUM_0]) != napi_object)) {
124 NETMANAGER_EXT_LOGE("funciton prameter error");
125 napi_throw_error(env, std::to_string(NETMANAGER_EXT_ERR_PARAMETER_ERROR).c_str(), "Parameter error");
126 return nullptr;
127 }
128
129 VpnExtensionContext *vpnExtensionContext = nullptr;
130 napi_status status = napi_unwrap(env, argv[ARG_NUM_0], reinterpret_cast<void **>(&vpnExtensionContext));
131 if (status != napi_ok || vpnExtensionContext == nullptr) {
132 NETMANAGER_EXT_LOGE("Failed to get vpnExtensionContext napi instance");
133 napi_throw_error(env, std::to_string(NETMANAGER_EXT_ERR_PARAMETER_ERROR).c_str(), "Parameter error");
134 return nullptr;
135 }
136
137 int32_t ret = NetworkVpnClient::GetInstance().CreateVpnConnection(true);
138 if (ret != NETMANAGER_EXT_SUCCESS) {
139 NETMANAGER_EXT_LOGE("execute CreateVpnConnection failed: %{public}d", ret);
140 std::string errorMsg = NetBaseErrorCodeConvertor().ConvertErrorCode(ret);
141 napi_throw_error(env, std::to_string(ret).c_str(), errorMsg.c_str());
142 return nullptr;
143 }
144 return reinterpret_cast<void *>(&NetworkVpnClient::GetInstance());
145 }
146
Replace(std::string s)147 static std::string Replace(std::string s)
148 {
149 std::string tmp = VPN_DIALOG_POSTFIX;
150 auto pos = s.find(tmp);
151 if (pos == std::string::npos) {
152 return s;
153 }
154 s.replace(pos, tmp.length(), "");
155 return s;
156 }
157
158 #ifdef SUPPORT_SYSVPN
CheckVpnPermission(const std::string & bundleName,std::string & vpnExtMode)159 int32_t CheckVpnPermission(const std::string &bundleName, std::string &vpnExtMode)
160 {
161 int32_t userId = AppExecFwk::Constants::UNSPECIFIED_USERID;
162 int32_t uid = IPCSkeleton::GetCallingUid();
163 if (AccountSA::OsAccountManager::GetOsAccountLocalIdFromUid(uid, userId) != ERR_OK) {
164 NETMANAGER_EXT_LOGE("checkVpnPermission::GetOsAccountLocalIdFromUid error, uid: %{public}d.", uid);
165 return -1;
166 }
167 NETMANAGER_EXT_LOGI("checkVpnPermission uid: %{public}d, userid: %{public}d", uid, userId);
168 std::string key = bundleName + "_" + std::to_string(userId);
169 int32_t ret = NetDataShareHelperUtilsIface::Query(VPNEXT_MODE_URI, key, vpnExtMode);
170 if (ret != 0 || vpnExtMode != "1") {
171 ret = NetDataShareHelperUtilsIface::Query(VPNEXT_MODE_URI, bundleName, vpnExtMode);
172 if (ret != 0 || vpnExtMode != "1") {
173 NETMANAGER_EXT_LOGE("checkVpnPermission::dataShareHelperUtils Query error, err = %{public}d", ret);
174 return -1;
175 }
176 }
177 return 0;
178 }
179 #endif // SUPPORT_SYSVPN
180
ProcessPermissionRequests(napi_env env,const std::string & bundleName,const std::string & abilityName)181 napi_value ProcessPermissionRequests(napi_env env, const std::string &bundleName, const std::string &abilityName)
182 {
183 std::string selfAppName;
184 std::string selfBundleName;
185 auto getAppNameRes = NetworkVpnClient::GetInstance().GetSelfAppName(selfAppName, selfBundleName);
186 NETMANAGER_EXT_LOGI("StartVpnExtensionAbility SelfAppName = %{public}s %{public}d", selfAppName.c_str(),
187 getAppNameRes);
188 if (bundleName != selfBundleName) {
189 NETMANAGER_EXT_LOGE("Not allowed to start other bundleName vpn!");
190 return CreateRejectedPromise(env);
191 }
192
193 bool vpnDialogSelect = false;
194 std::string vpnExtMode = std::to_string(vpnDialogSelect);
195 int32_t ret = 0;
196 #ifdef SUPPORT_SYSVPN
197 ret = CheckVpnPermission(bundleName, vpnExtMode);
198 #else
199 ret = NetDataShareHelperUtilsIface::Query(VPNEXT_MODE_URI, bundleName, vpnExtMode);
200 #endif // SUPPORT_SYSVPN
201 if (ret != 0 || vpnExtMode != "1") {
202 NETMANAGER_EXT_LOGE("dataShareHelperUtils Query error, err = %{public}d", ret);
203 VpnMonitor::GetInstance().ShowVpnDialog(bundleName, abilityName, selfAppName);
204 return CreateObserveDataSharePromise(env, bundleName);
205 }
206 return nullptr;
207 }
208
StartVpnExtensionAbility(napi_env env,napi_callback_info info)209 napi_value StartVpnExtensionAbility(napi_env env, napi_callback_info info)
210 {
211 HiAppEventReport hiAppEventReport("NetworkKit", "VpnStartVpnExtensionAbility");
212 napi_value thisVal = nullptr;
213 std::size_t argc = MAX_PARAM_NUM;
214
215 napi_value argv[MAX_PARAM_NUM] = {nullptr};
216 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVal, nullptr));
217 if ((argc != PARAM_ONE) || (NapiUtils::GetValueType(env, argv[ARG_NUM_0]) != napi_object)) {
218 NETMANAGER_EXT_LOGE("funciton prameter error");
219 napi_throw_error(env, std::to_string(NETMANAGER_EXT_ERR_PARAMETER_ERROR).c_str(), "Parameter error");
220 return CreateRejectedPromise(env);
221 }
222 AAFwk::Want want;
223 int32_t accountId = -1;
224 if (!AppExecFwk::UnwrapWant(env, argv[0], want)) {
225 NETMANAGER_EXT_LOGE("Failed to parse want");
226 napi_throw_error(env, std::to_string(NETMANAGER_EXT_ERR_PARAMETER_ERROR).c_str(), "Parse want error");
227 return CreateRejectedPromise(env);
228 }
229
230 std::string bundleName = want.GetElement().GetBundleName();
231 std::string abilityName = want.GetElement().GetAbilityName();
232 std::string selfAppName;
233 std::string selfBundleName;
234 NetworkVpnClient::GetInstance().GetSelfAppName(selfAppName, selfBundleName);
235 if (selfBundleName != VPN_DIALOG_BUNDLENAME || abilityName.find(VPN_DIALOG_POSTFIX) == std::string::npos) {
236 NetworkVpnClient::GetInstance().SetSelfVpnPid();
237 napi_value retVal = ProcessPermissionRequests(env, bundleName, abilityName);
238 if (retVal != nullptr) {
239 return retVal;
240 }
241 }
242 auto elem = want.GetElement();
243 elem.SetAbilityName(Replace(abilityName));
244 want.SetElement(elem);
245 if (OHOS::system::GetBoolParameter("persist.edm.vpn_disable", false)) {
246 napi_throw_error(env, std::to_string(NETMANAGER_EXT_ERR_PERMISSION_DENIED).c_str(),
247 "persist.edm.vpn_disable disallowed setting up vpn");
248 return CreateRejectedPromise(env);
249 }
250 ErrCode err = AAFwk::AbilityManagerClient::GetInstance()->StartExtensionAbility(
251 want, nullptr, accountId, AppExecFwk::ExtensionAbilityType::VPN);
252 NETMANAGER_EXT_LOGI("execute StartVpnExtensionAbility result: %{public}d", err);
253 hiAppEventReport.ReportSdkEvent(RESULT_SUCCESS, err);
254 if (err == 0) {
255 int32_t rst = NetworkVpnClient::GetInstance().RegisterBundleName(bundleName, Replace(abilityName));
256 NETMANAGER_EXT_LOGI("VPN RegisterBundleName result = %{public}d", rst);
257 hiAppEventReport.ReportSdkEvent(RESULT_SUCCESS, rst);
258 }
259 hiAppEventReport.ReportSdkEvent(RESULT_SUCCESS, ERR_NONE);
260 return CreateResolvedPromise(env);
261 }
262
StopVpnExtensionAbility(napi_env env,napi_callback_info info)263 napi_value StopVpnExtensionAbility(napi_env env, napi_callback_info info)
264 {
265 HiAppEventReport hiAppEventReport("NetworkKit", "VpnStopVpnExtensionAbility");
266 napi_value thisVal = nullptr;
267 std::size_t argc = MAX_PARAM_NUM;
268
269 napi_value argv[MAX_PARAM_NUM] = {nullptr};
270 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVal, nullptr));
271 if ((argc != PARAM_ONE) || (NapiUtils::GetValueType(env, argv[ARG_NUM_0]) != napi_object)) {
272 NETMANAGER_EXT_LOGE("funciton prameter error");
273 napi_throw_error(env, std::to_string(NETMANAGER_EXT_ERR_PARAMETER_ERROR).c_str(), "Parameter error");
274 return CreateRejectedPromise(env);
275 }
276 AAFwk::Want want;
277 int32_t accountId = -1;
278 if (!AppExecFwk::UnwrapWant(env, argv[0], want)) {
279 NETMANAGER_EXT_LOGE("Failed to parse want");
280 napi_throw_error(env, std::to_string(NETMANAGER_EXT_ERR_PARAMETER_ERROR).c_str(), "Parse want error");
281 return CreateRejectedPromise(env);
282 }
283
284 std::string bundleName = want.GetElement().GetBundleName();
285 std::string selfAppName;
286 std::string selfBundleName;
287 auto getAppNameRes = NetworkVpnClient::GetInstance().GetSelfAppName(selfAppName, selfBundleName);
288 NETMANAGER_EXT_LOGI("StopVpnExtensionAbility SelfAppName = %{public}s %{public}d", selfAppName.c_str(),
289 getAppNameRes);
290 if (bundleName != selfBundleName) {
291 NETMANAGER_EXT_LOGE("Not allowed to stop other bundleName vpn!");
292 return CreateRejectedPromise(env);
293 }
294 bool vpnDialogSelect = false;
295 std::string vpnExtMode = std::to_string(vpnDialogSelect);
296 int32_t ret = 0;
297 #ifdef SUPPORT_SYSVPN
298 ret = CheckVpnPermission(bundleName, vpnExtMode);
299 #else
300 ret = NetDataShareHelperUtilsIface::Query(VPNEXT_MODE_URI, bundleName, vpnExtMode);
301 #endif // SUPPORT_SYSVPN
302 if (ret != 0 || vpnExtMode != "1") {
303 NETMANAGER_EXT_LOGE("dataShareHelperUtils Query error, err = %{public}d", ret);
304 hiAppEventReport.ReportSdkEvent(RESULT_SUCCESS, ret);
305 return CreateRejectedPromise(env);
306 }
307
308 ErrCode err = AAFwk::AbilityManagerClient::GetInstance()->StopExtensionAbility(
309 want, nullptr, accountId, AppExecFwk::ExtensionAbilityType::VPN);
310 NETMANAGER_EXT_LOGI("execute StopExtensionAbility result: %{public}d", err);
311 hiAppEventReport.ReportSdkEvent(RESULT_SUCCESS, err);
312 return CreateResolvedPromise(env);
313 }
314
CreateVpnConnection(napi_env env,napi_callback_info info)315 static napi_value CreateVpnConnection(napi_env env, napi_callback_info info)
316 {
317 return ModuleTemplate::NewInstance(env, info, VPN_CONNECTION_EXT, MakeDataExt, [](napi_env, void *data, void *) {
318 NETMANAGER_EXT_LOGI("finalize VpnConnection");
319 });
320 }
321
UpdateVpnAuthorize(napi_env env,napi_callback_info info)322 static napi_value UpdateVpnAuthorize(napi_env env, napi_callback_info info)
323 {
324 napi_value thisVal = nullptr;
325 std::size_t argc = MAX_PARAM_NUM;
326 napi_value argv[MAX_PARAM_NUM] = {nullptr};
327 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVal, nullptr));
328
329 if ((argc != PARAM_ONE) || (NapiUtils::GetValueType(env, argv[ARG_NUM_0]) != napi_string)) {
330 NETMANAGER_EXT_LOGE("funciton prameter error");
331 napi_throw_error(env, std::to_string(NETMANAGER_EXT_ERR_PARAMETER_ERROR).c_str(), "Parameter error");
332 return nullptr;
333 }
334 std::string bundleName = NapiUtils::GetStringFromValueUtf8(env, argv[ARG_NUM_0]);
335
336 bool vpnDialogSelect = true;
337 if (bundleName.find(VPN_DIALOG_POSTFIX) != std::string::npos) {
338 vpnDialogSelect = false;
339 bundleName = Replace(bundleName);
340 }
341 std::string vpnExtMode = std::to_string(vpnDialogSelect);
342 int32_t ret = 0;
343 #ifdef SUPPORT_SYSVPN
344 int32_t userId = AppExecFwk::Constants::UNSPECIFIED_USERID;
345 int32_t uid = IPCSkeleton::GetCallingUid();
346 if (AccountSA::OsAccountManager::GetOsAccountLocalIdFromUid(uid, userId) != ERR_OK) {
347 NETMANAGER_EXT_LOGE("GetOsAccountLocalIdFromUid error, uid: %{public}d.", uid);
348 return nullptr;
349 }
350 std::string key = bundleName + "_" + std::to_string(userId);
351 ret = NetDataShareHelperUtilsIface::Update(VPNEXT_MODE_URI, key, vpnExtMode);
352 #else
353 ret = NetDataShareHelperUtilsIface::Update(VPNEXT_MODE_URI, bundleName, vpnExtMode);
354 #endif // SUPPORT_SYSVPN
355 NETMANAGER_EXT_LOGI("UpdateVpnAuthorize result. ret = %{public}d", ret);
356
357 napi_value jsValue = nullptr;
358 napi_get_boolean(env, true, &jsValue);
359 return jsValue;
360 }
361
RegisterVpnExtModule(napi_env env,napi_value exports)362 napi_value RegisterVpnExtModule(napi_env env, napi_value exports)
363 {
364 NapiUtils::DefineProperties(env, exports,
365 {
366 DECLARE_NAPI_FUNCTION(CREATE_VPN_CONNECTION, CreateVpnConnection),
367 DECLARE_NAPI_FUNCTION(START_VPN_EXTENSION, StartVpnExtensionAbility),
368 DECLARE_NAPI_FUNCTION(STOP_VPN_EXTENSION, StopVpnExtensionAbility),
369 DECLARE_NAPI_FUNCTION(UPDATE_VPN_AUTHORIZE, UpdateVpnAuthorize),
370 });
371 ModuleTemplate::DefineClass(env, exports,
372 {
373 DECLARE_NAPI_FUNCTION(SET_UP_EXT, VpnConnectionExt::SetUp),
374 DECLARE_NAPI_FUNCTION(PROTECT_EXT, VpnConnectionExt::Protect),
375 DECLARE_NAPI_FUNCTION(DESTROY_EXT, VpnConnectionExt::Destroy),
376 #ifdef SUPPORT_SYSVPN
377 DECLARE_NAPI_FUNCTION(GENERATE_VPN_ID_EXT, VpnConnectionExt::GenerateVpnId),
378 #endif // SUPPORT_SYSVPN
379 },
380 VPN_CONNECTION_EXT);
381 return exports;
382 }
383
384 static napi_module g_vpnModule = {
385 .nm_version = 1,
386 .nm_flags = 0,
387 .nm_filename = nullptr,
388 .nm_register_func = RegisterVpnExtModule,
389 .nm_modname = VPN_EXT_MODULE_NAME,
390 .nm_priv = nullptr,
391 .reserved = {nullptr},
392 };
393
VpnNapiRegister()394 extern "C" __attribute__((constructor)) void VpnNapiRegister()
395 {
396 napi_module_register(&g_vpnModule);
397 }
398 } // namespace NetManagerStandard
399 } // namespace OHOS
400