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 }
467 
ParseJsonBaseConfig(const cJSON * const root,BaseConfig & baseConfig)468 void NetworkSecurityConfig::ParseJsonBaseConfig(const cJSON* const root, BaseConfig &baseConfig)
469 {
470     if (root == nullptr) {
471         return;
472     }
473 
474     cJSON *trustAnchors = cJSON_GetObjectItem(root, TAG_TRUST_ANCHORS.c_str());
475     if (trustAnchors == nullptr) {
476         return;
477     }
478 
479     ParseJsonTrustAnchors(trustAnchors, baseConfig.trustAnchors_);
480 }
481 
ParseJsonDomainConfigs(const cJSON * const root,std::vector<DomainConfig> & domainConfigs)482 void NetworkSecurityConfig::ParseJsonDomainConfigs(const cJSON* const root, std::vector<DomainConfig> &domainConfigs)
483 {
484     if (!cJSON_IsArray(root)) {
485         return;
486     }
487     uint32_t size = cJSON_GetArraySize(root);
488     NETMGR_LOG_D("size: %{public}u", size);
489     for (uint32_t i = 0; i < size; i++) {
490         cJSON *domainConfigItem = cJSON_GetArrayItem(root, i);
491         DomainConfig domainConfig;
492         cJSON *domains = cJSON_GetObjectItem(domainConfigItem, TAG_DOMAINS.c_str());
493         ParseJsonDomains(domains, domainConfig.domains_);
494         cJSON *trustAnchors = cJSON_GetObjectItem(domainConfigItem, TAG_TRUST_ANCHORS.c_str());
495         ParseJsonTrustAnchors(trustAnchors, domainConfig.trustAnchors_);
496         cJSON *pinSet = cJSON_GetObjectItem(domainConfigItem, TAG_PIN_SET.c_str());
497         ParseJsonPinSet(pinSet, domainConfig.pinSet_);
498 
499         domainConfigs.push_back(domainConfig);
500     }
501 
502     return;
503 }
504 
ParseJsonConfig(const std::string & content)505 int32_t NetworkSecurityConfig::ParseJsonConfig(const std::string &content)
506 {
507     if (content.empty()) {
508         return NETMANAGER_SUCCESS;
509     }
510 
511     cJSON *root = cJSON_Parse(content.c_str());
512     if (root == nullptr) {
513         NETMGR_LOG_E("Failed to parse network json profile.");
514         return NETMANAGER_ERR_INTERNAL;
515     }
516 
517     cJSON *networkSecurityConfig = cJSON_GetObjectItem(root, TAG_NETWORK_SECURITY_CONFIG.c_str());
518     if (networkSecurityConfig == nullptr) {
519         NETMGR_LOG_E("networkSecurityConfig is null");
520         cJSON_Delete(root);
521         return NETMANAGER_SUCCESS;
522     }
523     cJSON *baseConfig = cJSON_GetObjectItem(networkSecurityConfig, TAG_BASE_CONFIG.c_str());
524     cJSON *domainConfig = cJSON_GetObjectItem(networkSecurityConfig, TAG_DOMAIN_CONFIG.c_str());
525 
526     ParseJsonBaseConfig(baseConfig, baseConfig_);
527     ParseJsonDomainConfigs(domainConfig, domainConfigs_);
528 
529     cJSON_Delete(root);
530     return NETMANAGER_SUCCESS;
531 }
532 
IsPinOpenMode(const std::string & hostname)533 bool NetworkSecurityConfig::IsPinOpenMode(const std::string &hostname)
534 {
535     if (hostname.empty()) {
536         return false;
537     }
538 
539     PinSet *pPinSet = nullptr;
540     for (auto &domainConfig : domainConfigs_) {
541         for (const auto &domain : domainConfig.domains_) {
542             if (hostname == domain.domainName_) {
543                 pPinSet = &domainConfig.pinSet_;
544                 break;
545             } else if (domain.includeSubDomains_ && CommonUtils::UrlRegexParse(hostname, domain.domainName_)) {
546                 pPinSet = &domainConfig.pinSet_;
547                 break;
548             }
549         }
550         if (pPinSet != nullptr) {
551             break;
552         }
553     }
554 
555     if (pPinSet == nullptr) {
556         return false;
557     }
558     return pPinSet->isOpenMode;
559 }
560 
GetPinSetForHostName(const std::string & hostname,std::string & pins)561 int32_t NetworkSecurityConfig::GetPinSetForHostName(const std::string &hostname, std::string &pins)
562 {
563     if (hostname.empty()) {
564         NETMGR_LOG_E("Failed to get pinset, hostname is empty.");
565         return NETMANAGER_SUCCESS;
566     }
567 
568     PinSet *pPinSet = nullptr;
569     for (auto &domainConfig : domainConfigs_) {
570         for (const auto &domain : domainConfig.domains_) {
571             if (hostname == domain.domainName_) {
572                 pPinSet = &domainConfig.pinSet_;
573                 break;
574             } else if (domain.includeSubDomains_ && CommonUtils::UrlRegexParse(hostname, domain.domainName_)) {
575                 pPinSet = &domainConfig.pinSet_;
576                 break;
577             }
578         }
579         if (pPinSet != nullptr) {
580             break;
581         }
582     }
583 
584     if (pPinSet == nullptr) {
585         NETMGR_LOG_D("No pinned pubkey configured.");
586         return NETMANAGER_SUCCESS;
587     }
588 
589     if (!ValidateDate(pPinSet->expiration_)) {
590         NETMGR_LOG_W("expiration date is invalid %{public}s", pPinSet->expiration_.c_str());
591         return NETMANAGER_SUCCESS;
592     }
593 
594     std::stringstream ss;
595     for (const auto &pin : pPinSet->pins_) {
596         NETMGR_LOG_D("Got pinnned pubkey %{public}s", pin.digest_.c_str());
597         ss << pin.digestAlgorithm_ << "//" << pin.digest_ << ";";
598     }
599 
600     pins = ss.str();
601     if (!pins.empty()) {
602         pins.pop_back();
603     }
604 
605     return NETMANAGER_SUCCESS;
606 }
607 
GetTrustAnchorsForHostName(const std::string & hostname,std::vector<std::string> & certs)608 int32_t NetworkSecurityConfig::GetTrustAnchorsForHostName(const std::string &hostname, std::vector<std::string> &certs)
609 {
610     if (hostname.empty()) {
611         NETMGR_LOG_E("Failed to get trust anchors, hostname is empty.");
612         return NETMANAGER_SUCCESS;
613     }
614 
615     TrustAnchors *pTrustAnchors = nullptr;
616     for (auto &domainConfig: domainConfigs_) {
617         for (const auto &domain: domainConfig.domains_) {
618             if (hostname == domain.domainName_) {
619                 pTrustAnchors = &domainConfig.trustAnchors_;
620                 break;
621             } else if (domain.includeSubDomains_ && CommonUtils::UrlRegexParse(hostname, domain.domainName_)) {
622                 pTrustAnchors = &domainConfig.trustAnchors_;
623                 break;
624             }
625         }
626         if (pTrustAnchors != nullptr) {
627             break;
628         }
629     }
630 
631     if (pTrustAnchors == nullptr) {
632         pTrustAnchors = &baseConfig_.trustAnchors_;
633     }
634 
635     for (auto &certPath : pTrustAnchors->certs_) {
636         auto rehashedCertpath = GetRehasedCAPath(certPath);
637         if (!rehashedCertpath.empty()) {
638             certs.push_back(rehashedCertpath);
639         }
640     }
641 
642     if (certs.empty()) {
643         NETMGR_LOG_D("No customized CA certs configured.");
644     }
645 
646     return NETMANAGER_SUCCESS;
647 }
648 
DumpConfigs()649 void NetworkSecurityConfig::DumpConfigs()
650 {
651     NETMGR_LOG_I("DumpConfigs:baseConfig_.trustAnchors_.certs");
652     for (auto &cert : baseConfig_.trustAnchors_.certs_) {
653         NETMGR_LOG_I("[%{public}s]", cert.c_str());
654     }
655 
656     NETMGR_LOG_I("DumpConfigs:domainConfigs_");
657     for (auto &domainConfig : domainConfigs_) {
658         NETMGR_LOG_I("=======================");
659         for (auto &domain : domainConfig.domains_) {
660             NETMGR_LOG_I("domainConfigs_.domains_[%{public}s][%{public}s]", domain.domainName_.c_str(),
661                          domain.includeSubDomains_ ? "include_subDomain" : "not_include_subDomain");
662         }
663         NETMGR_LOG_I("domainConfigs_.domains_.pinSet_.expiration_[%{public}s]",
664                      domainConfig.pinSet_.expiration_.c_str());
665         for (auto &pin : domainConfig.pinSet_.pins_) {
666             NETMGR_LOG_I("domainConfigs_.domains_.pinSet_.pins[%{public}s][%{public}s]", pin.digestAlgorithm_.c_str(),
667                          pin.digest_.c_str());
668         }
669         for (auto &cert : domainConfig.trustAnchors_.certs_) {
670             NETMGR_LOG_I("domainConfigs_.domains_.trustAnchors_.certs_[%{public}s]", cert.c_str());
671         }
672     }
673 }
674 
675 } // namespace NetManagerStandard
676 } // namespace OHOS
677