1 /*
2 * Copyright (c) 2023-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 "network_security_config.h"
17
18 #include <sys/stat.h>
19 #include <fstream>
20 #include <dirent.h>
21 #include <unistd.h>
22 #include <dlfcn.h>
23 #include <regex>
24 #include <sstream>
25 #include <securec.h>
26
27 #include "cJSON.h"
28 #include "openssl/evp.h"
29 #include "openssl/ssl.h"
30 #include "net_mgr_log_wrapper.h"
31 #include "net_manager_constants.h"
32 #include "netmanager_base_common_utils.h"
33 #include "net_bundle.h"
34
35 namespace OHOS {
36 namespace NetManagerStandard {
37
38 const std::string TAG_NETWORK_SECURITY_CONFIG("network-security-config");
39 const std::string TAG_BASE_CONFIG("base-config");
40 const std::string TAG_DOMAIN_CONFIG("domain-config");
41 const std::string TAG_COMPONENT_CONFIG("component-config");
42 const std::string TAG_TRUST_ANCHORS("trust-anchors");
43 const std::string TAG_CERTIFICATES("certificates");
44 const std::string TAG_DOMAINS("domains");
45 const std::string TAG_INCLUDE_SUBDOMAINS("include-subdomains");
46 const std::string TAG_NAME("name");
47 const std::string TAG_PIN_SET("pin-set");
48 const std::string TAG_EXPIRATION("expiration");
49 const std::string TAG_PIN("pin");
50 const std::string TAG_DIGEST_ALGORITHM("digest-algorithm");
51 const std::string TAG_DIGEST("digest");
52 const std::string TAG_CLEARTEXT_TRAFFIC_PERMITTED("cleartextTrafficPermitted");
53 const std::vector<std::string> SUPPORTED_COMPONENTS({"Network Kit", "ArkWeb"});
54
55 const std::string REHASHD_CA_CERTS_DIR("/data/storage/el2/base/files/rehashed_ca_certs");
56 #ifdef WINDOWS_PLATFORM
57 const char OS_PATH_SEPARATOR = '\\';
58 #else
59 const char OS_PATH_SEPARATOR = '/';
60 #endif
61
62 #ifdef __LP64__
63 const std::string LIB_LOAD_PATH = "/system/lib64/platformsdk/libnet_bundle_utils.z.so";
64 #else
65 const std::string LIB_LOAD_PATH = "/system/lib/platformsdk/libnet_bundle_utils.z.so";
66 #endif
67
68 using GetNetBundleClass = INetBundle *(*)();
69
NetworkSecurityConfig()70 NetworkSecurityConfig::NetworkSecurityConfig()
71 {
72 if (GetConfig() != NETMANAGER_SUCCESS) {
73 NETMGR_LOG_I("GetConfig failed");
74 } else {
75 NETMGR_LOG_D("Succeed to get NetworkSecurityConfig");
76 }
77 }
78
~NetworkSecurityConfig()79 NetworkSecurityConfig::~NetworkSecurityConfig() {}
80
GetInstance()81 NetworkSecurityConfig &NetworkSecurityConfig::GetInstance()
82 {
83 static NetworkSecurityConfig gInstance;
84 return gInstance;
85 }
86
IsCACertFileName(const char * fileName)87 bool NetworkSecurityConfig::IsCACertFileName(const char *fileName)
88 {
89 std::string str;
90 auto ext = strrchr(fileName, '.');
91 if (ext != nullptr) {
92 str = ext + 1;
93 }
94
95 for (auto &c : str) {
96 c = tolower(c);
97 }
98
99 return (str == "pem" || str == "crt");
100 }
101
GetCAFilesFromPath(const std::string caPath,std::vector<std::string> & caFiles)102 void NetworkSecurityConfig::GetCAFilesFromPath(const std::string caPath, std::vector<std::string> &caFiles)
103 {
104 DIR *dir = opendir(caPath.c_str());
105 if (dir == nullptr) {
106 NETMGR_LOG_E("open CA path[%{public}s] fail. [%{public}d]", caPath.c_str(), errno);
107 return;
108 }
109
110 struct dirent *entry = readdir(dir);
111 while (entry != nullptr) {
112 if (IsCACertFileName(entry->d_name)) {
113 if (caPath.back() != OS_PATH_SEPARATOR) {
114 caFiles.push_back(caPath + OS_PATH_SEPARATOR + entry->d_name);
115 } else {
116 caFiles.push_back(caPath + entry->d_name);
117 }
118 NETMGR_LOG_D("Read CA File [%{public}s] from CA Path", entry->d_name);
119 }
120 entry = readdir(dir);
121 }
122
123 closedir(dir);
124 }
125
AddSurfixToCACertFileName(const std::string & caPath,std::set<std::string> & allFileNames,std::string & caFile)126 void NetworkSecurityConfig::AddSurfixToCACertFileName(const std::string &caPath, std::set<std::string> &allFileNames,
127 std::string &caFile)
128 {
129 uint32_t count = 0;
130 for (auto &fileName : allFileNames) {
131 if (fileName.find(caFile) != std::string::npos) {
132 count++;
133 }
134 }
135
136 caFile = caFile + '.' + std::to_string(count);
137 allFileNames.insert(caFile);
138 }
139
ReadCertFile(const std::string & fileName)140 X509 *NetworkSecurityConfig::ReadCertFile(const std::string &fileName)
141 {
142 std::ifstream certFile(fileName.c_str());
143 if (!certFile.is_open()) {
144 NETMGR_LOG_E("Fail to read cert fail [%{public}s]", fileName.c_str());
145 return nullptr;
146 }
147
148 std::stringstream certStream;
149 certStream << certFile.rdbuf();
150
151 const std::string &certData = certStream.str();
152 BIO *bio = BIO_new_mem_buf(certData.c_str(), -1);
153 if (bio == nullptr) {
154 NETMGR_LOG_E("Fail to call BIO_new_mem_buf");
155 return nullptr;
156 }
157
158 X509 *x509 = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
159 if (x509 == nullptr) {
160 NETMGR_LOG_E("Fail to call PEM_read_bio_X509.");
161 }
162
163 BIO_free(bio);
164 return x509;
165 }
166
GetRehashedCADirName(const std::string & caPath)167 std::string NetworkSecurityConfig::GetRehashedCADirName(const std::string &caPath)
168 {
169 unsigned char hashedHex[EVP_MAX_MD_SIZE];
170 auto ret = EVP_Digest(reinterpret_cast<const unsigned char *>(caPath.c_str()), caPath.size(), hashedHex, nullptr,
171 EVP_sha256(), nullptr);
172 if (ret != 1) {
173 return "";
174 }
175
176 /* Encode the hashed string by base16 */
177 constexpr unsigned int HASHED_DIR_NAME_LEN = 32;
178 constexpr unsigned int BASE16_ELE_SIZE = 2;
179 char hashedStr[HASHED_DIR_NAME_LEN + 1] = {0};
180 for (unsigned int i = 0; i < HASHED_DIR_NAME_LEN / BASE16_ELE_SIZE; i++) {
181 if (sprintf_s(&hashedStr[BASE16_ELE_SIZE * i], sizeof(hashedStr) - BASE16_ELE_SIZE * i, "%02x", hashedHex[i]) <
182 0) {
183 return "";
184 }
185 }
186
187 return hashedStr;
188 }
189
BuildRehasedCAPath(const std::string & caPath)190 std::string NetworkSecurityConfig::BuildRehasedCAPath(const std::string &caPath)
191 {
192 if (access(REHASHD_CA_CERTS_DIR.c_str(), F_OK) == -1) {
193 if (mkdir(REHASHD_CA_CERTS_DIR.c_str(), S_IRWXU | S_IRWXG) == -1) {
194 NETMGR_LOG_E("Fail to make a rehased caCerts dir [%{public}d]", errno);
195 return "";
196 }
197 }
198
199 auto dirName = GetRehashedCADirName(caPath);
200 if (dirName.empty()) {
201 NETMGR_LOG_E("Fail to make a rehased caCerts dir for [%{public}s]", caPath.c_str());
202 return "";
203 }
204
205 auto rehashedCertpath = REHASHD_CA_CERTS_DIR + OS_PATH_SEPARATOR + dirName;
206 if (access(rehashedCertpath.c_str(), F_OK) == -1) {
207 if (mkdir(rehashedCertpath.c_str(), S_IRWXU | S_IRWXG) == -1) {
208 NETMGR_LOG_E("Fail to make a rehased caCerts dir [%{public}d]", errno);
209 return "";
210 }
211 }
212
213 NETMGR_LOG_D("Build dir [%{public}s]", rehashedCertpath.c_str());
214 return rehashedCertpath;
215 }
216
GetRehasedCAPath(const std::string & caPath)217 std::string NetworkSecurityConfig::GetRehasedCAPath(const std::string &caPath)
218 {
219 if (access(REHASHD_CA_CERTS_DIR.c_str(), F_OK) == -1) {
220 return "";
221 }
222
223 auto dirName = GetRehashedCADirName(caPath);
224 if (dirName.empty()) {
225 return "";
226 }
227
228 auto rehashedCertpath = REHASHD_CA_CERTS_DIR + OS_PATH_SEPARATOR + dirName;
229 if (access(rehashedCertpath.c_str(), F_OK) == -1) {
230 return "";
231 }
232
233 return rehashedCertpath;
234 }
235
ReHashCAPathForX509(const std::string & caPath)236 std::string NetworkSecurityConfig::ReHashCAPathForX509(const std::string &caPath)
237 {
238 std::set<std::string> allFiles;
239 std::vector<std::string> caFiles;
240
241 GetCAFilesFromPath(caPath, caFiles);
242 if (caFiles.empty()) {
243 NETMGR_LOG_D("No customized CA certs.");
244 return "";
245 }
246
247 auto rehashedCertpath = BuildRehasedCAPath(caPath);
248 if (rehashedCertpath.empty()) {
249 return rehashedCertpath;
250 }
251
252 for (auto &caFile : caFiles) {
253 auto x509 = ReadCertFile(caFile);
254 if (x509 == nullptr) {
255 continue;
256 }
257
258 constexpr int X509_HASH_LEN = 16;
259 char buf[X509_HASH_LEN] = {0};
260 if (sprintf_s(buf, sizeof(buf), "%08lx", X509_subject_name_hash(x509)) < 0) {
261 return "";
262 }
263 X509_free(x509);
264 x509 = nullptr;
265
266 std::string hashName(buf);
267 AddSurfixToCACertFileName(rehashedCertpath, allFiles, hashName);
268
269 std::string rehashedCaFile = rehashedCertpath + OS_PATH_SEPARATOR + hashName;
270 if (access(rehashedCaFile.c_str(), F_OK) == 0) {
271 NETMGR_LOG_D("File [%{public}s] exists.", rehashedCaFile.c_str());
272 continue;
273 }
274
275 std::ifstream src(caFile);
276 std::ofstream dst(rehashedCaFile);
277 if (!src.is_open() || !dst.is_open()) {
278 NETMGR_LOG_E("fail to open cert file.");
279 continue;
280 }
281 dst << src.rdbuf();
282 NETMGR_LOG_D("Rehased cert generated. [%{public}s]", rehashedCaFile.c_str());
283 }
284
285 return rehashedCertpath;
286 }
287
CreateRehashedCertFiles()288 int32_t NetworkSecurityConfig::CreateRehashedCertFiles()
289 {
290 for (auto &cert : baseConfig_.trustAnchors_.certs_) {
291 ReHashCAPathForX509(cert);
292 }
293 for (auto &domainConfig : domainConfigs_) {
294 for (auto &cert : domainConfig.trustAnchors_.certs_) {
295 ReHashCAPathForX509(cert);
296 }
297 }
298
299 return NETMANAGER_SUCCESS;
300 }
301
ValidateDate(const std::string & dateStr)302 bool NetworkSecurityConfig::ValidateDate(const std::string &dateStr)
303 {
304 if (dateStr.empty()) {
305 return true;
306 }
307 std::tm tm = {};
308 std::istringstream ss(dateStr);
309 if (!(ss >> std::get_time(&tm, "%Y-%m-%d"))) {
310 return false;
311 }
312 time_t expiryTime = mktime(&tm);
313 if (expiryTime == -1) {
314 return false;
315 }
316 auto expiryPoint = std::chrono::system_clock::from_time_t(expiryTime);
317 auto nowPoint = std::chrono::system_clock::now();
318 if (nowPoint > expiryPoint) {
319 return false;
320 }
321 return true;
322 }
323
GetConfig()324 int32_t NetworkSecurityConfig::GetConfig()
325 {
326 std::string json;
327 auto ret = GetJsonFromBundle(json);
328 if (ret != NETMANAGER_SUCCESS) {
329 NETMGR_LOG_I("Get json failed.");
330 return ret;
331 }
332
333 ret = ParseJsonConfig(json);
334 if (ret != NETMANAGER_SUCCESS) {
335 return ret;
336 }
337
338 ret = CreateRehashedCertFiles();
339 if (ret != NETMANAGER_SUCCESS) {
340 return ret;
341 }
342
343 NETMGR_LOG_D("NetworkSecurityConfig Cached.");
344 return NETMANAGER_SUCCESS;
345 }
346
GetJsonProfile()347 __attribute__((no_sanitize("cfi"))) std::string NetworkSecurityConfig::GetJsonProfile()
348 {
349 void *handler = dlopen(LIB_LOAD_PATH.c_str(), RTLD_LAZY | RTLD_NODELETE);
350 if (handler == nullptr) {
351 NETMGR_LOG_E("load failed, failed reason : %{public}s", dlerror());
352 return "";
353 }
354 GetNetBundleClass getNetBundle = (GetNetBundleClass)dlsym(handler, "GetNetBundle");
355 if (getNetBundle == nullptr) {
356 NETMGR_LOG_E("GetNetBundle faild, failed reason : %{public}s", dlerror());
357 dlclose(handler);
358 return "";
359 }
360 auto netBundle = getNetBundle();
361 if (netBundle == nullptr) {
362 NETMGR_LOG_E("netBundle is nullptr");
363 dlclose(handler);
364 return "";
365 }
366 std::string jsonProfile;
367 auto ret = netBundle->GetJsonFromBundle(jsonProfile);
368 if (ret != NETMANAGER_SUCCESS) {
369 NETMGR_LOG_I("get profile failed");
370 dlclose(handler);
371 return "";
372 }
373 NETMGR_LOG_D("get profile success");
374 dlclose(handler);
375 return jsonProfile;
376 }
377
GetJsonFromBundle(std::string & jsonProfile)378 __attribute__((no_sanitize("cfi"))) int32_t NetworkSecurityConfig::GetJsonFromBundle(std::string &jsonProfile)
379 {
380 static std::string json = GetJsonProfile();
381 if (json.empty()) {
382 return NETMANAGER_ERR_INTERNAL;
383 }
384 jsonProfile = json;
385 return NETMANAGER_SUCCESS;
386 }
387
ParseJsonTrustAnchors(const cJSON * const root,TrustAnchors & trustAnchors)388 void NetworkSecurityConfig::ParseJsonTrustAnchors(const cJSON* const root, TrustAnchors &trustAnchors)
389 {
390 if (!cJSON_IsArray(root)) {
391 return;
392 }
393
394 uint32_t size = cJSON_GetArraySize(root);
395 for (uint32_t i = 0; i < size; i++) {
396 cJSON *trustAnchorsItem = cJSON_GetArrayItem(root, i);
397 cJSON *certificates = cJSON_GetObjectItem(trustAnchorsItem, TAG_CERTIFICATES.c_str());
398 std::string cert_path = cJSON_GetStringValue(certificates);
399 trustAnchors.certs_.push_back(cert_path);
400 }
401
402 return;
403 }
404
ParseJsonDomains(const cJSON * const root,std::vector<Domain> & domains)405 void NetworkSecurityConfig::ParseJsonDomains(const cJSON* const root, std::vector<Domain> &domains)
406 {
407 if (!cJSON_IsArray(root)) {
408 return;
409 }
410
411 uint32_t size = cJSON_GetArraySize(root);
412 for (uint32_t i = 0; i < size; i++) {
413 Domain domain;
414 cJSON *domainItem = cJSON_GetArrayItem(root, i);
415 cJSON *name = cJSON_GetObjectItem(domainItem, TAG_NAME.c_str());
416 if (name == nullptr || !cJSON_IsString(name)) {
417 continue;
418 }
419 domain.domainName_ = cJSON_GetStringValue(name);
420 NETMGR_LOG_D("domainName_: %{public}s", domain.domainName_.c_str());
421 cJSON *subDomains = cJSON_GetObjectItem(domainItem, TAG_INCLUDE_SUBDOMAINS.c_str());
422 if (subDomains != nullptr && cJSON_IsBool(subDomains)) {
423 domain.includeSubDomains_ = cJSON_IsTrue(subDomains);
424 NETMGR_LOG_D("includeSubDomains_: %{public}d", domain.includeSubDomains_);
425 } else {
426 domain.includeSubDomains_ = true;
427 }
428
429 domains.push_back(domain);
430 }
431
432 return;
433 }
434
ParseJsonPinSet(const cJSON * const root,PinSet & pinSet)435 void NetworkSecurityConfig::ParseJsonPinSet(const cJSON* const root, PinSet &pinSet)
436 {
437 if (root == nullptr) {
438 return;
439 }
440 cJSON *expiration = cJSON_GetObjectItem(root, TAG_EXPIRATION.c_str());
441 if (expiration != nullptr && cJSON_IsString(expiration)) {
442 pinSet.expiration_ = cJSON_GetStringValue(expiration);
443 NETMGR_LOG_D("expiration: %{public}s", pinSet.expiration_.c_str());
444 }
445 cJSON *pins = cJSON_GetObjectItem(root, TAG_PIN.c_str());
446 if (pins == nullptr || !cJSON_IsArray(pins)) {
447 return;
448 }
449 uint32_t size = cJSON_GetArraySize(pins);
450 for (uint32_t i = 0; i < size; i++) {
451 Pin pin;
452 cJSON *pinsItem = cJSON_GetArrayItem(pins, i);
453 cJSON *digestAlgorithm = cJSON_GetObjectItem(pinsItem, TAG_DIGEST_ALGORITHM.c_str());
454 if (digestAlgorithm == nullptr || !cJSON_IsString(digestAlgorithm)) {
455 continue;
456 }
457 pin.digestAlgorithm_ = cJSON_GetStringValue(digestAlgorithm);
458 cJSON *digest = cJSON_GetObjectItem(pinsItem, TAG_DIGEST.c_str());
459 if (digest == nullptr || !cJSON_IsString(digest)) {
460 continue;
461 }
462 pin.digest_ = cJSON_GetStringValue(digest);
463 pinSet.pins_.push_back(pin);
464 }
465 auto isOpenMode = cJSON_GetObjectItem(root, "openMode");
466 if (isOpenMode) {
467 pinSet.isOpenMode = cJSON_IsTrue(isOpenMode);
468 }
469 if (pinSet.isOpenMode) {
470 // only when in open mode, verify root CA could be enabled.
471 auto verifyRootCaItem = cJSON_GetObjectItem(root, "open-mode-verify-root-ca");
472 if (verifyRootCaItem) {
473 pinSet.shouldVerifyRootCa_ = cJSON_IsTrue(verifyRootCaItem);
474 }
475 }
476 }
477
ParseJsonBaseConfig(const cJSON * const root,BaseConfig & baseConfig)478 void NetworkSecurityConfig::ParseJsonBaseConfig(const cJSON* const root, BaseConfig &baseConfig)
479 {
480 if (root == nullptr) {
481 return;
482 }
483 hasBaseConfig_ = true;
484 cJSON *cleartextPermitted = cJSON_GetObjectItem(root, TAG_CLEARTEXT_TRAFFIC_PERMITTED.c_str());
485 ParseJsonCleartextPermitted(cleartextPermitted, baseConfig.cleartextTrafficPermitted_);
486
487 cJSON *trustAnchors = cJSON_GetObjectItem(root, TAG_TRUST_ANCHORS.c_str());
488 if (trustAnchors == nullptr) {
489 return;
490 }
491
492 ParseJsonTrustAnchors(trustAnchors, baseConfig.trustAnchors_);
493 }
494
ParseJsonDomainConfigs(const cJSON * const root,std::vector<DomainConfig> & domainConfigs)495 void NetworkSecurityConfig::ParseJsonDomainConfigs(const cJSON* const root, std::vector<DomainConfig> &domainConfigs)
496 {
497 if (!cJSON_IsArray(root)) {
498 return;
499 }
500 uint32_t size = cJSON_GetArraySize(root);
501 NETMGR_LOG_D("size: %{public}u", size);
502 for (uint32_t i = 0; i < size; i++) {
503 cJSON *domainConfigItem = cJSON_GetArrayItem(root, i);
504 DomainConfig domainConfig;
505 cJSON *cleartextPermitted = cJSON_GetObjectItem(domainConfigItem, TAG_CLEARTEXT_TRAFFIC_PERMITTED.c_str());
506 ParseJsonCleartextPermitted(cleartextPermitted, domainConfig.cleartextTrafficPermitted_);
507 cJSON *domains = cJSON_GetObjectItem(domainConfigItem, TAG_DOMAINS.c_str());
508 ParseJsonDomains(domains, domainConfig.domains_);
509 cJSON *trustAnchors = cJSON_GetObjectItem(domainConfigItem, TAG_TRUST_ANCHORS.c_str());
510 ParseJsonTrustAnchors(trustAnchors, domainConfig.trustAnchors_);
511 cJSON *pinSet = cJSON_GetObjectItem(domainConfigItem, TAG_PIN_SET.c_str());
512 ParseJsonPinSet(pinSet, domainConfig.pinSet_);
513
514 domainConfigs.push_back(domainConfig);
515 }
516
517 return;
518 }
519
ParseJsonComponentCfg(const cJSON * const root,ComponentCfg & componentConfigs)520 void NetworkSecurityConfig::ParseJsonComponentCfg(const cJSON *const root, ComponentCfg &componentConfigs)
521 {
522 if (root == nullptr) {
523 return;
524 }
525 for (auto item : SUPPORTED_COMPONENTS) {
526 cJSON *componentCfg = cJSON_GetObjectItem(root, item.c_str());
527 ParseJsonComponentCfg(componentCfg, componentConfigs, item);
528 }
529 }
530
ParseJsonComponentCfg(const cJSON * const root,ComponentCfg & componentConfigs,const std::string & component)531 void NetworkSecurityConfig::ParseJsonComponentCfg(const cJSON *const root, ComponentCfg &componentConfigs,
532 const std::string &component)
533 {
534 if (root == nullptr || !cJSON_IsBool(root)) {
535 return;
536 }
537 componentConfigs[component] = cJSON_IsTrue(root);
538 NETMGR_LOG_D("Component Cfg: %{public}d", componentConfigs[component]);
539 }
540
ParseJsonConfig(const std::string & content)541 int32_t NetworkSecurityConfig::ParseJsonConfig(const std::string &content)
542 {
543 if (content.empty()) {
544 return NETMANAGER_SUCCESS;
545 }
546
547 cJSON *root = cJSON_Parse(content.c_str());
548 if (root == nullptr) {
549 NETMGR_LOG_E("Failed to parse network json profile.");
550 return NETMANAGER_ERR_INTERNAL;
551 }
552
553 auto trustUser0Ca = cJSON_GetObjectItem(root, "trust-global-user-ca");
554 if (trustUser0Ca) {
555 trustUser0Ca_ = cJSON_IsTrue(trustUser0Ca);
556 }
557
558 auto trustUserCa = cJSON_GetObjectItem(root, "trust-current-user-ca");
559 if (trustUserCa) {
560 trustUserCa_ = cJSON_IsTrue(trustUserCa);
561 }
562
563 auto isUserDnsCache = cJSON_GetObjectItem(root, "use-dns-cache");
564 if (isUserDnsCache) {
565 isUserDnsCache_ = cJSON_IsTrue(isUserDnsCache);
566 }
567
568 cJSON *networkSecurityConfig = cJSON_GetObjectItem(root, TAG_NETWORK_SECURITY_CONFIG.c_str());
569 if (networkSecurityConfig == nullptr) {
570 NETMGR_LOG_E("networkSecurityConfig is null");
571 cJSON_Delete(root);
572 return NETMANAGER_SUCCESS;
573 }
574 cJSON *baseConfig = cJSON_GetObjectItem(networkSecurityConfig, TAG_BASE_CONFIG.c_str());
575 cJSON *domainConfig = cJSON_GetObjectItem(networkSecurityConfig, TAG_DOMAIN_CONFIG.c_str());
576 cJSON *componentConfig = cJSON_GetObjectItem(networkSecurityConfig, TAG_COMPONENT_CONFIG.c_str());
577
578 ParseJsonBaseConfig(baseConfig, baseConfig_);
579 ParseJsonDomainConfigs(domainConfig, domainConfigs_);
580 ParseJsonComponentCfg(componentConfig, componentConfig_);
581
582 cJSON_Delete(root);
583 return NETMANAGER_SUCCESS;
584 }
585
IsPinOpenMode(const std::string & hostname)586 bool NetworkSecurityConfig::IsPinOpenMode(const std::string &hostname)
587 {
588 if (hostname.empty()) {
589 return false;
590 }
591
592 PinSet *pPinSet = nullptr;
593 for (auto &domainConfig : domainConfigs_) {
594 for (const auto &domain : domainConfig.domains_) {
595 if (hostname == domain.domainName_) {
596 pPinSet = &domainConfig.pinSet_;
597 break;
598 } else if (domain.includeSubDomains_ && CommonUtils::UrlRegexParse(hostname, domain.domainName_)) {
599 pPinSet = &domainConfig.pinSet_;
600 break;
601 }
602 }
603 if (pPinSet != nullptr) {
604 break;
605 }
606 }
607
608 if (pPinSet == nullptr) {
609 return false;
610 }
611 return pPinSet->isOpenMode;
612 }
613
IsPinOpenModeVerifyRootCa(const std::string & hostname)614 bool NetworkSecurityConfig::IsPinOpenModeVerifyRootCa(const std::string &hostname)
615 {
616 if (hostname.empty()) {
617 NETMGR_LOG_E("hostname is empty.");
618 return false;
619 }
620
621 PinSet *pPinSet = nullptr;
622 for (auto &domainConfig : domainConfigs_) {
623 for (const auto &domain : domainConfig.domains_) {
624 if (hostname == domain.domainName_) {
625 pPinSet = &domainConfig.pinSet_;
626 break;
627 } else if (domain.includeSubDomains_ && CommonUtils::UrlRegexParse(hostname, domain.domainName_)) {
628 pPinSet = &domainConfig.pinSet_;
629 break;
630 }
631 }
632 if (pPinSet != nullptr) {
633 break;
634 }
635 }
636
637 if (pPinSet == nullptr) {
638 NETMGR_LOG_E("pinset not configured for this hostname.");
639 return false;
640 }
641 if (!pPinSet->isOpenMode) {
642 NETMGR_LOG_D("Verify root CA only available when open mode is true.");
643 return false;
644 }
645 return pPinSet->shouldVerifyRootCa_;
646 }
647
GetPinSetForHostName(const std::string & hostname,std::string & pins)648 int32_t NetworkSecurityConfig::GetPinSetForHostName(const std::string &hostname, std::string &pins)
649 {
650 if (hostname.empty()) {
651 NETMGR_LOG_E("Failed to get pinset, hostname is empty.");
652 return NETMANAGER_SUCCESS;
653 }
654
655 PinSet *pPinSet = nullptr;
656 for (auto &domainConfig : domainConfigs_) {
657 for (const auto &domain : domainConfig.domains_) {
658 if (hostname == domain.domainName_) {
659 pPinSet = &domainConfig.pinSet_;
660 break;
661 } else if (domain.includeSubDomains_ && CommonUtils::UrlRegexParse(hostname, domain.domainName_)) {
662 pPinSet = &domainConfig.pinSet_;
663 break;
664 }
665 }
666 if (pPinSet != nullptr) {
667 break;
668 }
669 }
670
671 if (pPinSet == nullptr) {
672 NETMGR_LOG_D("No pinned pubkey configured.");
673 return NETMANAGER_SUCCESS;
674 }
675
676 if (!ValidateDate(pPinSet->expiration_)) {
677 NETMGR_LOG_W("expiration date is invalid %{public}s", pPinSet->expiration_.c_str());
678 return NETMANAGER_SUCCESS;
679 }
680
681 std::stringstream ss;
682 for (const auto &pin : pPinSet->pins_) {
683 ss << pin.digestAlgorithm_ << "//" << pin.digest_ << ";";
684 }
685
686 pins = ss.str();
687 if (!pins.empty()) {
688 pins.pop_back();
689 }
690
691 return NETMANAGER_SUCCESS;
692 }
693
GetTrustAnchorsForHostName(const std::string & hostname,std::vector<std::string> & certs)694 int32_t NetworkSecurityConfig::GetTrustAnchorsForHostName(const std::string &hostname, std::vector<std::string> &certs)
695 {
696 if (hostname.empty()) {
697 NETMGR_LOG_E("Failed to get trust anchors, hostname is empty.");
698 return NETMANAGER_SUCCESS;
699 }
700
701 TrustAnchors *pTrustAnchors = nullptr;
702 for (auto &domainConfig: domainConfigs_) {
703 for (const auto &domain: domainConfig.domains_) {
704 if (hostname == domain.domainName_) {
705 pTrustAnchors = &domainConfig.trustAnchors_;
706 break;
707 } else if (domain.includeSubDomains_ && CommonUtils::UrlRegexParse(hostname, domain.domainName_)) {
708 pTrustAnchors = &domainConfig.trustAnchors_;
709 break;
710 }
711 }
712 if (pTrustAnchors != nullptr) {
713 break;
714 }
715 }
716
717 if (pTrustAnchors == nullptr) {
718 pTrustAnchors = &baseConfig_.trustAnchors_;
719 }
720
721 for (auto &certPath : pTrustAnchors->certs_) {
722 auto rehashedCertpath = GetRehasedCAPath(certPath);
723 if (!rehashedCertpath.empty()) {
724 certs.push_back(rehashedCertpath);
725 }
726 }
727
728 if (certs.empty()) {
729 NETMGR_LOG_D("No customized CA certs configured.");
730 }
731
732 return NETMANAGER_SUCCESS;
733 }
734
DumpConfigs()735 void NetworkSecurityConfig::DumpConfigs()
736 {
737 NETMGR_LOG_I("DumpConfigs:baseConfig_.trustAnchors_.certs");
738 for (auto &cert : baseConfig_.trustAnchors_.certs_) {
739 NETMGR_LOG_I("[%{public}s]", cert.c_str());
740 }
741
742 NETMGR_LOG_I("DumpConfigs:domainConfigs_");
743 for (auto &domainConfig : domainConfigs_) {
744 NETMGR_LOG_I("=======================");
745 for (auto &domain : domainConfig.domains_) {
746 NETMGR_LOG_I("domainConfigs_.domains_[%{public}s][%{public}s]", domain.domainName_.c_str(),
747 domain.includeSubDomains_ ? "include_subDomain" : "not_include_subDomain");
748 }
749 NETMGR_LOG_I("domainConfigs_.domains_.pinSet_.expiration_[%{public}s]",
750 domainConfig.pinSet_.expiration_.c_str());
751 for (auto &cert : domainConfig.trustAnchors_.certs_) {
752 NETMGR_LOG_I("domainConfigs_.domains_.trustAnchors_.certs_[%{public}s]", cert.c_str());
753 }
754 }
755 }
756
TrustUser0Ca()757 bool NetworkSecurityConfig::TrustUser0Ca()
758 {
759 return trustUser0Ca_;
760 }
761
TrustUserCa()762 bool NetworkSecurityConfig::TrustUserCa()
763 {
764 return trustUserCa_;
765 }
766
IsUserDnsCache()767 bool NetworkSecurityConfig::IsUserDnsCache()
768 {
769 return isUserDnsCache_;
770 }
771
ParseJsonCleartextPermitted(const cJSON * const root,bool & cleartextPermitted)772 void NetworkSecurityConfig::ParseJsonCleartextPermitted(const cJSON* const root, bool &cleartextPermitted)
773 {
774 if (root == nullptr || !cJSON_IsBool(root)) {
775 cleartextPermitted = true;
776 return;
777 }
778 cleartextPermitted = cJSON_IsTrue(root);
779 NETMGR_LOG_D("CleartextPermitted: %{public}d", cleartextPermitted);
780 }
781
IsCleartextPermitted(bool & baseCleartextPermitted)782 int32_t NetworkSecurityConfig::IsCleartextPermitted(bool &baseCleartextPermitted)
783 {
784 if (!CommonUtils::HasInternetPermission()) {
785 return NETMANAGER_ERR_PERMISSION_DENIED;
786 }
787 baseCleartextPermitted = hasBaseConfig_ ? baseConfig_.cleartextTrafficPermitted_ : true;
788 return NETMANAGER_SUCCESS;
789 }
790
IsCleartextPermitted(const std::string & hostname,bool & cleartextPermitted)791 int32_t NetworkSecurityConfig::IsCleartextPermitted(const std::string &hostname, bool &cleartextPermitted)
792 {
793 if (!CommonUtils::HasInternetPermission()) {
794 return NETMANAGER_ERR_PERMISSION_DENIED;
795 }
796
797 bool baseCleartextPermitted = hasBaseConfig_ ? baseConfig_.cleartextTrafficPermitted_ : true;
798 if (hostname.empty()) {
799 NETMGR_LOG_E("Failed to get cleartextPermitted, hostname is empty.");
800 cleartextPermitted = baseCleartextPermitted;
801 return NETMANAGER_SUCCESS;
802 }
803
804 const bool *pCtTrafficPermitted = nullptr;
805 for (const auto &domainConfig : domainConfigs_) {
806 for (const auto &domain : domainConfig.domains_) {
807 if (hostname == domain.domainName_) {
808 pCtTrafficPermitted = &domainConfig.cleartextTrafficPermitted_;
809 break;
810 } else if (domain.includeSubDomains_ && CommonUtils::UrlRegexParse(hostname, domain.domainName_)) {
811 pCtTrafficPermitted = &domainConfig.cleartextTrafficPermitted_;
812 break;
813 }
814 }
815 if (pCtTrafficPermitted != nullptr) {
816 break;
817 }
818 }
819 cleartextPermitted = pCtTrafficPermitted == nullptr ? baseCleartextPermitted : *pCtTrafficPermitted;
820 return NETMANAGER_SUCCESS;
821 }
822
IsCleartextCfgByComponent(const std::string & component,bool & componentCfg)823 int32_t NetworkSecurityConfig::IsCleartextCfgByComponent(const std::string &component, bool &componentCfg)
824 {
825 if (componentConfig_.find(component) == componentConfig_.end()) {
826 NETMGR_LOG_E("Component Not Cfg.");
827 return NETMANAGER_ERR_INVALID_PARAMETER;
828 }
829 componentCfg = componentConfig_[component];
830 return NETMANAGER_SUCCESS;
831 }
832
833 } // namespace NetManagerStandard
834 } // namespace OHOS
835