1 /* 2 * Copyright 2024-2025 the Pacemaker project contributors 3 * 4 * The version control history for this file may have further details. 5 * 6 * This source code is licensed under the GNU Lesser General Public License 7 * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. 8 */ 9 10 #ifndef PCMK__CRM_COMMON_TLS_INTERNAL__H 11 #define PCMK__CRM_COMMON_TLS_INTERNAL__H 12 13 #include <gnutls/gnutls.h> // gnutls_session_t, gnutls_dh_params_t, etc. 14 15 #include <crm/common/ipc_internal.h> // pcmk__client_t 16 #include <crm/common/remote_internal.h> // pcmk__remote_t 17 18 #ifdef __cplusplus 19 extern "C" { 20 #endif 21 22 typedef struct { 23 bool server; 24 gnutls_dh_params_t dh_params; 25 gnutls_credentials_type_t cred_type; 26 27 const char *ca_file; 28 const char *cert_file; 29 const char *crl_file; 30 const char *key_file; 31 32 union { 33 gnutls_anon_server_credentials_t anon_s; 34 gnutls_anon_client_credentials_t anon_c; 35 gnutls_certificate_credentials_t cert; 36 gnutls_psk_server_credentials_t psk_s; 37 gnutls_psk_client_credentials_t psk_c; 38 } credentials; 39 } pcmk__tls_t; 40 41 /*! 42 * \internal 43 * \brief Free a previously allocated \p pcmk__tls_t object 44 * 45 * \param[in,out] tls The object to free 46 */ 47 void pcmk__free_tls(pcmk__tls_t *tls); 48 49 /*! 50 * \internal 51 * \brief Initialize a new TLS object 52 * 53 * Unlike \p pcmk__new_tls_session, this function is used for creating the 54 * global environment for TLS connections. 55 * 56 * \param[in,out] tls The object to be allocated and initialized 57 * \param[in] server Is this a server or not? 58 * \param[in] cred_type What type of gnutls credentials are in use? 59 * (GNUTLS_CRD_* constants) 60 * 61 * \returns Standard Pacemaker return code 62 */ 63 int pcmk__init_tls(pcmk__tls_t **tls, bool server, 64 gnutls_credentials_type_t cred_type); 65 66 /*! 67 * \internal 68 * \brief Initialize Diffie-Hellman parameters for a TLS server 69 * 70 * \param[out] dh_params Parameter object to initialize 71 * 72 * \return Standard Pacemaker return code 73 * \todo The current best practice is to allow the client and server to 74 * negotiate the Diffie-Hellman parameters via a TLS extension (RFC 7919). 75 * However, we have to support both older versions of GnuTLS (<3.6) that 76 * don't support the extension on our side, and older Pacemaker versions 77 * that don't support the extension on the other side. The next best 78 * practice would be to use a known good prime (see RFC 5114 section 2.2), 79 * possibly stored in a file distributed with Pacemaker. 80 */ 81 int pcmk__init_tls_dh(gnutls_dh_params_t *dh_params); 82 83 /*! 84 * \internal 85 * \brief Initialize a new TLS session 86 * 87 * \param[in] tls A TLS environment object 88 * \param[in] csock Connected socket for TLS session 89 * 90 * \return Pointer to newly created session object, or NULL on error 91 */ 92 gnutls_session_t pcmk__new_tls_session(pcmk__tls_t *tls, int csock); 93 94 int pcmk__tls_get_client_sock(const pcmk__remote_t *remote); 95 96 /*! 97 * \internal 98 * \brief Add the client PSK key to the TLS environment 99 * 100 * This function must be called for all TLS clients that are using PSK for 101 * authentication. 102 * 103 * \param[in,out] tls The TLS environment 104 * \param[in] key The client's PSK key 105 */ 106 void pcmk__tls_add_psk_key(pcmk__tls_t *tls, gnutls_datum_t *key); 107 108 /*! 109 * \internal 110 * \brief Register the server's PSK credential fetching callback 111 * 112 * This function must be called for all TLS servers that are using PSK for 113 * authentication. 114 * 115 * \param[in,out] tls The TLS environment 116 * \param[in] cb The server's PSK credential fetching callback 117 */ 118 void pcmk__tls_add_psk_callback(pcmk__tls_t *tls, 119 gnutls_psk_server_credentials_function *cb); 120 121 /*! 122 * \internal 123 * \brief Process handshake data from TLS client 124 * 125 * Read as much TLS handshake data as is available. 126 * 127 * \param[in] client Client connection 128 * 129 * \return Standard Pacemaker return code (of particular interest, EAGAIN 130 * if some data was successfully read but more data is needed) 131 */ 132 int pcmk__read_handshake_data(const pcmk__client_t *client); 133 134 /*! 135 * \internal 136 * \brief Log if a TLS certificate is near its expiration date 137 * 138 * \param[in] session The gnutls session object after handshaking is 139 * complete 140 */ 141 void pcmk__tls_check_cert_expiration(gnutls_session_t session); 142 143 /*! 144 * \internal 145 * \brief Perform client TLS handshake after establishing TCP socket 146 * 147 * \param[in,out] remote Newly established remote connection 148 * \param[in] timeout_sec Abort handshake if not completed within this time 149 * \param[out] gnutls_rc If this is non-NULL, it will be set to the GnuTLS 150 * rc (for logging) if this function returns EPROTO, 151 * otherwise GNUTLS_E_SUCCESS 152 * 153 * \return Standard Pacemaker return code 154 */ 155 int pcmk__tls_client_handshake(pcmk__remote_t *remote, int timeout_sec, 156 int *gnutls_rc); 157 158 /*! 159 * \internal 160 * \brief Make a single attempt to perform the client TLS handshake 161 * 162 * \param[in,out] remote Newly established remote connection 163 * \param[out] gnutls_rc If this is non-NULL, it will be set to the GnuTLS 164 * rc (for logging) if this function returns EPROTO, 165 * otherwise GNUTLS_E_SUCCESS 166 * 167 * \return Standard Pacemaker return code 168 */ 169 int pcmk__tls_client_try_handshake(pcmk__remote_t *remote, int *gnutls_rc); 170 171 /*! 172 * \internal 173 * \brief Is X509 authentication supported by the environment? 174 * 175 * \return true if the appropriate environment variables are set (see 176 * etc/sysconfig/pacemaker.in), otherwise false 177 */ 178 bool pcmk__x509_enabled(void); 179 180 #ifdef __cplusplus 181 } 182 #endif 183 184 #endif // PCMK__CRM_COMMON_TLS_INTERNAL__H