• 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 #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