LCOV - code coverage report
Current view: top level - src/connectivity/security - tlsvalidator.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 0 385 0.0 %
Date: 2024-12-21 08:56:24 Functions: 0 61 0.0 %

          Line data    Source code
       1             : /*
       2             :  *  Copyright (C) 2004-2024 Savoir-faire Linux Inc.
       3             :  *
       4             :  *  This program is free software: you can redistribute it and/or modify
       5             :  *  it under the terms of the GNU General Public License as published by
       6             :  *  the Free Software Foundation, either version 3 of the License, or
       7             :  *  (at your option) any later version.
       8             :  *
       9             :  *  This program is distributed in the hope that it will be useful,
      10             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      12             :  *  GNU General Public License for more details.
      13             :  *
      14             :  *  You should have received a copy of the GNU General Public License
      15             :  *  along with this program. If not, see <https://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #include "tlsvalidator.h"
      19             : 
      20             : #ifdef HAVE_CONFIG_H
      21             : #include "config.h"
      22             : #endif
      23             : 
      24             : #include <opendht/infohash.h> // for toHex
      25             : #include <dhtnet/certstore.h>
      26             : 
      27             : #include "fileutils.h"
      28             : #include "logger.h"
      29             : #include "security_const.h"
      30             : 
      31             : #include <sstream>
      32             : #include <iomanip>
      33             : 
      34             : #include <cstdio>
      35             : #include <cerrno>
      36             : #include <cassert>
      37             : #include <ctime>
      38             : 
      39             : #include <sys/types.h>
      40             : #include <sys/stat.h>
      41             : 
      42             : #ifndef _MSC_VER
      43             : #include <libgen.h>
      44             : #endif
      45             : 
      46             : #ifndef _WIN32
      47             : #include <sys/socket.h>
      48             : #include <netinet/tcp.h>
      49             : #include <netinet/in.h>
      50             : #include <netdb.h>
      51             : #else
      52             : #ifndef _MSC_VER
      53             : #define close(x) closesocket(x)
      54             : #endif
      55             : #endif
      56             : #include <unistd.h>
      57             : #include <fcntl.h>
      58             : 
      59             : #ifdef _MSC_VER
      60             : #include "windirent.h"
      61             : #endif
      62             : 
      63             : namespace jami {
      64             : namespace tls {
      65             : 
      66             : // Map the internal ring Enum class of the exported names
      67             : 
      68             : const EnumClassNames<TlsValidator::CheckValues> TlsValidator::CheckValuesNames = {{
      69             :     /* CheckValues                        Name                         */
      70             :     /* PASSED      */ libjami::Certificate::CheckValuesNames::PASSED,
      71             :     /* FAILED      */ libjami::Certificate::CheckValuesNames::FAILED,
      72             :     /* UNSUPPORTED */ libjami::Certificate::CheckValuesNames::UNSUPPORTED,
      73             :     /* ISO_DATE    */ libjami::Certificate::CheckValuesNames::ISO_DATE,
      74             :     /* CUSTOM      */ libjami::Certificate::CheckValuesNames::CUSTOM,
      75             :     /* CUSTOM      */ libjami::Certificate::CheckValuesNames::DATE,
      76             : }};
      77             : 
      78             : const CallbackMatrix1D<TlsValidator::CertificateCheck, TlsValidator, TlsValidator::CheckResult>
      79             :     TlsValidator::checkCallback = {{
      80             :         /*      CertificateCheck                       Callback                            */
      81             :         /*HAS_PRIVATE_KEY                  */ &TlsValidator::hasPrivateKey,
      82             :         /*EXPIRED                          */ &TlsValidator::notExpired,
      83             :         /*STRONG_SIGNING                   */ &TlsValidator::strongSigning,
      84             :         /*NOT_SELF_SIGNED                  */ &TlsValidator::notSelfSigned,
      85             :         /*KEY_MATCH                        */ &TlsValidator::keyMatch,
      86             :         /*PRIVATE_KEY_STORAGE_PERMISSION   */ &TlsValidator::privateKeyStoragePermissions,
      87             :         /*PUBLIC_KEY_STORAGE_PERMISSION    */ &TlsValidator::publicKeyStoragePermissions,
      88             :         /*PRIVATEKEY_DIRECTORY_PERMISSIONS */ &TlsValidator::privateKeyDirectoryPermissions,
      89             :         /*PUBLICKEY_DIRECTORY_PERMISSIONS  */ &TlsValidator::publicKeyDirectoryPermissions,
      90             :         /*PRIVATE_KEY_STORAGE_LOCATION     */ &TlsValidator::privateKeyStorageLocation,
      91             :         /*PUBLIC_KEY_STORAGE_LOCATION      */ &TlsValidator::publicKeyStorageLocation,
      92             :         /*PRIVATE_KEY_SELINUX_ATTRIBUTES   */ &TlsValidator::privateKeySelinuxAttributes,
      93             :         /*PUBLIC_KEY_SELINUX_ATTRIBUTES    */ &TlsValidator::publicKeySelinuxAttributes,
      94             :         /*EXIST                            */ &TlsValidator::exist,
      95             :         /*VALID                            */ &TlsValidator::valid,
      96             :         /*VALID_AUTHORITY                  */ &TlsValidator::validAuthority,
      97             :         /*KNOWN_AUTHORITY                  */ &TlsValidator::knownAuthority,
      98             :         /*NOT_REVOKED                      */ &TlsValidator::notRevoked,
      99             :         /*AUTHORITY_MISMATCH               */ &TlsValidator::authorityMatch,
     100             :         /*UNEXPECTED_OWNER                 */ &TlsValidator::expectedOwner,
     101             :         /*NOT_ACTIVATED                    */ &TlsValidator::activated,
     102             :     }};
     103             : 
     104             : const CallbackMatrix1D<TlsValidator::CertificateDetails, TlsValidator, TlsValidator::CheckResult>
     105             :     TlsValidator::getterCallback = {{
     106             :         /* EXPIRATION_DATE              */ &TlsValidator::getExpirationDate,
     107             :         /* ACTIVATION_DATE              */ &TlsValidator::getActivationDate,
     108             :         /* REQUIRE_PRIVATE_KEY_PASSWORD */ &TlsValidator::requirePrivateKeyPassword,
     109             :         /* PUBLIC_SIGNATURE             */ &TlsValidator::getPublicSignature,
     110             :         /* VERSION_NUMBER               */ &TlsValidator::getVersionNumber,
     111             :         /* SERIAL_NUMBER                */ &TlsValidator::getSerialNumber,
     112             :         /* ISSUER                       */ &TlsValidator::getIssuer,
     113             :         /* SUBJECT_KEY_ALGORITHM        */ &TlsValidator::getSubjectKeyAlgorithm,
     114             :         /* SUBJECT_KEY                  */ &TlsValidator::getSubjectKey,
     115             :         /* CN                           */ &TlsValidator::getCN,
     116             :         /* UID                          */ &TlsValidator::getUID,
     117             :         /* N                            */ &TlsValidator::getN,
     118             :         /* O                            */ &TlsValidator::getO,
     119             :         /* SIGNATURE_ALGORITHM          */ &TlsValidator::getSignatureAlgorithm,
     120             :         /* MD5_FINGERPRINT              */ &TlsValidator::getMd5Fingerprint,
     121             :         /* SHA1_FINGERPRINT             */ &TlsValidator::getSha1Fingerprint,
     122             :         /* PUBLIC_KEY_ID                */ &TlsValidator::getPublicKeyId,
     123             :         /* ISSUER_DN                    */ &TlsValidator::getIssuerDN,
     124             :         /* ISSUER_CN                    */ &TlsValidator::getIssuerCN,
     125             :         /* ISSUER_UID                   */ &TlsValidator::getIssuerUID,
     126             :         /* ISSUER_N                     */ &TlsValidator::getIssuerN,
     127             :         /* ISSUER_O                     */ &TlsValidator::getIssuerO,
     128             :         /* NEXT_EXPECTED_UPDATE_DATE    */ &TlsValidator::getIssuerDN, // TODO
     129             :         /* OUTGOING_SERVER              */ &TlsValidator::outgoingServer,
     130             :         /* IS_CA                        */ &TlsValidator::isCA,
     131             :     }};
     132             : 
     133             : const Matrix1D<TlsValidator::CertificateCheck, TlsValidator::CheckValuesType>
     134             :     TlsValidator::enforcedCheckType = {{
     135             :         /*      CertificateCheck                    Callback        */
     136             :         /*HAS_PRIVATE_KEY                  */ CheckValuesType::BOOLEAN,
     137             :         /*EXPIRED                          */ CheckValuesType::BOOLEAN,
     138             :         /*STRONG_SIGNING                   */ CheckValuesType::BOOLEAN,
     139             :         /*NOT_SELF_SIGNED                  */ CheckValuesType::BOOLEAN,
     140             :         /*KEY_MATCH                        */ CheckValuesType::BOOLEAN,
     141             :         /*PRIVATE_KEY_STORAGE_PERMISSION   */ CheckValuesType::BOOLEAN,
     142             :         /*PUBLIC_KEY_STORAGE_PERMISSION    */ CheckValuesType::BOOLEAN,
     143             :         /*PRIVATEKEY_DIRECTORY_PERMISSIONS */ CheckValuesType::BOOLEAN,
     144             :         /*PUBLICKEY_DIRECTORY_PERMISSIONS  */ CheckValuesType::BOOLEAN,
     145             :         /*PRIVATE_KEY_STORAGE_LOCATION     */ CheckValuesType::BOOLEAN,
     146             :         /*PUBLIC_KEY_STORAGE_LOCATION      */ CheckValuesType::BOOLEAN,
     147             :         /*PRIVATE_KEY_SELINUX_ATTRIBUTES   */ CheckValuesType::BOOLEAN,
     148             :         /*PUBLIC_KEY_SELINUX_ATTRIBUTES    */ CheckValuesType::BOOLEAN,
     149             :         /*EXIST                            */ CheckValuesType::BOOLEAN,
     150             :         /*VALID                            */ CheckValuesType::BOOLEAN,
     151             :         /*VALID_AUTHORITY                  */ CheckValuesType::BOOLEAN,
     152             :         /*KNOWN_AUTHORITY                  */ CheckValuesType::BOOLEAN,
     153             :         /*NOT_REVOKED                      */ CheckValuesType::BOOLEAN,
     154             :         /*AUTHORITY_MISMATCH               */ CheckValuesType::BOOLEAN,
     155             :         /*UNEXPECTED_OWNER                 */ CheckValuesType::BOOLEAN,
     156             :         /*NOT_ACTIVATED                    */ CheckValuesType::BOOLEAN,
     157             :     }};
     158             : 
     159             : const EnumClassNames<TlsValidator::CertificateCheck> TlsValidator::CertificateCheckNames = {{
     160             :     /*      CertificateCheck                                   Name */
     161             :     /*HAS_PRIVATE_KEY                  */ libjami::Certificate::ChecksNames::HAS_PRIVATE_KEY,
     162             :     /*EXPIRED                          */ libjami::Certificate::ChecksNames::EXPIRED,
     163             :     /*STRONG_SIGNING                   */ libjami::Certificate::ChecksNames::STRONG_SIGNING,
     164             :     /*NOT_SELF_SIGNED                  */ libjami::Certificate::ChecksNames::NOT_SELF_SIGNED,
     165             :     /*KEY_MATCH                        */ libjami::Certificate::ChecksNames::KEY_MATCH,
     166             :     /*PRIVATE_KEY_STORAGE_PERMISSION   */ libjami::Certificate::ChecksNames::PRIVATE_KEY_STORAGE_PERMISSION,
     167             :     /*PUBLIC_KEY_STORAGE_PERMISSION    */ libjami::Certificate::ChecksNames::PUBLIC_KEY_STORAGE_PERMISSION,
     168             :     /*PRIVATEKEY_DIRECTORY_PERMISSIONS */ libjami::Certificate::ChecksNames::PRIVATE_KEY_DIRECTORY_PERMISSIONS,
     169             :     /*PUBLICKEY_DIRECTORY_PERMISSIONS  */ libjami::Certificate::ChecksNames::PUBLIC_KEY_DIRECTORY_PERMISSIONS,
     170             :     /*PRIVATE_KEY_STORAGE_LOCATION     */ libjami::Certificate::ChecksNames::PRIVATE_KEY_STORAGE_LOCATION,
     171             :     /*PUBLIC_KEY_STORAGE_LOCATION      */ libjami::Certificate::ChecksNames::PUBLIC_KEY_STORAGE_LOCATION,
     172             :     /*PRIVATE_KEY_SELINUX_ATTRIBUTES   */ libjami::Certificate::ChecksNames::PRIVATE_KEY_SELINUX_ATTRIBUTES,
     173             :     /*PUBLIC_KEY_SELINUX_ATTRIBUTES    */ libjami::Certificate::ChecksNames::PUBLIC_KEY_SELINUX_ATTRIBUTES,
     174             :     /*EXIST                            */ libjami::Certificate::ChecksNames::EXIST,
     175             :     /*VALID                            */ libjami::Certificate::ChecksNames::VALID,
     176             :     /*VALID_AUTHORITY                  */ libjami::Certificate::ChecksNames::VALID_AUTHORITY,
     177             :     /*KNOWN_AUTHORITY                  */ libjami::Certificate::ChecksNames::KNOWN_AUTHORITY,
     178             :     /*NOT_REVOKED                      */ libjami::Certificate::ChecksNames::NOT_REVOKED,
     179             :     /*AUTHORITY_MISMATCH               */ libjami::Certificate::ChecksNames::AUTHORITY_MISMATCH,
     180             :     /*UNEXPECTED_OWNER                 */ libjami::Certificate::ChecksNames::UNEXPECTED_OWNER,
     181             :     /*NOT_ACTIVATED                    */ libjami::Certificate::ChecksNames::NOT_ACTIVATED,
     182             : }};
     183             : 
     184             : const EnumClassNames<TlsValidator::CertificateDetails> TlsValidator::CertificateDetailsNames = {{
     185             :     /* EXPIRATION_DATE              */ libjami::Certificate::DetailsNames::EXPIRATION_DATE,
     186             :     /* ACTIVATION_DATE              */ libjami::Certificate::DetailsNames::ACTIVATION_DATE,
     187             :     /* REQUIRE_PRIVATE_KEY_PASSWORD */ libjami::Certificate::DetailsNames::REQUIRE_PRIVATE_KEY_PASSWORD,
     188             :     /* PUBLIC_SIGNATURE             */ libjami::Certificate::DetailsNames::PUBLIC_SIGNATURE,
     189             :     /* VERSION_NUMBER               */ libjami::Certificate::DetailsNames::VERSION_NUMBER,
     190             :     /* SERIAL_NUMBER                */ libjami::Certificate::DetailsNames::SERIAL_NUMBER,
     191             :     /* ISSUER                       */ libjami::Certificate::DetailsNames::ISSUER,
     192             :     /* SUBJECT_KEY_ALGORITHM        */ libjami::Certificate::DetailsNames::SUBJECT_KEY_ALGORITHM,
     193             :     /* SUBJECT_KEY                  */ libjami::Certificate::DetailsNames::SUBJECT_KEY,
     194             :     /* CN                           */ libjami::Certificate::DetailsNames::CN,
     195             :     /* UID                          */ libjami::Certificate::DetailsNames::UID,
     196             :     /* N                            */ libjami::Certificate::DetailsNames::N,
     197             :     /* O                            */ libjami::Certificate::DetailsNames::O,
     198             :     /* SIGNATURE_ALGORITHM          */ libjami::Certificate::DetailsNames::SIGNATURE_ALGORITHM,
     199             :     /* MD5_FINGERPRINT              */ libjami::Certificate::DetailsNames::MD5_FINGERPRINT,
     200             :     /* SHA1_FINGERPRINT             */ libjami::Certificate::DetailsNames::SHA1_FINGERPRINT,
     201             :     /* PUBLIC_KEY_ID                */ libjami::Certificate::DetailsNames::PUBLIC_KEY_ID,
     202             :     /* ISSUER_DN                    */ libjami::Certificate::DetailsNames::ISSUER_DN,
     203             :     /* ISSUER_CN                    */ libjami::Certificate::DetailsNames::ISSUER_CN,
     204             :     /* ISSUER_UID                   */ libjami::Certificate::DetailsNames::ISSUER_UID,
     205             :     /* ISSUER_N                     */ libjami::Certificate::DetailsNames::ISSUER_N,
     206             :     /* ISSUER_O                     */ libjami::Certificate::DetailsNames::ISSUER_O,
     207             :     /* NEXT_EXPECTED_UPDATE_DATE    */ libjami::Certificate::DetailsNames::NEXT_EXPECTED_UPDATE_DATE,
     208             :     /* OUTGOING_SERVER              */ libjami::Certificate::DetailsNames::OUTGOING_SERVER,
     209             :     /* IS_CA                        */ libjami::Certificate::DetailsNames::IS_CA,
     210             : 
     211             : }};
     212             : 
     213             : const EnumClassNames<const TlsValidator::CheckValuesType> TlsValidator::CheckValuesTypeNames = {{
     214             :     /*   Type                            Name                          */
     215             :     /* BOOLEAN  */ libjami::Certificate::ChecksValuesTypesNames::BOOLEAN,
     216             :     /* ISO_DATE */ libjami::Certificate::ChecksValuesTypesNames::ISO_DATE,
     217             :     /* CUSTOM   */ libjami::Certificate::ChecksValuesTypesNames::CUSTOM,
     218             :     /* NUMBER   */ libjami::Certificate::ChecksValuesTypesNames::NUMBER,
     219             : }};
     220             : 
     221             : const Matrix2D<TlsValidator::CheckValuesType, TlsValidator::CheckValues, bool>
     222             :     TlsValidator::acceptedCheckValuesResult = {{
     223             :         /*   Type          PASSED    FAILED   UNSUPPORTED   ISO_DATE    CUSTOM    NUMBER */
     224             :         /* BOOLEAN  */ {{true, true, true, false, false, false}},
     225             :         /* ISO_DATE */ {{false, false, true, true, false, false}},
     226             :         /* CUSTOM   */ {{false, false, true, false, true, false}},
     227             :         /* NUMBER   */ {{false, false, true, false, false, true}},
     228             :     }};
     229             : 
     230           0 : TlsValidator::TlsValidator(const dhtnet::tls::CertificateStore& certStore, const std::vector<std::vector<uint8_t>>& crtChain)
     231           0 :     : TlsValidator(certStore, std::make_shared<dht::crypto::Certificate>(crtChain.begin(), crtChain.end()))
     232           0 : {}
     233             : 
     234           0 : TlsValidator::TlsValidator(const dhtnet::tls::CertificateStore& certStore,
     235             :                            const std::string& certificate,
     236             :                            const std::string& privatekey,
     237             :                            const std::string& privatekeyPasswd,
     238           0 :                            const std::string& caList)
     239           0 :     : certStore_(certStore)
     240           0 :     , certificatePath_(certificate)
     241           0 :     , privateKeyPath_(privatekey)
     242           0 :     , caListPath_(caList)
     243           0 :     , certificateFound_(false)
     244             : {
     245           0 :     std::vector<uint8_t> certificate_raw;
     246             :     try {
     247           0 :         certificate_raw = fileutils::loadFile(certificatePath_);
     248           0 :         certificateFileFound_ = true;
     249           0 :     } catch (const std::exception& e) {
     250           0 :     }
     251             : 
     252           0 :     if (not certificate_raw.empty()) {
     253             :         try {
     254           0 :             x509crt_ = std::make_shared<dht::crypto::Certificate>(certificate_raw);
     255           0 :             certificateContent_ = x509crt_->getPacked();
     256           0 :             certificateFound_ = true;
     257           0 :         } catch (const std::exception& e) {
     258           0 :         }
     259             :     }
     260             : 
     261             :     try {
     262           0 :         auto privateKeyContent = fileutils::loadFile(privateKeyPath_);
     263           0 :         dht::crypto::PrivateKey key_tmp(privateKeyContent, privatekeyPasswd);
     264           0 :         privateKeyFound_ = true;
     265           0 :         privateKeyPassword_ = not privatekeyPasswd.empty();
     266           0 :         privateKeyMatch_ = key_tmp.getPublicKey().getId() == x509crt_->getId();
     267           0 :     } catch (const dht::crypto::DecryptError& d) {
     268             :         // If we encounter a DecryptError, it means the private key exists and is encrypted,
     269             :         // otherwise we would get some other exception.
     270           0 :         JAMI_WARN("decryption error: %s", d.what());
     271           0 :         privateKeyFound_ = true;
     272           0 :         privateKeyPassword_ = true;
     273           0 :     } catch (const std::exception& e) {
     274           0 :         JAMI_WARN("creation failed: %s", e.what());
     275           0 :     }
     276           0 : }
     277             : 
     278           0 : TlsValidator::TlsValidator(const dhtnet::tls::CertificateStore& certStore, const std::vector<uint8_t>& certificate_raw)
     279           0 :     : certStore_(certStore)
     280             : {
     281             :     try {
     282           0 :         x509crt_ = std::make_shared<dht::crypto::Certificate>(certificate_raw);
     283           0 :         certificateContent_ = x509crt_->getPacked();
     284           0 :         certificateFound_ = true;
     285           0 :     } catch (const std::exception& e) {
     286           0 :         throw TlsValidatorException("Unable to load certificate");
     287           0 :     }
     288           0 : }
     289             : 
     290           0 : TlsValidator::TlsValidator(const dhtnet::tls::CertificateStore& certStore, const std::shared_ptr<dht::crypto::Certificate>& crt)
     291           0 :     : certStore_(certStore)
     292           0 :     , certificateFound_(true)
     293             : {
     294             :     try {
     295           0 :         if (not crt)
     296           0 :             throw std::invalid_argument("Certificate must be set");
     297           0 :         x509crt_ = crt;
     298           0 :         certificateContent_ = x509crt_->getPacked();
     299           0 :     } catch (const std::exception& e) {
     300           0 :         throw TlsValidatorException("Unable to load certificate");
     301           0 :     }
     302           0 : }
     303             : 
     304           0 : TlsValidator::~TlsValidator() {}
     305             : 
     306             : /**
     307             :  * This method convert results into validated strings
     308             :  *
     309             :  * @todo The date should be validated, this is currently not an issue
     310             :  */
     311             : std::string
     312           0 : TlsValidator::getStringValue(const TlsValidator::CertificateCheck check,
     313             :                              const TlsValidator::CheckResult result)
     314             : {
     315           0 :     assert(acceptedCheckValuesResult[enforcedCheckType[check]][result.first]);
     316             : 
     317           0 :     switch (result.first) {
     318           0 :     case CheckValues::PASSED:
     319             :     case CheckValues::FAILED:
     320             :     case CheckValues::UNSUPPORTED:
     321           0 :         return std::string(CheckValuesNames[result.first]);
     322           0 :     case CheckValues::ISO_DATE:
     323             :         // TODO validate date
     324             :         // return CheckValues::FAILED;
     325           0 :         return result.second;
     326           0 :     case CheckValues::NUMBER:
     327             :         // TODO Validate numbers
     328             :     case CheckValues::CUSTOM:
     329           0 :         return result.second;
     330           0 :     default:
     331             :         // Consider any other case (such as forced int->CheckValues casting) as failed
     332           0 :         return std::string(CheckValuesNames[CheckValues::FAILED]);
     333             :     };
     334             : }
     335             : 
     336             : /**
     337             :  * Check if all boolean check passed
     338             :  * return true if there was no ::FAILED checks
     339             :  *
     340             :  * Checks functions are not "const", so this function isn't
     341             :  */
     342             : bool
     343           0 : TlsValidator::isValid(bool verbose)
     344             : {
     345           0 :     for (const CertificateCheck check : Matrix0D<CertificateCheck>()) {
     346           0 :         if (enforcedCheckType[check] == CheckValuesType::BOOLEAN) {
     347           0 :             if (((this->*(checkCallback[check]))()).first == CheckValues::FAILED) {
     348           0 :                 if (verbose)
     349           0 :                     JAMI_WARNING("Check failed: {}", CertificateCheckNames[check]);
     350           0 :                 return false;
     351             :             }
     352             :         }
     353             :     }
     354           0 :     return true;
     355             : }
     356             : 
     357             : /**
     358             :  * Convert all checks results into a string map
     359             :  */
     360             : std::map<std::string, std::string>
     361           0 : TlsValidator::getSerializedChecks()
     362             : {
     363           0 :     std::map<std::string, std::string> ret;
     364           0 :     if (not certificateFound_) {
     365             :         // Instead of checking `certificateFound` everywhere, handle it once
     366           0 :         ret[std::string(CertificateCheckNames[CertificateCheck::EXIST])] = getStringValue(CertificateCheck::EXIST,
     367           0 :                                                                              exist());
     368             :     } else {
     369           0 :         for (const CertificateCheck check : Matrix0D<CertificateCheck>())
     370           0 :             ret[std::string(CertificateCheckNames[check])] = getStringValue(check,
     371           0 :                                                                (this->*(checkCallback[check]))());
     372             :     }
     373             : 
     374           0 :     return ret;
     375           0 : }
     376             : 
     377             : /**
     378             :  * Get a map with all common certificate details
     379             :  */
     380             : std::map<std::string, std::string>
     381           0 : TlsValidator::getSerializedDetails()
     382             : {
     383           0 :     std::map<std::string, std::string> ret;
     384           0 :     if (certificateFound_) {
     385           0 :         for (const CertificateDetails& det : Matrix0D<CertificateDetails>()) {
     386           0 :             const CheckResult r = (this->*(getterCallback[det]))();
     387           0 :             std::string val;
     388             :             // TODO move this to a fuction
     389           0 :             switch (r.first) {
     390           0 :             case CheckValues::PASSED:
     391             :             case CheckValues::FAILED:
     392             :             case CheckValues::UNSUPPORTED:
     393           0 :                 val = CheckValuesNames[r.first];
     394           0 :                 break;
     395           0 :             case CheckValues::ISO_DATE:
     396             :                 // TODO validate date
     397             :             case CheckValues::NUMBER:
     398             :                 // TODO Validate numbers
     399             :             case CheckValues::CUSTOM:
     400             :             default:
     401           0 :                 val = r.second;
     402           0 :                 break;
     403             :             }
     404           0 :             ret[std::string(CertificateDetailsNames[det])] = val;
     405           0 :         }
     406             :     }
     407           0 :     return ret;
     408           0 : }
     409             : 
     410             : /**
     411             :  * Helper method to return UNSUPPORTED when an error is detected
     412             :  */
     413             : static TlsValidator::CheckResult
     414           0 : checkError(int err, char* copy_buffer, size_t size)
     415             : {
     416             :     return TlsValidator::TlsValidator::CheckResult(err == GNUTLS_E_SUCCESS
     417           0 :                                                        ? TlsValidator::CheckValues::CUSTOM
     418             :                                                        : TlsValidator::CheckValues::UNSUPPORTED,
     419             :                                                    err == GNUTLS_E_SUCCESS
     420           0 :                                                        ? std::string(copy_buffer, size)
     421           0 :                                                        : "");
     422             : }
     423             : 
     424             : /**
     425             :  * Convert a time_t to an ISO date string
     426             :  */
     427             : static TlsValidator::CheckResult
     428           0 : formatDate(const time_t time)
     429             : {
     430             :     char buffer[12];
     431           0 :     struct tm* timeinfo = localtime(&time);
     432           0 :     strftime(buffer, sizeof(buffer), "%F", timeinfo);
     433           0 :     return TlsValidator::CheckResult(TlsValidator::CheckValues::ISO_DATE, buffer);
     434             : }
     435             : 
     436             : /**
     437             :  * Helper method to return UNSUPPORTED when an error is detected
     438             :  *
     439             :  * This method also convert the output to binary
     440             :  */
     441             : static TlsValidator::CheckResult
     442           0 : checkBinaryError(int err, char* copy_buffer, size_t resultSize)
     443             : {
     444           0 :     if (err == GNUTLS_E_SUCCESS)
     445           0 :         return TlsValidator::CheckResult(TlsValidator::CheckValues::CUSTOM,
     446           0 :                                          dht::toHex(reinterpret_cast<uint8_t*>(copy_buffer),
     447           0 :                                                      resultSize));
     448             :     else
     449           0 :         return TlsValidator::CheckResult(TlsValidator::CheckValues::UNSUPPORTED, "");
     450             : }
     451             : 
     452             : /**
     453             :  * Check if a certificate has been signed with the authority
     454             :  */
     455             : unsigned int
     456           0 : TlsValidator::compareToCa()
     457             : {
     458             :     // Don't check unless the certificate changed
     459           0 :     if (caChecked_)
     460           0 :         return caValidationOutput_;
     461             : 
     462             :     // build the CA trusted list
     463             :     gnutls_x509_trust_list_t trust;
     464           0 :     gnutls_x509_trust_list_init(&trust, 0);
     465             : 
     466           0 :     auto root_cas = certStore_.getTrustedCertificates();
     467           0 :     auto err = gnutls_x509_trust_list_add_cas(trust, root_cas.data(), root_cas.size(), 0);
     468           0 :     if (err)
     469           0 :         JAMI_WARN("gnutls_x509_trust_list_add_cas failed: %s", gnutls_strerror(err));
     470             : 
     471           0 :     if (not caListPath_.empty()) {
     472           0 :         if (std::filesystem::is_directory(caListPath_))
     473           0 :             gnutls_x509_trust_list_add_trust_dir(trust,
     474             :                                                  caListPath_.c_str(),
     475             :                                                  nullptr,
     476             :                                                  GNUTLS_X509_FMT_PEM,
     477             :                                                  0,
     478             :                                                  0);
     479             :         else
     480           0 :             gnutls_x509_trust_list_add_trust_file(trust,
     481             :                                                   caListPath_.c_str(),
     482             :                                                   nullptr,
     483             :                                                   GNUTLS_X509_FMT_PEM,
     484             :                                                   0,
     485             :                                                   0);
     486             :     }
     487             : 
     488             :     // build the certificate chain
     489           0 :     auto crts = x509crt_->getChain();
     490           0 :     err = gnutls_x509_trust_list_verify_crt2(trust,
     491             :                                              crts.data(),
     492           0 :                                              crts.size(),
     493             :                                              nullptr,
     494             :                                              0,
     495             :                                              GNUTLS_PROFILE_TO_VFLAGS(GNUTLS_PROFILE_MEDIUM),
     496             :                                              &caValidationOutput_,
     497             :                                              nullptr);
     498             : 
     499           0 :     gnutls_x509_trust_list_deinit(trust, true);
     500             : 
     501           0 :     if (err) {
     502           0 :         JAMI_WARN("gnutls_x509_trust_list_verify_crt2 failed: %s", gnutls_strerror(err));
     503           0 :         return GNUTLS_CERT_SIGNER_NOT_FOUND;
     504             :     }
     505             : 
     506           0 :     caChecked_ = true;
     507           0 :     return caValidationOutput_;
     508           0 : }
     509             : 
     510             : #if 0 // disabled, see .h for reason
     511             : /**
     512             :  * Verify if a hostname is valid
     513             :  *
     514             :  * @warning This function is blocking
     515             :  *
     516             :  * Mainly based on Fedora Defensive Coding tutorial
     517             :  * https://docs.fedoraproject.org/en-US/Fedora_Security_Team/1/html/Defensive_Coding/sect-Defensive_Coding-TLS-Client-GNUTLS.html
     518             :  */
     519             : int TlsValidator::verifyHostnameCertificate(const std::string& host, const uint16_t port)
     520             : {
     521             :     int err, arg, res = -1;
     522             :     unsigned int status = (unsigned) -1;
     523             :     const char *errptr = nullptr;
     524             :     gnutls_session_t session = nullptr;
     525             :     gnutls_certificate_credentials_t cred = nullptr;
     526             :     unsigned int certslen = 0;
     527             :     const gnutls_datum_t *certs = nullptr;
     528             :     gnutls_x509_crt_t cert = nullptr;
     529             : 
     530             :     char buf[4096];
     531             :     int sockfd;
     532             :     struct sockaddr_in name;
     533             :     struct hostent *hostinfo;
     534             :     const int one = 1;
     535             :     fd_set fdset;
     536             :     struct timeval tv;
     537             : 
     538             :     if (!host.size() || !port) {
     539             :         JAMI_ERR("Wrong parameters used - host %s, port %d.", host.c_str(), port);
     540             :         return res;
     541             :     }
     542             : 
     543             :     /* Create the socket. */
     544             :     sockfd = socket (PF_INET, SOCK_STREAM, 0);
     545             :     if (sockfd < 0) {
     546             :         JAMI_ERR("Unable to create socket.");
     547             :         return res;
     548             :     }
     549             :     /* Set non-blocking so we can dected timeouts. */
     550             :     arg = fcntl(sockfd, F_GETFL, nullptr);
     551             :     if (arg < 0)
     552             :         goto out;
     553             :     arg |= O_NONBLOCK;
     554             :     if (fcntl(sockfd, F_SETFL, arg) < 0)
     555             :         goto out;
     556             : 
     557             :     /* Give the socket a name. */
     558             :     memset(&name, 0, sizeof(name));
     559             :     name.sin_family = AF_INET;
     560             :     name.sin_port = htons(port);
     561             :     hostinfo = gethostbyname(host.c_str());
     562             :     if (hostinfo == nullptr) {
     563             :         JAMI_ERR("Unknown host %s.", host.c_str());
     564             :         goto out;
     565             :     }
     566             :     name.sin_addr = *(struct in_addr *)hostinfo->h_addr;
     567             :     /* Connect to the address specified in name struct. */
     568             :     err = connect(sockfd, (struct sockaddr *)&name, sizeof(name));
     569             :     if (err < 0) {
     570             :         /* Connection in progress, use select to see if timeout is reached. */
     571             :         if (errno == EINPROGRESS) {
     572             :             do {
     573             :                 FD_ZERO(&fdset);
     574             :                 FD_SET(sockfd, &fdset);
     575             :                 tv.tv_sec = 10;     // 10 second timeout
     576             :                 tv.tv_usec = 0;
     577             :                 err = select(sockfd + 1, nullptr, &fdset, nullptr, &tv);
     578             :                 if (err < 0 && errno != EINTR) {
     579             :                     JAMI_ERR("Unable to connect to hostname %s at port %d",
     580             :                           host.c_str(), port);
     581             :                     goto out;
     582             :                 } else if (err > 0) {
     583             :                     /* Select returned, if so_error is clean we are ready. */
     584             :                     int so_error;
     585             :                     socklen_t len = sizeof(so_error);
     586             :                     getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &so_error, &len);
     587             : 
     588             :                     if (so_error) {
     589             :                         JAMI_ERR("Connection delayed.");
     590             :                         goto out;
     591             :                     }
     592             :                     break;  // exit do-while loop
     593             :                 } else {
     594             :                     JAMI_ERR("Connection timeout.");
     595             :                     goto out;
     596             :                 }
     597             :             } while(1);
     598             :         } else {
     599             :             JAMI_ERR("Unable to connect to hostname %s at port %d", host.c_str(), port);
     600             :             goto out;
     601             :         }
     602             :     }
     603             :     /* Set the socked blocking again. */
     604             :     arg = fcntl(sockfd, F_GETFL, nullptr);
     605             :     if (arg < 0)
     606             :         goto out;
     607             :     arg &= ~O_NONBLOCK;
     608             :     if (fcntl(sockfd, F_SETFL, arg) < 0)
     609             :         goto out;
     610             : 
     611             :     /* Disable Nagle algorithm that slows down the SSL handshake. */
     612             :     err = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
     613             :     if (err < 0) {
     614             :         JAMI_ERR("Unable to set TCP_NODELAY.");
     615             :         goto out;
     616             :     }
     617             : 
     618             : 
     619             :     /* Load the trusted CA certificates. */
     620             :     err = gnutls_certificate_allocate_credentials(&cred);
     621             :     if (err != GNUTLS_E_SUCCESS) {
     622             :         JAMI_ERR("Unable to allocate credentials - %s", gnutls_strerror(err));
     623             :         goto out;
     624             :     }
     625             :     err = gnutls_certificate_set_x509_system_trust(cred);
     626             :     if (err != GNUTLS_E_SUCCESS) {
     627             :         JAMI_ERR("Unable to load credentials.");
     628             :         goto out;
     629             :     }
     630             : 
     631             :     /* Create the session object. */
     632             :     err = gnutls_init(&session, GNUTLS_CLIENT);
     633             :     if (err != GNUTLS_E_SUCCESS) {
     634             :         JAMI_ERR("Unable to init session -%s\n", gnutls_strerror(err));
     635             :         goto out;
     636             :     }
     637             : 
     638             :     /* Configure the cipher preferences. The default set should be good enough. */
     639             :     err = gnutls_priority_set_direct(session, "NORMAL", &errptr);
     640             :     if (err != GNUTLS_E_SUCCESS) {
     641             :         JAMI_ERR("Unable to set up ciphers - %s (%s)", gnutls_strerror(err), errptr);
     642             :         goto out;
     643             :     }
     644             : 
     645             :     /* Install the trusted certificates. */
     646             :     err = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cred);
     647             :     if (err != GNUTLS_E_SUCCESS) {
     648             :         JAMI_ERR("Unable to set up credentials - %s", gnutls_strerror(err));
     649             :         goto out;
     650             :     }
     651             : 
     652             :     /* Associate the socket with the session object and set the server name. */
     653             :     gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t) (uintptr_t) sockfd);
     654             :     err = gnutls_server_name_set(session, GNUTLS_NAME_DNS, host.c_str(), host.size());
     655             :     if (err != GNUTLS_E_SUCCESS) {
     656             :         JAMI_ERR("Unable to set server name - %s", gnutls_strerror(err));
     657             :         goto out;
     658             :     }
     659             : 
     660             :     /* Establish the connection. */
     661             :     err = gnutls_handshake(session);
     662             :     if (err != GNUTLS_E_SUCCESS) {
     663             :         JAMI_ERR("Handshake failed - %s", gnutls_strerror(err));
     664             :         goto out;
     665             :     }
     666             :     /* Obtain the server certificate chain. The server certificate
     667             :      * itself is stored in the first element of the array. */
     668             :     certs = gnutls_certificate_get_peers(session, &certslen);
     669             :     if (certs == nullptr || certslen == 0) {
     670             :         JAMI_ERR("Unable to obtain peer certificate - %s", gnutls_strerror(err));
     671             :         goto out;
     672             :     }
     673             : 
     674             :     /* Validate the certificate chain. */
     675             :     err = gnutls_certificate_verify_peers2(session, &status);
     676             :     if (err != GNUTLS_E_SUCCESS) {
     677             :         JAMI_ERR("Unable to verify the certificate chain - %s", gnutls_strerror(err));
     678             :         goto out;
     679             :     }
     680             :     if (status != 0) {
     681             :         gnutls_datum_t msg;
     682             : #if GNUTLS_VERSION_AT_LEAST_3_1_4
     683             :         int type = gnutls_certificate_type_get(session);
     684             :         err = gnutls_certificate_verification_status_print(status, type, &out, 0);
     685             : #else
     686             :         err = -1;
     687             : #endif
     688             :         if (err == 0) {
     689             :             JAMI_ERR("Certificate validation failed - %s\n", msg.data);
     690             :             gnutls_free(msg.data);
     691             :             goto out;
     692             :         } else {
     693             :             JAMI_ERR("Certificate validation failed with code 0x%x.", status);
     694             :             goto out;
     695             :         }
     696             :     }
     697             : 
     698             :     /* Match the peer certificate against the hostname.
     699             :      * We can only obtain a set of DER-encoded certificates from the
     700             :      * session object, so we have to re-parse the peer certificate into
     701             :      * a certificate object. */
     702             : 
     703             :     err = gnutls_x509_crt_init(&cert);
     704             :     if (err != GNUTLS_E_SUCCESS) {
     705             :         JAMI_ERR("Unable to init certificate - %s", gnutls_strerror(err));
     706             :         goto out;
     707             :     }
     708             : 
     709             :     /* The peer certificate is the first certificate in the list. */
     710             :     err = gnutls_x509_crt_import(cert, certs, GNUTLS_X509_FMT_PEM);
     711             :     if (err != GNUTLS_E_SUCCESS)
     712             :         err = gnutls_x509_crt_import(cert, certs, GNUTLS_X509_FMT_DER);
     713             :     if (err != GNUTLS_E_SUCCESS) {
     714             :         JAMI_ERR("Unable to read peer certificate - %s", gnutls_strerror(err));
     715             :         goto out;
     716             :     }
     717             :     /* Finally check if the hostnames match. */
     718             :     err = gnutls_x509_crt_check_hostname(cert, host.c_str());
     719             :     if (err == 0) {
     720             :         JAMI_ERR("Hostname %s does not match certificate.", host.c_str());
     721             :         goto out;
     722             :     }
     723             : 
     724             :     /* Try sending and receiving some data through. */
     725             :     snprintf(buf, sizeof(buf), "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", host.c_str());
     726             :     err = gnutls_record_send(session, buf, strlen(buf));
     727             :     if (err < 0) {
     728             :         JAMI_ERR("Send failed - %s", gnutls_strerror(err));
     729             :         goto out;
     730             :     }
     731             :     err = gnutls_record_recv(session, buf, sizeof(buf));
     732             :     if (err < 0) {
     733             :         JAMI_ERR("Recv failed - %s", gnutls_strerror(err));
     734             :         goto out;
     735             :     }
     736             : 
     737             :     JAMI_DBG("Hostname %s seems to point to a valid server.", host.c_str());
     738             :     res = 0;
     739             : out:
     740             :     if (session) {
     741             :         gnutls_bye(session, GNUTLS_SHUT_RDWR);
     742             :         gnutls_deinit(session);
     743             :     }
     744             :     if (cert)
     745             :         gnutls_x509_crt_deinit(cert);
     746             :     if (cred)
     747             :         gnutls_certificate_free_credentials(cred);
     748             :     close(sockfd);
     749             :     return res;
     750             : }
     751             : #endif
     752             : 
     753             : /**
     754             :  * Check if the Validator have access to a private key
     755             :  */
     756             : TlsValidator::CheckResult
     757           0 : TlsValidator::hasPrivateKey()
     758             : {
     759           0 :     if (privateKeyFound_)
     760           0 :         return TlsValidator::CheckResult(CheckValues::PASSED, "");
     761             : 
     762             :     try {
     763           0 :         dht::crypto::PrivateKey key_tmp(certificateContent_);
     764           0 :     } catch (const std::exception& e) {
     765           0 :         return CheckResult(CheckValues::FAILED, e.what());
     766           0 :     }
     767             : 
     768           0 :     JAMI_DBG("Key from %s seems valid.", certificatePath_.c_str());
     769           0 :     return CheckResult(CheckValues::PASSED, "");
     770             : }
     771             : 
     772             : /**
     773             :  * Check if the certificate is not expired
     774             :  *
     775             :  * The double negative is used because all boolean checks need to have
     776             :  * a consistent return value semantic
     777             :  *
     778             :  * @fixme Handle both "with ca" and "without ca" case
     779             :  */
     780             : TlsValidator::CheckResult
     781           0 : TlsValidator::notExpired()
     782             : {
     783           0 :     if (exist().first == CheckValues::FAILED)
     784           0 :         TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
     785             : 
     786             :     // time_t expirationTime = gnutls_x509_crt_get_expiration_time(cert);
     787           0 :     return TlsValidator::CheckResult(compareToCa() & GNUTLS_CERT_EXPIRED ? CheckValues::FAILED
     788             :                                                                          : CheckValues::PASSED,
     789           0 :                                      "");
     790             : }
     791             : 
     792             : /**
     793             :  * If the activation value is in the past
     794             :  *
     795             :  * @fixme Handle both "with ca" and "without ca" case
     796             :  */
     797             : TlsValidator::CheckResult
     798           0 : TlsValidator::activated()
     799             : {
     800           0 :     if (exist().first == CheckValues::FAILED)
     801           0 :         TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
     802             : 
     803             :     // time_t activationTime = gnutls_x509_crt_get_activation_time(cert);
     804           0 :     return TlsValidator::CheckResult(compareToCa() & GNUTLS_CERT_NOT_ACTIVATED
     805           0 :                                          ? CheckValues::FAILED
     806             :                                          : CheckValues::PASSED,
     807           0 :                                      "");
     808             : }
     809             : 
     810             : /**
     811             :  * If the algorithm used to sign the certificate is considered weak by modern
     812             :  * standard
     813             :  */
     814             : TlsValidator::CheckResult
     815           0 : TlsValidator::strongSigning()
     816             : {
     817           0 :     if (exist().first == CheckValues::FAILED)
     818           0 :         TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
     819             : 
     820             :     // Doesn't seem to have the same value as
     821             :     // certtool  --infile /home/etudiant/Téléchargements/mynsauser.pem --key-inf
     822             :     // TODO figure out why
     823           0 :     return TlsValidator::CheckResult(compareToCa() & GNUTLS_CERT_INSECURE_ALGORITHM
     824           0 :                                          ? CheckValues::FAILED
     825             :                                          : CheckValues::PASSED,
     826           0 :                                      "");
     827             : }
     828             : 
     829             : /**
     830             :  * The certificate is not self signed
     831             :  */
     832             : TlsValidator::CheckResult
     833           0 : TlsValidator::notSelfSigned()
     834             : {
     835           0 :     return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
     836             : }
     837             : 
     838             : /**
     839             :  * The provided key can be used along with the certificate
     840             :  */
     841             : TlsValidator::CheckResult
     842           0 : TlsValidator::keyMatch()
     843             : {
     844           0 :     if (exist().first == CheckValues::FAILED)
     845           0 :         return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
     846             : 
     847           0 :     if (not privateKeyFound_)
     848           0 :         return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
     849           0 :     return TlsValidator::CheckResult(privateKeyMatch_ ? CheckValues::PASSED : CheckValues::FAILED,
     850           0 :                                      "");
     851             : }
     852             : 
     853             : TlsValidator::CheckResult
     854           0 : TlsValidator::privateKeyStoragePermissions()
     855             : {
     856             :     struct stat statbuf;
     857           0 :     int err = stat(privateKeyPath_.c_str(), &statbuf);
     858           0 :     if (err)
     859           0 :         return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
     860             : 
     861             : // clang-format off
     862             :     return TlsValidator::CheckResult(
     863           0 :         (statbuf.st_mode & S_IFREG) && /* Regular file only */
     864             :         /*                          READ                      WRITE                            EXECUTE          */
     865           0 :         /* Owner */    ( (statbuf.st_mode & S_IRUSR) /* write is not relevant */     && !(statbuf.st_mode & S_IXUSR))
     866           0 :         /* Group */ && (!(statbuf.st_mode & S_IRGRP) && !(statbuf.st_mode & S_IWGRP) && !(statbuf.st_mode & S_IXGRP))
     867           0 :         /* Other */ && (!(statbuf.st_mode & S_IROTH) && !(statbuf.st_mode & S_IWOTH) && !(statbuf.st_mode & S_IXOTH))
     868           0 :         ? CheckValues::PASSED:CheckValues::FAILED, "");
     869             : // clang-format on
     870             : }
     871             : 
     872             : TlsValidator::CheckResult
     873           0 : TlsValidator::publicKeyStoragePermissions()
     874             : {
     875             :     struct stat statbuf;
     876           0 :     int err = stat(certificatePath_.c_str(), &statbuf);
     877           0 :     if (err)
     878           0 :         return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
     879             : 
     880             : // clang-format off
     881             :     return TlsValidator::CheckResult(
     882           0 :         (statbuf.st_mode & S_IFREG) && /* Regular file only */
     883             :         /*                          READ                      WRITE                            EXECUTE          */
     884           0 :         /* Owner */    ( (statbuf.st_mode & S_IRUSR) /* write is not relevant */   && !(statbuf.st_mode & S_IXUSR))
     885           0 :         /* Group */ && ( /* read is not relevant */   !(statbuf.st_mode & S_IWGRP) && !(statbuf.st_mode & S_IXGRP))
     886           0 :         /* Other */ && ( /* read is not relevant */   !(statbuf.st_mode & S_IWOTH) && !(statbuf.st_mode & S_IXOTH))
     887           0 :         ? CheckValues::PASSED:CheckValues::FAILED, "");
     888             : // clang-format on
     889             : }
     890             : 
     891             : TlsValidator::CheckResult
     892           0 : TlsValidator::privateKeyDirectoryPermissions()
     893             : {
     894           0 :     if (privateKeyPath_.empty())
     895           0 :         return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
     896             : 
     897             : #ifndef _MSC_VER
     898           0 :     auto path = std::unique_ptr<char, decltype(free)&>(strdup(privateKeyPath_.c_str()), free);
     899           0 :     const char* dir = dirname(path.get());
     900             : #else
     901             :     char* dir;
     902             :     _splitpath(certificatePath_.c_str(), nullptr, dir, nullptr, nullptr);
     903             : #endif
     904             : 
     905             :     struct stat statbuf;
     906           0 :     int err = stat(dir, &statbuf);
     907           0 :     if (err)
     908           0 :         return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
     909             : 
     910             :     return TlsValidator::CheckResult(
     911             :         /*                          READ                      WRITE EXECUTE             */
     912             :         /* Owner */ (
     913           0 :             (statbuf.st_mode & S_IRUSR) /* write is not relevant */ && (statbuf.st_mode & S_IXUSR))
     914             :                 /* Group */
     915           0 :                 && (!(statbuf.st_mode & S_IRGRP) && !(statbuf.st_mode & S_IWGRP)
     916           0 :                     && !(statbuf.st_mode & S_IXGRP))
     917             :                 /* Other */
     918           0 :                 && (!(statbuf.st_mode & S_IROTH) && !(statbuf.st_mode & S_IWOTH)
     919           0 :                     && !(statbuf.st_mode & S_IXOTH))
     920           0 :                 && S_ISDIR(statbuf.st_mode)
     921           0 :             ? CheckValues::PASSED
     922             :             : CheckValues::FAILED,
     923           0 :         "");
     924           0 : }
     925             : 
     926             : TlsValidator::CheckResult
     927           0 : TlsValidator::publicKeyDirectoryPermissions()
     928             : {
     929             : #ifndef _MSC_VER
     930           0 :     auto path = std::unique_ptr<char, decltype(free)&>(strdup(certificatePath_.c_str()), free);
     931           0 :     const char* dir = dirname(path.get());
     932             : #else
     933             :     char* dir;
     934             :     _splitpath(certificatePath_.c_str(), nullptr, dir, nullptr, nullptr);
     935             : #endif
     936             : 
     937             :     struct stat statbuf;
     938           0 :     int err = stat(dir, &statbuf);
     939           0 :     if (err)
     940           0 :         return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
     941             : 
     942             :     return TlsValidator::CheckResult(
     943             :         /*                          READ                      WRITE EXECUTE             */
     944             :         /* Owner */ (
     945           0 :             (statbuf.st_mode & S_IRUSR) /* write is not relevant */ && (statbuf.st_mode & S_IXUSR))
     946             :                 /* Group */
     947           0 :                 && (!(statbuf.st_mode & S_IRGRP) && !(statbuf.st_mode & S_IWGRP)
     948           0 :                     && !(statbuf.st_mode & S_IXGRP))
     949             :                 /* Other */
     950           0 :                 && (!(statbuf.st_mode & S_IROTH) && !(statbuf.st_mode & S_IWOTH)
     951           0 :                     && !(statbuf.st_mode & S_IXOTH))
     952           0 :                 && S_ISDIR(statbuf.st_mode)
     953           0 :             ? CheckValues::PASSED
     954             :             : CheckValues::FAILED,
     955           0 :         "");
     956           0 : }
     957             : 
     958             : /**
     959             :  * Certificate should be located in specific path on some operating systems
     960             :  */
     961             : TlsValidator::CheckResult
     962           0 : TlsValidator::privateKeyStorageLocation()
     963             : {
     964             :     // TODO
     965           0 :     return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
     966             : }
     967             : 
     968             : /**
     969             :  * Certificate should be located in specific path on some operating systems
     970             :  */
     971             : TlsValidator::CheckResult
     972           0 : TlsValidator::publicKeyStorageLocation()
     973             : {
     974             :     // TODO
     975           0 :     return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
     976             : }
     977             : 
     978             : /**
     979             :  * SELinux provide additional key protection mechanism
     980             :  */
     981             : TlsValidator::CheckResult
     982           0 : TlsValidator::privateKeySelinuxAttributes()
     983             : {
     984             :     // TODO
     985           0 :     return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
     986             : }
     987             : 
     988             : /**
     989             :  * SELinux provide additional key protection mechanism
     990             :  */
     991             : TlsValidator::CheckResult
     992           0 : TlsValidator::publicKeySelinuxAttributes()
     993             : {
     994             :     // TODO
     995           0 :     return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
     996             : }
     997             : 
     998             : /**
     999             :  * If the key need decryption
    1000             :  *
    1001             :  * Double factor authentication is recommended
    1002             :  */
    1003             : TlsValidator::CheckResult
    1004           0 : TlsValidator::requirePrivateKeyPassword()
    1005             : {
    1006           0 :     return TlsValidator::CheckResult(privateKeyPassword_ ? CheckValues::PASSED : CheckValues::FAILED,
    1007           0 :                                      "");
    1008             : }
    1009             : /**
    1010             :  * The CA and certificate provide conflicting ownership information
    1011             :  */
    1012             : TlsValidator::CheckResult
    1013           0 : TlsValidator::expectedOwner()
    1014             : {
    1015           0 :     return TlsValidator::CheckResult(compareToCa() & GNUTLS_CERT_UNEXPECTED_OWNER
    1016           0 :                                          ? CheckValues::FAILED
    1017             :                                          : CheckValues::PASSED,
    1018           0 :                                      "");
    1019             : }
    1020             : 
    1021             : /**
    1022             :  * The file has been found
    1023             :  */
    1024             : TlsValidator::CheckResult
    1025           0 : TlsValidator::exist()
    1026             : {
    1027           0 :     return TlsValidator::CheckResult((certificateFound_ or certificateFileFound_)
    1028           0 :                                          ? CheckValues::PASSED
    1029             :                                          : CheckValues::FAILED,
    1030           0 :                                      "");
    1031             : }
    1032             : 
    1033             : /**
    1034             :  * The certificate is invalid compared to the authority
    1035             :  *
    1036             :  * @todo Handle case when there is facultative authority, such as DHT
    1037             :  */
    1038             : TlsValidator::CheckResult
    1039           0 : TlsValidator::valid()
    1040             : {
    1041           0 :     return TlsValidator::CheckResult(certificateFound_ ? CheckValues::PASSED : CheckValues::FAILED,
    1042           0 :                                      "");
    1043             : }
    1044             : 
    1045             : /**
    1046             :  * The provided authority is invalid
    1047             :  */
    1048             : TlsValidator::CheckResult
    1049           0 : TlsValidator::validAuthority()
    1050             : {
    1051             :     // TODO Merge with either above or below
    1052           0 :     return TlsValidator::CheckResult((compareToCa() & GNUTLS_CERT_SIGNER_NOT_FOUND)
    1053           0 :                                          ? CheckValues::FAILED
    1054             :                                          : CheckValues::PASSED,
    1055           0 :                                      "");
    1056             : }
    1057             : 
    1058             : /**
    1059             :  * Check if the authority match the certificate
    1060             :  */
    1061             : TlsValidator::CheckResult
    1062           0 : TlsValidator::authorityMatch()
    1063             : {
    1064           0 :     return TlsValidator::CheckResult(compareToCa() & GNUTLS_CERT_SIGNER_NOT_CA
    1065           0 :                                          ? CheckValues::FAILED
    1066             :                                          : CheckValues::PASSED,
    1067           0 :                                      "");
    1068             : }
    1069             : 
    1070             : /**
    1071             :  * When an account require an authority known by the system (like /usr/share/ssl/certs)
    1072             :  * then the whole chain of trust need be to checked
    1073             :  *
    1074             :  * @fixme port crypto_cert_load_trusted
    1075             :  * @fixme add account settings
    1076             :  * @todo implement the check
    1077             :  */
    1078             : TlsValidator::CheckResult
    1079           0 : TlsValidator::knownAuthority()
    1080             : {
    1081             :     // TODO need a new boolean account setting "require trusted authority" or something defaulting
    1082             :     // to true using GNUTLS_CERT_SIGNER_NOT_FOUND is a temporary placeholder as it is close enough
    1083           0 :     return TlsValidator::CheckResult(compareToCa() & GNUTLS_CERT_SIGNER_NOT_FOUND
    1084           0 :                                          ? CheckValues::FAILED
    1085             :                                          : CheckValues::PASSED,
    1086           0 :                                      "");
    1087             : }
    1088             : 
    1089             : /**
    1090             :  * Check if the certificate has been revoked
    1091             :  */
    1092             : TlsValidator::CheckResult
    1093           0 : TlsValidator::notRevoked()
    1094             : {
    1095           0 :     return TlsValidator::CheckResult((compareToCa() & GNUTLS_CERT_REVOKED)
    1096           0 :                                              || (compareToCa()
    1097           0 :                                                  & GNUTLS_CERT_REVOCATION_DATA_ISSUED_IN_FUTURE)
    1098           0 :                                          ? CheckValues::FAILED
    1099             :                                          : CheckValues::PASSED,
    1100           0 :                                      "");
    1101             : }
    1102             : 
    1103             : /**
    1104             :  * A certificate authority has been provided
    1105             :  */
    1106             : bool
    1107           0 : TlsValidator::hasCa() const
    1108             : {
    1109           0 :     return (x509crt_ and x509crt_->issuer); /* or
    1110             :             (caCert_ != nullptr and caCert_->certificateFound_);*/
    1111             : }
    1112             : 
    1113             : //
    1114             : // Certificate details
    1115             : //
    1116             : 
    1117             : // TODO gnutls_x509_crl_get_this_update
    1118             : 
    1119             : /**
    1120             :  * An hexadecimal representation of the signature
    1121             :  */
    1122             : TlsValidator::CheckResult
    1123           0 : TlsValidator::getPublicSignature()
    1124             : {
    1125           0 :     size_t resultSize = sizeof(copy_buffer);
    1126           0 :     int err = gnutls_x509_crt_get_signature(x509crt_->cert, copy_buffer, &resultSize);
    1127           0 :     return checkBinaryError(err, copy_buffer, resultSize);
    1128             : }
    1129             : 
    1130             : /**
    1131             :  * Return the certificate version
    1132             :  */
    1133             : TlsValidator::CheckResult
    1134           0 : TlsValidator::getVersionNumber()
    1135             : {
    1136           0 :     int version = gnutls_x509_crt_get_version(x509crt_->cert);
    1137           0 :     if (version < 0)
    1138           0 :         return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
    1139             : 
    1140           0 :     std::ostringstream convert;
    1141           0 :     convert << version;
    1142             : 
    1143           0 :     return TlsValidator::CheckResult(CheckValues::NUMBER, convert.str());
    1144           0 : }
    1145             : 
    1146             : /**
    1147             :  * Return the certificate serial number
    1148             :  */
    1149             : TlsValidator::CheckResult
    1150           0 : TlsValidator::getSerialNumber()
    1151             : {
    1152             :     // gnutls_x509_crl_iter_crt_serial
    1153             :     // gnutls_x509_crt_get_authority_key_gn_serial
    1154           0 :     size_t resultSize = sizeof(copy_buffer);
    1155           0 :     int err = gnutls_x509_crt_get_serial(x509crt_->cert, copy_buffer, &resultSize);
    1156           0 :     return checkBinaryError(err, copy_buffer, resultSize);
    1157             : }
    1158             : 
    1159             : /**
    1160             :  * If the certificate is not self signed, return the issuer
    1161             :  */
    1162             : TlsValidator::CheckResult
    1163           0 : TlsValidator::getIssuer()
    1164             : {
    1165           0 :     if (not x509crt_->issuer) {
    1166           0 :         auto icrt = certStore_.findIssuer(x509crt_);
    1167           0 :         if (icrt)
    1168           0 :             return TlsValidator::CheckResult(CheckValues::CUSTOM, icrt->getId().toString());
    1169           0 :         return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
    1170           0 :     }
    1171           0 :     return TlsValidator::CheckResult(CheckValues::CUSTOM, x509crt_->issuer->getId().toString());
    1172             : }
    1173             : 
    1174             : /**
    1175             :  * The algorithm used to sign the certificate details (rather than the certificate itself)
    1176             :  */
    1177             : TlsValidator::CheckResult
    1178           0 : TlsValidator::getSubjectKeyAlgorithm()
    1179             : {
    1180           0 :     unsigned key_length = 0;
    1181             :     gnutls_pk_algorithm_t algo = (gnutls_pk_algorithm_t)
    1182           0 :         gnutls_x509_crt_get_pk_algorithm(x509crt_->cert, &key_length);
    1183             : 
    1184           0 :     if (algo < 0)
    1185           0 :         return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
    1186             : 
    1187           0 :     const char* name = gnutls_pk_get_name(algo);
    1188             : 
    1189           0 :     if (!name)
    1190           0 :         return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
    1191             : 
    1192           0 :     if (key_length)
    1193           0 :         return TlsValidator::CheckResult(CheckValues::CUSTOM, fmt::format("{} ({} bits)", name, key_length));
    1194             :     else
    1195           0 :         return TlsValidator::CheckResult(CheckValues::CUSTOM, name);
    1196             : }
    1197             : 
    1198             : /**
    1199             :  * The subject public key
    1200             :  */
    1201             : TlsValidator::CheckResult
    1202           0 : TlsValidator::getSubjectKey()
    1203             : {
    1204             :     try {
    1205           0 :         std::vector<uint8_t> data;
    1206           0 :         x509crt_->getPublicKey().pack(data);
    1207           0 :         return TlsValidator::CheckResult(CheckValues::CUSTOM, dht::toHex(data));
    1208           0 :     } catch (const dht::crypto::CryptoException& e) {
    1209           0 :         return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, e.what());
    1210           0 :     }
    1211             : }
    1212             : 
    1213             : /**
    1214             :  * The 'CN' section of a DN (RFC4514)
    1215             :  */
    1216             : TlsValidator::CheckResult
    1217           0 : TlsValidator::getCN()
    1218             : {
    1219             :     // TODO split, cache
    1220           0 :     size_t resultSize = sizeof(copy_buffer);
    1221           0 :     int err = gnutls_x509_crt_get_dn_by_oid(x509crt_->cert,
    1222             :                                             GNUTLS_OID_X520_COMMON_NAME,
    1223             :                                             0,
    1224             :                                             0,
    1225           0 :                                             copy_buffer,
    1226             :                                             &resultSize);
    1227           0 :     return checkError(err, copy_buffer, resultSize);
    1228             : }
    1229             : 
    1230             : /**
    1231             :  * The 'UID' section of a DN (RFC4514)
    1232             :  */
    1233             : TlsValidator::CheckResult
    1234           0 : TlsValidator::getUID()
    1235             : {
    1236           0 :     size_t resultSize = sizeof(copy_buffer);
    1237           0 :     int err = gnutls_x509_crt_get_dn_by_oid(x509crt_->cert,
    1238             :                                             GNUTLS_OID_LDAP_UID,
    1239             :                                             0,
    1240             :                                             0,
    1241           0 :                                             copy_buffer,
    1242             :                                             &resultSize);
    1243           0 :     return checkError(err, copy_buffer, resultSize);
    1244             : }
    1245             : 
    1246             : /**
    1247             :  * The 'N' section of a DN (RFC4514)
    1248             :  */
    1249             : TlsValidator::CheckResult
    1250           0 : TlsValidator::getN()
    1251             : {
    1252             :     // TODO split, cache
    1253           0 :     size_t resultSize = sizeof(copy_buffer);
    1254           0 :     int err = gnutls_x509_crt_get_dn_by_oid(x509crt_->cert,
    1255             :                                             GNUTLS_OID_X520_NAME,
    1256             :                                             0,
    1257             :                                             0,
    1258           0 :                                             copy_buffer,
    1259             :                                             &resultSize);
    1260           0 :     return checkError(err, copy_buffer, resultSize);
    1261             : }
    1262             : 
    1263             : /**
    1264             :  * The 'O' section of a DN (RFC4514)
    1265             :  */
    1266             : TlsValidator::CheckResult
    1267           0 : TlsValidator::getO()
    1268             : {
    1269             :     // TODO split, cache
    1270           0 :     size_t resultSize = sizeof(copy_buffer);
    1271           0 :     int err = gnutls_x509_crt_get_dn_by_oid(x509crt_->cert,
    1272             :                                             GNUTLS_OID_X520_ORGANIZATION_NAME,
    1273             :                                             0,
    1274             :                                             0,
    1275           0 :                                             copy_buffer,
    1276             :                                             &resultSize);
    1277           0 :     return checkError(err, copy_buffer, resultSize);
    1278             : }
    1279             : 
    1280             : /**
    1281             :  * Return the algorithm used to sign the Key
    1282             :  *
    1283             :  * For example: RSA
    1284             :  */
    1285             : TlsValidator::CheckResult
    1286           0 : TlsValidator::getSignatureAlgorithm()
    1287             : {
    1288           0 :     gnutls_sign_algorithm_t algo = (gnutls_sign_algorithm_t) gnutls_x509_crt_get_signature_algorithm(
    1289           0 :         x509crt_->cert);
    1290             : 
    1291           0 :     if (algo < 0)
    1292           0 :         return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
    1293             : 
    1294           0 :     const char* algoName = gnutls_sign_get_name(algo);
    1295           0 :     return TlsValidator::CheckResult(CheckValues::CUSTOM, algoName);
    1296             : }
    1297             : 
    1298             : /**
    1299             :  *Compute the key fingerprint
    1300             :  *
    1301             :  * This need to be used along with getSha1Fingerprint() to avoid collisions
    1302             :  */
    1303             : TlsValidator::CheckResult
    1304           0 : TlsValidator::getMd5Fingerprint()
    1305             : {
    1306           0 :     size_t resultSize = sizeof(copy_buffer);
    1307           0 :     int err = gnutls_x509_crt_get_fingerprint(x509crt_->cert,
    1308             :                                               GNUTLS_DIG_MD5,
    1309           0 :                                               copy_buffer,
    1310             :                                               &resultSize);
    1311           0 :     return checkBinaryError(err, copy_buffer, resultSize);
    1312             : }
    1313             : 
    1314             : /**
    1315             :  * Compute the key fingerprint
    1316             :  *
    1317             :  * This need to be used along with getMd5Fingerprint() to avoid collisions
    1318             :  */
    1319             : TlsValidator::CheckResult
    1320           0 : TlsValidator::getSha1Fingerprint()
    1321             : {
    1322           0 :     size_t resultSize = sizeof(copy_buffer);
    1323           0 :     int err = gnutls_x509_crt_get_fingerprint(x509crt_->cert,
    1324             :                                               GNUTLS_DIG_SHA1,
    1325           0 :                                               copy_buffer,
    1326             :                                               &resultSize);
    1327           0 :     return checkBinaryError(err, copy_buffer, resultSize);
    1328             : }
    1329             : 
    1330             : /**
    1331             :  * Return an hexadecimal identifier
    1332             :  */
    1333             : TlsValidator::CheckResult
    1334           0 : TlsValidator::getPublicKeyId()
    1335             : {
    1336             :     static unsigned char unsigned_copy_buffer[4096];
    1337           0 :     size_t resultSize = sizeof(unsigned_copy_buffer);
    1338           0 :     int err = gnutls_x509_crt_get_key_id(x509crt_->cert, 0, unsigned_copy_buffer, &resultSize);
    1339             : 
    1340             :     // TODO check for GNUTLS_E_SHORT_MEMORY_BUFFER and increase the buffer size
    1341             :     // TODO get rid of the cast, display a HEX or something, need research
    1342             : 
    1343           0 :     return checkBinaryError(err, (char*) unsigned_copy_buffer, resultSize);
    1344             : }
    1345             : // gnutls_x509_crt_get_authority_key_id
    1346             : 
    1347             : /**
    1348             :  *  If the certificate is not self signed, return the issuer DN (RFC4514)
    1349             :  */
    1350             : TlsValidator::CheckResult
    1351           0 : TlsValidator::getIssuerDN()
    1352             : {
    1353           0 :     size_t resultSize = sizeof(copy_buffer);
    1354           0 :     int err = gnutls_x509_crt_get_issuer_dn(x509crt_->cert, copy_buffer, &resultSize);
    1355           0 :     return checkError(err, copy_buffer, resultSize);
    1356             : }
    1357             : 
    1358             : /**
    1359             :  *  If the certificate is not self signed, return the issuer CN
    1360             :  */
    1361             : TlsValidator::CheckResult
    1362           0 : TlsValidator::getIssuerCN()
    1363             : {
    1364           0 :     size_t resultSize = sizeof(copy_buffer);
    1365           0 :     int err = gnutls_x509_crt_get_issuer_dn_by_oid(x509crt_->cert,
    1366             :                                                    GNUTLS_OID_X520_COMMON_NAME,
    1367             :                                                    0,
    1368             :                                                    0,
    1369           0 :                                                    copy_buffer,
    1370             :                                                    &resultSize);
    1371           0 :     return checkError(err, copy_buffer, resultSize);
    1372             : }
    1373             : 
    1374             : /**
    1375             :  *  If the certificate is not self signed, return the issuer UID
    1376             :  */
    1377             : TlsValidator::CheckResult
    1378           0 : TlsValidator::getIssuerUID()
    1379             : {
    1380           0 :     size_t resultSize = sizeof(copy_buffer);
    1381           0 :     int err = gnutls_x509_crt_get_issuer_dn_by_oid(x509crt_->cert,
    1382             :                                                    GNUTLS_OID_LDAP_UID,
    1383             :                                                    0,
    1384             :                                                    0,
    1385           0 :                                                    copy_buffer,
    1386             :                                                    &resultSize);
    1387           0 :     return checkError(err, copy_buffer, resultSize);
    1388             : }
    1389             : 
    1390             : /**
    1391             :  *  If the certificate is not self signed, return the issuer N
    1392             :  */
    1393             : TlsValidator::CheckResult
    1394           0 : TlsValidator::getIssuerN()
    1395             : {
    1396           0 :     size_t resultSize = sizeof(copy_buffer);
    1397           0 :     int err = gnutls_x509_crt_get_issuer_dn_by_oid(x509crt_->cert,
    1398             :                                                    GNUTLS_OID_X520_NAME,
    1399             :                                                    0,
    1400             :                                                    0,
    1401           0 :                                                    copy_buffer,
    1402             :                                                    &resultSize);
    1403           0 :     return checkError(err, copy_buffer, resultSize);
    1404             : }
    1405             : 
    1406             : /**
    1407             :  *  If the certificate is not self signed, return the issuer O
    1408             :  */
    1409             : TlsValidator::CheckResult
    1410           0 : TlsValidator::getIssuerO()
    1411             : {
    1412           0 :     size_t resultSize = sizeof(copy_buffer);
    1413           0 :     int err = gnutls_x509_crt_get_issuer_dn_by_oid(x509crt_->cert,
    1414             :                                                    GNUTLS_OID_X520_ORGANIZATION_NAME,
    1415             :                                                    0,
    1416             :                                                    0,
    1417           0 :                                                    copy_buffer,
    1418             :                                                    &resultSize);
    1419           0 :     return checkError(err, copy_buffer, resultSize);
    1420             : }
    1421             : 
    1422             : /**
    1423             :  * Get the expiration date
    1424             :  *
    1425             :  * @todo Move to "certificateDetails()" method once completed
    1426             :  */
    1427             : TlsValidator::CheckResult
    1428           0 : TlsValidator::getExpirationDate()
    1429             : {
    1430           0 :     if (not certificateFound_)
    1431           0 :         return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
    1432             : 
    1433           0 :     time_t expiration = gnutls_x509_crt_get_expiration_time(x509crt_->cert);
    1434             : 
    1435           0 :     return formatDate(expiration);
    1436             : }
    1437             : 
    1438             : /**
    1439             :  * Get the activation date
    1440             :  *
    1441             :  * @todo Move to "certificateDetails()" method once completed
    1442             :  */
    1443             : TlsValidator::CheckResult
    1444           0 : TlsValidator::getActivationDate()
    1445             : {
    1446           0 :     if (not certificateFound_)
    1447           0 :         return TlsValidator::CheckResult(CheckValues::UNSUPPORTED, "");
    1448             : 
    1449           0 :     time_t expiration = gnutls_x509_crt_get_activation_time(x509crt_->cert);
    1450             : 
    1451           0 :     return formatDate(expiration);
    1452             : }
    1453             : 
    1454             : /**
    1455             :  * The expected outgoing server domain
    1456             :  *
    1457             :  * @todo Move to "certificateDetails()" method once completed
    1458             :  * @todo extract information for the certificate
    1459             :  */
    1460             : TlsValidator::CheckResult
    1461           0 : TlsValidator::outgoingServer()
    1462             : {
    1463             :     // TODO
    1464           0 :     return TlsValidator::CheckResult(CheckValues::CUSTOM, "");
    1465             : }
    1466             : 
    1467             : /**
    1468             :  * If the certificate is not self signed, return the issuer
    1469             :  */
    1470             : TlsValidator::CheckResult
    1471           0 : TlsValidator::isCA()
    1472             : {
    1473           0 :     return TlsValidator::CheckResult(CheckValues::CUSTOM, x509crt_->isCA() ? TRUE_STR : FALSE_STR);
    1474             : }
    1475             : 
    1476             : } // namespace tls
    1477             : } // namespace jami

Generated by: LCOV version 1.14