blob: 831928f6d7c458ae04968fdeac6a7daf6852c1bc [file] [log] [blame]
Nan Zhou014be0b2021-12-28 18:00:14 -08001#include "config.h"
2
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -05003#include "certs_manager.hpp"
4
Nan Zhou014be0b2021-12-28 18:00:14 -08005#include <openssl/asn1.h>
6#include <openssl/bn.h>
7#include <openssl/ec.h>
Patrick Williams26fb83e2021-12-14 14:08:28 -06008#include <openssl/evp.h>
Nan Zhou014be0b2021-12-28 18:00:14 -08009#include <openssl/obj_mac.h>
10#include <openssl/objects.h>
11#include <openssl/opensslv.h>
Marri Devender Raof4682712019-03-19 05:00:28 -050012#include <openssl/pem.h>
Nan Zhou014be0b2021-12-28 18:00:14 -080013#include <openssl/rsa.h>
Marri Devender Raof4682712019-03-19 05:00:28 -050014#include <unistd.h>
15
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +020016#include <algorithm>
Nan Zhou014be0b2021-12-28 18:00:14 -080017#include <array>
18#include <cerrno>
19#include <chrono>
20#include <csignal>
21#include <cstdio>
22#include <cstdlib>
23#include <cstring>
24#include <exception>
Marri Devender Rao6ceec402019-02-01 03:15:19 -060025#include <phosphor-logging/elog-errors.hpp>
Nan Zhou014be0b2021-12-28 18:00:14 -080026#include <phosphor-logging/elog.hpp>
27#include <phosphor-logging/log.hpp>
28#include <sdbusplus/bus.hpp>
29#include <sdbusplus/exception.hpp>
30#include <sdbusplus/message.hpp>
31#include <sdeventplus/source/base.hpp>
32#include <sdeventplus/source/child.hpp>
33#include <utility>
Marri Devender Rao13bf74e2019-03-26 01:52:17 -050034#include <xyz/openbmc_project/Certs/error.hpp>
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -050035#include <xyz/openbmc_project/Common/error.hpp>
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +010036
Nan Zhoue1289ad2021-12-28 11:02:56 -080037namespace phosphor::certs
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -050038{
Nan Zhoucf06ccd2021-12-28 16:25:45 -080039namespace
40{
41namespace fs = std::filesystem;
42using ::phosphor::logging::commit;
43using ::phosphor::logging::elog;
44using ::phosphor::logging::entry;
45using ::phosphor::logging::level;
46using ::phosphor::logging::log;
47using ::phosphor::logging::report;
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -050048
Nan Zhoucf06ccd2021-12-28 16:25:45 -080049using ::sdbusplus::xyz::openbmc_project::Certs::Error::InvalidCertificate;
50using ::sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
51using ::sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
52using NotAllowedReason =
53 ::phosphor::logging::xyz::openbmc_project::Common::NotAllowed::REASON;
54using InvalidCertificateReason = ::phosphor::logging::xyz::openbmc_project::
55 Certs::InvalidCertificate::REASON;
56using ::sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
57using Argument =
58 ::phosphor::logging::xyz::openbmc_project::Common::InvalidArgument;
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -050059
Nan Zhoucf06ccd2021-12-28 16:25:45 -080060// RAII support for openSSL functions.
61using X509ReqPtr = std::unique_ptr<X509_REQ, decltype(&::X509_REQ_free)>;
62using EVPPkeyPtr = std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>;
63using BignumPtr = std::unique_ptr<BIGNUM, decltype(&::BN_free)>;
64
65constexpr int supportedKeyBitLength = 2048;
66constexpr int defaultKeyBitLength = 2048;
67// secp224r1 is equal to RSA 2048 KeyBitLength. Refer RFC 5349
68constexpr auto defaultKeyCurveID = "secp224r1";
69} // namespace
Marri Devender Raof4682712019-03-19 05:00:28 -050070
71Manager::Manager(sdbusplus::bus::bus& bus, sdeventplus::Event& event,
Nan Zhoucf06ccd2021-12-28 16:25:45 -080072 const char* path, CertificateType type,
73 const std::string& unit, const std::string& installPath) :
74 internal::ManagerInterface(bus, path),
Marri Devender Raof4682712019-03-19 05:00:28 -050075 bus(bus), event(event), objectPath(path), certType(type),
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -050076 unitToRestart(std::move(unit)), certInstallPath(std::move(installPath)),
77 certParentInstallPath(fs::path(certInstallPath).parent_path())
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -050078{
Marri Devender Raob57d75e2019-07-25 04:56:21 -050079 try
80 {
Marri Devender Raodb5c6fc2020-03-10 13:27:49 -050081 // Create certificate directory if not existing.
Nan Zhoubf3cf752021-12-28 11:02:07 -080082 // Set correct certificate directory permissions.
Marri Devender Raodb5c6fc2020-03-10 13:27:49 -050083 fs::path certDirectory;
84 try
Marri Devender Raob57d75e2019-07-25 04:56:21 -050085 {
Nan Zhoucf06ccd2021-12-28 16:25:45 -080086 if (certType == CertificateType::Authority)
Marri Devender Raodb5c6fc2020-03-10 13:27:49 -050087 {
88 certDirectory = certInstallPath;
89 }
90 else
91 {
92 certDirectory = certParentInstallPath;
93 }
94
95 if (!fs::exists(certDirectory))
96 {
97 fs::create_directories(certDirectory);
98 }
99
100 auto permission = fs::perms::owner_read | fs::perms::owner_write |
101 fs::perms::owner_exec;
102 fs::permissions(certDirectory, permission,
103 fs::perm_options::replace);
104 storageUpdate();
105 }
Patrick Williams71957992021-10-06 14:42:52 -0500106 catch (const fs::filesystem_error& e)
Marri Devender Raodb5c6fc2020-03-10 13:27:49 -0500107 {
108 log<level::ERR>(
109 "Failed to create directory", entry("ERR=%s", e.what()),
110 entry("DIRECTORY=%s", certParentInstallPath.c_str()));
111 report<InternalFailure>();
112 }
113
114 // Generating RSA private key file if certificate type is server/client
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800115 if (certType != CertificateType::Authority)
Marri Devender Raodb5c6fc2020-03-10 13:27:49 -0500116 {
117 createRSAPrivateKeyFile();
118 }
119
120 // restore any existing certificates
121 createCertificates();
122
123 // watch is not required for authority certificates
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800124 if (certType != CertificateType::Authority)
Marri Devender Raodb5c6fc2020-03-10 13:27:49 -0500125 {
126 // watch for certificate file create/replace
127 certWatchPtr = std::make_unique<
128 Watch>(event, certInstallPath, [this]() {
129 try
130 {
131 // if certificate file existing update it
132 if (!installedCerts.empty())
133 {
134 log<level::INFO>("Inotify callback to update "
135 "certificate properties");
136 installedCerts[0]->populateProperties();
137 }
138 else
139 {
140 log<level::INFO>(
141 "Inotify callback to create certificate object");
142 createCertificates();
143 }
144 }
145 catch (const InternalFailure& e)
146 {
147 commit<InternalFailure>();
148 }
149 catch (const InvalidCertificate& e)
150 {
151 commit<InvalidCertificate>();
152 }
153 });
Marri Devender Raob57d75e2019-07-25 04:56:21 -0500154 }
Zbigniew Lukwinskife590c42019-12-10 12:33:50 +0100155 else
156 {
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500157 try
158 {
Marri Devender Raodb5c6fc2020-03-10 13:27:49 -0500159 const std::string singleCertPath = "/etc/ssl/certs/Root-CA.pem";
160 if (fs::exists(singleCertPath) && !fs::is_empty(singleCertPath))
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500161 {
Marri Devender Raodb5c6fc2020-03-10 13:27:49 -0500162 log<level::NOTICE>(
163 "Legacy certificate detected, will be installed from: ",
164 entry("SINGLE_CERTPATH=%s", singleCertPath.c_str()));
165 install(singleCertPath);
166 if (!fs::remove(singleCertPath))
167 {
168 log<level::ERR>(
169 "Unable to remove old certificate from: ",
170 entry("SINGLE_CERTPATH=%s",
171 singleCertPath.c_str()));
172 elog<InternalFailure>();
173 }
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500174 }
175 }
Marri Devender Raodb5c6fc2020-03-10 13:27:49 -0500176 catch (const std::exception& ex)
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500177 {
Marri Devender Raodb5c6fc2020-03-10 13:27:49 -0500178 log<level::ERR>("Error in restoring legacy certificate",
179 entry("ERROR_STR=%s", ex.what()));
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200180 }
181 }
182 }
Patrick Williams71957992021-10-06 14:42:52 -0500183 catch (const std::exception& ex)
Marri Devender Raodb5c6fc2020-03-10 13:27:49 -0500184 {
185 log<level::ERR>("Error in certificate manager constructor",
186 entry("ERROR_STR=%s", ex.what()));
187 }
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -0500188}
189
Zbigniew Kurzynski06a69d72019-09-27 10:57:38 +0200190std::string Manager::install(const std::string filePath)
Jayanth Othayothcfbc8dc2018-09-03 07:22:27 -0500191{
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800192 if (certType != CertificateType::Authority && !installedCerts.empty())
Marri Devender Rao13965112019-02-27 08:47:12 -0600193 {
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800194 elog<NotAllowed>(NotAllowedReason("Certificate already exist"));
Marri Devender Rao13965112019-02-27 08:47:12 -0600195 }
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800196 else if (certType == CertificateType::Authority &&
Nan Zhou718eef32021-12-28 11:03:30 -0800197 installedCerts.size() >= maxNumAuthorityCertificates)
Zbigniew Lukwinski3b07b772019-10-09 11:43:34 +0200198 {
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800199 elog<NotAllowed>(NotAllowedReason("Certificates limit reached"));
Zbigniew Lukwinski3b07b772019-10-09 11:43:34 +0200200 }
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500201
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100202 std::string certObjectPath;
203 if (isCertificateUnique(filePath))
204 {
205 certObjectPath = objectPath + '/' + std::to_string(certIdCounter);
206 installedCerts.emplace_back(std::make_unique<Certificate>(
207 bus, certObjectPath, certType, certInstallPath, filePath,
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800208 certWatchPtr.get(), *this));
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100209 reloadOrReset(unitToRestart);
210 certIdCounter++;
211 }
212 else
213 {
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800214 elog<NotAllowed>(NotAllowedReason("Certificate already exist"));
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100215 }
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200216
Zbigniew Kurzynski06a69d72019-09-27 10:57:38 +0200217 return certObjectPath;
Jayanth Othayoth589159f2018-09-28 08:32:39 -0500218}
Deepak Kodihalliae70b3d2018-09-30 05:42:00 -0500219
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200220void Manager::deleteAll()
Deepak Kodihalliae70b3d2018-09-30 05:42:00 -0500221{
Marri Devender Rao6ceec402019-02-01 03:15:19 -0600222 // TODO: #Issue 4 when a certificate is deleted system auto generates
223 // certificate file. At present we are not supporting creation of
224 // certificate object for the auto-generated certificate file as
225 // deletion if only applicable for REST server and Bmcweb does not allow
226 // deletion of certificates
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200227 installedCerts.clear();
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100228 storageUpdate();
229 reloadOrReset(unitToRestart);
Deepak Kodihalliae70b3d2018-09-30 05:42:00 -0500230}
Marri Devender Raof4682712019-03-19 05:00:28 -0500231
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100232void Manager::deleteCertificate(const Certificate* const certificate)
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200233{
234 std::vector<std::unique_ptr<Certificate>>::iterator const& certIt =
235 std::find_if(installedCerts.begin(), installedCerts.end(),
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100236 [certificate](std::unique_ptr<Certificate> const& cert) {
237 return (cert.get() == certificate);
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200238 });
239 if (certIt != installedCerts.end())
240 {
241 installedCerts.erase(certIt);
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100242 storageUpdate();
243 reloadOrReset(unitToRestart);
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200244 }
245 else
246 {
247 log<level::ERR>("Certificate does not exist",
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100248 entry("ID=%s", certificate->getCertId().c_str()));
249 elog<InternalFailure>();
250 }
251}
252
253void Manager::replaceCertificate(Certificate* const certificate,
254 const std::string& filePath)
255{
256 if (isCertificateUnique(filePath, certificate))
257 {
258 certificate->install(filePath);
259 storageUpdate();
260 reloadOrReset(unitToRestart);
261 }
262 else
263 {
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800264 elog<NotAllowed>(NotAllowedReason("Certificate already exist"));
Zbigniew Kurzynskia3bb38f2019-09-17 13:34:25 +0200265 }
266}
267
Marri Devender Raof4682712019-03-19 05:00:28 -0500268std::string Manager::generateCSR(
269 std::vector<std::string> alternativeNames, std::string challengePassword,
270 std::string city, std::string commonName, std::string contactPerson,
271 std::string country, std::string email, std::string givenName,
272 std::string initials, int64_t keyBitLength, std::string keyCurveId,
273 std::string keyPairAlgorithm, std::vector<std::string> keyUsage,
274 std::string organization, std::string organizationalUnit, std::string state,
275 std::string surname, std::string unstructuredName)
276{
277 // We support only one CSR.
278 csrPtr.reset(nullptr);
279 auto pid = fork();
280 if (pid == -1)
281 {
282 log<level::ERR>("Error occurred during forking process");
283 report<InternalFailure>();
284 }
285 else if (pid == 0)
286 {
287 try
288 {
289 generateCSRHelper(alternativeNames, challengePassword, city,
290 commonName, contactPerson, country, email,
291 givenName, initials, keyBitLength, keyCurveId,
292 keyPairAlgorithm, keyUsage, organization,
293 organizationalUnit, state, surname,
294 unstructuredName);
295 exit(EXIT_SUCCESS);
296 }
297 catch (const InternalFailure& e)
298 {
299 // commit the error reported in child process and exit
300 // Callback method from SDEvent Loop looks for exit status
301 exit(EXIT_FAILURE);
302 commit<InternalFailure>();
303 }
Ramesh Iyyard2393f22020-10-29 09:46:51 -0500304 catch (const InvalidArgument& e)
305 {
306 // commit the error reported in child process and exit
307 // Callback method from SDEvent Loop looks for exit status
308 exit(EXIT_FAILURE);
309 commit<InvalidArgument>();
310 }
Marri Devender Raof4682712019-03-19 05:00:28 -0500311 }
312 else
313 {
314 using namespace sdeventplus::source;
315 Child::Callback callback = [this](Child& eventSource,
316 const siginfo_t* si) {
317 eventSource.set_enabled(Enabled::On);
318 if (si->si_status != 0)
319 {
320 this->createCSRObject(Status::FAILURE);
321 }
322 else
323 {
324 this->createCSRObject(Status::SUCCESS);
325 }
326 };
327 try
328 {
329 sigset_t ss;
330 if (sigemptyset(&ss) < 0)
331 {
332 log<level::ERR>("Unable to initialize signal set");
333 elog<InternalFailure>();
334 }
335 if (sigaddset(&ss, SIGCHLD) < 0)
336 {
337 log<level::ERR>("Unable to add signal to signal set");
338 elog<InternalFailure>();
339 }
340
341 // Block SIGCHLD first, so that the event loop can handle it
Nan Zhoucfb58022021-12-28 11:02:26 -0800342 if (sigprocmask(SIG_BLOCK, &ss, nullptr) < 0)
Marri Devender Raof4682712019-03-19 05:00:28 -0500343 {
344 log<level::ERR>("Unable to block signal");
345 elog<InternalFailure>();
346 }
347 if (childPtr)
348 {
349 childPtr.reset();
350 }
351 childPtr = std::make_unique<Child>(event, pid, WEXITED | WSTOPPED,
352 std::move(callback));
353 }
354 catch (const InternalFailure& e)
355 {
356 commit<InternalFailure>();
357 }
358 }
359 auto csrObjectPath = objectPath + '/' + "csr";
360 return csrObjectPath;
361}
362
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200363std::vector<std::unique_ptr<Certificate>>& Manager::getCertificates()
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500364{
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200365 return installedCerts;
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500366}
367
Marri Devender Raof4682712019-03-19 05:00:28 -0500368void Manager::generateCSRHelper(
369 std::vector<std::string> alternativeNames, std::string challengePassword,
370 std::string city, std::string commonName, std::string contactPerson,
371 std::string country, std::string email, std::string givenName,
372 std::string initials, int64_t keyBitLength, std::string keyCurveId,
373 std::string keyPairAlgorithm, std::vector<std::string> keyUsage,
374 std::string organization, std::string organizationalUnit, std::string state,
375 std::string surname, std::string unstructuredName)
376{
377 int ret = 0;
378
379 // set version of x509 req
380 int nVersion = 1;
381 // TODO: Issue#6 need to make version number configurable
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800382 X509ReqPtr x509Req(X509_REQ_new(), ::X509_REQ_free);
Marri Devender Raof4682712019-03-19 05:00:28 -0500383 ret = X509_REQ_set_version(x509Req.get(), nVersion);
384 if (ret == 0)
385 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800386 log<level::ERR>("Error occurred during X509_REQ_set_version call");
Marri Devender Raof4682712019-03-19 05:00:28 -0500387 elog<InternalFailure>();
388 }
389
390 // set subject of x509 req
391 X509_NAME* x509Name = X509_REQ_get_subject_name(x509Req.get());
392
393 if (!alternativeNames.empty())
394 {
395 for (auto& name : alternativeNames)
396 {
397 addEntry(x509Name, "subjectAltName", name);
398 }
399 }
400 addEntry(x509Name, "challengePassword", challengePassword);
401 addEntry(x509Name, "L", city);
402 addEntry(x509Name, "CN", commonName);
403 addEntry(x509Name, "name", contactPerson);
404 addEntry(x509Name, "C", country);
405 addEntry(x509Name, "emailAddress", email);
406 addEntry(x509Name, "GN", givenName);
407 addEntry(x509Name, "initials", initials);
408 addEntry(x509Name, "algorithm", keyPairAlgorithm);
409 if (!keyUsage.empty())
410 {
411 for (auto& usage : keyUsage)
412 {
Marri Devender Rao76411052019-08-07 01:25:07 -0500413 if (isExtendedKeyUsage(usage))
414 {
415 addEntry(x509Name, "extendedKeyUsage", usage);
416 }
417 else
418 {
419 addEntry(x509Name, "keyUsage", usage);
420 }
Marri Devender Raof4682712019-03-19 05:00:28 -0500421 }
422 }
423 addEntry(x509Name, "O", organization);
Jayanth Othayothdc91fb62021-05-04 23:17:47 -0500424 addEntry(x509Name, "OU", organizationalUnit);
Marri Devender Raof4682712019-03-19 05:00:28 -0500425 addEntry(x509Name, "ST", state);
426 addEntry(x509Name, "SN", surname);
427 addEntry(x509Name, "unstructuredName", unstructuredName);
428
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800429 EVPPkeyPtr pKey(nullptr, ::EVP_PKEY_free);
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500430
431 log<level::INFO>("Given Key pair algorithm",
432 entry("KEYPAIRALGORITHM=%s", keyPairAlgorithm.c_str()));
433
434 // Used EC algorithm as default if user did not give algorithm type.
435 if (keyPairAlgorithm == "RSA")
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500436 pKey = getRSAKeyPair(keyBitLength);
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500437 else if ((keyPairAlgorithm == "EC") || (keyPairAlgorithm.empty()))
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500438 pKey = generateECKeyPair(keyCurveId);
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500439 else
440 {
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500441 log<level::ERR>("Given Key pair algorithm is not supported. Supporting "
442 "RSA and EC only");
443 elog<InvalidArgument>(
444 Argument::ARGUMENT_NAME("KEYPAIRALGORITHM"),
445 Argument::ARGUMENT_VALUE(keyPairAlgorithm.c_str()));
446 }
447
448 ret = X509_REQ_set_pubkey(x509Req.get(), pKey.get());
449 if (ret == 0)
450 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800451 log<level::ERR>("Error occurred while setting Public key");
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500452 elog<InternalFailure>();
453 }
454
455 // Write private key to file
Nan Zhou718eef32021-12-28 11:03:30 -0800456 writePrivateKey(pKey, defaultPrivateKeyFileName);
Marri Devender Raof4682712019-03-19 05:00:28 -0500457
458 // set sign key of x509 req
459 ret = X509_REQ_sign(x509Req.get(), pKey.get(), EVP_sha256());
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500460 if (ret == 0)
Marri Devender Raof4682712019-03-19 05:00:28 -0500461 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800462 log<level::ERR>("Error occurred while signing key of x509");
Marri Devender Raof4682712019-03-19 05:00:28 -0500463 elog<InternalFailure>();
464 }
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500465
Marri Devender Raof4682712019-03-19 05:00:28 -0500466 log<level::INFO>("Writing CSR to file");
Nan Zhou718eef32021-12-28 11:03:30 -0800467 fs::path csrFilePath = certParentInstallPath / defaultCSRFileName;
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500468 writeCSR(csrFilePath.string(), x509Req);
Marri Devender Raof4682712019-03-19 05:00:28 -0500469}
470
Marri Devender Rao76411052019-08-07 01:25:07 -0500471bool Manager::isExtendedKeyUsage(const std::string& usage)
472{
473 const static std::array<const char*, 6> usageList = {
474 "ServerAuthentication", "ClientAuthentication", "OCSPSigning",
475 "Timestamping", "CodeSigning", "EmailProtection"};
476 auto it = std::find_if(
477 usageList.begin(), usageList.end(),
478 [&usage](const char* s) { return (strcmp(s, usage.c_str()) == 0); });
479 return it != usageList.end();
480}
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800481EVPPkeyPtr Manager::generateRSAKeyPair(const int64_t keyBitLength)
Marri Devender Raof4682712019-03-19 05:00:28 -0500482{
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500483 int64_t keyBitLen = keyBitLength;
Marri Devender Raof4682712019-03-19 05:00:28 -0500484 // set keybit length to default value if not set
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500485 if (keyBitLen <= 0)
Marri Devender Raof4682712019-03-19 05:00:28 -0500486 {
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500487 log<level::INFO>(
488 "KeyBitLength is not given.Hence, using default KeyBitLength",
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800489 entry("DEFAULTKEYBITLENGTH=%d", defaultKeyBitLength));
490 keyBitLen = defaultKeyBitLength;
Marri Devender Raof4682712019-03-19 05:00:28 -0500491 }
Patrick Williams26fb83e2021-12-14 14:08:28 -0600492
493#if (OPENSSL_VERSION_NUMBER < 0x30000000L)
494
495 // generate rsa key
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800496 BignumPtr bne(BN_new(), ::BN_free);
Patrick Williams26fb83e2021-12-14 14:08:28 -0600497 auto ret = BN_set_word(bne.get(), RSA_F4);
498 if (ret == 0)
499 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800500 log<level::ERR>("Error occurred during BN_set_word call");
Patrick Williams26fb83e2021-12-14 14:08:28 -0600501 elog<InternalFailure>();
502 }
Nan Zhou762da742022-01-14 17:21:44 -0800503 using RSAPtr = std::unique_ptr<RSA, decltype(&::RSA_free)>;
504 RSAPtr rsa(RSA_new(), ::RSA_free);
505 ret = RSA_generate_key_ex(rsa.get(), keyBitLen, bne.get(), nullptr);
Marri Devender Raof4682712019-03-19 05:00:28 -0500506 if (ret != 1)
507 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800508 log<level::ERR>("Error occurred during RSA_generate_key_ex call",
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500509 entry("KEYBITLENGTH=%PRIu64", keyBitLen));
Marri Devender Raof4682712019-03-19 05:00:28 -0500510 elog<InternalFailure>();
511 }
512
513 // set public key of x509 req
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800514 EVPPkeyPtr pKey(EVP_PKEY_new(), ::EVP_PKEY_free);
Nan Zhou762da742022-01-14 17:21:44 -0800515 ret = EVP_PKEY_assign_RSA(pKey.get(), rsa.get());
Marri Devender Raof4682712019-03-19 05:00:28 -0500516 if (ret == 0)
517 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800518 log<level::ERR>("Error occurred during assign rsa key into EVP");
Marri Devender Raof4682712019-03-19 05:00:28 -0500519 elog<InternalFailure>();
520 }
Nan Zhou762da742022-01-14 17:21:44 -0800521 // Now |rsa| is managed by |pKey|
522 rsa.release();
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500523 return pKey;
Patrick Williams26fb83e2021-12-14 14:08:28 -0600524
525#else
526 auto ctx = std::unique_ptr<EVP_PKEY_CTX, decltype(&::EVP_PKEY_CTX_free)>(
527 EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr), &::EVP_PKEY_CTX_free);
528 if (!ctx)
529 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800530 log<level::ERR>("Error occurred creating EVP_PKEY_CTX from algorithm");
Patrick Williams26fb83e2021-12-14 14:08:28 -0600531 elog<InternalFailure>();
532 }
533
534 if ((EVP_PKEY_keygen_init(ctx.get()) <= 0) ||
535 (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx.get(), keyBitLen) <= 0))
536
537 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800538 log<level::ERR>("Error occurred initializing keygen context");
Patrick Williams26fb83e2021-12-14 14:08:28 -0600539 elog<InternalFailure>();
540 }
541
542 EVP_PKEY* pKey = nullptr;
543 if (EVP_PKEY_keygen(ctx.get(), &pKey) <= 0)
544 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800545 log<level::ERR>("Error occurred during generate EC key");
Patrick Williams26fb83e2021-12-14 14:08:28 -0600546 elog<InternalFailure>();
547 }
548
549 return {pKey, &::EVP_PKEY_free};
550#endif
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500551}
552
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800553EVPPkeyPtr Manager::generateECKeyPair(const std::string& curveId)
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500554{
555 std::string curId(curveId);
556
557 if (curId.empty())
558 {
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500559 log<level::INFO>(
560 "KeyCurveId is not given. Hence using default curve id",
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800561 entry("DEFAULTKEYCURVEID=%s", defaultKeyCurveID));
562 curId = defaultKeyCurveID;
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500563 }
564
565 int ecGrp = OBJ_txt2nid(curId.c_str());
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500566 if (ecGrp == NID_undef)
567 {
568 log<level::ERR>(
Nan Zhoubf3cf752021-12-28 11:02:07 -0800569 "Error occurred during convert the curve id string format into NID",
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500570 entry("KEYCURVEID=%s", curId.c_str()));
571 elog<InternalFailure>();
572 }
573
Patrick Williams26fb83e2021-12-14 14:08:28 -0600574#if (OPENSSL_VERSION_NUMBER < 0x30000000L)
575
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500576 EC_KEY* ecKey = EC_KEY_new_by_curve_name(ecGrp);
577
Nan Zhoucfb58022021-12-28 11:02:26 -0800578 if (ecKey == nullptr)
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500579 {
580 log<level::ERR>(
Nan Zhoubf3cf752021-12-28 11:02:07 -0800581 "Error occurred during create the EC_Key object from NID",
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500582 entry("ECGROUP=%d", ecGrp));
583 elog<InternalFailure>();
584 }
585
586 // If you want to save a key and later load it with
587 // SSL_CTX_use_PrivateKey_file, then you must set the OPENSSL_EC_NAMED_CURVE
588 // flag on the key.
589 EC_KEY_set_asn1_flag(ecKey, OPENSSL_EC_NAMED_CURVE);
590
591 int ret = EC_KEY_generate_key(ecKey);
592
593 if (ret == 0)
594 {
595 EC_KEY_free(ecKey);
Nan Zhoubf3cf752021-12-28 11:02:07 -0800596 log<level::ERR>("Error occurred during generate EC key");
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500597 elog<InternalFailure>();
598 }
599
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800600 EVPPkeyPtr pKey(EVP_PKEY_new(), ::EVP_PKEY_free);
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500601 ret = EVP_PKEY_assign_EC_KEY(pKey.get(), ecKey);
602 if (ret == 0)
603 {
604 EC_KEY_free(ecKey);
Nan Zhoubf3cf752021-12-28 11:02:07 -0800605 log<level::ERR>("Error occurred during assign EC Key into EVP");
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500606 elog<InternalFailure>();
607 }
608
609 return pKey;
Patrick Williams26fb83e2021-12-14 14:08:28 -0600610
611#else
612 auto holder_of_key = [](EVP_PKEY* key) {
613 return std::unique_ptr<EVP_PKEY, decltype(&::EVP_PKEY_free)>{
614 key, &::EVP_PKEY_free};
615 };
616
617 // Create context to set up curve parameters.
618 auto ctx = std::unique_ptr<EVP_PKEY_CTX, decltype(&::EVP_PKEY_CTX_free)>(
619 EVP_PKEY_CTX_new_id(EVP_PKEY_EC, nullptr), &::EVP_PKEY_CTX_free);
620 if (!ctx)
621 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800622 log<level::ERR>("Error occurred creating EVP_PKEY_CTX for params");
Patrick Williams26fb83e2021-12-14 14:08:28 -0600623 elog<InternalFailure>();
624 }
625
626 // Set up curve parameters.
627 EVP_PKEY* params = nullptr;
628
629 if ((EVP_PKEY_paramgen_init(ctx.get()) <= 0) ||
630 (EVP_PKEY_CTX_set_ec_param_enc(ctx.get(), OPENSSL_EC_NAMED_CURVE) <=
631 0) ||
632 (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx.get(), ecGrp) <= 0) ||
633 (EVP_PKEY_paramgen(ctx.get(), &params) <= 0))
634 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800635 log<level::ERR>("Error occurred setting curve parameters");
Patrick Williams26fb83e2021-12-14 14:08:28 -0600636 elog<InternalFailure>();
637 }
638
639 // Move parameters to RAII holder.
640 auto pparms = holder_of_key(params);
641
642 // Create new context for key.
643 ctx.reset(EVP_PKEY_CTX_new_from_pkey(nullptr, params, nullptr));
644
645 if (!ctx || (EVP_PKEY_keygen_init(ctx.get()) <= 0))
646 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800647 log<level::ERR>("Error occurred initializing keygen context");
Patrick Williams26fb83e2021-12-14 14:08:28 -0600648 elog<InternalFailure>();
649 }
650
651 EVP_PKEY* pKey = nullptr;
652 if (EVP_PKEY_keygen(ctx.get(), &pKey) <= 0)
653 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800654 log<level::ERR>("Error occurred during generate EC key");
Patrick Williams26fb83e2021-12-14 14:08:28 -0600655 elog<InternalFailure>();
656 }
657
658 return holder_of_key(pKey);
659#endif
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500660}
661
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800662void Manager::writePrivateKey(const EVPPkeyPtr& pKey,
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500663 const std::string& privKeyFileName)
Ramesh Iyyar8a09b522019-06-07 05:23:29 -0500664{
665 log<level::INFO>("Writing private key to file");
Marri Devender Raof4682712019-03-19 05:00:28 -0500666 // write private key to file
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500667 fs::path privKeyPath = certParentInstallPath / privKeyFileName;
Marri Devender Raof4682712019-03-19 05:00:28 -0500668
669 FILE* fp = std::fopen(privKeyPath.c_str(), "w");
Nan Zhoucfb58022021-12-28 11:02:26 -0800670 if (fp == nullptr)
Marri Devender Raof4682712019-03-19 05:00:28 -0500671 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800672 log<level::ERR>("Error occurred creating private key file");
Marri Devender Raof4682712019-03-19 05:00:28 -0500673 elog<InternalFailure>();
674 }
Nan Zhoucfb58022021-12-28 11:02:26 -0800675 int ret =
676 PEM_write_PrivateKey(fp, pKey.get(), nullptr, nullptr, 0, 0, nullptr);
Marri Devender Raof4682712019-03-19 05:00:28 -0500677 std::fclose(fp);
678 if (ret == 0)
679 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800680 log<level::ERR>("Error occurred while writing private key to file");
Marri Devender Raof4682712019-03-19 05:00:28 -0500681 elog<InternalFailure>();
682 }
Marri Devender Raof4682712019-03-19 05:00:28 -0500683}
684
685void Manager::addEntry(X509_NAME* x509Name, const char* field,
686 const std::string& bytes)
687{
688 if (bytes.empty())
689 {
690 return;
691 }
692 int ret = X509_NAME_add_entry_by_txt(
693 x509Name, field, MBSTRING_ASC,
694 reinterpret_cast<const unsigned char*>(bytes.c_str()), -1, -1, 0);
695 if (ret != 1)
696 {
697 log<level::ERR>("Unable to set entry", entry("FIELD=%s", field),
698 entry("VALUE=%s", bytes.c_str()));
699 elog<InternalFailure>();
700 }
701}
702
703void Manager::createCSRObject(const Status& status)
704{
705 if (csrPtr)
706 {
707 csrPtr.reset(nullptr);
708 }
709 auto csrObjectPath = objectPath + '/' + "csr";
710 csrPtr = std::make_unique<CSR>(bus, csrObjectPath.c_str(),
711 certInstallPath.c_str(), status);
712}
713
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800714void Manager::writeCSR(const std::string& filePath, const X509ReqPtr& x509Req)
Marri Devender Raof4682712019-03-19 05:00:28 -0500715{
716 if (fs::exists(filePath))
717 {
718 log<level::INFO>("Removing the existing file",
719 entry("FILENAME=%s", filePath.c_str()));
720 if (!fs::remove(filePath.c_str()))
721 {
722 log<level::ERR>("Unable to remove the file",
723 entry("FILENAME=%s", filePath.c_str()));
724 elog<InternalFailure>();
725 }
726 }
727
Nan Zhoucfb58022021-12-28 11:02:26 -0800728 FILE* fp = nullptr;
Marri Devender Raof4682712019-03-19 05:00:28 -0500729
Nan Zhoucfb58022021-12-28 11:02:26 -0800730 if ((fp = std::fopen(filePath.c_str(), "w")) == nullptr)
Marri Devender Raof4682712019-03-19 05:00:28 -0500731 {
732 log<level::ERR>("Error opening the file to write the CSR",
733 entry("FILENAME=%s", filePath.c_str()));
734 elog<InternalFailure>();
735 }
736
737 int rc = PEM_write_X509_REQ(fp, x509Req.get());
738 if (!rc)
739 {
740 log<level::ERR>("PEM write routine failed",
741 entry("FILENAME=%s", filePath.c_str()));
742 std::fclose(fp);
743 elog<InternalFailure>();
744 }
745 std::fclose(fp);
746}
747
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200748void Manager::createCertificates()
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500749{
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200750 auto certObjectPath = objectPath + '/';
751
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800752 if (certType == CertificateType::Authority)
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500753 {
Zbigniew Lukwinskife590c42019-12-10 12:33:50 +0100754 // Check whether install path is a directory.
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200755 if (!fs::is_directory(certInstallPath))
756 {
757 log<level::ERR>("Certificate installation path exists and it is "
758 "not a directory");
759 elog<InternalFailure>();
760 return;
761 }
762
763 for (auto& path : fs::directory_iterator(certInstallPath))
764 {
765 try
766 {
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100767 // Assume here any regular file located in certificate directory
768 // contains certificates body. Do not want to use soft links
769 // would add value.
770 if (fs::is_regular_file(path))
771 {
772 installedCerts.emplace_back(std::make_unique<Certificate>(
773 bus, certObjectPath + std::to_string(certIdCounter++),
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800774 certType, certInstallPath, path.path(),
775 certWatchPtr.get(), *this));
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100776 }
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200777 }
778 catch (const InternalFailure& e)
779 {
780 report<InternalFailure>();
781 }
782 catch (const InvalidCertificate& e)
783 {
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800784 report<InvalidCertificate>(InvalidCertificateReason(
785 "Existing certificate file is corrupted"));
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200786 }
787 }
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500788 }
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200789 else if (fs::exists(certInstallPath))
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500790 {
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200791 try
792 {
793 installedCerts.emplace_back(std::make_unique<Certificate>(
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100794 bus, certObjectPath + '1', certType, certInstallPath,
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800795 certInstallPath, certWatchPtr.get(), *this));
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200796 }
797 catch (const InternalFailure& e)
798 {
799 report<InternalFailure>();
800 }
801 catch (const InvalidCertificate& e)
802 {
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800803 report<InvalidCertificate>(InvalidCertificateReason(
804 "Existing certificate file is corrupted"));
Kowalski, Kamildb029c92019-07-08 17:09:39 +0200805 }
Marri Devender Raoffad1ef2019-06-03 04:54:12 -0500806 }
807}
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500808
809void Manager::createRSAPrivateKeyFile()
810{
811 fs::path rsaPrivateKeyFileName =
Nan Zhou718eef32021-12-28 11:03:30 -0800812 certParentInstallPath / defaultRSAPrivateKeyFileName;
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500813
814 try
815 {
816 if (!fs::exists(rsaPrivateKeyFileName))
817 {
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800818 writePrivateKey(generateRSAKeyPair(supportedKeyBitLength),
Nan Zhou718eef32021-12-28 11:03:30 -0800819 defaultRSAPrivateKeyFileName);
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500820 }
821 }
822 catch (const InternalFailure& e)
823 {
824 report<InternalFailure>();
825 }
826}
827
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800828EVPPkeyPtr Manager::getRSAKeyPair(const int64_t keyBitLength)
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500829{
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800830 if (keyBitLength != supportedKeyBitLength)
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500831 {
832 log<level::ERR>(
833 "Given Key bit length is not supported",
834 entry("GIVENKEYBITLENGTH=%d", keyBitLength),
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800835 entry("SUPPORTEDKEYBITLENGTH=%d", supportedKeyBitLength));
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500836 elog<InvalidArgument>(
837 Argument::ARGUMENT_NAME("KEYBITLENGTH"),
838 Argument::ARGUMENT_VALUE(std::to_string(keyBitLength).c_str()));
839 }
840 fs::path rsaPrivateKeyFileName =
Nan Zhou718eef32021-12-28 11:03:30 -0800841 certParentInstallPath / defaultRSAPrivateKeyFileName;
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500842
843 FILE* privateKeyFile = std::fopen(rsaPrivateKeyFileName.c_str(), "r");
844 if (!privateKeyFile)
845 {
846 log<level::ERR>("Unable to open RSA private key file to read",
847 entry("RSAKEYFILE=%s", rsaPrivateKeyFileName.c_str()),
848 entry("ERRORREASON=%s", strerror(errno)));
849 elog<InternalFailure>();
850 }
851
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800852 EVPPkeyPtr privateKey(
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500853 PEM_read_PrivateKey(privateKeyFile, nullptr, nullptr, nullptr),
854 ::EVP_PKEY_free);
855 std::fclose(privateKeyFile);
856
857 if (!privateKey)
858 {
Nan Zhoubf3cf752021-12-28 11:02:07 -0800859 log<level::ERR>("Error occurred during PEM_read_PrivateKey call");
Ramesh Iyyarc6e58c72019-07-16 08:52:47 -0500860 elog<InternalFailure>();
861 }
862 return privateKey;
863}
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100864
865void Manager::storageUpdate()
866{
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800867 if (certType == CertificateType::Authority)
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100868 {
869 // Remove symbolic links in the certificate directory
870 for (auto& certPath : fs::directory_iterator(certInstallPath))
871 {
872 try
873 {
874 if (fs::is_symlink(certPath))
875 {
876 fs::remove(certPath);
877 }
878 }
879 catch (const std::exception& e)
880 {
881 log<level::ERR>(
882 "Failed to remove symlink for certificate",
883 entry("ERR=%s", e.what()),
884 entry("SYMLINK=%s", certPath.path().string().c_str()));
885 elog<InternalFailure>();
886 }
887 }
888 }
889
890 for (const auto& cert : installedCerts)
891 {
892 cert->storageUpdate();
893 }
894}
895
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800896void Manager::reloadOrReset(const std::string& unit)
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100897{
898 if (!unit.empty())
899 {
900 try
901 {
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800902 constexpr auto defaultSystemdService = "org.freedesktop.systemd1";
903 constexpr auto defaultSystemdObjectPath =
904 "/org/freedesktop/systemd1";
905 constexpr auto defaultSystemdInterface =
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100906 "org.freedesktop.systemd1.Manager";
Nan Zhoucf06ccd2021-12-28 16:25:45 -0800907 auto method = bus.new_method_call(
908 defaultSystemdService, defaultSystemdObjectPath,
909 defaultSystemdInterface, "ReloadOrRestartUnit");
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100910 method.append(unit, "replace");
911 bus.call_noreply(method);
912 }
Patrick Williamsca128112021-09-02 09:36:07 -0500913 catch (const sdbusplus::exception::exception& e)
Zbigniew Lukwinski2f3563c2020-01-08 12:35:23 +0100914 {
915 log<level::ERR>("Failed to reload or restart service",
916 entry("ERR=%s", e.what()),
917 entry("UNIT=%s", unit.c_str()));
918 elog<InternalFailure>();
919 }
920 }
921}
922
923bool Manager::isCertificateUnique(const std::string& filePath,
924 const Certificate* const certToDrop)
925{
926 if (std::any_of(
927 installedCerts.begin(), installedCerts.end(),
928 [&filePath, certToDrop](std::unique_ptr<Certificate> const& cert) {
929 return cert.get() != certToDrop && cert->isSame(filePath);
930 }))
931 {
932 return false;
933 }
934 else
935 {
936 return true;
937 }
938}
939
Nan Zhoue1289ad2021-12-28 11:02:56 -0800940} // namespace phosphor::certs