1 #pragma once 2 #ifdef BMCWEB_ENABLE_SSL 3 #include <dbus_singleton.hpp> 4 #include <dbus_utility.hpp> 5 #include <include/dbus_utility.hpp> 6 #include <sdbusplus/bus/match.hpp> 7 #include <sdbusplus/message/types.hpp> 8 #include <ssl_key_handler.hpp> 9 10 namespace crow 11 { 12 namespace hostname_monitor 13 { 14 static std::unique_ptr<sdbusplus::bus::match::match> hostnameSignalMonitor; 15 16 inline void installCertificate(const std::filesystem::path& certPath) 17 { 18 crow::connections::systemBus->async_method_call( 19 [certPath](const boost::system::error_code ec) { 20 if (ec) 21 { 22 BMCWEB_LOG_ERROR << "Replace Certificate Fail.."; 23 return; 24 } 25 26 BMCWEB_LOG_INFO << "Replace HTTPs Certificate Success, " 27 "remove temporary certificate file.."; 28 remove(certPath.c_str()); 29 }, 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 35 inline int onPropertyUpdate(sd_bus_message* m, void* /* userdata */, 36 sd_bus_error* retError) 37 { 38 if (retError == nullptr || (sd_bus_error_is_set(retError) != 0)) 39 { 40 BMCWEB_LOG_ERROR << "Got sdbus error on match"; 41 return 0; 42 } 43 44 sdbusplus::message::message message(m); 45 std::string iface; 46 dbus::utility::DBusPropertiesMap changedProperties; 47 48 message.read(iface, changedProperties); 49 const std::string* hostname = nullptr; 50 for (const auto& propertyPair : changedProperties) 51 { 52 if (propertyPair.first == "HostName") 53 { 54 hostname = std::get_if<std::string>(&propertyPair.second); 55 } 56 } 57 if (hostname == nullptr) 58 { 59 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)); 103 if (asn1 != nullptr) 104 { 105 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) 106 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 126 inline 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 143