13#include <gnutls/gnutls.h>
14#include <gnutls/x509.h>
22get_gnutls_priorities(gnutls_credentials_type_t cred_type)
26 if (prio_base == NULL) {
30 if (cred_type == GNUTLS_CRD_ANON) {
32 }
else if (cred_type == GNUTLS_CRD_PSK) {
35 return strdup(prio_base);
40tls_cred_str(gnutls_credentials_type_t cred_type)
42 if (cred_type == GNUTLS_CRD_ANON) {
43 return "unauthenticated";
44 }
else if (cred_type == GNUTLS_CRD_PSK) {
45 return "shared-key-authenticated";
46 }
else if (cred_type == GNUTLS_CRD_CERTIFICATE) {
47 return "certificate-authenticated";
70 crm_err(
"Failed to set X509 CA file: %s", gnutls_strerror(rc));
82 crm_err(
"Failed to set X509 CRL file: %s",
93 GNUTLS_X509_FMT_PEM, NULL,
96 crm_err(
"Failed to set X509 cert/key pair: %s",
112verify_peer_cert(gnutls_session_t session)
120 rc = gnutls_certificate_verify_peers3(session, NULL, &status);
125 if (rc != GNUTLS_E_SUCCESS) {
126 crm_err(
"Failed to verify peer certificate: %s", gnutls_strerror(rc));
135 type = gnutls_certificate_type_get(session);
136 gnutls_certificate_verification_status_print(status,
type, &out, 0);
137 crm_err(
"Peer certificate invalid: %s", out.data);
138 gnutls_free(out.data);
139 return GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR;
143_gnutls_log_func(
int level,
const char *msg)
166 }
else if (tls->
cred_type == GNUTLS_CRD_CERTIFICATE) {
168 }
else if (tls->
cred_type == GNUTLS_CRD_PSK) {
179 gnutls_global_deinit();
193 signal(SIGPIPE, SIG_IGN);
202 gnutls_global_init();
203 gnutls_global_set_log_level(8);
204 gnutls_global_set_log_function(_gnutls_log_func);
215 (*tls)->cred_type = cred_type;
216 (*tls)->server = server;
218 if (cred_type == GNUTLS_CRD_ANON) {
220 gnutls_anon_allocate_server_credentials(&(*tls)->credentials.anon_s);
221 gnutls_anon_set_server_dh_params((*tls)->credentials.anon_s,
224 gnutls_anon_allocate_client_credentials(&(*tls)->credentials.anon_c);
226 }
else if (cred_type == GNUTLS_CRD_CERTIFICATE) {
231 if (pcmk__str_empty((*tls)->ca_file)) {
232 (*tls)->ca_file = getenv(
"CIB_ca_file");
236 if (pcmk__str_empty((*tls)->cert_file)) {
237 (*tls)->cert_file = getenv(
"CIB_cert_file");
241 if (pcmk__str_empty((*tls)->crl_file)) {
242 (*tls)->crl_file = getenv(
"CIB_crl_file");
246 if (pcmk__str_empty((*tls)->key_file)) {
247 (*tls)->key_file = getenv(
"CIB_key_file");
250 gnutls_certificate_allocate_credentials(&(*tls)->credentials.cert);
253 gnutls_certificate_set_dh_params((*tls)->credentials.cert,
258 rc = tls_load_x509_data(*tls);
264 }
else if (cred_type == GNUTLS_CRD_PSK) {
266 gnutls_psk_allocate_server_credentials(&(*tls)->credentials.psk_s);
267 gnutls_psk_set_server_dh_params((*tls)->credentials.psk_s,
270 gnutls_psk_allocate_client_credentials(&(*tls)->credentials.psk_c);
280 int rc = GNUTLS_E_SUCCESS;
281 unsigned int dh_bits = 0;
284 rc = gnutls_dh_params_init(dh_params);
285 if (rc != GNUTLS_E_SUCCESS) {
289 dh_bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH,
290 GNUTLS_SEC_PARAM_NORMAL);
292 rc = GNUTLS_E_DH_PRIME_UNACCEPTABLE;
297 if ((dh_max_bits > 0) && (dh_bits > dh_max_bits)) {
298 dh_bits = dh_max_bits;
301 crm_info(
"Generating Diffie-Hellman parameters with %u-bit prime for TLS",
303 rc = gnutls_dh_params_generate2(*dh_params, dh_bits);
304 if (rc != GNUTLS_E_SUCCESS) {
311 crm_err(
"Could not initialize Diffie-Hellman parameters for TLS: %s "
312 QB_XS
" rc=%d", gnutls_strerror(rc), rc);
319 unsigned int conn_type = GNUTLS_CLIENT;
320 int rc = GNUTLS_E_SUCCESS;
322 gnutls_session_t session = NULL;
324 CRM_CHECK((tls != NULL) && (csock >= 0),
return NULL);
327 conn_type = GNUTLS_SERVER;
330 rc = gnutls_init(&session, conn_type);
331 if (rc != GNUTLS_E_SUCCESS) {
341 prio = get_gnutls_priorities(tls->
cred_type);
347 rc = gnutls_priority_set_direct(session, prio, NULL);
348 if (rc != GNUTLS_E_SUCCESS) {
352 gnutls_transport_set_ptr(session,
353 (gnutls_transport_ptr_t) GINT_TO_POINTER(csock));
358 }
else if (tls->
cred_type == GNUTLS_CRD_ANON) {
360 }
else if (tls->
cred_type == GNUTLS_CRD_CERTIFICATE) {
364 }
else if (tls->
cred_type == GNUTLS_CRD_PSK) {
372 if (rc != GNUTLS_E_SUCCESS) {
378 if (tls->
cred_type == GNUTLS_CRD_CERTIFICATE) {
379 if (conn_type == GNUTLS_SERVER) {
381 gnutls_certificate_server_set_request(session, GNUTLS_CERT_REQUIRE);
389 gnutls_certificate_set_verify_function(tls->
credentials.
cert, verify_peer_cert);
395 crm_err(
"Could not initialize %s TLS %s session: %s " QB_XS
" rc=%d priority='%s'",
397 (conn_type == GNUTLS_SERVER)?
"server" :
"client",
398 gnutls_strerror(rc), rc, prio);
400 if (session != NULL) {
401 gnutls_deinit(session);
420 gpointer sock_ptr = NULL;
424 sock_ptr = (gpointer) gnutls_transport_get_ptr(remote->
tls_session);
425 return GPOINTER_TO_INT(sock_ptr);
438 }
while (rc == GNUTLS_E_INTERRUPTED);
440 if (rc == GNUTLS_E_AGAIN) {
445 }
else if (rc != GNUTLS_E_SUCCESS) {
446 crm_err(
"TLS handshake with remote client failed: %s "
447 QB_XS
" rc=%d", gnutls_strerror(rc), rc);
463 gnutls_psk_server_credentials_function *cb)
471 gnutls_x509_crt_t cert;
472 const gnutls_datum_t *datum = NULL;
475 if (session == NULL) {
479 if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509) {
483 datum = gnutls_certificate_get_ours(session);
488 gnutls_x509_crt_init(&cert);
489 gnutls_x509_crt_import(cert, datum, GNUTLS_X509_FMT_DER);
491 expiry = gnutls_x509_crt_get_expiration_time(cert);
494 time_t now = time(NULL);
497 if (expiry - now <= 60 * 60 * 24 * 30) {
500 crm_time_log(LOG_WARNING,
"TLS certificate will expire on",
506 gnutls_x509_crt_deinit(cert);
514 if (gnutls_rc != NULL) {
515 *gnutls_rc = GNUTLS_E_SUCCESS;
521 case GNUTLS_E_SUCCESS:
525 case GNUTLS_E_INTERRUPTED:
531 if (gnutls_rc != NULL) {
546 const time_t time_limit = time(NULL) + timeout_sec;
554 }
while (time(NULL) < time_limit);
568 !pcmk__str_empty(getenv(
"CIB_cert_file"))) &&
570 !pcmk__str_empty(getenv(
"CIB_ca_file"))) &&
572 !pcmk__str_empty(getenv(
"CIB_key_file")));
#define pcmk__assert_alloc(nmemb, size)
#define PCMK__GNUTLS_PRIORITIES
enum pcmk_ipc_server type
#define crm_time_log_timeofday
void crm_time_free(crm_time_t *dt)
#define crm_time_log_date
struct crm_time_s crm_time_t
#define crm_time_log(level, prefix, dt, flags)
crm_time_t * pcmk__copy_timet(time_t source)
#define crm_info(fmt, args...)
#define CRM_CHECK(expr, failure_action)
#define crm_err(fmt, args...)
#define crm_trace(fmt, args...)
#define DEFAULT_REMOTE_USERNAME
#define PCMK__ENV_KEY_FILE
#define PCMK__ENV_DH_MAX_BITS
#define PCMK__ENV_CERT_FILE
#define PCMK__ENV_TLS_PRIORITIES
const char * pcmk__env_option(const char *option)
#define PCMK__ENV_CRL_FILE
#define PCMK__ENV_CA_FILE
#define pcmk__assert(expr)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
int pcmk__scan_min_int(const char *text, int *result, int minimum)
struct pcmk__remote_s * remote
gnutls_session_t tls_session
gnutls_psk_server_credentials_t psk_s
gnutls_psk_client_credentials_t psk_c
gnutls_credentials_type_t cred_type
gnutls_anon_server_credentials_t anon_s
gnutls_dh_params_t dh_params
gnutls_anon_client_credentials_t anon_c
gnutls_certificate_credentials_t cert
union pcmk__tls_t::@10 credentials
void pcmk__tls_add_psk_callback(pcmk__tls_t *tls, gnutls_psk_server_credentials_function *cb)
void pcmk__tls_add_psk_key(pcmk__tls_t *tls, gnutls_datum_t *key)
int pcmk__tls_get_client_sock(const pcmk__remote_t *remote)
int pcmk__tls_client_try_handshake(pcmk__remote_t *remote, int *gnutls_rc)
void pcmk__free_tls(pcmk__tls_t *tls)
bool pcmk__x509_enabled(void)
int pcmk__init_tls(pcmk__tls_t **tls, bool server, gnutls_credentials_type_t cred_type)
int pcmk__tls_client_handshake(pcmk__remote_t *remote, int timeout_sec, int *gnutls_rc)
void pcmk__tls_check_cert_expiration(gnutls_session_t session)
int pcmk__read_handshake_data(const pcmk__client_t *client)
int pcmk__init_tls_dh(gnutls_dh_params_t *dh_params)
gnutls_session_t pcmk__new_tls_session(pcmk__tls_t *tls, int csock)