blob: cb84ad67d0636072300241670cbba283f619b2b8 [file] [log] [blame]
Alan Kuoa8220702020-11-26 11:15:29 +08001#pragma once
2#ifdef BMCWEB_ENABLE_SSL
Alan Kuoa8220702020-11-26 11:15:29 +08003#include <dbus_singleton.hpp>
Ed Tanousb9d36b42022-02-26 21:42:46 -08004#include <dbus_utility.hpp>
Ed Tanous168e20c2021-12-13 14:39:53 -08005#include <include/dbus_utility.hpp>
Alan Kuoa8220702020-11-26 11:15:29 +08006#include <sdbusplus/bus/match.hpp>
7#include <sdbusplus/message/types.hpp>
8#include <ssl_key_handler.hpp>
9
10namespace crow
11{
12namespace hostname_monitor
13{
Ed Tanouscf9e4172022-12-21 09:30:16 -080014// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
Patrick Williams59d494e2022-07-22 19:26:55 -050015static std::unique_ptr<sdbusplus::bus::match_t> hostnameSignalMonitor;
Alan Kuoa8220702020-11-26 11:15:29 +080016
17inline void installCertificate(const std::filesystem::path& certPath)
18{
19 crow::connections::systemBus->async_method_call(
Ed Tanous914e2d52022-01-07 11:38:34 -080020 [certPath](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -070021 if (ec)
22 {
23 BMCWEB_LOG_ERROR << "Replace Certificate Fail..";
24 return;
25 }
Alan Kuoa8220702020-11-26 11:15:29 +080026
Ed Tanous002d39b2022-05-31 08:59:27 -070027 BMCWEB_LOG_INFO << "Replace HTTPs Certificate Success, "
28 "remove temporary certificate file..";
29 remove(certPath.c_str());
Alan Kuoa8220702020-11-26 11:15:29 +080030 },
31 "xyz.openbmc_project.Certs.Manager.Server.Https",
32 "/xyz/openbmc_project/certs/server/https/1",
33 "xyz.openbmc_project.Certs.Replace", "Replace", certPath.string());
34}
35
36inline int onPropertyUpdate(sd_bus_message* m, void* /* userdata */,
Ed Tanous81ce6092020-12-17 16:54:55 +000037 sd_bus_error* retError)
Alan Kuoa8220702020-11-26 11:15:29 +080038{
Ed Tanouse662eae2022-01-25 10:39:19 -080039 if (retError == nullptr || (sd_bus_error_is_set(retError) != 0))
Alan Kuoa8220702020-11-26 11:15:29 +080040 {
41 BMCWEB_LOG_ERROR << "Got sdbus error on match";
42 return 0;
43 }
44
Patrick Williams59d494e2022-07-22 19:26:55 -050045 sdbusplus::message_t message(m);
Alan Kuoa8220702020-11-26 11:15:29 +080046 std::string iface;
Ed Tanousb9d36b42022-02-26 21:42:46 -080047 dbus::utility::DBusPropertiesMap changedProperties;
Alan Kuoa8220702020-11-26 11:15:29 +080048
49 message.read(iface, changedProperties);
Ed Tanousb9d36b42022-02-26 21:42:46 -080050 const std::string* hostname = nullptr;
51 for (const auto& propertyPair : changedProperties)
Alan Kuoa8220702020-11-26 11:15:29 +080052 {
Ed Tanousb9d36b42022-02-26 21:42:46 -080053 if (propertyPair.first == "HostName")
54 {
55 hostname = std::get_if<std::string>(&propertyPair.second);
56 }
Alan Kuoa8220702020-11-26 11:15:29 +080057 }
Alan Kuoa8220702020-11-26 11:15:29 +080058 if (hostname == nullptr)
59 {
Alan Kuoa8220702020-11-26 11:15:29 +080060 return 0;
61 }
62
63 BMCWEB_LOG_DEBUG << "Read hostname from signal: " << *hostname;
64 const std::string certFile = "/etc/ssl/certs/https/server.pem";
65
66 X509* cert = ensuressl::loadCert(certFile);
67 if (cert == nullptr)
68 {
69 BMCWEB_LOG_ERROR << "Failed to read cert";
70 return 0;
71 }
72
73 const int maxKeySize = 256;
74 std::array<char, maxKeySize> cnBuffer{};
75
76 int cnLength =
77 X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName,
78 cnBuffer.data(), cnBuffer.size());
79 if (cnLength == -1)
80 {
81 BMCWEB_LOG_ERROR << "Failed to read NID_commonName";
82 X509_free(cert);
83 return 0;
84 }
85 std::string_view cnValue(std::begin(cnBuffer),
86 static_cast<size_t>(cnLength));
87
88 EVP_PKEY* pPubKey = X509_get_pubkey(cert);
89 if (pPubKey == nullptr)
90 {
91 BMCWEB_LOG_ERROR << "Failed to get public key";
92 X509_free(cert);
93 return 0;
94 }
95 int isSelfSigned = X509_verify(cert, pPubKey);
96 EVP_PKEY_free(pPubKey);
97
98 BMCWEB_LOG_DEBUG << "Current HTTPs Certificate Subject CN: " << cnValue
99 << ", New HostName: " << *hostname
100 << ", isSelfSigned: " << isSelfSigned;
101
102 ASN1_IA5STRING* asn1 = static_cast<ASN1_IA5STRING*>(
103 X509_get_ext_d2i(cert, NID_netscape_comment, nullptr, nullptr));
Ed Tanouse662eae2022-01-25 10:39:19 -0800104 if (asn1 != nullptr)
Alan Kuoa8220702020-11-26 11:15:29 +0800105 {
Ed Tanous46ff87b2022-01-07 09:25:51 -0800106 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
Alan Kuoa8220702020-11-26 11:15:29 +0800107 std::string_view comment(reinterpret_cast<const char*>(asn1->data),
108 static_cast<size_t>(asn1->length));
109 BMCWEB_LOG_DEBUG << "x509Comment: " << comment;
110
111 if (ensuressl::x509Comment == comment && isSelfSigned == 1 &&
112 cnValue != *hostname)
113 {
114 BMCWEB_LOG_INFO << "Ready to generate new HTTPs "
115 << "certificate with subject cn: " << *hostname;
116
117 ensuressl::generateSslCertificate("/tmp/hostname_cert.tmp",
118 *hostname);
119 installCertificate("/tmp/hostname_cert.tmp");
120 }
121 ASN1_STRING_free(asn1);
122 }
123 X509_free(cert);
124 return 0;
125}
126
127inline void registerHostnameSignal()
128{
129 BMCWEB_LOG_INFO << "Register HostName PropertiesChanged Signal";
130 std::string propertiesMatchString =
131 ("type='signal',"
132 "interface='org.freedesktop.DBus.Properties',"
133 "path='/xyz/openbmc_project/network/config',"
134 "arg0='xyz.openbmc_project.Network.SystemConfiguration',"
135 "member='PropertiesChanged'");
136
Patrick Williams59d494e2022-07-22 19:26:55 -0500137 hostnameSignalMonitor = std::make_unique<sdbusplus::bus::match_t>(
Alan Kuoa8220702020-11-26 11:15:29 +0800138 *crow::connections::systemBus, propertiesMatchString, onPropertyUpdate,
139 nullptr);
140}
141} // namespace hostname_monitor
142} // namespace crow
143#endif