mirror of
https://github.com/Icinga/icinga2.git
synced 2025-04-08 17:05:25 +02:00
GetCertificateCN(): if the CN is missing, fall back to the DNS SAN
if exactly one is given and use it as CN. Currently Icinga 2 populates both the DNS SAN and the subject CN of a newly issued certificate with the endpoint name. But the CN is limited to 64 characters. So endpoint names are. The only clean solution is omitting the CN for too long names. Icinga 2 must be able to extract the endpoint name from such certificates in the first place and exactly one DNS SAN is a legit source.
This commit is contained in:
parent
45452629db
commit
e7a21c1830
@ -9,6 +9,7 @@
|
||||
#include "base/application.hpp"
|
||||
#include "base/exception.hpp"
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
#include <memory>
|
||||
#include <openssl/opensslv.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/ssl.h>
|
||||
@ -399,7 +400,7 @@ void AddCRLToSSLContext(X509_STORE *x509_store, const String& crlPath)
|
||||
X509_VERIFY_PARAM_free(param);
|
||||
}
|
||||
|
||||
static String GetX509NameCN(X509_NAME *name)
|
||||
static String GetX509NameCN(X509_NAME* name, X509* fallback = nullptr)
|
||||
{
|
||||
char errbuf[256];
|
||||
char buffer[256];
|
||||
@ -407,12 +408,50 @@ static String GetX509NameCN(X509_NAME *name)
|
||||
int rc = X509_NAME_get_text_by_NID(name, NID_commonName, buffer, sizeof(buffer));
|
||||
|
||||
if (rc == -1) {
|
||||
ERR_error_string_n(ERR_peek_error(), errbuf, sizeof errbuf);
|
||||
auto err (ERR_peek_error());
|
||||
int totalSans = 0;
|
||||
int dnsSans = 0;
|
||||
|
||||
// Subject CN missing, fall back to the DNS SAN if exactly one given
|
||||
if (fallback) {
|
||||
std::unique_ptr<GENERAL_NAMES, void(*)(GENERAL_NAMES*)> sans (
|
||||
(GENERAL_NAMES*)X509_get_ext_d2i(fallback, NID_subject_alt_name, nullptr, nullptr),
|
||||
&GENERAL_NAMES_free
|
||||
);
|
||||
|
||||
if (sans) {
|
||||
const unsigned char* dnsSan = nullptr;
|
||||
totalSans = sk_GENERAL_NAME_num(sans.get());
|
||||
|
||||
for (int i = 0; i < totalSans; ++i) {
|
||||
auto gn (sk_GENERAL_NAME_value(sans.get(), i));
|
||||
|
||||
if (gn->type == GEN_DNS) {
|
||||
auto asn1Str (gn->d.uniformResourceIdentifier);
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
dnsSan = ASN1_STRING_data(asn1Str);
|
||||
#else /* OPENSSL_VERSION_NUMBER < 0x10100000L */
|
||||
dnsSan = ASN1_STRING_get0_data(asn1Str);
|
||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
|
||||
|
||||
++dnsSans;
|
||||
}
|
||||
}
|
||||
|
||||
if (dnsSans == 1) {
|
||||
return Convert::ToString(dnsSan);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ERR_error_string_n(err, errbuf, sizeof errbuf);
|
||||
Log(LogCritical, "SSL")
|
||||
<< "Error with x509 NAME getting text by NID: " << ERR_peek_error() << ", \"" << errbuf << "\"";
|
||||
<< "Error with x509 NAME getting text by NID: " << err << ", \"" << errbuf
|
||||
<< "\" (Also found " << dnsSans << " DNS SANs and " << totalSans - dnsSans << " others)";
|
||||
BOOST_THROW_EXCEPTION(openssl_error()
|
||||
<< boost::errinfo_api_function("X509_NAME_get_text_by_NID")
|
||||
<< errinfo_openssl_error(ERR_peek_error()));
|
||||
<< errinfo_openssl_error(err));
|
||||
}
|
||||
|
||||
return buffer;
|
||||
@ -426,7 +465,7 @@ static String GetX509NameCN(X509_NAME *name)
|
||||
*/
|
||||
String GetCertificateCN(const std::shared_ptr<X509>& certificate)
|
||||
{
|
||||
return GetX509NameCN(X509_get_subject_name(certificate.get()));
|
||||
return GetX509NameCN(X509_get_subject_name(certificate.get()), certificate.get());
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user