1 /*
2 * Copyright (c) 2024 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 "ipsec_vpn_ctl.h"
17
18 #include <string>
19 #include <sys/stat.h>
20
21 #include "multi_vpn_helper.h"
22 #include "netmgr_ext_log_wrapper.h"
23 #include "netmanager_base_common_utils.h"
24 #include "net_manager_ext_constants.h"
25
26 namespace OHOS {
27 namespace NetManagerStandard {
IpsecVpnCtl(sptr<VpnConfig> config,const std::string & pkg,int32_t userId,std::vector<int32_t> & activeUserIds)28 IpsecVpnCtl::IpsecVpnCtl(sptr<VpnConfig> config, const std::string &pkg, int32_t userId,
29 std::vector<int32_t> &activeUserIds)
30 : NetVpnImpl(config, pkg, userId, activeUserIds)
31 {}
32
~IpsecVpnCtl()33 IpsecVpnCtl::~IpsecVpnCtl()
34 {
35 NETMGR_EXT_LOG_I("~IpsecVpnCtl");
36 }
37
IsSystemVpn()38 bool IpsecVpnCtl::IsSystemVpn()
39 {
40 return true;
41 }
42
SetUp()43 int32_t IpsecVpnCtl::SetUp()
44 {
45 return StartSysVpn();
46 }
47
Destroy()48 int32_t IpsecVpnCtl::Destroy()
49 {
50 StopSysVpn();
51 if (multiVpnInfo_ != nullptr) {
52 NetsysController::GetInstance().ProcessVpnStage(SysVpnStageCode::VPN_STAGE_SET_VPN_CALL_MODE,
53 multiVpnInfo_->isVpnExtCall ? "0" : "1");
54 }
55 int result = NetVpnImpl::Destroy();
56 NETMGR_EXT_LOG_I("ipsec Destroy result %{public}d", result);
57 return result;
58 }
59
StopSysVpn()60 int32_t IpsecVpnCtl::StopSysVpn()
61 {
62 NETMGR_EXT_LOG_I("stop ipsec vpn");
63 state_ = IpsecVpnStateCode::STATE_DISCONNECTED;
64 std::string baseConnectName = IPSEC_CONNECT_NAME;
65 std::string connectName = multiVpnInfo_ == nullptr ? baseConnectName :
66 baseConnectName + std::to_string(multiVpnInfo_->ifNameId);
67 NetsysController::GetInstance().ProcessVpnStage(
68 SysVpnStageCode::VPN_STAGE_DOWN_HOME, connectName);
69 MultiVpnHelper::GetInstance().StopIpsec();
70 NotifyConnectState(VpnConnectState::VPN_DISCONNECTED);
71 return NETMANAGER_EXT_SUCCESS;
72 }
73
StartSysVpn()74 int32_t IpsecVpnCtl::StartSysVpn()
75 {
76 NETMGR_EXT_LOG_I("start ipsec vpn");
77 state_ = IpsecVpnStateCode::STATE_INIT;
78 InitConfigFile();
79 if (!MultiVpnHelper::GetInstance().StartIpsec()) {
80 state_ = IpsecVpnStateCode::STATE_STARTED;
81 NetsysController::GetInstance().ProcessVpnStage(SysVpnStageCode::VPN_STAGE_SWANCTL_LOAD);
82 };
83 return NETMANAGER_EXT_SUCCESS;
84 }
85
InitConfigFile()86 int32_t IpsecVpnCtl::InitConfigFile()
87 {
88 CleanTempFiles();
89 if (ipsecVpnConfig_ == nullptr) {
90 NETMGR_EXT_LOG_E("InitConfigFile ipsecVpnConfig is null");
91 return NETMANAGER_EXT_ERR_INTERNAL;
92 }
93 if (!ipsecVpnConfig_->strongswanConf_.empty()) {
94 CommonUtils::WriteFile(SWAN_CONFIG_FILE, ipsecVpnConfig_->strongswanConf_);
95 chmod(SWAN_CONFIG_FILE, S_IRUSR | S_IWUSR | S_IRGRP);
96 }
97 return NETMANAGER_EXT_SUCCESS;
98 }
99
CleanTempFiles()100 void IpsecVpnCtl::CleanTempFiles()
101 {
102 DeleteTempFile(SWAN_CONFIG_FILE);
103 DeleteTempFile(L2TP_CFG);
104 }
105
DeleteTempFile(const std::string & fileName)106 void IpsecVpnCtl::DeleteTempFile(const std::string &fileName)
107 {
108 if (std::filesystem::exists(fileName)) {
109 if (!std::filesystem::remove(fileName)) {
110 NETMGR_EXT_LOG_E("remove old cache file failed");
111 }
112 }
113 }
114
SetUpVpnTun()115 int32_t IpsecVpnCtl::SetUpVpnTun()
116 {
117 if (multiVpnInfo_ != nullptr) {
118 NetsysController::GetInstance().ProcessVpnStage(SysVpnStageCode::VPN_STAGE_SET_VPN_CALL_MODE,
119 multiVpnInfo_->isVpnExtCall ? "0" : "1");
120 }
121 if (NetVpnImpl::SetUp() != NETMANAGER_EXT_SUCCESS) {
122 StopSysVpn();
123 NETMGR_EXT_LOG_I("ipsec SetUp failed");
124 return NETMANAGER_EXT_ERR_INTERNAL;
125 }
126 if (multiVpnInfo_ != nullptr && vpnConfig_ != nullptr) {
127 multiVpnInfo_->localAddress = vpnConfig_->addresses_.empty() ?
128 "" : vpnConfig_->addresses_.back().address_;
129 }
130 NETMGR_EXT_LOG_I("ipsec SetUp success");
131 return NETMANAGER_EXT_SUCCESS;
132 }
133
UpdateConfig(const std::string & msg)134 int32_t IpsecVpnCtl::UpdateConfig(const std::string &msg)
135 {
136 if (msg.empty()) {
137 NETMGR_EXT_LOG_E("msg is empty");
138 return NETMANAGER_EXT_ERR_PARAMETER_ERROR;
139 }
140 const char *ret = strstr(msg.c_str(), "{");
141 if (ret == nullptr) {
142 NETMGR_EXT_LOG_E("client rootJson format error");
143 return NETMANAGER_EXT_ERR_PARAMETER_ERROR;
144 }
145 cJSON* rootJson = cJSON_Parse(ret);
146 if (rootJson == nullptr) {
147 NETMGR_EXT_LOG_E("not json string");
148 return NETMANAGER_EXT_ERR_PARAMETER_ERROR;
149 }
150
151 cJSON* jConfig = cJSON_GetObjectItem(rootJson, IPSEC_NODE_UPDATE_CONFIG);
152 if (!cJSON_IsObject(jConfig)) {
153 NETMGR_EXT_LOG_E("jConfig format error");
154 cJSON_Delete(rootJson);
155 return NETMANAGER_EXT_ERR_PARAMETER_ERROR;
156 }
157 ProcessUpdateConfig(jConfig);
158
159 cJSON_Delete(rootJson);
160 rootJson = nullptr;
161 if (vpnConfig_ != nullptr) {
162 std::string addr = vpnConfig_->addresses_.empty() ? "" : vpnConfig_->addresses_.back().address_;
163 if (MultiVpnHelper::GetInstance().CheckAndCompareMultiVpnLocalAddress(addr) != NETMANAGER_EXT_SUCCESS) {
164 NETMGR_EXT_LOG_E("ipsec check ip address is same error.");
165 return NETMANAGER_EXT_ERR_INTERNAL;
166 }
167 }
168 return NETMANAGER_EXT_SUCCESS;
169 }
170
171
NotifyConnectStage(const std::string & stage,const int32_t & result)172 int32_t IpsecVpnCtl::NotifyConnectStage(const std::string &stage, const int32_t &result)
173 {
174 if (stage.empty()) {
175 NETMGR_EXT_LOG_E("stage is empty");
176 return NETMANAGER_EXT_ERR_PARAMETER_ERROR;
177 }
178 if (result != NETMANAGER_EXT_SUCCESS) {
179 NETMGR_EXT_LOG_E("ipsec vpn connect failed");
180 HandleIpsecConnectFailed(result);
181 return NETMANAGER_EXT_ERR_INTERNAL;
182 }
183 switch (state_) {
184 case IpsecVpnStateCode::STATE_INIT:
185 if (stage.compare(IPSEC_START_TAG) == 0) {
186 ProcessSwanctlLoad();
187 }
188 break;
189 case IpsecVpnStateCode::STATE_STARTED:
190 if (stage.compare(SWANCTL_START_TAG) == 0) {
191 ProcessIpsecUp();
192 }
193 break;
194 case IpsecVpnStateCode::STATE_CONFIGED:
195 if (stage.compare(IPSEC_CONNECT_TAG) == 0) {
196 HandleConnected();
197 }
198 if (stage.find(IPSEC_NODE_UPDATE_CONFIG) != std::string::npos) {
199 if (HandleUpdateConfig(stage) != NETMANAGER_EXT_SUCCESS) {
200 return NETMANAGER_EXT_ERR_INTERNAL;
201 }
202 }
203 break;
204 default:
205 NETMGR_EXT_LOG_E("invalid state: %{public}d", state_);
206 return NETMANAGER_EXT_ERR_INTERNAL;
207 }
208 return NETMANAGER_EXT_SUCCESS;
209 }
210
GetSysVpnCertUri(const int32_t certType,std::string & certUri)211 int32_t IpsecVpnCtl::GetSysVpnCertUri(const int32_t certType, std::string &certUri)
212 {
213 if (ipsecVpnConfig_ == nullptr) {
214 NETMGR_EXT_LOG_E("GetSysVpnCertUri ipsecVpnConfig is null");
215 return NETMANAGER_EXT_ERR_INTERNAL;
216 }
217 switch (certType) {
218 case IpsecVpnCertType::CA_CERT:
219 certUri = ipsecVpnConfig_->ipsecCaCertConf_;
220 break;
221 case IpsecVpnCertType::USER_CERT:
222 certUri = ipsecVpnConfig_->ipsecPublicUserCertConf_;
223 break;
224 case IpsecVpnCertType::SERVER_CERT:
225 certUri = ipsecVpnConfig_->ipsecPublicServerCertConf_;
226 break;
227 case IpsecVpnCertType::SWAN_CTL_CONF:
228 certUri = ipsecVpnConfig_->swanctlConf_;
229 break;
230 default:
231 NETMGR_EXT_LOG_E("invalid certType: %{public}d", certType);
232 break;
233 }
234 return NETMANAGER_EXT_SUCCESS;
235 }
236
GetVpnCertData(const int32_t certType,std::vector<int8_t> & certData)237 int32_t IpsecVpnCtl::GetVpnCertData(const int32_t certType, std::vector<int8_t> &certData)
238 {
239 if (ipsecVpnConfig_ == nullptr) {
240 NETMGR_EXT_LOG_E("GetSysVpnCertUri ipsecVpnConfig is null");
241 return NETMANAGER_EXT_ERR_INTERNAL;
242 }
243 switch (certType) {
244 case IpsecVpnCertType::PKCS12_PASSWD: {
245 if (!ipsecVpnConfig_->pkcs12Password_.empty()) {
246 certData.assign(ipsecVpnConfig_->pkcs12Password_.begin(),
247 ipsecVpnConfig_->pkcs12Password_.end());
248 } else {
249 NETMGR_EXT_LOG_D("GetVpnCertData pkcs12 password is empty");
250 }
251 break;
252 }
253 case IpsecVpnCertType::PKCS12_DATA: {
254 if (!ipsecVpnConfig_->pkcs12FileData_.empty()) {
255 certData.assign(ipsecVpnConfig_->pkcs12FileData_.begin(),
256 ipsecVpnConfig_->pkcs12FileData_.end());
257 } else {
258 NETMGR_EXT_LOG_D("GetVpnCertData pkcs12 data is empty");
259 }
260 break;
261 }
262 default:
263 NETMGR_EXT_LOG_E("invalid certType: %{public}d", certType);
264 break;
265 }
266 return NETMANAGER_EXT_SUCCESS;
267 }
268
GetConnectedSysVpnConfig(sptr<SysVpnConfig> & sysVpnConfig)269 int32_t IpsecVpnCtl::GetConnectedSysVpnConfig(sptr<SysVpnConfig> &sysVpnConfig)
270 {
271 if (state_ == IpsecVpnStateCode::STATE_CONNECTED && ipsecVpnConfig_ != nullptr) {
272 NETMGR_EXT_LOG_I("GetConnectedSysVpnConfig success");
273 sysVpnConfig = ipsecVpnConfig_;
274 }
275 return NETMANAGER_EXT_SUCCESS;
276 }
277
IsInternalVpn()278 bool IpsecVpnCtl::IsInternalVpn()
279 {
280 return true;
281 }
282
ProcessUpdateConfig(cJSON * jConfig)283 void IpsecVpnCtl::ProcessUpdateConfig(cJSON* jConfig)
284 {
285 if (vpnConfig_ == nullptr) {
286 NETMGR_EXT_LOG_E("UpdateConfig vpnConfig_ is null");
287 return;
288 }
289 cJSON *mtu = cJSON_GetObjectItem(jConfig, IPSEC_NODE_MTU);
290 if (mtu != nullptr && cJSON_IsNumber(mtu)) {
291 int32_t ipsecVpnMtu = static_cast<int32_t>(cJSON_GetNumberValue(mtu));
292 vpnConfig_->mtu_ = ipsecVpnMtu;
293 NETMGR_EXT_LOG_I("UpdateConfig mtu %{public}d", ipsecVpnMtu);
294 }
295
296 INetAddr iNetAddr;
297 INetAddr destination;
298 INetAddr gateway;
299 cJSON *address = cJSON_GetObjectItem(jConfig, IPSEC_NODE_ADDRESS);
300 if (address != nullptr && cJSON_IsString(address)) {
301 std::string ipsecVpnAddress = cJSON_GetStringValue(address);
302 iNetAddr.address_ = ipsecVpnAddress;
303 gateway.address_ = ipsecVpnAddress;
304 destination.address_ = ipsecVpnAddress;
305 }
306
307 cJSON *netmask = cJSON_GetObjectItem(jConfig, IPSEC_NODE_NETMASK);
308 if (netmask != nullptr && cJSON_IsString(netmask)) {
309 std::string ipsecVpnNetmask = cJSON_GetStringValue(netmask);
310 iNetAddr.netMask_ = ipsecVpnNetmask;
311 destination.prefixlen_ = CommonUtils::GetMaskLength(ipsecVpnNetmask);
312 }
313
314 cJSON *phyIfNameObj = cJSON_GetObjectItem(jConfig, IPSEC_NODE_PHY_NAME);
315 if (phyIfNameObj != nullptr && cJSON_IsString(phyIfNameObj)) {
316 std::string phyIfName = cJSON_GetStringValue(phyIfNameObj);
317 NETMGR_EXT_LOG_I("phyIfName:%{public}s", phyIfName.c_str());
318 NetsysController::GetInstance().ProcessVpnStage(SysVpnStageCode::VPN_STAGE_SET_XFRM_PHY_IFNAME, phyIfName);
319 }
320
321 cJSON *dstIpObj = cJSON_GetObjectItem(jConfig, IPSEC_NODE_REMOTE_IP);
322 if (dstIpObj != nullptr && cJSON_IsString(dstIpObj)) {
323 std::string remoteIp = cJSON_GetStringValue(dstIpObj);
324 NetsysController::GetInstance().ProcessVpnStage(SysVpnStageCode::VPN_STAGE_SET_VPN_REMOTE_ADDRESS, remoteIp);
325 }
326 vpnConfig_->addresses_.emplace_back(iNetAddr);
327 ProcessDnsConfig(jConfig);
328 }
329
ProcessDnsConfig(cJSON * jConfig)330 int32_t IpsecVpnCtl::ProcessDnsConfig(cJSON* jConfig)
331 {
332 if (vpnConfig_ == nullptr) {
333 NETMGR_EXT_LOG_E("ProcessDnsConfig vpnConfig_ is null");
334 return NETMANAGER_EXT_ERR_INTERNAL;
335 }
336
337 for (auto it = vpnConfig_->dnsAddresses_.begin(); it != vpnConfig_->dnsAddresses_.end();) {
338 if (it->empty()) {
339 it = vpnConfig_->dnsAddresses_.erase(it);
340 } else {
341 ++it;
342 }
343 }
344 cJSON *primaryObj = cJSON_GetObjectItem(jConfig, PRIMARY_DNS);
345 if (primaryObj != nullptr && cJSON_IsString(primaryObj)) {
346 std::string dnsPrimary = cJSON_GetStringValue(primaryObj);
347 if (!dnsPrimary.empty()) {
348 vpnConfig_->dnsAddresses_.emplace_back(dnsPrimary);
349 }
350 }
351
352 cJSON *secondaryObj = cJSON_GetObjectItem(jConfig, SECONDARY_DNS);
353 if (secondaryObj != nullptr && cJSON_IsString(secondaryObj)) {
354 std::string dnsSecondary = cJSON_GetStringValue(secondaryObj);
355 if (!dnsSecondary.empty()) {
356 vpnConfig_->dnsAddresses_.emplace_back(dnsSecondary);
357 }
358 }
359 return NETMANAGER_EXT_SUCCESS;
360 }
361
ProcessSwanctlLoad()362 void IpsecVpnCtl::ProcessSwanctlLoad()
363 {
364 // 1. start strongswan
365 NETMGR_EXT_LOG_I("ipsec vpn setup step 1: start strongswan");
366 state_ = IpsecVpnStateCode::STATE_STARTED;
367 NetsysController::GetInstance().ProcessVpnStage(SysVpnStageCode::VPN_STAGE_SWANCTL_LOAD);
368 }
369
ProcessIpsecUp()370 void IpsecVpnCtl::ProcessIpsecUp()
371 {
372 // 2. start connect
373 NETMGR_EXT_LOG_I("ipsec vpn setup step 2: start connect");
374 state_ = IpsecVpnStateCode::STATE_CONFIGED;
375 std::string baseConnectName = IPSEC_CONNECT_NAME;
376 std::string connectName = multiVpnInfo_ == nullptr ? baseConnectName :
377 baseConnectName + std::to_string(multiVpnInfo_->ifNameId);
378 NetsysController::GetInstance().ProcessVpnStage(
379 SysVpnStageCode::VPN_STAGE_UP_HOME, std::string(connectName));
380 }
381
HandleConnected()382 void IpsecVpnCtl::HandleConnected()
383 {
384 // 3. is connected
385 NETMGR_EXT_LOG_I("ipsec vpn setup step 3: is connected");
386 state_ = IpsecVpnStateCode::STATE_CONNECTED;
387 NotifyConnectState(VpnConnectState::VPN_CONNECTED);
388 }
389
HandleUpdateConfig(const std::string & config)390 int32_t IpsecVpnCtl::HandleUpdateConfig(const std::string &config)
391 {
392 if (UpdateConfig(config) != NETMANAGER_EXT_SUCCESS) {
393 NETMGR_EXT_LOG_I("ipsec vpn config update failed");
394 return NETMANAGER_EXT_ERR_INTERNAL;
395 }
396 if (SetUpVpnTun() != NETMANAGER_EXT_SUCCESS) {
397 NETMGR_EXT_LOG_I("set up l2tp vpn failed");
398 return NETMANAGER_EXT_ERR_INTERNAL;
399 }
400 return NETMANAGER_EXT_SUCCESS;
401 }
402
HandleIpsecConnectFailed(const int32_t result)403 void IpsecVpnCtl::HandleIpsecConnectFailed(const int32_t result)
404 {
405 if (state_ == IpsecVpnStateCode::STATE_DISCONNECTED) {
406 NETMGR_EXT_LOG_I("ipsec already destroyed");
407 return;
408 }
409 if (multiVpnInfo_ != nullptr && ipsecVpnConfig_ != nullptr) {
410 VpnOperatorErrorType errorType;
411 switch (result) {
412 case VpnErrorCode::CONNECT_TIME_OUT:
413 errorType = VpnOperatorErrorType::ERROR_PEER_NO_RESPONSE;
414 break;
415 case VpnErrorCode::IKEV2_KEY_ERROR:
416 errorType = VpnOperatorErrorType::ERROR_IKEV2_KEY_INCORRECT;
417 break;
418 case VpnErrorCode::CA_ERROR:
419 errorType = VpnOperatorErrorType::ERROR_CA_INCORRECT;
420 break;
421 case VpnErrorCode::PASSWORD_ERROR:
422 errorType = VpnOperatorErrorType::ERROR_PASSWORD_INCORRECT;
423 break;
424 default:
425 Destroy();
426 return;
427 }
428 VpnHisysEvent::SetFaultVpnEvent(multiVpnInfo_->userId, multiVpnInfo_->bundleName,
429 VpnOperatorType::OPERATION_SETUP_VPN,
430 errorType, ipsecVpnConfig_->vpnType_);
431 }
432 Destroy();
433 }
434 } // namespace NetManagerStandard
435 } // namespace OHOS