• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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