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