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