1 /*
2 * Copyright (C) 2025 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 "eap_hdi_wpa_manager.h"
17
18 #include <filesystem>
19 #include <map>
20 #include <charconv>
21 #include <codecvt>
22 #include <fstream>
23
24 #include "base64_utils.h"
25 #include "net_eap_handler.h"
26 #include "netmgr_ext_log_wrapper.h"
27 #include "netmanager_base_common_utils.h"
28 #include "net_manager_constants.h"
29
30 namespace OHOS {
31 namespace NetManagerStandard {
32
33 static constexpr const char* ETHERNET_SERVICE_NAME = "ethernet_service";
34 static constexpr const char* ITEM_WPA_CTRL = "wpa_ctrl_";
35 static constexpr const char* ETH_CONFIG_ROOR_DIR = "/data/service/el1/public/eth";
36 static constexpr const char* ETH_WPA_CONFIG_PATH = "/data/service/el1/public/eth/eth_wpa_supplicant.conf";
37
38 static constexpr const char* ITEM_CTRL_IFACE = "ctrl_interface=/data/service/el1/public/eth\n";
39 static constexpr const char* ITEM_LINE = "\n";
40 static constexpr const char* ITEM_AP_SCAN = "ap_scan=0\n";
41 static constexpr const char* ITEM_NETWORK_START = "network={\n";
42 static constexpr const char* ITEM_NETWORK_END = "}\n";
43 static constexpr const char* ITEM_KEYMGMT = "key_mgmt=IEEE8021X\n";
44 static constexpr const char* ITEM_EAP = "eap=";
45 static constexpr const char* ITEM_PHASE2 = "phase2=";
46 static constexpr const char* ITEM_IDENTITY = "identity=";
47 static constexpr const char* ITEM_PASSWORD = "password=";
48 static constexpr const char* ITEM_CA_CERT = "ca_cert=";
49 static constexpr const char* ITEM_CLIENT_CERT = "client_cert=";
50 static constexpr const char* ITEM_PRIVATE_KEY = "private_key=";
51
52 static constexpr int8_t IDX_0 = 0;
53 static constexpr int8_t IDX_1 = 1;
54 static constexpr int8_t IDX_2 = 2;
55 static constexpr int8_t IDX_3 = 3;
56 static constexpr int8_t IDX_4 = 4;
57 static constexpr int8_t BASE_10 = 10;
58 static constexpr int8_t WPA_EVENT_REPORT_PARAM_CNT = 5;
59
60 static std::map<Phase2Method, std::string> PHASE2_METHOD_STR_MAP = {
61 { Phase2Method::PHASE2_NONE, "NONE" },
62 { Phase2Method::PHASE2_PAP, "PAP" },
63 { Phase2Method::PHASE2_MSCHAP, "MSCHAP" },
64 { Phase2Method::PHASE2_MSCHAPV2, "MSCHAPV2" },
65 { Phase2Method::PHASE2_GTC, "GTC" },
66 { Phase2Method::PHASE2_SIM, "SIM" },
67 { Phase2Method::PHASE2_AKA, "AKA" },
68 { Phase2Method::PHASE2_AKA_PRIME, "AKA" },
69 };
70 static std::map<EapMethod, std::string> EAP_METHOD_STR_MAP = {
71 { EapMethod::EAP_NONE, "NONE" },
72 { EapMethod::EAP_PEAP, "PEAP" },
73 { EapMethod::EAP_TLS, "TLS" },
74 { EapMethod::EAP_TTLS, "TTLS" },
75 { EapMethod::EAP_PWD, "PWD" },
76 { EapMethod::EAP_SIM, "SIM" },
77 { EapMethod::EAP_AKA, "AKA" },
78 { EapMethod::EAP_AKA_PRIME, "AKA'" },
79 { EapMethod::EAP_UNAUTH_TLS, "AKA" },
80 };
81
EapHdiWpaManager()82 EapHdiWpaManager::EapHdiWpaManager()
83 {
84 memset_s(ðCallback_, sizeof(ethCallback_), 0, sizeof(ethCallback_));
85 }
86
LoadEthernetHdiService()87 int32_t EapHdiWpaManager::LoadEthernetHdiService()
88 {
89 std::lock_guard<std::mutex> lock(wpaMutex_);
90 if (iEthernet_ != nullptr && devMgr_ != nullptr) {
91 NETMGR_EXT_LOG_I("EthService already load");
92 return EAP_ERRCODE_SUCCESS;
93 }
94 devMgr_ = HDIDeviceManagerGet();
95 if (devMgr_ == nullptr) {
96 NETMGR_EXT_LOG_E("EthService devMgr_ null");
97 return EAP_ERRCODE_INTERNAL_ERROR;
98 }
99 int32_t loadDevRet = devMgr_->LoadDevice(devMgr_, ETHERNET_SERVICE_NAME);
100 if ((loadDevRet != HDF_SUCCESS)) {
101 HDIDeviceManagerRelease(devMgr_);
102 devMgr_ = nullptr;
103 NETMGR_EXT_LOG_E("EthService load fail");
104 return EAP_ERRCODE_INTERNAL_ERROR;
105 }
106 iEthernet_ = IEthernetGetInstance(ETHERNET_SERVICE_NAME, false);
107 if (iEthernet_ == nullptr) {
108 NETMGR_EXT_LOG_E("EthService iEthernet_ null");
109 UnloadDeviceManager();
110 return EAP_ERRCODE_INTERNAL_ERROR;
111 }
112 NETMGR_EXT_LOG_I("EthService succ");
113 return EAP_ERRCODE_SUCCESS;
114 }
115
StartEap(const std::string & ifName,const EthEapProfile & profile)116 int32_t EapHdiWpaManager::StartEap(const std::string& ifName, const EthEapProfile& profile)
117 {
118 std::lock_guard<std::mutex> lock(wpaMutex_);
119 if (iEthernet_ == nullptr) {
120 NETMGR_EXT_LOG_E("StartEap iEthernet_ null");
121 return EAP_ERRCODE_INTERNAL_ERROR;
122 }
123 RemoveHistoryCtrl();
124 SetEapConfig(profile, ifName);
125 RegisterEapEventCallback(ifName);
126 int32_t ret = iEthernet_->StartEap(iEthernet_, ifName.c_str());
127 if (ret != HDF_SUCCESS) {
128 NETMGR_EXT_LOG_E("StartEap fail %{public}d", ret);
129 IEthernetReleaseInstance(ETHERNET_SERVICE_NAME, iEthernet_, false);
130 iEthernet_ = nullptr;
131 UnloadDeviceManager();
132 return EAP_ERRCODE_INTERNAL_ERROR;
133 }
134 NETMGR_EXT_LOG_I("StartEap succ");
135 return EAP_ERRCODE_SUCCESS;
136 }
137
StopEap(const std::string & ifName)138 int32_t EapHdiWpaManager::StopEap(const std::string& ifName)
139 {
140 std::lock_guard<std::mutex> lock(wpaMutex_);
141 if (iEthernet_ == nullptr) {
142 NETMGR_EXT_LOG_E("StopEap iEthernet_ null");
143 return EAP_ERRCODE_INTERNAL_ERROR;
144 }
145 UnregisterEapEventCallback(ifName);
146 int32_t ret = iEthernet_->StopEap(iEthernet_, ifName.c_str());
147 NETMGR_EXT_LOG_I("StopEap ret %{public}d", ret);
148 IEthernetReleaseInstance(ETHERNET_SERVICE_NAME, iEthernet_, false);
149 iEthernet_ = nullptr;
150 if (devMgr_ != nullptr) {
151 devMgr_->UnloadDevice(devMgr_, ETHERNET_SERVICE_NAME);
152 HDIDeviceManagerRelease(devMgr_);
153 devMgr_ = nullptr;
154 }
155 NETMGR_EXT_LOG_I("StopEap succ");
156 return (ret == HDF_SUCCESS) ? EAP_ERRCODE_SUCCESS : EAP_ERRCODE_LOGOFF_FAIL;
157 }
158
RemoveHistoryCtrl()159 void EapHdiWpaManager::RemoveHistoryCtrl()
160 {
161 std::filesystem::path filePath(ETH_CONFIG_ROOR_DIR);
162 if (!std::filesystem::exists(filePath)) {
163 return;
164 }
165 auto truePath = std::filesystem::canonical(filePath);
166 for (const auto& entry : std::filesystem::directory_iterator(truePath)) {
167 if (entry.is_regular_file()) {
168 std::string filename = entry.path().filename().string();
169 if (filename.find(ITEM_WPA_CTRL) != std::string::npos) {
170 std::filesystem::remove(entry.path());
171 }
172 }
173 }
174 }
175
SetEapConfig(const EthEapProfile & config,const std::string & ifName)176 int32_t EapHdiWpaManager::SetEapConfig(const EthEapProfile& config, const std::string& ifName)
177 {
178 std::string fileContext;
179 fileContext.append(ITEM_CTRL_IFACE);
180 fileContext.append(ITEM_AP_SCAN);
181 fileContext.append(ITEM_NETWORK_START);
182 fileContext.append(ITEM_KEYMGMT);
183 fileContext.append(ITEM_EAP + EAP_METHOD_STR_MAP[config.eapMethod] + ITEM_LINE);
184 fileContext.append(ITEM_IDENTITY + config.identity + ITEM_LINE);
185 switch (config.eapMethod) {
186 case EapMethod::EAP_PEAP:
187 case EapMethod::EAP_TTLS:
188 fileContext.append(ITEM_PASSWORD + config.password + ITEM_LINE);
189 fileContext.append(ITEM_CA_CERT + config.caPath + ITEM_LINE);
190 fileContext.append(ITEM_PHASE2 + Phase2MethodToStr(config.eapMethod, config.phase2Method) + ITEM_LINE);
191 break;
192 case EapMethod::EAP_TLS:
193 fileContext.append(ITEM_PASSWORD + config.password + ITEM_LINE);
194 fileContext.append(ITEM_CA_CERT + config.caPath + ITEM_LINE);
195 fileContext.append(ITEM_CLIENT_CERT + config.clientCertAliases + ITEM_LINE);
196 fileContext.append(ITEM_PRIVATE_KEY + config.certPassword + ITEM_LINE);
197 break;
198 case EapMethod::EAP_PWD:
199 fileContext.append(ITEM_PASSWORD + config.password + ITEM_LINE);
200 break;
201 default:
202 break;
203 }
204 fileContext.append(ITEM_NETWORK_END);
205 if (!WriteEapConfigToFile(fileContext)) {
206 NETMGR_EXT_LOG_E("SetEapConfig fail");
207 return EAP_ERRCODE_INTERNAL_ERROR;
208 }
209 NETMGR_EXT_LOG_I("SetEapConfig succ");
210 return EAP_ERRCODE_SUCCESS;
211 }
212
EapShellCmd(const std::string & ifName,const std::string & cmd)213 int32_t EapHdiWpaManager::EapShellCmd(const std::string& ifName, const std::string& cmd)
214 {
215 std::lock_guard<std::mutex> lock(wpaMutex_);
216 if (iEthernet_ == nullptr) {
217 NETMGR_EXT_LOG_E("EapShellCmd iEthernet_ null");
218 return EAP_ERRCODE_INTERNAL_ERROR;
219 }
220 int32_t ret = iEthernet_->EapShellCmd(iEthernet_, ifName.c_str(), cmd.c_str());
221 NETMGR_EXT_LOG_I("EthShellCmd cmd = %{public}s res = %{public}d", cmd.c_str(), ret);
222 return ret;
223 }
224
RegisterEapEventCallback(const std::string & ifName)225 int32_t EapHdiWpaManager::RegisterEapEventCallback(const std::string& ifName)
226 {
227 if (iEthernet_ == nullptr) {
228 NETMGR_EXT_LOG_E("RegisterEapEvent iEthernet_ null");
229 return EAP_ERRCODE_INTERNAL_ERROR;
230 }
231 ethCallback_.OnEapEventNotify = OnEapEventReport;
232 return iEthernet_->RegisterEapEventCallback(iEthernet_, ðCallback_, ifName.c_str());
233 }
234
UnregisterEapEventCallback(const std::string & ifName)235 int32_t EapHdiWpaManager::UnregisterEapEventCallback(const std::string& ifName)
236 {
237 if (iEthernet_ == nullptr) {
238 NETMGR_EXT_LOG_E("UnregisterEapEvent iEthernet_ null");
239 return EAP_ERRCODE_INTERNAL_ERROR;
240 }
241 ethCallback_.OnEapEventNotify = OnEapEventReport;
242 return iEthernet_->UnregisterEapEventCallback(iEthernet_, ðCallback_, ifName.c_str());
243 }
244
Phase2MethodToStr(EapMethod eap,Phase2Method method)245 std::string EapHdiWpaManager::Phase2MethodToStr(EapMethod eap, Phase2Method method)
246 {
247 std::string prefix = (eap == EapMethod::EAP_TTLS && method == Phase2Method::PHASE2_GTC) ? "autheap=" : "auth=";
248 return prefix + PHASE2_METHOD_STR_MAP[method];
249 }
250
WriteEapConfigToFile(const std::string & fileContext)251 bool EapHdiWpaManager::WriteEapConfigToFile(const std::string &fileContext)
252 {
253 std::string destPath = ETH_WPA_CONFIG_PATH;
254 std::ofstream file;
255 file.open(destPath, std::ios::out);
256 if (!file.is_open()) {
257 NETMGR_EXT_LOG_E("WriteEapConfig fail");
258 return false;
259 }
260 file << fileContext << std::endl;
261 file.close();
262 return true;
263 }
264
OnEapEventReport(IEthernetCallback * self,const char * ifName,const char * value)265 int32_t EapHdiWpaManager::OnEapEventReport(IEthernetCallback *self, const char *ifName, const char *value)
266 {
267 /* @param value -> msgId:eapCode:eapType:bufferLen:eapBuffer */
268 NETMGR_EXT_LOG_I("OnEapEventReport ifName = %{public}s", ifName);
269 std::vector<std::string> vecEapDatas = CommonUtils::Split(value, ":");
270 if (vecEapDatas.size() != WPA_EVENT_REPORT_PARAM_CNT) {
271 NETMGR_EXT_LOG_E("OnEapEventReport value size err");
272 return EAP_ERRCODE_INTERNAL_ERROR;
273 }
274 sptr<EapData> notifyEapData = (std::make_unique<EapData>()).release();
275 ConvertStrToInt(vecEapDatas[IDX_0], notifyEapData->msgId);
276 int32_t eapValue;
277 ConvertStrToInt(vecEapDatas[IDX_1], eapValue);
278 notifyEapData->eapCode = static_cast<uint32_t>(eapValue);
279 ConvertStrToInt(vecEapDatas[IDX_2], eapValue);
280 notifyEapData->eapType = static_cast<uint32_t>(eapValue);
281 ConvertStrToInt(vecEapDatas[IDX_3], notifyEapData->bufferLen);
282 std::string decodeEapBuf = Base64::Decode(vecEapDatas[IDX_4]);
283 notifyEapData->eapBuffer.assign(decodeEapBuf.begin(), decodeEapBuf.end());
284 return NetEapHandler::GetInstance().NotifyWpaEapInterceptInfo(NetType::ETH0, notifyEapData);
285 }
286
ConvertStrToInt(const std::string & str,int32_t & value)287 bool EapHdiWpaManager::ConvertStrToInt(const std::string &str, int32_t &value)
288 {
289 auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), value, BASE_10);
290 return ec == std::errc{} && ptr == str.data() + str.size();
291 }
292
RegisterCustomEapCallback(const std::string & ifName,const std::string & regCmd)293 int32_t EapHdiWpaManager::RegisterCustomEapCallback(const std::string &ifName, const std::string ®Cmd)
294 {
295 /* @param regCmd -> netType:size:composeParam1:composeParam2...((eapCode << 8) | eapType) */
296 NETMGR_EXT_LOG_I("RegisterEapCallback regCmd = %{public}s", regCmd.c_str());
297 std::lock_guard<std::mutex> lock(wpaMutex_);
298 if (iEthernet_ == nullptr) {
299 NETMGR_EXT_LOG_E("RegisterEapCallback iEthernet_ null");
300 return EAP_ERRCODE_INTERNAL_ERROR;
301 }
302 std::string cmd = "EXT_AUTH_REG " + regCmd;
303 int32_t result = iEthernet_->EapShellCmd(iEthernet_, ifName.c_str(), cmd.c_str());
304 if (result != HDF_SUCCESS) {
305 NETMGR_EXT_LOG_E("EapShellCmd fail %{public}d", result);
306 return EAP_ERRCODE_INTERNAL_ERROR;
307 }
308 return EAP_ERRCODE_SUCCESS;
309 }
310
ReplyCustomEapData(const std::string & ifName,int32_t result,const sptr<EapData> & eapData)311 int32_t EapHdiWpaManager::ReplyCustomEapData(const std::string &ifName, int32_t result,
312 const sptr<EapData> &eapData)
313 {
314 NETMGR_EXT_LOG_I("ReplyEapData ifName = %{public}s res = %{public}d", ifName.c_str(), result);
315 std::lock_guard<std::mutex> lock(wpaMutex_);
316 if (iEthernet_ == nullptr) {
317 NETMGR_EXT_LOG_E("ReplyEapData iEthernet_ null");
318 return EAP_ERRCODE_INTERNAL_ERROR;
319 }
320 std::string replyCmd = "EXT_AUTH_DATA " + std::to_string(result) + ":";
321 replyCmd.append(std::to_string(eapData->msgId) + ":");
322 replyCmd.append(std::to_string(eapData->bufferLen) + ":");
323 std::string encodeEapBuf = Base64::Encode(std::string(eapData->eapBuffer.begin(), eapData->eapBuffer.end()));
324 replyCmd.append(encodeEapBuf);
325 NETMGR_EXT_LOG_I("ReplyEapData cmd = %{public}s", replyCmd.c_str());
326 int32_t ret = iEthernet_->EapShellCmd(iEthernet_, ifName.c_str(), replyCmd.c_str());
327 if (ret != HDF_SUCCESS) {
328 NETMGR_EXT_LOG_E("ReplyEapData fail %{public}d", ret);
329 return EAP_ERRCODE_INTERNAL_ERROR;
330 }
331 return EAP_ERRCODE_SUCCESS;
332 }
333
UnloadDeviceManager()334 void EapHdiWpaManager::UnloadDeviceManager()
335 {
336 if (devMgr_ != nullptr) {
337 devMgr_->UnloadDevice(devMgr_, ETHERNET_SERVICE_NAME);
338 HDIDeviceManagerRelease(devMgr_);
339 devMgr_ = nullptr;
340 }
341 }
342
343 } // namespace NetManagerStandard
344 } // namespace OHOS
345