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