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