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