LCOV - code coverage report
Current view: top level - foo/src/connectivity/security - tlsvalidator.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 0 397 0.0 %
Date: 2025-10-16 08:11:43 Functions: 0 61 0.0 %

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

Generated by: LCOV version 1.14