Skip to content
Snippets Groups Projects
Commit 174c45b3 authored by Adrien Béraud's avatar Adrien Béraud
Browse files

tlsvalidator: add missing certificate details

Change-Id: I5094741acc1b395947bac34321cfc05b3e5328ae
parent acb3a44a
No related branches found
No related tags found
No related merge requests found
......@@ -27,6 +27,7 @@
#include "config.h"
#endif
#include <opendht/infohash.h> // for toHex
#include <dhtnet/certstore.h>
#include "fileutils.h"
......@@ -116,7 +117,9 @@ const CallbackMatrix1D<TlsValidator::CertificateDetails, TlsValidator, TlsValida
/* SERIAL_NUMBER */ &TlsValidator::getSerialNumber,
/* ISSUER */ &TlsValidator::getIssuer,
/* SUBJECT_KEY_ALGORITHM */ &TlsValidator::getSubjectKeyAlgorithm,
/* SUBJECT_KEY */ &TlsValidator::getSubjectKey,
/* CN */ &TlsValidator::getCN,
/* UID */ &TlsValidator::getUID,
/* N */ &TlsValidator::getN,
/* O */ &TlsValidator::getO,
/* SIGNATURE_ALGORITHM */ &TlsValidator::getSignatureAlgorithm,
......@@ -124,6 +127,10 @@ const CallbackMatrix1D<TlsValidator::CertificateDetails, TlsValidator, TlsValida
/* SHA1_FINGERPRINT */ &TlsValidator::getSha1Fingerprint,
/* PUBLIC_KEY_ID */ &TlsValidator::getPublicKeyId,
/* ISSUER_DN */ &TlsValidator::getIssuerDN,
/* ISSUER_CN */ &TlsValidator::getIssuerCN,
/* ISSUER_UID */ &TlsValidator::getIssuerUID,
/* ISSUER_N */ &TlsValidator::getIssuerN,
/* ISSUER_O */ &TlsValidator::getIssuerO,
/* NEXT_EXPECTED_UPDATE_DATE */ &TlsValidator::getIssuerDN, // TODO
/* OUTGOING_SERVER */ &TlsValidator::outgoingServer,
/* IS_CA */ &TlsValidator::isCA,
......@@ -189,7 +196,9 @@ const EnumClassNames<TlsValidator::CertificateDetails> TlsValidator::Certificate
/* SERIAL_NUMBER */ libjami::Certificate::DetailsNames::SERIAL_NUMBER,
/* ISSUER */ libjami::Certificate::DetailsNames::ISSUER,
/* SUBJECT_KEY_ALGORITHM */ libjami::Certificate::DetailsNames::SUBJECT_KEY_ALGORITHM,
/* SUBJECT_KEY */ libjami::Certificate::DetailsNames::SUBJECT_KEY,
/* CN */ libjami::Certificate::DetailsNames::CN,
/* UID */ libjami::Certificate::DetailsNames::UID,
/* N */ libjami::Certificate::DetailsNames::N,
/* O */ libjami::Certificate::DetailsNames::O,
/* SIGNATURE_ALGORITHM */ libjami::Certificate::DetailsNames::SIGNATURE_ALGORITHM,
......@@ -197,6 +206,10 @@ const EnumClassNames<TlsValidator::CertificateDetails> TlsValidator::Certificate
/* SHA1_FINGERPRINT */ libjami::Certificate::DetailsNames::SHA1_FINGERPRINT,
/* PUBLIC_KEY_ID */ libjami::Certificate::DetailsNames::PUBLIC_KEY_ID,
/* ISSUER_DN */ libjami::Certificate::DetailsNames::ISSUER_DN,
/* ISSUER_CN */ libjami::Certificate::DetailsNames::ISSUER_CN,
/* ISSUER_UID */ libjami::Certificate::DetailsNames::ISSUER_UID,
/* ISSUER_N */ libjami::Certificate::DetailsNames::ISSUER_N,
/* ISSUER_O */ libjami::Certificate::DetailsNames::ISSUER_O,
/* NEXT_EXPECTED_UPDATE_DATE */ libjami::Certificate::DetailsNames::NEXT_EXPECTED_UPDATE_DATE,
/* OUTGOING_SERVER */ libjami::Certificate::DetailsNames::OUTGOING_SERVER,
/* IS_CA */ libjami::Certificate::DetailsNames::IS_CA,
......@@ -311,7 +324,7 @@ TlsValidator::getStringValue(const TlsValidator::CertificateCheck check,
case CheckValues::PASSED:
case CheckValues::FAILED:
case CheckValues::UNSUPPORTED:
return CheckValuesNames[result.first];
return std::string(CheckValuesNames[result.first]);
case CheckValues::ISO_DATE:
// TODO validate date
// return CheckValues::FAILED;
......@@ -322,7 +335,7 @@ TlsValidator::getStringValue(const TlsValidator::CertificateCheck check,
return result.second;
default:
// Consider any other case (such as forced int->CheckValues casting) as failed
return CheckValuesNames[CheckValues::FAILED];
return std::string(CheckValuesNames[CheckValues::FAILED]);
};
}
......@@ -339,7 +352,7 @@ TlsValidator::isValid(bool verbose)
if (enforcedCheckType[check] == CheckValuesType::BOOLEAN) {
if (((this->*(checkCallback[check]))()).first == CheckValues::FAILED) {
if (verbose)
JAMI_WARN("Check failed: %s", CertificateCheckNames[check]);
JAMI_WARNING("Check failed: {}", CertificateCheckNames[check]);
return false;
}
}
......@@ -356,11 +369,11 @@ TlsValidator::getSerializedChecks()
std::map<std::string, std::string> ret;
if (not certificateFound_) {
// Instead of checking `certificateFound` everywhere, handle it once
ret[CertificateCheckNames[CertificateCheck::EXIST]] = getStringValue(CertificateCheck::EXIST,
ret[std::string(CertificateCheckNames[CertificateCheck::EXIST])] = getStringValue(CertificateCheck::EXIST,
exist());
} else {
for (const CertificateCheck check : Matrix0D<CertificateCheck>())
ret[CertificateCheckNames[check]] = getStringValue(check,
ret[std::string(CertificateCheckNames[check])] = getStringValue(check,
(this->*(checkCallback[check]))());
}
......@@ -375,7 +388,7 @@ TlsValidator::getSerializedDetails()
{
std::map<std::string, std::string> ret;
if (certificateFound_) {
for (const CertificateDetails det : Matrix0D<CertificateDetails>()) {
for (const CertificateDetails& det : Matrix0D<CertificateDetails>()) {
const CheckResult r = (this->*(getterCallback[det]))();
std::string val;
// TODO move this to a fuction
......@@ -393,8 +406,8 @@ TlsValidator::getSerializedDetails()
default:
val = r.second;
break;
};
ret[CertificateDetailsNames[det]] = val;
}
ret[std::string(CertificateDetailsNames[det])] = val;
}
}
return ret;
......@@ -414,21 +427,6 @@ checkError(int err, char* copy_buffer, size_t size)
: "");
}
/**
* Some fields, such as the binary signature need to be converted to an
* ASCII-hexadecimal representation before being sent to DBus as it will cause the
* process to assert
*/
static std::string
binaryToHex(const uint8_t* input, size_t input_sz)
{
std::ostringstream ret;
ret << std::hex;
for (size_t i = 0; i < input_sz; i++)
ret << std::setfill('0') << std::setw(2) << (unsigned) input[i];
return ret.str();
}
/**
* Convert a time_t to an ISO date string
*/
......@@ -451,7 +449,7 @@ checkBinaryError(int err, char* copy_buffer, size_t resultSize)
{
if (err == GNUTLS_E_SUCCESS)
return TlsValidator::CheckResult(TlsValidator::CheckValues::CUSTOM,
binaryToHex(reinterpret_cast<uint8_t*>(copy_buffer),
dht::toHex(reinterpret_cast<uint8_t*>(copy_buffer),
resultSize));
else
return TlsValidator::CheckResult(TlsValidator::CheckValues::UNSUPPORTED, "");
......@@ -1185,8 +1183,9 @@ TlsValidator::getIssuer()
TlsValidator::CheckResult
TlsValidator::getSubjectKeyAlgorithm()
{
unsigned key_length = 0;
gnutls_pk_algorithm_t algo = (gnutls_pk_algorithm_t)
gnutls_x509_crt_get_pk_algorithm(x509crt_->cert, nullptr);
gnutls_x509_crt_get_pk_algorithm(x509crt_->cert, &key_length);
if (algo < 0)
return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
......@@ -1196,7 +1195,25 @@ TlsValidator::getSubjectKeyAlgorithm()
if (!name)
return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
return TlsValidator::CheckResult(CheckValues::CUSTOM, name);
if (key_length)
return TlsValidator::CheckResult(CheckValues::CUSTOM, fmt::format("{} ({} bits)", name, key_length));
else
return TlsValidator::CheckResult(CheckValues::CUSTOM, name);
}
/**
* The subject public key
*/
TlsValidator::CheckResult
TlsValidator::getSubjectKey()
{
try {
std::vector<uint8_t> data;
x509crt_->getPublicKey().pack(data);
return TlsValidator::CheckResult(CheckValues::CUSTOM, dht::toHex(data));
} catch (const dht::crypto::CryptoException& e) {
return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, e.what());
}
}
/**
......@@ -1216,6 +1233,22 @@ TlsValidator::getCN()
return checkError(err, copy_buffer, resultSize);
}
/**
* The 'UID' section of a DN (RFC4514)
*/
TlsValidator::CheckResult
TlsValidator::getUID()
{
size_t resultSize = sizeof(copy_buffer);
int err = gnutls_x509_crt_get_dn_by_oid(x509crt_->cert,
GNUTLS_OID_LDAP_UID,
0,
0,
copy_buffer,
&resultSize);
return checkError(err, copy_buffer, resultSize);
}
/**
* The 'N' section of a DN (RFC4514)
*/
......@@ -1328,6 +1361,70 @@ TlsValidator::getIssuerDN()
return checkError(err, copy_buffer, resultSize);
}
/**
* If the certificate is not self signed, return the issuer CN
*/
TlsValidator::CheckResult
TlsValidator::getIssuerCN()
{
size_t resultSize = sizeof(copy_buffer);
int err = gnutls_x509_crt_get_issuer_dn_by_oid(x509crt_->cert,
GNUTLS_OID_X520_COMMON_NAME,
0,
0,
copy_buffer,
&resultSize);
return checkError(err, copy_buffer, resultSize);
}
/**
* If the certificate is not self signed, return the issuer UID
*/
TlsValidator::CheckResult
TlsValidator::getIssuerUID()
{
size_t resultSize = sizeof(copy_buffer);
int err = gnutls_x509_crt_get_issuer_dn_by_oid(x509crt_->cert,
GNUTLS_OID_LDAP_UID,
0,
0,
copy_buffer,
&resultSize);
return checkError(err, copy_buffer, resultSize);
}
/**
* If the certificate is not self signed, return the issuer N
*/
TlsValidator::CheckResult
TlsValidator::getIssuerN()
{
size_t resultSize = sizeof(copy_buffer);
int err = gnutls_x509_crt_get_issuer_dn_by_oid(x509crt_->cert,
GNUTLS_OID_X520_NAME,
0,
0,
copy_buffer,
&resultSize);
return checkError(err, copy_buffer, resultSize);
}
/**
* If the certificate is not self signed, return the issuer O
*/
TlsValidator::CheckResult
TlsValidator::getIssuerO()
{
size_t resultSize = sizeof(copy_buffer);
int err = gnutls_x509_crt_get_issuer_dn_by_oid(x509crt_->cert,
GNUTLS_OID_X520_ORGANIZATION_NAME,
0,
0,
copy_buffer,
&resultSize);
return checkError(err, copy_buffer, resultSize);
}
/**
* Get the expiration date
*
......
......@@ -122,7 +122,9 @@ public:
SERIAL_NUMBER,
ISSUER,
SUBJECT_KEY_ALGORITHM,
SUBJECT_KEY,
CN,
UID,
N,
O,
SIGNATURE_ALGORITHM,
......@@ -130,6 +132,10 @@ public:
SHA1_FINGERPRINT,
PUBLIC_KEY_ID,
ISSUER_DN,
ISSUER_CN,
ISSUER_UID,
ISSUER_N,
ISSUER_O,
NEXT_EXPECTED_UPDATE_DATE,
OUTGOING_SERVER, /** The hostname/outgoing server used for this certificate */
IS_CA,
......@@ -233,7 +239,9 @@ public:
CheckResult getSerialNumber();
CheckResult getIssuer();
CheckResult getSubjectKeyAlgorithm();
CheckResult getSubjectKey();
CheckResult getCN();
CheckResult getUID();
CheckResult getN();
CheckResult getO();
CheckResult getSignatureAlgorithm();
......@@ -241,6 +249,10 @@ public:
CheckResult getSha1Fingerprint();
CheckResult getPublicKeyId();
CheckResult getIssuerDN();
CheckResult getIssuerCN();
CheckResult getIssuerUID();
CheckResult getIssuerN();
CheckResult getIssuerO();
CheckResult outgoingServer();
CheckResult isCA();
......
......@@ -51,7 +51,7 @@ enum_class_size()
template<class Row, typename Value, typename A = Value>
struct Matrix1D
{
Matrix1D(std::initializer_list<std::initializer_list<Value>> s);
constexpr Matrix1D(std::initializer_list<std::initializer_list<Value>> s);
// Row is a built-in type ("int" by default)
Value operator[](Row v);
......@@ -136,7 +136,7 @@ struct Matrix0D
* A helper to type to match serializable string to enum elements
*/
template<class Row>
using EnumClassNames = Matrix1D<Row, const char*>;
using EnumClassNames = Matrix1D<Row, std::string_view>;
/**
* Create a matrix type with 2 enum class dimensions M[I,J] = V
......@@ -171,14 +171,14 @@ using CallbackMatrix2D = Matrix2D<Row, Column, void (Class::*)(Args... args)>;
*/
template<class Row, typename Value, typename Accessor>
Matrix1D<Row, Value, Accessor>::Matrix1D(std::initializer_list<std::initializer_list<Value>> s)
constexpr Matrix1D<Row, Value, Accessor>::Matrix1D(std::initializer_list<std::initializer_list<Value>> s)
: data_(*std::begin(s))
{
static_assert(std::is_enum<Row>(), "Row has to be an enum class");
static_assert((int) Row::COUNT__ > 0, "Row need a COUNT__ element");
// FIXME C++14, use static_assert and make the ctor constexpr
assert(std::begin(s)->size()
assert(s.begin()->size()
== enum_class_size<Row>()); //,"Matrix row have to match the enum class size");
}
......
......@@ -76,7 +76,9 @@ constexpr static char VERSION_NUMBER[] = "VERSION_NUMBER";
constexpr static char SERIAL_NUMBER[] = "SERIAL_NUMBER";
constexpr static char ISSUER[] = "ISSUER";
constexpr static char SUBJECT_KEY_ALGORITHM[] = "SUBJECT_KEY_ALGORITHM";
constexpr static char SUBJECT_KEY[] = "SUBJECT_KEY";
constexpr static char CN[] = "CN";
constexpr static char UID[] = "UID";
constexpr static char N[] = "N";
constexpr static char O[] = "O";
constexpr static char SIGNATURE_ALGORITHM[] = "SIGNATURE_ALGORITHM";
......@@ -84,6 +86,10 @@ constexpr static char MD5_FINGERPRINT[] = "MD5_FINGERPRINT";
constexpr static char SHA1_FINGERPRINT[] = "SHA1_FINGERPRINT";
constexpr static char PUBLIC_KEY_ID[] = "PUBLIC_KEY_ID";
constexpr static char ISSUER_DN[] = "ISSUER_DN";
constexpr static char ISSUER_CN[] = "ISSUER_CN";
constexpr static char ISSUER_UID[] = "ISSUER_UID";
constexpr static char ISSUER_N[] = "ISSUER_N";
constexpr static char ISSUER_O[] = "ISSUER_O";
constexpr static char NEXT_EXPECTED_UPDATE_DATE[] = "NEXT_EXPECTED_UPDATE_DATE";
constexpr static char OUTGOING_SERVER[] = "OUTGOING_SERVER";
constexpr static char IS_CA[] = "IS_CA";
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment