18e745fdaSopenharmony_ci/* 28e745fdaSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 38e745fdaSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 48e745fdaSopenharmony_ci * you may not use this file except in compliance with the License. 58e745fdaSopenharmony_ci * You may obtain a copy of the License at 68e745fdaSopenharmony_ci * 78e745fdaSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 88e745fdaSopenharmony_ci * 98e745fdaSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 108e745fdaSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 118e745fdaSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 128e745fdaSopenharmony_ci * See the License for the specific language governing permissions and 138e745fdaSopenharmony_ci * limitations under the License. 148e745fdaSopenharmony_ci */ 158e745fdaSopenharmony_ci 168e745fdaSopenharmony_ci#include "open_vpn_ctl.h" 178e745fdaSopenharmony_ci 188e745fdaSopenharmony_ci#include <fstream> 198e745fdaSopenharmony_ci 208e745fdaSopenharmony_ci#include "base64_utils.h" 218e745fdaSopenharmony_ci#include "netmanager_base_common_utils.h" 228e745fdaSopenharmony_ci#include "netmgr_ext_log_wrapper.h" 238e745fdaSopenharmony_ci 248e745fdaSopenharmony_cinamespace OHOS { 258e745fdaSopenharmony_cinamespace NetManagerStandard { 268e745fdaSopenharmony_ci 278e745fdaSopenharmony_ciOpenvpnCtl::OpenvpnCtl(sptr<VpnConfig> config, const std::string &pkg, int32_t userId, 288e745fdaSopenharmony_ci std::vector<int32_t> &activeUserIds) : NetVpnImpl(config, pkg, userId, activeUserIds) 298e745fdaSopenharmony_ci{ 308e745fdaSopenharmony_ci} 318e745fdaSopenharmony_ci 328e745fdaSopenharmony_ciint32_t OpenvpnCtl::SetUp() 338e745fdaSopenharmony_ci{ 348e745fdaSopenharmony_ci UpdateOpenvpnState(OPENVPN_STATE_SETUP); 358e745fdaSopenharmony_ci return StartOpenvpn(); 368e745fdaSopenharmony_ci} 378e745fdaSopenharmony_ci 388e745fdaSopenharmony_ciint32_t OpenvpnCtl::StartOpenvpn() 398e745fdaSopenharmony_ci{ 408e745fdaSopenharmony_ci if (openvpnConfig_ == nullptr) { 418e745fdaSopenharmony_ci NETMGR_EXT_LOG_E("StartOpenvpn openvpnConfig_ is null"); 428e745fdaSopenharmony_ci return NETMANAGER_EXT_ERR_INTERNAL; 438e745fdaSopenharmony_ci } 448e745fdaSopenharmony_ci UpdateOpenvpnState(OPENVPN_STATE_STARTED); 458e745fdaSopenharmony_ci if (!std::filesystem::exists(VPN_PIDDIR) || !std::filesystem::is_directory(VPN_PIDDIR)) { 468e745fdaSopenharmony_ci NETMGR_EXT_LOG_E("StartOpenvpn config dir check error."); 478e745fdaSopenharmony_ci return NETMANAGER_EXT_ERR_INTERNAL; 488e745fdaSopenharmony_ci } 498e745fdaSopenharmony_ci std::string cfg = Base64::Decode(openvpnConfig_->ovpnConfig_); 508e745fdaSopenharmony_ci std::ofstream ofs(OPENVPN_CONFIG_FILE, std::ios::out | std::ios::trunc); 518e745fdaSopenharmony_ci if (!ofs.is_open()) { 528e745fdaSopenharmony_ci NETMGR_EXT_LOG_E("StartOpenvpn config file open failed"); 538e745fdaSopenharmony_ci return NETMANAGER_EXT_ERR_INTERNAL; 548e745fdaSopenharmony_ci } 558e745fdaSopenharmony_ci ofs << cfg; 568e745fdaSopenharmony_ci if (!openvpnConfig_->askpass_.empty()) { 578e745fdaSopenharmony_ci std::ofstream askpassOfs(OPENVPN_ASKPASS_FILE, std::ios::out | std::ios::trunc); 588e745fdaSopenharmony_ci if (!askpassOfs.is_open()) { 598e745fdaSopenharmony_ci NETMGR_EXT_LOG_E("StartOpenvpn askpass file open failed"); 608e745fdaSopenharmony_ci return NETMANAGER_EXT_ERR_INTERNAL; 618e745fdaSopenharmony_ci } 628e745fdaSopenharmony_ci askpassOfs << openvpnConfig_->askpass_ << std::endl; 638e745fdaSopenharmony_ci ofs << OPENVPN_ASKPASS_PARAM << std::endl; 648e745fdaSopenharmony_ci } 658e745fdaSopenharmony_ci NetsysController::GetInstance().ProcessVpnStage(SysVpnStageCode::VPN_STAGE_OPENVPN_RESTART); 668e745fdaSopenharmony_ci return NETMANAGER_EXT_SUCCESS; 678e745fdaSopenharmony_ci} 688e745fdaSopenharmony_ci 698e745fdaSopenharmony_ciint32_t OpenvpnCtl::NotifyConnectStage(const std::string &stage, const int32_t &result) 708e745fdaSopenharmony_ci{ 718e745fdaSopenharmony_ci if (stage.empty()) { 728e745fdaSopenharmony_ci NETMGR_EXT_LOG_E("stage is empty"); 738e745fdaSopenharmony_ci return NETMANAGER_EXT_ERR_PARAMETER_ERROR; 748e745fdaSopenharmony_ci } 758e745fdaSopenharmony_ci if (result != NETMANAGER_EXT_SUCCESS) { 768e745fdaSopenharmony_ci NETMGR_EXT_LOG_E("vpn stage failed, result: %{public}d", result); 778e745fdaSopenharmony_ci return NETMANAGER_EXT_ERR_INTERNAL; 788e745fdaSopenharmony_ci } 798e745fdaSopenharmony_ci return HandleClientMessage(stage); 808e745fdaSopenharmony_ci} 818e745fdaSopenharmony_ci 828e745fdaSopenharmony_ciint32_t OpenvpnCtl::SetUpVpnTun() 838e745fdaSopenharmony_ci{ 848e745fdaSopenharmony_ci int result = NetVpnImpl::SetUp(); 858e745fdaSopenharmony_ci if (result != NETMANAGER_EXT_SUCCESS) { 868e745fdaSopenharmony_ci NETMGR_EXT_LOG_W("openvpn SetUp failed"); 878e745fdaSopenharmony_ci StopOpenvpn(); 888e745fdaSopenharmony_ci UpdateOpenvpnState(OPENVPN_STATE_DISCONNECTED); 898e745fdaSopenharmony_ci } 908e745fdaSopenharmony_ci NETMGR_EXT_LOG_I("openvpn SetUp %{public}d", result); 918e745fdaSopenharmony_ci return result; 928e745fdaSopenharmony_ci} 938e745fdaSopenharmony_ci 948e745fdaSopenharmony_ciint32_t OpenvpnCtl::HandleClientMessage(const std::string &msg) 958e745fdaSopenharmony_ci{ 968e745fdaSopenharmony_ci int result = NETMANAGER_EXT_SUCCESS; 978e745fdaSopenharmony_ci if (msg.empty()) { 988e745fdaSopenharmony_ci NETMGR_EXT_LOG_E("msg is empty"); 998e745fdaSopenharmony_ci return NETMANAGER_EXT_ERR_PARAMETER_ERROR; 1008e745fdaSopenharmony_ci } 1018e745fdaSopenharmony_ci NETMGR_EXT_LOG_I("Process Request message: %{public}s", MaskOpenvpnMessage(msg).c_str()); 1028e745fdaSopenharmony_ci if (strstr(msg.c_str(), OPENVPN_NODE_ROOT) != 0) { 1038e745fdaSopenharmony_ci const char *ret = strstr(msg.c_str(), "{"); 1048e745fdaSopenharmony_ci if (ret == nullptr) { 1058e745fdaSopenharmony_ci NETMGR_EXT_LOG_E("client message format error"); 1068e745fdaSopenharmony_ci return NETMANAGER_EXT_ERR_PARAMETER_ERROR; 1078e745fdaSopenharmony_ci } 1088e745fdaSopenharmony_ci cJSON* message = cJSON_Parse(ret); 1098e745fdaSopenharmony_ci if (message == nullptr) { 1108e745fdaSopenharmony_ci NETMGR_EXT_LOG_E("not json string"); 1118e745fdaSopenharmony_ci return NETMANAGER_EXT_ERR_PARAMETER_ERROR; 1128e745fdaSopenharmony_ci } 1138e745fdaSopenharmony_ci // is config message 1148e745fdaSopenharmony_ci cJSON* config = cJSON_GetObjectItem(message, OPENVPN_NODE_CONFIG); 1158e745fdaSopenharmony_ci if (config != nullptr && cJSON_IsObject(config)) { 1168e745fdaSopenharmony_ci UpdateConfig(config); 1178e745fdaSopenharmony_ci } 1188e745fdaSopenharmony_ci // is state message 1198e745fdaSopenharmony_ci cJSON* state = cJSON_GetObjectItem(message, OPENVPN_NODE_UPDATE_STATE); 1208e745fdaSopenharmony_ci if (state != nullptr && cJSON_IsObject(state)) { 1218e745fdaSopenharmony_ci UpdateState(state); 1228e745fdaSopenharmony_ci } 1238e745fdaSopenharmony_ci // is setup message 1248e745fdaSopenharmony_ci cJSON* vpnSetUp = cJSON_GetObjectItem(message, OPENVPN_NODE_SETUP_VPN_TUN); 1258e745fdaSopenharmony_ci if (vpnSetUp != nullptr && cJSON_IsObject(vpnSetUp)) { 1268e745fdaSopenharmony_ci result = SetUpVpnTun(); 1278e745fdaSopenharmony_ci } 1288e745fdaSopenharmony_ci cJSON_Delete(message); 1298e745fdaSopenharmony_ci } 1308e745fdaSopenharmony_ci return result; 1318e745fdaSopenharmony_ci} 1328e745fdaSopenharmony_ci 1338e745fdaSopenharmony_civoid OpenvpnCtl::UpdateState(cJSON* state) 1348e745fdaSopenharmony_ci{ 1358e745fdaSopenharmony_ci cJSON* updateState = cJSON_GetObjectItem(state, OPENVPN_NODE_STATE); 1368e745fdaSopenharmony_ci if (updateState != nullptr && cJSON_IsNumber(updateState)) { 1378e745fdaSopenharmony_ci int32_t openVpnState = static_cast<int32_t>(cJSON_GetNumberValue(updateState)); 1388e745fdaSopenharmony_ci UpdateOpenvpnState(openVpnState); 1398e745fdaSopenharmony_ci if (openVpnState == OPENVPN_STATE_DISCONNECTED || openVpnState >= OPENVPN_STATE_ERROR_PRIVATE_KEY) { 1408e745fdaSopenharmony_ci NETMGR_EXT_LOG_I("UpdatesState: %{public}d", openVpnState); 1418e745fdaSopenharmony_ci StopOpenvpn(); 1428e745fdaSopenharmony_ci } 1438e745fdaSopenharmony_ci } 1448e745fdaSopenharmony_ci} 1458e745fdaSopenharmony_ci 1468e745fdaSopenharmony_civoid OpenvpnCtl::UpdateConfig(cJSON *jConfig) 1478e745fdaSopenharmony_ci{ 1488e745fdaSopenharmony_ci if (vpnConfig_ == nullptr) { 1498e745fdaSopenharmony_ci NETMGR_EXT_LOG_E("UpdateConfig vpnConfig_ is null"); 1508e745fdaSopenharmony_ci return; 1518e745fdaSopenharmony_ci } 1528e745fdaSopenharmony_ci cJSON *mtu = cJSON_GetObjectItem(jConfig, OPENVPN_NODE_MTU); 1538e745fdaSopenharmony_ci if (mtu != nullptr && cJSON_IsNumber(mtu)) { 1548e745fdaSopenharmony_ci int32_t openVpnMtu = static_cast<int32_t>(cJSON_GetNumberValue(mtu)); 1558e745fdaSopenharmony_ci vpnConfig_->mtu_ = openVpnMtu; 1568e745fdaSopenharmony_ci NETMGR_EXT_LOG_I("UpdateConfig mtu %{public}d", openVpnMtu); 1578e745fdaSopenharmony_ci } 1588e745fdaSopenharmony_ci INetAddr iNetAddr; 1598e745fdaSopenharmony_ci INetAddr destination; 1608e745fdaSopenharmony_ci INetAddr gateway; 1618e745fdaSopenharmony_ci Route iRoute; 1628e745fdaSopenharmony_ci cJSON *address = cJSON_GetObjectItem(jConfig, OPENVPN_NODE_ADDRESS); 1638e745fdaSopenharmony_ci if (address != nullptr && cJSON_IsString(address)) { 1648e745fdaSopenharmony_ci std::string openVpnAddress = cJSON_GetStringValue(address); 1658e745fdaSopenharmony_ci iNetAddr.address_ = openVpnAddress; 1668e745fdaSopenharmony_ci gateway.address_ = openVpnAddress; 1678e745fdaSopenharmony_ci destination.address_ = openVpnAddress; 1688e745fdaSopenharmony_ci } 1698e745fdaSopenharmony_ci cJSON *netmask = cJSON_GetObjectItem(jConfig, OPENVPN_NODE_NETMASK); 1708e745fdaSopenharmony_ci if (netmask != nullptr && cJSON_IsString(netmask)) { 1718e745fdaSopenharmony_ci std::string openVpnNetmask = cJSON_GetStringValue(netmask); 1728e745fdaSopenharmony_ci iNetAddr.netMask_ = openVpnNetmask; 1738e745fdaSopenharmony_ci destination.prefixlen_ = CommonUtils::GetMaskLength(openVpnNetmask); 1748e745fdaSopenharmony_ci NETMGR_EXT_LOG_I("UpdateConfig prefixlen %{public}d", destination.prefixlen_); 1758e745fdaSopenharmony_ci } 1768e745fdaSopenharmony_ci vpnConfig_->addresses_.emplace_back(iNetAddr); 1778e745fdaSopenharmony_ci 1788e745fdaSopenharmony_ci iRoute.iface_ = TUN_CARD_NAME; 1798e745fdaSopenharmony_ci iRoute.isDefaultRoute_ = true; 1808e745fdaSopenharmony_ci iRoute.destination_ = destination; 1818e745fdaSopenharmony_ci iRoute.gateway_ = gateway; 1828e745fdaSopenharmony_ci vpnConfig_->routes_.emplace_back(iRoute); 1838e745fdaSopenharmony_ci} 1848e745fdaSopenharmony_ci 1858e745fdaSopenharmony_civoid OpenvpnCtl::UpdateOpenvpnState(const int32_t state) 1868e745fdaSopenharmony_ci{ 1878e745fdaSopenharmony_ci switch (state) { 1888e745fdaSopenharmony_ci case OPENVPN_STATE_CONNECTED: 1898e745fdaSopenharmony_ci NotifyConnectState(VpnConnectState::VPN_CONNECTED); 1908e745fdaSopenharmony_ci break; 1918e745fdaSopenharmony_ci case OPENVPN_STATE_DISCONNECTED: 1928e745fdaSopenharmony_ci case OPENVPN_STATE_ERROR_PRIVATE_KEY: 1938e745fdaSopenharmony_ci case OPENVPN_STATE_ERROR_CLIENT_CRT: 1948e745fdaSopenharmony_ci case OPENVPN_STATE_ERROR_CA_CAT: 1958e745fdaSopenharmony_ci case OPENVPN_STATE_ERROR_TIME_OUT: 1968e745fdaSopenharmony_ci NotifyConnectState(VpnConnectState::VPN_DISCONNECTED); 1978e745fdaSopenharmony_ci break; 1988e745fdaSopenharmony_ci default: 1998e745fdaSopenharmony_ci NETMGR_EXT_LOG_E("unknown openvpn state: %{public}d", state); 2008e745fdaSopenharmony_ci break; 2018e745fdaSopenharmony_ci } 2028e745fdaSopenharmony_ci openvpnState_ = state; 2038e745fdaSopenharmony_ci} 2048e745fdaSopenharmony_ci 2058e745fdaSopenharmony_cibool OpenvpnCtl::IsSystemVpn() 2068e745fdaSopenharmony_ci{ 2078e745fdaSopenharmony_ci return true; 2088e745fdaSopenharmony_ci} 2098e745fdaSopenharmony_ci 2108e745fdaSopenharmony_ciint32_t OpenvpnCtl::Destroy() 2118e745fdaSopenharmony_ci{ 2128e745fdaSopenharmony_ci StopOpenvpn(); 2138e745fdaSopenharmony_ci int result = NetVpnImpl::Destroy(); 2148e745fdaSopenharmony_ci NETMGR_EXT_LOG_I("openvpn Destroy result %{public}d}", result); 2158e745fdaSopenharmony_ci return result; 2168e745fdaSopenharmony_ci} 2178e745fdaSopenharmony_ci 2188e745fdaSopenharmony_civoid OpenvpnCtl::StopOpenvpn() 2198e745fdaSopenharmony_ci{ 2208e745fdaSopenharmony_ci NetsysController::GetInstance().ProcessVpnStage(SysVpnStageCode::VPN_STAGE_OPENVPN_STOP); 2218e745fdaSopenharmony_ci UpdateOpenvpnState(OPENVPN_STATE_DISCONNECTED); 2228e745fdaSopenharmony_ci} 2238e745fdaSopenharmony_ci 2248e745fdaSopenharmony_ciint32_t OpenvpnCtl::GetConnectedSysVpnConfig(sptr<SysVpnConfig> &sysVpnConfig) 2258e745fdaSopenharmony_ci{ 2268e745fdaSopenharmony_ci if (openvpnState_ == OPENVPN_STATE_CONNECTED && openvpnConfig_ != nullptr) { 2278e745fdaSopenharmony_ci sysVpnConfig = openvpnConfig_; 2288e745fdaSopenharmony_ci } 2298e745fdaSopenharmony_ci return NETMANAGER_EXT_SUCCESS; 2308e745fdaSopenharmony_ci} 2318e745fdaSopenharmony_ci 2328e745fdaSopenharmony_cibool OpenvpnCtl::IsInternalVpn() 2338e745fdaSopenharmony_ci{ 2348e745fdaSopenharmony_ci return true; 2358e745fdaSopenharmony_ci} 2368e745fdaSopenharmony_ci 2378e745fdaSopenharmony_cistd::string OpenvpnCtl::MaskOpenvpnMessage(const std::string &msg) 2388e745fdaSopenharmony_ci{ 2398e745fdaSopenharmony_ci if (msg.empty()) { 2408e745fdaSopenharmony_ci NETMGR_EXT_LOG_E("msg is empty"); 2418e745fdaSopenharmony_ci return ""; 2428e745fdaSopenharmony_ci } 2438e745fdaSopenharmony_ci std::string result = msg; 2448e745fdaSopenharmony_ci size_t addressPos = result.find(OPENVPN_NODE_CONFIG); 2458e745fdaSopenharmony_ci if (addressPos != std::string::npos) { 2468e745fdaSopenharmony_ci size_t pos = addressPos + strlen(OPENVPN_NODE_CONFIG); 2478e745fdaSopenharmony_ci size_t replaceLen = result.size() - pos; 2488e745fdaSopenharmony_ci if (replaceLen > 0) { 2498e745fdaSopenharmony_ci result.replace(pos, replaceLen, OPENVPN_MASK_TAG); 2508e745fdaSopenharmony_ci } 2518e745fdaSopenharmony_ci return result; 2528e745fdaSopenharmony_ci } 2538e745fdaSopenharmony_ci 2548e745fdaSopenharmony_ci return msg; 2558e745fdaSopenharmony_ci} 2568e745fdaSopenharmony_ci} // namespace NetManagerStandard 2578e745fdaSopenharmony_ci} // namespace OHOS