24#include <opendht/infohash.h>
25#include <dhtnet/certstore.h>
47#include <sys/socket.h>
48#include <netinet/tcp.h>
49#include <netinet/in.h>
53#define close(x) closesocket(x)
81 TlsValidator::checkCallback = {{
107 TlsValidator::getterCallback = {{
137 CheckValuesType::BOOLEAN,
138 CheckValuesType::BOOLEAN,
139 CheckValuesType::BOOLEAN,
140 CheckValuesType::BOOLEAN,
141 CheckValuesType::BOOLEAN,
142 CheckValuesType::BOOLEAN,
143 CheckValuesType::BOOLEAN,
144 CheckValuesType::BOOLEAN,
145 CheckValuesType::BOOLEAN,
146 CheckValuesType::BOOLEAN,
147 CheckValuesType::BOOLEAN,
148 CheckValuesType::BOOLEAN,
149 CheckValuesType::BOOLEAN,
150 CheckValuesType::BOOLEAN,
151 CheckValuesType::BOOLEAN,
152 CheckValuesType::BOOLEAN,
153 CheckValuesType::BOOLEAN,
154 CheckValuesType::BOOLEAN,
155 CheckValuesType::BOOLEAN,
156 CheckValuesType::BOOLEAN,
157 CheckValuesType::BOOLEAN,
225 {{
true,
true,
true,
false,
false,
false}},
226 {{
false,
false,
true,
true,
false,
false}},
227 {{
false,
false,
true,
false,
true,
false}},
228 {{
false,
false,
true,
false,
false,
true}},
232 const std::vector<std::vector<uint8_t>>&
crtChain)
237 const std::string& certificate,
240 const std::string&
caList)
241 : certStore_(certStore)
242 , certificatePath_(certificate)
245 , certificateFound_(
false)
250 certificateFileFound_ =
true;
251 }
catch (
const std::exception&
e) {
256 x509crt_ = std::make_shared<dht::crypto::Certificate>(
certificate_raw);
257 certificateContent_ = x509crt_->getPacked();
258 certificateFound_ =
true;
259 }
catch (
const std::exception&
e) {
266 privateKeyFound_ =
true;
268 privateKeyMatch_ =
key_tmp.getPublicKey().getId() == x509crt_->getId();
269 }
catch (
const dht::crypto::DecryptError&
d) {
273 privateKeyFound_ =
true;
274 privateKeyPassword_ =
true;
275 }
catch (
const std::exception&
e) {
281 : certStore_(certStore)
284 x509crt_ = std::make_shared<dht::crypto::Certificate>(
certificate_raw);
285 certificateContent_ = x509crt_->getPacked();
286 certificateFound_ =
true;
287 }
catch (
const std::exception&
e) {
293 const std::shared_ptr<dht::crypto::Certificate>&
crt)
294 : certStore_(certStore)
295 , certificateFound_(
true)
299 throw std::invalid_argument(
"Certificate must be set");
301 certificateContent_ = x509crt_->getPacked();
302 }
catch (
const std::exception&
e) {
318 assert(acceptedCheckValuesResult[enforcedCheckType[
check]][result.first]);
320 switch (result.first) {
324 return std::string(CheckValuesNames[result.first]);
328 return result.second;
332 return result.second;
363std::map<std::string, std::string>
366 std::map<std::string, std::string>
ret;
367 if (
not certificateFound_) {
373 ret[std::string(CertificateCheckNames[
check])] = getStringValue(
check, (this->*(checkCallback[
check]))());
382std::map<std::string, std::string>
385 std::map<std::string, std::string>
ret;
386 if (certificateFound_) {
395 val = CheckValuesNames[r.first];
406 ret[std::string(CertificateDetailsNames[
det])] =
val;
454TlsValidator::compareToCa()
458 return caValidationOutput_;
464 auto root_cas = certStore_.getTrustedCertificates();
469 if (
not caListPath_.empty()) {
470 if (std::filesystem::is_directory(caListPath_))
477 auto crts = x509crt_->getChain();
484 &caValidationOutput_,
495 return caValidationOutput_;
507int TlsValidator::verifyHostnameCertificate(const std::string& host, const uint16_t port)
510 unsigned int status = (
unsigned) -1;
511 const char *
errptr =
nullptr;
534 JAMI_ERR(
"Unable to create socket.");
546 memset(&name, 0,
sizeof(name));
567 JAMI_ERR(
"Unable to connect to hostname %s at port %d",
570 }
else if (
err > 0) {
587 JAMI_ERR(
"Unable to connect to hostname %s at port %d",
host.c_str(),
port);
602 JAMI_ERR(
"Unable to set TCP_NODELAY.");
615 JAMI_ERR(
"Unable to load credentials.");
670#if GNUTLS_VERSION_AT_LEAST_3_1_4
677 JAMI_ERR(
"Certificate validation failed - %s\n",
msg.data);
681 JAMI_ERR(
"Certificate validation failed with code 0x%x.", status);
708 JAMI_ERR(
"Hostname %s does not match certificate.",
host.c_str());
725 JAMI_DBG(
"Hostname %s seems to point to a valid server.",
host.c_str());
747 if (privateKeyFound_)
751 dht::crypto::PrivateKey
key_tmp(certificateContent_);
752 }
catch (
const std::exception&
e) {
756 JAMI_DBG(
"Key from %s seems valid.", certificatePath_.c_str());
832 if (
not privateKeyFound_)
878 namespace fs = std::filesystem;
880 if (privateKeyPath_.empty())
883 fs::path
dir = fs::path(privateKeyPath_).parent_path();
892 if (!fs::is_directory(
st))
895 auto perm =
st.permissions();
897 bool ownerRead = (
perm & fs::perms::owner_read) != fs::perms::none;
898 bool ownerExec = (
perm & fs::perms::owner_exec) != fs::perms::none;
899 bool groupAny = (
perm & (fs::perms::group_read | fs::perms::group_write | fs::perms::group_exec))
901 bool othersAny = (
perm & (fs::perms::others_read | fs::perms::others_write | fs::perms::others_exec))
911 namespace fs = std::filesystem;
913 if (certificatePath_.empty())
916 fs::path
dir = fs::path(certificatePath_).parent_path();
925 if (!fs::is_directory(
st))
928 auto perm =
st.permissions();
930 bool ownerRead = (
perm & fs::perms::owner_read) != fs::perms::none;
931 bool ownerExec = (
perm & fs::perms::owner_exec) != fs::perms::none;
932 bool groupAny = (
perm & (fs::perms::group_read | fs::perms::group_write | fs::perms::group_exec))
934 bool othersAny = (
perm & (fs::perms::others_read | fs::perms::others_write | fs::perms::others_exec))
1084 return (x509crt_
and x509crt_->issuer);
1140 if (
not x509crt_->issuer) {
1141 auto icrt = certStore_.findIssuer(x509crt_);
1179 std::vector<uint8_t> data;
1180 x509crt_->getPublicKey().pack(data);
1182 }
catch (
const dht::crypto::CryptoException&
e) {
1372 if (
not certificateFound_)
1388 if (
not certificateFound_)
CheckResult getSignatureAlgorithm()
Return the algorithm used to sign the Key.
CheckResult privateKeyStoragePermissions()
CheckResult requirePrivateKeyPassword()
If the key need decryption.
CheckResult getIssuerUID()
If the certificate is not self signed, return the issuer UID.
@ NUMBER
The check value cannot be represented with a finite set of values.
@ ISO_DATE
The operating system doesn't support or require the check
@ UNSUPPORTED
Equivalent of a boolean "false"
@ CUSTOM
The check value is an ISO 8601 date YYYY-MM-DD[TH24:MM:SS+00:00]
@ FAILED
Equivalent of a boolean "true"
CheckResult privateKeyDirectoryPermissions()
CheckResult getSerialNumber()
Return the certificate serial number.
CheckResult validAuthority()
The provided authority is invalid.
CheckResult activated()
If the activation value is in the past.
CheckResult keyMatch()
The provided key can be used along with the certificate.
CheckResult getN()
The 'N' section of a DN (RFC4514)
CheckResult getO()
The 'O' section of a DN (RFC4514)
CheckResult notRevoked()
Check if the certificate has been revoked.
CheckResult getActivationDate()
Get the activation date.
CheckResult notSelfSigned()
The certificate is not self signed.
CheckResult getVersionNumber()
Return the certificate version.
CheckResult strongSigning()
If the algorithm used to sign the certificate is considered weak by modern standard.
CheckResult getPublicKeyId()
Return an hexadecimal identifier.
CertificateCheck
All validation fields.
@ EXIST
Some operating systems require keys to have extra attributes
CheckResult authorityMatch()
Check if the authority match the certificate.
CheckResult getIssuer()
If the certificate is not self signed, return the issuer.
bool hasCa() const
A certificate authority has been provided.
CheckResult isCA()
If the certificate is not self signed, return the issuer.
CheckResult notExpired()
Check if the certificate is not expired.
CheckResult getUID()
The 'UID' section of a DN (RFC4514)
CheckResult getIssuerO()
If the certificate is not self signed, return the issuer O.
CheckResult getSubjectKeyAlgorithm()
The algorithm used to sign the certificate details (rather than the certificate itself)
bool isValid(bool verbose=false)
Check if all boolean check passed return true if there was no FAILED checks.
CheckResult getIssuerDN()
If the certificate is not self signed, return the issuer DN (RFC4514)
CheckResult outgoingServer()
The expected outgoing server domain.
CheckResult knownAuthority()
When an account require an authority known by the system (like /usr/share/ssl/certs) then the whole c...
CheckResult privateKeySelinuxAttributes()
SELinux provide additional key protection mechanism.
std::pair< CheckValues, std::string > CheckResult
CheckResult getPublicSignature()
An hexadecimal representation of the signature.
CheckResult getExpirationDate()
Get the expiration date.
CertificateDetails
Informative fields about a certificate.
CheckResult exist()
The file has been found.
CheckResult valid()
The certificate is invalid compared to the authority.
TlsValidator(const dhtnet::tls::CertificateStore &certStore, const std::string &certificate, const std::string &privatekey="", const std::string &privatekeyPasswd="", const std::string &caList="")
Create a TlsValidator for a given certificate.
CheckResult getMd5Fingerprint()
Compute the key fingerprint.
CheckResult hasPrivateKey()
Check if the Validator have access to a private key.
std::map< std::string, std::string > getSerializedChecks()
Convert all checks results into a string map.
CheckResult getSubjectKey()
The subject public key.
CheckResult publicKeyStoragePermissions()
CheckResult getIssuerN()
If the certificate is not self signed, return the issuer N.
CheckResult privateKeyStorageLocation()
Certificate should be located in specific path on some operating systems.
CheckResult publicKeyStorageLocation()
Certificate should be located in specific path on some operating systems.
CheckResult getIssuerCN()
If the certificate is not self signed, return the issuer CN.
CheckResult getSha1Fingerprint()
Compute the key fingerprint.
std::map< std::string, std::string > getSerializedDetails()
Get a map with all common certificate details.
CheckResult publicKeySelinuxAttributes()
SELinux provide additional key protection mechanism.
CheckResult expectedOwner()
The CA and certificate provide conflicting ownership information.
CheckResult publicKeyDirectoryPermissions()
CheckResult getCN()
The 'CN' section of a DN (RFC4514)
#define JAMI_WARNING(formatstr,...)
std::vector< uint8_t > loadFile(const std::filesystem::path &path, const std::filesystem::path &default_dir)
Read the full content of a file at path.
static constexpr int version
static TlsValidator::CheckResult checkBinaryError(int err, char *copy_buffer, size_t resultSize)
Helper method to return UNSUPPORTED when an error is detected.
static TlsValidator::CheckResult checkError(int err, char *copy_buffer, size_t size)
Helper method to return UNSUPPORTED when an error is detected.
static TlsValidator::CheckResult formatDate(const time_t time)
Convert a time_t to an ISO date string.
static constexpr const char TRUE_STR[]
void emitSignal(Args... args)
static constexpr const char FALSE_STR[]
static constexpr char DATE[]
static constexpr char ISO_DATE[]
static constexpr char PASSED[]
static constexpr char UNSUPPORTED[]
static constexpr char FAILED[]
static constexpr char CUSTOM[]
static constexpr char PUBLIC_KEY_STORAGE_LOCATION[]
static constexpr char NOT_SELF_SIGNED[]
static constexpr char AUTHORITY_MISMATCH[]
static constexpr char STRONG_SIGNING[]
static constexpr char HAS_PRIVATE_KEY[]
static constexpr char PRIVATE_KEY_STORAGE_LOCATION[]
static constexpr char KNOWN_AUTHORITY[]
static constexpr char PRIVATE_KEY_DIRECTORY_PERMISSIONS[]
static constexpr char KEY_MATCH[]
static constexpr char UNEXPECTED_OWNER[]
static constexpr char PRIVATE_KEY_SELINUX_ATTRIBUTES[]
static constexpr char VALID[]
static constexpr char NOT_ACTIVATED[]
static constexpr char PRIVATE_KEY_STORAGE_PERMISSION[]
static constexpr char EXIST[]
static constexpr char VALID_AUTHORITY[]
static constexpr char PUBLIC_KEY_STORAGE_PERMISSION[]
static constexpr char NOT_REVOKED[]
static constexpr char PUBLIC_KEY_SELINUX_ATTRIBUTES[]
static constexpr char EXPIRED[]
static constexpr char PUBLIC_KEY_DIRECTORY_PERMISSIONS[]
static constexpr char CUSTOM[]
static constexpr char NUMBER[]
static constexpr char ISO_DATE[]
static constexpr char BOOLEAN[]
static constexpr char ISSUER_DN[]
static constexpr char ISSUER_CN[]
static constexpr char UID[]
static constexpr char PUBLIC_SIGNATURE[]
static constexpr char NEXT_EXPECTED_UPDATE_DATE[]
static constexpr char CN[]
static constexpr char ACTIVATION_DATE[]
static constexpr char OUTGOING_SERVER[]
static constexpr char SERIAL_NUMBER[]
static constexpr char EXPIRATION_DATE[]
static constexpr char MD5_FINGERPRINT[]
static constexpr char N[]
static constexpr char PUBLIC_KEY_ID[]
static constexpr char SHA1_FINGERPRINT[]
static constexpr char ISSUER_N[]
static constexpr char ISSUER_O[]
static constexpr char ISSUER[]
static constexpr char REQUIRE_PRIVATE_KEY_PASSWORD[]
static constexpr char SIGNATURE_ALGORITHM[]
static constexpr char SUBJECT_KEY[]
static constexpr char IS_CA[]
static constexpr char O[]
static constexpr char VERSION_NUMBER[]
static constexpr char SUBJECT_KEY_ALGORITHM[]
static constexpr char ISSUER_UID[]
This generic class represents a multidimensional enum class array.