LCOV - code coverage report
Current view: top level - src/connectivity/security - tlsvalidator.h (source / functions) Coverage Total Hit
Test: jami-coverage-filtered.info Lines: 0.0 % 3 0
Test Date: 2026-06-13 09:18:46 Functions: 0.0 % 2 0

            Line data    Source code
       1              : /*
       2              :  *  Copyright (C) 2004-2026 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              : #pragma once
      18              : 
      19              : #include "enumclass_utils.h"
      20              : #include <dhtnet/certstore.h>
      21              : 
      22              : #include <string>
      23              : #include <vector>
      24              : #include <memory>
      25              : 
      26              : // OpenDHT
      27              : namespace dht {
      28              : namespace crypto {
      29              : struct Certificate;
      30              : }
      31              : } // namespace dht
      32              : 
      33              : namespace jami {
      34              : namespace tls {
      35              : 
      36              : #if !defined(S_IRWXG)
      37              : #define S_IRWXG 00070
      38              : #endif /* S_IRWXG */
      39              : #if !defined(S_IRGRP)
      40              : #define S_IRGRP 00040
      41              : #endif /* S_IRGRP */
      42              : #if !defined(S_IWGRP)
      43              : #define S_IWGRP 00020
      44              : #endif /* S_IWGRP */
      45              : #if !defined(S_IXGRP)
      46              : #define S_IXGRP 00010
      47              : #endif /* S_IXGRP */
      48              : #if !defined(S_IRWXO)
      49              : #define S_IRWXO 00007
      50              : #endif /* S_IRWXO */
      51              : #if !defined(S_IROTH)
      52              : #define S_IROTH 00004
      53              : #endif /* S_IROTH */
      54              : #if !defined(S_IWOTH)
      55              : #define S_IWOTH 00002
      56              : #endif /* S_IWOTH */
      57              : #if !defined(S_IXOTH)
      58              : #define S_IXOTH 00001
      59              : #endif /* S_IXOTH */
      60              : 
      61              : class TlsValidatorException : public std::runtime_error
      62              : {
      63              : public:
      64            0 :     TlsValidatorException(const std::string& str)
      65            0 :         : std::runtime_error(str) {};
      66              : };
      67              : 
      68              : class TlsValidator
      69              : {
      70              : public:
      71              :     /**
      72              :      * @enum CertificateCheck All validation fields
      73              :      *
      74              :      */
      75              :     enum class CertificateCheck : std::uint8_t {
      76              :         HAS_PRIVATE_KEY,                   /** This certificate has a build in private key                          */
      77              :         EXPIRED,                           /** This certificate is past its expiration date                         */
      78              :         STRONG_SIGNING,                    /** This certificate has been signed with a brute-force-able method      */
      79              :         NOT_SELF_SIGNED,                   /** This certificate has been self signed                                */
      80              :         KEY_MATCH,                         /** The public and private keys provided don't match                     */
      81              :         PRIVATE_KEY_STORAGE_PERMISSION,    /** The file hosting the private key isn't correctly secured */
      82              :         PUBLIC_KEY_STORAGE_PERMISSION,     /** The file hosting the public key isn't correctly secured */
      83              :         PRIVATE_KEY_DIRECTORY_PERMISSIONS, /** The folder storing the private key isn't correctly
      84              :                                               secured           */
      85              :         PUBLIC_KEY_DIRECTORY_PERMISSIONS,  /** The folder storing the public key isn't correctly
      86              :                                               secured            */
      87              :         PRIVATE_KEY_STORAGE_LOCATION,      /** Some operating systems have extra policies for certificate
      88              :                                               storage   */
      89              :         PUBLIC_KEY_STORAGE_LOCATION,       /** Some operating systems have extra policies for certificate
      90              :                                               storage   */
      91              :         PRIVATE_KEY_SELINUX_ATTRIBUTES,    /** Some operating systems require keys to have extra
      92              :                                               attributes         */
      93              :         PUBLIC_KEY_SELINUX_ATTRIBUTES,     /** Some operating systems require keys to have extra
      94              :                                               attributes         */
      95              :         EXIST,                             /** The certificate file doesn't exist or is not accessible              */
      96              :         VALID,                             /** The file is not a certificate                                        */
      97              :         VALID_AUTHORITY,                   /** The claimed authority did not sign the certificate                   */
      98              :         KNOWN_AUTHORITY,                   /** Some operating systems provide a list of trusted authorities, use it */
      99              :         NOT_REVOKED,                       /** The certificate has been revoked by the authority                    */
     100              :         AUTHORITY_MISMATCH,                /** The certificate and authority mismatch */
     101              :         UNEXPECTED_OWNER,                  /** The certificate has an expected owner   */
     102              :         NOT_ACTIVATED,                     /** The certificate has not been activated yet                           */
     103              :         COUNT__,
     104              :     };
     105              : 
     106              :     /**
     107              :      * @enum CertificateDetails Informative fields about a certificate
     108              :      */
     109              :     enum class CertificateDetails : std::uint8_t {
     110              :         EXPIRATION_DATE,              /** The certificate expiration date                                      */
     111              :         ACTIVATION_DATE,              /** The certificate activation date                                      */
     112              :         REQUIRE_PRIVATE_KEY_PASSWORD, /** Does the private key require a password */
     113              :         PUBLIC_SIGNATURE,
     114              :         VERSION_NUMBER,
     115              :         SERIAL_NUMBER,
     116              :         ISSUER,
     117              :         SUBJECT_KEY_ALGORITHM,
     118              :         SUBJECT_KEY,
     119              :         CN,
     120              :         UID,
     121              :         N,
     122              :         O,
     123              :         SIGNATURE_ALGORITHM,
     124              :         MD5_FINGERPRINT,
     125              :         SHA1_FINGERPRINT,
     126              :         PUBLIC_KEY_ID,
     127              :         ISSUER_DN,
     128              :         ISSUER_CN,
     129              :         ISSUER_UID,
     130              :         ISSUER_N,
     131              :         ISSUER_O,
     132              :         NEXT_EXPECTED_UPDATE_DATE,
     133              :         OUTGOING_SERVER, /** The hostname/outgoing server used for this certificate               */
     134              :         IS_CA,
     135              :         COUNT__
     136              :     };
     137              : 
     138              :     /**
     139              :      * @enum CheckValuesType Categories of possible values for each CertificateCheck
     140              :      */
     141              :     enum class CheckValuesType : std::uint8_t {
     142              :         BOOLEAN,
     143              :         ISO_DATE,
     144              :         CUSTOM,
     145              :         NUMBER,
     146              :         COUNT__,
     147              :     };
     148              : 
     149              :     /**
     150              :      * @enum CheckValue possible values for check
     151              :      *
     152              :      * All boolean check use PASSED when the test result is positive and
     153              :      * FAILED when it is negative. All new check need to keep this convention
     154              :      * or ::isValid() result will become unrepresentative of the real state.
     155              :      *
     156              :      * CUSTOM should be avoided when possible. This enum can be extended when
     157              :      * new validated types are required.
     158              :      */
     159              :     enum class CheckValues : std::uint8_t {
     160              :         PASSED,      /** Equivalent of a boolean "true"                                    */
     161              :         FAILED,      /** Equivalent of a boolean "false"                                   */
     162              :         UNSUPPORTED, /** The operating system doesn't support or require the check         */
     163              :         ISO_DATE,    /** The check value is an ISO 8601 date YYYY-MM-DD[TH24:MM:SS+00:00]  */
     164              :         CUSTOM,      /** The check value cannot be represented with a finite set of values */
     165              :         NUMBER,
     166              :         COUNT__,
     167              :     };
     168              : 
     169              :     /**
     170              :      * @typedef CheckResult A validated and unvalidated result pair
     171              :      *
     172              :      * The CheckValue is the most important value of the pair. The string
     173              :      * can either be the value of a CheckValues::CUSTOM result or an
     174              :      * error code (where applicable).
     175              :      */
     176              :     using CheckResult = std::pair<CheckValues, std::string>;
     177              : 
     178              :     /**
     179              :      * Create a TlsValidator for a given certificate
     180              :      * @param certificate The certificate path
     181              :      * @param privatekey An optional private key file path
     182              :      * @param privatekeyPasswd An optional private key password
     183              :      * @param caList An optional CA list to use for certificate validation
     184              :      */
     185              :     TlsValidator(const dhtnet::tls::CertificateStore& certStore,
     186              :                  const std::string& certificate,
     187              :                  const std::string& privatekey = "",
     188              :                  const std::string& privatekeyPasswd = "",
     189              :                  const std::string& caList = "");
     190              : 
     191              :     TlsValidator(const dhtnet::tls::CertificateStore& certStore,
     192              :                  const std::vector<std::vector<uint8_t>>& certificate_chain_raw);
     193              : 
     194              :     TlsValidator(const dhtnet::tls::CertificateStore& certStore, const std::vector<uint8_t>& certificate_raw);
     195              : 
     196              :     TlsValidator(const dhtnet::tls::CertificateStore& certStore, const std::shared_ptr<dht::crypto::Certificate>&);
     197              : 
     198              :     ~TlsValidator();
     199              : 
     200              :     bool hasCa() const;
     201              : 
     202              :     bool isValid(bool verbose = false);
     203              : 
     204              :     // Security checks
     205              :     CheckResult hasPrivateKey();
     206              :     CheckResult notExpired();
     207              :     CheckResult strongSigning();
     208              :     CheckResult notSelfSigned();
     209              :     CheckResult keyMatch();
     210              :     CheckResult privateKeyStoragePermissions();
     211              :     CheckResult publicKeyStoragePermissions();
     212              :     CheckResult privateKeyDirectoryPermissions();
     213              :     CheckResult publicKeyDirectoryPermissions();
     214              :     CheckResult privateKeyStorageLocation();
     215              :     CheckResult publicKeyStorageLocation();
     216              :     CheckResult privateKeySelinuxAttributes();
     217              :     CheckResult publicKeySelinuxAttributes();
     218              :     CheckResult exist();
     219              :     CheckResult valid();
     220              :     CheckResult validAuthority();
     221              :     CheckResult knownAuthority();
     222              :     CheckResult notRevoked();
     223              :     CheckResult authorityMatch();
     224              :     CheckResult expectedOwner();
     225              :     CheckResult activated();
     226              : 
     227              :     // Certificate details
     228              :     CheckResult getExpirationDate();
     229              :     CheckResult getActivationDate();
     230              :     CheckResult requirePrivateKeyPassword();
     231              :     CheckResult getPublicSignature();
     232              :     CheckResult getVersionNumber();
     233              :     CheckResult getSerialNumber();
     234              :     CheckResult getIssuer();
     235              :     CheckResult getSubjectKeyAlgorithm();
     236              :     CheckResult getSubjectKey();
     237              :     CheckResult getCN();
     238              :     CheckResult getUID();
     239              :     CheckResult getN();
     240              :     CheckResult getO();
     241              :     CheckResult getSignatureAlgorithm();
     242              :     CheckResult getMd5Fingerprint();
     243              :     CheckResult getSha1Fingerprint();
     244              :     CheckResult getPublicKeyId();
     245              :     CheckResult getIssuerDN();
     246              :     CheckResult getIssuerCN();
     247              :     CheckResult getIssuerUID();
     248              :     CheckResult getIssuerN();
     249              :     CheckResult getIssuerO();
     250              :     CheckResult outgoingServer();
     251              :     CheckResult isCA();
     252              : 
     253              :     void setCaTlsValidator(const TlsValidator& validator);
     254              : 
     255              :     std::map<std::string, std::string> getSerializedChecks();
     256              : 
     257              :     std::map<std::string, std::string> getSerializedDetails();
     258              : 
     259            0 :     std::shared_ptr<dht::crypto::Certificate> getCertificate() const { return x509crt_; }
     260              : 
     261              : private:
     262              :     // Enum class names
     263              :     static const EnumClassNames<CertificateCheck> CertificateCheckNames;
     264              : 
     265              :     static const EnumClassNames<CertificateDetails> CertificateDetailsNames;
     266              : 
     267              :     static const EnumClassNames<const CheckValuesType> CheckValuesTypeNames;
     268              : 
     269              :     static const EnumClassNames<CheckValues> CheckValuesNames;
     270              : 
     271              :     /**
     272              :      * Map check to their check method
     273              :      */
     274              :     static const CallbackMatrix1D<CertificateCheck, TlsValidator, CheckResult> checkCallback;
     275              : 
     276              :     /**
     277              :      * Map check to their getter method
     278              :      */
     279              :     static const CallbackMatrix1D<CertificateDetails, TlsValidator, CheckResult> getterCallback;
     280              : 
     281              :     /**
     282              :      * Valid values for each categories
     283              :      */
     284              :     static const Matrix2D<CheckValuesType, CheckValues, bool> acceptedCheckValuesResult;
     285              : 
     286              :     static const Matrix1D<CertificateCheck, CheckValuesType> enforcedCheckType;
     287              : 
     288              :     const dhtnet::tls::CertificateStore& certStore_;
     289              :     std::string certificatePath_;
     290              :     std::string privateKeyPath_;
     291              :     std::string caListPath_ {};
     292              : 
     293              :     std::vector<uint8_t> certificateContent_;
     294              : 
     295              :     std::shared_ptr<dht::crypto::Certificate> x509crt_;
     296              : 
     297              :     bool certificateFileFound_ {false};
     298              :     bool certificateFound_ {false};
     299              :     bool privateKeyFound_ {false};
     300              :     bool privateKeyPassword_ {false};
     301              :     bool privateKeyMatch_ {false};
     302              : 
     303              :     bool caChecked_ {false};
     304              :     unsigned int caValidationOutput_ {
     305              :         0}; // 0 means "no flags set", where flags are ones from gnutls_certificate_status_t
     306              : 
     307              :     mutable char copy_buffer[4096];
     308              : 
     309              :     /**
     310              :      * Helper method to convert a CheckResult into a std::string
     311              :      */
     312              :     std::string getStringValue(const CertificateCheck check, const CheckResult& result);
     313              : 
     314              :     // Helper
     315              :     unsigned int compareToCa();
     316              : 
     317              : public:
     318              : #if 0 // TODO reimplement this method. do not use it as it
     319              :     /**
     320              :      * Verify that the local hostname points to a valid SSL server by
     321              :      * establishing a connection to it and by validating its certificate.
     322              :      *
     323              :      * @param host the DNS domain address that the certificate should feature
     324              :      * @return 0 if success, -1 otherwise
     325              :      */
     326              :     static int verifyHostnameCertificate(const std::string& host,
     327              :                                          const uint16_t port);
     328              : #endif
     329              : 
     330              : }; // TlsValidator
     331              : 
     332              : } // namespace tls
     333              : } // namespace jami
        

Generated by: LCOV version 2.0-1