1 /* 2 * Copyright 2024 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 /*! 95 * \internal 96 * \brief Add the client PSK key to the TLS environment 97 * 98 * This function must be called for all TLS clients that are using PSK for 99 * authentication. 100 * 101 * \param[in,out] tls The TLS environment 102 * \param[in] key The client's PSK key 103 */ 104 void pcmk__tls_add_psk_key(pcmk__tls_t *tls, gnutls_datum_t *key); 105 106 /*! 107 * \internal 108 * \brief Register the server's PSK credential fetching callback 109 * 110 * This function must be called for all TLS servers that are using PSK for 111 * authentication. 112 * 113 * \param[in,out] tls The TLS environment 114 * \param[in] cb The server's PSK credential fetching callback 115 */ 116 void pcmk__tls_add_psk_callback(pcmk__tls_t *tls, 117 gnutls_psk_server_credentials_function *cb); 118 119 /*! 120 * \internal 121 * \brief Process handshake data from TLS client 122 * 123 * Read as much TLS handshake data as is available. 124 * 125 * \param[in] client Client connection 126 * 127 * \return Standard Pacemaker return code (of particular interest, EAGAIN 128 * if some data was successfully read but more data is needed) 129 */ 130 int pcmk__read_handshake_data(const pcmk__client_t *client); 131 132 /*! 133 * \internal 134 * \brief Log if a TLS certificate is near its expiration date 135 * 136 * \param[in] session The gnutls session object after handshaking is 137 * complete 138 */ 139 void pcmk__tls_check_cert_expiration(gnutls_session_t session); 140 141 /*! 142 * \internal 143 * \brief Perform client TLS handshake after establishing TCP socket 144 * 145 * \param[in,out] remote Newly established remote connection 146 * \param[in] timeout_sec Abort handshake if not completed within this time 147 * \param[out] gnutls_rc If this is non-NULL, it will be set to the GnuTLS 148 * rc (for logging) if this function returns EPROTO, 149 * otherwise GNUTLS_E_SUCCESS 150 * 151 * \return Standard Pacemaker return code 152 */ 153 int pcmk__tls_client_handshake(pcmk__remote_t *remote, int timeout_sec, 154 int *gnutls_rc); 155 156 /*! 157 * \internal 158 * \brief Make a single attempt to perform the client TLS handshake 159 * 160 * \param[in,out] remote Newly established remote connection 161 * \param[out] gnutls_rc If this is non-NULL, it will be set to the GnuTLS 162 * rc (for logging) if this function returns EPROTO, 163 * otherwise GNUTLS_E_SUCCESS 164 * 165 * \return Standard Pacemaker return code 166 */ 167 int pcmk__tls_client_try_handshake(pcmk__remote_t *remote, int *gnutls_rc); 168 169 /*! 170 * \internal 171 * \brief Is X509 authentication supported by the environment? 172 * 173 * \return true if the appropriate environment variables are set (see 174 * etc/sysconfig/pacemaker.in), otherwise false 175 */ 176 bool pcmk__x509_enabled(void); 177 178 #ifdef __cplusplus 179 } 180 #endif 181 182 #endif // PCMK__CRM_COMMON_TLS_INTERNAL__H