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