blob: cf017f552941b2700cd03ab66304bf1725eead7c [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
Alan Kuoa8220702020-11-26 11:15:29 +08003#pragma once
Ed Tanous3ccb3ad2023-01-13 17:40:03 -08004#include "dbus_singleton.hpp"
5#include "dbus_utility.hpp"
6#include "include/dbus_utility.hpp"
7#include "logging.hpp"
8#include "ssl_key_handler.hpp"
9
Alan Kuoa8220702020-11-26 11:15:29 +080010#include <sdbusplus/bus/match.hpp>
11#include <sdbusplus/message/types.hpp>
Alan Kuoa8220702020-11-26 11:15:29 +080012
13namespace crow
14{
15namespace hostname_monitor
16{
Ed Tanouscf9e4172022-12-21 09:30:16 -080017// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
Patrick Williams59d494e2022-07-22 19:26:55 -050018static std::unique_ptr<sdbusplus::bus::match_t> hostnameSignalMonitor;
Alan Kuoa8220702020-11-26 11:15:29 +080019
20inline void installCertificate(const std::filesystem::path& certPath)
21{
22 crow::connections::systemBus->async_method_call(
Ed Tanous5e7e2dc2023-02-16 10:37:01 -080023 [certPath](const boost::system::error_code& ec) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -040024 if (ec)
25 {
26 BMCWEB_LOG_ERROR("Replace Certificate Fail..");
27 return;
28 }
Alan Kuoa8220702020-11-26 11:15:29 +080029
Patrick Williamsbd79bce2024-08-16 15:22:20 -040030 BMCWEB_LOG_INFO("Replace HTTPs Certificate Success, "
31 "remove temporary certificate file..");
32 std::error_code ec2;
33 std::filesystem::remove(certPath.c_str(), ec2);
34 if (ec2)
35 {
36 BMCWEB_LOG_ERROR("Failed to remove certificate");
37 }
38 },
Alan Kuoa8220702020-11-26 11:15:29 +080039 "xyz.openbmc_project.Certs.Manager.Server.Https",
40 "/xyz/openbmc_project/certs/server/https/1",
41 "xyz.openbmc_project.Certs.Replace", "Replace", certPath.string());
42}
43
44inline int onPropertyUpdate(sd_bus_message* m, void* /* userdata */,
Ed Tanous81ce6092020-12-17 16:54:55 +000045 sd_bus_error* retError)
Alan Kuoa8220702020-11-26 11:15:29 +080046{
Ed Tanouse662eae2022-01-25 10:39:19 -080047 if (retError == nullptr || (sd_bus_error_is_set(retError) != 0))
Alan Kuoa8220702020-11-26 11:15:29 +080048 {
Ed Tanous62598e32023-07-17 17:06:25 -070049 BMCWEB_LOG_ERROR("Got sdbus error on match");
Alan Kuoa8220702020-11-26 11:15:29 +080050 return 0;
51 }
52
Patrick Williams59d494e2022-07-22 19:26:55 -050053 sdbusplus::message_t message(m);
Alan Kuoa8220702020-11-26 11:15:29 +080054 std::string iface;
Ed Tanousb9d36b42022-02-26 21:42:46 -080055 dbus::utility::DBusPropertiesMap changedProperties;
Alan Kuoa8220702020-11-26 11:15:29 +080056
57 message.read(iface, changedProperties);
Ed Tanousb9d36b42022-02-26 21:42:46 -080058 const std::string* hostname = nullptr;
59 for (const auto& propertyPair : changedProperties)
Alan Kuoa8220702020-11-26 11:15:29 +080060 {
Ed Tanousb9d36b42022-02-26 21:42:46 -080061 if (propertyPair.first == "HostName")
62 {
63 hostname = std::get_if<std::string>(&propertyPair.second);
64 }
Alan Kuoa8220702020-11-26 11:15:29 +080065 }
Alan Kuoa8220702020-11-26 11:15:29 +080066 if (hostname == nullptr)
67 {
Alan Kuoa8220702020-11-26 11:15:29 +080068 return 0;
69 }
70
Ed Tanous62598e32023-07-17 17:06:25 -070071 BMCWEB_LOG_DEBUG("Read hostname from signal: {}", *hostname);
Alan Kuoa8220702020-11-26 11:15:29 +080072 const std::string certFile = "/etc/ssl/certs/https/server.pem";
73
74 X509* cert = ensuressl::loadCert(certFile);
75 if (cert == nullptr)
76 {
Ed Tanous62598e32023-07-17 17:06:25 -070077 BMCWEB_LOG_ERROR("Failed to read cert");
Alan Kuoa8220702020-11-26 11:15:29 +080078 return 0;
79 }
80
81 const int maxKeySize = 256;
82 std::array<char, maxKeySize> cnBuffer{};
83
Patrick Williamsbd79bce2024-08-16 15:22:20 -040084 int cnLength =
85 X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName,
86 cnBuffer.data(), cnBuffer.size());
Alan Kuoa8220702020-11-26 11:15:29 +080087 if (cnLength == -1)
88 {
Ed Tanous62598e32023-07-17 17:06:25 -070089 BMCWEB_LOG_ERROR("Failed to read NID_commonName");
Alan Kuoa8220702020-11-26 11:15:29 +080090 X509_free(cert);
91 return 0;
92 }
93 std::string_view cnValue(std::begin(cnBuffer),
94 static_cast<size_t>(cnLength));
95
96 EVP_PKEY* pPubKey = X509_get_pubkey(cert);
97 if (pPubKey == nullptr)
98 {
Ed Tanous62598e32023-07-17 17:06:25 -070099 BMCWEB_LOG_ERROR("Failed to get public key");
Alan Kuoa8220702020-11-26 11:15:29 +0800100 X509_free(cert);
101 return 0;
102 }
103 int isSelfSigned = X509_verify(cert, pPubKey);
104 EVP_PKEY_free(pPubKey);
105
Ed Tanous62598e32023-07-17 17:06:25 -0700106 BMCWEB_LOG_DEBUG(
107 "Current HTTPs Certificate Subject CN: {}, New HostName: {}, isSelfSigned: {}",
108 cnValue, *hostname, isSelfSigned);
Alan Kuoa8220702020-11-26 11:15:29 +0800109
110 ASN1_IA5STRING* asn1 = static_cast<ASN1_IA5STRING*>(
111 X509_get_ext_d2i(cert, NID_netscape_comment, nullptr, nullptr));
Ed Tanouse662eae2022-01-25 10:39:19 -0800112 if (asn1 != nullptr)
Alan Kuoa8220702020-11-26 11:15:29 +0800113 {
Ed Tanous46ff87b2022-01-07 09:25:51 -0800114 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
Alan Kuoa8220702020-11-26 11:15:29 +0800115 std::string_view comment(reinterpret_cast<const char*>(asn1->data),
116 static_cast<size_t>(asn1->length));
Ed Tanous62598e32023-07-17 17:06:25 -0700117 BMCWEB_LOG_DEBUG("x509Comment: {}", comment);
Alan Kuoa8220702020-11-26 11:15:29 +0800118
119 if (ensuressl::x509Comment == comment && isSelfSigned == 1 &&
120 cnValue != *hostname)
121 {
Ed Tanous62598e32023-07-17 17:06:25 -0700122 BMCWEB_LOG_INFO(
123 "Ready to generate new HTTPs certificate with subject cn: {}",
124 *hostname);
Alan Kuoa8220702020-11-26 11:15:29 +0800125
Ed Tanous099225c2024-03-27 22:03:05 -0700126 std::string certData = ensuressl::generateSslCertificate(*hostname);
127 if (certData.empty())
128 {
129 BMCWEB_LOG_ERROR("Failed to generate cert");
130 return 0;
131 }
132 ensuressl::writeCertificateToFile("/tmp/hostname_cert.tmp",
133 certData);
134
Alan Kuoa8220702020-11-26 11:15:29 +0800135 installCertificate("/tmp/hostname_cert.tmp");
136 }
137 ASN1_STRING_free(asn1);
138 }
139 X509_free(cert);
140 return 0;
141}
142
143inline void registerHostnameSignal()
144{
Ed Tanous62598e32023-07-17 17:06:25 -0700145 BMCWEB_LOG_INFO("Register HostName PropertiesChanged Signal");
Alan Kuoa8220702020-11-26 11:15:29 +0800146 std::string propertiesMatchString =
147 ("type='signal',"
148 "interface='org.freedesktop.DBus.Properties',"
149 "path='/xyz/openbmc_project/network/config',"
150 "arg0='xyz.openbmc_project.Network.SystemConfiguration',"
151 "member='PropertiesChanged'");
152
Patrick Williams59d494e2022-07-22 19:26:55 -0500153 hostnameSignalMonitor = std::make_unique<sdbusplus::bus::match_t>(
Alan Kuoa8220702020-11-26 11:15:29 +0800154 *crow::connections::systemBus, propertiesMatchString, onPropertyUpdate,
155 nullptr);
156}
157} // namespace hostname_monitor
158} // namespace crow