1 #include "config.h" 2 3 #include "certificate.hpp" 4 #include "certs_manager.hpp" 5 #include "csr.hpp" 6 7 #include <openssl/bio.h> 8 #include <openssl/ossl_typ.h> 9 #include <openssl/pem.h> 10 #include <openssl/x509.h> 11 #include <systemd/sd-event.h> 12 #include <unistd.h> 13 14 #include <sdbusplus/bus.hpp> 15 #include <sdeventplus/event.hpp> 16 #include <xyz/openbmc_project/Certs/error.hpp> 17 #include <xyz/openbmc_project/Common/error.hpp> 18 19 #include <cstdint> 20 #include <cstdio> 21 #include <cstdlib> 22 #include <filesystem> 23 #include <fstream> 24 #include <iostream> 25 #include <iterator> 26 #include <memory> 27 #include <new> 28 #include <string> 29 #include <unordered_set> 30 #include <utility> 31 #include <vector> 32 33 #include <gmock/gmock.h> 34 #include <gtest/gtest.h> 35 36 namespace phosphor::certs 37 { 38 namespace 39 { 40 namespace fs = std::filesystem; 41 using ::sdbusplus::xyz::openbmc_project::Certs::Error::InvalidCertificate; 42 using ::sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 43 using ::testing::Eq; 44 using ::testing::Return; 45 // Compares two files; returns true only if the two are the same 46 bool compareFiles(const std::string& file1, const std::string& file2) 47 { 48 std::ifstream f1(file1, std::ifstream::binary | std::ifstream::ate); 49 std::ifstream f2(file2, std::ifstream::binary | std::ifstream::ate); 50 51 if (f1.fail() || f2.fail()) 52 { 53 return false; // file problem 54 } 55 56 if (f1.tellg() != f2.tellg()) 57 { 58 return false; // size mismatch 59 } 60 61 // seek back to beginning and use std::equal to compare contents 62 f1.seekg(0, std::ifstream::beg); 63 f2.seekg(0, std::ifstream::beg); 64 return std::equal(std::istreambuf_iterator<char>(f1.rdbuf()), 65 std::istreambuf_iterator<char>(), 66 std::istreambuf_iterator<char>(f2.rdbuf())); 67 } 68 69 /** 70 * Class to generate certificate file and test verification of certificate file 71 */ 72 class TestCertificates : public ::testing::Test 73 { 74 public: 75 TestCertificates() : bus(sdbusplus::bus::new_default()) {} 76 void SetUp() override 77 { 78 char dirTemplate[] = "/tmp/FakeCerts.XXXXXX"; 79 auto dirPtr = mkdtemp(dirTemplate); 80 if (dirPtr == nullptr) 81 { 82 throw std::bad_alloc(); 83 } 84 certDir = std::string(dirPtr) + "/certs"; 85 fs::create_directories(certDir); 86 87 createNewCertificate(); 88 } 89 90 void TearDown() override 91 { 92 fs::remove_all(certDir); 93 fs::remove(certificateFile); 94 fs::remove(CSRFile); 95 fs::remove(privateKeyFile); 96 fs::remove_all("demoCA"); 97 } 98 99 void createNewCertificate(bool setNewCertId = false) 100 { 101 certificateFile = "cert.pem"; 102 CSRFile = "domain.csr"; 103 privateKeyFile = "privkey.pem"; 104 rsaPrivateKeyFilePath = certDir + "/.rsaprivkey.pem"; 105 std::string cmd = "openssl req -x509 -sha256 -newkey rsa:2048 "; 106 cmd += "-keyout cert.pem -out cert.pem -days 365000 -nodes"; 107 cmd += " -subj /O=openbmc-project.xyz/CN=localhost"; 108 109 if (setNewCertId) 110 { 111 cmd += std::to_string(certId++); 112 } 113 114 auto val = std::system(cmd.c_str()); 115 if (val) 116 { 117 std::cout << "COMMAND Error: " << val << std::endl; 118 } 119 } 120 121 void createNeverExpiredRootCertificate() 122 { 123 // remove the old cert 124 fs::remove(certificateFile); 125 126 // The following routines create a cert that has NotBefore 127 // set to 1970/01/01 and NotAfter set to 9999/12/31 via the 128 // OpenSSL CA application. 129 certificateFile = "cert.pem"; 130 ASSERT_EQ(std::system("mkdir -p demoCA"), 0); 131 ASSERT_EQ(std::system("mkdir -p demoCA/private/"), 0); 132 ASSERT_EQ(std::system("mkdir -p demoCA/newcerts/"), 0); 133 ASSERT_EQ(std::system("touch demoCA/index.txt"), 0); 134 ASSERT_EQ(std::system("echo 1000 > demoCA/serial"), 0); 135 ASSERT_EQ( 136 std::system( 137 "openssl req -x509 -sha256 -newkey rsa:2048 -keyout " 138 "demoCA/private/cakey.pem -out demoCA/cacert.pem -nodes " 139 "-subj /O=openbmc-project.xyz/C=US/ST=CA/CN=localhost-ca"), 140 0); 141 ASSERT_EQ(std::system( 142 "openssl req -new -newkey rsa:2048 -nodes -keyout " 143 "demoCA/server.key -out demoCA/server.csr -subj " 144 "/O=openbmc-project.xyz/C=US/ST=CA/CN=localhost-server"), 145 0); 146 ASSERT_EQ( 147 std::system( 148 "openssl ca -batch -startdate 19700101000000Z -enddate " 149 "99991231235959Z -out cert.pem -infiles demoCA/server.csr"), 150 0); 151 } 152 153 bool compareFiles(const std::string& file1, const std::string& file2) 154 { 155 std::ifstream f1(file1, std::ifstream::binary | std::ifstream::ate); 156 std::ifstream f2(file2, std::ifstream::binary | std::ifstream::ate); 157 158 if (f1.fail() || f2.fail()) 159 { 160 return false; // file problem 161 } 162 163 if (f1.tellg() != f2.tellg()) 164 { 165 return false; // size mismatch 166 } 167 168 // seek back to beginning and use std::equal to compare contents 169 f1.seekg(0, std::ifstream::beg); 170 f2.seekg(0, std::ifstream::beg); 171 return std::equal(std::istreambuf_iterator<char>(f1.rdbuf()), 172 std::istreambuf_iterator<char>(), 173 std::istreambuf_iterator<char>(f2.rdbuf())); 174 } 175 176 std::string getCertSubjectNameHash(const std::string& certFilePath) 177 { 178 std::unique_ptr<X509, decltype(&::X509_free)> cert(X509_new(), 179 ::X509_free); 180 if (!cert) 181 { 182 std::string(); 183 } 184 185 std::unique_ptr<BIO, decltype(&::BIO_free)> bioCert( 186 BIO_new_file(certFilePath.c_str(), "rb"), ::BIO_free); 187 if (!bioCert) 188 { 189 std::string(); 190 } 191 192 X509* x509 = cert.get(); 193 if (!PEM_read_bio_X509(bioCert.get(), &x509, nullptr, nullptr)) 194 { 195 std::string(); 196 } 197 198 unsigned long hash = X509_subject_name_hash(cert.get()); 199 static constexpr auto authCertHashLength = 9; 200 char hashBuf[authCertHashLength]; 201 sprintf(hashBuf, "%08lx", hash); 202 return std::string(hashBuf); 203 } 204 205 protected: 206 sdbusplus::bus_t bus; 207 std::string certificateFile, CSRFile, privateKeyFile, rsaPrivateKeyFilePath; 208 209 std::string certDir; 210 uint64_t certId = 1; 211 }; 212 213 class MainApp 214 { 215 public: 216 MainApp(phosphor::certs::Manager* manager, 217 phosphor::certs::CSR* csr = nullptr) : manager(manager), csr_(csr) 218 {} 219 void install(std::string& path) 220 { 221 manager->install(path); 222 } 223 224 std::string generateCSR( 225 std::vector<std::string> alternativeNames, 226 std::string challengePassword, std::string city, std::string commonName, 227 std::string contactPerson, std::string country, std::string email, 228 std::string givenName, std::string initials, int64_t keyBitLength, 229 std::string keyCurveId, std::string keyPairAlgorithm, 230 std::vector<std::string> keyUsage, std::string organization, 231 std::string organizationalUnit, std::string state, std::string surname, 232 std::string unstructuredName) 233 { 234 return (manager->generateCSR( 235 alternativeNames, challengePassword, city, commonName, 236 contactPerson, country, email, givenName, initials, keyBitLength, 237 keyCurveId, keyPairAlgorithm, keyUsage, organization, 238 organizationalUnit, state, surname, unstructuredName)); 239 } 240 std::string csr() 241 { 242 return (csr_->csr()); 243 } 244 phosphor::certs::Manager* manager; 245 phosphor::certs::CSR* csr_; 246 }; 247 248 class ManagerInTest : public phosphor::certs::Manager 249 { 250 public: 251 static constexpr std::string_view unitToRestartInTest = 252 "xyz.openbmc_project.awesome-service"; 253 ManagerInTest(sdbusplus::bus_t& bus, sdeventplus::Event& event, 254 const char* path, CertificateType type, 255 const std::string& unit, const std::string& installPath) : 256 Manager(bus, event, path, type, unit, installPath) 257 {} 258 259 MOCK_METHOD(void, reloadOrReset, (const std::string&), (override)); 260 }; 261 262 /** @brief Check if server install routine is invoked for server setup 263 */ 264 TEST_F(TestCertificates, InvokeServerInstall) 265 { 266 std::string endpoint("https"); 267 CertificateType type = CertificateType::server; 268 std::string installPath(certDir + "/" + certificateFile); 269 std::string verifyPath(installPath); 270 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 271 auto objPath = std::string(objectNamePrefix) + '/' + 272 certificateTypeToString(type) + '/' + endpoint; 273 auto event = sdeventplus::Event::get_default(); 274 // Attach the bus to sd_event to service user requests 275 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 276 ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 277 installPath); 278 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 279 .WillOnce(Return()); 280 MainApp mainApp(&manager); 281 mainApp.install(certificateFile); 282 EXPECT_TRUE(fs::exists(verifyPath)); 283 } 284 285 /** @brief Check if client install routine is invoked for client setup 286 */ 287 TEST_F(TestCertificates, InvokeClientInstall) 288 { 289 std::string endpoint("ldap"); 290 CertificateType type = CertificateType::server; 291 std::string installPath(certDir + "/" + certificateFile); 292 std::string verifyPath(installPath); 293 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 294 auto objPath = std::string(objectNamePrefix) + '/' + 295 certificateTypeToString(type) + '/' + endpoint; 296 auto event = sdeventplus::Event::get_default(); 297 // Attach the bus to sd_event to service user requests 298 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 299 ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 300 installPath); 301 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 302 .WillOnce(Return()); 303 MainApp mainApp(&manager); 304 mainApp.install(certificateFile); 305 EXPECT_TRUE(fs::exists(verifyPath)); 306 } 307 308 /** @brief Check if storage install routine is invoked for storage setup 309 */ 310 TEST_F(TestCertificates, InvokeAuthorityInstall) 311 { 312 std::string endpoint("truststore"); 313 CertificateType type = CertificateType::authority; 314 std::string verifyDir(certDir); 315 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 316 auto objPath = std::string(objectNamePrefix) + '/' + 317 certificateTypeToString(type) + '/' + endpoint; 318 auto event = sdeventplus::Event::get_default(); 319 // Attach the bus to sd_event to service user requests 320 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 321 ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 322 verifyDir); 323 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 324 .WillOnce(Return()); 325 MainApp mainApp(&manager); 326 // install the default certificate that's valid from today to 100 years 327 // later 328 mainApp.install(certificateFile); 329 330 std::vector<std::unique_ptr<Certificate>>& certs = 331 manager.getCertificates(); 332 333 ASSERT_EQ(certs.size(), 1); 334 // check some attributes as well 335 EXPECT_EQ(certs.front()->validNotAfter() - certs.front()->validNotBefore(), 336 365000ULL * 24 * 3600); 337 EXPECT_EQ(certs.front()->subject(), "O=openbmc-project.xyz,CN=localhost"); 338 EXPECT_EQ(certs.front()->issuer(), "O=openbmc-project.xyz,CN=localhost"); 339 340 std::string verifyPath = 341 verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".0"; 342 343 // Check that certificate has been created at installation directory 344 EXPECT_FALSE(fs::is_empty(verifyDir)); 345 EXPECT_TRUE(fs::exists(verifyPath)); 346 347 // Check that installed cert is identical to input one 348 EXPECT_TRUE(compareFiles(certificateFile, verifyPath)); 349 } 350 351 /** @brief Check if storage install routine is invoked for storage setup 352 */ 353 TEST_F(TestCertificates, InvokeAuthorityInstallNeverExpiredRootCert) 354 { 355 std::string endpoint("truststore"); 356 CertificateType type = CertificateType::authority; 357 std::string verifyDir(certDir); 358 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 359 auto objPath = std::string(objectNamePrefix) + '/' + 360 certificateTypeToString(type) + '/' + endpoint; 361 auto event = sdeventplus::Event::get_default(); 362 // Attach the bus to sd_event to service user requests 363 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 364 ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 365 certDir); 366 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 367 .WillOnce(Return()); 368 MainApp mainApp(&manager); 369 370 // install the certificate that's valid from the Unix Epoch to Dec 31, 9999 371 createNeverExpiredRootCertificate(); 372 mainApp.install(certificateFile); 373 374 std::vector<std::unique_ptr<Certificate>>& certs = 375 manager.getCertificates(); 376 377 EXPECT_EQ(certs.front()->validNotBefore(), 0); 378 EXPECT_EQ(certs.front()->validNotAfter(), 253402300799ULL); 379 380 std::string verifyPath = 381 verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".0"; 382 383 // Check that certificate has been created at installation directory 384 EXPECT_FALSE(fs::is_empty(verifyDir)); 385 EXPECT_TRUE(fs::exists(verifyPath)); 386 387 // Check that installed cert is identical to input one 388 EXPECT_TRUE(compareFiles(certificateFile, verifyPath)); 389 } 390 391 /** @brief Check if in authority mode user can't install the same 392 * certificate twice. 393 */ 394 TEST_F(TestCertificates, InvokeInstallSameCertTwice) 395 { 396 std::string endpoint("truststore"); 397 CertificateType type = CertificateType::authority; 398 std::string verifyDir(certDir); 399 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 400 auto objPath = std::string(objectNamePrefix) + '/' + 401 certificateTypeToString(type) + '/' + endpoint; 402 auto event = sdeventplus::Event::get_default(); 403 // Attach the bus to sd_event to service user requests 404 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 405 ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 406 std::move(certDir)); 407 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 408 .WillOnce(Return()); 409 MainApp mainApp(&manager); 410 mainApp.install(certificateFile); 411 412 std::vector<std::unique_ptr<Certificate>>& certs = 413 manager.getCertificates(); 414 415 EXPECT_FALSE(certs.empty()); 416 417 // Check that certificate has been created at installation directory 418 std::string verifyPath = 419 verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".0"; 420 EXPECT_FALSE(fs::is_empty(verifyDir)); 421 EXPECT_TRUE(fs::exists(verifyPath)); 422 423 // Check that installed cert is identical to input one 424 EXPECT_TRUE(compareFiles(certificateFile, verifyPath)); 425 426 using NotAllowed = 427 sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed; 428 EXPECT_THROW( 429 { 430 try 431 { 432 // Try to install the same certificate second time 433 mainApp.install(certificateFile); 434 } 435 catch (const NotAllowed& e) 436 { 437 throw; 438 } 439 }, 440 NotAllowed); 441 442 // Check that the original certificate has been not removed 443 EXPECT_FALSE(fs::is_empty(verifyDir)); 444 EXPECT_TRUE(fs::exists(verifyPath)); 445 } 446 447 /** @brief Check if in authority mode user can install a certificate with 448 * certain subject hash twice. 449 */ 450 TEST_F(TestCertificates, InvokeInstallSameSubjectTwice) 451 { 452 std::string endpoint("truststore"); 453 CertificateType type = CertificateType::authority; 454 std::string verifyDir(certDir); 455 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 456 auto objPath = std::string(objectNamePrefix) + '/' + 457 certificateTypeToString(type) + '/' + endpoint; 458 auto event = sdeventplus::Event::get_default(); 459 // Attach the bus to sd_event to service user requests 460 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 461 ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 462 certDir); 463 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 464 .WillOnce(Return()) 465 .WillOnce(Return()); 466 MainApp mainApp(&manager); 467 mainApp.install(certificateFile); 468 469 std::vector<std::unique_ptr<Certificate>>& certs = 470 manager.getCertificates(); 471 472 EXPECT_FALSE(certs.empty()); 473 474 // Check that certificate has been created at installation directory 475 std::string verifyPath0 = 476 verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".0"; 477 EXPECT_FALSE(fs::is_empty(verifyDir)); 478 EXPECT_TRUE(fs::exists(verifyPath0)); 479 480 // Check that installed cert is identical to input one 481 EXPECT_TRUE(compareFiles(certificateFile, verifyPath0)); 482 483 // Prepare second certificate with the same subject 484 createNewCertificate(); 485 486 // Install second certificate 487 mainApp.install(certificateFile); 488 489 // Expect there are exactly two certificates in the collection 490 EXPECT_EQ(certs.size(), 2); 491 492 // Check that certificate has been created at installation directory 493 std::string verifyPath1 = 494 verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".1"; 495 EXPECT_TRUE(fs::exists(verifyPath1)); 496 497 // Check that installed cert is identical to input one 498 EXPECT_TRUE(compareFiles(certificateFile, verifyPath1)); 499 500 // Check that the original/first certificate has been not removed 501 EXPECT_FALSE(fs::is_empty(verifyDir)); 502 EXPECT_TRUE(fs::exists(verifyPath0)); 503 } 504 505 /** @brief Check if in authority mode user can't install more than 506 * maxNumAuthorityCertificates certificates. 507 */ 508 TEST_F(TestCertificates, InvokeInstallAuthCertLimit) 509 { 510 std::string endpoint("truststore"); 511 CertificateType type = CertificateType::authority; 512 std::string verifyDir(certDir); 513 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 514 auto objPath = std::string(objectNamePrefix) + '/' + 515 certificateTypeToString(type) + '/' + endpoint; 516 auto event = sdeventplus::Event::get_default(); 517 // Attach the bus to sd_event to service user requests 518 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 519 ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 520 certDir); 521 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 522 .WillRepeatedly(Return()); 523 MainApp mainApp(&manager); 524 525 std::vector<std::unique_ptr<Certificate>>& certs = 526 manager.getCertificates(); 527 528 std::vector<std::string> verifyPaths; 529 530 // Prepare maximum number of ceritificates 531 for (std::size_t i = 0; i < maxNumAuthorityCertificates; ++i) 532 { 533 // Prepare new certificatate 534 createNewCertificate(true); 535 536 // Install ceritificate 537 mainApp.install(certificateFile); 538 539 // Check number of certificates in the collection 540 EXPECT_EQ(certs.size(), i + 1); 541 542 // Check that certificate has been created at installation directory 543 std::string verifyPath = 544 verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".0"; 545 EXPECT_FALSE(fs::is_empty(verifyDir)); 546 EXPECT_TRUE(fs::exists(verifyPath)); 547 548 // Check that installed cert is identical to input one 549 EXPECT_TRUE(compareFiles(certificateFile, verifyPath)); 550 551 // Save current certificate file for later check 552 verifyPaths.push_back(verifyPath); 553 } 554 555 // Prepare new certificatate 556 createNewCertificate(true); 557 558 using NotAllowed = 559 sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed; 560 EXPECT_THROW( 561 { 562 try 563 { 564 // Try to install one more certificate 565 mainApp.install(certificateFile); 566 } 567 catch (const NotAllowed& e) 568 { 569 throw; 570 } 571 }, 572 NotAllowed); 573 574 // Check that the original certificate has been not removed 575 EXPECT_FALSE(fs::is_empty(verifyDir)); 576 for (size_t i = 0; i < maxNumAuthorityCertificates; ++i) 577 { 578 EXPECT_TRUE(fs::exists(verifyPaths[i])); 579 } 580 } 581 582 /** @brief Compare the installed certificate with the copied certificate 583 */ 584 TEST_F(TestCertificates, CompareInstalledCertificate) 585 { 586 std::string endpoint("ldap"); 587 CertificateType type = CertificateType::client; 588 std::string installPath(certDir + "/" + certificateFile); 589 std::string verifyPath(installPath); 590 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 591 auto objPath = std::string(objectNamePrefix) + '/' + 592 certificateTypeToString(type) + '/' + endpoint; 593 auto event = sdeventplus::Event::get_default(); 594 // Attach the bus to sd_event to service user requests 595 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 596 ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 597 installPath); 598 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 599 .WillOnce(Return()); 600 MainApp mainApp(&manager); 601 mainApp.install(certificateFile); 602 EXPECT_TRUE(fs::exists(verifyPath)); 603 EXPECT_TRUE(compareFiles(verifyPath, certificateFile)); 604 } 605 606 /** @brief Check if install fails if certificate file is not found 607 */ 608 TEST_F(TestCertificates, TestNoCertificateFile) 609 { 610 std::string endpoint("ldap"); 611 CertificateType type = CertificateType::client; 612 std::string installPath(certDir + "/" + certificateFile); 613 std::string verifyPath(installPath); 614 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 615 auto objPath = std::string(objectNamePrefix) + '/' + 616 certificateTypeToString(type) + '/' + endpoint; 617 std::string uploadFile = "nofile.pem"; 618 EXPECT_THROW( 619 { 620 try 621 { 622 auto event = sdeventplus::Event::get_default(); 623 // Attach the bus to sd_event to service user requests 624 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 625 ManagerInTest manager(bus, event, objPath.c_str(), type, 626 verifyUnit, installPath); 627 MainApp mainApp(&manager); 628 mainApp.install(uploadFile); 629 } 630 catch (const InternalFailure& e) 631 { 632 throw; 633 } 634 }, 635 InternalFailure); 636 EXPECT_FALSE(fs::exists(verifyPath)); 637 } 638 639 /** @brief Test replacing existing certificate 640 */ 641 TEST_F(TestCertificates, TestReplaceCertificate) 642 { 643 std::string endpoint("ldap"); 644 CertificateType type = CertificateType::server; 645 std::string installPath(certDir + "/" + certificateFile); 646 std::string verifyPath(installPath); 647 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 648 auto objPath = std::string(objectNamePrefix) + '/' + 649 certificateTypeToString(type) + '/' + endpoint; 650 auto event = sdeventplus::Event::get_default(); 651 // Attach the bus to sd_event to service user requests 652 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 653 ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 654 std::move(installPath)); 655 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 656 .WillOnce(Return()) 657 .WillOnce(Return()); 658 MainApp mainApp(&manager); 659 mainApp.install(certificateFile); 660 EXPECT_TRUE(fs::exists(verifyPath)); 661 std::vector<std::unique_ptr<Certificate>>& certs = 662 manager.getCertificates(); 663 EXPECT_FALSE(certs.empty()); 664 EXPECT_NE(certs[0], nullptr); 665 certs[0]->replace(certificateFile); 666 EXPECT_TRUE(fs::exists(verifyPath)); 667 } 668 669 /** @brief Test replacing existing certificate 670 */ 671 TEST_F(TestCertificates, TestAuthorityReplaceCertificate) 672 { 673 std::string endpoint("truststore"); 674 CertificateType type = CertificateType::authority; 675 std::string verifyDir(certDir); 676 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 677 auto objPath = std::string(objectNamePrefix) + '/' + 678 certificateTypeToString(type) + '/' + endpoint; 679 auto event = sdeventplus::Event::get_default(); 680 // Attach the bus to sd_event to service user requests 681 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 682 ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 683 certDir); 684 constexpr const unsigned int replaceIterations = 10; 685 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 686 .Times(replaceIterations + 1) 687 .WillRepeatedly(Return()); 688 MainApp mainApp(&manager); 689 mainApp.install(certificateFile); 690 691 std::vector<std::unique_ptr<Certificate>>& certs = 692 manager.getCertificates(); 693 694 for (unsigned int i = 0; i < replaceIterations; i++) 695 { 696 // Certificate successfully installed 697 EXPECT_FALSE(certs.empty()); 698 699 std::string verifyPath = 700 verifyDir + "/" + getCertSubjectNameHash(certificateFile) + ".0"; 701 702 // Check that certificate has been created at installation directory 703 EXPECT_FALSE(fs::is_empty(verifyDir)); 704 EXPECT_TRUE(fs::exists(verifyPath)); 705 706 // Check that installed cert is identical to input one 707 EXPECT_TRUE(compareFiles(certificateFile, verifyPath)); 708 709 // Create new certificate 710 createNewCertificate(true); 711 712 certs[0]->replace(certificateFile); 713 714 // Verify that old certificate has been removed 715 EXPECT_FALSE(fs::exists(verifyPath)); 716 } 717 } 718 719 /** @brief Test verifiing if delete function works. 720 */ 721 TEST_F(TestCertificates, TestStorageDeleteCertificate) 722 { 723 std::string endpoint("truststore"); 724 CertificateType type = CertificateType::authority; 725 std::string verifyDir(certDir); 726 std::string verifyUnit((ManagerInTest::unitToRestartInTest)); 727 auto objPath = std::string(objectNamePrefix) + '/' + 728 certificateTypeToString(type) + '/' + endpoint; 729 auto event = sdeventplus::Event::get_default(); 730 // Attach the bus to sd_event to service user requests 731 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 732 ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 733 certDir); 734 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 735 .WillRepeatedly(Return()); 736 MainApp mainApp(&manager); 737 738 // Check if certificate placeholder dir is empty 739 EXPECT_TRUE(fs::is_empty(verifyDir)); 740 mainApp.install(certificateFile); 741 742 // Create new certificate 743 createNewCertificate(true); 744 mainApp.install(certificateFile); 745 746 createNewCertificate(true); 747 mainApp.install(certificateFile); 748 749 std::vector<std::unique_ptr<Certificate>>& certs = 750 manager.getCertificates(); 751 752 // All 3 certificates successfully installed and added to manager 753 EXPECT_EQ(certs.size(), 3); 754 755 // Check if certificate placeholder is not empty, there should be 3 756 // certificates 757 EXPECT_FALSE(fs::is_empty(verifyDir)); 758 759 certs[0]->delete_(); 760 EXPECT_EQ(certs.size(), 2); 761 762 certs[0]->delete_(); 763 EXPECT_EQ(certs.size(), 1); 764 765 certs[0]->delete_(); 766 EXPECT_EQ(certs.size(), 0); 767 768 // Check if certificate placeholder is empty. 769 EXPECT_TRUE(fs::is_empty(verifyDir)); 770 } 771 772 /** @brief Check if install fails if certificate file is empty 773 */ 774 TEST_F(TestCertificates, TestEmptyCertificateFile) 775 { 776 std::string endpoint("ldap"); 777 CertificateType type = CertificateType::client; 778 std::string installPath(certDir + "/" + certificateFile); 779 std::string verifyPath(installPath); 780 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 781 auto objPath = std::string(objectNamePrefix) + '/' + 782 certificateTypeToString(type) + '/' + endpoint; 783 std::string emptyFile("emptycert.pem"); 784 std::ofstream ofs; 785 ofs.open(emptyFile, std::ofstream::out); 786 ofs.close(); 787 EXPECT_THROW( 788 { 789 try 790 { 791 auto event = sdeventplus::Event::get_default(); 792 // Attach the bus to sd_event to service user requests 793 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 794 ManagerInTest manager(bus, event, objPath.c_str(), type, 795 verifyUnit, installPath); 796 MainApp mainApp(&manager); 797 mainApp.install(emptyFile); 798 } 799 catch (const InvalidCertificate& e) 800 { 801 throw; 802 } 803 }, 804 InvalidCertificate); 805 EXPECT_FALSE(fs::exists(verifyPath)); 806 fs::remove(emptyFile); 807 } 808 809 /** @brief Check if install fails if certificate file is corrupted 810 */ 811 TEST_F(TestCertificates, TestInvalidCertificateFile) 812 { 813 std::string endpoint("ldap"); 814 CertificateType type = CertificateType::client; 815 816 std::ofstream ofs; 817 ofs.open(certificateFile, std::ofstream::out); 818 ofs << "-----BEGIN CERTIFICATE-----"; 819 ofs << "ADD_SOME_INVALID_DATA_INTO_FILE"; 820 ofs << "-----END CERTIFICATE-----"; 821 ofs.close(); 822 823 std::string installPath(certDir + "/" + certificateFile); 824 std::string verifyPath(installPath); 825 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 826 auto objPath = std::string(objectNamePrefix) + '/' + 827 certificateTypeToString(type) + '/' + endpoint; 828 EXPECT_THROW( 829 { 830 try 831 { 832 auto event = sdeventplus::Event::get_default(); 833 // Attach the bus to sd_event to service user requests 834 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 835 ManagerInTest manager(bus, event, objPath.c_str(), type, 836 verifyUnit, installPath); 837 MainApp mainApp(&manager); 838 mainApp.install(certificateFile); 839 } 840 catch (const InvalidCertificate& e) 841 { 842 throw; 843 } 844 }, 845 InvalidCertificate); 846 EXPECT_FALSE(fs::exists(verifyPath)); 847 } 848 849 /** 850 * Class to generate private and certificate only file and test verification 851 */ 852 class TestInvalidCertificate : public ::testing::Test 853 { 854 public: 855 TestInvalidCertificate() : bus(sdbusplus::bus::new_default()) {} 856 void SetUp() override 857 { 858 char dirTemplate[] = "/tmp/FakeCerts.XXXXXX"; 859 auto dirPtr = mkdtemp(dirTemplate); 860 if (dirPtr == nullptr) 861 { 862 throw std::bad_alloc(); 863 } 864 certDir = std::string(dirPtr) + "/certs"; 865 fs::create_directories(certDir); 866 certificateFile = "cert.pem"; 867 keyFile = "key.pem"; 868 std::string cmd = "openssl req -x509 -sha256 -newkey rsa:2048 "; 869 cmd += "-keyout key.pem -out cert.pem -days 3650 "; 870 cmd += "-subj " 871 "/O=openbmc-project.xyz/CN=localhost" 872 " -nodes"; 873 874 auto val = std::system(cmd.c_str()); 875 if (val) 876 { 877 std::cout << "command Error: " << val << std::endl; 878 } 879 } 880 void TearDown() override 881 { 882 fs::remove_all(certDir); 883 fs::remove(certificateFile); 884 fs::remove(keyFile); 885 } 886 887 protected: 888 sdbusplus::bus_t bus; 889 std::string certificateFile; 890 std::string keyFile; 891 std::string certDir; 892 }; 893 894 /** @brief Check install fails if private key is missing in certificate file 895 */ 896 TEST_F(TestInvalidCertificate, TestMissingPrivateKey) 897 { 898 std::string endpoint("ldap"); 899 CertificateType type = CertificateType::client; 900 std::string installPath(certDir + "/" + certificateFile); 901 std::string verifyPath(installPath); 902 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 903 auto objPath = std::string(objectNamePrefix) + '/' + 904 certificateTypeToString(type) + '/' + endpoint; 905 EXPECT_THROW( 906 { 907 try 908 { 909 auto event = sdeventplus::Event::get_default(); 910 // Attach the bus to sd_event to service user requests 911 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 912 ManagerInTest manager(bus, event, objPath.c_str(), type, 913 verifyUnit, installPath); 914 MainApp mainApp(&manager); 915 mainApp.install(certificateFile); 916 } 917 catch (const InternalFailure& e) 918 { 919 throw; 920 } 921 }, 922 InternalFailure); 923 EXPECT_FALSE(fs::exists(verifyPath)); 924 } 925 926 /** @brief Check install fails if ceritificate is missing in certificate file 927 */ 928 TEST_F(TestInvalidCertificate, TestMissingCeritificate) 929 { 930 std::string endpoint("ldap"); 931 CertificateType type = CertificateType::client; 932 std::string installPath(certDir + "/" + keyFile); 933 std::string verifyPath(installPath); 934 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 935 auto objPath = std::string(objectNamePrefix) + '/' + 936 certificateTypeToString(type) + '/' + endpoint; 937 EXPECT_THROW( 938 { 939 try 940 { 941 auto event = sdeventplus::Event::get_default(); 942 // Attach the bus to sd_event to service user requests 943 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 944 ManagerInTest manager(bus, event, objPath.c_str(), type, 945 verifyUnit, installPath); 946 MainApp mainApp(&manager); 947 mainApp.install(keyFile); 948 } 949 catch (const InternalFailure& e) 950 { 951 throw; 952 } 953 }, 954 InvalidCertificate); 955 EXPECT_FALSE(fs::exists(verifyPath)); 956 } 957 958 /** @brief Check if error is thrown when multiple certificates are installed 959 * At present only one certificate per service is allowed 960 */ 961 TEST_F(TestCertificates, TestCertInstallNotAllowed) 962 { 963 using NotAllowed = 964 sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed; 965 std::string endpoint("ldap"); 966 CertificateType type = CertificateType::client; 967 std::string installPath(certDir + "/" + certificateFile); 968 std::string verifyPath(installPath); 969 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 970 auto objPath = std::string(objectNamePrefix) + '/' + 971 certificateTypeToString(type) + '/' + endpoint; 972 auto event = sdeventplus::Event::get_default(); 973 // Attach the bus to sd_event to service user requests 974 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 975 ManagerInTest manager(bus, event, objPath.c_str(), type, verifyUnit, 976 installPath); 977 MainApp mainApp(&manager); 978 mainApp.install(certificateFile); 979 EXPECT_TRUE(fs::exists(verifyPath)); 980 EXPECT_THROW( 981 { 982 try 983 { 984 // install second certificate 985 mainApp.install(certificateFile); 986 } 987 catch (const NotAllowed& e) 988 { 989 throw; 990 } 991 }, 992 NotAllowed); 993 } 994 995 TEST_F(TestCertificates, TestGenerateCSR) 996 { 997 std::string endpoint("https"); 998 std::string unit; 999 CertificateType type = CertificateType::server; 1000 std::string installPath(certDir + "/" + certificateFile); 1001 std::string csrPath(certDir + "/" + CSRFile); 1002 std::string privateKeyPath(certDir + "/" + privateKeyFile); 1003 std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 1004 std::string challengePassword("Password"); 1005 std::string city("HYB"); 1006 std::string commonName("abc.com"); 1007 std::string contactPerson("Admin"); 1008 std::string country("IN"); 1009 std::string email("admin@in.ibm.com"); 1010 std::string givenName("givenName"); 1011 std::string initials("G"); 1012 int64_t keyBitLength(2048); 1013 std::string keyCurveId("0"); 1014 std::string keyPairAlgorithm("RSA"); 1015 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 1016 std::string organization("IBM"); 1017 std::string organizationalUnit("orgUnit"); 1018 std::string state("TS"); 1019 std::string surname("surname"); 1020 std::string unstructuredName("unstructuredName"); 1021 auto objPath = std::string(objectNamePrefix) + '/' + 1022 certificateTypeToString(type) + '/' + endpoint; 1023 auto event = sdeventplus::Event::get_default(); 1024 // Attach the bus to sd_event to service user requests 1025 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 1026 Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1027 std::move(installPath)); 1028 Status status = Status::success; 1029 CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1030 MainApp mainApp(&manager, &csr); 1031 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1032 contactPerson, country, email, givenName, initials, 1033 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1034 organization, organizationalUnit, state, surname, 1035 unstructuredName); 1036 std::string csrData{}; 1037 // generateCSR takes considerable time to create CSR and privateKey Files 1038 EXPECT_FALSE(fs::exists(csrPath)); 1039 EXPECT_FALSE(fs::exists(privateKeyPath)); 1040 EXPECT_THROW( 1041 { 1042 try 1043 { 1044 csrData = csr.csr(); 1045 } 1046 catch (const InternalFailure& e) 1047 { 1048 throw; 1049 } 1050 }, 1051 InternalFailure); 1052 // wait for 10 sec to get CSR and privateKey Files generated 1053 sleep(10); 1054 EXPECT_TRUE(fs::exists(csrPath)); 1055 EXPECT_TRUE(fs::exists(privateKeyPath)); 1056 csrData = csr.csr(); 1057 ASSERT_NE("", csrData.c_str()); 1058 } 1059 1060 /** @brief Check if ECC key pair is generated when user is not given algorithm 1061 * type. At present RSA and EC key pair algorithm are supported 1062 */ 1063 TEST_F(TestCertificates, TestGenerateCSRwithEmptyKeyPairAlgorithm) 1064 { 1065 std::string endpoint("https"); 1066 std::string unit; 1067 CertificateType type = CertificateType::server; 1068 std::string installPath(certDir + "/" + certificateFile); 1069 std::string csrPath(certDir + "/" + CSRFile); 1070 std::string privateKeyPath(certDir + "/" + privateKeyFile); 1071 std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 1072 std::string challengePassword("Password"); 1073 std::string city("HYB"); 1074 std::string commonName("abc.com"); 1075 std::string contactPerson("Admin"); 1076 std::string country("IN"); 1077 std::string email("admin@in.ibm.com"); 1078 std::string givenName("givenName"); 1079 std::string initials("G"); 1080 int64_t keyBitLength(2048); 1081 std::string keyCurveId(""); 1082 std::string keyPairAlgorithm(""); 1083 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 1084 std::string organization("IBM"); 1085 std::string organizationalUnit("orgUnit"); 1086 std::string state("TS"); 1087 std::string surname("surname"); 1088 std::string unstructuredName("unstructuredName"); 1089 auto objPath = std::string(objectNamePrefix) + '/' + 1090 certificateTypeToString(type) + '/' + endpoint; 1091 auto event = sdeventplus::Event::get_default(); 1092 Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1093 std::move(installPath)); 1094 Status status; 1095 CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1096 MainApp mainApp(&manager, &csr); 1097 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1098 contactPerson, country, email, givenName, initials, 1099 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1100 organization, organizationalUnit, state, surname, 1101 unstructuredName); 1102 sleep(10); 1103 EXPECT_TRUE(fs::exists(csrPath)); 1104 EXPECT_TRUE(fs::exists(privateKeyPath)); 1105 } 1106 1107 /** @brief Check if error is thrown when giving un supported key pair 1108 * algorithm. At present RSA and EC key pair algorithm are supported 1109 */ 1110 TEST_F(TestCertificates, TestGenerateCSRwithUnsupportedKeyPairAlgorithm) 1111 { 1112 std::string endpoint("https"); 1113 std::string unit; 1114 CertificateType type = CertificateType::server; 1115 std::string installPath(certDir + "/" + certificateFile); 1116 std::string csrPath(certDir + "/" + CSRFile); 1117 std::string privateKeyPath(certDir + "/" + privateKeyFile); 1118 std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 1119 std::string challengePassword("Password"); 1120 std::string city("HYB"); 1121 std::string commonName("abc.com"); 1122 std::string contactPerson("Admin"); 1123 std::string country("IN"); 1124 std::string email("admin@in.ibm.com"); 1125 std::string givenName("givenName"); 1126 std::string initials("G"); 1127 int64_t keyBitLength(2048); 1128 std::string keyCurveId("secp521r1"); 1129 std::string keyPairAlgorithm("UnSupportedAlgorithm"); 1130 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 1131 std::string organization("IBM"); 1132 std::string organizationalUnit("orgUnit"); 1133 std::string state("TS"); 1134 std::string surname("surname"); 1135 std::string unstructuredName("unstructuredName"); 1136 auto objPath = std::string(objectNamePrefix) + '/' + 1137 certificateTypeToString(type) + '/' + endpoint; 1138 auto event = sdeventplus::Event::get_default(); 1139 Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1140 std::move(installPath)); 1141 Status status; 1142 CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1143 MainApp mainApp(&manager, &csr); 1144 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1145 contactPerson, country, email, givenName, initials, 1146 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1147 organization, organizationalUnit, state, surname, 1148 unstructuredName); 1149 EXPECT_FALSE(fs::exists(csrPath)); 1150 EXPECT_FALSE(fs::exists(privateKeyPath)); 1151 } 1152 1153 /** @brief Check if error is thrown when NID_undef is returned for given key 1154 * curve id 1155 */ 1156 TEST_F(TestCertificates, TestECKeyGenerationwithNIDundefCase) 1157 { 1158 std::string endpoint("https"); 1159 std::string unit; 1160 CertificateType type = CertificateType::server; 1161 std::string installPath(certDir + "/" + certificateFile); 1162 std::string csrPath(certDir + "/" + CSRFile); 1163 std::string privateKeyPath(certDir + "/" + privateKeyFile); 1164 std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 1165 std::string challengePassword("Password"); 1166 std::string city("BLR"); 1167 std::string commonName("abc.com"); 1168 std::string contactPerson("Admin"); 1169 std::string country("IN"); 1170 std::string email("admin@in.ibm.com"); 1171 std::string givenName("givenName"); 1172 std::string initials("G"); 1173 int64_t keyBitLength(2048); 1174 std::string keyCurveId("DummyCurveName"); 1175 std::string keyPairAlgorithm("EC"); 1176 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 1177 std::string organization("IBM"); 1178 std::string organizationalUnit("orgUnit"); 1179 std::string state("TS"); 1180 std::string surname("surname"); 1181 std::string unstructuredName("unstructuredName"); 1182 auto objPath = std::string(objectNamePrefix) + '/' + 1183 certificateTypeToString(type) + '/' + endpoint; 1184 auto event = sdeventplus::Event::get_default(); 1185 Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1186 std::move(installPath)); 1187 Status status; 1188 CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1189 MainApp mainApp(&manager, &csr); 1190 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1191 contactPerson, country, email, givenName, initials, 1192 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1193 organization, organizationalUnit, state, surname, 1194 unstructuredName); 1195 EXPECT_FALSE(fs::exists(csrPath)); 1196 EXPECT_FALSE(fs::exists(privateKeyPath)); 1197 } 1198 1199 /** @brief Check default Key Curve Id is used if given curve id is empty 1200 */ 1201 TEST_F(TestCertificates, TestECKeyGenerationwithDefaultKeyCurveId) 1202 { 1203 std::string endpoint("https"); 1204 std::string unit; 1205 CertificateType type = CertificateType::server; 1206 std::string installPath(certDir + "/" + certificateFile); 1207 std::string csrPath(certDir + "/" + CSRFile); 1208 std::string privateKeyPath(certDir + "/" + privateKeyFile); 1209 std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 1210 std::string challengePassword("Password"); 1211 std::string city("BLR"); 1212 std::string commonName("abc.com"); 1213 std::string contactPerson("Admin"); 1214 std::string country("IN"); 1215 std::string email("admin@in.ibm.com"); 1216 std::string givenName("givenName"); 1217 std::string initials("G"); 1218 int64_t keyBitLength(2048); 1219 std::string keyCurveId(""); 1220 std::string keyPairAlgorithm("EC"); 1221 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 1222 std::string organization("IBM"); 1223 std::string organizationalUnit("orgUnit"); 1224 std::string state("TS"); 1225 std::string surname("surname"); 1226 std::string unstructuredName("unstructuredName"); 1227 auto objPath = std::string(objectNamePrefix) + '/' + 1228 certificateTypeToString(type) + '/' + endpoint; 1229 auto event = sdeventplus::Event::get_default(); 1230 Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1231 std::move(installPath)); 1232 Status status; 1233 CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1234 MainApp mainApp(&manager, &csr); 1235 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1236 contactPerson, country, email, givenName, initials, 1237 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1238 organization, organizationalUnit, state, surname, 1239 unstructuredName); 1240 sleep(10); 1241 EXPECT_TRUE(fs::exists(csrPath)); 1242 EXPECT_TRUE(fs::exists(privateKeyPath)); 1243 } 1244 1245 /** @brief Check if error is not thrown to generate EC key pair 1246 */ 1247 TEST_F(TestCertificates, TestECKeyGeneration) 1248 { 1249 std::string endpoint("https"); 1250 std::string unit; 1251 CertificateType type = CertificateType::server; 1252 std::string installPath(certDir + "/" + certificateFile); 1253 std::string csrPath(certDir + "/" + CSRFile); 1254 std::string privateKeyPath(certDir + "/" + privateKeyFile); 1255 std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 1256 std::string challengePassword("Password"); 1257 std::string city("BLR"); 1258 std::string commonName("abc.com"); 1259 std::string contactPerson("Admin"); 1260 std::string country("IN"); 1261 std::string email("admin@in.ibm.com"); 1262 std::string givenName("givenName"); 1263 std::string initials("G"); 1264 int64_t keyBitLength(2048); 1265 std::string keyCurveId("secp521r1"); 1266 std::string keyPairAlgorithm("EC"); 1267 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 1268 std::string organization("IBM"); 1269 std::string organizationalUnit("orgUnit"); 1270 std::string state("TS"); 1271 std::string surname("surname"); 1272 std::string unstructuredName("unstructuredName"); 1273 auto objPath = std::string(objectNamePrefix) + '/' + 1274 certificateTypeToString(type) + '/' + endpoint; 1275 auto event = sdeventplus::Event::get_default(); 1276 Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1277 std::move(installPath)); 1278 Status status = Status::success; 1279 CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1280 MainApp mainApp(&manager, &csr); 1281 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1282 contactPerson, country, email, givenName, initials, 1283 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1284 organization, organizationalUnit, state, surname, 1285 unstructuredName); 1286 std::cout << "CSRPath: " << csrPath << std::endl 1287 << "privateKeyPath: " << privateKeyPath << std::endl; 1288 sleep(10); 1289 EXPECT_TRUE(fs::exists(csrPath)); 1290 EXPECT_TRUE(fs::exists(privateKeyPath)); 1291 } 1292 1293 /** @brief Check error is thrown if giving unsupported key bit length to 1294 * generate rsa key 1295 */ 1296 TEST_F(TestCertificates, TestRSAKeyWithUnsupportedKeyBitLength) 1297 { 1298 std::string endpoint("https"); 1299 std::string unit; 1300 CertificateType type = CertificateType::server; 1301 std::string installPath(certDir + "/" + certificateFile); 1302 std::string csrPath(certDir + "/" + CSRFile); 1303 std::string privateKeyPath(certDir + "/" + privateKeyFile); 1304 std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 1305 std::string challengePassword("Password"); 1306 std::string city("BLR"); 1307 std::string commonName("abc.com"); 1308 std::string contactPerson("Admin"); 1309 std::string country("IN"); 1310 std::string email("admin@in.ibm.com"); 1311 std::string givenName("givenName"); 1312 std::string initials("G"); 1313 int64_t keyBitLength(4096); 1314 std::string keyCurveId("secp521r1"); 1315 std::string keyPairAlgorithm("RSA"); 1316 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 1317 std::string organization("IBM"); 1318 std::string organizationalUnit("orgUnit"); 1319 std::string state("TS"); 1320 std::string surname("surname"); 1321 std::string unstructuredName("unstructuredName"); 1322 auto objPath = std::string(objectNamePrefix) + '/' + 1323 certificateTypeToString(type) + '/' + endpoint; 1324 auto event = sdeventplus::Event::get_default(); 1325 Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1326 std::move(installPath)); 1327 Status status; 1328 CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1329 MainApp mainApp(&manager, &csr); 1330 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1331 contactPerson, country, email, givenName, initials, 1332 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1333 organization, organizationalUnit, state, surname, 1334 unstructuredName); 1335 EXPECT_FALSE(fs::exists(csrPath)); 1336 EXPECT_FALSE(fs::exists(privateKeyPath)); 1337 } 1338 1339 /** @brief Check error is thrown if generated rsa key file is not present 1340 */ 1341 TEST_F(TestCertificates, TestRSAKeyFileNotPresentCase) 1342 { 1343 std::string endpoint("https"); 1344 std::string unit; 1345 CertificateType type = CertificateType::server; 1346 std::string installPath(certDir + "/" + certificateFile); 1347 std::string csrPath(certDir + "/" + CSRFile); 1348 std::string privateKeyPath(certDir + "/" + privateKeyFile); 1349 std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 1350 std::string challengePassword("Password"); 1351 std::string city("BLR"); 1352 std::string commonName("abc.com"); 1353 std::string contactPerson("Admin"); 1354 std::string country("IN"); 1355 std::string email("admin@in.ibm.com"); 1356 std::string givenName("givenName"); 1357 std::string initials("G"); 1358 int64_t keyBitLength(2048); 1359 std::string keyCurveId("secp521r1"); 1360 std::string keyPairAlgorithm("RSA"); 1361 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 1362 std::string organization("IBM"); 1363 std::string organizationalUnit("orgUnit"); 1364 std::string state("TS"); 1365 std::string surname("surname"); 1366 std::string unstructuredName("unstructuredName"); 1367 auto objPath = std::string(objectNamePrefix) + '/' + 1368 certificateTypeToString(type) + '/' + endpoint; 1369 auto event = sdeventplus::Event::get_default(); 1370 Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1371 std::move(installPath)); 1372 1373 // Removing generated RSA key file 1374 fs::remove(rsaPrivateKeyFilePath); 1375 1376 Status status; 1377 CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1378 MainApp mainApp(&manager, &csr); 1379 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1380 contactPerson, country, email, givenName, initials, 1381 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1382 organization, organizationalUnit, state, surname, 1383 unstructuredName); 1384 EXPECT_FALSE(fs::exists(csrPath)); 1385 EXPECT_FALSE(fs::exists(privateKeyPath)); 1386 } 1387 1388 /** @brief Check private key file is created from generated rsa key file is 1389 * `present 1390 */ 1391 TEST_F(TestCertificates, TestRSAKeyFromRSAKeyFileIsWrittenIntoPrivateKeyFile) 1392 { 1393 std::string endpoint("https"); 1394 std::string unit; 1395 CertificateType type = CertificateType::server; 1396 std::string installPath(certDir + "/" + certificateFile); 1397 std::string csrPath(certDir + "/" + CSRFile); 1398 std::string privateKeyPath(certDir + "/" + privateKeyFile); 1399 std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 1400 std::string challengePassword("Password"); 1401 std::string city("BLR"); 1402 std::string commonName("abc.com"); 1403 std::string contactPerson("Admin"); 1404 std::string country("IN"); 1405 std::string email("admin@in.ibm.com"); 1406 std::string givenName("givenName"); 1407 std::string initials("G"); 1408 int64_t keyBitLength(2048); 1409 std::string keyCurveId("secp521r1"); 1410 std::string keyPairAlgorithm("RSA"); 1411 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 1412 std::string organization("IBM"); 1413 std::string organizationalUnit("orgUnit"); 1414 std::string state("TS"); 1415 std::string surname("surname"); 1416 std::string unstructuredName("unstructuredName"); 1417 auto objPath = std::string(objectNamePrefix) + '/' + 1418 certificateTypeToString(type) + '/' + endpoint; 1419 auto event = sdeventplus::Event::get_default(); 1420 Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1421 std::move(installPath)); 1422 Status status; 1423 CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1424 MainApp mainApp(&manager, &csr); 1425 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1426 contactPerson, country, email, givenName, initials, 1427 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1428 organization, organizationalUnit, state, surname, 1429 unstructuredName); 1430 sleep(10); 1431 EXPECT_TRUE(fs::exists(csrPath)); 1432 EXPECT_TRUE(fs::exists(privateKeyPath)); 1433 } 1434 1435 /** @brief Check RSA key is generated during application startup*/ 1436 TEST_F(TestCertificates, TestGenerateRSAPrivateKeyFile) 1437 { 1438 std::string endpoint("https"); 1439 CertificateType type = CertificateType::server; 1440 std::string installPath(certDir + "/" + certificateFile); 1441 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1442 auto objPath = std::string(objectNamePrefix) + '/' + 1443 certificateTypeToString(type) + '/' + endpoint; 1444 auto event = sdeventplus::Event::get_default(); 1445 1446 EXPECT_FALSE(fs::exists(rsaPrivateKeyFilePath)); 1447 Manager manager(bus, event, objPath.c_str(), type, verifyUnit, installPath); 1448 EXPECT_TRUE(fs::exists(rsaPrivateKeyFilePath)); 1449 } 1450 1451 /** 1452 * Class to test Authorities List installation and replacement 1453 */ 1454 class AuthoritiesListTest : public testing::Test 1455 { 1456 public: 1457 AuthoritiesListTest() : 1458 bus(sdbusplus::bus::new_default()), 1459 authoritiesListFolder( 1460 Certificate::generateUniqueFilePath(fs::temp_directory_path())) 1461 { 1462 fs::create_directory(authoritiesListFolder); 1463 createAuthoritiesList(maxNumAuthorityCertificates); 1464 } 1465 ~AuthoritiesListTest() override 1466 { 1467 fs::remove_all(authoritiesListFolder); 1468 } 1469 1470 protected: 1471 // Creates a testing authorities list which consists of |count| root 1472 // certificates 1473 void createAuthoritiesList(int count) 1474 { 1475 fs::path srcFolder = fs::temp_directory_path(); 1476 srcFolder = Certificate::generateUniqueFilePath(srcFolder); 1477 fs::create_directory(srcFolder); 1478 createSingleAuthority(srcFolder, "root_0"); 1479 sourceAuthoritiesListFile = srcFolder / "root_0_cert"; 1480 for (int i = 1; i < count; ++i) 1481 { 1482 std::string name = "root_" + std::to_string(i); 1483 createSingleAuthority(srcFolder, name); 1484 appendContentFromFile(sourceAuthoritiesListFile, 1485 srcFolder / (name + "_cert")); 1486 } 1487 } 1488 1489 // Creates a single self-signed root certificate in given |path|; the key 1490 // will be |path|/|cn|_key, the cert will be |path|/|cn|_cert, and the cn 1491 // will be "/O=openbmc-project.xyz/C=US/ST=CA/CN=|cn|" 1492 static void createSingleAuthority(const std::string& path, 1493 const std::string& cn) 1494 { 1495 std::string key = fs::path(path) / (cn + "_key"); 1496 std::string cert = fs::path(path) / (cn + "_cert"); 1497 std::string cmd = "openssl req -x509 -sha256 -newkey rsa:2048 -keyout "; 1498 cmd += key + " -out " + cert + " -nodes --days 365000 "; 1499 cmd += "-subj /O=openbmc-project.xyz/CN=" + cn; 1500 ASSERT_EQ(std::system(cmd.c_str()), 0); 1501 } 1502 1503 // Appends the content of the |from| file to the |to| file. 1504 static void appendContentFromFile(const std::string& to, 1505 const std::string& from) 1506 { 1507 ASSERT_NO_THROW({ 1508 std::ifstream inputCertFileStream; 1509 std::ofstream outputCertFileStream; 1510 inputCertFileStream.exceptions( 1511 std::ifstream::failbit | std::ifstream::badbit | 1512 std::ifstream::eofbit); 1513 outputCertFileStream.exceptions( 1514 std::ofstream::failbit | std::ofstream::badbit | 1515 std::ofstream::eofbit); 1516 inputCertFileStream.open(from); 1517 outputCertFileStream.open(to, std::ios::app); 1518 outputCertFileStream << inputCertFileStream.rdbuf() << std::flush; 1519 inputCertFileStream.close(); 1520 outputCertFileStream.close(); 1521 }); 1522 } 1523 1524 // Appends the content of the |from| buffer to the |to| file. 1525 static void setContentFromString(const std::string& to, 1526 const std::string& from) 1527 { 1528 ASSERT_NO_THROW({ 1529 std::ofstream outputCertFileStream; 1530 outputCertFileStream.exceptions( 1531 std::ofstream::failbit | std::ofstream::badbit | 1532 std::ofstream::eofbit); 1533 outputCertFileStream.open(to, std::ios::out); 1534 outputCertFileStream << from << std::flush; 1535 outputCertFileStream.close(); 1536 }); 1537 } 1538 1539 // Verifies the effect of InstallAll or ReplaceAll 1540 void verifyCertificates(std::vector<std::unique_ptr<Certificate>>& certs) 1541 { 1542 // The trust bundle file has been copied over 1543 EXPECT_FALSE(fs::is_empty(authoritiesListFolder)); 1544 EXPECT_TRUE( 1545 compareFiles(authoritiesListFolder / defaultAuthoritiesListFileName, 1546 sourceAuthoritiesListFile)); 1547 1548 ASSERT_EQ(certs.size(), maxNumAuthorityCertificates); 1549 // Check attributes and alias 1550 for (size_t i = 0; i < certs.size(); ++i) 1551 { 1552 std::string name = "root_" + std::to_string(i); 1553 EXPECT_EQ(certs[i]->subject(), "O=openbmc-project.xyz,CN=" + name); 1554 EXPECT_EQ(certs[i]->issuer(), "O=openbmc-project.xyz,CN=" + name); 1555 std::string symbolLink = 1556 authoritiesListFolder / 1557 (certs[i]->getCertId().substr(0, 8) + ".0"); 1558 ASSERT_TRUE(fs::exists(symbolLink)); 1559 compareFileAgainstString(symbolLink, certs[i]->certificateString()); 1560 } 1561 } 1562 1563 // Expects that the content of |path| file is |buffer|. 1564 static void compareFileAgainstString(const std::string& path, 1565 const std::string& buffer) 1566 { 1567 ASSERT_NO_THROW({ 1568 std::ifstream inputCertFileStream; 1569 inputCertFileStream.exceptions( 1570 std::ifstream::failbit | std::ifstream::badbit | 1571 std::ifstream::eofbit); 1572 inputCertFileStream.open(path); 1573 std::stringstream read; 1574 read << inputCertFileStream.rdbuf(); 1575 inputCertFileStream.close(); 1576 EXPECT_EQ(read.str(), buffer); 1577 }); 1578 }; 1579 1580 sdbusplus::bus_t bus; 1581 fs::path authoritiesListFolder; 1582 fs::path sourceAuthoritiesListFile; 1583 }; 1584 1585 // Tests that the Authority Manager installs all the certificates in an 1586 // authorities list 1587 TEST_F(AuthoritiesListTest, InstallAll) 1588 { 1589 std::string endpoint("truststore"); 1590 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1591 CertificateType type = CertificateType::authority; 1592 1593 std::string object = std::string(objectNamePrefix) + '/' + 1594 certificateTypeToString(type) + '/' + endpoint; 1595 auto event = sdeventplus::Event::get_default(); 1596 // Attach the bus to sd_event to service user requests 1597 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 1598 ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 1599 authoritiesListFolder); 1600 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 1601 .WillOnce(Return()); 1602 ASSERT_TRUE(manager.getCertificates().empty()); 1603 1604 std::vector<sdbusplus::message::object_path> objects = 1605 manager.installAll(sourceAuthoritiesListFile); 1606 for (size_t i = 0; i < manager.getCertificates().size(); ++i) 1607 { 1608 EXPECT_EQ(manager.getCertificates()[i]->getObjectPath(), objects[i]); 1609 } 1610 verifyCertificates(manager.getCertificates()); 1611 } 1612 1613 // Tests that the Authority Manager recovers from the authorities list persisted 1614 // in the installation path at boot up 1615 TEST_F(AuthoritiesListTest, RecoverAtBootUp) 1616 { 1617 std::string endpoint("truststore"); 1618 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1619 CertificateType type = CertificateType::authority; 1620 1621 std::string object = std::string(objectNamePrefix) + '/' + 1622 certificateTypeToString(type) + '/' + endpoint; 1623 auto event = sdeventplus::Event::get_default(); 1624 // Attach the bus to sd_event to service user requests 1625 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 1626 1627 // Copy the trust bundle into the installation path before creating an 1628 // Authority Manager 1629 fs::copy_file(/*from=*/sourceAuthoritiesListFile, 1630 authoritiesListFolder / defaultAuthoritiesListFileName); 1631 // Create some noise as well 1632 fs::copy_file(/*from=*/sourceAuthoritiesListFile, 1633 authoritiesListFolder / "should_be_deleted"); 1634 1635 ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 1636 authoritiesListFolder); 1637 1638 ASSERT_EQ(manager.getCertificates().size(), maxNumAuthorityCertificates); 1639 1640 // Check attributes and alias 1641 std::unordered_set<std::string> expectedFiles = { 1642 authoritiesListFolder / "trust_bundle"}; 1643 std::vector<std::unique_ptr<Certificate>>& certs = 1644 manager.getCertificates(); 1645 for (size_t i = 0; i < certs.size(); ++i) 1646 { 1647 std::string name = "root_" + std::to_string(i); 1648 EXPECT_EQ(certs[i]->subject(), "O=openbmc-project.xyz,CN=" + name); 1649 EXPECT_EQ(certs[i]->issuer(), "O=openbmc-project.xyz,CN=" + name); 1650 std::string symbolLink = 1651 authoritiesListFolder / (certs[i]->getCertId().substr(0, 8) + ".0"); 1652 expectedFiles.insert(symbolLink); 1653 expectedFiles.insert(certs[i]->getCertFilePath()); 1654 ASSERT_TRUE(fs::exists(symbolLink)); 1655 compareFileAgainstString(symbolLink, certs[i]->certificateString()); 1656 } 1657 1658 // Check folder content 1659 for (auto& path : fs::directory_iterator(authoritiesListFolder)) 1660 { 1661 EXPECT_NE(path, authoritiesListFolder / "should_be_deleted"); 1662 expectedFiles.erase(path.path()); 1663 } 1664 EXPECT_TRUE(expectedFiles.empty()); 1665 } 1666 1667 TEST_F(AuthoritiesListTest, InstallAndDelete) 1668 { 1669 std::string endpoint("truststore"); 1670 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1671 CertificateType type = CertificateType::authority; 1672 1673 std::string object = std::string(objectNamePrefix) + '/' + 1674 certificateTypeToString(type) + '/' + endpoint; 1675 1676 auto event = sdeventplus::Event::get_default(); 1677 // Attach the bus to sd_event to service user requests 1678 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 1679 ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 1680 authoritiesListFolder); 1681 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 1682 .WillOnce(Return()) 1683 .WillOnce(Return()); 1684 ASSERT_TRUE(manager.getCertificates().empty()); 1685 ASSERT_EQ(manager.installAll(sourceAuthoritiesListFile).size(), 1686 maxNumAuthorityCertificates); 1687 manager.deleteAll(); 1688 EXPECT_TRUE(manager.getCertificates().empty()); 1689 // Check folder content 1690 for (const fs::path& f : fs::directory_iterator(authoritiesListFolder)) 1691 { 1692 EXPECT_THAT(f.filename(), testing::AnyOf(".", "..")); 1693 } 1694 } 1695 1696 TEST_F(AuthoritiesListTest, InstallAllWrongManagerType) 1697 { 1698 std::string endpoint("ldap"); 1699 CertificateType type = CertificateType::server; 1700 1701 std::string object = std::string(objectNamePrefix) + '/' + 1702 certificateTypeToString(type) + '/' + endpoint; 1703 1704 auto event = sdeventplus::Event::get_default(); 1705 // Attach the bus to sd_event to service user requests 1706 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 1707 ManagerInTest serverManager(bus, event, object.c_str(), type, "", 1708 authoritiesListFolder); 1709 EXPECT_THROW(serverManager.installAll(sourceAuthoritiesListFile), 1710 sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed); 1711 1712 type = CertificateType::client; 1713 object = std::string(objectNamePrefix) + '/' + 1714 certificateTypeToString(type) + '/' + endpoint; 1715 ManagerInTest clientManager(bus, event, object.c_str(), type, "", 1716 authoritiesListFolder); 1717 EXPECT_THROW(clientManager.installAll(sourceAuthoritiesListFile), 1718 sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed); 1719 } 1720 1721 TEST_F(AuthoritiesListTest, InstallAllTwice) 1722 { 1723 std::string endpoint("truststore"); 1724 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1725 CertificateType type = CertificateType::authority; 1726 1727 std::string object = std::string(objectNamePrefix) + '/' + 1728 certificateTypeToString(type) + '/' + endpoint; 1729 1730 auto event = sdeventplus::Event::get_default(); 1731 // Attach the bus to sd_event to service user requests 1732 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 1733 ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 1734 authoritiesListFolder); 1735 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 1736 .WillOnce(Return()); 1737 ASSERT_TRUE(manager.getCertificates().empty()); 1738 1739 ASSERT_EQ(manager.installAll(sourceAuthoritiesListFile).size(), 1740 maxNumAuthorityCertificates); 1741 EXPECT_THROW(manager.installAll(sourceAuthoritiesListFile), 1742 sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed); 1743 } 1744 1745 TEST_F(AuthoritiesListTest, InstallAllMissSourceFile) 1746 { 1747 std::string endpoint("truststore"); 1748 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1749 CertificateType type = CertificateType::authority; 1750 1751 std::string object = std::string(objectNamePrefix) + '/' + 1752 certificateTypeToString(type) + '/' + endpoint; 1753 1754 auto event = sdeventplus::Event::get_default(); 1755 // Attach the bus to sd_event to service user requests 1756 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 1757 ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 1758 authoritiesListFolder); 1759 1760 EXPECT_THROW(manager.installAll(authoritiesListFolder / "trust_bundle"), 1761 InternalFailure); 1762 } 1763 1764 TEST_F(AuthoritiesListTest, TooManyRootCertificates) 1765 { 1766 std::string endpoint("truststore"); 1767 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1768 CertificateType type = CertificateType::authority; 1769 1770 std::string object = std::string(objectNamePrefix) + '/' + 1771 certificateTypeToString(type) + '/' + endpoint; 1772 1773 auto event = sdeventplus::Event::get_default(); 1774 // Attach the bus to sd_event to service user requests 1775 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 1776 ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 1777 authoritiesListFolder); 1778 createAuthoritiesList(maxNumAuthorityCertificates + 1); 1779 EXPECT_THROW(manager.installAll(sourceAuthoritiesListFile), 1780 sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed); 1781 } 1782 1783 TEST_F(AuthoritiesListTest, CertInWrongFormat) 1784 { 1785 std::string endpoint("truststore"); 1786 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1787 CertificateType type = CertificateType::authority; 1788 1789 std::string object = std::string(objectNamePrefix) + '/' + 1790 certificateTypeToString(type) + '/' + endpoint; 1791 1792 auto event = sdeventplus::Event::get_default(); 1793 // Attach the bus to sd_event to service user requests 1794 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 1795 1796 ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 1797 authoritiesListFolder); 1798 1799 // Replace the authorities list with non-valid PEM encoded x509 certificate 1800 setContentFromString(sourceAuthoritiesListFile, "blah-blah"); 1801 EXPECT_THROW(manager.installAll(sourceAuthoritiesListFile), 1802 InvalidCertificate); 1803 setContentFromString(sourceAuthoritiesListFile, 1804 "-----BEGIN CERTIFICATE-----"); 1805 EXPECT_THROW(manager.installAll(sourceAuthoritiesListFile), 1806 InvalidCertificate); 1807 } 1808 1809 TEST_F(AuthoritiesListTest, ReplaceAll) 1810 { 1811 std::string endpoint("truststore"); 1812 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1813 CertificateType type = CertificateType::authority; 1814 1815 std::string object = std::string(objectNamePrefix) + '/' + 1816 certificateTypeToString(type) + '/' + endpoint; 1817 1818 auto event = sdeventplus::Event::get_default(); 1819 // Attach the bus to sd_event to service user requests 1820 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 1821 ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 1822 authoritiesListFolder); 1823 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 1824 .WillOnce(Return()) 1825 .WillOnce(Return()); 1826 manager.installAll(sourceAuthoritiesListFile); 1827 1828 // Replace the current list with a different list 1829 fs::remove_all(sourceAuthoritiesListFile.parent_path()); 1830 createAuthoritiesList(maxNumAuthorityCertificates); 1831 std::vector<sdbusplus::message::object_path> objects = 1832 manager.replaceAll(sourceAuthoritiesListFile); 1833 1834 for (size_t i = 0; i < manager.getCertificates().size(); ++i) 1835 { 1836 EXPECT_EQ(manager.getCertificates()[i]->getObjectPath(), objects[i]); 1837 } 1838 verifyCertificates(manager.getCertificates()); 1839 } 1840 1841 } // namespace 1842 } // namespace phosphor::certs 1843