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