SolidSyslog coverage report
Current view: top level - Platform/OpenSsl/Source - SolidSyslogOpenSslPemFileCredentials.c (source / functions) Coverage Total Hit
Test: SolidSyslog Lines: 100.0 % 44 44
Test Date: 2026-11-12 23:14:35 Functions: 100.0 % 8 8
Branches: 100.0 % 22 22

             Branch data     Line data    Source code
       1                 :             : /* SPDX-FileCopyrightText: Copyright 2026 Cozens Software Solutions Limited
       2                 :             :  * SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 OR LicenseRef-PolyForm-Internal-Use-1.0.0 OR LicenseRef-COSOSO-Commercial
       3                 :             :  */
       4                 :             : 
       5                 :             : #include "SolidSyslogOpenSslPemFileCredentials.h"
       6                 :             : 
       7                 :             : #include <stdbool.h>
       8                 :             : #include <stddef.h>
       9                 :             : 
      10                 :             : #include <openssl/ssl.h>
      11                 :             : 
      12                 :             : #include "SolidSyslogOpenSslCredentialsDefinition.h"
      13                 :             : #include "SolidSyslogErrorCategory.h"
      14                 :             : #include "SolidSyslogOpenSslPemFileCredentialsPrivate.h"
      15                 :             : #include "SolidSyslogTlsCredentialsInstalled.h"
      16                 :             : 
      17                 :             : const struct SolidSyslogErrorSource SolidSyslogOpenSslPemFileCredentialsErrorSource = {
      18                 :             :     "OpenSslPemFileCredentials",
      19                 :             :     SolidSyslogTlsCredentialsErrors_Name
      20                 :             : };
      21                 :             : 
      22                 :             : static bool OpenSslPemFileCredentials_Install(
      23                 :             :     struct SolidSyslogOpenSslCredentials* base,
      24                 :             :     SSL_CTX* ctx,
      25                 :             :     struct SolidSyslogTlsCredentialsInstalled* installed
      26                 :             : );
      27                 :             : static inline void OpenSslPemFileCredentials_ConfigureClientIdentity(
      28                 :             :     SSL_CTX* ctx,
      29                 :             :     const struct SolidSyslogOpenSslPemFileCredentialsConfig* config
      30                 :             : );
      31                 :             : static inline bool OpenSslPemFileCredentials_HasClientCredential(
      32                 :             :     const struct SolidSyslogOpenSslPemFileCredentialsConfig* config
      33                 :             : );
      34                 :             : static inline bool OpenSslPemFileCredentials_HasHalfOfClientCredential(
      35                 :             :     const struct SolidSyslogOpenSslPemFileCredentialsConfig* config
      36                 :             : );
      37                 :             : static inline void OpenSslPemFileCredentials_LoadClientCredential(
      38                 :             :     SSL_CTX* ctx,
      39                 :             :     const struct SolidSyslogOpenSslPemFileCredentialsConfig* config
      40                 :             : );
      41                 :             : static void OpenSslPemFileCredentials_Release(struct SolidSyslogOpenSslCredentials* base);
      42                 :             : static inline struct SolidSyslogOpenSslPemFileCredentials* OpenSslPemFileCredentials_SelfFromBase(
      43                 :             :     struct SolidSyslogOpenSslCredentials* base
      44                 :             : );
      45                 :             : 
      46                 :          57 : void SolidSyslogOpenSslPemFileCredentials_Initialise(
      47                 :             :     struct SolidSyslogOpenSslCredentials* base,
      48                 :             :     const struct SolidSyslogOpenSslPemFileCredentialsConfig* config
      49                 :             : )
      50                 :             : {
      51                 :          57 :     struct SolidSyslogOpenSslPemFileCredentials* self = OpenSslPemFileCredentials_SelfFromBase(base);
      52                 :          57 :     self->Base.Install = OpenSslPemFileCredentials_Install;
      53                 :          57 :     self->Base.Release = OpenSslPemFileCredentials_Release;
      54                 :          57 :     self->Config = *config;
      55                 :          57 :     self->InstallHealth = (struct SolidSyslogStreamOpenHealth) {0};
      56                 :          57 : }
      57                 :             : 
      58                 :         112 : static inline struct SolidSyslogOpenSslPemFileCredentials* OpenSslPemFileCredentials_SelfFromBase(
      59                 :             :     struct SolidSyslogOpenSslCredentials* base
      60                 :             : )
      61                 :             : {
      62                 :         112 :     return (struct SolidSyslogOpenSslPemFileCredentials*) base;
      63                 :             : }
      64                 :             : 
      65                 :             : /* Trust anchors are named by path and opened by OpenSSL - this library performs
      66                 :             :  * no file handling of its own, so the PEM bytes never pass through it. The
      67                 :             :  * paths are re-read here rather than at Create, so a credential replaced while
      68                 :             :  * the device runs is picked up on the next connection. */
      69                 :          55 : static bool OpenSslPemFileCredentials_Install(
      70                 :             :     struct SolidSyslogOpenSslCredentials* base,
      71                 :             :     SSL_CTX* ctx,
      72                 :             :     struct SolidSyslogTlsCredentialsInstalled* installed
      73                 :             : )
      74                 :             : {
      75                 :          55 :     struct SolidSyslogOpenSslPemFileCredentials* self = OpenSslPemFileCredentials_SelfFromBase(base);
      76                 :          55 :     bool ok = true;
      77                 :          55 :     installed->TrustAnchorsInstalled = false;
      78                 :          55 :     installed->Fingerprints = self->Config.PeerFingerprints;
      79                 :          55 :     installed->FingerprintCount = self->Config.PeerFingerprintCount;
      80         [ +  + ]:          55 :     if (self->Config.CaBundlePath != NULL)
      81                 :             :     {
      82                 :          44 :         installed->TrustAnchorsInstalled = SSL_CTX_load_verify_locations(ctx, self->Config.CaBundlePath, NULL) == 1;
      83                 :          44 :         ok = installed->TrustAnchorsInstalled;
      84         [ +  + ]:          44 :         if (!ok)
      85                 :             :         {
      86                 :           8 :             OpenSslPemFileCredentials_ReportInstallFailure(
      87                 :             :                 self,
      88                 :             :                 SOLIDSYSLOG_SEVERITY_ERROR,
      89                 :             :                 SOLIDSYSLOG_CAT_BAD_CONFIG,
      90                 :             :                 SOLIDSYSLOG_TLS_CREDENTIALS_ERROR_TRUST_ANCHORS_NOT_LOADED
      91                 :             :             );
      92                 :             :         }
      93                 :             :     }
      94         [ +  + ]:          55 :     if (ok)
      95                 :             :     {
      96                 :          47 :         SolidSyslogStreamOpenHealth_Opened(&self->InstallHealth);
      97                 :             :     }
      98                 :          55 :     OpenSslPemFileCredentials_ConfigureClientIdentity(ctx, &self->Config);
      99                 :          55 :     return ok;
     100                 :             : }
     101                 :             : 
     102                 :             : /* No fault in our own credential stops delivery: the collector is the
     103                 :             :  * enforcement point for it, and one that requires a client certificate refuses
     104                 :             :  * the handshake anyway. OpenSSL presents a certificate only where both halves
     105                 :             :  * are installed and paired, so a credential it will not take degrades to
     106                 :             :  * server-authenticated TLS rather than being half-presented. */
     107                 :          55 : static inline void OpenSslPemFileCredentials_ConfigureClientIdentity(
     108                 :             :     SSL_CTX* ctx,
     109                 :             :     const struct SolidSyslogOpenSslPemFileCredentialsConfig* config
     110                 :             : )
     111                 :             : {
     112         [ +  + ]:          55 :     if (OpenSslPemFileCredentials_HasClientCredential(config))
     113                 :             :     {
     114                 :           7 :         OpenSslPemFileCredentials_LoadClientCredential(ctx, config);
     115                 :             :     }
     116         [ +  + ]:          48 :     else if (OpenSslPemFileCredentials_HasHalfOfClientCredential(config))
     117                 :             :     {
     118                 :           1 :         OpenSslPemFileCredentials_Report(
     119                 :             :             SOLIDSYSLOG_SEVERITY_WARNING,
     120                 :             :             SOLIDSYSLOG_CAT_BAD_CONFIG,
     121                 :             :             SOLIDSYSLOG_TLS_CREDENTIALS_ERROR_CLIENT_CREDENTIAL_INCOMPLETE
     122                 :             :         );
     123                 :             :     }
     124                 :             :     else
     125                 :             :     {
     126                 :             :         /* Neither supplied - server-authenticated TLS is the deliberate case. */
     127                 :             :     }
     128                 :          55 : }
     129                 :             : 
     130                 :          55 : static inline bool OpenSslPemFileCredentials_HasClientCredential(
     131                 :             :     const struct SolidSyslogOpenSslPemFileCredentialsConfig* config
     132                 :             : )
     133                 :             : {
     134   [ +  +  +  + ]:          55 :     return (config->ClientCertChainPath != NULL) && (config->ClientKeyPath != NULL);
     135                 :             : }
     136                 :             : 
     137                 :             : /* One half without the other. The integrator asked for mutual TLS and will not
     138                 :             :  * get it, so it is reported rather than read as a decision to go without. */
     139                 :          48 : static inline bool OpenSslPemFileCredentials_HasHalfOfClientCredential(
     140                 :             :     const struct SolidSyslogOpenSslPemFileCredentialsConfig* config
     141                 :             : )
     142                 :             : {
     143                 :          48 :     return (config->ClientCertChainPath != NULL) != (config->ClientKeyPath != NULL);
     144                 :             : }
     145                 :             : 
     146                 :             : /* A key that does not match its certificate is refused by SSL_CTX_use_PrivateKey_file
     147                 :             :  * itself where both are of the same type, so it reaches the explicit pairing check
     148                 :             :  * only as a cross-type pair. The two are reported apart where OpenSSL tells them
     149                 :             :  * apart, and a mismatch it hides inside the load is reported as one that would
     150                 :             :  * not install. */
     151                 :           7 : static inline void OpenSslPemFileCredentials_LoadClientCredential(
     152                 :             :     SSL_CTX* ctx,
     153                 :             :     const struct SolidSyslogOpenSslPemFileCredentialsConfig* config
     154                 :             : )
     155                 :             : {
     156   [ +  +  +  + ]:          12 :     bool installed = (SSL_CTX_use_certificate_chain_file(ctx, config->ClientCertChainPath) == 1) &&
     157                 :           5 :                      (SSL_CTX_use_PrivateKey_file(ctx, config->ClientKeyPath, SSL_FILETYPE_PEM) == 1);
     158         [ +  + ]:           7 :     if (installed == false)
     159                 :             :     {
     160                 :           3 :         OpenSslPemFileCredentials_Report(
     161                 :             :             SOLIDSYSLOG_SEVERITY_WARNING,
     162                 :             :             SOLIDSYSLOG_CAT_BAD_CONFIG,
     163                 :             :             SOLIDSYSLOG_TLS_CREDENTIALS_ERROR_CLIENT_CREDENTIAL_NOT_INSTALLED
     164                 :             :         );
     165                 :             :     }
     166         [ +  + ]:           4 :     else if (SSL_CTX_check_private_key(ctx) != 1)
     167                 :             :     {
     168                 :           1 :         OpenSslPemFileCredentials_Report(
     169                 :             :             SOLIDSYSLOG_SEVERITY_WARNING,
     170                 :             :             SOLIDSYSLOG_CAT_BAD_CONFIG,
     171                 :             :             SOLIDSYSLOG_TLS_CREDENTIALS_ERROR_CLIENT_CREDENTIAL_MISMATCHED
     172                 :             :         );
     173                 :             :     }
     174                 :             :     else
     175                 :             :     {
     176                 :             :         /* Installed and paired - the credential will be presented. */
     177                 :             :     }
     178                 :           7 : }
     179                 :             : 
     180                 :             : /* Nothing to release. This backend holds paths, and OpenSSL owns what it parsed
     181                 :             :  * from them: the SSL_CTX the stream frees at Close takes the certificate and the
     182                 :             :  * key with it. A backend that parses material itself - one reading a PEM buffer,
     183                 :             :  * or unwrapping a key - is where Release does real work. */
     184                 :          37 : static void OpenSslPemFileCredentials_Release(struct SolidSyslogOpenSslCredentials* base)
     185                 :             : {
     186                 :             :     (void) base;
     187                 :          37 : }
        

Generated by: LCOV version 2.0-1