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