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