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 verifyPath(installPath); 1002 std::string csrPath(certDir + "/" + CSRFile); 1003 std::string privateKeyPath(certDir + "/" + privateKeyFile); 1004 std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 1005 std::string challengePassword("Password"); 1006 std::string city("HYB"); 1007 std::string commonName("abc.com"); 1008 std::string contactPerson("Admin"); 1009 std::string country("IN"); 1010 std::string email("admin@in.ibm.com"); 1011 std::string givenName("givenName"); 1012 std::string initials("G"); 1013 int64_t keyBitLength(2048); 1014 std::string keyCurveId("0"); 1015 std::string keyPairAlgorithm("RSA"); 1016 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 1017 std::string organization("IBM"); 1018 std::string organizationalUnit("orgUnit"); 1019 std::string state("TS"); 1020 std::string surname("surname"); 1021 std::string unstructuredName("unstructuredName"); 1022 auto objPath = std::string(objectNamePrefix) + '/' + 1023 certificateTypeToString(type) + '/' + endpoint; 1024 auto event = sdeventplus::Event::get_default(); 1025 // Attach the bus to sd_event to service user requests 1026 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 1027 Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1028 std::move(installPath)); 1029 Status status = Status::success; 1030 CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1031 MainApp mainApp(&manager, &csr); 1032 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1033 contactPerson, country, email, givenName, initials, 1034 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1035 organization, organizationalUnit, state, surname, 1036 unstructuredName); 1037 std::string csrData{}; 1038 // generateCSR takes considerable time to create CSR and privateKey Files 1039 EXPECT_FALSE(fs::exists(csrPath)); 1040 EXPECT_FALSE(fs::exists(privateKeyPath)); 1041 EXPECT_THROW( 1042 { 1043 try 1044 { 1045 csrData = csr.csr(); 1046 } 1047 catch (const InternalFailure& e) 1048 { 1049 throw; 1050 } 1051 }, 1052 InternalFailure); 1053 // wait for 10 sec to get CSR and privateKey Files generated 1054 sleep(10); 1055 EXPECT_TRUE(fs::exists(csrPath)); 1056 EXPECT_TRUE(fs::exists(privateKeyPath)); 1057 csrData = csr.csr(); 1058 ASSERT_NE("", csrData.c_str()); 1059 } 1060 1061 /** @brief Check if ECC key pair is generated when user is not given algorithm 1062 * type. At present RSA and EC key pair algorithm are supported 1063 */ 1064 TEST_F(TestCertificates, TestGenerateCSRwithEmptyKeyPairAlgorithm) 1065 { 1066 std::string endpoint("https"); 1067 std::string unit; 1068 CertificateType type = CertificateType::server; 1069 std::string installPath(certDir + "/" + certificateFile); 1070 std::string verifyPath(installPath); 1071 std::string csrPath(certDir + "/" + CSRFile); 1072 std::string privateKeyPath(certDir + "/" + privateKeyFile); 1073 std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 1074 std::string challengePassword("Password"); 1075 std::string city("HYB"); 1076 std::string commonName("abc.com"); 1077 std::string contactPerson("Admin"); 1078 std::string country("IN"); 1079 std::string email("admin@in.ibm.com"); 1080 std::string givenName("givenName"); 1081 std::string initials("G"); 1082 int64_t keyBitLength(2048); 1083 std::string keyCurveId(""); 1084 std::string keyPairAlgorithm(""); 1085 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 1086 std::string organization("IBM"); 1087 std::string organizationalUnit("orgUnit"); 1088 std::string state("TS"); 1089 std::string surname("surname"); 1090 std::string unstructuredName("unstructuredName"); 1091 auto objPath = std::string(objectNamePrefix) + '/' + 1092 certificateTypeToString(type) + '/' + endpoint; 1093 auto event = sdeventplus::Event::get_default(); 1094 Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1095 std::move(installPath)); 1096 Status status; 1097 CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1098 MainApp mainApp(&manager, &csr); 1099 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1100 contactPerson, country, email, givenName, initials, 1101 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1102 organization, organizationalUnit, state, surname, 1103 unstructuredName); 1104 sleep(10); 1105 EXPECT_TRUE(fs::exists(csrPath)); 1106 EXPECT_TRUE(fs::exists(privateKeyPath)); 1107 } 1108 1109 /** @brief Check if error is thrown when giving un supported key pair 1110 * algorithm. At present RSA and EC key pair algorithm are supported 1111 */ 1112 TEST_F(TestCertificates, TestGenerateCSRwithUnsupportedKeyPairAlgorithm) 1113 { 1114 std::string endpoint("https"); 1115 std::string unit; 1116 CertificateType type = CertificateType::server; 1117 std::string installPath(certDir + "/" + certificateFile); 1118 std::string verifyPath(installPath); 1119 std::string csrPath(certDir + "/" + CSRFile); 1120 std::string privateKeyPath(certDir + "/" + privateKeyFile); 1121 std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 1122 std::string challengePassword("Password"); 1123 std::string city("HYB"); 1124 std::string commonName("abc.com"); 1125 std::string contactPerson("Admin"); 1126 std::string country("IN"); 1127 std::string email("admin@in.ibm.com"); 1128 std::string givenName("givenName"); 1129 std::string initials("G"); 1130 int64_t keyBitLength(2048); 1131 std::string keyCurveId("secp521r1"); 1132 std::string keyPairAlgorithm("UnSupportedAlgorithm"); 1133 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 1134 std::string organization("IBM"); 1135 std::string organizationalUnit("orgUnit"); 1136 std::string state("TS"); 1137 std::string surname("surname"); 1138 std::string unstructuredName("unstructuredName"); 1139 auto objPath = std::string(objectNamePrefix) + '/' + 1140 certificateTypeToString(type) + '/' + endpoint; 1141 auto event = sdeventplus::Event::get_default(); 1142 Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1143 std::move(installPath)); 1144 Status status; 1145 CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1146 MainApp mainApp(&manager, &csr); 1147 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1148 contactPerson, country, email, givenName, initials, 1149 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1150 organization, organizationalUnit, state, surname, 1151 unstructuredName); 1152 EXPECT_FALSE(fs::exists(csrPath)); 1153 EXPECT_FALSE(fs::exists(privateKeyPath)); 1154 } 1155 1156 /** @brief Check if error is thrown when NID_undef is returned for given key 1157 * curve id 1158 */ 1159 TEST_F(TestCertificates, TestECKeyGenerationwithNIDundefCase) 1160 { 1161 std::string endpoint("https"); 1162 std::string unit; 1163 CertificateType type = CertificateType::server; 1164 std::string installPath(certDir + "/" + certificateFile); 1165 std::string verifyPath(installPath); 1166 std::string csrPath(certDir + "/" + CSRFile); 1167 std::string privateKeyPath(certDir + "/" + privateKeyFile); 1168 std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 1169 std::string challengePassword("Password"); 1170 std::string city("BLR"); 1171 std::string commonName("abc.com"); 1172 std::string contactPerson("Admin"); 1173 std::string country("IN"); 1174 std::string email("admin@in.ibm.com"); 1175 std::string givenName("givenName"); 1176 std::string initials("G"); 1177 int64_t keyBitLength(2048); 1178 std::string keyCurveId("DummyCurveName"); 1179 std::string keyPairAlgorithm("EC"); 1180 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 1181 std::string organization("IBM"); 1182 std::string organizationalUnit("orgUnit"); 1183 std::string state("TS"); 1184 std::string surname("surname"); 1185 std::string unstructuredName("unstructuredName"); 1186 auto objPath = std::string(objectNamePrefix) + '/' + 1187 certificateTypeToString(type) + '/' + endpoint; 1188 auto event = sdeventplus::Event::get_default(); 1189 Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1190 std::move(installPath)); 1191 Status status; 1192 CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1193 MainApp mainApp(&manager, &csr); 1194 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1195 contactPerson, country, email, givenName, initials, 1196 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1197 organization, organizationalUnit, state, surname, 1198 unstructuredName); 1199 EXPECT_FALSE(fs::exists(csrPath)); 1200 EXPECT_FALSE(fs::exists(privateKeyPath)); 1201 } 1202 1203 /** @brief Check default Key Curve Id is used if given curve id is empty 1204 */ 1205 TEST_F(TestCertificates, TestECKeyGenerationwithDefaultKeyCurveId) 1206 { 1207 std::string endpoint("https"); 1208 std::string unit; 1209 CertificateType type = CertificateType::server; 1210 std::string installPath(certDir + "/" + certificateFile); 1211 std::string verifyPath(installPath); 1212 std::string csrPath(certDir + "/" + CSRFile); 1213 std::string privateKeyPath(certDir + "/" + privateKeyFile); 1214 std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 1215 std::string challengePassword("Password"); 1216 std::string city("BLR"); 1217 std::string commonName("abc.com"); 1218 std::string contactPerson("Admin"); 1219 std::string country("IN"); 1220 std::string email("admin@in.ibm.com"); 1221 std::string givenName("givenName"); 1222 std::string initials("G"); 1223 int64_t keyBitLength(2048); 1224 std::string keyCurveId(""); 1225 std::string keyPairAlgorithm("EC"); 1226 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 1227 std::string organization("IBM"); 1228 std::string organizationalUnit("orgUnit"); 1229 std::string state("TS"); 1230 std::string surname("surname"); 1231 std::string unstructuredName("unstructuredName"); 1232 auto objPath = std::string(objectNamePrefix) + '/' + 1233 certificateTypeToString(type) + '/' + endpoint; 1234 auto event = sdeventplus::Event::get_default(); 1235 Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1236 std::move(installPath)); 1237 Status status; 1238 CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1239 MainApp mainApp(&manager, &csr); 1240 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1241 contactPerson, country, email, givenName, initials, 1242 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1243 organization, organizationalUnit, state, surname, 1244 unstructuredName); 1245 sleep(10); 1246 EXPECT_TRUE(fs::exists(csrPath)); 1247 EXPECT_TRUE(fs::exists(privateKeyPath)); 1248 } 1249 1250 /** @brief Check if error is not thrown to generate EC key pair 1251 */ 1252 TEST_F(TestCertificates, TestECKeyGeneration) 1253 { 1254 std::string endpoint("https"); 1255 std::string unit; 1256 CertificateType type = CertificateType::server; 1257 std::string installPath(certDir + "/" + certificateFile); 1258 std::string verifyPath(installPath); 1259 std::string csrPath(certDir + "/" + CSRFile); 1260 std::string privateKeyPath(certDir + "/" + privateKeyFile); 1261 std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 1262 std::string challengePassword("Password"); 1263 std::string city("BLR"); 1264 std::string commonName("abc.com"); 1265 std::string contactPerson("Admin"); 1266 std::string country("IN"); 1267 std::string email("admin@in.ibm.com"); 1268 std::string givenName("givenName"); 1269 std::string initials("G"); 1270 int64_t keyBitLength(2048); 1271 std::string keyCurveId("secp521r1"); 1272 std::string keyPairAlgorithm("EC"); 1273 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 1274 std::string organization("IBM"); 1275 std::string organizationalUnit("orgUnit"); 1276 std::string state("TS"); 1277 std::string surname("surname"); 1278 std::string unstructuredName("unstructuredName"); 1279 auto objPath = std::string(objectNamePrefix) + '/' + 1280 certificateTypeToString(type) + '/' + endpoint; 1281 auto event = sdeventplus::Event::get_default(); 1282 Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1283 std::move(installPath)); 1284 Status status = Status::success; 1285 CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1286 MainApp mainApp(&manager, &csr); 1287 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1288 contactPerson, country, email, givenName, initials, 1289 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1290 organization, organizationalUnit, state, surname, 1291 unstructuredName); 1292 std::cout << "CSRPath: " << csrPath << std::endl 1293 << "privateKeyPath: " << privateKeyPath << std::endl; 1294 sleep(10); 1295 EXPECT_TRUE(fs::exists(csrPath)); 1296 EXPECT_TRUE(fs::exists(privateKeyPath)); 1297 } 1298 1299 /** @brief Check error is thrown if giving unsupported key bit length to 1300 * generate rsa key 1301 */ 1302 TEST_F(TestCertificates, TestRSAKeyWithUnsupportedKeyBitLength) 1303 { 1304 std::string endpoint("https"); 1305 std::string unit; 1306 CertificateType type = CertificateType::server; 1307 std::string installPath(certDir + "/" + certificateFile); 1308 std::string verifyPath(installPath); 1309 std::string csrPath(certDir + "/" + CSRFile); 1310 std::string privateKeyPath(certDir + "/" + privateKeyFile); 1311 std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 1312 std::string challengePassword("Password"); 1313 std::string city("BLR"); 1314 std::string commonName("abc.com"); 1315 std::string contactPerson("Admin"); 1316 std::string country("IN"); 1317 std::string email("admin@in.ibm.com"); 1318 std::string givenName("givenName"); 1319 std::string initials("G"); 1320 int64_t keyBitLength(4096); 1321 std::string keyCurveId("secp521r1"); 1322 std::string keyPairAlgorithm("RSA"); 1323 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 1324 std::string organization("IBM"); 1325 std::string organizationalUnit("orgUnit"); 1326 std::string state("TS"); 1327 std::string surname("surname"); 1328 std::string unstructuredName("unstructuredName"); 1329 auto objPath = std::string(objectNamePrefix) + '/' + 1330 certificateTypeToString(type) + '/' + endpoint; 1331 auto event = sdeventplus::Event::get_default(); 1332 Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1333 std::move(installPath)); 1334 Status status; 1335 CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1336 MainApp mainApp(&manager, &csr); 1337 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1338 contactPerson, country, email, givenName, initials, 1339 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1340 organization, organizationalUnit, state, surname, 1341 unstructuredName); 1342 EXPECT_FALSE(fs::exists(csrPath)); 1343 EXPECT_FALSE(fs::exists(privateKeyPath)); 1344 } 1345 1346 /** @brief Check error is thrown if generated rsa key file is not present 1347 */ 1348 TEST_F(TestCertificates, TestRSAKeyFileNotPresentCase) 1349 { 1350 std::string endpoint("https"); 1351 std::string unit; 1352 CertificateType type = CertificateType::server; 1353 std::string installPath(certDir + "/" + certificateFile); 1354 std::string verifyPath(installPath); 1355 std::string csrPath(certDir + "/" + CSRFile); 1356 std::string privateKeyPath(certDir + "/" + privateKeyFile); 1357 std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 1358 std::string challengePassword("Password"); 1359 std::string city("BLR"); 1360 std::string commonName("abc.com"); 1361 std::string contactPerson("Admin"); 1362 std::string country("IN"); 1363 std::string email("admin@in.ibm.com"); 1364 std::string givenName("givenName"); 1365 std::string initials("G"); 1366 int64_t keyBitLength(2048); 1367 std::string keyCurveId("secp521r1"); 1368 std::string keyPairAlgorithm("RSA"); 1369 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 1370 std::string organization("IBM"); 1371 std::string organizationalUnit("orgUnit"); 1372 std::string state("TS"); 1373 std::string surname("surname"); 1374 std::string unstructuredName("unstructuredName"); 1375 auto objPath = std::string(objectNamePrefix) + '/' + 1376 certificateTypeToString(type) + '/' + endpoint; 1377 auto event = sdeventplus::Event::get_default(); 1378 Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1379 std::move(installPath)); 1380 1381 // Removing generated RSA key file 1382 fs::remove(rsaPrivateKeyFilePath); 1383 1384 Status status; 1385 CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1386 MainApp mainApp(&manager, &csr); 1387 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1388 contactPerson, country, email, givenName, initials, 1389 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1390 organization, organizationalUnit, state, surname, 1391 unstructuredName); 1392 EXPECT_FALSE(fs::exists(csrPath)); 1393 EXPECT_FALSE(fs::exists(privateKeyPath)); 1394 } 1395 1396 /** @brief Check private key file is created from generated rsa key file is 1397 * `present 1398 */ 1399 TEST_F(TestCertificates, TestRSAKeyFromRSAKeyFileIsWrittenIntoPrivateKeyFile) 1400 { 1401 std::string endpoint("https"); 1402 std::string unit; 1403 CertificateType type = CertificateType::server; 1404 std::string installPath(certDir + "/" + certificateFile); 1405 std::string verifyPath(installPath); 1406 std::string csrPath(certDir + "/" + CSRFile); 1407 std::string privateKeyPath(certDir + "/" + privateKeyFile); 1408 std::vector<std::string> alternativeNames{"localhost1", "localhost2"}; 1409 std::string challengePassword("Password"); 1410 std::string city("BLR"); 1411 std::string commonName("abc.com"); 1412 std::string contactPerson("Admin"); 1413 std::string country("IN"); 1414 std::string email("admin@in.ibm.com"); 1415 std::string givenName("givenName"); 1416 std::string initials("G"); 1417 int64_t keyBitLength(2048); 1418 std::string keyCurveId("secp521r1"); 1419 std::string keyPairAlgorithm("RSA"); 1420 std::vector<std::string> keyUsage{"serverAuth", "clientAuth"}; 1421 std::string organization("IBM"); 1422 std::string organizationalUnit("orgUnit"); 1423 std::string state("TS"); 1424 std::string surname("surname"); 1425 std::string unstructuredName("unstructuredName"); 1426 auto objPath = std::string(objectNamePrefix) + '/' + 1427 certificateTypeToString(type) + '/' + endpoint; 1428 auto event = sdeventplus::Event::get_default(); 1429 Manager manager(bus, event, objPath.c_str(), type, std::move(unit), 1430 std::move(installPath)); 1431 Status status; 1432 CSR csr(bus, objPath.c_str(), csrPath.c_str(), status); 1433 MainApp mainApp(&manager, &csr); 1434 mainApp.generateCSR(alternativeNames, challengePassword, city, commonName, 1435 contactPerson, country, email, givenName, initials, 1436 keyBitLength, keyCurveId, keyPairAlgorithm, keyUsage, 1437 organization, organizationalUnit, state, surname, 1438 unstructuredName); 1439 sleep(10); 1440 EXPECT_TRUE(fs::exists(csrPath)); 1441 EXPECT_TRUE(fs::exists(privateKeyPath)); 1442 } 1443 1444 /** @brief Check RSA key is generated during application startup*/ 1445 TEST_F(TestCertificates, TestGenerateRSAPrivateKeyFile) 1446 { 1447 std::string endpoint("https"); 1448 CertificateType type = CertificateType::server; 1449 std::string installPath(certDir + "/" + certificateFile); 1450 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1451 auto objPath = std::string(objectNamePrefix) + '/' + 1452 certificateTypeToString(type) + '/' + endpoint; 1453 auto event = sdeventplus::Event::get_default(); 1454 1455 EXPECT_FALSE(fs::exists(rsaPrivateKeyFilePath)); 1456 Manager manager(bus, event, objPath.c_str(), type, verifyUnit, installPath); 1457 EXPECT_TRUE(fs::exists(rsaPrivateKeyFilePath)); 1458 } 1459 1460 /** 1461 * Class to test Authorities List installation and replacement 1462 */ 1463 class AuthoritiesListTest : public testing::Test 1464 { 1465 public: 1466 AuthoritiesListTest() : 1467 bus(sdbusplus::bus::new_default()), 1468 authoritiesListFolder( 1469 Certificate::generateUniqueFilePath(fs::temp_directory_path())) 1470 { 1471 fs::create_directory(authoritiesListFolder); 1472 createAuthoritiesList(maxNumAuthorityCertificates); 1473 } 1474 ~AuthoritiesListTest() override 1475 { 1476 fs::remove_all(authoritiesListFolder); 1477 } 1478 1479 protected: 1480 // Creates a testing authorities list which consists of |count| root 1481 // certificates 1482 void createAuthoritiesList(int count) 1483 { 1484 fs::path srcFolder = fs::temp_directory_path(); 1485 srcFolder = Certificate::generateUniqueFilePath(srcFolder); 1486 fs::create_directory(srcFolder); 1487 createSingleAuthority(srcFolder, "root_0"); 1488 sourceAuthoritiesListFile = srcFolder / "root_0_cert"; 1489 for (int i = 1; i < count; ++i) 1490 { 1491 std::string name = "root_" + std::to_string(i); 1492 createSingleAuthority(srcFolder, name); 1493 appendContentFromFile(sourceAuthoritiesListFile, 1494 srcFolder / (name + "_cert")); 1495 } 1496 } 1497 1498 // Creates a single self-signed root certificate in given |path|; the key 1499 // will be |path|/|cn|_key, the cert will be |path|/|cn|_cert, and the cn 1500 // will be "/O=openbmc-project.xyz/C=US/ST=CA/CN=|cn|" 1501 static void createSingleAuthority(const std::string& path, 1502 const std::string& cn) 1503 { 1504 std::string key = fs::path(path) / (cn + "_key"); 1505 std::string cert = fs::path(path) / (cn + "_cert"); 1506 std::string cmd = "openssl req -x509 -sha256 -newkey rsa:2048 -keyout "; 1507 cmd += key + " -out " + cert + " -nodes --days 365000 "; 1508 cmd += "-subj /O=openbmc-project.xyz/CN=" + cn; 1509 ASSERT_EQ(std::system(cmd.c_str()), 0); 1510 } 1511 1512 // Appends the content of the |from| file to the |to| file. 1513 static void appendContentFromFile(const std::string& to, 1514 const std::string& from) 1515 { 1516 ASSERT_NO_THROW({ 1517 std::ifstream inputCertFileStream; 1518 std::ofstream outputCertFileStream; 1519 inputCertFileStream.exceptions( 1520 std::ifstream::failbit | std::ifstream::badbit | 1521 std::ifstream::eofbit); 1522 outputCertFileStream.exceptions( 1523 std::ofstream::failbit | std::ofstream::badbit | 1524 std::ofstream::eofbit); 1525 inputCertFileStream.open(from); 1526 outputCertFileStream.open(to, std::ios::app); 1527 outputCertFileStream << inputCertFileStream.rdbuf() << std::flush; 1528 inputCertFileStream.close(); 1529 outputCertFileStream.close(); 1530 }); 1531 } 1532 1533 // Appends the content of the |from| buffer to the |to| file. 1534 static void setContentFromString(const std::string& to, 1535 const std::string& from) 1536 { 1537 ASSERT_NO_THROW({ 1538 std::ofstream outputCertFileStream; 1539 outputCertFileStream.exceptions( 1540 std::ofstream::failbit | std::ofstream::badbit | 1541 std::ofstream::eofbit); 1542 outputCertFileStream.open(to, std::ios::out); 1543 outputCertFileStream << from << std::flush; 1544 outputCertFileStream.close(); 1545 }); 1546 } 1547 1548 // Verifies the effect of InstallAll or ReplaceAll 1549 void verifyCertificates(std::vector<std::unique_ptr<Certificate>>& certs) 1550 { 1551 // The trust bundle file has been copied over 1552 EXPECT_FALSE(fs::is_empty(authoritiesListFolder)); 1553 EXPECT_TRUE( 1554 compareFiles(authoritiesListFolder / defaultAuthoritiesListFileName, 1555 sourceAuthoritiesListFile)); 1556 1557 ASSERT_EQ(certs.size(), maxNumAuthorityCertificates); 1558 // Check attributes and alias 1559 for (size_t i = 0; i < certs.size(); ++i) 1560 { 1561 std::string name = "root_" + std::to_string(i); 1562 EXPECT_EQ(certs[i]->subject(), "O=openbmc-project.xyz,CN=" + name); 1563 EXPECT_EQ(certs[i]->issuer(), "O=openbmc-project.xyz,CN=" + name); 1564 std::string symbolLink = 1565 authoritiesListFolder / 1566 (certs[i]->getCertId().substr(0, 8) + ".0"); 1567 ASSERT_TRUE(fs::exists(symbolLink)); 1568 compareFileAgainstString(symbolLink, certs[i]->certificateString()); 1569 } 1570 } 1571 1572 // Expects that the content of |path| file is |buffer|. 1573 static void compareFileAgainstString(const std::string& path, 1574 const std::string& buffer) 1575 { 1576 ASSERT_NO_THROW({ 1577 std::ifstream inputCertFileStream; 1578 inputCertFileStream.exceptions( 1579 std::ifstream::failbit | std::ifstream::badbit | 1580 std::ifstream::eofbit); 1581 inputCertFileStream.open(path); 1582 std::stringstream read; 1583 read << inputCertFileStream.rdbuf(); 1584 inputCertFileStream.close(); 1585 EXPECT_EQ(read.str(), buffer); 1586 }); 1587 }; 1588 1589 sdbusplus::bus_t bus; 1590 fs::path authoritiesListFolder; 1591 fs::path sourceAuthoritiesListFile; 1592 }; 1593 1594 // Tests that the Authority Manager installs all the certificates in an 1595 // authorities list 1596 TEST_F(AuthoritiesListTest, InstallAll) 1597 { 1598 std::string endpoint("truststore"); 1599 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1600 CertificateType type = CertificateType::authority; 1601 1602 std::string object = std::string(objectNamePrefix) + '/' + 1603 certificateTypeToString(type) + '/' + endpoint; 1604 auto event = sdeventplus::Event::get_default(); 1605 // Attach the bus to sd_event to service user requests 1606 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 1607 ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 1608 authoritiesListFolder); 1609 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 1610 .WillOnce(Return()); 1611 ASSERT_TRUE(manager.getCertificates().empty()); 1612 1613 std::vector<sdbusplus::message::object_path> objects = 1614 manager.installAll(sourceAuthoritiesListFile); 1615 for (size_t i = 0; i < manager.getCertificates().size(); ++i) 1616 { 1617 EXPECT_EQ(manager.getCertificates()[i]->getObjectPath(), objects[i]); 1618 } 1619 verifyCertificates(manager.getCertificates()); 1620 } 1621 1622 // Tests that the Authority Manager recovers from the authorities list persisted 1623 // in the installation path at boot up 1624 TEST_F(AuthoritiesListTest, RecoverAtBootUp) 1625 { 1626 std::string endpoint("truststore"); 1627 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1628 CertificateType type = CertificateType::authority; 1629 1630 std::string object = std::string(objectNamePrefix) + '/' + 1631 certificateTypeToString(type) + '/' + endpoint; 1632 auto event = sdeventplus::Event::get_default(); 1633 // Attach the bus to sd_event to service user requests 1634 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 1635 1636 // Copy the trust bundle into the installation path before creating an 1637 // Authority Manager 1638 fs::copy_file(/*from=*/sourceAuthoritiesListFile, 1639 authoritiesListFolder / defaultAuthoritiesListFileName); 1640 // Create some noise as well 1641 fs::copy_file(/*from=*/sourceAuthoritiesListFile, 1642 authoritiesListFolder / "should_be_deleted"); 1643 1644 ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 1645 authoritiesListFolder); 1646 1647 ASSERT_EQ(manager.getCertificates().size(), maxNumAuthorityCertificates); 1648 1649 // Check attributes and alias 1650 std::unordered_set<std::string> expectedFiles = { 1651 authoritiesListFolder / "trust_bundle"}; 1652 std::vector<std::unique_ptr<Certificate>>& certs = 1653 manager.getCertificates(); 1654 for (size_t i = 0; i < certs.size(); ++i) 1655 { 1656 std::string name = "root_" + std::to_string(i); 1657 EXPECT_EQ(certs[i]->subject(), "O=openbmc-project.xyz,CN=" + name); 1658 EXPECT_EQ(certs[i]->issuer(), "O=openbmc-project.xyz,CN=" + name); 1659 std::string symbolLink = 1660 authoritiesListFolder / (certs[i]->getCertId().substr(0, 8) + ".0"); 1661 expectedFiles.insert(symbolLink); 1662 expectedFiles.insert(certs[i]->getCertFilePath()); 1663 ASSERT_TRUE(fs::exists(symbolLink)); 1664 compareFileAgainstString(symbolLink, certs[i]->certificateString()); 1665 } 1666 1667 // Check folder content 1668 for (auto& path : fs::directory_iterator(authoritiesListFolder)) 1669 { 1670 EXPECT_NE(path, authoritiesListFolder / "should_be_deleted"); 1671 expectedFiles.erase(path.path()); 1672 } 1673 EXPECT_TRUE(expectedFiles.empty()); 1674 } 1675 1676 TEST_F(AuthoritiesListTest, InstallAndDelete) 1677 { 1678 std::string endpoint("truststore"); 1679 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1680 CertificateType type = CertificateType::authority; 1681 1682 std::string object = std::string(objectNamePrefix) + '/' + 1683 certificateTypeToString(type) + '/' + endpoint; 1684 1685 auto event = sdeventplus::Event::get_default(); 1686 // Attach the bus to sd_event to service user requests 1687 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 1688 ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 1689 authoritiesListFolder); 1690 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 1691 .WillOnce(Return()) 1692 .WillOnce(Return()); 1693 ASSERT_TRUE(manager.getCertificates().empty()); 1694 ASSERT_EQ(manager.installAll(sourceAuthoritiesListFile).size(), 1695 maxNumAuthorityCertificates); 1696 manager.deleteAll(); 1697 EXPECT_TRUE(manager.getCertificates().empty()); 1698 // Check folder content 1699 for (const fs::path& f : fs::directory_iterator(authoritiesListFolder)) 1700 { 1701 EXPECT_THAT(f.filename(), testing::AnyOf(".", "..")); 1702 } 1703 } 1704 1705 TEST_F(AuthoritiesListTest, InstallAllWrongManagerType) 1706 { 1707 std::string endpoint("ldap"); 1708 CertificateType type = CertificateType::server; 1709 1710 std::string object = std::string(objectNamePrefix) + '/' + 1711 certificateTypeToString(type) + '/' + endpoint; 1712 1713 auto event = sdeventplus::Event::get_default(); 1714 // Attach the bus to sd_event to service user requests 1715 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 1716 ManagerInTest serverManager(bus, event, object.c_str(), type, "", 1717 authoritiesListFolder); 1718 EXPECT_THROW(serverManager.installAll(sourceAuthoritiesListFile), 1719 sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed); 1720 1721 type = CertificateType::client; 1722 object = std::string(objectNamePrefix) + '/' + 1723 certificateTypeToString(type) + '/' + endpoint; 1724 ManagerInTest clientManager(bus, event, object.c_str(), type, "", 1725 authoritiesListFolder); 1726 EXPECT_THROW(clientManager.installAll(sourceAuthoritiesListFile), 1727 sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed); 1728 } 1729 1730 TEST_F(AuthoritiesListTest, InstallAllTwice) 1731 { 1732 std::string endpoint("truststore"); 1733 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1734 CertificateType type = CertificateType::authority; 1735 1736 std::string object = std::string(objectNamePrefix) + '/' + 1737 certificateTypeToString(type) + '/' + endpoint; 1738 1739 auto event = sdeventplus::Event::get_default(); 1740 // Attach the bus to sd_event to service user requests 1741 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 1742 ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 1743 authoritiesListFolder); 1744 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 1745 .WillOnce(Return()); 1746 ASSERT_TRUE(manager.getCertificates().empty()); 1747 1748 ASSERT_EQ(manager.installAll(sourceAuthoritiesListFile).size(), 1749 maxNumAuthorityCertificates); 1750 EXPECT_THROW(manager.installAll(sourceAuthoritiesListFile), 1751 sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed); 1752 } 1753 1754 TEST_F(AuthoritiesListTest, InstallAllMissSourceFile) 1755 { 1756 std::string endpoint("truststore"); 1757 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1758 CertificateType type = CertificateType::authority; 1759 1760 std::string object = std::string(objectNamePrefix) + '/' + 1761 certificateTypeToString(type) + '/' + endpoint; 1762 1763 auto event = sdeventplus::Event::get_default(); 1764 // Attach the bus to sd_event to service user requests 1765 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 1766 ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 1767 authoritiesListFolder); 1768 1769 EXPECT_THROW(manager.installAll(authoritiesListFolder / "trust_bundle"), 1770 InternalFailure); 1771 } 1772 1773 TEST_F(AuthoritiesListTest, TooManyRootCertificates) 1774 { 1775 std::string endpoint("truststore"); 1776 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1777 CertificateType type = CertificateType::authority; 1778 1779 std::string object = std::string(objectNamePrefix) + '/' + 1780 certificateTypeToString(type) + '/' + endpoint; 1781 1782 auto event = sdeventplus::Event::get_default(); 1783 // Attach the bus to sd_event to service user requests 1784 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 1785 ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 1786 authoritiesListFolder); 1787 createAuthoritiesList(maxNumAuthorityCertificates + 1); 1788 EXPECT_THROW(manager.installAll(sourceAuthoritiesListFile), 1789 sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed); 1790 } 1791 1792 TEST_F(AuthoritiesListTest, CertInWrongFormat) 1793 { 1794 std::string endpoint("truststore"); 1795 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1796 CertificateType type = CertificateType::authority; 1797 1798 std::string object = std::string(objectNamePrefix) + '/' + 1799 certificateTypeToString(type) + '/' + endpoint; 1800 1801 auto event = sdeventplus::Event::get_default(); 1802 // Attach the bus to sd_event to service user requests 1803 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 1804 1805 ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 1806 authoritiesListFolder); 1807 1808 // Replace the authorities list with non-valid PEM encoded x509 certificate 1809 setContentFromString(sourceAuthoritiesListFile, "blah-blah"); 1810 EXPECT_THROW(manager.installAll(sourceAuthoritiesListFile), 1811 InvalidCertificate); 1812 setContentFromString(sourceAuthoritiesListFile, 1813 "-----BEGIN CERTIFICATE-----"); 1814 EXPECT_THROW(manager.installAll(sourceAuthoritiesListFile), 1815 InvalidCertificate); 1816 } 1817 1818 TEST_F(AuthoritiesListTest, ReplaceAll) 1819 { 1820 std::string endpoint("truststore"); 1821 std::string verifyUnit(ManagerInTest::unitToRestartInTest); 1822 CertificateType type = CertificateType::authority; 1823 1824 std::string object = std::string(objectNamePrefix) + '/' + 1825 certificateTypeToString(type) + '/' + endpoint; 1826 1827 auto event = sdeventplus::Event::get_default(); 1828 // Attach the bus to sd_event to service user requests 1829 bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); 1830 ManagerInTest manager(bus, event, object.c_str(), type, verifyUnit, 1831 authoritiesListFolder); 1832 EXPECT_CALL(manager, reloadOrReset(Eq(ManagerInTest::unitToRestartInTest))) 1833 .WillOnce(Return()) 1834 .WillOnce(Return()); 1835 manager.installAll(sourceAuthoritiesListFile); 1836 1837 // Replace the current list with a different list 1838 fs::remove_all(sourceAuthoritiesListFile.parent_path()); 1839 createAuthoritiesList(maxNumAuthorityCertificates); 1840 std::vector<sdbusplus::message::object_path> objects = 1841 manager.replaceAll(sourceAuthoritiesListFile); 1842 1843 for (size_t i = 0; i < manager.getCertificates().size(); ++i) 1844 { 1845 EXPECT_EQ(manager.getCertificates()[i]->getObjectPath(), objects[i]); 1846 } 1847 verifyCertificates(manager.getCertificates()); 1848 } 1849 1850 } // namespace 1851 } // namespace phosphor::certs 1852