blob: 738dc1b22b464a75c816d378c6d7ce3bfcd04f0b [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{
14static std::unique_ptr<sdbusplus::bus::match::match> hostnameSignalMonitor;
15
16inline void installCertificate(const std::filesystem::path& certPath)
17{
18 crow::connections::systemBus->async_method_call(
Ed Tanous914e2d52022-01-07 11:38:34 -080019 [certPath](const boost::system::error_code ec) {
Ed Tanous002d39b2022-05-31 08:59:27 -070020 if (ec)
21 {
22 BMCWEB_LOG_ERROR << "Replace Certificate Fail..";
23 return;
24 }
Alan Kuoa8220702020-11-26 11:15:29 +080025
Ed Tanous002d39b2022-05-31 08:59:27 -070026 BMCWEB_LOG_INFO << "Replace HTTPs Certificate Success, "
27 "remove temporary certificate file..";
28 remove(certPath.c_str());
Alan Kuoa8220702020-11-26 11:15:29 +080029 },
30 "xyz.openbmc_project.Certs.Manager.Server.Https",
31 "/xyz/openbmc_project/certs/server/https/1",
32 "xyz.openbmc_project.Certs.Replace", "Replace", certPath.string());
33}
34
35inline int onPropertyUpdate(sd_bus_message* m, void* /* userdata */,
Ed Tanous81ce6092020-12-17 16:54:55 +000036 sd_bus_error* retError)
Alan Kuoa8220702020-11-26 11:15:29 +080037{
Ed Tanouse662eae2022-01-25 10:39:19 -080038 if (retError == nullptr || (sd_bus_error_is_set(retError) != 0))
Alan Kuoa8220702020-11-26 11:15:29 +080039 {
40 BMCWEB_LOG_ERROR << "Got sdbus error on match";
41 return 0;
42 }
43
44 sdbusplus::message::message message(m);
45 std::string iface;
Ed Tanousb9d36b42022-02-26 21:42:46 -080046 dbus::utility::DBusPropertiesMap changedProperties;
Alan Kuoa8220702020-11-26 11:15:29 +080047
48 message.read(iface, changedProperties);
Ed Tanousb9d36b42022-02-26 21:42:46 -080049 const std::string* hostname = nullptr;
50 for (const auto& propertyPair : changedProperties)
Alan Kuoa8220702020-11-26 11:15:29 +080051 {
Ed Tanousb9d36b42022-02-26 21:42:46 -080052 if (propertyPair.first == "HostName")
53 {
54 hostname = std::get_if<std::string>(&propertyPair.second);
55 }
Alan Kuoa8220702020-11-26 11:15:29 +080056 }
Alan Kuoa8220702020-11-26 11:15:29 +080057 if (hostname == nullptr)
58 {
Alan Kuoa8220702020-11-26 11:15:29 +080059 return 0;
60 }
61
62 BMCWEB_LOG_DEBUG << "Read hostname from signal: " << *hostname;
63 const std::string certFile = "/etc/ssl/certs/https/server.pem";
64
65 X509* cert = ensuressl::loadCert(certFile);
66 if (cert == nullptr)
67 {
68 BMCWEB_LOG_ERROR << "Failed to read cert";
69 return 0;
70 }
71
72 const int maxKeySize = 256;
73 std::array<char, maxKeySize> cnBuffer{};
74
75 int cnLength =
76 X509_NAME_get_text_by_NID(X509_get_subject_name(cert), NID_commonName,
77 cnBuffer.data(), cnBuffer.size());
78 if (cnLength == -1)
79 {
80 BMCWEB_LOG_ERROR << "Failed to read NID_commonName";
81 X509_free(cert);
82 return 0;
83 }
84 std::string_view cnValue(std::begin(cnBuffer),
85 static_cast<size_t>(cnLength));
86
87 EVP_PKEY* pPubKey = X509_get_pubkey(cert);
88 if (pPubKey == nullptr)
89 {
90 BMCWEB_LOG_ERROR << "Failed to get public key";
91 X509_free(cert);
92 return 0;
93 }
94 int isSelfSigned = X509_verify(cert, pPubKey);
95 EVP_PKEY_free(pPubKey);
96
97 BMCWEB_LOG_DEBUG << "Current HTTPs Certificate Subject CN: " << cnValue
98 << ", New HostName: " << *hostname
99 << ", isSelfSigned: " << isSelfSigned;
100
101 ASN1_IA5STRING* asn1 = static_cast<ASN1_IA5STRING*>(
102 X509_get_ext_d2i(cert, NID_netscape_comment, nullptr, nullptr));
Ed Tanouse662eae2022-01-25 10:39:19 -0800103 if (asn1 != nullptr)
Alan Kuoa8220702020-11-26 11:15:29 +0800104 {
Ed Tanous46ff87b2022-01-07 09:25:51 -0800105 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
Alan Kuoa8220702020-11-26 11:15:29 +0800106 std::string_view comment(reinterpret_cast<const char*>(asn1->data),
107 static_cast<size_t>(asn1->length));
108 BMCWEB_LOG_DEBUG << "x509Comment: " << comment;
109
110 if (ensuressl::x509Comment == comment && isSelfSigned == 1 &&
111 cnValue != *hostname)
112 {
113 BMCWEB_LOG_INFO << "Ready to generate new HTTPs "
114 << "certificate with subject cn: " << *hostname;
115
116 ensuressl::generateSslCertificate("/tmp/hostname_cert.tmp",
117 *hostname);
118 installCertificate("/tmp/hostname_cert.tmp");
119 }
120 ASN1_STRING_free(asn1);
121 }
122 X509_free(cert);
123 return 0;
124}
125
126inline void registerHostnameSignal()
127{
128 BMCWEB_LOG_INFO << "Register HostName PropertiesChanged Signal";
129 std::string propertiesMatchString =
130 ("type='signal',"
131 "interface='org.freedesktop.DBus.Properties',"
132 "path='/xyz/openbmc_project/network/config',"
133 "arg0='xyz.openbmc_project.Network.SystemConfiguration',"
134 "member='PropertiesChanged'");
135
136 hostnameSignalMonitor = std::make_unique<sdbusplus::bus::match::match>(
137 *crow::connections::systemBus, propertiesMatchString, onPropertyUpdate,
138 nullptr);
139}
140} // namespace hostname_monitor
141} // namespace crow
142#endif